]> source.dussan.org Git - poi.git/commitdiff
Fix from bug #43510 - support named ranges in formulas
authorNick Burch <nick@apache.org>
Tue, 8 Jan 2008 15:08:51 +0000 (15:08 +0000)
committerNick Burch <nick@apache.org>
Tue, 8 Jan 2008 15:08:51 +0000 (15:08 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@610016 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 06c9b0c07135b03d7f11a3a00e1c500e50d21f13..448cca0a4aca84f1ddbc1cb4576b991fdf8024d6 100644 (file)
@@ -36,6 +36,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.0.2-FINAL" date="2008-??-??">
+            <action dev="POI-DEVELOPERS" type="add">43510 - Add support for named ranges in formulas</action>
             <action dev="POI-DEVELOPERS" type="add">43937 - Add support for hiding and un-hiding sheets, and checking their current hidden status</action>
             <action dev="POI-DEVELOPERS" type="fix">44167 - Fix for non-contiguous named ranges</action>
             <action dev="POI-DEVELOPERS" type="fix">44070 - Fix for shifting comments when shifting rows</action>
index c7bf2de8d986bd78a79cfec3ad80be78f1a08e1b..edc7cccd374a7bd2b6fa6c1417d0fec6b6c6f318 100644 (file)
@@ -33,6 +33,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.0.2-FINAL" date="2008-??-??">
+            <action dev="POI-DEVELOPERS" type="add">43510 - Add support for named ranges in formulas</action>
             <action dev="POI-DEVELOPERS" type="add">43937 - Add support for hiding and un-hiding sheets, and checking their current hidden status</action>
             <action dev="POI-DEVELOPERS" type="fix">44167 - Fix for non-contiguous named ranges</action>
             <action dev="POI-DEVELOPERS" type="fix">44070 - Fix for shifting comments when shifting rows</action>
index 9697dadafd14910d470a18190efbda7d1e784d7b..832dbdef7a63b0b95dd4a6dc876a84e256b82b53 100644 (file)
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.regex.Pattern;
 
 //import PTG's .. since we need everything, import *
 import org.apache.poi.hssf.record.formula.*;
@@ -65,6 +66,12 @@ public class FormulaParser {
      * Using an unsynchronized linkedlist to implement a stack since we're not multi-threaded.
      */
     private List functionTokens = new LinkedList();
+
+    /**
+     * Used for spotting if we have a cell reference,
+     *  or a named range
+     */
+    private final static Pattern CELL_REFERENCE_PATTERN = Pattern.compile("(?:('?)[^:\\\\/\\?\\*\\[\\]]+\\1!)?\\$?[A-Za-z]+\\$?[\\d]+");
         
     private static char TAB = '\t';
     private static char CR = '\n';
@@ -306,15 +313,27 @@ public class FormulaParser {
                 tokens.add(new Ref3DPtg(first,externIdx));
             }
         } else {
-            //this can be either a cell ref or a named range !!
-            boolean cellRef = true ; //we should probably do it with reg exp??
+            // This can be either a cell ref or a named range
+               // Try to spot which it is
+               boolean cellRef = CELL_REFERENCE_PATTERN.matcher(name).matches();
             boolean boolLit = (name.equals("TRUE") || name.equals("FALSE"));
+            
             if (boolLit) {
                 tokens.add(new BoolPtg(name));
             } else if (cellRef) {
                 tokens.add(new ReferencePtg(name));
-            }else {
-                //handle after named range is integrated!!
+            } else {
+               boolean nameRecordExists = false;
+                for(int i = 0; i < book.getNumNames(); i++) {
+                       // Our formula will by now contain an upper-cased
+                       //  version of any named range names
+                    if(book.getNameRecord(i).getNameText().toUpperCase().equals(name)) {
+                        nameRecordExists = true;
+                    }
+                }
+                if(!nameRecordExists)
+                    Abort("Found reference to named range \"" + name + "\", but that named range wasn't defined!");
+                tokens.add(new NamePtg(name, book));
             }
         }
     }
index 2d1a25c0676811e4e93c89bf3255c0ab2532d40d..51d3e66996d37d1bbdc72494ecbbecfc9db88a08 100644 (file)
@@ -39,6 +39,8 @@ import org.apache.poi.hssf.record.formula.StringPtg;
 import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
 import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
 import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFName;
 import org.apache.poi.hssf.usermodel.HSSFRow;
 import org.apache.poi.hssf.usermodel.HSSFSheet;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@@ -349,6 +351,38 @@ public class TestFormulaParser extends TestCase {
                assertTrue("ptg0 is a StringPtg", ptg[0] instanceof StringPtg);
                assertTrue("ptg0 contains exact value", ((StringPtg)ptg[0]).getValue().equals(value));
        }
+       
+       public void testWithNamedRange() throws Exception {
+               HSSFWorkbook workbook = new HSSFWorkbook();
+               FormulaParser fp;
+               Ptg[] ptgs;
+
+               HSSFSheet s = workbook.createSheet("Foo");
+               s.createRow(0).createCell((short)0).setCellValue(1.1);
+               s.createRow(1).createCell((short)0).setCellValue(2.3);
+               s.createRow(2).createCell((short)2).setCellValue(3.1);
+
+               HSSFName name = workbook.createName();
+               name.setNameName("testName");
+               name.setReference("A1:A2");
+
+               fp = HSSFFormulaEvaluator.getUnderlyingParser(workbook, "SUM(testName)");
+               fp.parse();
+               ptgs = fp.getRPNPtg();
+               assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
+               assertEquals(NamePtg.class, ptgs[0].getClass());
+               assertEquals(FuncVarPtg.class, ptgs[1].getClass());
+
+               // Now make it a single cell
+               name.setReference("C3");
+
+               fp = HSSFFormulaEvaluator.getUnderlyingParser(workbook, "SUM(testName)");
+               fp.parse();
+               ptgs = fp.getRPNPtg();
+               assertTrue("two tokens expected, got "+ptgs.length,ptgs.length == 2);
+               assertEquals(NamePtg.class, ptgs[0].getClass());
+               assertEquals(FuncVarPtg.class, ptgs[1].getClass());
+       }
 
        public void testLookupAndMatchFunctionArgs()
        {