Summary: | POI 3.8 error attempting to program a "delete columns" capability | ||
---|---|---|---|
Product: | POI | Reporter: | Every Moment <everymoment> |
Component: | HSSF | Assignee: | POI Developers List <dev> |
Status: | RESOLVED WORKSFORME | ||
Severity: | normal | CC: | onealj |
Priority: | P2 | ||
Version: | 3.12-dev | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | All | ||
Attachments: | Demonstrates an error, possibly in HSSFrow.moveCell() |
I've also had difficulty getting a working 'deleteColumns()' method, and would very much like to know if a solution is on offer. When I run your test-program with the latest trunk-version of poi I get A D E correctly, it seems the bug was fixed at some point. Please reopen or report a new bug with updated information if there is still a problem for you with snapshot builds or the next upcoming release (likely 3.10). This bug recurs in 3.12. Using the previously-attached POI_error_in_column_deletes class, I created a batch file comprising the following commands: set c1=poi-3.12-20150511.jar set c2=POI_error_in_column_deletes del %c2%.class del testDeleteColumns.xls javac -cp %c1% %c2%.java java -cp %c1%; %c2% The result is a new .xls file whose columns read 'ACE', instead of the proper output of 'ADE'. The java version running is 1.8.0_60. The POI version is 3.12-20150511. I tried it again at it does work for me, not sure where the difference is to what you see. Please use the following unit test and show how it needs to be adjusted to cause the problem if this is really still a problem for you. This test verifies that "A", "D", "E" end up in the columns, but I also checked with LibreOffice (sorry, no MS Office on this machine) private static final int ROWS = 10; private static final int COLS = 10; @Test public void test_deleteColumns() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet("sheet1"); HSSFRow r = null; for (int row = 0; row < ROWS; row++) { r = sh.createRow(row); for (int col = 0; col < COLS; col++) { r.createCell(col); } } sh.getRow(2).getCell(0).setCellValue("A"); sh.getRow(2).getCell(1).setCellValue("B"); sh.getRow(2).getCell(2).setCellValue("C"); sh.getRow(2).getCell(3).setCellValue("D"); sh.getRow(2).getCell(4).setCellValue("E"); // Put in ABCDE into consecutive cells; // deletion should have gotten ADE but got ACE instead. for (int deleteIndex = 0; deleteIndex < 2; deleteIndex++) { HSSFRow row = sh.getRow(2); if (null != row) { deleteColumnFromRow(row, 1); } } assertEquals("A", sh.getRow(2).getCell(0).getStringCellValue()); assertEquals("D", sh.getRow(2).getCell(1).getStringCellValue()); assertEquals("E", sh.getRow(2).getCell(2).getStringCellValue()); wb.close(); } private void deleteColumnFromRow(HSSFRow row, final int START_COL) { if (START_COL >= COLS) { return; } HSSFCell check = row.getCell(START_COL); if (null != check) { row.removeCell(check); } System.err.println( " deleteColumnFromRow: row = " + row.getRowNum()); HSSFCell cell = null; for (int col = START_COL + 1; col < COLS; col++) { int source = col; int destination = col - 1; cell = row.getCell(source); if (null != row.getCell(destination)) { row.removeCell(row.getCell(destination)); // Because the API says the destination cannot exist, // the destination has been deleted. The API reference is // poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFRow.html } if (null != cell) { // moveCell is most likely where the error occurs. row.moveCell(cell, (short) (destination)); } } } |
Created attachment 29380 [details] Demonstrates an error, possibly in HSSFrow.moveCell() The attached java file POI_error_in_column_deletes.java attempts to demonstrate one way to program column deletes in POI 3.8. This java program does the following: - creates a new workbook - creates 10 rows each containing 10 empty cells - fills in range A3:E3 with "A", "B", "C", "D", and "E" - runs code designed to delete columns B and C, but instead of getting ADE in the third row it gets ACE - outputs a workbook testDeleteColumns.xls It get the same incorrect result in POI 3.8 and in the poi-3.9-beta1-20120915.jar nightly. The inner loop of deleting columns, which contains the error, is the method deleteColumnFromRow: /** Removes a cell at START_COL and shifts remainder of row to the left by one. * @param row row from which to delete and shift cells * @param START_COL index of cell to remove */ private static void deleteColumnFromRow(HSSFRow row, final int START_COL){ if(START_COL >= COLS){ return; } HSSFCell check = row.getCell(START_COL); if(null!=check){ row.removeCell(check); } System.err.println( " deleteColumnFromRow: row = "+ row.getRowNum()); HSSFCell cell = null; for(int col = START_COL+1; col < COLS; col++){ int source = col; int destination = col-1; cell = row.getCell(source); if(null != row.getCell(destination)){ row.removeCell(row.getCell(destination)); // Because the API says the destination cannot exist, // the destination has been deleted. The API reference is // poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFRow.html } if(null != cell){ // I THINK THE ERROR MIGHT BE IN moveCell(). row.moveCell(cell,(short)(destination)); } } }