diff --git a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadata.java b/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadata.java index fc5f845437..898a72ad44 100644 --- a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadata.java +++ b/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadata.java @@ -6,7 +6,7 @@ (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 + 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, @@ -16,12 +16,24 @@ ==================================================================== */ package org.apache.poi.hssf.record.formula.function; + +import org.apache.poi.ss.SpreadsheetVersion; + /** * Holds information about Excel built-in functions. - * + * * @author Josh Micich */ public final class FunctionMetadata { + /** + * 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. + * Perhaps a value like 'M' should be used instead of '30' in functionMetadata.txt + * to make that file more version neutral. + * @see org.apache.poi.ss.formula.FormulaParser#validateNumArgs(int, FunctionMetadata) + */ + private static final short FUNCTION_MAX_PARAMS = 30; private final int _index; private final String _name; @@ -58,7 +70,17 @@ public final class FunctionMetadata { return _returnClassCode; } public byte[] getParameterClassCodes() { - return (byte[]) _parameterClassCodes.clone(); + return _parameterClassCodes.clone(); + } + /** + * Some varags functions (like VLOOKUP) have a specific limit to the number of arguments that + * can be passed. Other functions (like SUM) don't have such a limit. For those functions, + * the spreadsheet version determines the maximum number of arguments that can be passed. + * @return true if this function can the maximum number of arguments allowable by + * the {@link SpreadsheetVersion} + */ + public boolean hasUnlimitedVarags() { + return FUNCTION_MAX_PARAMS == _maxParams; } public String toString() { StringBuffer sb = new StringBuffer(64); @@ -67,4 +89,4 @@ public final class FunctionMetadata { sb.append("]"); return sb.toString(); } -} \ No newline at end of file +} diff --git a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataRegistry.java b/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataRegistry.java index 848888e951..6fb0aabd3e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataRegistry.java +++ b/src/java/org/apache/poi/hssf/record/formula/function/FunctionMetadataRegistry.java @@ -20,24 +20,16 @@ package org.apache.poi.hssf.record.formula.function; import java.util.Map; import java.util.Set; /** - * Allows clients to get FunctionMetadata instances for any built-in function of Excel. - * + * Allows clients to get {@link FunctionMetadata} instances for any built-in function of Excel. + * * @author Josh Micich */ public final class FunctionMetadataRegistry { /** * The name of the IF function (i.e. "IF"). Extracted as a constant for clarity. - */ + */ public static final String FUNCTION_NAME_IF = "IF"; - /** - * 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; @@ -70,7 +62,7 @@ public final class FunctionMetadataRegistry { return _functionDataByIndex[index]; } /** - * Resolves a built-in function index. + * Resolves a built-in function index. * @param name uppercase function name * @return a negative value if the function name is not found. * This typically occurs for external functions. diff --git a/src/java/org/apache/poi/ss/formula/FormulaParser.java b/src/java/org/apache/poi/ss/formula/FormulaParser.java index d36793be93..7cd7e73941 100644 --- a/src/java/org/apache/poi/ss/formula/FormulaParser.java +++ b/src/java/org/apache/poi/ss/formula/FormulaParser.java @@ -31,7 +31,6 @@ 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. @@ -984,14 +983,20 @@ public final class FormulaParser { msg += " but got " + numArgs + "."; throw new FormulaParseException(msg); } - //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(); - } + //the maximum number of arguments depends on the Excel version + int maxArgs; + if (fm.hasUnlimitedVarags()) { + if(_book != null) { + maxArgs = _book.getSpreadsheetVersion().getMaxFunctionArgs(); + } else { + //_book can be omitted by test cases + maxArgs = fm.getMaxParams(); // just use BIFF8 + } + } else { + maxArgs = fm.getMaxParams(); + } - if(numArgs > maxArgs) { + if(numArgs > maxArgs) { String msg = "Too many arguments to function '" + fm.getName() + "'. "; if(fm.hasFixedArgsLength()) { msg += "Expected " + maxArgs;