diff --git a/src/java/org/apache/poi/ss/formula/FormulaParser.java b/src/java/org/apache/poi/ss/formula/FormulaParser.java index d7827b137c..9e63e6f4b9 100644 --- a/src/java/org/apache/poi/ss/formula/FormulaParser.java +++ b/src/java/org/apache/poi/ss/formula/FormulaParser.java @@ -1209,9 +1209,13 @@ public final class FormulaParser { case 'F': case 'f': case 'T': case 't': return parseBooleanLiteral(); + case '-': + Match('-'); + SkipWhite(); + return convertArrayNumber(parseNumber(), false); } // else assume number - return convertArrayNumber(parseNumber()); + return convertArrayNumber(parseNumber(), true); } private Boolean parseBooleanLiteral() { @@ -1225,14 +1229,19 @@ public final class FormulaParser { throw expected("'TRUE' or 'FALSE'"); } - private static Double convertArrayNumber(Ptg ptg) { + private static Double convertArrayNumber(Ptg ptg, boolean isPositive) { + double value; if (ptg instanceof IntPtg) { - return new Double(((IntPtg)ptg).getValue()); + value = ((IntPtg)ptg).getValue(); + } else if (ptg instanceof NumberPtg) { + value = ((NumberPtg)ptg).getValue(); + } else { + throw new RuntimeException("Unexpected ptg (" + ptg.getClass().getName() + ")"); } - if (ptg instanceof NumberPtg) { - return new Double(((NumberPtg)ptg).getValue()); + if (!isPositive) { + value = -value; } - throw new RuntimeException("Unexpected ptg (" + ptg.getClass().getName() + ")"); + return new Double(value); } private Ptg parseNumber() { diff --git a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java index 5891831cba..2d2784c2da 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java +++ b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java @@ -871,6 +871,28 @@ public final class TestFormulaParser extends TestCase { confirmTokenClasses(ptgs2, ArrayPtg.class, IntPtg.class, FuncVarPtg.class); } + public void testParseArrayNegativeElement() { + Ptg[] ptgs; + try { + ptgs = parseFormula("{-42}"); + } catch (FormulaParseException e) { + if (e.getMessage().equals("Parse error near char 1 '-' in specified formula '{-42}'. Expected Integer")) { + throw new AssertionFailedError("Identified bug - failed to parse negative array element."); + } + throw e; + } + confirmTokenClasses(ptgs, ArrayPtg.class); + Object element = ((ArrayPtg)ptgs[0]).getTokenArrayValues()[0][0]; + + assertEquals(-42.0, ((Double)element).doubleValue(), 0.0); + + // Should be able to handle whitespace between unary minus and digits (Excel + // accepts this formula after presenting the user with a confirmation dialog). + ptgs = parseFormula("{- 5}"); + element = ((ArrayPtg)ptgs[0]).getTokenArrayValues()[0][0]; + assertEquals(-5.0, ((Double)element).doubleValue(), 0.0); + } + public void testRangeOperator() { HSSFWorkbook wb = new HSSFWorkbook();