View | Details | Raw Unified | Return to bug 58452
Collapse All | Expand All

(-)src/java/org/apache/poi/ss/formula/FormulaParser.java (-11 / +50 lines)
Lines 50-55 Link Here
50
import org.apache.poi.ss.formula.ptg.MultiplyPtg;
50
import org.apache.poi.ss.formula.ptg.MultiplyPtg;
51
import org.apache.poi.ss.formula.ptg.NamePtg;
51
import org.apache.poi.ss.formula.ptg.NamePtg;
52
import org.apache.poi.ss.formula.ptg.NameXPtg;
52
import org.apache.poi.ss.formula.ptg.NameXPtg;
53
import org.apache.poi.ss.formula.ptg.NameXPxg;
53
import org.apache.poi.ss.formula.ptg.NotEqualPtg;
54
import org.apache.poi.ss.formula.ptg.NotEqualPtg;
54
import org.apache.poi.ss.formula.ptg.NumberPtg;
55
import org.apache.poi.ss.formula.ptg.NumberPtg;
55
import org.apache.poi.ss.formula.ptg.OperandPtg;
56
import org.apache.poi.ss.formula.ptg.OperandPtg;
Lines 67-75 Link Here
67
import org.apache.poi.ss.formula.ptg.UnionPtg;
68
import org.apache.poi.ss.formula.ptg.UnionPtg;
68
import org.apache.poi.ss.formula.ptg.ValueOperatorPtg;
69
import org.apache.poi.ss.formula.ptg.ValueOperatorPtg;
69
import org.apache.poi.ss.usermodel.ErrorConstants;
70
import org.apache.poi.ss.usermodel.ErrorConstants;
71
import org.apache.poi.ss.usermodel.Name;
70
import org.apache.poi.ss.util.AreaReference;
72
import org.apache.poi.ss.util.AreaReference;
71
import org.apache.poi.ss.util.CellReference;
73
import org.apache.poi.ss.util.CellReference;
72
import org.apache.poi.ss.util.CellReference.NameType;
74
import org.apache.poi.ss.util.CellReference.NameType;
75
import org.apache.poi.util.POILogFactory;
76
import org.apache.poi.util.POILogger;
73
77
74
/**
78
/**
75
 * This class parses a formula string into a List of tokens in RPN order.
79
 * This class parses a formula string into a List of tokens in RPN order.
Lines 85-90 Link Here
85
 * <p/>
89
 * <p/>
86
 */
90
 */
87
public final class FormulaParser {
91
public final class FormulaParser {
92
	private final static POILogger log = POILogFactory.getLogger(FormulaParser.class);
88
	private final String _formulaString;
93
	private final String _formulaString;
89
	private final int _formulaLength;
94
	private final int _formulaLength;
90
	/** points at the next character to be read (after the {@link #look} char) */
95
	/** points at the next character to be read (after the {@link #look} char) */
Lines 108-117 Link Here
108
     */
113
     */
109
	private boolean _inIntersection = false;
114
	private boolean _inIntersection = false;
110
115
111
	private FormulaParsingWorkbook _book;
116
	private final FormulaParsingWorkbook _book;
112
	private SpreadsheetVersion _ssVersion;
117
	private final SpreadsheetVersion _ssVersion;
113
118
114
	private int _sheetIndex;
119
	private final int _sheetIndex;
115
120
116
121
117
	/**
122
	/**
Lines 137-142 Link Here
137
142
138
	/**
143
	/**
139
	 * Parse a formula into a array of tokens
144
	 * Parse a formula into a array of tokens
145
	 * Side effect: creates name (Workbook.createName) if formula contains unrecognized names (names are likely UDFs)
140
	 *
146
	 *
141
	 * @param formula	 the formula to parse
147
	 * @param formula	 the formula to parse
142
	 * @param workbook	the parent workbook
148
	 * @param workbook	the parent workbook
Lines 927-932 Link Here
927
	 * Note - Excel function names are 'case aware but not case sensitive'.  This method may end
933
	 * Note - Excel function names are 'case aware but not case sensitive'.  This method may end
928
	 * up creating a defined name record in the workbook if the specified name is not an internal
934
	 * up creating a defined name record in the workbook if the specified name is not an internal
929
	 * Excel function, and has not been encountered before.
935
	 * Excel function, and has not been encountered before.
936
	 * 
937
	 * Side effect: creates workbook name if name is not recognized (name is probably a UDF)
930
	 *
938
	 *
931
	 * @param name case preserved function name (as it was entered/appeared in the formula).
939
	 * @param name case preserved function name (as it was entered/appeared in the formula).
932
	 */
940
	 */
Lines 940-961 Link Here
940
				// Only test cases omit the book (expecting it not to be needed)
948
				// Only test cases omit the book (expecting it not to be needed)
941
				throw new IllegalStateException("Need book to evaluate name '" + name + "'");
949
				throw new IllegalStateException("Need book to evaluate name '" + name + "'");
942
			}
950
			}
