aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/documentation/content/xdocs/changes.xml2
-rw-r--r--src/documentation/content/xdocs/status.xml2
-rw-r--r--src/java/org/apache/poi/hssf/model/FormulaParser.java137
-rw-r--r--src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java62
4 files changed, 149 insertions, 54 deletions
diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml
index 86ab48719b..0f17e7cc31 100644
--- a/src/documentation/content/xdocs/changes.xml
+++ b/src/documentation/content/xdocs/changes.xml
@@ -36,6 +36,8 @@
</devs>
<release version="3.0.2-FINAL" date="2007-??-??">
+ <action dev="POI-DEVELOPERS" type="fix">43410 - [PATCH] - Improved Formula Parser support for numbers and ranges</action>
+ <action dev="POI-DEVELOPERS" type="add">When writing HSLF files out, optionally preserve all OLE2 nodes (default is just the HSLF related nodes)</action>
<action dev="POI-DEVELOPERS" type="add">43323 - [PATCH] - Support for adding Pictures to ShapeGroups in HSLF.</action>
<action dev="POI-DEVELOPERS" type="add">43222 - [PATCH] - Support for getting OLE object data from HSSFWorkbook.</action>
<action dev="POI-DEVELOPERS" type="add">43247 - [PATCH] - Support for getting OLE object data from slideshows.</action>
diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml
index a5ab0905b9..9a3a8d6fa7 100644
--- a/src/documentation/content/xdocs/status.xml
+++ b/src/documentation/content/xdocs/status.xml
@@ -33,6 +33,8 @@
<changes>
<release version="3.0.2-FINAL" date="2007-??-??">
+ <action dev="POI-DEVELOPERS" type="fix">43410 - [PATCH] - Improved Formula Parser support for numbers and ranges</action>
+ <action dev="POI-DEVELOPERS" type="add">When writing HSLF files out, optionally preserve all OLE2 nodes (default is just the HSLF related nodes)</action>
<action dev="POI-DEVELOPERS" type="add">43323 - [PATCH] - Support for adding Pictures to ShapeGroups in HSLF.</action>
<action dev="POI-DEVELOPERS" type="add">43222 - [PATCH] - Support for getting OLE object data from HSSFWorkbook.</action>
<action dev="POI-DEVELOPERS" type="add">43247 - [PATCH] - Support for getting OLE object data from slideshows.</action>
diff --git a/src/java/org/apache/poi/hssf/model/FormulaParser.java b/src/java/org/apache/poi/hssf/model/FormulaParser.java
index ffecb6daff..af3382f155 100644
--- a/src/java/org/apache/poi/hssf/model/FormulaParser.java
+++ b/src/java/org/apache/poi/hssf/model/FormulaParser.java
@@ -45,6 +45,7 @@ import org.apache.poi.hssf.record.formula.*;
* @author Eric Ladner (eladner at goldinc dot com)
* @author Cameron Riley (criley at ekmail.com)
* @author Peter M. Murray (pete at quantrix dot com)
+ * @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
*/
public class FormulaParser {
@@ -230,36 +231,21 @@ public class FormulaParser {
}
- /** Get the exponent for numbers of form 1.3E21 */
- private String GetExponent() {
- StringBuffer retval = new StringBuffer();
- String sign = "";
- GetChar();
- if ('-' == look) {
- sign = "-";
- GetChar();
- }
- while (IsDigit(look)) {
- retval.append(look);
- GetChar();
- }
- if (retval.length() > 0) {
- retval.insert(0, sign);
- }
- return retval.toString();
- }
-
/** Get a Number */
private String GetNum() {
StringBuffer value = new StringBuffer();
- if (!IsDigit(look)) Expected("Integer");
- while (IsDigit(look)){
- value.append(look);
+
+ while (IsDigit(this.look)){
+ value.append(this.look);
GetChar();
}
+
SkipWhite();
- return value.toString();
+
+ return value.length() == 0 ? null : value.toString();
}
+
+
/** Output a String with Tab */
private void Emit(String s){
System.out.print(TAB+s);
@@ -278,9 +264,14 @@ public class FormulaParser {
if (look == '('){
//This is a function
function(name);
- } else if (look == ':') { // this is a AreaReference
+ } else if (look == ':' || look == '.') { // this is a AreaReference
+ GetChar();
+
+ while (look == '.') { // formulas can have . or .. or ... instead of :
+ GetChar();
+ }
+
String first = name;
- Match(':');
String second = GetName();
tokens.add(new AreaPtg(first+":"+second));
} else if (look == '!') {
@@ -508,43 +499,81 @@ public class FormulaParser {
} else if (look == ')' || look == ',') {
tokens.add(new MissingArgPtg());
} else {
-
- String number = GetNum();
- if (look=='.') {
- Match('.');
- String decimalPart = null;
- if (IsDigit(look)) number = number +"."+ GetNum(); //this also takes care of someone entering "1234."
- if ('E' == look) {
- String exponent = GetExponent();
- number += 'E' + exponent;
- }
- tokens.add(new NumberPtg(number));
+ String number2 = null;
+ String exponent = null;
+ String number1 = GetNum();
+
+ if (look == '.') {
+ GetChar();
+ number2 = GetNum();
}
- else if ('E' == look) {
- String exponent = GetExponent();
- number += 'E'+exponent;
- tokens.add(new NumberPtg(number));
+
+ if (look == 'E') {
+ GetChar();
+
+ String sign = "";
+ if (look == '+') {
+ GetChar();
+ } else if (look == '-') {
+ GetChar();
+ sign = "-";
+ }
+
+ String number = GetNum();
+ if (number == null) {
+ Expected("Integer");
+ }
+ exponent = sign + number;
}
- else {
- tokens.add(getNumberPtgFromString(number)); //TODO:what if the number is too big to be a short? ..add factory to return Int or Number!
+
+ if (number1 == null && number2 == null) {
+ Expected("Integer");
}
+
+ tokens.add(getNumberPtgFromString(number1, number2, exponent));
}
}
- /** Get a PTG for an integer from its string representation.
- * return Int or Number Ptg based on size of input
- * @param number
+ /**
+ * Get a PTG for an integer from its string representation.
+ * return Int or Number Ptg based on size of input
*/
- private Ptg getNumberPtgFromString(String number) {
- try {
- return new IntPtg(number);
- } catch (NumberFormatException e) {
- return new NumberPtg(number);
- }
-
+ private Ptg getNumberPtgFromString(String number1, String number2, String exponent) {
+ StringBuffer number = new StringBuffer();
+
+ if (number2 == null) {
+ number.append(number1);
+
+ if (exponent != null) {
+ number.append('E');
+ number.append(exponent);
+ }
+
+ String numberStr = number.toString();
+
+ try {
+ return new IntPtg(numberStr);
+ } catch (NumberFormatException e) {
+ return new NumberPtg(numberStr);
+ }
+ } else {
+ if (number1 != null) {
+ number.append(number1);
+ }
+
+ number.append('.');
+ number.append(number2);
+
+ if (exponent != null) {
+ number.append('E');
+ number.append(exponent);
+ }
+
+ return new NumberPtg(number.toString());
+ }
}
-
-
+
+
private void StringLiteral()
{
// Can't use match here 'cuz it consumes whitespace
diff --git a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
index a5be673593..2d1a25c067 100644
--- a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
+++ b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java
@@ -507,4 +507,66 @@ public class TestFormulaParser extends TestCase {
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
junit.textui.TestRunner.run(TestFormulaParser.class);
}
+
+ public void testNumbers() {
+ HSSFWorkbook wb = new HSSFWorkbook();
+
+ wb.createSheet("Cash_Flow");;
+
+ HSSFSheet sheet = wb.createSheet("Test");
+ HSSFRow row = sheet.createRow(0);
+ HSSFCell cell = row.createCell((short)0);
+ String formula = null;
+
+ // starts from decimal point
+
+ cell.setCellFormula(".1");
+ formula = cell.getCellFormula();
+ assertEquals("0.1", formula);
+
+ cell.setCellFormula("+.1");
+ formula = cell.getCellFormula();
+ assertEquals("+0.1", formula);
+
+ cell.setCellFormula("-.1");
+ formula = cell.getCellFormula();
+ assertEquals("-0.1", formula);
+
+ // has exponent
+
+ cell.setCellFormula("10E1");
+ formula = cell.getCellFormula();
+ assertEquals("100.0", formula);
+
+ cell.setCellFormula("10E+1");
+ formula = cell.getCellFormula();
+ assertEquals("100.0", formula);
+
+ cell.setCellFormula("10E-1");
+ formula = cell.getCellFormula();
+ assertEquals("1.0", formula);
+ }
+
+ public void testRanges() {
+ HSSFWorkbook wb = new HSSFWorkbook();
+
+ wb.createSheet("Cash_Flow");;
+
+ HSSFSheet sheet = wb.createSheet("Test");
+ HSSFRow row = sheet.createRow(0);
+ HSSFCell cell = row.createCell((short)0);
+ String formula = null;
+
+ cell.setCellFormula("A1.A2");
+ formula = cell.getCellFormula();
+ assertEquals("A1:A2", formula);
+
+ cell.setCellFormula("A1..A2");
+ formula = cell.getCellFormula();
+ assertEquals("A1:A2", formula);
+
+ cell.setCellFormula("A1...A2");
+ formula = cell.getCellFormula();
+ assertEquals("A1:A2", formula);
+ }
}