📄 multioperandnumericfunction.java
字号:
/** 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 22, 2005 * */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.Eval;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.RefEval;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 > * 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 */public abstract class MultiOperandNumericFunction extends NumericFunction { 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; /** * 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; } /** * Maximum number of operands accepted by this function. * Subclasses may override to change default value. * @return */ 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 null. * * @param operands * @param srcRow * @param srcCol * @return */ protected double[] getNumberArray(Eval[] operands, int srcRow, short srcCol) { 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; } /** * Same as getNumberArray(Eval[], int, short) except that this * takes Eval instead of Eval[]. * @param operand * @param srcRow * @param srcCol * @return */ protected double[] getNumberArray(Eval operand, int srcRow, short srcCol) { 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; } /** * 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 */ private static double[] putInArray(double[] arr, int pos, double d) { 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; } protected static boolean areSubArraysConsistent(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; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -