New formula eval stuff - added functions and refactored, by Amol

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353714 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Avik Sengupta 2005-06-09 18:34:57 +00:00
parent ab9e2a94d6
commit 0ac5c6ef94
83 changed files with 2091 additions and 1185 deletions

View File

@ -676,8 +676,8 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
functionData[209][0]=new Byte(Ptg.CLASS_VALUE);functionData[209][1]=new byte[] {Ptg.CLASS_VALUE};functionData[209][2]=new Integer(2); functionData[209][0]=new Byte(Ptg.CLASS_VALUE);functionData[209][1]=new byte[] {Ptg.CLASS_VALUE};functionData[209][2]=new Integer(2);
functionData[210][0]=new Byte(Ptg.CLASS_VALUE);functionData[210][1]=new byte[] {Ptg.CLASS_VALUE};functionData[210][2]=new Integer(2); functionData[210][0]=new Byte(Ptg.CLASS_VALUE);functionData[210][1]=new byte[] {Ptg.CLASS_VALUE};functionData[210][2]=new Integer(2);
functionData[211][0]=new Byte(Ptg.CLASS_VALUE);functionData[211][1]=new byte[] {Ptg.CLASS_VALUE};functionData[211][2]=new Integer(1); functionData[211][0]=new Byte(Ptg.CLASS_VALUE);functionData[211][1]=new byte[] {Ptg.CLASS_VALUE};functionData[211][2]=new Integer(1);
functionData[212][0]=new Byte(Ptg.CLASS_VALUE);functionData[212][1]=new byte[] {Ptg.CLASS_VALUE};functionData[212][2]=new Integer(1); functionData[212][0]=new Byte(Ptg.CLASS_VALUE);functionData[212][1]=new byte[] {Ptg.CLASS_VALUE};functionData[212][2]=new Integer(2);
functionData[213][0]=new Byte(Ptg.CLASS_VALUE);functionData[213][1]=new byte[] {Ptg.CLASS_REF};functionData[213][2]=new Integer(-1); functionData[213][0]=new Byte(Ptg.CLASS_VALUE);functionData[213][1]=new byte[] {Ptg.CLASS_REF};functionData[213][2]=new Integer(2);
functionData[214][0]=new Byte(Ptg.CLASS_VALUE);functionData[214][1]=new byte[] {Ptg.CLASS_VALUE};functionData[214][2]=new Integer(-1); functionData[214][0]=new Byte(Ptg.CLASS_VALUE);functionData[214][1]=new byte[] {Ptg.CLASS_VALUE};functionData[214][2]=new Integer(-1);

View File

@ -31,6 +31,7 @@ public class AddEval extends NumericOperationEval {
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED | ValueEvalToNumericXlator.STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
)); ));
public AddEval(Ptg ptg) { public AddEval(Ptg ptg) {

View File

@ -22,6 +22,7 @@ public class DivideEval extends NumericOperationEval {
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED | ValueEvalToNumericXlator.STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
)); ));
public DivideEval(Ptg ptg) { public DivideEval(Ptg ptg) {

View File

@ -7,576 +7,15 @@ package org.apache.poi.hssf.record.formula.eval;
/** /**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com > * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
* *
* Error code reference from OpenOffice documentation: <br/><TABLE WIDTH=575
* BORDER=1 CELLPADDING=2 CELLSPACING=0 BGCOLOR="#ffffff"> <COL WIDTH=42> <COL
* WIDTH=118> <COL WIDTH=401>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="tablehead" ALIGN=LEFT>
* Error Code
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="tablehead" ALIGN=LEFT>
* Message
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="tablehead" ALIGN=LEFT>
* Explanation
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 501
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Invalid character
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Character in a formula is not valid, for example, &quot;=1Eq&quot; instead of
* &quot;=1E2&quot;.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 502
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Invalid argument
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Function argument is not valid, for example, a negative number for the root
* function.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 503
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Invalid floating point operation
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Division by 0, or another calculation that results in an overflow of the
* defined value range.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 504
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Parameter list error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Function parameter is not valid, for example, text instead of a number, or a
* domain reference instead of cell reference.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 505
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal syntax error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Not used
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 506
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Invalid semicolon
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Not used
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 507
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Error: Pair missing
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Not used
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 508
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Error: Pair missing
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Missing bracket, for example, closing brackets, but no opening brackets
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 509
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Missing operator
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Operator is missing, for example, &quot;=2(3+4) * &quot;, where the operator
* between &quot;2&quot; and &quot;(&quot; is missing.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 510
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Missing variable
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Variable is missing, for example when two operators are together
* &quot;=1+*2&quot;.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 511
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Missing variable
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Function requires more variables than are provided, for example, AND() and
* OR().
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 512
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Formula overflow
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* <B>Compiler: </B> the total number of internal tokens, (that is, operators,
* variables, brackets) in the formula exceeds 512. <B>Interpreter: </B> the
* total number of matrices that the formula creates exceeds 150. This includes
* basic functions that receive too large an array as a parameter (max. 0xFFFE,
* for example, 65534 bytes).
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 513
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* String overflow
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* <B>Compiler: </B> an identifier in the formula exceeds 64 KB in size.
* <B>Interpreter: </B> a result of a string operation exceeds 64 KB in size.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 514
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal overflow
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Sort operation attempted on too much numerical data (max. 100000) or a
* calculation stack overflow.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 515
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal syntax error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Not used
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 516
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal syntax error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Matrix is expected on the calculation stack, but is not available.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 517
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal syntax error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Unknown code, for example, a document with a newer function is loaded in an
* older version that does not contain the function.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 518
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal syntax error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Variable is not available
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 519
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* No result (#VALUE is in the cell rather than Err:519!)
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Formula yields a value that does not corresponds to the definition, or a cell
* that is referenced in the formula contains text instead of a number.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 520
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal syntax error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Compiler creates an unknown compiler code.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 521
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal syntax error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* No result.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 522
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Circular reference
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Formula refers directly or indirectly to itself and the iterations option is
* not selected under Tools - Options - Table Document - Calculate.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 523
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* The calculation procedure does not converge
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Financial statistics function missed a targeted value or iterations of
* circular references do not reach the minimum change within the maximum steps
* that are set.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 524
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* <A NAME="kw66944_5"> </A><A NAME="kw66944_4"> </A> invalid references
* (instead of Err:524 cell contains #REF)
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* <B>Compiler: </B> a column or row description name could not be resolved.
* <B>Interpreter: </B> in a formula, the column, row, or sheet that contains a
* referenced cell is missing.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 525
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* <A NAME="kw66944_3"> </A><A NAME="kw66944_2"> </A> invalid names (instead of
* Err:525 cell contains #NAME?)
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* An identifier could not be evaluated, for example, no valid reference, no
* valid domain name, no column/row label, no macro, incorrect decimal divider,
* add-in not found.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 526
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal syntax error
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Obsolete, no longer used, but could come from old documents if the result is
* a formula from a domain.
* </P>
* </TD>
* </TR>
* <TR VALIGN=TOP>
* <TD WIDTH=42 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* 527
* </P>
* </TD>
* <TD WIDTH=118 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* Internal overflow
* </P>
* </TD>
* <TD WIDTH=401 BGCOLOR="#ffffff">
* <P CLASS="textintable" ALIGN=LEFT>
* <B>Interpreter: </B>References, such as when a cell references a cell, are
* too encapsulated.
* </P>
* </TD>
* </TR>
* </TABLE>
*
*/ */
public class ErrorEval implements ValueEval { public class ErrorEval implements ValueEval {
private int errorCode; private int errorCode;
// Oo std error codes
public static final ErrorEval ERROR_501 = new ErrorEval(501);
public static final ErrorEval ERROR_502 = new ErrorEval(502); public static final ErrorEval NAME_INVALID = new ErrorEval(525);
public static final ErrorEval ERROR_503 = new ErrorEval(503); public static final ErrorEval VALUE_INVALID = new ErrorEval(519);
public static final ErrorEval ERROR_504 = new ErrorEval(504);
public static final ErrorEval ERROR_505 = new ErrorEval(505);
public static final ErrorEval ERROR_506 = new ErrorEval(506);
public static final ErrorEval ERROR_507 = new ErrorEval(507);
public static final ErrorEval ERROR_508 = new ErrorEval(508);
public static final ErrorEval ERROR_509 = new ErrorEval(509);
public static final ErrorEval ERROR_510 = new ErrorEval(510);
public static final ErrorEval ERROR_511 = new ErrorEval(511);
public static final ErrorEval ERROR_512 = new ErrorEval(512);
public static final ErrorEval ERROR_513 = new ErrorEval(513);
public static final ErrorEval ERROR_514 = new ErrorEval(514);
public static final ErrorEval ERROR_515 = new ErrorEval(515);
public static final ErrorEval ERROR_516 = new ErrorEval(516);
public static final ErrorEval ERROR_517 = new ErrorEval(517);
public static final ErrorEval ERROR_518 = new ErrorEval(518);
public static final ErrorEval ERROR_519 = new ErrorEval(519);
public static final ErrorEval ERROR_520 = new ErrorEval(520);
public static final ErrorEval ERROR_521 = new ErrorEval(521);
public static final ErrorEval ERROR_522 = new ErrorEval(522);
public static final ErrorEval ERROR_523 = new ErrorEval(523);
public static final ErrorEval ERROR_524 = new ErrorEval(524);
public static final ErrorEval ERROR_525 = new ErrorEval(525);
public static final ErrorEval ERROR_526 = new ErrorEval(526);
public static final ErrorEval ERROR_527 = new ErrorEval(527);
public static final ErrorEval NAME_INVALID = ERROR_525;
public static final ErrorEval VALUE_INVALID = ERROR_519;
// Non std error codes // Non std error codes

View File

@ -22,6 +22,7 @@ public class MultiplyEval extends NumericOperationEval {
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED | ValueEvalToNumericXlator.STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
)); ));
public MultiplyEval(Ptg ptg) { public MultiplyEval(Ptg ptg) {

View File

@ -13,6 +13,8 @@ import org.apache.poi.hssf.record.formula.Ptg;
* *
*/ */
public class NumberEval implements NumericValueEval, StringValueEval { public class NumberEval implements NumericValueEval, StringValueEval {
public static final NumberEval ZERO = new NumberEval(0);
private double value; private double value;
private String stringValue; private String stringValue;

View File

@ -22,6 +22,7 @@ public class PowerEval extends NumericOperationEval {
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED | ValueEvalToNumericXlator.STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
)); ));
public PowerEval(Ptg ptg) { public PowerEval(Ptg ptg) {

View File

@ -38,7 +38,7 @@ public abstract class RelationalOperationEval implements OperationEval {
switch (operands.length) { switch (operands.length) {
default: default:
retval.ee = ErrorEval.ERROR_520; retval.ee = ErrorEval.VALUE_INVALID;
break; break;
case 2: case 2:
internalDoEvaluate(operands, srcRow, srcCol, retval, 0); internalDoEvaluate(operands, srcRow, srcCol, retval, 0);

View File

@ -13,6 +13,8 @@ import org.apache.poi.hssf.record.formula.StringPtg;
*/ */
public class StringEval implements StringValueEval { public class StringEval implements StringValueEval {
public static final StringEval EMPTY_INSTANCE = new StringEval("");
private String value; private String value;
public StringEval(Ptg ptg) { public StringEval(Ptg ptg) {

View File

@ -22,6 +22,7 @@ public class SubtractEval extends NumericOperationEval {
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED | ValueEvalToNumericXlator.STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
)); ));
public SubtractEval(Ptg ptg) { public SubtractEval(Ptg ptg) {

View File

@ -21,6 +21,7 @@ public class UnaryMinusEval extends NumericOperationEval {
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED | ValueEvalToNumericXlator.STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
)); ));

View File

@ -18,7 +18,7 @@ public class UnaryPlusEval implements OperationEval /*extends NumericOperationEv
/* /*
* COMMENT FOR COMMENTED CODE IN THIS FILE * COMMENT FOR COMMENTED CODE IN THIS FILE
* *
* The loser who programmed this in excel didnt care to * In excel the programmer seems to not have cared to
* think about how strings were handled in other numeric * think about how strings were handled in other numeric
* operations when he/she was implementing this operation :P * operations when he/she was implementing this operation :P
* *
@ -27,10 +27,8 @@ public class UnaryPlusEval implements OperationEval /*extends NumericOperationEv
* Q. If the formula -"hello" evaluates to #VALUE! in excel, what should * Q. If the formula -"hello" evaluates to #VALUE! in excel, what should
* the formula +"hello" evaluate to? * the formula +"hello" evaluate to?
* *
* A. +"hello" evaluates to "hello" * A. +"hello" evaluates to "hello" (what the...?)
* *
* DO NOT remove the commented code (In memory of the excel
* programmer who implemented the UnaryPlus operation :)
*/ */

View File

@ -10,25 +10,33 @@ package org.apache.poi.hssf.record.formula.eval;
*/ */
public class ValueEvalToNumericXlator { public class ValueEvalToNumericXlator {
public static final short STRING_IS_PARSED = 0x0001; public static final int STRING_IS_PARSED = 0x0001;
public static final short BOOL_IS_PARSED = 0x0002; public static final int BOOL_IS_PARSED = 0x0002;
public static final int BLANK_IS_PARSED = 0x0004; // => blanks are not ignored, converted to 0
public static final short REF_STRING_IS_PARSED = 0x0004; public static final int REF_STRING_IS_PARSED = 0x0008;
public static final short REF_BOOL_IS_PARSED = 0x0008; public static final int REF_BOOL_IS_PARSED = 0x0010;
public static final int REF_BLANK_IS_PARSED = 0x0020;
public static final short EVALUATED_REF_STRING_IS_PARSED = 0x0010; public static final int EVALUATED_REF_STRING_IS_PARSED = 0x0040;
public static final short EVALUATED_REF_BOOL_IS_PARSED = 0x0020; public static final int EVALUATED_REF_BOOL_IS_PARSED = 0x0080;
public static final int EVALUATED_REF_BLANK_IS_PARSED = 0x0100;
public static final short STRING_TO_BOOL_IS_PARSED = 0x0040; public static final int STRING_TO_BOOL_IS_PARSED = 0x0200;
public static final short REF_STRING_TO_BOOL_IS_PARSED = 0x0080; public static final int REF_STRING_TO_BOOL_IS_PARSED = 0x0400;
public static final short STRING_IS_INVALID_VALUE = 0x0100; public static final int STRING_IS_INVALID_VALUE = 0x0800;
public static final short REF_STRING_IS_INVALID_VALUE = 0x200; public static final int REF_STRING_IS_INVALID_VALUE = 0x1000;
private final short flags; // public static final int BOOL_IS_BLANK = 0x2000;
// public static final int REF_BOOL_IS_BLANK = 0x4000;
// public static final int STRING_IS_BLANK = 0x8000;
// public static final int REF_STRING_IS_BLANK = 0x10000;
private final int flags;
public ValueEvalToNumericXlator(short flags) { public ValueEvalToNumericXlator(int flags) {
this.flags = flags; this.flags = flags;
} }
@ -52,23 +60,20 @@ public class ValueEvalToNumericXlator {
} }
// booleval // booleval
else if (((flags | BOOL_IS_PARSED) > 0) && eval instanceof BoolEval) { else if (eval instanceof BoolEval) {
retval = (NumericValueEval) eval; retval = ((flags & BOOL_IS_PARSED) > 0)
? (NumericValueEval) eval
: xlateBlankEval(BLANK_IS_PARSED);
} }
// stringeval // stringeval
else if (eval instanceof StringEval) { else if (eval instanceof StringEval) {
retval = handleStringEval((StringEval) eval); retval = xlateStringEval((StringEval) eval); // TODO: recursive call needed
} }
// refeval // refeval
else if (eval instanceof RefEval) { else if (eval instanceof RefEval) {
retval = handleRefEval((RefEval) eval); retval = xlateRefEval((RefEval) eval);
}
//blankeval
else if (eval instanceof BlankEval) {
retval = eval;
} }
// erroreval // erroreval
@ -76,40 +81,55 @@ public class ValueEvalToNumericXlator {
retval = eval; retval = eval;
} }
else if (eval instanceof BlankEval) {
retval = xlateBlankEval(BLANK_IS_PARSED);
}
// probably AreaEval? then not acceptable. // probably AreaEval? then not acceptable.
else { else {
throw new RuntimeException("Invalid ValueEval type passed for conversion: " + eval.getClass()); throw new RuntimeException("Invalid ValueEval type passed for conversion: " + eval.getClass());
} }
return retval; return retval;
} }
/**
* no args are required since BlankEval has only one
* instance. If flag is set, a zero
* valued numbereval is returned, else BlankEval.INSTANCE
* is returned.
* @return
*/
private ValueEval xlateBlankEval(int flag) {
return ((flags & flag) > 0)
? (ValueEval) NumberEval.ZERO
: BlankEval.INSTANCE;
}
/** /**
* uses the relevant flags to decode the supplied RefVal * uses the relevant flags to decode the supplied RefVal
* @param eval * @param eval
* @return * @return
*/ */
private ValueEval handleRefEval(RefEval reval) { private ValueEval xlateRefEval(RefEval reval) {
ValueEval retval = null; ValueEval retval = null;
ValueEval eval = (ValueEval) reval.getInnerValueEval(); ValueEval eval = (ValueEval) reval.getInnerValueEval();
// most common case - least worries :) // most common case - least worries :)
if (eval instanceof NumberEval) { if (eval instanceof NumberEval) {
retval = (NumberEval) eval; // the cast is correct :) retval = (NumberEval) eval;
} }
// booleval // booleval
else if (((flags | REF_BOOL_IS_PARSED) > 0) && eval instanceof BoolEval) { else if (eval instanceof BoolEval) {
retval = (NumericValueEval) eval; retval = ((flags & REF_BOOL_IS_PARSED) > 0)
? (ValueEval) eval
: BlankEval.INSTANCE;
} }
// stringeval // stringeval
else if (eval instanceof StringEval) { else if (eval instanceof StringEval) {
retval = handleRefStringEval((StringEval) eval); retval = xlateRefStringEval((StringEval) eval);
}
//blankeval
else if (eval instanceof BlankEval) {
retval = eval;
} }
// erroreval // erroreval
@ -117,10 +137,24 @@ public class ValueEvalToNumericXlator {
retval = eval; retval = eval;
} }
// probably AreaEval or another RefEval? then not acceptable. // refeval
else { else if (eval instanceof RefEval) {
RefEval re = (RefEval) eval;
retval = xlateRefEval(re);
}
else if (eval instanceof BlankEval) {
retval = xlateBlankEval(reval.isEvaluated() ? EVALUATED_REF_BLANK_IS_PARSED : REF_BLANK_IS_PARSED);
}
// probably AreaEval ? then not acceptable.
else {
throw new RuntimeException("Invalid ValueEval type passed for conversion: " + eval.getClass()); throw new RuntimeException("Invalid ValueEval type passed for conversion: " + eval.getClass());
} }
return retval; return retval;
} }
@ -129,20 +163,29 @@ public class ValueEvalToNumericXlator {
* @param eval * @param eval
* @return * @return
*/ */
private ValueEval handleStringEval(StringEval eval) { private ValueEval xlateStringEval(StringEval eval) {
ValueEval retval = null; ValueEval retval = null;
if ((flags | STRING_IS_PARSED) > 0) { if ((flags & STRING_IS_PARSED) > 0) {
StringEval sve = (StringEval) eval; String s = eval.getStringValue();
String s = sve.getStringValue();
try { try {
double d = Double.parseDouble(s); double d = Double.parseDouble(s);
retval = new NumberEval(d); retval = new NumberEval(d);
} }
catch (Exception e) { retval = ErrorEval.VALUE_INVALID; } catch (Exception e) {
if ((flags & STRING_TO_BOOL_IS_PARSED) > 0) {
try {
boolean b = Boolean.getBoolean(s);
retval = b ? BoolEval.TRUE : BoolEval.FALSE;
}
catch (Exception e2) { retval = ErrorEval.VALUE_INVALID; }
}
else {
retval = ErrorEval.VALUE_INVALID;
}
}
} }
else if ((flags | STRING_TO_BOOL_IS_PARSED) > 0) { else if ((flags & STRING_TO_BOOL_IS_PARSED) > 0) {
StringEval sve = (StringEval) eval; String s = eval.getStringValue();
String s = sve.getStringValue();
try { try {
boolean b = Boolean.getBoolean(s); boolean b = Boolean.getBoolean(s);
retval = b ? BoolEval.TRUE : BoolEval.FALSE; retval = b ? BoolEval.TRUE : BoolEval.FALSE;
@ -151,13 +194,13 @@ public class ValueEvalToNumericXlator {
} }
// strings are errors? // strings are errors?
else if ((flags | STRING_IS_INVALID_VALUE) > 0) { else if ((flags & STRING_IS_INVALID_VALUE) > 0) {
retval = ErrorEval.VALUE_INVALID; retval = ErrorEval.VALUE_INVALID;
} }
// ignore strings // ignore strings
else { else {
retval = BlankEval.INSTANCE; retval = xlateBlankEval(BLANK_IS_PARSED);
} }
return retval; return retval;
} }
@ -167,18 +210,29 @@ public class ValueEvalToNumericXlator {
* @param eval * @param eval
* @return * @return
*/ */
private ValueEval handleRefStringEval(StringEval eval) { private ValueEval xlateRefStringEval(StringEval eval) {
ValueEval retval = null; ValueEval retval = null;
if ((flags | REF_STRING_IS_PARSED) > 0) { if ((flags & REF_STRING_IS_PARSED) > 0) {
StringEval sve = (StringEval) eval; StringEval sve = (StringEval) eval;
String s = sve.getStringValue(); String s = sve.getStringValue();
try { try {
double d = Double.parseDouble(s); double d = Double.parseDouble(s);
retval = new NumberEval(d); retval = new NumberEval(d);
} }
catch (Exception e) { retval = ErrorEval.VALUE_INVALID; } catch (Exception e) {
if ((flags & REF_STRING_TO_BOOL_IS_PARSED) > 0) {
try {
boolean b = Boolean.getBoolean(s);
retval = b ? BoolEval.TRUE : BoolEval.FALSE;
}
catch (Exception e2) { retval = ErrorEval.VALUE_INVALID; }
}
else {
retval = ErrorEval.VALUE_INVALID;
}
}
} }
else if ((flags | REF_STRING_TO_BOOL_IS_PARSED) > 0) { else if ((flags & REF_STRING_TO_BOOL_IS_PARSED) > 0) {
StringEval sve = (StringEval) eval; StringEval sve = (StringEval) eval;
String s = sve.getStringValue(); String s = sve.getStringValue();
try { try {
@ -189,11 +243,11 @@ public class ValueEvalToNumericXlator {
} }
// strings are errors? // strings are errors?
else if ((flags | REF_STRING_IS_INVALID_VALUE) > 0) { else if ((flags & REF_STRING_IS_INVALID_VALUE) > 0) {
retval = ErrorEval.VALUE_INVALID; retval = ErrorEval.VALUE_INVALID;
} }
// ignore strings // strings are blanks
else { else {
retval = BlankEval.INSTANCE; retval = BlankEval.INSTANCE;
} }

View File

@ -10,7 +10,6 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@ -18,19 +17,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
*/ */
public class Abs extends NumericFunction { public class Abs extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
@ -54,7 +40,10 @@ public class Abs extends NumericFunction {
} }
if (retval == null) { if (retval == null) {
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(Math.abs(d)); d = Math.abs(d);
retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.VALUE_INVALID
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Acos extends NumericFunction { public class Acos extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,10 +38,12 @@ public class Acos extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.acos(d); d = Math.acos(d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -9,38 +9,25 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* Support for hyperbolic trig functions was added as a part of * Support for hyperbolic trig functions was added as a part of
* Java distribution only in JDK1.5. This class uses custom * Java distribution only in JDK1.5. This class uses custom
* naive implementation based on formulas at: * naive implementation based on formulas at:
* http://www.math2.org/math/trig/hyperbolics.htm * http://www.math2.org/math/trig/hyperbolics.htm
* These formulas seem to agree with excel's implementation. * These formulas seem to agree with excel's implementation.
* *
*/ */
public class Acosh extends NumericFunction { public class Acosh extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -49,10 +36,12 @@ public class Acosh extends NumericFunction {
d = ne.getNumberValue(); d = ne.getNumberValue();
} }
} }
if (retval == null) { if (retval == null) {
d = Math.log(Math.sqrt(Math.pow(d, 2) - 1) + d); d = MathX.acosh(d);
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.NUM_ERROR : new NumberEval(d); retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Asin extends NumericFunction { public class Asin extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,10 +38,12 @@ public class Asin extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.asin(d); d = Math.asin(d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -10,38 +10,26 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* Support for hyperbolic trig functions was added as a part of * Support for hyperbolic trig functions was added as a part of
* Java distribution only in JDK1.5. This class uses custom * Java distribution only in JDK1.5. This class uses custom
* naive implementation based on formulas at: * naive implementation based on formulas at:
* http://www.math2.org/math/trig/hyperbolics.htm * http://www.math2.org/math/trig/hyperbolics.htm
* These formulas seem to agree with excel's implementation. * These formulas seem to agree with excel's implementation.
* *
*/ */
public class Asinh extends NumericFunction { public class Asinh extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -56,9 +44,9 @@ public class Asinh extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.log(Math.sqrt(Math.pow(d, 2) + 1) + d); d = MathX.asinh(d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.NUM_ERROR : new NumberEval(d); retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.NUM_ERROR : new NumberEval(d);
} }
return retval; return retval;

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Atan extends NumericFunction { public class Atan extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,10 +38,12 @@ public class Atan extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.atan(d); d = Math.atan(d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -10,34 +10,21 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Atan2 extends NumericFunction { public class Atan2 extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0; double d0 = 0;
double d1 = 0; double d1 = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 2: case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,7 +38,7 @@ public class Atan2 extends NumericFunction {
else { else {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
if (retval == null) { if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcRow, srcCol); ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) { if (ve instanceof NumericValueEval) {
@ -66,10 +53,14 @@ public class Atan2 extends NumericFunction {
} }
} }
} }
if (retval == null) { if (retval == null) {
double d = (d0 == d1 && d1 == 0) ? Double.NaN : Math.atan2(d1, d0); double d = (d0 == d1 && d1 == 0)
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); ? Double.NaN
: Math.atan2(d1, d0);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -10,38 +10,25 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* Support for hyperbolic trig functions was added as a part of * Support for hyperbolic trig functions was added as a part of
* Java distribution only in JDK1.5. This class uses custom * Java distribution only in JDK1.5. This class uses custom
* naive implementation based on formulas at: * naive implementation based on formulas at:
* http://www.math2.org/math/trig/hyperbolics.htm * http://www.math2.org/math/trig/hyperbolics.htm
* These formulas seem to agree with excel's implementation. * These formulas seem to agree with excel's implementation.
* *
*/ */
public class Atanh extends NumericFunction { public class Atanh extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -56,9 +43,9 @@ public class Atanh extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.log((1 + d)/(1 - d)) / 2; d = MathX.atanh(d);
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.NUM_ERROR : new NumberEval(d); retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.NUM_ERROR : new NumberEval(d);
} }
return retval; return retval;

View File

@ -4,10 +4,58 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Avedev extends DefaultFunctionImpl { public class Avedev extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
// ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = StatsLib.avedev(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,58 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Average extends DefaultFunctionImpl { public class Average extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
// ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = MathX.average(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,10 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Averagea extends DefaultFunctionImpl { public class Averagea extends DefaultFunctionImpl {
} }

View File

@ -1,14 +1,66 @@
/* /*
* Created on May 6, 2005 * Created on May 15, 2005
* *
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Ceiling extends DefaultFunctionImpl { public class Ceiling extends NumericFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0;
double d1 = 0;
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d0 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d1 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
}
if (retval == null) {
double d = MathX.ceiling(d0, d1);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,50 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author
* *
*/ */
public class Column extends DefaultFunctionImpl { public class Column extends DefaultFunctionImpl {
public Eval evaluate(Eval[] evals, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
int cnum = -1;
switch (evals.length) {
default:
retval = ErrorEval.VALUE_INVALID;
case 1:
if (evals[0] instanceof AreaEval) {
AreaEval ae = (AreaEval) evals[0];
cnum = ae.getFirstColumn();
}
else if (evals[0] instanceof RefEval) {
RefEval re = (RefEval) evals[0];
cnum = re.getColumn();
}
else { // anything else is not valid argument
retval = ErrorEval.VALUE_INVALID;
}
break;
case 0:
cnum = srcCellCol;
}
if (retval == null) {
retval = (cnum >= 0)
? new NumberEval(cnum + 1) // +1 since excel colnums are 1 based
: (ValueEval) ErrorEval.VALUE_INVALID;
}
return retval;
}
} }

View File

@ -4,10 +4,68 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Combin extends DefaultFunctionImpl { public class Combin extends NumericFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0;
double d1 = 0;
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d0 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d1 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
}
if (retval == null) {
if (d0 > Integer.MAX_VALUE || d1 > Integer.MAX_VALUE) {
retval = ErrorEval.NUM_ERROR;
}
else {
double d = MathX.nChooseK((int) d0, (int) d1);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
}
return retval;
}
} }

View File

@ -4,10 +4,41 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Concatenate extends DefaultFunctionImpl { public class Concatenate extends TextFunction {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
StringBuffer sb = new StringBuffer();
for (int i=0, iSize=operands.length; i<iSize; i++) {
ValueEval ve = singleOperandEvaluate(operands[i], srcCellRow, srcCellCol);
if (ve instanceof StringValueEval) {
StringValueEval sve = (StringValueEval) ve;
sb.append(sve.getStringValue());
}
else if (ve instanceof BlankEval) {}
else {
retval = ErrorEval.VALUE_INVALID;
break;
}
}
if (retval == null) {
retval = new StringEval(sb.toString());
}
return retval;
}
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Cos extends NumericFunction { public class Cos extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,7 +38,7 @@ public class Cos extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.cos(d); d = Math.cos(d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Cosh extends NumericFunction { public class Cosh extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,11 +38,9 @@ public class Cosh extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
double ePowX = Math.pow(E, d); d = MathX.cosh(d);
double ePowNegX = Math.pow(E, -d);
d = (ePowX + ePowNegX) / 2;
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);
} }
return retval; return retval;

View File

@ -10,7 +10,6 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@ -18,19 +17,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
*/ */
public class Degrees extends NumericFunction { public class Degrees extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;

View File

@ -4,10 +4,58 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Devsq extends DefaultFunctionImpl { public class Devsq extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
| ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = StatsLib.devsq(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Dollar extends NumericFunction { public class Dollar extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,7 +38,7 @@ public class Dollar extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);
} }

View File

@ -10,26 +10,12 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Even extends NumericFunction { public class Even extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;

View File

@ -4,10 +4,65 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Exact extends DefaultFunctionImpl { public class Exact extends TextFunction {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
String s0 = null;
String s1 = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
if (ve instanceof StringValueEval) {
StringValueEval sve = (StringValueEval) ve;
s0 = sve.getStringValue();
}
else if (ve instanceof BlankEval) {
s0 = StringEval.EMPTY_INSTANCE.getStringValue();
}
else {
retval = ErrorEval.VALUE_INVALID;
break;
}
if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
if (ve instanceof StringValueEval) {
StringValueEval sve = (StringValueEval) ve;
s1 = sve.getStringValue();
}
else if (ve instanceof BlankEval) {
s1 = StringEval.EMPTY_INSTANCE.getStringValue();
}
else {
retval = ErrorEval.VALUE_INVALID;
break;
}
}
}
if (retval == null) {
boolean b = s0.equals(s1);
retval = b ? BoolEval.TRUE : BoolEval.FALSE;
}
return retval;
}
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Exp extends NumericFunction { public class Exp extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,7 +38,7 @@ public class Exp extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.pow(E, d); d = Math.pow(E, d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);

View File

@ -1,13 +1,58 @@
/* /*
* Created on May 15, 2005 * Created on May 22, 2005
* *
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Fact extends DefaultFunctionImpl { public class Fact extends NumericFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0;
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
if (retval == null) {
if (d < Integer.MAX_VALUE && d >= 0) {
d = MathX.factorial((int) d);
retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.VALUE_INVALID
: (Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
return retval;
}
} }

View File

@ -4,10 +4,63 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Floor extends DefaultFunctionImpl { public class Floor extends NumericFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0;
double d1 = 0;
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d0 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d1 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
}
if (retval == null) {
double d = MathX.floor(d0, d1);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Int extends NumericFunction { public class Int extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,12 +38,14 @@ public class Int extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
if (d < 0) { if (d < 0) {
d = Math.round(d-0.5); d = Math.round(d-0.5);
} }
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval((long) d); retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval((long) d);
} }
return retval; return retval;
} }

View File

@ -4,10 +4,77 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class IsError extends DefaultFunctionImpl { public class IsError implements Function {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
boolean b = false;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 1:
if (operands[0] instanceof ErrorEval) {
b = true;
}
else if (operands[0] instanceof AreaEval) {
AreaEval ae = (AreaEval) operands[0];
if (ae.contains(srcCellRow, srcCellCol)) { // circular ref!
retval = ErrorEval.CIRCULAR_REF_ERROR;
}
else if (ae.isRow()) {
if (ae.containsColumn(srcCellCol)) {
ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCellCol);
if (ve instanceof RefEval)
b = ((RefEval) ve).getInnerValueEval() instanceof ErrorEval;
else
b = (ve instanceof ErrorEval);
}
else {
b = true;
}
}
else if (ae.isColumn()) {
if (ae.containsRow(srcCellRow)) {
ValueEval ve = ae.getValueAt(srcCellRow, ae.getFirstColumn());
if (ve instanceof RefEval)
b = ((RefEval) ve).getInnerValueEval() instanceof ErrorEval;
else
b = (ve instanceof ErrorEval);
}
else {
b = true;
}
}
else {
b = true;
}
}
else if (operands[0] instanceof RefEval) {
b = ((RefEval) operands[0]).getInnerValueEval() instanceof ErrorEval;
}
else {
b = false;
}
}
if (retval == null) {
retval = b
? BoolEval.TRUE
: BoolEval.FALSE;
}
return retval;
}
} }

View File

@ -4,10 +4,73 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Isblank extends DefaultFunctionImpl { public class Isblank implements Function {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
boolean b = false;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 1:
if (operands[0] instanceof BlankEval) {
b = true;
}
else if (operands[0] instanceof AreaEval) {
AreaEval ae = (AreaEval) operands[0];
if (ae.contains(srcCellRow, srcCellCol)) { // circular ref!
retval = ErrorEval.CIRCULAR_REF_ERROR;
}
else if (ae.isRow()) {
if (ae.containsColumn(srcCellCol)) {
ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCellCol);
b = (ve instanceof BlankEval);
}
else {
b = false;
}
}
else if (ae.isColumn()) {
if (ae.containsRow(srcCellRow)) {
ValueEval ve = ae.getValueAt(srcCellRow, ae.getFirstColumn());
b = (ve instanceof BlankEval);
}
else {
b = false;
}
}
else {
b = false;
}
}
else if (operands[0] instanceof RefEval) {
RefEval re = (RefEval) operands[0];
b = (!re.isEvaluated()) && re.getInnerValueEval() instanceof BlankEval;
}
else {
b = false;
}
}
if (retval == null) {
retval = b
? BoolEval.TRUE
: BoolEval.FALSE;
}
return retval;
}
} }

View File

@ -4,10 +4,62 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Large extends DefaultFunctionImpl { public class Large extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
| ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] ops = getNumberArray(operands, srcCellRow, srcCellCol);
if (ops == null || ops.length < 2) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double[] values = new double[ops.length-1];
int k = (int) ops[ops.length-1];
System.arraycopy(ops, 0, values, 0, values.length);
double d = StatsLib.kthLargest(values, k);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,120 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Len extends DefaultFunctionImpl { public class Len extends TextFunction {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
String s = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
if (ve instanceof StringValueEval) {
StringValueEval sve = (StringValueEval) ve;
s = sve.getStringValue();
}
else if (ve instanceof RefEval) {
RefEval re = (RefEval) ve;
ValueEval ive = re.getInnerValueEval();
if (ive instanceof BlankEval) {
s = re.isEvaluated() ? "0" : null;
}
else if (ive instanceof StringValueEval) {
s = ((StringValueEval) ive).getStringValue();
}
else if (ive instanceof BlankEval) {}
else {
retval = ErrorEval.VALUE_INVALID;
}
}
else if (ve instanceof BlankEval) {}
else {
retval = ErrorEval.VALUE_INVALID;
break;
}
}
if (retval == null) {
s = (s == null) ? EMPTY_STRING : s;
retval = new NumberEval(s.length());
}
return retval;
}
protected ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) {
ValueEval retval;
if (eval instanceof AreaEval) {
AreaEval ae = (AreaEval) eval;
if (ae.contains(srcRow, srcCol)) { // circular ref!
retval = ErrorEval.CIRCULAR_REF_ERROR;
}
else if (ae.isRow()) {
if (ae.containsColumn(srcCol)) {
ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCol);
retval = attemptXlateToText(ve);
}
else {
retval = ErrorEval.VALUE_INVALID;
}
}
else if (ae.isColumn()) {
if (ae.containsRow(srcRow)) {
ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn());
retval = attemptXlateToText(ve);
}
else {
retval = ErrorEval.VALUE_INVALID;
}
}
else {
retval = ErrorEval.VALUE_INVALID;
}
}
else {
retval = attemptXlateToText((ValueEval) eval);
}
return retval;
}
/**
* converts from Different ValueEval types to StringEval.
* Note: AreaEvals are not handled, if arg is an AreaEval,
* the returned value is ErrorEval.VALUE_INVALID
* @param ve
* @return
*/
protected ValueEval attemptXlateToText(ValueEval ve) {
ValueEval retval;
if (ve instanceof StringValueEval || ve instanceof RefEval) {
retval = ve;
}
else if (ve instanceof BlankEval) {
retval = ve;
}
else {
retval = ErrorEval.VALUE_INVALID;
}
return retval;
}
} }

View File

@ -14,29 +14,17 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Ln extends NumericFunction { public class Ln extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,7 +39,7 @@ public class Ln extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.log(d); d = Math.log(d);
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);

View File

@ -17,32 +17,20 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
* Log: LOG(number,[base]) * Log: LOG(number,[base])
*/ */
public class Log extends NumericFunction { public class Log extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
private static final double DEFAULT_BASE = 10;
protected ValueEvalToNumericXlator getXlator() { private static final double DEFAULT_BASE = 10;
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
double base = DEFAULT_BASE; double base = DEFAULT_BASE;
double num = 0; double num = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 2: // second arg is base case 2: // second arg is base
ValueEval ve = singleOperandEvaluate(operands[1], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) { if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve; NumericValueEval ne = (NumericValueEval) ve;
@ -54,7 +42,7 @@ public class Log extends NumericFunction {
else { else {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
case 1: // first arg is number case 1: // first arg is number
if (retval == null) { if (retval == null) {
ValueEval vev = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval vev = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -70,9 +58,9 @@ public class Log extends NumericFunction {
} }
} }
} }
if (retval == null) { if (retval == null) {
d = (base == E) d = (base == E)
? Math.log(num) ? Math.log(num)
: Math.log(num) / Math.log(base); : Math.log(num) / Math.log(base);
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);

View File

@ -10,35 +10,21 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Log10 extends NumericFunction { public class Log10 extends NumericFunction {
private static final double LOG_10_TO_BASE_e = Math.log(10); private static final double LOG_10_TO_BASE_e = Math.log(10);
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -53,10 +39,12 @@ public class Log10 extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.log(d) / LOG_10_TO_BASE_e; d = Math.log(d) / LOG_10_TO_BASE_e;
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -4,10 +4,46 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Lower extends DefaultFunctionImpl { public class Lower extends TextFunction {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
String s = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
if (ve instanceof StringValueEval) {
StringValueEval sve = (StringValueEval) ve;
s = sve.getStringValue();
}
else if (ve instanceof BlankEval) {}
else {
retval = ErrorEval.VALUE_INVALID;
break;
}
}
if (retval == null) {
s = (s == null) ? EMPTY_STRING : s;
retval = new StringEval(s.toLowerCase());
}
return retval;
}
} }

View File

@ -4,10 +4,49 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Max extends DefaultFunctionImpl { public class Max extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = values.length > 0 ? MathX.max(values) : 0;
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,51 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Maxa extends DefaultFunctionImpl { public class Maxa extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
| ValueEvalToNumericXlator.BLANK_IS_PARSED
| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = values.length > 0 ? MathX.max(values) : 0;
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,58 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Median extends DefaultFunctionImpl { public class Median extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
| ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = StatsLib.median(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,49 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Min extends DefaultFunctionImpl { public class Min extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = values.length > 0 ? MathX.min(values) : 0;
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,51 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Mina extends DefaultFunctionImpl { public class Mina extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
| ValueEvalToNumericXlator.BLANK_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = values.length > 0 ? MathX.min(values) : 0;
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,68 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Mod extends DefaultFunctionImpl { public class Mod extends NumericFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0;
double d1 = 0;
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d0 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d1 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
}
if (retval == null) {
if (d1 == 0) {
retval = ErrorEval.DIV_ZERO;
}
else {
double d = MathX.mod(d0, d1);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
}
return retval;
}
} }

View File

@ -4,10 +4,59 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Mode extends DefaultFunctionImpl { public class Mode extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
//| ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = StatsLib.mode(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -18,8 +18,32 @@ public abstract class NumericFunction implements Function {
protected static final double E = Math.E; protected static final double E = Math.E;
protected static final double PI = Math.PI; protected static final double PI = Math.PI;
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
));
private static final int DEFAULT_MAX_NUM_OPERANDS = 30;
protected abstract ValueEvalToNumericXlator getXlator(); /**
* this is the default impl of the factory(ish) method getXlator.
* Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
protected ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) { protected ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) {
ValueEval retval; ValueEval retval;

View File

@ -10,7 +10,6 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@ -18,19 +17,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
*/ */
public class Odd extends NumericFunction { public class Odd extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;

View File

@ -10,27 +10,13 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Power extends NumericFunction { public class Power extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0; double d0 = 0;
double d1 = 0; double d1 = 0;

View File

@ -4,10 +4,49 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Product extends DefaultFunctionImpl { public class Product extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = MathX.product(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -10,7 +10,6 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@ -18,19 +17,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
*/ */
public class Radians extends NumericFunction { public class Radians extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;

View File

@ -4,10 +4,68 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author
* *
*/ */
public class Round extends DefaultFunctionImpl { public class Round extends NumericFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0;
double d1 = 0;
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d0 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d1 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
}
if (retval == null) {
double d;
if (d0 > Integer.MAX_VALUE) {
d = (Double.isNaN(d0) || Double.isInfinite(d0))
? Double.NaN
: 0;
}
else {
d = MathX.round(d0, (int) d1);
}
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,68 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author
* *
*/ */
public class Rounddown extends DefaultFunctionImpl { public class Rounddown extends NumericFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0;
double d1 = 0;
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d0 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d1 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
}
if (retval == null) {
double d;
if (d0 > Integer.MAX_VALUE) {
d = (Double.isInfinite(d0))
? Double.NaN
: 0;
}
else {
d = MathX.roundDown(d0, (int) d1);
}
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,70 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author
* *
*/ */
public class Roundup extends DefaultFunctionImpl { public class Roundup extends NumericFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d0 = 0;
double d1 = 0;
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d0 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
if (retval == null) {
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
d1 = ne.getNumberValue();
}
else if (ve instanceof BlankEval) {
// do nothing
}
else {
retval = ErrorEval.NUM_ERROR;
}
}
}
if (retval == null) {
double d;
if (d0 > Integer.MAX_VALUE) {
d = (Double.isNaN(d0))
? Double.NaN
: 0;
}
else {
d = MathX.roundUp(d0, (int) d1);
}
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,50 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author
* *
*/ */
public class Row extends DefaultFunctionImpl { public class Row implements Function {
public Eval evaluate(Eval[] evals, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
int rnum = -1;
switch (evals.length) {
default:
retval = ErrorEval.VALUE_INVALID;
case 1:
if (evals[0] instanceof AreaEval) {
AreaEval ae = (AreaEval) evals[0];
rnum = ae.getFirstRow();
}
else if (evals[0] instanceof RefEval) {
RefEval re = (RefEval) evals[0];
rnum = re.getRow();
}
else { // anything else is not valid argument
retval = ErrorEval.VALUE_INVALID;
}
break;
case 0:
rnum = srcCellRow;
}
if (retval == null) {
retval = (rnum >= 0)
? new NumberEval(rnum + 1) // +1 since excel rownums are 1 based
: (ValueEval) ErrorEval.VALUE_INVALID;
}
return retval;
}
} }

View File

@ -10,7 +10,6 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author
@ -18,19 +17,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
*/ */
public class Sign extends NumericFunction { public class Sign extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
@ -56,11 +42,7 @@ public class Sign extends NumericFunction {
if (retval == null) { if (retval == null) {
retval = (Double.isNaN(d) || Double.isInfinite(d)) retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.VALUE_INVALID ? (ValueEval) ErrorEval.VALUE_INVALID
: (d == 0) : new NumberEval(MathX.sign(d));
? new NumberEval(0)
: (d < 0)
? new NumberEval(-1)
: new NumberEval(1);
} }
return retval; return retval;
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sin extends NumericFunction { public class Sin extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,10 +38,12 @@ public class Sin extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.sin(d); d = Math.sin(d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sinh extends NumericFunction { public class Sinh extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,12 +38,12 @@ public class Sinh extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
double ePowX = Math.pow(E, d); d = MathX.sinh(d);
double ePowNegX = Math.pow(E, -d); retval = (Double.isNaN(d) || Double.isInfinite(d))
d = (ePowX - ePowNegX) / 2; ? (ValueEval) ErrorEval.NUM_ERROR
retval = (Double.isNaN(d) || Double.isInfinite(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); : new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -4,10 +4,62 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Small extends DefaultFunctionImpl { public class Small extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
| ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] ops = getNumberArray(operands, srcCellRow, srcCellCol);
if (ops == null || ops.length < 2) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double[] values = new double[ops.length-1];
int k = (int) ops[ops.length-1];
System.arraycopy(ops, 0, values, 0, values.length);
double d = StatsLib.kthSmallest(values, k);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sqrt extends NumericFunction { public class Sqrt extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,10 +38,12 @@ public class Sqrt extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.sqrt(d); d = Math.sqrt(d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -4,10 +4,58 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Stdev extends DefaultFunctionImpl { public class Stdev extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
// ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = StatsLib.stdev(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,49 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sum extends DefaultFunctionImpl { public class Sum extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = values.length > 0 ? MathX.sum(values) : 0;
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,10 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sumproduct extends DefaultFunctionImpl { public class Sumproduct extends DefaultFunctionImpl {
} }

View File

@ -4,10 +4,51 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sumsq extends DefaultFunctionImpl { public class Sumsq extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
// ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
| ValueEvalToNumericXlator.BLANK_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[] values = getNumberArray(operands, srcCellRow, srcCellCol);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
}
else {
double d = MathX.sumsq(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,44 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sumx2my2 extends DefaultFunctionImpl { public class Sumx2my2 extends XYNumericFunction {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[][] values = null;
int checkLen = 0; // check to see that all array lengths are equal
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
values = getValues(operands, srcCellRow, srcCellCol);
if (values==null
|| values[X] == null || values[Y] == null
|| values[X].length == 0 || values[Y].length == 0
|| values[X].length != values[Y].length) {
retval = ErrorEval.VALUE_INVALID;
}
}
if (retval == null) {
double d = MathX.sumx2my2(values[X], values[Y]);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,44 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sumx2py2 extends DefaultFunctionImpl { public class Sumx2py2 extends XYNumericFunction {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[][] values = null;
int checkLen = 0; // check to see that all array lengths are equal
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
values = getValues(operands, srcCellRow, srcCellCol);
if (values==null
|| values[X] == null || values[Y] == null
|| values[X].length == 0 || values[Y].length == 0
|| values[X].length != values[Y].length) {
retval = ErrorEval.VALUE_INVALID;
}
}
if (retval == null) {
double d = MathX.sumx2py2(values[X], values[Y]);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,44 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Sumxmy2 extends DefaultFunctionImpl { public class Sumxmy2 extends XYNumericFunction {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
double[][] values = null;
int checkLen = 0; // check to see that all array lengths are equal
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 2:
values = getValues(operands, srcCellRow, srcCellCol);
if (values==null
|| values[X] == null || values[Y] == null
|| values[X].length == 0 || values[Y].length == 0
|| values[X].length != values[Y].length) {
retval = ErrorEval.VALUE_INVALID;
}
}
if (retval == null) {
double d = MathX.sumxmy2(values[X], values[Y]);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
} }

View File

@ -4,10 +4,34 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author
* *
*/ */
public class T extends DefaultFunctionImpl { public class T implements Function {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 1:
if (operands[0] instanceof StringEval
|| operands[0] instanceof ErrorEval) {
retval = (ValueEval) operands[0];
}
else if (operands[0] instanceof ErrorEval) {
retval = StringEval.EMPTY_INSTANCE;
}
}
return retval;
}
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Tan extends NumericFunction { public class Tan extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,10 +38,12 @@ public class Tan extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
d = Math.tan(d); d = Math.tan(d);
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.VALUE_INVALID
: new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -10,33 +10,20 @@ import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Tanh extends NumericFunction { public class Tanh extends NumericFunction {
private static final ValueEvalToNumericXlator NUM_XLATOR =
new ValueEvalToNumericXlator((short)
( ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return NUM_XLATOR;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double d = 0; double d = 0;
ValueEval retval = null; ValueEval retval = null;
switch (operands.length) { switch (operands.length) {
default: default:
retval = ErrorEval.VALUE_INVALID;
break; break;
case 1: case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
@ -51,12 +38,12 @@ public class Tanh extends NumericFunction {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;
} }
} }
if (retval == null) { if (retval == null) {
double ePowX = Math.pow(E, d); d = MathX.tanh(d);
double ePowNegX = Math.pow(E, -d); retval = (Double.isNaN(d) || Double.isInfinite(d))
d = (ePowX - ePowNegX) / (ePowX + ePowNegX); ? (ValueEval) ErrorEval.NUM_ERROR
retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); : new NumberEval(d);
} }
return retval; return retval;
} }

View File

@ -4,10 +4,46 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/** /**
* @author * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class Upper extends DefaultFunctionImpl { public class Upper extends TextFunction {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
ValueEval retval = null;
String s = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 1:
ValueEval ve = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
if (ve instanceof StringValueEval) {
StringValueEval sve = (StringValueEval) ve;
s = sve.getStringValue();
}
else if (ve instanceof BlankEval) {}
else {
retval = ErrorEval.VALUE_INVALID;
break;
}
}
if (retval == null) {
s = (s == null) ? EMPTY_STRING : s;
retval = new StringEval(s.toUpperCase());
}
return retval;
}
} }

View File

@ -280,7 +280,6 @@ public class HSSFFormulaEvaluator {
protected static ValueEval internalEvaluate(HSSFCell srcCell, HSSFRow srcRow, HSSFSheet sheet, HSSFWorkbook workbook) { protected static ValueEval internalEvaluate(HSSFCell srcCell, HSSFRow srcRow, HSSFSheet sheet, HSSFWorkbook workbook) {
int srcRowNum = srcRow.getRowNum(); int srcRowNum = srcRow.getRowNum();
short srcColNum = srcCell.getCellNum(); short srcColNum = srcCell.getCellNum();
FormulaParser parser = new FormulaParser(srcCell.getCellFormula(), workbook.getWorkbook()); FormulaParser parser = new FormulaParser(srcCell.getCellFormula(), workbook.getWorkbook());
parser.parse(); parser.parse();
Ptg[] ptgs = parser.getRPNPtg(); Ptg[] ptgs = parser.getRPNPtg();
@ -314,9 +313,6 @@ public class HSSFFormulaEvaluator {
// storing the ops in reverse order since they are popping // storing the ops in reverse order since they are popping
for (int j = numops - 1; j >= 0; j--) { for (int j = numops - 1; j >= 0; j--) {
Eval p = (Eval) stack.pop(); Eval p = (Eval) stack.pop();
if (p instanceof ErrorEval) { // fast fail
return (ErrorEval) p;
}
ops[j] = p; ops[j] = p;
} }
Eval opresult = operation.evaluate(ops, srcRowNum, srcColNum); Eval opresult = operation.evaluate(ops, srcRowNum, srcColNum);
@ -482,7 +478,7 @@ public class HSSFFormulaEvaluator {
retval = new StringEval(cell.getStringCellValue()); retval = new StringEval(cell.getStringCellValue());
break; break;
case HSSFCell.CELL_TYPE_FORMULA: case HSSFCell.CELL_TYPE_FORMULA:
retval = (ValueEval) internalEvaluate(cell, row, sheet, workbook); retval = internalEvaluate(cell, row, sheet, workbook);
break; break;
case HSSFCell.CELL_TYPE_BOOLEAN: case HSSFCell.CELL_TYPE_BOOLEAN:
retval = cell.getBooleanCellValue() ? BoolEval.TRUE : BoolEval.FALSE; retval = cell.getBooleanCellValue() ? BoolEval.TRUE : BoolEval.FALSE;

View File

@ -4,12 +4,12 @@
*/ */
package org.apache.poi.hssf.record.formula.eval; package org.apache.poi.hssf.record.formula.eval;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.record.formula.functions.TestMathX;
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFRow;
@ -77,12 +77,13 @@ public class GenericFormulaTestCase extends TestCase {
assertEquals(msg, HSSFCell.CELL_TYPE_ERROR, actual.getCellType()); // TODO: check if exact error matches assertEquals(msg, HSSFCell.CELL_TYPE_ERROR, actual.getCellType()); // TODO: check if exact error matches
break; break;
case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
throw new AssertionFailedError("Cannot expect formula as result of formula evaluation"); throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
case HSSFCell.CELL_TYPE_NUMERIC: case HSSFCell.CELL_TYPE_NUMERIC:
assertEquals(msg, HSSFCell.CELL_TYPE_NUMERIC, actual.getCellType()); assertEquals(msg, HSSFCell.CELL_TYPE_NUMERIC, actual.getCellType());
double delta = Math.abs(expected.getNumericCellValue()-actual.getNumberValue()); TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
double pctExpected = Math.abs(0.00001*expected.getNumericCellValue()); // double delta = Math.abs(expected.getNumericCellValue()-actual.getNumberValue());
assertTrue(msg, delta <= pctExpected); // double pctExpected = Math.abs(0.00001*expected.getNumericCellValue());
// assertTrue(msg, delta <= pctExpected);
break; break;
case HSSFCell.CELL_TYPE_STRING: case HSSFCell.CELL_TYPE_STRING:
assertEquals(msg, HSSFCell.CELL_TYPE_STRING, actual.getCellType()); assertEquals(msg, HSSFCell.CELL_TYPE_STRING, actual.getCellType());
@ -113,18 +114,20 @@ public class GenericFormulaTestCase extends TestCase {
HSSFCell c = null; HSSFCell c = null;
for (short colnum=getBeginCol(); colnum < endcolnum; colnum++) { for (short colnum=getBeginCol(); colnum < endcolnum; colnum++) {
try {
c = r.getCell(colnum); c = r.getCell(colnum);
if (c==null || c.getCellType() == HSSFCell.CELL_TYPE_BLANK) if (c==null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA)
continue; continue;
assertEquals("Sanity check input cell type ", HSSFCell.CELL_TYPE_FORMULA, c.getCellType());
HSSFFormulaEvaluator.CellValue actualValue = evaluator.evaluate(c); HSSFFormulaEvaluator.CellValue actualValue = evaluator.evaluate(c);
HSSFCell expectedValueCell = getExpectedValueCell(s, r, c); HSSFCell expectedValueCell = getExpectedValueCell(s, r, c);
assertEquals("Formula: " + c.getCellFormula() assertEquals("Formula: " + c.getCellFormula()
+ " @ " + getBeginRow() + ":" + colnum, + " @ " + getBeginRow() + ":" + colnum,
expectedValueCell, actualValue); expectedValueCell, actualValue);
} catch (RuntimeException re) {
throw new RuntimeException("CELL["+getBeginRow()+","+colnum+"]: "+re.getMessage(), re);
}
} }
} }

View File

@ -21,6 +21,7 @@ public class TestEverything extends TestSuite {
s = "D"+Integer.toString(i).trim(); s = "D"+Integer.toString(i).trim();
suite.addTest(new GenericFormulaTestCase(s)); suite.addTest(new GenericFormulaTestCase(s));
} }
// suite.addTest(new GenericFormulaTestCase("D1164"));
return suite; return suite;
} }
} }