diff --git a/src/java/org/apache/poi/hssf/dev/BiffViewer.java b/src/java/org/apache/poi/hssf/dev/BiffViewer.java
index a2ac1a767..da65d5920 100644
--- a/src/java/org/apache/poi/hssf/dev/BiffViewer.java
+++ b/src/java/org/apache/poi/hssf/dev/BiffViewer.java
@@ -630,6 +630,9 @@ public class BiffViewer {
case PaneRecord.sid:
retval = new PaneRecord( rectype, size, data );
break;
+ case SharedFormulaRecord.sid:
+ retval = new SharedFormulaRecord( rectype, size, data);
+ break;
default:
retval = new UnknownRecord( rectype, size, data );
}
diff --git a/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java b/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java
index 8bec71223..3b5765288 100644
--- a/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java
+++ b/src/java/org/apache/poi/hssf/eventmodel/EventRecordFactory.java
@@ -54,12 +54,14 @@
*/
package org.apache.poi.hssf.eventmodel;
-import java.io.InputStream;
import java.io.IOException;
-
-import java.util.*;
-
+import java.io.InputStream;
import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BackupRecord;
@@ -126,6 +128,7 @@ import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.SaveRecalcRecord;
import org.apache.poi.hssf.record.SelectionRecord;
+import org.apache.poi.hssf.record.SharedFormulaRecord;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.record.StyleRecord;
import org.apache.poi.hssf.record.TabIdRecord;
@@ -189,7 +192,7 @@ public class EventRecordFactory
BoolErrRecord.class, ExternSheetRecord.class, NameRecord.class,
LeftMarginRecord.class, RightMarginRecord.class,
TopMarginRecord.class, BottomMarginRecord.class,
- PaletteRecord.class, StringRecord.class
+ PaletteRecord.class, StringRecord.class, SharedFormulaRecord.class
};
}
diff --git a/src/java/org/apache/poi/hssf/record/RecordFactory.java b/src/java/org/apache/poi/hssf/record/RecordFactory.java
index 83bd7c637..f12f903b0 100644
--- a/src/java/org/apache/poi/hssf/record/RecordFactory.java
+++ b/src/java/org/apache/poi/hssf/record/RecordFactory.java
@@ -112,7 +112,7 @@ public class RecordFactory
FormulaRecord.class, BoolErrRecord.class, ExternSheetRecord.class,
NameRecord.class, LeftMarginRecord.class, RightMarginRecord.class,
TopMarginRecord.class, BottomMarginRecord.class,
- PaletteRecord.class, StringRecord.class, RecalcIdRecord.class
+ PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class
};
} else {
records = new Class[]
@@ -143,7 +143,7 @@ public class RecordFactory
BoolErrRecord.class, ExternSheetRecord.class, NameRecord.class,
LeftMarginRecord.class, RightMarginRecord.class,
TopMarginRecord.class, BottomMarginRecord.class,
- PaletteRecord.class, StringRecord.class, RecalcIdRecord.class
+ PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class
};
}
diff --git a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java
new file mode 100755
index 000000000..eb4482369
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java
@@ -0,0 +1,191 @@
+
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *
+ * Note: the documentation says that the SID is BC where biffviewer reports 4BC. The hex dump shows
+ * that the two byte sid representation to be 'BC 04' that is consistent with the other high byte
+ * record types.
+ * @author Danny Mui at apache dot org
+ */
+
+public class SharedFormulaRecord
+ extends Record
+{
+ public final static short sid = 0x4BC;
+ private short size = 0;
+ private byte[] thedata = null;
+ int offset = 0;
+
+ public SharedFormulaRecord()
+ {
+ }
+
+ /**
+ * construct the sharedformula record, save all the information
+ * @param id id of the record -not validated, just stored for serialization
+ * @param size size of the data
+ * @param data the data
+ */
+
+ public SharedFormulaRecord(short id, short size, byte [] data)
+ {
+ super(id, size, data);
+
+ this.fillFields(data, size, 0);
+ }
+
+ /**
+ * spit the record out AS IS. no interperatation or identification
+ */
+
+ public int serialize(int offset, byte [] data)
+ {
+ if (thedata == null)
+ {
+ thedata = new byte[ 0 ];
+ }
+ LittleEndian.putShort(data, 0 + offset, sid);
+ LittleEndian.putShort(data, 2 + offset, ( short ) (thedata.length));
+ if (thedata.length > 0)
+ {
+ System.arraycopy(thedata, 0, data, 4 + offset, thedata.length);
+ }
+ return getRecordSize();
+ }
+
+ public int getRecordSize()
+ {
+ int retval = 4;
+
+ if (thedata != null)
+ {
+ retval += thedata.length;
+ }
+ return retval;
+ }
+
+
+ protected void validateSid(short id)
+ {
+ if (id != this.sid)
+ {
+ throw new RecordFormatException("Not a valid SharedFormula");
+ }
+
+ }
+
+ /**
+ * print a sort of string representation ([SHARED FORMULA RECORD] id = x [/SHARED FORMULA RECORD])
+ */
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("[SHARED FORMULA RECORD:" + Integer.toHexString(sid) + "]\n");
+ buffer.append(" .id = ").append(Integer.toHexString(sid))
+ .append("\n");
+ buffer.append("[/SHARED FORMULA RECORD]\n");
+ return buffer.toString();
+ }
+
+ public short getSid()
+ {
+ return this.sid;
+ }
+
+ /**
+ * Shared formulas are to treated like unknown records, and as a result d
+ */
+ protected void fillFields(byte [] data, short size, int offset)
+ {
+ thedata = new byte[size];
+ System.arraycopy(data, 0, thedata, 0, size);
+
+ }
+
+ /**
+ * Mirroring formula records so it is registered in the ValueRecordsAggregate
+ */
+ public boolean isInValueSection()
+ {
+ return true;
+ }
+
+
+ /**
+ * Register it in the ValueRecordsAggregate so it can go into the FormulaRecordAggregate
+ */
+ public boolean isValue() {
+ return true;
+ }
+
+ public Object clone() {
+ SharedFormulaRecord rec = new SharedFormulaRecord();
+ rec.offset = offset;
+ rec.size = size;
+ rec.thedata = thedata;
+ return rec;
+ }
+}
diff --git a/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java
index 82d168bf8..7d5b0b048 100644
--- a/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java
+++ b/src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java
@@ -58,7 +58,7 @@ import org.apache.poi.hssf.record.*;
/**
* The formula record aggregate is used to join together the formula record and it's
- * (optional) string record.
+ * (optional) string record and (optional) Shared Formula Record (template reads, excel optimization).
*
* @author Glen Stampoultzis (glens at apache.org)
*/
@@ -70,6 +70,11 @@ public class FormulaRecordAggregate
private FormulaRecord formulaRecord;
private StringRecord stringRecord;
+
+ /**
+ * will only be set through the RecordFactory
+ */
+ private SharedFormulaRecord sharedFormulaRecord;
public FormulaRecordAggregate( FormulaRecord formulaRecord, StringRecord stringRecord )
{
@@ -105,7 +110,12 @@ public class FormulaRecordAggregate
{
pos += stringRecord.serialize(pos, data);
}
+ if (this.getSharedFormulaRecord() != null)
+ {
+ pos += getSharedFormulaRecord().serialize(pos, data);
+ }
return pos - offset;
+
}
/**
@@ -114,6 +124,7 @@ public class FormulaRecordAggregate
public int getRecordSize()
{
int size = formulaRecord.getRecordSize() + (stringRecord == null ? 0 : stringRecord.getRecordSize());
+ size += (getSharedFormulaRecord() == null) ? 0 : getSharedFormulaRecord().getRecordSize();
return size;
}
@@ -215,4 +226,19 @@ public class FormulaRecordAggregate
+ /**
+ * @return SharedFormulaRecord
+ */
+ public SharedFormulaRecord getSharedFormulaRecord() {
+ return sharedFormulaRecord;
+ }
+
+ /**
+ * Sets the sharedFormulaRecord, only set from RecordFactory since they are not generated by POI and are an Excel optimization
+ * @param sharedFormulaRecord The sharedFormulaRecord to set
+ */
+ public void setSharedFormulaRecord(SharedFormulaRecord sharedFormulaRecord) {
+ this.sharedFormulaRecord = sharedFormulaRecord;
+ }
+
}
diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java
index fae69130e..d985ac84f 100644
--- a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java
+++ b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java
@@ -157,6 +157,11 @@ public class ValueRecordsAggregate
{
lastFormulaAggregate.setStringRecord((StringRecord)rec);
}
+ else if (rec instanceof SharedFormulaRecord)
+ {
+ //these follow the first formula in a group
+ lastFormulaAggregate.setSharedFormulaRecord((SharedFormulaRecord)rec);
+ }
else if (rec.isValue())
{
insertCell(( CellValueRecordInterface ) rec);
diff --git a/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java b/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java
index 8b182230e..576bce331 100644
--- a/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java
+++ b/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java
@@ -66,6 +66,7 @@ import org.apache.poi.hssf.util.SheetReferences;
*
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
+ * @author dmui (save existing implementation)
*/
public class ExpPtg
@@ -73,6 +74,7 @@ public class ExpPtg
{
private final static int SIZE = 5;
public final static short sid = 0x1;
+ private byte[] existing = null;
/** Creates new ExpPtg */
@@ -84,10 +86,15 @@ public class ExpPtg
public ExpPtg(byte [] array, int offset)
{
+ existing = new byte[this.getSize()];
+ System.arraycopy(array, offset, existing, 0, this.getSize());
}
public void writeBytes(byte [] array, int offset)
{
+ if (existing != null) {
+ System.arraycopy(existing, 0, array, offset, existing.length);
+ }
}
public int getSize()
diff --git a/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java b/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java
index 0efdd7c71..2ab793d5e 100644
--- a/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java
+++ b/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java
@@ -121,6 +121,30 @@ public class TestFormulaRecord
}
+ /**
+ * Tests to see if the shared formula cells properly reserialize the expPtg
+ *
+ */
+ public void testExpFormula() {
+ byte[] formulaByte = new byte[27];
+
+ for (int i = 0; i < formulaByte.length; i++) formulaByte[i] = (byte)0;
+
+ formulaByte[4] =(byte)0x0F;
+ formulaByte[14]=(byte)0x08;
+ formulaByte[18]=(byte)0xE0;
+ formulaByte[19]=(byte)0xFD;
+ formulaByte[20]=(byte)0x05;
+ formulaByte[22]=(byte)0x01;
+ FormulaRecord record = new FormulaRecord(FormulaRecord.sid, (short)27, formulaByte);
+ assertEquals("Row", 0, record.getRow());
+ assertEquals("Column", 0, record.getColumn());
+ byte[] output = record.serialize();
+ assertEquals("Output size", 31, output.length); //includes sid+recordlength
+ assertEquals("Offset 22", 1, output[26]);
+ }
+
+
public static void main(String [] ignored_args)
{
String filename = System.getProperty("HSSF.testdata.path");
diff --git a/src/testcases/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java b/src/testcases/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java
new file mode 100755
index 000000000..9088f118d
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java
@@ -0,0 +1,96 @@
+
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *