2016-09-16 203 views
0

我想通过以下方式流Excel中的数据会导致损坏的Excel文件

<cfsavecontent variable="xlsOutput"> 
    //My data 
</cfsavecontent> 

<cfsetting enablecfoutputonly="no" showDebugOutput="false"> 

<cfheader name="ContentDisposition value='attachment;filename="#xls_file#.xls"'> 

<cfcontent type="application/vnd.ms-excel" reset="true" variable="#ToBinary(ToBase64(xlsOutput))#"> 

虽然附件已拿出很好的Excel格式发送Excel数据,当我试图打开它,它抛出以下错误

文件已损坏,无法打开

此错误信息后,T他甚至没有显示内容就关闭文件。

我知道我很亲密,但我不知道我在哪里得到它全部错误?

+0

(编辑)不是讽刺,但你在发布之前是否对该错误消息进行搜索?有很多关于该错误常见原因的线索。通常与Excel安全设置有关。另外,如果这是实际的代码,'cfheader'很害羞,而且头文件中有一个拼写错误。 – Leigh

+0

嗨Leigh ..是的,我在论坛上查看了其他相关的其他问题,但没有找到正确的答案。如果您能看到相关的内容,请将我引导至特定问题,并且您可以自由关闭此主题。我只是需要一个正确的答案,我的真正的问题,没有更多的东西:) – Tej

回答

-2

回来之前我们使用下面的技术来实现这一点。现在我会看看cfspreadsheet标签。

下面是我们所做的:首先将变量保存到htm文件,然后使用excel打开它。它仍然会向用户提出一个不太好看的问题:“您尝试打开的文件采用扩展名指定的不同格式,”等等。下面是解决方案...

<cfsavecontent variable="xlsOutput"> 
    //My data 
</cfsavecontent> 

<cffile action="WRITE" file="D:\wwwroot\yourwebsite\test.htm" output="#ToBinary(ToBase64(xlsOutput))#"> 

<cfheader name="Content-Type" value="xls"> 
<cfheader name="Content-Disposition" value="attachment; filename=report.xls"> 
<cfcontent type="application/vnd.ms-excel" file="D:\wwwroot\yourwebsite\test.htm" deletefile="No"> 
+0

*它仍然会给用户一个问题... *替换一个错误信息是不是一个真正的解决方案;-)增加安全功能让更新版本的Excel远远不能容忍旧的“欺骗浏览器进入思维html是电子表格”的伎俩。唯一可靠的解决方案是生成*真实*电子表格。 – Leigh

+0

我同意,这是一个解决方法,不太适合商业应用。我不相信在cfspreadsheet标签之前CF可以很好地工作......另外,我的示例中生成的文件实际上会在提示之后由excel打开,而与问题中的致命错误相关。 –

+0

全部取决于版本。有些人仍然会遇到问题。旧的html技巧*曾经是一个可行的选择。不幸的是,随着新版本越来越宽容,越来越可能导致错误或可怕的警告,这不是一个愉快的用户体验。底线,你的第一个建议是更好的选择,即创建一个真正的电子表格。 – Leigh

1

我想你的toBinary()和tobase64()可能会受到阻碍。

这是一个使用cfspreadsheet,spreadsheetAddColumn和SpreadsheetAddRows的工作示例。

<!--- FILE ---> 
<cfset myFile = expandPath('accountslog_#dateFormat(url.datefrom, 'yyyy-mm-dd')#_#dateFormat(dateAdd('d',1,url.dateto), 'yyyy-mm-dd')#.xls') /> 

<cfset thisSheet = SpreadsheetNew("accountLog") /> 

<cfquery name="all"> 
SELECT 
     accountlog.dateTime 
     , accounts.firstname 
     , accounts.lastname 
     , accounts.email 
     , ... more columns 
FROM accountlog INNER JOIN accounts on accountlog.accountid = accounts.id 
WHERE dateTime 
     BETWEEN <cfqueryparam value="#url.dateFrom#" cfsqltype="cf_sql_timestamp"> 
     AND <cfqueryparam value="#dateAdd('d',1,url.dateTo)#" cfsqltype="cf_sql_timestamp"> 

    <cfif url.accountid neq ''> 
     AND accounts.id = <cfqueryparam value="#url.accountid#" cfsqltype="cf_sql_varchar"> 
    </cfif> 
ORDER BY datetime 
</cfquery> 

<cfset thisTable = 'accountLog'> 
<cfset thisSheet = SpreadsheetNew(thisTable) /> 

<!--- COLUMN HEADERS, droooool ---> 
<cfloop array="#all.getMetaData().getColumnLabels()#" index="c"> 
    <cfset spreadsheetAddColumn(thisSheet, c) /> 
</cfloop> 

<!--- ADD THE DATA ---> 
<cfset SpreadsheetAddRows(thisSheet, all) /> 

<!--- SAVE THE SHEET ---> 
<cfspreadsheet 
    action="update" 
    filename="#myFile#" 
    name="thisSheet" 
    sheetname="#thisTable#" /> 

<cfheader name="Content-Disposition" value="attachment; filename=#listLast(myFile, '\')#" /> 
<cfcontent type="application/msexcel" reset="yes" file="#myFile#" deleteFile="yes" /> 
+1

生成临时文件时,请务必使用* unique *文件名。否则,该文件可能会被另一个同时运行的线程覆盖。保持显示名称的日期戳记逻辑,但使用唯一的东西,比如'createUUID()'作为物理文件。另外,如果您只是编写一次性文件,请使用SpreadSheetWrite()或''。根据我的经验[''cfspreadsheet action = update' is buggy](http://stackoverflow.com/questions/15010472/spreadsheet-cell-formatting/15027832#15027832),并且这里不需要。 – Leigh