Не удается создать правильную электронную таблицу Excel с помощью ColdFusion

У меня есть запрос от клиента на создание электронной таблицы Excel из запроса. У меня есть запрос, выбивающий поля, и я могу без проблем сгенерировать файл Excel. Проблема возникает, когда клиент берет этот файл Excel, а затем пытается им манипулировать.

Большинство проблем возникает из-за полей, которые должны быть помечены как валюта или даты. С некоторыми трудностями я могу создать «настоящее» поле даты. До этого Excel неправильно сортировал даты. Я смог вызвать формулу Excel, используя приведенный ниже код. DateValue заставляет Excel признать это поле реальной даты. Однако это не удается, когда этот файл обрабатывается через Excel.

<cfset SpreadsheetSetCellFormula(s
          ,"DATEVALUE(#Chr(34)##Replacement_ETD##Chr(34)#)"
          , therow
          , 9)>

Следующая проблема — поле валюты. Я не могу заставить Excel признать значения как валюту. Это всегда приходит на заказ. Когда это установлено, функция SUM не будет работать в Excel. Вы можете добавлять поля по отдельности, например A1+B1+C1 = TOTAL. Однако это бесполезно, когда есть 200 строк.

Мне удалось получить предложение от другого программиста CF, у которого была аналогичная ситуация. Сначала он создал файл Excel с правильными заголовками и установил для столбцов соответствующие поля, такие как дата, валюта и т. д.

Следующим шагом будет заполнение полей построчно, и они должны быть правильно отформатированы.

Код:

<cfset filename = expandPath("./reports/arrivals.xlsx")>
<cfspreadsheet  action="read" src = "#filename#"  name = "s" >
<cfset therow = 0>
<cfoutput query="myExcel" startrow="1">
    <cfset therow = myExcel.currentrow + 1>
    <cfset SpreadsheetSetCellValue(s, Incumbent, therow, 1)>
    <cfset SpreadsheetSetCellValue(s, Section, therow, 2)>
    <cfset SpreadsheetSetCellValue(s, Position_Number, therow, 3)>
    <cfset SpreadsheetSetCellValue(s, Position_Title, therow, 4)>
    <cfset SpreadsheetSetCellValue(s, Incumbent_Emplyment_Type, therow, 5)>
    <cfset SpreadsheetSetCellValue(s, Incumbent_ETD, therow, 6)>
    <cfset SpreadsheetSetCellValue(s, Tour_Comments, therow, 7)>
    <cfset SpreadsheetSetCellValue(s, Replacement, therow, 8)>
    <cfset SpreadsheetSetCellValue(s, Replacement_ETA, therow, 9)>
</cfoutput>    
<cfheader name="content-disposition" value="attachment; filename=Departures_(#DateFormat(now(),'mmddyy')#).xls">
<cfcontent type="application/msexcel" variable="#spreadsheetReadBinary(s)#" reset="true">

Данные в ячейках уже правильно отформатированы. Когда этот файл создается и передается пользователю, столбцы форматируются не так, как ожидалось.

Кто-нибудь еще знает, будет ли этот метод работать, или у него есть лучшее предложение о том, как заставить CF генерировать правильное поле даты и валюты для подтверждения Excel?

Adobe ColdFusion v10 работает на RHEL 5.

По запросу вот некоторый код, использующий queryNew, который будет генерировать кодовые даты и валюту.

Шаг первый: я создал файл Excel с замороженной первой строкой и заголовком столбца. Первая колонка была обозначена как дата в длинном формате - мм/дд/гггг; Второй столбец - это доллар, который был установлен в валюте.

Я читаю этот файл, затем заполняю строки и передаю файл пользователю для загрузки.

<cfset filename = expandPath("./reports/Test.xlsx")>

<cfspreadsheet  action="read" src = "#filename#"  name = "s" >

<cfset myQuery = QueryNew("MyDate, Dollar", "Date, Decimal")> 

<cfset newRow = QueryAddRow(MyQuery, 5)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "03-11-2000", 1)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "403.45", 1)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "01-01-2009", 2)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "603.22", 2)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "09-21-2013", 3)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "103.55", 3)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "01-15-2005", 4)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "3.33", 4)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "07-22-2003", 5)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "13.75", 5)> 

<cfset therow = 0>
<cfoutput query="myQuery" startrow="1">
  <cfset therow = myQuery.currentrow + 1>

  <cfset SpreadsheetSetCellValue(s, DateFormat(MyDate, 'mm/dd/yyyy'), therow, 1)>
  <cfset SpreadsheetSetCellValue(s, Dollar, therow, 2)>
  #myQuery.currentrow# <br>
  #myQuery.MyDate# <br>
  #myQuery.Dollar# <br>
</cfoutput>          

