2011-12-06 2 views
2

이상한 ArrayIndexOutOfBoundException로 실행되는 jxl API를 사용하여 xls을 만들 때 템플릿을 사용하려고 할 때마다. 여기 코드의 조각 나는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 파일을 만들려고 할 때만 발생합니다. 만약 내가 하나의 junit 테스트에 의해 두 파일을 만들면 그것을 의미합니다. 두 개의 개별 단위 테스트 클래스로이 작업을 수행하면 모든 것이 잘 작동합니다. 난 그냥 jxl 코드에서 일종의 강력한 참조를 찾고있다. 때문에 FormattingRecords.rationalize() 메소드에

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

문제가 발생합니다 :
는 그 때까지 나는 해결책을 찾아 냈다. 위의 설정은 합리화 프로세스를 전환합니다. DateFormats 및 NumberFormats 등이 작동합니다 BUT 이렇게하면 셀 형식의 WritableFonts가 느슨해집니다.

지켜봐 주시기 바랍니다. 아마도 더 많이 찾을 수 있습니다.

... 찾았습니다. 주된 문제는 jxl.biff.Fonts 클래스가 올바르게 다시 초기화되지 않고 4 개의 기본 FontRecord 엔터티 만 포함된다는 것입니다. 나는 조금 더 깊이 파고와 XFRecord 클래스의 초기화 방법에 if 문이 있음을 발견 폰트가 초기화되지 않고 성공적으로 여기에 추가 될 매우 처음으로

if (!font.isInitialized()) 
{ 
    fonts.addFont(font); 
} 

. 다른 모든 반복의 경우 글꼴이 초기화되고 추가되지 않습니다. XFRecords를 보유한 사람이 누구인지 알 수 없으며 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 메서드를 호출하기 전에 넣습니다. 그리고 모든 글꼴을 사용할 수 있습니다. 저는 이것이 해킹이고 좋은 해결책이 아니라는 것을 압니다. 이것이 티켓 대기열에서 문제를 열어야하는 이유입니다 (해킹은 수정이 가능할 때까지 기다릴 수없는 사람들을위한 것입니다).

나는 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를 사용하고있다. 두 개의 다른 ".xls"파일로 작업 중이며 3 개의 다른 WritableCellFormat 스타일을 적용하고있었습니다. 두 개의 ".xls"셀에서 같은 세 가지 쓰기 가능한 형식 개체를 사용할 때 문제가 발생했습니다.

솔루션 :
WritableCellFormat에 대해 다른 개체를 만드는 방법을 만들었습니다. 이 방법은 ".xls"통합 문서 작성과 별도로 호출되었습니다. 이 기능은 ".xls"파일 모두에서 쓰기 가능한 셀 형식의 다른 개체를 사용하여 통합 문서를 만들 수 있습니다.

관련 문제