#56737 Sometimes Excel writes an internal reference to a local name in an odd way, without an ExternalNameRecord, try to detect and work around those
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1611681 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c9d90732e5
commit
d4a1239efa
@ -26,8 +26,61 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.apache.poi.ddf.*;
|
import org.apache.poi.ddf.EscherBSERecord;
|
||||||
import org.apache.poi.hssf.record.*;
|
import org.apache.poi.ddf.EscherBoolProperty;
|
||||||
|
import org.apache.poi.ddf.EscherContainerRecord;
|
||||||
|
import org.apache.poi.ddf.EscherDgRecord;
|
||||||
|
import org.apache.poi.ddf.EscherDggRecord;
|
||||||
|
import org.apache.poi.ddf.EscherOptRecord;
|
||||||
|
import org.apache.poi.ddf.EscherProperties;
|
||||||
|
import org.apache.poi.ddf.EscherRGBProperty;
|
||||||
|
import org.apache.poi.ddf.EscherRecord;
|
||||||
|
import org.apache.poi.ddf.EscherSimpleProperty;
|
||||||
|
import org.apache.poi.ddf.EscherSpRecord;
|
||||||
|
import org.apache.poi.ddf.EscherSplitMenuColorsRecord;
|
||||||
|
import org.apache.poi.hssf.record.BOFRecord;
|
||||||
|
import org.apache.poi.hssf.record.BackupRecord;
|
||||||
|
import org.apache.poi.hssf.record.BookBoolRecord;
|
||||||
|
import org.apache.poi.hssf.record.BoundSheetRecord;
|
||||||
|
import org.apache.poi.hssf.record.CodepageRecord;
|
||||||
|
import org.apache.poi.hssf.record.CountryRecord;
|
||||||
|
import org.apache.poi.hssf.record.DSFRecord;
|
||||||
|
import org.apache.poi.hssf.record.DateWindow1904Record;
|
||||||
|
import org.apache.poi.hssf.record.DrawingGroupRecord;
|
||||||
|
import org.apache.poi.hssf.record.EOFRecord;
|
||||||
|
import org.apache.poi.hssf.record.EscherAggregate;
|
||||||
|
import org.apache.poi.hssf.record.ExtSSTRecord;
|
||||||
|
import org.apache.poi.hssf.record.ExtendedFormatRecord;
|
||||||
|
import org.apache.poi.hssf.record.ExternSheetRecord;
|
||||||
|
import org.apache.poi.hssf.record.FileSharingRecord;
|
||||||
|
import org.apache.poi.hssf.record.FnGroupCountRecord;
|
||||||
|
import org.apache.poi.hssf.record.FontRecord;
|
||||||
|
import org.apache.poi.hssf.record.FormatRecord;
|
||||||
|
import org.apache.poi.hssf.record.HideObjRecord;
|
||||||
|
import org.apache.poi.hssf.record.HyperlinkRecord;
|
||||||
|
import org.apache.poi.hssf.record.InterfaceEndRecord;
|
||||||
|
import org.apache.poi.hssf.record.InterfaceHdrRecord;
|
||||||
|
import org.apache.poi.hssf.record.MMSRecord;
|
||||||
|
import org.apache.poi.hssf.record.NameCommentRecord;
|
||||||
|
import org.apache.poi.hssf.record.NameRecord;
|
||||||
|
import org.apache.poi.hssf.record.PaletteRecord;
|
||||||
|
import org.apache.poi.hssf.record.PasswordRecord;
|
||||||
|
import org.apache.poi.hssf.record.PasswordRev4Record;
|
||||||
|
import org.apache.poi.hssf.record.PrecisionRecord;
|
||||||
|
import org.apache.poi.hssf.record.ProtectRecord;
|
||||||
|
import org.apache.poi.hssf.record.ProtectionRev4Record;
|
||||||
|
import org.apache.poi.hssf.record.RecalcIdRecord;
|
||||||
|
import org.apache.poi.hssf.record.Record;
|
||||||
|
import org.apache.poi.hssf.record.RefreshAllRecord;
|
||||||
|
import org.apache.poi.hssf.record.SSTRecord;
|
||||||
|
import org.apache.poi.hssf.record.StyleRecord;
|
||||||
|
import org.apache.poi.hssf.record.SupBookRecord;
|
||||||
|
import org.apache.poi.hssf.record.TabIdRecord;
|
||||||
|
import org.apache.poi.hssf.record.UseSelFSRecord;
|
||||||
|
import org.apache.poi.hssf.record.WindowOneRecord;
|
||||||
|
import org.apache.poi.hssf.record.WindowProtectRecord;
|
||||||
|
import org.apache.poi.hssf.record.WriteAccessRecord;
|
||||||
|
import org.apache.poi.hssf.record.WriteProtectRecord;
|
||||||
import org.apache.poi.hssf.record.common.UnicodeString;
|
import org.apache.poi.hssf.record.common.UnicodeString;
|
||||||
import org.apache.poi.hssf.util.HSSFColor;
|
import org.apache.poi.hssf.util.HSSFColor;
|
||||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
||||||
@ -1776,7 +1829,7 @@ public final class InternalWorkbook {
|
|||||||
return new ExternalSheet(extNames[0], extNames[1]);
|
return new ExternalSheet(extNames[0], extNames[1]);
|
||||||
}
|
}
|
||||||
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||||
String nameName = linkTable.resolveNameXText(externSheetIndex, externNameIndex);
|
String nameName = linkTable.resolveNameXText(externSheetIndex, externNameIndex, this);
|
||||||
if(nameName == null) {
|
if(nameName == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -2299,7 +2352,7 @@ public final class InternalWorkbook {
|
|||||||
* @return the string representation of the defined or external name
|
* @return the string representation of the defined or external name
|
||||||
*/
|
*/
|
||||||
public String resolveNameXText(int refIndex, int definedNameIndex) {
|
public String resolveNameXText(int refIndex, int definedNameIndex) {
|
||||||
return linkTable.resolveNameXText(refIndex, definedNameIndex);
|
return linkTable.resolveNameXText(refIndex, definedNameIndex, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +31,7 @@ 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.SheetNameFormatter;
|
||||||
import org.apache.poi.ss.formula.ptg.Area3DPtg;
|
import org.apache.poi.ss.formula.ptg.Area3DPtg;
|
||||||
import org.apache.poi.ss.formula.ptg.ErrPtg;
|
import org.apache.poi.ss.formula.ptg.ErrPtg;
|
||||||
import org.apache.poi.ss.formula.ptg.NameXPtg;
|
import org.apache.poi.ss.formula.ptg.NameXPtg;
|
||||||
@ -206,7 +207,7 @@ final class LinkTable {
|
|||||||
// collect zero or more DEFINEDNAMEs id=0x18,
|
// collect zero or more DEFINEDNAMEs id=0x18,
|
||||||
// with their comments if present
|
// with their comments if present
|
||||||
while(true) {
|
while(true) {
|
||||||
Class nextClass = rs.peekNextClass();
|
Class<? extends Record> nextClass = rs.peekNextClass();
|
||||||
if (nextClass == NameRecord.class) {
|
if (nextClass == NameRecord.class) {
|
||||||
NameRecord nr = (NameRecord)rs.getNext();
|
NameRecord nr = (NameRecord)rs.getNext();
|
||||||
_definedNames.add(nr);
|
_definedNames.add(nr);
|
||||||
@ -280,10 +281,9 @@ final class LinkTable {
|
|||||||
* @param sheetNumber 1-based sheet number
|
* @param sheetNumber 1-based sheet number
|
||||||
*/
|
*/
|
||||||
public NameRecord getSpecificBuiltinRecord(byte builtInCode, int sheetNumber) {
|
public NameRecord getSpecificBuiltinRecord(byte builtInCode, int sheetNumber) {
|
||||||
|
Iterator<NameRecord> iterator = _definedNames.iterator();
|
||||||
Iterator iterator = _definedNames.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
NameRecord record = ( NameRecord ) iterator.next();
|
NameRecord record = iterator.next();
|
||||||
|
|
||||||
//print areas are one based
|
//print areas are one based
|
||||||
if (record.getBuiltInName() == builtInCode && record.getSheetNumber() == sheetNumber) {
|
if (record.getBuiltInName() == builtInCode && record.getSheetNumber() == sheetNumber) {
|
||||||
@ -471,10 +471,37 @@ final class LinkTable {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String resolveNameXText(int refIndex, int definedNameIndex) {
|
public String resolveNameXText(int refIndex, int definedNameIndex, InternalWorkbook workbook) {
|
||||||
int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
|
int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
|
||||||
return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex);
|
int firstTabIndex = _externSheetRecord.getFirstSheetIndexFromRefIndex(refIndex);
|
||||||
|
if (firstTabIndex == -1) {
|
||||||
|
// The referenced sheet could not be found
|
||||||
|
throw new RuntimeException("Referenced sheet could not be found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does it exist via the external book block?
|
||||||
|
if (_externalBookBlocks.length > extBookIndex) {
|
||||||
|
return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex);
|
||||||
|
} else if (firstTabIndex == -2) {
|
||||||
|
// Workbook scoped name, not actually external after all
|
||||||
|
NameRecord nr = getNameRecord(definedNameIndex);
|
||||||
|
int sheetNumber = nr.getSheetNumber();
|
||||||
|
|
||||||
|
StringBuffer text = new StringBuffer();
|
||||||
|
if (sheetNumber > 0) {
|
||||||
|
String sheetName = workbook.getSheetName(sheetNumber-1);
|
||||||
|
SheetNameFormatter.appendFormat(text, sheetName);
|
||||||
|
text.append("!");
|
||||||
|
}
|
||||||
|
text.append(nr.getNameText());
|
||||||
|
return text.toString();
|
||||||
|
} else {
|
||||||
|
throw new ArrayIndexOutOfBoundsException(
|
||||||
|
"Ext Book Index relative but beyond the supported length, was " +
|
||||||
|
extBookIndex + " but maximum is " + _externalBookBlocks.length
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public int resolveNameXIx(int refIndex, int definedNameIndex) {
|
public int resolveNameXIx(int refIndex, int definedNameIndex) {
|
||||||
int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
|
int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex);
|
||||||
|
@ -200,9 +200,13 @@ public class ExternSheetRecord extends StandardRecord {
|
|||||||
return sid;
|
return sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExtbookIndexFromRefIndex(int refIndex) {
|
/**
|
||||||
return getRef(refIndex).getExtBookIndex();
|
* Returns the index of the SupBookRecord for this index
|
||||||
}
|
*/
|
||||||
|
public int getExtbookIndexFromRefIndex(int refIndex) {
|
||||||
|
RefSubRecord refRec = getRef(refIndex);
|
||||||
|
return refRec.getExtBookIndex();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return -1 if not found
|
* @return -1 if not found
|
||||||
@ -217,6 +221,11 @@ public class ExternSheetRecord extends StandardRecord {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first sheet that the reference applies to, or
|
||||||
|
* -1 if the referenced sheet can't be found, or -2 if the
|
||||||
|
* reference is workbook scoped.
|
||||||
|
*/
|
||||||
public int getFirstSheetIndexFromRefIndex(int extRefIndex) {
|
public int getFirstSheetIndexFromRefIndex(int extRefIndex) {
|
||||||
return getRef(extRefIndex).getFirstSheetIndex();
|
return getRef(extRefIndex).getFirstSheetIndex();
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,16 @@ import junit.framework.AssertionFailedError;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
import org.apache.poi.hssf.record.*;
|
import org.apache.poi.hssf.record.BOFRecord;
|
||||||
|
import org.apache.poi.hssf.record.CountryRecord;
|
||||||
|
import org.apache.poi.hssf.record.EOFRecord;
|
||||||
|
import org.apache.poi.hssf.record.ExternSheetRecord;
|
||||||
|
import org.apache.poi.hssf.record.ExternalNameRecord;
|
||||||
|
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.SSTRecord;
|
||||||
|
import org.apache.poi.hssf.record.SupBookRecord;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
import org.apache.poi.ss.formula.ptg.NameXPtg;
|
import org.apache.poi.ss.formula.ptg.NameXPtg;
|
||||||
@ -230,7 +239,7 @@ public final class TestLinkTable extends TestCase {
|
|||||||
|
|
||||||
//check that
|
//check that
|
||||||
assertEquals(0, tbl.resolveNameXIx(namex1.getSheetRefIndex(), namex1.getNameIndex()));
|
assertEquals(0, tbl.resolveNameXIx(namex1.getSheetRefIndex(), namex1.getNameIndex()));
|
||||||
assertEquals("ISODD", tbl.resolveNameXText(namex1.getSheetRefIndex(), namex1.getNameIndex()));
|
assertEquals("ISODD", tbl.resolveNameXText(namex1.getSheetRefIndex(), namex1.getNameIndex(), null));
|
||||||
|
|
||||||
assertNull(tbl.getNameXPtg("ISEVEN"));
|
assertNull(tbl.getNameXPtg("ISEVEN"));
|
||||||
NameXPtg namex2 = tbl.addNameXPtg("ISEVEN"); // adds two new rercords
|
NameXPtg namex2 = tbl.addNameXPtg("ISEVEN"); // adds two new rercords
|
||||||
@ -256,7 +265,7 @@ public final class TestLinkTable extends TestCase {
|
|||||||
assertTrue(wrl.get(7) instanceof EOFRecord);
|
assertTrue(wrl.get(7) instanceof EOFRecord);
|
||||||
|
|
||||||
assertEquals(0, tbl.resolveNameXIx(namex2.getSheetRefIndex(), namex2.getNameIndex()));
|
assertEquals(0, tbl.resolveNameXIx(namex2.getSheetRefIndex(), namex2.getNameIndex()));
|
||||||
assertEquals("ISEVEN", tbl.resolveNameXText(namex2.getSheetRefIndex(), namex2.getNameIndex()));
|
assertEquals("ISEVEN", tbl.resolveNameXText(namex2.getSheetRefIndex(), namex2.getNameIndex(), null));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2619,7 +2619,6 @@ public final class TestBugs extends BaseTestBugzillaIssues {
|
|||||||
* Currently failing with
|
* Currently failing with
|
||||||
* java.lang.RuntimeException: Unexpected eval class (org.apache.poi.ss.formula.eval.NameXEval)
|
* java.lang.RuntimeException: Unexpected eval class (org.apache.poi.ss.formula.eval.NameXEval)
|
||||||
*/
|
*/
|
||||||
@Ignore
|
|
||||||
@Test
|
@Test
|
||||||
public void bug56737() throws IOException {
|
public void bug56737() throws IOException {
|
||||||
Workbook wb = openSample("56737.xls");
|
Workbook wb = openSample("56737.xls");
|
||||||
|
Loading…
Reference in New Issue
Block a user