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

编辑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) 

这是相关的代码:

       

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


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

给出以下消息:org.apache.poi.hssf.util.HSSFColor.getIndexHash()Ljava / util /哈希表;

错误代码:

 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) 

在评论该行时,它现在再次崩溃:

错误代码:

 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) 

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

如果查看exception,它会清楚地显示当CF调用尝试自动调整列大小的POI方法时(在添加查询数据之后),会出现问题。 快速搜索发现了几个与HSSFSheet.autoSizeColumn类似的ArrayIndexOutOfBoundsException错误的报告, 就像这个 (恰好提到ColdFusion):

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

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

我以前成功地使用过cfspreadsheet,但是它没有生成带有标题的电子表格(并且它还有一个缺点,即需要创建一个临时文件来提供服务。)

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

如果你从代码中退一步并检查抛出的错误,你可以从java文档中得到这个 , 这是另一个参考

抛出以指示已使用非法索引访问数组。 索引为负数或大于或等于数组的大小。

该错误还会显示尝试的非法索引值: -32735

现在您的问题是您没有在代码中指定索引值,因为您使用的是ColdFusion函数。 该函数( SpreadsheetAddRows )正在尝试将您的查询结果转换为数组,然后将每个值附加到Excel电子表格的行中。 它正在利用底层Java运行时来执行这些任务,这就是抛出错误。 所以我担心你遇到的这种限制有点困难。 您可以尝试升级运行ColdFusion安装的JRE版本,以查看问题是否已在较新版本中得到解决。 我相信ColdFusion 9附带Java 1.6.0_14, 请看这里 。 由于DOS漏洞补丁,你应该至少运行1.6.0_24。 看起来它们现在已达到1.6.0_38,但您必须检查Adobe支持。

如果升级JRE无法解决问题,那么我相信您需要更改ColdFusion代码以避免此问题。 您声明使用CFSpreadSheet标记成功。 或者您可以使用不同的方式将查询结果传递给SpreadsheetAddRows函数。 (虽然我假设你已经筋疲力尽了。)可能循环查询并构建自己的数组或循环查询并一次添加一行。 我意识到这可能不是最佳的,但在尝试了几种不同的方式后,人们希望能够成为最佳选择。

我还要在你的post中添加ColdFusion标签(没有版本号),以便更多地关注它。

UPDATE

只想跟进ColdFusion 9支持的Java版本。我发现Charlie Arehart撰写的这篇博客文章讨论了Adobe对ColdFusion服务器的Java升级的立场。 这链接到官方Adobepost,其中声明将支持任何次要版本升级。 因此对于ColdFusion 9“支持所有未来的JDK 1.6.0_x版本”。

(摘自http://poi.apache.org/spreadsheet/quick-guide.html )

请注意,工作簿中唯一字体的最大数量限制为32767(最大正短)。 您应该在应用程序中重复使用字体,而不是为每个单元格创建字体。 例子:

错误:

 for (int i = 0; i < 10000; i++) { Row row = sheet.createRow(i); Cell cell = row.createCell((short) 0); CellStyle style = workbook.createCellStyle(); Font font = workbook.createFont(); font.setBoldweight(Font.BOLDWEIGHT_BOLD); style.setFont(font); cell.setCellStyle(style); } 

正确:

 CellStyle style = workbook.createCellStyle(); Font font = workbook.createFont(); font.setBoldweight(Font.BOLDWEIGHT_BOLD); style.setFont(font); for (int i = 0; i < 10000; i++) { Row row = sheet.createRow(i); Cell cell = row.createCell((short) 0); cell.setCellStyle(style); } 

无论如何,你也可以试试这个:

 org.apache.poi.hssf.usermodel.HSSFOptimiser.optimiseCellStyles(HSSFWorkbook) 

根据我对数组的经验,当你得到一个OutOfBoundsexception时,通常是因为我“超出”了数组 – 也就是说,我比索引中的项目总数多了一个。 这通常是因为我忘记了当数组以0开头时,我必须只循环到数组长度 – 1。

确保您没有循环超过arrays的长度。