3

我有一个客户要求从查询中生成 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 确认?

在 RHEL 5 上运行的 Adob​​e ColdFusion v10。

每个请求这里是一些使用queryNew 的代码,它将生成代码日期和货币。

第一步:我创建了一个第一行冻结的 Excel 文件,它有列标题。第一列已被指定为日期,格式为长日期-mm/dd/yyy;第二列是设置为货币的美元。

我阅读了该文件,然后填写行并将文件流式传输给用户以供下载。

<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 表格上没有收到这样的警告。

4

1 回答 1

1

使用日期单元格时,CF 可能有点古怪。当手动输入值时,Excel 非常擅长猜测正确的单元格类型。但是,使用 CF 有点棘手。由于 CF 是相对无类型的,它并不总是正确地匹配值和单元格类型。使用利用查询对象而不是 SpreadsheetSetCellValue() 的函数通常会产生更好的结果。很可能是因为查询对象同时包含和数据类型。尽管从 CF11 开始,SpreadsheetSetCellValue支持一个新的数据参数,它允许您指定值和单元格数据类型。由于您使用的是 CF10,因此请尝试使用SpreadsheetAddRows来填充值。

关于文件损坏的警告,是由于实际文件内容和下载代码中的文件扩展名不匹配造成的。该代码正在读取一个.xlsx文件,但下载声称它是一个 .xlsx 文件。xls(应用程序/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">
于 2016-05-26T18:26:37.610 回答