951
			// Check to see if name is a named range in the workbook
943
			EvaluationName hName = _book.getName(name, _sheetIndex);
952
			EvaluationName hName = _book.getName(name, _sheetIndex);
944
			if (hName == null) {
953
			if (hName != null) {
945
				nameToken = _book.getNameXPtg(name, null);
946
				if (nameToken == null) {
947
					throw new FormulaParseException("Name '" + name
948
							+ "' is completely unknown in the current workbook");
949
				}
950
			} else {
951
				if (!hName.isFunctionName()) {
954
				if (!hName.isFunctionName()) {
952
					throw new FormulaParseException("Attempt to use name '" + name
955
					throw new FormulaParseException("Attempt to use name '" + name
953
							+ "' as a function, but defined name in workbook does not refer to a function");
956
							+ "' as a function, but defined name in workbook does not refer to a function");
954
				}
957
				}
955
958
	
956
				// calls to user-defined functions within the workbook
959
				// calls to user-defined functions within the workbook
957
				// get a Name token which points to a defined name record
960
				// get a Name token which points to a defined name record
958
				nameToken = hName.createPtg();
961
				nameToken = hName.createPtg();
962
			} else {
963
				// Check if name is an external names table
964
				nameToken = _book.getNameXPtg(name, null);
965
				if (nameToken == null) {
966
					// name is not an internal or external name
967
					if (log.check(POILogger.WARN)) {
968
						log.log(POILogger.WARN,
969
								"FormulaParser.function: Name '" + name + "' is completely unknown in the current workbook.");
970
					}
971
					// name is probably the name of an unregistered User-Defined Function
972
					switch (_book.getSpreadsheetVersion()) {
973
						case EXCEL97:
974
							// HSSFWorkbooks require a name to be added to Workbook defined names table
975
							addName(name);
976
							hName = _book.getName(name, _sheetIndex);
977
							nameToken = hName.createPtg();
978
							break;
979
						case EXCEL2007:
980
							// XSSFWorkbooks store formula names as strings.
981
							nameToken = new NameXPxg(name);
982
							break;
983
						default:
984
							throw new IllegalStateException("Unexpected spreadsheet version: " + _book.getSpreadsheetVersion().name());
985
					}
986
				}
959
			}
987
			}
960
		}
988
		}
961
989
Lines 965-970 Link Here
965
993
966
		return getFunction(name, nameToken, args);
994
		return getFunction(name, nameToken, args);
967
	}
995
	}
996
	
997
	/**
998
	 * Adds a name (named range or user defined function) to underlying workbook's names table
999
	 * @param functionName
1000
	 */
1001
	private final void addName(String functionName) {
1002
		final Name name = _book.createName();
1003
		name.setFunction(true);
1004
		name.setNameName(functionName);
1005
		name.setSheetIndex(_sheetIndex);
1006
	}
968
1007
969
	/**
1008
	/**
970
	 * Generates the variable function ptg for the formula.
1009
	 * Generates the variable function ptg for the formula.
(-)src/ooxml/testcases/org/apache/poi/ss/formula/TestFormulaParser.java (+96 lines)
Lines 18-25 Link Here
18
 */
18
 */
19
package org.apache.poi.ss.formula;
19
package org.apache.poi.ss.formula;
20
20
21
import java.io.File;
22
import java.io.FileOutputStream;
23
import java.util.Locale;
24
21
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
25
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
22
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
26
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
27
import org.apache.poi.ss.formula.ptg.AbstractFunctionPtg;
28
import org.apache.poi.ss.formula.ptg.NameXPxg;
29
import org.apache.poi.ss.formula.ptg.Ptg;
30
import org.apache.poi.ss.formula.ptg.StringPtg;
31
import org.apache.poi.xssf.XSSFTestDataSamples;
23
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
32
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
24
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
33
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
25
34
Lines 62-66 Link Here
62
        catch (FormulaParseException expected) {
71
        catch (FormulaParseException expected) {
63
        }
72
        }
