mirror of https://github.com/apache/poi.git
Allow 255 arguments for excel functions in XSSF, see bugzilla 46279
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@766251 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9eff4e10b3
commit
46b06af35a
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.5-beta6" date="2009-??-??">
|
<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">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">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>
|
<action dev="POI-DEVELOPERS" type="fix">46987 - Allow RecordFactory to handle non-zero padding at the end of the workbook stream</action>
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.5-beta6" date="2009-??-??">
|
<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">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">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>
|
<action dev="POI-DEVELOPERS" type="fix">46987 - Allow RecordFactory to handle non-zero padding at the end of the workbook stream</action>
|
||||||
|
|
|
@ -30,7 +30,15 @@ public final class FunctionMetadataRegistry {
|
||||||
*/
|
*/
|
||||||
public static final String FUNCTION_NAME_IF = "IF";
|
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;
|
public static final short FUNCTION_INDEX_EXTERNAL = 255;
|
||||||
private static FunctionMetadataRegistry _instance;
|
private static FunctionMetadataRegistry _instance;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.formula.NamePtg;
|
||||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.ss.formula.*;
|
import org.apache.poi.ss.formula.*;
|
||||||
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal POI use only
|
* Internal POI use only
|
||||||
|
@ -154,4 +155,8 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
return new NamePtg(_index);
|
return new NamePtg(_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpreadsheetVersion getSpreadsheetVersion(){
|
||||||
|
return SpreadsheetVersion.EXCEL97;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
|
||||||
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.ss.util.CellReference.NameType;
|
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.
|
* 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 + ".";
|
msg += " but got " + numArgs + ".";
|
||||||
throw new FormulaParseException(msg);
|
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() + "'. ";
|
String msg = "Too many arguments to function '" + fm.getName() + "'. ";
|
||||||
if(fm.hasFixedArgsLength()) {
|
if(fm.hasFixedArgsLength()) {
|
||||||
msg += "Expected " + fm.getMaxParams();
|
msg += "Expected " + maxArgs;
|
||||||
} else {
|
} else {
|
||||||
msg += "At most " + fm.getMaxParams() + " were expected";
|
msg += "At most " + maxArgs + " were expected";
|
||||||
}
|
}
|
||||||
msg += " but got " + numArgs + ".";
|
msg += " but got " + numArgs + ".";
|
||||||
throw new FormulaParseException(msg);
|
throw new FormulaParseException(msg);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.apache.poi.ss.formula;
|
package org.apache.poi.ss.formula;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||||
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstracts a workbook for the purpose of formula parsing.<br/>
|
* Abstracts a workbook for the purpose of formula parsing.<br/>
|
||||||
|
@ -44,4 +45,11 @@ public interface FormulaParsingWorkbook {
|
||||||
* @param sheetName a name of a sheet in that workbook
|
* @param sheetName a name of a sheet in that workbook
|
||||||
*/
|
*/
|
||||||
int getExternalSheetIndex(String workbookName, String sheetName);
|
int getExternalSheetIndex(String workbookName, String sheetName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an enum holding spreadhseet properties specific to an Excel version (
|
||||||
|
* max column and row numbers, max arguments to a function, etc.)
|
||||||
|
*/
|
||||||
|
SpreadsheetVersion getSpreadsheetVersion();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -366,14 +366,8 @@ public final class XSSFCell implements Cell {
|
||||||
}
|
}
|
||||||
|
|
||||||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
|
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
|
||||||
try {
|
//validate through the FormulaParser
|
||||||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, wb.getSheetIndex(getSheet()));
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTCellFormula f = CTCellFormula.Factory.newInstance();
|
CTCellFormula f = CTCellFormula.Factory.newInstance();
|
||||||
f.setStringValue(formula);
|
f.setStringValue(formula);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.poi.hssf.record.formula.NamePtg;
|
||||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.ss.formula.*;
|
import org.apache.poi.ss.formula.*;
|
||||||
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,4 +173,8 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
|
||||||
return new NamePtg(_index);
|
return new NamePtg(_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpreadsheetVersion getSpreadsheetVersion(){
|
||||||
|
return SpreadsheetVersion.EXCEL2007;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,14 +191,9 @@ public final class XSSFName implements Name {
|
||||||
|
|
||||||
public void setRefersToFormula(String formulaText) {
|
public void setRefersToFormula(String formulaText) {
|
||||||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(workbook);
|
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(workbook);
|
||||||
try {
|
//validate through the FormulaParser
|
||||||
FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
|
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;
|
|
||||||
}
|
|
||||||
ctName.setStringValue(formulaText);
|
ctName.setStringValue(formulaText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,19 +22,12 @@ import java.util.*;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
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.ss.SpreadsheetVersion;
|
||||||
import org.apache.poi.xssf.model.CalculationChain;
|
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.POILogger;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
|
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.
|
* High level representation of a row of a spreadsheet.
|
||||||
|
|
|
@ -24,19 +24,12 @@ import java.util.*;
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.apache.poi.hssf.util.PaneInformation;
|
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.formula.FormulaShifter;
|
||||||
import org.apache.poi.hssf.record.SharedFormulaRecord;
|
|
||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
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.ss.SpreadsheetVersion;
|
||||||
import org.apache.poi.xssf.model.CommentsTable;
|
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.ColumnHelper;
|
||||||
import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
|
import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
|
||||||
import org.apache.poi.POIXMLDocumentPart;
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
|
|
|
@ -48,7 +48,7 @@ public final class HSSFITestDataProvider implements ITestDataProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpreadsheetVersion getSpreadsheetVersion(){
|
public SpreadsheetVersion getSpreadsheetVersion(){
|
||||||
return SpreadsheetVersion.EXCEL2007;
|
return SpreadsheetVersion.EXCEL97;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HSSFITestDataProvider(){}
|
private HSSFITestDataProvider(){}
|
||||||
|
|
|
@ -19,7 +19,9 @@ package org.apache.poi.ss.usermodel;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
import org.apache.poi.ss.ITestDataProvider;
|
import org.apache.poi.ss.ITestDataProvider;
|
||||||
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base class for bugzilla issues that can be described in terms of common ss interfaces.
|
* A base class for bugzilla issues that can be described in terms of common ss interfaces.
|
||||||
|
@ -295,4 +297,42 @@ public abstract class BaseTestBugzillaIssues extends TestCase {
|
||||||
|
|
||||||
assertEquals(d, (311+312+321+322), 0.0000001);
|
assertEquals(d, (311+312+321+322), 0.0000001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMaxFunctionArguments_bug46729(){
|
||||||
|
String[] func = {"COUNT", "AVERAGE", "MAX", "MIN", "OR", "SUBTOTAL", "SKEW"};
|
||||||
|
|
||||||
|
SpreadsheetVersion ssVersion = getTestDataProvider().getSpreadsheetVersion();
|
||||||
|
Workbook wb = getTestDataProvider().createWorkbook();
|
||||||
|
Cell cell = wb.createSheet().createRow(0).createCell(0);
|
||||||
|
|
||||||
|
String fmla;
|
||||||
|
for (String name : func) {
|
||||||
|
|
||||||
|
fmla = createFunction(name, 5);
|
||||||
|
cell.setCellFormula(fmla);
|
||||||
|
|
||||||
|
fmla = createFunction(name, ssVersion.getMaxFunctionArgs());
|
||||||
|
cell.setCellFormula(fmla);
|
||||||
|
|
||||||
|
try {
|
||||||
|
fmla = createFunction(name, ssVersion.getMaxFunctionArgs() + 1);
|
||||||
|
cell.setCellFormula(fmla);
|
||||||
|
fail("Expected FormulaParseException");
|
||||||
|
} catch (RuntimeException e){
|
||||||
|
assertTrue(e.getMessage().startsWith("Too many arguments to function '"+name+"'"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createFunction(String name, int maxArgs){
|
||||||
|
StringBuffer fmla = new StringBuffer();
|
||||||
|
fmla.append(name);
|
||||||
|
fmla.append("(");
|
||||||
|
for(int i=0; i < maxArgs; i++){
|
||||||
|
if(i > 0) fmla.append(',');
|
||||||
|
fmla.append("A1");
|
||||||
|
}
|
||||||
|
fmla.append(")");
|
||||||
|
return fmla.toString();
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue