diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java index 57eebc1dc..63a8cfe66 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java @@ -179,7 +179,7 @@ public class HSSFFormulaEvaluator { case HSSFCell.CELL_TYPE_NUMERIC: return new CellValue(cell.getNumericCellValue()); case HSSFCell.CELL_TYPE_STRING: - return new CellValue(cell.getRichStringCellValue()); + return new CellValue(cell.getRichStringCellValue().getString()); } throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")"); } @@ -270,7 +270,7 @@ public class HSSFFormulaEvaluator { cell.setCellValue(cv.getNumberValue()); break; case HSSFCell.CELL_TYPE_STRING: - cell.setCellValue(cv.getRichTextStringValue()); + cell.setCellValue(new HSSFRichTextString(cv.getStringValue())); break; case HSSFCell.CELL_TYPE_BLANK: // never happens - blanks eventually get translated to zero @@ -325,7 +325,7 @@ public class HSSFFormulaEvaluator { } if (eval instanceof StringEval) { StringEval ne = (StringEval) eval; - return new CellValue(new HSSFRichTextString(ne.getStringValue())); + return new CellValue(ne.getStringValue()); } if (eval instanceof ErrorEval) { return CellValue.getError(((ErrorEval)eval).getErrorCode()); @@ -423,7 +423,7 @@ public class HSSFFormulaEvaluator { throw new IllegalStateException("evaluation stack not empty"); } value = dereferenceValue(value, srcRowNum, srcColNum); - if (value instanceof BlankEval) { + if (value == BlankEval.INSTANCE) { // Note Excel behaviour here. A blank final final value is converted to zero. return NumberEval.ZERO; // Formulas _never_ evaluate to blank. If a formula appears to have evaluated to @@ -597,15 +597,15 @@ public class HSSFFormulaEvaluator { private final int _cellType; private final double _numberValue; private final boolean _booleanValue; - private final HSSFRichTextString _richTextStringValue; + private final String _textValue; private final int _errorCode; private CellValue(int cellType, double numberValue, boolean booleanValue, - HSSFRichTextString textValue, int errorCode) { + String textValue, int errorCode) { _cellType = cellType; _numberValue = numberValue; _booleanValue = booleanValue; - _richTextStringValue = textValue; + _textValue = textValue; _errorCode = errorCode; } @@ -616,7 +616,7 @@ public class HSSFFormulaEvaluator { /* package*/ static CellValue valueOf(boolean booleanValue) { return booleanValue ? TRUE : FALSE; } - /* package*/ CellValue(HSSFRichTextString stringValue) { + /* package*/ CellValue(String stringValue) { this(HSSFCell.CELL_TYPE_STRING, 0.0, false, stringValue, 0); } /* package*/ static CellValue getError(int errorCode) { @@ -637,12 +637,10 @@ public class HSSFFormulaEvaluator { return _numberValue; } /** - * @return Returns the stringValue. This method is deprecated, use - * getRichTextStringValue instead - * @deprecated + * @return Returns the stringValue. */ public String getStringValue() { - return _richTextStringValue.getString(); + return _textValue; } /** * @return Returns the cellType. @@ -658,9 +656,31 @@ public class HSSFFormulaEvaluator { } /** * @return Returns the richTextStringValue. + * @deprecated (Sep 2008) Text formatting is lost during formula evaluation. Use {@link #getStringValue()} */ public HSSFRichTextString getRichTextStringValue() { - return _richTextStringValue; + return new HSSFRichTextString(_textValue); + } + public String toString() { + StringBuffer sb = new StringBuffer(64); + sb.append(getClass().getName()).append(" ["); + sb.append(formatAsString()); + sb.append("]"); + return sb.toString(); + } + + public String formatAsString() { + switch (_cellType) { + case HSSFCell.CELL_TYPE_NUMERIC: + return String.valueOf(_numberValue); + case HSSFCell.CELL_TYPE_STRING: + return '"' + _textValue + '"'; + case HSSFCell.CELL_TYPE_BOOLEAN: + return _booleanValue ? "TRUE" : "FALSE"; + case HSSFCell.CELL_TYPE_ERROR: + return ErrorEval.getText(_errorCode); + } + return ""; } } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java index 9f28c488c..c8206c58e 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java @@ -132,7 +132,7 @@ public final class TestFormulasFromSpreadsheet extends TestCase { break; case HSSFCell.CELL_TYPE_STRING: assertEquals(msg, HSSFCell.CELL_TYPE_STRING, actual.getCellType()); - assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString()); + assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue()); break; } } @@ -142,7 +142,7 @@ public final class TestFormulasFromSpreadsheet extends TestCase { if (workbook == null) { workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME); sheet = workbook.getSheetAt( 0 ); - } + } _functionFailureCount = 0; _functionSuccessCount = 0; _evaluationFailureCount = 0; @@ -177,7 +177,7 @@ public final class TestFormulasFromSpreadsheet extends TestCase { * Typically pass null to test all functions */ private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) { - + HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook); int rowIndex = startRowIndex; @@ -248,7 +248,7 @@ public final class TestFormulasFromSpreadsheet extends TestCase { result = Result.SOME_EVALUATIONS_FAILED; } } - return result; + return result; } /** diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java index 1154c49c8..c869bd4b2 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java @@ -59,7 +59,7 @@ public final class TestIndexFunctionFromSpreadsheet extends TestCase { } - // Note - multiple failures are aggregated before ending. + // Note - multiple failures are aggregated before ending. // If one or more functions fail, a single AssertionFailedError is thrown at the end private int _evaluationFailureCount; private int _evaluationSuccessCount; @@ -95,7 +95,7 @@ public final class TestIndexFunctionFromSpreadsheet extends TestCase { assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0); break; case HSSFCell.CELL_TYPE_STRING: - assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString()); + assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue()); break; } } @@ -103,7 +103,7 @@ public final class TestIndexFunctionFromSpreadsheet extends TestCase { private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) { return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was " - + formatValue(actualValue) + + actualValue.formatAsString() + " but the expected result was " + formatValue(expectedCell) ); @@ -121,7 +121,7 @@ public final class TestIndexFunctionFromSpreadsheet extends TestCase { if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) { throw new AssertionFailedError(msgPrefix + " Expected cell error (" + ErrorEval.getText(expectedErrorCode) + ") but actual value was " - + formatValue(actual)); + + actual.formatAsString()); } if(expectedErrorCode != actual.getErrorValue()) { throw new AssertionFailedError(msgPrefix + " Expected cell error code (" @@ -142,15 +142,6 @@ public final class TestIndexFunctionFromSpreadsheet extends TestCase { } throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")"); } - private static String formatValue(CellValue actual) { - switch (actual.getCellType()) { - case HSSFCell.CELL_TYPE_BLANK: return ""; - case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(actual.getBooleanValue()); - case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(actual.getNumberValue()); - case HSSFCell.CELL_TYPE_STRING: return actual.getRichTextStringValue().getString(); - } - throw new RuntimeException("Unexpected cell type of evaluated value (" + actual.getCellType() + ")"); - } protected void setUp() { @@ -166,13 +157,13 @@ public final class TestIndexFunctionFromSpreadsheet extends TestCase { // confirm results String successMsg = "There were " + _evaluationSuccessCount + " function(s) without error"; - if(_evaluationFailureCount > 0) { + if(_evaluationFailureCount > 0) { String msg = _evaluationFailureCount + " evaluation(s) failed. " + successMsg; throw new AssertionFailedError(msg); } - if(false) { // normally no output for successful tests - System.out.println(getClass().getName() + ": " + successMsg); - } + if(false) { // normally no output for successful tests + System.out.println(getClass().getName() + ": " + successMsg); + } } private void processTestSheet(HSSFWorkbook workbook, String sheetName) { diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java index 4afdc2fac..84a9417fa 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java @@ -37,33 +37,33 @@ import org.apache.poi.hssf.util.CellReference; * Tests lookup functions (VLOOKUP, HLOOKUP, LOOKUP, MATCH) as loaded from a test data spreadsheet.

* These tests have been separated from the common function and operator tests because the lookup * functions have more complex test cases and test data setup. - * + * * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class * (TestXxxx) of the target (Xxxx) implementor, where execution can be observed * more easily. - * + * * @author Josh Micich */ public final class TestLookupFunctionsFromSpreadsheet extends TestCase { - + private static final class Result { public static final int SOME_EVALUATIONS_FAILED = -1; public static final int ALL_EVALUATIONS_SUCCEEDED = +1; public static final int NO_EVALUATIONS_FOUND = 0; } - /** + /** * This class defines constants for navigating around the test data spreadsheet used for these tests. */ private static final class SS { - + /** Name of the test spreadsheet (found in the standard test data folder) */ public final static String FILENAME = "LookupFunctionsTestCaseData.xls"; - + /** Name of the first sheet in the spreadsheet (contains comments) */ public final static String README_SHEET_NAME = "Read Me"; - - + + /** Row (zero-based) in each sheet where the evaluation cases start. */ public static final int START_TEST_CASES_ROW_INDEX = 4; // Row '5' /** Index of the column that contains the function names */ @@ -71,15 +71,15 @@ public final class TestLookupFunctionsFromSpreadsheet extends TestCase { public static final int COLUMN_INDEX_EVALUATION = 1; // Column 'B' public static final int COLUMN_INDEX_EXPECTED_RESULT = 2; // Column 'C' public static final int COLUMN_ROW_COMMENT = 3; // Column 'D' - + /** Used to indicate when there are no more test cases on the current sheet */ public static final String TEST_CASES_END_MARKER = ""; /** Used to indicate that the test on the current row should be ignored */ public static final String SKIP_CURRENT_TEST_CASE_MARKER = ""; - + } - // Note - multiple failures are aggregated before ending. + // Note - multiple failures are aggregated before ending. // If one or more functions fail, a single AssertionFailedError is thrown at the end private int _sheetFailureCount; private int _sheetSuccessCount; @@ -105,19 +105,19 @@ public final class TestLookupFunctionsFromSpreadsheet extends TestCase { if(actual.getCellType() != expected.getCellType()) { throw wrongTypeError(msg, expected, actual); } - - + + switch (expected.getCellType()) { case HSSFCell.CELL_TYPE_BOOLEAN: assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue()); break; case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation - throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg); + throw new IllegalStateException("Cannot expect formula as result of formula evaluation: " + msg); case HSSFCell.CELL_TYPE_NUMERIC: assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0); break; case HSSFCell.CELL_TYPE_STRING: - assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString()); + assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue()); break; } } @@ -125,14 +125,14 @@ public final class TestLookupFunctionsFromSpreadsheet extends TestCase { private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) { return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was " - + formatValue(actualValue) + + actualValue.formatAsString() + " but the expected result was " + formatValue(expectedCell) ); } private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) { return new AssertionFailedError(msgPrefix + " Error code (" - + ErrorEval.getText(actualErrorCode) + + ErrorEval.getText(actualErrorCode) + ") was evaluated, but the expected result was " + formatValue(expected) ); @@ -141,15 +141,15 @@ public final class TestLookupFunctionsFromSpreadsheet extends TestCase { private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) { if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) { - throw new AssertionFailedError(msgPrefix + " Expected cell error (" + throw new AssertionFailedError(msgPrefix + " Expected cell error (" + ErrorEval.getText(expectedErrorCode) + ") but actual value was " - + formatValue(actual)); + + actual.formatAsString()); } if(expectedErrorCode != actual.getErrorValue()) { - throw new AssertionFailedError(msgPrefix + " Expected cell error code (" - + ErrorEval.getText(expectedErrorCode) + throw new AssertionFailedError(msgPrefix + " Expected cell error code (" + + ErrorEval.getText(expectedErrorCode) + ") but actual error code was (" - + ErrorEval.getText(actual.getErrorValue()) + + ErrorEval.getText(actual.getErrorValue()) + ")"); } } @@ -164,49 +164,40 @@ public final class TestLookupFunctionsFromSpreadsheet extends TestCase { } throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")"); } - private static String formatValue(CellValue actual) { - switch (actual.getCellType()) { - case HSSFCell.CELL_TYPE_BLANK: return ""; - case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(actual.getBooleanValue()); - case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(actual.getNumberValue()); - case HSSFCell.CELL_TYPE_STRING: return actual.getRichTextStringValue().getString(); - } - throw new RuntimeException("Unexpected cell type of evaluated value (" + actual.getCellType() + ")"); - } - protected void setUp() throws Exception { + protected void setUp() { _sheetFailureCount = 0; _sheetSuccessCount = 0; _evaluationFailureCount = 0; _evaluationSuccessCount = 0; } - + public void testFunctionsFromTestSpreadsheet() { HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME); - + confirmReadMeSheet(workbook); int nSheets = workbook.getNumberOfSheets(); for(int i=1; i< nSheets; i++) { int sheetResult = processTestSheet(workbook, i, workbook.getSheetName(i)); switch(sheetResult) { - case Result.ALL_EVALUATIONS_SUCCEEDED: _sheetSuccessCount ++; break; - case Result.SOME_EVALUATIONS_FAILED: _sheetFailureCount ++; break; + case Result.ALL_EVALUATIONS_SUCCEEDED: _sheetSuccessCount ++; break; + case Result.SOME_EVALUATIONS_FAILED: _sheetFailureCount ++; break; } } - + // confirm results - String successMsg = "There were " + String successMsg = "There were " + _sheetSuccessCount + " successful sheets(s) and " + _evaluationSuccessCount + " function(s) without error"; - if(_sheetFailureCount > 0) { + if(_sheetFailureCount > 0) { String msg = _sheetFailureCount + " sheets(s) failed with " + _evaluationFailureCount + " evaluation(s). " + successMsg; throw new AssertionFailedError(msg); } - if(false) { // normally no output for successful tests - System.out.println(getClass().getName() + ": " + successMsg); - } + if(false) { // normally no output for successful tests + System.out.println(getClass().getName() + ": " + successMsg); + } } private int processTestSheet(HSSFWorkbook workbook, int sheetIndex, String sheetName) { @@ -214,7 +205,7 @@ public final class TestLookupFunctionsFromSpreadsheet extends TestCase { HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook); int maxRows = sheet.getLastRowNum()+1; int result = Result.NO_EVALUATIONS_FOUND; // so far - + String currentGroupComment = null; for(int rowIndex=SS.START_TEST_CASES_ROW_INDEX; rowIndexnull if cell is missing, empty or blank */ @@ -367,7 +358,7 @@ public final class TestLookupFunctionsFromSpreadsheet extends TestCase { if(cell.getCellType() == HSSFCell.CELL_TYPE_STRING) { return cell.getRichStringCellValue().getString(); } - + throw new RuntimeException("Bad cell type for '" + columnName + "' column: (" + cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")"); }