ColdFusion:如何在不将其保存为文件的情况下生成电子表格?

Joe*_*ose 4 coldfusion excel coldfusion-11

在ColdFusion应用程序中,我需要让用户将电子表格保存到他们的硬盘驱动器中.

我已经能够动态生成文件,将它们构建为XML或HTML表,应用application/vnd.ms-excelMIME类型,并使用.xls扩展名保存它们.

<cfheader name="Content-Disposition" value="attachment; filename=MySpreadsheet.xls"> 
<cfcontent type="application/vnd.ms-excel"> 
Run Code Online (Sandbox Code Playgroud)

但是当用户加载这样的文件时,他们总是会收到恼人的消息(由于Excel的扩展强化功能):

您尝试打开的文件"_____.xls"的格式与文件扩展名指定的格式不同.在打开文件之前,请验证文件是否已损坏且是否来自受信任的源.你想现在打开文件吗?

我宁愿避免这个消息.

我理解<cfspreadsheet>标签和SpreadsheetWrite()函数将生成一个不显示此消息的正确Excel文件 - 但它们都需要一个参数来指示服务器上文件的写入位置.因为下载可能包含敏感信息,并且因为一旦将文件写入服务器后我就无法轻松实施安全性,所以我不想创建这样的文件 - 即使是暂时的.(我知道我可以提供密码,但这不是生成Excel文件后将使用的业务流程环境中的理想解决方案.)

如何在不先将文件写入文件的情况下生成Excel文件并提示下载?

Joe*_*ose 6

在为此问题搜索Stack Overflow和其他资源之后,我终于在另一个问题的上下文中找到了解决方案.我现在在这里发布问题和我的发现,希望其他人比我更容易找到这些信息.

解决方案围绕标记中的SpreadsheetReadBinary()函数和variable属性<cfcontent>.

我使用ColdFusion电子表格函数构建了一个电子表格,然后将以下内容放在文件的末尾(与我在推文<cfheader>和<cfcontent>开头的习惯相反).

<cfheader name="Content-Disposition" value="attachment; filename=MySpreadsheet.xls"> 
<cfcontent type="application/vnd.ms-excel" variable="#SpreadsheetReadBinary( objSpreadsheet )#">
Run Code Online (Sandbox Code Playgroud)

如果有人从更多细节中受益,.cfm文件中的以下内容将构建电子表格并提示下载为正确格式的Excel文件:

<!---
Building a spreadsheet that looks like:

+-----+-----+-----+
| FOO | BAR | BAZ |
+-----+-----+-----+
| 101 | 102 | 103 |
+-----+-----+-----+
| 201 | 202 | 203 |
+-----+-----+-----+

--->


<!--- Create a new spreadsheet. --->
<cfset objSpreadsheet = SpreadsheetNew()>

<!--- Create and format the header row. --->
<cfset SpreadsheetAddRow( objSpreadsheet, "FOO,BAR,BAZ" )>
<cfset SpreadsheetFormatRow( objSpreadsheet, {bold=TRUE, alignment="center"}, 1 )>

<!--- Populate the spreadsheet. --->
<!--- In a real situation, this would be looped programmatically; it is done cell-by-cell here for readability. --->
<cfset SpreadsheetSetCellValue( objSpreadsheet, 101, 2, 1, "NUMERIC" ) >
<cfset SpreadsheetSetCellValue( objSpreadsheet, 102, 2, 2, "NUMERIC" ) >
<cfset SpreadsheetSetCellValue( objSpreadsheet, 103, 2, 3, "NUMERIC" ) >
<cfset SpreadsheetSetCellValue( objSpreadsheet, 201, 3, 1, "NUMERIC" ) >
<cfset SpreadsheetSetCellValue( objSpreadsheet, 202, 3, 2, "NUMERIC" ) >
<cfset SpreadsheetSetCellValue( objSpreadsheet, 203, 3, 3, "NUMERIC" ) >

<cfheader name="Content-Disposition" value="attachment; filename=MySpreadsheet.xls"> 
<cfcontent type="application/vnd.ms-excel" variable="#SpreadsheetReadBinary( objSpreadsheet )#"> 
Run Code Online (Sandbox Code Playgroud)