📄 hssfformulaevaluator.java
字号:
AreaPtg ap = (AreaPtg) ptgs[i]; short row0 = ap.getFirstRow(); short col0 = ap.getFirstColumn(); short row1 = ap.getLastRow(); short col1 = ap.getLastColumn(); ValueEval[] values = new ValueEval[(row1 - row0 + 1) * (col1 - col0 + 1)]; for (short x = row0; sheet != null && x < row1 + 1; x++) { HSSFRow row = sheet.getRow(x); for (short y = col0; row != null && y < col1 + 1; y++) { values[(x - row0) * (col1 - col0 + 1) + (y - col0)] = getEvalForCell(row.getCell(y), row, sheet, workbook); } } AreaEval ae = new Area2DEval(ap, values); stack.push(ae); } else if (ptgs[i] instanceof Area3DPtg) { Area3DPtg a3dp = (Area3DPtg) ptgs[i]; short row0 = a3dp.getFirstRow(); short col0 = a3dp.getFirstColumn(); short row1 = a3dp.getLastRow(); short col1 = a3dp.getLastColumn(); HSSFSheet xsheet = workbook.getSheetAt(a3dp.getExternSheetIndex()); ValueEval[] values = new ValueEval[(row1 - row0 + 1) * (col1 - col0 + 1)]; for (short x = row0; sheet != null && x < row1 + 1; x++) { HSSFRow row = sheet.getRow(x); for (short y = col0; row != null && y < col1 + 1; y++) { values[(x - row0) * (col1 - col0 + 1) + (y - col0)] = getEvalForCell(row.getCell(y), row, xsheet, workbook); } } AreaEval ae = new Area3DEval(a3dp, values); stack.push(ae); } else { Eval ptgEval = getEvalForPtg(ptgs[i]); stack.push(ptgEval); } } ValueEval value = ((ValueEval) stack.pop()); if (value instanceof RefEval) { RefEval rv = (RefEval) value; value = rv.getInnerValueEval(); } else if (value instanceof AreaEval) { AreaEval ae = (AreaEval) value; if (ae.isRow()) value = ae.getValueAt(ae.getFirstRow(), srcColNum); else if (ae.isColumn()) value = ae.getValueAt(srcRowNum, ae.getFirstColumn()); else value = ErrorEval.VALUE_INVALID; } return value; } /** * returns the OperationEval concrete impl instance corresponding * to the suplied operationPtg * @param ptg * @return */ protected static Eval getOperationEvalForPtg(OperationPtg ptg) { Eval retval = null; Class clazz = (Class) OPERATION_EVALS_MAP.get(ptg.getClass()); try { Constructor constructor = clazz.getConstructor(OPERATION_CONSTRUCTOR_CLASS_ARRAY); retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); } catch (Exception e) { throw new RuntimeException("Fatal Error: ", e); } return retval; } /** * returns an appropriate Eval impl instance for the Ptg. The Ptg must be * one of: Area3DPtg, AreaPtg, ReferencePtg, Ref3DPtg, IntPtg, NumberPtg, * StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be * passed here! * * @param ptg * @return */ protected static Eval getEvalForPtg(Ptg ptg) { Eval retval = null; Class clazz = (Class) VALUE_EVALS_MAP.get(ptg.getClass()); try { if (ptg instanceof Area3DPtg) { Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY); retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); } else if (ptg instanceof AreaPtg) { Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY); retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); } else if (ptg instanceof ReferencePtg) { Constructor constructor = clazz.getConstructor(REFERENCE_CONSTRUCTOR_CLASS_ARRAY); retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); } else if (ptg instanceof Ref3DPtg) { Constructor constructor = clazz.getConstructor(REF3D_CONSTRUCTOR_CLASS_ARRAY); retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); } else { if (ptg instanceof IntPtg || ptg instanceof NumberPtg || ptg instanceof StringPtg || ptg instanceof BoolPtg) { Constructor constructor = clazz.getConstructor(VALUE_CONTRUCTOR_CLASS_ARRAY); retval = (ValueEval) constructor.newInstance(new Ptg[] { ptg }); } } } catch (Exception e) { throw new RuntimeException("Fatal Error: ", e); } return retval; } /** * Given a cell, find its type and from that create an appropriate ValueEval * impl instance and return that. Since the cell could be an external * reference, we need the sheet that this belongs to. * Non existent cells are treated as empty. * @param cell * @param sheet * @param workbook * @return */ protected static ValueEval getEvalForCell(HSSFCell cell, HSSFRow row, HSSFSheet sheet, HSSFWorkbook workbook) { ValueEval retval = BlankEval.INSTANCE; if (cell != null) { switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: retval = new NumberEval(cell.getNumericCellValue()); break; case HSSFCell.CELL_TYPE_STRING: retval = new StringEval(cell.getRichStringCellValue().getString()); break; case HSSFCell.CELL_TYPE_FORMULA: retval = internalEvaluate(cell, row, sheet, workbook); break; case HSSFCell.CELL_TYPE_BOOLEAN: retval = cell.getBooleanCellValue() ? BoolEval.TRUE : BoolEval.FALSE; break; case HSSFCell.CELL_TYPE_BLANK: retval = BlankEval.INSTANCE; break; case HSSFCell.CELL_TYPE_ERROR: retval = ErrorEval.UNKNOWN_ERROR; // TODO: think about this... break; } } return retval; } /** * create a Ref2DEval for ReferencePtg and push it on the stack. * Non existent cells are treated as RefEvals containing BlankEval. * @param ptg * @param stack * @param cell * @param sheet * @param workbook */ protected static void pushRef2DEval(ReferencePtg ptg, Stack stack, HSSFCell cell, HSSFRow row, HSSFSheet sheet, HSSFWorkbook workbook) { if (cell != null) switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: stack.push(new Ref2DEval(ptg, new NumberEval(cell.getNumericCellValue()), false)); break; case HSSFCell.CELL_TYPE_STRING: stack.push(new Ref2DEval(ptg, new StringEval(cell.getRichStringCellValue().getString()), false)); break; case HSSFCell.CELL_TYPE_FORMULA: stack.push(new Ref2DEval(ptg, internalEvaluate(cell, row, sheet, workbook), true)); break; case HSSFCell.CELL_TYPE_BOOLEAN: stack.push(new Ref2DEval(ptg, cell.getBooleanCellValue() ? BoolEval.TRUE : BoolEval.FALSE, false)); break; case HSSFCell.CELL_TYPE_BLANK: stack.push(new Ref2DEval(ptg, BlankEval.INSTANCE, false)); break; case HSSFCell.CELL_TYPE_ERROR: stack.push(new Ref2DEval(ptg, ErrorEval.UNKNOWN_ERROR, false)); // TODO: think abt this break; } else { stack.push(new Ref2DEval(ptg, BlankEval.INSTANCE, false)); } } /** * create a Ref3DEval for Ref3DPtg and push it on the stack. * * @param ptg * @param stack * @param cell * @param sheet * @param workbook */ protected static void pushRef3DEval(Ref3DPtg ptg, Stack stack, HSSFCell cell, HSSFRow row, HSSFSheet sheet, HSSFWorkbook workbook) { if (cell != null) switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: stack.push(new Ref3DEval(ptg, new NumberEval(cell.getNumericCellValue()), false)); break; case HSSFCell.CELL_TYPE_STRING: stack.push(new Ref3DEval(ptg, new StringEval(cell.getRichStringCellValue().getString()), false)); break; case HSSFCell.CELL_TYPE_FORMULA: stack.push(new Ref3DEval(ptg, internalEvaluate(cell, row, sheet, workbook), true)); break; case HSSFCell.CELL_TYPE_BOOLEAN: stack.push(new Ref3DEval(ptg, cell.getBooleanCellValue() ? BoolEval.TRUE : BoolEval.FALSE, false)); break; case HSSFCell.CELL_TYPE_BLANK: stack.push(new Ref3DEval(ptg, BlankEval.INSTANCE, false)); break; case HSSFCell.CELL_TYPE_ERROR: stack.push(new Ref3DEval(ptg, ErrorEval.UNKNOWN_ERROR, false)); // TODO: think abt this break; } else { stack.push(new Ref3DEval(ptg, BlankEval.INSTANCE, false)); } } /** * Mimics the 'data view' of a cell. This allows formula evaluator * to return a CellValue instead of precasting the value to String * or Number or boolean type. * @author Amol S. Deshmukh < amolweb at ya hoo dot com > */ public static final class CellValue { private int cellType; private HSSFRichTextString richTextStringValue; private double numberValue; private boolean booleanValue; private byte errorValue; /** * CellType should be one of the types defined in HSSFCell * @param cellType */ public CellValue(int cellType) { super(); this.cellType = cellType; } /** * @return Returns the booleanValue. */ public boolean getBooleanValue() { return booleanValue; } /** * @param booleanValue The booleanValue to set. */ public void setBooleanValue(boolean booleanValue) { this.booleanValue = booleanValue; } /** * @return Returns the numberValue. */ public double getNumberValue() { return numberValue; } /** * @param numberValue The numberValue to set. */ public void setNumberValue(double numberValue) { this.numberValue = numberValue; } /** * @return Returns the stringValue. This method is deprecated, use * getRichTextStringValue instead * @deprecated */ public String getStringValue() { return richTextStringValue.getString(); } /** * @param stringValue The stringValue to set. This method is deprecated, use * getRichTextStringValue instead. * @deprecated */ public void setStringValue(String stringValue) { this.richTextStringValue = new HSSFRichTextString(stringValue); } /** * @return Returns the cellType. */ public int getCellType() { return cellType; } /** * @return Returns the errorValue. */ public byte getErrorValue() { return errorValue; } /** * @param errorValue The errorValue to set. */ public void setErrorValue(byte errorValue) { this.errorValue = errorValue; } /** * @return Returns the richTextStringValue. */ public HSSFRichTextString getRichTextStringValue() { return richTextStringValue; } /** * @param richTextStringValue The richTextStringValue to set. */ public void setRichTextStringValue(HSSFRichTextString richTextStringValue) { this.richTextStringValue = richTextStringValue; } } /** * debug method * * @param formula * @param sheet * @param workbook */ void inspectPtgs(String formula) { FormulaParser fp = new FormulaParser(formula, workbook.getWorkbook()); fp.parse(); Ptg[] ptgs = fp.getRPNPtg(); System.out.println("<ptg-group>"); for (int i = 0, iSize = ptgs.length; i < iSize; i++) { System.out.println("<ptg>"); System.out.println(ptgs[i]); if (ptgs[i] instanceof OperationPtg) { System.out.println("numoperands: " + ((OperationPtg) ptgs[i]).getNumberOfOperands()); } System.out.println("</ptg>"); } System.out.println("</ptg-group>"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -