]> source.dussan.org Git - poi.git/commitdiff
Improved Formula Parser support for ranges and exponents, from Pavel Krupets (Bug...
authorNick Burch <nick@apache.org>
Tue, 18 Sep 2007 11:53:28 +0000 (11:53 +0000)
committerNick Burch <nick@apache.org>
Tue, 18 Sep 2007 11:53:28 +0000 (11:53 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@576855 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/model/FormulaParser.java
src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java

index 86ab48719b70819d2b81eb8785c655845b9df197..0f17e7cc3157fed9b64f3cc0a549f7b2f877e72d 100644 (file)
@@ -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>
index a5ab0905b9f7511d81b097f26ede1e83672a3d81..9a3a8d6fa715b88b1073866b894d2f5737887232 100644 (file)
@@ -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>
index ffecb6daff95652ec13c9fa1a6186ee1fc681a6d..af3382f155c838e74064807de5b3e0bf75674610 100644 (file)
@@ -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
index a5be673593f9a1d6c22272ec12d82c72bdddfa35..2d1a25c0676811e4e93c89bf3255c0ab2532d40d 100644 (file)
@@ -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);
+    }        
 }