64
    }
73
    }
74
    
75
    // copied from org.apache.poi.hssf.model.TestFormulaParser
76
    public void testMacroFunction() throws Exception {
77
        // testNames.xlsm contains a VB function called 'myFunc'
78
        final String testFile = "testNames.xlsm";
79
        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(testFile);
80
        try {
81
            XSSFEvaluationWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
82
    
83
            //Expected ptg stack: [NamePtg(myFunc), StringPtg(arg), (additional operands would go here...), FunctionPtg(myFunc)]
84
            Ptg[] ptg = FormulaParser.parse("myFunc(\"arg\")", workbook, FormulaType.CELL, -1);
85
            assertEquals(3, ptg.length);
86
    
87
            // the name gets encoded as the first operand on the stack
88
            NameXPxg tname = (NameXPxg) ptg[0];
89
            assertEquals("myFunc", tname.toFormulaString());
90
            
91
            // the function's arguments are pushed onto the stack from left-to-right as OperandPtgs
92
            StringPtg arg = (StringPtg) ptg[1];
93
            assertEquals("arg", arg.getValue());
94
    
95
            // The external FunctionPtg is the last Ptg added to the stack
96
            // During formula evaluation, this Ptg pops off the the appropriate number of
97
            // arguments (getNumberOfOperands()) and pushes the result on the stack 
98
            AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[2];
99
            assertTrue(tfunc.isExternalFunction());
100
            
101
            // confirm formula parsing is case-insensitive
102
            FormulaParser.parse("mYfUnC(\"arg\")", workbook, FormulaType.CELL, -1);
103
            
104
            // confirm formula parsing doesn't care about argument count or type
105
            // this should only throw an error when evaluating the formula.
106
            FormulaParser.parse("myFunc()", workbook, FormulaType.CELL, -1);
107
            FormulaParser.parse("myFunc(\"arg\", 0, TRUE)", workbook, FormulaType.CELL, -1);
108
            
109
            // A completely unknown formula name (not saved in workbook) should still be parseable and renderable
110
            // but will throw an NotImplementedFunctionException or return a #NAME? error value if evaluated.
111
            FormulaParser.parse("yourFunc(\"arg\")", workbook, FormulaType.CELL, -1);
112
            
113
            // Make sure workbook can be written and read
114
            XSSFTestDataSamples.writeOutAndReadBack(wb).close();
115
            
116
            // Manually check to make sure file isn't corrupted
117
            final File fileIn = XSSFTestDataSamples.getSampleFile(testFile);
118
            final File reSavedFile = new File(fileIn.getParentFile(), fileIn.getName().replace(".xlsm", "-saved.xlsm"));
119
            final FileOutputStream fos = new FileOutputStream(reSavedFile);
120
            wb.write(fos);
121
            fos.close();
122
        } finally {
123
            wb.close();
124
        }
125
    }
126
    
127
    public void testParserErrors() throws Exception {
128
        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("testNames.xlsm");
129
        try {
130
            XSSFEvaluationWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
131
            
132
            parseExpectedException("(");
133
            parseExpectedException(")");
134
            parseExpectedException("+");
135
            parseExpectedException("42+");
136
            parseExpectedException("IF()");
137
            parseExpectedException("IF("); //no closing paren
138
            parseExpectedException("myFunc(", workbook); //no closing paren
139
        } finally {
140
            wb.close();
141
        }
142
    }
143
    
144
    private static void parseExpectedException(String formula) {
145
        parseExpectedException(formula, null);
146
    }
147
    
148
    /** confirm formula has invalid syntax and parsing the formula results in FormulaParseException
149
     * @param formula
150
     * @param wb
151
     */
152
    private static void parseExpectedException(String formula, FormulaParsingWorkbook wb) {
153
        try {
154
            FormulaParser.parse(formula, wb, FormulaType.CELL, -1);
155
            fail("Expected FormulaParseException: " + formula);
156
        } catch (final FormulaParseException e) {
157
            // expected during successful test
158
            assertNotNull(e.getMessage());
159
        }
160
    }
65
161
66
}
162
}
(-)src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java (-11 / +69 lines)
Lines 19-25 Link Here
19
19
20
import static org.junit.Assert.assertArrayEquals;
20
import static org.junit.Assert.assertArrayEquals;
21
21
22
import java.io.File;
23
import java.io.FileOutputStream;
22
import java.io.IOException;
24
import java.io.IOException;
25
import java.util.Locale;
23
26
24
import junit.framework.AssertionFailedError;
27
import junit.framework.AssertionFailedError;
25
import junit.framework.TestCase;
28
import junit.framework.TestCase;
Lines 111-131 Link Here
111
		assertEquals("TOTAL[", ((StringPtg)ptgs[0]).getValue());
114
		assertEquals("TOTAL[", ((StringPtg)ptgs[0]).getValue());
112
	}
115
	}
113
116
114
	public void testMacroFunction() {
117
	public void testMacroFunction() throws IOException {
115
		// testNames.xls contains a VB function called 'myFunc'
118
		// testNames.xls contains a VB function called 'myFunc'
116
		HSSFWorkbook w = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
119
		final String testFile = "testNames.xls";
117
		HSSFEvaluationWorkbook book = HSSFEvaluationWorkbook.create(w);
120
		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(testFile);
121
		try {
122
			HSSFEvaluationWorkbook book = HSSFEvaluationWorkbook.create(wb);
118
123
119
		Ptg[] ptg = HSSFFormulaParser.parse("myFunc()", w);
124
			//Expected ptg stack: [NamePtg(myFunc), StringPtg(arg), (additional operands go here...), FunctionPtg(myFunc)]
120
		// myFunc() actually takes 1 parameter.  Don't know if POI will ever be able to detect this problem
125
			Ptg[] ptg = FormulaParser.parse("myFunc(\"arg\")", book, FormulaType.CELL, -1);
126
			assertEquals(3, ptg.length); 
121
127
122
		// the name gets encoded as the first arg
128
			// the name gets encoded as the first operand on the stack
123
		NamePtg tname = (NamePtg) ptg[0];
129
			NamePtg tname = (NamePtg) ptg[0];
124
		assertEquals("myFunc", tname.toFormulaString(book));
130
			assertEquals("myFunc", tname.toFormulaString(book));
125
131
126
		AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[1];
132
			// the function's arguments are pushed onto the stack from left-to-right as OperandPtgs
127
		assertTrue(tfunc.isExternalFunction());
133
			StringPtg arg = (StringPtg) ptg[1];
134
			assertEquals("arg", arg.getValue());
135
136
			// The external FunctionPtg is the last Ptg added to the stack
137
			// During formula evaluation, this Ptg pops off the the appropriate number of
138
			// arguments (getNumberOfOperands()) and pushes the result on the stack
139
			AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[2]; //FuncVarPtg
140
			assertTrue(tfunc.isExternalFunction());
141
142
			// confirm formula parsing is case-insensitive
143
			FormulaParser.parse("mYfUnC(\"arg\")", book, FormulaType.CELL, -1);
144
145
			// confirm formula parsing doesn't care about argument count or type
146
			// this should only throw an error when evaluating the formula.
147
			FormulaParser.parse("myFunc()", book, FormulaType.CELL, -1);
148
			FormulaParser.parse("myFunc(\"arg\", 0, TRUE)", book, FormulaType.CELL, -1);
149
150
			// A completely unknown formula name (not saved in workbook) should still be parseable and renderable
151
			// but will throw an NotImplementedFunctionException or return a #NAME? error value if evaluated.
152
			FormulaParser.parse("yourFunc(\"arg\")", book, FormulaType.CELL, -1);
153
154
			// Verify that myFunc and yourFunc were successfully added to Workbook names
155
			HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb);
156
			try {
157
			    // HSSFWorkbook/EXCEL97-specific side-effects user-defined function names must be added to Workbook's defined names in order to be saved.
158
				assertNotNull(wb2.getName("myFunc"));
159
				assertEqualsIgnoreCase("myFunc", wb2.getName("myFunc").getNameName());
160
				assertNotNull(wb2.getName("yourFunc"));
161
				assertEqualsIgnoreCase("yourFunc", wb2.getName("yourFunc").getNameName());
162
163
				// Manually check to make sure file isn't corrupted
164
				final File fileIn = HSSFTestDataSamples.getSampleFile(testFile);
165
				final File reSavedFile = new File(fileIn.getParentFile(), fileIn.getName().replace(".xls", "-saved.xls"));
166
				FileOutputStream fos = new FileOutputStream(reSavedFile);
167
				wb2.write(fos);
168
				fos.close();
169
			} finally {
170
				wb2.close();
171
			}
172
		} finally {
173
			wb.close();
174
		}
128
	}
