<!-- 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>
<!-- 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>
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;
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.
{
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) {
} 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) {
retval += 2;
}
}
+ // Add space for UncalcedRecord
+ if (uncalced) {
+ retval += UncalcedRecord.getStaticRecordSize();
+ }
+
return retval;
}
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.
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);
--- /dev/null
+/* ====================================================================
+ 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;
+ }
+}
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.
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;
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);
}
}