Пример #1
0
  /**
   * @param sheetIden may be <code>null</code>
   * @param part1
   * @param part2 may be <code>null</code>
   */
  private ParseNode createAreaRefParseNode(
      SheetIdentifier sheetIden, SimpleRangePart part1, SimpleRangePart part2)
      throws FormulaParseException {

    int extIx;
    if (sheetIden == null) {
      extIx = Integer.MIN_VALUE;
    } else {
      String sName = sheetIden.getSheetIdentifier().getName();
      if (sheetIden.getBookName() == null) {
        extIx = _book.getExternalSheetIndex(sName);
      } else {
        extIx = _book.getExternalSheetIndex(sheetIden.getBookName(), sName);
      }
    }
    Ptg ptg;
    if (part2 == null) {
      CellReference cr = part1.getCellReference();
      if (sheetIden == null) {
        ptg = new RefPtg(cr);
      } else {
        ptg = new Ref3DPtg(cr, extIx);
      }
    } else {
      AreaReference areaRef = createAreaRef(part1, part2);

      if (sheetIden == null) {
        ptg = new AreaPtg(areaRef);
      } else {
        ptg = new Area3DPtg(areaRef, extIx);
      }
    }
    return new ParseNode(ptg);
  }
Пример #2
0
  private void validateNumArgs(int numArgs, FunctionMetadata fm) {
    if (numArgs < fm.getMinParams()) {
      String msg = "Too few arguments to function '" + fm.getName() + "'. ";
      if (fm.hasFixedArgsLength()) {
        msg += "Expected " + fm.getMinParams();
      } else {
        msg += "At least " + fm.getMinParams() + " were expected";
      }
      msg += " but got " + numArgs + ".";
      throw new FormulaParseException(msg);
    }
    // the maximum number of arguments depends on the Excel version
    int maxArgs;
    if (fm.hasUnlimitedVarags()) {
      if (_book != null) {
        maxArgs = _book.getSpreadsheetVersion().getMaxFunctionArgs();
      } else {
        // _book can be omitted by test cases
        maxArgs = fm.getMaxParams(); // just use BIFF8
      }
    } else {
      maxArgs = fm.getMaxParams();
    }

    if (numArgs > maxArgs) {
      String msg = "Too many arguments to function '" + fm.getName() + "'. ";
      if (fm.hasFixedArgsLength()) {
        msg += "Expected " + maxArgs;
      } else {
        msg += "At most " + maxArgs + " were expected";
      }
      msg += " but got " + numArgs + ".";
      throw new FormulaParseException(msg);
    }
  }
Пример #3
0
 /**
  * Create the formula parser, with the string that is to be parsed against the supplied workbook.
  * A later call the parse() method to return ptg list in rpn order, then call the getRPNPtg() to
  * retrieve the parse results. This class is recommended only for single threaded use.
  *
  * <p>If you only have a usermodel.HSSFWorkbook, and not a model.Workbook, then use the
  * convenience method on usermodel.HSSFFormulaEvaluator
  */
 private FormulaParser(String formula, FormulaParsingWorkbook book, int sheetIndex) {
   _formulaString = formula;
   _pointer = 0;
   _book = book;
   _ssVersion = book == null ? SpreadsheetVersion.EXCEL97 : book.getSpreadsheetVersion();
   _formulaLength = _formulaString.length();
   _sheetIndex = sheetIndex;
 }
Пример #4
0
  /**
   * Note - Excel function names are 'case aware but not case sensitive'. This method may end up
   * creating a defined name record in the workbook if the specified name is not an internal Excel
   * function, and has not been encountered before.
   *
   * @param name case preserved function name (as it was entered/appeared in the formula).
   */
  private ParseNode function(String name) {
    Ptg nameToken = null;
    if (!AbstractFunctionPtg.isBuiltInFunctionName(name)) {
      // user defined function
      // in the token tree, the name is more or less the first argument

      if (_book == null) {
        // Only test cases omit the book (expecting it not to be needed)
        throw new IllegalStateException("Need book to evaluate name '" + name + "'");
      }
      EvaluationName hName = _book.getName(name, _sheetIndex);
      if (hName == null) {

        nameToken = _book.getNameXPtg(name);
        if (nameToken == null) {
          throw new FormulaParseException(
              "Name '" + name + "' is completely unknown in the current workbook");
        }
      } else {
        if (!hName.isFunctionName()) {
          throw new FormulaParseException(
              "Attempt to use name '"
                  + name
                  + "' as a function, but defined name in workbook does not refer to a function");
        }

        // calls to user-defined functions within the workbook
        // get a Name token which points to a defined name record
        nameToken = hName.createPtg();
      }
    }

    Match('(');
    ParseNode[] args = Arguments();
    Match(')');

    return getFunction(name, nameToken, args);
  }
Пример #5
0
  /**
   * Parses simple factors that are not primitive ranges or range components i.e. '!', ':'(and equiv
   * '...') do not appear Examples
   *
   * <pre>
   *   my.named...range.
   *   foo.bar(123.456, "abc")
   *   123.456
   *   "abc"
   *   true
   * </pre>
   */
  private ParseNode parseNonRange(int savePointer) {
    resetPointer(savePointer);

    if (Character.isDigit(look)) {
      return new ParseNode(parseNumber());
    }
    if (look == '"') {
      return new ParseNode(new StringPtg(parseStringLiteral()));
    }
    // from now on we can only be dealing with non-quoted identifiers
    // which will either be named ranges or functions
    StringBuilder sb = new StringBuilder();

    if (!Character.isLetter(look)) {
      throw expected("number, string, or defined name");
    }
    while (isValidDefinedNameChar(look)) {
      sb.append(look);
      GetChar();
    }
    SkipWhite();
    String name = sb.toString();
    if (look == '(') {
      return function(name);
    }
    if (name.equalsIgnoreCase("TRUE") || name.equalsIgnoreCase("FALSE")) {
      return new ParseNode(new BoolPtg(name.toUpperCase()));
    }
    if (_book == null) {
      // Only test cases omit the book (expecting it not to be needed)
      throw new IllegalStateException("Need book to evaluate name '" + name + "'");
    }
    EvaluationName evalName = _book.getName(name, _sheetIndex);
    if (evalName == null) {
      throw new FormulaParseException(
          "Specified named range '" + name + "' does not exist in the current workbook.");
    }
    if (evalName.isRange()) {
      return new ParseNode(evalName.createPtg());
    }
    // TODO - what about NameX ?
    throw new FormulaParseException("Specified name '" + name + "' is not a range as expected.");
  }