Java 尝试将内容从一张工作表复制到另一张工作表时,ArrayIndexOutofBound异常与jxl api
每当我尝试使用模板创建xls时,都会使用运行在奇怪的ArrayIndexOutOfBoundException中的JXLAPI。 下面是我试图使用的代码片段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
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();
}
}