📄 hssfformulaevaluator.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 5, 2005 * */package org.apache.poi.hssf.usermodel;import java.lang.reflect.Constructor;import java.util.HashMap;import java.util.Map;import java.util.Stack;import org.apache.poi.hssf.model.FormulaParser;import org.apache.poi.hssf.model.Workbook;import org.apache.poi.hssf.record.formula.AddPtg;import org.apache.poi.hssf.record.formula.Area3DPtg;import org.apache.poi.hssf.record.formula.AreaPtg;import org.apache.poi.hssf.record.formula.AttrPtg;import org.apache.poi.hssf.record.formula.BoolPtg;import org.apache.poi.hssf.record.formula.ConcatPtg;import org.apache.poi.hssf.record.formula.ControlPtg;import org.apache.poi.hssf.record.formula.DividePtg;import org.apache.poi.hssf.record.formula.EqualPtg;import org.apache.poi.hssf.record.formula.FuncPtg;import org.apache.poi.hssf.record.formula.FuncVarPtg;import org.apache.poi.hssf.record.formula.GreaterEqualPtg;import org.apache.poi.hssf.record.formula.GreaterThanPtg;import org.apache.poi.hssf.record.formula.IntPtg;import org.apache.poi.hssf.record.formula.LessEqualPtg;import org.apache.poi.hssf.record.formula.LessThanPtg;import org.apache.poi.hssf.record.formula.MemErrPtg;import org.apache.poi.hssf.record.formula.MissingArgPtg;import org.apache.poi.hssf.record.formula.MultiplyPtg;import org.apache.poi.hssf.record.formula.NamePtg;import org.apache.poi.hssf.record.formula.NameXPtg;import org.apache.poi.hssf.record.formula.NotEqualPtg;import org.apache.poi.hssf.record.formula.NumberPtg;import org.apache.poi.hssf.record.formula.OperationPtg;import org.apache.poi.hssf.record.formula.ParenthesisPtg;import org.apache.poi.hssf.record.formula.PowerPtg;import org.apache.poi.hssf.record.formula.Ptg;import org.apache.poi.hssf.record.formula.Ref3DPtg;import org.apache.poi.hssf.record.formula.ReferencePtg;import org.apache.poi.hssf.record.formula.StringPtg;import org.apache.poi.hssf.record.formula.SubtractPtg;import org.apache.poi.hssf.record.formula.UnaryMinusPtg;import org.apache.poi.hssf.record.formula.UnaryPlusPtg;import org.apache.poi.hssf.record.formula.UnionPtg;import org.apache.poi.hssf.record.formula.UnknownPtg;import org.apache.poi.hssf.record.formula.eval.AddEval;import org.apache.poi.hssf.record.formula.eval.Area2DEval;import org.apache.poi.hssf.record.formula.eval.Area3DEval;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.ConcatEval;import org.apache.poi.hssf.record.formula.eval.DivideEval;import org.apache.poi.hssf.record.formula.eval.EqualEval;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.FuncVarEval;import org.apache.poi.hssf.record.formula.eval.GreaterEqualEval;import org.apache.poi.hssf.record.formula.eval.GreaterThanEval;import org.apache.poi.hssf.record.formula.eval.LessEqualEval;import org.apache.poi.hssf.record.formula.eval.LessThanEval;import org.apache.poi.hssf.record.formula.eval.MultiplyEval;import org.apache.poi.hssf.record.formula.eval.NotEqualEval;import org.apache.poi.hssf.record.formula.eval.NumberEval;import org.apache.poi.hssf.record.formula.eval.OperationEval;import org.apache.poi.hssf.record.formula.eval.PowerEval;import org.apache.poi.hssf.record.formula.eval.Ref2DEval;import org.apache.poi.hssf.record.formula.eval.Ref3DEval;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.SubtractEval;import org.apache.poi.hssf.record.formula.eval.UnaryMinusEval;import org.apache.poi.hssf.record.formula.eval.UnaryPlusEval;import org.apache.poi.hssf.record.formula.eval.ValueEval;import org.apache.poi.hssf.usermodel.HSSFSheet;/** * @author Amol S. Deshmukh < amolweb at ya hoo dot com > * * Limitations: Unfortunately, cyclic references will cause stackoverflow * exception */public class HSSFFormulaEvaluator { // params to lookup the right constructor using reflection private static final Class[] OPERATION_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class }; private static final Class[] VALUE_CONTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class }; private static final Class[] AREA3D_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval[].class }; private static final Class[] REFERENCE_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval.class }; private static final Class[] REF3D_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval.class }; // Maps for mapping *Eval to *Ptg private static final Map VALUE_EVALS_MAP = new HashMap(); private static final Map OPERATION_EVALS_MAP = new HashMap(); /* * Following is the mapping between the Ptg tokens returned * by the FormulaParser and the *Eval classes that are used * by the FormulaEvaluator */ static { VALUE_EVALS_MAP.put(BoolPtg.class, BoolEval.class); VALUE_EVALS_MAP.put(IntPtg.class, NumberEval.class); VALUE_EVALS_MAP.put(NumberPtg.class, NumberEval.class); VALUE_EVALS_MAP.put(StringPtg.class, StringEval.class); OPERATION_EVALS_MAP.put(AddPtg.class, AddEval.class); OPERATION_EVALS_MAP.put(ConcatPtg.class, ConcatEval.class); OPERATION_EVALS_MAP.put(DividePtg.class, DivideEval.class); OPERATION_EVALS_MAP.put(EqualPtg.class, EqualEval.class); //OPERATION_EVALS_MAP.put(ExpPtg.class, ExpEval.class); // TODO: check // this OPERATION_EVALS_MAP.put(FuncPtg.class, FuncVarEval.class); // TODO: // check this OPERATION_EVALS_MAP.put(FuncVarPtg.class, FuncVarEval.class); OPERATION_EVALS_MAP.put(GreaterEqualPtg.class, GreaterEqualEval.class); OPERATION_EVALS_MAP.put(GreaterThanPtg.class, GreaterThanEval.class); OPERATION_EVALS_MAP.put(LessEqualPtg.class, LessEqualEval.class); OPERATION_EVALS_MAP.put(LessThanPtg.class, LessThanEval.class); OPERATION_EVALS_MAP.put(MultiplyPtg.class, MultiplyEval.class); OPERATION_EVALS_MAP.put(NotEqualPtg.class, NotEqualEval.class); OPERATION_EVALS_MAP.put(PowerPtg.class, PowerEval.class); OPERATION_EVALS_MAP.put(SubtractPtg.class, SubtractEval.class); OPERATION_EVALS_MAP.put(UnaryMinusPtg.class, UnaryMinusEval.class); OPERATION_EVALS_MAP.put(UnaryPlusPtg.class, UnaryPlusEval.class); } protected HSSFRow row; protected HSSFSheet sheet; protected HSSFWorkbook workbook; public HSSFFormulaEvaluator(HSSFSheet sheet, HSSFWorkbook workbook) { this.sheet = sheet; this.workbook = workbook; } public void setCurrentRow(HSSFRow row) { this.row = row; } /** * Returns an underlying FormulaParser, for the specified * Formula String and HSSFWorkbook. * This will allow you to generate the Ptgs yourself, if * your needs are more complex than just having the * formula evaluated. */ public static FormulaParser getUnderlyingParser(HSSFWorkbook workbook, String formula) { return new FormulaParser(formula, workbook.getWorkbook()); } /** * If cell contains a formula, the formula is evaluated and returned, * else the CellValue simply copies the appropriate cell value from * the cell and also its cell type. This method should be preferred over * evaluateInCell() when the call should not modify the contents of the * original cell. * @param cell */ public CellValue evaluate(HSSFCell cell) { CellValue retval = null; if (cell != null) { switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_BLANK: retval = new CellValue(HSSFCell.CELL_TYPE_BLANK); break; case HSSFCell.CELL_TYPE_BOOLEAN: retval = new CellValue(HSSFCell.CELL_TYPE_BOOLEAN); retval.setBooleanValue(cell.getBooleanCellValue()); break; case HSSFCell.CELL_TYPE_ERROR: retval = new CellValue(HSSFCell.CELL_TYPE_ERROR); retval.setErrorValue(cell.getErrorCellValue()); break; case HSSFCell.CELL_TYPE_FORMULA: retval = getCellValueForEval(internalEvaluate(cell, row, sheet, workbook)); break; case HSSFCell.CELL_TYPE_NUMERIC: retval = new CellValue(HSSFCell.CELL_TYPE_NUMERIC); retval.setNumberValue(cell.getNumericCellValue()); break; case HSSFCell.CELL_TYPE_STRING: retval = new CellValue(HSSFCell.CELL_TYPE_STRING); retval.setRichTextStringValue(cell.getRichStringCellValue()); break; } } return retval; } /** * If cell contains formula, it evaluates the formula, * and saves the result of the formula. The cell * remains as a formula cell. * Else if cell does not contain formula, this method leaves * the cell unchanged. * Note that the type of the formula result is returned, * so you know what kind of value is also stored with * the formula. * <pre> * int evaluatedCellType = evaluator.evaluateFormulaCell(cell); * </pre> * Be aware that your cell will hold both the formula, * and the result. If you want the cell replaced with * the result of the formula, use {@link #evaluateInCell(HSSFCell)} * @param cell The cell to evaluate * @return The type of the formula result (the cell's type remains as HSSFCell.CELL_TYPE_FORMULA however) */ public int evaluateFormulaCell(HSSFCell cell) { if (cell != null) { switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_FORMULA: CellValue cv = getCellValueForEval(internalEvaluate(cell, row, sheet, workbook)); switch (cv.getCellType()) { case HSSFCell.CELL_TYPE_BOOLEAN: cell.setCellValue(cv.getBooleanValue()); break; case HSSFCell.CELL_TYPE_ERROR: cell.setCellValue(cv.getErrorValue()); break; case HSSFCell.CELL_TYPE_NUMERIC: cell.setCellValue(cv.getNumberValue()); break; case HSSFCell.CELL_TYPE_STRING: cell.setCellValue(cv.getRichTextStringValue()); break; case HSSFCell.CELL_TYPE_BLANK:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -