diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFEvaluationWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFEvaluationWorkbook.java index b873588db..3582daefc 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFEvaluationWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFEvaluationWorkbook.java @@ -28,7 +28,7 @@ import org.apache.poi.xssf.usermodel.BaseXSSFEvaluationWorkbook; * SXSSF wrapper around the SXSSF and XSSF workbooks */ public final class SXSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook { - private SXSSFWorkbook _uBook; + private final SXSSFWorkbook _uBook; public static SXSSFEvaluationWorkbook create(SXSSFWorkbook book) { if (book == null) { @@ -41,16 +41,19 @@ public final class SXSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook { super(book.getXSSFWorkbook()); _uBook = book; } - + + @Override public int getSheetIndex(EvaluationSheet evalSheet) { SXSSFSheet sheet = ((SXSSFEvaluationSheet)evalSheet).getSXSSFSheet(); return _uBook.getSheetIndex(sheet); } - + + @Override public EvaluationSheet getSheet(int sheetIndex) { return new SXSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex)); } - + + @Override public Ptg[] getFormulaTokens(EvaluationCell evalCell) { SXSSFCell cell = ((SXSSFEvaluationCell)evalCell).getSXSSFCell(); SXSSFEvaluationWorkbook frBook = SXSSFEvaluationWorkbook.create(_uBook); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java index 0bf7d501a..41dd05c6c 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java @@ -17,7 +17,10 @@ package org.apache.poi.xssf.usermodel; +import java.util.HashMap; import java.util.List; +import java.util.Locale; +import java.util.Map; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.formula.EvaluationName; @@ -37,6 +40,7 @@ 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.usermodel.Table; +import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.NotImplemented; @@ -310,9 +314,47 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork public XSSFName createName() { return _uBook.createName(); } - - public Table getTable(String name) { - return _uBook.getTable(name); + + /* + * TODO: data tables are stored at the workbook level in XSSF, but are bound to a single sheet. + * The current code structure has them hanging off XSSFSheet, but formulas reference them + * only by name (names are global, and case insensitive). + * This map stores names as lower case for case-insensitive lookups. + * + * FIXME: Caching tables by name here for fast formula lookup means the map is out of date if + * a table is renamed or added/removed to a sheet after the map is created. + * + * Perhaps tables can be managed similar to PivotTable references above? + */ + private Map _tableCache = null; + private Map getTableCache() { + if ( _tableCache != null ) { + return _tableCache; + } + // FIXME: use org.apache.commons.collections.map.CaseInsensitiveMap + _tableCache = new HashMap(); + + for (Sheet sheet : _uBook) { + for (XSSFTable tbl : ((XSSFSheet)sheet).getTables()) { + String lname = tbl.getName().toLowerCase(Locale.ROOT); + _tableCache.put(lname, tbl); + } + } + return _tableCache; + } + + /** + * Returns the data table with the given name (case insensitive). + * Tables are cached for performance (formula evaluation looks them up by name repeatedly). + * After the first table lookup, adding or removing a table from the document structure will cause trouble. + * This is meant to be used on documents whose structure is essentially static at the point formulas are evaluated. + * + * @param name the data table name (case-insensitive) + * @return The Data table in the workbook named name, or null if no table is named name. + * @since 3.15 beta 2 + */ + public XSSFTable getTable(String name) { + return getTableCache().get(name.toLowerCase(Locale.ROOT)); } public UDFFinder getUDFFinder(){ 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 bf6d1461e..5fead42f1 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java @@ -27,7 +27,6 @@ import org.apache.poi.ss.formula.ptg.Ptg; * Internal POI use only */ public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook { - @Override public static XSSFEvaluationWorkbook create(XSSFWorkbook book) { if (book == null) { return null;