2011-12-06 15 views
2

jxl APIを使用して、奇妙なArrayIndexOutOfBoundExceptionを実行するテンプレートを使用してxplを作成しようとしているときはいつでも。ここ は、私がArrayIndexOutOfBoundExceptionあるシートから別のシートにコンテンツをコピーしようとするとjxl apiが発生する

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

上記のスタックトレースは、いずれのコードも参照していないようです。あなたは例外からの完全なスタックトレースを含めましたか? –

+0

完全な例外トレースを追加しました – Amit

+0

try/catchでコードを囲みます。ファイルがC:\で作成されていますか? – Alfabravo

答えて

3

に実行しています。しかし、同じクラスで複数のExcelファイルを作成しようとする場合にのみ発生します。私は1つのjunitテストによって2つのファイルを作成する場合、それが発生することを意味します。 2つの別々のユニットテストクラスでこれを行うと、すべて正常に動作します。私はjxlコードで一種の強力な参照を探しています。原因FormattingRecords.rationalize()メソッドに

WorkbookSettings wbSettings = new WorkbookSettings(); 
wbSettings.setRationalization(false); 

問題が発生します。
は、それまで私は、回避策を見つけました。この設定は、合理化プロセスを切り替えます。 DateFormatsとNumberFormatsなどは動作しますBUTこれを実行すると、セル形式のWritableFontsが失われます。

お待ちください - 多分私はもっと見つけるでしょう。

...見つかったのは jxl.biff.Fontsクラスが正しく再初期化されず、デフォルトのFontRecordエンティティが4つしかないという主な問題があります。私は少し深く掘って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

ADDITION独自のフォントよりも、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); 
      } 
     } 
    } 
} 

はその後、その後ちょうど右の順にそれを追加します。私は、右のインデックスを見つけるために役立つ方法を書きました。

+0

であり、Fontsクラスが合理化して重複を見つけようとすると問題が発生するため、デフォルトのフォントを使用しないことは常に良いことです。特に上記のハックのために良いアドバイスがある。そうしないとアサーションが起こるからだ。 – MattW

0

私も同じ問題に直面していました。私はJXLライブラリ2.6.12を使用しています。 私は2つの異なる ".xls"ファイルを扱い、3つの異なるWritableCellFormatスタイルを適用していました。両方の ".xls"セルで同じ書式設定可能な3つの書式オブジェクトを使用していたときに問題が発生していました。

解決方法:
私はWritableCellFormat用に異なるオブジェクトを作成する方法を作成しました。両方の ".xls"ワークブックの作成で、このメソッドを個別に呼び出しました。これは、両方の ".xls"ファイルのワークブック作成は、書き込み可能なセル形式の異なるオブジェクトで行われます。

関連する問題