Refactored hierarchy of MultiOperandNumericFunction. Fixed error value handling. Enabled error value check in TestFormulasFromSpreadsheet

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@693990 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-09-10 21:21:28 +00:00
parent 26b4b8b6a7
commit 4f7bef34f6
20 changed files with 401 additions and 1278 deletions

View File

@ -1,23 +1,20 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval; package org.apache.poi.hssf.record.formula.eval;
import java.util.HashMap; import java.util.HashMap;
@ -81,15 +78,15 @@ public abstract class FunctionEval implements OperationEval {
retval[1] = new If(); // IF retval[1] = new If(); // IF
retval[2] = new IsNa(); // ISNA retval[2] = new IsNa(); // ISNA
retval[3] = new IsError(); // ISERROR retval[3] = new IsError(); // ISERROR
retval[4] = new Sum(); // SUM retval[4] = AggregateFunction.SUM;
retval[5] = new Average(); // AVERAGE retval[5] = AggregateFunction.AVERAGE;
retval[6] = new Min(); // MIN retval[6] = AggregateFunction.MIN;
retval[7] = new Max(); // MAX retval[7] = AggregateFunction.MAX;
retval[8] = new Row(); // ROW retval[8] = new Row(); // ROW
retval[9] = new Column(); // COLUMN retval[9] = new Column(); // COLUMN
retval[10] = new Na(); // NA retval[10] = new Na(); // NA
retval[11] = new Npv(); // NPV retval[11] = new Npv(); // NPV
retval[12] = new Stdev(); // STDEV retval[12] = AggregateFunction.STDEV;
retval[13] = NumericFunction.DOLLAR; retval[13] = NumericFunction.DOLLAR;
retval[14] = new Fixed(); // FIXED retval[14] = new Fixed(); // FIXED
retval[15] = NumericFunction.SIN; retval[15] = NumericFunction.SIN;
@ -255,7 +252,7 @@ public abstract class FunctionEval implements OperationEval {
retval[180] = new NotImplementedFunction(); // RESTART retval[180] = new NotImplementedFunction(); // RESTART
retval[181] = new Help(); // HELP retval[181] = new Help(); // HELP
retval[182] = new NotImplementedFunction(); // GETBAR retval[182] = new NotImplementedFunction(); // GETBAR
retval[183] = new Product(); // PRODUCT retval[183] = AggregateFunction.PRODUCT;
retval[184] = NumericFunction.FACT; retval[184] = NumericFunction.FACT;
retval[185] = new NotImplementedFunction(); // GETCELL retval[185] = new NotImplementedFunction(); // GETCELL
retval[186] = new NotImplementedFunction(); // GETWORKSPACE retval[186] = new NotImplementedFunction(); // GETWORKSPACE
@ -291,7 +288,7 @@ public abstract class FunctionEval implements OperationEval {
retval[220] = new Days360(); // DAYS360 retval[220] = new Days360(); // DAYS360
retval[221] = new Today(); // TODAY retval[221] = new Today(); // TODAY
retval[222] = new Vdb(); // VDB retval[222] = new Vdb(); // VDB
retval[227] = new Median(); // MEDIAN retval[227] = AggregateFunction.MEDIAN;
retval[228] = new Sumproduct(); // SUMPRODUCT retval[228] = new Sumproduct(); // SUMPRODUCT
retval[229] = NumericFunction.SINH; retval[229] = NumericFunction.SINH;
retval[230] = NumericFunction.COSH; retval[230] = NumericFunction.COSH;
@ -331,7 +328,7 @@ public abstract class FunctionEval implements OperationEval {
retval[266] = new NotImplementedFunction(); // PRESSTOOL retval[266] = new NotImplementedFunction(); // PRESSTOOL
retval[267] = new NotImplementedFunction(); // REGISTERID retval[267] = new NotImplementedFunction(); // REGISTERID
retval[268] = new NotImplementedFunction(); // GETWORKBOOK retval[268] = new NotImplementedFunction(); // GETWORKBOOK
retval[269] = new Avedev(); // AVEDEV retval[269] = AggregateFunction.AVEDEV;
retval[270] = new Betadist(); // BETADIST retval[270] = new Betadist(); // BETADIST
retval[271] = new Gammaln(); // GAMMALN retval[271] = new Gammaln(); // GAMMALN
retval[272] = new Betainv(); // BETAINV retval[272] = new Betainv(); // BETAINV
@ -380,15 +377,15 @@ public abstract class FunctionEval implements OperationEval {
retval[315] = new Slope(); // SLOPE retval[315] = new Slope(); // SLOPE
retval[316] = new Ttest(); // TTEST retval[316] = new Ttest(); // TTEST
retval[317] = new Prob(); // PROB retval[317] = new Prob(); // PROB
retval[318] = new Devsq(); // DEVSQ retval[318] = AggregateFunction.DEVSQ;
retval[319] = new Geomean(); // GEOMEAN retval[319] = new Geomean(); // GEOMEAN
retval[320] = new Harmean(); // HARMEAN retval[320] = new Harmean(); // HARMEAN
retval[321] = new Sumsq(); // SUMSQ retval[321] = AggregateFunction.SUMSQ;
retval[322] = new Kurt(); // KURT retval[322] = new Kurt(); // KURT
retval[323] = new Skew(); // SKEW retval[323] = new Skew(); // SKEW
retval[324] = new Ztest(); // ZTEST retval[324] = new Ztest(); // ZTEST
retval[325] = new Large(); // LARGE retval[325] = AggregateFunction.LARGE;
retval[326] = new Small(); // SMALL retval[326] = AggregateFunction.SMALL;
retval[327] = new Quartile(); // QUARTILE retval[327] = new Quartile(); // QUARTILE
retval[328] = new Percentile(); // PERCENTILE retval[328] = new Percentile(); // PERCENTILE
retval[329] = new Percentrank(); // PERCENTRANK retval[329] = new Percentrank(); // PERCENTRANK

View File

@ -0,0 +1,120 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
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.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
*
*/
public abstract class AggregateFunction extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected final ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
/* ---------------------------------------------------------------------- */
public static final Function AVEDEV = new AggregateFunction() {
protected double evaluate(double[] values) {
return StatsLib.avedev(values);
}
};
public static final Function AVERAGE = new AggregateFunction() {
protected double evaluate(double[] values) throws EvaluationException {
if (values.length < 1) {
throw new EvaluationException(ErrorEval.DIV_ZERO);
}
return MathX.average(values);
}
};
public static final Function DEVSQ = new AggregateFunction() {
protected double evaluate(double[] values) {
return StatsLib.devsq(values);
}
};
public static final Function LARGE = new AggregateFunction() {
protected double evaluate(double[] ops) throws EvaluationException {
if (ops.length < 2) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
double[] values = new double[ops.length-1];
int k = (int) ops[ops.length-1];
System.arraycopy(ops, 0, values, 0, values.length);
return StatsLib.kthLargest(values, k);
}
};
public static final Function MAX = new AggregateFunction() {
protected double evaluate(double[] values) {
return values.length > 0 ? MathX.max(values) : 0;
}
};
public static final Function MEDIAN = new AggregateFunction() {
protected double evaluate(double[] values) {
return StatsLib.median(values);
}
};
public static final Function MIN = new AggregateFunction() {
protected double evaluate(double[] values) {
return values.length > 0 ? MathX.min(values) : 0;
}
};
public static final Function PRODUCT = new AggregateFunction() {
protected double evaluate(double[] values) {
return MathX.product(values);
}
};
public static final Function SMALL = new AggregateFunction() {
protected double evaluate(double[] ops) throws EvaluationException {
if (ops.length < 2) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
double[] values = new double[ops.length-1];
int k = (int) ops[ops.length-1];
System.arraycopy(ops, 0, values, 0, values.length);
return StatsLib.kthSmallest(values, k);
}
};
public static final Function STDEV = new AggregateFunction() {
protected double evaluate(double[] values) throws EvaluationException {
if (values.length < 1) {
throw new EvaluationException(ErrorEval.DIV_ZERO);
}
return StatsLib.stdev(values);
}
};
public static final Function SUM = new AggregateFunction() {
protected double evaluate(double[] values) {
return MathX.sum(values);
}
};
public static final Function SUMSQ = new AggregateFunction() {
protected double evaluate(double[] values) {
return MathX.sumsq(values);
}
};
}

View File

@ -1,76 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
public class Avedev 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
));
/**
* 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

@ -1,76 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
public class Average 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
));
/**
* 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

@ -1,77 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -1,81 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -1,68 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -1,26 +1,22 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
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; import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
@ -47,20 +43,7 @@ public final class Maxa extends MultiOperandNumericFunction {
return DEFAULT_NUM_XLATOR; return DEFAULT_NUM_XLATOR;
} }
public double evaluate(double[] values) {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) { return values.length > 0 ? MathX.max(values) : 0;
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

@ -1,77 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -1,68 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -1,26 +1,22 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
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; import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
@ -47,20 +43,7 @@ public class Mina extends MultiOperandNumericFunction {
return DEFAULT_NUM_XLATOR; return DEFAULT_NUM_XLATOR;
} }
public double evaluate(double[] values) {
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) { return values.length > 0 ? MathX.min(values) : 0;
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

@ -1,29 +1,24 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
/*
* 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.ErrorEval; 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.EvaluationException;
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; import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/** /**
@ -58,21 +53,12 @@ public class Mode extends MultiOperandNumericFunction {
return DEFAULT_NUM_XLATOR; return DEFAULT_NUM_XLATOR;
} }
protected double evaluate(double[] values) throws EvaluationException {
double d = StatsLib.mode(values);
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) { if (Double.isNaN(d)) {
ValueEval retval = null; // TODO - StatsLib is returning NaN to denote 'no duplicate values'
double[] values = getNumberArray(operands, srcCellRow, srcCellCol); throw new EvaluationException(ErrorEval.NA);
if (values == null) {
retval = ErrorEval.VALUE_INVALID;
} }
else { return d;
double d = StatsLib.mode(values);
retval = (Double.isNaN(d) || Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
} }
} }

View File

@ -1,19 +1,19 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
@ -21,6 +21,8 @@ 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.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; 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.Eval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
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.Ref2DEval; import org.apache.poi.hssf.record.formula.eval.Ref2DEval;
import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.RefEval;
@ -34,203 +36,156 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
* where the order of operands does not matter * where the order of operands does not matter
*/ */
public abstract class MultiOperandNumericFunction implements Function { public abstract class MultiOperandNumericFunction implements Function {
static final double[] EMPTY_DOUBLE_ARRAY = { }; static final double[] EMPTY_DOUBLE_ARRAY = { };
private static class DoubleList { private static class DoubleList {
private double[] _array; private double[] _array;
private int _count; private int _count;
public DoubleList() { public DoubleList() {
_array = new double[8]; _array = new double[8];
_count = 0; _count = 0;
} }
public double[] toArray() { public double[] toArray() {
if(_count < 1) { if(_count < 1) {
return EMPTY_DOUBLE_ARRAY; return EMPTY_DOUBLE_ARRAY;
} }
double[] result = new double[_count]; double[] result = new double[_count];
System.arraycopy(_array, 0, result, 0, _count); System.arraycopy(_array, 0, result, 0, _count);
return result; return result;
} }
public void add(double[] values) { private void ensureCapacity(int reqSize) {
int addLen = values.length; if(reqSize > _array.length) {
ensureCapacity(_count + addLen); int newSize = reqSize * 3 / 2; // grow with 50% extra
System.arraycopy(values, 0, _array, _count, addLen); double[] newArr = new double[newSize];
_count += addLen; System.arraycopy(_array, 0, newArr, 0, _count);
} _array = newArr;
}
}
private void ensureCapacity(int reqSize) { public void add(double value) {
if(reqSize > _array.length) { ensureCapacity(_count + 1);
int newSize = reqSize * 3 / 2; // grow with 50% extra _array[_count] = value;
double[] newArr = new double[newSize]; _count++;
System.arraycopy(_array, 0, newArr, 0, _count); }
_array = newArr; }
}
}
public void add(double value) { private static final int DEFAULT_MAX_NUM_OPERANDS = 30;
ensureCapacity(_count + 1);
_array[_count] = value;
_count++;
}
}
private static final int DEFAULT_MAX_NUM_OPERANDS = 30; protected abstract ValueEvalToNumericXlator getXlator();
protected abstract ValueEvalToNumericXlator getXlator();
/**
* Maximum number of operands accepted by this function.
* Subclasses may override to change default value.
*/
protected int getMaxNumOperands() {
return DEFAULT_MAX_NUM_OPERANDS;
}
/**
* Returns a double array that contains values for the numeric cells
* from among the list of operands. Blanks and Blank equivalent cells
* are ignored. Error operands or cells containing operands of type
* that are considered invalid and would result in #VALUE! error in
* excel cause this function to return <code>null</code>.
*
* @param operands
* @param srcRow
* @param srcCol
*/
protected double[] getNumberArray(Eval[] operands, int srcRow, short srcCol) {
if (operands.length > getMaxNumOperands()) {
return null;
}
DoubleList retval = new DoubleList();
for (int i=0, iSize=operands.length; i<iSize; i++) {
double[] temp = getNumberArray(operands[i], srcRow, srcCol);
if (temp == null) {
return null; // error occurred.
}
retval.add(temp);
}
return retval.toArray();
}
/**
* Same as getNumberArray(Eval[], int, short) except that this
* takes Eval instead of Eval[].
* @param operand
* @param srcRow
* @param srcCol
*/
protected double[] getNumberArray(Eval operand, int srcRow, short srcCol) {
if (operand instanceof AreaEval) {
AreaEval ae = (AreaEval) operand;
DoubleList retval = new DoubleList();
int width = ae.getWidth();
int height = ae.getHeight();
for (int rrIx=0; rrIx<height; rrIx++) {
for (int rcIx=0; rcIx<width; rcIx++) {
ValueEval ve1 = ae.getRelativeValue(rrIx, rcIx);
/*
* TODO: For an AreaEval, we are constructing a RefEval
* per element.
* For now this is a tempfix solution since this may
* require a more generic fix at the level of
* HSSFFormulaEvaluator where we store an array
* of RefEvals as the "values" array.
*/
RefEval re = new Ref2DEval(null, ve1);
ValueEval ve = singleOperandEvaluate(re, srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval nve = (NumericValueEval) ve;
retval.add(nve.getNumberValue());
}
else if (ve instanceof BlankEval) {
// note - blanks are ignored, so returned array will be smaller.
}
else {
return null; // indicate to calling subclass that error occurred
}
}
}
return retval.toArray();
}
// for ValueEvals other than AreaEval
ValueEval ve = singleOperandEvaluate(operand, srcRow, srcCol);
if (ve instanceof NumericValueEval) {
NumericValueEval nve = (NumericValueEval) ve;
return new double[] { nve.getNumberValue(), };
}
if (ve instanceof BlankEval) {
// ignore blanks
return EMPTY_DOUBLE_ARRAY;
}
return null;
}
/**
* Ensures that a two dimensional array has all sub-arrays present and the same length
* @return <code>false</code> if any sub-array is missing, or is of different length
*/
protected static final boolean areSubArraysConsistent(double[][] values) {
if (values == null || values.length < 1) {
// TODO this doesn't seem right. Fix or add comment.
return true;
}
if (values[0] == null) {
return false;
}
int outerMax = values.length;
int innerMax = values[0].length;
for (int i=1; i<outerMax; i++) { // note - 'i=1' start at second sub-array
double[] subArr = values[i];
if (subArr == null) {
return false;
}
if (innerMax != subArr.length) {
return false;
}
}
return true;
}
protected final ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) { public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
if (eval instanceof AreaEval) { double d;
AreaEval ae = (AreaEval) eval; try {
if (ae.contains(srcRow, srcCol)) { // circular ref! double[] values = getNumberArray(args);
return ErrorEval.CIRCULAR_REF_ERROR; d = evaluate(values);
} } catch (EvaluationException e) {
if (ae.isRow()) { return e.getErrorEval();
if (ae.isColumn()) { }
return ae.getRelativeValue(0, 0);
}
if (ae.containsColumn(srcCol)) {
ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCol);
ve = getXlator().attemptXlateToNumeric(ve);
return getXlator().attemptXlateToNumeric(ve);
}
return ErrorEval.VALUE_INVALID;
}
if (ae.isColumn()) {
if (ae.containsRow(srcRow)) {
ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn());
return getXlator().attemptXlateToNumeric(ve);
}
return ErrorEval.VALUE_INVALID;
}
return ErrorEval.VALUE_INVALID;
}
return getXlator().attemptXlateToNumeric((ValueEval) eval);
}
if (Double.isNaN(d) || Double.isInfinite(d))
return ErrorEval.NUM_ERROR;
return new NumberEval(d);
}
protected abstract double evaluate(double[] values) throws EvaluationException;
/**
* Maximum number of operands accepted by this function.
* Subclasses may override to change default value.
*/
protected int getMaxNumOperands() {
return DEFAULT_MAX_NUM_OPERANDS;
}
/**
* Returns a double array that contains values for the numeric cells
* from among the list of operands. Blanks and Blank equivalent cells
* are ignored. Error operands or cells containing operands of type
* that are considered invalid and would result in #VALUE! error in
* excel cause this function to return <code>null</code>.
*
* @return never <code>null</code>
*/
protected final double[] getNumberArray(Eval[] operands) throws EvaluationException {
if (operands.length > getMaxNumOperands()) {
throw EvaluationException.invalidValue();
}
DoubleList retval = new DoubleList();
for (int i=0, iSize=operands.length; i<iSize; i++) {
collectValues(operands[i], retval);
}
return retval.toArray();
}
/**
* Collects values from a single argument
*/
private void collectValues(Eval operand, DoubleList temp) throws EvaluationException {
if (operand instanceof AreaEval) {
AreaEval ae = (AreaEval) operand;
int width = ae.getWidth();
int height = ae.getHeight();
for (int rrIx=0; rrIx<height; rrIx++) {
for (int rcIx=0; rcIx<width; rcIx++) {
ValueEval ve1 = ae.getRelativeValue(rrIx, rcIx);
/*
* TODO: For an AreaEval, we are constructing a RefEval
* per element.
* For now this is a tempfix solution since this may
* require a more generic fix at the level of
* HSSFFormulaEvaluator where we store an array
* of RefEvals as the "values" array.
*/
RefEval re = new Ref2DEval(null, ve1);
ValueEval ve = attemptXlateToNumeric(re);
if (ve instanceof ErrorEval) {
throw new EvaluationException((ErrorEval)ve);
}
if (ve instanceof BlankEval) {
// note - blanks are ignored, so returned array will be smaller.
continue;
}
if (ve instanceof NumericValueEval) {
NumericValueEval nve = (NumericValueEval) ve;
temp.add(nve.getNumberValue());
} else {
throw new RuntimeException("Unexpected value class (" + ve.getClass().getName() + ")");
}
}
}
return;
}
// for ValueEvals other than AreaEval
ValueEval ve = attemptXlateToNumeric((ValueEval) operand);
if (ve instanceof NumericValueEval) {
NumericValueEval nve = (NumericValueEval) ve;
temp.add(nve.getNumberValue());
return;
}
if (ve instanceof BlankEval) {
// ignore blanks
return;
}
if (ve instanceof ErrorEval) {
throw new EvaluationException((ErrorEval)ve);
}
throw new RuntimeException("Unexpected value class (" + ve.getClass().getName() + ")");
}
protected ValueEval attemptXlateToNumeric(ValueEval ve) {
return getXlator().attemptXlateToNumeric(ve);
}
} }

