]> source.dussan.org Git - poi.git/commitdiff
Allow 255 arguments for excel functions in XSSF, see bugzilla 46279
authorYegor Kozlov <yegor@apache.org>
Sat, 18 Apr 2009 07:12:38 +0000 (07:12 +0000)
committerYegor Kozlov <yegor@apache.org>
Sat, 18 Apr 2009 07:12:38 +0000 (07:12 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@766251 13f79535-47bb-0310-9956-ffa450edef68

13 files changed:
src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataRegistry.java
src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
src/java/org/apache/poi/ss/formula/FormulaParser.java
src/java/org/apache/poi/ss/formula/FormulaParsingWorkbook.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/XSSFRow.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java
src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java

index f58747e7edd00256ccc44b27aa499d600352d5c8..087588e7e5b126a8a588e8f7a8e44328adde982e 100644 (file)
@@ -37,6 +37,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.5-beta6" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">46279 - Allow 255 arguments for excel functions in XSSF </action>
            <action dev="POI-DEVELOPERS" type="fix">47028 - Fixed XSSFCell to preserve cell style when cell value is set to blank</action>
            <action dev="POI-DEVELOPERS" type="fix">47026 - Avoid NPE in XSSFCell.setCellType() when workbook does not have SST</action>
            <action dev="POI-DEVELOPERS" type="fix">46987 - Allow RecordFactory to handle non-zero padding at the end of the workbook stream</action>
index 4ef245ad87680cfb218d3b88c5a8c4a15bbd74f5..5bccbf28cd8f463931ad58565a317015737eff89 100644 (file)
@@ -34,6 +34,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.5-beta6" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">46279 - Allow 255 arguments for excel functions in XSSF </action>
            <action dev="POI-DEVELOPERS" type="fix">47028 - Fixed XSSFCell to preserve cell style when cell value is set to blank</action>
            <action dev="POI-DEVELOPERS" type="fix">47026 - Avoid NPE in XSSFCell.setCellType() when workbook does not have SST</action>
            <action dev="POI-DEVELOPERS" type="fix">46987 - Allow RecordFactory to handle non-zero padding at the end of the workbook stream</action>
index 1b78cc44df370199219cd8d019b916392d659691..848888e951798e1c4d9147093eee6812c32ad18c 100644 (file)
@@ -30,7 +30,15 @@ public final class FunctionMetadataRegistry {
         */ 
        public static final String FUNCTION_NAME_IF = "IF";
 
-       public static final short FUNCTION_INDEX_SUM = 4;
+    /**
+     * maxParams=30 in functionMetadata.txt means the maximum number arguments supported
+     * by the given version of Excel. Validation routines should take the actual limit (Excel 97 or 2007)
+     * from the SpreadsheetVersion enum.
+     * @see org.apache.poi.ss.formula.FormulaParser#validateNumArgs(int, FunctionMetadata)
+     */
+    public static final short FUNCTION_MAX_PARAMS = 30;
+
+    public static final short FUNCTION_INDEX_SUM = 4;
        public static final short FUNCTION_INDEX_EXTERNAL = 255;
        private static FunctionMetadataRegistry _instance;
 
index 046a9c29370cee3ec7e30d645acf0f0344a29972..10805658a75a2b87b1ef3350364261f7e9b39035 100644 (file)
@@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;\r
 import org.apache.poi.hssf.record.formula.Ptg;\r
 import org.apache.poi.ss.formula.*;\r
+import org.apache.poi.ss.SpreadsheetVersion;\r
 \r
 /**\r
  * Internal POI use only\r
@@ -154,4 +155,8 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
             return new NamePtg(_index);\r
         }\r
     }\r
+\r
+    public SpreadsheetVersion getSpreadsheetVersion(){\r
+        return SpreadsheetVersion.EXCEL97;    \r
+    }\r
 }\r
index 8311a17c44563a39ebe8ffd024d4122136dd6fd4..d36793be93150b386f7d059110581a0e9b1c807e 100644 (file)
@@ -31,6 +31,7 @@ import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.ss.util.CellReference.NameType;
+import org.apache.poi.ss.SpreadsheetVersion;
 
 /**
  * This class parses a formula string into a List of tokens in RPN order.
@@ -982,13 +983,20 @@ public final class FormulaParser {
                        }
                        msg += " but got " + numArgs + ".";
                        throw new FormulaParseException(msg);
-                }
-               if(numArgs > fm.getMaxParams()) {
+               }
+        //the maximum number of arguments depends on the Excel version
+        int maxArgs = fm.getMaxParams();
+        if( maxArgs == FunctionMetadataRegistry.FUNCTION_MAX_PARAMS) {
+            //_book can be omitted by test cases
+            if(_book != null) maxArgs = _book.getSpreadsheetVersion().getMaxFunctionArgs();
+        }
+
+        if(numArgs > maxArgs) {
                        String msg = "Too many arguments to function '" + fm.getName() + "'. ";
                        if(fm.hasFixedArgsLength()) {
-                               msg += "Expected " + fm.getMaxParams();
+                               msg += "Expected " + maxArgs;
                        } else {
-                               msg += "At most " + fm.getMaxParams() + " were expected";
+                               msg += "At most " + maxArgs + " were expected";
                        }
                        msg += " but got " + numArgs + ".";
                        throw new FormulaParseException(msg);
index 57f0f7a2c4a323b2a2cb9324e3329c8d3729e2e6..2ecd69be9a67d315061876bf8d55cda28463fa11 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.poi.ss.formula;\r
 \r
 import org.apache.poi.hssf.record.formula.NameXPtg;\r
+import org.apache.poi.ss.SpreadsheetVersion;\r
 \r
 /**\r
  * Abstracts a workbook for the purpose of formula parsing.<br/>\r
@@ -44,4 +45,11 @@ public interface FormulaParsingWorkbook {
         * @param sheetName a name of a sheet in that workbook\r
         */\r
        int getExternalSheetIndex(String workbookName, String sheetName);\r
+\r
+    /**\r
+     * Returns an enum holding spreadhseet properties specific to an Excel version (\r
+     * max column and row numbers, max arguments to a function, etc.)\r
+     */\r
+    SpreadsheetVersion getSpreadsheetVersion();\r
+\r
 }\r
index 2a0e1ff4b27a25d562a2da47ed3046bc313c4066..6bbcf1a8c632f372c4f5f39c0066858d6350a660 100644 (file)
@@ -366,14 +366,8 @@ public final class XSSFCell implements Cell {
         }
 
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
-        try {
-            Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, wb.getSheetIndex(getSheet()));
-        } catch (RuntimeException e) {
-            if (e.getClass().getName().startsWith(FormulaParser.class.getName())) {
-                throw new IllegalArgumentException("Unparsable formula '" + formula + "'", e);
-            }
-            throw e;
-        }
+        //validate through the FormulaParser
+        FormulaParser.parse(formula, fpb, FormulaType.CELL, wb.getSheetIndex(getSheet()));
 
         CTCellFormula f =  CTCellFormula.Factory.newInstance();
         f.setStringValue(formula);
