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 + -
显示快捷键?