merge trunk to common sl branch
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1691843 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
commit
d439f080d6
2
.settings/org.eclipse.core.resources.prefs
Normal file
2
.settings/org.eclipse.core.resources.prefs
Normal file
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
@ -152,6 +152,7 @@ org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
|
||||
@ -197,6 +198,7 @@ org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
|
||||
@ -244,6 +246,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=inser
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
|
||||
@ -321,6 +324,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do n
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
|
||||
|
File diff suppressed because one or more lines are too long
4
.settings/org.moreunit.prefs
Normal file
4
.settings/org.moreunit.prefs
Normal file
@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
org.moreunit.preferences.version=2
|
||||
org.moreunit.unitsourcefolder=ApachePOI\:src/java\:ApachePOI\:src/testcases\#ApachePOI\:src/java\:ApachePOI\:src/ooxml/testcases\#ApachePOI\:src/java\:ApachePOI\:src/scratchpad/testcases\#ApachePOI\:src/java\:ApachePOI\:src/excelant/testcases\#ApachePOI\:src/java\:ApachePOI\:src/integrationtest
|
||||
org.moreunit.useprojectsettings=true
|
345
KEYS
345
KEYS
@ -1796,3 +1796,348 @@ qoiVaXWfFHwg8u4bSHunrzNja17GyaZHdCEmM9vFzlaqBkoLWCMwIcaKnX9stQJp
|
||||
FZwpzgut7DanaPcCDk7LMBbntaJwRC72M0qcj16SUAdAuGt1yQ==
|
||||
=0DjT
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
pub 4096R/B4812553 2014-02-26 [expires: 2019-02-25]
|
||||
uid David North <david@dnorth.net>
|
||||
uid David North (Oxford CompSoc) <north@ox.compsoc.net>
|
||||
uid David North (ASF Committer ID) <dnorth@apache.org>
|
||||
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1
|
||||
|
||||
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
|
||||
HmRrAAoJEFk2rKVTkFoB0E0Aniydu8kZjiaob6/OT9hYtOkLaQRqAKCD+l2caV7i
|
||||
J/SkLCBgY2relojE2YkCGwQQAQIABgUCVGuZsAAKCRAXscp9ZAiVKMxYD/iZPK6P
|
||||
qwHxzEuQjquo8f9f0q1RkX4AZa1j5hvXcqAddUa3HpihHDFnW0UDpptlyonryxUE
|
||||
imhD9a22/eIsCz4sF8gAgrp9b1gRBJmJMvtRgVHaFn1u02/5IEvRj7JsWgVXzWFU
|
||||
yh9zLaiQtcpfvfFzmdZKtZ3hl0TGl8NFMLxUsownR2tx0iuc8r+NpzzKpxQeXlYS
|
||||
98DrDLjE3AKVSZcc8DUBTlwhCZLiXEaQjAKXW+Mxfg8C2E4hQIAsqLWhj8PRQEpG
|
||||
w9F0Wdrh9w4ePsKKnzsIaprkRve3vzEuDLvmHV+9DQd/sh+C5W1LjL4h+vC0eXhd
|
||||
42lIWrfgOhai2rrwgfSNEFnMAsB1zdWcwMgVSP97sSVfyrqMlDJWXuW8v2KR36ws
|
||||
zZnqVPsgQk0Uy53mItUnWblgabSb/udVa+ZI6NeOv1bMGMgKaFqXCn6aHD1X1/E3
|
||||
0XtCy2dE6reTAU0zNaRc9ZJOLvxJj8ymP+pUqzkvxLMWAuqpCKsM6YNFlCFkzdfO
|
||||
LHxhqGp68jKPUfuG7z6yRkgDZF84k55SUK7td8lHmJpbeiL1+N8Sm9CujQ+TEAbA
|
||||
ZFAQjonwnzXWxzI4N+1TWM8BbhLmFpG814JNxyswYdmps6pdKCWHi8zC60dYZ6Mw
|
||||
IQZfNWpkeLh7W44NuSJ7pIXuSfEaFCKXX+RwtIpEYXZpZCBOb3J0aCAoT3hmb3Jk
|
||||
IENvbXBTb2MpIChJIGRvbid0IHVzZSB0aGlzIGFkZHJlc3MgbXVjaCwgYW5kIGl0
|
||||
IHJvdXRlcyB0byB0aGUgc2FtZSBtYWlsYm94IGFzIG15IG1haW4gdXNlciBJRC4p
|
||||
IDxub3J0aEBveC5jb21wc29jLm5ldD6JAj0EEwEIACcFAlMOLj4CGwMFCQlmAYAF
|
||||
CwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ+bj6w7SBJVMTXw/+PqnnuxB7vBpk
|
||||
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
|
||||
=keWk
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
pub 4096R/27B9F635 2015-06-22
|
||||
uid Dominik Stadler <centic@apache.org>
|
||||
sub 4096R/EF9D5EA6 2015-06-22
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1
|
||||
|
||||
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
|
||||
kg==
|
||||
=rPGm
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
99
build.xml
99
build.xml
@ -47,8 +47,8 @@ under the License.
|
||||
|
||||
<description>The Apache POI project Ant build.</description>
|
||||
|
||||
<property name="version.id" value="3.12-beta1"/>
|
||||
<property name="version.rel" value="REL_3_12_BETA1"/>
|
||||
<property name="version.id" value="3.13-beta1"/>
|
||||
<property name="version.rel" value="REL_3_13_BETA1"/>
|
||||
|
||||
<property environment="env"/>
|
||||
<!-- the repository to download jars from -->
|
||||
@ -56,7 +56,7 @@ under the License.
|
||||
|
||||
<property name="main.lib" location="lib"/>
|
||||
<property name="ooxml.lib" location="ooxml-lib"/>
|
||||
<property name="compile.lib" location="compile-lib"/>
|
||||
<property name="compile.lib" location="compile-lib"/>
|
||||
<property name="forrest.home" value="${env.FORREST_HOME}"/>
|
||||
|
||||
<!-- compiler options options -->
|
||||
@ -82,7 +82,11 @@ under the License.
|
||||
<property name="POI.testdata.path" value="test-data"/>
|
||||
<property name="java.awt.headless" value="true"/>
|
||||
<property name="additionaljar" value=""/>
|
||||
<property name="http_proxy" value="${env.http_proxy}"/>
|
||||
<condition property="http_proxy"
|
||||
value="${env.http_proxy}"
|
||||
else="">
|
||||
<isset property="env.http_proxy"/>
|
||||
</condition>
|
||||
|
||||
<!-- Main: -->
|
||||
<property name="main.resource1.dir" value="src/resources/main"/>
|
||||
@ -175,8 +179,8 @@ under the License.
|
||||
value="${repository.m2}/maven2/org/apache/xmlbeans/xmlbeans/2.6.0/xmlbeans-2.6.0.jar"/>
|
||||
|
||||
<!-- coverage libs -->
|
||||
<property name="jacoco.zip" location="${main.lib}/jacoco-0.7.2.201409121644.zip"/>
|
||||
<property name="jacoco.url" value="${repository.m2}/maven2/org/jacoco/jacoco/0.7.2.201409121644/jacoco-0.7.2.201409121644.zip"/>
|
||||
<property name="jacoco.zip" location="${main.lib}/jacoco-0.7.4.201502262128.zip"/>
|
||||
<property name="jacoco.url" value="${repository.m2}/maven2/org/jacoco/jacoco/0.7.4.201502262128/jacoco-0.7.4.201502262128.zip"/>
|
||||
<property name="asm.jar" location="${main.lib}/asm-all-5.0.3.jar"/>
|
||||
<property name="asm.url" value="${repository.m2}/maven2/org/ow2/asm/asm-all/5.0.3/asm-all-5.0.3.jar"/>
|
||||
|
||||
@ -194,14 +198,14 @@ under the License.
|
||||
<property name="ooxml.xsds.src.jar" location="${ooxml.lib}/ooxml-schemas-1.1-sources.jar"/>
|
||||
<property name="ooxml.xsds.jar" location="${ooxml.lib}/ooxml-schemas-1.1.jar"/>
|
||||
|
||||
<!-- additional schemas are packed into the poi schemas jar, -->
|
||||
<!-- so we don't have to care about a seperate versioning of the original ooxml schemas -->
|
||||
<property name="ooxml.xsds.dc.1" value="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
|
||||
<property name="ooxml.xsds.dc.2" value="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
|
||||
<property name="ooxml.xsds.dc.3" value="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcmitype.xsd"/>
|
||||
<property name="ooxml.xsds.dsig.1" value="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd"/>
|
||||
<property name="ooxml.xsds.dsig.2" value="http://uri.etsi.org/01903/v1.3.2/XAdES.xsd"/>
|
||||
<property name="ooxml.xsds.dsig.3" value="http://uri.etsi.org/01903/v1.4.1/XAdESv141.xsd"/>
|
||||
<!-- additional schemas are packed into the poi schemas jar, -->
|
||||
<!-- so we don't have to care about a seperate versioning of the original ooxml schemas -->
|
||||
<property name="ooxml.xsds.dc.1" value="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
|
||||
<property name="ooxml.xsds.dc.2" value="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
|
||||
<property name="ooxml.xsds.dc.3" value="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcmitype.xsd"/>
|
||||
<property name="ooxml.xsds.dsig.1" value="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd"/>
|
||||
<property name="ooxml.xsds.dsig.2" value="http://uri.etsi.org/01903/v1.3.2/XAdES.xsd"/>
|
||||
<property name="ooxml.xsds.dsig.3" value="http://uri.etsi.org/01903/v1.4.1/XAdESv141.xsd"/>
|
||||
<property name="ooxml.xsds.ozip.2" value="OfficeOpenXML-Part2.zip"/>
|
||||
<property name="ooxml.xsds.izip.2" value="OpenPackagingConventions-XMLSchema.zip"/>
|
||||
<property name="ooxml.xsds.url.2"
|
||||
@ -263,17 +267,18 @@ under the License.
|
||||
<pathelement location="${ooxml.xsds.jar}"/>
|
||||
<path refid="main.classpath"/>
|
||||
<pathelement location="${main.output.dir}"/>
|
||||
<pathelement location="${scratchpad.output.dir}"/>
|
||||
<pathelement location="${ooxml.security.jar}"/>
|
||||
<!-- classes are omitted on test cases outside the xml-dsign area to avoid classpath poisioning -->
|
||||
<!-- classes are omitted on test cases outside the xml-dsign area to avoid classpath poisioning -->
|
||||
<!--path refid="ooxml.xmlsec.classpath"/-->
|
||||
<!-- Used only for ExtractorFactory, see #57963 -->
|
||||
<pathelement location="${scratchpad.output.dir}"/>
|
||||
</path>
|
||||
|
||||
<path id="test.classpath">
|
||||
<path refid="main.classpath"/>
|
||||
<pathelement location="${main.output.dir}"/>
|
||||
<pathelement location="${main.output.test.dir}"/>
|
||||
<pathelement location="${additionaljar}"/>
|
||||
<pathelement location="${additionaljar}"/>
|
||||
</path>
|
||||
|
||||
<path id="test.scratchpad.classpath">
|
||||
@ -281,7 +286,7 @@ under the License.
|
||||
<pathelement location="${main.output.test.dir}"/>
|
||||
<pathelement location="${scratchpad.output.dir}"/>
|
||||
<pathelement location="${scratchpad.output.test.dir}"/>
|
||||
<pathelement location="${additionaljar}"/>
|
||||
<pathelement location="${additionaljar}"/>
|
||||
</path>
|
||||
|
||||
<path id="test.ooxml.classpath">
|
||||
@ -289,14 +294,14 @@ under the License.
|
||||
<pathelement location="${ooxml.output.dir}"/>
|
||||
<pathelement location="${ooxml.output.test.dir}"/>
|
||||
<pathelement location="${main.output.test.dir}"/>
|
||||
<pathelement location="${additionaljar}"/>
|
||||
<pathelement location="${additionaljar}"/>
|
||||
</path>
|
||||
|
||||
<path id="test.integration.classpath">
|
||||
<path refid="scratchpad.classpath"/>
|
||||
<path refid="ooxml.classpath"/>
|
||||
<pathelement location="${main.output.test.dir}"/>
|
||||
<pathelement location="${ooxml.output.dir}"/>
|
||||
<pathelement location="${ooxml.output.dir}"/>
|
||||
<pathelement location="${integration.output.test.dir}"/>
|
||||
</path>
|
||||
|
||||
@ -331,7 +336,7 @@ under the License.
|
||||
<pathelement location="${excelant.output.dir}"/>
|
||||
<pathelement location="${excelant.output.test.dir}"/>
|
||||
<pathelement location="${main.output.test.dir}"/>
|
||||
<pathelement location="${additionaljar}"/>
|
||||
<pathelement location="${additionaljar}"/>
|
||||
</path>
|
||||
|
||||
<path id="javadoc.classpath">
|
||||
@ -360,6 +365,8 @@ under the License.
|
||||
- compile Compile all files from main, ooxml and scratchpad
|
||||
- test Run all unit tests from main, ooxml and scratchpad
|
||||
- jar Produce jar files
|
||||
- jar-src Produce source-jar files
|
||||
- assemble Produce the zipped distribution files
|
||||
- site Generate all documentation (Requires Apache Forrest)
|
||||
- dist Create a distribution (Requires Apache Forrest)
|
||||
</echo>
|
||||
@ -409,6 +416,7 @@ under the License.
|
||||
<!-- remove previous versions of third-party jars to prevent them from lingering around,
|
||||
we often had hard-to-find build/CI-problems because of these! -->
|
||||
<mkdir dir="${main.lib}"/>
|
||||
<mkdir dir="${compile.lib}"/>
|
||||
<delete verbose="true">
|
||||
<fileset dir="${main.lib}">
|
||||
<include name="ant-1.8*"/>
|
||||
@ -417,9 +425,13 @@ under the License.
|
||||
<include name="commons-logging-1.1.jar"/>
|
||||
<include name="jacoco-0.6*"/>
|
||||
<include name="jacoco-0.7.1*"/>
|
||||
<include name="jacoco-0.7.2*"/>
|
||||
<include name="jacoco-0.7.3*"/>
|
||||
<include name="log4j-1.2.13*"/>
|
||||
<include name="org.jacoco.*-0.6.*"/>
|
||||
<include name="org.jacoco.*-0.7.1*"/>
|
||||
<include name="org.jacoco.*-0.7.2*"/>
|
||||
<include name="org.jacoco.*-0.7.3*"/>
|
||||
<include name="dom4j*"/>
|
||||
<include name="apache-rat-0.10*"/>
|
||||
<include name="xercesImpl-*.jar"/>
|
||||
@ -721,7 +733,7 @@ under the License.
|
||||
<headfilter lines="16"/>
|
||||
</filterchain>
|
||||
</copy>
|
||||
<copy todir="${scratchpad.src}">
|
||||
<copy todir="${main.src}">
|
||||
<fileset dir="${geometry.output.tmpdir}" includes="**/*.java"/>
|
||||
<filterchain>
|
||||
<concatfilter prepend="${geometry.output.tmpdir}/apache-license.txt"/>
|
||||
@ -976,7 +988,7 @@ under the License.
|
||||
<xml destfile="${coverage.dir}/coverage.xml"/>
|
||||
</jacoco:report>
|
||||
|
||||
<echo message="Coverage results are available at coverage\index.html, coverage/coverage.xml" />
|
||||
<echo message="Coverage results are available at ${coverage.dir}/index.html, ${coverage.dir}/coverage.xml" />
|
||||
</target>
|
||||
|
||||
<target name="-test-main-check">
|
||||
@ -1280,7 +1292,7 @@ under the License.
|
||||
description="Generates the API documentation">
|
||||
<javadoc verbose="false" author="true" destdir="${apidocs.report.dir}"
|
||||
windowtitle="POI API Documentation" use="true" version="true"
|
||||
maxmemory="384M" additionalparam="-notimestamp"
|
||||
maxmemory="384M" additionalparam="-notimestamp" locale="en_US"
|
||||
classpathref="javadoc.classpath">
|
||||
<packageset dir="${main.src}" defaultexcludes="yes">
|
||||
<include name="org/apache/poi/**"/>
|
||||
@ -1440,7 +1452,7 @@ under the License.
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="jar-src" description="Sources for Maven">
|
||||
<target name="jar-src" depends="compile-all, compile-version, -manifest" description="Sources for Maven">
|
||||
<jar destfile="${dist.dir}/${jar.name}-${version.id}-sources-${DSTAMP}.jar"
|
||||
manifest="build/poi-manifest.mf">
|
||||
<fileset dir="${main.src}"/>
|
||||
@ -1508,12 +1520,12 @@ under the License.
|
||||
<mkdir dir="${build.maven.javadocs}"/>
|
||||
<javadoc verbose="false" author="false" destdir="${build.maven.javadocs}"
|
||||
windowtitle="POI API Documentation" use="false" version="false"
|
||||
maxmemory="384M" additionalparam="-notimestamp -quiet"
|
||||
maxmemory="384M" additionalparam="-notimestamp -quiet" locale="en_US"
|
||||
classpathref="javadoc.classpath">
|
||||
<packageset dir="${srcfolder}" defaultexcludes="yes">
|
||||
<include name="org/apache/poi/**"/>
|
||||
</packageset>
|
||||
<link href="https://poi.apache.org/apidocs" packagelistLoc="build/tmp/site/build/site/apidocs"/>
|
||||
<link offline="true" href="https://poi.apache.org/apidocs" packagelistLoc="build/tmp/site/build/site/apidocs"/>
|
||||
</javadoc>
|
||||
<jar destfile="${dist.dir}/${jarname}-${version.id}-javadocs-${DSTAMP}.jar"
|
||||
manifest="build/poi-manifest.mf">
|
||||
@ -1628,6 +1640,14 @@ under the License.
|
||||
<echo>Use ${dist.dir}/multisign.sh to create md5 checksums and GPG signatures</echo>
|
||||
</target>
|
||||
|
||||
<target name="osgi" depends="mvn-install">
|
||||
<echo message="Building OSGi bundle via Maven" />
|
||||
<mvn:mvn pom="osgi/pom.xml">
|
||||
<arg value="-Dpoi.version=${version.id}" />
|
||||
<arg value="install" />
|
||||
</mvn:mvn>
|
||||
</target>
|
||||
|
||||
<target name="dist" depends="clean, compile-all, test-all, site, jar, release-notes, assemble"
|
||||
description="Creates the entire distribution into build/dist, from scratch">
|
||||
</target>
|
||||
@ -1744,7 +1764,30 @@ under the License.
|
||||
<sourcePath path="src/java" />
|
||||
<sourcePath path="src/ooxml/java" />
|
||||
<sourcePath path="src/scratchpad/src" />
|
||||
</findbugs>
|
||||
</findbugs>
|
||||
<findbugs home="${findbugs.home}" output="xml" outputFile="build/findbugs.xml"
|
||||
excludeFilter="src/resources/devtools/findbugs-filters.xml">
|
||||
<fileset dir="${dist.dir}">
|
||||
<include name="poi-${version.id}-*.jar"/>
|
||||
<include name="poi-scratchpad-${version.id}-*.jar"/>
|
||||
<include name="poi-ooxml-${version.id}-*.jar"/>
|
||||
<exclude name="poi-*${version.id}-sources-*.jar"/>
|
||||
<exclude name="poi-*${version.id}-javadocs-*.jar"/>
|
||||
</fileset>
|
||||
<auxClasspath path="${compile.lib}/bcpkix-jdk15on-1.51.jar" />
|
||||
<auxClasspath path="${compile.lib}/bcprov-ext-jdk15on-1.51.jar" />
|
||||
<auxClasspath path="${compile.lib}/slf4j-api-1.7.7.jar" />
|
||||
<auxClasspath path="${compile.lib}/xmlsec-2.0.1.jar" />
|
||||
<auxClasspath path="ooxml-lib/ooxml-schemas-1.1.jar" />
|
||||
<auxClasspath path="ooxml-lib/ooxml-security-1.0.jar" />
|
||||
<auxClasspath path="ooxml-lib/xmlbeans-2.6.0.jar" />
|
||||
<auxClasspath path="lib/commons-codec-1.9.jar" />
|
||||
<auxClasspath path="lib/commons-logging-1.1.3.jar" />
|
||||
<auxClasspath path="lib/junit-4.12.jar" />
|
||||
<sourcePath path="src/java" />
|
||||
<sourcePath path="src/ooxml/java" />
|
||||
<sourcePath path="src/scratchpad/src" />
|
||||
</findbugs>
|
||||
</target>
|
||||
|
||||
<target name="test-scratchpad-download-resources">
|
||||
|
34
doap_POI.rdf
34
doap_POI.rdf
@ -19,22 +19,56 @@
|
||||
<programming-language>Java</programming-language>
|
||||
<category rdf:resource="http://projects.apache.org/category/content" />
|
||||
<category rdf:resource="http://projects.apache.org/category/library" />
|
||||
<release>
|
||||
<Version>
|
||||
<name>Apache POI 3.12</name>
|
||||
<created>2015-05-11</created>
|
||||
<revision>3.12</revision>
|
||||
</Version>
|
||||
</release>
|
||||
<release>
|
||||
<Version>
|
||||
<name>Apache POI 3.11</name>
|
||||
<created>2014-12-21</created>
|
||||
<revision>3.11</revision>
|
||||
</Version>
|
||||
</release>
|
||||
<release>
|
||||
<Version>
|
||||
<name>Apache POI 3.10.1</name>
|
||||
<created>2014-08-18</created>
|
||||
<revision>3.10.1</revision>
|
||||
</Version>
|
||||
</release>
|
||||
<release>
|
||||
<Version>
|
||||
<name>Apache POI 3.10</name>
|
||||
<created>2014-02-08</created>
|
||||
<revision>3.10</revision>
|
||||
</Version>
|
||||
</release>
|
||||
<release>
|
||||
<Version>
|
||||
<name>Apache POI 3.9</name>
|
||||
<created>2012-12-03</created>
|
||||
<revision>3.9</revision>
|
||||
</Version>
|
||||
</release>
|
||||
<release>
|
||||
<Version>
|
||||
<name>Apache POI 3.8</name>
|
||||
<created>2012-03-26</created>
|
||||
<revision>3.8</revision>
|
||||
</Version>
|
||||
</release>
|
||||
<release>
|
||||
<Version>
|
||||
<name>Apache POI 3.7</name>
|
||||
<created>2010-10-29</created>
|
||||
<revision>3.7</revision>
|
||||
</Version>
|
||||
</release>
|
||||
<release>
|
||||
<Version>
|
||||
<name>Apache POI 3.6</name>
|
||||
<created>2009-12-14</created>
|
||||
|
@ -1,5 +1,5 @@
|
||||
Apache POI
|
||||
Copyright 2003-2014 The Apache Software Foundation
|
||||
Copyright 2003-2015 The Apache Software Foundation
|
||||
|
||||
This product includes software developed by
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
229
osgi/pom.xml
Normal file
229
osgi/pom.xml
Normal file
@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache</groupId>
|
||||
<artifactId>apache</artifactId>
|
||||
<version>10</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-bundle</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>Apache POI OSGi bundle</name>
|
||||
<description>
|
||||
OSGi bundle that contains Apache POI, and the dependencies.
|
||||
</description>
|
||||
<url>http://poi.apache.org/</url>
|
||||
<version>${poi.version}</version>
|
||||
<!--
|
||||
<version>3.12-beta2</version>
|
||||
<version>@VERSION@</version>
|
||||
-->
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.6</maven.compiler.source>
|
||||
<maven.compiler.target>1.6</maven.compiler.target>
|
||||
<pax.exam.version>4.4.0</pax.exam.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>poi-scratchpad</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ops4j.pax.exam</groupId>
|
||||
<artifactId>pax-exam-junit4</artifactId>
|
||||
<version>${pax.exam.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ops4j.pax.exam</groupId>
|
||||
<artifactId>pax-exam-container-native</artifactId>
|
||||
<version>${pax.exam.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>org.apache.felix.framework</artifactId>
|
||||
<version>4.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ops4j.pax.exam</groupId>
|
||||
<artifactId>pax-exam-link-assembly</artifactId>
|
||||
<version>${pax.exam.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ops4j.pax.url</groupId>
|
||||
<artifactId>pax-url-aether</artifactId>
|
||||
<version>2.3.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.core</artifactId>
|
||||
<version>5.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-Activator>
|
||||
org.apache.poi.osgi.Activator
|
||||
</Bundle-Activator>
|
||||
<Embed-Dependency>
|
||||
poi;inline=true,
|
||||
poi-scratchpad;inline=true,
|
||||
poi-ooxml;inline=true,
|
||||
poi-ooxml-schemas,
|
||||
xmlbeans
|
||||
</Embed-Dependency>
|
||||
<Embed-Transitive>true</Embed-Transitive>
|
||||
<Bundle-DocURL>${project.url}</Bundle-DocURL>
|
||||
<Export-Package>
|
||||
org.apache.poi.*
|
||||
</Export-Package>
|
||||
<Import-Package>
|
||||
!org.junit,
|
||||
*,
|
||||
org.apache.xmlbeans.impl.xpath.saxon;resolution:=optional,
|
||||
org.apache.xmlbeans.impl.xquery.saxon;resolution:=optional,
|
||||
org.bouncycastle.cert;resolution:=optional,
|
||||
org.bouncycastle.cert.ocsp;resolution:=optional,
|
||||
org.bouncycastle.cms.bc;resolution:=optional,
|
||||
org.bouncycastle.cert.jcajce;resolution:=optional,
|
||||
org.bouncycastle.operator;resolution:=optional,
|
||||
org.bouncycastle.operator.bc;resolution:=optional,
|
||||
org.bouncycastle.tsp;resolution:=optional,
|
||||
org.openxmlformats.schemas.officeDocument.x2006.math;resolution:=optional,
|
||||
org.openxmlformats.schemas.schemaLibrary.x2006.main;resolution:=optional,
|
||||
schemasMicrosoftComOfficePowerpoint;resolution:=optional,
|
||||
schemasMicrosoftComOfficeWord;resolution:=optional,
|
||||
</Import-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>java6</id>
|
||||
<activation>
|
||||
<jdk>[1.6,)</jdk>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<descriptor>test-bundles.xml</descriptor>
|
||||
<finalName>test</finalName>
|
||||
<attach>false</attach>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.10</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<org.ops4j.pax.logging.DefaultServiceLog.level>
|
||||
WARN
|
||||
</org.ops4j.pax.logging.DefaultServiceLog.level>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<organization>
|
||||
<name>The Apache Software Founation</name>
|
||||
<url>http://www.apache.org</url>
|
||||
</organization>
|
||||
<scm>
|
||||
<url>http://svn.apache.org/viewvc/poi/trunk/osgi</url>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/poi/trunk/osgi</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/poi/trunk/osgi</developerConnection>
|
||||
</scm>
|
||||
</project>
|
28
osgi/src/main/java/org/apache/poi/osgi/Activator.java
Normal file
28
osgi/src/main/java/org/apache/poi/osgi/Activator.java
Normal file
@ -0,0 +1,28 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.osgi;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
public void start(BundleContext context) throws Exception {
|
||||
}
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
}
|
||||
}
|
84
osgi/src/test/java/org/apache/poi/osgi/TestOSGiBundle.java
Normal file
84
osgi/src/test/java/org/apache/poi/osgi/TestOSGiBundle.java
Normal file
@ -0,0 +1,84 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.osgi;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.ops4j.pax.exam.CoreOptions.bundle;
|
||||
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
|
||||
import static org.ops4j.pax.exam.CoreOptions.options;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.ops4j.pax.exam.Configuration;
|
||||
import org.ops4j.pax.exam.Option;
|
||||
import org.ops4j.pax.exam.junit.PaxExam;
|
||||
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
|
||||
import org.ops4j.pax.exam.spi.reactors.PerMethod;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
|
||||
/**
|
||||
* Test to ensure that all our main formats can create, write
|
||||
* and read back in, when running under OSGi
|
||||
*/
|
||||
@RunWith(PaxExam.class)
|
||||
@ExamReactorStrategy(PerMethod.class)
|
||||
public class TestOSGiBundle {
|
||||
|
||||
private final File TARGET = new File("target");
|
||||
|
||||
@Inject
|
||||
private BundleContext bc;
|
||||
|
||||
@Configuration
|
||||
public Option[] configuration() throws IOException, URISyntaxException {
|
||||
File base = new File(TARGET, "test-bundles");
|
||||
return options(
|
||||
junitBundles(),
|
||||
bundle(new File(base, "poi-bundle.jar").toURI().toURL().toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHSSF() throws Exception {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet s = wb.createSheet("OSGi");
|
||||
s.createRow(0).createCell(0).setCellValue("With OSGi");
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
wb.write(baos);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
|
||||
wb = new HSSFWorkbook(bais);
|
||||
assertEquals(1, wb.getNumberOfSheets());
|
||||
|
||||
s = wb.getSheet("OSGi");
|
||||
assertEquals("With OSGi", s.getRow(0).getCell(0).toString());
|
||||
}
|
||||
}
|
34
osgi/test-bundles.xml
Normal file
34
osgi/test-bundles.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
<id>bundles</id>
|
||||
<formats>
|
||||
<format>dir</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<outputDirectory/>
|
||||
<outputFileNameMapping>${artifact.artifactId}.jar</outputFileNameMapping>
|
||||
<includes>
|
||||
<include>org.apache.poi:poi-bundle</include>
|
||||
</includes>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
</assembly>
|
@ -93,12 +93,12 @@ public class ReadCustomPropertySets
|
||||
out(" No. of sections: " + sectionCount);
|
||||
|
||||
/* Print the list of sections: */
|
||||
List sections = ps.getSections();
|
||||
List<Section> sections = ps.getSections();
|
||||
int nr = 0;
|
||||
for (Iterator i = sections.iterator(); i.hasNext();)
|
||||
for (Iterator<Section> i = sections.iterator(); i.hasNext();)
|
||||
{
|
||||
/* Print a single section: */
|
||||
Section sec = (Section) i.next();
|
||||
Section sec = i.next();
|
||||
out(" Section " + nr++ + ":");
|
||||
String s = hex(sec.getFormatID().getBytes());
|
||||
s = s.substring(0, s.length() - 1);
|
||||
|
@ -50,5 +50,7 @@ public class CreateCells {
|
||||
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
|
||||
wb.write(fileOut);
|
||||
fileOut.close();
|
||||
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ package org.apache.poi.ss.examples;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.*;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
|
||||
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
@ -31,10 +33,9 @@ import java.io.IOException;
|
||||
* Excel Conditional Formatting -- Examples
|
||||
*
|
||||
* <p>
|
||||
* Based on the code snippets from http://www.contextures.com/xlcondformat03.html
|
||||
* Partly based on the code snippets from
|
||||
* http://www.contextures.com/xlcondformat03.html
|
||||
* </p>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class ConditionalFormats {
|
||||
|
||||
@ -46,6 +47,7 @@ public class ConditionalFormats {
|
||||
|
||||
sameCell(wb.createSheet("Same Cell"));
|
||||
multiCell(wb.createSheet("MultiCell"));
|
||||
overlapping(wb.createSheet("Overlapping"));
|
||||
errors(wb.createSheet("Errors"));
|
||||
hideDupplicates(wb.createSheet("Hide Dups"));
|
||||
formatDuplicates(wb.createSheet("Duplicates"));
|
||||
@ -53,6 +55,9 @@ public class ConditionalFormats {
|
||||
expiry(wb.createSheet("Expiry"));
|
||||
shadeAlt(wb.createSheet("Shade Alt"));
|
||||
shadeBands(wb.createSheet("Shade Bands"));
|
||||
iconSets(wb.createSheet("Icon Sets"));
|
||||
|
||||
// TODO Add colour scales, data bars etc, see bug #58130
|
||||
|
||||
// Write the output to a file
|
||||
String file = "cf-poi.xls";
|
||||
@ -60,7 +65,7 @@ public class ConditionalFormats {
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
wb.write(out);
|
||||
out.close();
|
||||
|
||||
System.out.println("Generated: " + file);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,6 +144,71 @@ public class ConditionalFormats {
|
||||
|
||||
sheet.getRow(2).createCell(4).setCellValue("<== Condition 1: Formula Is =$B2>75 (Blue Fill)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple conditional formatting rules can apply to
|
||||
* one cell, some combining, some beating others.
|
||||
* Done in order of the rules added to the
|
||||
* SheetConditionalFormatting object
|
||||
*/
|
||||
static void overlapping(Sheet sheet) {
|
||||
for (int i=0; i<40; i++) {
|
||||
int rn = i+1;
|
||||
Row r = sheet.createRow(i);
|
||||
r.createCell(0).setCellValue("This is row " + rn + " (" + i + ")");
|
||||
String str = "";
|
||||
if (rn%2 == 0) str = str + "even ";
|
||||
if (rn%3 == 0) str = str + "x3 ";
|
||||
if (rn%5 == 0) str = str + "x5 ";
|
||||
if (rn%10 == 0) str = str + "x10 ";
|
||||
if (str.length() == 0) str = "nothing special...";
|
||||
r.createCell(1).setCellValue("It is " + str);
|
||||
}
|
||||
sheet.autoSizeColumn(0);
|
||||
sheet.autoSizeColumn(1);
|
||||
|
||||
sheet.getRow(1).createCell(3).setCellValue("Even rows are blue");
|
||||
sheet.getRow(2).createCell(3).setCellValue("Multiples of 3 have a grey background");
|
||||
sheet.getRow(4).createCell(3).setCellValue("Multiples of 5 are bold");
|
||||
sheet.getRow(9).createCell(3).setCellValue("Multiples of 10 are red (beats even)");
|
||||
|
||||
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
|
||||
|
||||
// Condition 1: Row divides by 10, red (will beat #1)
|
||||
ConditionalFormattingRule rule1 =
|
||||
sheetCF.createConditionalFormattingRule("MOD(ROW(),10)=0");
|
||||
FontFormatting font1 = rule1.createFontFormatting();
|
||||
font1.setFontColorIndex(IndexedColors.RED.index);
|
||||
|
||||
// Condition 2: Row is even, blue
|
||||
ConditionalFormattingRule rule2 =
|
||||
sheetCF.createConditionalFormattingRule("MOD(ROW(),2)=0");
|
||||
FontFormatting font2 = rule2.createFontFormatting();
|
||||
font2.setFontColorIndex(IndexedColors.BLUE.index);
|
||||
|
||||
// Condition 3: Row divides by 5, bold
|
||||
ConditionalFormattingRule rule3 =
|
||||
sheetCF.createConditionalFormattingRule("MOD(ROW(),5)=0");
|
||||
FontFormatting font3 = rule3.createFontFormatting();
|
||||
font3.setFontStyle(false, true);
|
||||
|
||||
// Condition 4: Row divides by 3, grey background
|
||||
ConditionalFormattingRule rule4 =
|
||||
sheetCF.createConditionalFormattingRule("MOD(ROW(),3)=0");
|
||||
PatternFormatting fill4 = rule4.createPatternFormatting();
|
||||
fill4.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index);
|
||||
fill4.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
|
||||
|
||||
// Apply
|
||||
CellRangeAddress[] regions = {
|
||||
CellRangeAddress.valueOf("A1:F41")
|
||||
};
|
||||
|
||||
sheetCF.addConditionalFormatting(regions, rule1);
|
||||
sheetCF.addConditionalFormatting(regions, rule2);
|
||||
sheetCF.addConditionalFormatting(regions, rule3);
|
||||
sheetCF.addConditionalFormatting(regions, rule4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use Excel conditional formatting to check for errors,
|
||||
@ -346,4 +416,64 @@ public class ConditionalFormats {
|
||||
sheet.createRow(0).createCell(1).setCellValue("Shade Bands of Rows");
|
||||
sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),6)<2 (Light Grey Fill)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon Sets / Multi-States allow you to have icons shown which vary
|
||||
* based on the values, eg Red traffic light / Yellow traffic light /
|
||||
* Green traffic light
|
||||
*/
|
||||
static void iconSets(Sheet sheet) {
|
||||
sheet.createRow(0).createCell(0).setCellValue("Icon Sets");
|
||||
Row r = sheet.createRow(1);
|
||||
r.createCell(0).setCellValue("Reds");
|
||||
r.createCell(1).setCellValue(0);
|
||||
r.createCell(2).setCellValue(0);
|
||||
r.createCell(3).setCellValue(0);
|
||||
r = sheet.createRow(2);
|
||||
r.createCell(0).setCellValue("Yellows");
|
||||
r.createCell(1).setCellValue(5);
|
||||
r.createCell(2).setCellValue(5);
|
||||
r.createCell(3).setCellValue(5);
|
||||
r = sheet.createRow(3);
|
||||
r.createCell(0).setCellValue("Greens");
|
||||
r.createCell(1).setCellValue(10);
|
||||
r.createCell(2).setCellValue(10);
|
||||
r.createCell(3).setCellValue(10);
|
||||
|
||||
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
|
||||
|
||||
CellRangeAddress[] regions = { CellRangeAddress.valueOf("B1:B4") };
|
||||
ConditionalFormattingRule rule1 =
|
||||
sheetCF.createConditionalFormattingRule(IconSet.GYR_3_TRAFFIC_LIGHTS);
|
||||
IconMultiStateFormatting im1 = rule1.getMultiStateFormatting();
|
||||
im1.getThresholds()[0].setRangeType(RangeType.MIN);
|
||||
im1.getThresholds()[1].setRangeType(RangeType.PERCENT);
|
||||
im1.getThresholds()[1].setValue(33d);
|
||||
im1.getThresholds()[2].setRangeType(RangeType.MAX);
|
||||
sheetCF.addConditionalFormatting(regions, rule1);
|
||||
|
||||
regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C1:C4") };
|
||||
ConditionalFormattingRule rule2 =
|
||||
sheetCF.createConditionalFormattingRule(IconSet.GYR_3_FLAGS);
|
||||
IconMultiStateFormatting im2 = rule1.getMultiStateFormatting();
|
||||
im2.getThresholds()[0].setRangeType(RangeType.PERCENT);
|
||||
im2.getThresholds()[0].setValue(0d);
|
||||
im2.getThresholds()[1].setRangeType(RangeType.PERCENT);
|
||||
im2.getThresholds()[1].setValue(33d);
|
||||
im2.getThresholds()[2].setRangeType(RangeType.PERCENT);
|
||||
im2.getThresholds()[2].setValue(67d);
|
||||
sheetCF.addConditionalFormatting(regions, rule2);
|
||||
|
||||
regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D1:D4") };
|
||||
ConditionalFormattingRule rule3 =
|
||||
sheetCF.createConditionalFormattingRule(IconSet.GYR_3_SYMBOLS_CIRCLE);
|
||||
IconMultiStateFormatting im3 = rule1.getMultiStateFormatting();
|
||||
im3.setIconOnly(true);
|
||||
im3.getThresholds()[0].setRangeType(RangeType.MIN);
|
||||
im3.getThresholds()[1].setRangeType(RangeType.NUMBER);
|
||||
im3.getThresholds()[1].setValue(3d);
|
||||
im3.getThresholds()[2].setRangeType(RangeType.NUMBER);
|
||||
im3.getThresholds()[2].setValue(7d);
|
||||
sheetCF.addConditionalFormatting(regions, rule3);
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ public class ToHtml {
|
||||
private void fontStyle(CellStyle style) {
|
||||
Font font = wb.getFontAt(style.getFontIndex());
|
||||
|
||||
if (font.getBoldweight() >= HSSFFont.BOLDWEIGHT_NORMAL)
|
||||
if (font.getBoldweight() >= HSSFFont.BOLDWEIGHT_BOLD)
|
||||
out.format(" font-weight: bold;%n");
|
||||
if (font.getItalic())
|
||||
out.format(" font-style: italic;%n");
|
||||
@ -309,8 +309,12 @@ public class ToHtml {
|
||||
style = wb.getCellStyleAt((short) 0);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Formatter fmt = new Formatter(sb);
|
||||
fmt.format("style_%02x", style.getIndex());
|
||||
return fmt.toString();
|
||||
try {
|
||||
fmt.format("style_%02x", style.getIndex());
|
||||
return fmt.toString();
|
||||
} finally {
|
||||
fmt.close();
|
||||
}
|
||||
}
|
||||
|
||||
private <K> void styleOut(String attr, K key, Map<K, String> mapping) {
|
||||
|
@ -114,16 +114,17 @@ public class AligningCells {
|
||||
|
||||
// Make the selection
|
||||
CTRowImpl ctRow = (CTRowImpl) row.getCTRow();
|
||||
List spanList = new ArrayList();
|
||||
|
||||
// Add object with format start_coll:end_coll. For example 1:3 will span from
|
||||
// cell 1 to cell 3, where the column index starts with 0
|
||||
//
|
||||
// You can add multiple spans for one row
|
||||
Object span = start_column + ":" + end_column;
|
||||
|
||||
List<Object> spanList = new ArrayList<Object>();
|
||||
spanList.add(span);
|
||||
|
||||
//add spns to the row
|
||||
ctRow.setSpans(spanList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
@ -165,27 +166,31 @@ public class BigGridDemo {
|
||||
* @param out the stream to write the result to
|
||||
*/
|
||||
private static void substitute(File zipfile, File tmpfile, String entry, OutputStream out) throws IOException {
|
||||
ZipFile zip = new ZipFile(zipfile);
|
||||
ZipFile zip = ZipHelper.openZipFile(zipfile);
|
||||
|
||||
ZipOutputStream zos = new ZipOutputStream(out);
|
||||
try {
|
||||
ZipOutputStream zos = new ZipOutputStream(out);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Enumeration<ZipEntry> en = (Enumeration<ZipEntry>) zip.entries();
|
||||
while (en.hasMoreElements()) {
|
||||
ZipEntry ze = en.nextElement();
|
||||
if(!ze.getName().equals(entry)){
|
||||
zos.putNextEntry(new ZipEntry(ze.getName()));
|
||||
InputStream is = zip.getInputStream(ze);
|
||||
copyStream(is, zos);
|
||||
is.close();
|
||||
@SuppressWarnings("unchecked")
|
||||
Enumeration<ZipEntry> en = (Enumeration<ZipEntry>) zip.entries();
|
||||
while (en.hasMoreElements()) {
|
||||
ZipEntry ze = en.nextElement();
|
||||
if(!ze.getName().equals(entry)){
|
||||
zos.putNextEntry(new ZipEntry(ze.getName()));
|
||||
InputStream is = zip.getInputStream(ze);
|
||||
copyStream(is, zos);
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
zos.putNextEntry(new ZipEntry(entry));
|
||||
InputStream is = new FileInputStream(tmpfile);
|
||||
copyStream(is, zos);
|
||||
is.close();
|
||||
|
||||
zos.close();
|
||||
} finally {
|
||||
zip.close();
|
||||
}
|
||||
zos.putNextEntry(new ZipEntry(entry));
|
||||
InputStream is = new FileInputStream(tmpfile);
|
||||
copyStream(is, zos);
|
||||
is.close();
|
||||
|
||||
zos.close();
|
||||
}
|
||||
|
||||
private static void copyStream(InputStream in, OutputStream out) throws IOException {
|
||||
|
145
src/integrationtest/build.xml
Normal file
145
src/integrationtest/build.xml
Normal file
@ -0,0 +1,145 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<project name="POI Testbuild" default="run" basedir=".">
|
||||
|
||||
<description>Test-Ant file which verifies that the Apache POI distribution build sources can be compiled successfully.
|
||||
|
||||
Before running this, you should execute the "assemble" target in the main build.xml to have the packaged files
|
||||
created correctly.
|
||||
|
||||
</description>
|
||||
|
||||
<property name="dist" value="../../build/dist"/>
|
||||
<property name="build" value="../../build/distsourcebuild"/>
|
||||
|
||||
<target name="init" depends="">
|
||||
</target>
|
||||
|
||||
<target name="run" depends="init,runSourceBuild,runCompileTest"/>
|
||||
|
||||
<target name="runSourceBuild" depends="init">
|
||||
<!-- clean out old stuff in build-dir -->
|
||||
<delete dir="${build}"/>
|
||||
<mkdir dir="${build}"/>
|
||||
|
||||
<!-- select latest built source zip -->
|
||||
<pathconvert property="srcpackage">
|
||||
<last>
|
||||
<sort>
|
||||
<date xmlns="antlib:org.apache.tools.ant.types.resources.comparators"/>
|
||||
<resources>
|
||||
<fileset dir="${dist}">
|
||||
<include name="poi-src-*.zip" />
|
||||
</fileset>
|
||||
</resources>
|
||||
</sort>
|
||||
</last>
|
||||
</pathconvert>
|
||||
|
||||
<echo message="Found source package at ${srcpackage}"/>
|
||||
<unzip src="${srcpackage}" dest="${build}" failOnEmptyArchive="true"/>
|
||||
|
||||
<!-- look for name of sub-dir, do this dynamically as it changes with every (beta|rc)-release -->
|
||||
<pathconvert property="dirversion">
|
||||
<dirset dir="${build}">
|
||||
<include name="*" />
|
||||
</dirset>
|
||||
</pathconvert>
|
||||
|
||||
<!-- finally call Ant on the extracted source to check if we can build the packages -->
|
||||
<echo message="Building in temporary dir ${dirversion}/"/>
|
||||
<ant dir="${dirversion}" target="jar" inheritAll="false" inheritRefs="false" useNativeBasedir="true"/>
|
||||
</target>
|
||||
|
||||
<target name="runCompileTest" depends="init" description="Verify that we can compile most examples without including excelant or scratchpad jars">
|
||||
<!-- clean out old stuff in build-dir -->
|
||||
<delete dir="${build}"/>
|
||||
<mkdir dir="${build}"/>
|
||||
|
||||
<!-- select latest built jar files without scratchpad.jar -->
|
||||
<pathconvert property="jarpackage">
|
||||
<sort>
|
||||
<resources>
|
||||
<fileset dir="${dist}">
|
||||
<include name="poi-3.*.jar" />
|
||||
<include name="poi-ooxml-3.*.jar" />
|
||||
<include name="poi-ooxml-schemas-3.*.jar" />
|
||||
<exclude name="*-javadocs-*" />
|
||||
<exclude name="*-sources-*" />
|
||||
</fileset>
|
||||
</resources>
|
||||
</sort>
|
||||
</pathconvert>
|
||||
|
||||
<echo message="Found jar packages at ${jarpackage}"/>
|
||||
|
||||
<path id="libs">
|
||||
<fileset dir="../../lib">
|
||||
<include name="junit*.jar" />
|
||||
</fileset>
|
||||
<fileset dir="../../ooxml-lib">
|
||||
<include name="ooxml-schemas-*.jar" />
|
||||
<include name="xmlbeans-*.jar" />
|
||||
<exclude name="xmlbeans-2.3.*.jar" />
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<echo message="Compiling examples without linking to scratchpad.jar to ensure that only some specific ones require this jar" />
|
||||
<javac srcdir="../examples/src" destdir="${build}"
|
||||
target="1.6"
|
||||
source="1.6"
|
||||
debug="trye"
|
||||
encoding="ASCII"
|
||||
fork="yes"
|
||||
includeantruntime="false"
|
||||
excludes="org/apache/poi/hslf/**,org/apache/poi/hsmf/**,**/EmbeddedObjects.java,**/EmeddedObjects.java,**/Word2Forrest.java"
|
||||
classpath="${jarpackage}"
|
||||
classpathref="libs">
|
||||
</javac>
|
||||
|
||||
<!-- select latest built jar files with additionally scratchpad.jar -->
|
||||
<pathconvert property="jarpackagescratchpad">
|
||||
<sort>
|
||||
<resources>
|
||||
<fileset dir="${dist}">
|
||||
<include name="poi-3.*.jar" />
|
||||
<include name="poi-ooxml-3.*.jar" />
|
||||
<include name="poi-ooxml-schemas-3.*.jar" />
|
||||
<include name="poi-scratchpad-3.*.jar" />
|
||||
<exclude name="*-javadocs-*" />
|
||||
<exclude name="*-sources-*" />
|
||||
</fileset>
|
||||
</resources>
|
||||
</sort>
|
||||
</pathconvert>
|
||||
|
||||
<echo message="Compiling all examples with the additinal scratchpad.jar" />
|
||||
<javac srcdir="../examples/src" destdir="${build}"
|
||||
target="1.6"
|
||||
source="1.6"
|
||||
debug="trye"
|
||||
encoding="ASCII"
|
||||
fork="yes"
|
||||
includeantruntime="false"
|
||||
classpath="${jarpackagescratchpad}"
|
||||
classpathref="libs">
|
||||
</javac>
|
||||
</target>
|
||||
</project>
|
@ -31,6 +31,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.poi.hwpf.OldWordFileFormatException;
|
||||
import org.apache.poi.stress.*;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.junit.Test;
|
||||
@ -65,83 +66,91 @@ import org.junit.runners.Parameterized.Parameters;
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class TestAllFiles {
|
||||
private static final File ROOT_DIR = new File("test-data");
|
||||
private static final File ROOT_DIR = new File("test-data");
|
||||
|
||||
// map file extensions to the actual mappers
|
||||
private static final Map<String, FileHandler> HANDLERS = new HashMap<String, FileHandler>();
|
||||
static {
|
||||
// Excel
|
||||
HANDLERS.put(".xls", new HSSFFileHandler());
|
||||
HANDLERS.put(".xlsx", new XSSFFileHandler());
|
||||
HANDLERS.put(".xlsm", new XSSFFileHandler());
|
||||
HANDLERS.put(".xltx", new XSSFFileHandler());
|
||||
HANDLERS.put(".xlsb", new XSSFFileHandler());
|
||||
|
||||
// Word
|
||||
HANDLERS.put(".doc", new HWPFFileHandler());
|
||||
HANDLERS.put(".docx", new XWPFFileHandler());
|
||||
HANDLERS.put(".dotx", new XWPFFileHandler());
|
||||
HANDLERS.put(".docm", new XWPFFileHandler());
|
||||
HANDLERS.put(".ooxml", new XWPFFileHandler()); // OPCPackage
|
||||
private static final Map<String, FileHandler> HANDLERS = new HashMap<String, FileHandler>();
|
||||
static {
|
||||
// Excel
|
||||
HANDLERS.put(".xls", new HSSFFileHandler());
|
||||
HANDLERS.put(".xlsx", new XSSFFileHandler());
|
||||
HANDLERS.put(".xlsm", new XSSFFileHandler());
|
||||
HANDLERS.put(".xltx", new XSSFFileHandler());
|
||||
HANDLERS.put(".xlsb", new XSSFFileHandler());
|
||||
|
||||
// Powerpoint
|
||||
HANDLERS.put(".ppt", new HSLFFileHandler());
|
||||
HANDLERS.put(".pptx", new XSLFFileHandler());
|
||||
HANDLERS.put(".pptm", new XSLFFileHandler());
|
||||
HANDLERS.put(".ppsm", new XSLFFileHandler());
|
||||
HANDLERS.put(".ppsx", new XSLFFileHandler());
|
||||
HANDLERS.put(".thmx", new XSLFFileHandler());
|
||||
// Word
|
||||
HANDLERS.put(".doc", new HWPFFileHandler());
|
||||
HANDLERS.put(".docx", new XWPFFileHandler());
|
||||
HANDLERS.put(".dotx", new XWPFFileHandler());
|
||||
HANDLERS.put(".docm", new XWPFFileHandler());
|
||||
HANDLERS.put(".ooxml", new XWPFFileHandler()); // OPCPackage
|
||||
|
||||
// Outlook
|
||||
HANDLERS.put(".msg", new HSMFFileHandler());
|
||||
|
||||
// Publisher
|
||||
HANDLERS.put(".pub", new HPBFFileHandler());
|
||||
// Powerpoint
|
||||
HANDLERS.put(".ppt", new HSLFFileHandler());
|
||||
HANDLERS.put(".pptx", new XSLFFileHandler());
|
||||
HANDLERS.put(".pptm", new XSLFFileHandler());
|
||||
HANDLERS.put(".ppsm", new XSLFFileHandler());
|
||||
HANDLERS.put(".ppsx", new XSLFFileHandler());
|
||||
HANDLERS.put(".thmx", new XSLFFileHandler());
|
||||
|
||||
// Visio
|
||||
HANDLERS.put(".vsd", new HDGFFileHandler());
|
||||
|
||||
// POIFS
|
||||
HANDLERS.put(".ole2", new POIFSFileHandler());
|
||||
// Outlook
|
||||
HANDLERS.put(".msg", new HSMFFileHandler());
|
||||
|
||||
// Microsoft Admin Template?
|
||||
HANDLERS.put(".adm", new HPSFFileHandler());
|
||||
// Publisher
|
||||
HANDLERS.put(".pub", new HPBFFileHandler());
|
||||
|
||||
// Microsoft TNEF
|
||||
HANDLERS.put(".dat", new HMEFFileHandler());
|
||||
|
||||
// TODO: are these readable by some of the formats?
|
||||
HANDLERS.put(".shw", new NullFileHandler());
|
||||
HANDLERS.put(".zvi", new NullFileHandler());
|
||||
HANDLERS.put(".mpp", new NullFileHandler());
|
||||
HANDLERS.put(".qwp", new NullFileHandler());
|
||||
HANDLERS.put(".wps", new NullFileHandler());
|
||||
HANDLERS.put(".bin", new NullFileHandler());
|
||||
HANDLERS.put(".xps", new NullFileHandler());
|
||||
HANDLERS.put(".sldprt", new NullFileHandler());
|
||||
HANDLERS.put(".mdb", new NullFileHandler());
|
||||
HANDLERS.put(".vml", new NullFileHandler());
|
||||
// Visio - binary
|
||||
HANDLERS.put(".vsd", new HDGFFileHandler());
|
||||
|
||||
// Visio - ooxml (currently unsupported)
|
||||
HANDLERS.put(".vsdm", new NullFileHandler());
|
||||
HANDLERS.put(".vsdx", new NullFileHandler());
|
||||
HANDLERS.put(".vssm", new NullFileHandler());
|
||||
HANDLERS.put(".vssx", new NullFileHandler());
|
||||
HANDLERS.put(".vstm", new NullFileHandler());
|
||||
HANDLERS.put(".vstx", new NullFileHandler());
|
||||
|
||||
// ignore some file types, images, other formats, ...
|
||||
HANDLERS.put(".txt", new NullFileHandler());
|
||||
HANDLERS.put(".pdf", new NullFileHandler());
|
||||
HANDLERS.put(".rtf", new NullFileHandler());
|
||||
HANDLERS.put(".gif", new NullFileHandler());
|
||||
HANDLERS.put(".html", new NullFileHandler());
|
||||
HANDLERS.put(".png", new NullFileHandler());
|
||||
HANDLERS.put(".wmf", new NullFileHandler());
|
||||
HANDLERS.put(".emf", new NullFileHandler());
|
||||
HANDLERS.put(".dib", new NullFileHandler());
|
||||
HANDLERS.put(".svg", new NullFileHandler());
|
||||
HANDLERS.put(".pict", new NullFileHandler());
|
||||
HANDLERS.put(".jpg", new NullFileHandler());
|
||||
HANDLERS.put(".wav", new NullFileHandler());
|
||||
HANDLERS.put(".pfx", new NullFileHandler());
|
||||
HANDLERS.put(".xml", new NullFileHandler());
|
||||
HANDLERS.put(".csv", new NullFileHandler());
|
||||
|
||||
// map some files without extension
|
||||
HANDLERS.put("spreadsheet/BigSSTRecord", new NullFileHandler());
|
||||
// POIFS
|
||||
HANDLERS.put(".ole2", new POIFSFileHandler());
|
||||
|
||||
// Microsoft Admin Template?
|
||||
HANDLERS.put(".adm", new HPSFFileHandler());
|
||||
|
||||
// Microsoft TNEF
|
||||
HANDLERS.put(".dat", new HMEFFileHandler());
|
||||
|
||||
// TODO: are these readable by some of the formats?
|
||||
HANDLERS.put(".shw", new NullFileHandler());
|
||||
HANDLERS.put(".zvi", new NullFileHandler());
|
||||
HANDLERS.put(".mpp", new NullFileHandler());
|
||||
HANDLERS.put(".qwp", new NullFileHandler());
|
||||
HANDLERS.put(".wps", new NullFileHandler());
|
||||
HANDLERS.put(".bin", new NullFileHandler());
|
||||
HANDLERS.put(".xps", new NullFileHandler());
|
||||
HANDLERS.put(".sldprt", new NullFileHandler());
|
||||
HANDLERS.put(".mdb", new NullFileHandler());
|
||||
HANDLERS.put(".vml", new NullFileHandler());
|
||||
|
||||
// ignore some file types, images, other formats, ...
|
||||
HANDLERS.put(".txt", new NullFileHandler());
|
||||
HANDLERS.put(".pdf", new NullFileHandler());
|
||||
HANDLERS.put(".rtf", new NullFileHandler());
|
||||
HANDLERS.put(".gif", new NullFileHandler());
|
||||
HANDLERS.put(".html", new NullFileHandler());
|
||||
HANDLERS.put(".png", new NullFileHandler());
|
||||
HANDLERS.put(".wmf", new NullFileHandler());
|
||||
HANDLERS.put(".emf", new NullFileHandler());
|
||||
HANDLERS.put(".dib", new NullFileHandler());
|
||||
HANDLERS.put(".svg", new NullFileHandler());
|
||||
HANDLERS.put(".pict", new NullFileHandler());
|
||||
HANDLERS.put(".jpg", new NullFileHandler());
|
||||
HANDLERS.put(".wav", new NullFileHandler());
|
||||
HANDLERS.put(".pfx", new NullFileHandler());
|
||||
HANDLERS.put(".xml", new NullFileHandler());
|
||||
HANDLERS.put(".csv", new NullFileHandler());
|
||||
|
||||
// map some files without extension
|
||||
HANDLERS.put("spreadsheet/BigSSTRecord", new NullFileHandler());
|
||||
HANDLERS.put("spreadsheet/BigSSTRecord2", new NullFileHandler());
|
||||
HANDLERS.put("spreadsheet/BigSSTRecord2CR1", new NullFileHandler());
|
||||
HANDLERS.put("spreadsheet/BigSSTRecord2CR2", new NullFileHandler());
|
||||
@ -151,88 +160,104 @@ public class TestAllFiles {
|
||||
HANDLERS.put("spreadsheet/BigSSTRecord2CR6", new NullFileHandler());
|
||||
HANDLERS.put("spreadsheet/BigSSTRecord2CR7", new NullFileHandler());
|
||||
HANDLERS.put("spreadsheet/BigSSTRecordCR", new NullFileHandler());
|
||||
HANDLERS.put("spreadsheet/test_properties1", new NullFileHandler());
|
||||
}
|
||||
HANDLERS.put("spreadsheet/test_properties1", new NullFileHandler());
|
||||
}
|
||||
|
||||
private static final Set<String> EXPECTED_FAILURES = new HashSet<String>();
|
||||
static {
|
||||
// password protected files
|
||||
EXPECTED_FAILURES.add("spreadsheet/password.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/51832.xls");
|
||||
EXPECTED_FAILURES.add("document/PasswordProtected.doc");
|
||||
EXPECTED_FAILURES.add("slideshow/Password_Protected-hello.ppt");
|
||||
EXPECTED_FAILURES.add("slideshow/Password_Protected-56-hello.ppt");
|
||||
EXPECTED_FAILURES.add("slideshow/Password_Protected-np-hello.ppt");
|
||||
EXPECTED_FAILURES.add("slideshow/cryptoapi-proc2356.ppt");
|
||||
//EXPECTED_FAILURES.add("document/bug53475-password-is-pass.docx");
|
||||
//EXPECTED_FAILURES.add("document/bug53475-password-is-solrcell.docx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/xor-encryption-abc.xls");
|
||||
// Old Word Documents where we can at least extract some text
|
||||
private static final Set<String> OLD_FILES = new HashSet<String>();
|
||||
static {
|
||||
OLD_FILES.add("document/Bug49933.doc");
|
||||
OLD_FILES.add("document/Bug51944.doc");
|
||||
OLD_FILES.add("document/Word6.doc");
|
||||
OLD_FILES.add("document/Word6_sections.doc");
|
||||
OLD_FILES.add("document/Word6_sections2.doc");
|
||||
OLD_FILES.add("document/Word95.doc");
|
||||
OLD_FILES.add("document/word95err.doc");
|
||||
OLD_FILES.add("hpsf/TestMickey.doc");
|
||||
OLD_FILES.add("document/52117.doc");
|
||||
}
|
||||
|
||||
private static final Set<String> EXPECTED_FAILURES = new HashSet<String>();
|
||||
static {
|
||||
// password protected files
|
||||
EXPECTED_FAILURES.add("spreadsheet/password.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/protected_passtika.xlsx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/51832.xls");
|
||||
EXPECTED_FAILURES.add("document/PasswordProtected.doc");
|
||||
EXPECTED_FAILURES.add("slideshow/Password_Protected-hello.ppt");
|
||||
EXPECTED_FAILURES.add("slideshow/Password_Protected-56-hello.ppt");
|
||||
EXPECTED_FAILURES.add("slideshow/Password_Protected-np-hello.ppt");
|
||||
EXPECTED_FAILURES.add("slideshow/cryptoapi-proc2356.ppt");
|
||||
//EXPECTED_FAILURES.add("document/bug53475-password-is-pass.docx");
|
||||
//EXPECTED_FAILURES.add("document/bug53475-password-is-solrcell.docx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/xor-encryption-abc.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/35897-type4.xls");
|
||||
//EXPECTED_FAILURES.add("poifs/protect.xlsx");
|
||||
//EXPECTED_FAILURES.add("poifs/protected_sha512.xlsx");
|
||||
//EXPECTED_FAILURES.add("poifs/extenxls_pwd123.xlsx");
|
||||
//EXPECTED_FAILURES.add("poifs/protected_agile.docx");
|
||||
|
||||
// TODO: fails XMLExportTest, is this ok?
|
||||
EXPECTED_FAILURES.add("spreadsheet/CustomXMLMapping-singleattributenamespace.xlsx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/55864.xlsx");
|
||||
|
||||
// TODO: these fail now with some NPE/file read error because we now try to compute every value via Cell.toString()!
|
||||
EXPECTED_FAILURES.add("spreadsheet/44958.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/44958_1.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/testArraysAndTables.xls");
|
||||
|
||||
// TODO: good to ignore?
|
||||
EXPECTED_FAILURES.add("spreadsheet/sample-beta.xlsx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/49931.xls");
|
||||
EXPECTED_FAILURES.add("openxml4j/ContentTypeHasParameters.ooxml");
|
||||
// TODO: fails XMLExportTest, is this ok?
|
||||
EXPECTED_FAILURES.add("spreadsheet/CustomXMLMapping-singleattributenamespace.xlsx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/55864.xlsx");
|
||||
|
||||
// This is actually a spreadsheet!
|
||||
EXPECTED_FAILURES.add("hpsf/TestRobert_Flaherty.doc");
|
||||
|
||||
// some files that are broken, Excel 5.0/95, Word 95, ...
|
||||
EXPECTED_FAILURES.add("spreadsheet/43493.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/46904.xls");
|
||||
EXPECTED_FAILURES.add("document/56880.doc");
|
||||
EXPECTED_FAILURES.add("document/Bug49933.doc");
|
||||
EXPECTED_FAILURES.add("document/Bug50955.doc");
|
||||
EXPECTED_FAILURES.add("document/Bug51944.doc");
|
||||
EXPECTED_FAILURES.add("document/Word6.doc");
|
||||
EXPECTED_FAILURES.add("document/Word6_sections.doc");
|
||||
EXPECTED_FAILURES.add("document/Word6_sections2.doc");
|
||||
EXPECTED_FAILURES.add("document/Word95.doc");
|
||||
EXPECTED_FAILURES.add("document/word95err.doc");
|
||||
EXPECTED_FAILURES.add("hpsf/TestMickey.doc");
|
||||
EXPECTED_FAILURES.add("slideshow/PPT95.ppt");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_NotPresentFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_OnlyOneCorePropertiesPartFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_UnauthorizedXMLLangAttributeFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_DerivedPartNameFAIL.docx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/54764-2.xlsx"); // see TestXSSFBugs.bug54764()
|
||||
EXPECTED_FAILURES.add("spreadsheet/54764.xlsx"); // see TestXSSFBugs.bug54764()
|
||||
// TODO: these fail now with some NPE/file read error because we now try to compute every value via Cell.toString()!
|
||||
EXPECTED_FAILURES.add("spreadsheet/44958.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/44958_1.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/testArraysAndTables.xls");
|
||||
|
||||
// TODO: good to ignore?
|
||||
EXPECTED_FAILURES.add("spreadsheet/sample-beta.xlsx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/49931.xls");
|
||||
EXPECTED_FAILURES.add("openxml4j/ContentTypeHasParameters.ooxml");
|
||||
|
||||
// This is actually a spreadsheet!
|
||||
EXPECTED_FAILURES.add("hpsf/TestRobert_Flaherty.doc");
|
||||
|
||||
// some files that are broken, eg Word 95, ...
|
||||
EXPECTED_FAILURES.add("spreadsheet/43493.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/46904.xls");
|
||||
EXPECTED_FAILURES.add("document/56880.doc");
|
||||
EXPECTED_FAILURES.add("document/Bug50955.doc");
|
||||
EXPECTED_FAILURES.add("slideshow/PPT95.ppt");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_NotPresentFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_OnlyOneCorePropertiesPartFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_UnauthorizedXMLLangAttributeFAIL.docx");
|
||||
EXPECTED_FAILURES.add("openxml4j/OPCCompliance_DerivedPartNameFAIL.docx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/54764-2.xlsx"); // see TestXSSFBugs.bug54764()
|
||||
EXPECTED_FAILURES.add("spreadsheet/54764.xlsx"); // see TestXSSFBugs.bug54764()
|
||||
EXPECTED_FAILURES.add("spreadsheet/Simple.xlsb");
|
||||
EXPECTED_FAILURES.add("poifs/unknown_properties.msg"); // POIFS properties corrupted
|
||||
EXPECTED_FAILURES.add("poifs/only-zero-byte-streams.ole2"); // No actual contents
|
||||
|
||||
// old Excel files, which we only support simple text extraction of
|
||||
EXPECTED_FAILURES.add("spreadsheet/testEXCEL_2.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/testEXCEL_3.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/testEXCEL_4.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/testEXCEL_5.xls");
|
||||
EXPECTED_FAILURES.add("spreadsheet/testEXCEL_95.xls");
|
||||
|
||||
// OOXML Strict is not yet supported, see bug #57699
|
||||
EXPECTED_FAILURES.add("spreadsheet/SampleSS.strict.xlsx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/SimpleStrict.xlsx");
|
||||
EXPECTED_FAILURES.add("spreadsheet/sample.strict.xlsx");
|
||||
|
||||
// non-TNEF files
|
||||
EXPECTED_FAILURES.add("ddf/Container.dat");
|
||||
EXPECTED_FAILURES.add("ddf/47143.dat");
|
||||
}
|
||||
|
||||
// non-TNEF files
|
||||
EXPECTED_FAILURES.add("ddf/Container.dat");
|
||||
EXPECTED_FAILURES.add("ddf/47143.dat");
|
||||
}
|
||||
|
||||
@Parameters(name="{index}: {0} using {1}")
|
||||
public static Iterable<Object[]> files() {
|
||||
DirectoryScanner scanner = new DirectoryScanner();
|
||||
scanner.setBasedir(ROOT_DIR);
|
||||
scanner.setExcludes(new String[] { "**/.svn/**" });
|
||||
|
||||
|
||||
scanner.scan();
|
||||
|
||||
|
||||
System.out.println("Handling " + scanner.getIncludedFiles().length + " files");
|
||||
|
||||
List<Object[]> files = new ArrayList<Object[]>();
|
||||
@ -240,47 +265,72 @@ public class TestAllFiles {
|
||||
file = file.replace('\\', '/'); // ... failures/handlers lookup doesn't work on windows otherwise
|
||||
files.add(new Object[] { file, HANDLERS.get(getExtension(file)) });
|
||||
}
|
||||
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Parameter(value=0)
|
||||
public String file;
|
||||
|
||||
|
||||
@Parameter(value=1)
|
||||
public FileHandler handler;
|
||||
|
||||
|
||||
@Test
|
||||
public void testAllFiles() throws Exception {
|
||||
assertNotNull("Unknown file extension for file: " + file + ": " + getExtension(file), handler);
|
||||
InputStream stream = new BufferedInputStream(new FileInputStream(new File(ROOT_DIR, file)),100);
|
||||
try {
|
||||
handler.handleFile(stream);
|
||||
|
||||
assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!",
|
||||
EXPECTED_FAILURES.contains(file));
|
||||
} catch (Exception e) {
|
||||
// check if we expect failure for this file
|
||||
if(!EXPECTED_FAILURES.contains(file)) {
|
||||
throw new Exception("While handling " + file, e);
|
||||
}
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
assertNotNull("Unknown file extension for file: " + file + ": " + getExtension(file), handler);
|
||||
File inputFile = new File(ROOT_DIR, file);
|
||||
|
||||
private static String getExtension(String file) {
|
||||
int pos = file.lastIndexOf('.');
|
||||
if(pos == -1 || pos == file.length()-1) {
|
||||
return file;
|
||||
}
|
||||
|
||||
return file.substring(pos);
|
||||
}
|
||||
try {
|
||||
InputStream stream = new BufferedInputStream(new FileInputStream(inputFile), 64*1024);
|
||||
try {
|
||||
handler.handleFile(stream);
|
||||
|
||||
private static class NullFileHandler implements FileHandler {
|
||||
@Override
|
||||
assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!",
|
||||
OLD_FILES.contains(file));
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
handler.handleExtracting(inputFile);
|
||||
|
||||
assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!",
|
||||
EXPECTED_FAILURES.contains(file));
|
||||
} catch (OldWordFileFormatException e) {
|
||||
// for old word files we should still support extracting text
|
||||
if(OLD_FILES.contains(file)) {
|
||||
handler.handleExtracting(inputFile);
|
||||
} else {
|
||||
// check if we expect failure for this file
|
||||
if(!EXPECTED_FAILURES.contains(file) && !AbstractFileHandler.EXPECTED_EXTRACTOR_FAILURES.contains(file)) {
|
||||
System.out.println("Failed: " + file);
|
||||
throw new Exception("While handling " + file, e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// check if we expect failure for this file
|
||||
if(!EXPECTED_FAILURES.contains(file) && !AbstractFileHandler.EXPECTED_EXTRACTOR_FAILURES.contains(file)) {
|
||||
System.out.println("Failed: " + file);
|
||||
throw new Exception("While handling " + file, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getExtension(String file) {
|
||||
int pos = file.lastIndexOf('.');
|
||||
if(pos == -1 || pos == file.length()-1) {
|
||||
return file;
|
||||
}
|
||||
|
||||
return file.substring(pos);
|
||||
}
|
||||
|
||||
private static class NullFileHandler implements FileHandler {
|
||||
@Override
|
||||
public void handleFile(InputStream stream) throws Exception {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleExtracting(File file) throws Exception {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,143 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.stress;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
import org.apache.poi.POIOLE2TextExtractor;
|
||||
import org.apache.poi.POITextExtractor;
|
||||
import org.apache.poi.dev.OOXMLPrettyPrint;
|
||||
import org.apache.poi.extractor.ExtractorFactory;
|
||||
import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
|
||||
public abstract class AbstractFileHandler implements FileHandler {
|
||||
public static final Set<String> EXPECTED_EXTRACTOR_FAILURES = new HashSet<String>();
|
||||
static {
|
||||
// password protected files
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("document/bug53475-password-is-pass.docx");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("poifs/extenxls_pwd123.xlsx");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("poifs/protect.xlsx");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("poifs/protected_agile.docx");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("poifs/protected_sha512.xlsx");
|
||||
|
||||
// unsupported file-types, no supported OLE2 parts
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("hmef/quick-winmail.dat");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("hmef/winmail-sample1.dat");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("hmef/bug52400-winmail-simple.dat");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("hmef/bug52400-winmail-with-attachments.dat");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("hpsf/Test0313rur.adm");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("hsmf/attachment_msg_pdf.msg");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("poifs/Notes.ole2");
|
||||
EXPECTED_EXTRACTOR_FAILURES.add("slideshow/testPPT.thmx");
|
||||
}
|
||||
|
||||
public void handleExtracting(File file) throws Exception {
|
||||
boolean before = ExtractorFactory.getThreadPrefersEventExtractors();
|
||||
try {
|
||||
ExtractorFactory.setThreadPrefersEventExtractors(true);
|
||||
handleExtractingInternal(file);
|
||||
|
||||
ExtractorFactory.setThreadPrefersEventExtractors(false);
|
||||
handleExtractingInternal(file);
|
||||
} finally {
|
||||
ExtractorFactory.setThreadPrefersEventExtractors(before);
|
||||
}
|
||||
|
||||
/* Did fail for some documents with special XML contents...
|
||||
try {
|
||||
OOXMLPrettyPrint.main(new String[] { file.getAbsolutePath(),
|
||||
"/tmp/pretty-" + file.getName() });
|
||||
} catch (ZipException e) {
|
||||
// ignore, not a Zip/OOXML file
|
||||
}*/
|
||||
}
|
||||
|
||||
private void handleExtractingInternal(File file) throws Exception {
|
||||
long length = file.length();
|
||||
long modified = file.lastModified();
|
||||
|
||||
POITextExtractor extractor = ExtractorFactory.createExtractor(file);
|
||||
try {
|
||||
assertNotNull(extractor);
|
||||
|
||||
assertNotNull(extractor.getText());
|
||||
|
||||
// also try metadata
|
||||
POITextExtractor metadataExtractor = extractor.getMetadataTextExtractor();
|
||||
assertNotNull(metadataExtractor.getText());
|
||||
|
||||
assertFalse("Expected Extraction to fail for file " + file + " and handler " + this + ", but did not fail!",
|
||||
EXPECTED_EXTRACTOR_FAILURES.contains(file));
|
||||
|
||||
assertEquals("File should not be modified by extractor", length, file.length());
|
||||
assertEquals("File should not be modified by extractor", modified, file.lastModified());
|
||||
|
||||
handleExtractingAsStream(file);
|
||||
|
||||
if(extractor instanceof POIOLE2TextExtractor) {
|
||||
HPSFPropertiesExtractor hpsfExtractor = new HPSFPropertiesExtractor((POIOLE2TextExtractor)extractor);
|
||||
try {
|
||||
assertNotNull(hpsfExtractor.getDocumentSummaryInformationText());
|
||||
assertNotNull(hpsfExtractor.getSummaryInformationText());
|
||||
String text = hpsfExtractor.getText();
|
||||
//System.out.println(text);
|
||||
assertNotNull(text);
|
||||
} finally {
|
||||
hpsfExtractor.close();
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
if(!EXPECTED_EXTRACTOR_FAILURES.contains(file)) {
|
||||
throw new Exception("While handling " + file, e);
|
||||
}
|
||||
} finally {
|
||||
extractor.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleExtractingAsStream(File file) throws FileNotFoundException,
|
||||
IOException, InvalidFormatException, OpenXML4JException,
|
||||
XmlException {
|
||||
InputStream stream = new FileInputStream(file);
|
||||
try {
|
||||
POITextExtractor streamExtractor = ExtractorFactory.createExtractor(stream);
|
||||
try {
|
||||
assertNotNull(streamExtractor);
|
||||
|
||||
assertNotNull(streamExtractor.getText());
|
||||
} finally {
|
||||
streamExtractor.close();
|
||||
}
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.stress;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
@ -34,4 +35,10 @@ public interface FileHandler {
|
||||
* @throws Exception
|
||||
*/
|
||||
void handleFile(InputStream stream) throws Exception;
|
||||
|
||||
/**
|
||||
* Ensures that extracting text from the given file
|
||||
* is returning some text.
|
||||
*/
|
||||
void handleExtracting(File file) throws Exception;
|
||||
}
|
||||
|
@ -19,10 +19,12 @@ package org.apache.poi.stress;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.hdgf.HDGFDiagram;
|
||||
import org.apache.poi.hdgf.extractor.VisioTextExtractor;
|
||||
import org.apache.poi.hdgf.streams.Stream;
|
||||
import org.apache.poi.hdgf.streams.TrailerStream;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
@ -48,11 +50,27 @@ public class HDGFFileHandler extends POIFSFileHandler {
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
InputStream stream = new FileInputStream("test-data/diagram/44501.vsd");
|
||||
File file = new File("test-data/diagram/44501.vsd");
|
||||
|
||||
InputStream stream = new FileInputStream(file);
|
||||
try {
|
||||
handleFile(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
handleExtracting(file);
|
||||
|
||||
stream = new FileInputStream(file);
|
||||
try {
|
||||
VisioTextExtractor extractor = new VisioTextExtractor(stream);
|
||||
try {
|
||||
assertNotNull(extractor.getText());
|
||||
} finally {
|
||||
extractor.close();
|
||||
}
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import org.apache.poi.hmef.attribute.MAPIAttribute;
|
||||
import org.apache.poi.hmef.attribute.MAPIStringAttribute;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HMEFFileHandler implements FileHandler {
|
||||
public class HMEFFileHandler extends AbstractFileHandler {
|
||||
|
||||
@Override
|
||||
public void handleFile(InputStream stream) throws Exception {
|
||||
|
@ -18,10 +18,12 @@ package org.apache.poi.stress;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.hpbf.HPBFDocument;
|
||||
import org.apache.poi.hpbf.extractor.PublisherTextExtractor;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -39,11 +41,28 @@ public class HPBFFileHandler extends POIFSFileHandler {
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
InputStream stream = new FileInputStream("test-data/publisher/SampleBrochure.pub");
|
||||
File file = new File("test-data/publisher/SampleBrochure.pub");
|
||||
|
||||
InputStream stream = new FileInputStream(file);
|
||||
try {
|
||||
handleFile(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
handleExtracting(file);
|
||||
|
||||
stream = new FileInputStream(file);
|
||||
try {
|
||||
PublisherTextExtractor extractor = new PublisherTextExtractor(stream);
|
||||
try {
|
||||
assertNotNull(extractor.getText());
|
||||
} finally {
|
||||
extractor.close();
|
||||
}
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package org.apache.poi.stress;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
@ -25,7 +26,7 @@ import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HPSFFileHandler implements FileHandler {
|
||||
public class HPSFFileHandler extends AbstractFileHandler {
|
||||
@Override
|
||||
public void handleFile(InputStream stream) throws Exception {
|
||||
HPSFPropertiesOnlyDocument hpsf = new HPSFPropertiesOnlyDocument(new POIFSFileSystem(stream));
|
||||
@ -43,4 +44,10 @@ public class HPSFFileHandler implements FileHandler {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void testExtractor() throws Exception {
|
||||
handleExtracting(new File("test-data/hpsf/TestBug44375.xls"));
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.hsmf.MAPIMessage;
|
||||
import org.apache.poi.hsmf.datatypes.AttachmentChunks;
|
||||
import org.apache.poi.hsmf.datatypes.DirectoryChunk;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HSMFFileHandler extends POIFSFileHandler {
|
||||
@ -32,6 +34,19 @@ public class HSMFFileHandler extends POIFSFileHandler {
|
||||
assertNotNull(mapi.getDisplayBCC());
|
||||
assertNotNull(mapi.getMessageDate());
|
||||
|
||||
AttachmentChunks[] attachments = mapi.getAttachmentFiles();
|
||||
|
||||
for(AttachmentChunks attachment : attachments) {
|
||||
|
||||
DirectoryChunk chunkDirectory = attachment.attachmentDirectory;
|
||||
if(chunkDirectory != null) {
|
||||
MAPIMessage attachmentMSG = chunkDirectory.getAsEmbededMessage();
|
||||
assertNotNull(attachmentMSG);
|
||||
String body = attachmentMSG.getTextBody();
|
||||
assertNotNull(body);
|
||||
}
|
||||
}
|
||||
|
||||
/* => Writing isn't yet supported...
|
||||
// write out the file
|
||||
File file = TempFile.createTempFile("StressTest", ".msg");
|
||||
|
@ -16,6 +16,7 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.stress;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
@ -49,4 +50,10 @@ public class HSSFFileHandler extends SpreadsheetHandler {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void testExtractor() throws Exception {
|
||||
handleExtracting(new File("test-data/spreadsheet/BOOK_in_capitals.xls"));
|
||||
}
|
||||
}
|
@ -18,12 +18,21 @@ package org.apache.poi.stress;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.apache.poi.hdf.extractor.WordDocument;
|
||||
import org.apache.poi.hwpf.HWPFDocument;
|
||||
import org.apache.poi.hwpf.extractor.WordExtractor;
|
||||
import org.junit.Test;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class HWPFFileHandler extends POIFSFileHandler {
|
||||
@Override
|
||||
public void handleFile(InputStream stream) throws Exception {
|
||||
@ -33,16 +42,57 @@ public class HWPFFileHandler extends POIFSFileHandler {
|
||||
assertNotNull(doc.getEndnotes());
|
||||
|
||||
handlePOIDocument(doc);
|
||||
|
||||
// fails for many documents, but is deprecated anyway...
|
||||
// handleWordDocument(doc);
|
||||
}
|
||||
|
||||
protected void handleWordDocument(HWPFDocument doc) throws IOException {
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
doc.write(outStream);
|
||||
|
||||
WordDocument wordDoc = new WordDocument(new ByteArrayInputStream(outStream.toByteArray()));
|
||||
|
||||
StringWriter docTextWriter = new StringWriter();
|
||||
PrintWriter out = new PrintWriter(docTextWriter);
|
||||
try {
|
||||
wordDoc.writeAllText(out);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
docTextWriter.close();
|
||||
}
|
||||
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
InputStream stream = new FileInputStream("test-data/document/HeaderFooterUnicode.doc");
|
||||
File file = new File("test-data/document/52117.doc");
|
||||
|
||||
InputStream stream = new FileInputStream(file);
|
||||
try {
|
||||
handleFile(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
handleExtracting(file);
|
||||
|
||||
stream = new FileInputStream(file);
|
||||
try {
|
||||
WordExtractor extractor = new WordExtractor(stream);
|
||||
try {
|
||||
assertNotNull(extractor.getText());
|
||||
} finally {
|
||||
extractor.close();
|
||||
}
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractingOld() throws Exception {
|
||||
File file = new File("test-data/document/52117.doc");
|
||||
handleExtracting(file);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import java.io.InputStream;
|
||||
import org.apache.poi.POIDocument;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
public class POIFSFileHandler implements FileHandler {
|
||||
public class POIFSFileHandler extends AbstractFileHandler {
|
||||
|
||||
@Override
|
||||
public void handleFile(InputStream stream) throws Exception {
|
||||
|
@ -20,9 +20,17 @@ import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.POIXMLDocument;
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackageAccess;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.poifs.crypt.Decryptor;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public final class POIXMLDocumentHandler {
|
||||
protected void handlePOIXMLDocument(POIXMLDocument doc) throws Exception {
|
||||
@ -36,11 +44,33 @@ public final class POIXMLDocumentHandler {
|
||||
protected static boolean isEncrypted(InputStream stream) throws IOException {
|
||||
if (POIFSFileSystem.hasPOIFSHeader(stream)) {
|
||||
POIFSFileSystem poifs = new POIFSFileSystem(stream);
|
||||
if (poifs.getRoot().hasEntry("EncryptedPackage")) {
|
||||
if (poifs.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
|
||||
return true;
|
||||
}
|
||||
throw new IOException("wrong file format or file extension for OO XML file");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Ignore("POIXMLDocument cannot handle this Visio file currently...")
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
OPCPackage pkg = OPCPackage.open("test-data/diagram/test.vsdx", PackageAccess.READ);
|
||||
try {
|
||||
handlePOIXMLDocument(new TestPOIXMLDocument(pkg));
|
||||
} finally {
|
||||
pkg.close();
|
||||
}
|
||||
}
|
||||
|
||||
private final static class TestPOIXMLDocument extends POIXMLDocument {
|
||||
public TestPOIXMLDocument(OPCPackage pkg) {
|
||||
super(pkg);
|
||||
}
|
||||
|
||||
public List<PackagePart> getAllEmbedds() throws OpenXML4JException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
|
||||
public abstract class SpreadsheetHandler implements FileHandler {
|
||||
public abstract class SpreadsheetHandler extends AbstractFileHandler {
|
||||
public void handleWorkbook(Workbook wb, String extension) throws IOException {
|
||||
// try to access some of the content
|
||||
readContent(wb);
|
||||
|
@ -18,35 +18,97 @@ package org.apache.poi.stress;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.sl.draw.DrawFactory;
|
||||
import org.apache.poi.sl.draw.Drawable;
|
||||
import org.apache.poi.xslf.XSLFSlideShow;
|
||||
import org.apache.poi.xslf.usermodel.XMLSlideShow;
|
||||
import org.apache.poi.xslf.usermodel.XSLFNotes;
|
||||
import org.apache.poi.xslf.usermodel.XSLFShape;
|
||||
import org.apache.poi.xslf.usermodel.XSLFSlide;
|
||||
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
|
||||
import org.apache.poi.xslf.usermodel.XSLFTextShape;
|
||||
import org.junit.Test;
|
||||
|
||||
public class XSLFFileHandler implements FileHandler {
|
||||
public class XSLFFileHandler extends AbstractFileHandler {
|
||||
@Override
|
||||
public void handleFile(InputStream stream) throws Exception {
|
||||
// ignore password protected files
|
||||
if (POIXMLDocumentHandler.isEncrypted(stream)) return;
|
||||
|
||||
XSLFSlideShow slide = new XSLFSlideShow(OPCPackage.open(stream));
|
||||
assertNotNull(slide.getPresentation());
|
||||
assertNotNull(slide.getSlideMasterReferences());
|
||||
assertNotNull(slide.getSlideReferences());
|
||||
|
||||
new POIXMLDocumentHandler().handlePOIXMLDocument(slide);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try {
|
||||
slide.write(out);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
|
||||
createBitmaps(out);
|
||||
}
|
||||
|
||||
private void createBitmaps(ByteArrayOutputStream out) throws IOException {
|
||||
XMLSlideShow ppt = new XMLSlideShow(new ByteArrayInputStream(out.toByteArray()));
|
||||
Dimension pgsize = ppt.getPageSize();
|
||||
for (XSLFSlide xmlSlide : ppt.getSlides()) {
|
||||
// System.out.println("slide-" + (i + 1));
|
||||
// System.out.println("" + xmlSlide[i].getTitle());
|
||||
|
||||
BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D graphics = img.createGraphics();
|
||||
|
||||
// draw stuff
|
||||
xmlSlide.draw(graphics);
|
||||
|
||||
// Also try to read notes
|
||||
XSLFNotes notes = xmlSlide.getNotes();
|
||||
if(notes != null) {
|
||||
for (XSLFShape note : notes) {
|
||||
DrawFactory df = DrawFactory.getInstance(graphics);
|
||||
Drawable d = df.getDrawable(note);
|
||||
d.draw(graphics);
|
||||
|
||||
if (note instanceof XSLFTextShape) {
|
||||
XSLFTextShape txShape = (XSLFTextShape) note;
|
||||
for (XSLFTextParagraph xslfParagraph : txShape.getTextParagraphs()) {
|
||||
xslfParagraph.getText();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ppt.close();
|
||||
}
|
||||
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
InputStream stream = new FileInputStream("test-data/slideshow/testPPT.pptx");
|
||||
InputStream stream = new FileInputStream("test-data/slideshow/SampleShow.pptx");
|
||||
try {
|
||||
handleFile(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void testExtractor() throws Exception {
|
||||
handleExtracting(new File("test-data/slideshow/testPPT.thmx"));
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
package org.apache.poi.stress;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
@ -71,4 +72,10 @@ public class XSSFFileHandler extends SpreadsheetHandler {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void testExtractor() throws Exception {
|
||||
handleExtracting(new File("test-data/spreadsheet/56278.xlsx"));
|
||||
}
|
||||
}
|
@ -16,13 +16,15 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.stress;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
|
||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||
import org.junit.Test;
|
||||
|
||||
public class XWPFFileHandler implements FileHandler {
|
||||
public class XWPFFileHandler extends AbstractFileHandler {
|
||||
@Override
|
||||
public void handleFile(InputStream stream) throws Exception {
|
||||
// ignore password protected files
|
||||
@ -36,12 +38,16 @@ public class XWPFFileHandler implements FileHandler {
|
||||
// a test-case to test this locally without executing the full TestAllFiles
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
InputStream stream = new FileInputStream("test-data/document/footnotes.docx");
|
||||
File file = new File("test-data/document/51921-Word-Crash067.docx");
|
||||
|
||||
InputStream stream = new PushbackInputStream(new FileInputStream(file), 100000);
|
||||
try {
|
||||
handleFile(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
handleExtracting(file);
|
||||
}
|
||||
|
||||
}
|
28
src/java/org/apache/poi/EmptyFileException.java
Normal file
28
src/java/org/apache/poi/EmptyFileException.java
Normal file
@ -0,0 +1,28 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi;
|
||||
|
||||
/**
|
||||
* Exception thrown if an Empty (zero byte) file is supplied
|
||||
*/
|
||||
public class EmptyFileException extends IllegalArgumentException {
|
||||
private static final long serialVersionUID = 1536449292174360166L;
|
||||
|
||||
public EmptyFileException() {
|
||||
super("The supplied file was empty (zero bytes long)");
|
||||
}
|
||||
}
|
@ -16,9 +16,10 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class EncryptedDocumentException extends IllegalStateException
|
||||
{
|
||||
private static final long serialVersionUID = 7276950444540469193L;
|
||||
|
||||
public EncryptedDocumentException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
@ -30,14 +30,11 @@ import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.poifs.filesystem.EntryUtils;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
@ -45,8 +42,6 @@ import org.apache.poi.util.POILogger;
|
||||
* This holds the common functionality for all POI
|
||||
* Document classes.
|
||||
* Currently, this relates to Document Information Properties
|
||||
*
|
||||
* @author Nick Burch
|
||||
*/
|
||||
public abstract class POIDocument {
|
||||
/** Holds metadata on our document */
|
||||
@ -72,20 +67,23 @@ public abstract class POIDocument {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link POIDocument#POIDocument(DirectoryNode)} instead
|
||||
* Constructs from an old-style OPOIFS
|
||||
*/
|
||||
@Deprecated
|
||||
protected POIDocument(DirectoryNode dir, POIFSFileSystem fs) {
|
||||
this.directory = dir;
|
||||
}
|
||||
|
||||
protected POIDocument(POIFSFileSystem fs) {
|
||||
protected POIDocument(OPOIFSFileSystem fs) {
|
||||
this(fs.getRoot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs from an old-style OPOIFS
|
||||
*/
|
||||
protected POIDocument(NPOIFSFileSystem fs) {
|
||||
this(fs.getRoot());
|
||||
}
|
||||
/**
|
||||
* Constructs from the default POIFS
|
||||
*/
|
||||
protected POIDocument(POIFSFileSystem fs) {
|
||||
this(fs.getRoot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the Document Summary Information of the document
|
||||
@ -179,12 +177,13 @@ public abstract class POIDocument {
|
||||
protected PropertySet getPropertySet(String setName, EncryptionInfo encryptionInfo) {
|
||||
DirectoryNode dirNode = directory;
|
||||
|
||||
NPOIFSFileSystem encPoifs = null;
|
||||
if (encryptionInfo != null) {
|
||||
try {
|
||||
InputStream is = encryptionInfo.getDecryptor().getDataStream(directory);
|
||||
POIFSFileSystem poifs = new POIFSFileSystem(is);
|
||||
encPoifs = new NPOIFSFileSystem(is);
|
||||
is.close();
|
||||
dirNode = poifs.getRoot();
|
||||
dirNode = encPoifs.getRoot();
|
||||
} catch (Exception e) {
|
||||
logger.log(POILogger.ERROR, "Error getting encrypted property set with name " + setName, e);
|
||||
return null;
|
||||
@ -208,6 +207,11 @@ public abstract class POIDocument {
|
||||
try {
|
||||
// Create the Property Set
|
||||
PropertySet set = PropertySetFactory.create(dis);
|
||||
// Tidy up if needed
|
||||
if (encPoifs != null) {
|
||||
encPoifs.close();
|
||||
}
|
||||
// Return the properties
|
||||
return set;
|
||||
} catch(IOException ie) {
|
||||
// Must be corrupt or something like that
|
||||
@ -218,26 +222,39 @@ public abstract class POIDocument {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out the updated standard Document Information Properties (HPSF)
|
||||
* into the currently open NPOIFSFileSystem
|
||||
* TODO Implement in-place update
|
||||
*
|
||||
* @throws IOException if an error when writing to the open
|
||||
* {@link NPOIFSFileSystem} occurs
|
||||
* TODO throws exception if open from stream not file
|
||||
*/
|
||||
protected void writeProperties() throws IOException {
|
||||
throw new IllegalStateException("In-place write is not yet supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out the standard Documment Information Properties (HPSF)
|
||||
* Writes out the standard Document Information Properties (HPSF)
|
||||
* @param outFS the POIFSFileSystem to write the properties into
|
||||
*
|
||||
* @throws IOException if an error when writing to the
|
||||
* {@link POIFSFileSystem} occurs
|
||||
* {@link NPOIFSFileSystem} occurs
|
||||
*/
|
||||
protected void writeProperties(POIFSFileSystem outFS) throws IOException {
|
||||
protected void writeProperties(NPOIFSFileSystem outFS) throws IOException {
|
||||
writeProperties(outFS, null);
|
||||
}
|
||||
/**
|
||||
* Writes out the standard Documment Information Properties (HPSF)
|
||||
* @param outFS the POIFSFileSystem to write the properties into
|
||||
* Writes out the standard Document Information Properties (HPSF)
|
||||
* @param outFS the NPOIFSFileSystem to write the properties into
|
||||
* @param writtenEntries a list of POIFS entries to add the property names too
|
||||
*
|
||||
* @throws IOException if an error when writing to the
|
||||
* {@link POIFSFileSystem} occurs
|
||||
* {@link NPOIFSFileSystem} occurs
|
||||
*/
|
||||
protected void writeProperties(POIFSFileSystem outFS, List<String> writtenEntries) throws IOException {
|
||||
protected void writeProperties(NPOIFSFileSystem outFS, List<String> writtenEntries) throws IOException {
|
||||
SummaryInformation si = getSummaryInformation();
|
||||
if (si != null) {
|
||||
writePropertySet(SummaryInformation.DEFAULT_STREAM_NAME, si, outFS);
|
||||
@ -258,12 +275,12 @@ public abstract class POIDocument {
|
||||
* Writes out a given ProperySet
|
||||
* @param name the (POIFS Level) name of the property to write
|
||||
* @param set the PropertySet to write out
|
||||
* @param outFS the POIFSFileSystem to write the property into
|
||||
* @param outFS the NPOIFSFileSystem to write the property into
|
||||
*
|
||||
* @throws IOException if an error when writing to the
|
||||
* {@link POIFSFileSystem} occurs
|
||||
* {@link NPOIFSFileSystem} occurs
|
||||
*/
|
||||
protected void writePropertySet(String name, PropertySet set, POIFSFileSystem outFS) throws IOException {
|
||||
protected void writePropertySet(String name, PropertySet set, NPOIFSFileSystem outFS) throws IOException {
|
||||
try {
|
||||
MutablePropertySet mSet = new MutablePropertySet(set);
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
@ -288,55 +305,4 @@ public abstract class POIDocument {
|
||||
* @throws IOException thrown on errors writing to the stream
|
||||
*/
|
||||
public abstract void write(OutputStream out) throws IOException;
|
||||
|
||||
/**
|
||||
* Copies nodes from one POIFS to the other minus the excepts
|
||||
* @param source is the source POIFS to copy from
|
||||
* @param target is the target POIFS to copy to
|
||||
* @param excepts is a list of Strings specifying what nodes NOT to copy
|
||||
*
|
||||
* @throws IOException thrown on errors writing to the target file system.
|
||||
*
|
||||
* @deprecated Use {@link EntryUtils#copyNodes(DirectoryEntry, DirectoryEntry, List)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
protected void copyNodes( POIFSFileSystem source, POIFSFileSystem target,
|
||||
List<String> excepts ) throws IOException {
|
||||
EntryUtils.copyNodes( source, target, excepts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies nodes from one POIFS to the other minus the excepts
|
||||
* @param sourceRoot is the source POIFS to copy from
|
||||
* @param targetRoot is the target POIFS to copy to
|
||||
* @param excepts is a list of Strings specifying what nodes NOT to copy
|
||||
*
|
||||
* @throws IOException thrown on errors writing to the target directory node.
|
||||
*
|
||||
* @deprecated Use {@link EntryUtils#copyNodes(DirectoryEntry, DirectoryEntry, List)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
protected void copyNodes( DirectoryNode sourceRoot,
|
||||
DirectoryNode targetRoot, List<String> excepts ) throws IOException
|
||||
{
|
||||
EntryUtils.copyNodes( sourceRoot, targetRoot, excepts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies an Entry into a target POIFS directory, recursively
|
||||
*
|
||||
* @param entry the entry to copy from
|
||||
* @param target the entry to write to
|
||||
*
|
||||
* @throws IOException thrown on errors writing to the target directory entry.
|
||||
*
|
||||
* @deprecated Use {@link EntryUtils#copyNodeRecursively(Entry, DirectoryEntry)} instead
|
||||
*/
|
||||
@Internal
|
||||
@Deprecated
|
||||
protected void copyNodeRecursively( Entry entry, DirectoryEntry target )
|
||||
throws IOException
|
||||
{
|
||||
EntryUtils.copyNodeRecursively( entry, target );
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
/**
|
||||
* Common Parent for OLE2 based Text Extractors
|
||||
@ -34,15 +33,27 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
* @see org.apache.poi.hwpf.extractor.WordExtractor
|
||||
*/
|
||||
public abstract class POIOLE2TextExtractor extends POITextExtractor {
|
||||
/** The POIDocument that's open */
|
||||
protected POIDocument document;
|
||||
|
||||
/**
|
||||
* Creates a new text extractor for the given document
|
||||
*
|
||||
* @param document The POIDocument to use in this extractor.
|
||||
*/
|
||||
public POIOLE2TextExtractor(POIDocument document) {
|
||||
super(document);
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new text extractor, using the same
|
||||
* document as another text extractor. Normally
|
||||
* only used by properties extractors.
|
||||
*/
|
||||
protected POIOLE2TextExtractor(POIOLE2TextExtractor otherExtractor) {
|
||||
this.document = otherExtractor.document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the document information metadata for the document
|
||||
*
|
||||
@ -81,17 +92,4 @@ public abstract class POIOLE2TextExtractor extends POITextExtractor {
|
||||
{
|
||||
return document.directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying POIFS FileSystem of this document.
|
||||
*
|
||||
* @return the POIFSFileSystem that is associated with the POIDocument of this extractor.
|
||||
*
|
||||
* @deprecated Use {@link #getRoot()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public POIFSFileSystem getFileSystem()
|
||||
{
|
||||
return document.directory.getFileSystem();
|
||||
}
|
||||
}
|
||||
|
@ -31,24 +31,6 @@ import java.io.IOException;
|
||||
* @see org.apache.poi.hwpf.extractor.WordExtractor
|
||||
*/
|
||||
public abstract class POITextExtractor implements Closeable {
|
||||
/** The POIDocument that's open */
|
||||
protected POIDocument document;
|
||||
|
||||
/**
|
||||
* Creates a new text extractor for the given document
|
||||
*/
|
||||
public POITextExtractor(POIDocument document) {
|
||||
this.document = document;
|
||||
}
|
||||
/**
|
||||
* Creates a new text extractor, using the same
|
||||
* document as another text extractor. Normally
|
||||
* only used by properties extractors.
|
||||
*/
|
||||
protected POITextExtractor(POITextExtractor otherExtractor) {
|
||||
this.document = otherExtractor.document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the text from the document.
|
||||
* How cells, paragraphs etc are separated in the text
|
||||
|
@ -82,6 +82,13 @@ public final class EscherPropertyFactory {
|
||||
pos += ((EscherArrayProperty)p).setArrayData(data, pos);
|
||||
} else {
|
||||
byte[] complexData = ((EscherComplexProperty)p).getComplexData();
|
||||
|
||||
int leftover = data.length-pos;
|
||||
if(leftover < complexData.length){
|
||||
throw new IllegalStateException("Could not read complex escher property, lenght was " + complexData.length + ", but had only " +
|
||||
leftover + " bytes left");
|
||||
}
|
||||
|
||||
System.arraycopy(data, pos, complexData, 0, complexData.length);
|
||||
pos += complexData.length;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||
import org.apache.poi.POIDocument;
|
||||
import org.apache.poi.poifs.filesystem.EntryUtils;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
/**
|
||||
@ -36,6 +37,9 @@ public class HPSFPropertiesOnlyDocument extends POIDocument {
|
||||
public HPSFPropertiesOnlyDocument(NPOIFSFileSystem fs) {
|
||||
super(fs.getRoot());
|
||||
}
|
||||
public HPSFPropertiesOnlyDocument(OPOIFSFileSystem fs) {
|
||||
super(fs);
|
||||
}
|
||||
public HPSFPropertiesOnlyDocument(POIFSFileSystem fs) {
|
||||
super(fs);
|
||||
}
|
||||
@ -44,7 +48,7 @@ public class HPSFPropertiesOnlyDocument extends POIDocument {
|
||||
* Write out, with any properties changes, but nothing else
|
||||
*/
|
||||
public void write(OutputStream out) throws IOException {
|
||||
POIFSFileSystem fs = new POIFSFileSystem();
|
||||
NPOIFSFileSystem fs = new NPOIFSFileSystem();
|
||||
|
||||
// For tracking what we've written out, so far
|
||||
List<String> excepts = new ArrayList<String>(1);
|
||||
|
@ -285,7 +285,7 @@ public class Section
|
||||
/*
|
||||
* Extract the dictionary (if available).
|
||||
*/
|
||||
dictionary = (Map) getProperty(0);
|
||||
dictionary = (Map<Long,String>) getProperty(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.poi.POIDocument;
|
||||
import org.apache.poi.POIOLE2TextExtractor;
|
||||
import org.apache.poi.POITextExtractor;
|
||||
import org.apache.poi.hpsf.CustomProperties;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
@ -39,10 +40,10 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
* build in and custom, returning them in
|
||||
* textual form.
|
||||
*/
|
||||
public class HPSFPropertiesExtractor extends POITextExtractor {
|
||||
public class HPSFPropertiesExtractor extends POIOLE2TextExtractor {
|
||||
private Closeable toClose;
|
||||
|
||||
public HPSFPropertiesExtractor(POITextExtractor mainExtractor) {
|
||||
public HPSFPropertiesExtractor(POIOLE2TextExtractor mainExtractor) {
|
||||
super(mainExtractor);
|
||||
}
|
||||
public HPSFPropertiesExtractor(POIDocument doc) {
|
||||
@ -57,6 +58,10 @@ public class HPSFPropertiesExtractor extends POITextExtractor {
|
||||
}
|
||||
|
||||
public String getDocumentSummaryInformationText() {
|
||||
if(document == null) { // event based extractor does not have a document
|
||||
return "";
|
||||
}
|
||||
|
||||
DocumentSummaryInformation dsi = document.getDocumentSummaryInformation();
|
||||
StringBuffer text = new StringBuffer();
|
||||
|
||||
@ -78,6 +83,10 @@ public class HPSFPropertiesExtractor extends POITextExtractor {
|
||||
return text.toString();
|
||||
}
|
||||
public String getSummaryInformationText() {
|
||||
if(document == null) { // event based extractor does not have a document
|
||||
return "";
|
||||
}
|
||||
|
||||
SummaryInformation si = document.getSummaryInformation();
|
||||
|
||||
// Just normal properties
|
||||
|
@ -34,7 +34,7 @@ import org.apache.poi.hssf.record.DrawingGroupRecord;
|
||||
import org.apache.poi.hssf.record.EscherAggregate;
|
||||
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
|
||||
/**
|
||||
* Utility for representing drawings contained in a binary Excel file as a XML tree
|
||||
@ -138,7 +138,7 @@ public class BiffDrawingToXml {
|
||||
}
|
||||
|
||||
public static void writeToFile(OutputStream fos, InputStream xlsWorkbook, boolean excludeWorkbookRecords, String[] params) throws IOException {
|
||||
POIFSFileSystem fs = new POIFSFileSystem(xlsWorkbook);
|
||||
NPOIFSFileSystem fs = new NPOIFSFileSystem(xlsWorkbook);
|
||||
HSSFWorkbook workbook = new HSSFWorkbook(fs);
|
||||
InternalWorkbook internalWorkbook = getInternalWorkbook(workbook);
|
||||
DrawingGroupRecord r = (DrawingGroupRecord) internalWorkbook.findFirstRecordBySid(DrawingGroupRecord.sid);
|
||||
|
@ -17,13 +17,63 @@
|
||||
|
||||
package org.apache.poi.hssf.dev;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.record.*;
|
||||
import org.apache.poi.hssf.record.RecordInputStream.LeftoverDataException;
|
||||
import org.apache.poi.hssf.record.chart.*;
|
||||
import org.apache.poi.hssf.record.chart.AreaFormatRecord;
|
||||
import org.apache.poi.hssf.record.chart.AreaRecord;
|
||||
import org.apache.poi.hssf.record.chart.AxisLineFormatRecord;
|
||||
import org.apache.poi.hssf.record.chart.AxisOptionsRecord;
|
||||
import org.apache.poi.hssf.record.chart.AxisParentRecord;
|
||||
import org.apache.poi.hssf.record.chart.AxisRecord;
|
||||
import org.apache.poi.hssf.record.chart.AxisUsedRecord;
|
||||
import org.apache.poi.hssf.record.chart.BarRecord;
|
||||
import org.apache.poi.hssf.record.chart.BeginRecord;
|
||||
import org.apache.poi.hssf.record.chart.CatLabRecord;
|
||||
import org.apache.poi.hssf.record.chart.CategorySeriesAxisRecord;
|
||||
import org.apache.poi.hssf.record.chart.ChartEndBlockRecord;
|
||||
import org.apache.poi.hssf.record.chart.ChartEndObjectRecord;
|
||||
import org.apache.poi.hssf.record.chart.ChartFRTInfoRecord;
|
||||
import org.apache.poi.hssf.record.chart.ChartFormatRecord;
|
||||
import org.apache.poi.hssf.record.chart.ChartRecord;
|
||||
import org.apache.poi.hssf.record.chart.ChartStartBlockRecord;
|
||||
import org.apache.poi.hssf.record.chart.ChartStartObjectRecord;
|
||||
import org.apache.poi.hssf.record.chart.DatRecord;
|
||||
import org.apache.poi.hssf.record.chart.DataFormatRecord;
|
||||
import org.apache.poi.hssf.record.chart.DefaultDataLabelTextPropertiesRecord;
|
||||
import org.apache.poi.hssf.record.chart.EndRecord;
|
||||
import org.apache.poi.hssf.record.chart.FontBasisRecord;
|
||||
import org.apache.poi.hssf.record.chart.FontIndexRecord;
|
||||
import org.apache.poi.hssf.record.chart.FrameRecord;
|
||||
import org.apache.poi.hssf.record.chart.LegendRecord;
|
||||
import org.apache.poi.hssf.record.chart.LineFormatRecord;
|
||||
import org.apache.poi.hssf.record.chart.LinkedDataRecord;
|
||||
import org.apache.poi.hssf.record.chart.ObjectLinkRecord;
|
||||
import org.apache.poi.hssf.record.chart.PlotAreaRecord;
|
||||
import org.apache.poi.hssf.record.chart.PlotGrowthRecord;
|
||||
import org.apache.poi.hssf.record.chart.SeriesIndexRecord;
|
||||
import org.apache.poi.hssf.record.chart.SeriesListRecord;
|
||||
import org.apache.poi.hssf.record.chart.SeriesRecord;
|
||||
import org.apache.poi.hssf.record.chart.SeriesTextRecord;
|
||||
import org.apache.poi.hssf.record.chart.SeriesToChartGroupRecord;
|
||||
import org.apache.poi.hssf.record.chart.SheetPropertiesRecord;
|
||||
import org.apache.poi.hssf.record.chart.TextRecord;
|
||||
import org.apache.poi.hssf.record.chart.TickRecord;
|
||||
import org.apache.poi.hssf.record.chart.UnitsRecord;
|
||||
import org.apache.poi.hssf.record.chart.ValueRangeRecord;
|
||||
import org.apache.poi.hssf.record.pivottable.DataItemRecord;
|
||||
import org.apache.poi.hssf.record.pivottable.ExtendedPivotTableViewFieldsRecord;
|
||||
import org.apache.poi.hssf.record.pivottable.PageItemRecord;
|
||||
@ -32,330 +82,330 @@ import org.apache.poi.hssf.record.pivottable.ViewDefinitionRecord;
|
||||
import org.apache.poi.hssf.record.pivottable.ViewFieldsRecord;
|
||||
import org.apache.poi.hssf.record.pivottable.ViewSourceRecord;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Utillity for reading in BIFF8 records and displaying data from them.
|
||||
*
|
||||
*@author Andrew C. Oliver (acoliver at apache dot org)
|
||||
*@author Glen Stampoultzis (glens at apache.org)
|
||||
*@see #main
|
||||
* @see #main
|
||||
*/
|
||||
public final class BiffViewer {
|
||||
static final char[] NEW_LINE_CHARS = System.getProperty("line.separator").toCharArray();
|
||||
static final char[] NEW_LINE_CHARS = System.getProperty("line.separator").toCharArray();
|
||||
|
||||
private BiffViewer() {
|
||||
// no instances of this class
|
||||
}
|
||||
// no instances of this class
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of records from an input stream
|
||||
*
|
||||
*@param is the InputStream from which the records will be obtained
|
||||
*@return an array of Records created from the InputStream
|
||||
*@exception RecordFormatException on error processing the InputStream
|
||||
*/
|
||||
public static Record[] createRecords(InputStream is, PrintStream ps, BiffRecordListener recListener, boolean dumpInterpretedRecords)
|
||||
throws RecordFormatException {
|
||||
List<Record> temp = new ArrayList<Record>();
|
||||
/**
|
||||
* Create an array of records from an input stream
|
||||
*
|
||||
*@param is the InputStream from which the records will be obtained
|
||||
*@return an array of Records created from the InputStream
|
||||
*@exception RecordFormatException on error processing the InputStream
|
||||
*/
|
||||
public static Record[] createRecords(InputStream is, PrintStream ps, BiffRecordListener recListener, boolean dumpInterpretedRecords)
|
||||
throws RecordFormatException {
|
||||
List<Record> temp = new ArrayList<Record>();
|
||||
|
||||
RecordInputStream recStream = new RecordInputStream(is);
|
||||
while (true) {
|
||||
boolean hasNext;
|
||||
try {
|
||||
hasNext = recStream.hasNextRecord();
|
||||
} catch (LeftoverDataException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Discarding " + recStream.remaining() + " bytes and continuing");
|
||||
recStream.readRemainder();
|
||||
hasNext = recStream.hasNextRecord();
|
||||
}
|
||||
if (!hasNext) {
|
||||
break;
|
||||
}
|
||||
recStream.nextRecord();
|
||||
if (recStream.getSid() == 0) {
|
||||
continue;
|
||||
}
|
||||
Record record;
|
||||
if (dumpInterpretedRecords) {
|
||||
record = createRecord (recStream);
|
||||
if (record.getSid() == ContinueRecord.sid) {
|
||||
continue;
|
||||
}
|
||||
temp.add(record);
|
||||
RecordInputStream recStream = new RecordInputStream(is);
|
||||
while (true) {
|
||||
boolean hasNext;
|
||||
try {
|
||||
hasNext = recStream.hasNextRecord();
|
||||
} catch (LeftoverDataException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Discarding " + recStream.remaining() + " bytes and continuing");
|
||||
recStream.readRemainder();
|
||||
hasNext = recStream.hasNextRecord();
|
||||
}
|
||||
if (!hasNext) {
|
||||
break;
|
||||
}
|
||||
recStream.nextRecord();
|
||||
if (recStream.getSid() == 0) {
|
||||
continue;
|
||||
}
|
||||
Record record;
|
||||
if (dumpInterpretedRecords) {
|
||||
record = createRecord (recStream);
|
||||
if (record.getSid() == ContinueRecord.sid) {
|
||||
continue;
|
||||
}
|
||||
temp.add(record);
|
||||
|
||||
if (dumpInterpretedRecords) {
|
||||
for (String header : recListener.getRecentHeaders()) {
|
||||
ps.println(header);
|
||||
}
|
||||
ps.print(record.toString());
|
||||
}
|
||||
} else {
|
||||
recStream.readRemainder();
|
||||
}
|
||||
ps.println();
|
||||
}
|
||||
Record[] result = new Record[temp.size()];
|
||||
temp.toArray(result);
|
||||
return result;
|
||||
}
|
||||
if (dumpInterpretedRecords) {
|
||||
for (String header : recListener.getRecentHeaders()) {
|
||||
ps.println(header);
|
||||
}
|
||||
ps.print(record.toString());
|
||||
}
|
||||
} else {
|
||||
recStream.readRemainder();
|
||||
}
|
||||
ps.println();
|
||||
}
|
||||
Record[] result = new Record[temp.size()];
|
||||
temp.toArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Essentially a duplicate of RecordFactory. Kept separate as not to screw
|
||||
* up non-debug operations.
|
||||
*
|
||||
*/
|
||||
private static Record createRecord(RecordInputStream in) {
|
||||
switch (in.getSid()) {
|
||||
case AreaFormatRecord.sid: return new AreaFormatRecord(in);
|
||||
case AreaRecord.sid: return new AreaRecord(in);
|
||||
case ArrayRecord.sid: return new ArrayRecord(in);
|
||||
case AxisLineFormatRecord.sid: return new AxisLineFormatRecord(in);
|
||||
case AxisOptionsRecord.sid: return new AxisOptionsRecord(in);
|
||||
case AxisParentRecord.sid: return new AxisParentRecord(in);
|
||||
case AxisRecord.sid: return new AxisRecord(in);
|
||||
case AxisUsedRecord.sid: return new AxisUsedRecord(in);
|
||||
case AutoFilterInfoRecord.sid: return new AutoFilterInfoRecord(in);
|
||||
case BOFRecord.sid: return new BOFRecord(in);
|
||||
case BackupRecord.sid: return new BackupRecord(in);
|
||||
case BarRecord.sid: return new BarRecord(in);
|
||||
case BeginRecord.sid: return new BeginRecord(in);
|
||||
case BlankRecord.sid: return new BlankRecord(in);
|
||||
case BookBoolRecord.sid: return new BookBoolRecord(in);
|
||||
case BoolErrRecord.sid: return new BoolErrRecord(in);
|
||||
case BottomMarginRecord.sid: return new BottomMarginRecord(in);
|
||||
case BoundSheetRecord.sid: return new BoundSheetRecord(in);
|
||||
case CFHeaderRecord.sid: return new CFHeaderRecord(in);
|
||||
case CFRuleRecord.sid: return new CFRuleRecord(in);
|
||||
case CalcCountRecord.sid: return new CalcCountRecord(in);
|
||||
case CalcModeRecord.sid: return new CalcModeRecord(in);
|
||||
case CategorySeriesAxisRecord.sid: return new CategorySeriesAxisRecord(in);
|
||||
case ChartFormatRecord.sid: return new ChartFormatRecord(in);
|
||||
case ChartRecord.sid: return new ChartRecord(in);
|
||||
case CodepageRecord.sid: return new CodepageRecord(in);
|
||||
case ColumnInfoRecord.sid: return new ColumnInfoRecord(in);
|
||||
case ContinueRecord.sid: return new ContinueRecord(in);
|
||||
case CountryRecord.sid: return new CountryRecord(in);
|
||||
case DBCellRecord.sid: return new DBCellRecord(in);
|
||||
case DSFRecord.sid: return new DSFRecord(in);
|
||||
case DatRecord.sid: return new DatRecord(in);
|
||||
case DataFormatRecord.sid: return new DataFormatRecord(in);
|
||||
case DateWindow1904Record.sid: return new DateWindow1904Record(in);
|
||||
case DConRefRecord.sid: return new DConRefRecord(in);
|
||||
case DefaultColWidthRecord.sid:return new DefaultColWidthRecord(in);
|
||||
case DefaultDataLabelTextPropertiesRecord.sid: return new DefaultDataLabelTextPropertiesRecord(in);
|
||||
case DefaultRowHeightRecord.sid: return new DefaultRowHeightRecord(in);
|
||||
case DeltaRecord.sid: return new DeltaRecord(in);
|
||||
case DimensionsRecord.sid: return new DimensionsRecord(in);
|
||||
case DrawingGroupRecord.sid: return new DrawingGroupRecord(in);
|
||||
case DrawingRecordForBiffViewer.sid: return new DrawingRecordForBiffViewer(in);
|
||||
case DrawingSelectionRecord.sid: return new DrawingSelectionRecord(in);
|
||||
case DVRecord.sid: return new DVRecord(in);
|
||||
case DVALRecord.sid: return new DVALRecord(in);
|
||||
case EOFRecord.sid: return new EOFRecord(in);
|
||||
case EndRecord.sid: return new EndRecord(in);
|
||||
case ExtSSTRecord.sid: return new ExtSSTRecord(in);
|
||||
case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
|
||||
case ExternSheetRecord.sid: return new ExternSheetRecord(in);
|
||||
case ExternalNameRecord.sid: return new ExternalNameRecord(in);
|
||||
case FeatRecord.sid: return new FeatRecord(in);
|
||||
case FeatHdrRecord.sid: return new FeatHdrRecord(in);
|
||||
case FilePassRecord.sid: return new FilePassRecord(in);
|
||||
case FileSharingRecord.sid: return new FileSharingRecord(in);
|
||||
case FnGroupCountRecord.sid: return new FnGroupCountRecord(in);
|
||||
case FontBasisRecord.sid: return new FontBasisRecord(in);
|
||||
case FontIndexRecord.sid: return new FontIndexRecord(in);
|
||||
case FontRecord.sid: return new FontRecord(in);
|
||||
case FooterRecord.sid: return new FooterRecord(in);
|
||||
case FormatRecord.sid: return new FormatRecord(in);
|
||||
case FormulaRecord.sid: return new FormulaRecord(in);
|
||||
case FrameRecord.sid: return new FrameRecord(in);
|
||||
case GridsetRecord.sid: return new GridsetRecord(in);
|
||||
case GutsRecord.sid: return new GutsRecord(in);
|
||||
case HCenterRecord.sid: return new HCenterRecord(in);
|
||||
case HeaderRecord.sid: return new HeaderRecord(in);
|
||||
case HideObjRecord.sid: return new HideObjRecord(in);
|
||||
case HorizontalPageBreakRecord.sid: return new HorizontalPageBreakRecord(in);
|
||||
case HyperlinkRecord.sid: return new HyperlinkRecord(in);
|
||||
case IndexRecord.sid: return new IndexRecord(in);
|
||||
case InterfaceEndRecord.sid: return InterfaceEndRecord.create(in);
|
||||
case InterfaceHdrRecord.sid: return new InterfaceHdrRecord(in);
|
||||
case IterationRecord.sid: return new IterationRecord(in);
|
||||
case LabelRecord.sid: return new LabelRecord(in);
|
||||
case LabelSSTRecord.sid: return new LabelSSTRecord(in);
|
||||
case LeftMarginRecord.sid: return new LeftMarginRecord(in);
|
||||
case LegendRecord.sid: return new LegendRecord(in);
|
||||
case LineFormatRecord.sid: return new LineFormatRecord(in);
|
||||
case LinkedDataRecord.sid: return new LinkedDataRecord(in);
|
||||
case MMSRecord.sid: return new MMSRecord(in);
|
||||
case MergeCellsRecord.sid: return new MergeCellsRecord(in);
|
||||
case MulBlankRecord.sid: return new MulBlankRecord(in);
|
||||
case MulRKRecord.sid: return new MulRKRecord(in);
|
||||
case NameRecord.sid: return new NameRecord(in);
|
||||
case NameCommentRecord.sid: return new NameCommentRecord(in);
|
||||
case NoteRecord.sid: return new NoteRecord(in);
|
||||
case NumberRecord.sid: return new NumberRecord(in);
|
||||
case ObjRecord.sid: return new ObjRecord(in);
|
||||
case ObjectLinkRecord.sid: return new ObjectLinkRecord(in);
|
||||
case PaletteRecord.sid: return new PaletteRecord(in);
|
||||
case PaneRecord.sid: return new PaneRecord(in);
|
||||
case PasswordRecord.sid: return new PasswordRecord(in);
|
||||
case PasswordRev4Record.sid: return new PasswordRev4Record(in);
|
||||
case PlotAreaRecord.sid: return new PlotAreaRecord(in);
|
||||
case PlotGrowthRecord.sid: return new PlotGrowthRecord(in);
|
||||
case PrecisionRecord.sid: return new PrecisionRecord(in);
|
||||
case PrintGridlinesRecord.sid: return new PrintGridlinesRecord(in);
|
||||
case PrintHeadersRecord.sid: return new PrintHeadersRecord(in);
|
||||
case PrintSetupRecord.sid: return new PrintSetupRecord(in);
|
||||
case ProtectRecord.sid: return new ProtectRecord(in);
|
||||
case ProtectionRev4Record.sid: return new ProtectionRev4Record(in);
|
||||
case RKRecord.sid: return new RKRecord(in);
|
||||
case RecalcIdRecord.sid: return new RecalcIdRecord(in);
|
||||
case RefModeRecord.sid: return new RefModeRecord(in);
|
||||
case RefreshAllRecord.sid: return new RefreshAllRecord(in);
|
||||
case RightMarginRecord.sid: return new RightMarginRecord(in);
|
||||
case RowRecord.sid: return new RowRecord(in);
|
||||
case SCLRecord.sid: return new SCLRecord(in);
|
||||
case SSTRecord.sid: return new SSTRecord(in);
|
||||
case SaveRecalcRecord.sid: return new SaveRecalcRecord(in);
|
||||
case SelectionRecord.sid: return new SelectionRecord(in);
|
||||
case SeriesIndexRecord.sid: return new SeriesIndexRecord(in);
|
||||
case SeriesListRecord.sid: return new SeriesListRecord(in);
|
||||
case SeriesRecord.sid: return new SeriesRecord(in);
|
||||
case SeriesTextRecord.sid: return new SeriesTextRecord(in);
|
||||
case SeriesToChartGroupRecord.sid: return new SeriesToChartGroupRecord(in);
|
||||
case SharedFormulaRecord.sid: return new SharedFormulaRecord(in);
|
||||
case SheetPropertiesRecord.sid:return new SheetPropertiesRecord(in);
|
||||
case StringRecord.sid: return new StringRecord(in);
|
||||
case StyleRecord.sid: return new StyleRecord(in);
|
||||
case SupBookRecord.sid: return new SupBookRecord(in);
|
||||
case TabIdRecord.sid: return new TabIdRecord(in);
|
||||
case TableStylesRecord.sid: return new TableStylesRecord(in);
|
||||
case TableRecord.sid: return new TableRecord(in);
|
||||
case TextObjectRecord.sid: return new TextObjectRecord(in);
|
||||
case TextRecord.sid: return new TextRecord(in);
|
||||
case TickRecord.sid: return new TickRecord(in);
|
||||
case TopMarginRecord.sid: return new TopMarginRecord(in);
|
||||
case UncalcedRecord.sid: return new UncalcedRecord(in);
|
||||
case UnitsRecord.sid: return new UnitsRecord(in);
|
||||
case UseSelFSRecord.sid: return new UseSelFSRecord(in);
|
||||
case VCenterRecord.sid: return new VCenterRecord(in);
|
||||
case ValueRangeRecord.sid: return new ValueRangeRecord(in);
|
||||
case VerticalPageBreakRecord.sid: return new VerticalPageBreakRecord(in);
|
||||
case WSBoolRecord.sid: return new WSBoolRecord(in);
|
||||
case WindowOneRecord.sid: return new WindowOneRecord(in);
|
||||
case WindowProtectRecord.sid: return new WindowProtectRecord(in);
|
||||
case WindowTwoRecord.sid: return new WindowTwoRecord(in);
|
||||
case WriteAccessRecord.sid: return new WriteAccessRecord(in);
|
||||
case WriteProtectRecord.sid: return new WriteProtectRecord(in);
|
||||
/**
|
||||
* Essentially a duplicate of RecordFactory. Kept separate as not to screw
|
||||
* up non-debug operations.
|
||||
*
|
||||
*/
|
||||
private static Record createRecord(RecordInputStream in) {
|
||||
switch (in.getSid()) {
|
||||
case AreaFormatRecord.sid: return new AreaFormatRecord(in);
|
||||
case AreaRecord.sid: return new AreaRecord(in);
|
||||
case ArrayRecord.sid: return new ArrayRecord(in);
|
||||
case AxisLineFormatRecord.sid: return new AxisLineFormatRecord(in);
|
||||
case AxisOptionsRecord.sid: return new AxisOptionsRecord(in);
|
||||
case AxisParentRecord.sid: return new AxisParentRecord(in);
|
||||
case AxisRecord.sid: return new AxisRecord(in);
|
||||
case AxisUsedRecord.sid: return new AxisUsedRecord(in);
|
||||
case AutoFilterInfoRecord.sid: return new AutoFilterInfoRecord(in);
|
||||
case BOFRecord.sid: return new BOFRecord(in);
|
||||
case BackupRecord.sid: return new BackupRecord(in);
|
||||
case BarRecord.sid: return new BarRecord(in);
|
||||
case BeginRecord.sid: return new BeginRecord(in);
|
||||
case BlankRecord.sid: return new BlankRecord(in);
|
||||
case BookBoolRecord.sid: return new BookBoolRecord(in);
|
||||
case BoolErrRecord.sid: return new BoolErrRecord(in);
|
||||
case BottomMarginRecord.sid: return new BottomMarginRecord(in);
|
||||
case BoundSheetRecord.sid: return new BoundSheetRecord(in);
|
||||
case CFHeaderRecord.sid: return new CFHeaderRecord(in);
|
||||
case CFHeader12Record.sid: return new CFHeader12Record(in);
|
||||
case CFRuleRecord.sid: return new CFRuleRecord(in);
|
||||
case CFRule12Record.sid: return new CFRule12Record(in);
|
||||
// TODO Add CF Ex, and remove from UnknownRecord
|
||||
case CalcCountRecord.sid: return new CalcCountRecord(in);
|
||||
case CalcModeRecord.sid: return new CalcModeRecord(in);
|
||||
case CategorySeriesAxisRecord.sid:return new CategorySeriesAxisRecord(in);
|
||||
case ChartFormatRecord.sid: return new ChartFormatRecord(in);
|
||||
case ChartRecord.sid: return new ChartRecord(in);
|
||||
case CodepageRecord.sid: return new CodepageRecord(in);
|
||||
case ColumnInfoRecord.sid: return new ColumnInfoRecord(in);
|
||||
case ContinueRecord.sid: return new ContinueRecord(in);
|
||||
case CountryRecord.sid: return new CountryRecord(in);
|
||||
case DBCellRecord.sid: return new DBCellRecord(in);
|
||||
case DSFRecord.sid: return new DSFRecord(in);
|
||||
case DatRecord.sid: return new DatRecord(in);
|
||||
case DataFormatRecord.sid: return new DataFormatRecord(in);
|
||||
case DateWindow1904Record.sid: return new DateWindow1904Record(in);
|
||||
case DConRefRecord.sid: return new DConRefRecord(in);
|
||||
case DefaultColWidthRecord.sid: return new DefaultColWidthRecord(in);
|
||||
case DefaultDataLabelTextPropertiesRecord.sid: return new DefaultDataLabelTextPropertiesRecord(in);
|
||||
case DefaultRowHeightRecord.sid: return new DefaultRowHeightRecord(in);
|
||||
case DeltaRecord.sid: return new DeltaRecord(in);
|
||||
case DimensionsRecord.sid: return new DimensionsRecord(in);
|
||||
case DrawingGroupRecord.sid: return new DrawingGroupRecord(in);
|
||||
case DrawingRecordForBiffViewer.sid: return new DrawingRecordForBiffViewer(in);
|
||||
case DrawingSelectionRecord.sid: return new DrawingSelectionRecord(in);
|
||||
case DVRecord.sid: return new DVRecord(in);
|
||||
case DVALRecord.sid: return new DVALRecord(in);
|
||||
case EOFRecord.sid: return new EOFRecord(in);
|
||||
case EndRecord.sid: return new EndRecord(in);
|
||||
case ExtSSTRecord.sid: return new ExtSSTRecord(in);
|
||||
case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
|
||||
case ExternSheetRecord.sid: return new ExternSheetRecord(in);
|
||||
case ExternalNameRecord.sid: return new ExternalNameRecord(in);
|
||||
case FeatRecord.sid: return new FeatRecord(in);
|
||||
case FeatHdrRecord.sid: return new FeatHdrRecord(in);
|
||||
case FilePassRecord.sid: return new FilePassRecord(in);
|
||||
case FileSharingRecord.sid: return new FileSharingRecord(in);
|
||||
case FnGroupCountRecord.sid: return new FnGroupCountRecord(in);
|
||||
case FontBasisRecord.sid: return new FontBasisRecord(in);
|
||||
case FontIndexRecord.sid: return new FontIndexRecord(in);
|
||||
case FontRecord.sid: return new FontRecord(in);
|
||||
case FooterRecord.sid: return new FooterRecord(in);
|
||||
case FormatRecord.sid: return new FormatRecord(in);
|
||||
case FormulaRecord.sid: return new FormulaRecord(in);
|
||||
case FrameRecord.sid: return new FrameRecord(in);
|
||||
case GridsetRecord.sid: return new GridsetRecord(in);
|
||||
case GutsRecord.sid: return new GutsRecord(in);
|
||||
case HCenterRecord.sid: return new HCenterRecord(in);
|
||||
case HeaderRecord.sid: return new HeaderRecord(in);
|
||||
case HideObjRecord.sid: return new HideObjRecord(in);
|
||||
case HorizontalPageBreakRecord.sid: return new HorizontalPageBreakRecord(in);
|
||||
case HyperlinkRecord.sid: return new HyperlinkRecord(in);
|
||||
case IndexRecord.sid: return new IndexRecord(in);
|
||||
case InterfaceEndRecord.sid: return InterfaceEndRecord.create(in);
|
||||
case InterfaceHdrRecord.sid: return new InterfaceHdrRecord(in);
|
||||
case IterationRecord.sid: return new IterationRecord(in);
|
||||
case LabelRecord.sid: return new LabelRecord(in);
|
||||
case LabelSSTRecord.sid: return new LabelSSTRecord(in);
|
||||
case LeftMarginRecord.sid: return new LeftMarginRecord(in);
|
||||
case LegendRecord.sid: return new LegendRecord(in);
|
||||
case LineFormatRecord.sid: return new LineFormatRecord(in);
|
||||
case LinkedDataRecord.sid: return new LinkedDataRecord(in);
|
||||
case MMSRecord.sid: return new MMSRecord(in);
|
||||
case MergeCellsRecord.sid: return new MergeCellsRecord(in);
|
||||
case MulBlankRecord.sid: return new MulBlankRecord(in);
|
||||
case MulRKRecord.sid: return new MulRKRecord(in);
|
||||
case NameRecord.sid: return new NameRecord(in);
|
||||
case NameCommentRecord.sid: return new NameCommentRecord(in);
|
||||
case NoteRecord.sid: return new NoteRecord(in);
|
||||
case NumberRecord.sid: return new NumberRecord(in);
|
||||
case ObjRecord.sid: return new ObjRecord(in);
|
||||
case ObjectLinkRecord.sid: return new ObjectLinkRecord(in);
|
||||
case PaletteRecord.sid: return new PaletteRecord(in);
|
||||
case PaneRecord.sid: return new PaneRecord(in);
|
||||
case PasswordRecord.sid: return new PasswordRecord(in);
|
||||
case PasswordRev4Record.sid: return new PasswordRev4Record(in);
|
||||
case PlotAreaRecord.sid: return new PlotAreaRecord(in);
|
||||
case PlotGrowthRecord.sid: return new PlotGrowthRecord(in);
|
||||
case PrecisionRecord.sid: return new PrecisionRecord(in);
|
||||
case PrintGridlinesRecord.sid: return new PrintGridlinesRecord(in);
|
||||
case PrintHeadersRecord.sid: return new PrintHeadersRecord(in);
|
||||
case PrintSetupRecord.sid: return new PrintSetupRecord(in);
|
||||
case ProtectRecord.sid: return new ProtectRecord(in);
|
||||
case ProtectionRev4Record.sid: return new ProtectionRev4Record(in);
|
||||
case RKRecord.sid: return new RKRecord(in);
|
||||
case RecalcIdRecord.sid: return new RecalcIdRecord(in);
|
||||
case RefModeRecord.sid: return new RefModeRecord(in);
|
||||
case RefreshAllRecord.sid: return new RefreshAllRecord(in);
|
||||
case RightMarginRecord.sid: return new RightMarginRecord(in);
|
||||
case RowRecord.sid: return new RowRecord(in);
|
||||
case SCLRecord.sid: return new SCLRecord(in);
|
||||
case SSTRecord.sid: return new SSTRecord(in);
|
||||
case SaveRecalcRecord.sid: return new SaveRecalcRecord(in);
|
||||
case SelectionRecord.sid: return new SelectionRecord(in);
|
||||
case SeriesIndexRecord.sid: return new SeriesIndexRecord(in);
|
||||
case SeriesListRecord.sid: return new SeriesListRecord(in);
|
||||
case SeriesRecord.sid: return new SeriesRecord(in);
|
||||
case SeriesTextRecord.sid: return new SeriesTextRecord(in);
|
||||
case SeriesToChartGroupRecord.sid:return new SeriesToChartGroupRecord(in);
|
||||
case SharedFormulaRecord.sid: return new SharedFormulaRecord(in);
|
||||
case SheetPropertiesRecord.sid: return new SheetPropertiesRecord(in);
|
||||
case StringRecord.sid: return new StringRecord(in);
|
||||
case StyleRecord.sid: return new StyleRecord(in);
|
||||
case SupBookRecord.sid: return new SupBookRecord(in);
|
||||
case TabIdRecord.sid: return new TabIdRecord(in);
|
||||
case TableStylesRecord.sid: return new TableStylesRecord(in);
|
||||
case TableRecord.sid: return new TableRecord(in);
|
||||
case TextObjectRecord.sid: return new TextObjectRecord(in);
|
||||
case TextRecord.sid: return new TextRecord(in);
|
||||
case TickRecord.sid: return new TickRecord(in);
|
||||
case TopMarginRecord.sid: return new TopMarginRecord(in);
|
||||
case UncalcedRecord.sid: return new UncalcedRecord(in);
|
||||
case UnitsRecord.sid: return new UnitsRecord(in);
|
||||
case UseSelFSRecord.sid: return new UseSelFSRecord(in);
|
||||
case VCenterRecord.sid: return new VCenterRecord(in);
|
||||
case ValueRangeRecord.sid: return new ValueRangeRecord(in);
|
||||
case VerticalPageBreakRecord.sid: return new VerticalPageBreakRecord(in);
|
||||
case WSBoolRecord.sid: return new WSBoolRecord(in);
|
||||
case WindowOneRecord.sid: return new WindowOneRecord(in);
|
||||
case WindowProtectRecord.sid: return new WindowProtectRecord(in);
|
||||
case WindowTwoRecord.sid: return new WindowTwoRecord(in);
|
||||
case WriteAccessRecord.sid: return new WriteAccessRecord(in);
|
||||
case WriteProtectRecord.sid: return new WriteProtectRecord(in);
|
||||
|
||||
// chart
|
||||
case CatLabRecord.sid: return new CatLabRecord(in);
|
||||
case ChartEndBlockRecord.sid: return new ChartEndBlockRecord(in);
|
||||
case ChartEndObjectRecord.sid: return new ChartEndObjectRecord(in);
|
||||
case ChartFRTInfoRecord.sid: return new ChartFRTInfoRecord(in);
|
||||
case ChartStartBlockRecord.sid: return new ChartStartBlockRecord(in);
|
||||
case ChartStartObjectRecord.sid: return new ChartStartObjectRecord(in);
|
||||
// chart
|
||||
case CatLabRecord.sid: return new CatLabRecord(in);
|
||||
case ChartEndBlockRecord.sid: return new ChartEndBlockRecord(in);
|
||||
case ChartEndObjectRecord.sid: return new ChartEndObjectRecord(in);
|
||||
case ChartFRTInfoRecord.sid: return new ChartFRTInfoRecord(in);
|
||||
case ChartStartBlockRecord.sid: return new ChartStartBlockRecord(in);
|
||||
case ChartStartObjectRecord.sid: return new ChartStartObjectRecord(in);
|
||||
|
||||
// pivot table
|
||||
case StreamIDRecord.sid: return new StreamIDRecord(in);
|
||||
case ViewSourceRecord.sid: return new ViewSourceRecord(in);
|
||||
case PageItemRecord.sid: return new PageItemRecord(in);
|
||||
case ViewDefinitionRecord.sid: return new ViewDefinitionRecord(in);
|
||||
case ViewFieldsRecord.sid: return new ViewFieldsRecord(in);
|
||||
case DataItemRecord.sid: return new DataItemRecord(in);
|
||||
case ExtendedPivotTableViewFieldsRecord.sid: return new ExtendedPivotTableViewFieldsRecord(in);
|
||||
}
|
||||
return new UnknownRecord(in);
|
||||
}
|
||||
// pivot table
|
||||
case StreamIDRecord.sid: return new StreamIDRecord(in);
|
||||
case ViewSourceRecord.sid: return new ViewSourceRecord(in);
|
||||
case PageItemRecord.sid: return new PageItemRecord(in);
|
||||
case ViewDefinitionRecord.sid: return new ViewDefinitionRecord(in);
|
||||
case ViewFieldsRecord.sid: return new ViewFieldsRecord(in);
|
||||
case DataItemRecord.sid: return new DataItemRecord(in);
|
||||
case ExtendedPivotTableViewFieldsRecord.sid: return new ExtendedPivotTableViewFieldsRecord(in);
|
||||
}
|
||||
return new UnknownRecord(in);
|
||||
}
|
||||
|
||||
private static final class CommandArgs {
|
||||
private static final class CommandArgs {
|
||||
|
||||
private final boolean _biffhex;
|
||||
private final boolean _noint;
|
||||
private final boolean _out;
|
||||
private final boolean _rawhex;
|
||||
private final boolean _noHeader;
|
||||
private final File _file;
|
||||
private final boolean _biffhex;
|
||||
private final boolean _noint;
|
||||
private final boolean _out;
|
||||
private final boolean _rawhex;
|
||||
private final boolean _noHeader;
|
||||
private final File _file;
|
||||
|
||||
private CommandArgs(boolean biffhex, boolean noint, boolean out, boolean rawhex, boolean noHeader, File file) {
|
||||
_biffhex = biffhex;
|
||||
_noint = noint;
|
||||
_out = out;
|
||||
_rawhex = rawhex;
|
||||
_file = file;
|
||||
_noHeader = noHeader;
|
||||
}
|
||||
private CommandArgs(boolean biffhex, boolean noint, boolean out, boolean rawhex, boolean noHeader, File file) {
|
||||
_biffhex = biffhex;
|
||||
_noint = noint;
|
||||
_out = out;
|
||||
_rawhex = rawhex;
|
||||
_file = file;
|
||||
_noHeader = noHeader;
|
||||
}
|
||||
|
||||
public static CommandArgs parse(String[] args) throws CommandParseException {
|
||||
int nArgs = args.length;
|
||||
boolean biffhex = false;
|
||||
boolean noint = false;
|
||||
boolean out = false;
|
||||
boolean rawhex = false;
|
||||
boolean noheader = false;
|
||||
File file = null;
|
||||
for (int i=0; i<nArgs; i++) {
|
||||
String arg = args[i];
|
||||
if (arg.startsWith("--")) {
|
||||
if ("--biffhex".equals(arg)) {
|
||||
biffhex = true;
|
||||
} else if ("--noint".equals(arg)) {
|
||||
noint = true;
|
||||
} else if ("--out".equals(arg)) {
|
||||
out = true;
|
||||
} else if ("--escher".equals(arg)) {
|
||||
System.setProperty("poi.deserialize.escher", "true");
|
||||
} else if ("--rawhex".equals(arg)) {
|
||||
rawhex = true;
|
||||
} else if ("--noheader".equals(arg)) {
|
||||
noheader = true;
|
||||
} else {
|
||||
throw new CommandParseException("Unexpected option '" + arg + "'");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
file = new File(arg);
|
||||
if (!file.exists()) {
|
||||
throw new CommandParseException("Specified file '" + arg + "' does not exist");
|
||||
}
|
||||
if (i+1<nArgs) {
|
||||
throw new CommandParseException("File name must be the last arg");
|
||||
}
|
||||
}
|
||||
if (file == null) {
|
||||
throw new CommandParseException("Biff viewer needs a filename");
|
||||
}
|
||||
return new CommandArgs(biffhex, noint, out, rawhex, noheader, file);
|
||||
}
|
||||
public boolean shouldDumpBiffHex() {
|
||||
return _biffhex;
|
||||
}
|
||||
public boolean shouldDumpRecordInterpretations() {
|
||||
return !_noint;
|
||||
}
|
||||
public boolean shouldOutputToFile() {
|
||||
return _out;
|
||||
}
|
||||
public boolean shouldOutputRawHexOnly() {
|
||||
return _rawhex;
|
||||
}
|
||||
public boolean suppressHeader() {
|
||||
return _noHeader;
|
||||
}
|
||||
public File getFile() {
|
||||
return _file;
|
||||
}
|
||||
}
|
||||
private static final class CommandParseException extends Exception {
|
||||
public CommandParseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
public static CommandArgs parse(String[] args) throws CommandParseException {
|
||||
int nArgs = args.length;
|
||||
boolean biffhex = false;
|
||||
boolean noint = false;
|
||||
boolean out = false;
|
||||
boolean rawhex = false;
|
||||
boolean noheader = false;
|
||||
File file = null;
|
||||
for (int i=0; i<nArgs; i++) {
|
||||
String arg = args[i];
|
||||
if (arg.startsWith("--")) {
|
||||
if ("--biffhex".equals(arg)) {
|
||||
biffhex = true;
|
||||
} else if ("--noint".equals(arg)) {
|
||||
noint = true;
|
||||
} else if ("--out".equals(arg)) {
|
||||
out = true;
|
||||
} else if ("--escher".equals(arg)) {
|
||||
System.setProperty("poi.deserialize.escher", "true");
|
||||
} else if ("--rawhex".equals(arg)) {
|
||||
rawhex = true;
|
||||
} else if ("--noheader".equals(arg)) {
|
||||
noheader = true;
|
||||
} else {
|
||||
throw new CommandParseException("Unexpected option '" + arg + "'");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
file = new File(arg);
|
||||
if (!file.exists()) {
|
||||
throw new CommandParseException("Specified file '" + arg + "' does not exist");
|
||||
}
|
||||
if (i+1<nArgs) {
|
||||
throw new CommandParseException("File name must be the last arg");
|
||||
}
|
||||
}
|
||||
if (file == null) {
|
||||
throw new CommandParseException("Biff viewer needs a filename");
|
||||
}
|
||||
return new CommandArgs(biffhex, noint, out, rawhex, noheader, file);
|
||||
}
|
||||
public boolean shouldDumpBiffHex() {
|
||||
return _biffhex;
|
||||
}
|
||||
public boolean shouldDumpRecordInterpretations() {
|
||||
return !_noint;
|
||||
}
|
||||
public boolean shouldOutputToFile() {
|
||||
return _out;
|
||||
}
|
||||
public boolean shouldOutputRawHexOnly() {
|
||||
return _rawhex;
|
||||
}
|
||||
public boolean suppressHeader() {
|
||||
return _noHeader;
|
||||
}
|
||||
public File getFile() {
|
||||
return _file;
|
||||
}
|
||||
}
|
||||
private static final class CommandParseException extends Exception {
|
||||
public CommandParseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method main with 1 argument just run straight biffview against given
|
||||
@ -420,7 +470,7 @@ public final class BiffViewer {
|
||||
|
||||
protected static InputStream getPOIFSInputStream(File file)
|
||||
throws IOException, FileNotFoundException {
|
||||
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(file));
|
||||
NPOIFSFileSystem fs = new NPOIFSFileSystem(new FileInputStream(file));
|
||||
String workbookName = HSSFWorkbook.getWorkbookDirEntryName(fs.getRoot());
|
||||
return fs.createDocumentInputStream(workbookName);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package org.apache.poi.hssf.eventusermodel;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.poi.hssf.eventusermodel.HSSFUserException;
|
||||
import org.apache.poi.hssf.record.*;
|
||||
@ -56,11 +57,24 @@ public class HSSFEventFactory {
|
||||
* @param req an Instance of HSSFRequest which has your registered listeners
|
||||
* @param dir a DirectoryNode containing your workbook
|
||||
*/
|
||||
public void processWorkbookEvents(HSSFRequest req, DirectoryNode dir) throws IOException {
|
||||
InputStream in = dir.createDocumentInputStream("Workbook");
|
||||
public void processWorkbookEvents(HSSFRequest req, DirectoryNode dir) throws IOException {
|
||||
// some old documents have "WORKBOOK" or "BOOK"
|
||||
final String name;
|
||||
Set<String> entryNames = dir.getEntryNames();
|
||||
if (entryNames.contains("Workbook")) {
|
||||
name = "Workbook";
|
||||
} else if (entryNames.contains("WORKBOOK")) {
|
||||
name = "WORKBOOK";
|
||||
} else if (entryNames.contains("BOOK")) {
|
||||
name = "BOOK";
|
||||
} else {
|
||||
name = "Workbook";
|
||||
}
|
||||
|
||||
processEvents(req, in);
|
||||
}
|
||||
InputStream in = dir.createDocumentInputStream(name);
|
||||
|
||||
processEvents(req, in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.POIDocument;
|
||||
import org.apache.poi.POIOLE2TextExtractor;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
@ -75,7 +76,7 @@ public class EventBasedExcelExtractor extends POIOLE2TextExtractor implements or
|
||||
|
||||
public EventBasedExcelExtractor( DirectoryNode dir )
|
||||
{
|
||||
super( null );
|
||||
super( (POIDocument)null );
|
||||
_dir = dir;
|
||||
}
|
||||
|
||||
@ -83,16 +84,6 @@ public class EventBasedExcelExtractor extends POIOLE2TextExtractor implements or
|
||||
this(fs.getRoot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying POIFS FileSystem of
|
||||
* this document.
|
||||
*
|
||||
* @deprecated Use {@link #getRoot()} instead
|
||||
*/
|
||||
public POIFSFileSystem getFileSystem() {
|
||||
return _dir.getFileSystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Would return the document information metadata for the document,
|
||||
* if we supported it
|
||||
|
@ -774,11 +774,12 @@ public final class InternalWorkbook {
|
||||
}
|
||||
}
|
||||
|
||||
// also tell the LinkTable about the removed sheet
|
||||
// +1 because we already removed it from the count of sheets!
|
||||
for(int i = sheetIndex+1;i < getNumSheets()+1;i++) {
|
||||
// also update the link-table as otherwise references might point at invalid sheets
|
||||
linkTable.removeSheet(i);
|
||||
if (linkTable != null) {
|
||||
// also tell the LinkTable about the removed sheet
|
||||
// +1 because we already removed it from the count of sheets!
|
||||
for(int i = sheetIndex+1;i < getNumSheets()+1;i++) {
|
||||
linkTable.removeSheet(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
88
src/java/org/apache/poi/hssf/record/CFHeader12Record.java
Normal file
88
src/java/org/apache/poi/hssf/record/CFHeader12Record.java
Normal file
@ -0,0 +1,88 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.record.common.FtrHeader;
|
||||
import org.apache.poi.hssf.record.common.FutureRecord;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Conditional Formatting Header v12 record CFHEADER12 (0x0879),
|
||||
* for conditional formattings introduced in Excel 2007 and newer.
|
||||
*/
|
||||
public final class CFHeader12Record extends CFHeaderBase implements FutureRecord {
|
||||
public static final short sid = 0x0879;
|
||||
|
||||
private FtrHeader futureHeader;
|
||||
|
||||
/** Creates new CFHeaderRecord */
|
||||
public CFHeader12Record() {
|
||||
createEmpty();
|
||||
futureHeader = new FtrHeader();
|
||||
futureHeader.setRecordType(sid);
|
||||
}
|
||||
public CFHeader12Record(CellRangeAddress[] regions, int nRules) {
|
||||
super(regions, nRules);
|
||||
futureHeader = new FtrHeader();
|
||||
futureHeader.setRecordType(sid);
|
||||
}
|
||||
public CFHeader12Record(RecordInputStream in) {
|
||||
futureHeader = new FtrHeader(in);
|
||||
read(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRecordName() {
|
||||
return "CFHEADER12";
|
||||
}
|
||||
|
||||
protected int getDataSize() {
|
||||
return FtrHeader.getDataSize() + super.getDataSize();
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
// Sync the associated range
|
||||
futureHeader.setAssociatedRange(getEnclosingCellRange());
|
||||
// Write the future header first
|
||||
futureHeader.serialize(out);
|
||||
// Then the rest of the CF Header details
|
||||
super.serialize(out);
|
||||
}
|
||||
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public short getFutureRecordType() {
|
||||
return futureHeader.getRecordType();
|
||||
}
|
||||
public FtrHeader getFutureHeader() {
|
||||
return futureHeader;
|
||||
}
|
||||
public CellRangeAddress getAssociatedRange() {
|
||||
return futureHeader.getAssociatedRange();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
CFHeader12Record result = new CFHeader12Record();
|
||||
result.futureHeader = (FtrHeader)futureHeader.clone();
|
||||
super.copyTo(result);
|
||||
return result;
|
||||
}
|
||||
}
|
153
src/java/org/apache/poi/hssf/record/CFHeaderBase.java
Normal file
153
src/java/org/apache/poi/hssf/record/CFHeaderBase.java
Normal file
@ -0,0 +1,153 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.record.cf.CellRangeUtil;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Parent of Conditional Formatting Header records,
|
||||
* {@link CFHeaderRecord} and {@link CFHeader12Record}.
|
||||
*/
|
||||
public abstract class CFHeaderBase extends StandardRecord {
|
||||
private int field_1_numcf;
|
||||
private int field_2_need_recalculation_and_id;
|
||||
private CellRangeAddress field_3_enclosing_cell_range;
|
||||
private CellRangeAddressList field_4_cell_ranges;
|
||||
|
||||
/** Creates new CFHeaderBase */
|
||||
protected CFHeaderBase() {
|
||||
}
|
||||
protected CFHeaderBase(CellRangeAddress[] regions, int nRules) {
|
||||
CellRangeAddress[] unmergedRanges = regions;
|
||||
CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(unmergedRanges);
|
||||
setCellRanges(mergeCellRanges);
|
||||
field_1_numcf = nRules;
|
||||
}
|
||||
|
||||
protected void createEmpty() {
|
||||
field_3_enclosing_cell_range = new CellRangeAddress(0, 0, 0, 0);
|
||||
field_4_cell_ranges = new CellRangeAddressList();
|
||||
}
|
||||
protected void read(RecordInputStream in) {
|
||||
field_1_numcf = in.readShort();
|
||||
field_2_need_recalculation_and_id = in.readShort();
|
||||
field_3_enclosing_cell_range = new CellRangeAddress(in);
|
||||
field_4_cell_ranges = new CellRangeAddressList(in);
|
||||
}
|
||||
|
||||
public int getNumberOfConditionalFormats() {
|
||||
return field_1_numcf;
|
||||
}
|
||||
public void setNumberOfConditionalFormats(int n) {
|
||||
field_1_numcf=n;
|
||||
}
|
||||
|
||||
public boolean getNeedRecalculation() {
|
||||
// Held on the 1st bit
|
||||
return field_2_need_recalculation_and_id % 2 == 1;
|
||||
}
|
||||
public void setNeedRecalculation(boolean b) {
|
||||
// held on the first bit
|
||||
if (b == getNeedRecalculation()) return;
|
||||
if (b) field_2_need_recalculation_and_id++;
|
||||
else field_2_need_recalculation_and_id--;
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
// Remaining 15 bits of field 2
|
||||
return field_2_need_recalculation_and_id>>1;
|
||||
}
|
||||
public void setID(int id) {
|
||||
// Remaining 15 bits of field 2
|
||||
boolean needsRecalc = getNeedRecalculation();
|
||||
field_2_need_recalculation_and_id = (id<<1);
|
||||
if (needsRecalc) field_2_need_recalculation_and_id++;
|
||||
}
|
||||
|
||||
public CellRangeAddress getEnclosingCellRange() {
|
||||
return field_3_enclosing_cell_range;
|
||||
}
|
||||
public void setEnclosingCellRange(CellRangeAddress cr) {
|
||||
field_3_enclosing_cell_range = cr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cell ranges list to a single cell range and
|
||||
* modify the enclosing cell range accordingly.
|
||||
* @param cellRanges - list of CellRange objects
|
||||
*/
|
||||
public void setCellRanges(CellRangeAddress[] cellRanges) {
|
||||
if(cellRanges == null) {
|
||||
throw new IllegalArgumentException("cellRanges must not be null");
|
||||
}
|
||||
CellRangeAddressList cral = new CellRangeAddressList();
|
||||
CellRangeAddress enclosingRange = null;
|
||||
for (int i = 0; i < cellRanges.length; i++) {
|
||||
CellRangeAddress cr = cellRanges[i];
|
||||
enclosingRange = CellRangeUtil.createEnclosingCellRange(cr, enclosingRange);
|
||||
cral.addCellRangeAddress(cr);
|
||||
}
|
||||
field_3_enclosing_cell_range = enclosingRange;
|
||||
field_4_cell_ranges = cral;
|
||||
}
|
||||
|
||||
public CellRangeAddress[] getCellRanges() {
|
||||
return field_4_cell_ranges.getCellRangeAddresses();
|
||||
}
|
||||
|
||||
protected abstract String getRecordName();
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("[").append(getRecordName()).append("]\n");
|
||||
buffer.append("\t.numCF = ").append(getNumberOfConditionalFormats()).append("\n");
|
||||
buffer.append("\t.needRecalc = ").append(getNeedRecalculation()).append("\n");
|
||||
buffer.append("\t.id = ").append(getID()).append("\n");
|
||||
buffer.append("\t.enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
|
||||
buffer.append("\t.cfranges=[");
|
||||
for( int i=0; i<field_4_cell_ranges.countRanges(); i++) {
|
||||
buffer.append(i==0?"":",").append(field_4_cell_ranges.getCellRangeAddress(i).toString());
|
||||
}
|
||||
buffer.append("]\n");
|
||||
buffer.append("[/").append(getRecordName()).append("]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
protected int getDataSize() {
|
||||
return 4 // 2 short fields
|
||||
+ CellRangeAddress.ENCODED_SIZE
|
||||
+ field_4_cell_ranges.getSize();
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(field_1_numcf);
|
||||
out.writeShort(field_2_need_recalculation_and_id);
|
||||
field_3_enclosing_cell_range.serialize(out);
|
||||
field_4_cell_ranges.serialize(out);
|
||||
}
|
||||
|
||||
protected void copyTo(CFHeaderBase result) {
|
||||
result.field_1_numcf = field_1_numcf;
|
||||
result.field_2_need_recalculation_and_id = field_2_need_recalculation_and_id;
|
||||
result.field_3_enclosing_cell_range = field_3_enclosing_cell_range.copy();
|
||||
result.field_4_cell_ranges = field_4_cell_ranges.copy();
|
||||
}
|
||||
}
|
@ -17,144 +17,39 @@
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.record.cf.CellRangeUtil;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Conditional Formatting Header record CFHEADER (0x01B0)
|
||||
*
|
||||
* @author Dmitriy Kumshayev
|
||||
* Conditional Formatting Header record CFHEADER (0x01B0).
|
||||
* Used to describe a {@link CFRuleRecord}.
|
||||
* @see CFHeader12Record
|
||||
*/
|
||||
public final class CFHeaderRecord extends StandardRecord {
|
||||
public static final short sid = 0x01B0;
|
||||
public final class CFHeaderRecord extends CFHeaderBase {
|
||||
public static final short sid = 0x01B0;
|
||||
|
||||
private int field_1_numcf;
|
||||
private int field_2_need_recalculation;
|
||||
private CellRangeAddress field_3_enclosing_cell_range;
|
||||
private CellRangeAddressList field_4_cell_ranges;
|
||||
/** Creates new CFHeaderRecord */
|
||||
public CFHeaderRecord() {
|
||||
createEmpty();
|
||||
}
|
||||
public CFHeaderRecord(CellRangeAddress[] regions, int nRules) {
|
||||
super(regions, nRules);
|
||||
}
|
||||
|
||||
/** Creates new CFHeaderRecord */
|
||||
public CFHeaderRecord()
|
||||
{
|
||||
field_4_cell_ranges = new CellRangeAddressList();
|
||||
}
|
||||
public CFHeaderRecord(CellRangeAddress[] regions, int nRules) {
|
||||
CellRangeAddress[] unmergedRanges = regions;
|
||||
CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(unmergedRanges);
|
||||
setCellRanges(mergeCellRanges);
|
||||
field_1_numcf = nRules;
|
||||
}
|
||||
public CFHeaderRecord(RecordInputStream in) {
|
||||
read(in);
|
||||
}
|
||||
|
||||
public CFHeaderRecord(RecordInputStream in)
|
||||
{
|
||||
field_1_numcf = in.readShort();
|
||||
field_2_need_recalculation = in.readShort();
|
||||
field_3_enclosing_cell_range = new CellRangeAddress(in);
|
||||
field_4_cell_ranges = new CellRangeAddressList(in);
|
||||
}
|
||||
|
||||
public int getNumberOfConditionalFormats()
|
||||
{
|
||||
return field_1_numcf;
|
||||
}
|
||||
public void setNumberOfConditionalFormats(int n)
|
||||
{
|
||||
field_1_numcf=n;
|
||||
}
|
||||
|
||||
public boolean getNeedRecalculation()
|
||||
{
|
||||
return field_2_need_recalculation==1?true:false;
|
||||
}
|
||||
protected String getRecordName() {
|
||||
return "CFHEADER";
|
||||
}
|
||||
|
||||
public void setNeedRecalculation(boolean b)
|
||||
{
|
||||
field_2_need_recalculation=b?1:0;
|
||||
}
|
||||
|
||||
public CellRangeAddress getEnclosingCellRange()
|
||||
{
|
||||
return field_3_enclosing_cell_range;
|
||||
}
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public void setEnclosingCellRange(CellRangeAddress cr)
|
||||
{
|
||||
field_3_enclosing_cell_range = cr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cell ranges list to a single cell range and
|
||||
* modify the enclosing cell range accordingly.
|
||||
* @param cellRanges - list of CellRange objects
|
||||
*/
|
||||
public void setCellRanges(CellRangeAddress[] cellRanges)
|
||||
{
|
||||
if(cellRanges == null)
|
||||
{
|
||||
throw new IllegalArgumentException("cellRanges must not be null");
|
||||
}
|
||||
CellRangeAddressList cral = new CellRangeAddressList();
|
||||
CellRangeAddress enclosingRange = null;
|
||||
for (int i = 0; i < cellRanges.length; i++)
|
||||
{
|
||||
CellRangeAddress cr = cellRanges[i];
|
||||
enclosingRange = CellRangeUtil.createEnclosingCellRange(cr, enclosingRange);
|
||||
cral.addCellRangeAddress(cr);
|
||||
}
|
||||
field_3_enclosing_cell_range = enclosingRange;
|
||||
field_4_cell_ranges = cral;
|
||||
}
|
||||
|
||||
public CellRangeAddress[] getCellRanges() {
|
||||
return field_4_cell_ranges.getCellRangeAddresses();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("[CFHEADER]\n");
|
||||
buffer.append(" .id = ").append(Integer.toHexString(sid)).append("\n");
|
||||
buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
|
||||
buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
|
||||
buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
|
||||
buffer.append(" .cfranges=[");
|
||||
for( int i=0; i<field_4_cell_ranges.countRanges(); i++)
|
||||
{
|
||||
buffer.append(i==0?"":",").append(field_4_cell_ranges.getCellRangeAddress(i).toString());
|
||||
}
|
||||
buffer.append("]\n");
|
||||
buffer.append("[/CFHEADER]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
protected int getDataSize() {
|
||||
return 4 // 2 short fields
|
||||
+ CellRangeAddress.ENCODED_SIZE
|
||||
+ field_4_cell_ranges.getSize();
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
|
||||
out.writeShort(field_1_numcf);
|
||||
out.writeShort(field_2_need_recalculation);
|
||||
field_3_enclosing_cell_range.serialize(out);
|
||||
field_4_cell_ranges.serialize(out);
|
||||
}
|
||||
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
CFHeaderRecord result = new CFHeaderRecord();
|
||||
result.field_1_numcf = field_1_numcf;
|
||||
result.field_2_need_recalculation = field_2_need_recalculation;
|
||||
result.field_3_enclosing_cell_range = field_3_enclosing_cell_range;
|
||||
result.field_4_cell_ranges = field_4_cell_ranges.copy();
|
||||
return result;
|
||||
}
|
||||
public Object clone() {
|
||||
CFHeaderRecord result = new CFHeaderRecord();
|
||||
super.copyTo(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
365
src/java/org/apache/poi/hssf/record/CFRule12Record.java
Normal file
365
src/java/org/apache/poi/hssf/record/CFRule12Record.java
Normal file
@ -0,0 +1,365 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.hssf.record.cf.IconMultiStateFormatting;
|
||||
import org.apache.poi.hssf.record.cf.Threshold;
|
||||
import org.apache.poi.hssf.record.common.FtrHeader;
|
||||
import org.apache.poi.hssf.record.common.FutureRecord;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.ss.formula.Formula;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
/**
|
||||
* Conditional Formatting v12 Rule Record (0x087A).
|
||||
*
|
||||
* <p>This is for newer-style Excel conditional formattings,
|
||||
* from Excel 2007 onwards.
|
||||
*
|
||||
* <p>{@link CFRuleRecord} is used where the condition type is
|
||||
* {@link #CONDITION_TYPE_CELL_VALUE_IS} or {@link #CONDITION_TYPE_FORMULA},
|
||||
* this is only used for the other types
|
||||
*/
|
||||
public final class CFRule12Record extends CFRuleBase implements FutureRecord {
|
||||
public static final short sid = 0x087A;
|
||||
|
||||
private FtrHeader futureHeader;
|
||||
private int ext_formatting_length;
|
||||
private byte[] ext_formatting_data;
|
||||
private Formula formula_scale;
|
||||
private byte ext_opts;
|
||||
private int priority;
|
||||
private int template_type;
|
||||
private byte template_param_length;
|
||||
private byte[] template_params;
|
||||
|
||||
private IconMultiStateFormatting multistate;
|
||||
|
||||
// TODO Parse these
|
||||
private byte[] gradient_data;
|
||||
private byte[] databar_data;
|
||||
private byte[] filter_data;
|
||||
|
||||
/** Creates new CFRuleRecord */
|
||||
private CFRule12Record(byte conditionType, byte comparisonOperation) {
|
||||
super(conditionType, comparisonOperation);
|
||||
setDefaults();
|
||||
}
|
||||
|
||||
private CFRule12Record(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2, Ptg[] formulaScale) {
|
||||
super(conditionType, comparisonOperation, formula1, formula2);
|
||||
setDefaults();
|
||||
this.formula_scale = Formula.create(formulaScale);
|
||||
}
|
||||
private void setDefaults() {
|
||||
futureHeader = new FtrHeader();
|
||||
futureHeader.setRecordType(sid);
|
||||
|
||||
ext_formatting_length = 0;
|
||||
ext_formatting_data = new byte[4];
|
||||
|
||||
formula_scale = Formula.create(Ptg.EMPTY_PTG_ARRAY);
|
||||
|
||||
ext_opts = 0;
|
||||
priority = 0;
|
||||
template_type = getConditionType();
|
||||
template_param_length = 16;
|
||||
template_params = new byte[template_param_length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
public static CFRule12Record create(HSSFSheet sheet, String formulaText) {
|
||||
Ptg[] formula1 = parseFormula(formulaText, sheet);
|
||||
return new CFRule12Record(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON,
|
||||
formula1, null, null);
|
||||
}
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation,
|
||||
String formulaText1, String formulaText2) {
|
||||
Ptg[] formula1 = parseFormula(formulaText1, sheet);
|
||||
Ptg[] formula2 = parseFormula(formulaText2, sheet);
|
||||
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation,
|
||||
formula1, formula2, null);
|
||||
}
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation,
|
||||
String formulaText1, String formulaText2, String formulaTextScale) {
|
||||
Ptg[] formula1 = parseFormula(formulaText1, sheet);
|
||||
Ptg[] formula2 = parseFormula(formulaText2, sheet);
|
||||
Ptg[] formula3 = parseFormula(formulaTextScale, sheet);
|
||||
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation,
|
||||
formula1, formula2, formula3);
|
||||
}
|
||||
/**
|
||||
* Creates a new Icon Set / Multi-State formatting
|
||||
*/
|
||||
public static CFRule12Record create(HSSFSheet sheet, IconSet iconSet) {
|
||||
Threshold[] ts = new Threshold[iconSet.num];
|
||||
for (int i=0; i<ts.length; i++) {
|
||||
ts[i] = new Threshold();
|
||||
}
|
||||
|
||||
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE,
|
||||
ComparisonOperator.NO_COMPARISON);
|
||||
IconMultiStateFormatting imf = r.createMultiStateFormatting();
|
||||
imf.setIconSet(iconSet);
|
||||
imf.setThresholds(ts);
|
||||
return r;
|
||||
}
|
||||
// TODO Static creators for the other record types
|
||||
|
||||
public CFRule12Record(RecordInputStream in) {
|
||||
futureHeader = new FtrHeader(in);
|
||||
setConditionType(in.readByte());
|
||||
setComparisonOperation(in.readByte());
|
||||
int field_3_formula1_len = in.readUShort();
|
||||
int field_4_formula2_len = in.readUShort();
|
||||
|
||||
ext_formatting_length = in.readInt();
|
||||
ext_formatting_data = new byte[0];
|
||||
if (ext_formatting_length == 0) {
|
||||
// 2 bytes reserved
|
||||
in.readUShort();
|
||||
} else {
|
||||
int len = readFormatOptions(in);
|
||||
if (len < ext_formatting_length) {
|
||||
ext_formatting_data = new byte[ext_formatting_length-len];
|
||||
in.readFully(ext_formatting_data);
|
||||
}
|
||||
}
|
||||
|
||||
setFormula1(Formula.read(field_3_formula1_len, in));
|
||||
setFormula2(Formula.read(field_4_formula2_len, in));
|
||||
|
||||
int formula_scale_len = in.readUShort();
|
||||
formula_scale = Formula.read(formula_scale_len, in);
|
||||
|
||||
ext_opts = in.readByte();
|
||||
priority = in.readUShort();
|
||||
template_type = in.readUShort();
|
||||
template_param_length = in.readByte();
|
||||
if (template_param_length == 0 || template_param_length == 16) {
|
||||
template_params = new byte[template_param_length];
|
||||
in.readFully(template_params);
|
||||
} else {
|
||||
logger.log(POILogger.WARN, "CF Rule v12 template params length should be 0 or 16, found " + template_param_length);
|
||||
in.readRemainder();
|
||||
}
|
||||
|
||||
byte type = getConditionType();
|
||||
if (type == CONDITION_TYPE_COLOR_SCALE) {
|
||||
gradient_data = in.readRemainder();
|
||||
} else if (type == CONDITION_TYPE_DATA_BAR) {
|
||||
databar_data = in.readRemainder();
|
||||
} else if (type == CONDITION_TYPE_FILTER) {
|
||||
filter_data = in.readRemainder();
|
||||
} else if (type == CONDITION_TYPE_ICON_SET) {
|
||||
multistate = new IconMultiStateFormatting(in);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsMultiStateBlock() {
|
||||
return (multistate != null);
|
||||
}
|
||||
public IconMultiStateFormatting getMultiStateFormatting() {
|
||||
return multistate;
|
||||
}
|
||||
public IconMultiStateFormatting createMultiStateFormatting() {
|
||||
if (multistate != null) return multistate;
|
||||
|
||||
// Convert, setup and return
|
||||
setConditionType(CONDITION_TYPE_ICON_SET);
|
||||
multistate = new IconMultiStateFormatting();
|
||||
return multistate;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the stack of the scale expression as a list
|
||||
*
|
||||
* @return list of tokens (casts stack to a list and returns it!)
|
||||
* this method can return null is we are unable to create Ptgs from
|
||||
* existing excel file
|
||||
* callers should check for null!
|
||||
*/
|
||||
public Ptg[] getParsedExpressionScale() {
|
||||
return formula_scale.getTokens();
|
||||
}
|
||||
public void setParsedExpressionScale(Ptg[] ptgs) {
|
||||
formula_scale = Formula.create(ptgs);
|
||||
}
|
||||
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* called by the class that is responsible for writing this sucker.
|
||||
* Subclasses should implement this so that their data is passed back in a
|
||||
* byte array.
|
||||
*
|
||||
* @param out the stream to write to
|
||||
*/
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
futureHeader.serialize(out);
|
||||
|
||||
int formula1Len=getFormulaSize(getFormula1());
|
||||
int formula2Len=getFormulaSize(getFormula2());
|
||||
|
||||
out.writeByte(getConditionType());
|
||||
out.writeByte(getComparisonOperation());
|
||||
out.writeShort(formula1Len);
|
||||
out.writeShort(formula2Len);
|
||||
|
||||
// TODO Update ext_formatting_length
|
||||
if (ext_formatting_length == 0) {
|
||||
out.writeInt(0);
|
||||
out.writeShort(0);
|
||||
} else {
|
||||
out.writeInt(ext_formatting_length);
|
||||
serializeFormattingBlock(out);
|
||||
out.write(ext_formatting_data);
|
||||
}
|
||||
|
||||
getFormula1().serializeTokens(out);
|
||||
getFormula2().serializeTokens(out);
|
||||
out.writeShort(getFormulaSize(formula_scale));
|
||||
formula_scale.serializeTokens(out);
|
||||
|
||||
out.writeByte(ext_opts);
|
||||
out.writeShort(priority);
|
||||
out.writeShort(template_type);
|
||||
out.writeByte(template_param_length);
|
||||
out.write(template_params);
|
||||
|
||||
byte type = getConditionType();
|
||||
if (type == CONDITION_TYPE_COLOR_SCALE) {
|
||||
out.write(gradient_data);
|
||||
} else if (type == CONDITION_TYPE_DATA_BAR) {
|
||||
out.write(databar_data);
|
||||
} else if (type == CONDITION_TYPE_FILTER) {
|
||||
out.write(filter_data);
|
||||
} else if (type == CONDITION_TYPE_ICON_SET) {
|
||||
multistate.serialize(out);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getDataSize() {
|
||||
int len = FtrHeader.getDataSize() + 6;
|
||||
if (ext_formatting_length == 0) {
|
||||
len += 6;
|
||||
} else {
|
||||
len += 4 + getFormattingBlockSize() + ext_formatting_data.length;
|
||||
}
|
||||
len += getFormulaSize(getFormula1());
|
||||
len += getFormulaSize(getFormula2());
|
||||
len += 2 + getFormulaSize(formula_scale);
|
||||
len += 6 + template_params.length;
|
||||
|
||||
byte type = getConditionType();
|
||||
if (type == CONDITION_TYPE_COLOR_SCALE) {
|
||||
len += gradient_data.length;
|
||||
} else if (type == CONDITION_TYPE_DATA_BAR) {
|
||||
len += databar_data.length;
|
||||
} else if (type == CONDITION_TYPE_FILTER) {
|
||||
len += filter_data.length;
|
||||
} else if (type == CONDITION_TYPE_ICON_SET) {
|
||||
len += multistate.getDataLength();
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("[CFRULE12]\n");
|
||||
buffer.append(" .condition_type=").append(getConditionType()).append("\n");
|
||||
buffer.append(" .dxfn12_length =0x").append(Integer.toHexString(ext_formatting_length)).append("\n");
|
||||
buffer.append(" .option_flags =0x").append(Integer.toHexString(getOptions())).append("\n");
|
||||
if (containsFontFormattingBlock()) {
|
||||
buffer.append(_fontFormatting.toString()).append("\n");
|
||||
}
|
||||
if (containsBorderFormattingBlock()) {
|
||||
buffer.append(_borderFormatting.toString()).append("\n");
|
||||
}
|
||||
if (containsPatternFormattingBlock()) {
|
||||
buffer.append(_patternFormatting.toString()).append("\n");
|
||||
}
|
||||
buffer.append(" .dxfn12_ext=").append(HexDump.toHex(ext_formatting_data)).append("\n");
|
||||
buffer.append(" .formula_1 =").append(Arrays.toString(getFormula1().getTokens())).append("\n");
|
||||
buffer.append(" .formula_2 =").append(Arrays.toString(getFormula2().getTokens())).append("\n");
|
||||
buffer.append(" .formula_S =").append(Arrays.toString(formula_scale.getTokens())).append("\n");
|
||||
buffer.append(" .ext_opts =").append(ext_opts).append("\n");
|
||||
buffer.append(" .priority =").append(priority).append("\n");
|
||||
buffer.append(" .template_type =").append(template_type).append("\n");
|
||||
buffer.append(" .template_params=").append(HexDump.toHex(template_params)).append("\n");
|
||||
buffer.append(" .gradient_data =").append(HexDump.toHex(gradient_data)).append("\n");
|
||||
buffer.append(" .databar_data =").append(HexDump.toHex(databar_data)).append("\n");
|
||||
buffer.append(" .filter_data =").append(HexDump.toHex(filter_data)).append("\n");
|
||||
if (multistate != null) {
|
||||
buffer.append(multistate);
|
||||
}
|
||||
buffer.append("[/CFRULE12]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
CFRule12Record rec = new CFRule12Record(getConditionType(), getComparisonOperation());
|
||||
rec.futureHeader.setAssociatedRange(futureHeader.getAssociatedRange().copy());
|
||||
|
||||
super.copyTo(rec);
|
||||
|
||||
rec.ext_formatting_length = ext_formatting_length;
|
||||
rec.ext_formatting_data = new byte[ext_formatting_length];
|
||||
System.arraycopy(ext_formatting_data, 0, rec.ext_formatting_data, 0, ext_formatting_length);
|
||||
|
||||
rec.formula_scale = formula_scale.copy();
|
||||
|
||||
rec.ext_opts = ext_opts;
|
||||
rec.priority = priority;
|
||||
rec.template_type = template_type;
|
||||
rec.template_param_length = template_param_length;
|
||||
rec.template_params = new byte[template_param_length];
|
||||
System.arraycopy(template_params, 0, rec.template_params, 0, template_param_length);
|
||||
|
||||
// TODO Clone the rgbCT data like Gradients, Databars etc
|
||||
|
||||
return rec;
|
||||
}
|
||||
|
||||
public short getFutureRecordType() {
|
||||
return futureHeader.getRecordType();
|
||||
}
|
||||
public FtrHeader getFutureHeader() {
|
||||
return futureHeader;
|
||||
}
|
||||
public CellRangeAddress getAssociatedRange() {
|
||||
return futureHeader.getAssociatedRange();
|
||||
}
|
||||
}
|
455
src/java/org/apache/poi/hssf/record/CFRuleBase.java
Normal file
455
src/java/org/apache/poi/hssf/record/CFRuleBase.java
Normal file
@ -0,0 +1,455 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.model.HSSFFormulaParser;
|
||||
import org.apache.poi.hssf.record.cf.BorderFormatting;
|
||||
import org.apache.poi.hssf.record.cf.FontFormatting;
|
||||
import org.apache.poi.hssf.record.cf.PatternFormatting;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.ss.formula.Formula;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
/**
|
||||
* Conditional Formatting Rules. This can hold old-style rules
|
||||
*
|
||||
*
|
||||
* <p>This is for the older-style Excel conditional formattings,
|
||||
* new-style (Excel 2007+) also make use of {@link CFRule12Record}
|
||||
* and {@link CFExRuleRecord} for their rules.
|
||||
*/
|
||||
public abstract class CFRuleBase extends StandardRecord {
|
||||
public static final class ComparisonOperator {
|
||||
public static final byte NO_COMPARISON = 0;
|
||||
public static final byte BETWEEN = 1;
|
||||
public static final byte NOT_BETWEEN = 2;
|
||||
public static final byte EQUAL = 3;
|
||||
public static final byte NOT_EQUAL = 4;
|
||||
public static final byte GT = 5;
|
||||
public static final byte LT = 6;
|
||||
public static final byte GE = 7;
|
||||
public static final byte LE = 8;
|
||||
private static final byte max_operator = 8;
|
||||
}
|
||||
protected static final POILogger logger = POILogFactory.getLogger(CFRuleBase.class);
|
||||
|
||||
private byte condition_type;
|
||||
// The only kinds that CFRuleRecord handles
|
||||
public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1;
|
||||
public static final byte CONDITION_TYPE_FORMULA = 2;
|
||||
// These are CFRule12Rule only
|
||||
public static final byte CONDITION_TYPE_COLOR_SCALE = 3;
|
||||
public static final byte CONDITION_TYPE_DATA_BAR = 4;
|
||||
public static final byte CONDITION_TYPE_FILTER = 5;
|
||||
public static final byte CONDITION_TYPE_ICON_SET = 6;
|
||||
|
||||
private byte comparison_operator;
|
||||
|
||||
public static final int TEMPLATE_CELL_VALUE = 0x0000;
|
||||
public static final int TEMPLATE_FORMULA = 0x0001;
|
||||
public static final int TEMPLATE_COLOR_SCALE_FORMATTING = 0x0002;
|
||||
public static final int TEMPLATE_DATA_BAR_FORMATTING = 0x0003;
|
||||
public static final int TEMPLATE_ICON_SET_FORMATTING = 0x0004;
|
||||
public static final int TEMPLATE_FILTER = 0x0005;
|
||||
public static final int TEMPLATE_UNIQUE_VALUES = 0x0007;
|
||||
public static final int TEMPLATE_CONTAINS_TEXT = 0x0008;
|
||||
public static final int TEMPLATE_CONTAINS_BLANKS = 0x0009;
|
||||
public static final int TEMPLATE_CONTAINS_NO_BLANKS = 0x000A;
|
||||
public static final int TEMPLATE_CONTAINS_ERRORS = 0x000B;
|
||||
public static final int TEMPLATE_CONTAINS_NO_ERRORS = 0x000C;
|
||||
public static final int TEMPLATE_TODAY = 0x000F;
|
||||
public static final int TEMPLATE_TOMORROW = 0x0010;
|
||||
public static final int TEMPLATE_YESTERDAY = 0x0011;
|
||||
public static final int TEMPLATE_LAST_7_DAYS = 0x0012;
|
||||
public static final int TEMPLATE_LAST_MONTH = 0x0013;
|
||||
public static final int TEMPLATE_NEXT_MONTH = 0x0014;
|
||||
public static final int TEMPLATE_THIS_WEEK = 0x0015;
|
||||
public static final int TEMPLATE_NEXT_WEEK = 0x0016;
|
||||
public static final int TEMPLATE_LAST_WEEK = 0x0017;
|
||||
public static final int TEMPLATE_THIS_MONTH = 0x0018;
|
||||
public static final int TEMPLATE_ABOVE_AVERAGE = 0x0019;
|
||||
public static final int TEMPLATE_BELOW_AVERAGE = 0x001A;
|
||||
public static final int TEMPLATE_DUPLICATE_VALUES = 0x001B;
|
||||
public static final int TEMPLATE_ABOVE_OR_EQUAL_TO_AVERAGE = 0x001D;
|
||||
public static final int TEMPLATE_BELOW_OR_EQUAL_TO_AVERAGE = 0x001E;
|
||||
|
||||
static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot
|
||||
static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified
|
||||
static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified
|
||||
static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified
|
||||
static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified
|
||||
static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified
|
||||
static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified
|
||||
static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified
|
||||
static final BitField mergeCell = bf(0x00000080); // Normally 1, 0 = Merge Cell flag modified
|
||||
static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified
|
||||
static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified
|
||||
static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified
|
||||
static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified
|
||||
static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified
|
||||
static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified
|
||||
static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified
|
||||
static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified
|
||||
static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified
|
||||
static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified
|
||||
static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified
|
||||
static final BitField notUsed2 = bf(0x00380000); // Always 111 (ifmt / ifnt / 1)
|
||||
static final BitField undocumented = bf(0x03C00000); // Undocumented bits
|
||||
static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot
|
||||
static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block
|
||||
static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block
|
||||
static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block
|
||||
static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block
|
||||
static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block
|
||||
static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified
|
||||
|
||||
private static BitField bf(int i) {
|
||||
return BitFieldFactory.getInstance(i);
|
||||
}
|
||||
|
||||
protected int formatting_options;
|
||||
protected short formatting_not_used; // TODO Decode this properly
|
||||
|
||||
protected FontFormatting _fontFormatting;
|
||||
protected BorderFormatting _borderFormatting;
|
||||
protected PatternFormatting _patternFormatting;
|
||||
|
||||
private Formula formula1;
|
||||
private Formula formula2;
|
||||
|
||||
/** Creates new CFRuleRecord */
|
||||
protected CFRuleBase(byte conditionType, byte comparisonOperation) {
|
||||
setConditionType(conditionType);
|
||||
setComparisonOperation(comparisonOperation);
|
||||
formula1 = Formula.create(Ptg.EMPTY_PTG_ARRAY);
|
||||
formula2 = Formula.create(Ptg.EMPTY_PTG_ARRAY);
|
||||
}
|
||||
protected CFRuleBase(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) {
|
||||
this(conditionType, comparisonOperation);
|
||||
this.formula1 = Formula.create(formula1);
|
||||
this.formula2 = Formula.create(formula2);
|
||||
}
|
||||
protected CFRuleBase() {}
|
||||
|
||||
protected int readFormatOptions(RecordInputStream in) {
|
||||
formatting_options = in.readInt();
|
||||
formatting_not_used = in.readShort();
|
||||
|
||||
int len = 6;
|
||||
|
||||
if (containsFontFormattingBlock()) {
|
||||
_fontFormatting = new FontFormatting(in);
|
||||
len += _fontFormatting.getDataLength();
|
||||
}
|
||||
|
||||
if (containsBorderFormattingBlock()) {
|
||||
_borderFormatting = new BorderFormatting(in);
|
||||
len += _borderFormatting.getDataLength();
|
||||
}
|
||||
|
||||
if (containsPatternFormattingBlock()) {
|
||||
_patternFormatting = new PatternFormatting(in);
|
||||
len += _patternFormatting.getDataLength();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
public byte getConditionType() {
|
||||
return condition_type;
|
||||
}
|
||||
protected void setConditionType(byte condition_type) {
|
||||
if ((this instanceof CFRuleRecord)) {
|
||||
if (condition_type == CONDITION_TYPE_CELL_VALUE_IS ||
|
||||
condition_type == CONDITION_TYPE_FORMULA) {
|
||||
// Good, valid combination
|
||||
} else {
|
||||
throw new IllegalArgumentException("CFRuleRecord only accepts Value-Is and Formula types");
|
||||
}
|
||||
}
|
||||
this.condition_type = condition_type;
|
||||
}
|
||||
|
||||
public void setComparisonOperation(byte operation) {
|
||||
if (operation < 0 || operation > ComparisonOperator.max_operator)
|
||||
throw new IllegalArgumentException(
|
||||
"Valid operators are only in the range 0 to " +ComparisonOperator.max_operator);
|
||||
|
||||
this.comparison_operator = operation;
|
||||
}
|
||||
public byte getComparisonOperation() {
|
||||
return comparison_operator;
|
||||
}
|
||||
|
||||
public boolean containsFontFormattingBlock() {
|
||||
return getOptionFlag(font);
|
||||
}
|
||||
public void setFontFormatting(FontFormatting fontFormatting) {
|
||||
_fontFormatting = fontFormatting;
|
||||
setOptionFlag(fontFormatting != null, font);
|
||||
}
|
||||
public FontFormatting getFontFormatting() {
|
||||
if( containsFontFormattingBlock()) {
|
||||
return _fontFormatting;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean containsAlignFormattingBlock() {
|
||||
return getOptionFlag(align);
|
||||
}
|
||||
public void setAlignFormattingUnchanged() {
|
||||
setOptionFlag(false,align);
|
||||
}
|
||||
|
||||
public boolean containsBorderFormattingBlock() {
|
||||
return getOptionFlag(bord);
|
||||
}
|
||||
public void setBorderFormatting(BorderFormatting borderFormatting) {
|
||||
_borderFormatting = borderFormatting;
|
||||
setOptionFlag(borderFormatting != null, bord);
|
||||
}
|
||||
public BorderFormatting getBorderFormatting() {
|
||||
if( containsBorderFormattingBlock()) {
|
||||
return _borderFormatting;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean containsPatternFormattingBlock() {
|
||||
return getOptionFlag(patt);
|
||||
}
|
||||
public void setPatternFormatting(PatternFormatting patternFormatting) {
|
||||
_patternFormatting = patternFormatting;
|
||||
setOptionFlag(patternFormatting!=null, patt);
|
||||
}
|
||||
public PatternFormatting getPatternFormatting() {
|
||||
if( containsPatternFormattingBlock())
|
||||
{
|
||||
return _patternFormatting;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean containsProtectionFormattingBlock() {
|
||||
return getOptionFlag(prot);
|
||||
}
|
||||
public void setProtectionFormattingUnchanged() {
|
||||
setOptionFlag(false,prot);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the option flags
|
||||
*
|
||||
* @return bit mask
|
||||
*/
|
||||
public int getOptions() {
|
||||
return formatting_options;
|
||||
}
|
||||
|
||||
private boolean isModified(BitField field) {
|
||||
return !field.isSet(formatting_options);
|
||||
}
|
||||
private void setModified(boolean modified, BitField field) {
|
||||
formatting_options = field.setBoolean(formatting_options, !modified);
|
||||
}
|
||||
|
||||
public boolean isLeftBorderModified() {
|
||||
return isModified(bordLeft);
|
||||
}
|
||||
public void setLeftBorderModified(boolean modified) {
|
||||
setModified(modified,bordLeft);
|
||||
}
|
||||
|
||||
public boolean isRightBorderModified() {
|
||||
return isModified(bordRight);
|
||||
}
|
||||
public void setRightBorderModified(boolean modified)
|
||||
{
|
||||
setModified(modified,bordRight);
|
||||
}
|
||||
|
||||
public boolean isTopBorderModified() {
|
||||
return isModified(bordTop);
|
||||
}
|
||||
public void setTopBorderModified(boolean modified) {
|
||||
setModified(modified,bordTop);
|
||||
}
|
||||
|
||||
public boolean isBottomBorderModified() {
|
||||
return isModified(bordBot);
|
||||
}
|
||||
public void setBottomBorderModified(boolean modified) {
|
||||
setModified(modified,bordBot);
|
||||
}
|
||||
|
||||
public boolean isTopLeftBottomRightBorderModified() {
|
||||
return isModified(bordTlBr);
|
||||
}
|
||||
public void setTopLeftBottomRightBorderModified(boolean modified) {
|
||||
setModified(modified,bordTlBr);
|
||||
}
|
||||
|
||||
public boolean isBottomLeftTopRightBorderModified() {
|
||||
return isModified(bordBlTr);
|
||||
}
|
||||
public void setBottomLeftTopRightBorderModified(boolean modified) {
|
||||
setModified(modified,bordBlTr);
|
||||
}
|
||||
|
||||
public boolean isPatternStyleModified() {
|
||||
return isModified(pattStyle);
|
||||
}
|
||||
public void setPatternStyleModified(boolean modified) {
|
||||
setModified(modified,pattStyle);
|
||||
}
|
||||
|
||||
public boolean isPatternColorModified() {
|
||||
return isModified(pattCol);
|
||||
}
|
||||
public void setPatternColorModified(boolean modified) {
|
||||
setModified(modified,pattCol);
|
||||
}
|
||||
|
||||
public boolean isPatternBackgroundColorModified() {
|
||||
return isModified(pattBgCol);
|
||||
}
|
||||
public void setPatternBackgroundColorModified(boolean modified) {
|
||||
setModified(modified,pattBgCol);
|
||||
}
|
||||
|
||||
private boolean getOptionFlag(BitField field) {
|
||||
return field.isSet(formatting_options);
|
||||
}
|
||||
private void setOptionFlag(boolean flag, BitField field) {
|
||||
formatting_options = field.setBoolean(formatting_options, flag);
|
||||
}
|
||||
|
||||
protected int getFormattingBlockSize() {
|
||||
return 6 +
|
||||
(containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+
|
||||
(containsBorderFormattingBlock()?8:0)+
|
||||
(containsPatternFormattingBlock()?4:0);
|
||||
}
|
||||
protected void serializeFormattingBlock(LittleEndianOutput out) {
|
||||
out.writeInt(formatting_options);
|
||||
out.writeShort(formatting_not_used);
|
||||
|
||||
if (containsFontFormattingBlock()) {
|
||||
byte[] fontFormattingRawRecord = _fontFormatting.getRawRecord();
|
||||
out.write(fontFormattingRawRecord);
|
||||
}
|
||||
|
||||
if (containsBorderFormattingBlock()) {
|
||||
_borderFormatting.serialize(out);
|
||||
}
|
||||
|
||||
if (containsPatternFormattingBlock()) {
|
||||
_patternFormatting.serialize(out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the stack of the 1st expression as a list
|
||||
*
|
||||
* @return list of tokens (casts stack to a list and returns it!)
|
||||
* this method can return null is we are unable to create Ptgs from
|
||||
* existing excel file
|
||||
* callers should check for null!
|
||||
*/
|
||||
public Ptg[] getParsedExpression1() {
|
||||
return formula1.getTokens();
|
||||
}
|
||||
public void setParsedExpression1(Ptg[] ptgs) {
|
||||
formula1 = Formula.create(ptgs);
|
||||
}
|
||||
protected Formula getFormula1() {
|
||||
return formula1;
|
||||
}
|
||||
protected void setFormula1(Formula formula1) {
|
||||
this.formula1 = formula1;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the stack of the 2nd expression as a list
|
||||
*
|
||||
* @return array of {@link Ptg}s, possibly <code>null</code>
|
||||
*/
|
||||
public Ptg[] getParsedExpression2() {
|
||||
return Formula.getTokens(formula2);
|
||||
}
|
||||
public void setParsedExpression2(Ptg[] ptgs) {
|
||||
formula2 = Formula.create(ptgs);
|
||||
}
|
||||
protected Formula getFormula2() {
|
||||
return formula2;
|
||||
}
|
||||
protected void setFormula2(Formula formula2) {
|
||||
this.formula2 = formula2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param formula must not be <code>null</code>
|
||||
* @return encoded size of the formula tokens (does not include 2 bytes for ushort length)
|
||||
*/
|
||||
protected static int getFormulaSize(Formula formula) {
|
||||
return formula.getEncodedTokenSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea
|
||||
* this call will produce the wrong results if the formula contains any cell references
|
||||
* One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int)
|
||||
* Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects.
|
||||
*
|
||||
* @return <code>null</code> if <tt>formula</tt> was null.
|
||||
*/
|
||||
public static Ptg[] parseFormula(String formula, HSSFSheet sheet) {
|
||||
if(formula == null) {
|
||||
return null;
|
||||
}
|
||||
int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
|
||||
return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex);
|
||||
}
|
||||
|
||||
protected void copyTo(CFRuleBase rec) {
|
||||
rec.condition_type = condition_type;
|
||||
rec.comparison_operator = comparison_operator;
|
||||
|
||||
rec.formatting_options = formatting_options;
|
||||
rec.formatting_not_used = formatting_not_used;
|
||||
if (containsFontFormattingBlock()) {
|
||||
rec._fontFormatting = (FontFormatting) _fontFormatting.clone();
|
||||
}
|
||||
if (containsBorderFormattingBlock()) {
|
||||
rec._borderFormatting = (BorderFormatting) _borderFormatting.clone();
|
||||
}
|
||||
if (containsPatternFormattingBlock()) {
|
||||
rec._patternFormatting = (PatternFormatting) _patternFormatting.clone();
|
||||
}
|
||||
|
||||
rec.setFormula1(getFormula1().copy());
|
||||
rec.setFormula2(getFormula2().copy());
|
||||
}
|
||||
}
|
@ -19,512 +19,129 @@ package org.apache.poi.hssf.record;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.hssf.model.HSSFFormulaParser;
|
||||
import org.apache.poi.hssf.record.cf.BorderFormatting;
|
||||
import org.apache.poi.hssf.record.cf.FontFormatting;
|
||||
import org.apache.poi.hssf.record.cf.PatternFormatting;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.ss.formula.Formula;
|
||||
import org.apache.poi.ss.formula.FormulaType;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Conditional Formatting Rule Record (0x01B1).<br/>
|
||||
*
|
||||
* @author Dmitriy Kumshayev
|
||||
* Conditional Formatting Rule Record (0x01B1).
|
||||
*
|
||||
* <p>This is for the older-style Excel conditional formattings,
|
||||
* new-style (Excel 2007+) also make use of {@link CFRule12Record}
|
||||
* and {@link CFExRuleRecord} for their rules.
|
||||
*/
|
||||
public final class CFRuleRecord extends StandardRecord {
|
||||
public final class CFRuleRecord extends CFRuleBase {
|
||||
public static final short sid = 0x01B1;
|
||||
|
||||
public static final short sid = 0x01B1;
|
||||
/** Creates new CFRuleRecord */
|
||||
private CFRuleRecord(byte conditionType, byte comparisonOperation) {
|
||||
super(conditionType, comparisonOperation);
|
||||
setDefaults();
|
||||
}
|
||||
|
||||
public static final class ComparisonOperator {
|
||||
public static final byte NO_COMPARISON = 0;
|
||||
public static final byte BETWEEN = 1;
|
||||
public static final byte NOT_BETWEEN = 2;
|
||||
public static final byte EQUAL = 3;
|
||||
public static final byte NOT_EQUAL = 4;
|
||||
public static final byte GT = 5;
|
||||
public static final byte LT = 6;
|
||||
public static final byte GE = 7;
|
||||
public static final byte LE = 8;
|
||||
}
|
||||
private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) {
|
||||
super(conditionType, comparisonOperation, formula1, formula2);
|
||||
setDefaults();
|
||||
}
|
||||
private void setDefaults() {
|
||||
// Set modification flags to 1: by default options are not modified
|
||||
formatting_options = modificationBits.setValue(formatting_options, -1);
|
||||
// Set formatting block flags to 0 (no formatting blocks)
|
||||
formatting_options = fmtBlockBits.setValue(formatting_options, 0);
|
||||
formatting_options = undocumented.clear(formatting_options);
|
||||
|
||||
private byte field_1_condition_type;
|
||||
public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1;
|
||||
public static final byte CONDITION_TYPE_FORMULA = 2;
|
||||
formatting_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads
|
||||
_fontFormatting = null;
|
||||
_borderFormatting = null;
|
||||
_patternFormatting = null;
|
||||
}
|
||||
|
||||
private byte field_2_comparison_operator;
|
||||
|
||||
private int field_5_options;
|
||||
|
||||
private static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot
|
||||
private static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified
|
||||
private static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified
|
||||
private static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified
|
||||
private static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified
|
||||
private static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified
|
||||
private static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified
|
||||
private static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified
|
||||
private static final BitField notUsed1 = bf(0x00000080); // Always 1
|
||||
private static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified
|
||||
private static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified
|
||||
private static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified
|
||||
private static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified
|
||||
private static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified
|
||||
private static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified
|
||||
private static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified
|
||||
private static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified
|
||||
private static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified
|
||||
private static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified
|
||||
private static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified
|
||||
private static final BitField notUsed2 = bf(0x00380000); // Always 111
|
||||
private static final BitField undocumented = bf(0x03C00000); // Undocumented bits
|
||||
private static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot
|
||||
private static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block
|
||||
private static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block
|
||||
private static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block
|
||||
private static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block
|
||||
private static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block
|
||||
private static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified
|
||||
|
||||
|
||||
private static BitField bf(int i) {
|
||||
return BitFieldFactory.getInstance(i);
|
||||
}
|
||||
|
||||
private short field_6_not_used;
|
||||
|
||||
private FontFormatting _fontFormatting;
|
||||
|
||||
private BorderFormatting _borderFormatting;
|
||||
|
||||
private PatternFormatting _patternFormatting;
|
||||
|
||||
private Formula field_17_formula1;
|
||||
private Formula field_18_formula2;
|
||||
|
||||
/** Creates new CFRuleRecord */
|
||||
private CFRuleRecord(byte conditionType, byte comparisonOperation)
|
||||
{
|
||||
field_1_condition_type=conditionType;
|
||||
field_2_comparison_operator=comparisonOperation;
|
||||
|
||||
// Set modification flags to 1: by default options are not modified
|
||||
field_5_options = modificationBits.setValue(field_5_options, -1);
|
||||
// Set formatting block flags to 0 (no formatting blocks)
|
||||
field_5_options = fmtBlockBits.setValue(field_5_options, 0);
|
||||
field_5_options = undocumented.clear(field_5_options);
|
||||
|
||||
field_6_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads
|
||||
_fontFormatting=null;
|
||||
_borderFormatting=null;
|
||||
_patternFormatting=null;
|
||||
field_17_formula1=Formula.create(Ptg.EMPTY_PTG_ARRAY);
|
||||
field_18_formula2=Formula.create(Ptg.EMPTY_PTG_ARRAY);
|
||||
}
|
||||
|
||||
private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) {
|
||||
this(conditionType, comparisonOperation);
|
||||
field_17_formula1 = Formula.create(formula1);
|
||||
field_18_formula2 = Formula.create(formula2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
public static CFRuleRecord create(HSSFSheet sheet, String formulaText) {
|
||||
Ptg[] formula1 = parseFormula(formulaText, sheet);
|
||||
return new CFRuleRecord(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON,
|
||||
formula1, null);
|
||||
}
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation,
|
||||
String formulaText1, String formulaText2) {
|
||||
Ptg[] formula1 = parseFormula(formulaText1, sheet);
|
||||
Ptg[] formula2 = parseFormula(formulaText2, sheet);
|
||||
return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2);
|
||||
}
|
||||
/**
|
||||
* Creates a new comparison operation rule
|
||||
*/
|
||||
public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation,
|
||||
String formulaText1, String formulaText2) {
|
||||
Ptg[] formula1 = parseFormula(formulaText1, sheet);
|
||||
Ptg[] formula2 = parseFormula(formulaText2, sheet);
|
||||
return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2);
|
||||
}
|
||||
|
||||
public CFRuleRecord(RecordInputStream in) {
|
||||
field_1_condition_type = in.readByte();
|
||||
field_2_comparison_operator = in.readByte();
|
||||
int field_3_formula1_len = in.readUShort();
|
||||
int field_4_formula2_len = in.readUShort();
|
||||
field_5_options = in.readInt();
|
||||
field_6_not_used = in.readShort();
|
||||
public CFRuleRecord(RecordInputStream in) {
|
||||
setConditionType(in.readByte());
|
||||
setComparisonOperation(in.readByte());
|
||||
int field_3_formula1_len = in.readUShort();
|
||||
int field_4_formula2_len = in.readUShort();
|
||||
readFormatOptions(in);
|
||||
|
||||
if (containsFontFormattingBlock()) {
|
||||
_fontFormatting = new FontFormatting(in);
|
||||
}
|
||||
// "You may not use unions, intersections or array constants in Conditional Formatting criteria"
|
||||
setFormula1(Formula.read(field_3_formula1_len, in));
|
||||
setFormula2(Formula.read(field_4_formula2_len, in));
|
||||
}
|
||||
|
||||
if (containsBorderFormattingBlock()) {
|
||||
_borderFormatting = new BorderFormatting(in);
|
||||
}
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
if (containsPatternFormattingBlock()) {
|
||||
_patternFormatting = new PatternFormatting(in);
|
||||
}
|
||||
/**
|
||||
* called by the class that is responsible for writing this sucker.
|
||||
* Subclasses should implement this so that their data is passed back in a
|
||||
* byte array.
|
||||
*
|
||||
* @param out the stream to write to
|
||||
*/
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
int formula1Len=getFormulaSize(getFormula1());
|
||||
int formula2Len=getFormulaSize(getFormula2());
|
||||
|
||||
// "You may not use unions, intersections or array constants in Conditional Formatting criteria"
|
||||
field_17_formula1 = Formula.read(field_3_formula1_len, in);
|
||||
field_18_formula2 = Formula.read(field_4_formula2_len, in);
|
||||
}
|
||||
out.writeByte(getConditionType());
|
||||
out.writeByte(getComparisonOperation());
|
||||
out.writeShort(formula1Len);
|
||||
out.writeShort(formula2Len);
|
||||
|
||||
serializeFormattingBlock(out);
|
||||
|
||||
public byte getConditionType()
|
||||
{
|
||||
return field_1_condition_type;
|
||||
}
|
||||
getFormula1().serializeTokens(out);
|
||||
getFormula2().serializeTokens(out);
|
||||
}
|
||||
|
||||
public boolean containsFontFormattingBlock()
|
||||
{
|
||||
return getOptionFlag(font);
|
||||
}
|
||||
public void setFontFormatting(FontFormatting fontFormatting)
|
||||
{
|
||||
_fontFormatting = fontFormatting;
|
||||
setOptionFlag(fontFormatting != null, font);
|
||||
}
|
||||
public FontFormatting getFontFormatting()
|
||||
{
|
||||
if( containsFontFormattingBlock())
|
||||
{
|
||||
return _fontFormatting;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
protected int getDataSize() {
|
||||
return 6 + getFormattingBlockSize() +
|
||||
getFormulaSize(getFormula1())+
|
||||
getFormulaSize(getFormula2());
|
||||
}
|
||||
|
||||
public boolean containsAlignFormattingBlock()
|
||||
{
|
||||
return getOptionFlag(align);
|
||||
}
|
||||
public void setAlignFormattingUnchanged()
|
||||
{
|
||||
setOptionFlag(false,align);
|
||||
}
|
||||
|
||||
public boolean containsBorderFormattingBlock()
|
||||
{
|
||||
return getOptionFlag(bord);
|
||||
}
|
||||
public void setBorderFormatting(BorderFormatting borderFormatting)
|
||||
{
|
||||
_borderFormatting = borderFormatting;
|
||||
setOptionFlag(borderFormatting != null, bord);
|
||||
}
|
||||
public BorderFormatting getBorderFormatting()
|
||||
{
|
||||
if( containsBorderFormattingBlock())
|
||||
{
|
||||
return _borderFormatting;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean containsPatternFormattingBlock()
|
||||
{
|
||||
return getOptionFlag(patt);
|
||||
}
|
||||
public void setPatternFormatting(PatternFormatting patternFormatting)
|
||||
{
|
||||
_patternFormatting = patternFormatting;
|
||||
setOptionFlag(patternFormatting!=null, patt);
|
||||
}
|
||||
public PatternFormatting getPatternFormatting()
|
||||
{
|
||||
if( containsPatternFormattingBlock())
|
||||
{
|
||||
return _patternFormatting;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean containsProtectionFormattingBlock()
|
||||
{
|
||||
return getOptionFlag(prot);
|
||||
}
|
||||
public void setProtectionFormattingUnchanged()
|
||||
{
|
||||
setOptionFlag(false,prot);
|
||||
}
|
||||
|
||||
public void setComparisonOperation(byte operation)
|
||||
{
|
||||
field_2_comparison_operator = operation;
|
||||
}
|
||||
|
||||
public byte getComparisonOperation()
|
||||
{
|
||||
return field_2_comparison_operator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get the option flags
|
||||
*
|
||||
* @return bit mask
|
||||
*/
|
||||
public int getOptions()
|
||||
{
|
||||
return field_5_options;
|
||||
}
|
||||
|
||||
private boolean isModified(BitField field)
|
||||
{
|
||||
return !field.isSet(field_5_options);
|
||||
}
|
||||
|
||||
private void setModified(boolean modified, BitField field)
|
||||
{
|
||||
field_5_options = field.setBoolean(field_5_options, !modified);
|
||||
}
|
||||
|
||||
public boolean isLeftBorderModified()
|
||||
{
|
||||
return isModified(bordLeft);
|
||||
}
|
||||
|
||||
public void setLeftBorderModified(boolean modified)
|
||||
{
|
||||
setModified(modified,bordLeft);
|
||||
}
|
||||
|
||||
public boolean isRightBorderModified()
|
||||
{
|
||||
return isModified(bordRight);
|
||||
}
|
||||
|
||||
public void setRightBorderModified(boolean modified)
|
||||
{
|
||||
setModified(modified,bordRight);
|
||||
}
|
||||
|
||||
public boolean isTopBorderModified()
|
||||
{
|
||||
return isModified(bordTop);
|
||||
}
|
||||
|
||||
public void setTopBorderModified(boolean modified)
|
||||
{
|
||||
setModified(modified,bordTop);
|
||||
}
|
||||
|
||||
public boolean isBottomBorderModified()
|
||||
{
|
||||
return isModified(bordBot);
|
||||
}
|
||||
|
||||
public void setBottomBorderModified(boolean modified)
|
||||
{
|
||||
setModified(modified,bordBot);
|
||||
}
|
||||
|
||||
public boolean isTopLeftBottomRightBorderModified()
|
||||
{
|
||||
return isModified(bordTlBr);
|
||||
}
|
||||
|
||||
public void setTopLeftBottomRightBorderModified(boolean modified)
|
||||
{
|
||||
setModified(modified,bordTlBr);
|
||||
}
|
||||
|
||||
public boolean isBottomLeftTopRightBorderModified()
|
||||
{
|
||||
return isModified(bordBlTr);
|
||||
}
|
||||
|
||||
public void setBottomLeftTopRightBorderModified(boolean modified)
|
||||
{
|
||||
setModified(modified,bordBlTr);
|
||||
}
|
||||
|
||||
public boolean isPatternStyleModified()
|
||||
{
|
||||
return isModified(pattStyle);
|
||||
}
|
||||
|
||||
public void setPatternStyleModified(boolean modified)
|
||||
{
|
||||
setModified(modified,pattStyle);
|
||||
}
|
||||
|
||||
public boolean isPatternColorModified()
|
||||
{
|
||||
return isModified(pattCol);
|
||||
}
|
||||
|
||||
public void setPatternColorModified(boolean modified)
|
||||
{
|
||||
setModified(modified,pattCol);
|
||||
}
|
||||
|
||||
public boolean isPatternBackgroundColorModified()
|
||||
{
|
||||
return isModified(pattBgCol);
|
||||
}
|
||||
|
||||
public void setPatternBackgroundColorModified(boolean modified)
|
||||
{
|
||||
setModified(modified,pattBgCol);
|
||||
}
|
||||
|
||||
private boolean getOptionFlag(BitField field)
|
||||
{
|
||||
return field.isSet(field_5_options);
|
||||
}
|
||||
|
||||
private void setOptionFlag(boolean flag, BitField field)
|
||||
{
|
||||
field_5_options = field.setBoolean(field_5_options, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the stack of the 1st expression as a list
|
||||
*
|
||||
* @return list of tokens (casts stack to a list and returns it!)
|
||||
* this method can return null is we are unable to create Ptgs from
|
||||
* existing excel file
|
||||
* callers should check for null!
|
||||
*/
|
||||
|
||||
public Ptg[] getParsedExpression1()
|
||||
{
|
||||
return field_17_formula1.getTokens();
|
||||
}
|
||||
public void setParsedExpression1(Ptg[] ptgs) {
|
||||
field_17_formula1 = Formula.create(ptgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the stack of the 2nd expression as a list
|
||||
*
|
||||
* @return array of {@link Ptg}s, possibly <code>null</code>
|
||||
*/
|
||||
public Ptg[] getParsedExpression2() {
|
||||
return Formula.getTokens(field_18_formula2);
|
||||
}
|
||||
public void setParsedExpression2(Ptg[] ptgs) {
|
||||
field_18_formula2 = Formula.create(ptgs);
|
||||
}
|
||||
|
||||
public short getSid()
|
||||
{
|
||||
return sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ptgs must not be <code>null</code>
|
||||
* @return encoded size of the formula tokens (does not include 2 bytes for ushort length)
|
||||
*/
|
||||
private static int getFormulaSize(Formula formula) {
|
||||
return formula.getEncodedTokenSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* called by the class that is responsible for writing this sucker.
|
||||
* Subclasses should implement this so that their data is passed back in a
|
||||
* byte array.
|
||||
*
|
||||
* @param out the stream to write to
|
||||
*/
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
|
||||
int formula1Len=getFormulaSize(field_17_formula1);
|
||||
int formula2Len=getFormulaSize(field_18_formula2);
|
||||
|
||||
out.writeByte(field_1_condition_type);
|
||||
out.writeByte(field_2_comparison_operator);
|
||||
out.writeShort(formula1Len);
|
||||
out.writeShort(formula2Len);
|
||||
out.writeInt(field_5_options);
|
||||
out.writeShort(field_6_not_used);
|
||||
|
||||
if (containsFontFormattingBlock()) {
|
||||
byte[] fontFormattingRawRecord = _fontFormatting.getRawRecord();
|
||||
out.write(fontFormattingRawRecord);
|
||||
}
|
||||
|
||||
if (containsBorderFormattingBlock()) {
|
||||
_borderFormatting.serialize(out);
|
||||
}
|
||||
|
||||
if (containsPatternFormattingBlock()) {
|
||||
_patternFormatting.serialize(out);
|
||||
}
|
||||
|
||||
field_17_formula1.serializeTokens(out);
|
||||
field_18_formula2.serializeTokens(out);
|
||||
}
|
||||
|
||||
protected int getDataSize() {
|
||||
int i = 12 +
|
||||
(containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+
|
||||
(containsBorderFormattingBlock()?8:0)+
|
||||
(containsPatternFormattingBlock()?4:0)+
|
||||
getFormulaSize(field_17_formula1)+
|
||||
getFormulaSize(field_18_formula2);
|
||||
return i
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("[CFRULE]\n");
|
||||
buffer.append(" .condition_type =").append(field_1_condition_type).append("\n");
|
||||
buffer.append(" OPTION FLAGS=0x").append(Integer.toHexString(getOptions())).append("\n");
|
||||
if (containsFontFormattingBlock()) {
|
||||
buffer.append(_fontFormatting.toString()).append("\n");
|
||||
}
|
||||
if (containsBorderFormattingBlock()) {
|
||||
buffer.append(_borderFormatting.toString()).append("\n");
|
||||
}
|
||||
if (containsPatternFormattingBlock()) {
|
||||
buffer.append(_patternFormatting.toString()).append("\n");
|
||||
}
|
||||
buffer.append(" Formula 1 =").append(Arrays.toString(field_17_formula1.getTokens())).append("\n");
|
||||
buffer.append(" Formula 2 =").append(Arrays.toString(field_18_formula2.getTokens())).append("\n");
|
||||
buffer.append("[/CFRULE]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, field_2_comparison_operator);
|
||||
rec.field_5_options = field_5_options;
|
||||
rec.field_6_not_used = field_6_not_used;
|
||||
if (containsFontFormattingBlock()) {
|
||||
rec._fontFormatting = (FontFormatting) _fontFormatting.clone();
|
||||
}
|
||||
if (containsBorderFormattingBlock()) {
|
||||
rec._borderFormatting = (BorderFormatting) _borderFormatting.clone();
|
||||
}
|
||||
if (containsPatternFormattingBlock()) {
|
||||
rec._patternFormatting = (PatternFormatting) _patternFormatting.clone();
|
||||
}
|
||||
rec.field_17_formula1 = field_17_formula1.copy();
|
||||
rec.field_18_formula2 = field_18_formula2.copy();
|
||||
|
||||
return rec;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea
|
||||
* this call will produce the wrong results if the formula contains any cell references
|
||||
* One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int)
|
||||
* Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects.
|
||||
*
|
||||
* @return <code>null</code> if <tt>formula</tt> was null.
|
||||
*/
|
||||
private static Ptg[] parseFormula(String formula, HSSFSheet sheet) {
|
||||
if(formula == null) {
|
||||
return null;
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("[CFRULE]\n");
|
||||
buffer.append(" .condition_type =").append(getConditionType()).append("\n");
|
||||
buffer.append(" OPTION FLAGS=0x").append(Integer.toHexString(getOptions())).append("\n");
|
||||
if (containsFontFormattingBlock()) {
|
||||
buffer.append(_fontFormatting.toString()).append("\n");
|
||||
}
|
||||
int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
|
||||
return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex);
|
||||
if (containsBorderFormattingBlock()) {
|
||||
buffer.append(_borderFormatting.toString()).append("\n");
|
||||
}
|
||||
if (containsPatternFormattingBlock()) {
|
||||
buffer.append(_patternFormatting.toString()).append("\n");
|
||||
}
|
||||
buffer.append(" Formula 1 =").append(Arrays.toString(getFormula1().getTokens())).append("\n");
|
||||
buffer.append(" Formula 2 =").append(Arrays.toString(getFormula2().getTokens())).append("\n");
|
||||
buffer.append("[/CFRULE]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
CFRuleRecord rec = new CFRuleRecord(getConditionType(), getComparisonOperation());
|
||||
super.copyTo(rec);
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,11 @@ import org.apache.poi.util.POILogger;
|
||||
* up with a {@link FeatHdrRecord}.
|
||||
*/
|
||||
public final class FeatRecord extends StandardRecord {
|
||||
private static POILogger logger = POILogFactory.getLogger(FeatRecord.class);
|
||||
public final static short sid = 0x0868;
|
||||
private static POILogger logger = POILogFactory.getLogger(FeatRecord.class);
|
||||
public final static short sid = 0x0868;
|
||||
// SIDs from newer versions
|
||||
public final static short v11_sid = 0x0872;
|
||||
public final static short v12_sid = 0x0878;
|
||||
|
||||
private FtrHeader futureHeader;
|
||||
|
||||
|
@ -62,17 +62,27 @@ public final class NameCommentRecord extends StandardRecord {
|
||||
out.writeShort(field_4_name_length);
|
||||
out.writeShort(field_5_comment_length);
|
||||
|
||||
out.writeByte(0);
|
||||
StringUtil.putCompressedUnicode(field_6_name_text, out);
|
||||
out.writeByte(0);
|
||||
StringUtil.putCompressedUnicode(field_7_comment_text, out);
|
||||
boolean isNameMultiByte = StringUtil.hasMultibyte(field_6_name_text);
|
||||
out.writeByte(isNameMultiByte ? 1 : 0);
|
||||
if (isNameMultiByte) {
|
||||
StringUtil.putUnicodeLE(field_6_name_text, out);
|
||||
} else {
|
||||
StringUtil.putCompressedUnicode(field_6_name_text, out);
|
||||
}
|
||||
boolean isCommentMultiByte = StringUtil.hasMultibyte(field_7_comment_text);
|
||||
out.writeByte(isCommentMultiByte ? 1 : 0);
|
||||
if (isCommentMultiByte) {
|
||||
StringUtil.putUnicodeLE(field_7_comment_text, out);
|
||||
} else {
|
||||
StringUtil.putCompressedUnicode(field_7_comment_text, out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDataSize() {
|
||||
return 18 // 4 shorts + 1 long + 2 spurious 'nul's
|
||||
+ field_6_name_text.length()
|
||||
+ field_7_comment_text.length();
|
||||
+ (StringUtil.hasMultibyte(field_6_name_text) ? field_6_name_text.length()*2 : field_6_name_text.length())
|
||||
+ (StringUtil.hasMultibyte(field_7_comment_text) ? field_7_comment_text.length()*2 : field_7_comment_text.length());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,10 +96,16 @@ public final class NameCommentRecord extends StandardRecord {
|
||||
final int field_4_name_length = in.readShort();
|
||||
final int field_5_comment_length = in.readShort();
|
||||
|
||||
in.readByte(); //spurious NUL
|
||||
field_6_name_text = StringUtil.readCompressedUnicode(in, field_4_name_length);
|
||||
in.readByte(); //spurious NUL
|
||||
field_7_comment_text = StringUtil.readCompressedUnicode(in, field_5_comment_length);
|
||||
if (in.readByte() == 0) {
|
||||
field_6_name_text = StringUtil.readCompressedUnicode(in, field_4_name_length);
|
||||
} else {
|
||||
field_6_name_text = StringUtil.readUnicodeLE(in, field_4_name_length);
|
||||
}
|
||||
if (in.readByte() == 0) {
|
||||
field_7_comment_text = StringUtil.readCompressedUnicode(in, field_5_comment_length);
|
||||
} else {
|
||||
field_7_comment_text = StringUtil.readUnicodeLE(in, field_5_comment_length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,11 +411,12 @@ public final class NameRecord extends ContinuableRecord {
|
||||
* @return extern sheet index
|
||||
*/
|
||||
public int getExternSheetNumber(){
|
||||
if (field_13_name_definition.getEncodedSize() < 1) {
|
||||
Ptg[] tokens = field_13_name_definition.getTokens();
|
||||
if (tokens.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
Ptg ptg = field_13_name_definition.getTokens()[0];
|
||||
|
||||
Ptg ptg = tokens[0];
|
||||
if (ptg.getClass() == Area3DPtg.class){
|
||||
return ((Area3DPtg) ptg).getExternSheetIndex();
|
||||
|
||||
|
@ -62,425 +62,420 @@ import org.apache.poi.hssf.record.pivottable.ViewSourceRecord;
|
||||
* Description: Takes a stream and outputs an array of Record objects.<P>
|
||||
*
|
||||
* @see org.apache.poi.hssf.eventmodel.EventRecordFactory
|
||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Marc Johnson (mjohnson at apache dot org)
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
* @author Csaba Nagy (ncsaba at yahoo dot com)
|
||||
*/
|
||||
public final class RecordFactory {
|
||||
private static final int NUM_RECORDS = 512;
|
||||
private static final int NUM_RECORDS = 512;
|
||||
|
||||
private interface I_RecordCreator {
|
||||
Record create(RecordInputStream in);
|
||||
private interface I_RecordCreator {
|
||||
Record create(RecordInputStream in);
|
||||
|
||||
Class<? extends Record> getRecordClass();
|
||||
}
|
||||
private static final class ReflectionConstructorRecordCreator implements I_RecordCreator {
|
||||
Class<? extends Record> getRecordClass();
|
||||
}
|
||||
private static final class ReflectionConstructorRecordCreator implements I_RecordCreator {
|
||||
|
||||
private final Constructor<? extends Record> _c;
|
||||
public ReflectionConstructorRecordCreator(Constructor<? extends Record> c) {
|
||||
_c = c;
|
||||
}
|
||||
public Record create(RecordInputStream in) {
|
||||
Object[] args = { in, };
|
||||
try {
|
||||
return _c.newInstance(args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable t = e.getTargetException();
|
||||
if (t instanceof RecordFormatException) {
|
||||
throw (RecordFormatException)t;
|
||||
} else if (t instanceof EncryptedDocumentException) {
|
||||
throw (EncryptedDocumentException)t;
|
||||
} else {
|
||||
throw new RecordFormatException("Unable to construct record instance" , t);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Class<? extends Record> getRecordClass() {
|
||||
return _c.getDeclaringClass();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A "create" method is used instead of the usual constructor if the created record might
|
||||
* be of a different class to the declaring class.
|
||||
*/
|
||||
private static final class ReflectionMethodRecordCreator implements I_RecordCreator {
|
||||
private final Constructor<? extends Record> _c;
|
||||
public ReflectionConstructorRecordCreator(Constructor<? extends Record> c) {
|
||||
_c = c;
|
||||
}
|
||||
public Record create(RecordInputStream in) {
|
||||
Object[] args = { in, };
|
||||
try {
|
||||
return _c.newInstance(args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable t = e.getTargetException();
|
||||
if (t instanceof RecordFormatException) {
|
||||
throw (RecordFormatException)t;
|
||||
} else if (t instanceof EncryptedDocumentException) {
|
||||
throw (EncryptedDocumentException)t;
|
||||
} else {
|
||||
throw new RecordFormatException("Unable to construct record instance" , t);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Class<? extends Record> getRecordClass() {
|
||||
return _c.getDeclaringClass();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A "create" method is used instead of the usual constructor if the created record might
|
||||
* be of a different class to the declaring class.
|
||||
*/
|
||||
private static final class ReflectionMethodRecordCreator implements I_RecordCreator {
|
||||
private final Method _m;
|
||||
public ReflectionMethodRecordCreator(Method m) {
|
||||
_m = m;
|
||||
}
|
||||
public Record create(RecordInputStream in) {
|
||||
Object[] args = { in, };
|
||||
try {
|
||||
return (Record) _m.invoke(null, args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RecordFormatException("Unable to construct record instance" , e.getTargetException());
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends Record> getRecordClass() {
|
||||
return (Class<? extends Record>) _m.getDeclaringClass();
|
||||
}
|
||||
}
|
||||
|
||||
private final Method _m;
|
||||
public ReflectionMethodRecordCreator(Method m) {
|
||||
_m = m;
|
||||
}
|
||||
public Record create(RecordInputStream in) {
|
||||
Object[] args = { in, };
|
||||
try {
|
||||
return (Record) _m.invoke(null, args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RecordFormatException("Unable to construct record instance" , e.getTargetException());
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends Record> getRecordClass() {
|
||||
return (Class<? extends Record>) _m.getDeclaringClass();
|
||||
}
|
||||
}
|
||||
private static final Class<?>[] CONSTRUCTOR_ARGS = { RecordInputStream.class, };
|
||||
|
||||
|
||||
private static final Class<?>[] CONSTRUCTOR_ARGS = { RecordInputStream.class, };
|
||||
|
||||
/**
|
||||
* contains the classes for all the records we want to parse.<br/>
|
||||
* Note - this most but not *every* subclass of Record.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Class<? extends Record>[] recordClasses = new Class[] {
|
||||
ArrayRecord.class,
|
||||
/**
|
||||
* contains the classes for all the records we want to parse.<br/>
|
||||
* Note - this most but not *every* subclass of Record.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Class<? extends Record>[] recordClasses = new Class[] {
|
||||
ArrayRecord.class,
|
||||
AutoFilterInfoRecord.class,
|
||||
BackupRecord.class,
|
||||
BlankRecord.class,
|
||||
BOFRecord.class,
|
||||
BookBoolRecord.class,
|
||||
BoolErrRecord.class,
|
||||
BottomMarginRecord.class,
|
||||
BoundSheetRecord.class,
|
||||
CalcCountRecord.class,
|
||||
CalcModeRecord.class,
|
||||
CFHeaderRecord.class,
|
||||
CFRuleRecord.class,
|
||||
ChartRecord.class,
|
||||
ChartTitleFormatRecord.class,
|
||||
CodepageRecord.class,
|
||||
ColumnInfoRecord.class,
|
||||
ContinueRecord.class,
|
||||
CountryRecord.class,
|
||||
CRNCountRecord.class,
|
||||
CRNRecord.class,
|
||||
DateWindow1904Record.class,
|
||||
DBCellRecord.class,
|
||||
DConRefRecord.class,
|
||||
DefaultColWidthRecord.class,
|
||||
DefaultRowHeightRecord.class,
|
||||
DeltaRecord.class,
|
||||
DimensionsRecord.class,
|
||||
DrawingGroupRecord.class,
|
||||
DrawingRecord.class,
|
||||
DrawingSelectionRecord.class,
|
||||
DSFRecord.class,
|
||||
DVALRecord.class,
|
||||
DVRecord.class,
|
||||
EOFRecord.class,
|
||||
ExtendedFormatRecord.class,
|
||||
ExternalNameRecord.class,
|
||||
ExternSheetRecord.class,
|
||||
ExtSSTRecord.class,
|
||||
FeatRecord.class,
|
||||
FeatHdrRecord.class,
|
||||
FilePassRecord.class,
|
||||
FileSharingRecord.class,
|
||||
FnGroupCountRecord.class,
|
||||
FontRecord.class,
|
||||
FooterRecord.class,
|
||||
FormatRecord.class,
|
||||
FormulaRecord.class,
|
||||
GridsetRecord.class,
|
||||
GutsRecord.class,
|
||||
HCenterRecord.class,
|
||||
HeaderRecord.class,
|
||||
BlankRecord.class,
|
||||
BOFRecord.class,
|
||||
BookBoolRecord.class,
|
||||
BoolErrRecord.class,
|
||||
BottomMarginRecord.class,
|
||||
BoundSheetRecord.class,
|
||||
CalcCountRecord.class,
|
||||
CalcModeRecord.class,
|
||||
CFHeaderRecord.class,
|
||||
CFHeader12Record.class,
|
||||
CFRuleRecord.class,
|
||||
CFRule12Record.class,
|
||||
ChartRecord.class,
|
||||
ChartTitleFormatRecord.class,
|
||||
CodepageRecord.class,
|
||||
ColumnInfoRecord.class,
|
||||
ContinueRecord.class,
|
||||
CountryRecord.class,
|
||||
CRNCountRecord.class,
|
||||
CRNRecord.class,
|
||||
DateWindow1904Record.class,
|
||||
DBCellRecord.class,
|
||||
DConRefRecord.class,
|
||||
DefaultColWidthRecord.class,
|
||||
DefaultRowHeightRecord.class,
|
||||
DeltaRecord.class,
|
||||
DimensionsRecord.class,
|
||||
DrawingGroupRecord.class,
|
||||
DrawingRecord.class,
|
||||
DrawingSelectionRecord.class,
|
||||
DSFRecord.class,
|
||||
DVALRecord.class,
|
||||
DVRecord.class,
|
||||
EOFRecord.class,
|
||||
ExtendedFormatRecord.class,
|
||||
ExternalNameRecord.class,
|
||||
ExternSheetRecord.class,
|
||||
ExtSSTRecord.class,
|
||||
FeatRecord.class,
|
||||
FeatHdrRecord.class,
|
||||
FilePassRecord.class,
|
||||
FileSharingRecord.class,
|
||||
FnGroupCountRecord.class,
|
||||
FontRecord.class,
|
||||
FooterRecord.class,
|
||||
FormatRecord.class,
|
||||
FormulaRecord.class,
|
||||
GridsetRecord.class,
|
||||
GutsRecord.class,
|
||||
HCenterRecord.class,
|
||||
HeaderRecord.class,
|
||||
HeaderFooterRecord.class,
|
||||
HideObjRecord.class,
|
||||
HorizontalPageBreakRecord.class,
|
||||
HyperlinkRecord.class,
|
||||
IndexRecord.class,
|
||||
InterfaceEndRecord.class,
|
||||
InterfaceHdrRecord.class,
|
||||
IterationRecord.class,
|
||||
LabelRecord.class,
|
||||
LabelSSTRecord.class,
|
||||
LeftMarginRecord.class,
|
||||
LegendRecord.class,
|
||||
MergeCellsRecord.class,
|
||||
MMSRecord.class,
|
||||
MulBlankRecord.class,
|
||||
MulRKRecord.class,
|
||||
NameRecord.class,
|
||||
NameCommentRecord.class,
|
||||
NoteRecord.class,
|
||||
NumberRecord.class,
|
||||
ObjectProtectRecord.class,
|
||||
ObjRecord.class,
|
||||
PaletteRecord.class,
|
||||
PaneRecord.class,
|
||||
PasswordRecord.class,
|
||||
PasswordRev4Record.class,
|
||||
PrecisionRecord.class,
|
||||
PrintGridlinesRecord.class,
|
||||
PrintHeadersRecord.class,
|
||||
PrintSetupRecord.class,
|
||||
ProtectionRev4Record.class,
|
||||
ProtectRecord.class,
|
||||
RecalcIdRecord.class,
|
||||
RefModeRecord.class,
|
||||
RefreshAllRecord.class,
|
||||
RightMarginRecord.class,
|
||||
RKRecord.class,
|
||||
RowRecord.class,
|
||||
SaveRecalcRecord.class,
|
||||
ScenarioProtectRecord.class,
|
||||
SelectionRecord.class,
|
||||
SeriesRecord.class,
|
||||
SeriesTextRecord.class,
|
||||
SharedFormulaRecord.class,
|
||||
SSTRecord.class,
|
||||
StringRecord.class,
|
||||
StyleRecord.class,
|
||||
SupBookRecord.class,
|
||||
TabIdRecord.class,
|
||||
TableRecord.class,
|
||||
TableStylesRecord.class,
|
||||
TextObjectRecord.class,
|
||||
TopMarginRecord.class,
|
||||
UncalcedRecord.class,
|
||||
UseSelFSRecord.class,
|
||||
UserSViewBegin.class,
|
||||
UserSViewEnd.class,
|
||||
ValueRangeRecord.class,
|
||||
VCenterRecord.class,
|
||||
VerticalPageBreakRecord.class,
|
||||
WindowOneRecord.class,
|
||||
WindowProtectRecord.class,
|
||||
WindowTwoRecord.class,
|
||||
WriteAccessRecord.class,
|
||||
WriteProtectRecord.class,
|
||||
WSBoolRecord.class,
|
||||
HideObjRecord.class,
|
||||
HorizontalPageBreakRecord.class,
|
||||
HyperlinkRecord.class,
|
||||
IndexRecord.class,
|
||||
InterfaceEndRecord.class,
|
||||
InterfaceHdrRecord.class,
|
||||
IterationRecord.class,
|
||||
LabelRecord.class,
|
||||
LabelSSTRecord.class,
|
||||
LeftMarginRecord.class,
|
||||
LegendRecord.class,
|
||||
MergeCellsRecord.class,
|
||||
MMSRecord.class,
|
||||
MulBlankRecord.class,
|
||||
MulRKRecord.class,
|
||||
NameRecord.class,
|
||||
NameCommentRecord.class,
|
||||
NoteRecord.class,
|
||||
NumberRecord.class,
|
||||
ObjectProtectRecord.class,
|
||||
ObjRecord.class,
|
||||
PaletteRecord.class,
|
||||
PaneRecord.class,
|
||||
PasswordRecord.class,
|
||||
PasswordRev4Record.class,
|
||||
PrecisionRecord.class,
|
||||
PrintGridlinesRecord.class,
|
||||
PrintHeadersRecord.class,
|
||||
PrintSetupRecord.class,
|
||||
ProtectionRev4Record.class,
|
||||
ProtectRecord.class,
|
||||
RecalcIdRecord.class,
|
||||
RefModeRecord.class,
|
||||
RefreshAllRecord.class,
|
||||
RightMarginRecord.class,
|
||||
RKRecord.class,
|
||||
RowRecord.class,
|
||||
SaveRecalcRecord.class,
|
||||
ScenarioProtectRecord.class,
|
||||
SelectionRecord.class,
|
||||
SeriesRecord.class,
|
||||
SeriesTextRecord.class,
|
||||
SharedFormulaRecord.class,
|
||||
SSTRecord.class,
|
||||
StringRecord.class,
|
||||
StyleRecord.class,
|
||||
SupBookRecord.class,
|
||||
TabIdRecord.class,
|
||||
TableRecord.class,
|
||||
TableStylesRecord.class,
|
||||
TextObjectRecord.class,
|
||||
TopMarginRecord.class,
|
||||
UncalcedRecord.class,
|
||||
UseSelFSRecord.class,
|
||||
UserSViewBegin.class,
|
||||
UserSViewEnd.class,
|
||||
ValueRangeRecord.class,
|
||||
VCenterRecord.class,
|
||||
VerticalPageBreakRecord.class,
|
||||
WindowOneRecord.class,
|
||||
WindowProtectRecord.class,
|
||||
WindowTwoRecord.class,
|
||||
WriteAccessRecord.class,
|
||||
WriteProtectRecord.class,
|
||||
WSBoolRecord.class,
|
||||
|
||||
// chart records
|
||||
BeginRecord.class,
|
||||
ChartFRTInfoRecord.class,
|
||||
ChartStartBlockRecord.class,
|
||||
ChartEndBlockRecord.class,
|
||||
// TODO ChartFormatRecord.class,
|
||||
ChartStartObjectRecord.class,
|
||||
ChartEndObjectRecord.class,
|
||||
CatLabRecord.class,
|
||||
DataFormatRecord.class,
|
||||
EndRecord.class,
|
||||
LinkedDataRecord.class,
|
||||
SeriesToChartGroupRecord.class,
|
||||
// chart records
|
||||
BeginRecord.class,
|
||||
ChartFRTInfoRecord.class,
|
||||
ChartStartBlockRecord.class,
|
||||
ChartEndBlockRecord.class,
|
||||
// TODO ChartFormatRecord.class,
|
||||
ChartStartObjectRecord.class,
|
||||
ChartEndObjectRecord.class,
|
||||
CatLabRecord.class,
|
||||
DataFormatRecord.class,
|
||||
EndRecord.class,
|
||||
LinkedDataRecord.class,
|
||||
SeriesToChartGroupRecord.class,
|
||||
|
||||
// pivot table records
|
||||
DataItemRecord.class,
|
||||
ExtendedPivotTableViewFieldsRecord.class,
|
||||
PageItemRecord.class,
|
||||
StreamIDRecord.class,
|
||||
ViewDefinitionRecord.class,
|
||||
ViewFieldsRecord.class,
|
||||
ViewSourceRecord.class,
|
||||
};
|
||||
// pivot table records
|
||||
DataItemRecord.class,
|
||||
ExtendedPivotTableViewFieldsRecord.class,
|
||||
PageItemRecord.class,
|
||||
StreamIDRecord.class,
|
||||
ViewDefinitionRecord.class,
|
||||
ViewFieldsRecord.class,
|
||||
ViewSourceRecord.class,
|
||||
};
|
||||
|
||||
/**
|
||||
* cache of the recordsToMap();
|
||||
*/
|
||||
private static final Map<Integer, I_RecordCreator> _recordCreatorsById = recordsToMap(recordClasses);
|
||||
/**
|
||||
* cache of the recordsToMap();
|
||||
*/
|
||||
private static final Map<Integer, I_RecordCreator> _recordCreatorsById = recordsToMap(recordClasses);
|
||||
|
||||
private static short[] _allKnownRecordSIDs;
|
||||
private static short[] _allKnownRecordSIDs;
|
||||
|
||||
/**
|
||||
* Debug / diagnosis method<br/>
|
||||
* Gets the POI implementation class for a given <tt>sid</tt>. Only a subset of the any BIFF
|
||||
* records are actually interpreted by POI. A few others are known but not interpreted
|
||||
* (see {@link UnknownRecord#getBiffName(int)}).
|
||||
* @return the POI implementation class for the specified record <tt>sid</tt>.
|
||||
* <code>null</code> if the specified record is not interpreted by POI.
|
||||
*/
|
||||
public static Class<? extends Record> getRecordClass(int sid) {
|
||||
I_RecordCreator rc = _recordCreatorsById.get(Integer.valueOf(sid));
|
||||
if (rc == null) {
|
||||
return null;
|
||||
}
|
||||
return rc.getRecordClass();
|
||||
}
|
||||
/**
|
||||
* create a record, if there are MUL records than multiple records
|
||||
* are returned digested into the non-mul form.
|
||||
*/
|
||||
public static Record [] createRecord(RecordInputStream in) {
|
||||
/**
|
||||
* Debug / diagnosis method<br/>
|
||||
* Gets the POI implementation class for a given <tt>sid</tt>. Only a subset of the any BIFF
|
||||
* records are actually interpreted by POI. A few others are known but not interpreted
|
||||
* (see {@link UnknownRecord#getBiffName(int)}).
|
||||
* @return the POI implementation class for the specified record <tt>sid</tt>.
|
||||
* <code>null</code> if the specified record is not interpreted by POI.
|
||||
*/
|
||||
public static Class<? extends Record> getRecordClass(int sid) {
|
||||
I_RecordCreator rc = _recordCreatorsById.get(Integer.valueOf(sid));
|
||||
if (rc == null) {
|
||||
return null;
|
||||
}
|
||||
return rc.getRecordClass();
|
||||
}
|
||||
/**
|
||||
* create a record, if there are MUL records than multiple records
|
||||
* are returned digested into the non-mul form.
|
||||
*/
|
||||
public static Record [] createRecord(RecordInputStream in) {
|
||||
Record record = createSingleRecord(in);
|
||||
if (record instanceof DBCellRecord) {
|
||||
// Not needed by POI. Regenerated from scratch by POI when spreadsheet is written
|
||||
return new Record[] { null, };
|
||||
}
|
||||
if (record instanceof RKRecord) {
|
||||
return new Record[] { convertToNumberRecord((RKRecord) record), };
|
||||
}
|
||||
if (record instanceof MulRKRecord) {
|
||||
return convertRKRecords((MulRKRecord)record);
|
||||
}
|
||||
return new Record[] { record, };
|
||||
}
|
||||
|
||||
Record record = createSingleRecord(in);
|
||||
if (record instanceof DBCellRecord) {
|
||||
// Not needed by POI. Regenerated from scratch by POI when spreadsheet is written
|
||||
return new Record[] { null, };
|
||||
}
|
||||
if (record instanceof RKRecord) {
|
||||
return new Record[] { convertToNumberRecord((RKRecord) record), };
|
||||
}
|
||||
if (record instanceof MulRKRecord) {
|
||||
return convertRKRecords((MulRKRecord)record);
|
||||
}
|
||||
return new Record[] { record, };
|
||||
}
|
||||
public static Record createSingleRecord(RecordInputStream in) {
|
||||
I_RecordCreator constructor = _recordCreatorsById.get(Integer.valueOf(in.getSid()));
|
||||
|
||||
public static Record createSingleRecord(RecordInputStream in) {
|
||||
I_RecordCreator constructor = _recordCreatorsById.get(Integer.valueOf(in.getSid()));
|
||||
if (constructor == null) {
|
||||
return new UnknownRecord(in);
|
||||
}
|
||||
|
||||
if (constructor == null) {
|
||||
return new UnknownRecord(in);
|
||||
}
|
||||
return constructor.create(in);
|
||||
}
|
||||
|
||||
return constructor.create(in);
|
||||
}
|
||||
/**
|
||||
* RK record is a slightly smaller alternative to NumberRecord
|
||||
* POI likes NumberRecord better
|
||||
*/
|
||||
public static NumberRecord convertToNumberRecord(RKRecord rk) {
|
||||
NumberRecord num = new NumberRecord();
|
||||
|
||||
/**
|
||||
* RK record is a slightly smaller alternative to NumberRecord
|
||||
* POI likes NumberRecord better
|
||||
*/
|
||||
public static NumberRecord convertToNumberRecord(RKRecord rk) {
|
||||
NumberRecord num = new NumberRecord();
|
||||
num.setColumn(rk.getColumn());
|
||||
num.setRow(rk.getRow());
|
||||
num.setXFIndex(rk.getXFIndex());
|
||||
num.setValue(rk.getRKNumber());
|
||||
return num;
|
||||
}
|
||||
|
||||
num.setColumn(rk.getColumn());
|
||||
num.setRow(rk.getRow());
|
||||
num.setXFIndex(rk.getXFIndex());
|
||||
num.setValue(rk.getRKNumber());
|
||||
return num;
|
||||
}
|
||||
/**
|
||||
* Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s
|
||||
*/
|
||||
public static NumberRecord[] convertRKRecords(MulRKRecord mrk) {
|
||||
NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()];
|
||||
for (int k = 0; k < mrk.getNumColumns(); k++) {
|
||||
NumberRecord nr = new NumberRecord();
|
||||
|
||||
/**
|
||||
* Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s
|
||||
*/
|
||||
public static NumberRecord[] convertRKRecords(MulRKRecord mrk) {
|
||||
NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()];
|
||||
for (int k = 0; k < mrk.getNumColumns(); k++) {
|
||||
NumberRecord nr = new NumberRecord();
|
||||
nr.setColumn((short) (k + mrk.getFirstColumn()));
|
||||
nr.setRow(mrk.getRow());
|
||||
nr.setXFIndex(mrk.getXFAt(k));
|
||||
nr.setValue(mrk.getRKNumberAt(k));
|
||||
mulRecs[k] = nr;
|
||||
}
|
||||
return mulRecs;
|
||||
}
|
||||
|
||||
nr.setColumn((short) (k + mrk.getFirstColumn()));
|
||||
nr.setRow(mrk.getRow());
|
||||
nr.setXFIndex(mrk.getXFAt(k));
|
||||
nr.setValue(mrk.getRKNumberAt(k));
|
||||
mulRecs[k] = nr;
|
||||
}
|
||||
return mulRecs;
|
||||
}
|
||||
/**
|
||||
* Converts a {@link MulBlankRecord} into an equivalent array of {@link BlankRecord}s
|
||||
*/
|
||||
public static BlankRecord[] convertBlankRecords(MulBlankRecord mbk) {
|
||||
BlankRecord[] mulRecs = new BlankRecord[mbk.getNumColumns()];
|
||||
for (int k = 0; k < mbk.getNumColumns(); k++) {
|
||||
BlankRecord br = new BlankRecord();
|
||||
|
||||
/**
|
||||
* Converts a {@link MulBlankRecord} into an equivalent array of {@link BlankRecord}s
|
||||
*/
|
||||
public static BlankRecord[] convertBlankRecords(MulBlankRecord mbk) {
|
||||
BlankRecord[] mulRecs = new BlankRecord[mbk.getNumColumns()];
|
||||
for (int k = 0; k < mbk.getNumColumns(); k++) {
|
||||
BlankRecord br = new BlankRecord();
|
||||
br.setColumn((short) (k + mbk.getFirstColumn()));
|
||||
br.setRow(mbk.getRow());
|
||||
br.setXFIndex(mbk.getXFAt(k));
|
||||
mulRecs[k] = br;
|
||||
}
|
||||
return mulRecs;
|
||||
}
|
||||
|
||||
br.setColumn((short) (k + mbk.getFirstColumn()));
|
||||
br.setRow(mbk.getRow());
|
||||
br.setXFIndex(mbk.getXFAt(k));
|
||||
mulRecs[k] = br;
|
||||
}
|
||||
return mulRecs;
|
||||
}
|
||||
/**
|
||||
* @return an array of all the SIDS for all known records
|
||||
*/
|
||||
public static short[] getAllKnownRecordSIDs() {
|
||||
if (_allKnownRecordSIDs == null) {
|
||||
short[] results = new short[ _recordCreatorsById.size() ];
|
||||
int i = 0;
|
||||
|
||||
/**
|
||||
* @return an array of all the SIDS for all known records
|
||||
*/
|
||||
public static short[] getAllKnownRecordSIDs() {
|
||||
if (_allKnownRecordSIDs == null) {
|
||||
short[] results = new short[ _recordCreatorsById.size() ];
|
||||
int i = 0;
|
||||
for (Iterator<Integer> iterator = _recordCreatorsById.keySet().iterator(); iterator.hasNext(); ) {
|
||||
Integer sid = iterator.next();
|
||||
|
||||
for (Iterator<Integer> iterator = _recordCreatorsById.keySet().iterator(); iterator.hasNext(); ) {
|
||||
Integer sid = iterator.next();
|
||||
results[i++] = sid.shortValue();
|
||||
}
|
||||
Arrays.sort(results);
|
||||
_allKnownRecordSIDs = results;
|
||||
}
|
||||
|
||||
results[i++] = sid.shortValue();
|
||||
}
|
||||
Arrays.sort(results);
|
||||
_allKnownRecordSIDs = results;
|
||||
}
|
||||
return _allKnownRecordSIDs.clone();
|
||||
}
|
||||
|
||||
return _allKnownRecordSIDs.clone();
|
||||
}
|
||||
/**
|
||||
* gets the record constructors and sticks them in the map by SID
|
||||
* @return map of SIDs to short,short,byte[] constructors for Record classes
|
||||
* most of org.apache.poi.hssf.record.*
|
||||
*/
|
||||
private static Map<Integer, I_RecordCreator> recordsToMap(Class<? extends Record> [] records) {
|
||||
Map<Integer, I_RecordCreator> result = new HashMap<Integer, I_RecordCreator>();
|
||||
Set<Class<?>> uniqueRecClasses = new HashSet<Class<?>>(records.length * 3 / 2);
|
||||
|
||||
/**
|
||||
* gets the record constructors and sticks them in the map by SID
|
||||
* @return map of SIDs to short,short,byte[] constructors for Record classes
|
||||
* most of org.apache.poi.hssf.record.*
|
||||
*/
|
||||
private static Map<Integer, I_RecordCreator> recordsToMap(Class<? extends Record> [] records) {
|
||||
Map<Integer, I_RecordCreator> result = new HashMap<Integer, I_RecordCreator>();
|
||||
Set<Class<?>> uniqueRecClasses = new HashSet<Class<?>>(records.length * 3 / 2);
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
Class<? extends Record> recClass = records[ i ];
|
||||
if(!Record.class.isAssignableFrom(recClass)) {
|
||||
throw new RuntimeException("Invalid record sub-class (" + recClass.getName() + ")");
|
||||
}
|
||||
if(Modifier.isAbstract(recClass.getModifiers())) {
|
||||
throw new RuntimeException("Invalid record class (" + recClass.getName() + ") - must not be abstract");
|
||||
}
|
||||
if(!uniqueRecClasses.add(recClass)) {
|
||||
throw new RuntimeException("duplicate record class (" + recClass.getName() + ")");
|
||||
}
|
||||
|
||||
Class<? extends Record> recClass = records[ i ];
|
||||
if(!Record.class.isAssignableFrom(recClass)) {
|
||||
throw new RuntimeException("Invalid record sub-class (" + recClass.getName() + ")");
|
||||
}
|
||||
if(Modifier.isAbstract(recClass.getModifiers())) {
|
||||
throw new RuntimeException("Invalid record class (" + recClass.getName() + ") - must not be abstract");
|
||||
}
|
||||
if(!uniqueRecClasses.add(recClass)) {
|
||||
throw new RuntimeException("duplicate record class (" + recClass.getName() + ")");
|
||||
}
|
||||
int sid;
|
||||
try {
|
||||
sid = recClass.getField("sid").getShort(null);
|
||||
} catch (Exception illegalArgumentException) {
|
||||
throw new RecordFormatException(
|
||||
"Unable to determine record types");
|
||||
}
|
||||
Integer key = Integer.valueOf(sid);
|
||||
if (result.containsKey(key)) {
|
||||
Class<?> prevClass = result.get(key).getRecordClass();
|
||||
throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase()
|
||||
+ " for classes (" + recClass.getName() + ") and (" + prevClass.getName() + ")");
|
||||
}
|
||||
result.put(key, getRecordCreator(recClass));
|
||||
}
|
||||
// result.put(Integer.valueOf(0x0406), result.get(Integer.valueOf(0x06)));
|
||||
return result;
|
||||
}
|
||||
|
||||
int sid;
|
||||
try {
|
||||
sid = recClass.getField("sid").getShort(null);
|
||||
} catch (Exception illegalArgumentException) {
|
||||
throw new RecordFormatException(
|
||||
"Unable to determine record types");
|
||||
}
|
||||
Integer key = Integer.valueOf(sid);
|
||||
if (result.containsKey(key)) {
|
||||
Class<?> prevClass = result.get(key).getRecordClass();
|
||||
throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase()
|
||||
+ " for classes (" + recClass.getName() + ") and (" + prevClass.getName() + ")");
|
||||
}
|
||||
result.put(key, getRecordCreator(recClass));
|
||||
}
|
||||
// result.put(Integer.valueOf(0x0406), result.get(Integer.valueOf(0x06)));
|
||||
return result;
|
||||
}
|
||||
private static I_RecordCreator getRecordCreator(Class<? extends Record> recClass) {
|
||||
try {
|
||||
Constructor<? extends Record> constructor;
|
||||
constructor = recClass.getConstructor(CONSTRUCTOR_ARGS);
|
||||
return new ReflectionConstructorRecordCreator(constructor);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// fall through and look for other construction methods
|
||||
}
|
||||
try {
|
||||
Method m = recClass.getDeclaredMethod("create", CONSTRUCTOR_ARGS);
|
||||
return new ReflectionMethodRecordCreator(m);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("Failed to find constructor or create method for (" + recClass.getName() + ").");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create an array of records from an input stream
|
||||
*
|
||||
* @param in the InputStream from which the records will be obtained
|
||||
*
|
||||
* @return an array of Records created from the InputStream
|
||||
*
|
||||
* @exception RecordFormatException on error processing the InputStream
|
||||
*/
|
||||
public static List<Record> createRecords(InputStream in) throws RecordFormatException {
|
||||
|
||||
private static I_RecordCreator getRecordCreator(Class<? extends Record> recClass) {
|
||||
try {
|
||||
Constructor<? extends Record> constructor;
|
||||
constructor = recClass.getConstructor(CONSTRUCTOR_ARGS);
|
||||
return new ReflectionConstructorRecordCreator(constructor);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// fall through and look for other construction methods
|
||||
}
|
||||
try {
|
||||
Method m = recClass.getDeclaredMethod("create", CONSTRUCTOR_ARGS);
|
||||
return new ReflectionMethodRecordCreator(m);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("Failed to find constructor or create method for (" + recClass.getName() + ").");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create an array of records from an input stream
|
||||
*
|
||||
* @param in the InputStream from which the records will be obtained
|
||||
*
|
||||
* @return an array of Records created from the InputStream
|
||||
*
|
||||
* @exception RecordFormatException on error processing the InputStream
|
||||
*/
|
||||
public static List<Record> createRecords(InputStream in) throws RecordFormatException {
|
||||
List<Record> records = new ArrayList<Record>(NUM_RECORDS);
|
||||
|
||||
List<Record> records = new ArrayList<Record>(NUM_RECORDS);
|
||||
RecordFactoryInputStream recStream = new RecordFactoryInputStream(in, true);
|
||||
|
||||
RecordFactoryInputStream recStream = new RecordFactoryInputStream(in, true);
|
||||
Record record;
|
||||
while ((record = recStream.nextRecord())!=null) {
|
||||
records.add(record);
|
||||
}
|
||||
|
||||
Record record;
|
||||
while ((record = recStream.nextRecord())!=null) {
|
||||
records.add(record);
|
||||
}
|
||||
|
||||
return records;
|
||||
}
|
||||
return records;
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +52,17 @@ public final class RecordInputStream implements LittleEndianInput {
|
||||
public static final class LeftoverDataException extends RuntimeException {
|
||||
public LeftoverDataException(int sid, int remainingByteCount) {
|
||||
super("Initialisation of record 0x" + Integer.toHexString(sid).toUpperCase()
|
||||
+ " left " + remainingByteCount + " bytes remaining still to be read.");
|
||||
+ "(" + getRecordName(sid) + ") left " + remainingByteCount
|
||||
+ " bytes remaining still to be read.");
|
||||
}
|
||||
|
||||
private static String getRecordName(int sid) {
|
||||
Class<? extends Record> recordClass = RecordFactory.getRecordClass(sid);
|
||||
if(recordClass == null) {
|
||||
return null;
|
||||
}
|
||||
return recordClass.getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
/** Header {@link LittleEndianInput} facet of the wrapped {@link InputStream} */
|
||||
|
@ -64,6 +64,9 @@ public final class RowRecord extends StandardRecord {
|
||||
// bit 15 is unused
|
||||
|
||||
public RowRecord(int rowNumber) {
|
||||
if(rowNumber < 0) {
|
||||
throw new IllegalArgumentException("Invalid row number (" + rowNumber + ")");
|
||||
}
|
||||
field_1_row_number = rowNumber;
|
||||
field_4_height = (short)0xFF;
|
||||
field_5_optimize = ( short ) 0;
|
||||
@ -76,6 +79,9 @@ public final class RowRecord extends StandardRecord {
|
||||
|
||||
public RowRecord(RecordInputStream in) {
|
||||
field_1_row_number = in.readUShort();
|
||||
if(field_1_row_number < 0) {
|
||||
throw new IllegalArgumentException("Invalid row number " + field_1_row_number + " found in InputStream");
|
||||
}
|
||||
field_2_first_col = in.readShort();
|
||||
field_3_last_col = in.readShort();
|
||||
field_4_height = in.readShort();
|
||||
|
@ -179,8 +179,10 @@ public final class UnknownRecord extends StandardRecord {
|
||||
case SHEETPROTECTION_0867: return "SHEETPROTECTION";
|
||||
case 0x086B: return "DATALABEXTCONTENTS";
|
||||
case 0x086C: return "CELLWATCH";
|
||||
case FeatRecord.v11_sid: return "SHARED FEATURE v11";
|
||||
case 0x0874: return "DROPDOWNOBJIDS";
|
||||
case 0x0876: return "DCONN";
|
||||
case FeatRecord.v12_sid: return "SHARED FEATURE v12";
|
||||
case 0x087B: return "CFEX";
|
||||
case 0x087C: return "XFCRC";
|
||||
case 0x087D: return "XFEXT";
|
||||
@ -194,15 +196,21 @@ public final class UnknownRecord extends StandardRecord {
|
||||
case 0x089A: return "MTRSETTINGS";
|
||||
case 0x089B: return "COMPRESSPICTURES";
|
||||
case HEADER_FOOTER_089C: return "HEADERFOOTER";
|
||||
case 0x089D: return "CRTLAYOUT12";
|
||||
case 0x089E: return "CRTMLFRT";
|
||||
case 0x089F: return "CRTMLFRTCONTINUE";
|
||||
case 0x08A1: return "SHAPEPROPSSTREAM";
|
||||
case 0x08A3: return "FORCEFULLCALCULATION";
|
||||
case 0x08A4: return "SHAPEPROPSSTREAM";
|
||||
case 0x08A5: return "TEXTPROPSSTREAM";
|
||||
case 0x08A6: return "RICHTEXTSTREAM";
|
||||
case 0x08A7: return "CRTLAYOUT12A";
|
||||
|
||||
case 0x08C8: return "PLV{Mac Excel}";
|
||||
|
||||
|
||||
|
||||
case 0x1001: return "UNITS";
|
||||
case 0x1006: return "CHARTDATAFORMAT";
|
||||
case 0x1007: return "CHARTLINEFORMAT";
|
||||
}
|
||||
if (isObservedButUnknown(sid)) {
|
||||
return "UNKNOWN-" + Integer.toHexString(sid).toUpperCase();
|
||||
@ -215,6 +223,7 @@ public final class UnknownRecord extends StandardRecord {
|
||||
* @return <code>true</code> if the unknown record id has been observed in POI unit tests
|
||||
*/
|
||||
private static boolean isObservedButUnknown(int sid) {
|
||||
// TODO Look up more of these in the latest [MS-XLS] doc and move to getBiffName
|
||||
switch (sid) {
|
||||
case 0x0033:
|
||||
// contains 2 bytes of data: 0x0001 or 0x0003
|
||||
@ -227,13 +236,7 @@ public final class UnknownRecord extends StandardRecord {
|
||||
// Written by Excel 2007
|
||||
// rawData is multiple of 12 bytes long
|
||||
// appears after last cell value record and before WINDOW2 or drawing records
|
||||
case 0x089D:
|
||||
case 0x089E:
|
||||
case 0x08A7:
|
||||
|
||||
case 0x1001:
|
||||
case 0x1006:
|
||||
case 0x1007:
|
||||
case 0x1009:
|
||||
case 0x100A:
|
||||
case 0x100B:
|
||||
|
@ -21,7 +21,11 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.model.RecordStream;
|
||||
import org.apache.poi.hssf.record.CFHeader12Record;
|
||||
import org.apache.poi.hssf.record.CFHeaderBase;
|
||||
import org.apache.poi.hssf.record.CFHeaderRecord;
|
||||
import org.apache.poi.hssf.record.CFRule12Record;
|
||||
import org.apache.poi.hssf.record.CFRuleBase;
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.ss.formula.FormulaShifter;
|
||||
@ -38,212 +42,240 @@ import org.apache.poi.util.POILogger;
|
||||
* <p>Note that Excel versions before 2007 can only cope with a maximum of 3
|
||||
* Conditional Formatting rules per sheet. Excel 2007 or newer can cope with
|
||||
* unlimited numbers, as can Apache OpenOffice. This is an Excel limitation,
|
||||
* not a file format one.</p>
|
||||
* not a file format one.</p>
|
||||
*/
|
||||
public final class CFRecordsAggregate extends RecordAggregate {
|
||||
/** Excel 97-2003 allows up to 3 conditional formating rules */
|
||||
private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3;
|
||||
private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class);
|
||||
/** Excel 97-2003 allows up to 3 conditional formating rules */
|
||||
private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3;
|
||||
private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class);
|
||||
|
||||
private final CFHeaderRecord header;
|
||||
private final CFHeaderBase header;
|
||||
|
||||
/** List of CFRuleRecord objects */
|
||||
private final List<CFRuleRecord> rules;
|
||||
/** List of CFRuleRecord objects */
|
||||
private final List<CFRuleBase> rules;
|
||||
|
||||
private CFRecordsAggregate(CFHeaderRecord pHeader, CFRuleRecord[] pRules) {
|
||||
if(pHeader == null) {
|
||||
throw new IllegalArgumentException("header must not be null");
|
||||
}
|
||||
if(pRules == null) {
|
||||
throw new IllegalArgumentException("rules must not be null");
|
||||
}
|
||||
if(pRules.length > MAX_97_2003_CONDTIONAL_FORMAT_RULES) {
|
||||
logger.log(POILogger.WARN, "Excel versions before 2007 require that "
|
||||
+ "No more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
|
||||
+ " rules may be specified, " + pRules.length + " were found,"
|
||||
+ " this file will cause problems with old Excel versions");
|
||||
}
|
||||
if (pRules.length != pHeader.getNumberOfConditionalFormats()) {
|
||||
throw new RuntimeException("Mismatch number of rules");
|
||||
}
|
||||
header = pHeader;
|
||||
rules = new ArrayList<CFRuleRecord>(3);
|
||||
for (int i = 0; i < pRules.length; i++) {
|
||||
rules.add(pRules[i]);
|
||||
}
|
||||
}
|
||||
private CFRecordsAggregate(CFHeaderBase pHeader, CFRuleBase[] pRules) {
|
||||
if(pHeader == null) {
|
||||
throw new IllegalArgumentException("header must not be null");
|
||||
}
|
||||
if(pRules == null) {
|
||||
throw new IllegalArgumentException("rules must not be null");
|
||||
}
|
||||
if(pRules.length > MAX_97_2003_CONDTIONAL_FORMAT_RULES) {
|
||||
logger.log(POILogger.WARN, "Excel versions before 2007 require that "
|
||||
+ "No more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
|
||||
+ " rules may be specified, " + pRules.length + " were found,"
|
||||
+ " this file will cause problems with old Excel versions");
|
||||
}
|
||||
if (pRules.length != pHeader.getNumberOfConditionalFormats()) {
|
||||
throw new RuntimeException("Mismatch number of rules");
|
||||
}
|
||||
header = pHeader;
|
||||
rules = new ArrayList<CFRuleBase>(pRules.length);
|
||||
for (int i = 0; i < pRules.length; i++) {
|
||||
checkRuleType(pRules[i]);
|
||||
rules.add(pRules[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleRecord[] rules) {
|
||||
this(new CFHeaderRecord(regions, rules.length), rules);
|
||||
}
|
||||
public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleBase[] rules) {
|
||||
this(createHeader(regions, rules), rules);
|
||||
}
|
||||
private static CFHeaderBase createHeader(CellRangeAddress[] regions, CFRuleBase[] rules) {
|
||||
if (rules.length == 0 || rules[0] instanceof CFRuleRecord) {
|
||||
return new CFHeaderRecord(regions, rules.length);
|
||||
}
|
||||
return new CFHeader12Record(regions, rules.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create CFRecordsAggregate from a list of CF Records
|
||||
* @param rs - the stream to read from
|
||||
* @return CFRecordsAggregate object
|
||||
*/
|
||||
public static CFRecordsAggregate createCFAggregate(RecordStream rs) {
|
||||
Record rec = rs.getNext();
|
||||
if (rec.getSid() != CFHeaderRecord.sid) {
|
||||
throw new IllegalStateException("next record sid was " + rec.getSid()
|
||||
+ " instead of " + CFHeaderRecord.sid + " as expected");
|
||||
}
|
||||
/**
|
||||
* Create CFRecordsAggregate from a list of CF Records
|
||||
* @param rs - the stream to read from
|
||||
* @return CFRecordsAggregate object
|
||||
*/
|
||||
public static CFRecordsAggregate createCFAggregate(RecordStream rs) {
|
||||
Record rec = rs.getNext();
|
||||
if (rec.getSid() != CFHeaderRecord.sid &&
|
||||
rec.getSid() != CFHeader12Record.sid) {
|
||||
throw new IllegalStateException("next record sid was " + rec.getSid()
|
||||
+ " instead of " + CFHeaderRecord.sid + " or " +
|
||||
CFHeader12Record.sid + " as expected");
|
||||
}
|
||||
|
||||
CFHeaderRecord header = (CFHeaderRecord)rec;
|
||||
int nRules = header.getNumberOfConditionalFormats();
|
||||
CFHeaderBase header = (CFHeaderBase)rec;
|
||||
int nRules = header.getNumberOfConditionalFormats();
|
||||
|
||||
CFRuleRecord[] rules = new CFRuleRecord[nRules];
|
||||
for (int i = 0; i < rules.length; i++) {
|
||||
rules[i] = (CFRuleRecord) rs.getNext();
|
||||
}
|
||||
|
||||
return new CFRecordsAggregate(header, rules);
|
||||
}
|
||||
CFRuleBase[] rules = new CFRuleBase[nRules];
|
||||
for (int i = 0; i < rules.length; i++) {
|
||||
rules[i] = (CFRuleBase) rs.getNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deep clone of the record
|
||||
*/
|
||||
public CFRecordsAggregate cloneCFAggregate()
|
||||
{
|
||||
|
||||
CFRuleRecord[] newRecs = new CFRuleRecord[rules.size()];
|
||||
for (int i = 0; i < newRecs.length; i++) {
|
||||
newRecs[i] = (CFRuleRecord) getRule(i).clone();
|
||||
}
|
||||
return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs);
|
||||
}
|
||||
return new CFRecordsAggregate(header, rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the header. Never <code>null</code>.
|
||||
*/
|
||||
public CFHeaderRecord getHeader()
|
||||
{
|
||||
return header;
|
||||
}
|
||||
|
||||
private void checkRuleIndex(int idx) {
|
||||
if(idx < 0 || idx >= rules.size()) {
|
||||
throw new IllegalArgumentException("Bad rule record index (" + idx
|
||||
+ ") nRules=" + rules.size());
|
||||
}
|
||||
}
|
||||
public CFRuleRecord getRule(int idx) {
|
||||
checkRuleIndex(idx);
|
||||
return rules.get(idx);
|
||||
}
|
||||
public void setRule(int idx, CFRuleRecord r) {
|
||||
if (r == null) {
|
||||
throw new IllegalArgumentException("r must not be null");
|
||||
}
|
||||
checkRuleIndex(idx);
|
||||
rules.set(idx, r);
|
||||
}
|
||||
public void addRule(CFRuleRecord r) {
|
||||
if (r == null) {
|
||||
throw new IllegalArgumentException("r must not be null");
|
||||
}
|
||||
if(rules.size() >= MAX_97_2003_CONDTIONAL_FORMAT_RULES) {
|
||||
/**
|
||||
* Create a deep clone of the record
|
||||
*/
|
||||
public CFRecordsAggregate cloneCFAggregate() {
|
||||
CFRuleBase[] newRecs = new CFRuleBase[rules.size()];
|
||||
for (int i = 0; i < newRecs.length; i++) {
|
||||
newRecs[i] = (CFRuleRecord) getRule(i).clone();
|
||||
}
|
||||
return new CFRecordsAggregate((CFHeaderBase)header.clone(), newRecs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the header. Never <code>null</code>.
|
||||
*/
|
||||
public CFHeaderBase getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
private void checkRuleIndex(int idx) {
|
||||
if(idx < 0 || idx >= rules.size()) {
|
||||
throw new IllegalArgumentException("Bad rule record index (" + idx
|
||||
+ ") nRules=" + rules.size());
|
||||
}
|
||||
}
|
||||
private void checkRuleType(CFRuleBase r) {
|
||||
if (header instanceof CFHeaderRecord &&
|
||||
r instanceof CFRuleRecord) {
|
||||
return;
|
||||
}
|
||||
if (header instanceof CFHeader12Record &&
|
||||
r instanceof CFRule12Record) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("Header and Rule must both be CF or both be CF12, can't mix");
|
||||
}
|
||||
|
||||
public CFRuleBase getRule(int idx) {
|
||||
checkRuleIndex(idx);
|
||||
return rules.get(idx);
|
||||
}
|
||||
public void setRule(int idx, CFRuleBase r) {
|
||||
if (r == null) {
|
||||
throw new IllegalArgumentException("r must not be null");
|
||||
}
|
||||
checkRuleIndex(idx);
|
||||
checkRuleType(r);
|
||||
rules.set(idx, r);
|
||||
}
|
||||
public void addRule(CFRuleBase r) {
|
||||
if (r == null) {
|
||||
throw new IllegalArgumentException("r must not be null");
|
||||
}
|
||||
if(rules.size() >= MAX_97_2003_CONDTIONAL_FORMAT_RULES) {
|
||||
logger.log(POILogger.WARN, "Excel versions before 2007 cannot cope with"
|
||||
+ " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
|
||||
+ " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
|
||||
+ " - this file will cause problems with old Excel versions");
|
||||
}
|
||||
rules.add(r);
|
||||
header.setNumberOfConditionalFormats(rules.size());
|
||||
}
|
||||
public int getNumberOfRules() {
|
||||
return rules.size();
|
||||
}
|
||||
}
|
||||
checkRuleType(r);
|
||||
rules.add(r);
|
||||
header.setNumberOfConditionalFormats(rules.size());
|
||||
}
|
||||
public int getNumberOfRules() {
|
||||
return rules.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of CFRecordsAggregate
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
/**
|
||||
* String representation of CFRecordsAggregate
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
String type = "CF";
|
||||
if (header instanceof CFHeader12Record) {
|
||||
type = "CF12";
|
||||
}
|
||||
|
||||
buffer.append("[CF]\n");
|
||||
if( header != null )
|
||||
{
|
||||
buffer.append(header.toString());
|
||||
}
|
||||
for(int i=0; i<rules.size(); i++)
|
||||
{
|
||||
CFRuleRecord cfRule = rules.get(i);
|
||||
buffer.append(cfRule.toString());
|
||||
}
|
||||
buffer.append("[/CF]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
buffer.append("[").append(type).append("]\n");
|
||||
if( header != null ) {
|
||||
buffer.append(header.toString());
|
||||
}
|
||||
for(int i=0; i<rules.size(); i++) {
|
||||
CFRuleBase cfRule = rules.get(i);
|
||||
buffer.append(cfRule.toString());
|
||||
}
|
||||
buffer.append("[/").append(type).append("]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public void visitContainedRecords(RecordVisitor rv) {
|
||||
rv.visitRecord(header);
|
||||
for(int i=0; i<rules.size(); i++) {
|
||||
CFRuleRecord rule = rules.get(i);
|
||||
rv.visitRecord(rule);
|
||||
}
|
||||
}
|
||||
public void visitContainedRecords(RecordVisitor rv) {
|
||||
rv.visitRecord(header);
|
||||
for(int i=0; i<rules.size(); i++) {
|
||||
CFRuleBase rule = rules.get(i);
|
||||
rv.visitRecord(rule);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>false</code> if this whole {@link CFHeaderRecord} / {@link CFRuleRecord}s should be deleted
|
||||
*/
|
||||
public boolean updateFormulasAfterCellShift(FormulaShifter shifter, int currentExternSheetIx) {
|
||||
CellRangeAddress[] cellRanges = header.getCellRanges();
|
||||
boolean changed = false;
|
||||
List<CellRangeAddress> temp = new ArrayList<CellRangeAddress>();
|
||||
for (int i = 0; i < cellRanges.length; i++) {
|
||||
CellRangeAddress craOld = cellRanges[i];
|
||||
CellRangeAddress craNew = shiftRange(shifter, craOld, currentExternSheetIx);
|
||||
if (craNew == null) {
|
||||
changed = true;
|
||||
continue;
|
||||
}
|
||||
temp.add(craNew);
|
||||
if (craNew != craOld) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return <code>false</code> if this whole {@link CFHeaderRecord} / {@link CFRuleRecord}s should be deleted
|
||||
*/
|
||||
public boolean updateFormulasAfterCellShift(FormulaShifter shifter, int currentExternSheetIx) {
|
||||
CellRangeAddress[] cellRanges = header.getCellRanges();
|
||||
boolean changed = false;
|
||||
List<CellRangeAddress> temp = new ArrayList<CellRangeAddress>();
|
||||
for (int i = 0; i < cellRanges.length; i++) {
|
||||
CellRangeAddress craOld = cellRanges[i];
|
||||
CellRangeAddress craNew = shiftRange(shifter, craOld, currentExternSheetIx);
|
||||
if (craNew == null) {
|
||||
changed = true;
|
||||
continue;
|
||||
}
|
||||
temp.add(craNew);
|
||||
if (craNew != craOld) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
int nRanges = temp.size();
|
||||
if (nRanges == 0) {
|
||||
return false;
|
||||
}
|
||||
CellRangeAddress[] newRanges = new CellRangeAddress[nRanges];
|
||||
temp.toArray(newRanges);
|
||||
header.setCellRanges(newRanges);
|
||||
}
|
||||
|
||||
for(int i=0; i<rules.size(); i++) {
|
||||
CFRuleRecord rule = rules.get(i);
|
||||
Ptg[] ptgs;
|
||||
ptgs = rule.getParsedExpression1();
|
||||
if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
|
||||
rule.setParsedExpression1(ptgs);
|
||||
}
|
||||
ptgs = rule.getParsedExpression2();
|
||||
if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
|
||||
rule.setParsedExpression2(ptgs);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (changed) {
|
||||
int nRanges = temp.size();
|
||||
if (nRanges == 0) {
|
||||
return false;
|
||||
}
|
||||
CellRangeAddress[] newRanges = new CellRangeAddress[nRanges];
|
||||
temp.toArray(newRanges);
|
||||
header.setCellRanges(newRanges);
|
||||
}
|
||||
|
||||
private static CellRangeAddress shiftRange(FormulaShifter shifter, CellRangeAddress cra, int currentExternSheetIx) {
|
||||
// FormulaShifter works well in terms of Ptgs - so convert CellRangeAddress to AreaPtg (and back) here
|
||||
AreaPtg aptg = new AreaPtg(cra.getFirstRow(), cra.getLastRow(), cra.getFirstColumn(), cra.getLastColumn(), false, false, false, false);
|
||||
Ptg[] ptgs = { aptg, };
|
||||
|
||||
if (!shifter.adjustFormula(ptgs, currentExternSheetIx)) {
|
||||
return cra;
|
||||
}
|
||||
Ptg ptg0 = ptgs[0];
|
||||
if (ptg0 instanceof AreaPtg) {
|
||||
AreaPtg bptg = (AreaPtg) ptg0;
|
||||
return new CellRangeAddress(bptg.getFirstRow(), bptg.getLastRow(), bptg.getFirstColumn(), bptg.getLastColumn());
|
||||
}
|
||||
if (ptg0 instanceof AreaErrPtg) {
|
||||
return null;
|
||||
}
|
||||
throw new IllegalStateException("Unexpected shifted ptg class (" + ptg0.getClass().getName() + ")");
|
||||
}
|
||||
for(int i=0; i<rules.size(); i++) {
|
||||
CFRuleBase rule = rules.get(i);
|
||||
Ptg[] ptgs;
|
||||
ptgs = rule.getParsedExpression1();
|
||||
if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
|
||||
rule.setParsedExpression1(ptgs);
|
||||
}
|
||||
ptgs = rule.getParsedExpression2();
|
||||
if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
|
||||
rule.setParsedExpression2(ptgs);
|
||||
}
|
||||
if (rule instanceof CFRule12Record) {
|
||||
CFRule12Record rule12 = (CFRule12Record)rule;
|
||||
ptgs = rule12.getParsedExpressionScale();
|
||||
if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
|
||||
rule12.setParsedExpressionScale(ptgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static CellRangeAddress shiftRange(FormulaShifter shifter, CellRangeAddress cra, int currentExternSheetIx) {
|
||||
// FormulaShifter works well in terms of Ptgs - so convert CellRangeAddress to AreaPtg (and back) here
|
||||
AreaPtg aptg = new AreaPtg(cra.getFirstRow(), cra.getLastRow(), cra.getFirstColumn(), cra.getLastColumn(), false, false, false, false);
|
||||
Ptg[] ptgs = { aptg, };
|
||||
|
||||
if (!shifter.adjustFormula(ptgs, currentExternSheetIx)) {
|
||||
return cra;
|
||||
}
|
||||
Ptg ptg0 = ptgs[0];
|
||||
if (ptg0 instanceof AreaPtg) {
|
||||
AreaPtg bptg = (AreaPtg) ptg0;
|
||||
return new CellRangeAddress(bptg.getFirstRow(), bptg.getLastRow(), bptg.getFirstColumn(), bptg.getLastColumn());
|
||||
}
|
||||
if (ptg0 instanceof AreaErrPtg) {
|
||||
return null;
|
||||
}
|
||||
throw new IllegalStateException("Unexpected shifted ptg class (" + ptg0.getClass().getName() + ")");
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.model.RecordStream;
|
||||
import org.apache.poi.hssf.record.CFHeader12Record;
|
||||
import org.apache.poi.hssf.record.CFHeaderRecord;
|
||||
import org.apache.poi.ss.formula.FormulaShifter;
|
||||
|
||||
@ -28,11 +29,8 @@ import org.apache.poi.ss.formula.FormulaShifter;
|
||||
* Holds all the conditional formatting for a workbook sheet.<p/>
|
||||
*
|
||||
* See OOO exelfileformat.pdf sec 4.12 'Conditional Formatting Table'
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ConditionalFormattingTable extends RecordAggregate {
|
||||
|
||||
private final List<CFRecordsAggregate> _cfHeaders;
|
||||
|
||||
/**
|
||||
@ -45,7 +43,8 @@ public final class ConditionalFormattingTable extends RecordAggregate {
|
||||
public ConditionalFormattingTable(RecordStream rs) {
|
||||
|
||||
List<CFRecordsAggregate> temp = new ArrayList<CFRecordsAggregate>();
|
||||
while (rs.peekNextClass() == CFHeaderRecord.class) {
|
||||
while (rs.peekNextClass() == CFHeaderRecord.class ||
|
||||
rs.peekNextClass() == CFHeader12Record.class) {
|
||||
temp.add(CFRecordsAggregate.createCFAggregate(rs));
|
||||
}
|
||||
_cfHeaders = temp;
|
||||
@ -62,6 +61,7 @@ public final class ConditionalFormattingTable extends RecordAggregate {
|
||||
* @return index of the newly added CF header aggregate
|
||||
*/
|
||||
public int add(CFRecordsAggregate cfAggregate) {
|
||||
cfAggregate.getHeader().setID(_cfHeaders.size());
|
||||
_cfHeaders.add(cfAggregate);
|
||||
return _cfHeaders.size() - 1;
|
||||
}
|
||||
|
@ -25,11 +25,8 @@ import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Border Formatting Block of the Conditional Formatting Rule Record.
|
||||
*
|
||||
* @author Dmitriy Kumshayev
|
||||
*/
|
||||
public final class BorderFormatting {
|
||||
|
||||
/** No border */
|
||||
public final static short BORDER_NONE = 0x0;
|
||||
/** Thin border */
|
||||
@ -89,6 +86,9 @@ public final class BorderFormatting {
|
||||
field_14_border_styles2 = in.readInt();
|
||||
}
|
||||
|
||||
public int getDataLength() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the type of border to use for the left border of the cell
|
||||
|
@ -23,97 +23,93 @@ import java.util.List;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Dmitriy Kumshayev
|
||||
* TODO Should this move to org.apache.poi.ss.util ?
|
||||
*/
|
||||
public final class CellRangeUtil
|
||||
{
|
||||
|
||||
private CellRangeUtil() {
|
||||
// no instance of this class
|
||||
}
|
||||
|
||||
public static final int NO_INTERSECTION = 1;
|
||||
public static final int OVERLAP = 2;
|
||||
/** first range is within the second range */
|
||||
public static final int INSIDE = 3;
|
||||
/** first range encloses or is equal to the second */
|
||||
public static final int ENCLOSES = 4;
|
||||
|
||||
/**
|
||||
* Intersect this range with the specified range.
|
||||
*
|
||||
* @param crB - the specified range
|
||||
* @return code which reflects how the specified range is related to this range.<br/>
|
||||
* Possible return codes are:
|
||||
* NO_INTERSECTION - the specified range is outside of this range;<br/>
|
||||
* OVERLAP - both ranges partially overlap;<br/>
|
||||
* INSIDE - the specified range is inside of this one<br/>
|
||||
* ENCLOSES - the specified range encloses (possibly exactly the same as) this range<br/>
|
||||
*/
|
||||
public static int intersect(CellRangeAddress crA, CellRangeAddress crB )
|
||||
{
|
||||
|
||||
int firstRow = crB.getFirstRow();
|
||||
int lastRow = crB.getLastRow();
|
||||
int firstCol = crB.getFirstColumn();
|
||||
int lastCol = crB.getLastColumn();
|
||||
|
||||
if
|
||||
(
|
||||
public final class CellRangeUtil {
|
||||
private CellRangeUtil() {
|
||||
// no instance of this class
|
||||
}
|
||||
|
||||
public static final int NO_INTERSECTION = 1;
|
||||
public static final int OVERLAP = 2;
|
||||
/** first range is within the second range */
|
||||
public static final int INSIDE = 3;
|
||||
/** first range encloses or is equal to the second */
|
||||
public static final int ENCLOSES = 4;
|
||||
|
||||
/**
|
||||
* Intersect this range with the specified range.
|
||||
*
|
||||
* @param crB - the specified range
|
||||
* @return code which reflects how the specified range is related to this range.<br/>
|
||||
* Possible return codes are:
|
||||
* NO_INTERSECTION - the specified range is outside of this range;<br/>
|
||||
* OVERLAP - both ranges partially overlap;<br/>
|
||||
* INSIDE - the specified range is inside of this one<br/>
|
||||
* ENCLOSES - the specified range encloses (possibly exactly the same as) this range<br/>
|
||||
*/
|
||||
public static int intersect(CellRangeAddress crA, CellRangeAddress crB )
|
||||
{
|
||||
|
||||
int firstRow = crB.getFirstRow();
|
||||
int lastRow = crB.getLastRow();
|
||||
int firstCol = crB.getFirstColumn();
|
||||
int lastCol = crB.getLastColumn();
|
||||
|
||||
if
|
||||
(
|
||||
gt(crA.getFirstRow(),lastRow) ||
|
||||
lt(crA.getLastRow(),firstRow) ||
|
||||
gt(crA.getFirstColumn(),lastCol) ||
|
||||
lt(crA.getLastColumn(),firstCol)
|
||||
)
|
||||
{
|
||||
return NO_INTERSECTION;
|
||||
}
|
||||
else if( contains(crA, crB) )
|
||||
{
|
||||
return INSIDE;
|
||||
}
|
||||
else if( contains(crB, crA))
|
||||
{
|
||||
return ENCLOSES;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OVERLAP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Do all possible cell merges between cells of the list so that:<br>
|
||||
* <li>if a cell range is completely inside of another cell range, it gets removed from the list
|
||||
* <li>if two cells have a shared border, merge them into one bigger cell range
|
||||
* @param cellRanges
|
||||
* @return updated List of cell ranges
|
||||
*/
|
||||
public static CellRangeAddress[] mergeCellRanges(CellRangeAddress[] cellRanges) {
|
||||
if(cellRanges.length < 1) {
|
||||
return cellRanges;
|
||||
}
|
||||
)
|
||||
{
|
||||
return NO_INTERSECTION;
|
||||
}
|
||||
else if( contains(crA, crB) )
|
||||
{
|
||||
return INSIDE;
|
||||
}
|
||||
else if( contains(crB, crA))
|
||||
{
|
||||
return ENCLOSES;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OVERLAP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do all possible cell merges between cells of the list so that:<br>
|
||||
* <li>if a cell range is completely inside of another cell range, it gets removed from the list
|
||||
* <li>if two cells have a shared border, merge them into one bigger cell range
|
||||
* @param cellRanges
|
||||
* @return updated List of cell ranges
|
||||
*/
|
||||
public static CellRangeAddress[] mergeCellRanges(CellRangeAddress[] cellRanges) {
|
||||
if(cellRanges.length < 1) {
|
||||
return cellRanges;
|
||||
}
|
||||
|
||||
List<CellRangeAddress> lst = new ArrayList<CellRangeAddress>();
|
||||
for(CellRangeAddress cr : cellRanges) {
|
||||
lst.add(cr);
|
||||
}
|
||||
List<CellRangeAddress> temp = mergeCellRanges(lst);
|
||||
return toArray(temp);
|
||||
}
|
||||
return toArray(temp);
|
||||
}
|
||||
|
||||
private static List<CellRangeAddress> mergeCellRanges(List<CellRangeAddress> cellRangeList)
|
||||
{
|
||||
// loop until either only one item is left or we did not merge anything any more
|
||||
private static List<CellRangeAddress> mergeCellRanges(List<CellRangeAddress> cellRangeList)
|
||||
{
|
||||
// loop until either only one item is left or we did not merge anything any more
|
||||
while (cellRangeList.size() > 1) {
|
||||
boolean somethingGotMerged = false;
|
||||
|
||||
// look at all cell-ranges
|
||||
for (int i = 0; i < cellRangeList.size(); i++) {
|
||||
CellRangeAddress range1 = cellRangeList.get(i);
|
||||
|
||||
|
||||
// compare each cell range to all other cell-ranges
|
||||
for (int j = i + 1; j < cellRangeList.size(); j++) {
|
||||
CellRangeAddress range2 = cellRangeList.get(j);
|
||||
@ -139,16 +135,16 @@ public final class CellRangeUtil
|
||||
}
|
||||
}
|
||||
|
||||
return cellRangeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the new range(s) to replace the supplied ones. <code>null</code> if no merge is possible
|
||||
*/
|
||||
private static CellRangeAddress[] mergeRanges(CellRangeAddress range1, CellRangeAddress range2) {
|
||||
int x = intersect(range1, range2);
|
||||
switch(x)
|
||||
{
|
||||
return cellRangeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the new range(s) to replace the supplied ones. <code>null</code> if no merge is possible
|
||||
*/
|
||||
private static CellRangeAddress[] mergeRanges(CellRangeAddress range1, CellRangeAddress range2) {
|
||||
int x = intersect(range1, range2);
|
||||
switch(x)
|
||||
{
|
||||
case CellRangeUtil.NO_INTERSECTION:
|
||||
// nothing in common: at most they could be adjacent to each other and thus form a single bigger area
|
||||
if(hasExactSharedBorder(range1, range2)) {
|
||||
@ -171,108 +167,103 @@ public final class CellRangeUtil
|
||||
throw new RuntimeException("unexpected intersection result (" + x + ")");
|
||||
}
|
||||
|
||||
|
||||
private static CellRangeAddress[] toArray(List<CellRangeAddress> temp) {
|
||||
CellRangeAddress[] result = new CellRangeAddress[temp.size()];
|
||||
temp.toArray(result);
|
||||
return result;
|
||||
}
|
||||
private static CellRangeAddress[] toArray(List<CellRangeAddress> temp) {
|
||||
CellRangeAddress[] result = new CellRangeAddress[temp.size()];
|
||||
temp.toArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the specified range is located inside of this cell range.
|
||||
*
|
||||
* @param crB
|
||||
* @return true if this cell range contains the argument range inside if it's area
|
||||
*/
|
||||
public static boolean contains(CellRangeAddress crA, CellRangeAddress crB)
|
||||
{
|
||||
int firstRow = crB.getFirstRow();
|
||||
int lastRow = crB.getLastRow();
|
||||
int firstCol = crB.getFirstColumn();
|
||||
int lastCol = crB.getLastColumn();
|
||||
return le(crA.getFirstRow(), firstRow) && ge(crA.getLastRow(), lastRow)
|
||||
&& le(crA.getFirstColumn(), firstCol) && ge(crA.getLastColumn(), lastCol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the two cell ranges have a shared border.
|
||||
*
|
||||
* @return <code>true</code> if the ranges have a complete shared border (i.e.
|
||||
* the two ranges together make a simple rectangular region.
|
||||
*/
|
||||
public static boolean hasExactSharedBorder(CellRangeAddress crA, CellRangeAddress crB) {
|
||||
int oFirstRow = crB.getFirstRow();
|
||||
int oLastRow = crB.getLastRow();
|
||||
int oFirstCol = crB.getFirstColumn();
|
||||
int oLastCol = crB.getLastColumn();
|
||||
|
||||
/**
|
||||
* Check if the specified range is located inside of this cell range.
|
||||
*
|
||||
* @param crB
|
||||
* @return true if this cell range contains the argument range inside if it's area
|
||||
*/
|
||||
public static boolean contains(CellRangeAddress crA, CellRangeAddress crB)
|
||||
{
|
||||
int firstRow = crB.getFirstRow();
|
||||
int lastRow = crB.getLastRow();
|
||||
int firstCol = crB.getFirstColumn();
|
||||
int lastCol = crB.getLastColumn();
|
||||
return le(crA.getFirstRow(), firstRow) && ge(crA.getLastRow(), lastRow)
|
||||
&& le(crA.getFirstColumn(), firstCol) && ge(crA.getLastColumn(), lastCol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the two cell ranges have a shared border.
|
||||
*
|
||||
* @return <code>true</code> if the ranges have a complete shared border (i.e.
|
||||
* the two ranges together make a simple rectangular region.
|
||||
*/
|
||||
public static boolean hasExactSharedBorder(CellRangeAddress crA, CellRangeAddress crB) {
|
||||
int oFirstRow = crB.getFirstRow();
|
||||
int oLastRow = crB.getLastRow();
|
||||
int oFirstCol = crB.getFirstColumn();
|
||||
int oLastCol = crB.getLastColumn();
|
||||
|
||||
if (crA.getFirstRow() > 0 && crA.getFirstRow()-1 == oLastRow ||
|
||||
oFirstRow > 0 && oFirstRow-1 == crA.getLastRow()) {
|
||||
// ranges have a horizontal border in common
|
||||
// make sure columns are identical:
|
||||
return crA.getFirstColumn() == oFirstCol && crA.getLastColumn() == oLastCol;
|
||||
}
|
||||
if (crA.getFirstRow() > 0 && crA.getFirstRow()-1 == oLastRow ||
|
||||
oFirstRow > 0 && oFirstRow-1 == crA.getLastRow()) {
|
||||
// ranges have a horizontal border in common
|
||||
// make sure columns are identical:
|
||||
return crA.getFirstColumn() == oFirstCol && crA.getLastColumn() == oLastCol;
|
||||
}
|
||||
|
||||
if (crA.getFirstColumn()>0 && crA.getFirstColumn() - 1 == oLastCol ||
|
||||
oFirstCol>0 && crA.getLastColumn() == oFirstCol -1) {
|
||||
// ranges have a vertical border in common
|
||||
// make sure rows are identical:
|
||||
return crA.getFirstRow() == oFirstRow && crA.getLastRow() == oLastRow;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an enclosing CellRange for the two cell ranges.
|
||||
*
|
||||
* @return enclosing CellRange
|
||||
*/
|
||||
public static CellRangeAddress createEnclosingCellRange(CellRangeAddress crA, CellRangeAddress crB) {
|
||||
if( crB == null) {
|
||||
return crA.copy();
|
||||
}
|
||||
|
||||
return
|
||||
new CellRangeAddress(
|
||||
lt(crB.getFirstRow(), crA.getFirstRow()) ?crB.getFirstRow() :crA.getFirstRow(),
|
||||
gt(crB.getLastRow(), crA.getLastRow()) ?crB.getLastRow() :crA.getLastRow(),
|
||||
lt(crB.getFirstColumn(),crA.getFirstColumn())?crB.getFirstColumn():crA.getFirstColumn(),
|
||||
gt(crB.getLastColumn(), crA.getLastColumn()) ?crB.getLastColumn() :crA.getLastColumn()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a < b
|
||||
*/
|
||||
private static boolean lt(int a, int b)
|
||||
{
|
||||
return a == -1 ? false : (b == -1 ? true : a < b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a <= b
|
||||
*/
|
||||
private static boolean le(int a, int b)
|
||||
{
|
||||
return a == b || lt(a,b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a > b
|
||||
*/
|
||||
private static boolean gt(int a, int b)
|
||||
{
|
||||
return lt(b,a);
|
||||
}
|
||||
if (crA.getFirstColumn()>0 && crA.getFirstColumn() - 1 == oLastCol ||
|
||||
oFirstCol>0 && crA.getLastColumn() == oFirstCol -1) {
|
||||
// ranges have a vertical border in common
|
||||
// make sure rows are identical:
|
||||
return crA.getFirstRow() == oFirstRow && crA.getLastRow() == oLastRow;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a >= b
|
||||
*/
|
||||
private static boolean ge(int a, int b)
|
||||
{
|
||||
return !lt(a,b);
|
||||
}
|
||||
/**
|
||||
* Create an enclosing CellRange for the two cell ranges.
|
||||
*
|
||||
* @return enclosing CellRange
|
||||
*/
|
||||
public static CellRangeAddress createEnclosingCellRange(CellRangeAddress crA, CellRangeAddress crB) {
|
||||
if( crB == null) {
|
||||
return crA.copy();
|
||||
}
|
||||
|
||||
return new CellRangeAddress(
|
||||
lt(crB.getFirstRow(), crA.getFirstRow()) ?crB.getFirstRow() :crA.getFirstRow(),
|
||||
gt(crB.getLastRow(), crA.getLastRow()) ?crB.getLastRow() :crA.getLastRow(),
|
||||
lt(crB.getFirstColumn(),crA.getFirstColumn())?crB.getFirstColumn():crA.getFirstColumn(),
|
||||
gt(crB.getLastColumn(), crA.getLastColumn()) ?crB.getLastColumn() :crA.getLastColumn()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a < b
|
||||
*/
|
||||
private static boolean lt(int a, int b)
|
||||
{
|
||||
return a == -1 ? false : (b == -1 ? true : a < b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a <= b
|
||||
*/
|
||||
private static boolean le(int a, int b)
|
||||
{
|
||||
return a == b || lt(a,b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a > b
|
||||
*/
|
||||
private static boolean gt(int a, int b)
|
||||
{
|
||||
return lt(b,a);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a >= b
|
||||
*/
|
||||
private static boolean ge(int a, int b)
|
||||
{
|
||||
return !lt(a,b);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,139 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.cf;
|
||||
|
||||
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
/**
|
||||
* Icon / Multi-State Conditional Formatting Rule Record.
|
||||
*/
|
||||
public final class IconMultiStateFormatting implements Cloneable {
|
||||
private static POILogger log = POILogFactory.getLogger(IconMultiStateFormatting.class);
|
||||
|
||||
private IconSet iconSet;
|
||||
private byte options;
|
||||
private Threshold[] thresholds;
|
||||
|
||||
private static BitField iconOnly = BitFieldFactory.getInstance(0x01);
|
||||
private static BitField reversed = BitFieldFactory.getInstance(0x04);
|
||||
|
||||
public IconMultiStateFormatting() {
|
||||
iconSet = IconSet.GYR_3_TRAFFIC_LIGHTS;
|
||||
options = 0;
|
||||
thresholds = new Threshold[iconSet.num];
|
||||
}
|
||||
public IconMultiStateFormatting(LittleEndianInput in) {
|
||||
in.readShort(); // Ignored
|
||||
in.readByte(); // Reserved
|
||||
int num = in.readByte();
|
||||
int set = in.readByte();
|
||||
iconSet = IconSet.byId(set);
|
||||
if (iconSet.num != num) {
|
||||
log.log(POILogger.WARN, "Inconsistent Icon Set defintion, found " + iconSet + " but defined as " + num + " entries");
|
||||
}
|
||||
options = in.readByte();
|
||||
|
||||
thresholds = new Threshold[iconSet.num];
|
||||
for (int i=0; i<thresholds.length; i++) {
|
||||
thresholds[i] = new Threshold(in);
|
||||
}
|
||||
}
|
||||
|
||||
public IconSet getIconSet() {
|
||||
return iconSet;
|
||||
}
|
||||
public void setIconSet(IconSet set) {
|
||||
this.iconSet = set;
|
||||
}
|
||||
|
||||
public Threshold[] getThresholds() {
|
||||
return thresholds;
|
||||
}
|
||||
public void setThresholds(Threshold[] thresholds) {
|
||||
this.thresholds = thresholds;
|
||||
}
|
||||
|
||||
public boolean isIconOnly() {
|
||||
return getOptionFlag(iconOnly);
|
||||
}
|
||||
public void setIconOnly(boolean only) {
|
||||
setOptionFlag(only, iconOnly);
|
||||
}
|
||||
|
||||
public boolean isReversed() {
|
||||
return getOptionFlag(reversed);
|
||||
}
|
||||
public void setReversed(boolean rev) {
|
||||
setOptionFlag(rev, reversed);
|
||||
}
|
||||
|
||||
private boolean getOptionFlag(BitField field) {
|
||||
int value = field.getValue(options);
|
||||
return value==0 ? false : true;
|
||||
}
|
||||
private void setOptionFlag(boolean option, BitField field) {
|
||||
options = field.setByteBoolean(options, option);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(" [Icon Formatting]\n");
|
||||
buffer.append(" .icon_set = ").append(iconSet).append("\n");
|
||||
buffer.append(" .icon_only= ").append(isIconOnly()).append("\n");
|
||||
buffer.append(" .reversed = ").append(isReversed()).append("\n");
|
||||
for (Threshold t : thresholds) {
|
||||
buffer.append(t.toString());
|
||||
}
|
||||
buffer.append(" [/Icon Formatting]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
IconMultiStateFormatting rec = new IconMultiStateFormatting();
|
||||
rec.iconSet = iconSet;
|
||||
rec.options = options;
|
||||
rec.thresholds = new Threshold[thresholds.length];
|
||||
System.arraycopy(thresholds, 0, rec.thresholds, 0, thresholds.length);
|
||||
return rec;
|
||||
}
|
||||
|
||||
public int getDataLength() {
|
||||
int len = 6;
|
||||
for (Threshold t : thresholds) {
|
||||
len += t.getDataLength();
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(0);
|
||||
out.writeByte(0);
|
||||
out.writeByte(iconSet.num);
|
||||
out.writeByte(iconSet.id);
|
||||
out.writeByte(options);
|
||||
for (Threshold t : thresholds) {
|
||||
t.serialize(out);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,8 +24,6 @@ import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Pattern Formatting Block of the Conditional Formatting Rule Record.
|
||||
*
|
||||
* @author Dmitriy Kumshayev
|
||||
*/
|
||||
public final class PatternFormatting implements Cloneable {
|
||||
/** No background */
|
||||
@ -89,6 +87,10 @@ public final class PatternFormatting implements Cloneable {
|
||||
field_16_pattern_color_indexes = in.readUShort();
|
||||
}
|
||||
|
||||
public int getDataLength() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* setting fill pattern
|
||||
*
|
||||
|
146
src/java/org/apache/poi/hssf/record/cf/Threshold.java
Normal file
146
src/java/org/apache/poi/hssf/record/cf/Threshold.java
Normal file
@ -0,0 +1,146 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.cf;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.ss.formula.Formula;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Threshold / value for changes in Conditional Formatting
|
||||
*/
|
||||
public final class Threshold {
|
||||
/**
|
||||
* Cell values that are equal to the threshold value do not pass the threshold
|
||||
*/
|
||||
public static final byte EQUALS_EXCLUDE = 0;
|
||||
/**
|
||||
* Cell values that are equal to the threshold value pass the threshold.
|
||||
*/
|
||||
public static final byte EQUALS_INCLUDE = 1;
|
||||
|
||||
private byte type;
|
||||
private Formula formula;
|
||||
private Double value;
|
||||
private byte equals;
|
||||
|
||||
public Threshold() {
|
||||
type = (byte)RangeType.NUMBER.id;
|
||||
formula = Formula.create(null);
|
||||
value = 0d;
|
||||
}
|
||||
|
||||
/** Creates new Threshold */
|
||||
public Threshold(LittleEndianInput in) {
|
||||
type = in.readByte();
|
||||
short formulaLen = in.readShort();
|
||||
if (formulaLen > 0) {
|
||||
formula = Formula.read(formulaLen, in);
|
||||
} else {
|
||||
formula = Formula.create(null);
|
||||
}
|
||||
// Value is only there for non-formula, non min/max thresholds
|
||||
if (formulaLen == 0 && type != RangeType.MIN.id &&
|
||||
type != RangeType.MAX.id) {
|
||||
value = in.readDouble();
|
||||
}
|
||||
equals = in.readByte();
|
||||
// Reserved, 4 bytes, all 0
|
||||
in.readInt();
|
||||
}
|
||||
|
||||
public byte getType() {
|
||||
return type;
|
||||
}
|
||||
public void setType(byte type) {
|
||||
this.type = type;
|
||||
}
|
||||
public void setType(int type) {
|
||||
this.type = (byte)type;
|
||||
}
|
||||
|
||||
protected Formula getFormula() {
|
||||
return formula;
|
||||
}
|
||||
public Ptg[] getParsedExpression() {
|
||||
return formula.getTokens();
|
||||
}
|
||||
public void setParsedExpression(Ptg[] ptgs) {
|
||||
formula = Formula.create(ptgs);
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public byte getEquals() {
|
||||
return equals;
|
||||
}
|
||||
public void setEquals(byte equals) {
|
||||
this.equals = equals;
|
||||
}
|
||||
|
||||
public int getDataLength() {
|
||||
int len = 1 + formula.getEncodedSize();
|
||||
if (value != null) {
|
||||
len += 8;
|
||||
}
|
||||
len += 5;
|
||||
return len;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(" [CF Threshold]\n");
|
||||
buffer.append(" .type = ").append(Integer.toHexString(type)).append("\n");
|
||||
buffer.append(" .formula = ").append(Arrays.toString(formula.getTokens())).append("\n");
|
||||
buffer.append(" .value = ").append(value).append("\n");
|
||||
buffer.append(" [/CF Threshold]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
Threshold rec = new Threshold();
|
||||
rec.type = type;
|
||||
rec.formula = formula;
|
||||
rec.value = value;
|
||||
rec.equals = equals;
|
||||
return rec;
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeByte(type);
|
||||
if (formula.getTokens().length == 0) {
|
||||
out.writeShort(0);
|
||||
} else {
|
||||
formula.serialize(out);
|
||||
}
|
||||
if (value != null) {
|
||||
out.writeDouble(value);
|
||||
}
|
||||
out.writeByte(equals);
|
||||
out.writeInt(0); // Reserved
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
package org.apache.poi.hssf.record.common;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
@ -28,62 +29,69 @@ import org.apache.poi.util.LittleEndianOutput;
|
||||
* beyond those of a traditional record.
|
||||
*/
|
||||
public final class FtrHeader {
|
||||
/** This MUST match the type on the containing record */
|
||||
private short recordType;
|
||||
/** This is a FrtFlags */
|
||||
private short grbitFrt;
|
||||
/** MUST be 8 bytes and all zero */
|
||||
private byte[] reserved;
|
||||
/** This MUST match the type on the containing record */
|
||||
private short recordType;
|
||||
/** This is a FrtFlags */
|
||||
private short grbitFrt;
|
||||
/** The range of cells the parent record applies to, or 0 if N/A */
|
||||
private CellRangeAddress associatedRange;
|
||||
|
||||
public FtrHeader() {
|
||||
reserved = new byte[8];
|
||||
}
|
||||
public FtrHeader() {
|
||||
associatedRange = new CellRangeAddress(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public FtrHeader(RecordInputStream in) {
|
||||
recordType = in.readShort();
|
||||
grbitFrt = in.readShort();
|
||||
|
||||
reserved = new byte[8];
|
||||
in.read(reserved, 0, 8);
|
||||
}
|
||||
public FtrHeader(RecordInputStream in) {
|
||||
recordType = in.readShort();
|
||||
grbitFrt = in.readShort();
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(" [FUTURE HEADER]\n");
|
||||
buffer.append(" Type " + recordType);
|
||||
buffer.append(" Flags " + grbitFrt);
|
||||
buffer.append(" [/FUTURE HEADER]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
associatedRange = new CellRangeAddress(in);
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(recordType);
|
||||
out.writeShort(grbitFrt);
|
||||
out.write(reserved);
|
||||
}
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(" [FUTURE HEADER]\n");
|
||||
buffer.append(" Type " + recordType);
|
||||
buffer.append(" Flags " + grbitFrt);
|
||||
buffer.append(" [/FUTURE HEADER]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public static int getDataSize() {
|
||||
return 12;
|
||||
}
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(recordType);
|
||||
out.writeShort(grbitFrt);
|
||||
associatedRange.serialize(out);
|
||||
}
|
||||
|
||||
public short getRecordType() {
|
||||
return recordType;
|
||||
}
|
||||
public void setRecordType(short recordType) {
|
||||
this.recordType = recordType;
|
||||
}
|
||||
public static int getDataSize() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
public short getGrbitFrt() {
|
||||
return grbitFrt;
|
||||
}
|
||||
public void setGrbitFrt(short grbitFrt) {
|
||||
this.grbitFrt = grbitFrt;
|
||||
}
|
||||
public short getRecordType() {
|
||||
return recordType;
|
||||
}
|
||||
public void setRecordType(short recordType) {
|
||||
this.recordType = recordType;
|
||||
}
|
||||
|
||||
public byte[] getReserved() {
|
||||
return reserved;
|
||||
}
|
||||
public void setReserved(byte[] reserved) {
|
||||
this.reserved = reserved;
|
||||
}
|
||||
public short getGrbitFrt() {
|
||||
return grbitFrt;
|
||||
}
|
||||
public void setGrbitFrt(short grbitFrt) {
|
||||
this.grbitFrt = grbitFrt;
|
||||
}
|
||||
|
||||
public CellRangeAddress getAssociatedRange() {
|
||||
return associatedRange;
|
||||
}
|
||||
public void setAssociatedRange(CellRangeAddress associatedRange) {
|
||||
this.associatedRange = associatedRange;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
FtrHeader result = new FtrHeader();
|
||||
result.recordType = recordType;
|
||||
result.grbitFrt = grbitFrt;
|
||||
result.associatedRange = associatedRange.copy();
|
||||
return result;
|
||||
}
|
||||
}
|
30
src/java/org/apache/poi/hssf/record/common/FutureRecord.java
Normal file
30
src/java/org/apache/poi/hssf/record/common/FutureRecord.java
Normal file
@ -0,0 +1,30 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.common;
|
||||
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
|
||||
/**
|
||||
* Title: Future Record, a newer (largely Excel 2007+) record
|
||||
* which contains a Future Record Header ({@link FtrHeader})
|
||||
*/
|
||||
public interface FutureRecord {
|
||||
public short getFutureRecordType();
|
||||
public FtrHeader getFutureHeader();
|
||||
public CellRangeAddress getAssociatedRange();
|
||||
}
|
@ -95,7 +95,7 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia
|
||||
|
||||
|
||||
public int readUByte() {
|
||||
return _cipher.xorByte(_le.readUByte());
|
||||
return readByte() & 0xFF;
|
||||
}
|
||||
public byte readByte() {
|
||||
return (byte) _cipher.xorByte(_le.readUByte());
|
||||
@ -103,7 +103,7 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia
|
||||
|
||||
|
||||
public int readUShort() {
|
||||
return _cipher.xorShort(_le.readUShort());
|
||||
return readShort() & 0xFFFF;
|
||||
}
|
||||
public short readShort() {
|
||||
return (short) _cipher.xorShort(_le.readUShort());
|
||||
|
@ -17,196 +17,246 @@
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.CFRuleBase;
|
||||
import org.apache.poi.hssf.record.cf.BorderFormatting;
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.ss.usermodel.Color;
|
||||
|
||||
/**
|
||||
* High level representation for Border Formatting component
|
||||
* of Conditional Formatting settings
|
||||
*/
|
||||
public final class HSSFBorderFormatting implements org.apache.poi.ss.usermodel.BorderFormatting
|
||||
{
|
||||
private final CFRuleRecord cfRuleRecord;
|
||||
private final BorderFormatting borderFormatting;
|
||||
|
||||
protected HSSFBorderFormatting(CFRuleRecord cfRuleRecord)
|
||||
{
|
||||
this.cfRuleRecord = cfRuleRecord;
|
||||
this.borderFormatting = cfRuleRecord.getBorderFormatting();
|
||||
}
|
||||
public final class HSSFBorderFormatting implements org.apache.poi.ss.usermodel.BorderFormatting {
|
||||
private final HSSFWorkbook workbook;
|
||||
private final CFRuleBase cfRuleRecord;
|
||||
private final BorderFormatting borderFormatting;
|
||||
|
||||
protected BorderFormatting getBorderFormattingBlock()
|
||||
{
|
||||
return borderFormatting;
|
||||
}
|
||||
protected HSSFBorderFormatting(CFRuleBase cfRuleRecord, HSSFWorkbook workbook) {
|
||||
this.workbook = workbook;
|
||||
this.cfRuleRecord = cfRuleRecord;
|
||||
this.borderFormatting = cfRuleRecord.getBorderFormatting();
|
||||
}
|
||||
|
||||
public short getBorderBottom()
|
||||
{
|
||||
return (short)borderFormatting.getBorderBottom();
|
||||
}
|
||||
protected BorderFormatting getBorderFormattingBlock() {
|
||||
return borderFormatting;
|
||||
}
|
||||
|
||||
public short getBorderDiagonal()
|
||||
{
|
||||
return (short)borderFormatting.getBorderDiagonal();
|
||||
}
|
||||
public short getBorderBottom() {
|
||||
return (short)borderFormatting.getBorderBottom();
|
||||
}
|
||||
|
||||
public short getBorderLeft()
|
||||
{
|
||||
return (short)borderFormatting.getBorderLeft();
|
||||
}
|
||||
public short getBorderDiagonal() {
|
||||
return (short)borderFormatting.getBorderDiagonal();
|
||||
}
|
||||
|
||||
public short getBorderRight()
|
||||
{
|
||||
return (short)borderFormatting.getBorderRight();
|
||||
}
|
||||
public short getBorderLeft() {
|
||||
return (short)borderFormatting.getBorderLeft();
|
||||
}
|
||||
|
||||
public short getBorderTop()
|
||||
{
|
||||
return (short)borderFormatting.getBorderTop();
|
||||
}
|
||||
public short getBorderRight() {
|
||||
return (short)borderFormatting.getBorderRight();
|
||||
}
|
||||
|
||||
public short getBottomBorderColor()
|
||||
{
|
||||
return (short)borderFormatting.getBottomBorderColor();
|
||||
}
|
||||
public short getBorderTop() {
|
||||
return (short)borderFormatting.getBorderTop();
|
||||
}
|
||||
|
||||
public short getDiagonalBorderColor()
|
||||
{
|
||||
return (short)borderFormatting.getDiagonalBorderColor();
|
||||
}
|
||||
public short getBottomBorderColor() {
|
||||
return (short)borderFormatting.getBottomBorderColor();
|
||||
}
|
||||
public HSSFColor getBottomBorderColorColor() {
|
||||
return workbook.getCustomPalette().getColor(
|
||||
borderFormatting.getBottomBorderColor()
|
||||
);
|
||||
}
|
||||
|
||||
public short getLeftBorderColor()
|
||||
{
|
||||
return (short)borderFormatting.getLeftBorderColor();
|
||||
}
|
||||
public short getDiagonalBorderColor() {
|
||||
return (short)borderFormatting.getDiagonalBorderColor();
|
||||
}
|
||||
public HSSFColor getDiagonalBorderColorColor() {
|
||||
return workbook.getCustomPalette().getColor(
|
||||
borderFormatting.getDiagonalBorderColor()
|
||||
);
|
||||
}
|
||||
|
||||
public short getRightBorderColor()
|
||||
{
|
||||
return (short)borderFormatting.getRightBorderColor();
|
||||
}
|
||||
public short getLeftBorderColor() {
|
||||
return (short)borderFormatting.getLeftBorderColor();
|
||||
}
|
||||
public HSSFColor getLeftBorderColorColor() {
|
||||
return workbook.getCustomPalette().getColor(
|
||||
borderFormatting.getLeftBorderColor()
|
||||
);
|
||||
}
|
||||
|
||||
public short getTopBorderColor()
|
||||
{
|
||||
return (short)borderFormatting.getTopBorderColor();
|
||||
}
|
||||
public short getRightBorderColor() {
|
||||
return (short)borderFormatting.getRightBorderColor();
|
||||
}
|
||||
public HSSFColor getRightBorderColorColor() {
|
||||
return workbook.getCustomPalette().getColor(
|
||||
borderFormatting.getRightBorderColor()
|
||||
);
|
||||
}
|
||||
|
||||
public boolean isBackwardDiagonalOn()
|
||||
{
|
||||
return borderFormatting.isBackwardDiagonalOn();
|
||||
}
|
||||
public short getTopBorderColor() {
|
||||
return (short)borderFormatting.getTopBorderColor();
|
||||
}
|
||||
public HSSFColor getTopBorderColorColor() {
|
||||
return workbook.getCustomPalette().getColor(
|
||||
borderFormatting.getTopBorderColor()
|
||||
);
|
||||
}
|
||||
|
||||
public boolean isForwardDiagonalOn()
|
||||
{
|
||||
return borderFormatting.isForwardDiagonalOn();
|
||||
}
|
||||
public boolean isBackwardDiagonalOn() {
|
||||
return borderFormatting.isBackwardDiagonalOn();
|
||||
}
|
||||
public boolean isForwardDiagonalOn() {
|
||||
return borderFormatting.isForwardDiagonalOn();
|
||||
}
|
||||
|
||||
public void setBackwardDiagonalOn(boolean on)
|
||||
{
|
||||
borderFormatting.setBackwardDiagonalOn(on);
|
||||
if( on )
|
||||
{
|
||||
cfRuleRecord.setTopLeftBottomRightBorderModified(on);
|
||||
}
|
||||
}
|
||||
public void setBackwardDiagonalOn(boolean on) {
|
||||
borderFormatting.setBackwardDiagonalOn(on);
|
||||
if (on) {
|
||||
cfRuleRecord.setTopLeftBottomRightBorderModified(on);
|
||||
}
|
||||
}
|
||||
public void setForwardDiagonalOn(boolean on) {
|
||||
borderFormatting.setForwardDiagonalOn(on);
|
||||
if (on) {
|
||||
cfRuleRecord.setBottomLeftTopRightBorderModified(on);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBorderBottom(short border)
|
||||
{
|
||||
borderFormatting.setBorderBottom(border);
|
||||
if( border != 0)
|
||||
{
|
||||
cfRuleRecord.setBottomBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setBorderBottom(short border) {
|
||||
borderFormatting.setBorderBottom(border);
|
||||
if (border != 0) {
|
||||
cfRuleRecord.setBottomBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setBottomBorderModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBorderDiagonal(short border)
|
||||
{
|
||||
borderFormatting.setBorderDiagonal(border);
|
||||
if( border != 0)
|
||||
{
|
||||
cfRuleRecord.setBottomLeftTopRightBorderModified(true);
|
||||
cfRuleRecord.setTopLeftBottomRightBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setBorderDiagonal(short border) {
|
||||
borderFormatting.setBorderDiagonal(border);
|
||||
if (border != 0) {
|
||||
cfRuleRecord.setBottomLeftTopRightBorderModified(true);
|
||||
cfRuleRecord.setTopLeftBottomRightBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setBottomLeftTopRightBorderModified(false);
|
||||
cfRuleRecord.setTopLeftBottomRightBorderModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBorderLeft(short border)
|
||||
{
|
||||
borderFormatting.setBorderLeft(border);
|
||||
if( border != 0)
|
||||
{
|
||||
cfRuleRecord.setLeftBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setBorderLeft(short border) {
|
||||
borderFormatting.setBorderLeft(border);
|
||||
if (border != 0) {
|
||||
cfRuleRecord.setLeftBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setLeftBorderModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBorderRight(short border)
|
||||
{
|
||||
borderFormatting.setBorderRight(border);
|
||||
if( border != 0)
|
||||
{
|
||||
cfRuleRecord.setRightBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setBorderRight(short border) {
|
||||
borderFormatting.setBorderRight(border);
|
||||
if (border != 0) {
|
||||
cfRuleRecord.setRightBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setRightBorderModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBorderTop(short border)
|
||||
{
|
||||
borderFormatting.setBorderTop(border);
|
||||
if( border != 0)
|
||||
{
|
||||
cfRuleRecord.setTopBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setBorderTop(short border) {
|
||||
borderFormatting.setBorderTop(border);
|
||||
if (border != 0) {
|
||||
cfRuleRecord.setTopBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setTopBorderModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBottomBorderColor(short color)
|
||||
{
|
||||
borderFormatting.setBottomBorderColor(color);
|
||||
if( color != 0)
|
||||
{
|
||||
cfRuleRecord.setBottomBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setBottomBorderColor(short color) {
|
||||
borderFormatting.setBottomBorderColor(color);
|
||||
if (color != 0) {
|
||||
cfRuleRecord.setBottomBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setBottomBorderModified(false);
|
||||
}
|
||||
}
|
||||
public void setBottomBorderColor(Color color) {
|
||||
HSSFColor hcolor = HSSFColor.toHSSFColor(color);
|
||||
if (hcolor == null) {
|
||||
setBottomBorderColor((short)0);
|
||||
} else {
|
||||
setBottomBorderColor(hcolor.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void setDiagonalBorderColor(short color)
|
||||
{
|
||||
borderFormatting.setDiagonalBorderColor(color);
|
||||
if( color != 0)
|
||||
{
|
||||
cfRuleRecord.setBottomLeftTopRightBorderModified(true);
|
||||
cfRuleRecord.setTopLeftBottomRightBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setDiagonalBorderColor(short color) {
|
||||
borderFormatting.setDiagonalBorderColor(color);
|
||||
if (color != 0) {
|
||||
cfRuleRecord.setBottomLeftTopRightBorderModified(true);
|
||||
cfRuleRecord.setTopLeftBottomRightBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setBottomLeftTopRightBorderModified(false);
|
||||
cfRuleRecord.setTopLeftBottomRightBorderModified(false);
|
||||
}
|
||||
}
|
||||
public void setDiagonalBorderColor(Color color) {
|
||||
HSSFColor hcolor = HSSFColor.toHSSFColor(color);
|
||||
if (hcolor == null) {
|
||||
setDiagonalBorderColor((short)0);
|
||||
} else {
|
||||
setDiagonalBorderColor(hcolor.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void setForwardDiagonalOn(boolean on)
|
||||
{
|
||||
borderFormatting.setForwardDiagonalOn(on);
|
||||
if( on )
|
||||
{
|
||||
cfRuleRecord.setBottomLeftTopRightBorderModified(on);
|
||||
}
|
||||
}
|
||||
public void setLeftBorderColor(short color) {
|
||||
borderFormatting.setLeftBorderColor(color);
|
||||
if (color != 0) {
|
||||
cfRuleRecord.setLeftBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setLeftBorderModified(false);
|
||||
}
|
||||
}
|
||||
public void setLeftBorderColor(Color color) {
|
||||
HSSFColor hcolor = HSSFColor.toHSSFColor(color);
|
||||
if (hcolor == null) {
|
||||
setLeftBorderColor((short)0);
|
||||
} else {
|
||||
setLeftBorderColor(hcolor.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void setLeftBorderColor(short color)
|
||||
{
|
||||
borderFormatting.setLeftBorderColor(color);
|
||||
if( color != 0)
|
||||
{
|
||||
cfRuleRecord.setLeftBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setRightBorderColor(short color) {
|
||||
borderFormatting.setRightBorderColor(color);
|
||||
if (color != 0) {
|
||||
cfRuleRecord.setRightBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setRightBorderModified(false);
|
||||
}
|
||||
}
|
||||
public void setRightBorderColor(Color color) {
|
||||
HSSFColor hcolor = HSSFColor.toHSSFColor(color);
|
||||
if (hcolor == null) {
|
||||
setRightBorderColor((short)0);
|
||||
} else {
|
||||
setRightBorderColor(hcolor.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void setRightBorderColor(short color)
|
||||
{
|
||||
borderFormatting.setRightBorderColor(color);
|
||||
if( color != 0)
|
||||
{
|
||||
cfRuleRecord.setRightBorderModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTopBorderColor(short color)
|
||||
{
|
||||
borderFormatting.setTopBorderColor(color);
|
||||
if( color != 0)
|
||||
{
|
||||
cfRuleRecord.setTopBorderModified(true);
|
||||
}
|
||||
}
|
||||
public void setTopBorderColor(short color) {
|
||||
borderFormatting.setTopBorderColor(color);
|
||||
if (color != 0) {
|
||||
cfRuleRecord.setTopBorderModified(true);
|
||||
} else {
|
||||
cfRuleRecord.setTopBorderModified(false);
|
||||
}
|
||||
}
|
||||
public void setTopBorderColor(Color color) {
|
||||
HSSFColor hcolor = HSSFColor.toHSSFColor(color);
|
||||
if (hcolor == null) {
|
||||
setTopBorderColor((short)0);
|
||||
} else {
|
||||
setTopBorderColor(hcolor.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -538,18 +538,17 @@ public class HSSFCell implements Cell {
|
||||
|
||||
public void setCellValue(RichTextString value)
|
||||
{
|
||||
HSSFRichTextString hvalue = (HSSFRichTextString) value;
|
||||
int row=_record.getRow();
|
||||
short col=_record.getColumn();
|
||||
short styleIndex=_record.getXFIndex();
|
||||
if (hvalue == null)
|
||||
if (value == null)
|
||||
{
|
||||
notifyFormulaChanging();
|
||||
setCellType(CELL_TYPE_BLANK, false, row, col, styleIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
if(hvalue.length() > SpreadsheetVersion.EXCEL97.getMaxTextLength()){
|
||||
if(value.length() > SpreadsheetVersion.EXCEL97.getMaxTextLength()){
|
||||
throw new IllegalArgumentException("The maximum length of cell contents (text) is 32,767 characters");
|
||||
}
|
||||
|
||||
@ -557,7 +556,7 @@ public class HSSFCell implements Cell {
|
||||
// Set the 'pre-evaluated result' for the formula
|
||||
// note - formulas do not preserve text formatting.
|
||||
FormulaRecordAggregate fr = (FormulaRecordAggregate) _record;
|
||||
fr.setCachedStringResult(hvalue.getString());
|
||||
fr.setCachedStringResult(value.getString());
|
||||
// Update our local cache to the un-formatted version
|
||||
_stringValue = new HSSFRichTextString(value.getString());
|
||||
|
||||
@ -573,6 +572,7 @@ public class HSSFCell implements Cell {
|
||||
}
|
||||
int index = 0;
|
||||
|
||||
HSSFRichTextString hvalue = (HSSFRichTextString) value;
|
||||
UnicodeString str = hvalue.getUnicodeString();
|
||||
index = _book.getWorkbook().addSSTString(str);
|
||||
(( LabelSSTRecord ) _record).setSSTIndex(index);
|
||||
|
@ -129,10 +129,13 @@ public class HSSFComment extends HSSFTextbox implements Comment {
|
||||
|
||||
@Override
|
||||
void setShapeId(int shapeId) {
|
||||
if(shapeId > 65535) {
|
||||
throw new IllegalArgumentException("Cannot add more than " + 65535 + " shapes");
|
||||
}
|
||||
super.setShapeId(shapeId);
|
||||
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
|
||||
cod.setObjectId((short) (shapeId % 1024));
|
||||
_note.setShapeId(shapeId % 1024);
|
||||
cod.setObjectId(shapeId);
|
||||
_note.setShapeId(shapeId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.CFRuleBase;
|
||||
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormatting;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
|
||||
@ -73,91 +73,84 @@ import org.apache.poi.ss.util.CellRangeAddress;
|
||||
* sheet.addConditionalFormatting(regions, rule);
|
||||
* </PRE>
|
||||
*/
|
||||
public final class HSSFConditionalFormatting implements ConditionalFormatting
|
||||
{
|
||||
private final HSSFWorkbook _workbook;
|
||||
private final CFRecordsAggregate cfAggregate;
|
||||
public final class HSSFConditionalFormatting implements ConditionalFormatting {
|
||||
private final HSSFSheet sheet;
|
||||
private final CFRecordsAggregate cfAggregate;
|
||||
|
||||
HSSFConditionalFormatting(HSSFWorkbook workbook, CFRecordsAggregate cfAggregate)
|
||||
{
|
||||
if(workbook == null) {
|
||||
throw new IllegalArgumentException("workbook must not be null");
|
||||
}
|
||||
if(cfAggregate == null) {
|
||||
throw new IllegalArgumentException("cfAggregate must not be null");
|
||||
}
|
||||
_workbook = workbook;
|
||||
this.cfAggregate = cfAggregate;
|
||||
}
|
||||
CFRecordsAggregate getCFRecordsAggregate() {
|
||||
return cfAggregate;
|
||||
}
|
||||
HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate) {
|
||||
if(sheet == null) {
|
||||
throw new IllegalArgumentException("sheet must not be null");
|
||||
}
|
||||
if(cfAggregate == null) {
|
||||
throw new IllegalArgumentException("cfAggregate must not be null");
|
||||
}
|
||||
this.sheet = sheet;
|
||||
this.cfAggregate = cfAggregate;
|
||||
}
|
||||
CFRecordsAggregate getCFRecordsAggregate() {
|
||||
return cfAggregate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated (Aug-2008) use {@link HSSFConditionalFormatting#getFormattingRanges()}
|
||||
*/
|
||||
public org.apache.poi.ss.util.Region[] getFormattingRegions()
|
||||
{
|
||||
CellRangeAddress[] cellRanges = getFormattingRanges();
|
||||
return org.apache.poi.ss.util.Region.convertCellRangesToRegions(cellRanges);
|
||||
}
|
||||
/**
|
||||
* @return array of <tt>CellRangeAddress</tt>s. never <code>null</code>
|
||||
*/
|
||||
public CellRangeAddress[] getFormattingRanges() {
|
||||
return cfAggregate.getHeader().getCellRanges();
|
||||
}
|
||||
/**
|
||||
* @deprecated (Aug-2008) use {@link HSSFConditionalFormatting#getFormattingRanges()}
|
||||
*/
|
||||
public org.apache.poi.ss.util.Region[] getFormattingRegions() {
|
||||
CellRangeAddress[] cellRanges = getFormattingRanges();
|
||||
return org.apache.poi.ss.util.Region.convertCellRangesToRegions(cellRanges);
|
||||
}
|
||||
/**
|
||||
* @return array of <tt>CellRangeAddress</tt>s. never <code>null</code>
|
||||
*/
|
||||
public CellRangeAddress[] getFormattingRanges() {
|
||||
return cfAggregate.getHeader().getCellRanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces an existing Conditional Formatting rule at position idx.
|
||||
* Excel allows to create up to 3 Conditional Formatting rules.
|
||||
* This method can be useful to modify existing Conditional Formatting rules.
|
||||
*
|
||||
* @param idx position of the rule. Should be between 0 and 2.
|
||||
* @param cfRule - Conditional Formatting rule
|
||||
*/
|
||||
public void setRule(int idx, HSSFConditionalFormattingRule cfRule)
|
||||
{
|
||||
cfAggregate.setRule(idx, cfRule.getCfRuleRecord());
|
||||
}
|
||||
/**
|
||||
* Replaces an existing Conditional Formatting rule at position idx.
|
||||
* Older versions of Excel only allow up to 3 Conditional Formatting rules,
|
||||
* and will ignore rules beyond that, while newer versions are fine.
|
||||
* This method can be useful to modify existing Conditional Formatting rules.
|
||||
*
|
||||
* @param idx position of the rule. Should be between 0 and 2 for older Excel versions
|
||||
* @param cfRule - Conditional Formatting rule
|
||||
*/
|
||||
public void setRule(int idx, HSSFConditionalFormattingRule cfRule) {
|
||||
cfAggregate.setRule(idx, cfRule.getCfRuleRecord());
|
||||
}
|
||||
|
||||
public void setRule(int idx, ConditionalFormattingRule cfRule){
|
||||
setRule(idx, (HSSFConditionalFormattingRule)cfRule);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a Conditional Formatting rule.
|
||||
* Excel allows to create up to 3 Conditional Formatting rules.
|
||||
* @param cfRule - Conditional Formatting rule
|
||||
*/
|
||||
public void addRule(HSSFConditionalFormattingRule cfRule)
|
||||
{
|
||||
cfAggregate.addRule(cfRule.getCfRuleRecord());
|
||||
}
|
||||
/**
|
||||
* add a Conditional Formatting rule.
|
||||
* Excel allows to create up to 3 Conditional Formatting rules.
|
||||
* @param cfRule - Conditional Formatting rule
|
||||
*/
|
||||
public void addRule(HSSFConditionalFormattingRule cfRule) {
|
||||
cfAggregate.addRule(cfRule.getCfRuleRecord());
|
||||
}
|
||||
|
||||
public void addRule(ConditionalFormattingRule cfRule){
|
||||
addRule((HSSFConditionalFormattingRule)cfRule);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the Conditional Formatting rule at position idx.
|
||||
*/
|
||||
public HSSFConditionalFormattingRule getRule(int idx)
|
||||
{
|
||||
CFRuleRecord ruleRecord = cfAggregate.getRule(idx);
|
||||
return new HSSFConditionalFormattingRule(_workbook, ruleRecord);
|
||||
}
|
||||
/**
|
||||
* @return the Conditional Formatting rule at position idx.
|
||||
*/
|
||||
public HSSFConditionalFormattingRule getRule(int idx) {
|
||||
CFRuleBase ruleRecord = cfAggregate.getRule(idx);
|
||||
return new HSSFConditionalFormattingRule(sheet, ruleRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of Conditional Formatting rules.
|
||||
*/
|
||||
public int getNumberOfRules()
|
||||
{
|
||||
return cfAggregate.getNumberOfRules();
|
||||
}
|
||||
/**
|
||||
* @return number of Conditional Formatting rules.
|
||||
*/
|
||||
public int getNumberOfRules() {
|
||||
return cfAggregate.getNumberOfRules();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return cfAggregate.toString();
|
||||
}
|
||||
public String toString() {
|
||||
return cfAggregate.toString();
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,16 @@
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.model.HSSFFormulaParser;
|
||||
import org.apache.poi.hssf.record.CFRule12Record;
|
||||
import org.apache.poi.hssf.record.CFRuleBase;
|
||||
import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator;
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
|
||||
import org.apache.poi.hssf.record.cf.BorderFormatting;
|
||||
import org.apache.poi.hssf.record.cf.FontFormatting;
|
||||
import org.apache.poi.hssf.record.cf.IconMultiStateFormatting;
|
||||
import org.apache.poi.hssf.record.cf.PatternFormatting;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.ss.usermodel.ConditionType;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
|
||||
|
||||
/**
|
||||
@ -32,178 +36,224 @@ import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
|
||||
* It allows to specify formula based conditions for the Conditional Formatting
|
||||
* and the formatting settings such as font, border and pattern.
|
||||
*/
|
||||
public final class HSSFConditionalFormattingRule implements ConditionalFormattingRule
|
||||
{
|
||||
private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
|
||||
public final class HSSFConditionalFormattingRule implements ConditionalFormattingRule {
|
||||
private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
|
||||
|
||||
private final CFRuleRecord cfRuleRecord;
|
||||
private final HSSFWorkbook workbook;
|
||||
private final CFRuleBase cfRuleRecord;
|
||||
private final HSSFWorkbook workbook;
|
||||
private final HSSFSheet sheet;
|
||||
|
||||
HSSFConditionalFormattingRule(HSSFWorkbook pWorkbook, CFRuleRecord pRuleRecord) {
|
||||
if (pWorkbook == null) {
|
||||
throw new IllegalArgumentException("pWorkbook must not be null");
|
||||
}
|
||||
if (pRuleRecord == null) {
|
||||
throw new IllegalArgumentException("pRuleRecord must not be null");
|
||||
}
|
||||
workbook = pWorkbook;
|
||||
cfRuleRecord = pRuleRecord;
|
||||
}
|
||||
HSSFConditionalFormattingRule(HSSFSheet pSheet, CFRuleBase pRuleRecord) {
|
||||
if (pSheet == null) {
|
||||
throw new IllegalArgumentException("pSheet must not be null");
|
||||
}
|
||||
if (pRuleRecord == null) {
|
||||
throw new IllegalArgumentException("pRuleRecord must not be null");
|
||||
}
|
||||
sheet = pSheet;
|
||||
workbook = pSheet.getWorkbook();
|
||||
cfRuleRecord = pRuleRecord;
|
||||
}
|
||||
|
||||
CFRuleRecord getCfRuleRecord()
|
||||
{
|
||||
return cfRuleRecord;
|
||||
}
|
||||
CFRuleBase getCfRuleRecord()
|
||||
{
|
||||
return cfRuleRecord;
|
||||
}
|
||||
|
||||
private HSSFFontFormatting getFontFormatting(boolean create)
|
||||
{
|
||||
FontFormatting fontFormatting = cfRuleRecord.getFontFormatting();
|
||||
if ( fontFormatting != null)
|
||||
{
|
||||
cfRuleRecord.setFontFormatting(fontFormatting);
|
||||
return new HSSFFontFormatting(cfRuleRecord);
|
||||
}
|
||||
else if( create )
|
||||
{
|
||||
fontFormatting = new FontFormatting();
|
||||
cfRuleRecord.setFontFormatting(fontFormatting);
|
||||
return new HSSFFontFormatting(cfRuleRecord);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private HSSFFontFormatting getFontFormatting(boolean create)
|
||||
{
|
||||
FontFormatting fontFormatting = cfRuleRecord.getFontFormatting();
|
||||
if ( fontFormatting != null)
|
||||
{
|
||||
cfRuleRecord.setFontFormatting(fontFormatting);
|
||||
return new HSSFFontFormatting(cfRuleRecord, workbook);
|
||||
}
|
||||
else if( create )
|
||||
{
|
||||
fontFormatting = new FontFormatting();
|
||||
cfRuleRecord.setFontFormatting(fontFormatting);
|
||||
return new HSSFFontFormatting(cfRuleRecord, workbook);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - font formatting object if defined, <code>null</code> otherwise
|
||||
*/
|
||||
public HSSFFontFormatting getFontFormatting()
|
||||
{
|
||||
return getFontFormatting(false);
|
||||
}
|
||||
/**
|
||||
* create a new font formatting structure if it does not exist,
|
||||
* otherwise just return existing object.
|
||||
* @return - font formatting object, never returns <code>null</code>.
|
||||
*/
|
||||
public HSSFFontFormatting createFontFormatting()
|
||||
{
|
||||
return getFontFormatting(true);
|
||||
}
|
||||
/**
|
||||
* @return - font formatting object if defined, <code>null</code> otherwise
|
||||
*/
|
||||
public HSSFFontFormatting getFontFormatting()
|
||||
{
|
||||
return getFontFormatting(false);
|
||||
}
|
||||
/**
|
||||
* create a new font formatting structure if it does not exist,
|
||||
* otherwise just return existing object.
|
||||
* @return - font formatting object, never returns <code>null</code>.
|
||||
*/
|
||||
public HSSFFontFormatting createFontFormatting()
|
||||
{
|
||||
return getFontFormatting(true);
|
||||
}
|
||||
|
||||
private HSSFBorderFormatting getBorderFormatting(boolean create)
|
||||
{
|
||||
BorderFormatting borderFormatting = cfRuleRecord.getBorderFormatting();
|
||||
if ( borderFormatting != null)
|
||||
{
|
||||
cfRuleRecord.setBorderFormatting(borderFormatting);
|
||||
return new HSSFBorderFormatting(cfRuleRecord);
|
||||
}
|
||||
else if( create )
|
||||
{
|
||||
borderFormatting = new BorderFormatting();
|
||||
cfRuleRecord.setBorderFormatting(borderFormatting);
|
||||
return new HSSFBorderFormatting(cfRuleRecord);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return - border formatting object if defined, <code>null</code> otherwise
|
||||
*/
|
||||
public HSSFBorderFormatting getBorderFormatting()
|
||||
{
|
||||
return getBorderFormatting(false);
|
||||
}
|
||||
/**
|
||||
* create a new border formatting structure if it does not exist,
|
||||
* otherwise just return existing object.
|
||||
* @return - border formatting object, never returns <code>null</code>.
|
||||
*/
|
||||
public HSSFBorderFormatting createBorderFormatting()
|
||||
{
|
||||
return getBorderFormatting(true);
|
||||
}
|
||||
private HSSFBorderFormatting getBorderFormatting(boolean create)
|
||||
{
|
||||
BorderFormatting borderFormatting = cfRuleRecord.getBorderFormatting();
|
||||
if ( borderFormatting != null)
|
||||
{
|
||||
cfRuleRecord.setBorderFormatting(borderFormatting);
|
||||
return new HSSFBorderFormatting(cfRuleRecord, workbook);
|
||||
}
|
||||
else if( create )
|
||||
{
|
||||
borderFormatting = new BorderFormatting();
|
||||
cfRuleRecord.setBorderFormatting(borderFormatting);
|
||||
return new HSSFBorderFormatting(cfRuleRecord, workbook);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return - border formatting object if defined, <code>null</code> otherwise
|
||||
*/
|
||||
public HSSFBorderFormatting getBorderFormatting()
|
||||
{
|
||||
return getBorderFormatting(false);
|
||||
}
|
||||
/**
|
||||
* create a new border formatting structure if it does not exist,
|
||||
* otherwise just return existing object.
|
||||
* @return - border formatting object, never returns <code>null</code>.
|
||||
*/
|
||||
public HSSFBorderFormatting createBorderFormatting()
|
||||
{
|
||||
return getBorderFormatting(true);
|
||||
}
|
||||
|
||||
private HSSFPatternFormatting getPatternFormatting(boolean create)
|
||||
{
|
||||
PatternFormatting patternFormatting = cfRuleRecord.getPatternFormatting();
|
||||
if ( patternFormatting != null)
|
||||
{
|
||||
cfRuleRecord.setPatternFormatting(patternFormatting);
|
||||
return new HSSFPatternFormatting(cfRuleRecord);
|
||||
}
|
||||
else if( create )
|
||||
{
|
||||
patternFormatting = new PatternFormatting();
|
||||
cfRuleRecord.setPatternFormatting(patternFormatting);
|
||||
return new HSSFPatternFormatting(cfRuleRecord);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private HSSFPatternFormatting getPatternFormatting(boolean create)
|
||||
{
|
||||
PatternFormatting patternFormatting = cfRuleRecord.getPatternFormatting();
|
||||
if ( patternFormatting != null)
|
||||
{
|
||||
cfRuleRecord.setPatternFormatting(patternFormatting);
|
||||
return new HSSFPatternFormatting(cfRuleRecord, workbook);
|
||||
}
|
||||
else if( create )
|
||||
{
|
||||
patternFormatting = new PatternFormatting();
|
||||
cfRuleRecord.setPatternFormatting(patternFormatting);
|
||||
return new HSSFPatternFormatting(cfRuleRecord, workbook);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - pattern formatting object if defined, <code>null</code> otherwise
|
||||
*/
|
||||
public HSSFPatternFormatting getPatternFormatting()
|
||||
{
|
||||
return getPatternFormatting(false);
|
||||
}
|
||||
/**
|
||||
* create a new pattern formatting structure if it does not exist,
|
||||
* otherwise just return existing object.
|
||||
* @return - pattern formatting object, never returns <code>null</code>.
|
||||
*/
|
||||
public HSSFPatternFormatting createPatternFormatting()
|
||||
{
|
||||
return getPatternFormatting(true);
|
||||
}
|
||||
/**
|
||||
* @return - pattern formatting object if defined, <code>null</code> otherwise
|
||||
*/
|
||||
public HSSFPatternFormatting getPatternFormatting()
|
||||
{
|
||||
return getPatternFormatting(false);
|
||||
}
|
||||
/**
|
||||
* create a new pattern formatting structure if it does not exist,
|
||||
* otherwise just return existing object.
|
||||
* @return - pattern formatting object, never returns <code>null</code>.
|
||||
*/
|
||||
public HSSFPatternFormatting createPatternFormatting()
|
||||
{
|
||||
return getPatternFormatting(true);
|
||||
}
|
||||
|
||||
private HSSFIconMultiStateFormatting getMultiStateFormatting(boolean create) {
|
||||
if (cfRuleRecord instanceof CFRule12Record) {
|
||||
// Good
|
||||
} else {
|
||||
if (create) throw new IllegalArgumentException("Can't convert a CF into a CF12 record");
|
||||
return null;
|
||||
}
|
||||
CFRule12Record cfRule12Record = (CFRule12Record)cfRuleRecord;
|
||||
IconMultiStateFormatting iconFormatting = cfRule12Record.getMultiStateFormatting();
|
||||
if (iconFormatting != null)
|
||||
{
|
||||
return new HSSFIconMultiStateFormatting(cfRule12Record, sheet);
|
||||
}
|
||||
else if( create )
|
||||
{
|
||||
iconFormatting = cfRule12Record.createMultiStateFormatting();
|
||||
return new HSSFIconMultiStateFormatting(cfRule12Record, sheet);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return icon / multi-state formatting object if defined, <code>null</code> otherwise
|
||||
*/
|
||||
public HSSFIconMultiStateFormatting getMultiStateFormatting() {
|
||||
return getMultiStateFormatting(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the conditiontype for the cfrule
|
||||
*/
|
||||
public byte getConditionType() {
|
||||
return cfRuleRecord.getConditionType();
|
||||
}
|
||||
/**
|
||||
* create a new icon / multi-state formatting object if it does not exist,
|
||||
* otherwise just return the existing object.
|
||||
*/
|
||||
public HSSFIconMultiStateFormatting createMultiStateFormatting() {
|
||||
return getMultiStateFormatting(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the conditiontype for the cfrule
|
||||
*/
|
||||
public byte getConditionType() {
|
||||
return cfRuleRecord.getConditionType();
|
||||
}
|
||||
/**
|
||||
* @return - the conditiontype for the cfrule
|
||||
*/
|
||||
public ConditionType getConditionTypeType() {
|
||||
return ConditionType.forId(getConditionType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the comparisionoperatation for the cfrule
|
||||
*/
|
||||
public byte getComparisonOperation() {
|
||||
return cfRuleRecord.getComparisonOperation();
|
||||
}
|
||||
/**
|
||||
* @return - the comparisionoperatation for the cfrule
|
||||
*/
|
||||
public byte getComparisonOperation() {
|
||||
return cfRuleRecord.getComparisonOperation();
|
||||
}
|
||||
|
||||
public String getFormula1()
|
||||
{
|
||||
return toFormulaString(cfRuleRecord.getParsedExpression1());
|
||||
}
|
||||
public String getFormula1()
|
||||
{
|
||||
return toFormulaString(cfRuleRecord.getParsedExpression1());
|
||||
}
|
||||
|
||||
public String getFormula2()
|
||||
{
|
||||
byte conditionType = cfRuleRecord.getConditionType();
|
||||
if (conditionType == CELL_COMPARISON) {
|
||||
byte comparisonOperation = cfRuleRecord.getComparisonOperation();
|
||||
switch(comparisonOperation)
|
||||
{
|
||||
case ComparisonOperator.BETWEEN:
|
||||
case ComparisonOperator.NOT_BETWEEN:
|
||||
return toFormulaString(cfRuleRecord.getParsedExpression2());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public String getFormula2() {
|
||||
byte conditionType = cfRuleRecord.getConditionType();
|
||||
if (conditionType == CELL_COMPARISON) {
|
||||
byte comparisonOperation = cfRuleRecord.getComparisonOperation();
|
||||
switch(comparisonOperation) {
|
||||
case ComparisonOperator.BETWEEN:
|
||||
case ComparisonOperator.NOT_BETWEEN:
|
||||
return toFormulaString(cfRuleRecord.getParsedExpression2());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String toFormulaString(Ptg[] parsedExpression)
|
||||
{
|
||||
if(parsedExpression ==null) {
|
||||
return null;
|
||||
}
|
||||
return HSSFFormulaParser.toFormulaString(workbook, parsedExpression);
|
||||
}
|
||||
protected String toFormulaString(Ptg[] parsedExpression) {
|
||||
return toFormulaString(parsedExpression, workbook);
|
||||
}
|
||||
protected static String toFormulaString(Ptg[] parsedExpression, HSSFWorkbook workbook) {
|
||||
if(parsedExpression == null || parsedExpression.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return HSSFFormulaParser.toFormulaString(workbook, parsedExpression);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import static org.apache.poi.hssf.record.CFRuleBase.parseFormula;
|
||||
import static org.apache.poi.hssf.usermodel.HSSFConditionalFormattingRule.toFormulaString;
|
||||
|
||||
import org.apache.poi.hssf.record.cf.Threshold;
|
||||
|
||||
/**
|
||||
* High level representation for Icon / Multi-State / Databar /
|
||||
* Colour Scale change thresholds
|
||||
*/
|
||||
public final class HSSFConditionalFormattingThreshold implements org.apache.poi.ss.usermodel.ConditionalFormattingThreshold {
|
||||
private final Threshold threshold;
|
||||
private final HSSFSheet sheet;
|
||||
private final HSSFWorkbook workbook;
|
||||
|
||||
protected HSSFConditionalFormattingThreshold(Threshold threshold, HSSFSheet sheet) {
|
||||
this.threshold = threshold;
|
||||
this.sheet = sheet;
|
||||
this.workbook = sheet.getWorkbook();
|
||||
}
|
||||
protected Threshold getThreshold() {
|
||||
return threshold;
|
||||
}
|
||||
|
||||
public RangeType getRangeType() {
|
||||
return RangeType.byId(threshold.getType());
|
||||
}
|
||||
public void setRangeType(RangeType type) {
|
||||
threshold.setType((byte)type.id);
|
||||
}
|
||||
|
||||
public String getFormula() {
|
||||
return toFormulaString(threshold.getParsedExpression(), workbook);
|
||||
}
|
||||
public void setFormula(String formula) {
|
||||
threshold.setParsedExpression(parseFormula(formula, sheet));
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return threshold.getValue();
|
||||
}
|
||||
public void setValue(Double value) {
|
||||
threshold.setValue(value);
|
||||
}
|
||||
}
|
@ -17,382 +17,388 @@
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.CFRuleBase;
|
||||
import org.apache.poi.hssf.record.cf.FontFormatting;
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.ss.usermodel.Color;
|
||||
/**
|
||||
* High level representation for Font Formatting component
|
||||
* of Conditional Formatting settings
|
||||
*/
|
||||
public final class HSSFFontFormatting implements org.apache.poi.ss.usermodel.FontFormatting
|
||||
{
|
||||
public final class HSSFFontFormatting implements org.apache.poi.ss.usermodel.FontFormatting {
|
||||
/** Underline type - None */
|
||||
public final static byte U_NONE = FontFormatting.U_NONE;
|
||||
/** Underline type - Single */
|
||||
public final static byte U_SINGLE = FontFormatting.U_SINGLE;
|
||||
/** Underline type - Double */
|
||||
public final static byte U_DOUBLE = FontFormatting.U_DOUBLE;
|
||||
/** Underline type - Single Accounting */
|
||||
public final static byte U_SINGLE_ACCOUNTING = FontFormatting.U_SINGLE_ACCOUNTING;
|
||||
/** Underline type - Double Accounting */
|
||||
public final static byte U_DOUBLE_ACCOUNTING = FontFormatting.U_DOUBLE_ACCOUNTING;
|
||||
|
||||
/** Underline type - None */
|
||||
public final static byte U_NONE = FontFormatting.U_NONE;
|
||||
/** Underline type - Single */
|
||||
public final static byte U_SINGLE = FontFormatting.U_SINGLE;
|
||||
/** Underline type - Double */
|
||||
public final static byte U_DOUBLE = FontFormatting.U_DOUBLE;
|
||||
/** Underline type - Single Accounting */
|
||||
public final static byte U_SINGLE_ACCOUNTING = FontFormatting.U_SINGLE_ACCOUNTING;
|
||||
/** Underline type - Double Accounting */
|
||||
public final static byte U_DOUBLE_ACCOUNTING = FontFormatting.U_DOUBLE_ACCOUNTING;
|
||||
private final FontFormatting fontFormatting;
|
||||
private final HSSFWorkbook workbook;
|
||||
|
||||
private final FontFormatting fontFormatting;
|
||||
|
||||
protected HSSFFontFormatting(CFRuleRecord cfRuleRecord)
|
||||
{
|
||||
this.fontFormatting = cfRuleRecord.getFontFormatting();
|
||||
}
|
||||
|
||||
protected FontFormatting getFontFormattingBlock()
|
||||
{
|
||||
return fontFormatting;
|
||||
}
|
||||
protected HSSFFontFormatting(CFRuleBase cfRuleRecord, HSSFWorkbook workbook) {
|
||||
this.fontFormatting = cfRuleRecord.getFontFormatting();
|
||||
this.workbook = workbook;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the type of super or subscript for the font
|
||||
*
|
||||
* @return super or subscript option
|
||||
* @see #SS_NONE
|
||||
* @see #SS_SUPER
|
||||
* @see #SS_SUB
|
||||
*/
|
||||
public short getEscapementType()
|
||||
{
|
||||
return fontFormatting.getEscapementType();
|
||||
}
|
||||
protected FontFormatting getFontFormattingBlock() {
|
||||
return fontFormatting;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return font color index
|
||||
*/
|
||||
public short getFontColorIndex()
|
||||
{
|
||||
return fontFormatting.getFontColorIndex();
|
||||
}
|
||||
/**
|
||||
* get the type of super or subscript for the font
|
||||
*
|
||||
* @return super or subscript option
|
||||
* @see #SS_NONE
|
||||
* @see #SS_SUPER
|
||||
* @see #SS_SUB
|
||||
*/
|
||||
public short getEscapementType()
|
||||
{
|
||||
return fontFormatting.getEscapementType();
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the height of the font in 1/20th point units
|
||||
*
|
||||
* @return fontheight (in points/20); or -1 if not modified
|
||||
*/
|
||||
public int getFontHeight()
|
||||
{
|
||||
return fontFormatting.getFontHeight();
|
||||
}
|
||||
/**
|
||||
* @return font color index
|
||||
*/
|
||||
public short getFontColorIndex()
|
||||
{
|
||||
return fontFormatting.getFontColorIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is
|
||||
* 0x190 for normal and 0x2bc for bold
|
||||
*
|
||||
* @return bw - a number between 100-1000 for the fonts "boldness"
|
||||
*/
|
||||
public HSSFColor getFontColor() {
|
||||
return workbook.getCustomPalette().getColor(
|
||||
getFontColorIndex()
|
||||
);
|
||||
}
|
||||
|
||||
public short getFontWeight()
|
||||
{
|
||||
return fontFormatting.getFontWeight();
|
||||
}
|
||||
public void setFontColor(Color color) {
|
||||
HSSFColor hcolor = HSSFColor.toHSSFColor(color);
|
||||
if (hcolor == null) {
|
||||
fontFormatting.setFontColorIndex((short)0);
|
||||
} else {
|
||||
fontFormatting.setFontColorIndex(hcolor.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#getRawRecord()
|
||||
*/
|
||||
protected byte[] getRawRecord()
|
||||
{
|
||||
return fontFormatting.getRawRecord();
|
||||
}
|
||||
/**
|
||||
* gets the height of the font in 1/20th point units
|
||||
*
|
||||
* @return fontheight (in points/20); or -1 if not modified
|
||||
*/
|
||||
public int getFontHeight() {
|
||||
return fontFormatting.getFontHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the type of underlining for the font
|
||||
*
|
||||
* @return font underlining type
|
||||
*
|
||||
* @see #U_NONE
|
||||
* @see #U_SINGLE
|
||||
* @see #U_DOUBLE
|
||||
* @see #U_SINGLE_ACCOUNTING
|
||||
* @see #U_DOUBLE_ACCOUNTING
|
||||
*/
|
||||
public short getUnderlineType()
|
||||
{
|
||||
return fontFormatting.getUnderlineType();
|
||||
}
|
||||
/**
|
||||
* get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is
|
||||
* 0x190 for normal and 0x2bc for bold
|
||||
*
|
||||
* @return bw - a number between 100-1000 for the fonts "boldness"
|
||||
*/
|
||||
public short getFontWeight() {
|
||||
return fontFormatting.getFontWeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* get whether the font weight is set to bold or not
|
||||
*
|
||||
* @return bold - whether the font is bold or not
|
||||
*/
|
||||
public boolean isBold()
|
||||
{
|
||||
return fontFormatting.isFontWeightModified() && fontFormatting.isBold();
|
||||
}
|
||||
/**
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#getRawRecord()
|
||||
*/
|
||||
protected byte[] getRawRecord() {
|
||||
return fontFormatting.getRawRecord();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if escapement type was modified from default
|
||||
*/
|
||||
public boolean isEscapementTypeModified()
|
||||
{
|
||||
return fontFormatting.isEscapementTypeModified();
|
||||
}
|
||||
/**
|
||||
* get the type of underlining for the font
|
||||
*
|
||||
* @return font underlining type
|
||||
*
|
||||
* @see #U_NONE
|
||||
* @see #U_SINGLE
|
||||
* @see #U_DOUBLE
|
||||
* @see #U_SINGLE_ACCOUNTING
|
||||
* @see #U_DOUBLE_ACCOUNTING
|
||||
*/
|
||||
public short getUnderlineType()
|
||||
{
|
||||
return fontFormatting.getUnderlineType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font cancellation was modified from default
|
||||
*/
|
||||
public boolean isFontCancellationModified()
|
||||
{
|
||||
return fontFormatting.isFontCancellationModified();
|
||||
}
|
||||
/**
|
||||
* get whether the font weight is set to bold or not
|
||||
*
|
||||
* @return bold - whether the font is bold or not
|
||||
*/
|
||||
public boolean isBold()
|
||||
{
|
||||
return fontFormatting.isFontWeightModified() && fontFormatting.isBold();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font outline type was modified from default
|
||||
*/
|
||||
public boolean isFontOutlineModified()
|
||||
{
|
||||
return fontFormatting.isFontOutlineModified();
|
||||
}
|
||||
/**
|
||||
* @return true if escapement type was modified from default
|
||||
*/
|
||||
public boolean isEscapementTypeModified()
|
||||
{
|
||||
return fontFormatting.isEscapementTypeModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font shadow type was modified from default
|
||||
*/
|
||||
public boolean isFontShadowModified()
|
||||
{
|
||||
return fontFormatting.isFontShadowModified();
|
||||
}
|
||||
/**
|
||||
* @return true if font cancellation was modified from default
|
||||
*/
|
||||
public boolean isFontCancellationModified()
|
||||
{
|
||||
return fontFormatting.isFontCancellationModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font style was modified from default
|
||||
*/
|
||||
public boolean isFontStyleModified()
|
||||
{
|
||||
return fontFormatting.isFontStyleModified();
|
||||
}
|
||||
/**
|
||||
* @return true if font outline type was modified from default
|
||||
*/
|
||||
public boolean isFontOutlineModified()
|
||||
{
|
||||
return fontFormatting.isFontOutlineModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font style was set to <i>italic</i>
|
||||
*/
|
||||
public boolean isItalic()
|
||||
{
|
||||
return fontFormatting.isFontStyleModified() && fontFormatting.isItalic();
|
||||
}
|
||||
/**
|
||||
* @return true if font shadow type was modified from default
|
||||
*/
|
||||
public boolean isFontShadowModified()
|
||||
{
|
||||
return fontFormatting.isFontShadowModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font outline is on
|
||||
*/
|
||||
public boolean isOutlineOn()
|
||||
{
|
||||
return fontFormatting.isFontOutlineModified() && fontFormatting.isOutlineOn();
|
||||
}
|
||||
/**
|
||||
* @return true if font style was modified from default
|
||||
*/
|
||||
public boolean isFontStyleModified()
|
||||
{
|
||||
return fontFormatting.isFontStyleModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font shadow is on
|
||||
*/
|
||||
public boolean isShadowOn()
|
||||
{
|
||||
return fontFormatting.isFontOutlineModified() && fontFormatting.isShadowOn();
|
||||
}
|
||||
/**
|
||||
* @return true if font style was set to <i>italic</i>
|
||||
*/
|
||||
public boolean isItalic()
|
||||
{
|
||||
return fontFormatting.isFontStyleModified() && fontFormatting.isItalic();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font strikeout is on
|
||||
*/
|
||||
public boolean isStruckout()
|
||||
{
|
||||
return fontFormatting.isFontCancellationModified() && fontFormatting.isStruckout();
|
||||
}
|
||||
/**
|
||||
* @return true if font outline is on
|
||||
*/
|
||||
public boolean isOutlineOn()
|
||||
{
|
||||
return fontFormatting.isFontOutlineModified() && fontFormatting.isOutlineOn();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font underline type was modified from default
|
||||
*/
|
||||
public boolean isUnderlineTypeModified()
|
||||
{
|
||||
return fontFormatting.isUnderlineTypeModified();
|
||||
}
|
||||
/**
|
||||
* @return true if font shadow is on
|
||||
*/
|
||||
public boolean isShadowOn()
|
||||
{
|
||||
return fontFormatting.isFontOutlineModified() && fontFormatting.isShadowOn();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if font weight was modified from default
|
||||
*/
|
||||
public boolean isFontWeightModified()
|
||||
{
|
||||
return fontFormatting.isFontWeightModified();
|
||||
}
|
||||
/**
|
||||
* @return true if font strikeout is on
|
||||
*/
|
||||
public boolean isStruckout()
|
||||
{
|
||||
return fontFormatting.isFontCancellationModified() && fontFormatting.isStruckout();
|
||||
}
|
||||
|
||||
/**
|
||||
* set font style options.
|
||||
*
|
||||
* @param italic - if true, set posture style to italic, otherwise to normal
|
||||
* @param bold if true, set font weight to bold, otherwise to normal
|
||||
*/
|
||||
|
||||
public void setFontStyle(boolean italic, boolean bold)
|
||||
{
|
||||
boolean modified = italic || bold;
|
||||
fontFormatting.setItalic(italic);
|
||||
fontFormatting.setBold(bold);
|
||||
fontFormatting.setFontStyleModified(modified);
|
||||
fontFormatting.setFontWieghtModified(modified);
|
||||
}
|
||||
/**
|
||||
* @return true if font underline type was modified from default
|
||||
*/
|
||||
public boolean isUnderlineTypeModified()
|
||||
{
|
||||
return fontFormatting.isUnderlineTypeModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* set font style options to default values (non-italic, non-bold)
|
||||
*/
|
||||
public void resetFontStyle()
|
||||
{
|
||||
setFontStyle(false,false);
|
||||
}
|
||||
/**
|
||||
* @return true if font weight was modified from default
|
||||
*/
|
||||
public boolean isFontWeightModified()
|
||||
{
|
||||
return fontFormatting.isFontWeightModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* set the escapement type for the font
|
||||
*
|
||||
* @param escapementType super or subscript option
|
||||
* @see #SS_NONE
|
||||
* @see #SS_SUPER
|
||||
* @see #SS_SUB
|
||||
*/
|
||||
public void setEscapementType(short escapementType)
|
||||
{
|
||||
switch(escapementType)
|
||||
{
|
||||
case HSSFFontFormatting.SS_SUB:
|
||||
case HSSFFontFormatting.SS_SUPER:
|
||||
fontFormatting.setEscapementType(escapementType);
|
||||
fontFormatting.setEscapementTypeModified(true);
|
||||
break;
|
||||
case HSSFFontFormatting.SS_NONE:
|
||||
fontFormatting.setEscapementType(escapementType);
|
||||
fontFormatting.setEscapementTypeModified(false);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
/**
|
||||
* set font style options.
|
||||
*
|
||||
* @param italic - if true, set posture style to italic, otherwise to normal
|
||||
* @param bold if true, set font weight to bold, otherwise to normal
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setEscapementTypeModified(boolean)
|
||||
*/
|
||||
public void setEscapementTypeModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setEscapementTypeModified(modified);
|
||||
}
|
||||
public void setFontStyle(boolean italic, boolean bold)
|
||||
{
|
||||
boolean modified = italic || bold;
|
||||
fontFormatting.setItalic(italic);
|
||||
fontFormatting.setBold(bold);
|
||||
fontFormatting.setFontStyleModified(modified);
|
||||
fontFormatting.setFontWieghtModified(modified);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontCancellationModified(boolean)
|
||||
*/
|
||||
public void setFontCancellationModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setFontCancellationModified(modified);
|
||||
}
|
||||
/**
|
||||
* set font style options to default values (non-italic, non-bold)
|
||||
*/
|
||||
public void resetFontStyle()
|
||||
{
|
||||
setFontStyle(false,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fci
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontColorIndex(short)
|
||||
*/
|
||||
public void setFontColorIndex(short fci)
|
||||
{
|
||||
fontFormatting.setFontColorIndex(fci);
|
||||
}
|
||||
/**
|
||||
* set the escapement type for the font
|
||||
*
|
||||
* @param escapementType super or subscript option
|
||||
* @see #SS_NONE
|
||||
* @see #SS_SUPER
|
||||
* @see #SS_SUB
|
||||
*/
|
||||
public void setEscapementType(short escapementType) {
|
||||
switch(escapementType) {
|
||||
case HSSFFontFormatting.SS_SUB:
|
||||
case HSSFFontFormatting.SS_SUPER:
|
||||
fontFormatting.setEscapementType(escapementType);
|
||||
fontFormatting.setEscapementTypeModified(true);
|
||||
break;
|
||||
case HSSFFontFormatting.SS_NONE:
|
||||
fontFormatting.setEscapementType(escapementType);
|
||||
fontFormatting.setEscapementTypeModified(false);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param height
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontHeight(int)
|
||||
*/
|
||||
public void setFontHeight(int height)
|
||||
{
|
||||
fontFormatting.setFontHeight(height);
|
||||
}
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setEscapementTypeModified(boolean)
|
||||
*/
|
||||
public void setEscapementTypeModified(boolean modified) {
|
||||
fontFormatting.setEscapementTypeModified(modified);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontOutlineModified(boolean)
|
||||
*/
|
||||
public void setFontOutlineModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setFontOutlineModified(modified);
|
||||
}
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontCancellationModified(boolean)
|
||||
*/
|
||||
public void setFontCancellationModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setFontCancellationModified(modified);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontShadowModified(boolean)
|
||||
*/
|
||||
public void setFontShadowModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setFontShadowModified(modified);
|
||||
}
|
||||
/**
|
||||
* @param fci
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontColorIndex(short)
|
||||
*/
|
||||
public void setFontColorIndex(short fci)
|
||||
{
|
||||
fontFormatting.setFontColorIndex(fci);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontStyleModified(boolean)
|
||||
*/
|
||||
public void setFontStyleModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setFontStyleModified(modified);
|
||||
}
|
||||
/**
|
||||
* @param height
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontHeight(int)
|
||||
*/
|
||||
public void setFontHeight(int height)
|
||||
{
|
||||
fontFormatting.setFontHeight(height);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param on
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setOutline(boolean)
|
||||
*/
|
||||
public void setOutline(boolean on)
|
||||
{
|
||||
fontFormatting.setOutline(on);
|
||||
fontFormatting.setFontOutlineModified(on);
|
||||
}
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontOutlineModified(boolean)
|
||||
*/
|
||||
public void setFontOutlineModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setFontOutlineModified(modified);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param on
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setShadow(boolean)
|
||||
*/
|
||||
public void setShadow(boolean on)
|
||||
{
|
||||
fontFormatting.setShadow(on);
|
||||
fontFormatting.setFontShadowModified(on);
|
||||
}
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontShadowModified(boolean)
|
||||
*/
|
||||
public void setFontShadowModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setFontShadowModified(modified);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param strike
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setStrikeout(boolean)
|
||||
*/
|
||||
public void setStrikeout(boolean strike)
|
||||
{
|
||||
fontFormatting.setStrikeout(strike);
|
||||
fontFormatting.setFontCancellationModified(strike);
|
||||
}
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontStyleModified(boolean)
|
||||
*/
|
||||
public void setFontStyleModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setFontStyleModified(modified);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the type of underlining type for the font
|
||||
*
|
||||
* @param underlineType super or subscript option
|
||||
*
|
||||
* @see #U_NONE
|
||||
* @see #U_SINGLE
|
||||
* @see #U_DOUBLE
|
||||
* @see #U_SINGLE_ACCOUNTING
|
||||
* @see #U_DOUBLE_ACCOUNTING
|
||||
*/
|
||||
public void setUnderlineType(short underlineType)
|
||||
{
|
||||
switch(underlineType)
|
||||
{
|
||||
case HSSFFontFormatting.U_SINGLE:
|
||||
case HSSFFontFormatting.U_DOUBLE:
|
||||
case HSSFFontFormatting.U_SINGLE_ACCOUNTING:
|
||||
case HSSFFontFormatting.U_DOUBLE_ACCOUNTING:
|
||||
fontFormatting.setUnderlineType(underlineType);
|
||||
setUnderlineTypeModified(true);
|
||||
break;
|
||||
|
||||
case HSSFFontFormatting.U_NONE:
|
||||
fontFormatting.setUnderlineType(underlineType);
|
||||
setUnderlineTypeModified(false);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param on
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setOutline(boolean)
|
||||
*/
|
||||
public void setOutline(boolean on)
|
||||
{
|
||||
fontFormatting.setOutline(on);
|
||||
fontFormatting.setFontOutlineModified(on);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setUnderlineTypeModified(boolean)
|
||||
*/
|
||||
public void setUnderlineTypeModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setUnderlineTypeModified(modified);
|
||||
}
|
||||
/**
|
||||
* @param on
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setShadow(boolean)
|
||||
*/
|
||||
public void setShadow(boolean on)
|
||||
{
|
||||
fontFormatting.setShadow(on);
|
||||
fontFormatting.setFontShadowModified(on);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param strike
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setStrikeout(boolean)
|
||||
*/
|
||||
public void setStrikeout(boolean strike)
|
||||
{
|
||||
fontFormatting.setStrikeout(strike);
|
||||
fontFormatting.setFontCancellationModified(strike);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the type of underlining type for the font
|
||||
*
|
||||
* @param underlineType super or subscript option
|
||||
*
|
||||
* @see #U_NONE
|
||||
* @see #U_SINGLE
|
||||
* @see #U_DOUBLE
|
||||
* @see #U_SINGLE_ACCOUNTING
|
||||
* @see #U_DOUBLE_ACCOUNTING
|
||||
*/
|
||||
public void setUnderlineType(short underlineType) {
|
||||
switch(underlineType) {
|
||||
case HSSFFontFormatting.U_SINGLE:
|
||||
case HSSFFontFormatting.U_DOUBLE:
|
||||
case HSSFFontFormatting.U_SINGLE_ACCOUNTING:
|
||||
case HSSFFontFormatting.U_DOUBLE_ACCOUNTING:
|
||||
fontFormatting.setUnderlineType(underlineType);
|
||||
setUnderlineTypeModified(true);
|
||||
break;
|
||||
|
||||
case HSSFFontFormatting.U_NONE:
|
||||
fontFormatting.setUnderlineType(underlineType);
|
||||
setUnderlineTypeModified(false);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modified
|
||||
* @see org.apache.poi.hssf.record.cf.FontFormatting#setUnderlineTypeModified(boolean)
|
||||
*/
|
||||
public void setUnderlineTypeModified(boolean modified)
|
||||
{
|
||||
fontFormatting.setUnderlineTypeModified(modified);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.CFRule12Record;
|
||||
import org.apache.poi.hssf.record.cf.IconMultiStateFormatting;
|
||||
import org.apache.poi.hssf.record.cf.Threshold;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold;
|
||||
|
||||
/**
|
||||
* High level representation for Icon / Multi-State Formatting
|
||||
* component of Conditional Formatting settings
|
||||
*/
|
||||
public final class HSSFIconMultiStateFormatting implements org.apache.poi.ss.usermodel.IconMultiStateFormatting {
|
||||
private final HSSFSheet sheet;
|
||||
private final CFRule12Record cfRule12Record;
|
||||
private final IconMultiStateFormatting iconFormatting;
|
||||
|
||||
protected HSSFIconMultiStateFormatting(CFRule12Record cfRule12Record, HSSFSheet sheet) {
|
||||
this.sheet = sheet;
|
||||
this.cfRule12Record = cfRule12Record;
|
||||
this.iconFormatting = this.cfRule12Record.getMultiStateFormatting();
|
||||
}
|
||||
|
||||
public IconSet getIconSet() {
|
||||
return iconFormatting.getIconSet();
|
||||
}
|
||||
public void setIconSet(IconSet set) {
|
||||
iconFormatting.setIconSet(set);
|
||||
}
|
||||
|
||||
public boolean isIconOnly() {
|
||||
return iconFormatting.isIconOnly();
|
||||
}
|
||||
public void setIconOnly(boolean only) {
|
||||
iconFormatting.setIconOnly(only);
|
||||
}
|
||||
|
||||
public boolean isReversed() {
|
||||
return iconFormatting.isReversed();
|
||||
}
|
||||
public void setReversed(boolean reversed) {
|
||||
iconFormatting.setReversed(reversed);
|
||||
}
|
||||
|
||||
public HSSFConditionalFormattingThreshold[] getThresholds() {
|
||||
Threshold[] t = iconFormatting.getThresholds();
|
||||
HSSFConditionalFormattingThreshold[] ht = new HSSFConditionalFormattingThreshold[t.length];
|
||||
for (int i=0; i<t.length; i++) {
|
||||
ht[i] = new HSSFConditionalFormattingThreshold(t[i], sheet);
|
||||
}
|
||||
return ht;
|
||||
}
|
||||
|
||||
public void setThresholds(ConditionalFormattingThreshold[] thresholds) {
|
||||
Threshold[] t = new Threshold[thresholds.length];
|
||||
for (int i=0; i<t.length; i++) {
|
||||
t[i] = ((HSSFConditionalFormattingThreshold)thresholds[i]).getThreshold();
|
||||
}
|
||||
iconFormatting.setThresholds(t);
|
||||
}
|
||||
|
||||
public HSSFConditionalFormattingThreshold createThreshold() {
|
||||
return new HSSFConditionalFormattingThreshold(new Threshold(), sheet);
|
||||
}
|
||||
}
|
@ -45,7 +45,6 @@ import org.apache.poi.hssf.record.ObjRecord;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.ss.usermodel.Chart;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
|
@ -17,88 +17,116 @@
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.CFRuleBase;
|
||||
import org.apache.poi.hssf.record.cf.PatternFormatting;
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.ss.usermodel.Color;
|
||||
|
||||
/**
|
||||
* High level representation for Conditional Formatting settings
|
||||
*/
|
||||
public class HSSFPatternFormatting implements org.apache.poi.ss.usermodel.PatternFormatting
|
||||
{
|
||||
private final CFRuleRecord cfRuleRecord;
|
||||
private final PatternFormatting patternFormatting;
|
||||
|
||||
protected HSSFPatternFormatting(CFRuleRecord cfRuleRecord)
|
||||
{
|
||||
this.cfRuleRecord = cfRuleRecord;
|
||||
this.patternFormatting = cfRuleRecord.getPatternFormatting();
|
||||
}
|
||||
public class HSSFPatternFormatting implements org.apache.poi.ss.usermodel.PatternFormatting {
|
||||
private final HSSFWorkbook workbook;
|
||||
private final CFRuleBase cfRuleRecord;
|
||||
private final PatternFormatting patternFormatting;
|
||||
|
||||
protected PatternFormatting getPatternFormattingBlock()
|
||||
{
|
||||
return patternFormatting;
|
||||
}
|
||||
protected HSSFPatternFormatting(CFRuleBase cfRuleRecord, HSSFWorkbook workbook) {
|
||||
this.workbook = workbook;
|
||||
this.cfRuleRecord = cfRuleRecord;
|
||||
this.patternFormatting = cfRuleRecord.getPatternFormatting();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillBackgroundColor()
|
||||
*/
|
||||
public short getFillBackgroundColor()
|
||||
{
|
||||
return (short)patternFormatting.getFillBackgroundColor();
|
||||
}
|
||||
protected PatternFormatting getPatternFormattingBlock()
|
||||
{
|
||||
return patternFormatting;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillForegroundColor()
|
||||
*/
|
||||
public short getFillForegroundColor()
|
||||
{
|
||||
return (short)patternFormatting.getFillForegroundColor();
|
||||
}
|
||||
public HSSFColor getFillBackgroundColorColor() {
|
||||
return workbook.getCustomPalette().getColor(getFillBackgroundColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillPattern()
|
||||
*/
|
||||
public short getFillPattern()
|
||||
{
|
||||
return (short)patternFormatting.getFillPattern();
|
||||
}
|
||||
public HSSFColor getFillForegroundColorColor() {
|
||||
return workbook.getCustomPalette().getColor(getFillForegroundColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bg
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillBackgroundColor(int)
|
||||
*/
|
||||
public void setFillBackgroundColor(short bg)
|
||||
{
|
||||
patternFormatting.setFillBackgroundColor(bg);
|
||||
if( bg != 0)
|
||||
{
|
||||
cfRuleRecord.setPatternBackgroundColorModified(true);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillBackgroundColor()
|
||||
*/
|
||||
public short getFillBackgroundColor()
|
||||
{
|
||||
return (short)patternFormatting.getFillBackgroundColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fg
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillForegroundColor(int)
|
||||
*/
|
||||
public void setFillForegroundColor(short fg)
|
||||
{
|
||||
patternFormatting.setFillForegroundColor(fg);
|
||||
if( fg != 0)
|
||||
{
|
||||
cfRuleRecord.setPatternColorModified(true);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillForegroundColor()
|
||||
*/
|
||||
public short getFillForegroundColor()
|
||||
{
|
||||
return (short)patternFormatting.getFillForegroundColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fp
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillPattern(int)
|
||||
*/
|
||||
public void setFillPattern(short fp)
|
||||
{
|
||||
patternFormatting.setFillPattern(fp);
|
||||
if( fp != 0)
|
||||
{
|
||||
cfRuleRecord.setPatternStyleModified(true);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#getFillPattern()
|
||||
*/
|
||||
public short getFillPattern()
|
||||
{
|
||||
return (short)patternFormatting.getFillPattern();
|
||||
}
|
||||
|
||||
public void setFillBackgroundColor(Color bg) {
|
||||
HSSFColor hcolor = HSSFColor.toHSSFColor(bg);
|
||||
if (hcolor == null) {
|
||||
setFillBackgroundColor((short)0);
|
||||
} else {
|
||||
setFillBackgroundColor(hcolor.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void setFillForegroundColor(Color fg) {
|
||||
HSSFColor hcolor = HSSFColor.toHSSFColor(fg);
|
||||
if (hcolor == null) {
|
||||
setFillForegroundColor((short)0);
|
||||
} else {
|
||||
setFillForegroundColor(hcolor.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bg
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillBackgroundColor(int)
|
||||
*/
|
||||
public void setFillBackgroundColor(short bg)
|
||||
{
|
||||
patternFormatting.setFillBackgroundColor(bg);
|
||||
if( bg != 0)
|
||||
{
|
||||
cfRuleRecord.setPatternBackgroundColorModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fg
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillForegroundColor(int)
|
||||
*/
|
||||
public void setFillForegroundColor(short fg)
|
||||
{
|
||||
patternFormatting.setFillForegroundColor(fg);
|
||||
if( fg != 0)
|
||||
{
|
||||
cfRuleRecord.setPatternColorModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fp
|
||||
* @see org.apache.poi.hssf.record.cf.PatternFormatting#setFillPattern(int)
|
||||
*/
|
||||
public void setFillPattern(short fp)
|
||||
{
|
||||
patternFormatting.setFillPattern(fp);
|
||||
if( fp != 0)
|
||||
{
|
||||
cfRuleRecord.setPatternStyleModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,13 +29,6 @@ import java.util.Map;
|
||||
* Factory class for producing Excel Shapes from Escher records
|
||||
*/
|
||||
public class HSSFShapeFactory {
|
||||
|
||||
private final static short OBJECT_TYPE_LINE = 1;
|
||||
private final static short OBJECT_TYPE_RECTANGLE = 2;
|
||||
private final static short OBJECT_TYPE_OVAL = 3;
|
||||
private final static short OBJECT_TYPE_ARC = 4;
|
||||
private final static short OBJECT_TYPE_PICTURE = 8;
|
||||
|
||||
/**
|
||||
* build shape tree from escher container
|
||||
* @param container root escher container from which escher records must be taken
|
||||
@ -81,7 +74,7 @@ public class HSSFShapeFactory {
|
||||
return;
|
||||
}
|
||||
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0);
|
||||
HSSFShape shape;
|
||||
final HSSFShape shape;
|
||||
switch (cmo.getObjectType()) {
|
||||
case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE:
|
||||
shape = new HSSFPicture(container, objRecord);
|
||||
@ -97,11 +90,15 @@ public class HSSFShapeFactory {
|
||||
break;
|
||||
case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING:
|
||||
EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);
|
||||
EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);
|
||||
if (null != property) {
|
||||
shape = new HSSFPolygon(container, objRecord, txtRecord);
|
||||
if(optRecord == null) {
|
||||
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
|
||||
} else {
|
||||
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
|
||||
EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);
|
||||
if (null != property) {
|
||||
shape = new HSSFPolygon(container, objRecord, txtRecord);
|
||||
} else {
|
||||
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT:
|
||||
|
@ -867,6 +867,17 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
|
||||
return _sheet.getMergedRegionAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of merged regions
|
||||
*/
|
||||
public List<CellRangeAddress> getMergedRegions() {
|
||||
List<CellRangeAddress> addresses = new ArrayList<CellRangeAddress>();
|
||||
for (int i=0; i < _sheet.getNumMergedRegions(); i++) {
|
||||
addresses.add(_sheet.getMergedRegionAt(i));
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not
|
||||
* be the third row if say for instance the second row is undefined.
|
||||
|
@ -17,142 +17,156 @@
|
||||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.CFRule12Record;
|
||||
import org.apache.poi.hssf.record.CFRuleBase;
|
||||
import org.apache.poi.hssf.record.CFRuleRecord;
|
||||
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormatting;
|
||||
import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
|
||||
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
|
||||
import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
|
||||
/**
|
||||
* The 'Conditional Formatting' facet of <tt>HSSFSheet</tt>
|
||||
*/
|
||||
public final class HSSFSheetConditionalFormatting implements SheetConditionalFormatting {
|
||||
private final HSSFSheet _sheet;
|
||||
private final ConditionalFormattingTable _conditionalFormattingTable;
|
||||
|
||||
private final HSSFSheet _sheet;
|
||||
private final ConditionalFormattingTable _conditionalFormattingTable;
|
||||
/* package */ HSSFSheetConditionalFormatting(HSSFSheet sheet) {
|
||||
_sheet = sheet;
|
||||
_conditionalFormattingTable = sheet.getSheet().getConditionalFormattingTable();
|
||||
}
|
||||
|
||||
/* package */ HSSFSheetConditionalFormatting(HSSFSheet sheet) {
|
||||
_sheet = sheet;
|
||||
_conditionalFormattingTable = sheet.getSheet().getConditionalFormattingTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule
|
||||
* with a cell comparison operator<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
*
|
||||
* @param comparisonOperation - a constant value from
|
||||
* <tt>{@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator}</tt>: <p>
|
||||
* <ul>
|
||||
* <li>BETWEEN</li>
|
||||
* <li>NOT_BETWEEN</li>
|
||||
* <li>EQUAL</li>
|
||||
* <li>NOT_EQUAL</li>
|
||||
* <li>GT</li>
|
||||
* <li>LT</li>
|
||||
* <li>GE</li>
|
||||
* <li>LE</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* @param formula1 - formula for the valued, compared with the cell
|
||||
* @param formula2 - second formula (only used with
|
||||
* {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#BETWEEN}) and
|
||||
* {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#NOT_BETWEEN} operations)
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(
|
||||
byte comparisonOperation,
|
||||
String formula1,
|
||||
String formula2) {
|
||||
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, formula2);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
}
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule
|
||||
* with a cell comparison operator<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
*
|
||||
* @param comparisonOperation - a constant value from
|
||||
* <tt>{@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator}</tt>: <p>
|
||||
* <ul>
|
||||
* <li>BETWEEN</li>
|
||||
* <li>NOT_BETWEEN</li>
|
||||
* <li>EQUAL</li>
|
||||
* <li>NOT_EQUAL</li>
|
||||
* <li>GT</li>
|
||||
* <li>LT</li>
|
||||
* <li>GE</li>
|
||||
* <li>LE</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* @param formula1 - formula for the valued, compared with the cell
|
||||
* @param formula2 - second formula (only used with
|
||||
* {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#BETWEEN}) and
|
||||
* {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#NOT_BETWEEN} operations)
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(
|
||||
byte comparisonOperation,
|
||||
String formula1,
|
||||
String formula2) {
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, formula2);
|
||||
return new HSSFConditionalFormattingRule(_sheet, rr);
|
||||
}
|
||||
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(
|
||||
byte comparisonOperation,
|
||||
String formula1) {
|
||||
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, null);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
return new HSSFConditionalFormattingRule(_sheet, rr);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule with a formula.<br>
|
||||
*
|
||||
* The formatting rules are applied by Excel when the value of the formula not equal to 0.<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
* @param formula - formula for the valued, compared with the cell
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
|
||||
HSSFWorkbook wb = _sheet.getWorkbook();
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, formula);
|
||||
return new HSSFConditionalFormattingRule(wb, rr);
|
||||
}
|
||||
/**
|
||||
* A factory method allowing to create a conditional formatting rule with a formula.<br>
|
||||
*
|
||||
* The formatting rules are applied by Excel when the value of the formula not equal to 0.<p/>
|
||||
* TODO - formulas containing cell references are currently not parsed properly
|
||||
* @param formula - formula for the valued, compared with the cell
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {
|
||||
CFRuleRecord rr = CFRuleRecord.create(_sheet, formula);
|
||||
return new HSSFConditionalFormattingRule(_sheet, rr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a copy of HSSFConditionalFormatting object to the sheet
|
||||
* <p>This method could be used to copy HSSFConditionalFormatting object
|
||||
* from one sheet to another. For example:
|
||||
* <pre>
|
||||
* HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
|
||||
* newSheet.addConditionalFormatting(cf);
|
||||
* </pre>
|
||||
*
|
||||
* @param cf HSSFConditionalFormatting object
|
||||
* @return index of the new Conditional Formatting object
|
||||
*/
|
||||
public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
|
||||
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
|
||||
/**
|
||||
* A factory method allowing the creation of conditional formatting
|
||||
* rules using an Icon Set / Multi-State formatting.
|
||||
* The thresholds for it will be created, but will be empty
|
||||
* and require configuring with
|
||||
* {@link HSSFConditionalFormattingRule#getMultiStateFormatting()}
|
||||
* then
|
||||
* {@link HSSFIconMultiStateFormatting#getThresholds()}
|
||||
*/
|
||||
public HSSFConditionalFormattingRule createConditionalFormattingRule(
|
||||
IconSet iconSet) {
|
||||
CFRule12Record rr = CFRule12Record.create(_sheet, iconSet);
|
||||
return new HSSFConditionalFormattingRule(_sheet, rr);
|
||||
}
|
||||
|
||||
return _conditionalFormattingTable.add(cfraClone);
|
||||
}
|
||||
// TODO Support types beyond CELL_VALUE_IS and FORMULA and ICONs
|
||||
|
||||
/**
|
||||
* Adds a copy of HSSFConditionalFormatting object to the sheet
|
||||
* <p>This method could be used to copy HSSFConditionalFormatting object
|
||||
* from one sheet to another. For example:
|
||||
* <pre>
|
||||
* HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
|
||||
* newSheet.addConditionalFormatting(cf);
|
||||
* </pre>
|
||||
*
|
||||
* @param cf HSSFConditionalFormatting object
|
||||
* @return index of the new Conditional Formatting object
|
||||
*/
|
||||
public int addConditionalFormatting( HSSFConditionalFormatting cf ) {
|
||||
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();
|
||||
|
||||
return _conditionalFormattingTable.add(cfraClone);
|
||||
}
|
||||
|
||||
public int addConditionalFormatting( ConditionalFormatting cf ) {
|
||||
return addConditionalFormatting((HSSFConditionalFormatting)cf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use <tt>CellRangeAddress</tt> instead of <tt>Region</tt>
|
||||
*/
|
||||
public int addConditionalFormatting(org.apache.poi.ss.util.Region[] regions, HSSFConditionalFormattingRule[] cfRules) {
|
||||
return addConditionalFormatting(org.apache.poi.ss.util.Region.convertRegionsToCellRanges(regions), cfRules);
|
||||
}
|
||||
/**
|
||||
* Allows to add a new Conditional Formatting set to the sheet.
|
||||
*
|
||||
* @param regions - list of rectangular regions to apply conditional formatting rules
|
||||
* @param cfRules - set of up to three conditional formatting rules
|
||||
*
|
||||
* @return index of the newly created Conditional Formatting object
|
||||
*/
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) {
|
||||
if (regions == null) {
|
||||
throw new IllegalArgumentException("regions must not be null");
|
||||
}
|
||||
for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97);
|
||||
/**
|
||||
* @deprecated use <tt>CellRangeAddress</tt> instead of <tt>Region</tt>
|
||||
*/
|
||||
public int addConditionalFormatting(org.apache.poi.ss.util.Region[] regions, HSSFConditionalFormattingRule[] cfRules) {
|
||||
return addConditionalFormatting(org.apache.poi.ss.util.Region.convertRegionsToCellRanges(regions), cfRules);
|
||||
}
|
||||
/**
|
||||
* Allows to add a new Conditional Formatting set to the sheet.
|
||||
*
|
||||
* @param regions - list of rectangular regions to apply conditional formatting rules
|
||||
* @param cfRules - set of up to three conditional formatting rules
|
||||
*
|
||||
* @return index of the newly created Conditional Formatting object
|
||||
*/
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) {
|
||||
if (regions == null) {
|
||||
throw new IllegalArgumentException("regions must not be null");
|
||||
}
|
||||
for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97);
|
||||
|
||||
if (cfRules == null) {
|
||||
throw new IllegalArgumentException("cfRules must not be null");
|
||||
}
|
||||
if (cfRules.length == 0) {
|
||||
throw new IllegalArgumentException("cfRules must not be empty");
|
||||
}
|
||||
if (cfRules.length > 3) {
|
||||
throw new IllegalArgumentException("Number of rules must not exceed 3");
|
||||
}
|
||||
if (cfRules == null) {
|
||||
throw new IllegalArgumentException("cfRules must not be null");
|
||||
}
|
||||
if (cfRules.length == 0) {
|
||||
throw new IllegalArgumentException("cfRules must not be empty");
|
||||
}
|
||||
if (cfRules.length > 3) {
|
||||
throw new IllegalArgumentException("Number of rules must not exceed 3");
|
||||
}
|
||||
|
||||
CFRuleRecord[] rules = new CFRuleRecord[cfRules.length];
|
||||
for (int i = 0; i != cfRules.length; i++) {
|
||||
rules[i] = cfRules[i].getCfRuleRecord();
|
||||
}
|
||||
CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);
|
||||
return _conditionalFormattingTable.add(cfra);
|
||||
}
|
||||
CFRuleBase[] rules = new CFRuleBase[cfRules.length];
|
||||
for (int i = 0; i != cfRules.length; i++) {
|
||||
rules[i] = cfRules[i].getCfRuleRecord();
|
||||
}
|
||||
CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);
|
||||
return _conditionalFormattingTable.add(cfra);
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) {
|
||||
HSSFConditionalFormattingRule[] hfRules;
|
||||
@ -164,70 +178,61 @@ public final class HSSFSheetConditionalFormatting implements SheetConditionalFor
|
||||
return addConditionalFormatting(regions, hfRules);
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
HSSFConditionalFormattingRule rule1)
|
||||
{
|
||||
return addConditionalFormatting(regions,
|
||||
rule1 == null ? null : new HSSFConditionalFormattingRule[]
|
||||
{
|
||||
rule1
|
||||
});
|
||||
}
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
HSSFConditionalFormattingRule rule1) {
|
||||
return addConditionalFormatting(regions, rule1 == null ?
|
||||
null : new HSSFConditionalFormattingRule[] { rule1 }
|
||||
);
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
ConditionalFormattingRule rule1)
|
||||
{
|
||||
ConditionalFormattingRule rule1) {
|
||||
return addConditionalFormatting(regions, (HSSFConditionalFormattingRule)rule1);
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
HSSFConditionalFormattingRule rule1,
|
||||
HSSFConditionalFormattingRule rule2)
|
||||
{
|
||||
return addConditionalFormatting(regions,
|
||||
new HSSFConditionalFormattingRule[]
|
||||
{
|
||||
rule1, rule2
|
||||
});
|
||||
}
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
HSSFConditionalFormattingRule rule1,
|
||||
HSSFConditionalFormattingRule rule2) {
|
||||
return addConditionalFormatting(regions,
|
||||
new HSSFConditionalFormattingRule[] { rule1, rule2 });
|
||||
}
|
||||
|
||||
public int addConditionalFormatting(CellRangeAddress[] regions,
|
||||
ConditionalFormattingRule rule1,
|
||||
ConditionalFormattingRule rule2)
|
||||
{
|
||||
ConditionalFormattingRule rule2) {
|
||||
return addConditionalFormatting(regions,
|
||||
(HSSFConditionalFormattingRule)rule1,
|
||||
(HSSFConditionalFormattingRule)rule2
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets Conditional Formatting object at a particular index
|
||||
*
|
||||
* @param index
|
||||
* of the Conditional Formatting object to fetch
|
||||
* @return Conditional Formatting object
|
||||
*/
|
||||
public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
|
||||
CFRecordsAggregate cf = _conditionalFormattingTable.get(index);
|
||||
if (cf == null) {
|
||||
return null;
|
||||
}
|
||||
return new HSSFConditionalFormatting(_sheet.getWorkbook(), cf);
|
||||
}
|
||||
/**
|
||||
* gets Conditional Formatting object at a particular index
|
||||
*
|
||||
* @param index
|
||||
* of the Conditional Formatting object to fetch
|
||||
* @return Conditional Formatting object
|
||||
*/
|
||||
public HSSFConditionalFormatting getConditionalFormattingAt(int index) {
|
||||
CFRecordsAggregate cf = _conditionalFormattingTable.get(index);
|
||||
if (cf == null) {
|
||||
return null;
|
||||
}
|
||||
return new HSSFConditionalFormatting(_sheet, cf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of Conditional Formatting objects of the sheet
|
||||
*/
|
||||
public int getNumConditionalFormattings() {
|
||||
return _conditionalFormattingTable.size();
|
||||
}
|
||||
/**
|
||||
* @return number of Conditional Formatting objects of the sheet
|
||||
*/
|
||||
public int getNumConditionalFormattings() {
|
||||
return _conditionalFormattingTable.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a Conditional Formatting object by index
|
||||
* @param index of a Conditional Formatting object to remove
|
||||
*/
|
||||
public void removeConditionalFormatting(int index) {
|
||||
_conditionalFormattingTable.remove(index);
|
||||
}
|
||||
/**
|
||||
* removes a Conditional Formatting object by index
|
||||
* @param index of a Conditional Formatting object to remove
|
||||
*/
|
||||
public void removeConditionalFormatting(int index) {
|
||||
_conditionalFormattingTable.remove(index);
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ import org.apache.poi.hssf.record.UnknownRecord;
|
||||
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
|
||||
import org.apache.poi.hssf.record.common.UnicodeString;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.poifs.crypt.Decryptor;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.EntryUtils;
|
||||
@ -205,6 +206,19 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
|
||||
public HSSFWorkbook(POIFSFileSystem fs) throws IOException {
|
||||
this(fs,true);
|
||||
}
|
||||
/**
|
||||
* Given a POI POIFSFileSystem object, read in its Workbook along
|
||||
* with all related nodes, and populate the high and low level models.
|
||||
* <p>This calls {@link #HSSFWorkbook(POIFSFileSystem, boolean)} with
|
||||
* preserve nodes set to true.
|
||||
*
|
||||
* @see #HSSFWorkbook(POIFSFileSystem, boolean)
|
||||
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
|
||||
* @exception IOException if the stream cannot be read
|
||||
*/
|
||||
public HSSFWorkbook(NPOIFSFileSystem fs) throws IOException {
|
||||
this(fs.getRoot(),true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a POI POIFSFileSystem object, read in its Workbook and populate
|
||||
@ -248,7 +262,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
|
||||
|
||||
// check for an encrypted .xlsx file - they get OLE2 wrapped
|
||||
try {
|
||||
directory.getEntry("EncryptedPackage");
|
||||
directory.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
|
||||
throw new EncryptedDocumentException("The supplied spreadsheet seems to be an Encrypted .xlsx file. " +
|
||||
"It must be decrypted before use by XSSF, it cannot be used by HSSF");
|
||||
} catch (FileNotFoundException e) {
|
||||
@ -378,7 +392,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
|
||||
public HSSFWorkbook(InputStream s, boolean preserveNodes)
|
||||
throws IOException
|
||||
{
|
||||
this(new POIFSFileSystem(s), preserveNodes);
|
||||
this(new NPOIFSFileSystem(s).getRoot(), preserveNodes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1276,7 +1290,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
|
||||
throws IOException
|
||||
{
|
||||
byte[] bytes = getBytes();
|
||||
POIFSFileSystem fs = new POIFSFileSystem();
|
||||
NPOIFSFileSystem fs = new NPOIFSFileSystem();
|
||||
|
||||
// For tracking what we've written out, used if we're
|
||||
// going to be preserving nodes
|
||||
@ -1843,7 +1857,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
|
||||
throws IOException {
|
||||
// check if we were created by POIFS otherwise create a new dummy POIFS for storing the package data
|
||||
if (directory == null) {
|
||||
directory = new POIFSFileSystem().getRoot();
|
||||
directory = new NPOIFSFileSystem().getRoot();
|
||||
preserveNodes = true;
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,13 @@ public class HSSFColor implements Color {
|
||||
{
|
||||
return BLACK.hexString;
|
||||
}
|
||||
|
||||
public static HSSFColor toHSSFColor(Color color) {
|
||||
if (color != null && !(color instanceof HSSFColor)) {
|
||||
throw new IllegalArgumentException("Only HSSFColor objects are supported");
|
||||
}
|
||||
return (HSSFColor)color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class BLACK
|
||||
|
@ -16,6 +16,8 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.poifs.crypt;
|
||||
|
||||
import static org.apache.poi.poifs.crypt.Decryptor.DEFAULT_POIFS_ENTRY;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@ -132,8 +134,8 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
|
||||
super.close();
|
||||
|
||||
int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE);
|
||||
calculateChecksum(fileOut, oleStreamSize);
|
||||
dir.createDocument("EncryptedPackage", oleStreamSize, new EncryptedPackageWriter());
|
||||
calculateChecksum(fileOut, (int)_pos);
|
||||
dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, new EncryptedPackageWriter());
|
||||
createEncryptionInfoEntry(dir, fileOut);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new IOException(e);
|
||||
|
@ -36,7 +36,7 @@ public class DataSpaceMapUtils {
|
||||
public static void addDefaultDataSpace(DirectoryEntry dir) throws IOException {
|
||||
DataSpaceMapEntry dsme = new DataSpaceMapEntry(
|
||||
new int[]{ 0 }
|
||||
, new String[]{ "EncryptedPackage" }
|
||||
, new String[]{ Decryptor.DEFAULT_POIFS_ENTRY }
|
||||
, "StrongEncryptionDataSpace"
|
||||
);
|
||||
DataSpaceMap dsm = new DataSpaceMap(new DataSpaceMapEntry[]{dsme});
|
||||
|
@ -25,10 +25,12 @@ import javax.crypto.SecretKey;
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
public abstract class Decryptor {
|
||||
public static final String DEFAULT_PASSWORD="VelvetSweatshop";
|
||||
public static final String DEFAULT_POIFS_ENTRY="EncryptedPackage";
|
||||
|
||||
protected final EncryptionInfoBuilder builder;
|
||||
private SecretKey secretKey;
|
||||
@ -83,7 +85,9 @@ public abstract class Decryptor {
|
||||
public InputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
|
||||
return getDataStream(fs.getRoot());
|
||||
}
|
||||
|
||||
public InputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
|
||||
return getDataStream(fs.getRoot());
|
||||
}
|
||||
public InputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException {
|
||||
return getDataStream(fs.getRoot());
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import java.io.IOException;
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
@ -68,14 +69,27 @@ public class EncryptionInfo {
|
||||
public static BitField flagAES = BitFieldFactory.getInstance(0x20);
|
||||
|
||||
|
||||
/**
|
||||
* Opens for decryption
|
||||
*/
|
||||
public EncryptionInfo(POIFSFileSystem fs) throws IOException {
|
||||
this(fs.getRoot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens for decryption
|
||||
*/
|
||||
public EncryptionInfo(OPOIFSFileSystem fs) throws IOException {
|
||||
this(fs.getRoot());
|
||||
}
|
||||
/**
|
||||
* Opens for decryption
|
||||
*/
|
||||
public EncryptionInfo(NPOIFSFileSystem fs) throws IOException {
|
||||
this(fs.getRoot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens for decryption
|
||||
*/
|
||||
public EncryptionInfo(DirectoryNode dir) throws IOException {
|
||||
this(dir.createDocumentInputStream("EncryptionInfo"), false);
|
||||
}
|
||||
@ -131,7 +145,7 @@ public class EncryptionInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use constructor without fs parameter
|
||||
* @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (fs parameter no longer required)
|
||||
*/
|
||||
@Deprecated
|
||||
public EncryptionInfo(POIFSFileSystem fs, EncryptionMode encryptionMode) {
|
||||
@ -139,7 +153,7 @@ public class EncryptionInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use constructor without fs parameter
|
||||
* @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (fs parameter no longer required)
|
||||
*/
|
||||
@Deprecated
|
||||
public EncryptionInfo(NPOIFSFileSystem fs, EncryptionMode encryptionMode) {
|
||||
@ -147,7 +161,7 @@ public class EncryptionInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use constructor without dir parameter
|
||||
* @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (dir parameter no longer required)
|
||||
*/
|
||||
@Deprecated
|
||||
public EncryptionInfo(DirectoryNode dir, EncryptionMode encryptionMode) {
|
||||
@ -155,7 +169,7 @@ public class EncryptionInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use constructor without fs parameter
|
||||
* @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public EncryptionInfo(
|
||||
@ -171,7 +185,7 @@ public class EncryptionInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use constructor without fs parameter
|
||||
* @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public EncryptionInfo(
|
||||
@ -187,7 +201,7 @@ public class EncryptionInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use constructor without dir parameter
|
||||
* @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public EncryptionInfo(
|
||||
@ -202,6 +216,11 @@ public class EncryptionInfo {
|
||||
this(encryptionMode, cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares for encryption, using the given Encryption Mode, and
|
||||
* all other parameters as default.
|
||||
* @see #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)
|
||||
*/
|
||||
public EncryptionInfo(EncryptionMode encryptionMode) {
|
||||
this(encryptionMode, null, null, -1, -1, null);
|
||||
}
|
||||
|
@ -24,9 +24,11 @@ import javax.crypto.SecretKey;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
public abstract class Encryptor {
|
||||
protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY;
|
||||
private SecretKey secretKey;
|
||||
|
||||
/**
|
||||
@ -50,7 +52,9 @@ public abstract class Encryptor {
|
||||
public OutputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
|
||||
return getDataStream(fs.getRoot());
|
||||
}
|
||||
|
||||
public OutputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
|
||||
return getDataStream(fs.getRoot());
|
||||
}
|
||||
public OutputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException {
|
||||
return getDataStream(fs.getRoot());
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ public class BinaryRC4Decryptor extends Decryptor {
|
||||
|
||||
public InputStream getDataStream(DirectoryNode dir) throws IOException,
|
||||
GeneralSecurityException {
|
||||
DocumentInputStream dis = dir.createDocumentInputStream("EncryptedPackage");
|
||||
DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
|
||||
_length = dis.readLong();
|
||||
BinaryRC4CipherInputStream cipherStream = new BinaryRC4CipherInputStream(dis, _length);
|
||||
return cipherStream;
|
||||
@ -131,4 +131,4 @@ public class BinaryRC4Decryptor extends Decryptor {
|
||||
|
||||
return _length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.DocumentNode;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.BoundedInputStream;
|
||||
@ -200,7 +200,7 @@ public class CryptoAPIDecryptor extends Decryptor {
|
||||
@SuppressWarnings("unused")
|
||||
public InputStream getDataStream(DirectoryNode dir)
|
||||
throws IOException, GeneralSecurityException {
|
||||
POIFSFileSystem fsOut = new POIFSFileSystem();
|
||||
NPOIFSFileSystem fsOut = new NPOIFSFileSystem();
|
||||
DocumentNode es = (DocumentNode) dir.getEntry("EncryptedSummary");
|
||||
DocumentInputStream dis = dir.createDocumentInputStream(es);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
@ -240,6 +240,7 @@ public class CryptoAPIDecryptor extends Decryptor {
|
||||
sbis = null;
|
||||
bos.reset();
|
||||
fsOut.writeFilesystem(bos);
|
||||
fsOut.close();
|
||||
_length = bos.size();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
|
||||
return bis;
|
||||
|
@ -123,7 +123,7 @@ public class StandardDecryptor extends Decryptor {
|
||||
}
|
||||
|
||||
public InputStream getDataStream(DirectoryNode dir) throws IOException {
|
||||
DocumentInputStream dis = dir.createDocumentInputStream("EncryptedPackage");
|
||||
DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
|
||||
|
||||
_length = dis.readLong();
|
||||
|
||||
|
@ -166,7 +166,7 @@ public class StandardEncryptor extends Encryptor {
|
||||
|
||||
void writeToPOIFS() throws IOException {
|
||||
int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE);
|
||||
dir.createDocument("EncryptedPackage", oleStreamSize, this);
|
||||
dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, this);
|
||||
// TODO: any properties???
|
||||
}
|
||||
|
||||
|
@ -16,27 +16,54 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.poifs.dev;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.*;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.poi.poifs.common.POIFSConstants;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.DocumentNode;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSStream;
|
||||
import org.apache.poi.poifs.property.NPropertyTable;
|
||||
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||
|
||||
/**
|
||||
*
|
||||
* Dump internal structure of a OLE2 file into file system
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class POIFSDump {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
System.err.println("Must specify at least one file to dump");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
boolean dumpProps = false, dumpMini = false;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i].equalsIgnoreCase("-dumprops") ||
|
||||
args[i].equalsIgnoreCase("-dump-props") ||
|
||||
args[i].equalsIgnoreCase("-dump-properties")) {
|
||||
dumpProps = true;
|
||||
continue;
|
||||
}
|
||||
if (args[i].equalsIgnoreCase("-dumpmini") ||
|
||||
args[i].equalsIgnoreCase("-dump-mini") ||
|
||||
args[i].equalsIgnoreCase("-dump-ministream") ||
|
||||
args[i].equalsIgnoreCase("-dump-mini-stream")) {
|
||||
dumpMini = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.println("Dumping " + args[i]);
|
||||
FileInputStream is = new FileInputStream(args[i]);
|
||||
POIFSFileSystem fs = new POIFSFileSystem(is);
|
||||
NPOIFSFileSystem fs = new NPOIFSFileSystem(is);
|
||||
is.close();
|
||||
|
||||
DirectoryEntry root = fs.getRoot();
|
||||
@ -44,13 +71,39 @@ public class POIFSDump {
|
||||
file.mkdir();
|
||||
|
||||
dump(root, file);
|
||||
|
||||
if (dumpProps) {
|
||||
HeaderBlock header = getHeaderBlock(fs);
|
||||
dump(fs, header.getPropertyStart(), "properties", file);
|
||||
}
|
||||
if (dumpMini) {
|
||||
NPropertyTable props = getPropertyTable(fs);
|
||||
int startBlock = props.getRoot().getStartBlock();
|
||||
if (startBlock == POIFSConstants.END_OF_CHAIN) {
|
||||
System.err.println("No Mini Stream in file");
|
||||
} else {
|
||||
dump(fs, startBlock, "mini-stream", file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static HeaderBlock getHeaderBlock(NPOIFSFileSystem fs) throws Exception {
|
||||
Field headerF = NPOIFSFileSystem.class.getDeclaredField("_header");
|
||||
headerF.setAccessible(true);
|
||||
HeaderBlock header = (HeaderBlock)headerF.get(fs);
|
||||
return header;
|
||||
}
|
||||
protected static NPropertyTable getPropertyTable(NPOIFSFileSystem fs) throws Exception {
|
||||
Field ptF = NPOIFSFileSystem.class.getDeclaredField("_property_table");
|
||||
ptF.setAccessible(true);
|
||||
NPropertyTable table = (NPropertyTable)ptF.get(fs);
|
||||
return table;
|
||||
}
|
||||
|
||||
public static void dump(DirectoryEntry root, File parent) throws IOException {
|
||||
for(Iterator it = root.getEntries(); it.hasNext();){
|
||||
Entry entry = (Entry)it.next();
|
||||
for(Iterator<Entry> it = root.getEntries(); it.hasNext();){
|
||||
Entry entry = it.next();
|
||||
if(entry instanceof DocumentNode){
|
||||
DocumentNode node = (DocumentNode)entry;
|
||||
DocumentInputStream is = new DocumentInputStream(node);
|
||||
@ -58,9 +111,12 @@ public class POIFSDump {
|
||||
is.read(bytes);
|
||||
is.close();
|
||||
|
||||
FileOutputStream out = new FileOutputStream(new File(parent, node.getName().trim()));
|
||||
out.write(bytes);
|
||||
out.close();
|
||||
OutputStream out = new FileOutputStream(new File(parent, node.getName().trim()));
|
||||
try {
|
||||
out.write(bytes);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
} else if (entry instanceof DirectoryEntry){
|
||||
DirectoryEntry dir = (DirectoryEntry)entry;
|
||||
File file = new File(parent, entry.getName());
|
||||
@ -71,4 +127,17 @@ public class POIFSDump {
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void dump(NPOIFSFileSystem fs, int startBlock, String name, File parent) throws IOException {
|
||||
File file = new File(parent, name);
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
NPOIFSStream stream = new NPOIFSStream(fs, startBlock);
|
||||
|
||||
byte[] b = new byte[fs.getBigBlockSize()];
|
||||
for (ByteBuffer bb : stream) {
|
||||
int len = bb.remaining();
|
||||
bb.get(b);
|
||||
out.write(b, 0, len);
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,10 @@ import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.poi.poifs.common.POIFSBigBlockSize;
|
||||
import org.apache.poi.poifs.common.POIFSConstants;
|
||||
import org.apache.poi.poifs.property.DirectoryProperty;
|
||||
import org.apache.poi.poifs.property.Property;
|
||||
import org.apache.poi.poifs.property.PropertyTable;
|
||||
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
||||
import org.apache.poi.poifs.storage.BlockList;
|
||||
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||
import org.apache.poi.poifs.storage.ListManagedBlock;
|
||||
import org.apache.poi.poifs.storage.RawDataBlockList;
|
||||
@ -42,111 +43,146 @@ import org.apache.poi.util.IntList;
|
||||
* down the source of corruption in a file.
|
||||
*/
|
||||
public class POIFSHeaderDumper {
|
||||
/**
|
||||
* Display the entries of multiple POIFS files
|
||||
*
|
||||
* @param args the names of the files to be displayed
|
||||
*/
|
||||
public static void main(final String args[]) throws Exception {
|
||||
if (args.length == 0) {
|
||||
System.err.println("Must specify at least one file to view");
|
||||
System.exit(1);
|
||||
}
|
||||
/**
|
||||
* Display the entries of multiple POIFS files
|
||||
*
|
||||
* @param args the names of the files to be displayed
|
||||
*/
|
||||
public static void main(final String args[]) throws Exception {
|
||||
if (args.length == 0) {
|
||||
System.err.println("Must specify at least one file to view");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
for (int j = 0; j < args.length; j++) {
|
||||
viewFile(args[j]);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < args.length; j++) {
|
||||
viewFile(args[j]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void viewFile(final String filename) throws Exception {
|
||||
InputStream inp = new FileInputStream(filename);
|
||||
|
||||
// Header
|
||||
HeaderBlock header_block = new HeaderBlock(inp);
|
||||
displayHeader(header_block);
|
||||
|
||||
// Raw blocks
|
||||
POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize();
|
||||
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
|
||||
displayRawBlocksSummary(data_blocks);
|
||||
|
||||
// Main FAT Table
|
||||
BlockAllocationTableReader batReader =
|
||||
new BlockAllocationTableReader(
|
||||
header_block.getBigBlockSize(),
|
||||
header_block.getBATCount(),
|
||||
header_block.getBATArray(),
|
||||
header_block.getXBATCount(),
|
||||
header_block.getXBATIndex(),
|
||||
data_blocks);
|
||||
displayBATReader(batReader);
|
||||
public static void viewFile(final String filename) throws Exception {
|
||||
System.out.println("Dumping headers from: " + filename);
|
||||
InputStream inp = new FileInputStream(filename);
|
||||
|
||||
// Properties Table
|
||||
PropertyTable properties =
|
||||
new PropertyTable(header_block, data_blocks);
|
||||
|
||||
// Mini Fat
|
||||
BlockList sbat =
|
||||
SmallBlockTableReader.getSmallDocumentBlocks(
|
||||
bigBlockSize, data_blocks, properties.getRoot(),
|
||||
header_block.getSBATStart()
|
||||
);
|
||||
}
|
||||
// Header
|
||||
HeaderBlock header_block = new HeaderBlock(inp);
|
||||
displayHeader(header_block);
|
||||
|
||||
public static void displayHeader(HeaderBlock header_block) throws Exception {
|
||||
System.out.println("Header Details:");
|
||||
System.out.println(" Block size: " + header_block.getBigBlockSize().getBigBlockSize());
|
||||
System.out.println(" BAT (FAT) header blocks: " + header_block.getBATArray().length);
|
||||
System.out.println(" BAT (FAT) block count: " + header_block.getBATCount());
|
||||
System.out.println(" XBAT (FAT) block count: " + header_block.getXBATCount());
|
||||
System.out.println(" XBAT (FAT) block 1 at: " + header_block.getXBATIndex());
|
||||
System.out.println(" SBAT (MiniFAT) block count: " + header_block.getSBATCount());
|
||||
System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block.getSBATStart());
|
||||
System.out.println(" Property table at: " + header_block.getPropertyStart());
|
||||
System.out.println("");
|
||||
}
|
||||
// Raw blocks
|
||||
POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize();
|
||||
RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize);
|
||||
displayRawBlocksSummary(data_blocks);
|
||||
|
||||
public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception {
|
||||
System.out.println("Raw Blocks Details:");
|
||||
System.out.println(" Number of blocks: " + data_blocks.blockCount());
|
||||
|
||||
Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class);
|
||||
gbm.setAccessible(true);
|
||||
|
||||
for(int i=0; i<Math.min(16, data_blocks.blockCount()); i++) {
|
||||
ListManagedBlock block = (ListManagedBlock)gbm.invoke(data_blocks, Integer.valueOf(i));
|
||||
byte[] data = new byte[Math.min(48, block.getData().length)];
|
||||
System.arraycopy(block.getData(), 0, data, 0, data.length);
|
||||
|
||||
System.out.println(" Block #" + i + ":");
|
||||
System.out.println(HexDump.dump(data, 0, 0));
|
||||
}
|
||||
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
public static void displayBATReader(BlockAllocationTableReader batReader) throws Exception {
|
||||
System.out.println("Sectors, as referenced from the FAT:");
|
||||
Field entriesF = batReader.getClass().getDeclaredField("_entries");
|
||||
entriesF.setAccessible(true);
|
||||
IntList entries = (IntList)entriesF.get(batReader);
|
||||
|
||||
for(int i=0; i<entries.size(); i++) {
|
||||
int bn = entries.get(i);
|
||||
String bnS = Integer.toString(bn);
|
||||
if(bn == POIFSConstants.END_OF_CHAIN) {
|
||||
bnS = "End Of Chain";
|
||||
} else if(bn == POIFSConstants.DIFAT_SECTOR_BLOCK) {
|
||||
bnS = "DI Fat Block";
|
||||
} else if(bn == POIFSConstants.FAT_SECTOR_BLOCK) {
|
||||
bnS = "Normal Fat Block";
|
||||
} else if(bn == POIFSConstants.UNUSED_BLOCK) {
|
||||
bnS = "Block Not Used (Free)";
|
||||
}
|
||||
|
||||
System.out.println(" Block # " + i + " -> " + bnS);
|
||||
}
|
||||
|
||||
System.out.println("");
|
||||
}
|
||||
// Main FAT Table
|
||||
BlockAllocationTableReader batReader =
|
||||
new BlockAllocationTableReader(
|
||||
header_block.getBigBlockSize(),
|
||||
header_block.getBATCount(),
|
||||
header_block.getBATArray(),
|
||||
header_block.getXBATCount(),
|
||||
header_block.getXBATIndex(),
|
||||
data_blocks);
|
||||
displayBATReader("Big Blocks", batReader);
|
||||
|
||||
// Properties Table
|
||||
PropertyTable properties =
|
||||
new PropertyTable(header_block, data_blocks);
|
||||
|
||||
// Mini Fat
|
||||
BlockAllocationTableReader sbatReader =
|
||||
SmallBlockTableReader._getSmallDocumentBlockReader(
|
||||
bigBlockSize, data_blocks, properties.getRoot(),
|
||||
header_block.getSBATStart()
|
||||
);
|
||||
displayBATReader("Small Blocks", sbatReader);
|
||||
|
||||
// Summary of the properties
|
||||
displayPropertiesSummary(properties);
|
||||
}
|
||||
|
||||
public static void displayHeader(HeaderBlock header_block) throws Exception {
|
||||
System.out.println("Header Details:");
|
||||
System.out.println(" Block size: " + header_block.getBigBlockSize().getBigBlockSize());
|
||||
System.out.println(" BAT (FAT) header blocks: " + header_block.getBATArray().length);
|
||||
System.out.println(" BAT (FAT) block count: " + header_block.getBATCount());
|
||||
if (header_block.getBATCount() > 0)
|
||||
System.out.println(" BAT (FAT) block 1 at: " + header_block.getBATArray()[0]);
|
||||
System.out.println(" XBAT (FAT) block count: " + header_block.getXBATCount());
|
||||
System.out.println(" XBAT (FAT) block 1 at: " + header_block.getXBATIndex());
|
||||
System.out.println(" SBAT (MiniFAT) block count: " + header_block.getSBATCount());
|
||||
System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block.getSBATStart());
|
||||
System.out.println(" Property table at: " + header_block.getPropertyStart());
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception {
|
||||
System.out.println("Raw Blocks Details:");
|
||||
System.out.println(" Number of blocks: " + data_blocks.blockCount());
|
||||
|
||||
Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class);
|
||||
gbm.setAccessible(true);
|
||||
|
||||
for(int i=0; i<Math.min(16, data_blocks.blockCount()); i++) {
|
||||
ListManagedBlock block = (ListManagedBlock)gbm.invoke(data_blocks, Integer.valueOf(i));
|
||||
byte[] data = new byte[Math.min(48, block.getData().length)];
|
||||
System.arraycopy(block.getData(), 0, data, 0, data.length);
|
||||
|
||||
System.out.println(" Block #" + i + ":");
|
||||
System.out.println(HexDump.dump(data, 0, 0));
|
||||
}
|
||||
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
public static void displayBATReader(String type, BlockAllocationTableReader batReader) throws Exception {
|
||||
System.out.println("Sectors, as referenced from the "+type+" FAT:");
|
||||
Field entriesF = batReader.getClass().getDeclaredField("_entries");
|
||||
entriesF.setAccessible(true);
|
||||
IntList entries = (IntList)entriesF.get(batReader);
|
||||
|
||||
for(int i=0; i<entries.size(); i++) {
|
||||
int bn = entries.get(i);
|
||||
String bnS = Integer.toString(bn);
|
||||
if(bn == POIFSConstants.END_OF_CHAIN) {
|
||||
bnS = "End Of Chain";
|
||||
} else if(bn == POIFSConstants.DIFAT_SECTOR_BLOCK) {
|
||||
bnS = "DI Fat Block";
|
||||
} else if(bn == POIFSConstants.FAT_SECTOR_BLOCK) {
|
||||
bnS = "Normal Fat Block";
|
||||
} else if(bn == POIFSConstants.UNUSED_BLOCK) {
|
||||
bnS = "Block Not Used (Free)";
|
||||
}
|
||||
|
||||
System.out.println(" Block # " + i + " -> " + bnS);
|
||||
}
|
||||
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
public static void displayPropertiesSummary(PropertyTable properties) {
|
||||
System.out.println("Mini Stream starts at " + properties.getRoot().getStartBlock());
|
||||
System.out.println("Mini Stream length is " + properties.getRoot().getSize());
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Properties and their block start:");
|
||||
displayProperties(properties.getRoot(), "");
|
||||
System.out.println("");
|
||||
}
|
||||
public static void displayProperties(DirectoryProperty prop, String indent) {
|
||||
String nextIndent = indent + " ";
|
||||
System.out.println(indent + "-> " + prop.getName());
|
||||
for (Property cp : prop) {
|
||||
if (cp instanceof DirectoryProperty) {
|
||||
displayProperties((DirectoryProperty)cp, nextIndent);
|
||||
} else {
|
||||
System.out.println(nextIndent + "=> " + cp.getName());
|
||||
System.out.print(nextIndent + " " + cp.getSize() + " bytes in ");
|
||||
if (cp.shouldUseSmallBlocks()) {
|
||||
System.out.print("mini");
|
||||
} else {
|
||||
System.out.print("main");
|
||||
}
|
||||
System.out.println(" stream, starts at " + cp.getStartBlock());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,12 @@
|
||||
|
||||
package org.apache.poi.poifs.dev;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
|
||||
/**
|
||||
* A simple viewer for POIFS files
|
||||
@ -76,10 +76,10 @@ public class POIFSViewer
|
||||
try
|
||||
{
|
||||
POIFSViewable fs =
|
||||
new POIFSFileSystem(new FileInputStream(filename));
|
||||
List<String> strings = POIFSViewEngine.inspectViewable(fs, true,
|
||||
new NPOIFSFileSystem(new File(filename));
|
||||
List<String> strings = POIFSViewEngine.inspectViewable(fs, true,
|
||||
0, " ");
|
||||
Iterator<String> iter = strings.iterator();
|
||||
Iterator<String> iter = strings.iterator();
|
||||
|
||||
while (iter.hasNext())
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user