]> source.dussan.org Git - poi.git/commitdiff
Patch to support UncalcedRecord and usermodel code for it, to indicate formulas on...
authorNick Burch <nick@apache.org>
Wed, 16 Jan 2008 13:14:31 +0000 (13:14 +0000)
committerNick Burch <nick@apache.org>
Wed, 16 Jan 2008 13:14:31 +0000 (13:14 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@612445 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/model/Sheet.java
src/java/org/apache/poi/hssf/record/RecordFactory.java
src/java/org/apache/poi/hssf/record/UncalcedRecord.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
src/testcases/org/apache/poi/hssf/data/TestDataValidation.xls
src/testcases/org/apache/poi/hssf/data/UncalcedRecord.xls [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java

index be8df6576382a27734c34309997e6a8f4255dbbf..bc95d9b7a24867a1221064ce1282d7ade4ad50fe 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">44233 - Support for getting and setting a flag on the sheet, which tells excel to re-calculate all formulas on it at next reload</action>
             <action dev="POI-DEVELOPERS" type="fix">44201 - Enable cloning of sheets with data validation rules</action>
             <action dev="POI-DEVELOPERS" type="fix">44200 - Enable cloning of sheets with notes</action>
             <action dev="POI-DEVELOPERS" type="add">43008 - Add a moveCell method to HSSFRow, and deprecate setCellNum(), which didn't update things properly</action>
index 5868b0eb2d6983c19bfe3e8aeb6dfa066582dc2a..122cab85c3f5d62ba54ece013aee971c76f0bf65 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">44233 - Support for getting and setting a flag on the sheet, which tells excel to re-calculate all formulas on it at next reload</action>
             <action dev="POI-DEVELOPERS" type="fix">44201 - Enable cloning of sheets with data validation rules</action>
             <action dev="POI-DEVELOPERS" type="fix">44200 - Enable cloning of sheets with notes</action>
             <action dev="POI-DEVELOPERS" type="add">43008 - Add a moveCell method to HSSFRow, and deprecate setCellNum(), which didn't update things properly</action>
index 59e5de3246a7a248505f7006fd4184e6acef2faf..f3f7deba07c929d25f39eed6e8b021b1be854331 100644 (file)
@@ -97,6 +97,8 @@ public class Sheet implements Model
     protected ScenarioProtectRecord      scenprotect       =     null;
     protected PasswordRecord             password          =     null;
 
+    /** Add an UncalcedRecord if not true indicating formulas have not been calculated */ 
+    protected boolean uncalced = false;
        
     public static final byte PANE_LOWER_RIGHT = (byte)0;
     public static final byte PANE_UPPER_RIGHT = (byte)1;
@@ -161,6 +163,9 @@ public class Sheet implements Model
                     break;
                 }
             }
+            else if (rec.getSid() == UncalcedRecord.sid) {
+               retval.uncalced = true; 
+            }
             else if (rec.getSid() == DimensionsRecord.sid)
             {
                 // Make a columns aggregate if one hasn't ready been created.
@@ -736,8 +741,14 @@ public class Sheet implements Model
         {
             Record record = (( Record ) records.get(k));
             
-            //Once the rows have been found in the list of records, start
-            //writing out the blocked row information. This includes the DBCell references
+            // Don't write out UncalcedRecord entries, as
+            //  we handle those specially just below
+            if (record instanceof UncalcedRecord) {
+               continue;
+            }
+            
+            // Once the rows have been found in the list of records, start
+            //  writing out the blocked row information. This includes the DBCell references
             if (record instanceof RowRecordsAggregate) {
               pos += ((RowRecordsAggregate)record).serialize(pos, data, cells);   // rec.length;
             } else if (record instanceof ValueRecordsAggregate) {
@@ -745,8 +756,14 @@ public class Sheet implements Model
             } else {
               pos += record.serialize(pos, data );   // rec.length;
             }
-            //If the BOF record was just serialized then add the IndexRecord
+            
+            // If the BOF record was just serialized then add the IndexRecord
             if (record.getSid() == BOFRecord.sid) {
+              // Add an optional UncalcedRecord
+              if (uncalced) {
+                 UncalcedRecord rec = new UncalcedRecord();
+                 pos += rec.serialize(pos, data);
+              }
               //Can there be more than one BOF for a sheet? If not then we can
               //remove this guard. So be safe it is left here.
               if (rows != null && !haveSerializedIndex) {
@@ -2184,6 +2201,11 @@ public class Sheet implements Model
                     retval += 2;
             }
         }
+        // Add space for UncalcedRecord
+        if (uncalced) {
+               retval += UncalcedRecord.getStaticRecordSize();
+        }
+        
         return retval;
     }
 
@@ -2651,8 +2673,22 @@ public class Sheet implements Model
     public boolean isDisplayRowColHeadings() {
            return windowTwo.getDisplayRowColHeadings();
     }
+    
 
     /**
+        * @return whether an uncalced record must be inserted or not at generation
+        */
+       public boolean getUncalced() {
+               return uncalced;
+       }
+       /**
+        * @param uncalced whether an uncalced record must be inserted or not at generation
+        */
+       public void setUncalced(boolean uncalced) {
+               this.uncalced = uncalced;
+       }
+
+       /**
      * Returns the array of margins.  If not created, will create.
      *
      * @return the array of marings.
index cf705a316d2a8bca396c356e14f3e587cd60be56..20e8ba788accecef918403373efaa982e34a37ee 100644 (file)
@@ -76,7 +76,7 @@ public class RecordFactory
                 WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
                 NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class, 
                 FileSharingRecord.class, ChartTitleFormatRecord.class,
-                DVRecord.class, DVALRecord.class
+                DVRecord.class, DVALRecord.class, UncalcedRecord.class
             };
     }
     private static Map           recordsMap  = recordsToMap(records);
diff --git a/src/java/org/apache/poi/hssf/record/UncalcedRecord.java b/src/java/org/apache/poi/hssf/record/UncalcedRecord.java
new file mode 100644 (file)
index 0000000..c3243f2
--- /dev/null
@@ -0,0 +1,81 @@
+/* ====================================================================
+   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 org.apache.poi.util.LittleEndian;
+
+/**
+ * Title: Uncalced Record
+ * <P>
+ * If this record occurs in the Worksheet Substream, it indicates that the formulas have not 
+ * been recalculated before the document was saved.
+ * 
+ * @author Olivier Leprince
+ */
+
+public class UncalcedRecord extends Record 
+{
+       public final static short sid = 0x5E;
+
+       /**
+        * Default constructor
+        */
+       public UncalcedRecord() {
+       }
+       /**
+        * read constructor
+        */
+       public UncalcedRecord(RecordInputStream in) {
+               super(in);
+       }
+
+       public short getSid() {
+               return sid;
+       }
+
+       protected void validateSid(short id) {
+               if (id != sid) {
+                       throw new RecordFormatException("NOT AN UNCALCED RECORD");
+               }
+       }
+
+       protected void fillFields(RecordInputStream in) {
+       }
+
+       public String toString() {
+               StringBuffer buffer = new StringBuffer();
+               buffer.append("[UNCALCED]\n");
+               buffer.append("[/UNCALCED]\n");
+               return buffer.toString();
+       }
+
+       public int serialize(int offset, byte[] data) {
+               LittleEndian.putShort(data, 0 + offset, sid);
+               LittleEndian.putShort(data, 2 + offset, (short) 2);
+               LittleEndian.putShort(data, 4 + offset, (short) 0); // unused
+               return getRecordSize();
+       }
+
+       public int getRecordSize() {
+               return UncalcedRecord.getStaticRecordSize();
+       }
+
+       public static int getStaticRecordSize() {
+               return 6;
+       }
+}
index 7fe6ea9dcb69844daab38230450b6dbcf1507162..bb779fef36b727654c8efd8713c111867325cb9e 100644 (file)
@@ -594,6 +594,26 @@ public class HSSFSheet
                 region.getColumnTo());
     }
 
