This commit was manufactured by cvs2svn to create tag 'before21444'.

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/tags/before21444@353314 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
No Author 2003-08-23 19:18:19 +00:00
parent a70452b9dd
commit 8f25bb9dc2
81 changed files with 3241 additions and 679 deletions

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/testcases"/>
<classpathentry kind="src" path="src/java"/>
<classpathentry kind="src" path="src/examples/src"/>
<classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/>
<classpathentry kind="lib" path="tools/cents/junit.cent/lib/junit-3.7.jar"/>
<classpathentry kind="lib" path="lib/core/commons-logging-1.0.jar"/>
<classpathentry kind="output" path="build"/>
</classpath>

View File

@ -1,4 +1,5 @@
dist dist
build
scripts scripts
*.el *.el
*.ipr *.ipr
@ -8,3 +9,5 @@ build.number
log*.* log*.*
*.log *.log
build build
.classpath
.project

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>POI</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -6,7 +6,7 @@
Glen Stampoultzis glens at apache.org Glen Stampoultzis glens at apache.org
This build was tested with and 1.5.3 although it will probably work with This build was tested with ant 1.5.3 although it will probably work with
other versions. The following jar files should be installed other versions. The following jar files should be installed
into the ant lib directory: into the ant lib directory:
@ -15,6 +15,7 @@
junit(3.8+) http://www.ibiblio.org/maven/junit/jars/ junit(3.8+) http://www.ibiblio.org/maven/junit/jars/
xerces http://www.ibiblio.org/maven/xerces/jars/ xerces http://www.ibiblio.org/maven/xerces/jars/
jdepend http://www.ibiblio.org/maven/jdepend/jars/ jdepend http://www.ibiblio.org/maven/jdepend/jars/
xalan http://www.ibiblio.org/maven/xalan/jars/
The ant jar "optional.jar" should also be available otherwise the The ant jar "optional.jar" should also be available otherwise the
build will fail. build will fail.
@ -82,7 +83,7 @@
<property name="changelog.file" value="${build.site}/changelog.html"/> <property name="changelog.file" value="${build.site}/changelog.html"/>
<property name="dist.dir" value="build/dist"/> <property name="dist.dir" value="build/dist"/>
<property name="jar.name" value="poi"/> <property name="jar.name" value="poi"/>
<property name="version.id" value="2.0-pre1"/> <property name="version.id" value="2.0-pre3"/>
<property name="halt.on.test.failure" value="true"/> <property name="halt.on.test.failure" value="true"/>
<path id="main.classpath"> <path id="main.classpath">
@ -141,14 +142,17 @@
<target name="check-jars"> <target name="check-jars">
<condition property="jars.present"> <condition property="jars.present">
<or>
<and> <and>
<available file="${main.jar1.dir}"/> <available file="${main.jar1.dir}"/>
<available file="${main.jar2.dir}"/> <available file="${main.jar2.dir}"/>
<available file="${contrib.jar1.dir}"/> <available file="${contrib.jar1.dir}"/>
<available file="${contrib.jar2.dir}"/> <available file="${contrib.jar2.dir}"/>
<available file="${contrib.jar3.dir}"/> <available file="${contrib.jar3.dir}"/>
<available file="${junit.jar1.dir}"/> <available file="${junit.jar1.dir}"/>
</and> </and>
<isset property="disconnected"/>
</or>
</condition> </condition>
</target> </target>
@ -214,15 +218,16 @@
</uptodate> </uptodate>
</target> </target>
<target name="test-main" depends="compile-main,-test-main-check" unless="main.test.notRequired"> <path id="test.classpath">
<junit printsummary="yes" showoutput="true" filtertrace="no" fork="no"
haltonfailure="${halt.on.test.failure}" failureproperty="main.test.failed">
<classpath>
<path refid="main.classpath"/> <path refid="main.classpath"/>
<pathelement location="${main.output.dir}"/> <pathelement location="${main.output.dir}"/>
<pathelement location="${main.output.test.dir}"/> <pathelement location="${main.output.test.dir}"/>
<pathelement location="${junit.jar1.dir}"/> <pathelement location="${junit.jar1.dir}"/>
</classpath> </path>
<target name="test-main" depends="compile-main,-test-main-check" unless="main.test.notRequired">
<junit printsummary="yes" showoutput="true" filtertrace="no" fork="no"
haltonfailure="${halt.on.test.failure}" failureproperty="main.test.failed">
<classpath refid="test.classpath"/>
<sysproperty key="HSSF.testdata.path" value="${main.src.test}/org/apache/poi/hssf/data"/> <sysproperty key="HSSF.testdata.path" value="${main.src.test}/org/apache/poi/hssf/data"/>
<sysproperty key="HPSF.testdata.path" value="${main.src.test}/org/apache/poi/hpsf/data"/> <sysproperty key="HPSF.testdata.path" value="${main.src.test}/org/apache/poi/hpsf/data"/>
<formatter type="plain"/> <formatter type="plain"/>
@ -238,14 +243,9 @@
<antcall target="-test-main-write-testfile"/> <antcall target="-test-main-write-testfile"/>
</target> </target>
<target name="single-test" depends="compile-main"> <target name="single-test" depends="-test-property-check,compile-main">
<junit printsummary="no" showoutput="true" filtertrace="no" fork="no" haltonfailure="${halt.on.test.failure}" failureproperty="main.test.failed" > <junit printsummary="no" showoutput="true" filtertrace="no" haltonfailure="${halt.on.test.failure}" failureproperty="main.test.failed" >
<classpath> <classpath refid="test.classpath"/>
<path refid="main.classpath"/>
<pathelement location="${main.output.dir}"/>
<pathelement location="${main.output.test.dir}"/>
<pathelement location="${junit.jar1.dir}"/>
</classpath>
<sysproperty key="HSSF.testdata.path" value="${main.src.test}/org/apache/poi/hssf/data"/> <sysproperty key="HSSF.testdata.path" value="${main.src.test}/org/apache/poi/hssf/data"/>
<sysproperty key="HPSF.testdata.path" value="${main.src.test}/org/apache/poi/hpsf/data"/> <sysproperty key="HPSF.testdata.path" value="${main.src.test}/org/apache/poi/hpsf/data"/>
<formatter type="plain" usefile="no"/> <formatter type="plain" usefile="no"/>
@ -254,6 +254,24 @@
</junit> </junit>
</target> </target>
<target name="debug-test" depends="-test-property-check,compile-main">
<junit printsummary="no" showoutput="true" filtertrace="no" fork="yes" haltonfailure="${halt.on.test.failure}" failureproperty="main.test.failed" >
<jvmarg value="-Xdebug"/>
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=5001,server=y,suspend=y"/>
<sysproperty key="java.compiler" value="NONE"/>
<classpath refid="test.classpath"/>
<sysproperty key="HSSF.testdata.path" value="${main.src.test}/org/apache/poi/hssf/data"/>
<sysproperty key="HPSF.testdata.path" value="${main.src.test}/org/apache/poi/hpsf/data"/>
<formatter type="plain" usefile="no"/>
<test name="${testcase}" />
</junit>
</target>
<target name="-test-property-check" unless="testcase">
<echo message="Please use -Dtestcase=org.your.testcase to run a single test"/>
<fail/>
</target>
<target name="-test-main-write-testfile" unless="main.test.failed"> <target name="-test-main-write-testfile" unless="main.test.failed">
<echo file="${main.testokfile}" append="false" message="testok"/> <echo file="${main.testokfile}" append="false" message="testok"/>
</target> </target>
@ -334,11 +352,10 @@
</target> </target>
<target name="-check-forrest-installed" unless="env.FORREST_HOME"> <target name="-check-forrest-installed" unless="env.FORREST_HOME">
<echo> <echo>Please install Apache Forrest (see
Please install apache forrest and set the &lt;http://xml.apache.org/forrest/index.html&gt;) and set the
FORREST_HOME environment variable. FORREST_HOME environment variable!</echo>
</echo> <fail message="Apache Forrest is not installed."/>
<fail/>
</target> </target>
<!-- <target name="check-docs">--> <!-- <target name="check-docs">-->
@ -386,6 +403,18 @@
</condition> </condition>
</target> </target>
<target name="-cvschangelog" unless="disconnected">
<cvschangelog destfile="${changelog.file}" daysinpast="30"/>
<style in="${changelog.file}"
out="${build.site.src}/src/documentation/content/changelog.html"
style="changelog.xsl">
<param name="title" expression="POI Change Log"/>
<param name="module" expression="jakarta-poi"/>
<param name="cvsweb" expression="http://cvs.apache.org/viewcvs/"/>
</style>
</target>
<target name="reports" depends="-check-reports" unless="reports.notRequired" <target name="reports" depends="-check-reports" unless="reports.notRequired"
description="Creates junit,jdepend and javadoc reports"> description="Creates junit,jdepend and javadoc reports">
<antcall target="test"> <antcall target="test">
@ -425,15 +454,7 @@
out="${jdepend.report.out.dir}/index.html" out="${jdepend.report.out.dir}/index.html"
style="jdepend.xsl"/> style="jdepend.xsl"/>
<cvschangelog destfile="${changelog.file}" daysinpast="30"/> <antcall target="-cvschangelog"/>
<style in="${changelog.file}"
out="${build.site.src}/src/documentation/content/changelog.html"
style="changelog.xsl">
<param name="title" expression="POI Change Log"/>
<param name="module" expression="jakarta-poi"/>
<param name="cvsweb" expression="http://cvs.apache.org/viewcvs/"/>
</style>
<javadoc <javadoc
destdir="${apidocs.report.dir}" destdir="${apidocs.report.dir}"
@ -547,9 +568,9 @@
<tar destfile="${dist.dir}/${jar.name}-bin-${version.id}-${DSTAMP}.tar.gz" compression="gzip"> <tar destfile="${dist.dir}/${jar.name}-bin-${version.id}-${DSTAMP}.tar.gz" compression="gzip">
<tarfileset dir="${build.site}" prefix="docs"/> <tarfileset dir="${build.site}" prefix="docs"/>
<tarfileset file="${dist.dir}/${jar.name}-${version.id}.jar"/> <tarfileset file="${dist.dir}/${jar.name}-${version.id}-${DSTAMP}.jar"/>
<tarfileset file="${dist.dir}/${jar.name}-contrib-${version.id}.jar"/> <tarfileset file="${dist.dir}/${jar.name}-contrib-${version.id}-${DSTAMP}.jar"/>
<tarfileset file="${dist.dir}/${jar.name}-scratchpad-${version.id}.jar"/> <tarfileset file="${dist.dir}/${jar.name}-scratchpad-${version.id}-${DSTAMP}.jar"/>
<tarfileset dir="legal" prefix="legal"/> <tarfileset dir="legal" prefix="legal"/>
</tar> </tar>
@ -570,6 +591,6 @@
<target name="clean-dist" depends="clean,dist" description="Cleans the build directory then creates a distribution"/> <target name="clean-dist" depends="clean,dist" description="Cleans the build directory then creates a distribution"/>
<target name="gump" depends="jar"/> <target name="gump" depends="jar,test"/>
</project> </project>

View File

@ -46,6 +46,10 @@
<td>jdepend</td> <td>jdepend</td>
<td>http://www.ibiblio.org/maven/jdepend/jars/</td> <td>http://www.ibiblio.org/maven/jdepend/jars/</td>
</tr> </tr>
<tr>
<td>xalan</td>
<td>http://www.ibiblio.org/maven/xalan/jars/</td>
</tr>
</table> </table>
<p> <p>
Just pick the latest versions of these jars and place Just pick the latest versions of these jars and place

View File

@ -18,11 +18,15 @@
<section><title>Purpose</title> <section><title>Purpose</title>
<p> <p>
The POI project consists of APIs for manipulating various file formats The POI project consists of APIs for manipulating various file formats
based upon Microsoft's OLE 2 Compound Document format using pure Java. based upon Microsoft's OLE 2 Compound Document format using pure Java. In short, you can
read and write MS Excel files using Java. Soon, you'll be able to read and write
Word files using Java. POI is your Java Excel solution as well as your Word Excel solution.
However, we have a complete API for porting other OLE 2 Compound Document formats and welcome
others to participate.
</p> </p>
<p> <p>
OLE 2 Compound Document Format based files include most Microsoft Office OLE 2 Compound Document Format based files include most Microsoft Office
files such as XLS and DOC. files such as XLS and DOC as well as MFC serialization API based file formats.
</p> </p>
<p> <p>
As a general policy we try to collaborate as much as possible with other projects to As a general policy we try to collaborate as much as possible with other projects to
@ -46,7 +50,7 @@
we say that POIFS is the most complete and correct port of this file format to date! we say that POIFS is the most complete and correct port of this file format to date!
</p> </p>
<p> <p>
You'd use HSSF if you needed to read or write an XLS (Excel) file using Java. You can also read and modify You'd use HSSF if you needed to read or write an Excel file using Java (XLS). You can also read and modify
spreadsheets using this API, although right now writing is more mature. spreadsheets using this API, although right now writing is more mature.
</p> </p>
</section> </section>

View File

@ -54,6 +54,37 @@
<title>History of Changes</title> <title>History of Changes</title>
<release version="2.0-pre2" date="6 July 2003">
<action dev="POI-DEVELOPERS" type="fix">A nasty concurrency problem has been fixed. Any users working in a multithreaded environment should seriously consider upgrading to this release.</action>
<action dev="POI-DEVELOPERS" type="update">The EXTSST record has been implemented. This record is used by excel for optimized reading of strings.</action>
<action dev="POI-DEVELOPERS" type="update">When rows are shifted, the merged regions now move with them. If a row contains 2 merged cells, the resulting shifted row should have those cells merged as well.</action>
<action dev="POI-DEVELOPERS" type="fix">There were some issues when removing merged
regions (specifically, removing all of them and then adding some more) and have been resolved.</action>
<action dev="POI-DEVELOPERS" type="fix">When a sheet contained shared formulas (when a formula is
dragged across greater than 6 cells), the clone would fail. We now support cloning of
sheets that contain this Excel optimization. </action>
<action dev="POI-DEVELOPERS" type="add">Support added for reading formulas with UnaryPlus and UnaryMinus operators.</action>
</release>
<release version="2.0-pre1" date="17 May 2003">
<action dev="POI-DEVELOPERS" type="add">Patch applied for deep cloning of worksheets was provided</action>
<action dev="POI-DEVELOPERS" type="add">Patch applied to allow sheet reordering</action>
<action dev="POI-DEVELOPERS" type="add">Added additional print area setting methods using row/column numbers</action>
<action dev="POI-DEVELOPERS" type="fix">HDF: Negative Array size fix</action>
<action dev="POI-DEVELOPERS" type="update">Added argument pointers to support the IF formula</action>
<action dev="POI-DEVELOPERS" type="update">Formulas: Added special character support for string literals, specifically for SUMIF formula support and addresses a bug as well</action>
<action dev="POI-DEVELOPERS" type="fix">BlockingInputStream committed to help ensure reads</action>
<action dev="POI-DEVELOPERS" type="fix">Fixed problem with NaN values differing from the investigated value from file reads in FormulaRecords</action>
<action dev="POI-DEVELOPERS" type="fix">Patch for getColumnWidth in HSSF</action>
<action dev="POI-DEVELOPERS" type="add">Patch for dealing with mult-level numbered lists in HDF</action>
<action dev="POI-DEVELOPERS" type="fix">Due to named reference work, several named-ranged bugs were closed</action>
<action dev="POI-DEVELOPERS" type="fix">Patch applied to prevent sheet corruption after a template modification</action>
<action dev="POI-DEVELOPERS" type="update">Shared Formulas now Supported</action>
<action dev="POI-DEVELOPERS" type="update">Added GreaterEqual, LessEqual and NotEqual to Formula Parser</action>
<action dev="POI-DEVELOPERS" type="update">Added GreaterThan and LessThan functionality to formulas</action>
<action dev="POI-DEVELOPERS" type="fix">Patches for i10n</action>
<action dev="POI-DEVELOPERS" type="update">POI Build System Updated</action>
<action dev="POI-DEVELOPERS" type="fix">font names can now be null</action>
</release>
<release version="1.10-dev" date="19 Feb 2003"> <release version="1.10-dev" date="19 Feb 2003">
<action dev="POI-DEVELOPERS" type="add">Support for zoom level</action> <action dev="POI-DEVELOPERS" type="add">Support for zoom level</action>
<action dev="POI-DEVELOPERS" type="add">Freeze and split pane support</action> <action dev="POI-DEVELOPERS" type="add">Freeze and split pane support</action>
@ -149,4 +180,4 @@
</changes> </changes>
</status> </status>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -62,7 +62,6 @@
*/ */
package org.apache.poi.hpsf; package org.apache.poi.hpsf;
import java.util.*;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -85,6 +84,7 @@ public class TypeReader
* starts * starts
* @param length The length of the variant including the variant * @param length The length of the variant including the variant
* type field * type field
* @param type The variant type to read
* @return A Java object that corresponds best to the variant * @return A Java object that corresponds best to the variant
* field. For example, a VT_I4 is returned as a {@link Long}, a * field. For example, a VT_I4 is returned as a {@link Long}, a
* VT_LPSTR as a {@link String}. * VT_LPSTR as a {@link String}.
@ -92,15 +92,25 @@ public class TypeReader
* @see Variant * @see Variant
*/ */
public static Object read(final byte[] src, int offset, int length, public static Object read(final byte[] src, int offset, int length,
final int type) final int type)
{ {
/* /*
* FIXME: Support reading more types and clean up this code! * FIXME: Support reading more types and clean up this code!
*/ */
Object value; Object value;
length = length - LittleEndian.INT_SIZE; length = length - LittleEndian.INT_SIZE;
switch (type) switch (type)
{ {
case Variant.VT_EMPTY:
{
/*
* FIXME: The value returned by this case relies on the
* assumption that the value VT_EMPTY denotes consists of zero
* bytes. I'd be glad if some could confirm or correct this.
*/
value = null;
break;
}
case Variant.VT_I2: case Variant.VT_I2:
{ {
/* /*
@ -137,11 +147,11 @@ public class TypeReader
* Read a byte string. In Java it is represented as a * Read a byte string. In Java it is represented as a
* String object. The 0x00 bytes at the end must be * String object. The 0x00 bytes at the end must be
* stripped. * stripped.
* *
* FIXME: Reading an 8-bit string should pay attention * FIXME: Reading an 8-bit string should pay attention
* to the codepage. Currently the byte making out the * to the codepage. Currently the byte making out the
* property's value are interpreted according to the * property's value are interpreted according to the
* platform's default character set. * platform's default character set.
*/ */
final int first = offset + LittleEndian.INT_SIZE; final int first = offset + LittleEndian.INT_SIZE;
long last = first + LittleEndian.getUInt(src, offset) - 1; long last = first + LittleEndian.getUInt(src, offset) - 1;
@ -149,7 +159,7 @@ public class TypeReader
while (src[(int) last] == 0 && first <= last) while (src[(int) last] == 0 && first <= last)
last--; last--;
value = new String(src, (int) first, (int) (last - first + 1)); value = new String(src, (int) first, (int) (last - first + 1));
break; break;
} }
case Variant.VT_LPWSTR: case Variant.VT_LPWSTR:
{ {
@ -160,27 +170,27 @@ public class TypeReader
*/ */
final int first = offset + LittleEndian.INT_SIZE; final int first = offset + LittleEndian.INT_SIZE;
long last = first + LittleEndian.getUInt(src, offset) - 1; long last = first + LittleEndian.getUInt(src, offset) - 1;
long l = last - first; long l = last - first;
offset += LittleEndian.INT_SIZE; offset += LittleEndian.INT_SIZE;
StringBuffer b = new StringBuffer((int) (last - first)); StringBuffer b = new StringBuffer((int) (last - first));
for (int i = 0; i <= l; i++) for (int i = 0; i <= l; i++)
{ {
final int i1 = offset + (i * 2); final int i1 = offset + (i * 2);
final int i2 = i1 + 1; final int i2 = i1 + 1;
b.append((char) ((src[i2] << 8) + src[i1])); b.append((char) ((src[i2] << 8) + src[i1]));
} }
/* Strip 0x00 characters from the end of the string: */ /* Strip 0x00 characters from the end of the string: */
while (b.charAt(b.length() - 1) == 0x00) while (b.charAt(b.length() - 1) == 0x00)
b.setLength(b.length() - 1); b.setLength(b.length() - 1);
value = b.toString(); value = b.toString();
break; break;
} }
case Variant.VT_CF: case Variant.VT_CF:
{ {
final byte[] v = new byte[length]; final byte[] v = new byte[length];
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
v[i] = src[(int) (offset + i)]; v[i] = src[(int) (offset + i)];
value = v; value = v;
break; break;
} }
case Variant.VT_BOOL: case Variant.VT_BOOL:
@ -190,24 +200,24 @@ public class TypeReader
* src[offset + 3] contain the DWord for VT_BOOL, so * src[offset + 3] contain the DWord for VT_BOOL, so
* skip it, we don't need it. * skip it, we don't need it.
*/ */
final int first = offset + LittleEndian.INT_SIZE; // final int first = offset + LittleEndian.INT_SIZE;
long bool = LittleEndian.getUInt(src, offset); long bool = LittleEndian.getUInt(src, offset);
if (bool != 0) if (bool != 0)
value = new Boolean(true); value = new Boolean(true);
else else
value = new Boolean(false); value = new Boolean(false);
break; break;
} }
default: default:
{ {
final byte[] v = new byte[length]; final byte[] v = new byte[length];
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
v[i] = src[(int) (offset + i)]; v[i] = src[(int) (offset + i)];
value = v; value = v;
break; break;
} }
} }
return value; return value;
} }
} }

