Browse Source

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
tags/REL_3_10_FINAL
Dominik Stadler 10 years ago
parent
commit
9d7c124057

+ 3
- 0
src/java/org/apache/poi/hssf/model/InternalWorkbook.java View File

// 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);
} }
} }
} }

+ 13
- 8
src/java/org/apache/poi/hssf/model/LinkTable.java View File

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/>
* *
*/ */
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;
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);
public int getIndexToInternalSheet(int extRefIndex) { public int getIndexToInternalSheet(int extRefIndex) {
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 _externSheetRecord.addRef(thisWbIndex, sheetIndex, sheetIndex); return _externSheetRecord.addRef(thisWbIndex, sheetIndex, sheetIndex);
} }



/** /**
* copied from Workbook * copied from Workbook
*/ */
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++) {
Record record = (Record) iterator.next();
for (Iterator<Record> iterator = _workbookRecordList.iterator(); iterator.hasNext(); supLinkIndex++) {
Record record = iterator.next();
if (record instanceof SupBookRecord) { if (record instanceof SupBookRecord) {
if (((SupBookRecord) record).isAddInFunctions()) break; if (((SupBookRecord) record).isAddInFunctions()) break;
} }

+ 13
- 0
src/java/org/apache/poi/hssf/record/ExternSheetRecord.java View File

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
*/ */
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);
} }
@Override
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
int nItems = _list.size(); int nItems = _list.size();
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();


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;
} }

+ 50
- 0
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java View File

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;
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 View File


Loading…
Cancel
Save