Java 尝试将内容从一张工作表复制到另一张工作表时,ArrayIndexOutofBound异常与jxl api

Java 尝试将内容从一张工作表复制到另一张工作表时,ArrayIndexOutofBound异常与jxl api,java,xls,jxl,Java,Xls,Jxl,每当我尝试使用模板创建xls时,都会使用运行在奇怪的ArrayIndexOutOfBoundException中的JXLAPI。 下面是我试图使用的代码片段 private static void readWorkSheet()throws Exception{ File file = new File("C:\\reports\\"); Map template = new HashMap(); File[] listFi

每当我尝试使用模板创建xls时,都会使用运行在奇怪的ArrayIndexOutOfBoundException中的JXLAPI。 下面是我试图使用的代码片段

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(); 
        }

我也面临同样的问题。但是,只有当我试图用同一个类创建多个excel文件时,才会发生这种情况。意味着如果我通过一个junit测试创建了两个文件,就会发生这种情况。如果我通过两个独立的单元测试类来实现这一点,那么一切都可以正常工作。我只是在jxl代码中搜索一种强引用。
在此之前,我找到了一个解决办法:

WorkbookSettings wbSettings = new WorkbookSettings();
wbSettings.setRationalization(false);
@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);
    }
}
出现此问题的原因是FormattingRecords.rationalize()方法。此设置高于合理化过程的开关。DateFormats和NumberFormats等将起作用,但这样做会使单元格格式失去可写字体

请继续关注,也许我会发现更多

。。。我发现了更多: 主要问题是jxl.biff.Fonts类没有正确重新初始化,只包含4个默认FontRecord实体。我深入研究了一下,发现在XFRecord类的initialize方法中有一个if语句:

if (!font.isInitialized())
{
   fonts.addFont(font);
}
这是第一次字体未初始化,并将在此处成功添加。对于所有其他迭代,字体已初始化,不会添加。不知道谁持有XF记录,也不知道为什么不能正确刷新。但我找到了一个解决办法:

WorkbookSettings wbSettings = new WorkbookSettings();
wbSettings.setRationalization(false);
@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);
    }
}
@SuppressWarnings(“未选中”)
private void adjustUsedFonts(可写工作簿工作簿)引发NoSuchFieldException、IllegalAccessException{
WritableWorkbookImpl workbookImpl=(WritableWorkbookImpl)工作簿;
Field fontsField=WritableWorkbookImpl.class.getDeclaredField(“字体”);
fontsField.setAccessible(true);
字体字体=(字体)fontsField.get(workbookImpl);
Field fontsListField=Fonts.class.getDeclaredField(“字体”);
fontsListField.setAccessible(true);
ArrayList fontRecords=(ArrayList)fontsListField.get(fonts);
//只是为了了解哪些字体可用
用于(FontRecord FontRecord:fontRecords){
info(“找到的字体:name={};size={}”,fontRecord.getName(),fontRecord.getPointSize());
}
//不要这样硬编码
//但请检查字体是否可用,如果不可用,请添加
if(fontRecords.size()==4){
info(“只有4种字体可用-添加必要的字体”);
fontRecords.add(tableDefaultFont);
}
}
我将此方法放在调用workbook.write方法之前。而且所有字体都可用。 我知道这是一个黑客和没有好的解决办法。这就是为什么我会在他们的票证队列中打开一个问题(黑客只针对那些不能等到修复可用的人)

我使用了这个版本的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);
            }
        }
    }
}
private void determination contindizesofownFonts(可写工作簿工作簿)抛出NoSuchFieldException、IllegalAccessException{
WritableWorkbookImpl workbookImpl=(WritableWorkbookImpl)工作簿;
Field frField=WritableWorkbookImpl.class.getDeclaredField(“formatRecords”);
frField.setAccessible(true);
FormattingRecords formRecords=(FormattingRecords)frField.get(workbookImpl);
字段xfRecordListField=FormattingRecords.class.getDeclaredField(“xfRecords”);
xfRecordListField.setAccessible(true);
ArrayList xfRecords=(ArrayList)xfRecordListField.get(formRecords);
debug(“xfRecords的数量:{}”,xfRecords.size());
对于(XFRecord curXfRecord:xfRecords){
Font curFont=curxfreck.getFont();
if(curFont.equals(tableHeaderFont)){
logger.debug(“font'tableHeaderFont'info:idx={},initialized={},font[{},{}px]”,curXfRecord.getFontIndex(),curXfRecord.isInitialized(),
curFont.getName(),curFont.getPointSize());
如果(!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());
如果(!fontIdxToName.containsKey(curXfRecord.getFontIndex())){
fontIdxToName.put(curxRecord.getFontIndex(),tableContentFont);
}
}
if(curFont.equals(tableImportantOrFooterFont)){
logger.debug(“font'tableImportantOrFooterFont'info:idx={},initialized={},font[{},{}px]”,curxfreck.getFontIndex(),
curxRecord.isInitialized()、curFont.getName()、curFont.getPointSize());
如果(!fontIdxToName.containsKey(curXfRecord.getFontIndex())){
fontIdxToName.put(curxRecord.getFontIndex(),TableImportantorFooterFooterFont);
}
}
}
}

然后再按正确的顺序添加,参见其他方法。

我也面临同样的问题。我正在使用JXL库2.6.12。 我使用了两个不同的“.xls”文件,并应用了3种不同的WritableCellFormat样式。当我在两个“.xls”单元格中使用相同的三个可写格式对象时,这就导致了问题。


解决方案:
我创建了一个方法,为WritableCellFormat创建不同的对象。我分别在创建“.xls”工作簿时调用了此方法。这是因为“.xls”文件和工作簿都是用不同的可写单元格格式的对象创建的。

我刚才也遇到了这个问题,版本2.4.2和2.6.12都有

<
public class SomeExcelThing() {
   public createCell() {
      return new Cell(new Font());
   }
}
public class SomeExcelThing() {
   public createCell() {
      return new Cell(getMyFont());
   }

   private Font getMyFont() {
      return new Font();
   }
}