CFSPREADSHET читается в файле Excel, чтобы запрос не мог получить доступ к столбцам в результате

Я пытаюсь автоматизировать обработку электронных таблиц с помощью ColdFusion 10 и CFSpreadSheet. Пока я могу прочитать файл и выгрузить объект запроса без каких-либо проблем.

<cfspreadsheet action="read" src="#theFile#" query="qData" headerrow="1" columns="1,8,9,11,33"/>
<cfdump var="#qData#"/>  

cfdumpoutput

Проблема возникает, когда я пытаюсь работать с данными. Если я сделаю что-то вроде:

<cfoutput query="qData" maxrows="#qData.RecordCount#">
    #qData.GROUP#<br />
    #qData.DOB#<br />
</cfoutput>

Сразу получаю ошибку: "Элемент GROUP не определен в QDATA".

Если я сброшу qData.ColumnList, я получу список столбцов:

BTBN(002),DOB ,GROUP ,MEMBER/DEPENDENT NAME ,REL

Это пробелы и ( ) все портят? Если да, то как я могу избавиться от них и обновить имена столбцов либо при чтении файла, либо сразу после этого?


person Steve    schedule 07.04.2016    source источник


Ответы (3)


Сначала я подумал, что это может быть связано с тем, что «группа» является зарезервированным ключевым словом SQL. (Не пытайтесь использовать это имя столбца в запросе запросов.)

Вместо очистки значений первой строки для известных значений и повторного сохранения файла следует выполнить цикл и использовать isValid("variablename", ColumnName), чтобы определить, является ли имя столбца допустимым, а затем использовать UDF RenameColumn для его переименования. Мы предпочитаем этот метод, так как очень важно, чтобы мы не изменяли исходный файл Excel клиента (особенно потому, что Adobe ColdFusion имеет некоторые ошибки при записи файлов и, вероятно, испортит другие рабочие листы и/или форматирование в файле).

Простой способ удалить недопустимые символы — использовать замену:

ReReplace(NewColumnName, "[^a-zA-Z0-9!]", "", "ALL")

Но вам также необходимо убедиться, что имя нового столбца не пустое, начинается с буквы и еще не используется для другого столбца. Если вы ожидаете, что столбцы будут в определенном порядке, вы можете просто безопасно переименовать их в «col_1» (или использовать нумерацию в качестве запасного варианта по умолчанию для любых неуникальных и/или недопустимых имен столбцов).

Вот UDF RenameColumn, взятый из этого сообщения в блоге 2011 года:

http://www.neiland.net/blog/article/using-java-to-rename-columns-in-a-coldfusion-query-object/

<cffunction name="renameColumn" access="public" output="false" returntype="query" hint="Uses java to rename a given query object column">
  <cfargument name="queryObj" required="true" type="query">
  <cfargument name="oldColName" required="true" type="string">
  <cfargument name="newColName" required="true" type="string">

  <!--- Get an array of the current column names --->
  <cfset var colNameArray = queryObj.getColumnNames()>
  <cfset var i = 0>

  <!--- Loop through the name array and try match the current column name with the target col name--->
  <cfif arrayLen(colNameArray)>
        <cfloop from="1" to="#arrayLen(colNameArray)#" index="i">
              <!--- If we find the target col name change to the new name --->
              <cfif compareNoCase(colNameArray[i],arguments.oldColName) EQ 0>
                    <cfset colNameArray[i] = arguments.newColName>
              </cfif>
        </cfloop>
  </cfif>

  <!--- Update the column names with the updated name array --->
  <cfset queryObj.setColumnNames(colNameArray)>

  <cfreturn queryObj />
</cffunction>
person James Moberg    schedule 07.04.2016
comment
Одно примечание: isValid("variableName") в ColdFusion имеет известную ошибку/функцию и обрезает строку перед ее оценкой, поэтому вам также необходимо вручную проверить наличие начальных/конечных пробелов в имени столбца. - person James Moberg; 07.04.2016

(На случай, если люди не читают комментарии...)

Круглые скобки и косые черты будут проблематичными, поскольку они не соответствуют стандартные правила имен переменных. Самый простой вариант — использовать "columnNames" атрибут, чтобы вместо этого указать допустимые имена столбцов. (Кроме того, это не имеет отношения к вашему вопросу, но если вы хотите исключить строку заголовка, используйте excludeHeaderRow="true")

<cfspreadsheet action="read" src="c:\path\file.xlsx" 
     query="qData" 
     columnNames="BTBN_002,DOB,GROUP_NAME,MEMBER_DEPEND_NAME,REL"
     excludeHeaderRow="true"
     headerrow="1" 
     ... />

В большинстве случаев вы также можете получить доступ к недопустимым именам столбцов, используя нотацию ассоциативного массива. Однако использование атрибута «columnNames» проще/чище IMO.

<cfoutput query="qData" maxrows="#qData.RecordCount#">
    #qData["BTBN(002)"][currentRow]#<br />
    ....
</cfoutput>
person Leigh    schedule 07.04.2016

РЕШЕНИЕ - в именах столбцов было несколько пробелов, и ColdFusion не допускает этого. Вероятно, это можно было бы сделать лучше с помощью регулярного выражения, и я поработаю над этим дальше, но вот быстрое и грязное решение.

<cfset colNameArray = qData.getColumnNames() />

<cfloop from="1" to="#arrayLen(colNameArray)#" index="i">
  <cfset colNameArray[i] = colNameArray[i].replace(' ','') />
  <cfset colNameArray[i] = colNameArray[i].replace('(','') />
  <cfset colNameArray[i] = colNameArray[i].replace(')','') />
  <cfset colNameArray[i] = colNameArray[i].replace('/','') />
</cfloop>      

<cfset qData.setColumnNames(colNameArray) />
person Steve    schedule 07.04.2016
comment
Просто используйте атрибут columnNames, чтобы назначить любые имена столбцов, которые вы хотите :) Вы также можете использовать нотацию массива для доступа к недопустимым именам столбцов, т.е. #query["BTBN(002)"][currentRow]#, но columnNames проще/чище IMO. - person Leigh; 07.04.2016
comment
Я настоятельно рекомендую клиентам использовать ASAP Utilities for Excel, чтобы обрезать все значения перед загрузкой. Он также имеет функцию быстрого преобразования формул в значения, чтобы ColdFusion не выдавал ошибку при попытке определить значение. asap-utilities.com (это также удаляет невидимый неразрывный пробел, который мешает многим файлам Excel, которые не удаляется с помощью функции trim() и импортируется в SQL.) - person James Moberg; 07.04.2016