Fix Bug 54400 by updating the index in the LinkTable whenever sheets are
removed. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1538163 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a6b301e485
commit
8d345b13d0
@ -716,6 +716,9 @@ public final class InternalWorkbook {
|
|||||||
// Bump down by one, so still points
|
// Bump down by one, so still points
|
||||||
// at the same sheet
|
// at the same sheet
|
||||||
nr.setSheetNumber(nr.getSheetNumber()-1);
|
nr.setSheetNumber(nr.getSheetNumber()-1);
|
||||||
|
|
||||||
|
// also update the link-table as otherwise references might point at invalid sheets
|
||||||
|
linkTable.updateIndexToInternalSheet(i, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,17 @@ import org.apache.poi.hssf.record.NameCommentRecord;
|
|||||||
import org.apache.poi.hssf.record.NameRecord;
|
import org.apache.poi.hssf.record.NameRecord;
|
||||||
import org.apache.poi.hssf.record.Record;
|
import org.apache.poi.hssf.record.Record;
|
||||||
import org.apache.poi.hssf.record.SupBookRecord;
|
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 ) <p/>
|
* Link Table (OOO pdf reference: 4.10.3 ) <p/>
|
||||||
*
|
*
|
||||||
* The main data of all types of references is stored in the Link Table inside the Workbook Globals
|
* 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.
|
* references in the document.
|
||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
@ -63,9 +67,7 @@ import org.apache.poi.ss.formula.ptg.*;
|
|||||||
*/
|
*/
|
||||||
final class LinkTable {
|
final class LinkTable {
|
||||||
|
|
||||||
|
|
||||||
// TODO make this class into a record aggregate
|
// TODO make this class into a record aggregate
|
||||||
|
|
||||||
private static final class CRNBlock {
|
private static final class CRNBlock {
|
||||||
|
|
||||||
private final CRNCountRecord _countRecord;
|
private final CRNCountRecord _countRecord;
|
||||||
@ -174,7 +176,7 @@ final class LinkTable {
|
|||||||
private final int _recordCount;
|
private final int _recordCount;
|
||||||
private final WorkbookRecordList _workbookRecordList; // TODO - would be nice to remove this
|
private final WorkbookRecordList _workbookRecordList; // TODO - would be nice to remove this
|
||||||
|
|
||||||
public LinkTable(List inputList, int startIndex, WorkbookRecordList workbookRecordList, Map<String, NameCommentRecord> commentRecords) {
|
public LinkTable(List<Record> inputList, int startIndex, WorkbookRecordList workbookRecordList, Map<String, NameCommentRecord> commentRecords) {
|
||||||
|
|
||||||
_workbookRecordList = workbookRecordList;
|
_workbookRecordList = workbookRecordList;
|
||||||
RecordStream rs = new RecordStream(inputList, startIndex);
|
RecordStream rs = new RecordStream(inputList, startIndex);
|
||||||
@ -413,6 +415,10 @@ final class LinkTable {
|
|||||||
return _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex);
|
return _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateIndexToInternalSheet(int extRefIndex, int offset) {
|
||||||
|
_externSheetRecord.adjustIndex(extRefIndex, offset);
|
||||||
|
}
|
||||||
|
|
||||||
public int getSheetIndexFromExternSheetIndex(int extRefIndex) {
|
public int getSheetIndexFromExternSheetIndex(int extRefIndex) {
|
||||||
if (extRefIndex >= _externSheetRecord.getNumOfRefs() || extRefIndex < 0) {
|
if (extRefIndex >= _externSheetRecord.getNumOfRefs() || extRefIndex < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -442,7 +448,6 @@ final class LinkTable {
|
|||||||
return _externSheetRecord.addRef(thisWbIndex, sheetIndex, sheetIndex);
|
return _externSheetRecord.addRef(thisWbIndex, sheetIndex, sheetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* copied from Workbook
|
* copied from Workbook
|
||||||
*/
|
*/
|
||||||
@ -533,8 +538,8 @@ final class LinkTable {
|
|||||||
int supLinkIndex = 0;
|
int supLinkIndex = 0;
|
||||||
// find the posistion of the Add-In SupBookRecord in the workbook stream,
|
// find the posistion of the Add-In SupBookRecord in the workbook stream,
|
||||||
// the created ExternalNameRecord will be appended to it
|
// the created ExternalNameRecord will be appended to it
|
||||||
for (Iterator iterator = _workbookRecordList.iterator(); iterator.hasNext(); supLinkIndex++) {
|
for (Iterator<Record> iterator = _workbookRecordList.iterator(); iterator.hasNext(); supLinkIndex++) {
|
||||||
Record record = (Record) iterator.next();
|
Record record = iterator.next();
|
||||||
if (record instanceof SupBookRecord) {
|
if (record instanceof SupBookRecord) {
|
||||||
if (((SupBookRecord) record).isAddInFunctions()) break;
|
if (((SupBookRecord) record).isAddInFunctions()) break;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,10 @@ public class ExternSheetRecord extends StandardRecord {
|
|||||||
private int _firstSheetIndex; // may be -1 (0xFFFF)
|
private int _firstSheetIndex; // may be -1 (0xFFFF)
|
||||||
private int _lastSheetIndex; // 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
|
/** a Constructor for making new sub record
|
||||||
*/
|
*/
|
||||||
@ -66,6 +70,7 @@ public class ExternSheetRecord extends StandardRecord {
|
|||||||
return _lastSheetIndex;
|
return _lastSheetIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
buffer.append("extBook=").append(_extBookIndex);
|
buffer.append("extBook=").append(_extBookIndex);
|
||||||
@ -122,6 +127,7 @@ public class ExternSheetRecord extends StandardRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
int nItems = _list.size();
|
int nItems = _list.size();
|
||||||
@ -138,10 +144,12 @@ public class ExternSheetRecord extends StandardRecord {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected int getDataSize() {
|
protected int getDataSize() {
|
||||||
return 2 + _list.size() * RefSubRecord.ENCODED_SIZE;
|
return 2 + _list.size() * RefSubRecord.ENCODED_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void serialize(LittleEndianOutput out) {
|
public void serialize(LittleEndianOutput out) {
|
||||||
int nItems = _list.size();
|
int nItems = _list.size();
|
||||||
|
|
||||||
@ -156,9 +164,14 @@ public class ExternSheetRecord extends StandardRecord {
|
|||||||
return _list.get(i);
|
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.
|
* return the non static version of the id for this record.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public short getSid() {
|
public short getSid() {
|
||||||
return sid;
|
return sid;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
|||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
import org.apache.poi.ss.formula.ptg.Area3DPtg;
|
import org.apache.poi.ss.formula.ptg.Area3DPtg;
|
||||||
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
|
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.ss.util.CellRangeAddress;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.TempFile;
|
import org.apache.poi.util.TempFile;
|
||||||
@ -965,4 +966,53 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
|
|||||||
HSSFWorkbook read = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
HSSFWorkbook read = HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||||
assertSheetOrder(read, "Invoice", "Deferred", "Received", "Digest");
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
BIN
test-data/spreadsheet/54500.xls
Normal file
BIN
test-data/spreadsheet/54500.xls
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user