添加大型查询时,如何修复SpreadSheetAddRows函数崩溃?

Ale*_*lex 7 java arrays coldfusion apache-poi coldfusion-9

编辑3:感谢@Leigh的帮助我将问题缩小到了查询中的日期列.使用原始代码集和POI时,当SpreadSheetAddRows()尝试添加包含类似日期的单元格的非常大的查询时,页面崩溃.我在这里做了一个错误报告:https://bugbase.adobe.com/index.cfm?event = bug &id = 3432184.


我有一个查询,我添加到一个spreadhseet对象,当查询具有非常多的行(在此示例中为18583)时似乎出错.确切的错误如下:

java.lang.ArrayIndexOutOfBoundsException: -32735
at java.util.ArrayList.get(ArrayList.java:324)
at org.apache.poi.hssf.model.WorkbookRecordList.get(WorkbookRecordList.j ava:50)
at org.apache.poi.hssf.model.Workbook.getExFormatAt(Workbook.java:787)
at org.apache.poi.hssf.usermodel.HSSFCell.getCellStyle(HSSFCell.java:901 )
at org.apache.poi.hssf.usermodel.HSSFSheet.autoSizeColumn(HSSFSheet.java :1727)
at coldfusion.excel.Excel.autoResize(Excel.java:1246)
at coldfusion.excel.Excel.autoResize(Excel.java:1240)
at coldfusion.excel.Excel.addRows(Excel.java:1214)
at coldfusion.runtime.CFPage.SpreadSheetAddRows(CFPage.java:7089) at coldfusion.runtime.CFPage.SpreadSheetAddRows(CFPage.java:7076)
Run Code Online (Sandbox Code Playgroud)

这是相关的代码:

<cfset xls = spreadsheetNew()>
<cfset spreadsheetAddRow(xls, arrayToList( qryTest.getMeta().getColumnLabels() ))>
<cfset SpreadsheetFormatRow(xls, {bold=true,fgcolor="brown",color="white"}, 1)>
<cfset SpreadsheetAddRows(xls, qryTest)>
<cfheader name="Content-Disposition" value="attachment; filename=#filename#">
<cfcontent variable="#spreadsheetReadBinary(xls)#" reset="yes" type="application/vnd.ms-excel">
Run Code Online (Sandbox Code Playgroud)

编辑:我之前成功使用过cfspreadsheet,但它没有生成带有标题的电子表格(并且它还有需要创建临时文件以供服务的缺点.)


EDIT2:关注@Leigh建议我更新了CF9/lib文件夹中的POI.现在错误已更改为以下内容:

<cfset SpreadsheetFormatRow(xls, {bold=true,fgcolor="brown",color="white"}, 1)> 给出以下消息:org.apache.poi.hssf.util.HSSFColor.getIndexHash()Ljava/util/Hashtable;

错误代码:

java.lang.NoSuchMethodError:
org.apache.poi.hssf.util.HSSFColor.getIndexHash()Ljava/util/Hashtable;
at coldfusion.excel.Excel.getHSSFColor(Excel.java:2094)
at coldfusion.excel.Excel.findFont(Excel.java:2237)
at coldfusion.excel.Excel.getCellStyle(Excel.java:2318)
at coldfusion.excel.Excel.formatRow(Excel.java:2948)
at coldfusion.excel.Excel.formatRow(Excel.java:2963)
at coldfusion.excel.Excel.formatRow(Excel.java:2981)
at coldfusion.runtime.CFPage.SpreadSheetFormatRow(CFPage.java:7268)
Run Code Online (Sandbox Code Playgroud)

在评论该线路时,它现在再次崩溃: <cfset SpreadsheetAddRows(xls, qryTest)>

错误代码:

java.lang.IllegalStateException: The maximum number of cell styles was exceeded. You can define up to 4000 styles in a .xls workbook 
at org.apache.poi.hssf.usermodel.HSSFWorkbook.createCellStyle(HSSFWorkbook.java:1120) 
at org.apache.poi.hssf.usermodel.HSSFWorkbook.createCellStyle(HSSFWorkbook.java:73) 
at coldfusion.excel.Excel.addRow(Excel.java:1323)
at coldfusion.excel.Excel.addRows(Excel.java:1203) 
at coldfusion.runtime.CFPage.SpreadSheetAddRows(CFPage.java:7089) 
at coldfusion.runtime.CFPage.SpreadSheetAddRows(CFPage.java:7076) 
Run Code Online (Sandbox Code Playgroud)

Lei*_*igh 3

我怀疑它与 CF 或 JRE 版本完全无关。至少不是直接的。听起来像是 POI 中的一个错误。

如果您查看该异常,它清楚地表明当 CF 调用尝试自动调整列大小的 POI 方法(添加查询数据后)时会出现问题。快速搜索后发现了几份类似错误的报告ArrayIndexOutOfBoundsException恰好提到了 ColdFusion):HSSFSheet.autoSizeColumn

如果在设置超过 32767 个单元格后尝试在列上使用 org.apache.poi.hssf.usermodel.HSSFSheet 和方法 autosizecolumn(int),则会引发 ArrayOutOfBoundsException。

根据错误报告,该问题存在于版本 3.5 中,该版本与 ColdFusion 9 中包含的相同(主要)版本。其中一位 POI 开发人员建议该问题已在更高版本中修复。所以你可以尝试更新 POI jar。除此之外,如果您可以组合一个重现问题的测试用例,您可能需要提交错误报告

我之前确实成功使用了 cfspreadsheet,但它不会生成带有标题的电子表格(而且它还有一个缺点,即需要创建一个临时文件来提供服务。)

cfspreadsheet可能不会像spreadsheetAddRows那样尝试自动调整列大小,因此不会发生错误。因此,明显的解决方法(但不是一个很好的方法)是避免尝试调整列宽大小的函数。

  • 这是已知的 [Excel 限制](http://support.microsoft.com/kb/213904)。根据我的经验,您必须小心在 POI 中创建样式的方式,以免超出 Excel 的最大值。例如,假设您有 3 列,每列的整个列都使用相同的“格式”。如果您为*每个*单元格创建新样式,您可以轻松突破最大限制。推荐的方法是创建“3”样式并为每列中的所有单元格重用它们。但是,我不确定 CF 电子表格函数是否正在这样做......从错误消息来看,可能没有。但我必须检查一下。 (2认同)