175
	}
176
	
177
	private final static void assertEqualsIgnoreCase(String expected, String actual) {
178
	    assertEquals(expected.toLowerCase(Locale.ROOT), actual.toLowerCase(Locale.ROOT));
179
	}
129
180
130
	public void testEmbeddedSlash() {
181
	public void testEmbeddedSlash() {
131
		confirmTokenClasses("HYPERLINK(\"http://www.jakarta.org\",\"Jakarta\")",
182
		confirmTokenClasses("HYPERLINK(\"http://www.jakarta.org\",\"Jakarta\")",
Lines 713-724 Link Here
713
764
714
		parseExpectedException("IF(TRUE)");
765
		parseExpectedException("IF(TRUE)");
715
		parseExpectedException("countif(A1:B5, C1, D1)");
766
		parseExpectedException("countif(A1:B5, C1, D1)");
767
		
768
		parseExpectedException("(");
769
		parseExpectedException(")");
770
		parseExpectedException("+");
771
		parseExpectedException("42+");
772
		
773
		parseExpectedException("IF(");
716
	}
774
	}
717
775
718
	private static void parseExpectedException(String formula) {
776
	private static void parseExpectedException(String formula) {
719
		try {
777
		try {
720
			parseFormula(formula);
778
			parseFormula(formula);
721
			throw new AssertionFailedError("expected parse exception");
779
			throw new AssertionFailedError("Expected FormulaParseException: " + formula);
722
		} catch (FormulaParseException e) {
780
		} catch (FormulaParseException e) {
723
			// expected during successful test
781
			// expected during successful test
724
			assertNotNull(e.getMessage());
782
			assertNotNull(e.getMessage());
(-)src/testcases/org/apache/poi/ss/usermodel/BaseTestCell.java (+39 lines)
Lines 298-303 Link Here
298
	private Cell createACell() {
298
	private Cell createACell() {
299
		return _testDataProvider.createWorkbook().createSheet("Sheet1").createRow(0).createCell(0);
299
		return _testDataProvider.createWorkbook().createSheet("Sheet1").createRow(0).createCell(0);
300
	}
300
	}
301
	
302
	/**
303
	 * bug 58452: Copy cell formulas containing unregistered function names
304
	 * Make sure that formulas with unknown/unregistered UDFs can be written to and read back from a file.
305
	 *
306
	 * @throws IOException
307
	 */
308
	@Test
309
	public void testFormulaWithUnknownUDF() throws IOException {
310
		final Workbook wb1 = _testDataProvider.createWorkbook();
311
		final FormulaEvaluator evaluator1 = wb1.getCreationHelper().createFormulaEvaluator();
312
		try {
313
			final Cell cell1 = wb1.createSheet().createRow(0).createCell(0);
314
			final String formula = "myFunc(\"arg\")";
315
			cell1.setCellFormula(formula);
316
			confirmFormulaWithUnknownUDF(formula, cell1, evaluator1);
317
			
318
			final Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
319
			final FormulaEvaluator evaluator2 = wb2.getCreationHelper().createFormulaEvaluator();
320
			try {
321
				final Cell cell2 = wb2.getSheetAt(0).getRow(0).getCell(0);
322
				confirmFormulaWithUnknownUDF(formula, cell2, evaluator2);
323
			} finally {
324
				wb2.close();
325
			}
326
		} finally {
327
			wb1.close();
328
		}
329
	}
330
	
331
	private static void confirmFormulaWithUnknownUDF(String expectedFormula, Cell cell, FormulaEvaluator evaluator) {
332
		assertEquals(expectedFormula, cell.getCellFormula());
333
		try {
334
			evaluator.evaluate(cell);
335
			fail("Expected NotImplementedFunctionException/NotImplementedException");
336
		} catch (final org.apache.poi.ss.formula.eval.NotImplementedException e) {
337
			// expected
338
		}
339
	}
301
340
302
	@Test
341
	@Test
303
	public void testChangeTypeStringToBool() {
342
	public void testChangeTypeStringToBool() {
(-)src/testcases/org/apache/poi/ss/formula/BaseTestExternalFunctions.java (-5 / +11 lines)
Lines 19-24 Link Here
19
import junit.framework.TestCase;
19
import junit.framework.TestCase;
20
import org.apache.poi.ss.ITestDataProvider;
20
import org.apache.poi.ss.ITestDataProvider;
21
import org.apache.poi.ss.formula.eval.ErrorEval;
21
import org.apache.poi.ss.formula.eval.ErrorEval;
22
import org.apache.poi.ss.formula.eval.NotImplementedException;
23
import org.apache.poi.ss.formula.eval.NotImplementedFunctionException;
22
import org.apache.poi.ss.formula.eval.StringEval;
24
import org.apache.poi.ss.formula.eval.StringEval;
23
import org.apache.poi.ss.formula.eval.ValueEval;
25
import org.apache.poi.ss.formula.eval.ValueEval;
24
import org.apache.poi.ss.formula.functions.FreeRefFunction;
26
import org.apache.poi.ss.formula.functions.FreeRefFunction;
Lines 84-89 Link Here
84
86
85
    public void testExternalFunctions() {
87
    public void testExternalFunctions() {
86
        Workbook wb = _testDataProvider.createWorkbook();
88
        Workbook wb = _testDataProvider.createWorkbook();
89
        FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
87
90
88
        Sheet sh = wb.createSheet();
91
        Sheet sh = wb.createSheet();
89
92
Lines 92-102 Link Here
92
        assertEquals("ISODD(1)+ISEVEN(2)", cell1.getCellFormula());
95
        assertEquals("ISODD(1)+ISEVEN(2)", cell1.getCellFormula());
93
96
94
        Cell cell2 = sh.createRow(1).createCell(0);
97
        Cell cell2 = sh.createRow(1).createCell(0);
98
        cell2.setCellFormula("MYFUNC(\"B1\")"); //unregistered functions are parseable and renderable, but may not be evaluateable
95
        try {
99
        try {
96
            cell2.setCellFormula("MYFUNC(\"B1\")");
100
            evaluator.evaluate(cell2);
97
            fail("Should fail because MYFUNC is an unknown function");
101
        } catch (final NotImplementedException e) {
98
        } catch (FormulaParseException e){
102
            if (!(e.getCause() instanceof NotImplementedFunctionException))
99
            ; //expected
103
                throw e;
104
            // expected
105
            // Alternatively, a future implementation of evaluate could return #NAME? error to align behavior with Excel
106
            // assertEquals(ErrorEval.NAME_INVALID, ErrorEval.valueOf(evaluator.evaluate(cell2).getErrorValue()));
100
        }
107
        }
101
108
102
        wb.addToolPack(customToolpack);
109
        wb.addToolPack(customToolpack);
Lines 108-114 Link Here
108
        cell3.setCellFormula("MYFUNC2(\"C1\")&\"-\"&A2");  //where A2 is defined above
115
        cell3.setCellFormula("MYFUNC2(\"C1\")&\"-\"&A2");  //where A2 is defined above
109
        assertEquals("MYFUNC2(\"C1\")&\"-\"&A2", cell3.getCellFormula());
116
        assertEquals("MYFUNC2(\"C1\")&\"-\"&A2", cell3.getCellFormula());
110
117
111
        FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
112
        assertEquals(2.0, evaluator.evaluate(cell1).getNumberValue());
118
        assertEquals(2.0, evaluator.evaluate(cell1).getNumberValue());
113
        assertEquals("B1abc", evaluator.evaluate(cell2).getStringValue());
119
        assertEquals("B1abc", evaluator.evaluate(cell2).getStringValue());
114
        assertEquals("C1abc2-B1abc", evaluator.evaluate(cell3).getStringValue());
120
        assertEquals("C1abc2-B1abc", evaluator.evaluate(cell3).getStringValue());

Return to bug 58452