You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2009/04/06 21:57:22 UTC

svn commit: r762479 - in /poi/trunk/src: documentation/content/xdocs/ java/org/apache/poi/hssf/record/formula/ java/org/apache/poi/hssf/usermodel/ ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/ ooxml/java/org/apache/poi/xssf/usermodel/ testcases/o...

Author: josh
Date: Mon Apr  6 19:57:21 2009
New Revision: 762479

URL: http://svn.apache.org/viewvc?rev=762479&view=rev
Log:
Bugzilla 46973 - fixed defined names to behave better when refersToFormula is unset

Modified:
    poi/trunk/src/documentation/content/xdocs/changes.xml
    poi/trunk/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java
    poi/trunk/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java
    poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestNamedRange.java

Modified: poi/trunk/src/documentation/content/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/changes.xml?rev=762479&r1=762478&r2=762479&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/changes.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/changes.xml Mon Apr  6 19:57:21 2009
@@ -37,6 +37,7 @@
 
 		<!-- Don't forget to update status.xml too! -->
         <release version="3.5-beta6" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">46973 - Fixed defined names to behave better when refersToFormula is unset</action>
            <action dev="POI-DEVELOPERS" type="fix">46832 - Allow merged regions with columns greater than 255 or rows bigger than 65536 in XSSF</action>
            <action dev="POI-DEVELOPERS" type="fix">46951 - Fixed formula parser to better handle range operators and whole row/column refs.</action>
            <action dev="POI-DEVELOPERS" type="fix">46948 - Fixed evaluation of range operator to allow for area-ref operands</action>

Modified: poi/trunk/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=762479&r1=762478&r2=762479&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/status.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/status.xml Mon Apr  6 19:57:21 2009
@@ -34,6 +34,7 @@
 	<!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.5-beta6" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">46973 - Fixed defined names to behave better when refersToFormula is unset</action>
            <action dev="POI-DEVELOPERS" type="fix">46832 - Allow merged regions with columns greater than 255 or rows bigger than 65536 in XSSF</action>
            <action dev="POI-DEVELOPERS" type="fix">46951 - Fixed formula parser to better handle range operators and whole row/column refs.</action>
            <action dev="POI-DEVELOPERS" type="fix">46948 - Fixed evaluation of range operator to allow for area-ref operands</action>

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java?rev=762479&r1=762478&r2=762479&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java Mon Apr  6 19:57:21 2009
@@ -321,4 +321,32 @@
 	 * @return <code>false</code> if this token is classified as 'reference', 'value', or 'array'
 	 */
 	public abstract boolean isBaseToken();
+
+	public static boolean doesFormulaReferToDeletedCell(Ptg[] ptgs) {
+		for (int i = 0; i < ptgs.length; i++) {
+			if (isDeletedCellRef(ptgs[i])) {
+				return true;
+			}
+		}
+		return false;
+	}
+	private static boolean isDeletedCellRef(Ptg ptg) {
+		if (ptg == ErrPtg.REF_INVALID) {
+			return true;
+		}
+		if (ptg instanceof DeletedArea3DPtg) {
+			return true;
+		}
+		if (ptg instanceof DeletedRef3DPtg) {
+			return true;
+		}
+		if (ptg instanceof AreaErrPtg) {
+			return true;
+		}
+		if (ptg instanceof RefErrorPtg) {
+			return true;
+		}
+		return false;
+	}
+
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java?rev=762479&r1=762478&r2=762479&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFName.java Mon Apr  6 19:57:21 2009
@@ -21,8 +21,8 @@
 import org.apache.poi.hssf.model.Workbook;
 import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.ss.usermodel.Name;
 import org.apache.poi.ss.formula.FormulaType;
