use of org.apache.poi.ss.formula.ptg.NameXPtg in project poi by apache.
the class FormulaParser method parseRangeable.
/**
* Parses area refs (things which could be the operand of ':') and simple factors
* Examples
* <pre>
* A$1
* $A$1 : $B1
* A1 ....... C2
* Sheet1 !$A1
* a..b!A1
* 'my sheet'!A1
* .my.sheet!A1
* 'my sheet':'my alt sheet'!A1
* .my.sheet1:.my.sheet2!$B$2
* my.named..range.
* 'my sheet'!my.named.range
* .my.sheet!my.named.range
* foo.bar(123.456, "abc")
* 123.456
* "abc"
* true
* [Foo.xls]!$A$1
* [Foo.xls]'my sheet'!$A$1
* [Foo.xls]!my.named.range
* </pre>
*
*/
private ParseNode parseRangeable() {
SkipWhite();
int savePointer = _pointer;
SheetIdentifier sheetIden = parseSheetName();
if (sheetIden == null) {
resetPointer(savePointer);
} else {
SkipWhite();
savePointer = _pointer;
}
SimpleRangePart part1 = parseSimpleRangePart();
if (part1 == null) {
if (sheetIden != null) {
if (look == '#') {
// error ref like MySheet!#REF!
return new ParseNode(ErrPtg.valueOf(parseErrorLiteral()));
} else {
// Is it a named range?
String name = parseAsName();
if (name.length() == 0) {
throw new FormulaParseException("Cell reference or Named Range " + "expected after sheet name at index " + _pointer + ".");
}
Ptg nameXPtg = _book.getNameXPtg(name, sheetIden);
if (nameXPtg == null) {
throw new FormulaParseException("Specified name '" + name + "' for sheet " + sheetIden.asFormulaString() + " not found");
}
return new ParseNode(nameXPtg);
}
}
return parseNonRange(savePointer);
}
boolean whiteAfterPart1 = IsWhite(look);
if (whiteAfterPart1) {
SkipWhite();
}
if (look == ':') {
int colonPos = _pointer;
GetChar();
SkipWhite();
SimpleRangePart part2 = parseSimpleRangePart();
if (part2 != null && !part1.isCompatibleForArea(part2)) {
// second part is not compatible with an area ref e.g. S!A1:S!B2
// where S might be a sheet name (that looks like a column name)
part2 = null;
}
if (part2 == null) {
// second part is not compatible with an area ref e.g. A1:OFFSET(B2, 1, 2)
// reset and let caller use explicit range operator
resetPointer(colonPos);
if (!part1.isCell()) {
String prefix = "";
if (sheetIden != null) {
prefix = "'" + sheetIden.getSheetIdentifier().getName() + '!';
}
throw new FormulaParseException(prefix + part1.getRep() + "' is not a proper reference.");
}
}
return createAreaRefParseNode(sheetIden, part1, part2);
}
if (look == '.') {
GetChar();
int dotCount = 1;
while (look == '.') {
dotCount++;
GetChar();
}
boolean whiteBeforePart2 = IsWhite(look);
SkipWhite();
SimpleRangePart part2 = parseSimpleRangePart();
String part1And2 = _formulaString.substring(savePointer - 1, _pointer - 1);
if (part2 == null) {
if (sheetIden != null) {
throw new FormulaParseException("Complete area reference expected after sheet name at index " + _pointer + ".");
}
return parseNonRange(savePointer);
}
if (whiteAfterPart1 || whiteBeforePart2) {
if (part1.isRowOrColumn() || part2.isRowOrColumn()) {
// and there's no other valid expression that fits this grammar
throw new FormulaParseException("Dotted range (full row or column) expression '" + part1And2 + "' must not contain whitespace.");
}
return createAreaRefParseNode(sheetIden, part1, part2);
}
if (dotCount == 1 && part1.isRow() && part2.isRow()) {
// actually, this is looking more like a number
return parseNonRange(savePointer);
}
if (part1.isRowOrColumn() || part2.isRowOrColumn()) {
if (dotCount != 2) {
throw new FormulaParseException("Dotted range (full row or column) expression '" + part1And2 + "' must have exactly 2 dots.");
}
}
return createAreaRefParseNode(sheetIden, part1, part2);
}
if (part1.isCell() && isValidCellReference(part1.getRep())) {
return createAreaRefParseNode(sheetIden, part1, null);
}
if (sheetIden != null) {
throw new FormulaParseException("Second part of cell reference expected after sheet name at index " + _pointer + ".");
}
return parseNonRange(savePointer);
}
use of org.apache.poi.ss.formula.ptg.NameXPtg in project poi by apache.
the class InternalWorkbook method getNameXPtg.
/**
*
* @param name the name of an external function, typically a name of a UDF
* @param sheetRefIndex the sheet ref index, or -1 if not known
* @param udf locator of user-defiend functions to resolve names of VBA and Add-In functions
* @return the external name or null
*/
public NameXPtg getNameXPtg(String name, int sheetRefIndex, UDFFinder udf) {
LinkTable lnk = getOrCreateLinkTable();
NameXPtg xptg = lnk.getNameXPtg(name, sheetRefIndex);
if (xptg == null && udf.findFunction(name) != null) {
// the name was not found in the list of external names
// check if the Workbook's UDFFinder is aware about it and register the name if it is
xptg = lnk.addNameXPtg(name);
}
return xptg;
}
use of org.apache.poi.ss.formula.ptg.NameXPtg in project poi by apache.
the class LinkTable method addNameXPtg.
/**
* Register an external name in this workbook
*
* @param name the name to register
* @return a NameXPtg describing this name
*/
public NameXPtg addNameXPtg(String name) {
int extBlockIndex = -1;
ExternalBookBlock extBlock = null;
// find ExternalBlock for Add-In functions and remember its index
for (int i = 0; i < _externalBookBlocks.length; i++) {
SupBookRecord ebr = _externalBookBlocks[i].getExternalBookRecord();
if (ebr.isAddInFunctions()) {
extBlock = _externalBookBlocks[i];
extBlockIndex = i;
break;
}
}
// An ExternalBlock for Add-In functions was not found. Create a new one.
if (extBlock == null) {
extBlock = new ExternalBookBlock();
extBlockIndex = extendExternalBookBlocks(extBlock);
// add the created SupBookRecord before ExternSheetRecord
int idx = findFirstRecordLocBySid(ExternSheetRecord.sid);
_workbookRecordList.add(idx, extBlock.getExternalBookRecord());
// register the SupBookRecord in the ExternSheetRecord
// -2 means that the scope of this name is Workbook and the reference applies to the entire workbook.
_externSheetRecord.addRef(_externalBookBlocks.length - 1, -2, -2);
}
// create a ExternalNameRecord that will describe this name
ExternalNameRecord extNameRecord = new ExternalNameRecord();
extNameRecord.setText(name);
// The docs don't explain why Excel set the formula to #REF!
extNameRecord.setParsedExpression(new Ptg[] { ErrPtg.REF_INVALID });
int nameIndex = extBlock.addExternalName(extNameRecord);
int supLinkIndex = 0;
// the created ExternalNameRecord will be appended to it
for (Iterator<Record> iterator = _workbookRecordList.iterator(); iterator.hasNext(); supLinkIndex++) {
Record record = iterator.next();
if (record instanceof SupBookRecord) {
if (((SupBookRecord) record).isAddInFunctions())
break;
}
}
int numberOfNames = extBlock.getNumberOfNames();
// a new name is inserted in the end of the SupBookRecord, after the last name
_workbookRecordList.add(supLinkIndex + numberOfNames, extNameRecord);
int fakeSheetIdx = -2;
/* the scope is workbook*/
int ix = _externSheetRecord.getRefIxForSheet(extBlockIndex, fakeSheetIdx, fakeSheetIdx);
return new NameXPtg(ix, nameIndex);
}
use of org.apache.poi.ss.formula.ptg.NameXPtg in project poi by apache.
the class TestLinkTable method testAddNameX.
public void testAddNameX() {
WorkbookRecordList wrl = new WorkbookRecordList();
wrl.add(0, new BOFRecord());
wrl.add(1, new CountryRecord());
wrl.add(2, EOFRecord.instance);
int numberOfSheets = 3;
LinkTable tbl = new LinkTable(numberOfSheets, wrl);
// creation of a new LinkTable insert two new records: SupBookRecord followed by ExternSheetRecord
// assure they are in place:
// [BOFRecord]
// [CountryRecord]
// [SUPBOOK Internal References nSheets= 3]
// [EXTERNSHEET]
// [EOFRecord]
assertEquals(5, wrl.getRecords().size());
assertTrue(wrl.get(2) instanceof SupBookRecord);
SupBookRecord sup1 = (SupBookRecord) wrl.get(2);
assertEquals(numberOfSheets, sup1.getNumberOfSheets());
assertTrue(wrl.get(3) instanceof ExternSheetRecord);
ExternSheetRecord extSheet = (ExternSheetRecord) wrl.get(3);
assertEquals(0, extSheet.getNumOfRefs());
assertNull(tbl.getNameXPtg("ISODD", -1));
//still have five records
assertEquals(5, wrl.getRecords().size());
// adds two new rercords
NameXPtg namex1 = tbl.addNameXPtg("ISODD");
assertEquals(0, namex1.getSheetRefIndex());
assertEquals(0, namex1.getNameIndex());
assertEquals(namex1.toString(), tbl.getNameXPtg("ISODD", -1).toString());
// Can only find on the right sheet ref, if restricting
assertEquals(namex1.toString(), tbl.getNameXPtg("ISODD", 0).toString());
assertNull(tbl.getNameXPtg("ISODD", 1));
assertNull(tbl.getNameXPtg("ISODD", 2));
// assure they are in place:
// [BOFRecord]
// [CountryRecord]
// [SUPBOOK Internal References nSheets= 3]
// [SUPBOOK Add-In Functions nSheets= 1]
// [EXTERNALNAME .name = ISODD]
// [EXTERNSHEET]
// [EOFRecord]
assertEquals(7, wrl.getRecords().size());
assertTrue(wrl.get(3) instanceof SupBookRecord);
SupBookRecord sup2 = (SupBookRecord) wrl.get(3);
assertTrue(sup2.isAddInFunctions());
assertTrue(wrl.get(4) instanceof ExternalNameRecord);
ExternalNameRecord ext1 = (ExternalNameRecord) wrl.get(4);
assertEquals("ISODD", ext1.getText());
assertTrue(wrl.get(5) instanceof ExternSheetRecord);
assertEquals(1, extSheet.getNumOfRefs());
//check that
assertEquals(0, tbl.resolveNameXIx(namex1.getSheetRefIndex(), namex1.getNameIndex()));
assertEquals("ISODD", tbl.resolveNameXText(namex1.getSheetRefIndex(), namex1.getNameIndex(), null));
assertNull(tbl.getNameXPtg("ISEVEN", -1));
// adds two new rercords
NameXPtg namex2 = tbl.addNameXPtg("ISEVEN");
assertEquals(0, namex2.getSheetRefIndex());
// name index increased by one
assertEquals(1, namex2.getNameIndex());
assertEquals(namex2.toString(), tbl.getNameXPtg("ISEVEN", -1).toString());
assertEquals(8, wrl.getRecords().size());
// assure they are in place:
// [BOFRecord]
// [CountryRecord]
// [SUPBOOK Internal References nSheets= 3]
// [SUPBOOK Add-In Functions nSheets= 1]
// [EXTERNALNAME .name = ISODD]
// [EXTERNALNAME .name = ISEVEN]
// [EXTERNSHEET]
// [EOFRecord]
assertTrue(wrl.get(3) instanceof SupBookRecord);
assertTrue(wrl.get(4) instanceof ExternalNameRecord);
assertTrue(wrl.get(5) instanceof ExternalNameRecord);
assertEquals("ISODD", ((ExternalNameRecord) wrl.get(4)).getText());
assertEquals("ISEVEN", ((ExternalNameRecord) wrl.get(5)).getText());
assertTrue(wrl.get(6) instanceof ExternSheetRecord);
assertTrue(wrl.get(7) instanceof EOFRecord);
assertEquals(0, tbl.resolveNameXIx(namex2.getSheetRefIndex(), namex2.getNameIndex()));
assertEquals("ISEVEN", tbl.resolveNameXText(namex2.getSheetRefIndex(), namex2.getNameIndex(), null));
}
Aggregations