]> source.dussan.org Git - poi.git/commitdiff
Fix for bug 45123 - SharedFormulaRecord.convertSharedFormulas was ignoring token...
authorJosh Micich <josh@apache.org>
Thu, 5 Jun 2008 03:12:35 +0000 (03:12 +0000)
committerJosh Micich <josh@apache.org>
Thu, 5 Jun 2008 03:12:35 +0000 (03:12 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@663436 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java
src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java [new file with mode: 0644]

index 08aebb79d0d8eaa228ea46baf57cb92e08f61228..5cc5a00e0cb980e55e9db721a5100f39173775b0 100644 (file)
@@ -37,6 +37,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.1-final" date="2008-06-??">
+           <action dev="POI-DEVELOPERS" type="fix">45123 - Fixed SharedFormulaRecord.convertSharedFormulas() to propagate token operand classes</action>
            <action dev="POI-DEVELOPERS" type="fix">45087 - Correctly detect date formats like [Black]YYYY as being date based</action>
            <action dev="POI-DEVELOPERS" type="add">45060 - Improved token class transformation during formula parsing</action>
            <action dev="POI-DEVELOPERS" type="add">44840 - Improved handling of HSSFObjectData, especially for entries with data held not in POIFS</action>
index 0431bd3fdeecdb990e087abe80d907d01b1e02e2..b8c44d9b9dd8687b8b6b10696e12af219863a9d2 100644 (file)
@@ -34,6 +34,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.1-final" date="2008-06-??">
+           <action dev="POI-DEVELOPERS" type="fix">45123 - Fixed SharedFormulaRecord.convertSharedFormulas() to propagate token operand classes</action>
            <action dev="POI-DEVELOPERS" type="fix">45087 - Correctly detect date formats like [Black]YYYY as being date based</action>
            <action dev="POI-DEVELOPERS" type="add">45060 - Improved token class transformation during formula parsing</action>
            <action dev="POI-DEVELOPERS" type="add">44840 - Improved handling of HSSFObjectData, especially for entries with data held not in POIFS</action>
index 2b0c50d122675828157fe158fd89486acbaa55bc..e4c0f28ea48ba047abce5957787d2a6f5d683765 100755 (executable)
@@ -201,6 +201,10 @@ public final class SharedFormulaRecord extends Record {
         if (ptgs != null)
           for (int k = 0; k < ptgs.size(); k++) {
             Ptg ptg = (Ptg) ptgs.get(k);
+            byte originalOperandClass = -1;
+            if (!ptg.isBaseToken()) {
+                originalOperandClass = ptg.getPtgClass();
+            }
             if (ptg instanceof RefNPtg) {
               RefNPtg refNPtg = (RefNPtg)ptg;
               ptg = new ReferencePtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()),
@@ -249,7 +253,11 @@ public final class SharedFormulaRecord extends Record {
                                 areaNAPtg.isLastRowRelative(),
                                 areaNAPtg.isFirstColRelative(),
                                 areaNAPtg.isLastColRelative());
-            } 
+            }
+            if (!ptg.isBaseToken()) {
+                ptg.setClass(originalOperandClass);
+            }
+            
             newPtgStack.add(ptg);
         }
         return newPtgStack;
index 2b8e3c3ab557f2c6dd95a3ce4d63f778517c1348..988be1dac5ef7303ff03314764819ba6c4910a68 100755 (executable)
@@ -95,6 +95,7 @@ public final class AllRecordTests {
                result.addTestSuite(TestSeriesTextRecord.class);
                result.addTestSuite(TestSeriesToChartGroupRecord.class);
                result.addTestSuite(TestSheetPropertiesRecord.class);
+               result.addTestSuite(TestSharedFormulaRecord.class);
                result.addTestSuite(TestStringRecord.class);
                result.addTestSuite(TestSubRecord.class);
                result.addTestSuite(TestSupBookRecord.class);
diff --git a/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java b/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java
new file mode 100644 (file)
index 0000000..cb08ede
--- /dev/null
@@ -0,0 +1,97 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record;
+
+import java.util.List;
+import java.util.Stack;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.ComparisonFailure;
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.RefAPtg;
+
+/**
+ * @author Josh Micich
+ */
+public final class TestSharedFormulaRecord extends TestCase {
+
+       /**
+        * Binary data for an encoded formula.  Taken from attachment 22062 (bugzilla 45123/45421).
+        * The shared formula is in Sheet1!C6:C21, with text "SUMPRODUCT(--(End_Acct=$C6),--(End_Bal))"
+        * This data is found at offset 0x1A4A (within the shared formula record).
+        * The critical thing about this formula is that it contains shared formula tokens (tRefN*,
+        * tAreaN*) with operand class 'array'.
+        */
+       private static final byte[] SHARED_FORMULA_WITH_REF_ARRAYS_DATA = {
+               0x1A, 0x00,
+               0x63, 0x02, 0x00, 0x00, 0x00,
+               0x6C, 0x00, 0x00, 0x02, (byte)0x80,  // tRefNA
+               0x0B,
+               0x15,
+               0x13,
+               0x13,
+               0x63, 0x03, 0x00, 0x00, 0x00,
+               0x15,
+               0x13,
+               0x13,
+               0x42, 0x02, (byte)0xE4, 0x00,
+       };
+       
+       /**
+        * The method <tt>SharedFormulaRecord.convertSharedFormulas()</tt> converts formulas from
+        * 'shared formula' to 'single cell formula' format.  It is important that token operand
+        * classes are preserved during this transformation, because Excel may not tolerate the
+        * incorrect encoding.  The formula here is one such example (Excel displays #VALUE!).
+        */
+       public void testConvertSharedFormulasOperandClasses_bug45123() {
+               
+               TestcaseRecordInputStream in = new TestcaseRecordInputStream(0, SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
+               short encodedLen = in.readShort();
+               Stack sharedFormula = Ptg.createParsedExpressionTokens(encodedLen, in);
+               
+               Stack convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 100, 200);
+               
+               RefAPtg refPtg = (RefAPtg) convertedFormula.get(1);
+               assertEquals("$C101", refPtg.toFormulaString(null));
+               if (refPtg.getPtgClass() == Ptg.CLASS_REF) {
+                       throw new AssertionFailedError("Identified bug 45123");
+               }
+               
+               confirmOperandClasses(toPtgArray(sharedFormula), toPtgArray(convertedFormula));
+       }
+
+       private static void confirmOperandClasses(Ptg[] originalPtgs, Ptg[] convertedPtgs) {
+               assertEquals(originalPtgs.length, convertedPtgs.length);
+               for (int i = 0; i < convertedPtgs.length; i++) {
+                       Ptg originalPtg = originalPtgs[i];
+                       Ptg convertedPtg = convertedPtgs[i];
+                       if (originalPtg.getPtgClass() != convertedPtg.getPtgClass()) {
+                               throw new ComparisonFailure("Different operand class for token[" + i + "]",
+                                               String.valueOf(originalPtg.getPtgClass()), String.valueOf(convertedPtg.getPtgClass()));
+                       }
+               }
+       }
+
+       private static Ptg[] toPtgArray(List list) {
+               Ptg[] result = new Ptg[list.size()];
+               list.toArray(result);
+               return result;
+       }
+}