+import org.apache.poi.ss.usermodel.Name;
 
 /**
  * High Level Representation of a 'defined name' which could be a 'built-in' name,
@@ -160,46 +160,26 @@
         setRefersToFormula(ref);
     }
 
-    /**
-     * Sets the formula that the name is defined to refer to. The following are representative examples:
-     *
-     * <ul>
-     *  <li><code>'My Sheet'!$A$3</code></li>
-     *  <li><code>8.3</code></li>
-     *  <li><code>HR!$A$1:$Z$345</code></li>
-     *  <li><code>SUM(Sheet1!A1,Sheet2!B2)</li>
-     *  <li><code>-PMT(Interest_Rate/12,Number_of_Payments,Loan_Amount)</li>
-     * </ul>
-     *
-     * @param formulaText the reference for this name
-     * @throws IllegalArgumentException if the specified reference is unparsable
-    */
     public void setRefersToFormula(String formulaText) {
         Ptg[] ptgs = HSSFFormulaParser.parse(formulaText, _book, FormulaType.NAMEDRANGE, getSheetIndex());
         _definedNameRec.setNameDefinition(ptgs);
     }
 
-    /**
-     * Returns the formula that the name is defined to refer to. The following are representative examples:
-     *
-     * @return the reference for this name
-     * @see #setRefersToFormula(String)
-     */
     public String getRefersToFormula() {
         if (_definedNameRec.isFunctionName()) {
             throw new IllegalStateException("Only applicable to named ranges");
         }
-        return HSSFFormulaParser.toFormulaString(_book, _definedNameRec.getNameDefinition());
+        Ptg[] ptgs = _definedNameRec.getNameDefinition();
+        if (ptgs.length < 1) {
+            // 'refersToFormula' has not been set yet
+            return null;
+        }
+        return HSSFFormulaParser.toFormulaString(_book, ptgs);
     }
 
-    /**
-     * Tests if this name points to a cell that no longer exists
-     *
-     * @return true if the name refers to a deleted cell, false otherwise
-     */
     public boolean isDeleted(){
-        String formulaText = getRefersToFormula();
-        return formulaText.indexOf("#REF!") != -1;
+        Ptg[] ptgs = _definedNameRec.getNameDefinition();
+        return Ptg.doesFormulaReferToDeletedCell(ptgs);
     }
 
     /**

Modified: poi/trunk/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java?rev=762479&r1=762478&r2=762479&view=diff
==============================================================================
--- poi/trunk/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java (original)
+++ poi/trunk/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Name.java Mon Apr  6 19:57:21 2009
@@ -118,7 +118,7 @@
     /**
      * Returns the formula that the name is defined to refer to. 
      *
-     * @return the reference for this name
+     * @return the reference for this name, <code>null</code> if it has not been set yet. Never empty string
      * @see #setRefersToFormula(String)
      */
     String getRefersToFormula();
@@ -134,10 +134,10 @@
      *  <li><code>-PMT(Interest_Rate/12,Number_of_Payments,Loan_Amount)</li>
      * </ul>
      *
-     * @param ref the reference for this name
-     * @throws IllegalArgumentException if the specified reference is unparsable
+     * @param formulaText the reference for this name
+     * @throws IllegalArgumentException if the specified formulaText is unparsable
     */
-   void setRefersToFormula(String ref);
+   void setRefersToFormula(String formulaText);
 
     /**
      * Checks if this name is a function name
@@ -149,7 +149,7 @@
     /**
      * Checks if this name points to a cell that no longer exists
      *
-     * @return true if the name refers to a deleted cell, false otherwise
+     * @return <code>true</code> if the name refers to a deleted cell, <code>false</code> otherwise
      */
     boolean isDeleted();
 

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java?rev=762479&r1=762478&r2=762479&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java Mon Apr  6 19:57:21 2009
@@ -181,25 +181,18 @@
         ctName.setName(name);
     }
 
-    /**
-     * Returns the reference of this named range, such as Sales!C20:C30.
-     *
-     * @return the reference of this named range
-     */
     public String getRefersToFormula() {
-        return ctName.getStringValue();
+        String result = ctName.getStringValue();
+        if (result == null || result.length() < 1) {
+            return null;
+        }
+        return result;
     }
 
