mirror of https://github.com/apache/poi.git
Start to update how the formula parser looks up sheets from formula ptgs, to account for the differences in how HSSF and XSSF store references to external sheets. For #56737
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1611948 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
76c8077a40
commit
83d9405d43
|
@ -120,10 +120,29 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||||
return _iBook.getExternalSheet(externSheetIndex);
|
ExternalSheet sheet = _iBook.getExternalSheet(externSheetIndex);
|
||||||
|
if (sheet == null) {
|
||||||
|
// Try to treat it as a local sheet
|
||||||
|
int localSheetIndex = convertFromExternSheetIndex(externSheetIndex);
|
||||||
|
if (localSheetIndex == -1) {
|
||||||
|
// The sheet referenced can't be found, sorry
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (localSheetIndex == -2) {
|
||||||
|
// Not actually sheet based at all - is workbook scoped
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Look up the local sheet
|
||||||
|
String sheetName = getSheetName(localSheetIndex);
|
||||||
|
sheet = new ExternalSheet(null, sheetName);
|
||||||
|
}
|
||||||
|
return sheet;
|
||||||
}
|
}
|
||||||
|
public ExternalSheet getExternalSheet(String sheetName, int externalWorkbookNumber) {
|
||||||
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
throw new IllegalStateException("XSSF-style external references are not supported for HSSF");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
|
||||||
return _iBook.getExternalName(externSheetIndex, externNameIndex);
|
return _iBook.getExternalName(externSheetIndex, externNameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +160,9 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
int ix = namePtg.getIndex();
|
int ix = namePtg.getIndex();
|
||||||
return new Name(_iBook.getNameRecord(ix), ix);
|
return new Name(_iBook.getNameRecord(ix), ix);
|
||||||
}
|
}
|
||||||
public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
|
||||||
HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
|
HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
|
||||||
if (false) {
|
if (false) {
|
||||||
// re-parsing the formula text also works, but is a waste of time
|
// re-parsing the formula text also works, but is a waste of time
|
||||||
|
@ -159,6 +180,7 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
|
||||||
return fra.getFormulaTokens();
|
return fra.getFormulaTokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UDFFinder getUDFFinder(){
|
public UDFFinder getUDFFinder(){
|
||||||
return _uBook.getUDFFinder();
|
return _uBook.getUDFFinder();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,21 @@ public interface EvaluationWorkbook {
|
||||||
EvaluationSheet getSheet(int sheetIndex);
|
EvaluationSheet getSheet(int sheetIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return <code>null</code> if externSheetIndex refers to a sheet inside the current workbook
|
* HSSF Only - fetch the external-style sheet details
|
||||||
|
* <p>Return will have no workbook set if it's actually in our own workbook</p>
|
||||||
*/
|
*/
|
||||||
ExternalSheet getExternalSheet(int externSheetIndex);
|
ExternalSheet getExternalSheet(int externSheetIndex);
|
||||||
|
/**
|
||||||
|
* XSSF Only - fetch the external-style sheet details
|
||||||
|
* <p>Return will have no workbook set if it's actually in our own workbook</p>
|
||||||
|
*/
|
||||||
|
ExternalSheet getExternalSheet(String sheetName, int externalWorkbookNumber);
|
||||||
|
/**
|
||||||
|
* HSSF Only - convert an external sheet index to an internal sheet index,
|
||||||
|
* for an external-style reference to one of this workbook's own sheets
|
||||||
|
*/
|
||||||
int convertFromExternSheetIndex(int externSheetIndex);
|
int convertFromExternSheetIndex(int externSheetIndex);
|
||||||
|
|
||||||
ExternalName getExternalName(int externSheetIndex, int externNameIndex);
|
ExternalName getExternalName(int externSheetIndex, int externNameIndex);
|
||||||
EvaluationName getName(NamePtg namePtg);
|
EvaluationName getName(NamePtg namePtg);
|
||||||
EvaluationName getName(String name, int sheetIndex);
|
EvaluationName getName(String name, int sheetIndex);
|
||||||
|
|
|
@ -17,16 +17,21 @@
|
||||||
|
|
||||||
package org.apache.poi.ss.formula;
|
package org.apache.poi.ss.formula;
|
||||||
|
|
||||||
import org.apache.poi.ss.formula.ptg.Area3DPtg;
|
|
||||||
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.eval.*;
|
|
||||||
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
|
||||||
import org.apache.poi.ss.SpreadsheetVersion;
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
|
||||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
|
||||||
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
|
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
|
||||||
|
import org.apache.poi.ss.formula.eval.AreaEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.NameXEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.RefEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||||
|
import org.apache.poi.ss.formula.functions.FreeRefFunction;
|
||||||
|
import org.apache.poi.ss.formula.ptg.Area3DPtg;
|
||||||
|
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.ptg.Ref3DPxg;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.apache.poi.ss.util.CellReference.NameType;
|
import org.apache.poi.ss.util.CellReference.NameType;
|
||||||
|
|
||||||
|
@ -70,13 +75,20 @@ public final class OperationEvaluationContext {
|
||||||
SheetRefEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) {
|
SheetRefEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) {
|
||||||
return createExternSheetRefEvaluator(ptg.getExternSheetIndex());
|
return createExternSheetRefEvaluator(ptg.getExternSheetIndex());
|
||||||
}
|
}
|
||||||
|
SheetRefEvaluator createExternSheetRefEvaluator(String sheetName, int externalWorkbookNumber) {
|
||||||
|
ExternalSheet externalSheet = _workbook.getExternalSheet(sheetName, externalWorkbookNumber);
|
||||||
|
return createExternSheetRefEvaluator(externalSheet);
|
||||||
|
}
|
||||||
SheetRefEvaluator createExternSheetRefEvaluator(int externSheetIndex) {
|
SheetRefEvaluator createExternSheetRefEvaluator(int externSheetIndex) {
|
||||||
ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex);
|
ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex);
|
||||||
|
return createExternSheetRefEvaluator(externalSheet);
|
||||||
|
}
|
||||||
|
SheetRefEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) {
|
||||||
WorkbookEvaluator targetEvaluator;
|
WorkbookEvaluator targetEvaluator;
|
||||||
int otherSheetIndex;
|
int otherSheetIndex;
|
||||||
if (externalSheet == null) {
|
if (externalSheet == null || externalSheet.getWorkbookName() == null) {
|
||||||
// sheet is in same workbook
|
// sheet is in same workbook
|
||||||
otherSheetIndex = _workbook.convertFromExternSheetIndex(externSheetIndex);
|
otherSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName());
|
||||||
targetEvaluator = _bookEvaluator;
|
targetEvaluator = _bookEvaluator;
|
||||||
} else {
|
} else {
|
||||||
// look up sheet by name from external workbook
|
// look up sheet by name from external workbook
|
||||||
|
@ -259,10 +271,14 @@ public final class OperationEvaluationContext {
|
||||||
SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet();
|
SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet();
|
||||||
return new LazyRefEval(rowIndex, columnIndex, sre);
|
return new LazyRefEval(rowIndex, columnIndex, sre);
|
||||||
}
|
}
|
||||||
public ValueEval getRef3DEval(int rowIndex, int columnIndex, int extSheetIndex) {
|
public ValueEval getRef3DEval(Ref3DPtg rptg) {
|
||||||
SheetRefEvaluator sre = createExternSheetRefEvaluator(extSheetIndex);
|
SheetRefEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex());
|
||||||
return new LazyRefEval(rowIndex, columnIndex, sre);
|
return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
|
||||||
}
|
}
|
||||||
|
public ValueEval getRef3DEval(Ref3DPxg rptg) {
|
||||||
|
SheetRefEvaluator sre = createExternSheetRefEvaluator(rptg.getSheetName(), rptg.getExternalWorkbookNumber());
|
||||||
|
return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
|
||||||
|
}
|
||||||
public ValueEval getAreaEval(int firstRowIndex, int firstColumnIndex,
|
public ValueEval getAreaEval(int firstRowIndex, int firstColumnIndex,
|
||||||
int lastRowIndex, int lastColumnIndex) {
|
int lastRowIndex, int lastColumnIndex) {
|
||||||
SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet();
|
SheetRefEvaluator sre = getRefEvaluatorForCurrentSheet();
|
||||||
|
|
|
@ -28,7 +28,6 @@ import org.apache.poi.ss.usermodel.Cell;
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
final class SheetRefEvaluator {
|
final class SheetRefEvaluator {
|
||||||
|
|
||||||
private final WorkbookEvaluator _bookEvaluator;
|
private final WorkbookEvaluator _bookEvaluator;
|
||||||
private final EvaluationTracker _tracker;
|
private final EvaluationTracker _tracker;
|
||||||
private final int _sheetIndex;
|
private final int _sheetIndex;
|
||||||
|
|
|
@ -673,12 +673,10 @@ public final class WorkbookEvaluator {
|
||||||
return ErrorEval.REF_INVALID;
|
return ErrorEval.REF_INVALID;
|
||||||
}
|
}
|
||||||
if (ptg instanceof Ref3DPtg) {
|
if (ptg instanceof Ref3DPtg) {
|
||||||
Ref3DPtg rptg = (Ref3DPtg) ptg;
|
return ec.getRef3DEval((Ref3DPtg)ptg);
|
||||||
return ec.getRef3DEval(rptg.getRow(), rptg.getColumn(), rptg.getExternSheetIndex());
|
|
||||||
}
|
}
|
||||||
if (ptg instanceof Ref3DPxg) {
|
if (ptg instanceof Ref3DPxg) {
|
||||||
Ref3DPtg rptg = (Ref3DPtg) ptg;
|
return ec.getRef3DEval((Ref3DPxg)ptg);
|
||||||
// TODO Return the right eval, should be easy as we already know the sheet details
|
|
||||||
}
|
}
|
||||||
if (ptg instanceof Area3DPtg) {
|
if (ptg instanceof Area3DPtg) {
|
||||||
Area3DPtg aptg = (Area3DPtg) ptg;
|
Area3DPtg aptg = (Area3DPtg) ptg;
|
||||||
|
|
|
@ -20,13 +20,13 @@ package org.apache.poi.ss.formula.eval.forked;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
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.EvaluationCell;
|
import org.apache.poi.ss.formula.EvaluationCell;
|
||||||
import org.apache.poi.ss.formula.EvaluationName;
|
import org.apache.poi.ss.formula.EvaluationName;
|
||||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||||
|
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.ss.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
|
||||||
|
@ -90,8 +90,11 @@ final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||||
return _masterBook.getExternalSheet(externSheetIndex);
|
return _masterBook.getExternalSheet(externSheetIndex);
|
||||||
}
|
}
|
||||||
|
public ExternalSheet getExternalSheet(String sheetName, int externalWorkbookNumber) {
|
||||||
|
return _masterBook.getExternalSheet(sheetName, externalWorkbookNumber);
|
||||||
|
}
|
||||||
|
|
||||||
public Ptg[] getFormulaTokens(EvaluationCell cell) {
|
public Ptg[] getFormulaTokens(EvaluationCell cell) {
|
||||||
if (cell instanceof ForkedEvaluationCell) {
|
if (cell instanceof ForkedEvaluationCell) {
|
||||||
// doesn't happen yet because formulas cannot be modified from the master workbook
|
// doesn't happen yet because formulas cannot be modified from the master workbook
|
||||||
throw new RuntimeException("Updated formulas not supported yet");
|
throw new RuntimeException("Updated formulas not supported yet");
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.poi.ss.formula.udf.IndexedUDFFinder;
|
||||||
import org.apache.poi.ss.formula.udf.UDFFinder;
|
import org.apache.poi.ss.formula.udf.UDFFinder;
|
||||||
import org.apache.poi.ss.util.AreaReference;
|
import org.apache.poi.ss.util.AreaReference;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
|
import org.apache.poi.xssf.model.ExternalLinksTable;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +64,8 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
return externSheetIndex;
|
return externSheetIndex;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return the sheet index of the sheet with the given external index.
|
* XSSF doesn't use external sheet indexes, so when asked treat
|
||||||
|
* it just as a local index
|
||||||
*/
|
*/
|
||||||
public int convertFromExternSheetIndex(int externSheetIndex) {
|
public int convertFromExternSheetIndex(int externSheetIndex) {
|
||||||
return externSheetIndex;
|
return externSheetIndex;
|
||||||
|
@ -175,10 +177,21 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||||
// TODO Auto-generated method stub
|
throw new IllegalStateException("HSSF-style external references are not supported for XSSF");
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
public int getExternalSheetIndex(String workbookName, String sheetName) {
|
public ExternalSheet getExternalSheet(String sheetName, int externalWorkbookNumber) {
|
||||||
|
if (externalWorkbookNumber > 0) {
|
||||||
|
// External reference - reference is 1 based, link table is 0 based
|
||||||
|
int linkNumber = externalWorkbookNumber - 1;
|
||||||
|
ExternalLinksTable linkTable = _uBook.getExternalLinksTable().get(linkNumber);
|
||||||
|
return new ExternalSheet(linkTable.getLinkedFileName(), sheetName);
|
||||||
|
} else {
|
||||||
|
// Internal reference
|
||||||
|
return new ExternalSheet(null, sheetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getExternalSheetIndex(String workbookName, String sheetName) {
|
||||||
throw new RuntimeException("not implemented yet");
|
throw new RuntimeException("not implemented yet");
|
||||||
}
|
}
|
||||||
public int getSheetIndex(String sheetName) {
|
public int getSheetIndex(String sheetName) {
|
||||||
|
|
Loading…
Reference in New Issue