View File

@ -76,178 +76,178 @@ public class Variant
/** /**
* <p>[V][P] Nothing.</p> * <p>[V][P] Nothing.</p>
*/ */
public final static int VT_EMPTY = 0; public static final int VT_EMPTY = 0;
/** /**
* <p>[V][P] SQL style Null.</p> * <p>[V][P] SQL style Null.</p>
*/ */
public final static int VT_NULL = 1; public static final int VT_NULL = 1;
/** /**
* <p>[V][T][P][S] 2 byte signed int.</p> * <p>[V][T][P][S] 2 byte signed int.</p>
*/ */
public final static int VT_I2 = 2; public static final int VT_I2 = 2;
/** /**
* <p>[V][T][P][S] 4 byte signed int.</p> * <p>[V][T][P][S] 4 byte signed int.</p>
*/ */
public final static int VT_I4 = 3; public static final int VT_I4 = 3;
/** /**
* <p>[V][T][P][S] 4 byte real.</p> * <p>[V][T][P][S] 4 byte real.</p>
*/ */
public final static int VT_R4 = 4; public static final int VT_R4 = 4;
/** /**
* <p>[V][T][P][S] 8 byte real.</p> * <p>[V][T][P][S] 8 byte real.</p>
*/ */
public final static int VT_R8 = 5; public static final int VT_R8 = 5;
/** /**
* <p>[V][T][P][S] currency. <span style="background-color: * <p>[V][T][P][S] currency. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_CY = 6; public static final int VT_CY = 6;
/** /**
* <p>[V][T][P][S] date. <span style="background-color: * <p>[V][T][P][S] date. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_DATE = 7; public static final int VT_DATE = 7;
/** /**
* <p>[V][T][P][S] OLE Automation string. <span * <p>[V][T][P][S] OLE Automation string. <span
* style="background-color: #ffff00">How long is this? How is it * style="background-color: #ffff00">How long is this? How is it
* to be interpreted?</span></p> * to be interpreted?</span></p>
*/ */
public final static int VT_BSTR = 8; public static final int VT_BSTR = 8;
/** /**
* <p>[V][T][P][S] IDispatch *. <span style="background-color: * <p>[V][T][P][S] IDispatch *. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_DISPATCH = 9; public static final int VT_DISPATCH = 9;
/** /**
* <p>[V][T][S] SCODE. <span style="background-color: #ffff00">How * <p>[V][T][S] SCODE. <span style="background-color: #ffff00">How
* long is this? How is it to be interpreted?</span></p> * long is this? How is it to be interpreted?</span></p>
*/ */
public final static int VT_ERROR = 10; public static final int VT_ERROR = 10;
/** /**
* <p>[V][T][P][S] True=-1, False=0.</p> * <p>[V][T][P][S] True=-1, False=0.</p>
*/ */
public final static int VT_BOOL = 11; public static final int VT_BOOL = 11;
/** /**
* <p>[V][T][P][S] VARIANT *. <span style="background-color: * <p>[V][T][P][S] VARIANT *. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_VARIANT = 12; public static final int VT_VARIANT = 12;
/** /**
* <p>[V][T][S] IUnknown *. <span style="background-color: * <p>[V][T][S] IUnknown *. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_UNKNOWN = 13; public static final int VT_UNKNOWN = 13;
/** /**
* <p>[V][T][S] 16 byte fixed point.</p> * <p>[V][T][S] 16 byte fixed point.</p>
*/ */
public final static int VT_DECIMAL = 14; public static final int VT_DECIMAL = 14;
/** /**
* <p>[T] signed char.</p> * <p>[T] signed char.</p>
*/ */
public final static int VT_I1 = 16; public static final int VT_I1 = 16;
/** /**
* <p>[V][T][P][S] unsigned char.</p> * <p>[V][T][P][S] unsigned char.</p>
*/ */
public final static int VT_UI1 = 17; public static final int VT_UI1 = 17;
/** /**
* <p>[T][P] unsigned short.</p> * <p>[T][P] unsigned short.</p>
*/ */
public final static int VT_UI2 = 18; public static final int VT_UI2 = 18;
/** /**
* <p>[T][P] unsigned int.</p> * <p>[T][P] unsigned int.</p>
*/ */
public final static int VT_UI4 = 19; public static final int VT_UI4 = 19;
/** /**
* <p>[T][P] signed 64-bit int.</p> * <p>[T][P] signed 64-bit int.</p>
*/ */
public final static int VT_I8 = 20; public static final int VT_I8 = 20;
/** /**
* <p>[T][P] unsigned 64-bit int.</p> * <p>[T][P] unsigned 64-bit int.</p>
*/ */
public final static int VT_UI8 = 21; public static final int VT_UI8 = 21;
/** /**
* <p>[T] signed machine int.</p> * <p>[T] signed machine int.</p>
*/ */
public final static int VT_INT = 22; public static final int VT_INT = 22;
/** /**
* <p>[T] unsigned machine int.</p> * <p>[T] unsigned machine int.</p>
*/ */
public final static int VT_UINT = 23; public static final int VT_UINT = 23;
/** /**
* <p>[T] C style void.</p> * <p>[T] C style void.</p>
*/ */
public final static int VT_VOID = 24; public static final int VT_VOID = 24;
/** /**
* <p>[T] Standard return type. <span style="background-color: * <p>[T] Standard return type. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_HRESULT = 25; public static final int VT_HRESULT = 25;
/** /**
* <p>[T] pointer type. <span style="background-color: * <p>[T] pointer type. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_PTR = 26; public static final int VT_PTR = 26;
/** /**
* <p>[T] (use VT_ARRAY in VARIANT).</p> * <p>[T] (use VT_ARRAY in VARIANT).</p>
*/ */
public final static int VT_SAFEARRAY = 27; public static final int VT_SAFEARRAY = 27;
/** /**
* <p>[T] C style array. <span style="background-color: * <p>[T] C style array. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_CARRAY = 28; public static final int VT_CARRAY = 28;
/** /**
* <p>[T] user defined type. <span style="background-color: * <p>[T] user defined type. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_USERDEFINED = 29; public static final int VT_USERDEFINED = 29;
/** /**
* <p>[T][P] null terminated string.</p> * <p>[T][P] null terminated string.</p>
*/ */
public final static int VT_LPSTR = 30; public static final int VT_LPSTR = 30;
/** /**
* <p>[T][P] wide (Unicode) null terminated string.</p> * <p>[T][P] wide (Unicode) null terminated string.</p>
*/ */
public final static int VT_LPWSTR = 31; public static final int VT_LPWSTR = 31;
/** /**
* <p>[P] FILETIME. The FILETIME structure holds a date and time * <p>[P] FILETIME. The FILETIME structure holds a date and time
@ -256,50 +256,50 @@ public class Variant
* have passed since January 1, 1601. This 64-bit value is split * have passed since January 1, 1601. This 64-bit value is split
* into the two dwords stored in the structure.</p> * into the two dwords stored in the structure.</p>
*/ */
public final static int VT_FILETIME = 64; public static final int VT_FILETIME = 64;
/** /**
* <p>[P] Length prefixed bytes.</p> * <p>[P] Length prefixed bytes.</p>
*/ */
public final static int VT_BLOB = 65; public static final int VT_BLOB = 65;
/** /**
* <p>[P] Name of the stream follows.</p> * <p>[P] Name of the stream follows.</p>
*/ */
public final static int VT_STREAM = 66; public static final int VT_STREAM = 66;
/** /**
* <p>[P] Name of the storage follows.</p> * <p>[P] Name of the storage follows.</p>
*/ */
public final static int VT_STORAGE = 67; public static final int VT_STORAGE = 67;
/** /**
* <p>[P] Stream contains an object. <span * <p>[P] Stream contains an object. <span
* style="background-color: #ffff00"> How long is this? How is it * style="background-color: #ffff00"> How long is this? How is it
* to be interpreted?</span></p> * to be interpreted?</span></p>
*/ */
public final static int VT_STREAMED_OBJECT = 68; public static final int VT_STREAMED_OBJECT = 68;
/** /**
* <p>[P] Storage contains an object. <span * <p>[P] Storage contains an object. <span
* style="background-color: #ffff00"> How long is this? How is it * style="background-color: #ffff00"> How long is this? How is it
* to be interpreted?</span></p> * to be interpreted?</span></p>
*/ */
public final static int VT_STORED_OBJECT = 69; public static final int VT_STORED_OBJECT = 69;
/** /**
* <p>[P] Blob contains an object. <span style="background-color: * <p>[P] Blob contains an object. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_BLOB_OBJECT = 70; public static final int VT_BLOB_OBJECT = 70;
/** /**
* <p>[P] Clipboard format. <span style="background-color: * <p>[P] Clipboard format. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_CF = 71; public static final int VT_CF = 71;
/** /**
* <p>[P] A Class ID.</p> * <p>[P] A Class ID.</p>
@ -331,34 +331,46 @@ public class Variant
* target="_blank"> * target="_blank">
* msdn.microsoft.com/library/en-us/com/stgrstrc_0uwk.asp</a>.</p> * msdn.microsoft.com/library/en-us/com/stgrstrc_0uwk.asp</a>.</p>
*/ */
public final static int VT_CLSID = 72; public static final int VT_CLSID = 72;
/** /**
* <p>[P] simple counted array. <span style="background-color: * <p>[P] simple counted array. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_VECTOR = 0x1000; public static final int VT_VECTOR = 0x1000;
/** /**
* <p>[V] SAFEARRAY*. <span style="background-color: #ffff00">How * <p>[V] SAFEARRAY*. <span style="background-color: #ffff00">How
* long is this? How is it to be interpreted?</span></p> * long is this? How is it to be interpreted?</span></p>
*/ */
public final static int VT_ARRAY = 0x2000; public static final int VT_ARRAY = 0x2000;
/** /**
* <p>[V] void* for local use. <span style="background-color: * <p>[V] void* for local use. <span style="background-color:
* #ffff00">How long is this? How is it to be * #ffff00">How long is this? How is it to be
* interpreted?</span></p> * interpreted?</span></p>
*/ */
public final static int VT_BYREF = 0x4000; public static final int VT_BYREF = 0x4000;
public final static int VT_RESERVED = 0x8000; /**
* <p>FIXME: Document this!</p>
*/
public static final int VT_RESERVED = 0x8000;
public final static int VT_ILLEGAL = 0xFFFF; /**
* <p>FIXME: Document this!</p>
*/
public static final int VT_ILLEGAL = 0xFFFF;
public final static int VT_ILLEGALMASKED = 0xFFF; /**
* <p>FIXME: Document this!</p>
*/
public static final int VT_ILLEGALMASKED = 0xFFF;
public final static int VT_TYPEMASK = 0xFFF; /**
* <p>FIXME: Document this!</p>
*/
public static final int VT_TYPEMASK = 0xFFF;
} }

View File

