mirror of https://github.com/apache/poi.git
Patch to support UncalcedRecord and usermodel code for it, to indicate formulas on a sheet need recalculating (from bug #44233)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@612445 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0034e00a5c
commit
7618be0d35
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -19,14 +19,18 @@
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue