]> source.dussan.org Git - poi.git/commitdiff
bug 57840: apply patch from Daniel Livshen and Greg Woolsey to get structured referen...
authorJaven O'Neal <onealj@apache.org>
Fri, 10 Jun 2016 00:21:59 +0000 (00:21 +0000)
committerJaven O'Neal <onealj@apache.org>
Fri, 10 Jun 2016 00:21:59 +0000 (00:21 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xssf_structured_references@1747612 13f79535-47bb-0310-9956-ffa450edef68

20 files changed:
src/java/org/apache/poi/hssf/model/HSSFFormulaParser.java
src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java
src/java/org/apache/poi/ss/formula/FormulaParser.java
src/java/org/apache/poi/ss/formula/FormulaParsingWorkbook.java
src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java
src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
src/java/org/apache/poi/ss/formula/functions/Indirect.java
src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java
src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java
src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
src/testcases/org/apache/poi/hssf/record/TestArrayRecord.java
src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java

index 1f295d0f338d458bc27bba5cb12309f6710079a0..e5f2afd2503fe21aa3778df3600635d8fa233c4d 100644 (file)
@@ -67,7 +67,7 @@ public final class HSSFFormulaParser {
      * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid
         */
        public static Ptg[] parse(String formula, HSSFWorkbook workbook, int formulaType, int sheetIndex) throws FormulaParseException {
-               return FormulaParser.parse(formula, createParsingWorkbook(workbook), formulaType, sheetIndex);
+               return FormulaParser.parse(formula, createParsingWorkbook(workbook), formulaType, sheetIndex, -1);
        }
 
        /**
index dbf85b869bcc4a7edbef27613f7930a564891534..1d9459a71a06a86fe64df9195fae9b4d71b065b0 100644 (file)
@@ -38,6 +38,7 @@ 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.usermodel.Table;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.POILogFactory;
@@ -267,4 +268,8 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
     public SpreadsheetVersion getSpreadsheetVersion(){
         return SpreadsheetVersion.EXCEL97;
     }
+
+    public Table getTable(String name) {
+        throw new IllegalStateException("XSSF-style tables are not supported for HSSF");
+    }
 }
index b0a3c76060fcc27caa6d75ec16057ae7ba185e5c..45e6351f53b275ec6049ffc73ee5b2ef1015c597 100644 (file)
@@ -68,6 +68,7 @@ public interface EvaluationWorkbook {
      */
     ExternalName getExternalName(String nameName, String sheetName, int externalWorkbookNumber);
     
+    
     EvaluationName getName(NamePtg namePtg);
     EvaluationName getName(String name, int sheetIndex);
     String resolveNameXText(NameXPtg ptg);
index 3820043d1f7c19283c93277adc030b25915eec33..b2e7acf7301b14d16ad53f1525cdf69d26ea3979 100644 (file)
@@ -28,6 +28,7 @@ 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.Area3DPxg;
 import org.apache.poi.ss.formula.ptg.AreaPtg;
 import org.apache.poi.ss.formula.ptg.ArrayPtg;
 import org.apache.poi.ss.formula.ptg.AttrPtg;
@@ -69,6 +70,7 @@ import org.apache.poi.ss.formula.ptg.UnionPtg;
 import org.apache.poi.ss.formula.ptg.ValueOperatorPtg;
 import org.apache.poi.ss.usermodel.FormulaError;
 import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.ss.usermodel.Table;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.ss.util.CellReference.NameType;
@@ -117,6 +119,7 @@ public final class FormulaParser {
        private final SpreadsheetVersion _ssVersion;
 
        private final int _sheetIndex;
+       private final int _rowIndex; // 0-based
 
 
        /**
@@ -131,13 +134,14 @@ public final class FormulaParser {
         *  model.Workbook, then use the convenience method on
         *  usermodel.HSSFFormulaEvaluator
         */
-       private FormulaParser(String formula, FormulaParsingWorkbook book, int sheetIndex){
+       private FormulaParser(String formula, FormulaParsingWorkbook book, int sheetIndex, int rowIndex){
                _formulaString = formula;
                _pointer=0;
                _book = book;
                _ssVersion = book == null ? SpreadsheetVersion.EXCEL97 : book.getSpreadsheetVersion();
                _formulaLength = _formulaString.length();
                _sheetIndex = sheetIndex;
+               _rowIndex = rowIndex;
        }
 
        /**
@@ -148,18 +152,41 @@ public final class FormulaParser {
         * @param workbook      the parent workbook
         * @param formulaType the type of the formula, see {@link FormulaType}
         * @param sheetIndex  the 0-based index of the sheet this formula belongs to.
+        * @param rowIndex  - the related cell's row index in 0-based form (-1 if the formula is not cell related)
+        *                     used to handle structured references that have the "#This Row" quantifier.
         * The sheet index is required to resolve sheet-level names. <code>-1</code> means that
         * the scope of the name will be ignored and  the parser will match names only by name
         *
         * @return array of parsed tokens
         * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid
         */
-       public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType, int sheetIndex) {
-               FormulaParser fp = new FormulaParser(formula, workbook, sheetIndex);
+       public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType, int sheetIndex, int rowIndex) {
+               FormulaParser fp = new FormulaParser(formula, workbook, sheetIndex, rowIndex);
                fp.parse();
                return fp.getRPNPtg(formulaType);
        }
        
+    public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType, int sheetIndex) {
+        return parse(formula, workbook, formulaType, sheetIndex, -1);
+    }
+
+    /**
+     * Parse a structured reference. Converts the structured
+     *  reference to the area that represent it.
+     *
+     * @param tableText - The structured reference text
+     * @param workbook - the parent workbook
+     * @param rowIndex - the 0-based cell's row index ( used to handle "#This Row" quantifiers )
+     * @return the area that being represented by the structured reference.
+     */
+    public static Area3DPxg parseStructuredReference(String tableText, FormulaParsingWorkbook workbook, int rowIndex) {
+        Ptg[] arr = FormulaParser.parse(tableText, workbook, 0, 0, rowIndex);
+        if (arr.length != 1 || !(arr[0] instanceof Area3DPxg) ) {
+            throw new IllegalStateException("Illegal structured reference");
+        }
+        return (Area3DPxg) arr[0];
+    }
+    
        /** Read New Character From Input Stream */
        private void GetChar() {
                // The intersection operator is a space.  We track whether the run of 
@@ -528,6 +555,266 @@ public final class FormulaParser {
        }
 
 
+       
+       private final static String specHeaders = "Headers";
+       private final static String specAll = "All";
+       private final static String specData = "Data";
+       private final static String specTotals = "Totals";
+       private final static String specThisRow = "This Row";
+       
+       /**
+        * Parses a structured reference, returns it as area reference.
+        * Examples:
+        * <pre>
+        * Table1[col]
+        * Table1[[#Totals],[col]]
+        * Table1[#Totals]
+        * Table1[#All]
+        * Table1[#Data]
+        * Table1[#Headers]
+        * Table1[#Totals]
+        * Table1[#This Row]
+        * Table1[[#All],[col]]
+        * Table1[[#Headers],[col]]
+        * Table1[[#Totals],[col]]
+        * Table1[[#All],[col1]:[col2]]
+        * Table1[[#Data],[col1]:[col2]]
+        * Table1[[#Headers],[col1]:[col2]]
+        * Table1[[#Totals],[col1]:[col2]]
+        * Table1[[#Headers],[#Data],[col2]]
+        * Table1[[#This Row], [col1]]
+        * Table1[ [col1]:[col2] ]
+        * </pre>
+        * @param tableName
+        * @return
+        */
+       private ParseNode parseStructuredReference(String tableName){
+           
+        if ( ! (_ssVersion.equals(SpreadsheetVersion.EXCEL2007)) ) {
+            throw new FormulaParseException("Strctured references work only on XSSF (Excel 2007)!");
+        }
+        Table tbl = _book.getTable(tableName);
+        if (tbl == null) {
+           throw new  FormulaParseException("Illegal table name!");
+        }
+        String sheetName = tbl.getSheetName();
+        
+        int startCol = tbl.getStartColIndex();
+        int endCol = tbl.getEndColIndex();
+        int startRow = tbl.getStartRowIndex();
+        int endRow = tbl.getEndRowIndex();
+        
+        int savePtr0 = _pointer;
+        GetChar();
+        
+        boolean isTotalsSpec = false;
+        boolean isThisRowSpec = false;
+        boolean isDataSpec = false;
+        boolean isHeadersSpec = false;
+        boolean isAllSpec = false;
+        int nSpecQuantifiers = 0; // The number of special quantifiers
+        while (true) {
+            int savePtr1 = _pointer;
+            String specName = parseAsSpecialQuantifier();
+            if (specName == null) {
+                resetPointer(savePtr1);
+                break;
+            }
+            if (specName.equals(specAll)) {
+                isAllSpec = true;
+            } else if (specName.equals(specData)) {
+                isDataSpec = true;
+            } else if (specName.equals(specHeaders)) {
+                isHeadersSpec = true;
+            } else if (specName.equals(specThisRow)) {
+                isThisRowSpec = true;
+            } else if (specName.equals(specTotals)) {
+                isTotalsSpec  = true;
+            } else {
+                throw new FormulaParseException("Unknown special qunatifier "+ specName);
+            }
+            nSpecQuantifiers++ ;
+            if (look == ','){
+                GetChar();
+            } else {
+                break;
+            }
+        }
+        boolean isThisRow = false;
+        SkipWhite();
+        if (look == '@') {
+            isThisRow = true;
+            GetChar();
+        }
+        // parse column quantifier
+        String startColumnName = null;
+        String endColumnName = null;
+        int nColQuantifiers = 0;
+        int savePtr1 = _pointer;
+        startColumnName = parseAsColumnQuantifier();
+        if (startColumnName == null) {
+            resetPointer(savePtr1);
+        } else {
+            nColQuantifiers++;
+            if (look == ','){
+                throw new FormulaParseException("The formula "+ _formulaString + "is illegal: you should not use ',' with column quantifiers");
+            } else if (look == ':') {
+                GetChar();
+                endColumnName = parseAsColumnQuantifier();
+                nColQuantifiers++;
+                if (endColumnName == null) {
+                    throw new FormulaParseException("The formula "+ _formulaString + "is illegal: the string after ':' must be column quantifier");
+                }
+            }
+        }
+        
+        if(nColQuantifiers == 0 && nSpecQuantifiers == 0){
+            resetPointer(savePtr0);
+            savePtr0 = _pointer;
+            startColumnName = parseAsColumnQuantifier();
+            if (startColumnName != null) {
+                nColQuantifiers++;
+            } else {
+                resetPointer(savePtr0);
+                String name = parseAsSpecialQuantifier();
+                if (name!=null) {
+                    if (name.equals(specAll)) {
+                        isAllSpec = true;
+                    } else if (name.equals(specData)) {
+                        isDataSpec = true;
+                    } else if (name.equals(specHeaders)) {
+                        isHeadersSpec = true;
+                    } else if (name.equals(specThisRow)) {
+                        isThisRowSpec = true;
+                    } else if (name.equals(specTotals)) {
+                        isTotalsSpec  = true;
+                    } else {
+                        throw new FormulaParseException("Unknown special qunatifier "+ name);
+                    }
+                    nSpecQuantifiers++;
+                } else {
+                    throw new FormulaParseException("The formula "+ _formulaString + " is illegal");
+                }
+            }
+        } else {
+            Match(']');
+        }
+        
+        int actualStartRow = startRow;
+        int actualEndRow = endRow;
+        int actualStartCol = startCol;
+        int actualEndCol = endCol; 
+        if (nSpecQuantifiers > 0) {
+        //Selecting rows
+            if (nSpecQuantifiers == 1 && isAllSpec) {
+                //do nothing
+            } else if (isDataSpec && isHeadersSpec) {
+                if (tbl.isHasTotalsRow()) {
+                    actualEndRow = endRow - 1;
+                }
+            } else if (isDataSpec && isTotalsSpec) {
+                actualStartRow = startRow + 1;
+            } else if (nSpecQuantifiers == 1 && isDataSpec) {
+                actualStartRow = startRow + 1;
+                if (tbl.isHasTotalsRow()) {
+                    actualEndRow = endRow - 1;
+                }
+            } else if (nSpecQuantifiers == 1 && isHeadersSpec) {
+                actualEndRow = actualStartRow;
+            } else if (nSpecQuantifiers == 1 && isTotalsSpec) {
+                actualStartRow = actualEndRow;
+            } else if ((nSpecQuantifiers == 1 && isThisRowSpec) || isThisRow) {
+                actualStartRow = _rowIndex; //The rowNum is 0 based
+                actualEndRow = _rowIndex; 
+            } else {
+                throw new FormulaParseException("The formula "+ _formulaString + " is illegal");
+            }
+        } else {
+            if (isThisRow) { // there is a @
+                actualStartRow = _rowIndex; //The rowNum is 0 based
+                actualEndRow = _rowIndex; 
+            } else { // Really no special quantifiers
+                actualStartRow++;
+            }
+        }
+        //Selecting cols
+
+        if (nColQuantifiers == 2){
+            if (startColumnName == null || endColumnName == null){
+                throw new IllegalStateException("Fatal error");
+            }
+            int startIdx = tbl.findColumnIndex(startColumnName);
+            int endIdx = tbl.findColumnIndex(endColumnName);
+            if (startIdx == -1 || endIdx == -1) {
+                throw new FormulaParseException("One of the columns "+ startColumnName +", "+ endColumnName +" doesn't exist in table "+ tbl.getName()); 
+            } 
+            actualStartCol = startCol+ startIdx;
+            actualEndCol = startCol + endIdx;
+                
+        } else if(nColQuantifiers == 1){
+            if (startColumnName == null){
+                throw new IllegalStateException("Fatal error");
+            }
+            int idx = tbl.findColumnIndex(startColumnName);
+            if (idx == -1) {
+                throw new FormulaParseException("The column "+ startColumnName + " doesn't exist in table "+ tbl.getName());
+            }
+            actualStartCol = startCol + idx;
+            actualEndCol = actualStartCol;
+        }
+        CellReference tl = new CellReference(actualStartRow, actualStartCol);
+        CellReference br = new CellReference(actualEndRow, actualEndCol);
+        SheetIdentifier sheetIden = new SheetIdentifier( null, new NameIdentifier(sheetName, true));
+        Ptg ptg = _book.get3DReferencePtg(new AreaReference(tl, br), sheetIden);
+        return new ParseNode(ptg);
+       }
+       
+       /**
+     * Tries to parse the next as column - can contain whitespace
+     * Caller should save pointer.
+     * @return
+    */
+    private String parseAsColumnQuantifier(){
+        if ( look != '[') {
+            return null;
+        }
+        GetChar();
+        String name = "";
+        if (look == '#') {
+            return null;
+        }
+        if (look == '@') {
+            GetChar();
+        }
+        while (look!=']') {
+           name += look;
+           GetChar();
+        }
+        Match(']');
+        return name;
+    }    
+    /**
+     * Tries to parse the next as special quantifier
+     * Caller should save pointer.
+     * @return
+     */
+    private String parseAsSpecialQuantifier(){
+        if ( look != '[') {
+            return null;
+        }
+        GetChar();
+        if( look != '#') {
+            return null;
+        }
+        GetChar();
+        String name = parseAsName();
+        if ( name.equals("This")) {
+            name = name + ' ' + parseAsName();
+        }
+        Match(']');
+        return name;
+    }
+
 
        /**
         * Parses simple factors that are not primitive ranges or range components
@@ -558,6 +845,11 @@ public final class FormulaParser {
                if (look == '(') {
                        return function(name);
                }
+               //TODO Livshen's code
+               if(look == '['){
+                   return parseStructuredReference(name);
+               }
+               //TODO End of Livshen's code
                if (name.equalsIgnoreCase("TRUE") || name.equalsIgnoreCase("FALSE")) {
                        return  new ParseNode(BoolPtg.valueOf(name.equalsIgnoreCase("TRUE")));
                }
@@ -581,9 +873,9 @@ public final class FormulaParser {
        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");
+        // defined names may begin with a letter or underscore or backslash
+        if (!Character.isLetter(look) && look != '_' && look != '\\') {
+            throw expected("number, string, defined name, or table");
         }
         while (isValidDefinedNameChar(look)) {
             sb.append(look);
@@ -1175,7 +1467,9 @@ public final class FormulaParser {
                                Match('}');
                                return arrayNode;
                }
-               if (IsAlpha(look) || Character.isDigit(look) || look == '\'' || look == '['){
+               // named ranges and tables can start with underscore or backslash
+               // see https://support.office.com/en-us/article/Define-and-use-names-in-formulas-4d0f13ac-53b7-422e-afd2-abd7ff379c64?ui=en-US&rs=en-US&ad=US#bmsyntax_rules_for_names
+               if (IsAlpha(look) || Character.isDigit(look) || look == '\'' || look == '[' || look == '_' || look == '\\' ) {
                        return parseRangeExpression();
                }
                if (look == '.') {
index fe907fbb1dc5f31d95a540d2bbe2debaa738eaef..0fe93eec7fb9cba3cd7977a9be36bdb45563b570 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.poi.ss.formula;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.formula.ptg.Ptg;
 import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.ss.usermodel.Table;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 
@@ -41,6 +42,11 @@ public interface FormulaParsingWorkbook {
         */
        Name createName();
 
+       /**
+        * XSSF Only - gets a table that exists in the worksheet
+        */
+       Table getTable(String name);
+       
        /**
         * Return an external name (named range, function, user-defined function) Ptg
         */
index cc590772de5841ae14ac73e8b28c1dd12677aef9..277fbfc15969841a02efe8e814e60a486b76910e 100644 (file)
@@ -407,6 +407,9 @@ public final class OperationEvaluationContext {
             return new FunctionNameEval(name);
         }
        }
+       public int getSheetIndex() {
+           return _sheetIndex;
+       }
        
     private ValueEval getExternalNameXEval(ExternalName externName, String workbookName) {
         try {
index f4b30c4f0e83ac4d39eb7c0875b8e2a7523f6590..84099bf2bbf37293573a5c0a88dac23f1aa501cb 100644 (file)
@@ -26,20 +26,60 @@ import java.util.TreeSet;
 
 import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
 import org.apache.poi.ss.formula.atp.AnalysisToolPak;
-import org.apache.poi.ss.formula.eval.*;
+import org.apache.poi.ss.formula.eval.BlankEval;
+import org.apache.poi.ss.formula.eval.BoolEval;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.ss.formula.eval.ExternalNameEval;
+import org.apache.poi.ss.formula.eval.FunctionEval;
+import org.apache.poi.ss.formula.eval.FunctionNameEval;
+import org.apache.poi.ss.formula.eval.MissingArgEval;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.OperandResolver;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
 import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
 import org.apache.poi.ss.formula.functions.Choose;
 import org.apache.poi.ss.formula.functions.FreeRefFunction;
 import org.apache.poi.ss.formula.functions.Function;
 import org.apache.poi.ss.formula.functions.IfFunc;
-import org.apache.poi.ss.formula.ptg.*;
+import org.apache.poi.ss.formula.ptg.Area3DPtg;
+import org.apache.poi.ss.formula.ptg.Area3DPxg;
+import org.apache.poi.ss.formula.ptg.AreaErrPtg;
+import org.apache.poi.ss.formula.ptg.AreaPtg;
+import org.apache.poi.ss.formula.ptg.AttrPtg;
+import org.apache.poi.ss.formula.ptg.BoolPtg;
+import org.apache.poi.ss.formula.ptg.ControlPtg;
+import org.apache.poi.ss.formula.ptg.DeletedArea3DPtg;
+import org.apache.poi.ss.formula.ptg.DeletedRef3DPtg;
+import org.apache.poi.ss.formula.ptg.ErrPtg;
+import org.apache.poi.ss.formula.ptg.ExpPtg;
+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.MemErrPtg;
+import org.apache.poi.ss.formula.ptg.MemFuncPtg;
+import org.apache.poi.ss.formula.ptg.MissingArgPtg;
+import org.apache.poi.ss.formula.ptg.NamePtg;
+import org.apache.poi.ss.formula.ptg.NameXPtg;
+import org.apache.poi.ss.formula.ptg.NameXPxg;
+import org.apache.poi.ss.formula.ptg.NumberPtg;
+import org.apache.poi.ss.formula.ptg.OperationPtg;
+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.RefErrorPtg;
+import org.apache.poi.ss.formula.ptg.RefPtg;
+import org.apache.poi.ss.formula.ptg.StringPtg;
+import org.apache.poi.ss.formula.ptg.UnionPtg;
+import org.apache.poi.ss.formula.ptg.UnknownPtg;
 import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
 import org.apache.poi.ss.formula.udf.UDFFinder;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
-
 /**
  * Evaluates formula cells.<p/>
  *
@@ -259,6 +299,15 @@ public final class WorkbookEvaluator {
                        try {
 
                                Ptg[] ptgs = _workbook.getFormulaTokens(srcCell);
+//                             System.out.println("=====");
+//                             XSSFCell c = ((XSSFEvaluationCell)srcCell).getXSSFCell();
+//                             System.out.println("Formula is "+ c);
+//                             System.out.println("The cell is " + c.getSheet().getSheetName()+"!"+c.getReference());
+//                             System.out.println("Evaluation tokens : ");  // TODO Dlivshen remove
+//                             for (Ptg ptg : ptgs) {  // TODO Dlivshen remove
+//                                 System.out.println(ptg);  // TODO Dlivshen remove
+//                             } // TODO Dlivshen remove
+//                             System.out.println("======"); // TODO Dlivshen remove
                                if (evalListener == null) {
                                        result = evaluateFormula(ec, ptgs);
                                } else {
@@ -270,9 +319,9 @@ public final class WorkbookEvaluator {
                                tracker.updateCacheResult(result);
                        }
                         catch (NotImplementedException e) {
-                               throw addExceptionInfo(e, sheetIndex, rowIndex, columnIndex);
+                               throw addExceptionInfo(e,  sheetIndex, rowIndex, columnIndex);
                         } catch (RuntimeException re) {
-                                if (re.getCause() instanceof WorkbookNotFoundException && _ignoreMissingWorkbooks) {
+                                if (re.getCause() instanceof  WorkbookNotFoundException && _ignoreMissingWorkbooks) {
                                        logInfo(re.getCause().getMessage() + " - Continuing with cached value!");
                                        switch(srcCell.getCachedFormulaResultType()) {
                                                case Cell.CELL_TYPE_NUMERIC:
index 7774af506de73ddf90d99277d6d6deb2c112092a..7366c798cc46e09b41114a9b6e1192ec56ed71fe 100644 (file)
 
 package org.apache.poi.ss.formula.functions;
 
+import org.apache.poi.ss.formula.FormulaParseException;
+import org.apache.poi.ss.formula.FormulaParser;
+import org.apache.poi.ss.formula.FormulaParsingWorkbook;
+import org.apache.poi.ss.formula.OperationEvaluationContext;
 import org.apache.poi.ss.formula.eval.BlankEval;
 import org.apache.poi.ss.formula.eval.ErrorEval;
 import org.apache.poi.ss.formula.eval.EvaluationException;
 import org.apache.poi.ss.formula.eval.MissingArgEval;
 import org.apache.poi.ss.formula.eval.OperandResolver;
 import org.apache.poi.ss.formula.eval.ValueEval;
-import org.apache.poi.ss.formula.OperationEvaluationContext;
+import org.apache.poi.ss.formula.ptg.Area3DPxg;
+import org.apache.poi.ss.usermodel.Table;
 
 /**
  * Implementation for Excel function INDIRECT<p/>
@@ -42,7 +47,7 @@ import org.apache.poi.ss.formula.OperationEvaluationContext;
  */
 public final class Indirect implements FreeRefFunction {
 
-       public static final FreeRefFunction instance = new Indirect();
+    public static final FreeRefFunction instance = new Indirect();
 
        private Indirect() {
                // enforce singleton
@@ -88,8 +93,12 @@ public final class Indirect implements FreeRefFunction {
                return OperandResolver.coerceValueToBoolean(ve, false).booleanValue();
        }
 
-       private static ValueEval evaluateIndirect(OperationEvaluationContext ec, String text,
+       private static ValueEval evaluateIndirect(final OperationEvaluationContext ec, String text,
                        boolean isA1style) {
+           
+           ec.getRowIndex();
+           ec.getColumnIndex();
+
                // Search backwards for '!' because sheet names can contain '!'
                int plingPos = text.lastIndexOf('!');
 
@@ -112,16 +121,25 @@ public final class Indirect implements FreeRefFunction {
 
                String refStrPart1;
                String refStrPart2;
-
-               int colonPos = refText.indexOf(':');
-               if (colonPos < 0) {
-                       refStrPart1 = refText.trim();
-                       refStrPart2 = null;
-               } else {
-                       refStrPart1 = refText.substring(0, colonPos).trim();
-                       refStrPart2 = refText.substring(colonPos + 1).trim();
-               }
-               return ec.getDynamicReference(workbookName, sheetName, refStrPart1, refStrPart2, isA1style);
+        if (Table.isStructuredReference.matcher(refText).matches()) { // The argument is structured reference
+            Area3DPxg areaPtg = null;
+            try{
+                areaPtg = FormulaParser.parseStructuredReference(refText, (FormulaParsingWorkbook) ec.getWorkbook(), ec.getRowIndex());
+            } catch(FormulaParseException e) {
+                return ErrorEval.REF_INVALID;
+            }
+            return ec.getArea3DEval(areaPtg);
+        } else { // The argumnet is regular reference
+               int colonPos = refText.indexOf(':');
+               if (colonPos < 0) {
+                       refStrPart1 = refText.trim();
+                       refStrPart2 = null;                     
+               } else {
+                       refStrPart1 = refText.substring(0, colonPos).trim();
+                       refStrPart2 = refText.substring(colonPos + 1).trim();
+               }
+               return ec.getDynamicReference(workbookName, sheetName, refStrPart1, refStrPart2, isA1style);
+        }
        }
 
        /**
index 4a6882ac4289899f647af365fe0aeeaa3a60fedd..25d80a37213d267c3ebcea713949972c51998a45 100644 (file)
@@ -36,6 +36,7 @@ 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.usermodel.Table;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.NotImplemented;
@@ -310,6 +311,10 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork
                return _uBook.createName();
        }
        
+       public Table getTable(String name) {
+           return _uBook.getTable(name);
+       }
+       
     public UDFFinder getUDFFinder(){
         return _uBook.getUDFFinder();
     }
index 29aaa867e251b21f810266750ce61eebbb2c1b91..f542e0f172d406ffd54ecfa219d1f36b59bbbda0 100644 (file)
@@ -506,7 +506,7 @@ public final class XSSFCell implements Cell {
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(sheet.getWorkbook());
         SharedFormula sf = new SharedFormula(SpreadsheetVersion.EXCEL2007);
 
-        Ptg[] ptgs = FormulaParser.parse(sharedFormula, fpb, FormulaType.CELL, sheetIndex);
+        Ptg[] ptgs = FormulaParser.parse(sharedFormula, fpb, FormulaType.CELL, sheetIndex, getRowIndex());
         Ptg[] fmla = sf.convertSharedFormulas(ptgs,
                 getRowIndex() - ref.getFirstRow(), getColumnIndex() - ref.getFirstColumn());
         return FormulaRenderer.toFormulaString(fpb, fmla);
@@ -550,7 +550,7 @@ public final class XSSFCell implements Cell {
 
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
         //validate through the FormulaParser
-        FormulaParser.parse(formula, fpb, formulaType, wb.getSheetIndex(getSheet()));
+        FormulaParser.parse(formula, fpb, formulaType, wb.getSheetIndex(getSheet()), -1);
 
         CTCellFormula f = CTCellFormula.Factory.newInstance();
         f.setStringValue(formula);
index 70fc7206711cbb14f13880f1dda2e54f981fe3d9..b3d3343ec5f8f9f346ac4793a4bd8254dc94ec31 100644 (file)
@@ -50,6 +50,6 @@ public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook {
     public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
         XSSFCell cell = ((XSSFEvaluationCell)evalCell).getXSSFCell();
         XSSFEvaluationWorkbook frBook = XSSFEvaluationWorkbook.create(_uBook);
-        return FormulaParser.parse(cell.getCellFormula(), frBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
+        return FormulaParser.parse(cell.getCellFormula(), frBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()), cell.getRowIndex());
     }
 }
index ecbec23b5aee906adde80ad6c57ccefd59c67ae1..be68c3050075910169e2046ece33af43f3b669e1 100644 (file)
@@ -192,7 +192,7 @@ public final class XSSFName implements Name {
     public void setRefersToFormula(String formulaText) {
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(_workbook);
         //validate through the FormulaParser
-        FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
+        FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex(), -1);
 
         _ctName.setStringValue(formulaText);
     }
@@ -203,7 +203,7 @@ public final class XSSFName implements Name {
             return false;
         }
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(_workbook);
-        Ptg[] ptgs = FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
+        Ptg[] ptgs = FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex(), -1);
         return Ptg.doesFormulaReferToDeletedCell(ptgs);
     }
 
index c8a932bb98a50268975351390ce4f035322014b7..72e3d341ad59f5ac98cee95b9a28ed408a32c2ce 100644 (file)
@@ -24,11 +24,13 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 
 import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.ss.usermodel.Table;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr;
 import org.apache.xmlbeans.XmlException;
@@ -48,10 +50,12 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.TableDocument;
  *
  * @author Roberto Manicardi
  */
-public class XSSFTable extends POIXMLDocumentPart {
+public class XSSFTable extends POIXMLDocumentPart implements Table {
 
     private CTTable ctTable;
     private List<XSSFXmlColumnPr> xmlColumnPr;
+    private CTTableColumn[] ctColumns;
+    private HashMap<String, Integer> columnMap;
     private CellReference startCellReference;
     private CellReference endCellReference;    
     private String commonXPath; 
@@ -131,6 +135,12 @@ public class XSSFTable extends POIXMLDocumentPart {
         return maps;
     }
 
+    private CTTableColumn[] getTableColumns() {
+        if (ctColumns == null) {
+            ctColumns = ctTable.getTableColumns().getTableColumnArray();
+        }
+        return ctColumns;
+    }
     
     /**
      * 
@@ -142,7 +152,7 @@ public class XSSFTable extends POIXMLDocumentPart {
     public String getCommonXpath() {
         if (commonXPath == null) {
             String[] commonTokens = {};
-            for (CTTableColumn column :ctTable.getTableColumns().getTableColumnArray()) {
+            for (CTTableColumn column : getTableColumns()) {
                 if (column.getXmlColumnPr()!=null) {
                     String xpath = column.getXmlColumnPr().getXpath();
                     String[] tokens =  xpath.split("/");
@@ -176,11 +186,15 @@ public class XSSFTable extends POIXMLDocumentPart {
     }
 
     
+    /**
+     * Note this list is static - once read, it does not notice later changes to the underlying column structures
+     * @return List of XSSFXmlColumnPr
+     */
     public List<XSSFXmlColumnPr> getXmlColumnPrs() {
         
         if (xmlColumnPr==null) {
             xmlColumnPr = new ArrayList<XSSFXmlColumnPr>();
-            for (CTTableColumn column:ctTable.getTableColumns().getTableColumnArray()) {
+            for (CTTableColumn column: getTableColumns()) {
                 if (column.getXmlColumnPr()!=null) {
                     XSSFXmlColumnPr columnPr = new XSSFXmlColumnPr(this,column,column.getXmlColumnPr());
                     xmlColumnPr.add(columnPr);
@@ -301,6 +315,46 @@ public class XSSFTable extends POIXMLDocumentPart {
                 }
                 cellnum++;
             }
+            ctColumns = null;
+            columnMap = null;
+        }
+    }
+
+    public int findColumnIndex(String column) {
+        if (columnMap == null) {
+            columnMap = new HashMap<String, Integer>(getTableColumns().length);
+            
+            for (int i=0; i < getTableColumns().length; i++) {
+                columnMap.put(getTableColumns()[i].getName().toUpperCase(), Integer.valueOf(i));
+            }
         }
+        // Table column names with special characters need a single quote escape
+        // but the escape is not present in the column definition
+        Integer idx = columnMap.get(column.replace("'", "").toUpperCase());
+        return idx == null ? -1 : idx.intValue();
+    }
+
+    public String getSheetName() {
+        return getXSSFSheet().getSheetName();
+    }
+
+    public boolean isHasTotalsRow() {
+        return ctTable.getTotalsRowShown();
+    }
+
+    public int getStartColIndex() {
+        return getStartCellReference().getCol();
+    }
+
+    public int getStartRowIndex() {
+        return getStartCellReference().getRow();
+    }
+
+    public int getEndColIndex() {
+        return getEndCellReference().getCol();
+    }
+
+    public int getEndRowIndex() {
+        return getEndCellReference().getRow();
     }
 }
index 100c2b95bde6577b9f6aef43268f7b51bb58d59a..622979d167cbb6240e75ab1f4b8369758fd908ca 100644 (file)
@@ -33,6 +33,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.regex.Pattern;
@@ -2261,4 +2262,49 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
     public SpreadsheetVersion getSpreadsheetVersion() {
         return SpreadsheetVersion.EXCEL2007;
     }
+    
+    /*
+     * 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?
+     */
+    Map<String, XSSFTable> _tableCache = null;
+    private Map<String, XSSFTable> getTableCache() {
+        if ( _tableCache != null ) {
+            return _tableCache;
+        }
+        // FIXME: use org.apache.commons.collections.map.CaseInsensitiveMap
+        _tableCache = new HashMap<String, XSSFTable>();
+
+        if (sheets != null) {
+            for (XSSFSheet sheet : sheets) {
+                for (XSSFTable tbl : 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 <tt>name</tt>, or <tt>null</tt> if no table is named <tt>name</tt>.
+     * @since 3.15 beta 2
+     */
+    public XSSFTable getTable(String name) {
+        String lname = name.toLowerCase(Locale.ROOT);
+        return getTableCache().get(lname);
+    }
 }
index a9d995fb729420f11440c7c754808e3e9835cd12..50190b0a6bb733e72ad042a700fc08af35d8db8f 100644 (file)
@@ -94,7 +94,7 @@ public final class XSSFFormulaUtils {
             String formula = f.getStringValue();
             if (formula != null && formula.length() > 0) {
                 int sheetIndex = _wb.getSheetIndex(cell.getSheet());
-                Ptg[] ptgs = FormulaParser.parse(formula, _fpwb, FormulaType.CELL, sheetIndex);
+                Ptg[] ptgs = FormulaParser.parse(formula, _fpwb, FormulaType.CELL, sheetIndex, cell.getRowIndex());
                 for (Ptg ptg : ptgs) {
                     updatePtg(ptg, oldName, newName);
                 }
@@ -113,7 +113,7 @@ public final class XSSFFormulaUtils {
         String formula = name.getRefersToFormula();
         if (formula != null) {
             int sheetIndex = name.getSheetIndex();
-            Ptg[] ptgs = FormulaParser.parse(formula, _fpwb, FormulaType.NAMEDRANGE, sheetIndex);
+            Ptg[] ptgs = FormulaParser.parse(formula, _fpwb, FormulaType.NAMEDRANGE, sheetIndex, -1);
             for (Ptg ptg : ptgs) {
                 updatePtg(ptg, oldName, newName);
             }
index 80462ac4c8423887a7599e4105639549f114ef8e..77236913b9e0d8529fdc3215b1d079dd8068eeb6 100644 (file)
@@ -135,7 +135,7 @@ public final class XSSFRowShifter {
             String formula = name.getRefersToFormula();
             int sheetIndex = name.getSheetIndex();
 
-            Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex);
+            Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex, -1);
             if (shifter.adjustFormula(ptgs, sheetIndex)) {
                 String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
                 name.setRefersToFormula(shiftedFmla);
@@ -221,7 +221,7 @@ public final class XSSFRowShifter {
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
         
         try {
-            Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex);
+            Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, -1);
             String shiftedFmla = null;
             if (shifter.adjustFormula(ptgs, sheetIndex)) {
                 shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
@@ -283,7 +283,7 @@ public final class XSSFRowShifter {
                 String[] formulaArray = cfRule.getFormulaArray();
                 for (int i = 0; i < formulaArray.length; i++) {
                     String formula = formulaArray[i];
-                    Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex);
+                    Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, -1);
                     if (shifter.adjustFormula(ptgs, sheetIndex)) {
                         String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
                         cfRule.setFormulaArray(i, shiftedFmla);
index 83dabacb9fd283446fa7b6cda35dffb16eb2eb0c..a9f697ba9e51e71905bd6820f2c011acf60c3ca8 100644 (file)
@@ -42,7 +42,7 @@ import java.util.Arrays;
 
 public final class TestXSSFFormulaParser {
        private static Ptg[] parse(FormulaParsingWorkbook fpb, String fmla) {
-               return FormulaParser.parse(fmla, fpb, FormulaType.CELL, -1);
+               return FormulaParser.parse(fmla, fpb, FormulaType.CELL, -1, -1);
        }
 
        @Test
index f39d07b94bff18d9012a6d83c6792ac7df28e3d2..f99672b7cfff005a7f87eee7cb5d736cc5585357 100644 (file)
@@ -1197,7 +1197,7 @@ public final class TestFormulaParser {
                String formula = "Sheet1!$B$2:$C$3,OFFSET(Sheet1!$E$2:$E$4,1,Sheet1!$A$1),Sheet1!$D$6";
                HSSFWorkbook wb = new HSSFWorkbook();
                wb.createSheet("Sheet1");
-               Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb), FormulaType.CELL, -1);
+               Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb), FormulaType.CELL, -1,-1);
 
                confirmTokenClasses(ptgs,
                                // TODO - AttrPtg.class, // Excel prepends this
@@ -1285,7 +1285,7 @@ public final class TestFormulaParser {
                String formula = "Sheet1!A1:Sheet1!B3";
                HSSFWorkbook wb = new HSSFWorkbook();
                wb.createSheet("Sheet1");
-               Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb), FormulaType.CELL, -1);
+               Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb), FormulaType.CELL, -1, -1);
 
                if (ptgs.length == 3) {
                        confirmTokenClasses(ptgs, Ref3DPtg.class, Ref3DPtg.class, RangePtg.class);
@@ -1486,8 +1486,8 @@ public final class TestFormulaParser {
 
                confirmParseError(wb, "A1:ROUND(B1,1)", "The RHS of the range operator ':' at position 3 is not a proper reference.");
 
-        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!!!", "Parse error near char 7 '!' in specified formula 'Sheet1!!!'. Expected number, string, defined name, or table");
+        confirmParseError(wb, "Sheet1!.Name", "Parse error near char 7 '.' in specified formula 'Sheet1!.Name'. Expected number, string, defined name, or table");
                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.");
index ff5fe0ad9b8c27daf229b1f919f4b0c923b6c700..7affe462e6197edef379c71919622f87268c35af 100644 (file)
@@ -51,7 +51,7 @@ public final class TestArrayRecord extends TestCase {
         assertEquals("MAX(C1:C2-D1:D2)", FormulaRenderer.toFormulaString(null, ptg));
 
         //construct a new ArrayRecord with the same contents as r1
-        Ptg[] fmlaPtg = FormulaParser.parse("MAX(C1:C2-D1:D2)", null, FormulaType.ARRAY, 0);
+        Ptg[] fmlaPtg = FormulaParser.parse("MAX(C1:C2-D1:D2)", null, FormulaType.ARRAY, 0, -1);
         ArrayRecord r2 = new ArrayRecord(Formula.create(fmlaPtg), new CellRangeAddress8Bit(1, 1, 1, 1));
         byte[] ser = r2.serialize();
         //serialize and check that the data is the same as in r1
index 3a5a43493e38f1e18f07f528f7278e22747140b0..7b81c7cff70957fbcc506062a59941958069eedc 100644 (file)
@@ -107,7 +107,7 @@ public final class TestSharedFormulaRecord extends TestCase {
 
         SharedFormula sf = new SharedFormula(SpreadsheetVersion.EXCEL97);
 
-        sharedFormula = FormulaParser.parse("A2", fpb, FormulaType.CELL, -1);
+        sharedFormula = FormulaParser.parse("A2", fpb, FormulaType.CELL, -1, -1);
         convertedFormula = sf.convertSharedFormulas(sharedFormula, 0, 0);
         confirmOperandClasses(sharedFormula, convertedFormula);
         //conversion relative to [0,0] should return the original formula
@@ -123,7 +123,7 @@ public final class TestSharedFormulaRecord extends TestCase {
         //one row down and one cell right
         assertEquals("B3", FormulaRenderer.toFormulaString(fpb, convertedFormula));
 
-        sharedFormula = FormulaParser.parse("SUM(A1:C1)", fpb, FormulaType.CELL, -1);
+        sharedFormula = FormulaParser.parse("SUM(A1:C1)", fpb, FormulaType.CELL, -1, -1);
         convertedFormula = sf.convertSharedFormulas(sharedFormula, 0, 0);
         confirmOperandClasses(sharedFormula, convertedFormula);
         assertEquals("SUM(A1:C1)", FormulaRenderer.toFormulaString(fpb, convertedFormula));