/** * 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."); }
/** * 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); }