From: Dominik Stadler Date: Thu, 15 May 2014 21:14:52 +0000 (+0000) Subject: Bug 56325: fix Exception when removing sheets with named ranges in the workbook X-Git-Tag: REL_3_11_BETA1~136 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e76448a83ca7e015d18f0b3cf12473d487b35899;p=poi.git Bug 56325: fix Exception when removing sheets with named ranges in the workbook git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1595048 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java index 4b4a11f9c9..e54d6c5d80 100644 --- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -716,11 +716,15 @@ public final class InternalWorkbook { // Bump down by one, so still points // at the same sheet nr.setSheetNumber(nr.getSheetNumber()-1); - - // also update the link-table as otherwise references might point at invalid sheets - linkTable.updateIndexToInternalSheet(i, -1); } } + + // also tell the LinkTable about the removed sheet + // +1 because we already removed it from the count of sheets! + for(int i = sheetIndex+1;i < getNumSheets()+1;i++) { + // also update the link-table as otherwise references might point at invalid sheets + linkTable.removeSheet(i); + } } /** diff --git a/src/java/org/apache/poi/hssf/model/LinkTable.java b/src/java/org/apache/poi/hssf/model/LinkTable.java index 3304ae2351..6e203ef1d1 100644 --- a/src/java/org/apache/poi/hssf/model/LinkTable.java +++ b/src/java/org/apache/poi/hssf/model/LinkTable.java @@ -414,9 +414,17 @@ final class LinkTable { public int getIndexToInternalSheet(int extRefIndex) { return _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex); } - - public void updateIndexToInternalSheet(int extRefIndex, int offset) { - _externSheetRecord.adjustIndex(extRefIndex, offset); + + /** + * @deprecated Was prevously used for removing sheets, which we now do differently + */ + @Deprecated + public void updateIndexToInternalSheet(int extRefIndex, int offset) { + _externSheetRecord.adjustIndex(extRefIndex, offset); + } + + public void removeSheet(int sheetIdx) { + _externSheetRecord.removeSheet(sheetIdx); } public int getSheetIndexFromExternSheetIndex(int extRefIndex) { @@ -453,8 +461,8 @@ final class LinkTable { */ private int findFirstRecordLocBySid(short sid) { int index = 0; - for (Iterator iterator = _workbookRecordList.iterator(); iterator.hasNext(); ) { - Record record = ( Record ) iterator.next(); + for (Iterator iterator = _workbookRecordList.iterator(); iterator.hasNext(); ) { + Record record = iterator.next(); if (record.getSid() == sid) { return index; diff --git a/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java b/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java index 4de0f60b02..0ff062b088 100644 --- a/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java @@ -164,8 +164,32 @@ public class ExternSheetRecord extends StandardRecord { return _list.get(i); } - public void adjustIndex(int extRefIndex, int offset) { - getRef(extRefIndex).adjustIndex(offset); + /** + * @deprecated Was prevously used for removing sheets, which we now do differently + */ + @Deprecated + public void adjustIndex(int extRefIndex, int offset) { + getRef(extRefIndex).adjustIndex(offset); + } + + public void removeSheet(int sheetIdx) { + int nItems = _list.size(); + int toRemove = -1; + for (int i = 0; i < nItems; i++) { + RefSubRecord refSubRecord = _list.get(i); + if(refSubRecord.getFirstSheetIndex() == sheetIdx && + refSubRecord.getLastSheetIndex() == sheetIdx) { + toRemove = i; + } else if (refSubRecord.getFirstSheetIndex() > sheetIdx && + refSubRecord.getLastSheetIndex() > sheetIdx) { + _list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), refSubRecord.getFirstSheetIndex()-1, refSubRecord.getLastSheetIndex()-1)); + } + } + + // finally remove entries for sheet indexes that we remove + if(toRemove != -1) { + _list.remove(toRemove); + } } /** diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java index 3bd97827cc..a6894a1a1b 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java @@ -27,9 +27,11 @@ import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -2582,4 +2584,32 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals(5, cf.getNumConditionalFormattings()); } + + @Test + public void bug56325() throws IOException { + HSSFWorkbook wb; + + File file = HSSFTestDataSamples.getSampleFile("56325.xls"); + InputStream stream = new FileInputStream(file); + try { + POIFSFileSystem fs = new POIFSFileSystem(stream); + wb = new HSSFWorkbook(fs); + } finally { + stream.close(); + } + + assertEquals(3, wb.getNumberOfSheets()); + wb.removeSheetAt(0); + assertEquals(2, wb.getNumberOfSheets()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + assertEquals(2, wb.getNumberOfSheets()); + wb.removeSheetAt(0); + assertEquals(1, wb.getNumberOfSheets()); + wb.removeSheetAt(0); + assertEquals(0, wb.getNumberOfSheets()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + assertEquals(0, wb.getNumberOfSheets()); + } } diff --git a/test-data/spreadsheet/56325.xls b/test-data/spreadsheet/56325.xls new file mode 100644 index 0000000000..38b0e4abb5 Binary files /dev/null and b/test-data/spreadsheet/56325.xls differ