<cfheader name="content-disposition" value="attachment; 
                  filename=Departures_(#DateFormat(now(),'mmddyy')#).xls">
<cfcontent type="application/msexcel" variable="#spreadsheetReadBinary(s)#" reset="true">

Вы можете открыть файл в MS Excel или в Google Таблицах. Протестируйте один, с замороженной первой строкой, мы должны иметь возможность сортировать по полю даты. Мои результаты: даты не сортируются должным образом. В столбце 2 с валютой, если мы попытаемся сделать SUM, это сработает! Раньше это не работало, но теперь работает.

Кроме того, когда я пытаюсь открыть файл, мне выдается предупреждение о том, что этот файл поврежден, и Excel попытается его открыть. Я не получаю такого предупреждения в Google Таблицах.


person weggie    schedule 24.05.2016    source источник
comment
Такие фразы, как «сбой» и «не будет работать», очень двусмысленны. Не могли бы вы предоставить небольшой самостоятельный пример, который мы можем протестировать, демонстрирующий проблему? Совет: вы можете использовать QueryNew() для создания запроса вручную, чтобы в примере не требовался запрос к базе данных.   -  person Leigh    schedule 24.05.2016
comment
@Ли конечно. Я на скорую руку примерю и отредактирую пост.   -  person weggie    schedule 24.05.2016
comment
@Leigh Код обновлен, это пример и мои результаты этого теста. Спасибо.   -  person weggie    schedule 24.05.2016
comment
Итак, вы предварительно форматируете столбцы (в виде мм/дд/гггг и валюты) перед заполнением их с помощью CF? Re: Внимание! Этот файл поврежден. Это связано с тем, что вы читаете файл .XLSX, а cfcontent и тип mime предназначены для .XLS. Им нужно соответствовать.   -  person Leigh    schedule 25.05.2016
comment
Хм... может быть, это момент DUH для меня. Завтра я заново сгенерирую это с помощью XLS и проверю. Спасибо   -  person weggie    schedule 25.05.2016
comment
Хорошо. Последняя ошибка может быть только ее частью. Было бы ясно, если бы вы сказали, что установили форматы ячеек в Excel и что они не соблюдаются после добавления данных... или если была какая-то другая проблема.   -  person Leigh    schedule 25.05.2016
comment
@ Ли, да, все еще есть. После быстрого теста, даже если файл сохраняется как файл xls, а столбец распознается как дата, он не сортирует даты должным образом.   -  person weggie    schedule 25.05.2016
comment
Да, я прикинул, но... вы так и не ответили на вопрос о том, форматируете ли вы ячейки заранее ;-)   -  person Leigh    schedule 25.05.2016
comment
@Leigh Извините, это был день.. лол Да. Я предварительно отформатировал ячейки для даты и валюты.   -  person weggie    schedule 25.05.2016
comment
Вы можете попробовать это? Протестировано с CF11: pastebin.com/8hmBGvZ9   -  person Leigh    schedule 25.05.2016
comment
@Leigh - Спасибо, я работаю над этим сейчас. Сообщу о результатах!   -  person weggie    schedule 25.05.2016
comment
@Leigh - Спасибо за вашу помощь, у меня есть рабочая модель, и я могу двигаться вперед. Создается файл Excel, и им можно манипулировать с помощью сводных таблиц и т. Д. Пожалуйста, дайте мне знать, что я могу поблагодарить вас за правильный ответ на этот вопрос?   -  person weggie    schedule 26.05.2016
comment
Пожалуйста. Я повысил его до ответа вместе с некоторыми дополнительными деталями на случай, если это поможет следующему парню :)   -  person Leigh    schedule 26.05.2016


Ответы (1)


CF может быть немного причудливым при работе с ячейками даты. Excel довольно хорошо угадывает правильный тип ячейки, когда значение вводится вручную. Однако с CF немного сложнее. Поскольку CF является относительно бестиповым, он не всегда правильно сопоставляет значения и типы ячеек. Использование функций, использующих объект запроса, вместо SpreadsheetSetCellValue() обычно дает лучшие результаты. Скорее всего потому, что объекты запросов содержат и значения, и типы данных. Хотя в CF11 SpreadsheetSetCellValue поддерживает новый параметр данных, который позволяет указать как значение, так и тип данных ячейки. Поскольку вы используете CF10, попробуйте использовать SpreadsheetAddRows для заполнения значений вместо этого.

Что касается предупреждения о том, что файл поврежден, то оно вызвано тем, что фактическое содержимое файла и расширение файла в коде загрузки не совпадают. Код читается в файле .xlsx, но при загрузке утверждается, что это файл .xls (application/msexcel). Чтобы избавиться от ошибки, убедитесь, что они совпадают.

Вот рабочий пример, протестированный с CF11.

<!---
    Test.xlsx contains two columns, with headers on row 1
    - Column A format: *m/d/yyyy
    - Column B format: number with 2 decimal places
--->
<cfspreadsheet  action="read" src="c:/temp/Test.xlsx"  name="sheet" >

<cfset myQuery = QueryNew("")> 
<cfset QueryAddColumn(MyQuery, "Dollar", "Decimal", [ 403.45, 703.22, 103.55, 3.33, 13.75]  )>
<cfset QueryAddColumn(MyQuery, "MyDate", "date", [ parseDateTime("2000-03-11", "yyyy-mm-dd")
                                                , parseDateTime("2009-01-01", "yyyy-mm-dd")
                                                , parseDateTime("2013-09-21", "yyyy-mm-dd")
                                                , parseDateTime("2005-01-15", "yyyy-mm-dd")
                                                , parseDateTime("2003-07-22", "yyyy-mm-dd")] ) > 

<cfset spreadsheetAddRows(sheet, myQuery)>
<cfset spreadsheetFormatColumn(sheet, {dataFormat="m/d/yy"}, 1)>
<cfset spreadsheetFormatColumn(sheet, {dataFormat="##,####0.00"}, 2)>

<cfheader name="content-disposition" value="attachment; filename=Departures_(#DateFormat(now(),'mmddyy')#).xlsx">
<cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" variable="#spreadsheetReadBinary(sheet)#" reset="true">
person Leigh    schedule 26.05.2016
comment
Спасибо за помощь! Я могу подтвердить, что с помощью этого метода все выходит чистым. - person weggie; 26.05.2016