diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java index 24b30180d..0e51637e9 100644 --- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -716,6 +716,9 @@ 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); } } } diff --git a/src/java/org/apache/poi/hssf/model/LinkTable.java b/src/java/org/apache/poi/hssf/model/LinkTable.java index 1cec62de3..3304ae235 100644 --- a/src/java/org/apache/poi/hssf/model/LinkTable.java +++ b/src/java/org/apache/poi/hssf/model/LinkTable.java @@ -31,13 +31,17 @@ import org.apache.poi.hssf.record.NameCommentRecord; import org.apache.poi.hssf.record.NameRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.SupBookRecord; -import org.apache.poi.ss.formula.ptg.*; +import org.apache.poi.ss.formula.ptg.Area3DPtg; +import org.apache.poi.ss.formula.ptg.ErrPtg; +import org.apache.poi.ss.formula.ptg.NameXPtg; +import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.ss.formula.ptg.Ref3DPtg; /** * Link Table (OOO pdf reference: 4.10.3 )

* * The main data of all types of references is stored in the Link Table inside the Workbook Globals - * Substream (4.2.5). The Link Table itself is optional and occurs only, if there are any + * Substream (4.2.5). The Link Table itself is optional and occurs only if there are any * references in the document. *

* @@ -63,9 +67,7 @@ import org.apache.poi.ss.formula.ptg.*; */ final class LinkTable { - // TODO make this class into a record aggregate - private static final class CRNBlock { private final CRNCountRecord _countRecord; @@ -174,7 +176,7 @@ final class LinkTable { private final int _recordCount; private final WorkbookRecordList _workbookRecordList; // TODO - would be nice to remove this - public LinkTable(List inputList, int startIndex, WorkbookRecordList workbookRecordList, Map commentRecords) { + public LinkTable(List inputList, int startIndex, WorkbookRecordList workbookRecordList, Map commentRecords) { _workbookRecordList = workbookRecordList; RecordStream rs = new RecordStream(inputList, startIndex); @@ -412,6 +414,10 @@ final class LinkTable { public int getIndexToInternalSheet(int extRefIndex) { return _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex); } + + public void updateIndexToInternalSheet(int extRefIndex, int offset) { + _externSheetRecord.adjustIndex(extRefIndex, offset); + } public int getSheetIndexFromExternSheetIndex(int extRefIndex) { if (extRefIndex >= _externSheetRecord.getNumOfRefs() || extRefIndex < 0) { @@ -442,7 +448,6 @@ final class LinkTable { return _externSheetRecord.addRef(thisWbIndex, sheetIndex, sheetIndex); } - /** * copied from Workbook */ @@ -533,8 +538,8 @@ final class LinkTable { int supLinkIndex = 0; // find the posistion of the Add-In SupBookRecord in the workbook stream, // the created ExternalNameRecord will be appended to it - for (Iterator iterator = _workbookRecordList.iterator(); iterator.hasNext(); supLinkIndex++) { - Record record = (Record) iterator.next(); + for (Iterator iterator = _workbookRecordList.iterator(); iterator.hasNext(); supLinkIndex++) { + Record record = iterator.next(); if (record instanceof SupBookRecord) { if (((SupBookRecord) record).isAddInFunctions()) break; } diff --git a/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java b/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java index 963e325ab..4de0f60b0 100644 --- a/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java @@ -41,6 +41,10 @@ public class ExternSheetRecord extends StandardRecord { private int _firstSheetIndex; // may be -1 (0xFFFF) private int _lastSheetIndex; // may be -1 (0xFFFF) + public void adjustIndex(int offset) { + _firstSheetIndex += offset; + _lastSheetIndex += offset; + } /** a Constructor for making new sub record */ @@ -66,6 +70,7 @@ public class ExternSheetRecord extends StandardRecord { return _lastSheetIndex; } + @Override public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("extBook=").append(_extBookIndex); @@ -122,6 +127,7 @@ public class ExternSheetRecord extends StandardRecord { } + @Override public String toString() { StringBuffer sb = new StringBuffer(); int nItems = _list.size(); @@ -138,10 +144,12 @@ public class ExternSheetRecord extends StandardRecord { return sb.toString(); } + @Override protected int getDataSize() { return 2 + _list.size() * RefSubRecord.ENCODED_SIZE; } + @Override public void serialize(LittleEndianOutput out) { int nItems = _list.size(); @@ -156,9 +164,14 @@ public class ExternSheetRecord extends StandardRecord { return _list.get(i); } + public void adjustIndex(int extRefIndex, int offset) { + getRef(extRefIndex).adjustIndex(offset); + } + /** * return the non static version of the id for this record. */ + @Override public short getSid() { return sid; } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java index 1927727e4..88fa84ac2 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java @@ -48,6 +48,7 @@ import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.usermodel.BaseTestWorkbook; +import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.TempFile; @@ -965,4 +966,53 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook { HSSFWorkbook read = HSSFTestDataSamples.writeOutAndReadBack(wb); assertSheetOrder(read, "Invoice", "Deferred", "Received", "Digest"); } + + public void testBug54500() throws Exception { + String nameName = "AName"; + String sheetName = "ASheet"; + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("54500.xls"); + + assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3"); + + wb.createSheet(sheetName); + + assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3", "ASheet"); + + Name n = wb.createName(); + n.setNameName(nameName); + n.setSheetIndex(3); + n.setRefersToFormula(sheetName + "!A1"); + + assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3", "ASheet"); + assertEquals("ASheet!A1", wb.getName(nameName).getRefersToFormula()); + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + wb.write(stream); + + assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3", "ASheet"); + assertEquals("ASheet!A1", wb.getName(nameName).getRefersToFormula()); + + wb.removeSheetAt(1); + + assertSheetOrder(wb, "Sheet1", "Sheet3", "ASheet"); + assertEquals("ASheet!A1", wb.getName(nameName).getRefersToFormula()); + + ByteArrayOutputStream stream2 = new ByteArrayOutputStream(); + wb.write(stream2); + + assertSheetOrder(wb, "Sheet1", "Sheet3", "ASheet"); + assertEquals("ASheet!A1", wb.getName(nameName).getRefersToFormula()); + + expectName( + new HSSFWorkbook(new ByteArrayInputStream(stream.toByteArray())), + nameName, "ASheet!A1"); + expectName( + new HSSFWorkbook( + new ByteArrayInputStream(stream2.toByteArray())), + nameName, "ASheet!A1"); + } + + private void expectName(HSSFWorkbook wb, String name, String expect) { + assertEquals(expect, wb.getName(name).getRefersToFormula()); + } } diff --git a/test-data/spreadsheet/54500.xls b/test-data/spreadsheet/54500.xls new file mode 100644 index 000000000..0cd18b51d Binary files /dev/null and b/test-data/spreadsheet/54500.xls differ