Search in sources :

Example 1 with NameXPxg

use of org.apache.poi.ss.formula.ptg.NameXPxg in project poi by apache.

the class TestFormulaParser method testMacroFunction.

// copied from org.apache.poi.hssf.model.TestFormulaParser
@Test
public void testMacroFunction() throws Exception {
    // testNames.xlsm contains a VB function called 'myFunc'
    final String testFile = "testNames.xlsm";
    XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(testFile);
    try {
        XSSFEvaluationWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
        //Expected ptg stack: [NamePtg(myFunc), StringPtg(arg), (additional operands would go here...), FunctionPtg(myFunc)]
        Ptg[] ptg = FormulaParser.parse("myFunc(\"arg\")", workbook, FormulaType.CELL, -1);
        assertEquals(3, ptg.length);
        // the name gets encoded as the first operand on the stack
        NameXPxg tname = (NameXPxg) ptg[0];
        assertEquals("myFunc", tname.toFormulaString());
        // the function's arguments are pushed onto the stack from left-to-right as OperandPtgs
        StringPtg arg = (StringPtg) ptg[1];
        assertEquals("arg", arg.getValue());
        // The external FunctionPtg is the last Ptg added to the stack
        // During formula evaluation, this Ptg pops off the the appropriate number of
        // arguments (getNumberOfOperands()) and pushes the result on the stack 
        AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[2];
        assertTrue(tfunc.isExternalFunction());
        // confirm formula parsing is case-insensitive
        FormulaParser.parse("mYfUnC(\"arg\")", workbook, FormulaType.CELL, -1);
        // confirm formula parsing doesn't care about argument count or type
        // this should only throw an error when evaluating the formula.
        FormulaParser.parse("myFunc()", workbook, FormulaType.CELL, -1);
        FormulaParser.parse("myFunc(\"arg\", 0, TRUE)", workbook, FormulaType.CELL, -1);
        // A completely unknown formula name (not saved in workbook) should still be parseable and renderable
        // but will throw an NotImplementedFunctionException or return a #NAME? error value if evaluated.
        FormulaParser.parse("yourFunc(\"arg\")", workbook, FormulaType.CELL, -1);
        // Make sure workbook can be written and read
        XSSFTestDataSamples.writeOutAndReadBack(wb).close();
    // Manually check to make sure file isn't corrupted
    // TODO: develop a process for occasionally manually reviewing workbooks
    // to verify workbooks are not corrupted
    /*
            final File fileIn = XSSFTestDataSamples.getSampleFile(testFile);
            final File reSavedFile = new File(fileIn.getParentFile(), fileIn.getName().replace(".xlsm", "-saved.xlsm"));
            final FileOutputStream fos = new FileOutputStream(reSavedFile);
            wb.write(fos);
            fos.close();
            */
    } finally {
        wb.close();
    }
}
Also used : XSSFEvaluationWorkbook(org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook) Ptg(org.apache.poi.ss.formula.ptg.Ptg) StringPtg(org.apache.poi.ss.formula.ptg.StringPtg) AbstractFunctionPtg(org.apache.poi.ss.formula.ptg.AbstractFunctionPtg) NameXPxg(org.apache.poi.ss.formula.ptg.NameXPxg) XSSFWorkbook(org.apache.poi.xssf.usermodel.XSSFWorkbook) AbstractFunctionPtg(org.apache.poi.ss.formula.ptg.AbstractFunctionPtg) StringPtg(org.apache.poi.ss.formula.ptg.StringPtg) Test(org.junit.Test)

Example 2 with NameXPxg

use of org.apache.poi.ss.formula.ptg.NameXPxg in project poi by apache.

the class FormulaParser method function.

