git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@642904 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ede1814a1d
commit
5b0efa8e57
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.0.3-beta1" date="2008-04-??">
|
<release version="3.0.3-beta1" date="2008-04-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">Various fixes: Recognising var-arg built-in functions #44675, ExternalNameRecord serialisation bug #44695, PMT() bug #44691</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
|
<action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>
|
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">Move the missing record aware eventusermodel code out of scratchpad</action>
|
<action dev="POI-DEVELOPERS" type="add">Move the missing record aware eventusermodel code out of scratchpad</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.0.3-beta1" date="2008-04-??">
|
<release version="3.0.3-beta1" date="2008-04-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">Various fixes: Recognising var-arg built-in functions #44675, ExternalNameRecord serialisation bug #44695, PMT() bug #44691</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
|
<action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>
|
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">Move the missing record aware eventusermodel code out of scratchpad</action>
|
<action dev="POI-DEVELOPERS" type="add">Move the missing record aware eventusermodel code out of scratchpad</action>
|
||||||
|
@ -28,8 +28,6 @@ import org.apache.poi.hssf.record.formula.*;
|
|||||||
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
|
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
|
||||||
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
* Inspired by
|
* Inspired by
|
||||||
@ -48,11 +46,11 @@ import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
|||||||
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
|
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
|
||||||
*/
|
*/
|
||||||
public final class FormulaParser {
|
public final class FormulaParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific exception thrown when a supplied formula does not parse properly.<br/>
|
* Specific exception thrown when a supplied formula does not parse properly.<br/>
|
||||||
* Primarily used by test cases when testing for specific parsing exceptions.</p>
|
* Primarily used by test cases when testing for specific parsing exceptions.</p>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static final class FormulaParseException extends RuntimeException {
|
static final class FormulaParseException extends RuntimeException {
|
||||||
// This class was given package scope until it would become clear that it is useful to
|
// This class was given package scope until it would become clear that it is useful to
|
||||||
|
@ -37,7 +37,7 @@ public final class ExternalNameRecord extends Record {
|
|||||||
private static final int OPT_PICTURE_LINK = 0x0004;
|
private static final int OPT_PICTURE_LINK = 0x0004;
|
||||||
private static final int OPT_STD_DOCUMENT_NAME = 0x0008;
|
private static final int OPT_STD_DOCUMENT_NAME = 0x0008;
|
||||||
private static final int OPT_OLE_LINK = 0x0010;
|
private static final int OPT_OLE_LINK = 0x0010;
|
||||||
// private static final int OPT_CLIP_FORMAT_MASK = 0x7FE0;
|
// private static final int OPT_CLIP_FORMAT_MASK = 0x7FE0;
|
||||||
private static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000;
|
private static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000;
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,27 +23,27 @@ import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides the base functionality for Excel sheet functions
|
* This class provides the base functionality for Excel sheet functions
|
||||||
* There are two kinds of function Ptgs - tFunc and tFuncVar
|
* There are two kinds of function Ptgs - tFunc and tFuncVar
|
||||||
* Therefore, this class will have ONLY two subclasses
|
* Therefore, this class will have ONLY two subclasses
|
||||||
* @author Avik Sengupta
|
* @author Avik Sengupta
|
||||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractFunctionPtg extends OperationPtg {
|
public abstract class AbstractFunctionPtg extends OperationPtg {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
|
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
|
||||||
*/
|
*/
|
||||||
public static final String FUNCTION_NAME_IF = "IF";
|
public static final String FUNCTION_NAME_IF = "IF";
|
||||||
/** All external functions have function index 255 */
|
/** All external functions have function index 255 */
|
||||||
private static final short FUNCTION_INDEX_EXTERNAL = 255;
|
private static final short FUNCTION_INDEX_EXTERNAL = 255;
|
||||||
|
|
||||||
protected byte returnClass;
|
protected byte returnClass;
|
||||||
protected byte[] paramClass;
|
protected byte[] paramClass;
|
||||||
|
|
||||||
protected byte field_1_num_args;
|
protected byte field_1_num_args;
|
||||||
protected short field_2_fnc_index;
|
protected short field_2_fnc_index;
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer(64);
|
StringBuffer sb = new StringBuffer(64);
|
||||||
sb.append(getClass().getName()).append(" [");
|
sb.append(getClass().getName()).append(" [");
|
||||||
@ -51,17 +51,17 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
|
|||||||
sb.append("]");
|
sb.append("]");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public short getFunctionIndex() {
|
public short getFunctionIndex() {
|
||||||
return field_2_fnc_index;
|
return field_2_fnc_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return lookupName(field_2_fnc_index);
|
return lookupName(field_2_fnc_index);
|
||||||
}
|
}
|
||||||
@ -72,14 +72,14 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
|
|||||||
public boolean isExternalFunction() {
|
public boolean isExternalFunction() {
|
||||||
return field_2_fnc_index == FUNCTION_INDEX_EXTERNAL;
|
return field_2_fnc_index == FUNCTION_INDEX_EXTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toFormulaString(Workbook book) {
|
public String toFormulaString(Workbook book) {
|
||||||
return getName();
|
return getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toFormulaString(String[] operands) {
|
public String toFormulaString(String[] operands) {
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
|
|
||||||
if(isExternalFunction()) {
|
if(isExternalFunction()) {
|
||||||
buf.append(operands[0]); // first operand is actually the function name
|
buf.append(operands[0]); // first operand is actually the function name
|
||||||
appendArgs(buf, 1, operands);
|
appendArgs(buf, 1, operands);
|
||||||
@ -100,23 +100,23 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
|
|||||||
}
|
}
|
||||||
buf.append(")");
|
buf.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void writeBytes(byte[] array, int offset);
|
public abstract void writeBytes(byte[] array, int offset);
|
||||||
public abstract int getSize();
|
public abstract int getSize();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to detect whether a function name found in a formula is one of the standard excel functions
|
* Used to detect whether a function name found in a formula is one of the standard excel functions
|
||||||
* <p>
|
* <p>
|
||||||
* The name matching is case insensitive.
|
* The name matching is case insensitive.
|
||||||
* @return <code>true</code> if the name specifies a standard worksheet function,
|
* @return <code>true</code> if the name specifies a standard worksheet function,
|
||||||
* <code>false</code> if the name should be assumed to be an external function.
|
* <code>false</code> if the name should be assumed to be an external function.
|
||||||
*/
|
*/
|
||||||
public static final boolean isInternalFunctionName(String name) {
|
public static final boolean isInternalFunctionName(String name) {
|
||||||
short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
|
short ix = FunctionMetadataRegistry.lookupIndexByName(name.toUpperCase());
|
||||||
return ix >= 0;
|
return ix >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String lookupName(short index) {
|
protected String lookupName(short index) {
|
||||||
if(index == FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL) {
|
if(index == FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL) {
|
||||||
return "#external#";
|
return "#external#";
|
||||||
@ -127,7 +127,7 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
|
|||||||
}
|
}
|
||||||
return fm.getName();
|
return fm.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves internal function names into function indexes.
|
* Resolves internal function names into function indexes.
|
||||||
* <p>
|
* <p>
|
||||||
@ -145,7 +145,7 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
|
|||||||
public byte getDefaultOperandClass() {
|
public byte getDefaultOperandClass() {
|
||||||
return returnClass;
|
return returnClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getParameterClass(int index) {
|
public byte getParameterClass(int index) {
|
||||||
try {
|
try {
|
||||||
return paramClass[index];
|
return paramClass[index];
|
||||||
|
@ -27,11 +27,11 @@ import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
|||||||
* @author Danny Mui (dmui at apache dot org) (Leftover handling)
|
* @author Danny Mui (dmui at apache dot org) (Leftover handling)
|
||||||
*/
|
*/
|
||||||
public final class FuncPtg extends AbstractFunctionPtg {
|
public final class FuncPtg extends AbstractFunctionPtg {
|
||||||
|
|
||||||
public final static byte sid = 0x21;
|
public final static byte sid = 0x21;
|
||||||
public final static int SIZE = 3;
|
public final static int SIZE = 3;
|
||||||
private int numParams=0;
|
private int numParams=0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FuncPtgs are defined to be 4 bytes but the actual FuncPtg uses only 2 bytes.
|
* FuncPtgs are defined to be 4 bytes but the actual FuncPtg uses only 2 bytes.
|
||||||
* If we have leftOvers that are read from the file we should serialize them back out.
|
* If we have leftOvers that are read from the file we should serialize them back out.
|
||||||
@ -39,18 +39,18 @@ public final class FuncPtg extends AbstractFunctionPtg {
|
|||||||
* If the leftovers are removed, a prompt "Warning: Data may have been lost occurs in Excel"
|
* If the leftovers are removed, a prompt "Warning: Data may have been lost occurs in Excel"
|
||||||
*/
|
*/
|
||||||
//protected byte[] leftOvers = null;
|
//protected byte[] leftOvers = null;
|
||||||
|
|
||||||
private FuncPtg() {
|
private FuncPtg() {
|
||||||
//Required for clone methods
|
//Required for clone methods
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Creates new function pointer from a byte array
|
/**Creates new function pointer from a byte array
|
||||||
* usually called while reading an excel file.
|
* usually called while reading an excel file.
|
||||||
*/
|
*/
|
||||||
public FuncPtg(RecordInputStream in) {
|
public FuncPtg(RecordInputStream in) {
|
||||||
//field_1_num_args = data[ offset + 0 ];
|
//field_1_num_args = data[ offset + 0 ];
|
||||||
field_2_fnc_index = in.readShort();
|
field_2_fnc_index = in.readShort();
|
||||||
|
|
||||||
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
|
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
|
||||||
if(fm == null) {
|
if(fm == null) {
|
||||||
throw new RuntimeException("Invalid built-in function index (" + field_2_fnc_index + ")");
|
throw new RuntimeException("Invalid built-in function index (" + field_2_fnc_index + ")");
|
||||||
@ -62,12 +62,12 @@ public final class FuncPtg extends AbstractFunctionPtg {
|
|||||||
numParams = numberOfParameters;
|
numParams = numberOfParameters;
|
||||||
paramClass = new byte[] { Ptg.CLASS_VALUE, }; // TODO
|
paramClass = new byte[] { Ptg.CLASS_VALUE, }; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeBytes(byte[] array, int offset) {
|
public void writeBytes(byte[] array, int offset) {
|
||||||
array[offset+0]= (byte) (sid + ptgClass);
|
array[offset+0]= (byte) (sid + ptgClass);
|
||||||
LittleEndian.putShort(array,offset+1,field_2_fnc_index);
|
LittleEndian.putShort(array,offset+1,field_2_fnc_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumberOfOperands() {
|
public int getNumberOfOperands() {
|
||||||
return numParams;
|
return numParams;
|
||||||
}
|
}
|
||||||
@ -79,11 +79,11 @@ public final class FuncPtg extends AbstractFunctionPtg {
|
|||||||
ptg.setClass(ptgClass);
|
ptg.setClass(ptgClass);
|
||||||
return ptg;
|
return ptg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return SIZE;
|
return SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer(64);
|
StringBuffer sb = new StringBuffer(64);
|
||||||
sb.append(getClass().getName()).append(" [");
|
sb.append(getClass().getName()).append(" [");
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|
||||||
|
|
||||||
package org.apache.poi.hssf.record.formula;
|
package org.apache.poi.hssf.record.formula;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.hssf.record.RecordInputStream;
|
import org.apache.poi.hssf.record.RecordInputStream;
|
||||||
@ -27,22 +26,22 @@ import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
|||||||
* @author Jason Height (jheight at chariot dot net dot au)
|
* @author Jason Height (jheight at chariot dot net dot au)
|
||||||
*/
|
*/
|
||||||
public final class FuncVarPtg extends AbstractFunctionPtg{
|
public final class FuncVarPtg extends AbstractFunctionPtg{
|
||||||
|
|
||||||
public final static byte sid = 0x22;
|
public final static byte sid = 0x22;
|
||||||
private final static int SIZE = 4;
|
private final static int SIZE = 4;
|
||||||
|
|
||||||
private FuncVarPtg() {
|
private FuncVarPtg() {
|
||||||
//Required for clone methods
|
//Required for clone methods
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Creates new function pointer from a byte array
|
/**Creates new function pointer from a byte array
|
||||||
* usually called while reading an excel file.
|
* usually called while reading an excel file.
|
||||||
*/
|
*/
|
||||||
public FuncVarPtg(RecordInputStream in) {
|
public FuncVarPtg(RecordInputStream in) {
|
||||||
field_1_num_args = in.readByte();
|
field_1_num_args = in.readByte();
|
||||||
field_2_fnc_index = in.readShort();
|
field_2_fnc_index = in.readShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a function ptg from a string tokenised by the parser
|
* Create a function ptg from a string tokenised by the parser
|
||||||
*/
|
*/
|
||||||
@ -59,17 +58,17 @@ public final class FuncVarPtg extends AbstractFunctionPtg{
|
|||||||
paramClass = new byte[] {Ptg.CLASS_VALUE};
|
paramClass = new byte[] {Ptg.CLASS_VALUE};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeBytes(byte[] array, int offset) {
|
public void writeBytes(byte[] array, int offset) {
|
||||||
array[offset+0]=(byte) (sid + ptgClass);
|
array[offset+0]=(byte) (sid + ptgClass);
|
||||||
array[offset+1]=field_1_num_args;
|
array[offset+1]=field_1_num_args;
|
||||||
LittleEndian.putShort(array,offset+2,field_2_fnc_index);
|
LittleEndian.putShort(array,offset+2,field_2_fnc_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumberOfOperands() {
|
public int getNumberOfOperands() {
|
||||||
return field_1_num_args;
|
return field_1_num_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object clone() {
|
public Object clone() {
|
||||||
FuncVarPtg ptg = new FuncVarPtg();
|
FuncVarPtg ptg = new FuncVarPtg();
|
||||||
ptg.field_1_num_args = field_1_num_args;
|
ptg.field_1_num_args = field_1_num_args;
|
||||||
@ -77,11 +76,11 @@ public final class FuncVarPtg extends AbstractFunctionPtg{
|
|||||||
ptg.setClass(ptgClass);
|
ptg.setClass(ptgClass);
|
||||||
return ptg;
|
return ptg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return SIZE;
|
return SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer(64);
|
StringBuffer sb = new StringBuffer(64);
|
||||||
sb.append(getClass().getName()).append(" [");
|
sb.append(getClass().getName()).append(" [");
|
||||||
|
@ -23,7 +23,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporarily collects <tt>FunctionMetadata</tt> instances for creation of a
|
* Temporarily collects <tt>FunctionMetadata</tt> instances for creation of a
|
||||||
* <tt>FunctionMetadataRegistry</tt>.
|
* <tt>FunctionMetadataRegistry</tt>.
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.record.formula.function;
|
package org.apache.poi.hssf.record.formula.function;
|
||||||
/**
|
/**
|
||||||
|
* Holds information about Excel built-in functions.
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
@ -46,7 +47,7 @@ public final class FunctionMetadata {
|
|||||||
return _maxParams;
|
return _maxParams;
|
||||||
}
|
}
|
||||||
public boolean hasFixedArgsLength() {
|
public boolean hasFixedArgsLength() {
|
||||||
return _minParams == _maxParams;
|
return _minParams == _maxParams;
|
||||||
}
|
}
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer(64);
|
StringBuffer sb = new StringBuffer(64);
|
||||||
|
@ -46,7 +46,7 @@ final class FunctionMetadataReader {
|
|||||||
|
|
||||||
public static FunctionMetadataRegistry createRegistry() {
|
public static FunctionMetadataRegistry createRegistry() {
|
||||||
InputStream is = FunctionMetadataReader.class.getResourceAsStream(METADATA_FILE_NAME);
|
InputStream is = FunctionMetadataReader.class.getResourceAsStream(METADATA_FILE_NAME);
|
||||||
if(is == null) {
|
if (is == null) {
|
||||||
throw new RuntimeException("resource '" + METADATA_FILE_NAME + "' not found");
|
throw new RuntimeException("resource '" + METADATA_FILE_NAME + "' not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,11 @@ package org.apache.poi.hssf.record.formula.function;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
/**
|
||||||
|
* Allows clients to get <tt>FunctionMetadata</tt> instances for any built-in function of Excel.
|
||||||
|
*
|
||||||
|
* @author Josh Micich
|
||||||
|
*/
|
||||||
public final class FunctionMetadataRegistry {
|
public final class FunctionMetadataRegistry {
|
||||||
/**
|
/**
|
||||||
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
|
* The name of the IF function (i.e. "IF"). Extracted as a constant for clarity.
|
||||||
@ -35,7 +39,6 @@ public final class FunctionMetadataRegistry {
|
|||||||
private static FunctionMetadataRegistry getInstance() {
|
private static FunctionMetadataRegistry getInstance() {
|
||||||
if (_instance == null) {
|
if (_instance == null) {
|
||||||
_instance = FunctionMetadataReader.createRegistry();
|
_instance = FunctionMetadataReader.createRegistry();
|
||||||
// _instance = POIFunctionMetadataCreator.createInstance();
|
|
||||||
}
|
}
|
||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
@ -46,15 +46,15 @@ public final class Pmt extends FinanceFunction {
|
|||||||
if(args.length < 3 || args.length > 5) {
|
if(args.length < 3 || args.length > 5) {
|
||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// evaluate first three (always present) args
|
// evaluate first three (always present) args
|
||||||
double rate = evalArg(args[0], srcRow, srcCol);
|
double rate = evalArg(args[0], srcRow, srcCol);
|
||||||
double nper = evalArg(args[1], srcRow, srcCol);
|
double nper = evalArg(args[1], srcRow, srcCol);
|
||||||
double pv = evalArg(args[2], srcRow, srcCol);
|
double pv = evalArg(args[2], srcRow, srcCol);
|
||||||
double fv = 0;
|
double fv = 0;
|
||||||
boolean arePaymentsAtPeriodBeginning = false;
|
boolean arePaymentsAtPeriodBeginning = false;
|
||||||
|
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
case 5:
|
case 5:
|
||||||
ValueEval ve = singleOperandNumericAsBoolean(args[4], srcRow, srcCol);
|
ValueEval ve = singleOperandNumericAsBoolean(args[4], srcRow, srcCol);
|
||||||
@ -67,10 +67,10 @@ public final class Pmt extends FinanceFunction {
|
|||||||
}
|
}
|
||||||
double d = FinanceLib.pmt(rate, nper, pv, fv, arePaymentsAtPeriodBeginning);
|
double d = FinanceLib.pmt(rate, nper, pv, fv, arePaymentsAtPeriodBeginning);
|
||||||
if (Double.isNaN(d)) {
|
if (Double.isNaN(d)) {
|
||||||
return (ValueEval) ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
if (Double.isInfinite(d)) {
|
if (Double.isInfinite(d)) {
|
||||||
return (ValueEval) ErrorEval.NUM_ERROR;
|
return ErrorEval.NUM_ERROR;
|
||||||
}
|
}
|
||||||
return new NumberEval(d);
|
return new NumberEval(d);
|
||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|
||||||
package org.apache.poi.hssf.model;
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
@ -54,7 +54,7 @@ import org.apache.poi.hssf.usermodel.HSSFSheet;
|
|||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the low level formula parser functionality. High level tests are to
|
* Test the low level formula parser functionality. High level tests are to
|
||||||
* be done via usermodel/HSSFCell.setFormulaValue() .
|
* be done via usermodel/HSSFCell.setFormulaValue() .
|
||||||
* Some tests are also done in scratchpad, if they need
|
* Some tests are also done in scratchpad, if they need
|
||||||
* HSSFFormulaEvaluator, which is there
|
* HSSFFormulaEvaluator, which is there
|
||||||
@ -71,7 +71,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertNotNull("Ptg array should not be null", result);
|
assertNotNull("Ptg array should not be null", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSimpleFormula() {
|
public void testSimpleFormula() {
|
||||||
FormulaParser fp = new FormulaParser("2+2",null);
|
FormulaParser fp = new FormulaParser("2+2",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
@ -86,9 +86,9 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertTrue("",(ptgs[0] instanceof IntPtg));
|
assertTrue("",(ptgs[0] instanceof IntPtg));
|
||||||
assertTrue("",(ptgs[1] instanceof IntPtg));
|
assertTrue("",(ptgs[1] instanceof IntPtg));
|
||||||
assertTrue("",(ptgs[2] instanceof AddPtg));
|
assertTrue("",(ptgs[2] instanceof AddPtg));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFormulaWithSpace2() {
|
public void testFormulaWithSpace2() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
FormulaParser fp;
|
FormulaParser fp;
|
||||||
@ -97,7 +97,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
ptgs = fp.getRPNPtg();
|
ptgs = fp.getRPNPtg();
|
||||||
assertTrue("five tokens expected, got "+ptgs.length,ptgs.length == 5);
|
assertTrue("five tokens expected, got "+ptgs.length,ptgs.length == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFormulaWithSpaceNRef() {
|
public void testFormulaWithSpaceNRef() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
FormulaParser fp;
|
FormulaParser fp;
|
||||||
@ -106,7 +106,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
ptgs = fp.getRPNPtg();
|
ptgs = fp.getRPNPtg();
|
||||||
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
|
assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFormulaWithString() {
|
public void testFormulaWithString() {
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
FormulaParser fp;
|
FormulaParser fp;
|
||||||
@ -172,7 +172,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make sure the ptgs are generated properly with two functions embedded
|
* Make sure the ptgs are generated properly with two functions embedded
|
||||||
*
|
*
|
||||||
@ -225,7 +225,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertEquals("4 Ptgs expected", 4, asts.length);
|
assertEquals("4 Ptgs expected", 4, asts.length);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bug Reported by xt-jens.riis@nokia.com (Jens Riis)
|
* Bug Reported by xt-jens.riis@nokia.com (Jens Riis)
|
||||||
* Refers to Bug <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17582">#17582</a>
|
* Refers to Bug <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17582">#17582</a>
|
||||||
@ -247,7 +247,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSimpleLogical() {
|
public void testSimpleLogical() {
|
||||||
FormulaParser fp=new FormulaParser("IF(A1<A2,B1,B2)",null);
|
FormulaParser fp=new FormulaParser("IF(A1<A2,B1,B2)",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
@ -255,10 +255,10 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertTrue("Ptg array should not be null", ptgs !=null);
|
assertTrue("Ptg array should not be null", ptgs !=null);
|
||||||
assertEquals("Ptg array length", 9, ptgs.length);
|
assertEquals("Ptg array length", 9, ptgs.length);
|
||||||
assertEquals("3rd Ptg is less than",LessThanPtg.class,ptgs[2].getClass());
|
assertEquals("3rd Ptg is less than",LessThanPtg.class,ptgs[2].getClass());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParenIf() {
|
public void testParenIf() {
|
||||||
FormulaParser fp=new FormulaParser("IF((A1+A2)<=3,\"yes\",\"no\")",null);
|
FormulaParser fp=new FormulaParser("IF((A1+A2)<=3,\"yes\",\"no\")",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
@ -281,7 +281,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertEquals("15th Ptg is not the inner IF variable function ptg",FuncVarPtg.class,ptgs[14].getClass());
|
assertEquals("15th Ptg is not the inner IF variable function ptg",FuncVarPtg.class,ptgs[14].getClass());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMacroFunction() {
|
public void testMacroFunction() {
|
||||||
Workbook w = Workbook.createWorkbook();
|
Workbook w = Workbook.createWorkbook();
|
||||||
FormulaParser fp = new FormulaParser("FOO()", w);
|
FormulaParser fp = new FormulaParser("FOO()", w);
|
||||||
@ -291,7 +291,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
// the name gets encoded as the first arg
|
// the name gets encoded as the first arg
|
||||||
NamePtg tname = (NamePtg) ptg[0];
|
NamePtg tname = (NamePtg) ptg[0];
|
||||||
assertEquals("FOO", tname.toFormulaString(w));
|
assertEquals("FOO", tname.toFormulaString(w));
|
||||||
|
|
||||||
AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
|
AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
|
||||||
assertTrue(tfunc.isExternalFunction());
|
assertTrue(tfunc.isExternalFunction());
|
||||||
}
|
}
|
||||||
@ -302,9 +302,9 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
Ptg[] ptg = fp.getRPNPtg();
|
Ptg[] ptg = fp.getRPNPtg();
|
||||||
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
|
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
|
||||||
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
|
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConcatenate(){
|
public void testConcatenate(){
|
||||||
FormulaParser fp = new FormulaParser("CONCATENATE(\"first\",\"second\")",null);
|
FormulaParser fp = new FormulaParser("CONCATENATE(\"first\",\"second\")",null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
@ -312,7 +312,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
|
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
|
||||||
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
|
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWorksheetReferences()
|
public void testWorksheetReferences()
|
||||||
{
|
{
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
@ -330,7 +330,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
cell = row.createCell((short)1);
|
cell = row.createCell((short)1);
|
||||||
cell.setCellFormula("'Quotes Needed Here &#$@'!A1");
|
cell.setCellFormula("'Quotes Needed Here &#$@'!A1");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnaryMinus()
|
public void testUnaryMinus()
|
||||||
{
|
{
|
||||||
FormulaParser fp = new FormulaParser("-A1", null);
|
FormulaParser fp = new FormulaParser("-A1", null);
|
||||||
@ -340,7 +340,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
|
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
|
||||||
assertTrue("second ptg is Minus",ptg[1] instanceof UnaryMinusPtg);
|
assertTrue("second ptg is Minus",ptg[1] instanceof UnaryMinusPtg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnaryPlus()
|
public void testUnaryPlus()
|
||||||
{
|
{
|
||||||
FormulaParser fp = new FormulaParser("+A1", null);
|
FormulaParser fp = new FormulaParser("+A1", null);
|
||||||
@ -350,14 +350,14 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
|
assertTrue("first ptg is reference",ptg[0] instanceof ReferencePtg);
|
||||||
assertTrue("second ptg is Plus",ptg[1] instanceof UnaryPlusPtg);
|
assertTrue("second ptg is Plus",ptg[1] instanceof UnaryPlusPtg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLeadingSpaceInString()
|
public void testLeadingSpaceInString()
|
||||||
{
|
{
|
||||||
String value = " hi ";
|
String value = " hi ";
|
||||||
FormulaParser fp = new FormulaParser("\"" + value + "\"", null);
|
FormulaParser fp = new FormulaParser("\"" + value + "\"", null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
Ptg[] ptg = fp.getRPNPtg();
|
||||||
|
|
||||||
assertTrue("got 1 ptg", ptg.length == 1);
|
assertTrue("got 1 ptg", ptg.length == 1);
|
||||||
assertTrue("ptg0 is a StringPtg", ptg[0] instanceof StringPtg);
|
assertTrue("ptg0 is a StringPtg", ptg[0] instanceof StringPtg);
|
||||||
assertTrue("ptg0 contains exact value", ((StringPtg)ptg[0]).getValue().equals(value));
|
assertTrue("ptg0 contains exact value", ((StringPtg)ptg[0]).getValue().equals(value));
|
||||||
@ -368,14 +368,14 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
FormulaParser fp = new FormulaParser("lookup(A1, A3:A52, B3:B52)", null);
|
FormulaParser fp = new FormulaParser("lookup(A1, A3:A52, B3:B52)", null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
Ptg[] ptg = fp.getRPNPtg();
|
Ptg[] ptg = fp.getRPNPtg();
|
||||||
|
|
||||||
assertTrue("got 4 ptg", ptg.length == 4);
|
assertTrue("got 4 ptg", ptg.length == 4);
|
||||||
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
|
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
|
||||||
|
|
||||||
fp = new FormulaParser("match(A1, A3:A52)", null);
|
fp = new FormulaParser("match(A1, A3:A52)", null);
|
||||||
fp.parse();
|
fp.parse();
|
||||||
ptg = fp.getRPNPtg();
|
ptg = fp.getRPNPtg();
|
||||||
|
|
||||||
assertTrue("got 3 ptg", ptg.length == 3);
|
assertTrue("got 3 ptg", ptg.length == 3);
|
||||||
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
|
assertTrue("ptg0 has Value class", ptg[0].getPtgClass() == Ptg.CLASS_VALUE);
|
||||||
}
|
}
|
||||||
@ -521,77 +521,77 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
|
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
|
||||||
junit.textui.TestRunner.run(TestFormulaParser.class);
|
junit.textui.TestRunner.run(TestFormulaParser.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNumbers() {
|
public void testNumbers() {
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
|
||||||
wb.createSheet("Cash_Flow");
|
wb.createSheet("Cash_Flow");
|
||||||
|
|
||||||
HSSFSheet sheet = wb.createSheet("Test");
|
HSSFSheet sheet = wb.createSheet("Test");
|
||||||
HSSFRow row = sheet.createRow(0);
|
HSSFRow row = sheet.createRow(0);
|
||||||
HSSFCell cell = row.createCell((short)0);
|
HSSFCell cell = row.createCell((short)0);
|
||||||
String formula = null;
|
String formula = null;
|
||||||
|
|
||||||
// starts from decimal point
|
// starts from decimal point
|
||||||
|
|
||||||
cell.setCellFormula(".1");
|
cell.setCellFormula(".1");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("0.1", formula);
|
assertEquals("0.1", formula);
|
||||||
|
|
||||||
cell.setCellFormula("+.1");
|
cell.setCellFormula("+.1");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("+0.1", formula);
|
assertEquals("+0.1", formula);
|
||||||
|
|
||||||
cell.setCellFormula("-.1");
|
cell.setCellFormula("-.1");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("-0.1", formula);
|
assertEquals("-0.1", formula);
|
||||||
|
|
||||||
// has exponent
|
// has exponent
|
||||||
|
|
||||||
cell.setCellFormula("10E1");
|
cell.setCellFormula("10E1");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("100.0", formula);
|
assertEquals("100.0", formula);
|
||||||
|
|
||||||
cell.setCellFormula("10E+1");
|
cell.setCellFormula("10E+1");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("100.0", formula);
|
assertEquals("100.0", formula);
|
||||||
|
|
||||||
cell.setCellFormula("10E-1");
|
cell.setCellFormula("10E-1");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("1.0", formula);
|
assertEquals("1.0", formula);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRanges() {
|
public void testRanges() {
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
|
||||||
wb.createSheet("Cash_Flow");
|
wb.createSheet("Cash_Flow");
|
||||||
|
|
||||||
HSSFSheet sheet = wb.createSheet("Test");
|
HSSFSheet sheet = wb.createSheet("Test");
|
||||||
HSSFRow row = sheet.createRow(0);
|
HSSFRow row = sheet.createRow(0);
|
||||||
HSSFCell cell = row.createCell((short)0);
|
HSSFCell cell = row.createCell((short)0);
|
||||||
String formula = null;
|
String formula = null;
|
||||||
|
|
||||||
cell.setCellFormula("A1.A2");
|
cell.setCellFormula("A1.A2");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("A1:A2", formula);
|
assertEquals("A1:A2", formula);
|
||||||
|
|
||||||
cell.setCellFormula("A1..A2");
|
cell.setCellFormula("A1..A2");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("A1:A2", formula);
|
assertEquals("A1:A2", formula);
|
||||||
|
|
||||||
cell.setCellFormula("A1...A2");
|
cell.setCellFormula("A1...A2");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
assertEquals("A1:A2", formula);
|
assertEquals("A1:A2", formula);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for bug observable at svn revision 618865 (5-Feb-2008)<br/>
|
* Test for bug observable at svn revision 618865 (5-Feb-2008)<br/>
|
||||||
* a formula consisting of a single no-arg function got rendered without the function braces
|
* a formula consisting of a single no-arg function got rendered without the function braces
|
||||||
*/
|
*/
|
||||||
public void testToFormulaStringZeroArgFunction() {
|
public void testToFormulaStringZeroArgFunction() {
|
||||||
|
|
||||||
Workbook book = Workbook.createWorkbook(); // not really used in this test
|
Workbook book = Workbook.createWorkbook(); // not really used in this test
|
||||||
|
|
||||||
Ptg[] ptgs = {
|
Ptg[] ptgs = {
|
||||||
new FuncPtg(10, 0),
|
new FuncPtg(10, 0),
|
||||||
};
|
};
|
||||||
@ -610,21 +610,21 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
assertEquals(2, ptgs.length);
|
assertEquals(2, ptgs.length);
|
||||||
assertEquals(ptgs[0].getClass(), IntPtg.class);
|
assertEquals(ptgs[0].getClass(), IntPtg.class);
|
||||||
assertEquals(ptgs[1].getClass(), PercentPtg.class);
|
assertEquals(ptgs[1].getClass(), PercentPtg.class);
|
||||||
|
|
||||||
|
|
||||||
// double percent OK
|
// double percent OK
|
||||||
ptgs = parseFormula("12345.678%%");
|
ptgs = parseFormula("12345.678%%");
|
||||||
assertEquals(3, ptgs.length);
|
assertEquals(3, ptgs.length);
|
||||||
assertEquals(ptgs[0].getClass(), NumberPtg.class);
|
assertEquals(ptgs[0].getClass(), NumberPtg.class);
|
||||||
assertEquals(ptgs[1].getClass(), PercentPtg.class);
|
assertEquals(ptgs[1].getClass(), PercentPtg.class);
|
||||||
assertEquals(ptgs[2].getClass(), PercentPtg.class);
|
assertEquals(ptgs[2].getClass(), PercentPtg.class);
|
||||||
|
|
||||||
// percent of a bracketed expression
|
// percent of a bracketed expression
|
||||||
ptgs = parseFormula("(A1+35)%*B1%");
|
ptgs = parseFormula("(A1+35)%*B1%");
|
||||||
assertEquals(8, ptgs.length);
|
assertEquals(8, ptgs.length);
|
||||||
assertEquals(ptgs[4].getClass(), PercentPtg.class);
|
assertEquals(ptgs[4].getClass(), PercentPtg.class);
|
||||||
assertEquals(ptgs[6].getClass(), PercentPtg.class);
|
assertEquals(ptgs[6].getClass(), PercentPtg.class);
|
||||||
|
|
||||||
// percent of a text quantity
|
// percent of a text quantity
|
||||||
ptgs = parseFormula("\"8.75\"%");
|
ptgs = parseFormula("\"8.75\"%");
|
||||||
assertEquals(2, ptgs.length);
|
assertEquals(2, ptgs.length);
|
||||||
@ -641,64 +641,64 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
|
|
||||||
//
|
//
|
||||||
// things that parse OK but would *evaluate* to an error
|
// things that parse OK but would *evaluate* to an error
|
||||||
|
|
||||||
ptgs = parseFormula("\"abc\"%");
|
ptgs = parseFormula("\"abc\"%");
|
||||||
assertEquals(2, ptgs.length);
|
assertEquals(2, ptgs.length);
|
||||||
assertEquals(ptgs[0].getClass(), StringPtg.class);
|
assertEquals(ptgs[0].getClass(), StringPtg.class);
|
||||||
assertEquals(ptgs[1].getClass(), PercentPtg.class);
|
assertEquals(ptgs[1].getClass(), PercentPtg.class);
|
||||||
|
|
||||||
ptgs = parseFormula("#N/A%");
|
ptgs = parseFormula("#N/A%");
|
||||||
assertEquals(2, ptgs.length);
|
assertEquals(2, ptgs.length);
|
||||||
assertEquals(ptgs[0].getClass(), ErrPtg.class);
|
assertEquals(ptgs[0].getClass(), ErrPtg.class);
|
||||||
assertEquals(ptgs[1].getClass(), PercentPtg.class);
|
assertEquals(ptgs[1].getClass(), PercentPtg.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests combinations of various operators in the absence of brackets
|
* Tests combinations of various operators in the absence of brackets
|
||||||
*/
|
*/
|
||||||
public void testPrecedenceAndAssociativity() {
|
public void testPrecedenceAndAssociativity() {
|
||||||
|
|
||||||
Class[] expClss;
|
Class[] expClss;
|
||||||
|
|
||||||
// TRUE=TRUE=2=2 evaluates to FALSE
|
// TRUE=TRUE=2=2 evaluates to FALSE
|
||||||
expClss = new Class[] { BoolPtg.class, BoolPtg.class, EqualPtg.class,
|
expClss = new Class[] { BoolPtg.class, BoolPtg.class, EqualPtg.class,
|
||||||
IntPtg.class, EqualPtg.class, IntPtg.class, EqualPtg.class, };
|
IntPtg.class, EqualPtg.class, IntPtg.class, EqualPtg.class, };
|
||||||
confirmTokenClasses("TRUE=TRUE=2=2", expClss);
|
confirmTokenClasses("TRUE=TRUE=2=2", expClss);
|
||||||
|
|
||||||
|
|
||||||
// 2^3^2 evaluates to 64 not 512
|
// 2^3^2 evaluates to 64 not 512
|
||||||
expClss = new Class[] { IntPtg.class, IntPtg.class, PowerPtg.class,
|
expClss = new Class[] { IntPtg.class, IntPtg.class, PowerPtg.class,
|
||||||
IntPtg.class, PowerPtg.class, };
|
IntPtg.class, PowerPtg.class, };
|
||||||
confirmTokenClasses("2^3^2", expClss);
|
confirmTokenClasses("2^3^2", expClss);
|
||||||
|
|
||||||
// "abc" & 2 + 3 & "def" evaluates to "abc5def"
|
// "abc" & 2 + 3 & "def" evaluates to "abc5def"
|
||||||
expClss = new Class[] { StringPtg.class, IntPtg.class, IntPtg.class,
|
expClss = new Class[] { StringPtg.class, IntPtg.class, IntPtg.class,
|
||||||
AddPtg.class, ConcatPtg.class, StringPtg.class, ConcatPtg.class, };
|
AddPtg.class, ConcatPtg.class, StringPtg.class, ConcatPtg.class, };
|
||||||
confirmTokenClasses("\"abc\"&2+3&\"def\"", expClss);
|
confirmTokenClasses("\"abc\"&2+3&\"def\"", expClss);
|
||||||
|
|
||||||
|
|
||||||
// (1 / 2) - (3 * 4)
|
// (1 / 2) - (3 * 4)
|
||||||
expClss = new Class[] { IntPtg.class, IntPtg.class, DividePtg.class,
|
expClss = new Class[] { IntPtg.class, IntPtg.class, DividePtg.class,
|
||||||
IntPtg.class, IntPtg.class, MultiplyPtg.class, SubtractPtg.class, };
|
IntPtg.class, IntPtg.class, MultiplyPtg.class, SubtractPtg.class, };
|
||||||
confirmTokenClasses("1/2-3*4", expClss);
|
confirmTokenClasses("1/2-3*4", expClss);
|
||||||
|
|
||||||
// 2 * (2^2)
|
// 2 * (2^2)
|
||||||
expClss = new Class[] { IntPtg.class, IntPtg.class, IntPtg.class, PowerPtg.class, MultiplyPtg.class, };
|
expClss = new Class[] { IntPtg.class, IntPtg.class, IntPtg.class, PowerPtg.class, MultiplyPtg.class, };
|
||||||
// NOT: (2 *2) ^ 2 -> int int multiply int power
|
// NOT: (2 *2) ^ 2 -> int int multiply int power
|
||||||
confirmTokenClasses("2*2^2", expClss);
|
confirmTokenClasses("2*2^2", expClss);
|
||||||
|
|
||||||
// 2^200% -> 2 not 1.6E58
|
// 2^200% -> 2 not 1.6E58
|
||||||
expClss = new Class[] { IntPtg.class, IntPtg.class, PercentPtg.class, PowerPtg.class, };
|
expClss = new Class[] { IntPtg.class, IntPtg.class, PercentPtg.class, PowerPtg.class, };
|
||||||
confirmTokenClasses("2^200%", expClss);
|
confirmTokenClasses("2^200%", expClss);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void confirmTokenClasses(String formula, Class[] expectedClasses) {
|
private static void confirmTokenClasses(String formula, Class[] expectedClasses) {
|
||||||
Ptg[] ptgs = parseFormula(formula);
|
Ptg[] ptgs = parseFormula(formula);
|
||||||
assertEquals(expectedClasses.length, ptgs.length);
|
assertEquals(expectedClasses.length, ptgs.length);
|
||||||
for (int i = 0; i < expectedClasses.length; i++) {
|
for (int i = 0; i < expectedClasses.length; i++) {
|
||||||
if(expectedClasses[i] != ptgs[i].getClass()) {
|
if(expectedClasses[i] != ptgs[i].getClass()) {
|
||||||
fail("difference at token[" + i + "]: expected ("
|
fail("difference at token[" + i + "]: expected ("
|
||||||
+ expectedClasses[i].getName() + ") but got ("
|
+ expectedClasses[i].getName() + ") but got ("
|
||||||
+ ptgs[i].getClass().getName() + ")");
|
+ ptgs[i].getClass().getName() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -718,38 +718,38 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
|
|
||||||
public void testParseNumber() {
|
public void testParseNumber() {
|
||||||
IntPtg ip;
|
IntPtg ip;
|
||||||
|
|
||||||
// bug 33160
|
// bug 33160
|
||||||
ip = (IntPtg) parseSingleToken("40", IntPtg.class);
|
ip = (IntPtg) parseSingleToken("40", IntPtg.class);
|
||||||
assertEquals(40, ip.getValue());
|
assertEquals(40, ip.getValue());
|
||||||
ip = (IntPtg) parseSingleToken("40000", IntPtg.class);
|
ip = (IntPtg) parseSingleToken("40000", IntPtg.class);
|
||||||
assertEquals(40000, ip.getValue());
|
assertEquals(40000, ip.getValue());
|
||||||
|
|
||||||
// check the upper edge of the IntPtg range:
|
// check the upper edge of the IntPtg range:
|
||||||
ip = (IntPtg) parseSingleToken("65535", IntPtg.class);
|
ip = (IntPtg) parseSingleToken("65535", IntPtg.class);
|
||||||
assertEquals(65535, ip.getValue());
|
assertEquals(65535, ip.getValue());
|
||||||
NumberPtg np = (NumberPtg) parseSingleToken("65536", NumberPtg.class);
|
NumberPtg np = (NumberPtg) parseSingleToken("65536", NumberPtg.class);
|
||||||
assertEquals(65536, np.getValue(), 0);
|
assertEquals(65536, np.getValue(), 0);
|
||||||
|
|
||||||
np = (NumberPtg) parseSingleToken("65534.6", NumberPtg.class);
|
np = (NumberPtg) parseSingleToken("65534.6", NumberPtg.class);
|
||||||
assertEquals(65534.6, np.getValue(), 0);
|
assertEquals(65534.6, np.getValue(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMissingArgs() {
|
public void testMissingArgs() {
|
||||||
|
|
||||||
Class[] expClss;
|
Class[] expClss;
|
||||||
|
|
||||||
expClss = new Class[] { ReferencePtg.class, MissingArgPtg.class, ReferencePtg.class,
|
expClss = new Class[] { ReferencePtg.class, MissingArgPtg.class, ReferencePtg.class,
|
||||||
FuncVarPtg.class, };
|
FuncVarPtg.class, };
|
||||||
confirmTokenClasses("if(A1, ,C1)", expClss);
|
confirmTokenClasses("if(A1, ,C1)", expClss);
|
||||||
|
|
||||||
expClss = new Class[] { MissingArgPtg.class, AreaPtg.class, MissingArgPtg.class,
|
expClss = new Class[] { MissingArgPtg.class, AreaPtg.class, MissingArgPtg.class,
|
||||||
FuncVarPtg.class, };
|
FuncVarPtg.class, };
|
||||||
confirmTokenClasses("counta( , A1:B2, )", expClss);
|
confirmTokenClasses("counta( , A1:B2, )", expClss);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseErrorLiterals() {
|
public void testParseErrorLiterals() {
|
||||||
|
|
||||||
confirmParseErrorLiteral(ErrPtg.NULL_INTERSECTION, "#NULL!");
|
confirmParseErrorLiteral(ErrPtg.NULL_INTERSECTION, "#NULL!");
|
||||||
confirmParseErrorLiteral(ErrPtg.DIV_ZERO, "#DIV/0!");
|
confirmParseErrorLiteral(ErrPtg.DIV_ZERO, "#DIV/0!");
|
||||||
confirmParseErrorLiteral(ErrPtg.VALUE_INVALID, "#VALUE!");
|
confirmParseErrorLiteral(ErrPtg.VALUE_INVALID, "#VALUE!");
|
||||||
@ -762,7 +762,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
private static void confirmParseErrorLiteral(ErrPtg expectedToken, String formula) {
|
private static void confirmParseErrorLiteral(ErrPtg expectedToken, String formula) {
|
||||||
assertEquals(expectedToken, parseSingleToken(formula, ErrPtg.class));
|
assertEquals(expectedToken, parseSingleToken(formula, ErrPtg.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To aid readability the parameters have been encoded with single quotes instead of double
|
* To aid readability the parameters have been encoded with single quotes instead of double
|
||||||
* quotes. This method converts single quotes to double quotes before performing the parse
|
* quotes. This method converts single quotes to double quotes before performing the parse
|
||||||
@ -772,23 +772,23 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
// formula: internal quotes become double double, surround with double quotes
|
// formula: internal quotes become double double, surround with double quotes
|
||||||
String formula = '"' + singleQuotedValue.replaceAll("'", "\"\"") + '"';
|
String formula = '"' + singleQuotedValue.replaceAll("'", "\"\"") + '"';
|
||||||
String expectedValue = singleQuotedValue.replace('\'', '"');
|
String expectedValue = singleQuotedValue.replace('\'', '"');
|
||||||
|
|
||||||
StringPtg sp = (StringPtg) parseSingleToken(formula, StringPtg.class);
|
StringPtg sp = (StringPtg) parseSingleToken(formula, StringPtg.class);
|
||||||
assertEquals(expectedValue, sp.getValue());
|
assertEquals(expectedValue, sp.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPaseStringLiterals() {
|
public void testPaseStringLiterals() {
|
||||||
confirmStringParse("goto considered harmful");
|
confirmStringParse("goto considered harmful");
|
||||||
|
|
||||||
confirmStringParse("goto 'considered' harmful");
|
confirmStringParse("goto 'considered' harmful");
|
||||||
|
|
||||||
confirmStringParse("");
|
confirmStringParse("");
|
||||||
confirmStringParse("'");
|
confirmStringParse("'");
|
||||||
confirmStringParse("''");
|
confirmStringParse("''");
|
||||||
confirmStringParse("' '");
|
confirmStringParse("' '");
|
||||||
confirmStringParse(" ' ");
|
confirmStringParse(" ' ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseSumIfSum() {
|
public void testParseSumIfSum() {
|
||||||
String formulaString;
|
String formulaString;
|
||||||
Ptg[] ptgs;
|
Ptg[] ptgs;
|
||||||
@ -809,14 +809,14 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
parseExpectedException("1 + #N / A * 2");
|
parseExpectedException("1 + #N / A * 2");
|
||||||
parseExpectedException("#value?");
|
parseExpectedException("#value?");
|
||||||
parseExpectedException("#DIV/ 0+2");
|
parseExpectedException("#DIV/ 0+2");
|
||||||
|
|
||||||
|
|
||||||
if (false) { // TODO - add functionality to detect func arg count mismatch
|
if (false) { // TODO - add functionality to detect func arg count mismatch
|
||||||
parseExpectedException("IF(TRUE)");
|
parseExpectedException("IF(TRUE)");
|
||||||
parseExpectedException("countif(A1:B5, C1, D1)");
|
parseExpectedException("countif(A1:B5, C1, D1)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseExpectedException(String formula) {
|
private static void parseExpectedException(String formula) {
|
||||||
try {
|
try {
|
||||||
parseFormula(formula);
|
parseFormula(formula);
|
||||||
@ -831,11 +831,11 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testSetFormulaWithRowBeyond32768_Bug44539() {
|
public void testSetFormulaWithRowBeyond32768_Bug44539() {
|
||||||
|
|
||||||
HSSFWorkbook wb = new HSSFWorkbook();
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
HSSFSheet sheet = wb.createSheet();
|
HSSFSheet sheet = wb.createSheet();
|
||||||
wb.setSheetName(0, "Sheet1");
|
wb.setSheetName(0, "Sheet1");
|
||||||
|
|
||||||
HSSFRow row = sheet.createRow(0);
|
HSSFRow row = sheet.createRow(0);
|
||||||
HSSFCell cell = row.createCell((short)0);
|
HSSFCell cell = row.createCell((short)0);
|
||||||
cell.setCellFormula("SUM(A32769:A32770)");
|
cell.setCellFormula("SUM(A32769:A32770)");
|
||||||
@ -862,11 +862,11 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
// FormulaParser strips spaces anyway
|
// FormulaParser strips spaces anyway
|
||||||
assertEquals("4", formulaString);
|
assertEquals("4", formulaString);
|
||||||
|
|
||||||
ptgs = new Ptg[] { new IntPtg(3), spacePtg, new IntPtg(4), spacePtg, new AddPtg()};
|
ptgs = new Ptg[] { new IntPtg(3), spacePtg, new IntPtg(4), spacePtg, new AddPtg()};
|
||||||
formulaString = FormulaParser.toFormulaString(null, ptgs);
|
formulaString = FormulaParser.toFormulaString(null, ptgs);
|
||||||
assertEquals("3+4", formulaString);
|
assertEquals("3+4", formulaString);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -875,7 +875,7 @@ public final class TestFormulaParser extends TestCase {
|
|||||||
public void testTooFewOperandArgs() {
|
public void testTooFewOperandArgs() {
|
||||||
// Simulating badly encoded cell formula of "=/1"
|
// Simulating badly encoded cell formula of "=/1"
|
||||||
// Not sure if Excel could ever produce this
|
// Not sure if Excel could ever produce this
|
||||||
Ptg[] ptgs = {
|
Ptg[] ptgs = {
|
||||||
// Excel would probably have put tMissArg here
|
// Excel would probably have put tMissArg here
|
||||||
new IntPtg(1),
|
new IntPtg(1),
|
||||||
new DividePtg(),
|
new DividePtg(),
|
||||||
|
@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
|
|||||||
|
|
||||||
import org.apache.poi.hssf.record.aggregates.AllRecordAggregateTests;
|
import org.apache.poi.hssf.record.aggregates.AllRecordAggregateTests;
|
||||||
import org.apache.poi.hssf.record.formula.AllFormulaTests;
|
import org.apache.poi.hssf.record.formula.AllFormulaTests;
|
||||||
|
import org.apache.poi.hssf.record.formula.functions.AllIndividualFunctionEvaluationTests;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
@ -35,7 +36,7 @@ public final class AllRecordTests {
|
|||||||
|
|
||||||
result.addTest(AllFormulaTests.suite());
|
result.addTest(AllFormulaTests.suite());
|
||||||
result.addTest(AllRecordAggregateTests.suite());
|
result.addTest(AllRecordAggregateTests.suite());
|
||||||
|
|
||||||
result.addTestSuite(TestAreaFormatRecord.class);
|
result.addTestSuite(TestAreaFormatRecord.class);
|
||||||
result.addTestSuite(TestAreaRecord.class);
|
result.addTestSuite(TestAreaRecord.class);
|
||||||
result.addTestSuite(TestAxisLineFormatRecord.class);
|
result.addTestSuite(TestAxisLineFormatRecord.class);
|
||||||
|
@ -44,7 +44,7 @@ public final class TestExternalNameRecord extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBasicSize() {
|
public void testBasicSize() {
|
||||||
ExternalNameRecord enr = createSimpleENR();
|
ExternalNameRecord enr = createSimpleENR();
|
||||||
if(enr.getRecordSize() == 13) {
|
if(enr.getRecordSize() == 13) {
|
||||||
|
@ -17,13 +17,15 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.record.formula;
|
package org.apache.poi.hssf.record.formula;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.AllFormulaEvalTests;
|
||||||
import org.apache.poi.hssf.record.formula.function.AllFormulaFunctionTests;
|
import org.apache.poi.hssf.record.formula.function.AllFormulaFunctionTests;
|
||||||
|
import org.apache.poi.hssf.record.formula.functions.AllIndividualFunctionEvaluationTests;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects all tests for this package.
|
* Collects all tests for <tt>org.apache.poi.hssf.record.formula</tt>.
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
@ -31,6 +33,10 @@ public class AllFormulaTests {
|
|||||||
|
|
||||||
public static Test suite() {
|
public static Test suite() {
|
||||||
TestSuite result = new TestSuite(AllFormulaTests.class.getName());
|
TestSuite result = new TestSuite(AllFormulaTests.class.getName());
|
||||||
|
result.addTest(AllFormulaEvalTests.suite());
|
||||||
|
result.addTest(AllFormulaFunctionTests.suite());
|
||||||
|
result.addTest(AllIndividualFunctionEvaluationTests.suite());
|
||||||
|
|
||||||
result.addTestSuite(TestArea3DPtg.class);
|
result.addTestSuite(TestArea3DPtg.class);
|
||||||
result.addTestSuite(TestAreaErrPtg.class);
|
result.addTestSuite(TestAreaErrPtg.class);
|
||||||
result.addTestSuite(TestAreaPtg.class);
|
result.addTestSuite(TestAreaPtg.class);
|
||||||
|
@ -21,7 +21,7 @@ import junit.framework.Test;
|
|||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects all tests for this package.
|
* Collects all tests for this <tt>org.apache.poi.hssf.record.formula.function</tt>.
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
|
@ -49,14 +49,14 @@ import org.xml.sax.XMLReader;
|
|||||||
import org.xml.sax.helpers.XMLReaderFactory;
|
import org.xml.sax.helpers.XMLReaderFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is not used during normal POI run-time but is used at development time to generate
|
* This class is not used during normal POI run-time but is used at development time to generate
|
||||||
* the file 'functionMetadata.txt'. There are more than 300 built-in functions in Excel and the
|
* the file 'functionMetadata.txt'. There are more than 300 built-in functions in Excel and the
|
||||||
* intention of this class is to make it easier to maintain the metadata, by extracting it from
|
* intention of this class is to make it easier to maintain the metadata, by extracting it from
|
||||||
* a reliable source.
|
* a reliable source.
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
public class ExcelFileFormatDocFunctionExtractor {
|
public final class ExcelFileFormatDocFunctionExtractor {
|
||||||
|
|
||||||
private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt";
|
private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt";
|
||||||
|
|
||||||
@ -195,19 +195,19 @@ public class ExcelFileFormatDocFunctionExtractor {
|
|||||||
"table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref",
|
"table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private final Stack _elemNameStack;
|
private final Stack _elemNameStack;
|
||||||
/** <code>true</code> only when parsing the target tables */
|
/** <code>true</code> only when parsing the target tables */
|
||||||
private boolean _isInsideTable;
|
private boolean _isInsideTable;
|
||||||
|
|
||||||
private final List _rowData;
|
private final List _rowData;
|
||||||
private final StringBuffer _textNodeBuffer;
|
private final StringBuffer _textNodeBuffer;
|
||||||
private final List _rowNoteFlags;
|
private final List _rowNoteFlags;
|
||||||
private boolean _cellHasNote;
|
private boolean _cellHasNote;
|
||||||
|
|
||||||
private final FunctionDataCollector _fdc;
|
private final FunctionDataCollector _fdc;
|
||||||
private String _lastHeadingText;
|
private String _lastHeadingText;
|
||||||
|
|
||||||
public EFFDocHandler(FunctionDataCollector fdc) {
|
public EFFDocHandler(FunctionDataCollector fdc) {
|
||||||
_fdc = fdc;
|
_fdc = fdc;
|
||||||
_elemNameStack = new Stack();
|
_elemNameStack = new Stack();
|
||||||
@ -216,7 +216,7 @@ public class ExcelFileFormatDocFunctionExtractor {
|
|||||||
_textNodeBuffer = new StringBuffer();
|
_textNodeBuffer = new StringBuffer();
|
||||||
_rowNoteFlags = new ArrayList();
|
_rowNoteFlags = new ArrayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean matchesTargetPath() {
|
private boolean matchesTargetPath() {
|
||||||
return matchesPath(0, TABLE_BASE_PATH_NAMES);
|
return matchesPath(0, TABLE_BASE_PATH_NAMES);
|
||||||
}
|
}
|
||||||
@ -365,7 +365,7 @@ public class ExcelFileFormatDocFunctionExtractor {
|
|||||||
xr.setContentHandler(new EFFDocHandler(fdc));
|
xr.setContentHandler(new EFFDocHandler(fdc));
|
||||||
|
|
||||||
InputSource inSrc = new InputSource(is);
|
InputSource inSrc = new InputSource(is);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
xr.parse(inSrc);
|
xr.parse(inSrc);
|
||||||
is.close();
|
is.close();
|
||||||
@ -407,30 +407,30 @@ public class ExcelFileFormatDocFunctionExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void outputLicenseHeader(PrintStream ps) {
|
private static void outputLicenseHeader(PrintStream ps) {
|
||||||
String[] lines= {
|
String[] lines= {
|
||||||
"Licensed to the Apache Software Foundation (ASF) under one or more",
|
"Licensed to the Apache Software Foundation (ASF) under one or more",
|
||||||
"contributor license agreements. See the NOTICE file distributed with",
|
"contributor license agreements. See the NOTICE file distributed with",
|
||||||
"this work for additional information regarding copyright ownership.",
|
"this work for additional information regarding copyright ownership.",
|
||||||
"The ASF licenses this file to You under the Apache License, Version 2.0",
|
"The ASF licenses this file to You under the Apache License, Version 2.0",
|
||||||
"(the \"License\"); you may not use this file except in compliance with",
|
"(the \"License\"); you may not use this file except in compliance with",
|
||||||
"the License. You may obtain a copy of the License at",
|
"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",
|
"Unless required by applicable law or agreed to in writing, software",
|
||||||
"distributed under the License is distributed on an \"AS IS\" BASIS,",
|
"distributed under the License is distributed on an \"AS IS\" BASIS,",
|
||||||
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
|
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
|
||||||
"See the License for the specific language governing permissions and",
|
"See the License for the specific language governing permissions and",
|
||||||
"limitations under the License.",
|
"limitations under the License.",
|
||||||
};
|
};
|
||||||
for (int i = 0; i < lines.length; i++) {
|
for (int i = 0; i < lines.length; i++) {
|
||||||
ps.print("# ");
|
ps.print("# ");
|
||||||
ps.println(lines[i]);
|
ps.println(lines[i]);
|
||||||
}
|
}
|
||||||
ps.println();
|
ps.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helps identify the source file
|
* Helps identify the source file
|
||||||
*/
|
*/
|
||||||
private static String getFileCRC(File f) {
|
private static String getFileCRC(File f) {
|
||||||
@ -451,10 +451,10 @@ public class ExcelFileFormatDocFunctionExtractor {
|
|||||||
}
|
}
|
||||||
return "0x" + Long.toHexString(crc.getValue()).toUpperCase();
|
return "0x" + Long.toHexString(crc.getValue()).toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File getSourceFile() {
|
private static File getSourceFile() {
|
||||||
if (true) {
|
if (false) {
|
||||||
File dir = new File("c:/josh/ref-docs");
|
File dir = new File("c:/temp");
|
||||||
File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
|
File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME);
|
||||||
return effDocFile;
|
return effDocFile;
|
||||||
}
|
}
|
||||||
@ -464,7 +464,7 @@ public class ExcelFileFormatDocFunctionExtractor {
|
|||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
File result;
|
File result;
|
||||||
byte[]buf = new byte[2048];
|
byte[]buf = new byte[2048];
|
||||||
try {
|
try {
|
||||||
@ -488,16 +488,15 @@ public class ExcelFileFormatDocFunctionExtractor {
|
|||||||
System.out.println("file downloaded ok");
|
System.out.println("file downloaded ok");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
File effDocFile = getSourceFile();
|
File effDocFile = getSourceFile();
|
||||||
if(!effDocFile.exists()) {
|
if(!effDocFile.exists()) {
|
||||||
throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
|
throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
File outFile = new File("functionMetadata-asGenerated.txt");
|
File outFile = new File("functionMetadata-asGenerated.txt");
|
||||||
processFile(effDocFile, outFile);
|
processFile(effDocFile, outFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,26 +18,27 @@
|
|||||||
package org.apache.poi.hssf.record.formula.function;
|
package org.apache.poi.hssf.record.formula.function;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
public final class TestFunctionMetadataRegistry extends TestCase {
|
public final class TestFunctionMetadataRegistry extends TestCase {
|
||||||
|
|
||||||
public void testWellKnownFunctions() {
|
public void testWellKnownFunctions() {
|
||||||
confirmFunction(0, "COUNT");
|
confirmFunction(0, "COUNT");
|
||||||
confirmFunction(1, "IF");
|
confirmFunction(1, "IF");
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void confirmFunction(int index, String funcName) {
|
}
|
||||||
FunctionMetadata fm;
|
|
||||||
fm = FunctionMetadataRegistry.getFunctionByIndex(index);
|
private static void confirmFunction(int index, String funcName) {
|
||||||
assertNotNull(fm);
|
FunctionMetadata fm;
|
||||||
assertEquals(funcName, fm.getName());
|
fm = FunctionMetadataRegistry.getFunctionByIndex(index);
|
||||||
|
assertNotNull(fm);
|
||||||
fm = FunctionMetadataRegistry.getFunctionByName(funcName);
|
assertEquals(funcName, fm.getName());
|
||||||
assertNotNull(fm);
|
|
||||||
assertEquals(index, fm.getIndex());
|
fm = FunctionMetadataRegistry.getFunctionByName(funcName);
|
||||||
}
|
assertNotNull(fm);
|
||||||
|
assertEquals(index, fm.getIndex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,8 @@ public final class TestParseMissingBuiltInFuncs extends TestCase {
|
|||||||
}
|
}
|
||||||
AbstractFunctionPtg func = (AbstractFunctionPtg) ptgF;
|
AbstractFunctionPtg func = (AbstractFunctionPtg) ptgF;
|
||||||
if(func.getFunctionIndex() == 255) {
|
if(func.getFunctionIndex() == 255) {
|
||||||
throw new AssertionFailedError("Failed to recognise built-in function in formula '"
|
throw new AssertionFailedError("Failed to recognise built-in function in formula '"
|
||||||
+ formula + "'");
|
+ formula + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(expPtgArraySize, ptgs.length);
|
assertEquals(expPtgArraySize, ptgs.length);
|
||||||
|
@ -48,7 +48,7 @@ public final class TestReadMissingBuiltInFuncs extends TestCase {
|
|||||||
}
|
}
|
||||||
sht = wb.getSheetAt(0);
|
sht = wb.getSheetAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDatedif() {
|
public void testDatedif() {
|
||||||
|
|
||||||
String formula;
|
String formula;
|
||||||
@ -56,9 +56,9 @@ public final class TestReadMissingBuiltInFuncs extends TestCase {
|
|||||||
formula = getCellFormula(0);
|
formula = getCellFormula(0);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
if(e.getMessage().startsWith("Too few arguments")) {
|
if(e.getMessage().startsWith("Too few arguments")) {
|
||||||
if(e.getMessage().indexOf("AttrPtg") > 0) {
|
if(e.getMessage().indexOf("AttrPtg") > 0) {
|
||||||
throw afe("tAttrVolatile not supported in FormulaParser.toFormulaString");
|
throw afe("tAttrVolatile not supported in FormulaParser.toFormulaString");
|
||||||
}
|
}
|
||||||
throw afe("NOW() registered with 1 arg instead of 0");
|
throw afe("NOW() registered with 1 arg instead of 0");
|
||||||
}
|
}
|
||||||
if(e.getMessage().startsWith("too much stuff")) {
|
if(e.getMessage().startsWith("too much stuff")) {
|
||||||
@ -70,7 +70,7 @@ public final class TestReadMissingBuiltInFuncs extends TestCase {
|
|||||||
assertEquals("DATEDIF(NOW(),NOW(),\"d\")", formula);
|
assertEquals("DATEDIF(NOW(),NOW(),\"d\")", formula);
|
||||||
}
|
}
|
||||||
public void testDdb() {
|
public void testDdb() {
|
||||||
|
|
||||||
String formula = getCellFormula(1);
|
String formula = getCellFormula(1);
|
||||||
if("externalflag(1,1,1,1,1)".equals(formula)) {
|
if("externalflag(1,1,1,1,1)".equals(formula)) {
|
||||||
throw afe("DDB() not registered");
|
throw afe("DDB() not registered");
|
||||||
@ -78,14 +78,14 @@ public final class TestReadMissingBuiltInFuncs extends TestCase {
|
|||||||
assertEquals("DDB(1,1,1,1,1)", formula);
|
assertEquals("DDB(1,1,1,1,1)", formula);
|
||||||
}
|
}
|
||||||
public void testAtan() {
|
public void testAtan() {
|
||||||
|
|
||||||
String formula = getCellFormula(2);
|
String formula = getCellFormula(2);
|
||||||
if(formula.equals("ARCTAN(1)")) {
|
if(formula.equals("ARCTAN(1)")) {
|
||||||
throw afe("func ix 18 registered as ARCTAN() instead of ATAN()");
|
throw afe("func ix 18 registered as ARCTAN() instead of ATAN()");
|
||||||
}
|
}
|
||||||
assertEquals("ATAN(1)", formula);
|
assertEquals("ATAN(1)", formula);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUsdollar() {
|
public void testUsdollar() {
|
||||||
|
|
||||||
String formula = getCellFormula(3);
|
String formula = getCellFormula(3);
|
||||||
@ -128,7 +128,7 @@ public final class TestReadMissingBuiltInFuncs extends TestCase {
|
|||||||
}
|
}
|
||||||
assertEquals("ISNONTEXT(\"abc\")", formula);
|
assertEquals("ISNONTEXT(\"abc\")", formula);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCellFormula(int rowIx) {
|
private String getCellFormula(int rowIx) {
|
||||||
String result = sht.getRow(rowIx).getCell((short)0).getCellFormula();
|
String result = sht.getRow(rowIx).getCell((short)0).getCellFormula();
|
||||||
if (false) {
|
if (false) {
|
||||||
|
@ -27,9 +27,8 @@ import junit.framework.TestSuite;
|
|||||||
*/
|
*/
|
||||||
public final class AllIndividualFunctionEvaluationTests {
|
public final class AllIndividualFunctionEvaluationTests {
|
||||||
|
|
||||||
// TODO - have this suite incorporated into a higher level one
|
|
||||||
public static Test suite() {
|
public static Test suite() {
|
||||||
TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.record.formula.functions");
|
TestSuite result = new TestSuite(AllIndividualFunctionEvaluationTests.class.getName());
|
||||||
result.addTestSuite(TestAverage.class);
|
result.addTestSuite(TestAverage.class);
|
||||||
result.addTestSuite(TestCountFuncs.class);
|
result.addTestSuite(TestCountFuncs.class);
|
||||||
result.addTestSuite(TestDate.class);
|
result.addTestSuite(TestDate.class);
|
||||||
|
@ -30,7 +30,7 @@ import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
|
|||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
public final class TestPmt extends TestCase {
|
public final class TestPmt extends TestCase {
|
||||||
|
|
||||||
private static void confirm(double expected, NumberEval ne) {
|
private static void confirm(double expected, NumberEval ne) {
|
||||||
// only asserting accuracy to 4 fractional digits
|
// only asserting accuracy to 4 fractional digits
|
||||||
assertEquals(expected, ne.getNumberValue(), 0.00005);
|
assertEquals(expected, ne.getNumberValue(), 0.00005);
|
||||||
@ -61,12 +61,12 @@ public final class TestPmt extends TestCase {
|
|||||||
confirm(expected, invokeNormal(args));
|
confirm(expected, invokeNormal(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testBasic() {
|
public void testBasic() {
|
||||||
confirm(-1037.0321, (0.08/12), 10, 10000, 0, false);
|
confirm(-1037.0321, (0.08/12), 10, 10000, 0, false);
|
||||||
confirm(-1030.1643, (0.08/12), 10, 10000, 0, true);
|
confirm(-1030.1643, (0.08/12), 10, 10000, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void test3args() {
|
public void test3args() {
|
||||||
|
|
||||||
Eval[] args = {
|
Eval[] args = {
|
||||||
|
Loading…
Reference in New Issue
Block a user