View File

@ -1,68 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -1,81 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -1,76 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
public class Stdev 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
));
/**
* 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

@ -1,68 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -1,70 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 15, 2005
*
*/
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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
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

@ -112,15 +112,6 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
throw new AssertionFailedError(msg + " - actual value was null"); throw new AssertionFailedError(msg + " - actual value was null");
} }
if (expected.getCellType() == HSSFCell.CELL_TYPE_STRING) {
String value = expected.getRichStringCellValue().getString();
if (value.startsWith("#")) {
// TODO - this code never called
expected.setCellType(HSSFCell.CELL_TYPE_ERROR);
// expected.setCellErrorValue(...?);
}
}
switch (expected.getCellType()) { switch (expected.getCellType()) {
case HSSFCell.CELL_TYPE_BLANK: case HSSFCell.CELL_TYPE_BLANK:
assertEquals(msg, HSSFCell.CELL_TYPE_BLANK, actual.getCellType()); assertEquals(msg, HSSFCell.CELL_TYPE_BLANK, actual.getCellType());
@ -131,18 +122,13 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
break; break;
case HSSFCell.CELL_TYPE_ERROR: case HSSFCell.CELL_TYPE_ERROR:
assertEquals(msg, HSSFCell.CELL_TYPE_ERROR, actual.getCellType()); assertEquals(msg, HSSFCell.CELL_TYPE_ERROR, actual.getCellType());
if(false) { // TODO: fix ~45 functions which are currently returning incorrect error values assertEquals(msg, ErrorEval.getText(expected.getErrorCellValue()), ErrorEval.getText(actual.getErrorValue()));
assertEquals(msg, expected.getErrorCellValue(), actual.getErrorValue());
}
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: " + msg); 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());
TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR); TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
// double delta = Math.abs(expected.getNumericCellValue()-actual.getNumberValue());
// 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());
@ -152,7 +138,7 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
} }
protected void setUp() throws Exception { protected void setUp() {
if (workbook == null) { if (workbook == null) {
workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME); workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
sheet = workbook.getSheetAt( 0 ); sheet = workbook.getSheetAt( 0 );

View File

@ -32,9 +32,8 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
*/ */
public final class TestAverage extends TestCase { public final class TestAverage extends TestCase {
private static Eval invokeAverage(Eval[] args) { private static Eval invokeAverage(Eval[] args) {
return new Average().evaluate(args, -1, (short)-1); return AggregateFunction.AVERAGE.evaluate(args, -1, (short)-1);
} }
private void confirmAverage(Eval[] args, double expected) { private void confirmAverage(Eval[] args, double expected) {