Bug 52233 - IndexOutOfBoundsException when calling sheet.getColumnWidth after calling XSSFWorkbook.write
Summary: IndexOutOfBoundsException when calling sheet.getColumnWidth after calling XSS...
Status: RESOLVED FIXED
Alias: None
Product: POI
Classification: Unclassified
Component: XSSF (show other bugs)
Version: 3.8-dev
Hardware: PC Linux
: P2 major (vote)
Target Milestone: ---
Assignee: POI Developers List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-11-23 16:22 UTC by Stuart Owen
Modified: 2013-08-20 19:06 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stuart Owen 2011-11-23 16:22:31 UTC
Whenever I write a XSSFWorkbook out using XSSFWorkbook.write, the book afterwards is left in a state where calling getColumnWidth on one of its sheet causes an IndexOutOfBoundsException. Below is a unit test that isolates the problem (in this case it creates a new Workbook and constucts a sheet and cells, but I also have the same problem when starting from an existing workbook loaded through WorkbookFactory).

@Test
public void testColumnWidthPOI() throws Exception {
       XSSFWorkbook workbook = new XSSFWorkbook();
       XSSFSheet sheet = workbook.createSheet();
       XSSFRow row = sheet.createRow(0);
       XSSFCell cell = row.createCell(0);
       cell.setCellValue("hello world");
       assertEquals("hello world",workbook.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
       assertEquals(2048,workbook.getSheetAt(0).getColumnWidth(0)); //<-works

       //gets a UUID based temporary file
       File tmpDir = new File(System.getProperty("java.io.tmpdir"));
       String uuid = UUID.randomUUID().toString();
       File f = new File(tmpDir,uuid+".xlsx");

       BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(f));
       workbook.write(stream);
       stream.close();
       assertTrue(f.exists());

       assertEquals("hello world",workbook.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
       assertEquals(2048,workbook.getSheetAt(0).getColumnWidth(0)); //<- throws IndexOutOfBoundsException
   }
Comment 1 Dominik Stadler 2013-08-13 19:23:38 UTC
Analysis:
Class ColumnHelper has a member worksheet of type CTWorksheetImpl. If I look at it before and after the call to write(), there is a line "  <main:cols/>" missing after writing, so it seems writing is removing this line somehow.

When looking more closely the onSave() call in XSSFWorkbook.write() invokes XSSFSheet.write(), which causes the removal via 

                worksheet.setColsArray(null);

I am not sure why the setColsArray() is done here and if not doing this would have side-effects, but it would solve the problem here and probably some others that are reported in some other Bugs when users try using a Workbook after writing it out once.
Comment 2 Dominik Stadler 2013-08-14 14:58:42 UTC
I have now removed the setting of colsarray to null in XSSFSheet.write() to not make the Workbook corrupt by writing it out. This fixes this bug, all existing unit tests still run fine, not sure why the code was there initiallly, also the SNV Log did not provide any useful information here.
Comment 3 Dominik Stadler 2013-08-20 15:01:01 UTC
Reopening this bug as I need to revert the changes done for this Bug for now as it breaks xlsx reading in Excel!
Comment 4 Dominik Stadler 2013-08-20 19:06:40 UTC
Fix differently now, it seems we need to set the colsArray to null in order to produce valid XLSX-files, so we restore the colsArray after writing the document out.