workbookevaluator.java
来自「EXCEL read and write」· Java 代码 · 共 469 行 · 第 1/2 页
JAVA
469 行
} int cellType = cell.getCellType(); switch (cellType) { case HSSFCell.CELL_TYPE_NUMERIC: return new NumberEval(cell.getNumericCellValue()); case HSSFCell.CELL_TYPE_STRING: return new StringEval(cell.getStringCellValue()); case HSSFCell.CELL_TYPE_BOOLEAN: return BoolEval.valueOf(cell.getBooleanCellValue()); case HSSFCell.CELL_TYPE_BLANK: return BlankEval.INSTANCE; case HSSFCell.CELL_TYPE_ERROR: return ErrorEval.valueOf(cell.getErrorCellValue()); } throw new RuntimeException("Unexpected cell type (" + cellType + ")"); } // visibility raised for testing /* package */ ValueEval evaluateFormula(int sheetIndex, int srcRowNum, int srcColNum, Ptg[] ptgs, EvaluationTracker tracker) { Stack stack = new Stack(); for (int i = 0, iSize = ptgs.length; i < iSize; i++) { // since we don't know how to handle these yet :( Ptg ptg = ptgs[i]; if (ptg instanceof AttrPtg) { AttrPtg attrPtg = (AttrPtg) ptg; if (attrPtg.isSum()) { // Excel prefers to encode 'SUM()' as a tAttr token, but this evaluator // expects the equivalent function token byte nArgs = 1; // tAttrSum always has 1 parameter ptg = new FuncVarPtg("SUM", nArgs); } } if (ptg instanceof ControlPtg) { // skip Parentheses, Attr, etc continue; } if (ptg instanceof MemFuncPtg) { // can ignore, rest of tokens for this expression are in OK RPN order continue; } if (ptg instanceof MemErrPtg) { continue; } Eval opResult; if (ptg instanceof OperationPtg) { OperationPtg optg = (OperationPtg) ptg; if (optg instanceof UnionPtg) { continue; } OperationEval operation = OperationEvaluatorFactory.create(optg); int numops = operation.getNumberOfOperands(); Eval[] ops = new Eval[numops]; // storing the ops in reverse order since they are popping for (int j = numops - 1; j >= 0; j--) { Eval p = (Eval) stack.pop(); ops[j] = p; }// logDebug("invoke " + operation + " (nAgs=" + numops + ")"); opResult = invokeOperation(operation, ops, _workbook, sheetIndex, srcRowNum, srcColNum); if (opResult == MissingArgEval.instance) { opResult = BlankEval.INSTANCE; } } else { opResult = getEvalForPtg(ptg, sheetIndex, tracker); } if (opResult == null) { throw new RuntimeException("Evaluation result must not be null"); }// logDebug("push " + opResult); stack.push(opResult); } ValueEval value = ((ValueEval) stack.pop()); if (!stack.isEmpty()) { throw new IllegalStateException("evaluation stack not empty"); } value = dereferenceValue(value, srcRowNum, srcColNum); if (value == BlankEval.INSTANCE) { // Note Excel behaviour here. A blank final final value is converted to zero. return NumberEval.ZERO; // Formulas _never_ evaluate to blank. If a formula appears to have evaluated to // blank, the actual value is empty string. This can be verified with ISBLANK(). } return value; } /** * Dereferences a single value from any AreaEval or RefEval evaluation result. * If the supplied evaluationResult is just a plain value, it is returned as-is. * @return a <tt>NumberEval</tt>, <tt>StringEval</tt>, <tt>BoolEval</tt>, * <tt>BlankEval</tt> or <tt>ErrorEval</tt>. Never <code>null</code>. */ private static ValueEval dereferenceValue(ValueEval evaluationResult, int srcRowNum, int srcColNum) { if (evaluationResult instanceof RefEval) { RefEval rv = (RefEval) evaluationResult; return rv.getInnerValueEval(); } if (evaluationResult instanceof AreaEval) { AreaEval ae = (AreaEval) evaluationResult; if (ae.isRow()) { if(ae.isColumn()) { return ae.getRelativeValue(0, 0); } return ae.getValueAt(ae.getFirstRow(), srcColNum); } if (ae.isColumn()) { return ae.getValueAt(srcRowNum, ae.getFirstColumn()); } return ErrorEval.VALUE_INVALID; } return evaluationResult; } private static Eval invokeOperation(OperationEval operation, Eval[] ops, EvaluationWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum) { if(operation instanceof FunctionEval) { FunctionEval fe = (FunctionEval) operation; if(fe.isFreeRefFunction()) { return fe.getFreeRefFunction().evaluate(ops, workbook, sheetIndex, srcRowNum, srcColNum); } } return operation.evaluate(ops, srcRowNum, (short)srcColNum); } private SheetRefEvaluator createExternSheetRefEvaluator(EvaluationTracker tracker, ExternSheetReferenceToken ptg) { int externSheetIndex = ptg.getExternSheetIndex(); ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex); if (externalSheet != null) { WorkbookEvaluator otherEvaluator = _collaboratingWorkbookEnvironment.getWorkbookEvaluator(externalSheet.getWorkbookName()); EvaluationWorkbook otherBook = otherEvaluator._workbook; int otherSheetIndex = otherBook.getSheetIndex(externalSheet.getSheetName()); return new SheetRefEvaluator(otherEvaluator, tracker, otherBook, otherSheetIndex); } int otherSheetIndex = _workbook.convertFromExternSheetIndex(externSheetIndex); return new SheetRefEvaluator(this, tracker, _workbook, otherSheetIndex); } /** * 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! */ private Eval getEvalForPtg(Ptg ptg, int sheetIndex, EvaluationTracker tracker) { // consider converting all these (ptg instanceof XxxPtg) expressions to (ptg.getClass() == XxxPtg.class) if (ptg instanceof NamePtg) { // named ranges, macro functions NamePtg namePtg = (NamePtg) ptg; EvaluationName nameRecord = _workbook.getName(namePtg); if (nameRecord.isFunctionName()) { return new NameEval(nameRecord.getNameText()); } if (nameRecord.hasFormula()) { return evaluateNameFormula(nameRecord.getNameDefinition(), sheetIndex, tracker); } throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'"); } if (ptg instanceof NameXPtg) { return new NameXEval(((NameXPtg) ptg)); } if (ptg instanceof IntPtg) { return new NumberEval(((IntPtg)ptg).getValue()); } if (ptg instanceof NumberPtg) { return new NumberEval(((NumberPtg)ptg).getValue()); } if (ptg instanceof StringPtg) { return new StringEval(((StringPtg) ptg).getValue()); } if (ptg instanceof BoolPtg) { return BoolEval.valueOf(((BoolPtg) ptg).getValue()); } if (ptg instanceof ErrPtg) { return ErrorEval.valueOf(((ErrPtg) ptg).getErrorCode()); } if (ptg instanceof MissingArgPtg) { return MissingArgEval.instance; } if (ptg instanceof AreaErrPtg ||ptg instanceof RefErrorPtg || ptg instanceof DeletedArea3DPtg || ptg instanceof DeletedRef3DPtg) { return ErrorEval.REF_INVALID; } if (ptg instanceof Ref3DPtg) { Ref3DPtg refPtg = (Ref3DPtg) ptg; SheetRefEvaluator sre = createExternSheetRefEvaluator(tracker, refPtg); return new LazyRefEval(refPtg, sre); } if (ptg instanceof Area3DPtg) { Area3DPtg aptg = (Area3DPtg) ptg; SheetRefEvaluator sre = createExternSheetRefEvaluator(tracker, aptg); return new LazyAreaEval(aptg, sre); } SheetRefEvaluator sre = new SheetRefEvaluator(this, tracker, _workbook, sheetIndex); if (ptg instanceof RefPtg) { return new LazyRefEval(((RefPtg) ptg), sre); } if (ptg instanceof AreaPtg) { return new LazyAreaEval(((AreaPtg) ptg), sre); } if (ptg instanceof UnknownPtg) { // POI uses UnknownPtg when the encoded Ptg array seems to be corrupted. // This seems to occur in very rare cases (e.g. unused name formulas in bug 44774, attachment 21790) // In any case, formulas are re-parsed before execution, so UnknownPtg should not get here throw new RuntimeException("UnknownPtg not allowed"); } throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")"); } private Eval evaluateNameFormula(Ptg[] ptgs, int sheetIndex, EvaluationTracker tracker) { if (ptgs.length > 1) { throw new RuntimeException("Complex name formulas not supported yet"); } return getEvalForPtg(ptgs[0], sheetIndex, tracker); } /** * Used by the lazy ref evals whenever they need to get the value of a contained cell. */ /* package */ ValueEval evaluateReference(EvaluationSheet sheet, int sheetIndex, int rowIndex, int columnIndex, EvaluationTracker tracker) { EvaluationCell cell = sheet.getCell(rowIndex, columnIndex); return evaluateAny(cell, sheetIndex, rowIndex, columnIndex, tracker); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?