/**
*
* @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, UDFFinder udf) {
+ public NameXPtg getNameXPtg(String name, int sheetRefIndex, UDFFinder udf) {
LinkTable lnk = getOrCreateLinkTable();
- NameXPtg xptg = lnk.getNameXPtg(name);
+ NameXPtg xptg = lnk.getNameXPtg(name, sheetRefIndex);
if(xptg == null && udf.findFunction(name) != null) {
// the name was not found in the list of external names
}
return xptg;
}
+ public NameXPtg getNameXPtg(String name, UDFFinder udf) {
+ return getNameXPtg(name, -1, udf);
+ }
/**
* Check if the cloned sheet has drawings. If yes, then allocate a new drawing group ID and
return _externalBookBlocks[extBookIndex].getNameIx(definedNameIndex);
}
- public NameXPtg getNameXPtg(String name) {
+ /**
+ * Finds the external name definition for the given name,
+ * optionally restricted by externsheet index, and returns
+ * (if found) as a NameXPtg.
+ * @param sheetRefIndex The Extern Sheet Index to look for, or -1 if any
+ */
+ public NameXPtg getNameXPtg(String name, int sheetRefIndex) {
// first find any external book block that contains the name:
for (int i = 0; i < _externalBookBlocks.length; i++) {
int definedNameIndex = _externalBookBlocks[i].getIndexOfName(name);
if (definedNameIndex < 0) {
continue;
}
- // found it.
- int sheetRefIndex = findRefIndexFromExtBookIndex(i);
- if (sheetRefIndex >= 0) {
- return new NameXPtg(sheetRefIndex, definedNameIndex);
+
+ // Found one
+ int thisSheetRefIndex = findRefIndexFromExtBookIndex(i);
+ if (thisSheetRefIndex >= 0) {
+ // Check for the sheet index match, if requested
+ if (sheetRefIndex == -1 || thisSheetRefIndex == sheetRefIndex) {
+ return new NameXPtg(thisSheetRefIndex, definedNameIndex);
+ }
}
}
return null;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
-import org.apache.poi.ss.formula.ptg.NamePtg;
-import org.apache.poi.ss.formula.ptg.NameXPtg;
-import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.EvaluationCell;
import org.apache.poi.ss.formula.EvaluationName;
import org.apache.poi.ss.formula.FormulaParsingWorkbook;
import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
import org.apache.poi.ss.formula.FormulaType;
+import org.apache.poi.ss.formula.ptg.NamePtg;
+import org.apache.poi.ss.formula.ptg.NameXPtg;
+import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
return _iBook.getExternalSheetIndex(workbookName, sheetName);
}
- public NameXPtg getNameXPtg(String name) {
- return _iBook.getNameXPtg(name, _uBook.getUDFFinder());
+ public NameXPtg getNameXPtg(String name, int sheetRefIndex) {
+ return _iBook.getNameXPtg(name, sheetRefIndex, _uBook.getUDFFinder());
}
/**
import java.util.List;
import java.util.regex.Pattern;
+import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.constant.ErrorConstant;
-import org.apache.poi.ss.formula.ptg.*;
import org.apache.poi.ss.formula.function.FunctionMetadata;
import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
+import org.apache.poi.ss.formula.ptg.AbstractFunctionPtg;
+import org.apache.poi.ss.formula.ptg.AddPtg;
+import org.apache.poi.ss.formula.ptg.Area3DPtg;
+import org.apache.poi.ss.formula.ptg.AreaPtg;
+import org.apache.poi.ss.formula.ptg.ArrayPtg;
+import org.apache.poi.ss.formula.ptg.AttrPtg;
+import org.apache.poi.ss.formula.ptg.BoolPtg;
+import org.apache.poi.ss.formula.ptg.ConcatPtg;
+import org.apache.poi.ss.formula.ptg.DividePtg;
+import org.apache.poi.ss.formula.ptg.EqualPtg;
+import org.apache.poi.ss.formula.ptg.ErrPtg;
+import org.apache.poi.ss.formula.ptg.FuncPtg;
+import org.apache.poi.ss.formula.ptg.FuncVarPtg;
+import org.apache.poi.ss.formula.ptg.GreaterEqualPtg;
+import org.apache.poi.ss.formula.ptg.GreaterThanPtg;
+import org.apache.poi.ss.formula.ptg.IntPtg;
+import org.apache.poi.ss.formula.ptg.LessEqualPtg;
+import org.apache.poi.ss.formula.ptg.LessThanPtg;
+import org.apache.poi.ss.formula.ptg.MemAreaPtg;
+import org.apache.poi.ss.formula.ptg.MemFuncPtg;
+import org.apache.poi.ss.formula.ptg.MissingArgPtg;
+import org.apache.poi.ss.formula.ptg.MultiplyPtg;
+import org.apache.poi.ss.formula.ptg.NamePtg;
+import org.apache.poi.ss.formula.ptg.NameXPtg;
+import org.apache.poi.ss.formula.ptg.NotEqualPtg;
+import org.apache.poi.ss.formula.ptg.NumberPtg;
+import org.apache.poi.ss.formula.ptg.OperandPtg;
+import org.apache.poi.ss.formula.ptg.OperationPtg;
+import org.apache.poi.ss.formula.ptg.ParenthesisPtg;
+import org.apache.poi.ss.formula.ptg.PercentPtg;
+import org.apache.poi.ss.formula.ptg.PowerPtg;
+import org.apache.poi.ss.formula.ptg.Ptg;
+import org.apache.poi.ss.formula.ptg.RangePtg;
+import org.apache.poi.ss.formula.ptg.Ref3DPtg;
+import org.apache.poi.ss.formula.ptg.RefPtg;
+import org.apache.poi.ss.formula.ptg.StringPtg;
+import org.apache.poi.ss.formula.ptg.SubtractPtg;
+import org.apache.poi.ss.formula.ptg.UnaryMinusPtg;
+import org.apache.poi.ss.formula.ptg.UnaryPlusPtg;
+import org.apache.poi.ss.formula.ptg.UnionPtg;
+import org.apache.poi.ss.formula.ptg.ValueOperatorPtg;
import org.apache.poi.ss.usermodel.ErrorConstants;
-import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.CellReference.NameType;
public Identifier getSheetIdentifier() {
return _sheetIdentifier;
}
+ private void asFormulaString(StringBuffer sb) {
+ if (_bookName != null) {
+ sb.append(" [").append(_sheetIdentifier.getName()).append("]");
+ }
+ if (_sheetIdentifier.isQuoted()) {
+ sb.append("'").append(_sheetIdentifier.getName()).append("'");
+ } else {
+ sb.append(_sheetIdentifier.getName());
+ }
+ }
+ public String asFormulaString() {
+ StringBuffer sb = new StringBuffer(32);
+ asFormulaString(sb);
+ return sb.toString();
+ }
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName());
sb.append(" [");
- if (_bookName != null) {
- sb.append(" [").append(_sheetIdentifier.getName()).append("]");
- }
- if (_sheetIdentifier.isQuoted()) {
- sb.append("'").append(_sheetIdentifier.getName()).append("'");
- } else {
- sb.append(_sheetIdentifier.getName());
- }
+ asFormulaString(sb);
sb.append("]");
return sb.toString();
}
* 'my sheet'!A1
* .my.sheet!A1
* my.named..range.
+ * 'my sheet'!my.named.range
+ * .my.sheet!my.named.range
* foo.bar(123.456, "abc")
* 123.456
* "abc"
if (part1 == null) {
if (sheetIden != null) {
if(look == '#'){ // error ref like MySheet!#REF!
- return new ParseNode(ErrPtg.valueOf(parseErrorLiteral()));
+ return new ParseNode(ErrPtg.valueOf(parseErrorLiteral()));
} else {
- throw new FormulaParseException("Cell reference expected after sheet name at index "
- + _pointer + ".");
+ // 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 + ".");
+ }
+ int extIx = getSheetExtIx(sheetIden);
+ NameXPtg nameXPtg = _book.getNameXPtg(name, extIx);
+ if (nameXPtg == null) {
+ throw new FormulaParseException("Specified name '" + name +
+ "' for sheet " + sheetIden.asFormulaString() + " not found");
+ }
+ return new ParseNode(nameXPtg);
}
}
return parseNonRange(savePointer);
if (look == '"') {
return new ParseNode(new StringPtg(parseStringLiteral()));
}
+
// from now on we can only be dealing with non-quoted identifiers
// which will either be named ranges or functions
- StringBuilder sb = new StringBuilder();
+ String name = parseAsName();
- // defined names may begin with a letter or underscore
- if (!Character.isLetter(look) && look != '_') {
- throw expected("number, string, or defined name");
- }
- while (isValidDefinedNameChar(look)) {
- sb.append(look);
- GetChar();
- }
- SkipWhite();
- String name = sb.toString();
if (look == '(') {
return function(name);
}
throw new FormulaParseException("Specified name '"
+ name + "' is not a range as expected.");
}
+
+ private String parseAsName() {
+ StringBuilder sb = new StringBuilder();
+
+ // defined names may begin with a letter or underscore
+ if (!Character.isLetter(look) && look != '_') {
+ throw expected("number, string, or defined name");
+ }
+ while (isValidDefinedNameChar(look)) {
+ sb.append(look);
+ GetChar();
+ }
+ SkipWhite();
+
+ return sb.toString();
+ }
/**
*
}
return false;
}
+
+ private int getSheetExtIx(SheetIdentifier sheetIden) {
+ int extIx;
+ if (sheetIden == null) {
+ extIx = Integer.MIN_VALUE;
+ } else {
+ String sName = sheetIden.getSheetIdentifier().getName();
+ if (sheetIden.getBookName() == null) {
+ extIx = _book.getExternalSheetIndex(sName);
+ } else {
+ extIx = _book.getExternalSheetIndex(sheetIden.getBookName(), sName);
+ }
+ }
+ return extIx;
+ }
/**
*
*/
private ParseNode createAreaRefParseNode(SheetIdentifier sheetIden, SimpleRangePart part1,
SimpleRangePart part2) throws FormulaParseException {
+ int extIx = getSheetExtIx(sheetIden);
- int extIx;
- if (sheetIden == null) {
- extIx = Integer.MIN_VALUE;
- } else {
- String sName = sheetIden.getSheetIdentifier().getName();
- if (sheetIden.getBookName() == null) {
- extIx = _book.getExternalSheetIndex(sName);
- } else {
- extIx = _book.getExternalSheetIndex(sheetIden.getBookName(), sName);
- }
- }
Ptg ptg;
if (part2 == null) {
CellReference cr = part1.getCellReference();
}
EvaluationName hName = _book.getName(name, _sheetIndex);
if (hName == null) {
-
- nameToken = _book.getNameXPtg(name);
+ nameToken = _book.getNameXPtg(name, -1);
if (nameToken == null) {
throw new FormulaParseException("Name '" + name
+ "' is completely unknown in the current workbook");
package org.apache.poi.ss.formula;
-import org.apache.poi.ss.formula.ptg.NameXPtg;
import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.formula.ptg.NameXPtg;
/**
* Abstracts a workbook for the purpose of formula parsing.<br/>
*/
EvaluationName getName(String name, int sheetIndex);
- NameXPtg getNameXPtg(String name);
+ NameXPtg getNameXPtg(String name, int sheetRefIndex);
/**
* gets the externSheet index for a sheet from this workbook
throw new RuntimeException("Not implemented yet");
}
- public NameXPtg getNameXPtg(String name) {
+ public NameXPtg getNameXPtg(String name, int sheetRefIndex) {
IndexedUDFFinder udfFinder = (IndexedUDFFinder)getUDFFinder();
FreeRefFunction func = udfFinder.findFunction(name);
if(func == null) return null;
bug53798Work(wb, xlsOutput);
}
- @Ignore("Shifting rows is not yet implemented in XSSFSheet")
+ @Ignore("Shifting rows is not yet implemented in SXSSFSheet")
@Test
public void testBug53798XLSXStream() throws IOException {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("53798_shiftNegative_TMPL.xlsx");
* org.apache.poi.ss.formula.FormulaParseException: Cell reference expected after sheet name at index 9
* org.apache.poi.ss.formula.FormulaParseException: Parse error near char 0 '[' in specified formula '[0]!NR_Global_B2'. Expected number, string, or defined name
*/
- @Ignore
@Test
+ @Ignore
public void bug56737() throws IOException {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56737.xlsx");
Cell cRefWName = s.getRow(2).getCell(3);
assertEquals("Defines!NR_To_A1", cRefSName.getCellFormula());
+ // TODO Why aren't we showing the real filename as Excel does?
assertEquals("[0]!NR_Global_B2", cRefWName.getCellFormula());
// Try to evaluate them
import org.apache.poi.ss.formula.FormulaParser;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.formula.constant.ErrorConstant;
-import org.apache.poi.ss.formula.ptg.*;
+import org.apache.poi.ss.formula.ptg.AbstractFunctionPtg;
+import org.apache.poi.ss.formula.ptg.AddPtg;
+import org.apache.poi.ss.formula.ptg.Area3DPtg;
+import org.apache.poi.ss.formula.ptg.AreaI;
+import org.apache.poi.ss.formula.ptg.AreaPtg;
+import org.apache.poi.ss.formula.ptg.AreaPtgBase;
+import org.apache.poi.ss.formula.ptg.ArrayPtg;
+import org.apache.poi.ss.formula.ptg.AttrPtg;
+import org.apache.poi.ss.formula.ptg.BoolPtg;
+import org.apache.poi.ss.formula.ptg.ConcatPtg;
+import org.apache.poi.ss.formula.ptg.DividePtg;
+import org.apache.poi.ss.formula.ptg.EqualPtg;
+import org.apache.poi.ss.formula.ptg.ErrPtg;
+import org.apache.poi.ss.formula.ptg.FuncPtg;
+import org.apache.poi.ss.formula.ptg.FuncVarPtg;
+import org.apache.poi.ss.formula.ptg.IntPtg;
+import org.apache.poi.ss.formula.ptg.MemAreaPtg;
+import org.apache.poi.ss.formula.ptg.MemFuncPtg;
+import org.apache.poi.ss.formula.ptg.MissingArgPtg;
+import org.apache.poi.ss.formula.ptg.MultiplyPtg;
+import org.apache.poi.ss.formula.ptg.NamePtg;
+import org.apache.poi.ss.formula.ptg.NumberPtg;
+import org.apache.poi.ss.formula.ptg.ParenthesisPtg;
+import org.apache.poi.ss.formula.ptg.PercentPtg;
+import org.apache.poi.ss.formula.ptg.PowerPtg;
+import org.apache.poi.ss.formula.ptg.Ptg;
+import org.apache.poi.ss.formula.ptg.RangePtg;
+import org.apache.poi.ss.formula.ptg.Ref3DPtg;
+import org.apache.poi.ss.formula.ptg.RefPtg;
+import org.apache.poi.ss.formula.ptg.StringPtg;
+import org.apache.poi.ss.formula.ptg.SubtractPtg;
+import org.apache.poi.ss.formula.ptg.UnaryMinusPtg;
+import org.apache.poi.ss.formula.ptg.UnaryPlusPtg;
+import org.apache.poi.ss.formula.ptg.UnionPtg;
import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.util.HexRead;
confirmParseError(wb, "A1:ROUND(B1,1)", "The RHS of the range operator ':' at position 3 is not a proper reference.");
- confirmParseError(wb, "Sheet1!Sheet1", "Cell reference expected after sheet name at index 8.");
+ confirmParseError(wb, "Sheet1!!!", "Parse error near char 7 '!' in specified formula 'Sheet1!!!'. Expected number, string, or defined name");
+ confirmParseError(wb, "Sheet1!.Name", "Parse error near char 7 '.' in specified formula 'Sheet1!.Name'. Expected number, string, or defined name");
+ confirmParseError(wb, "Sheet1!Sheet1", "Specified name 'Sheet1' for sheet Sheet1 not found");
confirmParseError(wb, "Sheet1!F:Sheet1!G", "'Sheet1!F' is not a proper reference.");
confirmParseError(wb, "Sheet1!F..foobar", "Complete area reference expected after sheet name at index 11.");
confirmParseError(wb, "Sheet1!A .. B", "Dotted range (full row or column) expression 'A .. B' must not contain whitespace.");
ExternSheetRecord extSheet = (ExternSheetRecord)wrl.get(3);
assertEquals(0, extSheet.getNumOfRefs());
- assertNull(tbl.getNameXPtg("ISODD"));
+ assertNull(tbl.getNameXPtg("ISODD", -1));
assertEquals(5, wrl.getRecords().size()); //still have five records
NameXPtg namex1 = tbl.addNameXPtg("ISODD"); // adds two new rercords
assertEquals(0, namex1.getSheetRefIndex());
assertEquals(0, namex1.getNameIndex());
- assertEquals(namex1.toString(), tbl.getNameXPtg("ISODD").toString());
+ 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]
assertEquals(0, tbl.resolveNameXIx(namex1.getSheetRefIndex(), namex1.getNameIndex()));
assertEquals("ISODD", tbl.resolveNameXText(namex1.getSheetRefIndex(), namex1.getNameIndex(), null));
- assertNull(tbl.getNameXPtg("ISEVEN"));
+ assertNull(tbl.getNameXPtg("ISEVEN", -1));
NameXPtg namex2 = tbl.addNameXPtg("ISEVEN"); // adds two new rercords
assertEquals(0, namex2.getSheetRefIndex());
assertEquals(1, namex2.getNameIndex()); // name index increased by one
- assertEquals(namex2.toString(), tbl.getNameXPtg("ISEVEN").toString());
+ assertEquals(namex2.toString(), tbl.getNameXPtg("ISEVEN", -1).toString());
assertEquals(8, wrl.getRecords().size());
// assure they are in place:
// [BOFRecord]
// Try to evaluate everything
eval.evaluateAll();
+
+ // Try to set the same kinds of formula elsewhere
+ Cell newF = s.getRow(0).createCell(10, Cell.CELL_TYPE_FORMULA);
+ newF.setCellFormula("Defines!NR_To_A1");
}
}