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
18a4647b24
commit
33602b0c80
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.0.2-FINAL" date="2008-??-??">
|
<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">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="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>
|
<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! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.0.2-FINAL" date="2008-??-??">
|
<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">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="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>
|
<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 ScenarioProtectRecord scenprotect = null;
|
||||||
protected PasswordRecord password = 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_LOWER_RIGHT = (byte)0;
|
||||||
public static final byte PANE_UPPER_RIGHT = (byte)1;
|
public static final byte PANE_UPPER_RIGHT = (byte)1;
|
||||||
@ -161,6 +163,9 @@ public class Sheet implements Model
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (rec.getSid() == UncalcedRecord.sid) {
|
||||||
|
retval.uncalced = true;
|
||||||
|
}
|
||||||
else if (rec.getSid() == DimensionsRecord.sid)
|
else if (rec.getSid() == DimensionsRecord.sid)
|
||||||
{
|
{
|
||||||
// Make a columns aggregate if one hasn't ready been created.
|
// 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));
|
Record record = (( Record ) records.get(k));
|
||||||
|
|
||||||
//Once the rows have been found in the list of records, start
|
// Don't write out UncalcedRecord entries, as
|
||||||
//writing out the blocked row information. This includes the DBCell references
|
// 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) {
|
if (record instanceof RowRecordsAggregate) {
|
||||||
pos += ((RowRecordsAggregate)record).serialize(pos, data, cells); // rec.length;
|
pos += ((RowRecordsAggregate)record).serialize(pos, data, cells); // rec.length;
|
||||||
} else if (record instanceof ValueRecordsAggregate) {
|
} else if (record instanceof ValueRecordsAggregate) {
|
||||||
@ -745,8 +756,14 @@ public class Sheet implements Model
|
|||||||
} else {
|
} else {
|
||||||
pos += record.serialize(pos, data ); // rec.length;
|
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) {
|
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
|
//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.
|
//remove this guard. So be safe it is left here.
|
||||||
if (rows != null && !haveSerializedIndex) {
|
if (rows != null && !haveSerializedIndex) {
|
||||||
@ -2184,6 +2201,11 @@ public class Sheet implements Model
|
|||||||
retval += 2;
|
retval += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Add space for UncalcedRecord
|
||||||
|
if (uncalced) {
|
||||||
|
retval += UncalcedRecord.getStaticRecordSize();
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2652,6 +2674,20 @@ public class Sheet implements Model
|
|||||||
return windowTwo.getDisplayRowColHeadings();
|
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.
|
* Returns the array of margins. If not created, will create.
|
||||||
*
|
*
|
||||||
|
@ -76,7 +76,7 @@ public class RecordFactory
|
|||||||
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
|
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
|
||||||
NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class,
|
NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class,
|
||||||
FileSharingRecord.class, ChartTitleFormatRecord.class,
|
FileSharingRecord.class, ChartTitleFormatRecord.class,
|
||||||
DVRecord.class, DVALRecord.class
|
DVRecord.class, DVALRecord.class, UncalcedRecord.class
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
private static Map recordsMap = recordsToMap(records);
|
private static Map recordsMap = recordsToMap(records);
|
||||||
|
81
src/java/org/apache/poi/hssf/record/UncalcedRecord.java
Normal file
81
src/java/org/apache/poi/hssf/record/UncalcedRecord.java
Normal file
@ -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());
|
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.
|
* determines whether the output is vertically centered on the page.
|
||||||
* @param value true to vertically center, false otherwise.
|
* @param value true to vertically center, false otherwise.
|
||||||
|
Binary file not shown.
BIN
src/testcases/org/apache/poi/hssf/data/UncalcedRecord.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/UncalcedRecord.xls
Normal file
Binary file not shown.
@ -19,14 +19,18 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.usermodel;
|
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 junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hssf.model.Sheet;
|
import org.apache.poi.hssf.model.Sheet;
|
||||||
import org.apache.poi.hssf.record.HCenterRecord;
|
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.PasswordRecord;
|
||||||
|
import org.apache.poi.hssf.record.ProtectRecord;
|
||||||
import org.apache.poi.hssf.record.SCLRecord;
|
import org.apache.poi.hssf.record.SCLRecord;
|
||||||
import org.apache.poi.hssf.record.VCenterRecord;
|
import org.apache.poi.hssf.record.VCenterRecord;
|
||||||
import org.apache.poi.hssf.record.WSBoolRecord;
|
import org.apache.poi.hssf.record.WSBoolRecord;
|
||||||
@ -790,6 +794,80 @@ public class TestHSSFSheet
|
|||||||
assertTrue(sheet3.getColumnWidth((short)0) <= maxWithRow1And2);
|
assertTrue(sheet3.getColumnWidth((short)0) <= maxWithRow1And2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
public static void main(java.lang.String[] args) {
|
||||||
junit.textui.TestRunner.run(TestHSSFSheet.class);
|
junit.textui.TestRunner.run(TestHSSFSheet.class);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user