@ -108,7 +108,9 @@ public class Sheet implements Model
protected HeaderRecord header = null; protected HeaderRecord header = null;
protected FooterRecord footer = null; protected FooterRecord footer = null;
protected PrintGridlinesRecord printGridlines = null; protected PrintGridlinesRecord printGridlines = null;
protected WindowTwoRecord windowTwo = null;
protected MergeCellsRecord merged = null; protected MergeCellsRecord merged = null;
protected Margin margins[] = null;
protected ArrayList mergedRecords = new ArrayList(); protected ArrayList mergedRecords = new ArrayList();
protected ArrayList mergedLocs = new ArrayList(); protected ArrayList mergedLocs = new ArrayList();
protected int numMergedRegions = 0; protected int numMergedRegions = 0;
@ -120,6 +122,7 @@ public class Sheet implements Model
private Iterator valueRecIterator = null; private Iterator valueRecIterator = null;
private Iterator rowRecIterator = null; private Iterator rowRecIterator = null;
protected int eofLoc = 0; protected int eofLoc = 0;
protected ProtectRecord protect = null;
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;
@ -249,22 +252,46 @@ public class Sheet implements Model
{ {
retval.printGridlines = (PrintGridlinesRecord) rec; retval.printGridlines = (PrintGridlinesRecord) rec;
} }
else if ( rec.getSid() == HeaderRecord.sid ) else if ( rec.getSid() == HeaderRecord.sid && bofEofNestingLevel == 1)
{ {
retval.header = (HeaderRecord) rec; retval.header = (HeaderRecord) rec;
} }
else if ( rec.getSid() == FooterRecord.sid ) else if ( rec.getSid() == FooterRecord.sid && bofEofNestingLevel == 1)
{ {
retval.footer = (FooterRecord) rec; retval.footer = (FooterRecord) rec;
} }
else if ( rec.getSid() == PrintSetupRecord.sid ) else if ( rec.getSid() == PrintSetupRecord.sid && bofEofNestingLevel == 1)
{ {
retval.printSetup = (PrintSetupRecord) rec; retval.printSetup = (PrintSetupRecord) rec;
} }
else if ( rec.getSid() == LeftMarginRecord.sid)
{
retval.getMargins()[LeftMargin] = (LeftMarginRecord) rec;
}
else if ( rec.getSid() == RightMarginRecord.sid)
{
retval.getMargins()[RightMargin] = (RightMarginRecord) rec;
}
else if ( rec.getSid() == TopMarginRecord.sid)
{
retval.getMargins()[TopMargin] = (TopMarginRecord) rec;
}
else if ( rec.getSid() == BottomMarginRecord.sid)
{
retval.getMargins()[BottomMargin] = (BottomMarginRecord) rec;
}
else if ( rec.getSid() == SelectionRecord.sid ) else if ( rec.getSid() == SelectionRecord.sid )
{ {
retval.selection = (SelectionRecord) rec; retval.selection = (SelectionRecord) rec;
} }
else if ( rec.getSid() == WindowTwoRecord.sid )
{
retval.windowTwo = (WindowTwoRecord) rec;
}
else if ( rec.getSid() == ProtectRecord.sid )
{
retval.protect = (ProtectRecord) rec;
}
if (rec != null) if (rec != null)
{ {
@ -391,11 +418,13 @@ public class Sheet implements Model
retval.dims = ( DimensionsRecord ) retval.createDimensions(); retval.dims = ( DimensionsRecord ) retval.createDimensions();
retval.dimsloc = 19; retval.dimsloc = 19;
records.add(retval.dims); records.add(retval.dims);
records.add(retval.createWindowTwo()); records.add(retval.windowTwo = retval.createWindowTwo());
retval.setLoc(records.size() - 1); retval.setLoc(records.size() - 1);
retval.selection = retval.selection =
(SelectionRecord) retval.createSelection(); (SelectionRecord) retval.createSelection();
records.add(retval.selection); records.add(retval.selection);
retval.protect = (ProtectRecord) retval.createProtect();
records.add(retval.protect);
records.add(retval.createEOF()); records.add(retval.createEOF());
retval.records = records; retval.records = records;
log.log(log.DEBUG, "Sheet createsheet from scratch exit"); log.log(log.DEBUG, "Sheet createsheet from scratch exit");
@ -469,12 +498,21 @@ public class Sheet implements Model
numMergedRegions--; numMergedRegions--;
if (rec.getNumAreas() == 0) if (rec.getNumAreas() == 0)
{ {
mergedRecords.remove(pos); mergedRecords.remove(pos);
if (merged == rec) if (merged == rec) {
merged = (MergeCellsRecord) mergedRecords.get(mergedRecords.size() - 1); //pull up the LAST record for operations when we finally
//support continue records for mergedRegions
if (mergedRecords.size() > 0) {
merged = (MergeCellsRecord) mergedRecords.get(mergedRecords.size() - 1);
} else {
merged = null;
}
}
int removePos = ((Integer) mergedLocs.get(pos)).intValue(); int removePos = ((Integer) mergedLocs.get(pos)).intValue();
records.remove(removePos); records.remove(removePos);
mergedLocs.remove(pos); mergedLocs.remove(pos);
} }
} }
@ -2011,7 +2049,7 @@ public class Sheet implements Model
* @return record containing a WindowTwoRecord * @return record containing a WindowTwoRecord
*/ */
protected Record createWindowTwo() protected WindowTwoRecord createWindowTwo()
{ {
WindowTwoRecord retval = new WindowTwoRecord(); WindowTwoRecord retval = new WindowTwoRecord();
@ -2312,7 +2350,6 @@ public class Sheet implements Model
* @param sel True to select the sheet, false otherwise. * @param sel True to select the sheet, false otherwise.
*/ */
public void setSelected(boolean sel) { public void setSelected(boolean sel) {
WindowTwoRecord windowTwo = (WindowTwoRecord) findFirstRecordBySid(WindowTwoRecord.sid);
windowTwo.setSelected(sel); windowTwo.setSelected(sel);
} }
@ -2321,82 +2358,59 @@ public class Sheet implements Model
* @param margin which margin to get * @param margin which margin to get
* @return the size of the margin * @return the size of the margin
*/ */
public double getMargin(short margin) { public double getMargin(short margin) {
Margin m; if (getMargins()[margin] != null)
switch ( margin ) return margins[margin].getMargin();
{ else {
case LeftMargin: switch ( margin )
m = (Margin) findFirstRecordBySid( LeftMarginRecord.sid ); {
if ( m == null ) case LeftMargin:
return .75; return .75;
break; case RightMargin:
case RightMargin: return .75;
m = (Margin) findFirstRecordBySid( RightMarginRecord.sid ); case TopMargin:
if ( m == null ) return 1.0;
return .75; case BottomMargin:
break; return 1.0;
case TopMargin: default :
m = (Margin) findFirstRecordBySid( TopMarginRecord.sid ); throw new RuntimeException( "Unknown margin constant: " + margin );
if ( m == null ) }
return 1.0; }
break; }
case BottomMargin:
m = (Margin) findFirstRecordBySid( BottomMarginRecord.sid );
if ( m == null )
return 1.0;
break;
default :
throw new RuntimeException( "Unknown margin constant: " + margin );
}
return m.getMargin();
}
/** /**
* Sets the size of the margin in inches. * Sets the size of the margin in inches.
* @param margin which margin to get * @param margin which margin to get
* @param size the size of the margin * @param size the size of the margin
*/ */
public void setMargin(short margin, double size) { public void setMargin(short margin, double size) {
Margin m; Margin m = getMargins()[margin];
switch ( margin ) if (m == null) {
{ switch ( margin )
case LeftMargin: {
m = (Margin) findFirstRecordBySid( LeftMarginRecord.sid ); case LeftMargin:
if ( m == null ) m = new LeftMarginRecord();
{ records.add( getDimsLoc() + 1, m );
m = new LeftMarginRecord(); break;
records.add( getDimsLoc() + 1, m ); case RightMargin:
} m = new RightMarginRecord();
break; records.add( getDimsLoc() + 1, m );
case RightMargin: break;
m = (Margin) findFirstRecordBySid( RightMarginRecord.sid ); case TopMargin:
if ( m == null ) m = new TopMarginRecord();
{ records.add( getDimsLoc() + 1, m );
m = new RightMarginRecord(); break;
records.add( getDimsLoc() + 1, m ); case BottomMargin:
} m = new BottomMarginRecord();
break; records.add( getDimsLoc() + 1, m );
case TopMargin: break;
m = (Margin) findFirstRecordBySid( TopMarginRecord.sid ); default :
if ( m == null ) throw new RuntimeException( "Unknown margin constant: " + margin );
{ }
m = new TopMarginRecord(); margins[margin] = m;
records.add( getDimsLoc() + 1, m ); }
} m.setMargin( size );
break; }
case BottomMargin:
m = (Margin) findFirstRecordBySid( BottomMarginRecord.sid );
if ( m == null )
{
m = new BottomMarginRecord();
records.add( getDimsLoc() + 1, m );
}
break;
default :
throw new RuntimeException( "Unknown margin constant: " + margin );
}
m.setMargin( size );
}
public int getEofLoc() public int getEofLoc()
{ {
@ -2434,9 +2448,8 @@ public class Sheet implements Model
} }
records.add(loc+1, pane); records.add(loc+1, pane);
WindowTwoRecord windowRecord = (WindowTwoRecord) records.get(loc); windowTwo.setFreezePanes(true);
windowRecord.setFreezePanes(true); windowTwo.setFreezePanesNoSplit(true);
windowRecord.setFreezePanesNoSplit(true);
SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid); SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
// SelectionRecord sel2 = (SelectionRecord) sel.clone(); // SelectionRecord sel2 = (SelectionRecord) sel.clone();
@ -2484,9 +2497,8 @@ public class Sheet implements Model
r.setActivePane((short) activePane); r.setActivePane((short) activePane);
records.add(loc+1, r); records.add(loc+1, r);
WindowTwoRecord windowRecord = (WindowTwoRecord) records.get(loc); windowTwo.setFreezePanes(false);
windowRecord.setFreezePanes(false); windowTwo.setFreezePanesNoSplit(false);
windowRecord.setFreezePanesNoSplit(false);
SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid); SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
// SelectionRecord sel2 = (SelectionRecord) sel.clone(); // SelectionRecord sel2 = (SelectionRecord) sel.clone();
@ -2519,5 +2531,84 @@ public class Sheet implements Model
{ {
this.selection = selection; this.selection = selection;
} }
/**
* creates a Protect record with protect set to false.
* @see org.apache.poi.hssf.record.ProtectRecord
* @see org.apache.poi.hssf.record.Record
* @return a ProtectRecord
*/
protected Record createProtect()
{
log.log(log.DEBUG, "create protect record with protection disabled");
ProtectRecord retval = new ProtectRecord();
retval.setProtect(false);
// by default even when we support encryption we won't
return retval;
}
public ProtectRecord getProtect()
{
return protect;
}
/**
* Sets whether the gridlines are shown in a viewer.
* @param show whether to show gridlines or not
*/
public void setDisplayGridlines(boolean show) {
windowTwo.setDisplayGridlines(show);
}
/**
* Returns if gridlines are displayed.
* @return whether gridlines are displayed
*/
public boolean isDisplayGridlines() {
return windowTwo.getDisplayGridlines();
}
/**
* Sets whether the formulas are shown in a viewer.
* @param show whether to show formulas or not
*/
public void setDisplayFormulas(boolean show) {
windowTwo.setDisplayFormulas(show);
}
/**
* Returns if formulas are displayed.
* @return whether formulas are displayed
*/
public boolean isDisplayFormulas() {
return windowTwo.getDisplayFormulas();
}
/**
* Sets whether the RowColHeadings are shown in a viewer.
* @param show whether to show RowColHeadings or not
*/
public void setDisplayRowColHeadings(boolean show) {
windowTwo.setDisplayRowColHeadings(show);
}
/**
* Returns if RowColHeadings are displayed.
* @return whether RowColHeadings are displayed
*/
public boolean isDisplayRowColHeadings() {
return windowTwo.getDisplayRowColHeadings();
}
/**
* Returns the array of margins. If not created, will create.
*
* @return the array of marings.
*/
protected Margin[] getMargins() {
if (margins == null)
margins = new Margin[4];
return margins;
}
} }

View File

@ -513,7 +513,7 @@ public class Workbook implements Model {
for (int k = 0; k < boundsheets.size(); k++) { for (int k = 0; k < boundsheets.size(); k++) {
String sheet = getSheetName(k); String sheet = getSheetName(k);
if (sheet.equals(name)) { if (sheet.equalsIgnoreCase(name)) {
retval = k; retval = k;
break; break;
} }
@ -686,37 +686,27 @@ public class Workbook implements Model {
* *
* @return byte array containing the HSSF-only portions of the POIFS file. * @return byte array containing the HSSF-only portions of the POIFS file.
*/ */
// GJS: Not used so why keep it.
public byte [] serialize() { // public byte [] serialize() {
log.log(DEBUG, "Serializing Workbook!"); // log.log(DEBUG, "Serializing Workbook!");
byte[] retval = null; // byte[] retval = null;
//
// ArrayList bytes = new ArrayList(records.size()); //// ArrayList bytes = new ArrayList(records.size());
int arraysize = getSize(); // int arraysize = getSize();
int pos = 0; // int pos = 0;
//
// for (int k = 0; k < records.size(); k++) // retval = new byte[ arraysize ];
// { // for (int k = 0; k < records.size(); k++) {
// bytes.add((( Record ) records.get(k)).serialize()); //
// } // Record record = records.get(k);
// for (int k = 0; k < bytes.size(); k++) //// Let's skip RECALCID records, as they are only use for optimization
// { // if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
// arraysize += (( byte [] ) bytes.get(k)).length; // pos += record.serialize(pos, retval); // rec.length;
// } // }
retval = new byte[ arraysize ]; // }
for (int k = 0; k < records.size(); k++) { // log.log(DEBUG, "Exiting serialize workbook");
// return retval;
// byte[] rec = (( byte [] ) bytes.get(k)); // }
// System.arraycopy(rec, 0, retval, pos, rec.length);
Record record = records.get(k);
// Let's skip RECALCID records, as they are only use for optimization
if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
pos += record.serialize(pos, retval); // rec.length;
}
}
log.log(DEBUG, "Exiting serialize workbook");
return retval;
}
/** /**
* Serializes all records int the worksheet section into a big byte array. Use * Serializes all records int the worksheet section into a big byte array. Use
@ -725,44 +715,54 @@ public class Workbook implements Model {
* @param data array of bytes to write this to * @param data array of bytes to write this to
*/ */
public int serialize(int offset, byte [] data) { public int serialize( int offset, byte[] data )
log.log(DEBUG, "Serializing Workbook with offsets"); {
log.log( DEBUG, "Serializing Workbook with offsets" );
// ArrayList bytes = new ArrayList(records.size()); int pos = 0;
// int arraysize = getSize(); // 0;
int pos = 0;
// for (int k = 0; k < records.size(); k++) SSTRecord sst = null;
// { int sstPos = 0;
// bytes.add((( Record ) records.get(k)).serialize()); for ( int k = 0; k < records.size(); k++ )
// {
// }
// for (int k = 0; k < bytes.size(); k++)
// {
// arraysize += (( byte [] ) bytes.get(k)).length;
// }
for (int k = 0; k < records.size(); k++) {
// byte[] rec = (( byte [] ) bytes.get(k)); Record record = records.get( k );
// System.arraycopy(rec, 0, data, offset + pos, rec.length);
Record record = records.get(k);
// Let's skip RECALCID records, as they are only use for optimization // Let's skip RECALCID records, as they are only use for optimization
if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
pos += record.serialize(pos + offset, data); // rec.length; {
if (record instanceof SSTRecord)
{
sst = (SSTRecord)record;
sstPos = pos;
}
if (record.getSid() == ExtSSTRecord.sid && sst != null)
{
record = sst.createExtSSTRecord(sstPos + offset);
}
pos += record.serialize( pos + offset, data ); // rec.length;
} }
} }
log.log(DEBUG, "Exiting serialize workbook"); log.log( DEBUG, "Exiting serialize workbook" );
return pos; return pos;
} }
public int getSize() { public int getSize()
{
int retval = 0; int retval = 0;
for (int k = 0; k < records.size(); k++) { SSTRecord sst = null;
Record record = records.get(k); for ( int k = 0; k < records.size(); k++ )
{
Record record = records.get( k );
// Let's skip RECALCID records, as they are only use for optimization // Let's skip RECALCID records, as they are only use for optimization
if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
retval += record.getRecordSize(); {
if (record instanceof SSTRecord)
sst = (SSTRecord)record;
if (record.getSid() == ExtSSTRecord.sid && sst != null)
retval += sst.calcExtSSTRecordSize();
else
retval += record.getRecordSize();
} }
} }
return retval; return retval;
@ -1729,15 +1729,17 @@ public class Workbook implements Model {
} }
public SheetReferences getSheetReferences() { public SheetReferences getSheetReferences() {
SheetReferences refs = new SheetReferences(); SheetReferences refs = new SheetReferences();
if (externSheet != null) { if (externSheet != null) {
for (int k = 0; k < externSheet.getNumOfREFStructures(); k++) { for (int k = 0; k < externSheet.getNumOfREFStructures(); k++) {
String sheetName = findSheetNameFromExternSheet((short)k);
refs.addSheetReference(sheetName, k); String sheetName = findSheetNameFromExternSheet((short)k);
} refs.addSheetReference(sheetName, k);
}
return refs; }
}
return refs;
} }
/** finds the sheet name by his extern sheet index /** finds the sheet name by his extern sheet index
@ -1745,10 +1747,12 @@ public class Workbook implements Model {
* @return sheet name * @return sheet name
*/ */
public String findSheetNameFromExternSheet(short num){ public String findSheetNameFromExternSheet(short num){
String result; String result="";
short indexToSheet = externSheet.getREFRecordAt(num).getIndexToFirstSupBook(); short indexToSheet = externSheet.getREFRecordAt(num).getIndexToFirstSupBook();
result = getSheetName(indexToSheet); if (indexToSheet>-1) { //error check, bail out gracefully!
result = getSheetName(indexToSheet);
}
return result; return result;
} }

File diff suppressed because one or more lines are too long

View File

@ -267,4 +267,14 @@ public class ContinueRecord
protected void fillFields(byte [] ignored_parm1, short ignored_parm2, int ignored_parm3) protected void fillFields(byte [] ignored_parm1, short ignored_parm2, int ignored_parm3)
{ {
} }
/**
* Clone this record.
*/
public Object clone() {
ContinueRecord clone = new ContinueRecord();
clone.setData(field_1_data);
return clone;
}
} }

View File

@ -114,7 +114,7 @@ public class ExtSSTInfoSubRecord
field_1_stream_pos = pos; field_1_stream_pos = pos;
} }
public void setBucketSSTOffset(short offset) public void setBucketRecordOffset(short offset)
{ {
field_2_bucket_sst_offset = offset; field_2_bucket_sst_offset = offset;
} }
@ -159,6 +159,6 @@ public class ExtSSTInfoSubRecord
public short getSid() public short getSid()
{ {
return this.sid; return sid;
} }
} }

View File

@ -79,6 +79,7 @@ public class ExtSSTRecord
private short field_1_strings_per_bucket; private short field_1_strings_per_bucket;
private ArrayList field_2_sst_info; private ArrayList field_2_sst_info;
public ExtSSTRecord() public ExtSSTRecord()
{ {
field_2_sst_info = new ArrayList(); field_2_sst_info = new ArrayList();
@ -189,26 +190,39 @@ public class ExtSSTRecord
public int serialize(int offset, byte [] data) public int serialize(int offset, byte [] data)
{ {
LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
// LittleEndian.putShort(data,2,(short)(2 + (getNumInfoRecords() *8))); LittleEndian.putShort(data, 4 + offset, field_1_strings_per_bucket);
LittleEndian.putShort(data, 2 + offset, ( short ) (2 + (0x3fa - 2))); int pos = 6;
int pos = 4;
for (int k = 0; k < getNumInfoRecords(); k++) for (int k = 0; k < getNumInfoRecords(); k++)
{ {
System.arraycopy(getInfoRecordAt(k).serialize(), 0, data, System.arraycopy(getInfoRecordAt(k).serialize(), 0, data,
pos + offset, 8); pos + offset, 8);
pos += getInfoRecordAt(k).getRecordSize();
} }
return getRecordSize(); return getRecordSize();
} }
public int getRecordSize() public int getRecordSize()
{ {
return 6 + 0x3fa - 2; return 4 + 2 + field_2_sst_info.size() * 8;
} }
public short getSid() public short getSid()
{ {
return this.sid; return sid;
} }
public void setBucketOffsets( int[] bucketAbsoluteOffsets, int[] bucketRelativeOffsets )
{
this.field_2_sst_info = new ArrayList(bucketAbsoluteOffsets.length);
for ( int i = 0; i < bucketAbsoluteOffsets.length; i++ )
{
ExtSSTInfoSubRecord r = new ExtSSTInfoSubRecord();
r.setBucketRecordOffset((short)bucketRelativeOffsets[i]);
r.setStreamPos(bucketAbsoluteOffsets[i]);
field_2_sst_info.add(r);
}
}
} }

File diff suppressed because one or more lines are too long

View File

@ -557,8 +557,13 @@ public class FormulaRecord
.append("\n"); .append("\n");
buffer.append(" .xf = ") buffer.append(" .xf = ")
.append(Integer.toHexString(getXFIndex())).append("\n"); .append(Integer.toHexString(getXFIndex())).append("\n");
buffer.append(" .value = ").append(getValue()) if (Double.isNaN(this.getValue()) && value_data != null)
.append("\n"); buffer.append(" .value (NaN) = ")
.append(org.apache.poi.util.HexDump.dump(value_data,0,0))
.append("\n");
else
buffer.append(" .value = ").append(getValue())
.append("\n");
buffer.append(" .options = ").append(getOptions()) buffer.append(" .options = ").append(getOptions())
.append("\n"); .append("\n");
buffer.append(" .zero = ").append(field_6_zero) buffer.append(" .zero = ").append(field_6_zero)
@ -607,9 +612,10 @@ public class FormulaRecord
if (field_8_parsed_expr != null) if (field_8_parsed_expr != null)
size = field_8_parsed_expr.size(); size = field_8_parsed_expr.size();
for (int i=0; i< size; i++) { for (int i=0; i< size; i++) {
Ptg ptg = (Ptg)((Ptg)field_8_parsed_expr.get(i)).clone(); Ptg ptg = (Ptg)((Ptg)field_8_parsed_expr.get(i)).clone();
rec.field_8_parsed_expr.set(i, ptg); rec.field_8_parsed_expr.add(i, ptg);
} }
rec.value_data = value_data;
rec.all_data = all_data; rec.all_data = all_data;
return rec; return rec;
} }

View File

@ -794,6 +794,8 @@ public class NameRecord extends Record {
pos += ptg.getSize(); pos += ptg.getSize();
sizeCounter += ptg.getSize(); sizeCounter += ptg.getSize();
stack.push(ptg); stack.push(ptg);
field_13_raw_name_definition=new byte[size];
System.arraycopy(data,offset,field_13_raw_name_definition,0,size);
} }
} catch (java.lang.UnsupportedOperationException uoe) { } catch (java.lang.UnsupportedOperationException uoe) {
System.err.println("[WARNING] Unknown Ptg " System.err.println("[WARNING] Unknown Ptg "
@ -880,7 +882,7 @@ public class NameRecord extends Record {
.append("\n"); .append("\n");
buffer.append(" .unused = ").append( field_5_index_to_sheet ) buffer.append(" .unused = ").append( field_5_index_to_sheet )
.append("\n"); .append("\n");
buffer.append(" .( 0 = Global name, otherwise index to sheet (one-based) ) = ").append( field_6_equals_to_index_to_sheet ) buffer.append(" .index to sheet (1-based, 0=Global) = ").append( field_6_equals_to_index_to_sheet )
.append("\n"); .append("\n");
buffer.append(" .Length of menu text (character count) = ").append( field_7_length_custom_menu ) buffer.append(" .Length of menu text (character count) = ").append( field_7_length_custom_menu )
.append("\n"); .append("\n");
@ -906,6 +908,7 @@ public class NameRecord extends Record {
.append("\n"); .append("\n");
buffer.append(" .Status bar text (Unicode string without length field) = ").append( field_17_status_bar_text ) buffer.append(" .Status bar text (Unicode string without length field) = ").append( field_17_status_bar_text )
.append("\n"); .append("\n");
buffer.append(org.apache.poi.util.HexDump.dump(this.field_13_raw_name_definition,0,0));
buffer.append("[/NAME]\n"); buffer.append("[/NAME]\n");
return buffer.toString(); return buffer.toString();

View File

@ -166,4 +166,14 @@ public class PasswordRecord
{ {
return this.sid; return this.sid;
} }
/**
* Clone this record.
*/
public Object clone() {
PasswordRecord clone = new PasswordRecord();
clone.setPassword(field_1_password);
return clone;
}
} }

View File

@ -139,9 +139,9 @@ public class ProtectRecord
* @return whether to protect the sheet or not * @return whether to protect the sheet or not
*/ */
public short getProtect() public boolean getProtect()
{ {
return field_1_protect; return (field_1_protect == 1);
} }
public String toString() public String toString()
@ -149,8 +149,8 @@ public class ProtectRecord
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("[PROTECT]\n"); buffer.append("[PROTECT]\n");
buffer.append(" .protected = ") buffer.append(" .protect = ").append(getProtect())
.append(Integer.toHexString(getProtect())).append("\n"); .append("\n");
buffer.append("[/PROTECT]\n"); buffer.append("[/PROTECT]\n");
return buffer.toString(); return buffer.toString();
} }
@ -160,7 +160,7 @@ public class ProtectRecord
LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, LittleEndian.putShort(data, 2 + offset,
(( short ) 0x02)); // 2 bytes (6 total) (( short ) 0x02)); // 2 bytes (6 total)
LittleEndian.putShort(data, 4 + offset, getProtect()); LittleEndian.putShort(data, 4 + offset, field_1_protect);
return getRecordSize(); return getRecordSize();
} }

View File

@ -139,18 +139,18 @@ public class ProtectionRev4Record
* @return whether to protect the workbook or not * @return whether to protect the workbook or not
*/ */
public short getProtect() public boolean getProtect()
{ {
return field_1_protect; return (field_1_protect == 1);
} }
public String toString() public String toString()
{ {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("[PROT4REV]\n"); buffer.append("[PROT4REV]\n");
buffer.append(" .rowheight = ") buffer.append(" .protect = ").append(getProtect())
.append(Integer.toHexString(getProtect())).append("\n"); .append("\n");
buffer.append("[/PROT4REV]\n"); buffer.append("[/PROT4REV]\n");
return buffer.toString(); return buffer.toString();
} }
@ -160,7 +160,7 @@ public class ProtectionRev4Record
LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, LittleEndian.putShort(data, 2 + offset,
(( short ) 0x02)); // 2 bytes (6 total) (( short ) 0x02)); // 2 bytes (6 total)
LittleEndian.putShort(data, 4 + offset, getProtect()); LittleEndian.putShort(data, 4 + offset, field_1_protect);
return getRecordSize(); return getRecordSize();
} }

View File

@ -70,16 +70,6 @@ package org.apache.poi.hssf.record;
public abstract class Record public abstract class Record
{ {
/**
* The static ID, subclasses should override this value with the id for the
* record type they handle.
*/
public short sid = 0;
private short id = 0;
private short size = 0;
private byte[] data = null;
/** /**
* instantiates a blank record strictly for ID matching * instantiates a blank record strictly for ID matching
*/ */
@ -98,9 +88,6 @@ public abstract class Record
public Record(short id, short size, byte [] data) public Record(short id, short size, byte [] data)
{ {
this.id = id;
this.size = size;
this.data = data;
validateSid(id); validateSid(id);
fillFields(data, size); fillFields(data, size);
} }
@ -115,9 +102,6 @@ public abstract class Record
public Record(short id, short size, byte [] data, int offset) public Record(short id, short size, byte [] data, int offset)
{ {
this.id = id;
this.size = size;
this.data = data;
validateSid(id); validateSid(id);
fillFields(data, size, offset); fillFields(data, size, offset);
} }

View File

@ -156,5 +156,10 @@ class RecordProcessor
recordOffset += amount; recordOffset += amount;
available -= amount; available -= amount;
} }
public int getRecordOffset()
{
return recordOffset;
}
} }

View File

@ -60,7 +60,6 @@ import org.apache.poi.util.LittleEndianConsts;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ArrayList;
/** /**
* Title: Static String Table Record * Title: Static String Table Record
@ -73,7 +72,7 @@ import java.util.ArrayList;
* @author Andrew C. Oliver (acoliver at apache dot org) * @author Andrew C. Oliver (acoliver at apache dot org)
* @author Marc Johnson (mjohnson at apache dot org) * @author Marc Johnson (mjohnson at apache dot org)
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
* @version 2.0-pre *
* @see org.apache.poi.hssf.record.LabelSSTRecord * @see org.apache.poi.hssf.record.LabelSSTRecord
* @see org.apache.poi.hssf.record.ContinueRecord * @see org.apache.poi.hssf.record.ContinueRecord
*/ */
@ -112,10 +111,14 @@ public class SSTRecord
private List _record_lengths = null; private List _record_lengths = null;
private SSTDeserializer deserializer; private SSTDeserializer deserializer;
/** Offsets from the beginning of the SST record (even across continuations) */
int[] bucketAbsoluteOffsets;
/** Offsets relative the start of the current SST or continue record */
int[] bucketRelativeOffsets;
/** /**
* default constructor * default constructor
*/ */
public SSTRecord() public SSTRecord()
{ {
field_1_num_strings = 0; field_1_num_strings = 0;
@ -220,7 +223,7 @@ public class SSTRecord
field_1_num_strings++; field_1_num_strings++;
String str = ( string == null ) ? "" String str = ( string == null ) ? ""
: string; : string;
int rval = -1; int rval;
UnicodeString ucs = new UnicodeString(); UnicodeString ucs = new UnicodeString();
ucs.setString( str ); ucs.setString( str );
@ -334,7 +337,7 @@ public class SSTRecord
for ( int k = 0; k < field_3_strings.size(); k++ ) for ( int k = 0; k < field_3_strings.size(); k++ )
{ {
buffer.append( " .string_" + k + " = " ) buffer.append( " .string_" + k + " = " )
.append( ( (UnicodeString) field_3_strings .append( ( field_3_strings
.get( new Integer( k ) ) ).toString() ).append( "\n" ); .get( new Integer( k ) ) ).toString() ).append( "\n" );
} }
buffer.append( "[/SST]\n" ); buffer.append( "[/SST]\n" );
@ -394,7 +397,7 @@ public class SSTRecord
* The data consists of sets of string data. This string data is * The data consists of sets of string data. This string data is
* arranged as follows: * arranged as follows:
* <P> * <P>
* <CODE> * <CODE><pre>
* short string_length; // length of string data * short string_length; // length of string data
* byte string_flag; // flag specifying special string * byte string_flag; // flag specifying special string
* // handling * // handling
@ -407,7 +410,7 @@ public class SSTRecord
* // array is run_count) * // array is run_count)
* byte[] extension; // optional extension (length of array * byte[] extension; // optional extension (length of array
* // is extend_length) * // is extend_length)
* </CODE> * </pre></CODE>
* <P> * <P>
* The string_flag is bit mapped as follows: * The string_flag is bit mapped as follows:
* <P> * <P>
@ -507,14 +510,22 @@ public class SSTRecord
* Subclasses should implement this so that their data is passed back in a * Subclasses should implement this so that their data is passed back in a
* byte array. * byte array.
* *
* @return byte array containing instance data * @return size
*/ */
public int serialize( int offset, byte[] data ) public int serialize( int offset, byte[] data )
{ {
SSTSerializer serializer = new SSTSerializer( SSTSerializer serializer = new SSTSerializer(
_record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() ); _record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() );
return serializer.serialize( getRecordSize(), offset, data ); int bytes = serializer.serialize( getRecordSize(), offset, data );
bucketAbsoluteOffsets = serializer.getBucketAbsoluteOffsets();
bucketRelativeOffsets = serializer.getBucketRelativeOffsets();
// for ( int i = 0; i < bucketAbsoluteOffsets.length; i++ )
// {
// System.out.println( "bucketAbsoluteOffset = " + bucketAbsoluteOffsets[i] );
// System.out.println( "bucketRelativeOffset = " + bucketRelativeOffsets[i] );
// }
return bytes;
} }
@ -538,6 +549,45 @@ public class SSTRecord
{ {
deserializer.processContinueRecord( record ); deserializer.processContinueRecord( record );
} }
/**
* Creates an extended string record based on the current contents of
* the current SST record. The offset within the stream to the SST record
* is required because the extended string record points directly to the
* strings in the SST record.
* <p>
* NOTE: THIS FUNCTION MUST ONLY BE CALLED AFTER THE SST RECORD HAS BEEN
* SERIALIZED.
*
* @param sstOffset The offset in the stream to the start of the
* SST record.
* @return The new SST record.
*/
public ExtSSTRecord createExtSSTRecord(int sstOffset)
{
if (bucketAbsoluteOffsets == null || bucketAbsoluteOffsets == null)
throw new IllegalStateException("SST record has not yet been serialized.");
ExtSSTRecord extSST = new ExtSSTRecord();
extSST.setNumStringsPerBucket((short)8);
int[] absoluteOffsets = (int[]) bucketAbsoluteOffsets.clone();
int[] relativeOffsets = (int[]) bucketRelativeOffsets.clone();
for ( int i = 0; i < absoluteOffsets.length; i++ )
absoluteOffsets[i] += sstOffset;
extSST.setBucketOffsets(absoluteOffsets, relativeOffsets);
return extSST;
}
/**
* Calculates the size in bytes of the EXTSST record as it would be if the
* record was serialized.
*
* @return The size of the ExtSST record in bytes.
*/
public int calcExtSSTRecordSize()
{
return 4 + 2 + ((field_3_strings.size() / SSTSerializer.DEFAULT_BUCKET_SIZE) + 1) * 8;
}
} }

View File

@ -61,7 +61,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Used to calculate the record sizes for a particular record. * Used to calculate the record sizes for a particular record. This kind of
* sucks because it's similar to the SST serialization code. In general
* the SST serialization code needs to be rewritten.
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */

View File

@ -77,6 +77,14 @@ class SSTSerializer
private int numUniqueStrings; private int numUniqueStrings;
private SSTRecordHeader sstRecordHeader; private SSTRecordHeader sstRecordHeader;
/** Offsets from the beginning of the SST record (even across continuations) */
int[] bucketAbsoluteOffsets;
/** Offsets relative the start of the current SST or continue record */
int[] bucketRelativeOffsets;
int startOfSST, startOfRecord;
/** The default bucket size (this is used for ExternSST) */
final static int DEFAULT_BUCKET_SIZE = 8;
public SSTSerializer( List recordLengths, BinaryTree strings, int numStrings, int numUniqueStrings ) public SSTSerializer( List recordLengths, BinaryTree strings, int numStrings, int numUniqueStrings )
{ {
this.recordLengths = recordLengths; this.recordLengths = recordLengths;
@ -84,6 +92,9 @@ class SSTSerializer
this.numStrings = numStrings; this.numStrings = numStrings;
this.numUniqueStrings = numUniqueStrings; this.numUniqueStrings = numUniqueStrings;
this.sstRecordHeader = new SSTRecordHeader( numStrings, numUniqueStrings ); this.sstRecordHeader = new SSTRecordHeader( numStrings, numUniqueStrings );
this.bucketAbsoluteOffsets = new int[strings.size()/DEFAULT_BUCKET_SIZE+1];
this.bucketRelativeOffsets = new int[strings.size()/DEFAULT_BUCKET_SIZE+1];
} }
/** /**
@ -133,7 +144,6 @@ class SSTSerializer
/** /**
* This case is chosen when an SST record does not span over to a continue record. * This case is chosen when an SST record does not span over to a continue record.
*
*/ */
private void serializeSingleSSTRecord( byte[] data, int offset, int record_length_index ) private void serializeSingleSSTRecord( byte[] data, int offset, int record_length_index )
{ {
@ -144,6 +154,11 @@ class SSTSerializer
for ( int k = 0; k < strings.size(); k++ ) for ( int k = 0; k < strings.size(); k++ )
{ {
if (k % DEFAULT_BUCKET_SIZE == 0)
{
bucketAbsoluteOffsets[k / DEFAULT_BUCKET_SIZE] = pos;
bucketRelativeOffsets[k / DEFAULT_BUCKET_SIZE] = pos;
}
System.arraycopy( getUnicodeString( k ).serialize(), 0, data, pos + offset, getUnicodeString( k ).getRecordSize() ); System.arraycopy( getUnicodeString( k ).serialize(), 0, data, pos + offset, getUnicodeString( k ).getRecordSize() );
pos += getUnicodeString( k ).getRecordSize(); pos += getUnicodeString( k ).getRecordSize();
} }
@ -157,6 +172,8 @@ class SSTSerializer
private void serializeLargeRecord( int record_size, int record_length_index, byte[] buffer, int offset ) private void serializeLargeRecord( int record_size, int record_length_index, byte[] buffer, int offset )
{ {
startOfSST = offset;
byte[] stringReminant = null; byte[] stringReminant = null;
int stringIndex = 0; int stringIndex = 0;
boolean lastneedcontinue = false; boolean lastneedcontinue = false;
@ -170,6 +187,7 @@ class SSTSerializer
recordLength, numStrings, numUniqueStrings ); recordLength, numStrings, numUniqueStrings );
// write the appropriate header // write the appropriate header
startOfRecord = offset + totalWritten;
recordProcessor.writeRecordHeader( offset, totalWritten, recordLength, first_record ); recordProcessor.writeRecordHeader( offset, totalWritten, recordLength, first_record );
first_record = false; first_record = false;
@ -189,6 +207,12 @@ class SSTSerializer
{ {
UnicodeString unistr = getUnicodeString( stringIndex ); UnicodeString unistr = getUnicodeString( stringIndex );
if (stringIndex % DEFAULT_BUCKET_SIZE == 0)
{
bucketAbsoluteOffsets[stringIndex / DEFAULT_BUCKET_SIZE] = offset + totalWritten + recordProcessor.getRecordOffset() - startOfSST;
bucketRelativeOffsets[stringIndex / DEFAULT_BUCKET_SIZE] = offset + totalWritten + recordProcessor.getRecordOffset() - startOfRecord;
}
if ( unistr.getRecordSize() <= recordProcessor.getAvailable() ) if ( unistr.getRecordSize() <= recordProcessor.getAvailable() )
{ {
recordProcessor.writeWholeString( unistr, offset, totalWritten ); recordProcessor.writeWholeString( unistr, offset, totalWritten );
@ -235,4 +259,14 @@ class SSTSerializer
{ {
return recordLengths; return recordLengths;
} }
public int[] getBucketAbsoluteOffsets()
{
return bucketAbsoluteOffsets;
}
public int[] getBucketRelativeOffsets()
{
return bucketRelativeOffsets;
}
} }

View File

@ -57,12 +57,14 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
import org.apache.poi.util.BitField;
/** /**
* Title: Style Record<P> * Title: Style Record<P>
* Description: Describes a builtin to the gui or user defined style<P> * Description: Describes a builtin to the gui or user defined style<P>
* REFERENCE: PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> * REFERENCE: PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org) * @author Andrew C. Oliver (acoliver at apache dot org)
* @author aviks : string fixes for UserDefined Style
* @version 2.0-pre * @version 2.0-pre
*/ */
@ -81,8 +83,10 @@ public class StyleRecord
private byte field_3_outline_style_level; private byte field_3_outline_style_level;
// only for user defined styles // only for user defined styles
private byte field_2_name_length; private short field_2_name_length; //OO doc says 16 bit length, so we believe
private String field_3_name; private byte field_3_string_options;
private BitField fHighByte;
private String field_4_name;
public StyleRecord() public StyleRecord()
{ {
@ -125,17 +129,24 @@ public class StyleRecord
protected void fillFields(byte [] data, short size, int offset) protected void fillFields(byte [] data, short size, int offset)
{ {
fHighByte = new BitField(0x01); //have to init here, since we are being called
//from super, and class level init hasnt been done.
field_1_xf_index = LittleEndian.getShort(data, 0 + offset); field_1_xf_index = LittleEndian.getShort(data, 0 + offset);
if (getType() == 1) if (getType() == STYLE_BUILT_IN)
{ {
field_2_builtin_style = data[ 2 + offset ]; field_2_builtin_style = data[ 2 + offset ];
field_3_outline_style_level = data[ 3 + offset ]; field_3_outline_style_level = data[ 3 + offset ];
} }
else if (getType() == 0) else if (getType() == STYLE_USER_DEFINED)
{ {
field_2_name_length = data[ 2 + offset ]; field_2_name_length = LittleEndian.getShort(data, 2 + offset );
field_3_name = StringUtil.getFromCompressedUnicode(data, 3 + offset, field_3_string_options = data[4+offset];
LittleEndian.ubyteToInt(field_2_name_length));
if (fHighByte.isSet(field_3_string_options)) {
field_4_name= StringUtil.getFromUnicode(data,offset+5,field_2_name_length);
}else {
field_4_name=StringUtil.getFromCompressedUnicode(data,offset+5,field_2_name_length);
}
} }
// todo sanity check exception to make sure we're one or the other // todo sanity check exception to make sure we're one or the other
@ -199,7 +210,8 @@ public class StyleRecord
public void setName(String name) public void setName(String name)
{ {
field_3_name = name; field_4_name = name;
//TODO set name length and string options
} }
// end user defined // end user defined
@ -273,7 +285,7 @@ public class StyleRecord
* @see #getName() * @see #getName()
*/ */
public byte getNameLength() public short getNameLength()
{ {
return field_2_name_length; return field_2_name_length;
} }
@ -286,7 +298,7 @@ public class StyleRecord
public String getName() public String getName()
{ {
return field_3_name; return field_4_name;
} }
// end user defined // end user defined
@ -361,7 +373,7 @@ public class StyleRecord
else else
{ {
LittleEndian.putShort(data, 2 + offset, LittleEndian.putShort(data, 2 + offset,
(( short ) (0x03 + getNameLength()))); (( short ) (getRecordSize()-4)));
} }
LittleEndian.putShort(data, 4 + offset, getIndex()); LittleEndian.putShort(data, 4 + offset, getIndex());
if (getType() == STYLE_BUILT_IN) if (getType() == STYLE_BUILT_IN)
@ -371,8 +383,9 @@ public class StyleRecord
} }
else else
{ {
data[ 6 + offset ] = getNameLength(); LittleEndian.putShort(data, 6 + offset , getNameLength());
StringUtil.putCompressedUnicode(getName(), data, 7 + offset); data[8+offset]=this.field_3_string_options;
StringUtil.putCompressedUnicode(getName(), data, 9 + offset);
} }
return getRecordSize(); return getRecordSize();
} }
@ -387,7 +400,11 @@ public class StyleRecord
} }
else else
{ {
retval = 7 + getNameLength(); if (fHighByte.isSet(field_3_string_options)) {
retval= 9+2*getNameLength();
}else {
retval = 9 + getNameLength();
}
} }
return retval; return retval;
} }

View File

@ -65,16 +65,14 @@ import org.apache.poi.util.LittleEndian;
* Company: SuperLink Software, Inc.<P> * Company: SuperLink Software, Inc.<P>
* @author Andrew C. Oliver (acoliver at apache dot org) * @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au) * @author Jason Height (jheight at chariot dot net dot au)
* @version 2.0-pre * @author Glen Stampoultzis (glens at apache.org)
*/ */
public class UnknownRecord public class UnknownRecord
extends Record extends Record
{ {
private short sid = 0; private short sid = 0;
private short size = 0; private byte[] thedata = null;
private byte[] thedata = null;
int offset = 0;
public UnknownRecord() public UnknownRecord()
{ {
@ -91,7 +89,6 @@ public class UnknownRecord
public UnknownRecord(short id, short size, byte [] data) public UnknownRecord(short id, short size, byte [] data)
{ {
sid = id; sid = id;
size = size;
thedata = data; thedata = data;
} }
@ -127,7 +124,7 @@ public class UnknownRecord
protected void fillFields(byte [] data, short sid) protected void fillFields(byte [] data, short sid)
{ {
sid = sid; this.sid = sid;
thedata = data; thedata = data;
} }
@ -179,9 +176,7 @@ public class UnknownRecord
/** Unlike the other Record.clone methods this is a shallow clone*/ /** Unlike the other Record.clone methods this is a shallow clone*/
public Object clone() { public Object clone() {
UnknownRecord rec = new UnknownRecord(); UnknownRecord rec = new UnknownRecord();
rec.offset = offset;
rec.sid = sid; rec.sid = sid;
rec.size = size;
rec.thedata = thedata; rec.thedata = thedata;
return rec; return rec;
} }

View File

@ -82,6 +82,19 @@ public class FormulaRecordAggregate
this.stringRecord = stringRecord; this.stringRecord = stringRecord;
} }
/**
* Used only in the clone
* @param formulaRecord
* @param stringRecord
* @param sharedRecord
*/
public FormulaRecordAggregate( FormulaRecord formulaRecord, StringRecord stringRecord, SharedFormulaRecord sharedRecord)
{
this.formulaRecord = formulaRecord;
this.stringRecord = stringRecord;
this.sharedFormulaRecord = sharedRecord;
}
protected void validateSid( short id ) protected void validateSid( short id )
@ -106,14 +119,14 @@ public class FormulaRecordAggregate
{ {
int pos = offset; int pos = offset;
pos += formulaRecord.serialize(pos, data); pos += formulaRecord.serialize(pos, data);
if (stringRecord != null)
{
pos += stringRecord.serialize(pos, data);
}
if (this.getSharedFormulaRecord() != null) if (this.getSharedFormulaRecord() != null)
{ {
pos += getSharedFormulaRecord().serialize(pos, data); pos += getSharedFormulaRecord().serialize(pos, data);
} }
if (stringRecord != null)
{
pos += stringRecord.serialize(pos, data);
}
return pos - offset; return pos - offset;
} }
@ -221,7 +234,10 @@ public class FormulaRecordAggregate
* @see java.lang.Object#clone() * @see java.lang.Object#clone()
*/ */
public Object clone() { public Object clone() {
return new FormulaRecordAggregate((FormulaRecord) this.formulaRecord.clone(), (StringRecord) this.stringRecord.clone()); StringRecord clonedString = (stringRecord == null) ? null : (StringRecord)stringRecord.clone();
SharedFormulaRecord clonedShared = (sharedFormulaRecord == null) ? null : (SharedFormulaRecord)sharedFormulaRecord.clone();
return new FormulaRecordAggregate((FormulaRecord) this.formulaRecord.clone(), clonedString, clonedShared);
} }
@ -241,4 +257,14 @@ public class FormulaRecordAggregate
this.sharedFormulaRecord = sharedFormulaRecord; this.sharedFormulaRecord = sharedFormulaRecord;
} }
/*
* Setting to true so that this value does not abort the whole ValueAggregation
* (non-Javadoc)
* @see org.apache.poi.hssf.record.Record#isInValueSection()
*/
public boolean isInValueSection() {
return true;
}
} }

View File

@ -318,6 +318,7 @@ public class Area3DPtg extends Ptg
ptg.field_3_last_row = field_3_last_row; ptg.field_3_last_row = field_3_last_row;
ptg.field_4_first_column = field_4_first_column; ptg.field_4_first_column = field_4_first_column;
ptg.field_5_last_column = field_5_last_column; ptg.field_5_last_column = field_5_last_column;
ptg.setClass(ptgClass);
return ptg; return ptg;
} }

View File

@ -321,6 +321,7 @@ public class AreaPtg
ptg.field_2_last_row = field_2_last_row; ptg.field_2_last_row = field_2_last_row;
ptg.field_3_first_column = field_3_first_column; ptg.field_3_first_column = field_3_first_column;
ptg.field_4_last_column = field_4_last_column; ptg.field_4_last_column = field_4_last_column;
ptg.setClass(ptgClass);
return ptg; return ptg;
} }

View File

@ -110,7 +110,10 @@ public class ExpPtg
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;} public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() { public Object clone() {
throw new RuntimeException("NO IDEA SHARED FORMULA EXP PTG"); //can't clone one that doesnt have data can we??
if (this.existing == null) throw new RuntimeException("NO IDEA SHARED FORMULA EXP PTG");
return new ExpPtg(this.existing, 0);
} }
} }

View File

@ -63,7 +63,8 @@ public class FuncPtg extends AbstractFunctionPtg{
FuncPtg ptg = new FuncPtg(); FuncPtg ptg = new FuncPtg();
//ptg.field_1_num_args = field_1_num_args; //ptg.field_1_num_args = field_1_num_args;
ptg.field_2_fnc_index = field_2_fnc_index; ptg.field_2_fnc_index = field_2_fnc_index;
return ptg; ptg.setClass(ptgClass);
return ptg;
} }
public int getSize() { public int getSize() {

View File

@ -52,6 +52,7 @@ public class FuncVarPtg extends AbstractFunctionPtg{
FuncVarPtg ptg = new FuncVarPtg(); FuncVarPtg ptg = new FuncVarPtg();
ptg.field_1_num_args = field_1_num_args; ptg.field_1_num_args = field_1_num_args;
ptg.field_2_fnc_index = field_2_fnc_index; ptg.field_2_fnc_index = field_2_fnc_index;
ptg.setClass(ptgClass);
return ptg; return ptg;
} }

View File

@ -66,7 +66,7 @@ public class GreaterEqualPtg
public final static int SIZE = 1; public final static int SIZE = 1;
public final static byte sid = 0x0c; public final static byte sid = 0x0c;
/** Creates new AddPtg */ /** Creates new GreaterEqualPtg */
public GreaterEqualPtg() public GreaterEqualPtg()
{ {

View File

@ -67,7 +67,7 @@ public class LessEqualPtg
public final static int SIZE = 1; public final static int SIZE = 1;
public final static byte sid = 0x0a; public final static byte sid = 0x0a;
/** Creates new AddPtg */ /** Creates new LessEqualPtg */
public LessEqualPtg() public LessEqualPtg()
{ {

View File

@ -73,10 +73,10 @@ public class NamePtg
extends Ptg extends Ptg
{ {
public final static short sid = 0x23; public final static short sid = 0x23;
private final static int SIZE = 7; private final static int SIZE = 5;
private short field_1_ixti; // unknown function private short field_1_label_index;
private short field_2_label_index; private short field_2_zero; // reserved must be 0
private short field_3_zero; // reserved must be 0 boolean xtra=false;
private NamePtg() { private NamePtg() {
@ -95,13 +95,17 @@ public class NamePtg
public NamePtg(byte [] data, int offset) public NamePtg(byte [] data, int offset)
{ {
offset++; offset++;
field_1_ixti = LittleEndian.getShort(data, offset); //field_1_ixti = LittleEndian.getShort(data, offset);
field_2_label_index = LittleEndian.getShort(data, offset + 2); field_1_label_index = LittleEndian.getShort(data, offset );
field_3_zero = LittleEndian.getShort(data, offset + 4); field_2_zero = LittleEndian.getShort(data, offset + 2);
//if (data[offset+6]==0) xtra=true;
} }
public void writeBytes(byte [] array, int offset) public void writeBytes(byte [] array, int offset)
{ {
array[offset+0]= (byte) (sid + ptgClass);
LittleEndian.putShort(array,offset+1,field_1_label_index);
LittleEndian.putShort(array,offset+3, field_2_zero);
} }
public int getSize() public int getSize()
@ -111,16 +115,15 @@ public class NamePtg
public String toFormulaString(SheetReferences refs) public String toFormulaString(SheetReferences refs)
{ {
return "NO IDEA - NAME"; return "NAMED RANGE";
} }
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;} public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() { public Object clone() {
NamePtg ptg = new NamePtg(); NamePtg ptg = new NamePtg();
ptg.field_1_ixti = field_1_ixti; ptg.field_1_label_index = field_1_label_index;
ptg.field_2_label_index = field_2_label_index; ptg.field_2_zero = field_2_zero;
ptg.field_3_zero = field_3_zero;
return ptg; return ptg;
} }
} }

View File

@ -102,7 +102,7 @@ public class NameXPtg extends Ptg
public void writeBytes(byte [] array, int offset) public void writeBytes(byte [] array, int offset)
{ {
array[ offset + 0 ] = sid; array[ offset + 0 ] = (byte)(sid + ptgClass);
LittleEndian.putShort(array, offset + 1, field_1_ixals); LittleEndian.putShort(array, offset + 1, field_1_ixals);
LittleEndian.putShort(array,offset+3, field_2_ilbl); LittleEndian.putShort(array,offset+3, field_2_ilbl);
LittleEndian.putShort(array, offset + 5, field_3_reserved); LittleEndian.putShort(array, offset + 5, field_3_reserved);
@ -125,6 +125,7 @@ public class NameXPtg extends Ptg
ptg.field_1_ixals = field_1_ixals; ptg.field_1_ixals = field_1_ixals;
ptg.field_3_reserved = field_3_reserved; ptg.field_3_reserved = field_3_reserved;
ptg.field_2_ilbl = field_2_ilbl; ptg.field_2_ilbl = field_2_ilbl;
ptg.setClass(ptgClass);
return ptg; return ptg;
} }
} }

View File

@ -69,7 +69,7 @@ public class NotEqualPtg
public final static int SIZE = 1; public final static int SIZE = 1;
public final static byte sid = 0x0e; public final static byte sid = 0x0e;
/** Creates new AddPtg */ /** Creates new NotEqualPtg */
public NotEqualPtg() public NotEqualPtg()
{ {

View File

@ -307,6 +307,12 @@ public abstract class Ptg
case MissingArgPtg.sid: case MissingArgPtg.sid:
retval = new MissingArgPtg(data,offset); retval = new MissingArgPtg(data,offset);
break; break;
case UnaryPlusPtg.sid:
retval=new UnaryPlusPtg(data,offset);
break;
case UnaryMinusPtg.sid:
retval=new UnaryMinusPtg(data,offset);
break;
default : default :
@ -357,6 +363,14 @@ public abstract class Ptg
return retval; return retval;
} }
/** Overridden toString method to ensure object hash is not printed.
* This helps get rid of gratuitous diffs when comparing two dumps
* Subclasses may output more relevant information by overriding this method
**/
public String toString(){
return this.getClass().toString();
}
public static final byte CLASS_REF = 0x00; public static final byte CLASS_REF = 0x00;
public static final byte CLASS_VALUE = 0x20; public static final byte CLASS_VALUE = 0x20;
public static final byte CLASS_ARRAY = 0x40; public static final byte CLASS_ARRAY = 0x40;

View File

@ -104,7 +104,7 @@ public class Ref3DPtg extends Ptg {
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("Ref3dPrg\n"); buffer.append("Ref3dPtg\n");
buffer.append("Index to Extern Sheet = " + getExternSheetIndex()).append("\n"); buffer.append("Index to Extern Sheet = " + getExternSheetIndex()).append("\n");
buffer.append("Row = " + getRow()).append("\n"); buffer.append("Row = " + getRow()).append("\n");
buffer.append("Col = " + getColumn()).append("\n"); buffer.append("Col = " + getColumn()).append("\n");
@ -210,6 +210,7 @@ public class Ref3DPtg extends Ptg {
ptg.field_1_index_extern_sheet = field_1_index_extern_sheet; ptg.field_1_index_extern_sheet = field_1_index_extern_sheet;
ptg.field_2_row = field_2_row; ptg.field_2_row = field_2_row;
ptg.field_3_column = field_3_column; ptg.field_3_column = field_3_column;
ptg.setClass(ptgClass);
return ptg; return ptg;
} }

View File

@ -193,6 +193,7 @@ public class ReferencePtg extends Ptg
ReferencePtg ptg = new ReferencePtg(); ReferencePtg ptg = new ReferencePtg();
ptg.field_1_row = field_1_row; ptg.field_1_row = field_1_row;
ptg.field_2_col = field_2_col; ptg.field_2_col = field_2_col;
ptg.setClass(ptgClass);
return ptg; return ptg;
} }
} }

View File