/**
     * 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.
     * 
     * Side effect: creates workbook name if name is not recognized (name is probably a UDF)
     *
     * @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)) {
        if (_book == null) {
            // Only test cases omit the book (expecting it not to be needed)
            throw new IllegalStateException("Need book to evaluate name '" + name + "'");
        }
        // Check to see if name is a named range in the workbook
        EvaluationName hName = _book.getName(name, _sheetIndex);
        if (hName != null) {
            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();
        } else {
            // Check if name is an external names table
            nameToken = _book.getNameXPtg(name, null);
            if (nameToken == null) {
                // name is not an internal or external name
                if (log.check(POILogger.WARN)) {
                    log.log(POILogger.WARN, "FormulaParser.function: Name '" + name + "' is completely unknown in the current workbook.");
                }
                // name is probably the name of an unregistered User-Defined Function
                switch(_book.getSpreadsheetVersion()) {
                    case EXCEL97:
                        // HSSFWorkbooks require a name to be added to Workbook defined names table
                        addName(name);
                        hName = _book.getName(name, _sheetIndex);
                        nameToken = hName.createPtg();
                        break;
                    case EXCEL2007:
                        // XSSFWorkbooks store formula names as strings.
                        nameToken = new NameXPxg(name);
                        break;
                    default:
                        throw new IllegalStateException("Unexpected spreadsheet version: " + _book.getSpreadsheetVersion().name());
                }
            }
        }
    }
    Match('(');
    ParseNode[] args = Arguments();
    Match(')');
    return getFunction(name, nameToken, args);
}
Also used : NumberPtg(org.apache.poi.ss.formula.ptg.NumberPtg) ArrayPtg(org.apache.poi.ss.formula.ptg.ArrayPtg) AttrPtg(org.apache.poi.ss.formula.ptg.AttrPtg) PercentPtg(org.apache.poi.ss.formula.ptg.PercentPtg) RangePtg(org.apache.poi.ss.formula.ptg.RangePtg) AddPtg(org.apache.poi.ss.formula.ptg.AddPtg) EqualPtg(org.apache.poi.ss.formula.ptg.EqualPtg) UnaryMinusPtg(org.apache.poi.ss.formula.ptg.UnaryMinusPtg) NameXPtg(org.apache.poi.ss.formula.ptg.NameXPtg) RefPtg(org.apache.poi.ss.formula.ptg.RefPtg) DividePtg(org.apache.poi.ss.formula.ptg.DividePtg) GreaterThanPtg(org.apache.poi.ss.formula.ptg.GreaterThanPtg) MultiplyPtg(org.apache.poi.ss.formula.ptg.MultiplyPtg) StringPtg(org.apache.poi.ss.formula.ptg.StringPtg) ErrPtg(org.apache.poi.ss.formula.ptg.ErrPtg) Ptg(org.apache.poi.ss.formula.ptg.Ptg) NamePtg(org.apache.poi.ss.formula.ptg.NamePtg) MemAreaPtg(org.apache.poi.ss.formula.ptg.MemAreaPtg) NotEqualPtg(org.apache.poi.ss.formula.ptg.NotEqualPtg) ValueOperatorPtg(org.apache.poi.ss.formula.ptg.ValueOperatorPtg) ConcatPtg(org.apache.poi.ss.formula.ptg.ConcatPtg) UnaryPlusPtg(org.apache.poi.ss.formula.ptg.UnaryPlusPtg) GreaterEqualPtg(org.apache.poi.ss.formula.ptg.GreaterEqualPtg) LessThanPtg(org.apache.poi.ss.formula.ptg.LessThanPtg) BoolPtg(org.apache.poi.ss.formula.ptg.BoolPtg) IntersectionPtg(org.apache.poi.ss.formula.ptg.IntersectionPtg) AbstractFunctionPtg(org.apache.poi.ss.formula.ptg.AbstractFunctionPtg) IntPtg(org.apache.poi.ss.formula.ptg.IntPtg) LessEqualPtg(org.apache.poi.ss.formula.ptg.LessEqualPtg) UnionPtg(org.apache.poi.ss.formula.ptg.UnionPtg) FuncVarPtg(org.apache.poi.ss.formula.ptg.FuncVarPtg) SubtractPtg(org.apache.poi.ss.formula.ptg.SubtractPtg) FuncPtg(org.apache.poi.ss.formula.ptg.FuncPtg) OperandPtg(org.apache.poi.ss.formula.ptg.OperandPtg) MissingArgPtg(org.apache.poi.ss.formula.ptg.MissingArgPtg) MemFuncPtg(org.apache.poi.ss.formula.ptg.MemFuncPtg) OperationPtg(org.apache.poi.ss.formula.ptg.OperationPtg) PowerPtg(org.apache.poi.ss.formula.ptg.PowerPtg) AreaPtg(org.apache.poi.ss.formula.ptg.AreaPtg) ParenthesisPtg(org.apache.poi.ss.formula.ptg.ParenthesisPtg) NameXPxg(org.apache.poi.ss.formula.ptg.NameXPxg)

Example 3 with NameXPxg

use of org.apache.poi.ss.formula.ptg.NameXPxg in project poi by apache.

the class BaseXSSFEvaluationWorkbook method getNameXPtg.

/**
     * Return an external name (named range, function, user-defined function) Pxg
     */
