添加大型查询时,如何修复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)
根据我对数组的经验,当你得到一个OutOfBounds
exception时,通常是因为我“超出”了数组 – 也就是说,我比索引中的项目总数多了一个。 这通常是因为我忘记了当数组以0开头时,我必须只循环到数组长度 – 1。
确保您没有循环超过arrays的长度。