@ -55,8 +55,9 @@
package org.apache.poi.hssf.record.formula; package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.BitField;
import org.apache.poi.hssf.util.SheetReferences; import org.apache.poi.hssf.util.SheetReferences;
import org.apache.poi.util.StringUtil;
/** /**
* Number * Number
@ -70,7 +71,12 @@ public class StringPtg
{ {
public final static int SIZE = 9; public final static int SIZE = 9;
public final static byte sid = 0x17; public final static byte sid = 0x17;
private String field_1_value; //NOTE: OO doc says 16bit lenght, but BiffViewer says 8
// Book says something totally different, so dont look there!
byte field_1_length;
byte field_2_options;
BitField fHighByte = new BitField(0x01);
private String field_3_string;
private StringPtg() { private StringPtg() {
//Required for clone methods //Required for clone methods
@ -79,7 +85,16 @@ public class StringPtg
/** Create a StringPtg from a byte array read from disk */ /** Create a StringPtg from a byte array read from disk */
public StringPtg(byte [] data, int offset) public StringPtg(byte [] data, int offset)
{ {
setValue(new String(data, offset+3, data[offset+1] + 256*data[offset+2])); offset++;
field_1_length = data[offset];
field_2_options = data[offset+1];
if (fHighByte.isSet(field_2_options)) {
field_3_string= StringUtil.getFromUnicode(data,offset+2,field_1_length);
}else {
field_3_string=StringUtil.getFromCompressedUnicode(data,offset+2,field_1_length);
}
//setValue(new String(data, offset+3, data[offset+1] + 256*data[offset+2]));
} }
/** Create a StringPtg from a string representation of the number /** Create a StringPtg from a string representation of the number
@ -88,32 +103,46 @@ public class StringPtg
* @param value : String representation of a floating point number * @param value : String representation of a floating point number
*/ */
public StringPtg(String value) { public StringPtg(String value) {
setValue(value); if (value.length() >255) {
throw new IllegalArgumentException("String literals in formulas cant be bigger than 255 characters ASCII");
}
this.field_2_options=0;
this.fHighByte.setBoolean(field_2_options, false);
this.field_3_string=value;
this.field_1_length=(byte)value.length(); //for the moment, we support only ASCII strings in formulas we create
} }
/*
public void setValue(String value) public void setValue(String value)
{ {
field_1_value = value; field_1_value = value;
} }*/
public String getValue() public String getValue()
{ {
return field_1_value; return field_3_string;
} }
public void writeBytes(byte [] array, int offset) public void writeBytes(byte [] array, int offset)
{ {
array[ offset + 0 ] = sid; array[ offset + 0 ] = sid;
array[ offset + 1 ] = (byte)(getValue().length() % 256); array[ offset + 1 ] = field_1_length;
array[ offset + 2 ] = (byte)(getValue().length() / 256); array[ offset + 2 ] = field_2_options;
System.arraycopy(getValue().getBytes(), 0, array, offset + 3, getValue().length()); if (fHighByte.isSet(field_2_options)) {
StringUtil.putUncompressedUnicode(getValue(),array,offset+3);
}else {
StringUtil.putCompressedUnicode(getValue(),array,offset+3);
}
} }
public int getSize() public int getSize()
{ {
return field_1_value.length() + 3; if (fHighByte.isSet(field_2_options)) {
return 2*field_1_length+3;
}else {
return field_1_length+3;
}
} }
public String toFormulaString(SheetReferences refs) public String toFormulaString(SheetReferences refs)
@ -126,7 +155,9 @@ public class StringPtg
public Object clone() { public Object clone() {
StringPtg ptg = new StringPtg(); StringPtg ptg = new StringPtg();
ptg.field_1_value = field_1_value; ptg.field_1_length = field_1_length;
ptg.field_2_options=field_2_options;
ptg.field_3_string=field_3_string;
return ptg; return ptg;
} }

View File

@ -0,0 +1,127 @@
/* ====================================================================
* 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
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record.formula;
import java.util.List;
import org.apache.poi.hssf.util.SheetReferences;
/**
* Unary Plus operator
* does not have any effect on the operand
* @author Avik Sengupta
*/
public class UnaryMinusPtg extends OperationPtg
{
public final static int SIZE = 1;
public final static byte sid = 0x13;
private final static String MINUS = "-";
/** Creates new AddPtg */
public UnaryMinusPtg()
{
}
public UnaryMinusPtg(byte[] data, int offset)
{
// doesn't need anything
}
public void writeBytes(byte [] array, int offset)
{
array[ offset + 0 ] = sid;
}
public int getSize()
{
return SIZE;
}
public int getType()
{
return this.TYPE_UNARY;
}
public int getNumberOfOperands()
{
return 1;
}
/** Implementation of method from Ptg */
public String toFormulaString(SheetReferences refs)
{
return "+";
}
/** implementation of method from OperationsPtg*/
public String toFormulaString(String[] operands) {
StringBuffer buffer = new StringBuffer();
buffer.append(MINUS);
buffer.append(operands[ 0]);
return buffer.toString();
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new UnaryPlusPtg();
}
}

View File

@ -0,0 +1,127 @@
/* ====================================================================
* 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
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record.formula;
import java.util.List;
import org.apache.poi.hssf.util.SheetReferences;
/**
* Unary Plus operator
* does not have any effect on the operand
* @author Avik Sengupta
*/
public class UnaryPlusPtg extends OperationPtg
{
public final static int SIZE = 1;
public final static byte sid = 0x12;
private final static String ADD = "+";
/** Creates new AddPtg */
public UnaryPlusPtg()
{
}
public UnaryPlusPtg(byte[] data, int offset)
{
// doesn't need anything
}
public void writeBytes(byte [] array, int offset)
{
array[ offset + 0 ] = sid;
}
public int getSize()
{
return SIZE;
}
public int getType()
{
return this.TYPE_UNARY;
}
public int getNumberOfOperands()
{
return 1;
}
/** Implementation of method from Ptg */
public String toFormulaString(SheetReferences refs)
{
return "+";
}
/** implementation of method from OperationsPtg*/
public String toFormulaString(String[] operands) {
StringBuffer buffer = new StringBuffer();
buffer.append(ADD);
buffer.append(operands[ 0]);
return buffer.toString();
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new UnaryPlusPtg();
}
}

View File

@ -103,7 +103,7 @@ public class HSSFPalette
for (short i = (short) PaletteRecord.FIRST_COLOR_INDEX; b != null; for (short i = (short) PaletteRecord.FIRST_COLOR_INDEX; b != null;
b = palette.getColor(++i)) b = palette.getColor(++i))
{ {
if (b[0] == red && b[1] == blue && b[2] == green) if (b[0] == red && b[1] == green && b[2] == blue)
{ {
return new CustomColor(i, b); return new CustomColor(i, b);
} }

View File

@ -59,17 +59,25 @@
*/ */
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.HCenterRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.VCenterRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.util.Region; import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.List;
/** /**
* High level representation of a worksheet. * High level representation of a worksheet.
* @author Andrew C. Oliver (acoliver at apache dot org) * @author Andrew C. Oliver (acoliver at apache dot org)
@ -865,6 +873,22 @@ public class HSSFSheet
{ {
getSheet().setMargin( margin, size ); getSheet().setMargin( margin, size );
} }
/**
* Answer whether protection is enabled or disabled
* @return true => protection enabled; false => protection disabled
*/
public boolean getProtect() {
return getSheet().getProtect().getProtect();
}
/**
* Sets the protection on enabled or disabled
* @param protect true => protection enabled; false => protection disabled
*/
public void setProtect(boolean protect) {
getSheet().getProtect().setProtect(protect);
}
/** /**
* Sets the zoom magnication for the sheet. The zoom is expressed as a * Sets the zoom magnication for the sheet. The zoom is expressed as a
@ -887,6 +911,50 @@ public class HSSFSheet
getSheet().setSCLRecord(sclRecord); getSheet().setSCLRecord(sclRecord);
} }
/**
* Shifts the merged regions left or right depending on mode
* <p>
* TODO: MODE , this is only row specific
* @param startRow
* @param endRow
* @param n
* @param isRow
*/
protected void shiftMerged(int startRow, int endRow, int n, boolean isRow) {
List shiftedRegions = new ArrayList();
//move merged regions completely if they fall within the new region boundaries when they are shifted
for (int i = 0; i < this.getNumMergedRegions(); i++) {
Region merged = this.getMergedRegionAt(i);
boolean inStart = (merged.getRowFrom() >= startRow || merged.getRowTo() >= startRow);
boolean inEnd = (merged.getRowTo() <= endRow || merged.getRowFrom() <= endRow);
//dont check if it's not within the shifted area
if (! (inStart && inEnd)) continue;
//only shift if the region outside the shifted rows is not merged too
if (!merged.contains(startRow-1, (short)0) && !merged.contains(endRow+1, (short)0)){
merged.setRowFrom(merged.getRowFrom()+n);
merged.setRowTo(merged.getRowTo()+n);
//have to remove/add it back
shiftedRegions.add(merged);
this.removeMergedRegion(i);
i = i -1; // we have to back up now since we removed one
}
}
//readd so it doesn't get shifted again
Iterator iterator = shiftedRegions.iterator();
while (iterator.hasNext()) {
Region region = (Region)iterator.next();
this.addMergedRegion(region);
}
}
/** /**
* Shifts rows between startRow and endRow n number of rows. * Shifts rows between startRow and endRow n number of rows.
* If you use a negative number, it will shift rows up. * If you use a negative number, it will shift rows up.
@ -894,19 +962,25 @@ public class HSSFSheet
* *
* Calls shiftRows(startRow, endRow, n, false, false); * Calls shiftRows(startRow, endRow, n, false, false);
* *
* <p>
* Additionally shifts merged regions that are completely defined in these
* rows (ie. merged 2 cells on a row to be shifted).
* @param startRow the row to start shifting * @param startRow the row to start shifting
* @param endRow the row to end shifting * @param endRow the row to end shifting
* @param n the number of rows to shift * @param n the number of rows to shift
*/ */
public void shiftRows( int startRow, int endRow, int n ) { public void shiftRows( int startRow, int endRow, int n ) {
shiftRows(startRow, endRow, n, false, false); shiftRows(startRow, endRow, n, false, false);
} }
/** /**
* Shifts rows between startRow and endRow n number of rows. * Shifts rows between startRow and endRow n number of rows.
* If you use a negative number, it will shift rows up. * If you use a negative number, it will shift rows up.
* Code ensures that rows don't wrap around * Code ensures that rows don't wrap around
* *
* <p>
* Additionally shifts merged regions that are completely defined in these
* rows (ie. merged 2 cells on a row to be shifted).
* @param startRow the row to start shifting * @param startRow the row to start shifting
* @param endRow the row to end shifting * @param endRow the row to end shifting
* @param n the number of rows to shift * @param n the number of rows to shift
@ -928,6 +1002,9 @@ public class HSSFSheet
e = startRow; e = startRow;
inc = -1; inc = -1;
} }
shiftMerged(startRow, endRow, n, true);
for ( int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc ) for ( int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc )
{ {
HSSFRow row = getRow( rowNum ); HSSFRow row = getRow( rowNum );
@ -937,6 +1014,9 @@ public class HSSFSheet
HSSFCell cell; HSSFCell cell;
// Removes the cells before over writting them. // Removes the cells before over writting them.
for ( short col = row2Replace.getFirstCellNum(); col <= row2Replace.getLastCellNum(); col++ ) for ( short col = row2Replace.getFirstCellNum(); col <= row2Replace.getLastCellNum(); col++ )
{ {
@ -1021,5 +1101,51 @@ public class HSSFSheet
getSheet().createSplitPane( xSplitPos, ySplitPos, topRow, leftmostColumn, activePane ); getSheet().createSplitPane( xSplitPos, ySplitPos, topRow, leftmostColumn, activePane );
} }
/**
* Sets whether the gridlines are shown in a viewer.
* @param show whether to show gridlines or not
*/
public void setDisplayGridlines(boolean show) {
sheet.setDisplayGridlines(show);
}
/**
* Returns if gridlines are displayed.
* @return whether gridlines are displayed
*/
public boolean isDisplayGridlines() {
return sheet.isDisplayGridlines();
}
/**
* Sets whether the formulas are shown in a viewer.
* @param show whether to show formulas or not
*/
public void setDisplayFormulas(boolean show) {
sheet.setDisplayFormulas(show);
}
/**
* Returns if formulas are displayed.
* @return whether formulas are displayed
*/
public boolean isDisplayFormulas() {
return sheet.isDisplayFormulas();
}
/**
* Sets whether the RowColHeadings are shown in a viewer.
* @param show whether to show RowColHeadings or not
*/
public void setDisplayRowColHeadings(boolean show) {
sheet.setDisplayRowColHeadings(show);
}
/**
* Returns if RowColHeadings are displayed.
* @return whether RowColHeadings are displayed
*/
public boolean isDisplayRowColHeadings() {
return sheet.isDisplayRowColHeadings();
}
} }

View File

@ -147,6 +147,14 @@ public class HSSFWorkbook
* memory. * memory.
*/ */
private POIFSFileSystem poifs; private POIFSFileSystem poifs;
/**
* Used to keep track of the data formatter so that all
* createDataFormatter calls return the same one for a given
* book. This ensures that updates from one places is visible
* someplace else.
*/
private HSSFDataFormat formatter;
private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class); private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class);
@ -945,13 +953,15 @@ public class HSSFWorkbook
} }
/** /**
* Creates an instance of HSSFDataFormat. * Returns the instance of HSSFDataFormat for this workbook.
* @return the HSSFDataFormat object * @return the HSSFDataFormat object
* @see org.apache.poi.hssf.record.FormatRecord * @see org.apache.poi.hssf.record.FormatRecord
* @see org.apache.poi.hssf.record.Record * @see org.apache.poi.hssf.record.Record
*/ */
public HSSFDataFormat createDataFormat() { public HSSFDataFormat createDataFormat() {
return new HSSFDataFormat(workbook); if (formatter == null)
formatter = new HSSFDataFormat(workbook);
return formatter;
} }
/** remove the named range by his name /** remove the named range by his name

View File

@ -62,6 +62,7 @@ import java.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.IntegerField; import org.apache.poi.util.IntegerField;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -106,7 +107,7 @@ public class DocumentBlock
throws IOException throws IOException
{ {
this(); this();
int count = stream.read(_data); int count = IOUtils.readFully(stream, _data);
_bytes_read = (count == -1) ? 0 _bytes_read = (count == -1) ? 0
: count; : count;

View File

@ -60,6 +60,7 @@ import java.io.*;
import java.util.*; import java.util.*;
import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.IntegerField; import org.apache.poi.util.IntegerField;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
@ -104,7 +105,7 @@ public class HeaderBlockReader
throws IOException throws IOException
{ {
_data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ]; _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
int byte_count = stream.read(_data); int byte_count = IOUtils.readFully(stream, _data);
if (byte_count != POIFSConstants.BIG_BLOCK_SIZE) if (byte_count != POIFSConstants.BIG_BLOCK_SIZE)
{ {

View File

@ -56,6 +56,7 @@
package org.apache.poi.poifs.storage; package org.apache.poi.poifs.storage;
import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IOUtils;
import java.io.*; import java.io.*;
@ -84,7 +85,7 @@ public class RawDataBlock
throws IOException throws IOException
{ {
_data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ]; _data = new byte[ POIFSConstants.BIG_BLOCK_SIZE ];
int count = stream.read(_data); int count = IOUtils.readFully(stream, _data);
if (count == -1) if (count == -1)
{ {

View File

@ -67,6 +67,20 @@ import java.io.*;
public class HexDump public class HexDump
{ {
public static final String EOL =
System.getProperty("line.separator");
// private static final StringBuffer _lbuffer = new StringBuffer(8);
// private static final StringBuffer _cbuffer = new StringBuffer(2);
private static final char _hexcodes[] =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F'
};
private static final int _shifts[] =
{
28, 24, 20, 16, 12, 8, 4, 0
};
// all static methods, so no need for a public constructor // all static methods, so no need for a public constructor
private HexDump() private HexDump()
@ -95,12 +109,14 @@ public class HexDump
throws IOException, ArrayIndexOutOfBoundsException, throws IOException, ArrayIndexOutOfBoundsException,
IllegalArgumentException IllegalArgumentException
{ {
if ((index < 0) || (index >= data.length)) if ((index < 0) || (data.length != 0 && index >= data.length))
{ {
throw new ArrayIndexOutOfBoundsException( throw new ArrayIndexOutOfBoundsException(
"illegal index: " + index + " into array of length " "illegal index: " + index + " into array of length "
+ data.length); + data.length);
} }
if (data.length == 0)
return; // nothing more to do.
if (stream == null) if (stream == null)
{ {
throw new IllegalArgumentException("cannot write to nullstream"); throw new IllegalArgumentException("cannot write to nullstream");
@ -241,39 +257,26 @@ public class HexDump
} }
public static final String EOL =
System.getProperty("line.separator");
private static final StringBuffer _lbuffer = new StringBuffer(8);
private static final StringBuffer _cbuffer = new StringBuffer(2);
private static final char _hexcodes[] =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F'
};
private static final int _shifts[] =
{
28, 24, 20, 16, 12, 8, 4, 0
};
private static String dump(final long value) private static String dump(final long value)
{ {
_lbuffer.setLength(0); StringBuffer buf = new StringBuffer();
buf.setLength(0);
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
{ {
_lbuffer buf.append( _hexcodes[ (( int ) (value >> _shifts[ j ])) & 15 ]);
.append(_hexcodes[ (( int ) (value >> _shifts[ j ])) & 15 ]);
} }
return _lbuffer.toString(); return buf.toString();
} }
private static String dump(final byte value) private static String dump(final byte value)
{ {
_cbuffer.setLength(0); StringBuffer buf = new StringBuffer();
buf.setLength(0);
for (int j = 0; j < 2; j++) for (int j = 0; j < 2; j++)
{ {
_cbuffer.append(_hexcodes[ (value >> _shifts[ j + 6 ]) & 15 ]); buf.append(_hexcodes[ (value >> _shifts[ j + 6 ]) & 15 ]);
} }
return _cbuffer.toString(); return buf.toString();
} }
/** /**
@ -294,6 +297,7 @@ public class HexDump
retVal.append(']'); retVal.append(']');
return retVal.toString(); return retVal.toString();
} }
/** /**
* Converts the parameter to a hex value. * Converts the parameter to a hex value.
* *
@ -337,4 +341,41 @@ public class HexDump
} }
return result.toString(); return result.toString();
} }
/**
* Dumps <code>bytesToDump</code> bytes to an output stream.
*
* @param in The stream to read from
* @param out The output stream
* @param start The index to use as the starting position for the left hand side label
* @param bytesToDump The number of bytes to output. Use -1 to read until the end of file.
*/
public static void dump( InputStream in, PrintStream out, int start, int bytesToDump ) throws IOException
{
ByteArrayOutputStream buf = new ByteArrayOutputStream();
if (bytesToDump == -1)
{
int c = in.read();
while (c != -1)
{
buf.write(c);
c = in.read();
}
}
else
{
int bytesRemaining = bytesToDump;
while (bytesRemaining-- > 0)
{
int c = in.read();
if (c == -1)
break;
else
buf.write(c);
}
}
byte[] data = buf.toByteArray();
dump(data, 0, out, start, data.length);
}
} }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,99 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 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
* <http://www.apache.org/>.
*/
package org.apache.poi.util;
import java.io.IOException;
import java.io.InputStream;
public class IOUtils
{
private IOUtils()
{
}
/**
* Helper method, just calls <tt>readFully(in, b, 0, b.length)</tt>
*/
public static int readFully(InputStream in, byte[] b)
throws IOException
{
return readFully(in, b, 0, b.length);
}
/**
* Same as the normal <tt>in.read(b, off, len)</tt>, but tries to ensure that
* the entire len number of bytes is read.
* <p>
* If the end of file is reached before any bytes are read, returns -1.
* Otherwise, returns the number of bytes read.
*/
public static int readFully(InputStream in, byte[] b, int off, int len)
throws IOException
{
int total = 0;
for (;;) {
int got = in.read(b, off + total, len - total);
if (got < 0) {
return (total == 0) ? -1 : total;
} else {
total += got;
if (total == len)
return total;
}
}
}
}

View File

@ -475,23 +475,10 @@ public class LittleEndian
return getLong(readFromStream(stream, LONG_SIZE)); return getLong(readFromStream(stream, LONG_SIZE));
} }
private final static byte[] _short_buffer = new byte[SHORT_SIZE];
private final static byte[] _int_buffer = new byte[INT_SIZE];
private final static byte[] _long_buffer = new byte[LONG_SIZE];
/** /**
* Read the appropriate number of bytes from the stream and return them to * Read the appropriate number of bytes from the stream and return them to
* the caller. <p> * the caller. <p>
* *
* It should be noted that, in an attempt to improve system performance and
* to prevent a transient explosion of discarded byte arrays to be garbage
* collected, static byte arrays are employed for the standard cases of
* reading a short, an int, or a long. <p>
*
* <b>THIS INTRODUCES A RISK FOR THREADED OPERATIONS!</b> <p>
*
* However, for the purposes of the POI project, this risk is deemed * However, for the purposes of the POI project, this risk is deemed
* negligible. It is, however, so noted. * negligible. It is, however, so noted.
* *
@ -510,23 +497,8 @@ public class LittleEndian
public static byte[] readFromStream(final InputStream stream, public static byte[] readFromStream(final InputStream stream,
final int size) final int size)
throws IOException, BufferUnderrunException { throws IOException, BufferUnderrunException {
byte[] buffer = null; byte[] buffer = new byte[size];
switch (size) {
case SHORT_SIZE:
buffer = _short_buffer;
break;
case INT_SIZE:
buffer = _int_buffer;
break;
case LONG_SIZE:
buffer = _long_buffer;
break;
default:
buffer = new byte[size];
break;
}
int count = stream.read(buffer); int count = stream.read(buffer);
if (count == -1) { if (count == -1) {

File diff suppressed because one or more lines are too long

View File

@ -53,7 +53,8 @@
*/ */
package org.apache.poi.hpsf.basic; package org.apache.poi.hpsf.basic;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
@ -73,32 +74,32 @@ public class POIFile
public void setName(final String name) public void setName(final String name)
{ {
this.name = name; this.name = name;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public void setPath(final POIFSDocumentPath path) public void setPath(final POIFSDocumentPath path)
{ {
this.path = path; this.path = path;
} }
public POIFSDocumentPath getPath() public POIFSDocumentPath getPath()
{ {
return path; return path;
} }
public void setBytes(final byte[] bytes) public void setBytes(final byte[] bytes)
{ {
this.bytes = bytes; this.bytes = bytes;
} }
public byte[] getBytes() public byte[] getBytes()
{ {
return bytes; return bytes;
} }
} }

View File

@ -54,10 +54,23 @@
package org.apache.poi.hpsf.basic; package org.apache.poi.hpsf.basic;
import java.io.*; import java.io.ByteArrayInputStream;
import java.util.*; import java.io.File;
import junit.framework.*; import java.io.FileNotFoundException;
import org.apache.poi.hpsf.*; import java.io.IOException;
import java.io.InputStream;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.HPSFException;
import org.apache.poi.hpsf.MarkUnsupportedException;
import org.apache.poi.hpsf.NoPropertySetStreamException;
import org.apache.poi.hpsf.PropertySet;
import org.apache.poi.hpsf.PropertySetFactory;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
@ -71,37 +84,37 @@ import org.apache.poi.hpsf.*;
public class TestBasic extends TestCase public class TestBasic extends TestCase
{ {
final static String POI_FS = "TestGermanWord90.doc"; static final String POI_FS = "TestGermanWord90.doc";
final static String[] POI_FILES = new String[] static final String[] POI_FILES = new String[]
{ {
"\005SummaryInformation", "\005SummaryInformation",
"\005DocumentSummaryInformation", "\005DocumentSummaryInformation",
"WordDocument", "WordDocument",
"\001CompObj", "\001CompObj",
"1Table" "1Table"
}; };
final static int BYTE_ORDER = 0xfffe; static final int BYTE_ORDER = 0xfffe;
final static int FORMAT = 0x0000; static final int FORMAT = 0x0000;
final static int OS_VERSION = 0x00020A04; static final int OS_VERSION = 0x00020A04;
final static byte[] CLASS_ID = static final byte[] CLASS_ID =
{ {
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00
}; };
final static int[] SECTION_COUNT = static final int[] SECTION_COUNT =
{1, 2}; {1, 2};
final static boolean[] IS_SUMMARY_INFORMATION = static final boolean[] IS_SUMMARY_INFORMATION =
{true, false}; {true, false};
final static boolean[] IS_DOCUMENT_SUMMARY_INFORMATION = static final boolean[] IS_DOCUMENT_SUMMARY_INFORMATION =
{false, true}; {false, true};
POIFile[] poiFiles; POIFile[] poiFiles;
public TestBasic(String name) public TestBasic(final String name)
{ {
super(name); super(name);
} }
@ -113,11 +126,11 @@ public class TestBasic extends TestCase
*/ */
public void setUp() throws FileNotFoundException, IOException public void setUp() throws FileNotFoundException, IOException
{ {
final File dataDir = final File dataDir =
new File(System.getProperty("HPSF.testdata.path")); new File(System.getProperty("HPSF.testdata.path"));
final File data = new File(dataDir, POI_FS); final File data = new File(dataDir, POI_FS);
poiFiles = Util.readPOIFiles(data); poiFiles = Util.readPOIFiles(data);
} }
@ -128,9 +141,9 @@ public class TestBasic extends TestCase
*/ */
public void testReadFiles() throws IOException public void testReadFiles() throws IOException
{ {
String[] expected = POI_FILES; String[] expected = POI_FILES;
for (int i = 0; i < expected.length; i++) for (int i = 0; i < expected.length; i++)
Assert.assertEquals(poiFiles[i].getName(), expected[i]); Assert.assertEquals(poiFiles[i].getName(), expected[i]);
} }
@ -146,37 +159,37 @@ public class TestBasic extends TestCase
*/ */
public void testCreatePropertySets() throws IOException public void testCreatePropertySets() throws IOException
{ {
Class[] expected = new Class[] Class[] expected = new Class[]
{ {
SummaryInformation.class, SummaryInformation.class,
DocumentSummaryInformation.class, DocumentSummaryInformation.class,
NoPropertySetStreamException.class, NoPropertySetStreamException.class,
NoPropertySetStreamException.class, NoPropertySetStreamException.class,
NoPropertySetStreamException.class NoPropertySetStreamException.class
}; };
for (int i = 0; i < expected.length; i++) for (int i = 0; i < expected.length; i++)
{ {
InputStream in = new ByteArrayInputStream(poiFiles[i].getBytes()); InputStream in = new ByteArrayInputStream(poiFiles[i].getBytes());
Object o; Object o;
try try
{ {
o = PropertySetFactory.create(in); o = PropertySetFactory.create(in);
} }
catch (NoPropertySetStreamException ex) catch (NoPropertySetStreamException ex)
{ {
o = ex; o = ex;
} }
catch (UnexpectedPropertySetTypeException ex) catch (UnexpectedPropertySetTypeException ex)
{ {
o = ex; o = ex;
} }
catch (MarkUnsupportedException ex) catch (MarkUnsupportedException ex)
{ {
o = ex; o = ex;
} }
in.close(); in.close();
Assert.assertEquals(o.getClass(), expected[i]); Assert.assertEquals(o.getClass(), expected[i]);
} }
} }
@ -188,25 +201,24 @@ public class TestBasic extends TestCase
*/ */
public void testPropertySetMethods() throws IOException, HPSFException public void testPropertySetMethods() throws IOException, HPSFException
{ {
String[] expected = POI_FILES;
/* Loop over the two property sets. */ /* Loop over the two property sets. */
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
byte[] b = poiFiles[i].getBytes(); byte[] b = poiFiles[i].getBytes();
PropertySet ps = PropertySet ps =
PropertySetFactory.create(new ByteArrayInputStream(b)); PropertySetFactory.create(new ByteArrayInputStream(b));
Assert.assertEquals(ps.getByteOrder(), BYTE_ORDER); Assert.assertEquals(ps.getByteOrder(), BYTE_ORDER);
Assert.assertEquals(ps.getFormat(), FORMAT); Assert.assertEquals(ps.getFormat(), FORMAT);
Assert.assertEquals(ps.getOSVersion(), OS_VERSION); Assert.assertEquals(ps.getOSVersion(), OS_VERSION);
Assert.assertEquals(new String(ps.getClassID().getBytes()), Assert.assertEquals(new String(ps.getClassID().getBytes()),
new String(CLASS_ID)); new String(CLASS_ID));
Assert.assertEquals(ps.getSectionCount(), SECTION_COUNT[i]); Assert.assertEquals(ps.getSectionCount(), SECTION_COUNT[i]);
Assert.assertEquals(ps.isSummaryInformation(), Assert.assertEquals(ps.isSummaryInformation(),
IS_SUMMARY_INFORMATION[i]); IS_SUMMARY_INFORMATION[i]);
Assert.assertEquals(ps.isDocumentSummaryInformation(), Assert.assertEquals(ps.isDocumentSummaryInformation(),
IS_DOCUMENT_SUMMARY_INFORMATION[i]); IS_DOCUMENT_SUMMARY_INFORMATION[i]);
} }
} }
@ -214,11 +226,11 @@ public class TestBasic extends TestCase
/** /**
* <p>Runs the test cases stand-alone.</p> * <p>Runs the test cases stand-alone.</p>
*/ */
public static void main(String[] args) throws Throwable public static void main(final String[] args) throws Throwable
{ {
System.setProperty("HPSF.testdata.path", System.setProperty("HPSF.testdata.path",
"./src/testcases/org/apache/poi/hpsf/data"); "./src/testcases/org/apache/poi/hpsf/data");
junit.textui.TestRunner.run(TestBasic.class); junit.textui.TestRunner.run(TestBasic.class);
} }
} }

View File

@ -0,0 +1,189 @@
package org.apache.poi.hpsf.basic;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.poi.hpsf.HPSFException;
import org.apache.poi.hpsf.MarkUnsupportedException;
import org.apache.poi.hpsf.NoPropertySetStreamException;
import org.apache.poi.hpsf.PropertySet;
import org.apache.poi.hpsf.PropertySetFactory;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
/**
* <p>Test case for OLE2 files with empty properties. An empty property's type
* is {@link Variant.VT_EMPTY}.</p>
*
* @author Rainer Klute <a
* href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
* @since 2003-07-25
* @version $Id$
*/
public class TestEmptyProperties extends TestCase
{
/**
* <p>This test file's summary information stream contains some empty
* properties.</p>
*/
static final String POI_FS = "TestCorel.shw";
static final String[] POI_FILES = new String[]
{
"PerfectOffice_MAIN",
"\005SummaryInformation",
"Main"
};
POIFile[] poiFiles;
/**
* <p>Constructor</p>
*
* @param name The name of the test case
*/
public TestEmptyProperties(final String name)
{
super(name);
}
/**
* <p>Read a the test file from the "data" directory.</p>
*
* @exception FileNotFoundException if the file containing the test data
* does not exist
* @exception IOException if an I/O exception occurs
*/
public void setUp() throws FileNotFoundException, IOException
{
final File dataDir =
new File(System.getProperty("HPSF.testdata.path"));
final File data = new File(dataDir, POI_FS);
poiFiles = Util.readPOIFiles(data);
}
/**
* <p>Checks the names of the files in the POI filesystem. They
* are expected to be in a certain order.</p>
*
* @exception IOException if an I/O exception occurs
*/
public void testReadFiles() throws IOException
{
String[] expected = POI_FILES;
for (int i = 0; i < expected.length; i++)
Assert.assertEquals(poiFiles[i].getName(), expected[i]);
}
/**
* <p>Tests whether property sets can be created from the POI
* files in the POI file system. This test case expects the first
* file to be a {@link SummaryInformation}, the second file to be
* a {@link DocumentSummaryInformation} and the rest to be no
* property sets. In the latter cases a {@link
* NoPropertySetStreamException} will be thrown when trying to
* create a {@link PropertySet}.</p>
*
* @exception IOException if an I/O exception occurs
*/
public void testCreatePropertySets() throws IOException
{
Class[] expected = new Class[]
{
NoPropertySetStreamException.class,
SummaryInformation.class,
NoPropertySetStreamException.class
};
for (int i = 0; i < expected.length; i++)
{
InputStream in = new ByteArrayInputStream(poiFiles[i].getBytes());
Object o;
try
{
o = PropertySetFactory.create(in);
}
catch (NoPropertySetStreamException ex)
{
o = ex;
}
catch (UnexpectedPropertySetTypeException ex)
{
o = ex;
}
catch (MarkUnsupportedException ex)
{
o = ex;
}
in.close();
Assert.assertEquals(o.getClass(), expected[i]);
}
}
/**
* <p>Tests the {@link PropertySet} methods. The test file has two
* property sets: the first one is a {@link SummaryInformation},
* the second one is a {@link DocumentSummaryInformation}.</p>
*
* @exception IOException if an I/O exception occurs
* @exception HPSFException if an HPSF operation fails
*/
public void testPropertySetMethods() throws IOException, HPSFException
{
byte[] b = poiFiles[1].getBytes();
PropertySet ps =
PropertySetFactory.create(new ByteArrayInputStream(b));
SummaryInformation s = (SummaryInformation) ps;
assertNull(s.getTitle());
assertNull(s.getSubject());
assertNotNull(s.getAuthor());
assertNull(s.getKeywords());
assertNull(s.getComments());
assertNotNull(s.getTemplate());
assertNotNull(s.getLastAuthor());
assertNotNull(s.getRevNumber());
assertNull(s.getEditTime());
assertNull(s.getLastPrinted());
assertNull(s.getCreateDateTime());
assertNull(s.getLastSaveDateTime());
assertEquals(s.getPageCount(), 0);
assertEquals(s.getWordCount(), 0);
assertEquals(s.getCharCount(), 0);
assertNull(s.getThumbnail());
assertNull(s.getApplicationName());
}
/**
* <p>Runs the test cases stand-alone.</p>
*
* @param args the command-line arguments (unused)
*
* @exception Throwable if any exception or error occurs
*/
public static void main(final String[] args) throws Throwable
{
System.setProperty("HPSF.testdata.path",
"./src/testcases/org/apache/poi/hpsf/data");
junit.textui.TestRunner.run(TestBasic.class);
}
}

View File

@ -54,10 +54,18 @@
package org.apache.poi.hpsf.basic; package org.apache.poi.hpsf.basic;
import java.io.*; import java.io.ByteArrayInputStream;
import java.util.*; import java.io.File;
import junit.framework.*; import java.io.FileNotFoundException;
import org.apache.poi.hpsf.*; import java.io.IOException;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.poi.hpsf.HPSFException;
import org.apache.poi.hpsf.PropertySet;
import org.apache.poi.hpsf.PropertySetFactory;
import org.apache.poi.hpsf.Section;
@ -72,17 +80,22 @@ import org.apache.poi.hpsf.*;
public class TestUnicode extends TestCase public class TestUnicode extends TestCase
{ {
final static String POI_FS = "TestUnicode.xls"; static final String POI_FS = "TestUnicode.xls";
final static String[] POI_FILES = new String[] static final String[] POI_FILES = new String[]
{ {
"\005DocumentSummaryInformation", "\005DocumentSummaryInformation",
}; };
File data; File data;
POIFile[] poiFiles; POIFile[] poiFiles;
public TestUnicode(String name) /**
* <p>Constructor</p>
*
* @param name the test case's name
*/
public TestUnicode(final String name)
{ {
super(name); super(name);
} }
@ -92,11 +105,11 @@ public class TestUnicode extends TestCase
/** /**
* <p>Read a the test file from the "data" directory.</p> * <p>Read a the test file from the "data" directory.</p>
*/ */
public void setUp() throws FileNotFoundException, IOException protected void setUp() throws FileNotFoundException, IOException
{ {
final File dataDir = final File dataDir =
new File(System.getProperty("HPSF.testdata.path")); new File(System.getProperty("HPSF.testdata.path"));
data = new File(dataDir, POI_FS); data = new File(dataDir, POI_FS);
} }
@ -108,23 +121,23 @@ public class TestUnicode extends TestCase
*/ */
public void testPropertySetMethods() throws IOException, HPSFException public void testPropertySetMethods() throws IOException, HPSFException
{ {
POIFile poiFile = Util.readPOIFiles(data, POI_FILES)[0]; POIFile poiFile = Util.readPOIFiles(data, POI_FILES)[0];
byte[] b = poiFile.getBytes(); byte[] b = poiFile.getBytes();
PropertySet ps = PropertySet ps =
PropertySetFactory.create(new ByteArrayInputStream(b)); PropertySetFactory.create(new ByteArrayInputStream(b));
Assert.assertTrue(ps.isDocumentSummaryInformation()); Assert.assertTrue(ps.isDocumentSummaryInformation());
Assert.assertEquals(ps.getSectionCount(), 2); Assert.assertEquals(ps.getSectionCount(), 2);
Section s = (Section) ps.getSections().get(1); Section s = (Section) ps.getSections().get(1);
Assert.assertEquals(s.getProperty(1), Assert.assertEquals(s.getProperty(1),
new Integer(1200)); new Integer(1200));
Assert.assertEquals(s.getProperty(2), Assert.assertEquals(s.getProperty(2),
new Long(4198897018l)); new Long(4198897018L));
Assert.assertEquals(s.getProperty(3), Assert.assertEquals(s.getProperty(3),
"MCon_Info zu Office bei Schreiner"); "MCon_Info zu Office bei Schreiner");
Assert.assertEquals(s.getProperty(4), Assert.assertEquals(s.getProperty(4),
"petrovitsch@schreiner-online.de"); "petrovitsch@schreiner-online.de");
Assert.assertEquals(s.getProperty(5), Assert.assertEquals(s.getProperty(5),
"Petrovitsch, Wilhelm"); "Petrovitsch, Wilhelm");
} }
@ -132,10 +145,10 @@ public class TestUnicode extends TestCase
/** /**
* <p>Runs the test cases stand-alone.</p> * <p>Runs the test cases stand-alone.</p>
*/ */
public static void main(String[] args) public static void main(final String[] args)
{ {
System.setProperty("HPSF.testdata.path", System.setProperty("HPSF.testdata.path",
"./src/testcases/org/apache/poi/hpsf/data"); "./src/testcases/org/apache/poi/hpsf/data");
junit.textui.TestRunner.run(TestUnicode.class); junit.textui.TestRunner.run(TestUnicode.class);
} }

View File

@ -54,9 +54,24 @@
package org.apache.poi.hpsf.basic; package org.apache.poi.hpsf.basic;
import java.io.*; import java.io.ByteArrayOutputStream;
import java.util.*; import java.io.EOFException;
import org.apache.poi.poifs.eventfilesystem.*; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
@ -73,6 +88,9 @@ public class Util
/** /**
* <p>Reads bytes from an input stream and writes them to an * <p>Reads bytes from an input stream and writes them to an
* output stream until end of file is encountered.</p> * output stream until end of file is encountered.</p>
*
* @param in the input stream to read from
* @param out the output stream to write to
*/ */
public static void copy(final InputStream in, final OutputStream out) public static void copy(final InputStream in, final OutputStream out)
throws IOException throws IOException
@ -88,8 +106,8 @@ public class Util
read = in.read(b, 0, BUF_SIZE); read = in.read(b, 0, BUF_SIZE);
if (read > 0) if (read > 0)
out.write(b, 0, read); out.write(b, 0, read);
else else
eof = true; eof = true;
} }
catch (EOFException ex) catch (EOFException ex)
{ {
@ -106,16 +124,16 @@ public class Util
* into memory and thus does not cope well with large POI * into memory and thus does not cope well with large POI
* filessystems.</p> * filessystems.</p>
* *
* @param file The name of the POI filesystem as seen by the * @param poiFs The name of the POI filesystem as seen by the
* operating system. (This is the "filename".) * operating system. (This is the "filename".)
* *
* @return The POI files. The elements are ordered in the same way * @return The POI files. The elements are ordered in the same way
* as the files in the POI filesystem. * as the files in the POI filesystem.
*/ */
public static POIFile[] readPOIFiles(final File poiFs) public static POIFile[] readPOIFiles(final File poiFs)
throws FileNotFoundException, IOException throws FileNotFoundException, IOException
{ {
return readPOIFiles(poiFs, null); return readPOIFiles(poiFs, null);
} }
@ -126,7 +144,7 @@ public class Util
* files into memory and thus does not cope well with large POI * files into memory and thus does not cope well with large POI
* filessystems.</p> * filessystems.</p>
* *
* @param file The name of the POI filesystem as seen by the * @param poiFs The name of the POI filesystem as seen by the
* operating system. (This is the "filename".) * operating system. (This is the "filename".)
* *
* @param poiFiles The names of the POI files to be read. * @param poiFiles The names of the POI files to be read.
@ -135,50 +153,49 @@ public class Util
* as the files in the POI filesystem. * as the files in the POI filesystem.
*/ */
public static POIFile[] readPOIFiles(final File poiFs, public static POIFile[] readPOIFiles(final File poiFs,
final String[] poiFiles) final String[] poiFiles)
throws FileNotFoundException, IOException throws FileNotFoundException, IOException
{ {
final List files = new ArrayList(); final List files = new ArrayList();
POIFSReader r = new POIFSReader(); POIFSReader r = new POIFSReader();
POIFSReaderListener pfl = new POIFSReaderListener() POIFSReaderListener pfl = new POIFSReaderListener()
{ {
public void processPOIFSReaderEvent(POIFSReaderEvent event) public void processPOIFSReaderEvent(final POIFSReaderEvent event)
{ {
try try
{ {
POIFile f = new POIFile(); POIFile f = new POIFile();
f.setName(event.getName()); f.setName(event.getName());
f.setPath(event.getPath()); f.setPath(event.getPath());
InputStream in = event.getStream(); InputStream in = event.getStream();
ByteArrayOutputStream out = ByteArrayOutputStream out = new ByteArrayOutputStream();
new ByteArrayOutputStream(); Util.copy(in, out);
Util.copy(in, out); out.close();
out.close(); f.setBytes(out.toByteArray());
f.setBytes(out.toByteArray()); files.add(f);
files.add(f); }
} catch (IOException ex)
catch (IOException ex) {
{ ex.printStackTrace();
ex.printStackTrace(); throw new RuntimeException(ex.getMessage());
throw new RuntimeException(ex.getMessage()); }
} }
} };
}; if (poiFiles == null)
if (poiFiles == null) /* Register the listener for all POI files. */
/* Register the listener for all POI files. */ r.registerListener(pfl);
r.registerListener(pfl); else
else /* Register the listener for the specified POI files
/* Register the listener for the specified POI files * only. */
* only. */ for (int i = 0; i < poiFiles.length; i++)
for (int i = 0; i < poiFiles.length; i++) r.registerListener(pfl, poiFiles[i]);
r.registerListener(pfl, poiFiles[i]);
/* Read the POI filesystem. */ /* Read the POI filesystem. */
r.read(new FileInputStream(poiFs)); r.read(new FileInputStream(poiFs));
POIFile[] result = new POIFile[files.size()]; POIFile[] result = new POIFile[files.size()];
for (int i = 0; i < result.length; i++) for (int i = 0; i < result.length; i++)
result[i] = (POIFile) files.get(i); result[i] = (POIFile) files.get(i);
return result; return result;
} }
@ -188,19 +205,19 @@ public class Util
*/ */
public static void printSystemProperties() public static void printSystemProperties()
{ {
Properties p = System.getProperties(); final Properties p = System.getProperties();
List names = new LinkedList(); final List names = new LinkedList();
for (Iterator i = p.keySet().iterator(); i.hasNext();) for (Iterator i = p.keySet().iterator(); i.hasNext();)
names.add(i.next()); names.add(i.next());
Collections.sort(names); Collections.sort(names);
for (Iterator i = names.iterator(); i.hasNext();) for (final Iterator i = names.iterator(); i.hasNext();)
{ {
String name = (String) i.next(); String name = (String) i.next();
String value = (String) p.get(name); String value = (String) p.get(name);
System.out.println(name + ": " + value); System.out.println(name + ": " + value);
} }
System.out.println("Current directory: " + System.out.println("Current directory: " +
System.getProperty("user.dir")); System.getProperty("user.dir"));
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,119 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003, 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
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.usermodel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import junit.framework.TestCase;
/**
* @author Avik Sengupta
*/
public class TestBugs
extends TestCase {
public TestBugs(String s) {
super(s);
}
public void test15228()
throws java.io.IOException
{
String readFilename = System.getProperty("HSSF.testdata.path");
FileInputStream in = new FileInputStream(readFilename+File.separator+"15228.xls");
HSSFWorkbook wb = new HSSFWorkbook(in);
HSSFSheet s = wb.getSheetAt(0);
HSSFRow r = s.createRow(0);
HSSFCell c = r.createCell((short)0);
c.setCellValue(10);
File file = File.createTempFile("test15228",".xls");
FileOutputStream out = new FileOutputStream(file);
wb.write(out);
assertTrue("No exception thrown", true);
assertTrue("File Should Exist", file.exists());
}
public void test13796()
throws java.io.IOException
{
String readFilename = System.getProperty("HSSF.testdata.path");
FileInputStream in = new FileInputStream(readFilename+File.separator+"13796.xls");
HSSFWorkbook wb = new HSSFWorkbook(in);
HSSFSheet s = wb.getSheetAt(0);
HSSFRow r = s.createRow(0);
HSSFCell c = r.createCell((short)0);
c.setCellValue(10);
File file = File.createTempFile("test13796",".xls");
FileOutputStream out = new FileOutputStream(file);
wb.write(out);
assertTrue("No exception thrown", true);
assertTrue("File Should Exist", file.exists());
}
}

View File

@ -0,0 +1,126 @@
/* ====================================================================
* 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
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.hssf.usermodel.HSSFHeader;
import org.apache.poi.hssf.usermodel.HSSFFooter;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* Tests row shifting capabilities.
*
*
* @author Shawn Laubach (slaubach at apache dot com)
*/
public class TestHSSFHeaderFooter extends TestCase {
/**
* Constructor for TestHeaderFooter.
* @param arg0
*/
public TestHSSFHeaderFooter(String arg0) {
super(arg0);
}
/**
* Tests that get header retreives the proper values.
*
* @author Shawn Laubach (slaubach at apache dot org)
*/
public void testRetrieveCorrectHeader() throws Exception
{
// Read initial file in
String filename = System.getProperty( "HSSF.testdata.path" );
filename = filename + "/EmbeddedChartHeaderTest.xls";
FileInputStream fin = new FileInputStream( filename );
HSSFWorkbook wb = new HSSFWorkbook( fin );
fin.close();
HSSFSheet s = wb.getSheetAt( 0 );
HSSFHeader head = s.getHeader();
assertEquals("Top Left", head.getLeft());
assertEquals("Top Center", head.getCenter());
assertEquals("Top Right", head.getRight());
}
/**
* Tests that get header retreives the proper values.
*
* @author Shawn Laubach (slaubach at apache dot org)
*/
public void testRetrieveCorrectFooter() throws Exception
{
// Read initial file in
String filename = System.getProperty( "HSSF.testdata.path" );
filename = filename + "/EmbeddedChartHeaderTest.xls";
FileInputStream fin = new FileInputStream( filename );
HSSFWorkbook wb = new HSSFWorkbook( fin );
fin.close();
HSSFSheet s = wb.getSheetAt( 0 );
HSSFFooter foot = s.getFooter();
assertEquals("Bottom Left", foot.getLeft());
assertEquals("Bottom Center", foot.getCenter());
assertEquals("Bottom Right", foot.getRight());
}
}

View File

@ -54,18 +54,21 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.record.HCenterRecord;
import org.apache.poi.hssf.record.VCenterRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; 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.SCLRecord;
import org.apache.poi.hssf.record.VCenterRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.util.Region;
/** /**
* Tests HSSFSheet. This test case is very incomplete at the moment. * Tests HSSFSheet. This test case is very incomplete at the moment.
* *
@ -236,6 +239,27 @@ public class TestHSSFSheet
cell.setCellValue("Difference Check"); cell.setCellValue("Difference Check");
assertEquals(cloned.getRow((short)0).getCell((short)0).getStringCellValue(), "clone_test"); assertEquals(cloned.getRow((short)0).getCell((short)0).getStringCellValue(), "clone_test");
} }
/**
* Test that the ProtectRecord is included when creating or cloning a sheet
*/
public void testProtect() {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet hssfSheet = workbook.createSheet();
Sheet sheet = hssfSheet.getSheet();
ProtectRecord protect = sheet.getProtect();
assertFalse(protect.getProtect());
// This will tell us that cloneSheet, and by extension,
// the list forms of createSheet leave us with an accessible
// ProtectRecord.
hssfSheet.setProtect(true);
Sheet cloned = sheet.cloneSheet();
assertNotNull(cloned.getProtect());
assertTrue(hssfSheet.getProtect());
}
public void testZoom() public void testZoom()
throws Exception throws Exception
@ -254,4 +278,111 @@ public class TestHSSFSheet
assertTrue(sclLoc == window2Loc + 1); assertTrue(sclLoc == window2Loc + 1);
} }
/**
* When removing one merged region, it would break
*
*/
public void testRemoveMerged() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
Region region = new Region(0, (short)0, 1, (short)1);
sheet.addMergedRegion(region);
region = new Region(1, (short)0, 2, (short)1);
sheet.addMergedRegion(region);
sheet.removeMergedRegion(0);
region = sheet.getMergedRegionAt(0);
assertEquals("Left over region should be starting at row 1", 1, region.getRowFrom());
sheet.removeMergedRegion(0);
assertEquals("there should be no merged regions left!", 0, sheet.getNumMergedRegions());
//an, add, remove, get(0) would null pointer
sheet.addMergedRegion(region);
assertEquals("there should now be one merged region!", 1, sheet.getNumMergedRegions());
sheet.removeMergedRegion(0);
assertEquals("there should now be zero merged regions!", 0, sheet.getNumMergedRegions());
//add it again!
region.setRowTo(4);
sheet.addMergedRegion(region);
assertEquals("there should now be one merged region!", 1, sheet.getNumMergedRegions());
//should exist now!
assertTrue("there isn't more than one merged region in there", 1 <= sheet.getNumMergedRegions());
region = sheet.getMergedRegionAt(0);
assertEquals("the merged row to doesnt match the one we put in ", 4, region.getRowTo());
}
public void testShiftMerged() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short)0);
cell.setCellValue("first row, first cell");
row = sheet.createRow(1);
cell = row.createCell((short)1);
cell.setCellValue("second row, second cell");
Region region = new Region(1, (short)0, 1, (short)1);
sheet.addMergedRegion(region);
sheet.shiftRows(1, 1, 1);
region = sheet.getMergedRegionAt(0);
assertEquals("Merged region not moved over to row 2", 2, region.getRowFrom());
}
/**
* Tests the display of gridlines, formulas, and rowcolheadings.
* @author Shawn Laubach (slaubach at apache dot org)
*/
public void testDisplayOptions() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
File tempFile = File.createTempFile("display", "test.xls");
FileOutputStream stream = new FileOutputStream(tempFile);
wb.write(stream);
stream.close();
FileInputStream readStream = new FileInputStream(tempFile);
wb = new HSSFWorkbook(readStream);
sheet = wb.getSheetAt(0);
readStream.close();
assertEquals(sheet.isDisplayGridlines(), true);
assertEquals(sheet.isDisplayRowColHeadings(), true);
assertEquals(sheet.isDisplayFormulas(), false);
sheet.setDisplayGridlines(false);
sheet.setDisplayRowColHeadings(false);
sheet.setDisplayFormulas(true);
tempFile = File.createTempFile("display", "test.xls");
stream = new FileOutputStream(tempFile);
wb.write(stream);
stream.close();
readStream = new FileInputStream(tempFile);
wb = new HSSFWorkbook(readStream);
sheet = wb.getSheetAt(0);
readStream.close();
assertEquals(sheet.isDisplayGridlines(), false);
assertEquals(sheet.isDisplayRowColHeadings(), false);
assertEquals(sheet.isDisplayFormulas(), true);
}
public static void main(java.lang.String[] args) {
junit.textui.TestRunner.run(TestHSSFSheet.class);
}
} }

View File

@ -304,6 +304,8 @@ public class TestWorkbook
assertEquals(1.25,cell.getNumericCellValue(), 1e-10); assertEquals(1.25,cell.getNumericCellValue(), 1e-10);
assertEquals(format.getFormat(df), "0.0"); assertEquals(format.getFormat(df), "0.0");
assertEquals(format, workbook.createDataFormat());
stream.close(); stream.close();
} }

View File

@ -0,0 +1,76 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 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
* <http://www.apache.org/>.
*/
package org.apache.poi.poifs.filesystem;
import java.io.*;
import java.util.Random;
/**
* Returns a random amount of requested data. Used to check conformance with
* InputStream API contracts.
*/
public class SlowInputStream extends FilterInputStream
{
private Random r = new Random(0);
public SlowInputStream(InputStream in) {
super(in);
}
public int read(byte[] b, int off, int len) throws IOException {
return super.read(b, off, r.nextInt(len) + 1);
}
}

View File

@ -107,7 +107,7 @@ public class TestDocument
{ {
array[ j ] = ( byte ) j; array[ j ] = ( byte ) j;
} }
document = new POIFSDocument("foo", new ByteArrayInputStream(array)); document = new POIFSDocument("foo", new SlowInputStream(new ByteArrayInputStream(array)));
checkDocument(document, array); checkDocument(document, array);
// verify correct number of blocks get created for document // verify correct number of blocks get created for document

View File

@ -314,6 +314,9 @@ public class TestHexDump
// as expected // as expected
} }
// verify proper behaviour with a 0 length dump on 0 length dataset
HexDump.dump(new byte[0], 0, new ByteArrayOutputStream(), 0, 0);
} }
public void testToHex() public void testToHex()