Ejemplo n.º 1
0
  public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {

    int maxN = args.length;

    if (maxN < 1) {
      return ErrorEval.VALUE_INVALID;
    }
    ValueEval firstArg = args[0];
    try {
      if (firstArg instanceof NumericValueEval) {
        return evaluateSingleProduct(args);
      }
      if (firstArg instanceof RefEval) {
        return evaluateSingleProduct(args);
      }
      if (firstArg instanceof TwoDEval) {
        TwoDEval ae = (TwoDEval) firstArg;
        if (ae.isRow() && ae.isColumn()) {
          return evaluateSingleProduct(args);
        }
        return evaluateAreaSumProduct(args);
      }
    } catch (EvaluationException e) {
      return e.getErrorEval();
    }
    throw new RuntimeException(
        "Invalid arg type for SUMPRODUCT: (" + firstArg.getClass().getName() + ")");
  }
Ejemplo n.º 2
0
  /**
   * Determines a <code>double</code> value for the specified <code>ValueEval</code>.
   *
   * @param isScalarProduct <code>false</code> for SUMPRODUCTs over area refs.
   * @throws EvaluationException if <code>ve</code> represents an error value.
   *     <p>Note - string values and empty cells are interpreted differently depending on <code>
   *     isScalarProduct</code>. For scalar products, if any term is blank or a string, the error
   *     (#VALUE!) is raised. For area (sum)products, if any term is blank or a string, the result
   *     is zero.
   */
  private static double getProductTerm(ValueEval ve, boolean isScalarProduct)
      throws EvaluationException {

    if (ve instanceof BlankEval || ve == null) {
      // TODO - shouldn't BlankEval.INSTANCE be used always instead of null?
      // null seems to occur when the blank cell is part of an area ref (but not reliably)
      if (isScalarProduct) {
        throw new EvaluationException(ErrorEval.VALUE_INVALID);
      }
      return 0;
    }

    if (ve instanceof ErrorEval) {
      throw new EvaluationException((ErrorEval) ve);
    }
    if (ve instanceof StringEval) {
      if (isScalarProduct) {
        throw new EvaluationException(ErrorEval.VALUE_INVALID);
      }
      // Note for area SUMPRODUCTs, string values are interpreted as zero
      // even if they would parse as valid numeric values
      return 0;
    }
    if (ve instanceof NumericValueEval) {
      NumericValueEval nve = (NumericValueEval) ve;
      return nve.getNumberValue();
    }
    throw new RuntimeException("Unexpected value eval class (" + ve.getClass().getName() + ")");
  }
Ejemplo n.º 3
0
  /** @return never <code>null</code>, never {@link BlankEval} */
  private ValueEval evaluateAny(
      EvaluationCell srcCell,
      int sheetIndex,
      int rowIndex,
      int columnIndex,
      EvaluationTracker tracker) {

    // avoid tracking dependencies for cells that have constant definition
    boolean shouldCellDependencyBeRecorded =
        _stabilityClassifier == null
            ? true
            : !_stabilityClassifier.isCellFinal(sheetIndex, rowIndex, columnIndex);
    if (srcCell == null || srcCell.getCellType() != Cell.CELL_TYPE_FORMULA) {
      ValueEval result = getValueFromNonFormulaCell(srcCell);
      if (shouldCellDependencyBeRecorded) {
        tracker.acceptPlainValueDependency(_workbookIx, sheetIndex, rowIndex, columnIndex, result);
      }
      return result;
    }

    FormulaCellCacheEntry cce = _cache.getOrCreateFormulaCellEntry(srcCell);
    if (shouldCellDependencyBeRecorded || cce.isInputSensitive()) {
      tracker.acceptFormulaDependency(cce);
    }
    IEvaluationListener evalListener = _evaluationListener;
    ValueEval result;
    if (cce.getValue() == null) {
      if (!tracker.startEvaluate(cce)) {
        return ErrorEval.CIRCULAR_REF_ERROR;
      }
      OperationEvaluationContext ec =
          new OperationEvaluationContext(
              this, _workbook, sheetIndex, rowIndex, columnIndex, tracker);

      try {

        Ptg[] ptgs = _workbook.getFormulaTokens(srcCell);
        if (evalListener == null) {
          result = evaluateFormula(ec, ptgs);
        } else {
          evalListener.onStartEvaluate(srcCell, cce, ptgs);
          result = evaluateFormula(ec, ptgs);
          evalListener.onEndEvaluate(cce, result);
        }

        tracker.updateCacheResult(result);
      } catch (NotImplementedException e) {
        throw addExceptionInfo(e, sheetIndex, rowIndex, columnIndex);
      } finally {
        tracker.endEvaluate(cce);
      }
    } else {
      if (evalListener != null) {
        evalListener.onCacheHit(sheetIndex, rowIndex, columnIndex, cce.getValue());
      }
      return cce.getValue();
    }
    if (isDebugLogEnabled()) {
      String sheetName = getSheetName(sheetIndex);
      CellReference cr = new CellReference(rowIndex, columnIndex);
      logDebug("Evaluated " + sheetName + "!" + cr.formatAsString() + " to " + result.toString());
    }
    // Usually (result === cce.getValue())
    // But sometimes: (result==ErrorEval.CIRCULAR_REF_ERROR, cce.getValue()==null)
    // When circular references are detected, the cache entry is only updated for
    // the top evaluation frame
    return result;
  }