每当我尝试使用模板创建xls时,使用jxl API运行到奇怪的ArrayIndexOutOfBoundException。 这是我尝试使用的代码片段
private static void readWorkSheet()throws Exception{
File file = new File("C:\\reports\\");
Map template = new HashMap();
File[] listFiles = file.listFiles();
for(File file1:listFiles){
if(file1.getName().endsWith(".xls")){
System.out.println(" ==> "+file1.getName());
Workbook workbookTemplate = Workbook.getWorkbook(file1);
template.put(file1.getName(), workbookTemplate);
}
}
System.out.println("template "+template);
Workbook templateWorkBook = (Workbook)template.get("TestReport.xls");
Sheet readSheet = templateWorkBook.getSheet("Sheet1");
WritableWorkbook copy = Workbook.createWorkbook(new File("c://myfile_copy2.xls"));
WritableSheet sheet = copy.createSheet("Test", 0);
for (int i = 0; i < readSheet.getRows(); i++) {
for (int j = 0; j < readSheet.getColumns(); j++) {
Cell readCell = readSheet.getCell(j, i);
CellFormat readFormat = readCell.getCellFormat();
if(readFormat != null && readCell.getContents() != null && readCell.getContents() != ""){
WritableCell newCell = new Label(i,j,readCell.getContents());
WritableCellFormat newFormat = new WritableCellFormat(readFormat);
newCell.setCellFormat(newFormat);
System.out.println("details of cell ["+i+", "+j+"]"+" Name = "+readCell.getContents());
System.out.println("details of newCell ["+i+", "+j+"]"+" Name = "+newCell.getContents());
sheet.addCell(newCell);
}
}
}
copy.write();
copy.close();
}
不确定我在这里错过了什么!!!
异常我遇到了
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 56
at jxl.biff.IndexMapping.getNewIndex(IndexMapping.java:68)
at jxl.biff.XFRecord.rationalize(XFRecord.java:1667)
at jxl.biff.FormattingRecords.rationalize(FormattingRecords.java:443)
at jxl.write.biff.WritableWorkbookImpl.rationalize(WritableWorkbookImpl.java:1023)
at jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:701)
at com.jxl.test.JXLTest.readWorkSheet(JXLTest.java:83)
at com.jxl.test.JXLTest.main(JXLTest.java:30)
答案 0 :(得分:3)
我面临同样的问题。但只有当我尝试通过同一个类创建多个excel文件时才会发生这种情况。意味着如果我通过一个junit测试创建两个文件就会发生。如果我通过两个单独的单元测试类来完成这一切,一切正常。我只是在jxl代码中搜索一种强引用。
在那之前我找到了一个解决方法:
WorkbookSettings wbSettings = new WorkbookSettings();
wbSettings.setRationalization(false);
由于FormattingRecords.rationalize()方法而出现问题。上面的设置合理化过程的开关。 DateFormats和NumberFormats等将起作用但你将通过这样做松开单元格格式的WritableFonts。
敬请关注 - 也许我会找到更多。
......我发现了更多: 主要问题是jxl.biff.Fonts类没有正确重新初始化,只包含4个默认的FontRecord实体。我挖得更深一点,发现在XFRecord类的initialize方法中有一个if语句:
if (!font.isInitialized())
{
fonts.addFont(font);
}
第一次没有初始化字体,这里将成功添加。对于所有其他迭代,字体被初始化并且不会被添加。不知道谁持有XFRecords以及为什么它没有正确刷新。但我发现了一个有效的解决方法:
@SuppressWarnings("unchecked")
private void adjustUsedFonts(WritableWorkbook workbook) throws NoSuchFieldException, IllegalAccessException {
WritableWorkbookImpl workbookImpl = (WritableWorkbookImpl) workbook;
Field fontsField = WritableWorkbookImpl.class.getDeclaredField("fonts");
fontsField.setAccessible(true);
Fonts fonts = (Fonts) fontsField.get(workbookImpl);
Field fontsListField = Fonts.class.getDeclaredField("fonts");
fontsListField.setAccessible(true);
ArrayList<FontRecord> fontRecords = (ArrayList<FontRecord>) fontsListField.get(fonts);
// just to get to know which fonts are available
for (FontRecord fontRecord : fontRecords) {
logger.info("found font: name={}; size={}", fontRecord.getName(), fontRecord.getPointSize());
}
// DON'T DO THIS HARDCODED LIKE THIS
// BUT CHECK IF YOUR FONTS ARE AVAILABLE AND ADD IF NOT
if (fontRecords.size() == 4) {
logger.info("only 4 fonts available - add necessary ones");
fontRecords.add(tableDefaultFont);
}
}
我把这个方法放在调用workbook.write方法之前。并且它可以使用所有字体。 我知道这是一个黑客,没有好的解决方案。这就是为什么我会在他们的Ticket-Queue中打开一个问题(黑客只针对那些不能等到修复可用的人)。
我使用了这个版本的jxl,它似乎是最新的:
groupId:net.sourceforge.jexcelapi
artifactId:jxl
版本:2.6.12
此外: 如果您有多个自己的字体,您还需要使用其fontIndex以正确的顺序添加它。否则字体会混淆。我写了一个有用的方法来找出正确的索引:
private void determineFontIndizesOfOwnFonts(WritableWorkbook workbook) throws NoSuchFieldException, IllegalAccessException {
WritableWorkbookImpl workbookImpl = (WritableWorkbookImpl) workbook;
Field frField = WritableWorkbookImpl.class.getDeclaredField("formatRecords");
frField.setAccessible(true);
FormattingRecords formRecords = (FormattingRecords) frField.get(workbookImpl);
Field xfRecordListField = FormattingRecords.class.getDeclaredField("xfRecords");
xfRecordListField.setAccessible(true);
ArrayList<XFRecord> xfRecords = (ArrayList<XFRecord>) xfRecordListField.get(formRecords);
logger.debug("amount of xfRecords: {}", xfRecords.size());
for (XFRecord curXfRecord : xfRecords) {
Font curFont = curXfRecord.getFont();
if (curFont.equals(tableHeaderFont)) {
logger.debug("font 'tableHeaderFont' info: idx={}, initialized={}, font[{}, {}px]", curXfRecord.getFontIndex(), curXfRecord.isInitialized(),
curFont.getName(), curFont.getPointSize());
if (!fontIdxToName.containsKey(curXfRecord.getFontIndex())) {
fontIdxToName.put(curXfRecord.getFontIndex(), tableHeaderFont);
}
}
if (curFont.equals(tableContentFont)) {
logger.debug("font 'tableContentFont' info: idx={}, initialized={}, font[{}, {}px]", curXfRecord.getFontIndex(), curXfRecord.isInitialized(),
curFont.getName(), curFont.getPointSize());
if (!fontIdxToName.containsKey(curXfRecord.getFontIndex())) {
fontIdxToName.put(curXfRecord.getFontIndex(), tableContentFont);
}
}
if (curFont.equals(tableImportantOrFooterFont)) {
logger.debug("font 'tableImportantOrFooterFont' info: idx={}, initialized={}, font[{}, {}px]", curXfRecord.getFontIndex(),
curXfRecord.isInitialized(), curFont.getName(), curFont.getPointSize());
if (!fontIdxToName.containsKey(curXfRecord.getFontIndex())) {
fontIdxToName.put(curXfRecord.getFontIndex(), tableImportantOrFooterFont);
}
}
}
}
然后只需按正确的顺序添加,请参阅其他方法。
答案 1 :(得分:0)
我也遇到了同样的问题。我正在使用JXL库2.6.12。
我正在使用两个不同的“.xls”文件,并应用了3种不同的WritableCellFormat样式。当我在“.xls”单元格中使用相同的三个可写格式对象时,就会导致问题
解决方案:
我创建了一个方法,我在为WritableCellFormat创建不同的对象。我分别在“.xls”工作簿创建上调用了这个方法。这有效,两个“.xls”文件工作簿创建都是使用不同的可写单元格格式对象完成的。
答案 2 :(得分:0)
在2.4.2和2.6.12版本中,我也都遇到了这个问题。
我不再通过将任何Fonts / DisplayFormats / WritableCellFormats对象设为静态来解决此问题。
说句公道话,我确实在这里找到了解决方案: http://www.logikdev.com/2010/01/18/writablefont-doesnt-like-to-be-static/ 其中还引用了JExcelAPI常见问题解答:
来自http://jexcelapi.sourceforge.net/resources/faq/
”而且,请勿将单元格格式声明为静态也是很重要的。当单元格格式添加到工作表时,将为其分配一个内部索引号。如果您有两个线程(例如在Web环境中)编写两个不同的电子表格,则格式编号将变得混乱,结果工作表可能已损坏或不正确。”