diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java index d1b80932a..877a8f21d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java @@ -30,10 +30,15 @@ import org.apache.poi.ss.formula.FormulaParseException; 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.SheetIdentifier; +import org.apache.poi.ss.formula.ptg.Area3DPtg; 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.ptg.Ref3DPtg; import org.apache.poi.ss.formula.udf.UDFFinder; +import org.apache.poi.ss.util.AreaReference; +import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -64,8 +69,17 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E public int getExternalSheetIndex(String workbookName, String sheetName) { return _iBook.getExternalSheetIndex(workbookName, sheetName); } - - public NameXPtg getNameXPtg(String name, int sheetRefIndex) { + + public Ptg get3DReferencePtg(CellReference cr, SheetIdentifier sheet) { + int extIx = getSheetExtIx(sheet); + return new Ref3DPtg(cr, extIx); + } + public Ptg get3DReferencePtg(AreaReference areaRef, SheetIdentifier sheet) { + int extIx = getSheetExtIx(sheet); + return new Area3DPtg(areaRef, extIx); + } + public NameXPtg getNameXPtg(String name, SheetIdentifier sheet) { + int sheetRefIndex = getSheetExtIx(sheet); return _iBook.getNameXPtg(name, sheetRefIndex, _uBook.getUDFFinder()); } @@ -178,6 +192,21 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E } } + private int getSheetExtIx(SheetIdentifier sheetIden) { + int extIx; + if (sheetIden == null) { + extIx = -1; + } else { + String sName = sheetIden.getSheetIdentifier().getName(); + if (sheetIden.getBookName() == null) { + extIx = getExternalSheetIndex(sName); + } else { + extIx = getExternalSheetIndex(sheetIden.getBookName(), sName); + } + } + return extIx; + } + public SpreadsheetVersion getSpreadsheetVersion(){ return SpreadsheetVersion.EXCEL97; } diff --git a/src/java/org/apache/poi/ss/formula/FormulaParser.java b/src/java/org/apache/poi/ss/formula/FormulaParser.java index c8a5ecc55..570dd5bca 100644 --- a/src/java/org/apache/poi/ss/formula/FormulaParser.java +++ b/src/java/org/apache/poi/ss/formula/FormulaParser.java @@ -27,7 +27,6 @@ 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; @@ -58,7 +57,6 @@ 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; @@ -83,85 +81,8 @@ import org.apache.poi.ss.util.CellReference.NameType; *
* For POI internal use only * - * - * - * @author Avik Senguptanull
@@ -686,15 +591,13 @@ public final class FormulaParser {
*/
private ParseNode createAreaRefParseNode(SheetIdentifier sheetIden, SimpleRangePart part1,
SimpleRangePart part2) throws FormulaParseException {
- int extIx = getSheetExtIx(sheetIden);
-
Ptg ptg;
if (part2 == null) {
CellReference cr = part1.getCellReference();
if (sheetIden == null) {
ptg = new RefPtg(cr);
} else {
- ptg = new Ref3DPtg(cr, extIx);
+ ptg = _book.get3DReferencePtg(cr, sheetIden);
}
} else {
AreaReference areaRef = createAreaRef(part1, part2);
@@ -702,7 +605,7 @@ public final class FormulaParser {
if (sheetIden == null) {
ptg = new AreaPtg(areaRef);
} else {
- ptg = new Area3DPtg(areaRef, extIx);
+ ptg = _book.get3DReferencePtg(areaRef, sheetIden);
}
}
return new ParseNode(ptg);
@@ -895,7 +798,7 @@ public final class FormulaParser {
}
}
- Identifier iden = new Identifier(sb.toString(), true);
+ NameIdentifier iden = new NameIdentifier(sb.toString(), true);
// quoted identifier - can't concatenate anything more
SkipWhite();
if (look == '!') {
@@ -916,7 +819,7 @@ public final class FormulaParser {
SkipWhite();
if (look == '!') {
GetChar();
- return new SheetIdentifier(bookName, new Identifier(sb.toString(), false));
+ return new SheetIdentifier(bookName, new NameIdentifier(sb.toString(), false));
}
return null;
}
@@ -987,7 +890,7 @@ public final class FormulaParser {
}
EvaluationName hName = _book.getName(name, _sheetIndex);
if (hName == null) {
- nameToken = _book.getNameXPtg(name, -1);
+ nameToken = _book.getNameXPtg(name, null);
if (nameToken == null) {
throw new FormulaParseException("Name '" + name
+ "' is completely unknown in the current workbook");
diff --git a/src/java/org/apache/poi/ss/formula/FormulaParsingWorkbook.java b/src/java/org/apache/poi/ss/formula/FormulaParsingWorkbook.java
index f5b52237f..ef2256025 100644
--- a/src/java/org/apache/poi/ss/formula/FormulaParsingWorkbook.java
+++ b/src/java/org/apache/poi/ss/formula/FormulaParsingWorkbook.java
@@ -19,6 +19,9 @@ package org.apache.poi.ss.formula;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.ptg.NameXPtg;
+import org.apache.poi.ss.formula.ptg.Ptg;
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.util.CellReference;
/**
* Abstracts a workbook for the purpose of formula parsing.- * Description: Defined a cell in extern sheet.
- * REFERENCE:
- * @author Libin Roman (Vista Portal LDT. Developer) - * @author Jason Height (jheight at chariot dot net dot au) + *
Title: Reference 3D Ptg
+ *Description: Defined a cell in extern sheet.
+ *REFERENCE:
+ * + *This is HSSF only, as it matches the HSSF file format way of + * referring to the sheet by an extern index. The XSSF equivalent + * is {@link Ref3DPxg} */ public final class Ref3DPtg extends RefPtgBase implements WorkbookDependentFormula, ExternSheetReferenceToken { public final static byte sid = 0x3a; diff --git a/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java b/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java new file mode 100644 index 000000000..ed95892fb --- /dev/null +++ b/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java @@ -0,0 +1,97 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.ptg; + +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.util.LittleEndianOutput; + +/** + *
Title: XSSF 3D Reference
+ *Description: Defines a cell in an external or different sheet.
+ *REFERENCE:
+ * + *This is XSSF only, as it stores the sheet / book references + * in String form. The HSSF equivalent using indexes is {@link Ref3DPtg}
+ */ +public final class Ref3DPxg extends RefPtgBase { + private int externalWorkbookNumber = -1; + private String sheetName; + + public Ref3DPxg(int externalWorkbookNumber, String sheetName, String cellref) { + this(externalWorkbookNumber, sheetName, new CellReference(cellref)); + } + public Ref3DPxg(int externalWorkbookNumber, String sheetName, CellReference c) { + super(c); + this.externalWorkbookNumber = externalWorkbookNumber; + this.sheetName = sheetName; + } + + public Ref3DPxg(String sheetName, String cellref) { + this(sheetName, new CellReference(cellref)); + } + public Ref3DPxg(String sheetName, CellReference c) { + this(-1, sheetName, c); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(getClass().getName()); + sb.append(" ["); + if (externalWorkbookNumber >= 0) { + sb.append(" ["); + sb.append("workbook=").append(getExternalWorkbookNumber()); + sb.append("] "); + } + sb.append("sheet=").append(getSheetName()); + sb.append(" ! "); + sb.append(formatReferenceAsString()); + sb.append("]"); + return sb.toString(); + } + + public int getExternalWorkbookNumber() { + return externalWorkbookNumber; + } + public String getSheetName() { + return sheetName; + } + + public String format2DRefAsString() { + return formatReferenceAsString(); + } + + public String toFormulaString() { + StringBuffer sb = new StringBuffer(); + if (externalWorkbookNumber >= 0) { + sb.append('['); + sb.append(externalWorkbookNumber); + sb.append(']'); + } + sb.append(sheetName); + sb.append('!'); + sb.append(formatReferenceAsString()); + return sb.toString(); + } + + public int getSize() { + return 1; + } + public void write(LittleEndianOutput out) { + throw new IllegalStateException("XSSF-only Ptg, should not be serialised"); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java index ea9f93d61..5a4bfa534 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java @@ -26,12 +26,17 @@ import org.apache.poi.ss.formula.FormulaParser; 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.SheetIdentifier; import org.apache.poi.ss.formula.functions.FreeRefFunction; +import org.apache.poi.ss.formula.ptg.Area3DPtg; 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.ptg.Ref3DPxg; import org.apache.poi.ss.formula.udf.IndexedUDFFinder; import org.apache.poi.ss.formula.udf.UDFFinder; +import org.apache.poi.ss.util.AreaReference; +import org.apache.poi.ss.util.CellReference; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName; /** @@ -77,6 +82,19 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E int sheetIndex = _uBook.getSheetIndex(sheetName); return convertToExternalSheetIndex(sheetIndex); } + + private int resolveBookIndex(String bookName) { + // Is it already in numeric form? + if (bookName.startsWith("[") && bookName.endsWith("]")) { + bookName = bookName.substring(1, bookName.length()-2); + try { + return Integer.parseInt(bookName); + } catch (NumberFormatException e) {} + } + + // Look up an External Link Table for this name + throw new RuntimeException("Not implemented yet"); // TODO + } public EvaluationName getName(String name, int sheetIndex) { for (int i = 0; i < _uBook.getNumberOfNames(); i++) { @@ -102,7 +120,7 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E throw new RuntimeException("Not implemented yet"); } - public NameXPtg getNameXPtg(String name, int sheetRefIndex) { + public NameXPtg getNameXPtg(String name, SheetIdentifier sheet) { // First, try to find it as a User Defined Function IndexedUDFFinder udfFinder = (IndexedUDFFinder)getUDFFinder(); FreeRefFunction func = udfFinder.findFunction(name); @@ -119,6 +137,20 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E return null; } } + public Ptg get3DReferencePtg(CellReference cell, SheetIdentifier sheet) { + String sheetName = sheet._sheetIdentifier.getName(); + + if (sheet._bookName != null) { + int bookIndex = resolveBookIndex(sheet._bookName); + return new Ref3DPxg(bookIndex, sheetName, cell); + } else { + return new Ref3DPxg(sheetName, cell); + } + } + public Ptg get3DReferencePtg(AreaReference area, SheetIdentifier sheet) { + // TODO Implement properly + return new Area3DPtg(area, getExternalSheetIndex(sheet._sheetIdentifier.getName())); + } public String resolveNameXText(NameXPtg n) { int idx = n.getNameIndex(); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java index 9819935ad..f0cc98a31 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java @@ -27,7 +27,7 @@ import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.ptg.FuncPtg; import org.apache.poi.ss.formula.ptg.IntPtg; import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.formula.ptg.Ref3DPtg; +import org.apache.poi.ss.formula.ptg.Ref3DPxg; import org.apache.poi.ss.formula.ptg.RefPtg; import org.apache.poi.xssf.XSSFTestDataSamples; import org.junit.Ignore; @@ -106,9 +106,9 @@ public final class TestXSSFFormulaParser { // Reference to a single cell in a different sheet ptgs = parse(fpb, "Uses!A1"); assertEquals(1, ptgs.length); - assertEquals(Ref3DPtg.class, ptgs[0].getClass()); - assertEquals("A1", ((Ref3DPtg)ptgs[0]).format2DRefAsString()); - assertEquals("Uses!A1", ((Ref3DPtg)ptgs[0]).toFormulaString(fpb)); + assertEquals(Ref3DPxg.class, ptgs[0].getClass()); + assertEquals("A1", ((Ref3DPxg)ptgs[0]).format2DRefAsString()); + assertEquals("Uses!A1", ((Ref3DPxg)ptgs[0]).toFormulaString()); // Reference to a sheet scoped named range from another sheet ptgs = parse(fpb, "Defines!NR_To_A1");