EDIT3:感谢@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)
以下是相关代码:
<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">
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)
评论该行,它现在再次崩溃:
<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)
答案 0 :(得分:3)
我怀疑它与CF或JRE版本完全无关。至少不是直接的。这听起来像是POI中的一个错误。
如果查看异常,它会清楚地显示当CF调用尝试自动调整列大小的POI方法时(在添加查询数据之后),会出现问题。快速搜索发现了一些与ArrayIndexOutOfBoundsException
like this one发生类似HSSFSheet.autoSizeColumn
错误的报告(恰好提及ColdFusion):
如果您尝试使用org.apache.poi.hssf.usermodel.HSSFSheet和 设置超过32767后,在列上的方法autosizecolumn(int) 然后抛出ArrayOutOfBoundsException。
根据错误报告,问题存在于3.5版本中,这是ColdFusion 9中包含的相同(主要)版本。其中一位POI开发人员表示该问题已在更高版本中得到修复。所以你可以尝试更新POI jar。除此之外,如果您可以组合一个再现问题的测试用例,您可能需要提交bug report。
我之前使用cfspreadsheet成功,但事实并非如此 生成一个带标题的电子表格(它也有一个缺点 需要创建一个临时文件来服务。)
cfspreadsheet
可能不会尝试像spreadsheetAddRows
那样自动调整列的大小,因此不会发生错误。所以明显的解决方法(而不是一个很好的解决方法)是避免尝试调整列宽的函数。
答案 1 :(得分:1)
如果您退出代码并检查错误,则会获得this from the java documentation和here is another reference
抛出以指示已使用非法索引访问数组。索引为负数或大于或等于数组的大小。
该错误还会显示尝试的非法索引值:-32735
现在您的问题是您没有在代码中指定索引值,因为您使用的是ColdFusion函数。该函数(SpreadsheetAddRows
)正在尝试将查询结果转换为数组,然后将每个值附加到Excel电子表格的行中。它正在利用底层Java运行时来执行这些任务,这就是抛出错误。所以我担心你遇到这种限制时会有点困惑。您可以尝试升级运行ColdFusion安装的JRE版本,以查看问题是否已在较新版本中得到解决。我相信ColdFusion 9附带Java 1.6.0_14 see here。由于DOS vulnerability patch,您应该至少运行1.6.0_24。它看起来高达1.6.0_38 now,但您必须检查Adobe支持。
如果升级JRE无法解决问题,那么我相信您需要更改ColdFusion代码以避免此问题。您声明使用CFSpreadSheet
标记取得了成功。或者,您可以使用不同的方式将查询结果传递给SpreadsheetAddRows
函数。 (虽然我假设你已经筋疲力尽了。)可能循环查询并构建自己的数组或循环查询并一次添加一行。我意识到这可能不是最佳的,但在尝试了几种不同的方式之后,人们希望能够成为最佳选择。
我还要在你的帖子中添加ColdFusion标签(没有版本号),以便更多地关注它。
<强>更新强>
只想跟进ColdFusion 9支持的Java版本。我发现this blog entry by Charlie Arehart讨论了Adobe对ColdFusion服务器的Java升级的立场。这链接到official Adobe post here,表示将支持任何次要版本升级。因此对于ColdFusion 9“支持所有未来的JDK 1.6.0_x版本。”
答案 2 :(得分:1)
(摘自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)
答案 3 :(得分:0)
根据我对数组的经验,当你得到OutOfBounds
异常时,通常是因为我“超出”了数组 - 也就是说,我比索引中的项目总数多了一个。这通常是因为我忘记了当数组以0开头时,我必须只循环到数组长度 - 1.
确保没有超过数组的长度。