-    /**
-     * Sets the reference of this named range, such as Sales!C20:C30.
-     *
-     * @param formulaText the reference to set
-     * @throws IllegalArgumentException if the specified reference is unparsable
-     */
     public void setRefersToFormula(String formulaText) {
         XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(workbook);
         try {
-            Ptg[] ptgs = FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
+            FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
         } catch (RuntimeException e) {
             if (e.getClass().getName().startsWith(FormulaParser.class.getName())) {
                 throw new IllegalArgumentException("Unparsable formula '" + formulaText + "'", e);
@@ -209,14 +202,14 @@
         ctName.setStringValue(formulaText);
     }
 
-    /**
-     * Tests if this name points to a cell that no longer exists
-     *
-     * @return true if the name refers to a deleted cell, false otherwise
-     */
     public boolean isDeleted(){
-        String ref = getRefersToFormula();
-        return ref != null && ref.indexOf("#REF!") != -1;
+        String formulaText = getRefersToFormula();
+        if (formulaText == null) {
+            return false;
+        }
+        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(workbook);
+        Ptg[] ptgs = FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex());
+        return Ptg.doesFormulaReferToDeletedCell(ptgs);
     }
 
     /**

Modified: poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestNamedRange.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestNamedRange.java?rev=762479&r1=762478&r2=762479&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestNamedRange.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestNamedRange.java Mon Apr  6 19:57:21 2009
@@ -17,13 +17,13 @@
 
 package org.apache.poi.ss.usermodel;
 
+import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
+
+import org.apache.poi.hssf.usermodel.HSSFName;
 import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.ss.formula.FormulaParser;
-import org.apache.poi.ss.formula.FormulaType;
-import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.ss.util.CellReference;
 
 /**
  * Tests of implementations of {@link org.apache.poi.ss.usermodel.Name}.
@@ -395,7 +395,7 @@
      * Test that multiple named ranges can be added written and read
      */
     public void testMultipleNamedWrite() {
-        Workbook wb	 = getTestDataProvider().createWorkbook();
+        Workbook wb = getTestDataProvider().createWorkbook();
 
 
         wb.createSheet("testSheet1");
@@ -498,4 +498,50 @@
         assertEquals("Contents of cell retrieved by its named reference", contents, cvalue);
     }
 
+    
+    /**
+     * Bugzilla attachment 23444 (from bug 46973) has a NAME record with the following encoding: 
+     * <pre>
+     * 00000000 | 18 00 17 00 00 00 00 08 00 00 00 00 00 00 00 00 | ................
+     * 00000010 | 00 00 00 55 50 53 53 74 61 74 65                | ...UPSState
+     * </pre>     
+     * 
+     * This caused trouble for anything that requires {@link HSSFName#getRefersToFormula()}
+     * It is easy enough to re-create the the same data (by not setting the formula). Excel
+     * seems to gracefully remove this uninitialized name record.  It would be nice if POI
+     * could do the same, but that would involve adjusting subsequent name indexes across 
+     * all formulas. <p/>
+     * 
+     * For the moment, POI has been made to behave more sensibly with uninitialised name 
+     * records.
+     */
+    public final void testUninitialisedNameGetRefersToFormula_bug46973() {
+        Workbook wb = getTestDataProvider().createWorkbook();
+        Name n = wb.createName();
+        n.setNameName("UPSState");
+        String formula;
+        try {
+            formula = n.getRefersToFormula();
+        } catch (IllegalArgumentException e) {
+            if (e.getMessage().equals("ptgs must not be null")) {
+                throw new AssertionFailedError("Identified bug 46973");
+            }
+            throw e;
+        }
+        assertNull(formula);
+        assertFalse(n.isDeleted()); // according to exact definition of isDeleted()
+    }
+
+    public void testDeletedCell() {
+        Workbook wb = getTestDataProvider().createWorkbook();
+        Name n = wb.createName();
+        n.setNameName("MyName");
+        // contrived example to expose bug:
+        n.setRefersToFormula("if(A1,\"#REF!\", \"\")");
+
+        if (n.isDeleted()) {
+            throw new AssertionFailedError("Identified bug in recoginising formulas referring to deleted cells");
+        }
+
+    }
 }
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org