@Override
public NameXPxg getNameXPtg(String name, SheetIdentifier sheet) {
    // First, try to find it as a User Defined Function
    IndexedUDFFinder udfFinder = (IndexedUDFFinder) getUDFFinder();
    FreeRefFunction func = udfFinder.findFunction(name);
    if (func != null) {
        return new NameXPxg(null, name);
    }
    // Otherwise, try it as a named range
    if (sheet == null) {
        if (!_uBook.getNames(name).isEmpty()) {
            return new NameXPxg(null, name);
        }
        return null;
    }
    if (sheet._sheetIdentifier == null) {
        // Workbook + Named Range only
        int bookIndex = resolveBookIndex(sheet._bookName);
        return new NameXPxg(bookIndex, null, name);
    }
    // Use the sheetname and process
    String sheetName = sheet._sheetIdentifier.getName();
    if (sheet._bookName != null) {
        int bookIndex = resolveBookIndex(sheet._bookName);
        return new NameXPxg(bookIndex, sheetName, name);
    } else {
        return new NameXPxg(sheetName, name);
    }
}
Also used : NameXPxg(org.apache.poi.ss.formula.ptg.NameXPxg) IndexedUDFFinder(org.apache.poi.ss.formula.udf.IndexedUDFFinder) FreeRefFunction(org.apache.poi.ss.formula.functions.FreeRefFunction)

Aggregations

NameXPxg (org.apache.poi.ss.formula.ptg.NameXPxg)3 AbstractFunctionPtg (org.apache.poi.ss.formula.ptg.AbstractFunctionPtg)2 Ptg (org.apache.poi.ss.formula.ptg.Ptg)2 StringPtg (org.apache.poi.ss.formula.ptg.StringPtg)2 FreeRefFunction (org.apache.poi.ss.formula.functions.FreeRefFunction)1 AddPtg (org.apache.poi.ss.formula.ptg.AddPtg)1 AreaPtg (org.apache.poi.ss.formula.ptg.AreaPtg)1 ArrayPtg (org.apache.poi.ss.formula.ptg.ArrayPtg)1 AttrPtg (org.apache.poi.ss.formula.ptg.AttrPtg)1 BoolPtg (org.apache.poi.ss.formula.ptg.BoolPtg)1 ConcatPtg (org.apache.poi.ss.formula.ptg.ConcatPtg)1 DividePtg (org.apache.poi.ss.formula.ptg.DividePtg)1 EqualPtg (org.apache.poi.ss.formula.ptg.EqualPtg)1 ErrPtg (org.apache.poi.ss.formula.ptg.ErrPtg)1 FuncPtg (org.apache.poi.ss.formula.ptg.FuncPtg)1 FuncVarPtg (org.apache.poi.ss.formula.ptg.FuncVarPtg)1 GreaterEqualPtg (org.apache.poi.ss.formula.ptg.GreaterEqualPtg)1 GreaterThanPtg (org.apache.poi.ss.formula.ptg.GreaterThanPtg)1 IntPtg (org.apache.poi.ss.formula.ptg.IntPtg)1 IntersectionPtg (org.apache.poi.ss.formula.ptg.IntersectionPtg)1