index f733a67bd1836fecdde65a96752f723c093529ab..ef2bdf89b3feada626938f14d4c9a9b34badc53c 100644 (file)
@@ -21,6 +21,7 @@ import org.apache.poi.hssf.record.formula.NamePtg;
 import org.apache.poi.hssf.record.formula.NameXPtg;\r
 import org.apache.poi.hssf.record.formula.Ptg;\r
 import org.apache.poi.ss.formula.*;\r
+import org.apache.poi.ss.SpreadsheetVersion;\r
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;\r
 \r
 /**\r
@@ -172,4 +173,8 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
                        return new NamePtg(_index);\r
                }\r
        }\r
+    \r
+    public SpreadsheetVersion getSpreadsheetVersion(){\r
+        return SpreadsheetVersion.EXCEL2007;\r
+    }\r
 }\r
index 9f3c7f0125955ab2dac32aae6ad1dace3b283b18..ed4d364abe49de37eef6c0fb6a81be03c113927f 100644 (file)
@@ -191,14 +191,9 @@ public final class XSSFName implements Name {
 
     public void setRefersToFormula(String formulaText) {
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(workbook);
-        try {
-            FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
-        } catch (RuntimeException e) {
-            if (e.getClass().getName().startsWith(FormulaParser.class.getName())) {
-                throw new IllegalArgumentException("Unparsable formula '" + formulaText + "'", e);
-            }
-            throw e;
-        }
+        //validate through the FormulaParser
+        FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
+
         ctName.setStringValue(formulaText);
     }
 
index 4cc3db4e56ceeb5b4e102a435054bbd5a8553b51..4cd7c416344ee1d71055d9d405b1241875cc27eb 100644 (file)
@@ -22,19 +22,12 @@ import java.util.*;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.ss.formula.FormulaParser;
-import org.apache.poi.ss.formula.FormulaType;
-import org.apache.poi.ss.formula.FormulaRenderer;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.xssf.model.CalculationChain;
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.FormulaShifter;
-import org.apache.poi.hssf.record.SharedFormulaRecord;
 import org.apache.poi.util.POILogger;
 import org.apache.poi.util.POILogFactory;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
 
 /**
  * High level representation of a row of a spreadsheet.
index 80d383d75946dc9607b3d954eaa62834d09e38f4..242f24f04846238c2faa84644b0a9c351fc7673a 100644 (file)
@@ -24,19 +24,12 @@ import java.util.*;
 import javax.xml.namespace.QName;
 
 import org.apache.poi.hssf.util.PaneInformation;
-import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.hssf.record.formula.FormulaShifter;
-import org.apache.poi.hssf.record.SharedFormulaRecord;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.ss.formula.FormulaParser;
-import org.apache.poi.ss.formula.FormulaType;
-import org.apache.poi.ss.formula.FormulaRenderer;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.xssf.model.CommentsTable;
-import org.apache.poi.xssf.model.CalculationChain;
 import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
 import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
 import org.apache.poi.POIXMLDocumentPart;
index 926ed3d382944d17ee130c47f3bcde011444e760..d77f3a09984dcc5b2cf1fb1016e4423385c39d71 100755 (executable)
@@ -48,7 +48,7 @@ public final class HSSFITestDataProvider implements ITestDataProvider {
     }\r
     \r
     public SpreadsheetVersion getSpreadsheetVersion(){\r
-        return SpreadsheetVersion.EXCEL2007;\r
+        return SpreadsheetVersion.EXCEL97;\r
     }\r
 \r
     private HSSFITestDataProvider(){}\r
index ef6d0a14fa4083a8cd66d1c74220fad7bbd51ee7..adbcaad9406e632d00e285afc2c1cba953300b72 100755 (executable)
@@ -19,7 +19,9 @@ package org.apache.poi.ss.usermodel;
 import junit.framework.TestCase;\r
 import junit.framework.AssertionFailedError;\r
 import org.apache.poi.ss.ITestDataProvider;\r
+import org.apache.poi.ss.SpreadsheetVersion;\r
 import org.apache.poi.ss.util.CellRangeAddress;\r
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;\r
 \r
 /**\r
  * A base class for bugzilla issues that can be described in terms of common ss interfaces.\r
@@ -295,4 +297,42 @@ public abstract class BaseTestBugzillaIssues extends TestCase {
 \r
         assertEquals(d, (311+312+321+322), 0.0000001);\r
     }\r
+\r
+    public void testMaxFunctionArguments_bug46729(){\r
+        String[] func = {"COUNT", "AVERAGE", "MAX", "MIN", "OR", "SUBTOTAL", "SKEW"};\r
+\r
+        SpreadsheetVersion ssVersion = getTestDataProvider().getSpreadsheetVersion();\r
+        Workbook wb = getTestDataProvider().createWorkbook();\r
+        Cell cell = wb.createSheet().createRow(0).createCell(0);\r
+\r
+        String fmla;\r
+        for (String name : func) {\r
+\r
+            fmla = createFunction(name, 5);\r
+            cell.setCellFormula(fmla);\r
+\r
+            fmla = createFunction(name, ssVersion.getMaxFunctionArgs());\r
+            cell.setCellFormula(fmla);\r
+\r
+            try {\r
+                fmla = createFunction(name, ssVersion.getMaxFunctionArgs() + 1);\r
+                cell.setCellFormula(fmla);\r
+                fail("Expected FormulaParseException");\r
+            } catch (RuntimeException e){\r
+                 assertTrue(e.getMessage().startsWith("Too many arguments to function '"+name+"'"));\r
+            }\r
+        }\r
+    }\r
+\r
+    private String createFunction(String name, int maxArgs){\r
+        StringBuffer fmla = new StringBuffer();\r
+        fmla.append(name);\r
+        fmla.append("(");\r
+        for(int i=0; i < maxArgs; i++){\r
+            if(i > 0) fmla.append(',');\r
+            fmla.append("A1");\r
+        }\r
+        fmla.append(")");\r
+        return fmla.toString();\r
+    }\r
 }
\ No newline at end of file