+    /**
+     * Whether a record must be inserted or not at generation to indicate that 
+     * formula must be recalculated when workbook is opened.
+     * @param value true if an uncalced record must be inserted or not at generation
+     */
+    public void setForceFormulaRecalculation(boolean value)
+    {
+       sheet.setUncalced(value);
+    }
+    /**
+     * Whether a record must be inserted or not at generation to indicate that 
+     * formula must be recalculated when workbook is opened.
+     * @return true if an uncalced record must be inserted or not at generation
+     */
+    public boolean getForceFormulaRecalculation()
+    {
+       return sheet.getUncalced();
+    }
+
+    
     /**
      * determines whether the output is vertically centered on the page.
      * @param value true to vertically center, false otherwise.
index 6b71a77f2d0e03b699cecc29f6bc31f5c413e84e..556ea8192758d22c8b5427a379673771298ee08d 100644 (file)
Binary files a/src/testcases/org/apache/poi/hssf/data/TestDataValidation.xls and b/src/testcases/org/apache/poi/hssf/data/TestDataValidation.xls differ
diff --git a/src/testcases/org/apache/poi/hssf/data/UncalcedRecord.xls b/src/testcases/org/apache/poi/hssf/data/UncalcedRecord.xls
new file mode 100644 (file)
index 0000000..f1a0396
Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/UncalcedRecord.xls differ
index f0deb68e0c04479a57cb24fac2235f62daf3c158..5523638d9acaa397173aa3d9d94e05d1db1e4070 100644 (file)
 
 package org.apache.poi.hssf.usermodel;
 
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.model.Sheet;
 import org.apache.poi.hssf.record.HCenterRecord;
-import org.apache.poi.hssf.record.ProtectRecord;
 import org.apache.poi.hssf.record.PasswordRecord;
+import org.apache.poi.hssf.record.ProtectRecord;
 import org.apache.poi.hssf.record.SCLRecord;
 import org.apache.poi.hssf.record.VCenterRecord;
 import org.apache.poi.hssf.record.WSBoolRecord;
@@ -790,7 +794,81 @@ public class TestHSSFSheet
                assertTrue(sheet3.getColumnWidth((short)0) <= maxWithRow1And2);
     }
 
-       public static void main(java.lang.String[] args) {
+    /**
+     * Setting ForceFormulaRecalculation on sheets
+     */
+    public void testForceRecalculation() throws Exception {
+        String filename = System.getProperty("HSSF.testdata.path");
+        filename = filename + "/UncalcedRecord.xls";
+        HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(filename));
+        
+        HSSFSheet sheet = workbook.getSheetAt(0);
+        HSSFSheet sheet2 = workbook.getSheetAt(0);
+        HSSFRow row = sheet.getRow(0);
+        row.createCell((short) 0).setCellValue(5);
+        row.createCell((short) 1).setCellValue(8);
+               assertFalse(sheet.getForceFormulaRecalculation());
+               assertFalse(sheet2.getForceFormulaRecalculation());
+
+        // Save and manually verify that on column C we have 0, value in template
+        File tempFile = new File(System.getProperty("java.io.tmpdir")+"/uncalced_err.xls" );
+        tempFile.delete();
+        FileOutputStream fout = new FileOutputStream( tempFile );
+        workbook.write( fout );
+        fout.close();
+        sheet.setForceFormulaRecalculation(true);
+               assertTrue(sheet.getForceFormulaRecalculation());
+
+        // Save and manually verify that on column C we have now 13, calculated value
+        tempFile = new File(System.getProperty("java.io.tmpdir")+"/uncalced_succ.xls" );
+        tempFile.delete();
+        fout = new FileOutputStream( tempFile );
+        workbook.write( fout );
+        fout.close();
+
+        // Try it can be opened
+               HSSFWorkbook wb2 = new HSSFWorkbook(new FileInputStream(tempFile));
+               
+               // And check correct sheet settings found
+               sheet = wb2.getSheetAt(0);
+               sheet2 = wb2.getSheetAt(1);
+               assertTrue(sheet.getForceFormulaRecalculation());
+               assertFalse(sheet2.getForceFormulaRecalculation());
+               
+               // Now turn if back off again
+               sheet.setForceFormulaRecalculation(false);
+               
+        fout = new FileOutputStream( tempFile );
+        wb2.write( fout );
+        fout.close();
+        wb2 = new HSSFWorkbook(new FileInputStream(tempFile));
+        
+               assertFalse(wb2.getSheetAt(0).getForceFormulaRecalculation());
+               assertFalse(wb2.getSheetAt(1).getForceFormulaRecalculation());
+               assertFalse(wb2.getSheetAt(2).getForceFormulaRecalculation());
+               
+               // Now add a new sheet, and check things work
+               //  with old ones unset, new one set
+               HSSFSheet s4 = wb2.createSheet();
+               s4.setForceFormulaRecalculation(true);
+               
+               assertFalse(sheet.getForceFormulaRecalculation());
+               assertFalse(sheet2.getForceFormulaRecalculation());
+               assertTrue(s4.getForceFormulaRecalculation());
+               
+        fout = new FileOutputStream( tempFile );
+        wb2.write( fout );
+        fout.close();
+        
+               HSSFWorkbook wb3 = new HSSFWorkbook(new FileInputStream(tempFile));
+               assertFalse(wb3.getSheetAt(0).getForceFormulaRecalculation());
+               assertFalse(wb3.getSheetAt(1).getForceFormulaRecalculation());
+               assertFalse(wb3.getSheetAt(2).getForceFormulaRecalculation());
+               assertTrue(wb3.getSheetAt(3).getForceFormulaRecalculation());
+    }
+
+    
+    public static void main(java.lang.String[] args) {
                 junit.textui.TestRunner.run(TestHSSFSheet.class);
        }    
 }