retval[359] = new Hyperlink(); // HYPERLINK
retval[360] = new NotImplementedFunction(); // PHONETIC
retval[361] = new Averagea(); // AVERAGEA
- retval[362] = new Maxa(); // MAXA
- retval[363] = new Mina(); // MINA
+ retval[362] = MinaMaxa.MAXA;
+ retval[363] = MinaMaxa.MINA;
retval[364] = new Stdevpa(); // STDEVPA
retval[365] = new Varpa(); // VARPA
retval[366] = new Stdeva(); // STDEVA
+++ /dev/null
-/*
-* 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.eval;
-
-import org.apache.poi.hssf.record.formula.RefPtg;
-
-/**
- * @author adeshmukh
- *
- */
-public final class Ref2DEval implements RefEval {
-
- private final ValueEval value;
- private final RefPtg delegate;
-
- public Ref2DEval(RefPtg ptg, ValueEval ve) {
- if(ve == null) {
- throw new IllegalArgumentException("ve must not be null");
- }
- if(false && ptg == null) { // TODO - fix dodgy code in MultiOperandNumericFunction
- throw new IllegalArgumentException("ptg must not be null");
- }
- value = ve;
- delegate = ptg;
- }
- public ValueEval getInnerValueEval() {
- return value;
- }
- public int getRow() {
- return delegate.getRow();
- }
- public int getColumn() {
- return delegate.getColumn();
- }
- public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
- throw new RuntimeException("should not be called"); // TODO - delete this whole class
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.eval;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public final class ValueEvalToNumericXlator {
-
- public static final int BLANK_IS_PARSED = 0x0001; // => blanks are not ignored, converted to 0
-
- public static final int REF_BOOL_IS_PARSED = 0x0002;
-
- private final int flags;
-
-
- public ValueEvalToNumericXlator(int flags) {
-
- if (false) { // uncomment to see who is using this class
- System.err.println(new Throwable().getStackTrace()[1].getClassName() + "\t0x"
- + Integer.toHexString(flags).toUpperCase());
- }
- this.flags = flags;
- }
-
- /**
- * returned value can be either A NumericValueEval, BlankEval or ErrorEval.
- * The params can be either NumberEval, BoolEval, StringEval, or
- * RefEval
- * @param eval
- */
- public ValueEval attemptXlateToNumeric(ValueEval eval) {
-
- if (eval == null) {
- throw new IllegalArgumentException("eval must not be null");
- }
-
- // most common case - least worries :)
- if (eval instanceof NumberEval) {
- return eval;
- }
-
- if (eval instanceof BoolEval) {
- return eval;
- }
-
- if (eval instanceof StringEval) {
- return xlateStringEval((StringEval) eval);
- }
-
- if (eval instanceof RefEval) {
- return xlateRefEval((RefEval) eval);
- }
-
- if (eval instanceof ErrorEval) {
- return eval;
- }
-
- if (eval instanceof BlankEval) {
- return xlateBlankEval();
- }
-
- // probably AreaEval? then not acceptable.
- throw new RuntimeException("Invalid ValueEval type passed for conversion: " + eval.getClass());
- }
-
- /**
- * 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.
- */
- private ValueEval xlateBlankEval() {
- return ((flags & BLANK_IS_PARSED) > 0)
- ? (ValueEval) NumberEval.ZERO
- : BlankEval.INSTANCE;
- }
-
- /**
- * uses the relevant flags to decode the supplied RefVal
- * @param eval
- */
- private ValueEval xlateRefEval(RefEval reval) {
- ValueEval eval = reval.getInnerValueEval();
-
- // most common case - least worries :)
- if (eval instanceof NumberEval) {
- return eval;
- }
-
- if (eval instanceof BoolEval) {
- return ((flags & REF_BOOL_IS_PARSED) > 0)
- ? (ValueEval) eval
- : BlankEval.INSTANCE;
- }
-
- if (eval instanceof StringEval) {
- // all ref strings are blanks
- return BlankEval.INSTANCE;
- }
-
- if (eval instanceof ErrorEval) {
- return eval;
- }
-
- if (eval instanceof BlankEval) {
- return xlateBlankEval();
- }
-
- throw new RuntimeException("Invalid ValueEval type passed for conversion: ("
- + eval.getClass().getName() + ")");
- }
-
- /**
- * uses the relevant flags to decode the StringEval
- * @param eval
- */
- private static ValueEval xlateStringEval(StringEval eval) {
-
- String s = eval.getStringValue();
- Double d = OperandResolver.parseDouble(s);
- if(d == null) {
- return ErrorEval.VALUE_INVALID;
- }
- return new NumberEval(d.doubleValue());
- }
-}
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.ValueEval;
-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(0);
- protected ValueEval attemptXlateToNumeric(ValueEval ve) {
- return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve);
+ protected AggregateFunction() {
+ super(false, false);
}
-
/* ---------------------------------------------------------------------- */
public static final Function AVEDEV = new AggregateFunction() {
+++ /dev/null
-/* ====================================================================
- 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.ValueEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public final class Maxa extends MultiOperandNumericFunction {
- private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
- new ValueEvalToNumericXlator((short) (
- ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
- | ValueEvalToNumericXlator.BLANK_IS_PARSED
- ));
-
- protected ValueEval attemptXlateToNumeric(ValueEval ve) {
- return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve);
- }
-
- public double evaluate(double[] values) {
- return values.length > 0 ? MathX.max(values) : 0;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ValueEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public final class Mina extends MultiOperandNumericFunction {
- private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
- new ValueEvalToNumericXlator((short) (
- ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
- | ValueEvalToNumericXlator.BLANK_IS_PARSED
- ));
-
- protected ValueEval attemptXlateToNumeric(ValueEval ve) {
- return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve);
- }
-
- public double evaluate(double[] values) {
- return values.length > 0 ? MathX.min(values) : 0;
- }
-}
--- /dev/null
+/* ====================================================================
+ 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;
+
+/**
+ * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
+ *
+ */
+public abstract class MinaMaxa extends MultiOperandNumericFunction {
+
+ protected MinaMaxa() {
+ super(true, true);
+ }
+
+ public static final Function MAXA = new MinaMaxa() {
+ protected double evaluate(double[] values) {
+ return values.length > 0 ? MathX.max(values) : 0;
+ }
+ };
+ public static final Function MINA = new MinaMaxa() {
+ protected double evaluate(double[] values) {
+ return values.length > 0 ? MathX.min(values) : 0;
+ }
+ };
+}
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.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.Ref2DEval;
+import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.RefEval;
+import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* where the order of operands does not matter
*/
public abstract class MultiOperandNumericFunction implements Function {
+
+ private final boolean _isReferenceBoolCounted;
+ private final boolean _isBlankCounted;
+
+ protected MultiOperandNumericFunction(boolean isReferenceBoolCounted, boolean isBlankCounted) {
+ _isReferenceBoolCounted = isReferenceBoolCounted;
+ _isBlankCounted = isBlankCounted;
+ }
+
+
static final double[] EMPTY_DOUBLE_ARRAY = { };
private static class DoubleList {
private static final int DEFAULT_MAX_NUM_OPERANDS = 30;
public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
-
+
double d;
try {
double[] values = getNumberArray(args);
} catch (EvaluationException e) {
return e.getErrorEval();
}
-
+
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.
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() + ")");
- }
+ ValueEval ve = ae.getRelativeValue(rrIx, rcIx);
+ collectValue(ve, true, temp);
}
}
return;
}
-
- // for ValueEvals other than AreaEval
- ValueEval ve = attemptXlateToNumeric((ValueEval) operand);
-
- if (ve instanceof NumericValueEval) {
- NumericValueEval nve = (NumericValueEval) ve;
- temp.add(nve.getNumberValue());
+ if (operand instanceof RefEval) {
+ RefEval re = (RefEval) operand;
+ collectValue(re.getInnerValueEval(), true, temp);
return;
}
-
- if (ve instanceof BlankEval) {
- // ignore blanks
+ collectValue((ValueEval)operand, false, temp);
+ }
+ private void collectValue(ValueEval ve, boolean isViaReference, DoubleList temp) throws EvaluationException {
+ if (ve == null) {
+ throw new IllegalArgumentException("ve must not be null");
+ }
+ if (ve instanceof NumberEval) {
+ NumberEval ne = (NumberEval) ve;
+ temp.add(ne.getNumberValue());
return;
}
if (ve instanceof ErrorEval) {
- throw new EvaluationException((ErrorEval)ve);
+ throw new EvaluationException((ErrorEval) ve);
}
- throw new RuntimeException("Unexpected value class (" + ve.getClass().getName() + ")");
+ if (ve instanceof StringEval) {
+ if (isViaReference) {
+ // ignore all ref strings
+ return;
+ }
+ String s = ((StringEval) ve).getStringValue();
+ Double d = OperandResolver.parseDouble(s);
+ if(d == null) {
+ throw new EvaluationException(ErrorEval.VALUE_INVALID);
+ }
+ temp.add(d.doubleValue());
+ return;
+ }
+ if (ve instanceof BoolEval) {
+ if (!isViaReference || _isReferenceBoolCounted) {
+ BoolEval boolEval = (BoolEval) ve;
+ temp.add(boolEval.getNumberValue());
+ }
+ return;
+ }
+ if (ve == BlankEval.INSTANCE) {
+ if (_isBlankCounted) {
+ temp.add(0.0);
+ }
+ return;
+ }
+ throw new RuntimeException("Invalid ValueEval type passed for conversion: ("
+ + ve.getClass() + ")");
}
-
-
- protected abstract ValueEval attemptXlateToNumeric(ValueEval ve);
}