FileDocCategorySizeDatePackage
MultiOperandNumericFunction.javaAPI DocApache Poi 3.0.18983Sun Mar 11 12:59:30 GMT 2007org.apache.poi.hssf.record.formula.functions

MultiOperandNumericFunction

public abstract class MultiOperandNumericFunction extends NumericFunction
author
Amol S. Deshmukh < amolweb at ya hoo dot com > This is the super class for all excel function evaluator classes that take variable number of operands, and where the order of operands does not matter

Fields Summary
private static final org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator
DEFAULT_NUM_XLATOR
private static final int
DEFAULT_MAX_NUM_OPERANDS
Constructors Summary
Methods Summary
protected static booleanareSubArraysConsistent(double[][] values)

        boolean retval = false;
        
        outer: do {
            if (values != null && values.length > 0) {
                if (values[0] == null)
                    break outer;
                int len = values[0].length;
                for (int i=1, iSize=values.length; i<iSize; i++) {
                    if (values[i] == null)
                        break outer;
                    int tlen = values[i].length;
                    if (len != tlen) {
                        break outer;
                    }
                }
            }
            retval = true;
        } while (false);
        return retval;
    
protected intgetMaxNumOperands()
Maximum number of operands accepted by this function. Subclasses may override to change default value.

return

        return DEFAULT_MAX_NUM_OPERANDS;
    
protected double[]getNumberArray(org.apache.poi.hssf.record.formula.eval.Eval[] operands, int srcRow, short srcCol)
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 null.

param
operands
param
srcRow
param
srcCol
return

        double[] retval = new double[30];
        int count = 0;
        
        outer: do { // goto simulator loop
            if (operands.length > getMaxNumOperands()) {
                break outer;
            }
            else {
                for (int i=0, iSize=operands.length; i<iSize; i++) {
                    double[] temp = getNumberArray(operands[i], srcRow, srcCol);
                    if (temp == null) {
                        retval = null; // error occurred.
                        break;
                    }
                    retval = putInArray(retval, count, temp);
                    count += temp.length;
                }
            }
        } while (false); // end goto simulator loop
        
        if (retval != null) {
            double[] temp = retval;
            retval = new double[count];
            System.arraycopy(temp, 0, retval, 0, count);
        }
        
        return retval;
    
protected double[]getNumberArray(org.apache.poi.hssf.record.formula.eval.Eval operand, int srcRow, short srcCol)
Same as getNumberArray(Eval[], int, short) except that this takes Eval instead of Eval[].

param
operand
param
srcRow
param
srcCol
return

        double[] retval;
        int count = 0;
        
        if (operand instanceof AreaEval) {
            AreaEval ae = (AreaEval) operand;
            ValueEval[] values = ae.getValues();
            retval = new double[values.length];
            for (int j=0, jSize=values.length; j<jSize; j++) {
                /*
                 * 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 = (values[j] instanceof RefEval)
                        ? new Ref2DEval(null, ((RefEval) values[j]).getInnerValueEval(), true)
                        : new Ref2DEval(null, values[j], false);
                ValueEval ve = singleOperandEvaluate(re, srcRow, srcCol);
                
                if (ve instanceof NumericValueEval) {
                    NumericValueEval nve = (NumericValueEval) ve;
                    retval = putInArray(retval, count++, nve.getNumberValue());
                }
                else if (ve instanceof BlankEval) {} // ignore operand
                else {
                    retval = null; // null => indicate to calling subclass that error occurred
                    break;
                }
            }
        }
        else { // for ValueEvals other than AreaEval
            retval = new double[1];
            ValueEval ve = singleOperandEvaluate(operand, srcRow, srcCol);
            
            if (ve instanceof NumericValueEval) {
                NumericValueEval nve = (NumericValueEval) ve;
                retval = putInArray(retval, count++, nve.getNumberValue());
            }
            else if (ve instanceof BlankEval) {} // ignore operand
            else {
                retval = null; // null => indicate to calling subclass that error occurred
            }
        }
        
        if (retval != null && retval.length >= 1) {
            double[] temp = retval;
            retval = new double[count];
            System.arraycopy(temp, 0, retval, 0, count);
        }
        
        return retval;
    
protected org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlatorgetXlator()
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.


                                         
       
        return DEFAULT_NUM_XLATOR;
    
private static double[]putInArray(double[] arr, int pos, double d)
puts d at position pos in array arr. If pos is greater than arr, the array is dynamically resized (using a simple doubling rule).

param
arr
param
pos
param
d
return

        double[] tarr = arr;
        while (pos >= arr.length) {
            arr = new double[arr.length << 1];
        }
        if (tarr.length != arr.length) {
            System.arraycopy(tarr, 0, arr, 0, tarr.length);
        }
        arr[pos] = d;
        return arr;
    
private static double[]putInArray(double[] arr, int pos, double[] d)

        double[] tarr = arr;
        while (pos+d.length >= arr.length) {
            arr = new double[arr.length << 1];
        }
        if (tarr.length != arr.length) {
            System.arraycopy(tarr, 0, arr, 0, tarr.length);
        }
        for (int i=0, iSize=d.length; i<iSize; i++) {
            arr[pos+i] = d[i];
        }
        return arr;