<property name="main-tests.lib" location="${basedir}/lib/main-tests"/>
<property name="ooxml.lib" location="${basedir}/lib/ooxml"/>
<property name="ooxml-tests.lib" location="${basedir}/lib/ooxml-tests"/>
+ <property name="ooxml-provided.lib" location="${basedir}/lib/ooxml-provided"/>
<property name="util.lib" location="${basedir}/lib/util"/>
<property name="ooxml.output.test.dir" location="build/ooxml-test-classes"/>
<property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/>
- <property name="ooxml.lite.agent" location="build/ooxml-lite-agent.jar"/>
+ <property name="ooxml.lite.agent" location="lib/ooxml-tests/ooxml-lite-agent.jar"/>
<property name="ooxml.lite.report" location="build/ooxml-lite-report.txt"/>
- <property name="ooxml.lite.jar" location="build/ooxml-lite-classes.jar"/>
+ <property name="ooxml.lite.jar" location="build/dist/maven/poi-ooxml-schemas/poi-ooxml-schemas-${version.id}.jar"/>
<property name="ooxml.lite.includes" value="^(com/microsoft/schemas|org/(etsi|openxmlformats|w3/)|org/apache/poi/schemas)"/>
<property name="excelant.output.test.dir" location="build/excelant-test-classes"/>
<property name="excelant.testokfile" location="build/excelant-testokfile.txt"/>
-
- <scriptdef name="dependency" language="javascript" description="define properties for library dependency">
+ <macrodef name="dependency">
<attribute name="prefix"/>
<attribute name="artifact"/>
<attribute name="usage"/>
- <attribute name="packaging"/>
- <attribute name="repo"/>
- <attribute name="snapshot"/>
- <attribute name="query"/>
- <attribute name="target"/>
- <attribute name="url"/>
- <![CDATA[
- var parts = attributes.get("artifact").split(/:/);
- var packaging = attributes.get("packaging") || "jar";
- var version = attributes.get("snapshot") || parts[2];
- var repo = attributes.get("repo");
- if (repo == null) {
- repo = project.getProperty("repository.m2");
- }
- var query = attributes.get("query") || "";
- var usageDir = attributes.get("usage");
- usageDir = project.getProperty("basedir")+(usageDir.charAt(0) == '/' ? "" : "/lib/")+usageDir;
- var jarLoc = usageDir+"/"+(attributes.get("target")||(parts[1]+"-"+parts[2]+"."+packaging));
- var urlLoc = attributes.get("url") ||
- repo+"/"+parts[0].replace(/\./g,"/")+"/"+parts[1]+"/"+parts[2]+"/"+
- parts[1]+"-"+(attributes.get("snapshot") || parts[2])+"."+packaging+query;
- project.setProperty(attributes.get("prefix")+"."+packaging, jarLoc);
- project.setProperty(attributes.get("prefix")+".url", urlLoc);
- ]]>
- <!-- TODO: add library to a queue for downloading ... -->
- </scriptdef>
+ <attribute name="packaging" default="jar"/>
+ <attribute name="repo" default="${repository.m2}"/>
+ <attribute name="snapshot" default=""/>
+ <attribute name="query" default=""/>
+ <attribute name="target" default=""/>
+ <attribute name="url" default=""/>
+
+ <sequential>
+ <local name="groupDir"/>
+ <loadresource property="groupDir">
+ <string>@{artifact}</string>
+ <filterchain>
+ <replaceregex pattern="([^:]+).*" replace="\1"/>
+ <replaceregex pattern="\." replace="/" flags="g"/>
+ </filterchain>
+ </loadresource>
+
+ <local name="artifactId"/>
+ <loadresource property="artifactId">
+ <string>@{artifact}</string>
+ <filterchain>
+ <replaceregex pattern="[^:]+:([^:]+).*" replace="\1"/>
+ </filterchain>
+ </loadresource>
+
+ <local name="versionDir"/>
+ <loadresource property="versionDir">
+ <string>@{artifact}</string>
+ <filterchain>
+ <replaceregex pattern="[^:]+:[^:]+:(.*)" replace="\1"/>
+ </filterchain>
+ </loadresource>
+
+ <local name="version"/>
+ <property name="version" value="${versionDir}" if:blank="@{snapshot}"/>
+ <property name="version" value="@{snapshot}"/>
+
+ <local name="usageDir"/>
+ <loadresource property="usageDir">
+ <string>@{usage}</string>
+ <filterchain>
+ <replaceregex pattern="^([^/])" replace="/lib/\1"/>
+ <prefixlines prefix="${basedir}"/>
+ </filterchain>
+ </loadresource>
+
+ <local name="jarLoc"/>
+ <property name="jarLoc" value="${usageDir}/@{target}" unless:blank="@{target}"/>
+ <property name="jarLoc" value="${usageDir}/${artifactId}-${version}.@{packaging}"/>
+
+ <local name="urlLoc"/>
+ <property name="urlLoc" value="@{url}" unless:blank="@{url}"/>
+ <property name="urlLoc" value="@{repo}/${groupDir}/${artifactId}/${versionDir}/${artifactId}-${version}.@{packaging}@{query}"/>
+
+ <property name="@{prefix}.@{packaging}" value="${jarLoc}"/>
+ <property name="@{prefix}.url" value="${urlLoc}"/>
+
+ <!-- TODO: add library to a queue for downloading ... -->
+ </sequential>
+ </macrodef>
<!-- jars in the /lib directory, see the fetch-jars target-->
<dependency prefix="main.byte-buddy-agent" artifact="net.bytebuddy:byte-buddy-agent:1.10.1" usage="main-tests"/>
<dependency prefix="main.objenesis" artifact="org.objenesis:objenesis:2.6" usage="main-tests"/>
- <dependency prefix="main.ant" artifact="org.apache.ant:ant:1.10.1" usage="excelant"/>
- <dependency prefix="main.antlauncher" artifact="org.apache.ant:ant-launcher:1.10.1" usage="excelant"/>
+ <dependency prefix="main.ant" artifact="org.apache.ant:ant:1.10.8" usage="excelant"/>
+ <dependency prefix="main.antlauncher" artifact="org.apache.ant:ant-launcher:1.10.8" usage="excelant"/>
<!-- xml signature libs - not part of the distribution -->
<dependency prefix="dsig.xmlsec" artifact="org.apache.santuario:xmlsec:2.1.5" usage="ooxml-provided"/>
- <dependency prefix="dsig.bouncycastle-prov" artifact="org.bouncycastle:bcprov-ext-jdk15on:1.65" usage="ooxml-provided"/>
- <dependency prefix="dsig.bouncycastle-pkix" artifact="org.bouncycastle:bcpkix-jdk15on:1.65" usage="ooxml-provided"/>
+ <dependency prefix="dsig.bouncycastle-prov" artifact="org.bouncycastle:bcprov-ext-jdk15on:1.66" usage="ooxml-provided"/>
+ <dependency prefix="dsig.bouncycastle-pkix" artifact="org.bouncycastle:bcpkix-jdk15on:1.66" usage="ooxml-provided"/>
<dependency prefix="dsig.slf4j-api" artifact="org.slf4j:slf4j-api:1.7.30" usage="ooxml-provided"/>
<!-- svg/batik libs - not part of the distribution -->
<!-- jars in the ooxml-test-lib directory, see the fetch-ooxml-jars target-->
<dependency prefix="ooxml.test.reflections" artifact="org.reflections:reflections:0.9.11" usage="ooxml-tests"/>
- <dependency prefix="ooxml.test.guava" artifact="com.google.guava:guava:20.0" usage="ooxml-tests"/>
+ <dependency prefix="ooxml.test.guava" artifact="com.google.guava:guava:29.0-jre" usage="ooxml-tests"/>
<dependency prefix="ooxml.test.javassist" artifact="org.javassist:javassist:3.21.0-GA" usage="ooxml-tests"/>
<!-- coverage libs -->
<dependency prefix="rat" artifact="org.apache.rat:apache-rat:0.12" usage="util"/>
<dependency prefix="forbidden" artifact="de.thetaphi:forbiddenapis:2.6" usage="util"/>
- <property name="maven.ooxml.xsds.version.id" value="1.4"/>
+ <property name="maven.ooxml.xsds.version.id" value="1.5"/>
<!-- See https://www.ecma-international.org/publications/standards/Ecma-376.htm -->
<!-- "Copy these file(s), free of charge" -->
<property name="ooxml.xsds.izip.1" value="${basedir}/src/ooxml/resources/org/apache/poi/schemas/OfficeOpenXML-XMLSchema.zip"/>
<property name="ooxml.xsds.src.dir" location="build/ooxml-xsds-src"/>
- <property name="ooxml.xsds.src.jar" location="${ooxml.lib}/ooxml-schemas-${maven.ooxml.xsds.version.id}-sources.jar"/>
- <property name="ooxml.xsds.jar" location="${ooxml.lib}/ooxml-schemas-${maven.ooxml.xsds.version.id}.jar"/>
+ <property name="ooxml.xsds.src.jar" location="build/dist/maven/ooxml-schemas/ooxml-schemas-${maven.ooxml.xsds.version.id}-sources.jar"/>
+ <property name="ooxml.xsds.jar" location="build/dist/maven/ooxml-schemas/ooxml-schemas-${maven.ooxml.xsds.version.id}.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.izip.2" value="${basedir}/src/ooxml/resources/org/apache/poi/schemas/OpenPackagingConventions-XMLSchema.zip"/>
<property name="ooxml.security.src.dir" location="build/ooxml-security-src"/>
- <property name="ooxml.security.src.jar" location="${ooxml.lib}/ooxml-security-1.1-sources.jar"/>
- <property name="ooxml.security.jar" location="${ooxml.lib}/ooxml-security-1.1.jar"/>
<property name="ooxml.security.xsd.dir" location="src/ooxml/resources/org/apache/poi/poifs/crypt"/>
<property name="ooxml.visio.xsd.dir" location="src/ooxml/resources/org/apache/poi/xdgf"/>
<property name="ooxml.schema.xsdconfig.dir" location="src/ooxml/resources/org/apache/poi/schemas"/>
<pathelement location="${ooxml.commons-compress.jar}"/>
<path refid="main.classpath"/>
<pathelement location="${main.output.dir}"/>
- <pathelement location="${ooxml.security.jar}"/>
<pathelement location="${ooxml.test.guava.jar}"/>
<!-- classes are omitted on test cases outside the xml-dsign area to avoid classpath poisioning -->
<!--path refid="ooxml.xmlsec.classpath"/-->
<pathelement location="${svg.xmlgraphics-commons.jar}"/>
</path>
- <path id="ooxml-lite.classpath">
- <path refid="ooxml.base.classpath"/>
- <!-- instead of ooxml-xsds.jar use the filtered classes-->
- <pathelement location="${ooxml.lite.jar}"/>
- <pathelement location="${ooxml.output.dir}"/>
- <pathelement location="${ooxml.output.test.dir}"/>
- <pathelement location="${main.output.test.dir}"/>
- <path refid="batik.classpath"/>
- </path>
-
<path id="ooxml.classpath">
- <pathelement location="${ooxml.xsds.jar}"/>
+ <pathelement location="${ooxml.xsds.jar}"/>
<path refid="ooxml.base.classpath"/>
<path refid="batik.classpath"/>
</path>
<path refid="ooxml.base.classpath"/>
</path>
- <path id="test.classpath">
- <path refid="main.classpath"/>
- <pathelement location="${main.output.dir}"/>
- <pathelement location="${main.output.test.dir}"/>
- <pathelement location="${additionaljar}"/>
- </path>
-
- <path id="test.scratchpad.classpath">
- <path refid="scratchpad.classpath"/>
- <pathelement location="${main.output.test.dir}"/>
- <pathelement location="${scratchpad.output.dir}"/>
- <pathelement location="${scratchpad.output.test.dir}"/>
- <pathelement location="${additionaljar}"/>
- </path>
-
<path id="test.ooxml.reflections.classpath">
<pathelement location="${ooxml.test.reflections.jar}"/>
<pathelement location="${ooxml.test.guava.jar}"/>
<pathelement location="${ooxml.test.javassist.jar}"/>
</path>
- <path id="test.ooxml.classpath">
- <path refid="ooxml.classpath"/>
- <path refid="ooxml.xmlsec.classpath"/>
- <path refid="test.jar.classpath"/>
- <path refid="test.ooxml.reflections.classpath"/>
- <pathelement location="${ooxml.output.dir}"/>
- <pathelement location="${ooxml.output.test.dir}"/>
- <pathelement location="${main.output.test.dir}"/>
- <pathelement location="${additionaljar}"/>
- </path>
-
<path id="test.ooxml.lite.verify.classpath">
<path refid="ooxml.lite.verify.classpath"/>
<path refid="ooxml.xmlsec.classpath"/>
<pathelement location="${additionaljar}"/>
</path>
- <path id="test.integration.classpath">
- <pathelement location="${integration.src.test}"/>
- <path refid="scratchpad.classpath"/>
- <path refid="ooxml.classpath"/>
- <path refid="test.jar.classpath"/>
- <pathelement location="${main.output.test.dir}"/>
- <pathelement location="${ooxml.output.dir}"/>
- <pathelement location="${integration.output.test.dir}"/>
- <pathelement location="${examples.output.dir}"/>
- </path>
-
<path id="examples.classpath">
<path refid="main.classpath"/>
<pathelement location="${main.output.dir}"/>
<pathelement location="${ooxml.output.dir}"/>
</path>
- <path id="test.excelant.classpath">
- <path refid="ooxml.classpath"/>
- <path refid="test.jar.classpath"/>
- <pathelement location="${ooxml.output.dir}"/>
- <pathelement location="${excelant.output.dir}"/>
- <pathelement location="${excelant.output.test.dir}"/>
- <pathelement location="${main.output.test.dir}"/>
- <pathelement location="${additionaljar}"/>
- </path>
-
<path id="javadoc.classpath">
<path refid="main.classpath"/>
<path refid="scratchpad.classpath"/>
<path path="${env.CLASSPATH}"/>
</path>
- <path id="forbiddenapis.classpath">
- <path refid="main.classpath"/>
- <path refid="test.jar.classpath"/>
- <path refid="scratchpad.classpath"/>
- <path refid="ooxml.classpath"/>
- <path refid="ooxml.xmlsec.classpath"/>
- <path refid="test.ooxml.reflections.classpath"/>
- <path refid="excelant.classpath"/>
- <path refid="examples.classpath"/>
- <pathelement location="${examples.output.dir}"/>
- <path path="${env.CLASSPATH}"/>
- </path>
-
- <path id="lib.jacoco">
- <fileset dir="${util.lib}">
- <include name="org.jacoco*.jar" />
- <include name="asm-*.jar" />
- </fileset>
- </path>
-
<patternset id="exclude-scratchpad-test">
<exclude name="**/TestExtractorFactory.java"/>
<exclude name="**/TestEmbedOLEPackage.java"/>
- 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)
<delete verbose="true" failonerror="false">
<fileset dir="${basedir}/lib" includes="*.jar"/>
- <fileset dir="${basedir}/lib/util">
- <include name="asm*7.2.jar"/>
+ <fileset dir="${basedir}/lib/main-tests">
+ <include name="mockito-core-3.2.4.jar"/>
</fileset>
<fileset dir="${basedir}/lib/ooxml">
<include name="xmlbeans-3.1.0.jar"/>
</fileset>
- <fileset dir="${basedir}/lib/main-tests">
- <include name="mockito-core-3.2.4.jar"/>
+ <fileset dir="${basedir}/lib/ooxml-tests">
+ <include name="guava-20.0.jar"/>
+ </fileset>
+ <fileset dir="${basedir}/lib/util">
+ <include name="asm*7.2.jar"/>
</fileset>
</delete>
<target name="fetch-ooxml-jars" depends="check-ooxml-jars" unless="ooxml.jars.present">
<mkdir dir="${ooxml.lib}"/>
<mkdir dir="${ooxml-tests.lib}"/>
+<!-- <downloadfile src="${ooxml.xml-apis.url}" dest="${ooxml.xml-apis.jar}"/>-->
<downloadfile src="${ooxml.curvesapi.url}" dest="${ooxml.curvesapi.jar}"/>
<downloadfile src="${ooxml.xmlbeans.url}" dest="${ooxml.xmlbeans.jar}"/>
<downloadfile src="${ooxml.commons-compress.url}" dest="${ooxml.commons-compress.jar}"/>
<and>
<available file="${ooxml.xsds.jar}"/>
<available file="${ooxml.xsds.src.jar}"/>
- <available file="${ooxml.security.jar}"/>
- <available file="${ooxml.security.src.jar}"/>
</and>
</condition>
</target>
- <macrodef name="compile-ooxml-xmlbean">
- <attribute name="classes-jar"/>
- <attribute name="sources-jar"/>
- <attribute name="noupa" default="false"/>
- <attribute name="nopvr" default="false"/>
- <attribute name="multi-src"/>
- <attribute name="typesystemname"/>
- <element name="xsds"/>
- <sequential>
- <!-- We need a fair amount of memory to compile the xml schema, -->
- <!-- but limit it in case it goes wrong! -->
- <!-- Pick the right amount based on 32 vs 64 bit jvm -->
- <condition property="ooxml.memory" value="1536m" else="1024m">
- <equals arg1="${sun.arch.data.model}" arg2="64" />
- </condition>
+ <target name="compile-ooxml-xsds"
+ depends="init,check-compiled-ooxml-xsds"
+ unless="ooxml-compiled-xsds.present"
+ description="Unpacks the OOXML xsd files, and compiles them into XmlBeans">
- <taskdef name="xmlbean"
- classname="org.apache.xmlbeans.impl.tool.XMLBean"
- classpath="${ooxml.xmlbeans.jar}"/>
+ <local name="ooxml.memory"/>
- <property name="xmlbean.xsds.dir" location="build/xmlbean-xsds"/>
- <property name="xmlbean.sources.dir" location="build/xmlbean-sources"/>
- <property name="xmlbean.classes.dir" location="build/xmlbean-classes"/>
+ <!-- We need a fair amount of memory to compile the xml schema, -->
+ <!-- but limit it in case it goes wrong! -->
+ <!-- Pick the right amount based on 32 vs 64 bit jvm -->
+ <condition property="ooxml.memory" value="1536m" else="1024m">
+ <equals arg1="${sun.arch.data.model}" arg2="64" />
+ </condition>
- <delete dir="${xmlbean.xsds.dir}"/>
- <mkdir dir="${xmlbean.xsds.dir}"/>
- <delete dir="${xmlbean.sources.dir}"/>
- <mkdir dir="${xmlbean.sources.dir}"/>
- <delete dir="${xmlbean.classes.dir}"/>
- <mkdir dir="${xmlbean.classes.dir}"/>
+ <local name="xmlbean.xsds.dir"/>
+ <property name="xmlbean.xsds.dir" location="build/xmlbean-xsds"/>
+ <mkdir dir="${xmlbean.xsds.dir}"/>
+
+ <copy todir="${xmlbean.xsds.dir}">
+ <zipfileset src="${ooxml.xsds.izip.1}"/>
+ <fileset dir="${ooxml.visio.xsd.dir}"/>
+ <fileset dir="${ooxml.schema.xsdconfig.dir}" includes="ooxmlSchemas.xsdconfig,markup-compatibility.xsd"/>
+ <zipfileset src="${ooxml.xsds.izip.2}" includes="opc-digSig.xsd,opc-relationships.xsd"/>
+ <fileset dir="${ooxml.security.xsd.dir}" includes="signatureInfo.xsd"/>
+ <fileset dir="${ooxml.schema.xsdconfig.dir}" includes="XAdES*.xsd,*.xsdconfig,xmldsig*.xsd"/>
+ </copy>
- <copy todir="${xmlbean.xsds.dir}">
- <xsds/>
- </copy>
+ <local name="xmlbean.sources.dir"/>
+ <local name="xmlbean.classes.dir"/>
+ <property name="xmlbean.sources.dir" location="build/xmlbean-sources"/>
+ <property name="xmlbean.classes.dir" location="build/xmlbean-classes"/>
+ <mkdir dir="${xmlbean.sources.dir}"/>
+ <mkdir dir="${xmlbean.classes.dir}"/>
+
+ <taskdef name="xmlbean"
+ classname="org.apache.xmlbeans.impl.tool.XMLBean"
+ classpath="${ooxml.xmlbeans.jar}"/>
+
+ <!-- javasource > 1.5 will not generate all array accessor -->
+ <xmlbean
+ schema="${xmlbean.xsds.dir}"
+ srcgendir="${xmlbean.sources.dir}"
+ classgendir="${xmlbean.classes.dir}"
+ destfile="${xmlbean.xsds.dir}.jar"
+ srconly="true"
+ javasource="1.5"
+ failonerror="true"
+ fork="true"
+ memoryMaximumSize="${ooxml.memory}"
+ typesystemname="ooxml"
+ repackage="org.apache.xmlbeans.metadata:org.apache.poi.schemas.ooxml">
+ <classpath>
+ <path location="${ooxml.xmlbeans.jar}"/>
+ </classpath>
+ </xmlbean>
- <!-- javasource > 1.5 will not generate all array accessor -->
- <xmlbean
- schema="${xmlbean.xsds.dir}"
- srcgendir="${xmlbean.sources.dir}"
- classgendir="${xmlbean.classes.dir}"
- destfile="${xmlbean.xsds.dir}.jar"
- srconly="true"
- javasource="1.5"
- failonerror="true"
- fork="true"
- memoryMaximumSize="${ooxml.memory}"
- noupa="@{noupa}"
- nopvr="@{nopvr}"
- typesystemname="@{typesystemname}"
- repackage="org.apache.xmlbeans.metadata:org.apache.poi.schemas.@{typesystemname}"
- >
- <classpath>
- <path location="${ooxml.xmlbeans.jar}"/>
- </classpath>
- </xmlbean>
+ <javac release="8"
+ target="${jdk.version.class}"
+ source="${jdk.version.source}"
+ srcdir="${xmlbean.sources.dir}"
+ destdir="${xmlbean.classes.dir}"
+ encoding="${java.source.encoding}"
+ fork="yes"
+ debug="${compile.debug}"
+ memoryMaximumSize="${ooxml.memory}"
+ includeantruntime="false">
+ <classpath refid="ooxml.classpath"/>
+ </javac>
+
+ <javac release="9"
+ srcdir="${basedir}/src/multimodule/ooxml-schemas/java9"
+ destdir="${basedir}/src/multimodule/ooxml-schemas/java9"
+ includeantruntime="false"
+ fork="true"
+ modulepath="lib/ooxml"
+ unless:true="${isJava8}">
+ <compilerarg line="--patch-module org.apache.poi.ooxml.schemas=${xmlbean.classes.dir}"/>
+ </javac>
+
+ <mkdir dir="build/dist/maven/ooxml-schemas"/>
+
+ <jar destfile="${ooxml.xsds.jar}">
+ <fileset dir="${xmlbean.classes.dir}"/>
+ <zipfileset dir="${basedir}/src/multimodule/ooxml-schemas/java9" prefix="META-INF/versions/9" excludes="*.java"/>
+ <metainf dir="legal/"/>
+ <manifest>
+ <attribute name="Multi-Release" value="true"/>
+ <attribute name="Automatic-Module-Name" value="org.apache.poi.ooxml.schemas"/>
+ <attribute name="Built-By" value="${user.name}"/>
+ <attribute name="Specification-Title" value="Apache POI OOXML Schemas"/>
+ <attribute name="Specification-Version" value="${maven.ooxml.xsds.version.id}"/>
+ <attribute name="Specification-Vendor" value="The Apache Software Foundation"/>
+ <attribute name="Implementation-Title" value="Apache POI OOXML Schemas"/>
+ <attribute name="Implementation-Version" value="${version.id}"/>
+ <attribute name="Implementation-Vendor-Id" value="org.apache.poi"/>
+ <attribute name="Implementation-Vendor" value="The Apache Software Foundation"/>
+ </manifest>
+ </jar>
+
+ <jar destfile="${ooxml.xsds.src.jar}">
+ <fileset dir="${xmlbean.sources.dir}"/>
+ <zipfileset dir="${basedir}/src/multimodule/ooxml-schemas/java9" prefix="META-INF/versions/9/" excludes="*.class"/>
+ <metainf dir="legal"/>
+ </jar>
+ </target>
+
+ <target name="compile" depends="init, compile-main,
+ compile-scratchpad, compile-examples, compile-excelant"
+ description="Compiles the POI main classes, scratchpad and examples"/>
- <echo>Forking javac with max heap size ${ooxml.memory}</echo>
+ <macrodef name="compile-jar">
+ <attribute name="module"/>
+ <attribute name="java"/>
+ <attribute name="classes"/>
+ <attribute name="test" default=""/>
+ <attribute name="test-classes" default=""/>
+ <attribute name="version" default="${version.id}"/>
+ <element name="lib"/>
+ <element name="resources" optional="true"/>
+ <element name="test-resources" optional="true"/>
+ <sequential>
+ <local name="cp_java"/>
+ <pathconvert property="cp_java" pathsep=",">
+ <path><lib/></path>
+ <regexpmapper from="^${basedir}[/\\](.*)$" to="\1/*.jar"/>
+ </pathconvert>
- <javac target="${jdk.version.class}"
+ <local name="maven-name"/>
+ <loadresource property="maven-name">
+ <string>@{module}</string>
+ <filterchain>
+ <prefixlines prefix="poi-"/>
+ <replacestring from="poi-poi" to="poi"/>
+ </filterchain>
+ </loadresource>
+
+ <!-- compile the sources -->
+ <javac release="8"
+ target="${jdk.version.class}"
source="${jdk.version.source}"
- srcdir="${xmlbean.sources.dir}"
- destdir="${xmlbean.classes.dir}"
+ destdir="@{classes}"
+ srcdir="@{java}"
+ debug="${compile.debug}"
encoding="${java.source.encoding}"
fork="yes"
- optimize="true"
- memoryMaximumSize="${ooxml.memory}"
includeantruntime="false">
- <classpath refid="ooxml.classpath"/>
+ <classpath>
+ <fileset dir="${basedir}" includes="${cp_java}"/>
+ </classpath>
</javac>
- <local name="module-package"/>
- <loadfile property="module-package" srcFile="@{multi-src}/java9/module-info.java">
- <filterchain>
- <containsregex pattern=".*module ([^ ]+).*" replace="\1" flags="i"/>
- <striplinebreaks/>
- </filterchain>
- </loadfile>
-
- <mkdir dir="${xmlbean.classes.dir}/META-INF/versions/9"/>
-
+ <!-- compile jigsaw files to sources, so we don't forget to update/provide them for Java 8 builds -->
<javac release="9"
- srcdir="@{multi-src}/java9"
- destdir="${xmlbean.classes.dir}/META-INF/versions/9"
+ srcdir="${basedir}/src/multimodule/@{module}/java9"
+ destdir="${basedir}/src/multimodule/@{module}/java9"
includeantruntime="false"
fork="true"
- modulepath="${ooxml.lib}"
unless:true="${isJava8}">
- <compilerarg line="--patch-module ${module-package}=${xmlbean.classes.dir}"/>
+ <compilerarg line="--patch-module org.apache.poi.@{module}=@{classes}"/>
+ <modulepath>
+ <lib/>
+ </modulepath>
</javac>
- <delete file="@{classes-jar}"/>
- <delete file="@{sources-jar}"/>
+ <mkdir dir="build/dist/maven/${maven-name}"/>
- <jar destfile="@{classes-jar}" level="9">
- <fileset dir="${xmlbean.classes.dir}"/>
- <zipfileset prefix="META-INF/versions/9/" dir="@{multi-src}/java9" includes="**/*.class" if:true="${isJava8}"/>
- <metainf dir="legal"/>
+ <!-- create classes jar -->
+ <jar destfile="build/dist/maven/${maven-name}/${maven-name}-@{version}.jar">
+ <fileset dir="@{classes}"/>
+ <resources/>
+ <zipfileset dir="${basedir}/src/multimodule/@{module}/java9"
+ prefix="META-INF/versions/9"
+ excludes="*.java"/>
+ <metainf dir="legal/"/>
<manifest>
<attribute name="Multi-Release" value="true"/>
+ <attribute name="Automatic-Module-Name" value="org.apache.poi.@{module}"/>
+ <attribute name="Built-By" value="${user.name}"/>
+ <attribute name="Specification-Title" value="Apache POI"/>
+ <attribute name="Specification-Version" value="${version.id}"/>
+ <attribute name="Specification-Vendor" value="The Apache Software Foundation"/>
+ <attribute name="Implementation-Title" value="Apache POI"/>
+ <attribute name="Implementation-Version" value="${version.id}"/>
+ <attribute name="Implementation-Vendor-Id" value="org.apache.poi"/>
+ <attribute name="Implementation-Vendor" value="The Apache Software Foundation"/>
</manifest>
</jar>
- <jar destfile="@{sources-jar}" level="9">
- <fileset dir="${xmlbean.sources.dir}"/>
- <zipfileset prefix="META-INF/versions/9/" dir="@{multi-src}/java9" excludes="**/*.class"/>
- <metainf dir="legal"/>
- </jar>
-
- <delete file="${xmlbean.xsds.dir}.jar"/>
- <delete dir="${xmlbean.xsds.dir}"/>
- <delete dir="${xmlbean.sources.dir}"/>
- <delete dir="${xmlbean.classes.dir}"/>
- </sequential>
- </macrodef>
- <target name="compile-ooxml-xsds"
- depends="init,check-compiled-ooxml-xsds"
- unless="ooxml-compiled-xsds.present"
- description="Unpacks the OOXML xsd files, and compiles them into XmlBeans">
- <compile-ooxml-xmlbean
- classes-jar="${ooxml.xsds.jar}"
- sources-jar="${ooxml.xsds.src.jar}"
- multi-src="${basedir}/src/multimodule/ooxml-schemas"
- typesystemname="ooxml"
- >
- <xsds>
- <zipfileset src="${ooxml.xsds.izip.1}"/>
- <fileset dir="${ooxml.visio.xsd.dir}"/>
- <fileset dir="${ooxml.schema.xsdconfig.dir}" includes="ooxmlSchemas.xsdconfig,markup-compatibility.xsd"/>
- </xsds>
- </compile-ooxml-xmlbean>
- <!-- Now do the same for the security schemas -->
- <compile-ooxml-xmlbean
- classes-jar="${ooxml.security.jar}"
- sources-jar="${ooxml.security.src.jar}"
- multi-src="${basedir}/src/multimodule/ooxml-security"
- typesystemname="security"
- >
- <xsds>
- <zipfileset src="${ooxml.xsds.izip.2}" includes="opc-digSig.xsd,opc-relationships.xsd"/>
- <fileset dir="${ooxml.security.xsd.dir}"/>
- <fileset dir="${ooxml.schema.xsdconfig.dir}" includes="XAdES*.xsd,*.xsdconfig,xmldsig*.xsd"/>
- </xsds>
- </compile-ooxml-xmlbean>
- </target>
+ <!-- compile the tests -->
+ <javac release="8"
+ target="${jdk.version.class}"
+ source="${jdk.version.source}"
+ destdir="@{test-classes}"
+ srcdir="@{test}"
+ debug="${compile.debug}"
+ encoding="${java.source.encoding}"
+ fork="yes"
+ includeantruntime="false" unless:blank="@{test}">
+ <classpath>
+ <fileset dir="${basedir}" includes="${cp_java}"/>
+ <pathelement path="build/dist/maven/${maven-name}/${maven-name}-@{version}.jar"/>
+ </classpath>
+ </javac>
- <target name="compile" depends="init, compile-main,
- compile-scratchpad, compile-examples, compile-excelant"
- description="Compiles the POI main classes, scratchpad and examples"/>
+ <!-- again, generate jigsaw files to sources ... -->
+ <local name="merged"/>
+ <pathconvert property="merged">
+ <path location="@{classes}"/>
+ <path location="@{test-classes}"/>
+ </pathconvert>
- <target name="compile-main" depends="init">
- <!-- compile the sources -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${main.output.dir}"
- srcdir="${main.src}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath refid="main.classpath"/>
- </javac>
- <!-- compile the tests -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${main.output.test.dir}"
- srcdir="${main.src.test}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath>
- <path refid="main.classpath"/>
- <path refid="test.jar.classpath"/>
- <pathelement path="${main.output.dir}"/>
- </classpath>
- </javac>
- <copy todir="${main.output.dir}">
- <fileset dir="${main.resource1.dir}"/>
- </copy>
+ <javac release="9"
+ srcdir="${basedir}/src/multimodule/@{module}/test9"
+ destdir="${basedir}/src/multimodule/@{module}/test9"
+ includeantruntime="false"
+ fork="true"
+ unless:true="${isJava8}" unless:blank="@{test}">
+ <compilerarg line="--patch-module org.apache.poi.@{module}=${merged}"/>
+ <modulepath>
+ <lib/>
+ </modulepath>
+ </javac>
+ <!-- create test classes jar - using the module-info of the tests -->
+ <jar destfile="build/dist/maven/${maven-name}-tests/${maven-name}-@{version}-tests.jar" unless:blank="@{test}">
+ <fileset dir="@{classes}"/>
+ <fileset dir="@{test-classes}">
+ <exclude name="org/apache/poi/ooxml/lite/**"/>
+ </fileset>
+ <resources/>
+ <test-resources/>
+ <zipfileset dir="${basedir}/src/multimodule/@{module}/test9" prefix="META-INF/versions/9" excludes="*.java"/>
+ <metainf dir="legal/"/>
+ <manifest>
+ <attribute name="Multi-Release" value="true"/>
+ <attribute name="Automatic-Module-Name" value="org.apache.poi.@{module}"/>
+ <attribute name="Built-By" value="${user.name}"/>
+ <attribute name="Specification-Title" value="Apache POI"/>
+ <attribute name="Specification-Version" value="${version.id}"/>
+ <attribute name="Specification-Vendor" value="The Apache Software Foundation"/>
+ <attribute name="Implementation-Title" value="Apache POI"/>
+ <attribute name="Implementation-Version" value="${version.id}"/>
+ <attribute name="Implementation-Vendor-Id" value="org.apache.poi"/>
+ <attribute name="Implementation-Vendor" value="The Apache Software Foundation"/>
+ </manifest>
+ </jar>
- <mkdir dir="${main.output.dir}/META-INF/versions/9"/>
+ <!-- create the sources jar -->
+ <jar destfile="build/dist/maven/${maven-name}/${maven-name}-@{version}-sources.jar">
+ <fileset dir="@{java}"/>
+ <metainf dir="legal/"/>
+<!-- <resources/>-->
+<!-- <zipfileset dir="src/multimodule/@{module}/java9" prefix="META-INF/versions/9" excludes="*.class"/>-->
+ <manifest>
+ <attribute name="Built-By" value="${user.name}"/>
+ <attribute name="Specification-Title" value="Apache POI"/>
+ <attribute name="Specification-Version" value="${version.id}"/>
+ <attribute name="Specification-Vendor" value="The Apache Software Foundation"/>
+ <attribute name="Implementation-Title" value="Apache POI"/>
+ <attribute name="Implementation-Version" value="${version.id}"/>
+ <attribute name="Implementation-Vendor-Id" value="org.apache.poi"/>
+ <attribute name="Implementation-Vendor" value="The Apache Software Foundation"/>
+ </manifest>
+ </jar>
+ </sequential>
+ </macrodef>
- <javac release="9"
- srcdir="${basedir}/src/multimodule/poi/java9"
- destdir="${main.output.dir}/META-INF/versions/9"
- includeantruntime="false"
- fork="true"
- modulepath="${main.lib}"
- unless:true="${isJava8}">
- <compilerarg line="--patch-module org.apache.poi.poi=${main.output.dir}"/>
- </javac>
+ <target name="compile-main" depends="init, compile-version">
+ <compile-jar module="poi"
+ java="${main.src}" classes="${main.output.dir}"
+ test="${main.src.test}" test-classes="${main.output.test.dir}">
+ <lib>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ </lib>
+ <resources>
+ <fileset dir="${main.resource1.dir}"/>
+ </resources>
+ </compile-jar>
</target>
<target name="compile-scratchpad" depends="compile-main">
- <!-- compile the sources -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${scratchpad.output.dir}"
- srcdir="${scratchpad.src}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath refid="scratchpad.classpath"/>
- </javac>
- <!-- compile the tests -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${scratchpad.output.test.dir}"
- srcdir="${scratchpad.src.test}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath>
- <path refid="scratchpad.classpath"/>
- <path refid="test.jar.classpath"/>
- <pathelement location="${scratchpad.output.dir}"/>
- <pathelement location="${main.output.test.dir}"/>
- </classpath>
- </javac>
- <copy todir="${scratchpad.output.dir}">
- <fileset dir="${scratchpad.resource1.dir}"/>
- </copy>
+ <compile-jar module="scratchpad"
+ java="${scratchpad.src}" classes="${scratchpad.output.dir}"
+ test="${scratchpad.src.test}" test-classes="${scratchpad.output.test.dir}">
+ <lib>
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ </lib>
+ <resources>
+ <fileset dir="${scratchpad.resource1.dir}"/>
+ </resources>
+ </compile-jar>
</target>
<target name="compile-examples" depends="compile-main,compile-scratchpad,compile-ooxml">
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${examples.output.dir}"
- srcdir="${examples.src}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath>
- <path refid="ooxml.classpath"/>
- <pathelement path="${ooxml.output.dir}"/>
- <pathelement location="${scratchpad.output.dir}"/>
- </classpath>
- </javac>
- <copy todir="${examples.output.dir}">
- <fileset dir="${examples.src}">
- <include name="**/*.css"/>
- </fileset>
- </copy>
+ <compile-jar module="examples"
+ java="${examples.src}" classes="${examples.output.dir}">
+ <lib>
+ <pathelement path="build/dist/maven/ooxml-schemas"/>
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="build/dist/maven/poi-scratchpad-tests"/>
+ <pathelement path="build/dist/maven/poi-ooxml-tests"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/ooxml"/>
+ </lib>
+ </compile-jar>
</target>
<target name="compile-ooxml" depends="compile-main,compile-scratchpad,compile-ooxml-xsds">
- <!-- compile the sources -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${ooxml.output.dir}"
- srcdir="${ooxml.src}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath>
- <path refid="ooxml.classpath"/>
- <path refid="ooxml.xmlsec.classpath"/>
- </classpath>
- </javac>
- <!-- compile the tests -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${ooxml.output.test.dir}"
- srcdir="${ooxml.src.test}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath>
- <path refid="ooxml.classpath"/>
- <path refid="ooxml.xmlsec.classpath"/>
- <path refid="test.ooxml.classpath"/>
- <pathelement path="${ooxml.output.dir}"/>
- <pathelement path="${main.output.test.dir}"/>
- </classpath>
+ <compile-jar module="ooxml"
+ java="${ooxml.src}" classes="${ooxml.output.dir}"
+ test="${ooxml.src.test}" test-classes="${ooxml.output.test.dir}">
+ <lib>
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="build/dist/maven/poi-scratchpad-tests"/>
+ <pathelement path="build/dist/maven/ooxml-schemas"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ <pathelement path="lib/ooxml"/>
+ <pathelement path="lib/ooxml-provided"/>
+ <pathelement path="lib/ooxml-tests"/>
+ </lib>
+ <resources>
+ <fileset dir="${ooxml.resource1.dir}"/>
+ </resources>
+ </compile-jar>
+
+ <!-- create ooxml-lite-agent jar -->
+ <javac release="9"
+ srcdir="${basedir}/src/multimodule/ooxml-lite-agent/java9"
+ destdir="${basedir}/src/multimodule/ooxml-lite-agent/java9"
+ includeantruntime="false"
+ fork="true"
+ unless:true="${isJava8}">
+ <compilerarg line="--patch-module org.apache.poi.ooxml_lite=${ooxml.output.test.dir}"/>
</javac>
- <copy todir="${ooxml.output.dir}">
- <fileset dir="${ooxml.resource1.dir}"/>
- </copy>
+
+ <jar destfile="${ooxml.lite.agent}">
+ <fileset dir="${ooxml.output.test.dir}" includes="org/apache/poi/ooxml/lite/**"/>
+ <zipfileset dir="${basedir}/src/multimodule/ooxml-lite-agent/java9" prefix="META-INF/versions/9" excludes="*.java"/>
+ <manifest>
+ <attribute name="Multi-Release" value="true"/>
+ <attribute name="Automatic-Module-Name" value="org.apache.poi.ooxml_lite"/>
+ <attribute name="Premain-Class" value="org.apache.poi.ooxml.lite.OOXMLLiteAgent"/>
+ </manifest>
+ </jar>
</target>
<macrodef name="poiunit" xmlns:jacoco="antlib:org.jacoco.ant">
<attribute name="heap" default="512"/>
<attribute name="showoutput" default="false"/>
<attribute name="jacocodest" default="build/jacoco-dest.exec"/>
+ <attribute name="modulepath-ref"/>
<element name="elements" implicit="true"/>
<sequential>
<local name="no.jit.sherlock"/>
<!-- see http://www-01.ibm.com/support/docview.wss?uid=swg21294023 on how to determine the method strings -->
- <property name="no.jit.sherlock">
- sun/java2d/pipe/AAShapePipe.renderTiles(Lsun/java2d/SunGraphics2D;Ljava/awt/Shape;Lsun/java2d/pipe/AATileGenerator;[I)V
- sun/java2d/pipe/AlphaPaintPipe.renderPathTile(Ljava/lang/Object;[BIIIIII)V
- java/awt/TexturePaintContext.getRaster(IIII)Ljava/awt/image/Raster;
- </property>
- <script language="javascript">
- var before = project.getProperty("no.jit.sherlock");
- project.setProperty("no.jit.sherlock", before.trim().replace(/ *(\S+) */g,"exclude={$1}").replace(/\s/g,","));
- </script>
+ <loadresource property="no.jit.sherlock">
+ <string>
+ sun/java2d/pipe/AAShapePipe.renderTiles(Lsun/java2d/SunGraphics2D;Ljava/awt/Shape;Lsun/java2d/pipe/AATileGenerator;[I)V
+ sun/java2d/pipe/AlphaPaintPipe.renderPathTile(Ljava/lang/Object;[BIIIIII)V
+ java/awt/TexturePaintContext.getRaster(IIII)Ljava/awt/image/Raster;
+ </string>
+ <filterchain>
+ <trim/>
+ <ignoreblank/>
+ <prefixlines prefix=",exclude={"/>
+ <suffixlines suffix="}"/>
+ <striplinebreaks/>
+ </filterchain>
+ </loadresource>
<local name="ooxml.lite.agent.exists"/>
<available property="ooxml.lite.agent.exists" file="${ooxml.lite.agent}"/>
+ <local name="cp_java"/>
+ <pathconvert property="cp_java" pathsep=",">
+ <path refid="@{modulepath-ref}"/>
+ <regexpmapper from="^${basedir}[/\\](.*)$" to="\1/*.jar"/>
+ </pathconvert>
+
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="@{jacocodest}">
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
- failureproperty="@{failureproperty}" showoutput="@{showoutput}">
+ failureproperty="@{failureproperty}" showoutput="@{showoutput}" filtertrace="off">
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-Xmx@{heap}M"/>
<jvmarg value="-ea"/>
- <!-- some "add-opens" are needed for Java 10, but not for 11+ -->
- <jvmarg value="--add-modules=java.xml.bind" if:true="${addOpens10}" />
- <jvmarg value="--add-opens=java.base/java.lang=java.xml.bind" if:true="${addOpens10}" />
-
<!-- some "add-opens" and other properties are needed when running with Java 9 or newer -->
<sysproperty key="sun.reflect.debugModuleAccessChecks" value="true" if:true="${addOpens}" />
<sysproperty key="com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize" value="true" if:true="${addOpens}" />
<jvmarg value="--illegal-access=warn" if:true="${addOpens}" />
- <jvmarg value="--add-opens=java.xml/com.sun.org.apache.xerces.internal.util=ALL-UNNAMED" if:true="${addOpens}" />
- <jvmarg value="--add-opens=java.base/java.io=ALL-UNNAMED" if:true="${addOpens}" />
- <jvmarg value="--add-opens=java.base/java.nio=ALL-UNNAMED" if:true="${addOpens}" />
- <jvmarg value="--add-opens=java.base/java.lang=ALL-UNNAMED" if:true="${addOpens}" />
- <jvmarg value="--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED" if:true="${addOpens}" />
-
<jvmarg value="-javaagent:${ooxml.lite.agent}=${ooxml.lite.report}|${ooxml.lite.includes}" if:true="${ooxml.lite.agent.exists}"/>
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<jvmarg value="${file.leak.detector}" />
- <jvmarg value="-Xjit:verbose={compileStart|compileEnd},vlog=build/jit.log,${no.jit.sherlock}" if:true="${isIBMVM}"/>
+ <jvmarg value="-Xjit:verbose={compileStart|compileEnd},vlog=build/jit.log${no.jit.sherlock}" if:true="${isIBMVM}"/>
<formatter type="plain"/>
<formatter type="xml"/>
+ <modulepath refid="@{modulepath-ref}" unless:true="${isJava8}"/>
+ <classpath if:true="${isJava8}">
+ <fileset dir="${basedir}" includes="${cp_java}"/>
+ </classpath>
<elements/>
</junit>
</jacoco:coverage>
</sequential>
</macrodef>
- <target name="retest-ooxml" depends="jar">
- <delete dir="${ooxml.reports.test}"/>
- <delete dir="${ooxml.output.test.dir}"/>
- <mkdir dir="${ooxml.reports.test}"/>
- <mkdir dir="${ooxml.output.test.dir}"/>
- <!-- compile the sources -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${ooxml.output.dir}"
- srcdir="${ooxml.src}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath>
- <path refid="ooxml.lite.verify.classpath"/>
- <path refid="ooxml.xmlsec.classpath"/>
- </classpath>
- </javac>
- <!-- compile the tests -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${ooxml.output.test.dir}"
- srcdir="${ooxml.src.test}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath>
- <path refid="ooxml.classpath"/>
- <path refid="ooxml.xmlsec.classpath"/>
- <path refid="test.ooxml.lite.verify.classpath"/>
- <pathelement path="${ooxml.output.dir}"/>
- <pathelement path="${main.output.test.dir}"/>
- </classpath>
- </javac>
- <copy todir="${ooxml.output.dir}">
- <fileset dir="${ooxml.resource1.dir}"/>
- </copy>
+ <target name="retest-ooxml" depends="jar"
+ description="run ooxml tests with poi-ooxml-schemas (= lite schema)">
+ <path id="restest.modules">
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="build/dist/maven/poi-scratchpad-tests"/>
+ <pathelement path="build/dist/maven/poi-ooxml-tests"/>
+ <pathelement path="build/dist/maven/poi-ooxml-schemas"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ <pathelement path="lib/ooxml"/>
+ <pathelement path="lib/ooxml-provided"/>
+ <pathelement path="lib/ooxml-tests"/>
+ </path>
- <poiunit failureproperty="ooxml.test.failed" heap="768">
- <classpath>
- <path refid="test.ooxml.lite.verify.classpath"/>
- <path refid="test.jar.classpath"/>
- </classpath>
+ <poiunit failureproperty="ooxml.test.failed" heap="768"
+ modulepath-ref="restest.modules">
+ <jvmarg line="--add-modules org.apache.poi.ooxml" unless:true="${isJava8}"/>
+ <jvmarg line="--add-modules org.apache.poi.scratchpad" unless:true="${isJava8}"/>
<batchtest todir="${ooxml.reports.test}">
<fileset dir="${ooxml.src.test}">
<include name="**/${testpattern}.java"/>
</target>
<target name="compile-excelant" depends="compile-main,compile-ooxml">
- <!-- compile the sources -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${excelant.output.dir}"
- srcdir="${excelant.src}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath refid="excelant.classpath"/>
- </javac>
- <!-- compile the tests -->
- <javac target="${jdk.version.class}"
- source="${jdk.version.source}"
- destdir="${excelant.output.test.dir}"
- srcdir="${excelant.src.test}"
- debug="${compile.debug}"
- encoding="${java.source.encoding}"
- fork="yes"
- includeantruntime="false">
- <classpath>
- <path refid="excelant.classpath"/>
- <path refid="test.jar.classpath"/>
- <pathelement location="${excelant.output.dir}"/>
- <pathelement path="${main.output.test.dir}"/>
- </classpath>
- </javac>
- <copy todir="${excelant.output.dir}">
- <fileset dir="${excelant.resource.dir}"/>
- </copy>
+ <compile-jar module="excelant"
+ java="${excelant.src}" classes="${excelant.output.dir}"
+ test="${excelant.src.test}" test-classes="${excelant.output.test.dir}">
+ <lib>
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="build/dist/maven/poi-scratchpad-tests"/>
+ <pathelement path="build/dist/maven/poi-ooxml-tests"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ <pathelement path="lib/excelant"/>
+ </lib>
+ <resources>
+ <fileset dir="${excelant.resource.dir}"/>
+ </resources>
+ </compile-jar>
</target>
<target name="compile-integration" depends="compile-scratchpad, compile-main, compile-ooxml, compile-examples">
- <javac target="${jdk.version.class}"
+ <javac release="8"
+ target="${jdk.version.class}"
source="${jdk.version.source}"
destdir="${integration.output.test.dir}"
srcdir="${integration.src.test}"
</classpath>
<exclude name="**/HeapDump**" if:true="${isIBMVM}"/>
</javac>
- <!--copy todir="${integration.output.dir}">
- <fileset dir="${integration.resource1.dir}"/>
- </copy-->
+
+
+ <mkdir dir="${integration.output.test.dir}/META-INF/versions/9"/>
+
+ <javac release="9"
+ srcdir="${basedir}/src/multimodule/integration/java9"
+ destdir="${integration.output.test.dir}/META-INF/versions/9"
+ includeantruntime="false"
+ fork="true"
+ unless:true="${isJava8}">
+ <compilerarg line="--patch-module org.apache.poi.stress=${integration.output.test.dir}"/>
+ <modulepath>
+ <pathelement path="build/dist/maven/poi"/>
+ <pathelement path="build/dist/maven/poi-ooxml"/>
+ <pathelement path="build/dist/maven/poi-scratchpad"/>
+ <pathelement path="build/dist/maven/poi-examples"/>
+ <pathelement path="${main.lib}"/>
+ <pathelement path="${main-tests.lib}"/>
+ <pathelement path="${ooxml.lib}"/>
+ <pathelement path="${ooxml-provided.lib}"/>
+ </modulepath>
+ </javac>
+
+ <manifest file="build/poi-manifest.mf">
+ <attribute name="Multi-Release" value="true"/>
+ <attribute name="Automatic-Module-Name" value="org.apache.poi.stress"/>
+ </manifest>
+
+ <jar destfile="lib/ooxml-tests/poi-integration.jar"
+ basedir="${integration.output.test.dir}"
+ manifest="build/poi-manifest.mf"/>
</target>
<target name="-version-java-check">
<target name="jacocotask" depends="">
<echo message="Coverage reporting: ${coverage.enabled}"/>
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
- <classpath refid="lib.jacoco"/>
+ <classpath>
+ <fileset dir="${util.lib}">
+ <include name="org.jacoco*.jar" />
+ <include name="asm-*.jar" />
+ </fileset>
+ </classpath>
</taskdef>
</target>
<target name="test-main" unless="main.test.notRequired"
depends="compile-main, -test-main-check,jacocotask"
description="tests POI classes that deal with the Microsoft Office binary (BIFF8) file formats (excludes OOXML)">
- <poiunit failureproperty="main.test.failed" heap="256" showoutput="true" jacocodest="build/jacoco-main.exec">
- <classpath>
- <path refid="test.classpath"/>
- <path refid="test.jar.classpath"/>
- </classpath>
+
+ <path id="test-main.modules">
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ </path>
+
+ <poiunit failureproperty="main.test.failed" heap="256" showoutput="true" jacocodest="build/jacoco-main.exec"
+ modulepath-ref="test-main.modules">
+ <jvmarg line="--add-modules org.apache.poi.poi" unless:true="${isJava8}"/>
+
<batchtest todir="${main.reports.test}">
<fileset dir="${main.src.test}">
<include name="**/${testpattern}.java"/>
</fileset>
</batchtest>
</poiunit>
+
<delete file="${main.testokfile}"/>
<antcall target="-test-main-write-testfile"/>
</target>
</uptodate>
</target>
- <target name="test-scratchpad" depends="jacocotask,compile-main,compile-scratchpad,-test-scratchpad-check,test-scratchpad-download-resources"
+
+ <target name="test-scratchpad" depends="jacocotask,compile-scratchpad,-test-scratchpad-check,test-scratchpad-download-resources"
unless="scratchpad.test.notRequired"
description="test non-OOXML scratchpad classes">
- <poiunit failureproperty="scratchpad.test.failed" heap="512" jacocodest="build/jacoco-scratchpad.exec">
- <classpath>
- <path refid="test.scratchpad.classpath"/>
- <path refid="test.jar.classpath"/>
- </classpath>
+
+ <path id="test-scratchpad.modules">
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="build/dist/maven/poi-scratchpad-tests"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ </path>
+
+ <poiunit failureproperty="scratchpad.test.failed" heap="512" jacocodest="build/jacoco-scratchpad.exec"
+ modulepath-ref="test-scratchpad.modules">
+ <jvmarg line="--add-modules org.apache.poi.scratchpad" unless:true="${isJava8}"/>
+
<batchtest todir="${scratchpad.reports.test}">
<fileset dir="${scratchpad.src.test}">
<include name="**/${testpattern}.java"/>
</target>
<macrodef name="ooxml-test-runner" xmlns:jacoco="antlib:org.jacoco.ant">
- <attribute name="classpath"/>
+ <attribute name="modulepath-ref"/>
<attribute name="type"/>
<sequential>
- <poiunit failureproperty="ooxml.test.failed" heap="768" jacocodest="build/jacoco-@{type}.exec">
- <classpath>
- <path refid="@{classpath}"/>
- <path refid="test.jar.classpath"/>
- </classpath>
+ <poiunit failureproperty="ooxml.test.failed" heap="768" jacocodest="build/jacoco-@{type}.exec"
+ modulepath-ref="@{modulepath-ref}">
+ <jvmarg line="--add-modules org.apache.poi.ooxml" unless:true="${isJava8}"/>
+ <jvmarg line="--add-modules org.apache.poi.scratchpad" unless:true="${isJava8}"/>
+
<batchtest todir="${ooxml.reports.test}">
<fileset dir="${ooxml.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/TestUnfixedBugs.java"/>
<exclude name="**/All*Tests.java"/>
- <exclude name="**/TestSignatureInfo.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</poiunit>
-
- <poiunit failureproperty="ooxml.xmlsec.test.failed" heap="768" jacocodest="build/jacoco-@{type}-xmlsec.exec">
- <classpath>
- <path refid="@{classpath}"/>
- <path refid="test.jar.classpath"/>
- <path refid="ooxml.xmlsec.classpath"/>
- </classpath>
- <batchtest todir="${ooxml.reports.test}">
- <fileset dir="${ooxml.src.test}">
- <include name="**/TestSignatureInfo.java"/>
- </fileset>
- </batchtest>
- </poiunit>
</sequential>
</macrodef>
- <target name="test-ooxml" depends="compile-main,compile-ooxml,-test-ooxml-check,jacocotask,-ooxml-lite-agent" unless="ooxml.test.notRequired"
+ <target name="test-ooxml" depends="compile-main,compile-ooxml,-test-ooxml-check,jacocotask" unless="ooxml.test.notRequired"
description="test OOXML classes">
- <ooxml-test-runner classpath="test.ooxml.classpath" type="ooxml"/>
+ <path id="test-ooxml.modules">
+ <!-- full schema -->
+ <pathelement path="build/dist/maven/ooxml-schemas"/>
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="build/dist/maven/poi-ooxml-tests"/>
+ <pathelement path="build/dist/maven/poi-scratchpad-tests"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ <pathelement path="lib/ooxml"/>
+ <pathelement path="lib/ooxml-provided"/>
+ <pathelement path="lib/ooxml-tests"/>
+ </path>
+
+ <ooxml-test-runner modulepath-ref="test-ooxml.modules" type="ooxml"/>
<delete file="${ooxml.testokfile}"/>
<antcall target="-test-ooxml-write-testfile"/>
</target>
</uptodate>
</target>
- <target name="test-integration" depends="compile-integration,-test-integration-check,jacocotask,-ooxml-lite-agent"
+ <target name="test-integration" depends="compile-integration,-test-integration-check,jacocotask"
unless="integration.test.notRequired">
<propertyreset name="org.apache.poi.util.POILogger" value="org.apache.poi.util.CommonsLogger"/>
<delete dir="build" includes="test-integration.log*"/>
- <poiunit failureproperty="integration.test.failed" heap="1512" showoutput="true" jacocodest="build/jacoco-integration.exec">
- <classpath refid="test.integration.classpath"/>
+
+ <path id="test-integration.modules">
+ <pathelement path="build/dist/maven/poi"/>
+ <pathelement path="build/dist/maven/poi-ooxml"/>
+ <pathelement path="build/dist/maven/poi-scratchpad"/>
+ <pathelement path="build/dist/maven/poi-examples"/>
+ <pathelement path="build/dist/maven/ooxml-schemas"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ <pathelement path="lib/ooxml"/>
+ <pathelement path="lib/ooxml-provided"/>
+ <pathelement path="lib/ooxml-tests"/>
+ </path>
+
+ <poiunit failureproperty="integration.test.failed" heap="1512" showoutput="true" jacocodest="build/jacoco-integration.exec"
+ modulepath-ref="test-integration.modules">
+ <jvmarg line="--add-modules org.apache.poi.stress" unless:true="${isJava8}"/>
+
<batchtest todir="${integration.reports.test}">
<fileset dir="${integration.src.test}">
<include name="**/${testpattern}.java"/>
<!-- the ooxml lite agent collects referenced schema files while other junit tests are run, -->
<!-- therefore its best to compile the ooxml lite jar after all usual tests are done -->
- <target name="compile-ooxml-lite" depends="compile-ooxml,-ooxml-lite-agent,test-ooxml">
+ <target name="compile-ooxml-lite" depends="test-ooxml">
<echo message="Create ooxml-lite schemas"/>
+ <local name="lite.exports"/>
+ <loadresource property="lite.exports">
+ <file file="${ooxml.lite.report}"/>
+ <filterchain>
+ <tokenfilter>
+ <replaceregex pattern="[/\\][^/\\]+$" replace=""/>
+ <replaceregex pattern="[/\\]" replace="." flags="g"/>
+ </tokenfilter>
+ <linecontainsregexp negate="true" regexp="\.impl$"/>
+ <sortfilter/>
+ <uniqfilter/>
+ <prefixlines prefix=" exports "/>
+ <suffixlines suffix=";"/>
+ </filterchain>
+ </loadresource>
- <copy file="${ooxml.lite.report}" tofile="${ooxml.lite.report}-pat" overwrite="true"/>
- <replaceregexp file="${ooxml.lite.report}-pat" byline="true" match="(.*)" replace="\1.class${line.separator}\1$*.class"/>
+ <local name="full.schema"/>
+ <loadresource property="full.schema">
+ <file file="${basedir}/src/multimodule/ooxml-schemas/java9/module-info.java"/>
+ <filterchain>
+ <linecontains negate="true" matchany="true">
+ <contains value="exports"/>
+ <contains value="}"/>
+ </linecontains>
+ </filterchain>
+ </loadresource>
- <patternset id="xsbfiles">
- <includesfile name="${ooxml.lite.report}-pat"/>
- <include name="org/apache/poi/schemas/*/system/**/*.xsb"/>
- <include name="org/apache/poi/schemas/*/element/**/*.xsb"/>
- </patternset>
+ <echo output="${basedir}/src/multimodule/ooxml-lite/java9/module-info.java">${full.schema}${lite.exports}}</echo>
+
+ <javac release="9"
+ srcdir="${basedir}/src/multimodule/ooxml-lite/java9"
+ destdir="${basedir}/src/multimodule/ooxml-lite/java9"
+ includeantruntime="false"
+ fork="true"
+ unless:true="${isJava8}">
+ <compilerarg line="--patch-module org.apache.poi.ooxml.schemas=${ooxml.xsds.jar}"/>
+ <modulepath>
+ <pathelement path="lib/ooxml"/>
+ </modulepath>
+ </javac>
+
+ <local name="lite.classes"/>
+ <loadresource property="lite.classes">
+ <file file="${ooxml.lite.report}"/>
+ <filterchain>
+ <tokenfilter>
+ <replaceregex pattern="(.*)" replace="\1.class \1$*.class "/>
+ </tokenfilter>
+ <striplinebreaks/>
+ </filterchain>
+ </loadresource>
+
+ <mkdir dir="build/dist/maven/poi-ooxml-schemas"/>
<jar destfile="${ooxml.lite.jar}" duplicate="preserve">
+ <zipfileset dir="${basedir}/src/multimodule/ooxml-lite/java9" prefix="META-INF/versions/9" excludes="*.java"/>
<zipfileset src="${ooxml.xsds.jar}">
- <patternset refid="xsbfiles"/>
- </zipfileset>
- <zipfileset src="${ooxml.security.jar}">
- <patternset refid="xsbfiles"/>
+ <patternset includes="${lite.classes}">
+ <include name="org/apache/poi/schemas/*/system/**/*.xsb"/>
+ <include name="org/apache/poi/schemas/*/element/**/*.xsb"/>
+ </patternset>
</zipfileset>
+ <zipfileset dir="src/multimodule/ooxml-schemas/java9" prefix="META-INF/versions/9" excludes="*.java"/>
+ <manifest>
+ <attribute name="Multi-Release" value="true"/>
+ <attribute name="Automatic-Module-Name" value="org.apache.poi.ooxml.schemas"/>
+ </manifest>
</jar>
</target>
- <target name="test-ooxml-lite" depends="jacocotask,compile-ooxml-xsds,compile-ooxml-lite">
+ <target name="test-ooxml-lite" depends="jacocotask,compile-ooxml-lite">
<delete file="${ooxml.testokfile}"/>
<echo message="Running ooxml tests against 'poi-ooxml-schemas'"/>
- <ooxml-test-runner classpath="ooxml-lite.classpath" type="ooxml-lite"/>
- </target>
- <target name="-ooxml-lite-agent" depends="jacocotask,compile-ooxml-xsds,compile-ooxml">
- <jar destfile="${ooxml.lite.agent}">
- <fileset dir="${ooxml.output.test.dir}" includes="org/apache/poi/ooxml/util/OOXMLLiteAgent*.class"/>
- <manifest>
- <attribute name="Premain-Class" value="org.apache.poi.ooxml.util.OOXMLLiteAgent"/>
- </manifest>
- </jar>
+ <path id="test-ooxml-lite.modules">
+ <!-- lite schema -->
+ <pathelement path="build/dist/maven/poi-ooxml-schemas"/>
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="build/dist/maven/poi-ooxml-tests"/>
+ <pathelement path="build/dist/maven/poi-scratchpad-tests"/>
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ <pathelement path="lib/ooxml"/>
+ <pathelement path="lib/ooxml-provided"/>
+ <pathelement path="lib/ooxml-tests"/>
+ </path>
+
+
+ <ooxml-test-runner modulepath-ref="test-ooxml-lite.modules" type="ooxml-lite"/>
</target>
<!-- Section: test-excelant -->
<echo file="${excelant.testokfile}" append="false" message="testok"/>
</target>
- <target name="test-excelant" depends="compile-excelant,-test-excelant-check,jacocotask"
+ <target name="test-excelant" depends="compile-excelant,compile-ooxml-lite,-test-excelant-check,jacocotask"
unless="excelant.test.notRequired">
- <poiunit failureproperty="excelant.test.failed" jacocodest="build/jacoco-excelant.exec">
- <classpath refid="test.excelant.classpath"/>
+
+ <path id="test-excelant.modules">
+ <pathelement path="lib/main"/>
+ <pathelement path="lib/main-tests"/>
+ <pathelement path="lib/ooxml"/>
+ <pathelement path="lib/ooxml-tests"/>
+ <pathelement path="lib/ooxml-provided"/>
+ <pathelement path="lib/excelant"/>
+ <pathelement path="build/dist/maven/poi-tests"/>
+ <pathelement path="build/dist/maven/poi-ooxml-tests"/>
+ <pathelement path="build/dist/maven/poi-ooxml-schemas"/>
+ <pathelement path="build/dist/maven/poi-scratchpad-tests"/>
+ <pathelement path="build/dist/maven/poi-excelant-tests"/>
+ </path>
+
+ <poiunit failureproperty="excelant.test.failed" jacocodest="build/jacoco-excelant.exec"
+ modulepath-ref="test-excelant.modules">
+ <jvmarg line="--add-modules org.apache.poi.excelant" unless:true="${isJava8}"/>
+
<batchtest todir="${excelant.reports.test}">
<fileset dir="${excelant.src.test}">
<include name="**/${testpattern}.java"/>
<target name="-manifest">
<manifest file="build/poi-manifest.mf">
+ <attribute name="Multi-Release" value="true"/>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Specification-Title" value="Apache POI"/>
<attribute name="Specification-Version" value="${version.id}"/>
<macrodef name="maven-jar">
<attribute name="src"/>
+ <attribute name="module"/>
+ <element name="elements" implicit="true" optional="true"/>
+
<sequential>
<local name="destfile"/>
<pathconvert property="destfile" targetos="unix">
</chainedmapper>
</mapper>
</pathconvert>
+
<local name="isjar"/>
<condition property="isjar">
<contains string="@{src}" substring=".jar"/>
</condition>
- <jar destfile="build/dist/maven/${destfile}.jar"
- manifest="build/poi-manifest.mf">
+ <mkdir dir="@{src}/META-INF/versions/9"/>
+
+ <javac release="9"
+ srcdir="${basedir}/src/multimodule/@{module}/java9"
+ destdir="@{src}/META-INF/versions/9"
+ includeantruntime="false"
+ fork="true"
+ modulepath="${main.lib}"
+ unless:true="${isJava8}">
+ <compilerarg line="--patch-module org.apache.poi.@{module}=@{src}"/>
+ <elements/>
+ </javac>
+
+ <jar destfile="build/dist/maven/${destfile}.jar">
<fileset dir="@{src}" unless:true="${isjar}"/>
<zipfileset src="@{src}" if:true="${isjar}"/>
<metainf dir="legal/"/>
+ <manifest>
+ <attribute name="Multi-Release" value="true"/>
+ <attribute name="Automatic-Module-Name" value="org.apache.poi.@{module}"/>
+ <attribute name="Built-By" value="${user.name}"/>
+ <attribute name="Specification-Title" value="Apache POI"/>
+ <attribute name="Specification-Version" value="${version.id}"/>
+ <attribute name="Specification-Vendor" value="The Apache Software Foundation"/>
+ <attribute name="Implementation-Title" value="Apache POI"/>
+ <attribute name="Implementation-Version" value="${version.id}"/>
+ <attribute name="Implementation-Vendor-Id" value="org.apache.poi"/>
+ <attribute name="Implementation-Vendor" value="The Apache Software Foundation"/>
+ </manifest>
</jar>
</sequential>
</macrodef>
- <target name="jar" depends="compile, compile-version, compile-ooxml-lite, -manifest" description="Creates jar files for distribution">
- <maven-jar src="${main.output.dir}"/>
- <maven-jar src="${scratchpad.output.dir}"/>
- <maven-jar src="${ooxml.output.dir}"/>
- <maven-jar src="${examples.output.dir}"/>
- <maven-jar src="${excelant.output.dir}"/>
- <maven-jar src="${ooxml.lite.jar}"/>
- </target>
-
- <target name="jar-src" depends="compile, compile-version, -manifest" description="Sources for Maven">
- <maven-jar src="${main.src}"/>
- <maven-jar src="${scratchpad.src}"/>
- <maven-jar src="${ooxml.src}"/>
- <maven-jar src="${examples.src}"/>
- <maven-jar src="${excelant.src}"/>
+ <target name="jar" depends="compile, compile-ooxml-lite" description="Creates jar files for distribution">
</target>
<target name="integration-test-jar" depends="compile-integration,-manifest" description="target for packaging the integration-test code for mass regression test runs">
</copy>
</target>
- <target name="assemble" depends="jar,jar-src,jar-javadocs" description="Produce the zipped distribution files">
+ <target name="assemble" depends="jar,jar-javadocs" description="Produce the zipped distribution files">
<property name="zipdir" value="${jar.name}-${version.id}"/>
<mappedresources id="legal-files" cache="true">
classname="de.thetaphi.forbiddenapis.ant.AntTask"
classpath="${forbidden.jar}"/>
+ <path id="forbiddenapis.classpath">
+ <fileset dir="lib/main" includes="*.jar"/>
+ <fileset dir="lib/main-tests" includes="*.jar"/>
+ <fileset dir="lib/ooxml" includes="*.jar"/>
+ <fileset dir="lib/ooxml-tests" includes="*.jar"/>
+ <fileset dir="lib/ooxml-provided" includes="*.jar"/>
+ <fileset dir="lib/excelant" includes="*.jar"/>
+ <pathelement location="${ooxml.xsds.jar}"/>
+ <pathelement location="build/dist/maven/poi-examples/poi-examples-${version.id}.jar"/>
+ <path path="${env.CLASSPATH}"/>
+ </path>
+
+
<!-- first check rules that apply to all the source code -->
<forbiddenapis
classpathref="forbiddenapis.classpath"
-->
<signaturesFileset file="src/resources/devtools/forbidden-signatures.txt"/>
<!-- sources -->
- <fileset dir="${main.output.dir}"/>
- <fileset dir="${ooxml.output.dir}"/>
- <fileset dir="${scratchpad.output.dir}"/>
- <fileset dir="${excelant.output.dir}"/>
+ <!-- zipfileset src="build/dist/maven/poi/poi-5.0.0-SNAPSHOT.jar"/ -->
+ <!-- zipfileset src="build/dist/maven/poi-ooxml/poi-ooxml-5.0.0-SNAPSHOT.jar"/ -->
+ <zipfileset src="build/dist/maven/poi-scratchpad/poi-scratchpad-5.0.0-SNAPSHOT.jar"/>
+ <zipfileset src="build/dist/maven/poi-excelant/poi-excelant-5.0.0-SNAPSHOT.jar"/>
<!--
<fileset dir="${examples.output.dir}"/>
-->
- <!-- test-sources -->
- <fileset dir="${main.output.test.dir}"/>
- <fileset dir="${ooxml.output.test.dir}"/>
+ <!-- test-sources (incl. sources) -->
+ <zipfileset src="build/dist/maven/poi-tests/poi-${version.id}-tests.jar"/>
+ <zipfileset src="build/dist/maven/poi-ooxml-tests/poi-ooxml-${version.id}-tests.jar"/>
<!--
<fileset dir="${scratchpad.output.test.dir}"/>
<fileset dir="${excelant.output.test.dir}"/>
>
<signaturesFileset file="src/resources/devtools/forbidden-signatures-prod.txt"/>
<!-- sources -->
- <fileset dir="${main.output.dir}"/>
- <fileset dir="${ooxml.output.dir}"/>
- <fileset dir="${scratchpad.output.dir}"/>
- <fileset dir="${excelant.output.dir}"/>
- <fileset dir="${integration.output.test.dir}"/>
+ <zipfileset src="build/dist/maven/poi/poi-5.0.0-SNAPSHOT.jar"/>
+ <zipfileset src="build/dist/maven/poi-ooxml/poi-ooxml-5.0.0-SNAPSHOT.jar"/>
+ <zipfileset src="build/dist/maven/poi-scratchpad/poi-scratchpad-5.0.0-SNAPSHOT.jar"/>
+ <zipfileset src="build/dist/maven/poi-excelant/poi-excelant-5.0.0-SNAPSHOT.jar"/>
+
+ <zipfileset src="lib/ooxml-tests/poi-integration.jar"/>
</forbiddenapis>
</target>
<auxClasspath path="${dsig.slf4j-api.jar}" />
<auxClasspath path="${dsig.xmlsec.jar}" />
<auxClasspath path="${ooxml.xsds.jar}" />
- <auxClasspath path="${ooxml.security.jar}" />
<auxClasspath path="${ooxml.curvesapi.jar}" />
<auxClasspath path="${ooxml.xmlbeans.jar}" />
<auxClasspath path="${ooxml.commons-compress.jar}" />
+++ /dev/null
-/*
- * ====================================================================
- * 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.crypt.examples;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.security.GeneralSecurityException;
-import java.util.Optional;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
-
-import org.apache.poi.poifs.crypt.Decryptor;
-import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-/**
- * Tries a list of possible passwords for an OOXML protected file
- *
- * Note that this isn't very fast, and is aimed at when you have
- * just a few passwords to check.
- * For serious processing, you'd be best off grabbing the hash
- * out with POI or office2john.py, then running that against
- * "John The Ripper" or GPU enabled version of "hashcat"
- */
-public final class OOXMLPasswordsTry {
-
- private OOXMLPasswordsTry() {}
-
- @SuppressWarnings({"java:S106","java:S4823"})
- public static void main(String[] args) throws Exception {
- if (args.length < 2) {
- System.err.println("Use:");
- System.err.println(" OOXMLPasswordsTry <file.ooxml> <wordlist>");
- System.exit(1);
- }
- String ooxml = args[0];
- String words = args[1];
-
- System.out.println("Trying passwords from " + words + " against " + ooxml);
- System.out.println();
-
- try (POIFSFileSystem fs = new POIFSFileSystem(new File(ooxml), true)) {
- EncryptionInfo info = new EncryptionInfo(fs);
- Decryptor d = Decryptor.getInstance(info);
-
- final long start = System.currentTimeMillis();
- final int[] count = { 0 };
- Predicate<String> counter = s -> {
- if (++count[0] % 1000 == 0) {
- int secs = (int) ((System.currentTimeMillis() - start) / 1000);
- System.out.println("Done " + count[0] + " passwords, " + secs + " seconds, last password " + s);
- }
- return true;
- };
-
- // Try each password in turn, reporting progress
- try (Stream<String> lines = Files.lines(Paths.get(words))) {
- Optional<String> found = lines.filter(counter).filter(w -> isValid(d, w)).findFirst();
- System.out.println(found.map(s -> "Password found: " + s).orElse("Error - No password matched"));
- }
- }
- }
-
- private static boolean isValid(Decryptor dec, String password) {
- try {
- return dec.verifyPassword(password);
- } catch (GeneralSecurityException e) {
- return false;
- }
- }
-}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.crypt;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+/**
+ * Tries a list of possible passwords for an OOXML protected file
+ *
+ * Note that this isn't very fast, and is aimed at when you have
+ * just a few passwords to check.
+ * For serious processing, you'd be best off grabbing the hash
+ * out with POI or office2john.py, then running that against
+ * "John The Ripper" or GPU enabled version of "hashcat"
+ */
+public final class OOXMLPasswordsTry {
+
+ private OOXMLPasswordsTry() {}
+
+ @SuppressWarnings({"java:S106","java:S4823"})
+ public static void main(String[] args) throws Exception {
+ if (args.length < 2) {
+ System.err.println("Use:");
+ System.err.println(" OOXMLPasswordsTry <file.ooxml> <wordlist>");
+ System.exit(1);
+ }
+ String ooxml = args[0];
+ String words = args[1];
+
+ System.out.println("Trying passwords from " + words + " against " + ooxml);
+ System.out.println();
+
+ try (POIFSFileSystem fs = new POIFSFileSystem(new File(ooxml), true)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ Decryptor d = Decryptor.getInstance(info);
+
+ final long start = System.currentTimeMillis();
+ final int[] count = { 0 };
+ Predicate<String> counter = s -> {
+ if (++count[0] % 1000 == 0) {
+ int secs = (int) ((System.currentTimeMillis() - start) / 1000);
+ System.out.println("Done " + count[0] + " passwords, " + secs + " seconds, last password " + s);
+ }
+ return true;
+ };
+
+ // Try each password in turn, reporting progress
+ try (Stream<String> lines = Files.lines(Paths.get(words))) {
+ Optional<String> found = lines.filter(counter).filter(w -> isValid(d, w)).findFirst();
+ System.out.println(found.map(s -> "Password found: " + s).orElse("Error - No password matched"));
+ }
+ }
+ }
+
+ private static boolean isValid(Decryptor dec, String password) {
+ try {
+ return dec.verifyPassword(password);
+ } catch (GeneralSecurityException e) {
+ return false;
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hpsf;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.poi.hpsf.DocumentSummaryInformation;
+import org.apache.poi.hpsf.HPSFException;
+import org.apache.poi.hpsf.HPSFRuntimeException;
+import org.apache.poi.hpsf.PropertySet;
+import org.apache.poi.hpsf.PropertySetFactory;
+import org.apache.poi.hpsf.SummaryInformation;
+import org.apache.poi.hpsf.WritingNotSupportedException;
+import org.apache.poi.poifs.eventfilesystem.POIFSReader;
+import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
+import org.apache.poi.poifs.filesystem.DirectoryEntry;
+import org.apache.poi.poifs.filesystem.DocumentInputStream;
+import org.apache.poi.poifs.filesystem.EntryUtils;
+import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.TempFile;
+
+/**
+ * <p>This class copies a POI file system to a new file and compares the copy
+ * with the original.</p>
+ * <p>
+ * <p>Property set streams are copied logically, i.e. the application
+ * establishes a {@link org.apache.poi.hpsf.PropertySet} of an original property
+ * set, creates a {@link org.apache.poi.hpsf.PropertySet} and writes the
+ * {@link org.apache.poi.hpsf.PropertySet} to the destination POI file
+ * system. - Streams which are no property set streams are copied bit by
+ * bit.</p>
+ * <p>
+ * <p>The comparison of the POI file systems is done logically. That means that
+ * the two disk files containing the POI file systems do not need to be
+ * exactly identical. However, both POI file systems must contain the same
+ * files, and most of these files must be bitwise identical. Property set
+ * streams, however, are compared logically: they must have the same sections
+ * with the same attributes, and the sections must contain the same properties.
+ * Details like the ordering of the properties do not matter.</p>
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class CopyCompare {
+ private CopyCompare() {}
+
+ /**
+ * Runs the example program. The application expects one or two arguments:
+ *
+ * <ol>
+ * <li>The first argument is the disk file name of the POI filesystem to copy.</li>
+ * <li>The second argument is optional. If it is given, it is the name of
+ * a disk file the copy of the POI filesystem will be written to. If it is
+ * not given, the copy will be written to a temporary file which will be
+ * deleted at the end of the program.</li>
+ * </ol>
+ *
+ * @param args Command-line arguments.
+ * @throws IOException if any I/O exception occurs.
+ * @throws UnsupportedEncodingException if a character encoding is not
+ * supported.
+ */
+ public static void main(final String[] args) throws IOException {
+ String originalFileName = null;
+ String copyFileName = null;
+
+ // Check the command-line arguments.
+ if (args.length == 1) {
+ originalFileName = args[0];
+ File f = TempFile.createTempFile("CopyOfPOIFileSystem-", ".ole2");
+ f.deleteOnExit();
+ copyFileName = f.getAbsolutePath();
+ } else if (args.length == 2) {
+ originalFileName = args[0];
+ copyFileName = args[1];
+ } else {
+ System.err.println("Usage: CopyCompare originPOIFS [copyPOIFS]");
+ System.exit(1);
+ }
+
+
+ // Read the origin POIFS using the eventing API.
+ final POIFSReader r = new POIFSReader();
+ try (final POIFSFileSystem poiFs = new POIFSFileSystem();
+ OutputStream fos = new FileOutputStream(copyFileName)) {
+ r.registerListener(e -> handleEvent(poiFs, e));
+ r.setNotifyEmptyDirectories(true);
+
+ r.read(new File(originalFileName));
+
+ // Write the new POIFS to disk.
+ poiFs.writeFilesystem(fos);
+ }
+
+ // Read all documents from the original POI file system and compare them with
+ // the equivalent document from the copy.
+ try (POIFSFileSystem opfs = new POIFSFileSystem(new File(originalFileName));
+ POIFSFileSystem cpfs = new POIFSFileSystem(new File(copyFileName))) {
+ final DirectoryEntry oRoot = opfs.getRoot();
+ final DirectoryEntry cRoot = cpfs.getRoot();
+ System.out.println(EntryUtils.areDirectoriesIdentical(oRoot, cRoot) ? "Equal" : "Not equal");
+ }
+ }
+
+ private interface InputStreamSupplier {
+ InputStream get() throws IOException, WritingNotSupportedException;
+ }
+
+ /**
+ * The method is called by POI's eventing API for each file in the origin POIFS.
+ */
+ public static void handleEvent(final POIFSFileSystem poiFs, final POIFSReaderEvent event) {
+ // The following declarations are shortcuts for accessing the "event" object.
+ final DocumentInputStream stream = event.getStream();
+
+ try {
+
+ // Find out whether the current document is a property set stream or not.
+ InputStreamSupplier su;
+ if (stream != null && PropertySet.isPropertySetStream(stream)) {
+ // Yes, the current document is a property set stream. Let's create
+ // a PropertySet instance from it.
+ PropertySet ps = PropertySetFactory.create(stream);
+
+ // Copy the property set to the destination POI file system.
+ final PropertySet mps;
+ if (ps instanceof DocumentSummaryInformation) {
+ mps = new DocumentSummaryInformation(ps);
+ } else if (ps instanceof SummaryInformation) {
+ mps = new SummaryInformation(ps);
+ } else {
+ mps = new PropertySet(ps);
+ }
+ su = mps::toInputStream;
+ } else {
+ // No, the current document is not a property set stream.
+ // We copy it unmodified to the destination POIFS.
+ su = event::getStream;
+ }
+
+ try (InputStream is = su.get()) {
+ final POIFSDocumentPath path = event.getPath();
+
+ // Ensures that the directory hierarchy for a document in a POI fileystem is in place.
+ // Get the root directory. It does not have to be created since it always exists in a POIFS.
+ DirectoryEntry de = poiFs.getRoot();
+ if (File.separator.equals(path.toString())) {
+ de.setStorageClsid(event.getStorageClassId());
+ }
+
+ for (int i=0; i<path.length(); i++) {
+ String subDir = path.getComponent(i);
+ if (de.hasEntry(subDir)) {
+ de = (DirectoryEntry)de.getEntry(subDir);
+ } else {
+ de = de.createDirectory(subDir);
+ if (i == path.length()-1) {
+ de.setStorageClsid(event.getStorageClassId());
+ }
+ }
+ }
+
+ if (event.getName() != null) {
+ de.createDocument(event.getName(), is);
+ }
+ }
+
+ } catch (HPSFException | IOException ex) {
+ // According to the definition of the processPOIFSReaderEvent method we cannot pass checked
+ // exceptions to the caller.
+ throw new HPSFRuntimeException("Could not read file " + event.getPath() + "/" + event.getName(), ex);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hpsf;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Date;
+
+import org.apache.poi.hpsf.CustomProperties;
+import org.apache.poi.hpsf.DocumentSummaryInformation;
+import org.apache.poi.hpsf.PropertySetFactory;
+import org.apache.poi.hpsf.SummaryInformation;
+import org.apache.poi.poifs.filesystem.DirectoryEntry;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+/**
+ * <p>This is a sample application showing how to easily modify properties in
+ * the summary information and in the document summary information. The
+ * application reads the name of a POI filesystem from the command line and
+ * performs the following actions:</p>
+ *
+ * <ul>
+ *
+ * <li><p>Open the POI filesystem.</p></li>
+ *
+ * <li><p>Read the summary information.</p></li>
+ *
+ * <li><p>Read and print the "author" property.</p></li>
+ *
+ * <li><p>Change the author to "Rainer Klute".</p></li>
+ *
+ * <li><p>Read the document summary information.</p></li>
+ *
+ * <li><p>Read and print the "category" property.</p></li>
+ *
+ * <li><p>Change the category to "POI example".</p></li>
+ *
+ * <li><p>Read the custom properties (if available).</p></li>
+ *
+ * <li><p>Insert a new custom property.</p></li>
+ *
+ * <li><p>Write the custom properties back to the document summary
+ * information.</p></li>
+ *
+ * <li><p>Write the summary information to the POI filesystem.</p></li>
+ *
+ * <li><p>Write the document summary information to the POI filesystem.</p></li>
+ *
+ * <li><p>Write the POI filesystem back to the original file.</p></li>
+ *
+ * </ol>
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class ModifyDocumentSummaryInformation {
+
+ private ModifyDocumentSummaryInformation() {}
+
+ /**
+ * <p>Main method - see class description.</p>
+ *
+ * @param args The command-line parameters.
+ */
+ public static void main(final String[] args) throws Exception {
+ /* Read the name of the POI filesystem to modify from the command line.
+ * For brevity to boundary check is performed on the command-line
+ * arguments. */
+ File summaryFile = new File(args[0]);
+
+ /* Open the POI filesystem. */
+ try (POIFSFileSystem poifs = new POIFSFileSystem(summaryFile, false)) {
+
+ /* Read the summary information. */
+ DirectoryEntry dir = poifs.getRoot();
+ SummaryInformation si;
+ try {
+ si = (SummaryInformation) PropertySetFactory.create(
+ dir, SummaryInformation.DEFAULT_STREAM_NAME);
+ } catch (FileNotFoundException ex) {
+ // There is no summary information yet. We have to create a new one
+ si = PropertySetFactory.newSummaryInformation();
+ }
+ assert(si != null);
+
+ /* Change the author to "Rainer Klute". Any former author value will
+ * be lost. If there has been no author yet, it will be created. */
+ si.setAuthor("Rainer Klute");
+ System.out.println("Author changed to " + si.getAuthor() + ".");
+
+
+ /* Handling the document summary information is analogous to handling
+ * the summary information. An additional feature, however, are the
+ * custom properties. */
+
+ /* Read the document summary information. */
+ DocumentSummaryInformation dsi;
+ try {
+ dsi = (DocumentSummaryInformation) PropertySetFactory.create(
+ dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
+ } catch (FileNotFoundException ex) {
+ /* There is no document summary information yet. We have to create a
+ * new one. */
+ dsi = PropertySetFactory.newDocumentSummaryInformation();
+ }
+ assert(dsi != null);
+
+ /* Change the category to "POI example". Any former category value will
+ * be lost. If there has been no category yet, it will be created. */
+ dsi.setCategory("POI example");
+ System.out.println("Category changed to " + dsi.getCategory() + ".");
+
+ /* Read the custom properties. If there are no custom properties yet,
+ * the application has to create a new CustomProperties object. It will
+ * serve as a container for custom properties. */
+ CustomProperties customProperties = dsi.getCustomProperties();
+ if (customProperties == null)
+ customProperties = new CustomProperties();
+
+ /* Insert some custom properties into the container. */
+ customProperties.put("Key 1", "Value 1");
+ customProperties.put("Schl\u00fcssel 2", "Wert 2");
+ customProperties.put("Sample Number", 12345);
+ customProperties.put("Sample Boolean", Boolean.TRUE);
+ customProperties.put("Sample Date", new Date());
+
+ /* Read a custom property. */
+ Object value = customProperties.get("Sample Number");
+ System.out.println("Custom Sample Number is now " + value);
+
+ /* Write the custom properties back to the document summary
+ * information. */
+ dsi.setCustomProperties(customProperties);
+
+ /* Write the summary information and the document summary information
+ * to the POI filesystem. */
+ si.write(dir, SummaryInformation.DEFAULT_STREAM_NAME);
+ dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
+
+ /* Write the POI filesystem back to the original file. Please note that
+ * in production code you should take care when write directly to the
+ * origin, to make sure you don't loose things on error */
+ poifs.writeFilesystem();
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hpsf;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.poi.hpsf.HPSFRuntimeException;
+import org.apache.poi.hpsf.NoPropertySetStreamException;
+import org.apache.poi.hpsf.Property;
+import org.apache.poi.hpsf.PropertySet;
+import org.apache.poi.hpsf.PropertySetFactory;
+import org.apache.poi.hpsf.Section;
+import org.apache.poi.poifs.eventfilesystem.POIFSReader;
+import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
+
+/**
+ * <p>Sample application showing how to read a document's custom property set.
+ * Call it with the document's file name as command-line parameter.</p>
+ *
+ * <p>Explanations can be found in the HPSF HOW-TO.</p>
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class ReadCustomPropertySets {
+
+ private ReadCustomPropertySets() {}
+
+ /**
+ * <p>Runs the example program.</p>
+ *
+ * @param args Command-line arguments (unused).
+ * @throws IOException if any I/O exception occurs.
+ */
+ public static void main(final String[] args) throws IOException {
+ final String filename = args[0];
+ POIFSReader r = new POIFSReader();
+
+ /* Register a listener for *all* documents. */
+ r.registerListener(ReadCustomPropertySets::processPOIFSReaderEvent);
+ r.read(new File(filename));
+ }
+
+
+ public static void processPOIFSReaderEvent(final POIFSReaderEvent event) {
+ final String streamName = event.getPath() + event.getName();
+ PropertySet ps;
+ try {
+ ps = PropertySetFactory.create(event.getStream());
+ } catch (NoPropertySetStreamException ex) {
+ out("No property set stream: \"" + streamName + "\"");
+ return;
+ } catch (Exception ex) {
+ throw new HPSFRuntimeException("Property set stream \"" + streamName + "\": " + ex);
+ }
+
+ /* Print the name of the property set stream: */
+ out("Property set stream \"" + streamName + "\":");
+
+ /* Print the number of sections: */
+ final long sectionCount = ps.getSectionCount();
+ out(" No. of sections: " + sectionCount);
+
+ /* Print the list of sections: */
+ List<Section> sections = ps.getSections();
+ int nr = 0;
+ for (Section sec : sections) {
+ /* Print a single section: */
+ out(" Section " + nr++ + ":");
+ String s = sec.getFormatID().toString();
+ s = s.substring(0, s.length() - 1);
+ out(" Format ID: " + s);
+
+ /* Print the number of properties in this section. */
+ int propertyCount = sec.getPropertyCount();
+ out(" No. of properties: " + propertyCount);
+
+ /* Print the properties: */
+ Property[] properties = sec.getProperties();
+ for (Property p : properties) {
+ /* Print a single property: */
+ long id = p.getID();
+ long type = p.getType();
+ Object value = p.getValue();
+ out(" Property ID: " + id + ", type: " + type +
+ ", value: " + value);
+ }
+ }
+ }
+
+ private static void out(final String msg) {
+ System.out.println(msg);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hpsf;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.poi.hpsf.PropertySetFactory;
+import org.apache.poi.hpsf.SummaryInformation;
+import org.apache.poi.poifs.eventfilesystem.POIFSReader;
+import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
+
+/**
+ * <p>Sample application showing how to read a OLE 2 document's
+ * title. Call it with the document's file name as command line
+ * parameter.</p>
+ *
+ * <p>Explanations can be found in the HPSF HOW-TO.</p>
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class ReadTitle {
+ private ReadTitle() {}
+
+ /**
+ * <p>Runs the example program.</p>
+ *
+ * @param args Command-line arguments. The first command-line argument must
+ * be the name of a POI filesystem to read.
+ * @throws IOException if any I/O exception occurs.
+ */
+ public static void main(final String[] args) throws IOException {
+ final String filename = args[0];
+ POIFSReader r = new POIFSReader();
+ r.registerListener(ReadTitle::processPOIFSReaderEvent, SummaryInformation.DEFAULT_STREAM_NAME);
+ r.read(new File(filename));
+ }
+
+
+ private static void processPOIFSReaderEvent(final POIFSReaderEvent event) {
+ SummaryInformation si;
+ try {
+ si = (SummaryInformation) PropertySetFactory.create(event.getStream());
+ } catch (Exception ex) {
+ throw new RuntimeException("Property set stream \"" + event.getPath() + event.getName() + "\": " + ex);
+ }
+ final String title = si.getTitle();
+ System.out.println(title != null ? "Title: \"" + title + "\"" : "Document has no title.");
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hpsf;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.poi.hpsf.HPSFRuntimeException;
+import org.apache.poi.hpsf.MarkUnsupportedException;
+import org.apache.poi.hpsf.NoPropertySetStreamException;
+import org.apache.poi.hpsf.PropertySet;
+import org.apache.poi.hpsf.PropertySetFactory;
+import org.apache.poi.hpsf.Section;
+import org.apache.poi.hpsf.SummaryInformation;
+import org.apache.poi.hpsf.Variant;
+import org.apache.poi.hpsf.WritingNotSupportedException;
+import org.apache.poi.hpsf.wellknown.PropertyIDMap;
+import org.apache.poi.poifs.eventfilesystem.POIFSReader;
+import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
+import org.apache.poi.poifs.filesystem.DirectoryEntry;
+import org.apache.poi.poifs.filesystem.DocumentInputStream;
+import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+/**
+ * <p>This class is a sample application which shows how to write or modify the
+ * author and title property of an OLE 2 document. This could be done in two
+ * different ways:</p>
+ *
+ * <ul>
+ *
+ * <li><p>The first approach is to open the OLE 2 file as a POI filesystem
+ * (see class {@link POIFSFileSystem}), read the summary information property
+ * set (see classes {@link SummaryInformation} and {@link PropertySet}), write
+ * the author and title properties into it and write the property set back into
+ * the POI filesystem.</p></li>
+ *
+ * <li><p>The second approach does not modify the original POI filesystem, but
+ * instead creates a new one. All documents from the original POIFS are copied
+ * to the destination POIFS, except for the summary information stream. The
+ * latter is modified by setting the author and title property before writing
+ * it to the destination POIFS. It there are several summary information streams
+ * in the original POIFS - e.g. in subordinate directories - they are modified
+ * just the same.</p></li>
+ *
+ * </ul>
+ *
+ * <p>This sample application takes the second approach. It expects the name of
+ * the existing POI filesystem's name as its first command-line parameter and
+ * the name of the output POIFS as the second command-line argument. The
+ * program then works as described above: It copies nearly all documents
+ * unmodified from the input POI filesystem to the output POI filesystem. If it
+ * encounters a summary information stream it reads its properties. Then it sets
+ * the "author" and "title" properties to new values and writes the modified
+ * summary information stream into the output file.</p>
+ *
+ * <p>Further explanations can be found in the HPSF HOW-TO.</p>
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class WriteAuthorAndTitle {
+ private WriteAuthorAndTitle() {}
+
+ /**
+ * <p>Runs the example program.</p>
+ *
+ * @param args Command-line arguments. The first command-line argument must
+ * be the name of a POI filesystem to read.
+ * @throws IOException if any I/O exception occurs.
+ */
+ public static void main(final String[] args) throws IOException {
+ /* Check whether we have exactly two command-line arguments. */
+ if (args.length != 2) {
+ System.err.println("Usage: WriteAuthorAndTitle originPOIFS destinationPOIFS");
+ System.exit(1);
+ }
+
+ /* Read the names of the origin and destination POI filesystems. */
+ final String srcName = args[0];
+ final String dstName = args[1];
+
+ /* Read the origin POIFS using the eventing API. The real work is done
+ * in the class ModifySICopyTheRest which is registered here as a
+ * POIFSReader. */
+ try (POIFSFileSystem poifs = new POIFSFileSystem();
+ OutputStream out = new FileOutputStream(dstName)) {
+ final POIFSReader r = new POIFSReader();
+ r.registerListener(e -> handleEvent(poifs, e));
+ r.read(new File(srcName));
+
+ /* Write the new POIFS to disk. */
+ poifs.writeFilesystem(out);
+ }
+ }
+
+ private interface InputStreamSupplier {
+ InputStream get() throws IOException, WritingNotSupportedException;
+ }
+
+ /**
+ * The method is called by POI's eventing API for each file in the origin POIFS.
+ */
+ private static void handleEvent(final POIFSFileSystem poiFs, final POIFSReaderEvent event) {
+ // The following declarations are shortcuts for accessing the "event" object.
+ final DocumentInputStream stream = event.getStream();
+
+ try {
+ final InputStreamSupplier isSup;
+
+ // Find out whether the current document is a property set stream or not.
+ if (PropertySet.isPropertySetStream(stream)) {
+ // Yes, the current document is a property set stream. Let's create a PropertySet instance from it.
+ PropertySet ps = PropertySetFactory.create(stream);
+
+ // Now we know that we really have a property set.
+ // The next step is to find out whether it is a summary information or not.
+ if (ps.isSummaryInformation()) {
+ // Create a mutable property set as a copy of the original read-only property set.
+ ps = new PropertySet(ps);
+
+ // Retrieve the section containing the properties to modify.
+ // A summary information property set contains exactly one section.
+ final Section s = ps.getSections().get(0);
+
+ // Set the properties.
+ s.setProperty(PropertyIDMap.PID_AUTHOR, Variant.VT_LPSTR, "Rainer Klute");
+ s.setProperty(PropertyIDMap.PID_TITLE, Variant.VT_LPWSTR, "Test");
+ }
+
+ isSup = ps::toInputStream;
+ } else {
+ // No, the current document is not a property set stream. We copy it unmodified to the destination POIFS.
+ isSup = event::getStream;
+ }
+
+ try (InputStream is = isSup.get()) {
+ final POIFSDocumentPath path = event.getPath();
+
+ // Ensures that the directory hierarchy for a document in a POI fileystem is in place.
+ // Get the root directory. It does not have to be created since it always exists in a POIFS.
+ DirectoryEntry de = poiFs.getRoot();
+
+ for (int i=0; i<path.length(); i++) {
+ String subDir = path.getComponent(i);
+ de = (de.hasEntry(subDir)) ? (DirectoryEntry)de.getEntry(subDir) : de.createDirectory(subDir);
+ }
+
+ de.createDocument(event.getName(), is);
+ }
+
+ } catch (MarkUnsupportedException | WritingNotSupportedException | IOException | NoPropertySetStreamException ex) {
+ // According to the definition of the processPOIFSReaderEvent method we cannot pass checked
+ // exceptions to the caller.
+ throw new HPSFRuntimeException("Could not read file " + event.getPath() + "/" + event.getName(), ex);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hpsf;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.hpsf.Property;
+import org.apache.poi.hpsf.PropertySet;
+import org.apache.poi.hpsf.Section;
+import org.apache.poi.hpsf.SummaryInformation;
+import org.apache.poi.hpsf.Variant;
+import org.apache.poi.hpsf.WritingNotSupportedException;
+import org.apache.poi.hpsf.wellknown.PropertyIDMap;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+/**
+ * <p>This class is a simple sample application showing how to create a property
+ * set and write it to disk.</p>
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class WriteTitle {
+
+ private WriteTitle() {}
+
+ /**
+ * <p>Runs the example program.</p>
+ *
+ * @param args Command-line arguments. The first and only command-line
+ * argument is the name of the POI file system to create.
+ * @throws IOException if any I/O exception occurs.
+ * @throws WritingNotSupportedException if HPSF does not (yet) support
+ * writing a certain property type.
+ */
+ public static void main(final String[] args)
+ throws WritingNotSupportedException, IOException
+ {
+ /* Check whether we have exactly one command-line argument. */
+ if (args.length != 1)
+ {
+ System.err.println("Usage: " + WriteTitle.class.getName() + "destinationPOIFS");
+ System.exit(1);
+ }
+
+ final String fileName = args[0];
+
+ /* Create a mutable property set. Initially it contains a single section
+ * with no properties. */
+ final PropertySet mps = new PropertySet();
+
+ /* Retrieve the section the property set already contains. */
+ final Section ms = mps.getSections().get(0);
+
+ /* Turn the property set into a summary information property. This is
+ * done by setting the format ID of its first section to
+ * SectionIDMap.SUMMARY_INFORMATION_ID. */
+ ms.setFormatID(SummaryInformation.FORMAT_ID);
+
+ /* Create an empty property. */
+ final Property p = new Property();
+
+ /* Fill the property with appropriate settings so that it specifies the
+ * document's title. */
+ p.setID(PropertyIDMap.PID_TITLE);
+ p.setType(Variant.VT_LPWSTR);
+ p.setValue("Sample title");
+
+ /* Place the property into the section. */
+ ms.setProperty(p);
+
+ /* Create the POI file system the property set is to be written to.
+ * For writing the property set into a POI file system it has to be
+ * handed over to the POIFS.createDocument() method as an input stream
+ * which produces the bytes making out the property set stream. */
+ try (final POIFSFileSystem poiFs = new POIFSFileSystem();
+ final InputStream is = mps.toInputStream();
+ final FileOutputStream fos = new FileOutputStream(fileName)) {
+
+ /* Create the summary information property set in the POI file
+ * system. It is given the default name most (if not all) summary
+ * information property sets have. */
+ poiFs.createDocument(is, SummaryInformation.DEFAULT_STREAM_NAME);
+
+ /* Write the whole POI file system to a disk file. */
+ poiFs.writeFilesystem(fos);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.sl.draw.DrawTableShape;
+import org.apache.poi.sl.draw.SLGraphics;
+import org.apache.poi.sl.usermodel.AutoShape;
+import org.apache.poi.sl.usermodel.GroupShape;
+import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.TableCell;
+import org.apache.poi.sl.usermodel.TableShape;
+import org.apache.poi.sl.usermodel.TextBox;
+import org.apache.poi.sl.usermodel.TextParagraph;
+import org.apache.poi.sl.usermodel.TextRun;
+import org.apache.poi.sl.usermodel.TextShape.TextPlaceholder;
+import org.apache.poi.sl.usermodel.VerticalAlignment;
+
+/**
+ * Presentation for Fast Feather Track on ApacheconEU 2008
+ *
+ * @author Yegor Kozlov
+ */
+@SuppressWarnings("java:S1192")
+public final class ApacheconEU08 {
+
+ private ApacheconEU08() {}
+
+ public static void main(String[] args) throws IOException {
+ // use HSLFSlideShow or XMLSlideShow
+ try (SlideShow<?,?> ppt = new HSLFSlideShow()) {
+ ppt.setPageSize(new Dimension(720, 540));
+
+ slide1(ppt);
+ slide2(ppt);
+ slide3(ppt);
+ slide4(ppt);
+ slide5(ppt);
+ slide6(ppt);
+ slide7(ppt);
+ slide8(ppt);
+ slide9(ppt);
+ slide10(ppt);
+ slide11(ppt);
+ slide12(ppt);
+
+ String ext = ppt.getClass().getName().contains("HSLF") ? "ppt" : "pptx";
+ try (FileOutputStream out = new FileOutputStream("apachecon_eu_08." + ext)) {
+ ppt.write(out);
+ }
+ }
+ }
+
+ public static void slide1(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.CENTER_TITLE);
+ box1.setText("POI-HSLF");
+ box1.setAnchor(new Rectangle(54, 78, 612, 115));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.CENTER_BODY);
+ box2.setText("Java API To Access Microsoft PowerPoint Format Files");
+ box2.setAnchor(new Rectangle(108, 204, 504, 138));
+
+ TextBox<?,?> box3 = slide.createTextBox();
+ box3.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(32d);
+ box3.setText(
+ "Yegor Kozlov\r" +
+ "yegor - apache - org");
+ box3.setHorizontalCentered(true);
+ box3.setAnchor(new Rectangle(206, 348, 310, 84));
+ }
+
+ public static void slide2(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
+ box1.setText("What is HSLF?");
+ box1.setAnchor(new Rectangle(36, 21, 648, 90));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
+ box2.setText("HorribleSLideshowFormat is the POI Project's pure Java implementation " +
+ "of the Powerpoint binary file format. \r" +
+ "POI sub-project since 2005\r" +
+ "Started by Nick Burch, Yegor Kozlov joined soon after");
+ box2.setAnchor(new Rectangle(36, 126, 648, 356));
+ }
+
+ public static void slide3(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
+ box1.setText("HSLF in a Nutshell");
+ box1.setAnchor(new Rectangle(36, 15, 648, 65));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
+ box2.setText(
+ "HSLF provides a way to read, create and modify MS PowerPoint presentations\r" +
+ "Pure Java API - you don't need PowerPoint to read and write *.ppt files\r" +
+ "Comprehensive support of PowerPoint objects\r" +
+ "Rich text\r" +
+ "Tables\r" +
+ "Shapes\r" +
+ "Pictures\r" +
+ "Master slides\r" +
+ "Access to low level data structures"
+ );
+
+ List<? extends TextParagraph<?,?,?>> tp = box2.getTextParagraphs();
+ for (int i : new byte[]{0,1,2,8}) {
+ tp.get(i).getTextRuns().get(0).setFontSize(28d);
+ }
+ for (int i : new byte[]{3,4,5,6,7}) {
+ tp.get(i).getTextRuns().get(0).setFontSize(24d);
+ tp.get(i).setIndentLevel(1);
+ }
+ box2.setAnchor(new Rectangle(36, 80, 648, 400));
+ }
+
+ public static void slide4(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ String[][] txt1 = {
+ {"Note"},
+ {"This presentation was created programmatically using POI HSLF"}
+ };
+ TableShape<?,?> table1 = slide.createTable(2, 1);
+ for (int i = 0; i < txt1.length; i++) {
+ for (int j = 0; j < txt1[i].length; j++) {
+ TableCell<?,?> cell = table1.getCell(i, j);
+ cell.setText(txt1[i][j]);
+ TextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
+ rt.setFontSize(10d);
+ rt.setFontFamily("Arial");
+ rt.setBold(true);
+ if(i == 0){
+ rt.setFontSize(32d);
+ rt.setFontColor(Color.white);
+ cell.setFillColor(new Color(0, 153, 204));
+ } else {
+ rt.setFontSize(28d);
+ cell.setFillColor(new Color(235, 239, 241));
+ }
+ cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
+ }
+ }
+
+ DrawTableShape dts = new DrawTableShape(table1);
+ dts.setAllBorders(1.0, Color.black);
+ dts.setOutsideBorders(4.0);
+
+ table1.setColumnWidth(0, 450);
+ table1.setRowHeight(0, 50);
+ table1.setRowHeight(1, 80);
+
+ Dimension dim = ppt.getPageSize();
+ Rectangle2D oldAnchor = table1.getAnchor();
+ table1.setAnchor(new Rectangle2D.Double((dim.width-450)/2d, 100, oldAnchor.getWidth(), oldAnchor.getHeight()));
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setHorizontalCentered(true);
+ box1.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(24d);
+ box1.setText("The source code is available at\r" +
+ "http://people.apache.org/~yegor/apachecon_eu08/");
+ box1.setAnchor(new Rectangle(80, 356, 553, 65));
+ }
+
+ public static void slide5(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
+ box1.setText("HSLF in Action - 1\rData Extraction");
+ box1.setAnchor(new Rectangle(36, 21, 648, 100));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
+ box2.setText(
+ "Text from slides and notes\r" +
+ "Images\r" +
+ "Shapes and their properties (type, position in the slide, color, font, etc.)");
+ box2.setAnchor(new Rectangle(36, 150, 648, 300));
+ }
+
+ public static void slide6(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
+ box1.setText("HSLF in Action - 2");
+ box1.setAnchor(new Rectangle(36, 20, 648, 90));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18d);
+ box2.setText("Creating a simple presentation from scratch");
+ box2.setAnchor(new Rectangle(170, 100, 364, 30));
+
+ TextBox<?,?> box3 = slide.createTextBox();
+ TextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
+ rt3.setFontFamily("Courier New");
+ rt3.setFontSize(8d);
+ box3.setText(
+ "SlideShow ppt = new SlideShow();\u000b" +
+ "Slide slide = ppt.createSlide();\u000b" +
+ "\u000b" +
+ "TextBox box2 = new TextBox();\u000b" +
+ "box2.setHorizontalAlignment(TextBox.AlignCenter);\u000b" +
+ "box2.setVerticalAlignment(TextBox.AnchorMiddle);\u000b" +
+ "box2.getTextRun().setText(\"Java Code\");\u000b" +
+ "box2.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
+ "box2.setLineColor(Color.black);\u000b" +
+ "box2.setLineWidth(0.75);\u000b" +
+ "box2.setAnchor(new Rectangle(66, 243, 170, 170));\u000b" +
+ "slide.addShape(box2);\u000b" +
+ "\u000b" +
+ "TextBox box3 = new TextBox();\u000b" +
+ "box3.setHorizontalAlignment(TextBox.AlignCenter);\u000b" +
+ "box3.setVerticalAlignment(TextBox.AnchorMiddle);\u000b" +
+ "box3.getTextRun().setText(\"*.ppt file\");\u000b" +
+ "box3.setLineWidth(0.75);\u000b" +
+ "box3.setLineColor(Color.black);\u000b" +
+ "box3.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
+ "box3.setAnchor(new Rectangle(473, 243, 170, 170));\u000b" +
+ "slide.addShape(box3);\u000b" +
+ "\u000b" +
+ "AutoShape box4 = new AutoShape(ShapeTypes.Arrow);\u000b" +
+ "box4.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
+ "box4.setLineWidth(0.75);\u000b" +
+ "box4.setLineColor(Color.black);\u000b" +
+ "box4.setAnchor(new Rectangle(253, 288, 198, 85));\u000b" +
+ "slide.addShape(box4);\u000b" +
+ "\u000b" +
+ "FileOutputStream out = new FileOutputStream(\"hslf-demo.ppt\");\u000b" +
+ "ppt.write(out);\u000b" +
+ "out.close();");
+ box3.setAnchor(new Rectangle(30, 150, 618, 411));
+ box3.setHorizontalCentered(true);
+ }
+
+ public static void slide7(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setHorizontalCentered(true);
+ box2.setVerticalAlignment(VerticalAlignment.MIDDLE);
+ box2.setText("Java Code");
+ box2.setFillColor(new Color(187, 224, 227));
+ box2.setStrokeStyle(0.75, Color.black);
+ box2.setAnchor(new Rectangle(66, 243, 170, 170));
+
+ TextBox<?,?> box3 = slide.createTextBox();
+ box3.setHorizontalCentered(true);
+ box3.setVerticalAlignment(VerticalAlignment.MIDDLE);
+ box3.setText("*.ppt file");
+ box3.setFillColor(new Color(187, 224, 227));
+ box3.setStrokeStyle(0.75, Color.black);
+ box3.setAnchor(new Rectangle(473, 243, 170, 170));
+
+ AutoShape<?,?> box4 = slide.createAutoShape();
+ box4.setShapeType(ShapeType.RIGHT_ARROW);
+ box4.setFillColor(new Color(187, 224, 227));
+ box4.setStrokeStyle(0.75, Color.black);
+ box4.setAnchor(new Rectangle(253, 288, 198, 85));
+ }
+
+ public static void slide8(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
+ box1.setText("Wait, there is more!");
+ box1.setAnchor(new Rectangle(36, 21, 648, 90));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
+ box2.setText(
+ "Rich text\r" +
+ "Tables\r" +
+ "Pictures (JPEG, PNG, BMP, WMF, PICT)\r" +
+ "Comprehensive formatting features");
+ box2.setAnchor(new Rectangle(36, 126, 648, 356));
+ }
+
+ public static void slide9(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
+ box1.setText("HSLF in Action - 3");
+ box1.setAnchor(new Rectangle(36, 20, 648, 50));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18d);
+ box2.setText("PPGraphics2D: PowerPoint Graphics2D driver");
+ box2.setAnchor(new Rectangle(178, 70, 387, 30));
+
+ TextBox<?,?> box3 = slide.createTextBox();
+ TextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
+ rt3.setFontFamily("Courier New");
+ rt3.setFontSize(8d);
+ box3.setText(
+ "//bar chart data. The first value is the bar color, the second is the width\u000b" +
+ "Object[] def = new Object[]{\u000b" +
+ " Color.yellow, new Integer(100),\u000b" +
+ " Color.green, new Integer(150),\u000b" +
+ " Color.gray, new Integer(75),\u000b" +
+ " Color.red, new Integer(200),\u000b" +
+ "};\u000b" +
+ "\u000b" +
+ "SlideShow ppt = new SlideShow();\u000b" +
+ "Slide slide = ppt.createSlide();\u000b" +
+ "\u000b" +
+ "ShapeGroup group = new ShapeGroup();\u000b" +
+ "//define position of the drawing in the slide\u000b" +
+ "Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);\u000b" +
+ "group.setAnchor(bounds);\u000b" +
+ "slide.addShape(group);\u000b" +
+ "Graphics2D graphics = new PPGraphics2D(group);\u000b" +
+ "\u000b" +
+ "//draw a simple bar graph\u000b" +
+ "int x = bounds.x + 50, y = bounds.y + 50;\u000b" +
+ "graphics.setFont(new Font(\"Arial\", Font.BOLD, 10));\u000b" +
+ "for (int i = 0, idx = 1; i < def.length; i+=2, idx++) {\u000b" +
+ " graphics.setColor(Color.black);\u000b" +
+ " int width = ((Integer)def[i+1]).intValue();\u000b" +
+ " graphics.drawString(\"Q\" + idx, x-20, y+20);\u000b" +
+ " graphics.drawString(width + \"%\", x + width + 10, y + 20);\u000b" +
+ " graphics.setColor((Color)def[i]);\u000b" +
+ " graphics.fill(new Rectangle(x, y, width, 30));\u000b" +
+ " y += 40;\u000b" +
+ "}\u000b" +
+ "graphics.setColor(Color.black);\u000b" +
+ "graphics.setFont(new Font(\"Arial\", Font.BOLD, 14));\u000b" +
+ "graphics.draw(bounds);\u000b" +
+ "graphics.drawString(\"Performance\", x + 70, y + 40);\u000b" +
+ "\u000b" +
+ "FileOutputStream out = new FileOutputStream(\"hslf-demo.ppt\");\u000b" +
+ "ppt.write(out);\u000b" +
+ "out.close();");
+ box3.setAnchor(new Rectangle(96, 110, 499, 378));
+ box3.setHorizontalCentered(true);
+ }
+
+ public static void slide10(SlideShow<?,?> ppt) throws IOException {
+ //bar chart data. The first value is the bar color, the second is the width
+ Object[] def = new Object[]{
+ Color.yellow, 100,
+ Color.green, 150,
+ Color.gray, 75,
+ Color.red, 200,
+ };
+
+ Slide<?,?> slide = ppt.createSlide();
+
+ GroupShape<?,?> group = slide.createGroup();
+ //define position of the drawing in the slide
+ Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);
+ group.setAnchor(bounds);
+ Graphics2D graphics = new SLGraphics(group);
+
+ //draw a simple bar graph
+ int x = bounds.x + 50;
+ int y = bounds.y + 50;
+ graphics.setFont(new Font("Arial", Font.BOLD, 10));
+ for (int i = 0, idx = 1; i < def.length; i+=2, idx++) {
+ graphics.setColor(Color.black);
+ int width = (Integer) def[i + 1];
+ graphics.drawString("Q" + idx, x-20, y+20);
+ graphics.drawString(width + "%", x + width + 10, y + 20);
+ graphics.setColor((Color)def[i]);
+ graphics.fill(new Rectangle(x, y, width, 30));
+ y += 40;
+ }
+ graphics.setColor(Color.black);
+ graphics.setFont(new Font("Arial", Font.BOLD, 14));
+ graphics.draw(bounds);
+ graphics.drawString("Performance", x + 70, y + 40);
+
+ }
+
+ public static void slide11(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
+ box1.setText("HSLF Development Plans");
+ box1.setAnchor(new Rectangle(36, 21, 648, 90));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
+ box2.setText(
+ "Support for more PowerPoint functionality\r" +
+ "Rendering slides into java.awt.Graphics2D\r" +
+ "A way to export slides into images or other formats\r" +
+ "Integration with Apache FOP - Formatting Objects Processor\r" +
+ "Transformation of XSL-FO into PPT\r" +
+ "PPT2PDF transcoder"
+ );
+
+ List<? extends TextParagraph<?,?,?>> tp = box2.getTextParagraphs();
+ for (int i : new byte[]{0,1,3}) {
+ tp.get(i).getTextRuns().get(0).setFontSize(28d);
+ }
+ for (int i : new byte[]{2,4,5}) {
+ tp.get(i).getTextRuns().get(0).setFontSize(24d);
+ tp.get(i).setIndentLevel(1);
+ }
+
+ box2.setAnchor(new Rectangle(36, 126, 648, 400));
+ }
+
+ public static void slide12(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
+
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.CENTER_TITLE);
+ box1.setText("Questions?");
+ box1.setAnchor(new Rectangle(54, 167, 612, 115));
+
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.CENTER_BODY);
+ box2.setText(
+ "https://poi.apache.org/hslf/\r" +
+ "http://people.apache.org/~yegor");
+ box2.setAnchor(new Rectangle(108, 306, 504, 138));
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFTextBox;
+import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
+
+/**
+ * How to create a single-level bulleted list
+ * and change some of the bullet attributes
+ */
+public final class BulletsDemo {
+
+ public static void main(String[] args) throws IOException {
+ try (HSLFSlideShow ppt = new HSLFSlideShow()) {
+ HSLFSlide slide = ppt.createSlide();
+
+ HSLFTextBox shape = new HSLFTextBox();
+ HSLFTextParagraph rt = shape.getTextParagraphs().get(0);
+ rt.getTextRuns().get(0).setFontSize(42d);
+ rt.setBullet(true);
+ rt.setIndent(0d); //bullet offset
+ rt.setLeftMargin(50d); //text offset (should be greater than bullet offset)
+ rt.setBulletChar('\u263A'); //bullet character
+ shape.setText(
+ "January\r" +
+ "February\r" +
+ "March\r" +
+ "April");
+ slide.addShape(shape);
+
+ shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); //position of the text box in the slide
+ slide.addShape(shape);
+
+ try (FileOutputStream out = new FileOutputStream("bullets.ppt")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+
+import java.awt.Rectangle;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hslf.usermodel.HSLFHyperlink;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFTextBox;
+
+/**
+ * Demonstrates how to create hyperlinks in PowerPoint presentations
+ */
+public final class CreateHyperlink {
+
+ private CreateHyperlink() {}
+
+ public static void main(String[] args) throws IOException {
+ try (HSLFSlideShow ppt = new HSLFSlideShow()) {
+ HSLFSlide slideA = ppt.createSlide();
+ ppt.createSlide();
+ HSLFSlide slideC = ppt.createSlide();
+
+ // link to a URL
+ HSLFTextBox textBox1 = slideA.createTextBox();
+ textBox1.setText("Apache POI");
+ textBox1.setAnchor(new Rectangle(100, 100, 200, 50));
+
+ HSLFHyperlink link1 = textBox1.getTextParagraphs().get(0).getTextRuns().get(0).createHyperlink();
+ link1.linkToUrl("http://www.apache.org");
+ link1.setLabel(textBox1.getText());
+
+ // link to another slide
+ HSLFTextBox textBox2 = slideA.createTextBox();
+ textBox2.setText("Go to slide #3");
+ textBox2.setAnchor(new Rectangle(100, 300, 200, 50));
+
+ HSLFHyperlink link2 = textBox2.getTextParagraphs().get(0).getTextRuns().get(0).createHyperlink();
+ link2.linkToSlide(slideC);
+
+ try (FileOutputStream out = new FileOutputStream("hyperlink.ppt")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.hslf.usermodel.HSLFObjectData;
+import org.apache.poi.hslf.usermodel.HSLFObjectShape;
+import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSoundData;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.usermodel.Paragraph;
+import org.apache.poi.hwpf.usermodel.Range;
+import org.apache.poi.util.IOUtils;
+
+/**
+ * Demonstrates how you can extract misc embedded data from a ppt file
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class DataExtraction {
+
+ private DataExtraction() {}
+
+ public static void main(String[] args) throws Exception {
+
+ if (args.length == 0) {
+ usage();
+ return;
+ }
+
+ try (FileInputStream fis = new FileInputStream(args[0]);
+ HSLFSlideShow ppt = new HSLFSlideShow(fis)) {
+
+ //extract all sound files embedded in this presentation
+ HSLFSoundData[] sound = ppt.getSoundData();
+ for (HSLFSoundData aSound : sound) {
+ handleSound(aSound);
+ }
+
+ int oleIdx = -1;
+ int picIdx = -1;
+ for (HSLFSlide slide : ppt.getSlides()) {
+ //extract embedded OLE documents
+ for (HSLFShape shape : slide.getShapes()) {
+ if (shape instanceof HSLFObjectShape) {
+ handleShape((HSLFObjectShape) shape, ++oleIdx);
+ } else if (shape instanceof HSLFPictureShape) {
+ handlePicture((HSLFPictureShape) shape, ++picIdx);
+ }
+ }
+ }
+ }
+ }
+
+ private static void handleShape(HSLFObjectShape ole, int oleIdx) throws IOException {
+ HSLFObjectData data = ole.getObjectData();
+ String name = ole.getInstanceName();
+ switch (name == null ? "" : name) {
+ case "Worksheet":
+ //read xls
+ handleWorkbook(data, name, oleIdx);
+ break;
+ case "Document":
+ //read the word document
+ handleDocument(data, name, oleIdx);
+ break;
+ default:
+ handleUnknown(data, ole.getProgId(), oleIdx);
+ break;
+ }
+
+ }
+
+ private static void handleWorkbook(HSLFObjectData data, String name, int oleIdx) throws IOException {
+ try (InputStream is = data.getInputStream();
+ HSSFWorkbook wb = new HSSFWorkbook(is);
+ FileOutputStream out = new FileOutputStream(name + "-(" + (oleIdx) + ").xls")) {
+ wb.write(out);
+ }
+ }
+
+ private static void handleDocument(HSLFObjectData data, String name, int oleIdx) throws IOException {
+ try (InputStream is = data.getInputStream();
+ HWPFDocument doc = new HWPFDocument(is);
+ FileOutputStream out = new FileOutputStream(name + "-(" + (oleIdx) + ").doc")) {
+ Range r = doc.getRange();
+ for (int k = 0; k < r.numParagraphs(); k++) {
+ Paragraph p = r.getParagraph(k);
+ System.out.println(p.text());
+ }
+
+ //save on disk
+ doc.write(out);
+ }
+ }
+
+ private static void handleUnknown(HSLFObjectData data, String name, int oleIdx) throws IOException {
+ try (InputStream is = data.getInputStream();
+ FileOutputStream out = new FileOutputStream(name + "-" + (oleIdx + 1) + ".dat")) {
+ IOUtils.copy(is, out);
+ }
+ }
+
+ private static void handlePicture(HSLFPictureShape p, int picIdx) throws IOException {
+ HSLFPictureData data = p.getPictureData();
+ String ext = data.getType().extension;
+ try (FileOutputStream out = new FileOutputStream("pict-" + picIdx + ext)) {
+ out.write(data.getData());
+ }
+ }
+
+ private static void handleSound(HSLFSoundData aSound) throws IOException {
+ String type = aSound.getSoundType(); //*.wav
+ String name = aSound.getSoundName(); //typically file name
+
+ //save the sound on disk
+ try (FileOutputStream out = new FileOutputStream(name + type)) {
+ out.write(aSound.getData());
+ }
+ }
+
+ private static void usage(){
+ System.out.println("Usage: DataExtraction ppt");
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.io.FileOutputStream;
+
+import org.apache.poi.hslf.usermodel.HSLFGroupShape;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.sl.draw.SLGraphics;
+
+/**
+ * Demonstrates how to draw into a slide using the HSLF Graphics2D driver.
+ */
+public final class Graphics2DDemo {
+
+ private Graphics2DDemo() {}
+
+ /**
+ * A simple bar chart demo
+ */
+ public static void main(String[] args) throws Exception {
+ try (HSLFSlideShow ppt = new HSLFSlideShow();
+ FileOutputStream out = new FileOutputStream("hslf-graphics.ppt")) {
+ //bar chart data. The first value is the bar color, the second is the width
+ Object[] def = {
+ Color.yellow, 40,
+ Color.green, 60,
+ Color.gray, 30,
+ Color.red, 80,
+ };
+
+ HSLFSlide slide = ppt.createSlide();
+
+ HSLFGroupShape group = new HSLFGroupShape();
+ //define position of the drawing in the slide
+ Rectangle bounds = new Rectangle(200, 100, 350, 300);
+ group.setAnchor(bounds);
+ group.setInteriorAnchor(new Rectangle(0, 0, 100, 100));
+ slide.addShape(group);
+ Graphics2D graphics = new SLGraphics(group);
+
+ //draw a simple bar graph
+ int x = 10, y = 10;
+ graphics.setFont(new Font("Arial", Font.BOLD, 10));
+ for (int i = 0, idx = 1; i < def.length; i += 2, idx++) {
+ graphics.setColor(Color.black);
+ int width = (Integer) def[i + 1];
+ graphics.drawString("Q" + idx, x - 5, y + 10);
+ graphics.drawString(width + "%", x + width + 3, y + 10);
+ graphics.setColor((Color) def[i]);
+ graphics.fill(new Rectangle(x, y, width, 10));
+ y += 15;
+ }
+ graphics.setColor(Color.black);
+ graphics.setFont(new Font("Arial", Font.BOLD, 14));
+ graphics.draw(group.getInteriorAnchor());
+ graphics.drawString("Performance", x + 30, y + 10);
+
+ ppt.write(out);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hslf.model.HeadersFooters;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+
+/**
+ * Demonstrates how to set headers / footers
+ */
+public final class HeadersFootersDemo {
+ private HeadersFootersDemo() {}
+
+ public static void main(String[] args) throws IOException {
+ try (HSLFSlideShow ppt = new HSLFSlideShow()) {
+ HeadersFooters slideHeaders = ppt.getSlideHeadersFooters();
+ slideHeaders.setFootersText("Created by POI-HSLF");
+ slideHeaders.setSlideNumberVisible(true);
+ slideHeaders.setDateTimeText("custom date time");
+
+ HeadersFooters notesHeaders = ppt.getNotesHeadersFooters();
+ notesHeaders.setFootersText("My notes footers");
+ notesHeaders.setHeaderText("My notes header");
+
+ ppt.createSlide();
+
+ try (FileOutputStream out = new FileOutputStream("headers_footers.ppt")) {
+ ppt.write(out);
+ }
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+
+import java.io.FileInputStream;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.poi.hslf.usermodel.HSLFHyperlink;
+import org.apache.poi.hslf.usermodel.HSLFSimpleShape;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
+import org.apache.poi.hslf.usermodel.HSLFTextRun;
+
+/**
+ * Demonstrates how to read hyperlinks from a presentation
+ */
+@SuppressWarnings({"java:S106", "java:S4823"})
+public final class Hyperlinks {
+
+ private Hyperlinks() {}
+
+ public static void main(String[] args) throws Exception {
+ for (String arg : args) {
+ try (FileInputStream is = new FileInputStream(arg);
+ HSLFSlideShow ppt = new HSLFSlideShow(is)) {
+
+ for (HSLFSlide slide : ppt.getSlides()) {
+ System.out.println("\nslide " + slide.getSlideNumber());
+
+ // read hyperlinks from the slide's text runs
+ System.out.println("- reading hyperlinks from the text runs");
+ slide.getTextParagraphs().stream().
+ flatMap(List::stream).
+ map(HSLFTextParagraph::getTextRuns).
+ flatMap(List::stream).
+ forEach(run -> out(run.getHyperlink(), run));
+
+ // in PowerPoint you can assign a hyperlink to a shape without text,
+ // for example to a Line object. The code below demonstrates how to
+ // read such hyperlinks
+ System.out.println("- reading hyperlinks from the slide's shapes");
+ slide.getShapes().stream().
+ filter(sh -> sh instanceof HSLFSimpleShape).
+ forEach(sh -> out(((HSLFSimpleShape) sh).getHyperlink(), null));
+ }
+ }
+ }
+ }
+
+ private static void out(HSLFHyperlink link, HSLFTextRun run) {
+ if (link == null) {
+ return;
+ }
+ String rawText = run == null ? null : run.getRawText();
+ //in ppt end index is inclusive
+ String formatStr = "title: %1$s, address: %2$s" + (rawText == null ? "" : ", start: %3$s, end: %4$s, substring: %5$s");
+ String line = String.format(Locale.ROOT, formatStr, link.getLabel(), link.getAddress(), link.getStartIndex(), link.getEndIndex(), rawText);
+ System.out.println(line);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import org.apache.poi.hslf.record.InteractiveInfoAtom;
+import org.apache.poi.hslf.record.RecordTypes;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSoundData;
+
+/**
+ * For each slide iterate over shapes and found associated sound data.
+ */
+@SuppressWarnings({"java:S106", "java:S4823"})
+public final class SoundFinder {
+ private SoundFinder() {}
+
+ public static void main(String[] args) throws IOException {
+ try (FileInputStream fis = new FileInputStream(args[0])) {
+ try (HSLFSlideShow ppt = new HSLFSlideShow(fis)) {
+ HSLFSoundData[] sounds = ppt.getSoundData();
+
+ for (HSLFSlide slide : ppt.getSlides()) {
+ for (HSLFShape shape : slide.getShapes()) {
+ int soundRef = getSoundReference(shape);
+ if (soundRef == -1) continue;
+
+
+ System.out.println("Slide[" + slide.getSlideNumber() + "], shape[" + shape.getShapeId() + "], soundRef: " + soundRef);
+ System.out.println(" " + sounds[soundRef].getSoundName());
+ System.out.println(" " + sounds[soundRef].getSoundType());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Check if a given shape is associated with a sound.
+ * @return 0-based reference to a sound in the sound collection
+ * or -1 if the shape is not associated with a sound
+ */
+ private static int getSoundReference(HSLFShape shape){
+ int soundRef = -1;
+ //dive into the shape container and search for InteractiveInfoAtom
+ InteractiveInfoAtom info = shape.getClientDataRecord(RecordTypes.InteractiveInfo.typeID);
+ if (info != null && info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) {
+ soundRef = info.getSoundRef();
+ }
+ return soundRef;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hslf;
+
+import java.awt.Color;
+import java.io.FileOutputStream;
+
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFTable;
+import org.apache.poi.hslf.usermodel.HSLFTableCell;
+import org.apache.poi.hslf.usermodel.HSLFTextRun;
+import org.apache.poi.sl.draw.DrawTableShape;
+import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
+import org.apache.poi.sl.usermodel.VerticalAlignment;
+
+/**
+ * Demonstrates how to create tables
+ */
+public final class TableDemo {
+
+ //test data for the first table
+ static final String[][] txt1 = {
+ {"INPUT FILE", "NUMBER OF RECORDS"},
+ {"Item File", "11,559"},
+ {"Vendor File", "502"},
+ {"Purchase History File - # of PO\u2019s\r(12/01/04 - 05/31/06)", "12,852"},
+ {"Purchase History File - # of PO Lines\r(12/01/04 - 05/31/06)", "53,523" },
+ {"Total PO History Spend", "$10,172,038"}
+ };
+
+ //test data for the second taable
+ static final String[][] txt2 = {
+ {"Data Source"},
+ {"CAS Internal Metrics - Item Master Summary\r" +
+ "CAS Internal Metrics - Vendor Summary\r" +
+ "CAS Internal Metrics - PO History Summary"}
+ };
+
+
+ public static void main(String[] args) throws Exception {
+ try (HSLFSlideShow ppt = new HSLFSlideShow()) {
+ HSLFSlide slide = ppt.createSlide();
+ create1stTable(slide);
+ create2ndTable(slide);
+
+ try (FileOutputStream out = new FileOutputStream("hslf-table.ppt")) {
+ ppt.write(out);
+ }
+ }
+ }
+
+ static void create1stTable(HSLFSlide slide) {
+ //six rows, two columns
+ HSLFTable table1 = slide.createTable(6, 2);
+ for (int i = 0; i < txt1.length; i++) {
+ for (int j = 0; j < txt1[i].length; j++) {
+ HSLFTableCell cell = table1.getCell(i, j);
+ HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
+ rt.setFontFamily("Arial");
+ rt.setFontSize(10d);
+ if(i == 0){
+ cell.getFill().setForegroundColor(new Color(227, 227, 227));
+ } else {
+ rt.setBold(true);
+ }
+ cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
+ cell.setHorizontalCentered(true);
+ cell.setText(txt1[i][j]);
+ }
+ }
+
+ DrawTableShape dts1 = new DrawTableShape(table1);
+ dts1.setAllBorders(1.0, Color.black);
+
+ table1.setColumnWidth(0, 300);
+ table1.setColumnWidth(1, 150);
+
+ int pgWidth = slide.getSlideShow().getPageSize().width;
+ table1.moveTo((pgWidth - table1.getAnchor().getWidth())/2., 100.);
+ }
+
+ static void create2ndTable(HSLFSlide slide) {
+ //two rows, one column
+ HSLFTable table2 = slide.createTable(2, 1);
+ for (int i = 0; i < txt2.length; i++) {
+ for (int j = 0; j < txt2[i].length; j++) {
+ HSLFTableCell cell = table2.getCell(i, j);
+ HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
+ rt.setFontSize(10d);
+ rt.setFontFamily("Arial");
+ if(i == 0){
+ cell.getFill().setForegroundColor(new Color(0, 51, 102));
+ rt.setFontColor(Color.white);
+ rt.setBold(true);
+ rt.setFontSize(14d);
+ cell.setHorizontalCentered(true);
+ } else {
+ rt.getTextParagraph().setBullet(true);
+ rt.setFontSize(12d);
+ rt.getTextParagraph().setTextAlign(TextAlign.LEFT);
+ cell.setHorizontalCentered(false);
+ }
+ cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
+ cell.setText(txt2[i][j]);
+ }
+ }
+ table2.setColumnWidth(0, 300);
+ table2.setRowHeight(0, 30);
+ table2.setRowHeight(1, 70);
+
+ DrawTableShape dts2 = new DrawTableShape(table2);
+ dts2.setOutsideBorders(Color.black, 1.0);
+
+ table2.moveTo(200, 400);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hsmf;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import org.apache.poi.hsmf.MAPIMessage;
+import org.apache.poi.hsmf.datatypes.AttachmentChunks;
+import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
+
+/**
+ * Reads one or several Outlook MSG files and for each of them creates
+ * a text file from available chunks and a directory that contains
+ * attachments.
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public class Msg2txt {
+
+ /**
+ * The stem used to create file names for the text file and the directory
+ * that contains the attachments.
+ */
+ private String fileNameStem;
+
+ /**
+ * The Outlook MSG file being processed.
+ */
+ private MAPIMessage msg;
+
+ public Msg2txt(String fileName) throws IOException {
+ fileNameStem = fileName;
+ if(fileNameStem.endsWith(".msg") || fileNameStem.endsWith(".MSG")) {
+ fileNameStem = fileNameStem.substring(0, fileNameStem.length() - 4);
+ }
+ msg = new MAPIMessage(fileName);
+ }
+
+ /**
+ * Processes the message.
+ *
+ * @throws IOException if an exception occurs while writing the message out
+ */
+ public void processMessage() throws IOException {
+ String txtFileName = fileNameStem + ".txt";
+ String attDirName = fileNameStem + "-att";
+ try (PrintWriter txtOut = new PrintWriter(txtFileName)) {
+ try {
+ String displayFrom = msg.getDisplayFrom();
+ txtOut.println("From: " + displayFrom);
+ } catch (ChunkNotFoundException e) {
+ // ignore
+ }
+ try {
+ String displayTo = msg.getDisplayTo();
+ txtOut.println("To: " + displayTo);
+ } catch (ChunkNotFoundException e) {
+ // ignore
+ }
+ try {
+ String displayCC = msg.getDisplayCC();
+ txtOut.println("CC: " + displayCC);
+ } catch (ChunkNotFoundException e) {
+ // ignore
+ }
+ try {
+ String displayBCC = msg.getDisplayBCC();
+ txtOut.println("BCC: " + displayBCC);
+ } catch (ChunkNotFoundException e) {
+ // ignore
+ }
+ try {
+ String subject = msg.getSubject();
+ txtOut.println("Subject: " + subject);
+ } catch (ChunkNotFoundException e) {
+ // ignore
+ }
+ try {
+ String body = msg.getTextBody();
+ txtOut.println(body);
+ } catch (ChunkNotFoundException e) {
+ System.err.println("No message body");
+ }
+
+ AttachmentChunks[] attachments = msg.getAttachmentFiles();
+ if (attachments.length > 0) {
+ File d = new File(attDirName);
+ if (d.mkdir()) {
+ for (AttachmentChunks attachment : attachments) {
+ processAttachment(attachment, d);
+ }
+ } else {
+ System.err.println("Can't create directory " + attDirName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes a single attachment: reads it from the Outlook MSG file and
+ * writes it to disk as an individual file.
+ *
+ * @param attachment the chunk group describing the attachment
+ * @param dir the directory in which to write the attachment file
+ * @throws IOException when any of the file operations fails
+ */
+ public void processAttachment(AttachmentChunks attachment,
+ File dir) throws IOException {
+ String fileName = attachment.getAttachFileName().toString();
+ if(attachment.getAttachLongFileName() != null) {
+ fileName = attachment.getAttachLongFileName().toString();
+ }
+
+ File f = new File(dir, fileName);
+ try (OutputStream fileOut = new FileOutputStream(f)) {
+ fileOut.write(attachment.getAttachData().getValue());
+ }
+ }
+
+ /**
+ * Processes the list of arguments as a list of names of Outlook MSG files.
+ *
+ * @param args the list of MSG files to process
+ */
+ public static void main(String[] args) {
+ if(args.length <= 0) {
+ System.err.println("No files names provided");
+ } else {
+ for (String arg : args) {
+ try {
+ Msg2txt processor = new Msg2txt(arg);
+ processor.processMessage();
+ } catch (IOException e) {
+ System.err.println("Could not process " + arg + ": " + e);
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.eventusermodel;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder.SheetRecordCollectingListener;
+import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
+import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
+import org.apache.poi.hssf.eventusermodel.HSSFListener;
+import org.apache.poi.hssf.eventusermodel.HSSFRequest;
+import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener;
+import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
+import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
+import org.apache.poi.hssf.model.HSSFFormulaParser;
+import org.apache.poi.hssf.record.BOFRecord;
+import org.apache.poi.hssf.record.BlankRecord;
+import org.apache.poi.hssf.record.BoolErrRecord;
+import org.apache.poi.hssf.record.BoundSheetRecord;
+import org.apache.poi.hssf.record.FormulaRecord;
+import org.apache.poi.hssf.record.LabelRecord;
+import org.apache.poi.hssf.record.LabelSSTRecord;
+import org.apache.poi.hssf.record.NoteRecord;
+import org.apache.poi.hssf.record.NumberRecord;
+import org.apache.poi.hssf.record.RKRecord;
+import org.apache.poi.hssf.record.SSTRecord;
+import org.apache.poi.hssf.record.StringRecord;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+/**
+ * A XLS -> CSV processor, that uses the MissingRecordAware
+ * EventModel code to ensure it outputs all columns and rows.
+ * @author Nick Burch
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public class XLS2CSVmra implements HSSFListener {
+ private int minColumns;
+ private POIFSFileSystem fs;
+ private PrintStream output;
+
+ private int lastRowNumber;
+ private int lastColumnNumber;
+
+ /** Should we output the formula, or the value it has? */
+ private boolean outputFormulaValues = true;
+
+ /** For parsing Formulas */
+ private SheetRecordCollectingListener workbookBuildingListener;
+ private HSSFWorkbook stubWorkbook;
+
+ // Records we pick up as we process
+ private SSTRecord sstRecord;
+ private FormatTrackingHSSFListener formatListener;
+
+ /** So we known which sheet we're on */
+ private int sheetIndex = -1;
+ private BoundSheetRecord[] orderedBSRs;
+ private List<BoundSheetRecord> boundSheetRecords = new ArrayList<>();
+
+ // For handling formulas with string results
+ private int nextRow;
+ private int nextColumn;
+ private boolean outputNextStringRecord;
+
+ /**
+ * Creates a new XLS -> CSV converter
+ * @param fs The POIFSFileSystem to process
+ * @param output The PrintStream to output the CSV to
+ * @param minColumns The minimum number of columns to output, or -1 for no minimum
+ */
+ public XLS2CSVmra(POIFSFileSystem fs, PrintStream output, int minColumns) {
+ this.fs = fs;
+ this.output = output;
+ this.minColumns = minColumns;
+ }
+
+ /**
+ * Creates a new XLS -> CSV converter
+ * @param filename The file to process
+ * @param minColumns The minimum number of columns to output, or -1 for no minimum
+ */
+ public XLS2CSVmra(String filename, int minColumns) throws IOException, FileNotFoundException {
+ this(
+ new POIFSFileSystem(new FileInputStream(filename)),
+ System.out, minColumns
+ );
+ }
+
+ /**
+ * Initiates the processing of the XLS file to CSV
+ */
+ public void process() throws IOException {
+ MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);
+ formatListener = new FormatTrackingHSSFListener(listener);
+
+ HSSFEventFactory factory = new HSSFEventFactory();
+ HSSFRequest request = new HSSFRequest();
+
+ if(outputFormulaValues) {
+ request.addListenerForAllRecords(formatListener);
+ } else {
+ workbookBuildingListener = new SheetRecordCollectingListener(formatListener);
+ request.addListenerForAllRecords(workbookBuildingListener);
+ }
+
+ factory.processWorkbookEvents(request, fs);
+ }
+
+ /**
+ * Main HSSFListener method, processes events, and outputs the
+ * CSV as the file is processed.
+ */
+ @Override
+ public void processRecord(org.apache.poi.hssf.record.Record record) {
+ int thisRow = -1;
+ int thisColumn = -1;
+ String thisStr = null;
+
+ switch (record.getSid())
+ {
+ case BoundSheetRecord.sid:
+ boundSheetRecords.add((BoundSheetRecord)record);
+ break;
+ case BOFRecord.sid:
+ BOFRecord br = (BOFRecord)record;
+ if(br.getType() == BOFRecord.TYPE_WORKSHEET) {
+ // Create sub workbook if required
+ if(workbookBuildingListener != null && stubWorkbook == null) {
+ stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();
+ }
+
+ // Output the worksheet name
+ // Works by ordering the BSRs by the location of
+ // their BOFRecords, and then knowing that we
+ // process BOFRecords in byte offset order
+ sheetIndex++;
+ if(orderedBSRs == null) {
+ orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
+ }
+ output.println();
+ output.println(
+ orderedBSRs[sheetIndex].getSheetname() +
+ " [" + (sheetIndex+1) + "]:"
+ );
+ }
+ break;
+
+ case SSTRecord.sid:
+ sstRecord = (SSTRecord) record;
+ break;
+
+ case BlankRecord.sid:
+ BlankRecord brec = (BlankRecord) record;
+
+ thisRow = brec.getRow();
+ thisColumn = brec.getColumn();
+ thisStr = "";
+ break;
+ case BoolErrRecord.sid:
+ BoolErrRecord berec = (BoolErrRecord) record;
+
+ thisRow = berec.getRow();
+ thisColumn = berec.getColumn();
+ thisStr = "";
+ break;
+
+ case FormulaRecord.sid:
+ FormulaRecord frec = (FormulaRecord) record;
+
+ thisRow = frec.getRow();
+ thisColumn = frec.getColumn();
+
+ if(outputFormulaValues) {
+ if(Double.isNaN( frec.getValue() )) {
+ // Formula result is a string
+ // This is stored in the next record
+ outputNextStringRecord = true;
+ nextRow = frec.getRow();
+ nextColumn = frec.getColumn();
+ } else {
+ thisStr = formatListener.formatNumberDateCell(frec);
+ }
+ } else {
+ thisStr = '"' +
+ HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression()) + '"';
+ }
+ break;
+ case StringRecord.sid:
+ if(outputNextStringRecord) {
+ // String for formula
+ StringRecord srec = (StringRecord)record;
+ thisStr = srec.getString();
+ thisRow = nextRow;
+ thisColumn = nextColumn;
+ outputNextStringRecord = false;
+ }
+ break;
+
+ case LabelRecord.sid:
+ LabelRecord lrec = (LabelRecord) record;
+
+ thisRow = lrec.getRow();
+ thisColumn = lrec.getColumn();
+ thisStr = '"' + lrec.getValue() + '"';
+ break;
+ case LabelSSTRecord.sid:
+ LabelSSTRecord lsrec = (LabelSSTRecord) record;
+
+ thisRow = lsrec.getRow();
+ thisColumn = lsrec.getColumn();
+ if(sstRecord == null) {
+ thisStr = '"' + "(No SST Record, can't identify string)" + '"';
+ } else {
+ thisStr = '"' + sstRecord.getString(lsrec.getSSTIndex()).toString() + '"';
+ }
+ break;
+ case NoteRecord.sid:
+ NoteRecord nrec = (NoteRecord) record;
+
+ thisRow = nrec.getRow();
+ thisColumn = nrec.getColumn();
+ // TODO: Find object to match nrec.getShapeId()
+ thisStr = '"' + "(TODO)" + '"';
+ break;
+ case NumberRecord.sid:
+ NumberRecord numrec = (NumberRecord) record;
+
+ thisRow = numrec.getRow();
+ thisColumn = numrec.getColumn();
+
+ // Format
+ thisStr = formatListener.formatNumberDateCell(numrec);
+ break;
+ case RKRecord.sid:
+ RKRecord rkrec = (RKRecord) record;
+
+ thisRow = rkrec.getRow();
+ thisColumn = rkrec.getColumn();
+ thisStr = '"' + "(TODO)" + '"';
+ break;
+ default:
+ break;
+ }
+
+ // Handle new row
+ if(thisRow != -1 && thisRow != lastRowNumber) {
+ lastColumnNumber = -1;
+ }
+
+ // Handle missing column
+ if(record instanceof MissingCellDummyRecord) {
+ MissingCellDummyRecord mc = (MissingCellDummyRecord)record;
+ thisRow = mc.getRow();
+ thisColumn = mc.getColumn();
+ thisStr = "";
+ }
+
+ // If we got something to print out, do so
+ if(thisStr != null) {
+ if(thisColumn > 0) {
+ output.print(',');
+ }
+ output.print(thisStr);
+ }
+
+ // Update column and row count
+ if(thisRow > -1)
+ lastRowNumber = thisRow;
+ if(thisColumn > -1)
+ lastColumnNumber = thisColumn;
+
+ // Handle end of row
+ if(record instanceof LastCellOfRowDummyRecord) {
+ // Print out any missing commas if needed
+ if(minColumns > 0) {
+ // Columns are 0 based
+ if(lastColumnNumber == -1) { lastColumnNumber = 0; }
+ for(int i=lastColumnNumber; i<(minColumns); i++) {
+ output.print(',');
+ }
+ }
+
+ // We're onto a new row
+ lastColumnNumber = -1;
+
+ // End the row
+ output.println();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ if(args.length < 1) {
+ System.err.println("Use:");
+ System.err.println(" XLS2CSVmra <xls file> [min columns]");
+ System.exit(1);
+ }
+
+ int minColumns = -1;
+ if(args.length >= 2) {
+ minColumns = Integer.parseInt(args[1]);
+ }
+
+ XLS2CSVmra xls2csv = new XLS2CSVmra(args[0], minColumns);
+ xls2csv.process();
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+/* Placeholder - this is now handled in the Common SS example **/
+public class AddDimensionedImage extends org.apache.poi.examples.ss.AddDimensionedImage {
+}
\ No newline at end of file
--- /dev/null
+
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+
+/**
+ * Shows how various alignment options work.
+ *
+ * @author Glen Stampoultzis (glens at apache.org)
+ */
+public class Alignment {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+ HSSFRow row = sheet.createRow(2);
+ createCell(wb, row, 0, HorizontalAlignment.CENTER);
+ createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION);
+ createCell(wb, row, 2, HorizontalAlignment.FILL);
+ createCell(wb, row, 3, HorizontalAlignment.GENERAL);
+ createCell(wb, row, 4, HorizontalAlignment.JUSTIFY);
+ createCell(wb, row, 5, HorizontalAlignment.LEFT);
+ createCell(wb, row, 6, HorizontalAlignment.RIGHT);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ /**
+ * Creates a cell and aligns it a certain way.
+ *
+ * @param wb the workbook
+ * @param row the row to create the cell in
+ * @param column the column number to create the cell in
+ * @param align the alignment for the cell.
+ */
+ private static void createCell(HSSFWorkbook wb, HSSFRow row, int column, HorizontalAlignment align) {
+ HSSFCell cell = row.createCell(column);
+ cell.setCellValue("Align It");
+ HSSFCellStyle cellStyle = wb.createCellStyle();
+ cellStyle.setAlignment(align);
+ cell.setCellStyle(cellStyle);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFDataFormat;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+
+/**
+ * Demonstrates many features of the user API at once. Used in the HOW-TO guide.
+ */
+public class BigExample {
+ public static void main(String[] args) throws IOException {
+ int rownum;
+
+ // create a new workbook
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ // create a new sheet
+ HSSFSheet s = wb.createSheet();
+ // declare a row object reference
+ HSSFRow r;
+ // declare a cell object reference
+ HSSFCell c;
+ // create 3 cell styles
+ HSSFCellStyle cs = wb.createCellStyle();
+ HSSFCellStyle cs2 = wb.createCellStyle();
+ HSSFCellStyle cs3 = wb.createCellStyle();
+ // create 2 fonts objects
+ HSSFFont f = wb.createFont();
+ HSSFFont f2 = wb.createFont();
+
+ //set font 1 to 12 point type
+ f.setFontHeightInPoints((short) 12);
+ //make it red
+ f.setColor(HSSFColorPredefined.RED.getIndex());
+ // make it bold
+ //arial is the default font
+ f.setBold(true);
+
+ //set font 2 to 10 point type
+ f2.setFontHeightInPoints((short) 10);
+ //make it the color at palette index 0xf (white)
+ f2.setColor(HSSFColorPredefined.WHITE.getIndex());
+ //make it bold
+ f2.setBold(true);
+
+ //set cell style
+ cs.setFont(f);
+ //set the cell format see HSSFDataFormat for a full list
+ cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("($#,##0_);[Red]($#,##0)"));
+
+ //set a thin border
+ cs2.setBorderBottom(BorderStyle.THIN);
+ //fill w fg fill color
+ cs2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ // set foreground fill to red
+ cs2.setFillForegroundColor(HSSFColorPredefined.RED.getIndex());
+
+ // set the font
+ cs2.setFont(f2);
+
+ // set the sheet name to HSSF Test
+ wb.setSheetName(0, "HSSF Test");
+ // create a sheet with 300 rows (0-299)
+ for (rownum = 0; rownum < 300; rownum++) {
+ // create a row
+ r = s.createRow(rownum);
+ // on every other row
+ if ((rownum % 2) == 0) {
+ // make the row height bigger (in twips - 1/20 of a point)
+ r.setHeight((short) 0x249);
+ }
+
+ // create 50 cells (0-49) (the += 2 becomes apparent later
+ for (int cellnum = 0; cellnum < 50; cellnum += 2) {
+ // create a numeric cell
+ c = r.createCell(cellnum);
+ // do some goofy math to demonstrate decimals
+ c.setCellValue((rownum * 10000.0) + cellnum
+ + (rownum / 1000.0)
+ + (cellnum / 10000.0));
+
+ // on every other row
+ if ((rownum % 2) == 0) {
+ // set this cell to the first cell style we defined
+ c.setCellStyle(cs);
+ }
+
+ // create a string cell (see why += 2 in the
+ c = r.createCell(cellnum + 1);
+
+ // set the cell's string value to "TEST"
+ c.setCellValue("TEST");
+ // make this column a bit wider
+ s.setColumnWidth(cellnum + 1, (int) ((50 * 8) / ((double) 1 / 20)));
+
+ // on every other row
+ if ((rownum % 2) == 0) {
+ // set this to the white on red cell style
+ // we defined above
+ c.setCellStyle(cs2);
+ }
+
+ }
+ }
+
+ //draw a thick black border on the row at the bottom using BLANKS
+ // advance 2 rows
+ rownum++;
+ rownum++;
+
+ r = s.createRow(rownum);
+
+ // define the third style to be the default
+ // except with a thick black border at the bottom
+ cs3.setBorderBottom(BorderStyle.THICK);
+
+ //create 50 cells
+ for (int cellnum = 0; cellnum < 50; cellnum++) {
+ //create a blank type cell (no value)
+ c = r.createCell(cellnum);
+ // set it to the thick black border style
+ c.setCellStyle(cs3);
+ }
+
+ //end draw thick black border
+
+
+ // demonstrate adding/naming and deleting a sheet
+ // create a sheet, set its title then delete it
+ wb.createSheet();
+ wb.setSheetName(1, "DeletedSheet");
+ wb.removeSheetAt(1);
+ //end deleted sheet
+
+ // create a new file
+ try (FileOutputStream out = new FileOutputStream("workbook.xls")) {
+ // write the workbook to the output stream
+ // close our file (don't blow out our file handles
+ wb.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
+import org.apache.poi.ss.usermodel.BorderStyle;
+
+/**
+ * Demonstrates how to create borders around cells.
+ */
+public class Borders {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ HSSFRow row = sheet.createRow(1);
+
+ // Create a cell and put a value in it.
+ HSSFCell cell = row.createCell(1);
+ cell.setCellValue(4);
+
+ // Style the cell with borders all around.
+ HSSFCellStyle style = wb.createCellStyle();
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(HSSFColorPredefined.BLACK.getIndex());
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(HSSFColorPredefined.GREEN.getIndex());
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(HSSFColorPredefined.BLUE.getIndex());
+ style.setBorderTop(BorderStyle.MEDIUM_DASHED);
+ style.setTopBorderColor(HSSFColorPredefined.ORANGE.getIndex());
+ cell.setCellStyle(style);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFComment;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.Comment;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.RichTextString;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+
+/**
+ * Demonstrates how to work with excel cell comments.<p>
+ *
+ * Excel comment is a kind of a text shape,
+ * so inserting a comment is very similar to placing a text box in a worksheet
+ */
+public class CellComments {
+
+ public static void main(String[] args) throws IOException {
+ createWorkbook(false, ".xls");
+ createWorkbook(true, ".xlsx");
+ }
+
+ private static void createWorkbook(boolean xssf, String extension) throws IOException {
+ try (Workbook wb = WorkbookFactory.create(xssf)) {
+ Sheet sheet = wb.createSheet("Cell comments in POI " + extension);
+ CreationHelper creationHelper = wb.getCreationHelper();
+
+ // Create the drawing patriarch. This is the top level container for all shapes including cell comments.
+ Drawing<?> patr = sheet.createDrawingPatriarch();
+
+ //create a cell in row 3
+ Cell cell1 = sheet.createRow(3).createCell(1);
+ cell1.setCellValue(creationHelper.createRichTextString("Hello, World"));
+
+ //anchor defines size and position of the comment in worksheet
+ ClientAnchor clientAnchor = creationHelper.createClientAnchor();
+ clientAnchor.setCol1(4);
+ clientAnchor.setRow1(2);
+ clientAnchor.setCol2(6);
+ clientAnchor.setRow2(5);
+ Comment comment1 = patr.createCellComment(clientAnchor);
+
+ // set text in the comment
+ comment1.setString(creationHelper.createRichTextString("We can set comments in POI"));
+
+ //set comment author.
+ //you can see it in the status bar when moving mouse over the commented cell
+ comment1.setAuthor("Apache Software Foundation");
+
+ // The first way to assign comment to a cell is via Cell.setCellComment method
+ cell1.setCellComment(comment1);
+
+ //create another cell in row 6
+ Cell cell2 = sheet.createRow(6).createCell(1);
+ cell2.setCellValue(36.6);
+
+
+ clientAnchor = creationHelper.createClientAnchor();
+ clientAnchor.setCol1(4);
+ clientAnchor.setRow1(8);
+ clientAnchor.setCol2(6);
+ clientAnchor.setRow2(11);
+ Comment comment2 = patr.createCellComment(clientAnchor);
+ //modify background color of the comment, only available in HSSF currently
+ if (wb instanceof HSSFWorkbook) {
+ ((HSSFComment) comment2).setFillColor(204, 236, 255);
+ }
+
+ RichTextString string = creationHelper.createRichTextString("Normal body temperature");
+
+ //apply custom font to the text in the comment
+ Font font = wb.createFont();
+ font.setFontName("Arial");
+ font.setFontHeightInPoints((short) 10);
+ font.setBold(true);
+ font.setColor(IndexedColors.RED.getIndex());
+ string.applyFont(font);
+
+ comment2.setString(string);
+ comment2.setVisible(true); //by default comments are hidden. This one is always visible.
+
+ comment2.setAuthor("Bill Gates");
+
+ /*
+ * The second way to assign comment to a cell is to implicitly specify its row and column.
+ * Note, it is possible to set row and column of a non-existing cell.
+ * It works, the comment is visible.
+ */
+ comment2.setRow(6);
+ comment2.setColumn(1);
+
+ try (FileOutputStream out = new FileOutputStream("poi_comment" + extension)) {
+ wb.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.FormulaError;
+
+public class CellTypes {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+ HSSFRow row = sheet.createRow(2);
+ row.createCell(0).setCellValue(1.1);
+ row.createCell(1).setCellValue(new Date());
+ row.createCell(2).setCellValue("a string");
+ row.createCell(3).setCellValue(true);
+ row.createCell(4).setCellErrorValue(FormulaError.NUM);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Illustrates how to create cell values.
+ *
+ * @author Glen Stampoultzis (glens at apache.org)
+ */
+public class CreateCells {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ HSSFRow row = sheet.createRow(0);
+ // Create a cell and put a value in it.
+ HSSFCell cell = row.createCell(0);
+ cell.setCellValue(1);
+
+ // Or do it on one line.
+ row.createCell(1).setCellValue(1.2);
+ row.createCell(2).setCellValue("This is a string");
+ row.createCell(3).setCellValue(true);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFDataFormat;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * An example on how to cells with dates. The important thing to note
+ * about dates is that they are really normal numeric cells that are
+ * formatted specially.
+ */
+public class CreateDateCells {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ HSSFRow row = sheet.createRow(0);
+
+ // Create a cell and put a date value in it. The first cell is not styled as a date.
+ HSSFCell cell = row.createCell(0);
+ cell.setCellValue(new Date());
+
+ // we style the second cell as a date (and time). It is important to create a new cell style from the workbook
+ // otherwise you can end up modifying the built in style and effecting not only this cell but other cells.
+ HSSFCellStyle cellStyle = wb.createCellStyle();
+ cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));
+ cell = row.createCell(1);
+ cell.setCellValue(new Date());
+ cell.setCellStyle(cellStyle);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.Closeable;
+import java.io.FileInputStream;
+
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hssf.usermodel.HSSFObjectData;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.Entry;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+/**
+ * Demonstrates how you can extract embedded data from a .xls file
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class EmbeddedObjects {
+ private EmbeddedObjects() {}
+
+ @SuppressWarnings("unused")
+ public static void main(String[] args) throws Exception {
+ try (
+ FileInputStream fis = new FileInputStream(args[0]);
+ POIFSFileSystem fs = new POIFSFileSystem(fis);
+ HSSFWorkbook workbook = new HSSFWorkbook(fs)
+ ) {
+ for (HSSFObjectData obj : workbook.getAllEmbeddedObjects()) {
+ //the OLE2 Class Name of the object
+ String oleName = obj.getOLE2ClassName();
+ DirectoryNode dn = (obj.hasDirectoryEntry()) ? (DirectoryNode) obj.getDirectory() : null;
+ Closeable document = null;
+ switch (oleName) {
+ case "Worksheet":
+ document = new HSSFWorkbook(dn, fs, false);
+ break;
+ case "Document":
+ document = new HWPFDocument(dn);
+ break;
+ case "Presentation":
+ document = new HSLFSlideShow(dn);
+ break;
+ default:
+ if (dn != null) {
+ // The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is
+ for (Entry entry : dn) {
+ String name = entry.getName();
+ }
+ } else {
+ // There is no DirectoryEntry
+ // Recover the object's data from the HSSFObjectData instance.
+ byte[] objectData = obj.getObjectData();
+ }
+ break;
+ }
+ if (document != null) {
+ document.close();
+ }
+ }
+ }
+ }
+}
--- /dev/null
+
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
+import org.apache.poi.hssf.eventusermodel.HSSFListener;
+import org.apache.poi.hssf.eventusermodel.HSSFRequest;
+import org.apache.poi.hssf.record.BOFRecord;
+import org.apache.poi.hssf.record.BoundSheetRecord;
+import org.apache.poi.hssf.record.LabelSSTRecord;
+import org.apache.poi.hssf.record.NumberRecord;
+import org.apache.poi.hssf.record.RowRecord;
+import org.apache.poi.hssf.record.SSTRecord;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+/**
+ * This example shows how to use the event API for reading a file.
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public class EventExample implements HSSFListener {
+ private SSTRecord sstrec;
+
+ /**
+ * This method listens for incoming records and handles them as required.
+ * @param record The record that was found while reading.
+ */
+ @Override
+ public void processRecord(org.apache.poi.hssf.record.Record record)
+ {
+ switch (record.getSid())
+ {
+ // the BOFRecord can represent either the beginning of a sheet or the workbook
+ case BOFRecord.sid:
+ BOFRecord bof = (BOFRecord) record;
+ if (bof.getType() == BOFRecord.TYPE_WORKBOOK)
+ {
+ System.out.println("Encountered workbook");
+ // assigned to the class level member
+ } else if (bof.getType() == BOFRecord.TYPE_WORKSHEET)
+ {
+ System.out.println("Encountered sheet reference");
+ }
+ break;
+ case BoundSheetRecord.sid:
+ BoundSheetRecord bsr = (BoundSheetRecord) record;
+ System.out.println("New sheet named: " + bsr.getSheetname());
+ break;
+ case RowRecord.sid:
+ RowRecord rowrec = (RowRecord) record;
+ System.out.println("Row found, first column at "
+ + rowrec.getFirstCol() + " last column at " + rowrec.getLastCol());
+ break;
+ case NumberRecord.sid:
+ NumberRecord numrec = (NumberRecord) record;
+ System.out.println("Cell found with value " + numrec.getValue()
+ + " at row " + numrec.getRow() + " and column " + numrec.getColumn());
+ break;
+ // SSTRecords store a array of unique strings used in Excel.
+ case SSTRecord.sid:
+ sstrec = (SSTRecord) record;
+ for (int k = 0; k < sstrec.getNumUniqueStrings(); k++)
+ {
+ System.out.println("String table value " + k + " = " + sstrec.getString(k));
+ }
+ break;
+ case LabelSSTRecord.sid:
+ LabelSSTRecord lrec = (LabelSSTRecord) record;
+ System.out.println("String cell found with value "
+ + sstrec.getString(lrec.getSSTIndex()));
+ break;
+ }
+ }
+
+ /**
+ * Read an excel file and spit out what we find.
+ *
+ * @param args Expect one argument that is the file to read.
+ * @throws IOException When there is an error processing the file.
+ */
+ public static void main(String[] args) throws IOException
+ {
+ // create a new file input stream with the input file specified
+ // at the command line
+ try (FileInputStream fin = new FileInputStream(args[0])) {
+ // create a new org.apache.poi.poifs.filesystem.Filesystem
+ try (POIFSFileSystem poifs = new POIFSFileSystem(fin)) {
+ // get the Workbook (excel part) stream in a InputStream
+ try (InputStream din = poifs.createDocumentInputStream("Workbook")) {
+ // construct out HSSFRequest object
+ HSSFRequest req = new HSSFRequest();
+ // lazy listen for ALL records with the listener shown above
+ req.addListenerForAllRecords(new EventExample());
+ // create our event factory
+ HSSFEventFactory factory = new HSSFEventFactory();
+ // process our events based on the document input stream
+ factory.processEvents(req, din);
+ }
+ }
+ }
+ System.out.println("done.");
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
+import org.apache.poi.ss.usermodel.FillPatternType;
+
+/**
+ * Shows how to use various fills.
+ */
+public class FrillsAndFills {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ HSSFRow row = sheet.createRow(1);
+
+ // Aqua background
+ HSSFCellStyle style = wb.createCellStyle();
+ style.setFillBackgroundColor(HSSFColorPredefined.AQUA.getIndex());
+ style.setFillPattern(FillPatternType.BIG_SPOTS);
+ HSSFCell cell = row.createCell(1);
+ cell.setCellValue("X");
+ cell.setCellStyle(style);
+
+ // Orange "foreground", foreground being the fill foreground not the font color.
+ style = wb.createCellStyle();
+ style.setFillForegroundColor(HSSFColorPredefined.ORANGE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ cell = row.createCell(2);
+ cell.setCellValue("X");
+ cell.setCellStyle(style);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFDataFormat;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFRichTextString;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+/**
+ * File for HSSF testing/examples
+ *
+ * THIS IS NOT THE MAIN HSSF FILE!! This is a utility for testing functionality.
+ * It does contain sample API usage that may be educational to regular API
+ * users.
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class HSSFReadWrite {
+
+ private HSSFReadWrite() {}
+
+ /**
+ * creates an {@link HSSFWorkbook} with the specified OS filename.
+ */
+ private static HSSFWorkbook readFile(String filename) throws IOException {
+ try (FileInputStream fis = new FileInputStream(filename)) {
+ return new HSSFWorkbook(fis); // NOSONAR - should not be closed here
+ }
+ }
+
+ /**
+ * given a filename this outputs a sample sheet with just a set of
+ * rows/cells.
+ */
+ private static void testCreateSampleSheet(String outputFilename) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook();
+ FileOutputStream out = new FileOutputStream(outputFilename)) {
+ HSSFSheet s = wb.createSheet();
+ HSSFCellStyle cs = wb.createCellStyle();
+ HSSFCellStyle cs2 = wb.createCellStyle();
+ HSSFCellStyle cs3 = wb.createCellStyle();
+ HSSFFont f = wb.createFont();
+ HSSFFont f2 = wb.createFont();
+
+ f.setFontHeightInPoints((short) 12);
+ f.setColor((short) 0xA);
+ f.setBold(true);
+ f2.setFontHeightInPoints((short) 10);
+ f2.setColor((short) 0xf);
+ f2.setBold(true);
+ cs.setFont(f);
+ cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("($#,##0_);[Red]($#,##0)"));
+ cs2.setBorderBottom(BorderStyle.THIN);
+ cs2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ cs2.setFillForegroundColor((short) 0xA);
+ cs2.setFont(f2);
+ wb.setSheetName(0, "HSSF Test");
+ int rownum;
+ for (rownum = 0; rownum < 300; rownum++) {
+ HSSFRow r = s.createRow(rownum);
+ if ((rownum % 2) == 0) {
+ r.setHeight((short) 0x249);
+ }
+
+ for (int cellnum = 0; cellnum < 50; cellnum += 2) {
+ HSSFCell c = r.createCell(cellnum);
+ c.setCellValue((rownum * 10000.0) + cellnum
+ + (rownum / 1000.0) + (cellnum / 10000.0));
+ if ((rownum % 2) == 0) {
+ c.setCellStyle(cs);
+ }
+ c = r.createCell(cellnum + 1);
+ c.setCellValue(new HSSFRichTextString("TEST"));
+ // 50 characters divided by 1/20th of a point
+ s.setColumnWidth(cellnum + 1, (int) (50 * 8 / 0.05));
+ if ((rownum % 2) == 0) {
+ c.setCellStyle(cs2);
+ }
+ }
+ }
+
+ // draw a thick black border on the row at the bottom using BLANKS
+ rownum++;
+ rownum++;
+ HSSFRow r = s.createRow(rownum);
+ cs3.setBorderBottom(BorderStyle.THICK);
+ for (int cellnum = 0; cellnum < 50; cellnum++) {
+ HSSFCell c = r.createCell(cellnum);
+ c.setCellStyle(cs3);
+ }
+ s.addMergedRegion(new CellRangeAddress(0, 3, 0, 3));
+ s.addMergedRegion(new CellRangeAddress(100, 110, 100, 110));
+
+ // end draw thick black border
+ // create a sheet, set its title then delete it
+ wb.createSheet();
+ wb.setSheetName(1, "DeletedSheet");
+ wb.removeSheetAt(1);
+
+ // end deleted sheet
+ wb.write(out);
+ }
+ }
+
+ /**
+ * Method main
+ *
+ * Given 1 argument takes that as the filename, inputs it and dumps the
+ * cell values/types out to sys.out.<br>
+ *
+ * given 2 arguments where the second argument is the word "write" and the
+ * first is the filename - writes out a sample (test) spreadsheet
+ * see {@link HSSFReadWrite#testCreateSampleSheet(String)}.<br>
+ *
+ * given 2 arguments where the first is an input filename and the second
+ * an output filename (not write), attempts to fully read in the
+ * spreadsheet and fully write it out.<br>
+ *
+ * given 3 arguments where the first is an input filename and the second an
+ * output filename (not write) and the third is "modify1", attempts to read in the
+ * spreadsheet, deletes rows 0-24, 74-99. Changes cell at row 39, col 3 to
+ * "MODIFIED CELL" then writes it out. Hence this is "modify test 1". If you
+ * take the output from the write test, you'll have a valid scenario.
+ */
+ public static void main(String[] args) throws Exception {
+ if (args.length < 1) {
+ System.err.println("At least one argument expected");
+ return;
+ }
+
+ String fileName = args[0];
+ if (args.length < 2) {
+
+ try (HSSFWorkbook wb = HSSFReadWrite.readFile(fileName)) {
+ System.out.println("Data dump:\n");
+
+ for (int k = 0; k < wb.getNumberOfSheets(); k++) {
+ HSSFSheet sheet = wb.getSheetAt(k);
+ int rows = sheet.getPhysicalNumberOfRows();
+ System.out.println("Sheet " + k + " \"" + wb.getSheetName(k) + "\" has " + rows + " row(s).");
+ for (int r = 0; r < rows; r++) {
+ HSSFRow row = sheet.getRow(r);
+ if (row == null) {
+ continue;
+ }
+
+ System.out.println("\nROW " + row.getRowNum() + " has " + row.getPhysicalNumberOfCells() + " cell(s).");
+ for (int c = 0; c < row.getLastCellNum(); c++) {
+ HSSFCell cell = row.getCell(c);
+ String value;
+
+ if (cell != null) {
+ switch (cell.getCellType()) {
+
+ case FORMULA:
+ value = "FORMULA value=" + cell.getCellFormula();
+ break;
+
+ case NUMERIC:
+ value = "NUMERIC value=" + cell.getNumericCellValue();
+ break;
+
+ case STRING:
+ value = "STRING value=" + cell.getStringCellValue();
+ break;
+
+ case BLANK:
+ value = "<BLANK>";
+ break;
+
+ case BOOLEAN:
+ value = "BOOLEAN value-" + cell.getBooleanCellValue();
+ break;
+
+ case ERROR:
+ value = "ERROR value=" + cell.getErrorCellValue();
+ break;
+
+ default:
+ value = "UNKNOWN value of type " + cell.getCellType();
+ }
+ System.out.println("CELL col=" + cell.getColumnIndex() + " VALUE=" + value);
+ }
+ }
+ }
+ }
+ }
+ } else if (args.length == 2) {
+ if ("write".equalsIgnoreCase(args[1])) {
+ System.out.println("Write mode");
+ long time = System.currentTimeMillis();
+ HSSFReadWrite.testCreateSampleSheet(fileName);
+
+ System.out.println("" + (System.currentTimeMillis() - time) + " ms generation time");
+ } else {
+ System.out.println("readwrite test");
+ try (HSSFWorkbook wb = HSSFReadWrite.readFile(fileName);
+ FileOutputStream stream = new FileOutputStream(args[1])) {
+ wb.write(stream);
+ }
+ }
+ } else if (args.length == 3 && "modify1".equalsIgnoreCase(args[2])) {
+ // delete row 0-24, row 74 - 99 && change cell 3 on row 39 to string "MODIFIED CELL!!"
+
+ try (HSSFWorkbook wb = HSSFReadWrite.readFile(fileName);
+ FileOutputStream stream = new FileOutputStream(args[1])) {
+ HSSFSheet sheet = wb.getSheetAt(0);
+
+ for (int k = 0; k < 25; k++) {
+ HSSFRow row = sheet.getRow(k);
+ sheet.removeRow(row);
+ }
+ for (int k = 74; k < 100; k++) {
+ HSSFRow row = sheet.getRow(k);
+ sheet.removeRow(row);
+ }
+ HSSFRow row = sheet.getRow(39);
+ HSSFCell cell = row.getCell(3);
+ cell.setCellValue("MODIFIED CELL!!!!!");
+
+ wb.write(stream);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Test if hyperlink formula, with url that got more than 127 characters, works
+ */
+public class HyperlinkFormula {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+ HSSFRow row = sheet.createRow(0);
+
+ HSSFCell cell = row.createCell(0);
+ cell.setCellFormula("HYPERLINK(\"http://127.0.0.1:8080/toto/truc/index.html?test=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", \"test\")");
+
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.common.usermodel.HyperlinkType;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFCreationHelper;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFHyperlink;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
+import org.apache.poi.ss.usermodel.Font;
+
+/**
+ * Demonstrates how to create hyperlinks.
+ */
+public class Hyperlinks {
+
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFCreationHelper helper = wb.getCreationHelper();
+
+ //cell style for hyperlinks
+ //by default hyperlinks are blue and underlined
+ HSSFCellStyle hlinkStyle = wb.createCellStyle();
+ HSSFFont hlinkFont = wb.createFont();
+ hlinkFont.setUnderline(Font.U_SINGLE);
+ hlinkFont.setColor(HSSFColorPredefined.BLUE.getIndex());
+ hlinkStyle.setFont(hlinkFont);
+
+ HSSFCell cell;
+ HSSFSheet sheet = wb.createSheet("Hyperlinks");
+
+ //URL
+ cell = sheet.createRow(0).createCell(0);
+ cell.setCellValue("URL Link");
+ HSSFHyperlink link = helper.createHyperlink(HyperlinkType.URL);
+ link.setAddress("https://poi.apache.org/");
+ cell.setHyperlink(link);
+ cell.setCellStyle(hlinkStyle);
+
+ //link to a file in the current directory
+ cell = sheet.createRow(1).createCell(0);
+ cell.setCellValue("File Link");
+ link = helper.createHyperlink(HyperlinkType.FILE);
+ link.setAddress("link1.xls");
+ cell.setHyperlink(link);
+ cell.setCellStyle(hlinkStyle);
+
+ //e-mail link
+ cell = sheet.createRow(2).createCell(0);
+ cell.setCellValue("Email Link");
+ link = helper.createHyperlink(HyperlinkType.EMAIL);
+ //note, if subject contains white spaces, make sure they are url-encoded
+ link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
+ cell.setHyperlink(link);
+ cell.setCellStyle(hlinkStyle);
+
+ //link to a place in this workbook
+
+ //create a target sheet and cell
+ HSSFSheet sheet2 = wb.createSheet("Target Sheet");
+ sheet2.createRow(0).createCell(0).setCellValue("Target Cell");
+
+ cell = sheet.createRow(3).createCell(0);
+ cell.setCellValue("Worksheet Link");
+ link = helper.createHyperlink(HyperlinkType.DOCUMENT);
+ link.setAddress("'Target Sheet'!A1");
+ cell.setHyperlink(link);
+ cell.setCellStyle(hlinkStyle);
+
+ try (FileOutputStream out = new FileOutputStream("hssf-links.xls")) {
+ wb.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFDataFormat;
+import org.apache.poi.hssf.usermodel.HSSFRichTextString;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * This class contains code that demonstrates how to insert plain, numbered
+ * and bulleted lists into an Excel spreadsheet cell.
+ *
+ * Look at the code contained in the demonstrateMethodCalls() method. It calls
+ * other methods that create plain, numbered and bulleted single and
+ * multi-level lists. The demonstrateMethodCalls() method appears at the top
+ * of the class definition.
+ *
+ * Though different methods are provided to construct single and multi-level
+ * plain, numbered and bulleted lists, close examination will reveal that they
+ * are not strictly necessary. If the inputs to the listInCell() and
+ * multilLevelListInCell() methods are constructed to include the bullet
+ * character or the item numbers then these methods alone may be sufficient.
+ *
+ * @author Mark Beardsley [msb at apache.org]
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public class InCellLists {
+
+ // This character looks like a solid, black, loser case letter 'o'
+ // positioned up from the base line of the text.
+ private static final char BULLET_CHARACTER = '\u2022';
+
+ // The tab character - \t - cannot be used to create a tab space
+ // within a cell as it is rendered as a square. Therefore, four
+ // spaces are used to simulate that character.
+ private static final String TAB = " ";
+
+ /**
+ * Call each of the list creation methods.
+ *
+ * @param outputFilename A String that encapsulates the name of and path to
+ * the Excel spreadsheet file this code will create.
+ */
+ public void demonstrateMethodCalls(String outputFilename) throws IOException {
+ try (HSSFWorkbook workbook = new HSSFWorkbook()) {
+ HSSFSheet sheet = workbook.createSheet("In Cell Lists");
+ HSSFRow row = sheet.createRow(0);
+
+ // Create a cell at A1 and insert a single, bulleted, item into
+ // that cell.
+ HSSFCell cell = row.createCell(0);
+ this.bulletedItemInCell(workbook, "List Item", cell);
+
+ // Create a cell at A2 and insert a plain list - that is one
+ // whose items are neither bulleted or numbered - into that cell.
+ row = sheet.createRow(1);
+ cell = row.createCell(0);
+ List<String> listItems = new ArrayList<>();
+ listItems.add("List Item One.");
+ listItems.add("List Item Two.");
+ listItems.add("List Item Three.");
+ listItems.add("List Item Four.");
+ this.listInCell(workbook, listItems, cell);
+ // The row height and cell width are set here to ensure that the
+ // list may be seen.
+ row.setHeight((short) 1100);
+ sheet.setColumnWidth(0, 9500);
+
+ // Create a cell at A3 and insert a numbered list into that cell.
+ // Note that a couple of items have been added to the listItems
+ // ArrayList
+ row = sheet.createRow(2);
+ cell = row.createCell(0);
+ listItems.add("List Item Five.");
+ listItems.add("List Item Six.");
+ this.numberedListInCell(workbook, listItems, cell, 1, 2);
+ row.setHeight((short) 1550);
+
+ // Create a cell at A4 and insert a numbered list into that cell.
+ // Note that a couple of items have been added to the listItems
+ // ArrayList
+ row = sheet.createRow(3);
+ cell = row.createCell(0);
+ listItems.add("List Item Seven.");
+ listItems.add("List Item Eight.");
+ listItems.add("List Item Nine.");
+ listItems.add("List Item Ten.");
+ this.bulletedListInCell(workbook, listItems, cell);
+ row.setHeight((short) 2550);
+
+ // Insert a plain, multi-level list into cell A5. Note that
+ // the major difference here is that the list items are passed as
+ // an ArrayList of MultiLevelListItems. Note that an ArrayList
+ // of instances of an inner class was used here in preference to
+ // a Hashtable or HashMap as the ArrayList will preserve the
+ // ordering of the items added to it; the first item added will
+ // be the first item recovered and the last item added, the last
+ // item recovered. Alternatively, a LinkedHashMap could be used
+ // to preserve order.
+ row = sheet.createRow(4);
+ cell = row.createCell(0);
+ List<MultiLevelListItem> multiLevelListItems = new ArrayList<>();
+ listItems = new ArrayList<>();
+ listItems.add("ML List Item One - Sub Item One.");
+ listItems.add("ML List Item One - Sub Item Two.");
+ listItems.add("ML List Item One - Sub Item Three.");
+ listItems.add("ML List Item One - Sub Item Four.");
+ multiLevelListItems.add(new MultiLevelListItem("List Item One.", listItems));
+ // Passing either null or an empty ArrayList will signal that
+ // there are no lower level items associated with the top level
+ // item
+ multiLevelListItems.add(new MultiLevelListItem("List Item Two.", null));
+ multiLevelListItems.add(new MultiLevelListItem("List Item Three.", null));
+ listItems = new ArrayList<>();
+ listItems.add("ML List Item Four - Sub Item One.");
+ listItems.add("ML List Item Four - Sub Item Two.");
+ listItems.add("ML List Item Four - Sub Item Three.");
+ multiLevelListItems.add(new MultiLevelListItem("List Item Four.", listItems));
+ this.multiLevelListInCell(workbook, multiLevelListItems, cell);
+ row.setHeight((short) 2800);
+
+ // Insert a numbered multi-level list into cell A6. Note that the
+ // same ArrayList as constructed for the above plain multi-level
+ // list example will be re-used
+ row = sheet.createRow(5);
+ cell = row.createCell(0);
+ this.multiLevelNumberedListInCell(workbook, multiLevelListItems,
+ cell, 1, 1, 1, 2);
+ row.setHeight((short) 2800);
+
+ // Insert a numbered multi-level list into cell A7. Note that the
+ // same ArrayList as constructed for the plain multi-level list
+ // example will be re-used
+ row = sheet.createRow(6);
+ cell = row.createCell(0);
+ this.multiLevelBulletedListInCell(workbook, multiLevelListItems, cell);
+ row.setHeight((short) 2800);
+
+ // Save the completed workbook
+ try (FileOutputStream fos = new FileOutputStream(new File(outputFilename))) {
+ workbook.write(fos);
+ }
+ } catch (IOException ioEx) {
+ System.out.println("Caught a: " + ioEx.getClass().getName());
+ System.out.println("Message: " + ioEx.getMessage());
+ System.out.println("Stacktrace follows...........");
+ ioEx.printStackTrace(System.out);
+ }
+ }
+
+ /**
+ * Inserts a single bulleted item into a cell.
+ *
+ * @param workbook A reference to the HSSFWorkbook that 'contains' the
+ * cell.
+ * @param listItem An instance of the String class encapsulating the
+ * items text.
+ * @param cell An instance of the HSSFCell class that encapsulates a
+ * reference to the spreadsheet cell into which the list item
+ * will be written.
+ */
+ public void bulletedItemInCell(HSSFWorkbook workbook, String listItem, HSSFCell cell) {
+ // A format String must be built to ensure that the contents of the
+ // cell appear as a bulleted item.
+ HSSFDataFormat format = workbook.createDataFormat();
+ String formatString = InCellLists.BULLET_CHARACTER + " @";
+ int formatIndex = format.getFormat(formatString);
+
+ // Construct an HSSFCellStyle and set it's data formt to use the
+ // object created above.
+ HSSFCellStyle bulletStyle = workbook.createCellStyle();
+ bulletStyle.setDataFormat((short)formatIndex);
+
+ // Set the cells contents and style.
+ cell.setCellValue(new HSSFRichTextString(listItem));
+ cell.setCellStyle(bulletStyle);
+ }
+
+ /**
+ * Inserts a list of plain items - that is items that are neither
+ * numbered or bulleted - into a single cell.
+ *
+ * @param workbook A reference to the HSSFWorkbook that 'contains' the
+ * cell.
+ * @param listItems An ArrayList whose elements encapsulate the text for
+ * the list's items.
+ * @param cell An instance of the HSSFCell class that encapsulates a
+ * reference to the spreadsheet cell into which the list
+ * will be written.
+ */
+ public void listInCell(HSSFWorkbook workbook, List<String> listItems, HSSFCell cell) {
+ StringBuilder buffer = new StringBuilder();
+ HSSFCellStyle wrapStyle = workbook.createCellStyle();
+ wrapStyle.setWrapText(true);
+ for(String listItem : listItems) {
+ buffer.append(listItem);
+ buffer.append("\n");
+ }
+ // The StringBuilder's contents are the source for the contents
+ // of the cell.
+ cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
+ cell.setCellStyle(wrapStyle);
+ }
+
+ /**
+ * Inserts a numbered list into a single cell.
+ *
+ * @param workbook A reference to the HSSFWorkbook that 'contains' the
+ * cell.
+ * @param listItems An ArrayList whose elements encapsulate the text for
+ * the lists items.
+ * @param cell An instance of the HSSFCell class that encapsulates a
+ * reference to the spreadsheet cell into which the list
+ * will be written.
+ * @param startingValue A primitive int containing the number for the first
+ * item in the list.
+ * @param increment A primitive int containing the value that should be used
+ * to calculate subsequent item numbers.
+ */
+ public void numberedListInCell(HSSFWorkbook workbook,
+ List<String> listItems,
+ HSSFCell cell,
+ int startingValue,
+ int increment) {
+ StringBuilder buffer = new StringBuilder();
+ int itemNumber = startingValue;
+ // Note that again, an HSSFCellStye object is required and that
+ // it's wrap text property should be set to 'true'
+ HSSFCellStyle wrapStyle = workbook.createCellStyle();
+ wrapStyle.setWrapText(true);
+ // Note that the basic method is identical to the listInCell() method
+ // with one difference; a number prefixed to the items text.
+ for(String listItem : listItems) {
+ buffer.append(itemNumber).append(". ");
+ buffer.append(listItem);
+ buffer.append("\n");
+ itemNumber += increment;
+ }
+ // The StringBuilder's contents are the source for the contents
+ // of the cell.
+ cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
+ cell.setCellStyle(wrapStyle);
+ }
+
+ /**
+ * Insert a bulleted list into a cell.
+ *
+ * @param workbook A reference to the HSSFWorkbook that 'contains' the
+ * cell.
+ * @param listItems An ArrayList whose elements encapsulate the text for
+ * the lists items.
+ * @param cell An instance of the HSSFCell class that encapsulates a
+ * reference to the spreadsheet cell into which the list
+ * will be written.
+ */
+ public void bulletedListInCell(HSSFWorkbook workbook,
+ List<String> listItems,
+ HSSFCell cell) {
+ StringBuilder buffer = new StringBuilder();
+ // Note that again, an HSSFCellStye object is required and that
+ // it's wrap text property should be set to 'true'
+ HSSFCellStyle wrapStyle = workbook.createCellStyle();
+ wrapStyle.setWrapText(true);
+ // Note that the basic method is identical to the listInCell() method
+ // with one difference; the bullet character prefixed to the items text.
+ for(String listItem : listItems) {
+ buffer.append(InCellLists.BULLET_CHARACTER + " ");
+ buffer.append(listItem);
+ buffer.append("\n");
+ }
+ // The StringBuilder's contents are the source for the contents
+ // of the cell.
+ cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
+ cell.setCellStyle(wrapStyle);
+ }
+
+ /**
+ * Insert a multi-level list into a cell.
+ *
+ * @param workbook A reference to the HSSFWorkbook that 'contains' the
+ * cell.
+ * @param multiLevelListItems An ArrayList whose elements contain instances
+ * of the MultiLevelListItem class. Each element
+ * encapsulates the text for the high level item
+ * along with an ArrayList. Each element of this
+ * ArrayList encapsulates the text for a lower
+ * level item.
+ * @param cell An instance of the HSSFCell class that encapsulates a
+ * reference to the spreadsheet cell into which the list
+ * will be written.
+ */
+ public void multiLevelListInCell(HSSFWorkbook workbook,
+ List<MultiLevelListItem> multiLevelListItems,
+ HSSFCell cell) {
+ StringBuilder buffer = new StringBuilder();
+ // Note that again, an HSSFCellStye object is required and that
+ // it's wrap text property should be set to 'true'
+ HSSFCellStyle wrapStyle = workbook.createCellStyle();
+ wrapStyle.setWrapText(true);
+ // Step through the ArrayList of MultilLevelListItem instances.
+ for(MultiLevelListItem multiLevelListItem : multiLevelListItems) {
+ // For each element in the ArrayList, get the text for the high
+ // level list item......
+ buffer.append(multiLevelListItem.getItemText());
+ buffer.append("\n");
+ // and then an ArrayList whose elements encapsulate the text
+ // for the lower level list items.
+ List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
+ if (lowerLevelItems == null || lowerLevelItems.isEmpty()) {
+ continue;
+ }
+ for(String item : lowerLevelItems) {
+ buffer.append(InCellLists.TAB);
+ buffer.append(item);
+ buffer.append("\n");
+ }
+ }
+ // The StringBuilder's contents are the source for the contents
+ // of the cell.
+ cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
+ cell.setCellStyle(wrapStyle);
+ }
+
+ /**
+ * Insert a multi-level list into a cell.
+ *
+ * @param workbook A reference to the HSSFWorkbook that 'contains' the
+ * cell.
+ * @param multiLevelListItems An ArrayList whose elements contain instances
+ * of the MultiLevelListItem class. Each element
+ * encapsulates the text for the high level item
+ * along with an ArrayList. Each element of this
+ * ArrayList encapsulates the text for a lower
+ * level item.
+ * @param cell An instance of the HSSFCell class that encapsulates a
+ * reference to the spreadsheet cell into which the list
+ * will be written.
+ * @param highLevelStartingValue A primitive int containing the number
+ * for the first high level item in the list.
+ * @param highLevelIncrement A primitive int containing the value that
+ * should be used to calculate the number of
+ * subsequent high level item.
+ * @param lowLevelStartingValue A primitive int will containing the number
+ * for the first low level item associated
+ * with a high level item.
+ * @param lowLevelIncrement A primitive int containing the value that
+ * should be used to calculate the number of
+ * subsequent low level item.
+ */
+ public void multiLevelNumberedListInCell(HSSFWorkbook workbook,
+ List<MultiLevelListItem> multiLevelListItems,
+ HSSFCell cell,
+ int highLevelStartingValue,
+ int highLevelIncrement,
+ int lowLevelStartingValue,
+ int lowLevelIncrement) {
+ StringBuilder buffer = new StringBuilder();
+ int highLevelItemNumber = highLevelStartingValue;
+ // Note that again, an HSSFCellStye object is required and that
+ // it's wrap text property should be set to 'true'
+ HSSFCellStyle wrapStyle = workbook.createCellStyle();
+ wrapStyle.setWrapText(true);
+ // Step through the ArrayList of MultilLevelListItem instances.
+ for(MultiLevelListItem multiLevelListItem : multiLevelListItems) {
+ // For each element in the ArrayList, get the text for the high
+ // level list item......
+ buffer.append(highLevelItemNumber);
+ buffer.append(". ");
+ buffer.append(multiLevelListItem.getItemText());
+ buffer.append("\n");
+ // and then an ArrayList whose elements encapsulate the text
+ // for the lower level list items.
+ List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
+ if(lowerLevelItems != null && !lowerLevelItems.isEmpty()) {
+ int lowLevelItemNumber = lowLevelStartingValue;
+ for(String item : lowerLevelItems) {
+ buffer.append(InCellLists.TAB);
+ buffer.append(highLevelItemNumber);
+ buffer.append(".");
+ buffer.append(lowLevelItemNumber);
+ buffer.append(" ");
+ buffer.append(item);
+ buffer.append("\n");
+ lowLevelItemNumber += lowLevelIncrement;
+ }
+ }
+ highLevelItemNumber += highLevelIncrement;
+ }
+ // The StringBuilder's contents are the source for the contents
+ // of the cell.
+ cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
+ cell.setCellStyle(wrapStyle);
+ }
+
+ /**
+ * Insert a bulleted multi-level list into a cell.
+ *
+ * @param workbook A reference to the HSSFWorkbook that 'contains' the
+ * cell.
+ * @param multiLevelListItems An ArrayList whose elements contain instances
+ * of the MultiLevelListItem class. Each element
+ * encapsulates the text for the high level item
+ * along with an ArrayList. Each element of this
+ * ArrayList encapsulates the text for a lower
+ * level item.
+ * @param cell An instance of the HSSFCell class that encapsulates a
+ * reference to the spreadsheet cell into which the list
+ * will be written.
+ */
+ public void multiLevelBulletedListInCell(HSSFWorkbook workbook,
+ List<MultiLevelListItem> multiLevelListItems,
+ HSSFCell cell) {
+ StringBuilder buffer = new StringBuilder();
+ // Note that again, an HSSFCellStye object is required and that
+ // it's wrap text property should be set to 'true'
+ HSSFCellStyle wrapStyle = workbook.createCellStyle();
+ wrapStyle.setWrapText(true);
+ // Step through the ArrayList of MultilLevelListItem instances.
+ for(MultiLevelListItem multiLevelListItem : multiLevelListItems) {
+ // For each element in the ArrayList, get the text for the high
+ // level list item......
+ buffer.append(InCellLists.BULLET_CHARACTER);
+ buffer.append(" ");
+ buffer.append(multiLevelListItem.getItemText());
+ buffer.append("\n");
+ // and then an ArrayList whose elements encapsulate the text
+ // for the lower level list items.
+ List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
+ if(lowerLevelItems != null && !lowerLevelItems.isEmpty()) {
+ for(String item : lowerLevelItems) {
+ buffer.append(InCellLists.TAB);
+ buffer.append(InCellLists.BULLET_CHARACTER);
+ buffer.append(" ");
+ buffer.append(item);
+ buffer.append("\n");
+ }
+ }
+ }
+ // The StringBuilder's contents are the source for the contents
+ // of the cell.
+ cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
+ cell.setCellStyle(wrapStyle);
+ }
+
+ /**
+ * The main entry point to the program. Demonstrates how to call the method
+ * that will create an Excel workbook containing many different sorts of
+ * lists.
+ *
+ * @param args the command line arguments.
+ */
+ public static void main(String[] args) throws IOException {
+ new InCellLists().demonstrateMethodCalls("Latest In Cell List.xls");
+ }
+
+ /**
+ * An instance of this inner class models an item or element in a
+ * multi-level list. Each multi-level list item consists of the text for the
+ * high level items and an ArrayList containing the text for each of the
+ * associated lower level items. When written into a cell, each multi-level
+ * list item will have this general appearance.
+ *
+ * Item One
+ * Sub Item One.
+ * Sub Item Two.
+ * Item Two
+ * Sub Item One.
+ * Sub Item Two.
+ * etc.
+ *
+ * It would be quite possible to modify this class to model much more
+ * complex list structures descending through two, three or even more
+ * levels.
+ */
+ public final class MultiLevelListItem {
+
+ private String itemText;
+ private List<String> lowerLevelItems;
+
+ /**
+ * Create a new instance of the MultiLevelListItem class using the
+ * following parameters.
+ *
+ * @param itemText A String that encapsulates the text for the high
+ * level list item.
+ * @param lowerLevelItems An ArrayList whose elements encapsulate the
+ * text for the associated lower level list
+ * items.
+ */
+ public MultiLevelListItem(String itemText, List<String> lowerLevelItems) {
+ this.itemText = itemText;
+ this.lowerLevelItems = lowerLevelItems;
+ }
+
+ /**
+ * Get the text for the high level list item.
+ *
+ * @return A String that encapsulates the text for the high level list
+ * item.
+ */
+ public String getItemText() {
+ return(this.itemText);
+ }
+
+ /**
+ * Get the text for the associated lower level list items.
+ *
+ * @return An ArrayList whose elements each encapsulate the text for a
+ * single associated lower level list item.
+ */
+ public List<String> getLowerLevelItems() {
+ return lowerLevelItems;
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+/**
+ * An example of how to merge regions of cells.
+ */
+public class MergedCells {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+
+ HSSFRow row = sheet.createRow(1);
+ HSSFCell cell = row.createCell(1);
+ cell.setCellValue("This is a test of merging");
+
+ sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, 2));
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Demonstrates how to use newlines in cells.
+ */
+public class NewLinesInCells {
+ public static void main( String[] args ) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet s = wb.createSheet();
+ HSSFFont f2 = wb.createFont();
+
+ HSSFCellStyle cs = wb.createCellStyle();
+
+ cs.setFont(f2);
+ // Word Wrap MUST be turned on
+ cs.setWrapText(true);
+
+ HSSFRow r = s.createRow(2);
+ r.setHeight((short) 0x349);
+ HSSFCell c = r.createCell(2);
+ c.setCellValue("Use \n with word wrap on to create a new line");
+ c.setCellStyle(cs);
+ s.setColumnWidth(2, (int) ((50 * 8) / ((double) 1 / 20)));
+
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.util.WorkbookUtil;
+
+/**
+ * Creates a new workbook with a sheet that's been explicitly defined.
+ */
+public abstract class NewSheet {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ wb.createSheet("new sheet");
+ // create with default name
+ wb.createSheet();
+ final String name = "second sheet";
+ // setting sheet name later
+ wb.setSheetName(1, WorkbookUtil.createSafeSheetName(name));
+
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * This example creates a new blank workbook. This workbook will contain a single blank sheet.
+ */
+public class NewWorkbook {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFChildAnchor;
+import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFPatriarch;
+import org.apache.poi.hssf.usermodel.HSSFPicture;
+import org.apache.poi.hssf.usermodel.HSSFPolygon;
+import org.apache.poi.hssf.usermodel.HSSFRichTextString;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFShape;
+import org.apache.poi.hssf.usermodel.HSSFShapeGroup;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFSimpleShape;
+import org.apache.poi.hssf.usermodel.HSSFTextbox;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.Workbook;
+
+/**
+ * Demonstrates how to use the office drawing capabilities of POI.
+ */
+public final class OfficeDrawing {
+ private OfficeDrawing() {}
+
+ public static void main(String[] args) throws IOException {
+ // Create the workbook and sheets.
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+ HSSFSheet sheet2 = wb.createSheet("second sheet");
+ HSSFSheet sheet3 = wb.createSheet("third sheet");
+ HSSFSheet sheet4 = wb.createSheet("fourth sheet");
+ HSSFSheet sheet5 = wb.createSheet("fifth sheet");
+
+ // Draw stuff in them
+ drawSheet1(sheet1);
+ drawSheet2(sheet2);
+ drawSheet3(sheet3);
+ drawSheet4(sheet4, wb);
+ drawSheet5(sheet5, wb);
+
+ // Write the file out.
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ private static void drawSheet1( HSSFSheet sheet1 )
+ {
+ // Create a row and size one of the cells reasonably large.
+ HSSFRow row = sheet1.createRow(2);
+ row.setHeight((short) 2800);
+ row.createCell(1);
+ sheet1.setColumnWidth(2, 9000);
+
+ // Create the drawing patriarch. This is the top level container for
+ // all shapes.
+ HSSFPatriarch patriarch = sheet1.createDrawingPatriarch();
+
+ // Draw some lines and an oval.
+ drawLinesToCenter( patriarch );
+ drawManyLines( patriarch );
+ drawOval( patriarch );
+ drawPolygon( patriarch );
+
+ // Draw a rectangle.
+ HSSFSimpleShape rect = patriarch.createSimpleShape( new HSSFClientAnchor(100, 100, 900, 200, (short)0, 0, (short)0, 0) );
+ rect.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
+ }
+
+ private static void drawSheet2( HSSFSheet sheet2 )
+ {
+ // Create a row and size one of the cells reasonably large.
+ HSSFRow row = sheet2.createRow(2);
+ row.createCell(1);
+ row.setHeightInPoints(240);
+ sheet2.setColumnWidth(2, 9000);
+
+ // Create the drawing patriarch. This is the top level container for
+ // all shapes. This will clear out any existing shapes for that sheet.
+ HSSFPatriarch patriarch = sheet2.createDrawingPatriarch();
+
+ // Draw a grid in one of the cells.
+ drawGrid( patriarch );
+ }
+
+ private static void drawSheet3( HSSFSheet sheet3 )
+ {
+ // Create a row and size one of the cells reasonably large
+ HSSFRow row = sheet3.createRow(2);
+ row.setHeightInPoints(140);
+ row.createCell(1);
+ sheet3.setColumnWidth(2, 9000);
+
+ // Create the drawing patriarch. This is the top level container for
+ // all shapes. This will clear out any existing shapes for that sheet.
+ HSSFPatriarch patriarch = sheet3.createDrawingPatriarch();
+
+ // Create a shape group.
+ HSSFShapeGroup group = patriarch.createGroup(
+ new HSSFClientAnchor(0,0,900,200,(short)2,2,(short)2,2));
+
+ // Create a couple of lines in the group.
+ HSSFSimpleShape shape1 = group.createShape(new HSSFChildAnchor(3,3,500,500));
+ shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+ ( (HSSFChildAnchor) shape1.getAnchor() ).setAnchor((short)3,3,500,500);
+ HSSFSimpleShape shape2 = group.createShape(new HSSFChildAnchor((short)1,200,400,600));
+ shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+
+ }
+
+ private static void drawSheet4( HSSFSheet sheet4, HSSFWorkbook wb )
+ {
+ // Create the drawing patriarch. This is the top level container for
+ // all shapes. This will clear out any existing shapes for that sheet.
+ HSSFPatriarch patriarch = sheet4.createDrawingPatriarch();
+
+ // Create a couple of textboxes
+ HSSFTextbox textbox1 = patriarch.createTextbox(
+ new HSSFClientAnchor(0,0,0,0,(short)1,1,(short)2,2));
+ textbox1.setString(new HSSFRichTextString("This is a test") );
+ HSSFTextbox textbox2 = patriarch.createTextbox(
+ new HSSFClientAnchor(0,0,900,100,(short)3,3,(short)3,4));
+ textbox2.setString(new HSSFRichTextString("Woo") );
+ textbox2.setFillColor(200,0,0);
+ textbox2.setLineStyle(HSSFShape.LINESTYLE_DOTGEL);
+
+ // Create third one with some fancy font styling.
+ HSSFTextbox textbox3 = patriarch.createTextbox(
+ new HSSFClientAnchor(0,0,900,100,(short)4,4,(short)5,4+1));
+ HSSFFont font = wb.createFont();
+ font.setItalic(true);
+ font.setUnderline(Font.U_DOUBLE);
+ HSSFRichTextString string = new HSSFRichTextString("Woo!!!");
+ string.applyFont(2,5,font);
+ textbox3.setString(string );
+ textbox3.setFillColor(0x08000030);
+ textbox3.setLineStyle(HSSFShape.LINESTYLE_NONE); // no line around the textbox.
+ textbox3.setNoFill(true); // make it transparent
+ }
+
+ private static void drawSheet5( HSSFSheet sheet5, HSSFWorkbook wb ) throws IOException
+ {
+
+ // Create the drawing patriarch. This is the top level container for
+ // all shapes. This will clear out any existing shapes for that sheet.
+ HSSFPatriarch patriarch = sheet5.createDrawingPatriarch();
+
+ HSSFClientAnchor anchor;
+ anchor = new HSSFClientAnchor(0,0,0,255,(short)2,2,(short)4,7);
+ anchor.setAnchorType( AnchorType.MOVE_DONT_RESIZE );
+ patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4.png", wb ));
+
+ anchor = new HSSFClientAnchor(0,0,0,255,(short)4,2,(short)5,7);
+ anchor.setAnchorType( AnchorType.MOVE_DONT_RESIZE );
+ patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4edited.png", wb ));
+
+ anchor = new HSSFClientAnchor(0,0,1023,255,(short)6,2,(short)8,7);
+ anchor.setAnchorType( AnchorType.MOVE_DONT_RESIZE );
+ HSSFPicture picture = patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4s.png", wb ));
+ //Reset the image to the original size.
+ picture.resize();
+ picture.setLineStyle( HSSFShape.LINESTYLE_DASHDOTGEL );
+
+ }
+
+ private static int loadPicture( String path, HSSFWorkbook wb ) throws IOException
+ {
+ int pictureIndex;
+ try (FileInputStream fis = new FileInputStream(path);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
+ int c;
+ while ((c = fis.read()) != -1)
+ bos.write(c);
+ pictureIndex = wb.addPicture(bos.toByteArray(), Workbook.PICTURE_TYPE_PNG);
+ }
+ return pictureIndex;
+ }
+
+ private static void drawOval( HSSFPatriarch patriarch )
+ {
+ // Create an oval and style to taste.
+ HSSFClientAnchor a = new HSSFClientAnchor();
+ a.setAnchor((short)2, 2, 20, 20, (short) 2, 2, 190, 80);
+ HSSFSimpleShape s = patriarch.createSimpleShape(a);
+ s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_OVAL);
+ s.setLineStyleColor(10,10,10);
+ s.setFillColor(90,10,200);
+ s.setLineWidth(HSSFShape.LINEWIDTH_ONE_PT * 3);
+ s.setLineStyle(HSSFShape.LINESTYLE_DOTSYS);
+ }
+
+ private static void drawPolygon( HSSFPatriarch patriarch )
+ {
+ // HSSFClientAnchor a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 2, 2, (short) 3, 3 );
+ // HSSFPolygon p = patriarch.createPolygon(a);
+ // p.setPolygonDrawArea(100,100);
+ // p.setPoints( new int[]{30, 90, 50}, new int[]{88, 5, 44} );
+
+
+ HSSFClientAnchor a = new HSSFClientAnchor();
+ a.setAnchor( (short) 2, 2, 0, 0, (short) 3, 3, 1023, 255 );
+ HSSFShapeGroup g = patriarch.createGroup( a );
+ g.setCoordinates(0,0,200,200);
+ HSSFPolygon p1 = g.createPolygon( new HSSFChildAnchor( 0, 0, 200, 200 ) );
+ p1.setPolygonDrawArea( 100, 100 );
+ p1.setPoints( new int[]{0, 90, 50}, new int[]{5, 5, 44} );
+ p1.setFillColor( 0, 255, 0 );
+ HSSFPolygon p2 = g.createPolygon( new HSSFChildAnchor( 20, 20, 200, 200 ) );
+ p2.setPolygonDrawArea( 200, 200 );
+ p2.setPoints( new int[]{120, 20, 150}, new int[]{105, 30, 195} );
+ p2.setFillColor( 255, 0, 0 );
+ }
+
+ private static void drawManyLines( HSSFPatriarch patriarch )
+ {
+ // Draw bunch of lines
+ int x1 = 100;
+ int y1 = 100;
+ int x2 = 800;
+ int y2 = 200;
+ int color = 0;
+ for (int i = 0; i < 10; i++)
+ {
+ HSSFClientAnchor a2 = new HSSFClientAnchor();
+ a2.setAnchor((short) 2, 2, x1, y1, (short) 2, 2, x2, y2);
+ HSSFSimpleShape shape2 = patriarch.createSimpleShape(a2);
+ shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+ shape2.setLineStyleColor(color);
+ y1 -= 10;
+ y2 -= 10;
+ color += 30;
+ }
+ }
+
+ private static void drawGrid( HSSFPatriarch patriarch )
+ {
+ // This draws a grid of lines. Since the coordinates space fixed at
+ // 1024 by 256 we use a ratio to get a reasonably square grids.
+
+ double xRatio = 3.22;
+ double yRatio = 0.6711;
+
+ int x1 = 0;
+ int y1 = 0;
+ int x2 = 0;
+ int y2 = 200;
+ for (int i = 0; i < 20; i++)
+ {
+ HSSFClientAnchor a2 = new HSSFClientAnchor();
+ a2.setAnchor((short) 2, 2, (int) ( x1 * xRatio ), (int) ( y1 * yRatio ),
+ (short) 2, 2, (int) ( x2 * xRatio ), (int) ( y2 * yRatio ));
+ HSSFSimpleShape shape2 = patriarch.createSimpleShape(a2);
+ shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+
+ x1 += 10;
+ x2 += 10;
+ }
+
+ x1 = 0;
+ y1 = 0;
+ x2 = 200;
+ y2 = 0;
+ for (int i = 0; i < 20; i++)
+ {
+ HSSFClientAnchor a2 = new HSSFClientAnchor();
+ a2.setAnchor((short) 2, 2, (int) ( x1 * xRatio ), (int) ( y1 * yRatio ),
+ (short) 2, 2, (int) ( x2 * xRatio ), (int) ( y2 * yRatio ));
+ HSSFSimpleShape shape2 = patriarch.createSimpleShape(a2);
+ shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+
+ y1 += 10;
+ y2 += 10;
+ }
+ }
+
+ private static void drawLinesToCenter( HSSFPatriarch patriarch )
+ {
+ // Draw some lines from and to the corners
+ {
+ HSSFClientAnchor a1 = new HSSFClientAnchor();
+ a1.setAnchor( (short)2, 2, 0, 0, (short) 2, 2, 512, 128);
+ HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
+ shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+ }
+ {
+ HSSFClientAnchor a1 = new HSSFClientAnchor();
+ a1.setAnchor( (short)2, 2, 512, 128, (short) 2, 2, 1024, 0);
+ HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
+ shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+ }
+ {
+ HSSFClientAnchor a1 = new HSSFClientAnchor();
+ a1.setAnchor( (short)1, 1, 0, 0, (short) 1, 1, 512, 100);
+ HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
+ shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+ }
+ {
+ HSSFClientAnchor a1 = new HSSFClientAnchor();
+ a1.setAnchor( (short)1, 1, 512, 100, (short) 1, 1, 1024, 0);
+ HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
+ shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
+ }
+
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.RenderingHints;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.EscherGraphics;
+import org.apache.poi.hssf.usermodel.EscherGraphics2d;
+import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
+import org.apache.poi.hssf.usermodel.HSSFPatriarch;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFShapeGroup;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Demonstrates the use of the EscherGraphics2d library.
+ *
+ * @author Glen Stampoultzis (glens at apache.org)
+ */
+public class OfficeDrawingWithGraphics {
+ public static void main( String[] args ) throws IOException {
+ // Create a workbook with one sheet and size the first three somewhat
+ // larger so we can fit the chemical structure diagram in.
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("my drawing");
+ sheet.setColumnWidth(1, 256 * 27);
+ HSSFRow row1 = sheet.createRow(0);
+ row1.setHeightInPoints(10 * 15f);
+ HSSFRow row2 = sheet.createRow(1);
+ row2.setHeightInPoints(5 * 15f);
+ HSSFRow row3 = sheet.createRow(2);
+ row3.setHeightInPoints(10 * 15f);
+
+ // Add some cells so we can test that the anchoring works when we
+ // sort them.
+ row1.createCell(0).setCellValue("C");
+ row2.createCell(0).setCellValue("A");
+ row3.createCell(0).setCellValue("B");
+
+ // Create the top level drawing patriarch.
+ HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
+
+ HSSFClientAnchor a;
+ HSSFShapeGroup group;
+ EscherGraphics g;
+ EscherGraphics2d g2d;
+ // Anchor entirely within one cell.
+ a = new HSSFClientAnchor(0, 0, 1023, 255, (short) 1, 0, (short) 1, 0);
+ group = patriarch.createGroup(a);
+ group.setCoordinates(0, 0, 320, 276);
+ float verticalPointsPerPixel = a.getAnchorHeightInPoints(sheet) / Math.abs(group.getY2() - group.getY1());
+ g = new EscherGraphics(group, wb, Color.black, verticalPointsPerPixel);
+ g2d = new EscherGraphics2d(g);
+ drawStar(g2d);
+
+ a = new HSSFClientAnchor(0, 0, 1023, 255, (short) 1, 1, (short) 1, 1);
+ group = patriarch.createGroup(a);
+ group.setCoordinates(0, 0, 640, 276);
+ verticalPointsPerPixel = a.getAnchorHeightInPoints(sheet) / Math.abs(group.getY2() - group.getY1());
+// verticalPixelsPerPoint = (float)Math.abs(group.getY2() - group.getY1()) / a.getAnchorHeightInPoints(sheet);
+ g = new EscherGraphics(group, wb, Color.black, verticalPointsPerPixel);
+ g2d = new EscherGraphics2d(g);
+ drawStar(g2d);
+
+ try (FileOutputStream out = new FileOutputStream("workbook.xls")) {
+ wb.write(out);
+ }
+ }
+ }
+
+ private static void drawStar( EscherGraphics2d g2d )
+ {
+ g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
+ for (double i = 0; i < Math.PI; i += 0.1)
+ {
+ g2d.setColor( new Color((int)(i * 5343062d) ) );
+ int x1 = (int) ( Math.cos(i) * 160.0 ) + 160;
+ int y1 = (int) ( Math.sin(i) * 138.0 ) + 138;
+ int x2 = (int) ( -Math.cos(i) * 160.0 ) + 160;
+ int y2 = (int) ( -Math.sin(i) * 138.0 ) + 138;
+ g2d.setStroke(new BasicStroke(2));
+ g2d.drawLine(x1,y1,x2,y2);
+ }
+ g2d.setFont(new Font("SansSerif",Font.BOLD | Font.ITALIC, 20));
+ g2d.drawString("EscherGraphics2d",70,100);
+ g2d.setColor(Color.yellow);
+ g2d.fillOval( 160-20,138-20,40,40);
+ g2d.setColor(Color.black);
+ g2d.fillPolygon(new int[] {-10+160,0+160,10+160,0+160}, new int[] {0+138,10+138,0+138,-10+138}, 4);
+ g2d.drawPolygon(new int[] {-160+160,0+160,160+160,0+160}, new int[] {0+138,138+138,0+138,-138+138}, 4);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.Closeable;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ * Creates outlines.
+ */
+public class Outlines implements Closeable {
+ public static void main(String[] args)
+ throws IOException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ POILogger LOGGER = POILogFactory.getLogger(Outlines.class);
+ for (int i=1; i<=13; i++) {
+ try (Outlines o = new Outlines()) {
+ String log = (String) Outlines.class.getDeclaredMethod("test" + i).invoke(o);
+ String filename = "outline" + i + ".xls";
+ o.writeOut(filename);
+ LOGGER.log(POILogger.INFO, filename + " written. " + log);
+ }
+ }
+ }
+
+ private final HSSFWorkbook wb = new HSSFWorkbook();
+ private final HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ public void writeOut(String filename) throws IOException {
+ try (FileOutputStream fileOut = new FileOutputStream(filename)) {
+ wb.write(fileOut);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ wb.close();
+ }
+
+ public String test1() {
+ sheet1.groupColumn(4, 7);
+
+ for (int row = 0; row < 200; row++) {
+ HSSFRow r = sheet1.createRow(row);
+ for (int column = 0; column < 200; column++) {
+ HSSFCell c = r.createCell(column);
+ c.setCellValue(column);
+ }
+ }
+ return "Two expanded groups.";
+ }
+
+ public String test2() {
+ sheet1.groupColumn(2, 10);
+ sheet1.groupColumn(4, 7);
+ sheet1.setColumnGroupCollapsed(4, true);
+ return "Two groups. Inner group collapsed.";
+ }
+
+ public String test3() {
+ sheet1.groupColumn(2, 10);
+ sheet1.groupColumn(4, 7);
+ sheet1.setColumnGroupCollapsed(4, true);
+ sheet1.setColumnGroupCollapsed(2, true);
+ return "Two groups. Both collapsed.";
+ }
+
+ public String test4() {
+ sheet1.groupColumn(2, 10);
+ sheet1.groupColumn(4, 7);
+ sheet1.setColumnGroupCollapsed(4, true);
+ sheet1.setColumnGroupCollapsed(2, true);
+
+ sheet1.setColumnGroupCollapsed(4, false);
+ return "Two groups. Collapsed then inner group expanded.";
+ }
+
+ public String test5() {
+ sheet1.groupColumn(2, 10);
+ sheet1.groupColumn(4, 7);
+ sheet1.setColumnGroupCollapsed(4, true);
+ sheet1.setColumnGroupCollapsed(2, true);
+
+ sheet1.setColumnGroupCollapsed(4, false);
+ sheet1.setColumnGroupCollapsed(3, false);
+ return "Two groups. Collapsed then reexpanded.";
+ }
+
+ public String test6() {
+ sheet1.groupColumn(2, 10);
+ sheet1.groupColumn(4, 10);
+ sheet1.setColumnGroupCollapsed(4, true);
+ sheet1.setColumnGroupCollapsed(2, true);
+
+ sheet1.setColumnGroupCollapsed(3, false);
+ return "Two groups with matching end points. Second group collapsed.";
+ }
+
+ public String test7() {
+ sheet1.groupRow(5, 14);
+ sheet1.groupRow(7, 10);
+ return "Row outlines.";
+ }
+
+ public String test8() {
+ sheet1.groupRow(5, 14);
+ sheet1.groupRow(7, 10);
+ sheet1.setRowGroupCollapsed(7, true);
+ return "Row outlines. Inner group collapsed.";
+ }
+
+ public String test9() {
+ sheet1.groupRow(5, 14);
+ sheet1.groupRow(7, 10);
+ sheet1.setRowGroupCollapsed(7, true);
+ sheet1.setRowGroupCollapsed(5, true);
+ return "Row outlines. Both collapsed.";
+ }
+
+ public String test10() {
+ sheet1.groupRow(5, 14);
+ sheet1.groupRow(7, 10);
+ sheet1.setRowGroupCollapsed(7, true);
+ sheet1.setRowGroupCollapsed(5, true);
+ sheet1.setRowGroupCollapsed(8, false);
+ return "Row outlines. Collapsed then inner group expanded.";
+ }
+
+ public String test11() {
+ sheet1.groupRow(5, 14);
+ sheet1.groupRow(7, 10);
+ sheet1.setRowGroupCollapsed(7, true);
+ sheet1.setRowGroupCollapsed(5, true);
+ sheet1.setRowGroupCollapsed(8, false);
+ sheet1.setRowGroupCollapsed(14, false);
+ return "Row outlines. Collapsed then expanded.";
+ }
+
+ public String test12() {
+ sheet1.groupRow(5, 14);
+ sheet1.groupRow(7, 14);
+ sheet1.setRowGroupCollapsed(7, true);
+ sheet1.setRowGroupCollapsed(5, true);
+ sheet1.setRowGroupCollapsed(6, false);
+ return "Row outlines. Two row groups with matching end points. Second group collapsed.";
+ }
+
+ public String test13() {
+ sheet1.groupRow(5, 14);
+ sheet1.groupRow(7, 14);
+ sheet1.groupRow(16, 19);
+
+ sheet1.groupColumn(4, 7);
+ sheet1.groupColumn(9, 12);
+ sheet1.groupColumn(10, 11);
+ return "Mixed bag.";
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+/**
+ * This example demonstrates opening a workbook, modifying it and writing
+ * the results back out.
+ *
+ * @author Glen Stampoultzis (glens at apache.org)
+ */
+public class ReadWriteWorkbook {
+ public static void main(String[] args) throws IOException {
+ try (FileInputStream fileIn = new FileInputStream("workbook.xls")) {
+ POIFSFileSystem fs = new POIFSFileSystem(fileIn);
+ HSSFWorkbook wb = new HSSFWorkbook(fs);
+ HSSFSheet sheet = wb.getSheetAt(0);
+ HSSFRow row = sheet.getRow(2);
+ if (row == null)
+ row = sheet.createRow(2);
+ HSSFCell cell = row.getCell(3);
+ if (cell == null)
+ cell = row.createCell(3);
+ cell.setCellValue("a test");
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbookout.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+public class RepeatingRowsAndColumns {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet1 = wb.createSheet("first sheet");
+ HSSFSheet sheet2 = wb.createSheet("second sheet");
+ HSSFSheet sheet3 = wb.createSheet("third sheet");
+
+ HSSFFont boldFont = wb.createFont();
+ boldFont.setFontHeightInPoints((short) 22);
+ boldFont.setBold(true);
+
+ HSSFCellStyle boldStyle = wb.createCellStyle();
+ boldStyle.setFont(boldFont);
+
+ HSSFRow row = sheet1.createRow(1);
+ HSSFCell cell = row.createCell(0);
+ cell.setCellValue("This quick brown fox");
+ cell.setCellStyle(boldStyle);
+
+ // Set the columns to repeat from column 0 to 2 on the first sheet
+ sheet1.setRepeatingColumns(CellRangeAddress.valueOf("A:C"));
+ // Set the rows to repeat from row 0 to 2 on the second sheet.
+ sheet2.setRepeatingRows(CellRangeAddress.valueOf("1:3"));
+ // Set the the repeating rows and columns on the third sheet.
+ CellRangeAddress cra = CellRangeAddress.valueOf("D1:E2");
+ sheet3.setRepeatingColumns(cra);
+ sheet3.setRepeatingRows(cra);
+
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Sheet;
+
+public class SplitAndFreezePanes {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+ HSSFSheet sheet2 = wb.createSheet("second sheet");
+ HSSFSheet sheet3 = wb.createSheet("third sheet");
+ HSSFSheet sheet4 = wb.createSheet("fourth sheet");
+
+ // Freeze just one row
+ sheet1.createFreezePane(0, 1, 0, 1);
+ // Freeze just one column
+ sheet2.createFreezePane(1, 0, 1, 0);
+ // Freeze the columns and rows (forget about scrolling position of the lower right quadrant).
+ sheet3.createFreezePane(2, 2);
+ // Create a split with the lower left side being the active quadrant
+ sheet4.createSplitPane(2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT);
+
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Demonstrates how to create and use fonts.
+ */
+public class WorkingWithFonts {
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("new sheet");
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ HSSFRow row = sheet.createRow(1);
+
+ // Create a new font and alter it.
+ HSSFFont font = wb.createFont();
+ font.setFontHeightInPoints((short) 24);
+ font.setFontName("Courier New");
+ font.setItalic(true);
+ font.setStrikeout(true);
+
+ // Fonts are set into a style so create a new one to use.
+ HSSFCellStyle style = wb.createCellStyle();
+ style.setFont(font);
+
+ // Create a cell and put a value in it.
+ HSSFCell cell = row.createCell(1);
+ cell.setCellValue("This is a test of fonts");
+ cell.setCellStyle(style);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+
+/* ====================================================================
+ 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.examples.hssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Sets the zoom magnication for a sheet.
+ *
+ * @author Glen Stampoultzis (glens at apache.org)
+ */
+public class ZoomSheet
+{
+ public static void main(String[] args) throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+ sheet1.setZoom(75); // 75 percent magnification
+
+ try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.hwpf;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.model.StyleDescription;
+import org.apache.poi.hwpf.model.StyleSheet;
+import org.apache.poi.hwpf.usermodel.CharacterRun;
+import org.apache.poi.hwpf.usermodel.Paragraph;
+import org.apache.poi.hwpf.usermodel.Range;
+
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class Word2Forrest
+{
+ Writer _out;
+ HWPFDocument _doc;
+
+ @SuppressWarnings("unused")
+ public Word2Forrest(HWPFDocument doc, OutputStream stream) throws IOException
+ {
+ _out = new OutputStreamWriter (stream, StandardCharsets.UTF_8);
+ _doc = doc;
+
+ init ();
+ openDocument ();
+ openBody ();
+
+ Range r = doc.getRange ();
+ StyleSheet styleSheet = doc.getStyleSheet ();
+
+ int sectionLevel = 0;
+ int lenParagraph = r.numParagraphs ();
+ boolean inCode = false;
+ for (int x = 0; x < lenParagraph; x++)
+ {
+ Paragraph p = r.getParagraph (x);
+ String text = p.text ();
+ if (text.trim ().length () == 0)
+ {
+ continue;
+ }
+ StyleDescription paragraphStyle = styleSheet.getStyleDescription (p.
+ getStyleIndex ());
+ String styleName = paragraphStyle.getName();
+ if (styleName.startsWith ("Heading"))
+ {
+ if (inCode)
+ {
+ closeSource();
+ inCode = false;
+ }
+
+ int headerLevel = Integer.parseInt (styleName.substring (8));
+ if (headerLevel > sectionLevel)
+ {
+ openSection ();
+ }
+ else
+ {
+ for (int y = 0; y < (sectionLevel - headerLevel) + 1; y++)
+ {
+ closeSection ();
+ }
+ openSection ();
+ }
+ sectionLevel = headerLevel;
+ openTitle ();
+ writePlainText (text);
+ closeTitle ();
+ }
+ else
+ {
+ int cruns = p.numCharacterRuns ();
+ CharacterRun run = p.getCharacterRun (0);
+ String fontName = run.getFontName();
+ if (fontName.startsWith ("Courier"))
+ {
+ if (!inCode)
+ {
+ openSource ();
+ inCode = true;
+ }
+ writePlainText (p.text());
+ }
+ else
+ {
+ if (inCode)
+ {
+ inCode = false;
+ closeSource();
+ }
+ openParagraph();
+ writePlainText(p.text());
+ closeParagraph();
+ }
+ }
+ }
+ for (int x = 0; x < sectionLevel; x++)
+ {
+ closeSection();
+ }
+ closeBody();
+ closeDocument();
+ _out.flush();
+
+ }
+
+ public void init ()
+ throws IOException
+ {
+ _out.write ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
+ _out.write ("<!DOCTYPE document PUBLIC \"-//APACHE//DTD Documentation V1.1//EN\" \"./dtd/document-v11.dtd\">\r\n");
+ }
+
+ public void openDocument ()
+ throws IOException
+ {
+ _out.write ("<document>\r\n");
+ }
+ public void closeDocument ()
+ throws IOException
+ {
+ _out.write ("</document>\r\n");
+ }
+
+
+ public void openBody ()
+ throws IOException
+ {
+ _out.write ("<body>\r\n");
+ }
+
+ public void closeBody ()
+ throws IOException
+ {
+ _out.write ("</body>\r\n");
+ }
+
+
+ public void openSection ()
+ throws IOException
+ {
+ _out.write ("<section>");
+
+ }
+
+ public void closeSection ()
+ throws IOException
+ {
+ _out.write ("</section>");
+
+ }
+
+ public void openTitle ()
+ throws IOException
+ {
+ _out.write ("<title>");
+ }
+
+ public void closeTitle ()
+ throws IOException
+ {
+ _out.write ("</title>");
+ }
+
+ public void writePlainText (String text)
+ throws IOException
+ {
+ _out.write (text);
+ }
+
+ public void openParagraph ()
+ throws IOException
+ {
+ _out.write ("<p>");
+ }
+
+ public void closeParagraph ()
+ throws IOException
+ {
+ _out.write ("</p>");
+ }
+
+ public void openSource ()
+ throws IOException
+ {
+ _out.write ("<source><![CDATA[");
+ }
+ public void closeSource ()
+ throws IOException
+ {
+ _out.write ("]]></source>");
+ }
+
+
+ public static void main(String[] args) throws IOException {
+ try (InputStream is = new FileInputStream(args[0]);
+ OutputStream out = new FileOutputStream("test.xml")) {
+ new Word2Forrest(new HWPFDocument(is), out);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Locale;
+
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.util.IOUtils;
+
+
+/**
+ * Demonstrates how to add an image to a worksheet and set that images size
+ * to a specific number of millimetres irrespective of the width of the columns
+ * or height of the rows. Overridden methods are provided so that the location
+ * of the image - the cells row and column coordinates that define the top
+ * left hand corners of the image - can be identified either in the familiar
+ * Excel manner - A1 for instance - or using POI's methodology of a column and
+ * row index where 0, 0 would indicate cell A1.
+ *
+ * The best way to make use of these techniques is to delay adding the image to
+ * the sheet until all other work has been completed. That way, the sizes of
+ * all rows and columns will have been adjusted - assuming that step was
+ * necessary. Even though the anchors type is set to prevent the image moving
+ * or re-sizing, this setting does not have any effect until the sheet is being
+ * viewed using the Excel application.
+ *
+ * The key to the process is the ClientAnchor class. It defines methods that allow
+ * us to define the location of an image by specifying the following;
+ *
+ * * How far - in terms of coordinate positions - the image should be inset
+ * from the left hand border of a cell.
+ * * How far - in terms of coordinate positions - the image should be inset
+ * from the from the top of the cell.
+ * * How far - in terms of coordinate positions - the right hand edge of
+ * the image should protrude into a cell (measured from the cells left hand
+ * edge to the images right hand edge).
+ * * How far - in terms of coordinate positions - the bottom edge of the
+ * image should protrude into a row (measured from the cells top edge to
+ * the images bottom edge).
+ * * The index of the column that contains the cell whose top left hand
+ * corner should be aligned with the top left hand corner of the image.
+ * * The index of the row that contains the cell whose top left hand corner
+ * should be aligned with the images top left hand corner.
+ * * The index of the column that contains the cell whose top left hand
+ * corner should be aligned with the images bottom right hand corner
+ * * The index number of the row that contains the cell whose top left
+ * hand corner should be aligned with the images bottom right hand corner.
+ *
+ * It can be used to add an image into cell A1, for example, in the following
+ * manner;
+ *
+ * ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();
+ *
+ * anchor.setDx1(0);
+ * anchor.setDy1(0);
+ * anchor.setDx2(0);
+ * anchor.setDy2(0);
+ * anchor.setCol1(0);
+ * anchor.setRow1(0);
+ * anchor.setCol2(1);
+ * anchor.setRow2(1);
+ *
+ * Taken together, the first four methods define the locations of the top left
+ * and bottom right hand corners of the image if you imagine that the image is
+ * represented by a simple rectangle. The setDx1() and setDy1() methods locate
+ * the top left hand corner of the image while setDx2() and and Dy2() locate the
+ * bottom right hand corner of the image. An individual image can be inserted
+ * into a single cell or is can lie across many cells and the latter four methods
+ * are used to define just where the image should be positioned. They do this by
+ * again by identifying where the top left and bottom right hand corners of the
+ * image should be located but this time in terms of the indexes of the cells
+ * in which those corners should be located. The setCol1() and setRow1() methods
+ * together identify the cell that should contain the top left hand corner of
+ * the image while setCol2() and setRow2() do the same for the images bottom
+ * right hand corner.
+ *
+ * Knowing that, it is possible to look again at the example above and to see
+ * that the top left hand corner of the image will be located in cell A1 (0, 0)
+ * and it will be aligned with the very top left hand corner of the cell. Likewise,
+ * the bottom right hand corner of the image will be located in cell B2 (1, 1) and
+ * it will again be aligned with the top left hand corner of the cell. This has the
+ * effect of making the image seem to occupy the whole of cell A1. Interestingly, it
+ * also has an effect on the images resizing behaviour because testing has
+ * demonstrated that if the image is wholly contained within one cell and is not
+ * 'attached' for want of a better word, to a neighbouring cell, then that image
+ * will not increase in size in response to the user dragging the column wider
+ * or the cell higher.
+ *
+ * The following example demonstrates a slightly different way to insert an
+ * image into cell A1 and to ensure that it occupies the whole of the cell. This
+ * is accomplished by specifying the the images bottom right hand corner should be
+ * aligned with the bottom right hand corner of the cell. It is also a case
+ * where the image will not increase in size if the user increases the size of
+ * the enclosing cell - irrespective of the anchors type - but it will reduce in
+ * size if the cell is made smaller.
+ *
+ * ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();
+ *
+ * anchor.setDx1(0);
+ * anchor.setDy1(0);
+ * anchor.setDx2(1023);
+ * anchor.setDy2(255);
+ * anchor.setCol1(0);
+ * anchor.setRow1(0);
+ * anchor.setCol2(0);
+ * anchor.setRow2(0);
+ *
+ * Note that the final four method calls all pass the same value and seem to
+ * indicate that the images top left hand corner is aligned with the top left
+ * hand corner of cell A1 and that it's bottom right hand corner is also
+ * aligned with the top left hand corner of cell A1. Yet, running this code
+ * would see the image fully occupying cell A1. That is the result of the
+ * values passed to parameters three and four; these I have referred to as
+ * determining the images coordinates within the cell. They indicate that the
+ * image should occupy - in order - the full width of the column and the full
+ * height of the row.
+ *
+ * The co-ordinate values shown are the maxima; and they are independent of
+ * row height/column width and of the font used. Passing 255 will always result
+ * in the image occupying the full height of the row and passing 1023 will
+ * always result in the image occupying the full width of the column. They help
+ * in situations where an image is larger than a column/row and must overlap
+ * into the next column/row. Using them does mean, however, that it is often
+ * necessary to perform conversions between Excels characters units, points,
+ * pixels and millimetres in order to establish how many rows/columns an image
+ * should occupy and just what the various insets ought to be.
+ *
+ * Note that the setDx1(int) and setDy1(int) methods of the ClientAchor class
+ * are not made use of in the code that follows. It would be fairly trivial
+ * however to extend this example further and provide methods that would centre
+ * an image within a cell or allow the user to specify that a plain border a
+ * fixed number of millimetres wide should wrap around the image. Those first
+ * two parameters would make this sort of functionality perfectly possible.
+ *
+ * Owing to the various conversions used, the actual size of the image may vary
+ * from that required; testing has so far found this to be in the region of
+ * plus or minus two millimetres. Most likely by modifying the way the
+ * calculations are performed - possibly using double(s) throughout and
+ * rounding the values at the correct point - it is likely that these errors
+ * could be reduced or removed.
+ *
+ * A note concerning Excels image resizing behaviour. The ClientAnchor
+ * class contains a method called setAnchorType(int) which can be used to
+ * determine how Excel will resize an image in response to the user increasing
+ * or decreasing the dimensions of the cell containing the image. There are
+ * three values that can be passed to this method; 0 = To move and size the
+ * image with the cell, 2 = To move but don't size the image with the cell,
+ * 3 = To prevent the image from moving or being resized along with the cell. If
+ * an image is inserted using this class and placed into a single cell then if
+ * the setAnchorType(int) method is called and a value of either 0 or 2 passed
+ * to it, the resultant resizing behaviour may be a surprise. The image will not
+ * grow in size of the column is made wider or the row higher but it will shrink
+ * if the columns width or rows height are reduced.
+ *
+ * @author Mark Beardsley [msb at apache.org] and Mark Southern [southern at scripps.edu]
+ * @version 1.00 5th August 2009.
+ * 2.00 26th February 2010.
+ * Ported to make use of the the SS usermodel classes.
+ * Ability to reuse the Drawing Patriarch so that multiple images
+ * can be inserted without unintentionally erasing earlier images.
+ * Check on image type added; i.e. jpg, jpeg or png.
+ * The String used to contain the files name is now converted
+ * into a URL.
+ * 2.10 17th May 2012
+ * Corrected gross error that occurred when using the code with
+ * XSSF or SXSSF workbooks. In short, the code did not correctly
+ * calculate the size of the image(s) owing to the use of EMUs
+ * within the OOXML file format. That problem has largely been
+ * corrected although it should be mentioned that images are not
+ * sized with the same level of accuracy. Discrepancies of up to
+ * 2mm have been noted in testing. Further investigation will
+ * continue to rectify this issue.
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public class AddDimensionedImage {
+
+ // Four constants that determine how - and indeed whether - the rows
+ // and columns an image may overlie should be expanded to accommodate that
+ // image.
+ // Passing EXPAND_ROW will result in the height of a row being increased
+ // to accommodate the image if it is not already larger. The image will
+ // be layed across one or more columns.
+ // Passing EXPAND_COLUMN will result in the width of the column being
+ // increased to accommodate the image if it is not already larger. The image
+ // will be layed across one or many rows.
+ // Passing EXPAND_ROW_AND_COLUMN will result in the height of the row
+ // bing increased along with the width of the column to accomdate the
+ // image if either is not already larger.
+ // Passing OVERLAY_ROW_AND_COLUMN will result in the image being layed
+ // over one or more rows and columns. No row or column will be resized,
+ // instead, code will determine how many rows and columns the image should
+ // overlie.
+ public static final int EXPAND_ROW = 1;
+ public static final int EXPAND_COLUMN = 2;
+ public static final int EXPAND_ROW_AND_COLUMN = 3;
+ public static final int OVERLAY_ROW_AND_COLUMN = 7;
+
+ // Modified to support EMU - English Metric Units - used within the OOXML
+ // workbooks, this multoplier is used to convert between measurements in
+ // millimetres and in EMUs
+ private static final int EMU_PER_MM = 36000;
+
+ /**
+ * Add an image to a worksheet.
+ *
+ * @param cellNumber A String that contains the location of the cell whose
+ * top left hand corner should be aligned with the top
+ * left hand corner of the image; for example "A1", "A2"
+ * etc. This is to support the familiar Excel syntax.
+ * Whilst images are are not actually inserted into cells
+ * this provides a convenient method of indicating where
+ * the image should be positioned on the sheet.
+ * @param sheet A reference to the sheet that contains the cell referenced
+ * above.
+ * @param drawing An instance of the DrawingPatriarch class. This is now
+ * passed into the method where it was, previously, recovered
+ * from the sheet in order to allow multiple pictures be
+ * inserted. If the patriarch was not 'cached in this manner
+ * each time it was created any previously positioned images
+ * would be simply over-written.
+ * @param imageFile An instance of the URL class that encapsulates the name
+ * of and path to the image that is to be 'inserted into'
+ * the sheet.
+ * @param reqImageWidthMM A primitive double that contains the required
+ * width of the image in millimetres.
+ * @param reqImageHeightMM A primitive double that contains the required
+ * height of the image in millimetres.
+ * @param resizeBehaviour A primitive int whose value will determine how
+ * the code should react if the image is larger than
+ * the cell referenced by the cellNumber parameter.
+ * Four constants are provided to determine what
+ * should happen;
+ * AddDimensionedImage.EXPAND_ROW
+ * AddDimensionedImage.EXPAND_COLUMN
+ * AddDimensionedImage.EXPAND_ROW_AND_COLUMN
+ * AddDimensionedImage.OVERLAY_ROW_AND_COLUMN
+ * @throws java.io.FileNotFoundException If the file containing the image
+ * cannot be located.
+ * @throws java.io.IOException If a problem occurs whilst reading the file
+ * of image data.
+ * @throws java.lang.IllegalArgumentException If an invalid value is passed
+ * to the resizeBehaviour
+ * parameter.
+ */
+ public void addImageToSheet(String cellNumber, Sheet sheet, Drawing<?> drawing,
+ URL imageFile, double reqImageWidthMM, double reqImageHeightMM,
+ int resizeBehaviour) throws IOException, IllegalArgumentException {
+ // Convert the String into column and row indices then chain the
+ // call to the overridden addImageToSheet() method.
+ CellReference cellRef = new CellReference(cellNumber);
+ this.addImageToSheet(cellRef.getCol(), cellRef.getRow(), sheet, drawing,
+ imageFile, reqImageWidthMM, reqImageHeightMM,resizeBehaviour);
+ }
+
+ /**
+ * Add an image to a worksheet.
+ *
+ * @param colNumber A primitive int that contains the index number of a
+ * column on the worksheet; POI column indices are zero
+ * based. Together with the rowNumber parameter's value,
+ * this parameter identifies a cell on the worksheet. The
+ * images top left hand corner will be aligned with the
+ * top left hand corner of this cell.
+ * @param rowNumber A primitive int that contains the index number of a row
+ * on the worksheet; POI row indices are zero based.
+ * Together with the rowNumber parameter's value, this
+ * parameter identifies a cell on the worksheet. The
+ * images top left hand corner will be aligned with the
+ * top left hand corner of this cell.
+ * @param sheet A reference to the sheet that contains the cell identified
+ * by the two parameters above.
+ * @param drawing An instance of the DrawingPatriarch class. This is now
+ * passed into the method where it was, previously, recovered
+ * from the sheet in order to allow multiple pictures be
+ * inserted. If the patriarch was not 'cached in this manner
+ * each time it was created any previously positioned images
+ * would be simply over-written.
+ * @param imageFile An instance of the URL class that encapsulates the name
+ * of and path to the image that is to be 'inserted into'
+ * the sheet.
+ * @param reqImageWidthMM A primitive double that contains the required
+ * width of the image in millimetres.
+ * @param reqImageHeightMM A primitive double that contains the required
+ * height of the image in millimetres.
+ * @param resizeBehaviour A primitive int whose value will determine how
+ * the code should react if the image is larger than
+ * the cell referenced by the colNumber and
+ * rowNumber parameters. Four constants are provided
+ * to determine what should happen;
+ * AddDimensionedImage.EXPAND_ROW
+ * AddDimensionedImage.EXPAND_COLUMN
+ * AddDimensionedImage.EXPAND_ROW_AND_COLUMN
+ * AddDimensionedImage.OVERLAY_ROW_AND_COLUMN
+ * @throws java.io.FileNotFoundException If the file containing the image
+ * cannot be located.
+ * @throws java.io.IOException If a problem occurs whilst reading the file
+ * of image data.
+ * @throws java.lang.IllegalArgumentException If an invalid value is passed
+ * to the resizeBehaviour
+ * parameter or if the extension
+ * of the image file indicates that
+ * it is of a type that cannot
+ * currently be added to the worksheet.
+ */
+ public void addImageToSheet(int colNumber, int rowNumber, Sheet sheet, Drawing<?> drawing,
+ URL imageFile, double reqImageWidthMM, double reqImageHeightMM,
+ int resizeBehaviour) throws IOException,
+ IllegalArgumentException {
+ ClientAnchor anchor;
+ ClientAnchorDetail rowClientAnchorDetail;
+ ClientAnchorDetail colClientAnchorDetail;
+ int imageType;
+
+ // Validate the resizeBehaviour parameter.
+ if((resizeBehaviour != AddDimensionedImage.EXPAND_COLUMN) &&
+ (resizeBehaviour != AddDimensionedImage.EXPAND_ROW) &&
+ (resizeBehaviour != AddDimensionedImage.EXPAND_ROW_AND_COLUMN) &&
+ (resizeBehaviour != AddDimensionedImage.OVERLAY_ROW_AND_COLUMN)) {
+ throw new IllegalArgumentException("Invalid value passed to the " +
+ "resizeBehaviour parameter of AddDimensionedImage.addImageToSheet()");
+ }
+
+ // Call methods to calculate how the image and sheet should be
+ // manipulated to accommodate the image; columns and then rows.
+ colClientAnchorDetail = this.fitImageToColumns(sheet, colNumber,
+ reqImageWidthMM, resizeBehaviour);
+ rowClientAnchorDetail = this.fitImageToRows(sheet, rowNumber,
+ reqImageHeightMM, resizeBehaviour);
+
+ // Having determined if and how to resize the rows, columns and/or the
+ // image, create the ClientAnchor object to position the image on
+ // the worksheet. Note how the two ClientAnchorDetail records are
+ // interrogated to recover the row/column co-ordinates and any insets.
+ // The first two parameters are not used currently but could be if the
+ // need arose to extend the functionality of this code by adding the
+ // ability to specify that a clear 'border' be placed around the image.
+ anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();
+
+ anchor.setDx1(0);
+ anchor.setDy1(0);
+ if (colClientAnchorDetail != null) {
+ anchor.setDx2(colClientAnchorDetail.getInset());
+ anchor.setCol1(colClientAnchorDetail.getFromIndex());
+ anchor.setCol2(colClientAnchorDetail.getToIndex());
+ }
+ if (rowClientAnchorDetail != null) {
+ anchor.setDy2(rowClientAnchorDetail.getInset());
+ anchor.setRow1(rowClientAnchorDetail.getFromIndex());
+ anchor.setRow2(rowClientAnchorDetail.getToIndex());
+ }
+
+ // For now, set the anchor type to do not move or resize the
+ // image as the size of the row/column is adjusted. This could easily
+ // become another parameter passed to the method. Please read the note
+ // above regarding the behaviour of image resizing.
+ anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE);
+
+ // Now, add the picture to the workbook. Note that unlike the similar
+ // method in the HSSF Examples section, the image type is checked. First,
+ // the image files location is identified by interrogating the URL passed
+ // to the method, the images type is identified before it is added to the
+ // sheet.
+ String sURL = imageFile.toString().toLowerCase(Locale.ROOT);
+ if( sURL.endsWith(".png") ) {
+ imageType = Workbook.PICTURE_TYPE_PNG;
+ }
+ else if( sURL.endsWith(".jpg") || sURL.endsWith(".jpeg") ) {
+ imageType = Workbook.PICTURE_TYPE_JPEG;
+ }
+ else {
+ throw new IllegalArgumentException("Invalid Image file : " +
+ sURL);
+ }
+ int index = sheet.getWorkbook().addPicture(
+ IOUtils.toByteArray(imageFile.openStream()), imageType);
+ drawing.createPicture(anchor, index);
+ }
+
+ /**
+ * Determines whether the sheets columns should be re-sized to accommodate
+ * the image, adjusts the columns width if necessary and creates then
+ * returns a ClientAnchorDetail object that facilitates construction of
+ * an ClientAnchor that will fix the image on the sheet and establish
+ * it's size.
+ *
+ * @param sheet A reference to the sheet that will 'contain' the image.
+ * @param colNumber A primitive int that contains the index number of a
+ * column on the sheet.
+ * @param reqImageWidthMM A primitive double that contains the required
+ * width of the image in millimetres
+ * @param resizeBehaviour A primitive int whose value will indicate how the
+ * width of the column should be adjusted if the
+ * required width of the image is greater than the
+ * width of the column.
+ * @return An instance of the ClientAnchorDetail class that will contain
+ * the index number of the column containing the cell whose top
+ * left hand corner also defines the top left hand corner of the
+ * image, the index number column containing the cell whose top
+ * left hand corner also defines the bottom right hand corner of
+ * the image and an inset that determines how far the right hand
+ * edge of the image can protrude into the next column - expressed
+ * as a specific number of coordinate positions.
+ */
+ private ClientAnchorDetail fitImageToColumns(Sheet sheet, int colNumber,
+ double reqImageWidthMM, int resizeBehaviour) {
+
+ double colWidthMM;
+ double colCoordinatesPerMM;
+ int pictureWidthCoordinates;
+ ClientAnchorDetail colClientAnchorDetail = null;
+
+ // Get the colum's width in millimetres
+ colWidthMM = ConvertImageUnits.widthUnits2Millimetres(
+ (short)sheet.getColumnWidth(colNumber));
+
+ // Check that the column's width will accommodate the image at the
+ // required dimension. If the width of the column is LESS than the
+ // required width of the image, decide how the application should
+ // respond - resize the column or overlay the image across one or more
+ // columns.
+ if(colWidthMM < reqImageWidthMM) {
+
+ // Should the column's width simply be expanded?
+ if((resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN) ||
+ (resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) {
+ // Set the width of the column by converting the required image
+ // width from millimetres into Excel's column width units.
+ sheet.setColumnWidth(colNumber,
+ ConvertImageUnits.millimetres2WidthUnits(reqImageWidthMM));
+ // To make the image occupy the full width of the column, convert
+ // the required width of the image into co-ordinates. This value
+ // will become the inset for the ClientAnchorDetail class that
+ // is then instantiated.
+ if(sheet instanceof HSSFSheet) {
+ colWidthMM = reqImageWidthMM;
+ colCoordinatesPerMM = colWidthMM == 0 ? 0
+ : ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colWidthMM;
+ pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM);
+
+ }
+ else {
+ pictureWidthCoordinates = (int)reqImageWidthMM * AddDimensionedImage.EMU_PER_MM;
+ }
+ colClientAnchorDetail = new ClientAnchorDetail(colNumber,
+ colNumber, pictureWidthCoordinates);
+ }
+ // If the user has chosen to overlay both rows and columns or just
+ // to expand ONLY the size of the rows, then calculate how to lay
+ // the image out across one or more columns.
+ else if ((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) ||
+ (resizeBehaviour == AddDimensionedImage.EXPAND_ROW)) {
+ colClientAnchorDetail = this.calculateColumnLocation(sheet,
+ colNumber, reqImageWidthMM);
+ }
+ }
+ // If the column is wider than the image.
+ else {
+ if(sheet instanceof HSSFSheet) {
+ // Mow many co-ordinate positions are there per millimetre?
+ colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS /
+ colWidthMM;
+ // Given the width of the image, what should be it's co-ordinate?
+ pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM);
+ }
+ else {
+ pictureWidthCoordinates = (int)reqImageWidthMM *
+ AddDimensionedImage.EMU_PER_MM;
+ }
+ colClientAnchorDetail = new ClientAnchorDetail(colNumber,
+ colNumber, pictureWidthCoordinates);
+ }
+ return(colClientAnchorDetail);
+ }
+
+ /**
+ * Determines whether the sheets row should be re-sized to accommodate
+ * the image, adjusts the rows height if necessary and creates then
+ * returns a ClientAnchorDetail object that facilitates construction of
+ * a ClientAnchor that will fix the image on the sheet and establish
+ * it's size.
+ *
+ * @param sheet A reference to the sheet that will 'contain' the image.
+ * @param rowNumber A primitive int that contains the index number of a
+ * row on the sheet.
+ * @param reqImageHeightMM A primitive double that contains the required
+ * height of the image in millimetres
+ * @param resizeBehaviour A primitive int whose value will indicate how the
+ * height of the row should be adjusted if the
+ * required height of the image is greater than the
+ * height of the row.
+ * @return An instance of the ClientAnchorDetail class that will contain
+ * the index number of the row containing the cell whose top
+ * left hand corner also defines the top left hand corner of the
+ * image, the index number of the row containing the cell whose
+ * top left hand corner also defines the bottom right hand
+ * corner of the image and an inset that determines how far the
+ * bottom edge of the image can protrude into the next (lower)
+ * row - expressed as a specific number of coordinate positions.
+ */
+ private ClientAnchorDetail fitImageToRows(Sheet sheet, int rowNumber,
+ double reqImageHeightMM, int resizeBehaviour) {
+ Row row;
+ double rowHeightMM;
+ double rowCoordinatesPerMM;
+ int pictureHeightCoordinates;
+ ClientAnchorDetail rowClientAnchorDetail = null;
+
+ // Get the row and it's height
+ row = sheet.getRow(rowNumber);
+ if(row == null) {
+ // Create row if it does not exist.
+ row = sheet.createRow(rowNumber);
+ }
+
+ // Get the row's height in millimetres
+ rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE;
+
+ // Check that the row's height will accommodate the image at the required
+ // dimensions. If the height of the row is LESS than the required height
+ // of the image, decide how the application should respond - resize the
+ // row or overlay the image across a series of rows.
+ if(rowHeightMM < reqImageHeightMM) {
+ if((resizeBehaviour == AddDimensionedImage.EXPAND_ROW) ||
+ (resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) {
+ row.setHeightInPoints((float)(reqImageHeightMM *
+ ConvertImageUnits.POINTS_PER_MILLIMETRE));
+ if(sheet instanceof HSSFSheet) {
+ rowHeightMM = reqImageHeightMM;
+ rowCoordinatesPerMM = rowHeightMM == 0 ? 0
+ : ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowHeightMM;
+ pictureHeightCoordinates = (int)(reqImageHeightMM *
+ rowCoordinatesPerMM);
+ }
+ else {
+ pictureHeightCoordinates = (int)(reqImageHeightMM *
+ AddDimensionedImage.EMU_PER_MM);
+ }
+ rowClientAnchorDetail = new ClientAnchorDetail(rowNumber,
+ rowNumber, pictureHeightCoordinates);
+ }
+ // If the user has chosen to overlay both rows and columns or just
+ // to expand ONLY the size of the columns, then calculate how to lay
+ // the image out ver one or more rows.
+ else if((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) ||
+ (resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN)) {
+ rowClientAnchorDetail = this.calculateRowLocation(sheet,
+ rowNumber, reqImageHeightMM);
+ }
+ }
+ // Else, if the image is smaller than the space available
+ else {
+ if(sheet instanceof HSSFSheet) {
+ rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS /
+ rowHeightMM;
+ pictureHeightCoordinates = (int)(reqImageHeightMM * rowCoordinatesPerMM);
+ }
+ else {
+ pictureHeightCoordinates = (int)(reqImageHeightMM *
+ AddDimensionedImage.EMU_PER_MM);
+ }
+ rowClientAnchorDetail = new ClientAnchorDetail(rowNumber,
+ rowNumber, pictureHeightCoordinates);
+ }
+ return(rowClientAnchorDetail);
+ }
+
+ /**
+ * If the image is to overlie more than one column, calculations need to be
+ * performed to determine how many columns and whether the image will
+ * overlie just a part of one column in order to be presented at the
+ * required size.
+ *
+ * @param sheet The sheet that will 'contain' the image.
+ * @param startingColumn A primitive int whose value is the index of the
+ * column that contains the cell whose top left hand
+ * corner should be aligned with the top left hand
+ * corner of the image.
+ * @param reqImageWidthMM A primitive double whose value will indicate the
+ * required width of the image in millimetres.
+ * @return An instance of the ClientAnchorDetail class that will contain
+ * the index number of the column containing the cell whose top
+ * left hand corner also defines the top left hand corner of the
+ * image, the index number column containing the cell whose top
+ * left hand corner also defines the bottom right hand corner of
+ * the image and an inset that determines how far the right hand
+ * edge of the image can protrude into the next column - expressed
+ * as a specific number of coordinate positions.
+ */
+ private ClientAnchorDetail calculateColumnLocation(Sheet sheet,
+ int startingColumn,
+ double reqImageWidthMM) {
+ ClientAnchorDetail anchorDetail;
+ double totalWidthMM = 0.0D;
+ double colWidthMM = 0.0D;
+ double overlapMM;
+ double coordinatePositionsPerMM;
+ int toColumn = startingColumn;
+ int inset;
+
+ // Calculate how many columns the image will have to
+ // span in order to be presented at the required size.
+ while(totalWidthMM < reqImageWidthMM) {
+ colWidthMM = ConvertImageUnits.widthUnits2Millimetres(
+ (short)(sheet.getColumnWidth(toColumn)));
+ // Note use of the cell border width constant. Testing with an image
+ // declared to fit exactly into one column demonstrated that it's
+ // width was greater than the width of the column the POI returned.
+ // Further, this difference was a constant value that I am assuming
+ // related to the cell's borders. Either way, that difference needs
+ // to be allowed for in this calculation.
+ totalWidthMM += (colWidthMM + ConvertImageUnits.CELL_BORDER_WIDTH_MILLIMETRES);
+ toColumn++;
+ }
+ // De-crement by one the last column value.
+ toColumn--;
+ // Highly unlikely that this will be true but, if the width of a series
+ // of columns is exactly equal to the required width of the image, then
+ // simply build a ClientAnchorDetail object with an inset equal to the
+ // total number of co-ordinate positions available in a column, a
+ // from column co-ordinate (top left hand corner) equal to the value
+ // of the startingColumn parameter and a to column co-ordinate equal
+ // to the toColumn variable.
+ //
+ // Convert both values to ints to perform the test.
+ if((int)totalWidthMM == (int)reqImageWidthMM) {
+ // A problem could occur if the image is sized to fit into one or
+ // more columns. If that occurs, the value in the toColumn variable
+ // will be in error. To overcome this, there are two options, to
+ // ibcrement the toColumn variable's value by one or to pass the
+ // total number of co-ordinate positions to the third paramater
+ // of the ClientAnchorDetail constructor. For no sepcific reason,
+ // the latter option is used below.
+ if(sheet instanceof HSSFSheet) {
+ anchorDetail = new ClientAnchorDetail(startingColumn,
+ toColumn, ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS);
+ }
+ else {
+ anchorDetail = new ClientAnchorDetail(startingColumn,
+ toColumn, (int)reqImageWidthMM * AddDimensionedImage.EMU_PER_MM);
+ }
+ }
+ // In this case, the image will overlap part of another column and it is
+ // necessary to calculate just how much - this will become the inset
+ // for the ClientAnchorDetail object.
+ else {
+ // Firstly, claculate how much of the image should overlap into
+ // the next column.
+ overlapMM = reqImageWidthMM - (totalWidthMM - colWidthMM);
+
+ // When the required size is very close indded to the column size,
+ // the calcaulation above can produce a negative value. To prevent
+ // problems occuring in later caculations, this is simply removed
+ // be setting the overlapMM value to zero.
+ if(overlapMM < 0) {
+ overlapMM = 0.0D;
+ }
+
+ if(sheet instanceof HSSFSheet) {
+ // Next, from the columns width, calculate how many co-ordinate
+ // positons there are per millimetre
+ coordinatePositionsPerMM = (colWidthMM == 0) ? 0
+ : ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colWidthMM;
+ // From this figure, determine how many co-ordinat positions to
+ // inset the left hand or bottom edge of the image.
+ inset = (int)(coordinatePositionsPerMM * overlapMM);
+ }
+ else {
+ inset = (int)overlapMM * AddDimensionedImage.EMU_PER_MM;
+ }
+
+ // Now create the ClientAnchorDetail object, setting the from and to
+ // columns and the inset.
+ anchorDetail = new ClientAnchorDetail(startingColumn, toColumn, inset);
+ }
+ return(anchorDetail);
+ }
+
+ /**
+ * If the image is to overlie more than one rows, calculations need to be
+ * performed to determine how many rows and whether the image will
+ * overlie just a part of one row in order to be presented at the
+ * required size.
+ *
+ * @param sheet The sheet that will 'contain' the image.
+ * @param startingRow A primitive int whose value is the index of the row
+ * that contains the cell whose top left hand corner
+ * should be aligned with the top left hand corner of
+ * the image.
+ * @param reqImageHeightMM A primitive double whose value will indicate the
+ * required height of the image in millimetres.
+ * @return An instance of the ClientAnchorDetail class that will contain
+ * the index number of the row containing the cell whose top
+ * left hand corner also defines the top left hand corner of the
+ * image, the index number of the row containing the cell whose top
+ * left hand corner also defines the bottom right hand corner of
+ * the image and an inset that determines how far the bottom edge
+ * can protrude into the next (lower) row - expressed as a specific
+ * number of co-ordinate positions.
+ */
+ private ClientAnchorDetail calculateRowLocation(Sheet sheet,
+ int startingRow, double reqImageHeightMM) {
+ ClientAnchorDetail clientAnchorDetail;
+ Row row;
+ double rowHeightMM = 0.0D;
+ double totalRowHeightMM = 0.0D;
+ double overlapMM;
+ double rowCoordinatesPerMM;
+ int toRow = startingRow;
+ int inset;
+
+ // Step through the rows in the sheet and accumulate a total of their
+ // heights.
+ while(totalRowHeightMM < reqImageHeightMM) {
+ row = sheet.getRow(toRow);
+ // Note, if the row does not already exist on the sheet then create
+ // it here.
+ if(row == null) {
+ row = sheet.createRow(toRow);
+ }
+ // Get the row's height in millimetres and add to the running total.
+ rowHeightMM = row.getHeightInPoints() /
+ ConvertImageUnits.POINTS_PER_MILLIMETRE;
+ totalRowHeightMM += rowHeightMM;
+ toRow++;
+ }
+ // Owing to the way the loop above works, the rowNumber will have been
+ // incremented one row too far. Undo that here.
+ toRow--;
+ // Check to see whether the image should occupy an exact number of
+ // rows. If so, build the ClientAnchorDetail record to point
+ // to those rows and with an inset of the total number of co-ordinate
+ // position in the row.
+ //
+ // To overcome problems that can occur with comparing double values for
+ // equality, cast both to int(s) to truncate the value; VERY crude and
+ // I do not really like it!!
+ if((int)totalRowHeightMM == (int)reqImageHeightMM) {
+ if(sheet instanceof HSSFSheet) {
+ clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow,
+ ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS);
+ }
+ else {
+ clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow,
+ (int)reqImageHeightMM * AddDimensionedImage.EMU_PER_MM);
+ }
+ }
+ else {
+ // Calculate how far the image will project into the next row. Note
+ // that the height of the last row assessed is subtracted from the
+ // total height of all rows assessed so far.
+ overlapMM = reqImageHeightMM - (totalRowHeightMM - rowHeightMM);
+
+ // To prevent an exception being thrown when the required width of
+ // the image is very close indeed to the column size.
+ if(overlapMM < 0) {
+ overlapMM = 0.0D;
+ }
+
+ if(sheet instanceof HSSFSheet) {
+ rowCoordinatesPerMM = (rowHeightMM == 0) ? 0
+ : ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowHeightMM;
+ inset = (int)(overlapMM * rowCoordinatesPerMM);
+ }
+ else {
+ inset = (int)overlapMM * AddDimensionedImage.EMU_PER_MM;
+ }
+ clientAnchorDetail = new ClientAnchorDetail(startingRow,
+ toRow, inset);
+ }
+ return(clientAnchorDetail);
+ }
+
+ /**
+ * The main entry point to the program. It contains code that demonstrates
+ * one way to use the program.
+ *
+ * Note, the code is not restricted to use on new workbooks only. If an
+ * image is to be inserted into an existing workbook. just open that
+ * workbook, gat a reference to a sheet and pass that;
+ *
+ * AddDimensionedImage addImage = new AddDimensionedImage();
+ *
+ * File file = new File("....... Existing Workbook .......");
+ * FileInputStream fis = new FileInputStream(file);
+ * Workbook workbook = new HSSFWorkbook(fis);
+ * HSSFSheet sheet = workbook.getSheetAt(0);
+ * addImage.addImageToSheet("C3", sheet, "image.jpg", 30, 20,
+ * AddDimensionedImage.EXPAND.ROW);
+ *
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) throws IOException {
+ if(args.length < 2){
+ System.err.println("Usage: AddDimensionedImage imageFile outputFile");
+ return;
+ }
+
+ final String imageFile = args[0];
+ final String outputFile = args[1];
+
+ try (final Workbook workbook = new HSSFWorkbook();
+ final FileOutputStream fos = new FileOutputStream(outputFile)) { // OR XSSFWorkbook
+ Sheet sheet = workbook.createSheet("Picture Test");
+ new AddDimensionedImage().addImageToSheet("B5", sheet, sheet.createDrawingPatriarch(),
+ new File(imageFile).toURI().toURL(), 100, 40,
+ AddDimensionedImage.EXPAND_ROW_AND_COLUMN);
+ workbook.write(fos);
+ }
+ }
+
+ /**
+ * The HSSFClientAnchor class accepts eight arguments. In order, these are;
+ *
+ * * How far the left hand edge of the image is inset from the left hand
+ * edge of the cell
+ * * How far the top edge of the image is inset from the top of the cell
+ * * How far the right hand edge of the image is inset from the left
+ * hand edge of the cell
+ * * How far the bottom edge of the image is inset from the top of the
+ * cell.
+ * * Together, arguments five and six determine the column and row
+ * coordinates of the cell whose top left hand corner will be aligned
+ * with the images top left hand corner.
+ * * Together, arguments seven and eight determine the column and row
+ * coordinates of the cell whose top left hand corner will be aligned
+ * with the images bottom right hand corner.
+ *
+ * An instance of the ClientAnchorDetail class provides three of the eight
+ * parameters, one of the coordinates for the images top left hand corner,
+ * one of the coordinates for the images bottom right hand corner and
+ * either how far the image should be inset from the top or the left hand
+ * edge of the cell.
+ *
+ * @author Mark Beardsley [msb at apache.org]
+ * @version 1.00 5th August 2009.
+ */
+ public class ClientAnchorDetail {
+
+ private int fromIndex;
+ private int toIndex;
+ private int inset;
+
+ /**
+ * Create a new instance of the ClientAnchorDetail class using the
+ * following parameters.
+ *
+ * @param fromIndex A primitive int that contains one of the
+ * coordinates (row or column index) for the top left
+ * hand corner of the image.
+ * @param toIndex A primitive int that contains one of the
+ * coordinates (row or column index) for the bottom
+ * right hand corner of the image.
+ * @param inset A primitive int that contains a value which indicates
+ * how far the image should be inset from the top or the
+ * left hand edge of a cell.
+ */
+ public ClientAnchorDetail(int fromIndex, int toIndex, int inset) {
+ this.fromIndex = fromIndex;
+ this.toIndex = toIndex;
+ this.inset = inset;
+ }
+
+ /**
+ * Get one of the number of the column or row that contains the cell
+ * whose top left hand corner will be aligned with the top left hand
+ * corner of the image.
+ *
+ * @return The value - row or column index - for one of the coordinates
+ * of the top left hand corner of the image.
+ */
+ public int getFromIndex() {
+ return(this.fromIndex);
+ }
+
+ /**
+ * Get one of the number of the column or row that contains the cell
+ * whose top left hand corner will be aligned with the bottom right hand
+ * corner of the image.
+ *
+ * @return The value - row or column index - for one of the coordinates
+ * of the bottom right hand corner of the image.
+ */
+ public int getToIndex() {
+ return(this.toIndex);
+ }
+
+ /**
+ * Get the images offset from the edge of a cell.
+ *
+ * @return How far either the right hand or bottom edge of the image is
+ * inset from the left hand or top edge of a cell.
+ */
+ public int getInset() {
+ return(this.inset);
+ }
+ }
+
+ /**
+ * Utility methods used to convert Excels character based column and row
+ * size measurements into pixels and/or millimetres. The class also contains
+ * various constants that are required in other calculations.
+ *
+ * @author xio[darjino@hotmail.com]
+ * @version 1.01 30th July 2009.
+ * Added by Mark Beardsley [msb at apache.org].
+ * Additional constants.
+ * widthUnits2Millimetres() and millimetres2Units() methods.
+ */
+ public static class ConvertImageUnits {
+
+ // Each cell conatins a fixed number of co-ordinate points; this number
+ // does not vary with row height or column width or with font. These two
+ // constants are defined below.
+ public static final int TOTAL_COLUMN_COORDINATE_POSITIONS = 1023;
+ public static final int TOTAL_ROW_COORDINATE_POSITIONS = 255;
+ // The resoultion of an image can be expressed as a specific number
+ // of pixels per inch. Displays and printers differ but 96 pixels per
+ // inch is an acceptable standard to beging with.
+ public static final int PIXELS_PER_INCH = 96;
+ // Cnstants that defines how many pixels and points there are in a
+ // millimetre. These values are required for the conversion algorithm.
+ public static final double PIXELS_PER_MILLIMETRES = 3.78;
+ public static final double POINTS_PER_MILLIMETRE = 2.83;
+ // The column width returned by HSSF and the width of a picture when
+ // positioned to exactly cover one cell are different by almost exactly
+ // 2mm - give or take rounding errors. This constant allows that
+ // additional amount to be accounted for when calculating how many
+ // celles the image ought to overlie.
+ public static final double CELL_BORDER_WIDTH_MILLIMETRES = 2.0D;
+ public static final short EXCEL_COLUMN_WIDTH_FACTOR = 256;
+ public static final int UNIT_OFFSET_LENGTH = 7;
+ private static final int[] UNIT_OFFSET_MAP = { 0, 36, 73, 109, 146, 182, 219 };
+
+ /**
+ * pixel units to excel width units(units of 1/256th of a character width)
+ */
+ public static short pixel2WidthUnits(int pxs) {
+ short widthUnits = (short) (EXCEL_COLUMN_WIDTH_FACTOR *
+ (pxs / UNIT_OFFSET_LENGTH));
+ widthUnits += UNIT_OFFSET_MAP[(pxs % UNIT_OFFSET_LENGTH)];
+ return widthUnits;
+ }
+
+ /**
+ * excel width units(units of 1/256th of a character width) to pixel
+ * units.
+ */
+ public static int widthUnits2Pixel(short widthUnits) {
+ int pixels = (widthUnits / EXCEL_COLUMN_WIDTH_FACTOR)
+ * UNIT_OFFSET_LENGTH;
+ int offsetWidthUnits = widthUnits % EXCEL_COLUMN_WIDTH_FACTOR;
+ pixels += Math.round(offsetWidthUnits /
+ ((float) EXCEL_COLUMN_WIDTH_FACTOR / UNIT_OFFSET_LENGTH));
+ return pixels;
+ }
+
+ /**
+ * Convert Excels width units into millimetres.
+ *
+ * @param widthUnits The width of the column or the height of the
+ * row in Excels units.
+ * @return A primitive double that contains the columns width or rows
+ * height in millimetres.
+ */
+ public static double widthUnits2Millimetres(short widthUnits) {
+ return(ConvertImageUnits.widthUnits2Pixel(widthUnits) /
+ ConvertImageUnits.PIXELS_PER_MILLIMETRES);
+ }
+
+ /**
+ * Convert into millimetres Excels width units..
+ *
+ * @param millimetres A primitive double that contains the columns
+ * width or rows height in millimetres.
+ * @return A primitive int that contains the columns width or rows
+ * height in Excels units.
+ */
+ public static int millimetres2WidthUnits(double millimetres) {
+ return(ConvertImageUnits.pixel2WidthUnits((int)(millimetres *
+ ConvertImageUnits.PIXELS_PER_MILLIMETRES)));
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+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.examples.ss;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Shows how various alignment options work.
+ */
+public class AligningCells {
+
+ public static void main(String[] args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+
+ Sheet sheet = wb.createSheet();
+ Row row = sheet.createRow(2);
+ row.setHeightInPoints(30);
+ for (int i = 0; i < 8; i++) {
+ //column width is set in units of 1/256th of a character width
+ sheet.setColumnWidth(i, 256 * 15);
+ }
+
+ createCell(wb, row, 0, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
+ createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.BOTTOM);
+ createCell(wb, row, 2, HorizontalAlignment.FILL, VerticalAlignment.CENTER);
+ createCell(wb, row, 3, HorizontalAlignment.GENERAL, VerticalAlignment.CENTER);
+ createCell(wb, row, 4, HorizontalAlignment.JUSTIFY, VerticalAlignment.JUSTIFY);
+ createCell(wb, row, 5, HorizontalAlignment.LEFT, VerticalAlignment.TOP);
+ createCell(wb, row, 6, HorizontalAlignment.RIGHT, VerticalAlignment.TOP);
+
+ // Write the output to a file
+ try (OutputStream fileOut = new FileOutputStream("ss-example-align.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ /**
+ * Creates a cell and aligns it a certain way.
+ *
+ * @param wb the workbook
+ * @param row the row to create the cell in
+ * @param column the column number to create the cell in
+ * @param halign the horizontal alignment for the cell.
+ */
+ private static void createCell(Workbook wb, Row row, int column, HorizontalAlignment halign, VerticalAlignment valign) {
+ CreationHelper ch = wb.getCreationHelper();
+ Cell cell = row.createCell(column);
+ cell.setCellValue(ch.createRichTextString("Align It"));
+ CellStyle cellStyle = wb.createCellStyle();
+ cellStyle.setAlignment(halign);
+ cellStyle.setVerticalAlignment(valign);
+ cell.setCellStyle(cellStyle);
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+import java.io.FileOutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.PrintSetup;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * A business plan demo
+ * Usage:
+ * BusinessPlan -xls|xlsx
+ *
+ * @author Yegor Kozlov
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class BusinessPlan {
+
+ private static final String[] titles = {
+ "ID", "Project Name", "Owner", "Days", "Start", "End"};
+
+ //sample data to fill the sheet.
+ private static final String[][] data = {
+ {"1.0", "Marketing Research Tactical Plan", "J. Dow", "70", "9-Jul", null,
+ "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x"},
+ null,
+ {"1.1", "Scope Definition Phase", "J. Dow", "10", "9-Jul", null,
+ "x", "x", null, null, null, null, null, null, null, null, null},
+ {"1.1.1", "Define research objectives", "J. Dow", "3", "9-Jul", null,
+ "x", null, null, null, null, null, null, null, null, null, null},
+ {"1.1.2", "Define research requirements", "S. Jones", "7", "10-Jul", null,
+ "x", "x", null, null, null, null, null, null, null, null, null},
+ {"1.1.3", "Determine in-house resource or hire vendor", "J. Dow", "2", "15-Jul", null,
+ "x", "x", null, null, null, null, null, null, null, null, null},
+ null,
+ {"1.2", "Vendor Selection Phase", "J. Dow", "19", "19-Jul", null,
+ null, "x", "x", "x", "x", null, null, null, null, null, null},
+ {"1.2.1", "Define vendor selection criteria", "J. Dow", "3", "19-Jul", null,
+ null, "x", null, null, null, null, null, null, null, null, null},
+ {"1.2.2", "Develop vendor selection questionnaire", "S. Jones, T. Wates", "2", "22-Jul", null,
+ null, "x", "x", null, null, null, null, null, null, null, null},
+ {"1.2.3", "Develop Statement of Work", "S. Jones", "4", "26-Jul", null,
+ null, null, "x", "x", null, null, null, null, null, null, null},
+ {"1.2.4", "Evaluate proposal", "J. Dow, S. Jones", "4", "2-Aug", null,
+ null, null, null, "x", "x", null, null, null, null, null, null},
+ {"1.2.5", "Select vendor", "J. Dow", "1", "6-Aug", null,
+ null, null, null, null, "x", null, null, null, null, null, null},
+ null,
+ {"1.3", "Research Phase", "G. Lee", "47", "9-Aug", null,
+ null, null, null, null, "x", "x", "x", "x", "x", "x", "x"},
+ {"1.3.1", "Develop market research information needs questionnaire", "G. Lee", "2", "9-Aug", null,
+ null, null, null, null, "x", null, null, null, null, null, null},
+ {"1.3.2", "Interview marketing group for market research needs", "G. Lee", "2", "11-Aug", null,
+ null, null, null, null, "x", "x", null, null, null, null, null},
+ {"1.3.3", "Document information needs", "G. Lee, S. Jones", "1", "13-Aug", null,
+ null, null, null, null, null, "x", null, null, null, null, null},
+ };
+
+ private BusinessPlan() {}
+
+ public static void main(String[] args) throws Exception {
+ Workbook wb;
+
+ if(args.length > 0 && args[0].equals("-xls")) wb = new HSSFWorkbook();
+ else wb = new XSSFWorkbook();
+
+ final SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM");
+
+ Map<String, CellStyle> styles = createStyles(wb);
+
+ Sheet sheet = wb.createSheet("Business Plan");
+
+ //turn off gridlines
+ sheet.setDisplayGridlines(false);
+ sheet.setPrintGridlines(false);
+ sheet.setFitToPage(true);
+ sheet.setHorizontallyCenter(true);
+ PrintSetup printSetup = sheet.getPrintSetup();
+ printSetup.setLandscape(true);
+
+ //the following three statements are required only for HSSF
+ sheet.setAutobreaks(true);
+ printSetup.setFitHeight((short)1);
+ printSetup.setFitWidth((short)1);
+
+ //the header row: centered text in 48pt font
+ Row headerRow = sheet.createRow(0);
+ headerRow.setHeightInPoints(12.75f);
+ for (int i = 0; i < titles.length; i++) {
+ Cell cell = headerRow.createCell(i);
+ cell.setCellValue(titles[i]);
+ cell.setCellStyle(styles.get("header"));
+ }
+ //columns for 11 weeks starting from 9-Jul
+ Calendar calendar = Calendar.getInstance();
+ int year = calendar.get(Calendar.YEAR);
+
+ calendar.setTime(fmt.parse("9-Jul"));
+ calendar.set(Calendar.YEAR, year);
+ for (int i = 0; i < 11; i++) {
+ Cell cell = headerRow.createCell(titles.length + i);
+ cell.setCellValue(calendar);
+ cell.setCellStyle(styles.get("header_date"));
+ calendar.roll(Calendar.WEEK_OF_YEAR, true);
+ }
+ //freeze the first row
+ sheet.createFreezePane(0, 1);
+
+ Row row;
+ Cell cell;
+ int rownum = 1;
+ for (int i = 0; i < data.length; i++, rownum++) {
+ row = sheet.createRow(rownum);
+ if(data[i] == null) continue;
+
+ for (int j = 0; j < data[i].length; j++) {
+ cell = row.createCell(j);
+ String styleName;
+ boolean isHeader = i == 0 || data[i-1] == null;
+ switch(j){
+ case 0:
+ if(isHeader) {
+ styleName = "cell_b";
+ cell.setCellValue(Double.parseDouble(data[i][j]));
+ } else {
+ styleName = "cell_normal";
+ cell.setCellValue(data[i][j]);
+ }
+ break;
+ case 1:
+ if(isHeader) {
+ styleName = i == 0 ? "cell_h" : "cell_bb";
+ } else {
+ styleName = "cell_indented";
+ }
+ cell.setCellValue(data[i][j]);
+ break;
+ case 2:
+ styleName = isHeader ? "cell_b" : "cell_normal";
+ cell.setCellValue(data[i][j]);
+ break;
+ case 3:
+ styleName = isHeader ? "cell_b_centered" : "cell_normal_centered";
+ cell.setCellValue(Integer.parseInt(data[i][j]));
+ break;
+ case 4: {
+ calendar.setTime(fmt.parse(data[i][j]));
+ calendar.set(Calendar.YEAR, year);
+ cell.setCellValue(calendar);
+ styleName = isHeader ? "cell_b_date" : "cell_normal_date";
+ break;
+ }
+ case 5: {
+ int r = rownum + 1;
+ String fmla = "IF(AND(D"+r+",E"+r+"),E"+r+"+D"+r+",\"\")";
+ cell.setCellFormula(fmla);
+ styleName = isHeader ? "cell_bg" : "cell_g";
+ break;
+ }
+ default:
+ styleName = data[i][j] != null ? "cell_blue" : "cell_normal";
+ }
+
+ cell.setCellStyle(styles.get(styleName));
+ }
+ }
+
+ //group rows for each phase, row numbers are 0-based
+ sheet.groupRow(4, 6);
+ sheet.groupRow(9, 13);
+ sheet.groupRow(16, 18);
+
+ //set column widths, the width is measured in units of 1/256th of a character width
+ sheet.setColumnWidth(0, 256*6);
+ sheet.setColumnWidth(1, 256*33);
+ sheet.setColumnWidth(2, 256*20);
+ sheet.setZoom(75); //75% scale
+
+
+ // Write the output to a file
+ String file = "businessplan.xls";
+ if(wb instanceof XSSFWorkbook) file += "x";
+ FileOutputStream out = new FileOutputStream(file);
+ wb.write(out);
+ out.close();
+
+ wb.close();
+ }
+
+ /**
+ * create a library of cell styles
+ */
+ private static Map<String, CellStyle> createStyles(Workbook wb){
+ Map<String, CellStyle> styles = new HashMap<>();
+ DataFormat df = wb.createDataFormat();
+
+ CellStyle style;
+ Font headerFont = wb.createFont();
+ headerFont.setBold(true);
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFont(headerFont);
+ styles.put("header", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFont(headerFont);
+ style.setDataFormat(df.getFormat("d-mmm"));
+ styles.put("header_date", style);
+
+ Font font1 = wb.createFont();
+ font1.setBold(true);
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setFont(font1);
+ styles.put("cell_b", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setFont(font1);
+ styles.put("cell_b_centered", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(font1);
+ style.setDataFormat(df.getFormat("d-mmm"));
+ styles.put("cell_b_date", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(font1);
+ style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setDataFormat(df.getFormat("d-mmm"));
+ styles.put("cell_g", style);
+
+ Font font2 = wb.createFont();
+ font2.setColor(IndexedColors.BLUE.getIndex());
+ font2.setBold(true);
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setFont(font2);
+ styles.put("cell_bb", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(font1);
+ style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setDataFormat(df.getFormat("d-mmm"));
+ styles.put("cell_bg", style);
+
+ Font font3 = wb.createFont();
+ font3.setFontHeightInPoints((short)14);
+ font3.setColor(IndexedColors.DARK_BLUE.getIndex());
+ font3.setBold(true);
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setFont(font3);
+ style.setWrapText(true);
+ styles.put("cell_h", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setWrapText(true);
+ styles.put("cell_normal", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setWrapText(true);
+ styles.put("cell_normal_centered", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setWrapText(true);
+ style.setDataFormat(df.getFormat("d-mmm"));
+ styles.put("cell_normal_date", style);
+
+ style = createBorderedStyle(wb);
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setIndention((short)1);
+ style.setWrapText(true);
+ styles.put("cell_indented", style);
+
+ style = createBorderedStyle(wb);
+ style.setFillForegroundColor(IndexedColors.BLUE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ styles.put("cell_blue", style);
+
+ return styles;
+ }
+
+ private static CellStyle createBorderedStyle(Workbook wb){
+ BorderStyle thin = BorderStyle.THIN;
+ short black = IndexedColors.BLACK.getIndex();
+
+ CellStyle style = wb.createCellStyle();
+ style.setBorderRight(thin);
+ style.setRightBorderColor(black);
+ style.setBorderBottom(thin);
+ style.setBottomBorderColor(black);
+ style.setBorderLeft(thin);
+ style.setLeftBorderColor(black);
+ style.setBorderTop(thin);
+ style.setTopBorderColor(black);
+ return style;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+import java.io.FileOutputStream;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.PrintSetup;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * A monthly calendar created using Apache POI. Each month is on a separate sheet.
+ * <pre>
+ * Usage:
+ * CalendarDemo -xls|xlsx <year>
+ * </pre>
+ *
+ * @author Yegor Kozlov
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class CalendarDemo {
+
+ private static final String[] days = {
+ "Sunday", "Monday", "Tuesday",
+ "Wednesday", "Thursday", "Friday", "Saturday"};
+
+ private static final String[] months = {
+ "January", "February", "March","April", "May", "June","July", "August",
+ "September","October", "November", "December"};
+
+ private CalendarDemo() {}
+
+ public static void main(String[] args) throws Exception {
+
+ Calendar calendar = Calendar.getInstance();
+ boolean xlsx = true;
+ for (String arg : args) {
+ if (arg.charAt(0) == '-') {
+ xlsx = arg.equals("-xlsx");
+ } else {
+ calendar.set(Calendar.YEAR, Integer.parseInt(arg));
+ }
+ }
+ int year = calendar.get(Calendar.YEAR);
+
+ try (Workbook wb = xlsx ? new XSSFWorkbook() : new HSSFWorkbook()) {
+
+ Map<String, CellStyle> styles = createStyles(wb);
+
+ for (int month = 0; month < 12; month++) {
+ calendar.set(Calendar.MONTH, month);
+ calendar.set(Calendar.DAY_OF_MONTH, 1);
+ //create a sheet for each month
+ Sheet sheet = wb.createSheet(months[month]);
+
+ //turn off gridlines
+ sheet.setDisplayGridlines(false);
+ sheet.setPrintGridlines(false);
+ sheet.setFitToPage(true);
+ sheet.setHorizontallyCenter(true);
+ PrintSetup printSetup = sheet.getPrintSetup();
+ printSetup.setLandscape(true);
+
+ //the following three statements are required only for HSSF
+ sheet.setAutobreaks(true);
+ printSetup.setFitHeight((short) 1);
+ printSetup.setFitWidth((short) 1);
+
+ //the header row: centered text in 48pt font
+ Row headerRow = sheet.createRow(0);
+ headerRow.setHeightInPoints(80);
+ Cell titleCell = headerRow.createCell(0);
+ titleCell.setCellValue(months[month] + " " + year);
+ titleCell.setCellStyle(styles.get("title"));
+ sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$N$1"));
+
+ //header with month titles
+ Row monthRow = sheet.createRow(1);
+ for (int i = 0; i < days.length; i++) {
+ //set column widths, the width is measured in units of 1/256th of a character width
+ sheet.setColumnWidth(i * 2, 5 * 256); //the column is 5 characters wide
+ sheet.setColumnWidth(i * 2 + 1, 13 * 256); //the column is 13 characters wide
+ sheet.addMergedRegion(new CellRangeAddress(1, 1, i * 2, i * 2 + 1));
+ Cell monthCell = monthRow.createCell(i * 2);
+ monthCell.setCellValue(days[i]);
+ monthCell.setCellStyle(styles.get("month"));
+ }
+
+ int cnt = 1, day = 1;
+ int rownum = 2;
+ for (int j = 0; j < 6; j++) {
+ Row row = sheet.createRow(rownum++);
+ row.setHeightInPoints(100);
+ for (int i = 0; i < days.length; i++) {
+ Cell dayCell_1 = row.createCell(i * 2);
+ Cell dayCell_2 = row.createCell(i * 2 + 1);
+
+ int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
+ if (cnt >= day_of_week && calendar.get(Calendar.MONTH) == month) {
+ dayCell_1.setCellValue(day);
+ calendar.set(Calendar.DAY_OF_MONTH, ++day);
+
+ if (i == 0 || i == days.length - 1) {
+ dayCell_1.setCellStyle(styles.get("weekend_left"));
+ dayCell_2.setCellStyle(styles.get("weekend_right"));
+ } else {
+ dayCell_1.setCellStyle(styles.get("workday_left"));
+ dayCell_2.setCellStyle(styles.get("workday_right"));
+ }
+ } else {
+ dayCell_1.setCellStyle(styles.get("grey_left"));
+ dayCell_2.setCellStyle(styles.get("grey_right"));
+ }
+ cnt++;
+ }
+ if (calendar.get(Calendar.MONTH) > month) break;
+ }
+ }
+
+ // Write the output to a file
+ String file = "calendar.xls";
+ if (wb instanceof XSSFWorkbook) file += "x";
+
+ try (FileOutputStream out = new FileOutputStream(file)) {
+ wb.write(out);
+ }
+ }
+ }
+
+ /**
+ * cell styles used for formatting calendar sheets
+ */
+ private static Map<String, CellStyle> createStyles(Workbook wb){
+ Map<String, CellStyle> styles = new HashMap<>();
+
+ short borderColor = IndexedColors.GREY_50_PERCENT.getIndex();
+
+ CellStyle style;
+ Font titleFont = wb.createFont();
+ titleFont.setFontHeightInPoints((short)48);
+ titleFont.setColor(IndexedColors.DARK_BLUE.getIndex());
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFont(titleFont);
+ styles.put("title", style);
+
+ Font monthFont = wb.createFont();
+ monthFont.setFontHeightInPoints((short)12);
+ monthFont.setColor(IndexedColors.WHITE.getIndex());
+ monthFont.setBold(true);
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFont(monthFont);
+ styles.put("month", style);
+
+ Font dayFont = wb.createFont();
+ dayFont.setFontHeightInPoints((short)14);
+ dayFont.setBold(true);
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setVerticalAlignment(VerticalAlignment.TOP);
+ style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(borderColor);
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(borderColor);
+ style.setFont(dayFont);
+ styles.put("weekend_left", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.TOP);
+ style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(borderColor);
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(borderColor);
+ styles.put("weekend_right", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setVerticalAlignment(VerticalAlignment.TOP);
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setLeftBorderColor(borderColor);
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(borderColor);
+ style.setFont(dayFont);
+ styles.put("workday_left", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.TOP);
+ style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(borderColor);
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(borderColor);
+ styles.put("workday_right", style);
+
+ style = wb.createCellStyle();
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(borderColor);
+ styles.put("grey_left", style);
+
+ style = wb.createCellStyle();
+ style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(borderColor);
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(borderColor);
+ styles.put("grey_right", style);
+
+ return styles;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+import java.io.File;
+
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Color;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+
+/**
+ * Demonstrates how to read excel styles for cells
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class CellStyleDetails {
+ private CellStyleDetails() {}
+
+ public static void main(String[] args) throws Exception {
+ if(args.length == 0) {
+ throw new IllegalArgumentException("Filename must be given");
+ }
+
+ try (Workbook wb = WorkbookFactory.create(new File(args[0]))) {
+ DataFormatter formatter = new DataFormatter();
+
+ for (int sn = 0; sn < wb.getNumberOfSheets(); sn++) {
+ Sheet sheet = wb.getSheetAt(sn);
+ System.out.println("Sheet #" + sn + " : " + sheet.getSheetName());
+
+ for (Row row : sheet) {
+ System.out.println(" Row " + row.getRowNum());
+
+ for (Cell cell : row) {
+ CellReference ref = new CellReference(cell);
+ System.out.print(" " + ref.formatAsString());
+ System.out.print(" (" + cell.getColumnIndex() + ") ");
+
+ CellStyle style = cell.getCellStyle();
+ System.out.print("Format=" + style.getDataFormatString() + " ");
+ System.out.print("FG=" + renderColor(style.getFillForegroundColorColor()) + " ");
+ System.out.print("BG=" + renderColor(style.getFillBackgroundColorColor()) + " ");
+
+ Font font = wb.getFontAt(style.getFontIndexAsInt());
+ System.out.print("Font=" + font.getFontName() + " ");
+ System.out.print("FontColor=");
+ if (font instanceof HSSFFont) {
+ System.out.print(renderColor(((HSSFFont) font).getHSSFColor((HSSFWorkbook) wb)));
+ }
+ if (font instanceof XSSFFont) {
+ System.out.print(renderColor(((XSSFFont) font).getXSSFColor()));
+ }
+
+ System.out.println();
+ System.out.println(" " + formatter.formatCellValue(cell));
+ }
+ }
+
+ System.out.println();
+ }
+ }
+ }
+
+ private static String renderColor(Color color) {
+ if(color instanceof HSSFColor) {
+ return ((HSSFColor)color).getHexString();
+ } else if(color instanceof XSSFColor) {
+ return ((XSSFColor)color).getARGBHex();
+ } else {
+ return "(none)";
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.ss;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.formula.ConditionalFormattingEvaluator;
+import org.apache.poi.ss.formula.EvaluationConditionalFormatRule;
+import org.apache.poi.ss.formula.WorkbookEvaluatorProvider;
+import org.apache.poi.ss.usermodel.BuiltinFormats;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.ColorScaleFormatting;
+import org.apache.poi.ss.usermodel.ComparisonOperator;
+import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
+import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
+import org.apache.poi.ss.usermodel.DataBarFormatting;
+import org.apache.poi.ss.usermodel.ExtendedColor;
+import org.apache.poi.ss.usermodel.FontFormatting;
+import org.apache.poi.ss.usermodel.IconMultiStateFormatting;
+import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.PatternFormatting;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Excel Conditional Formatting -- Examples
+ *
+ * <p>
+ * Partly based on the code snippets from
+ * http://www.contextures.com/xlcondformat03.html
+ * </p>
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class ConditionalFormats {
+
+ private ConditionalFormats() {}
+
+ /**
+ * generates a sample workbook with conditional formatting,
+ * and prints out a summary of applied formats for one sheet
+ * @param args pass "-xls" to generate an HSSF workbook, default is XSSF
+ */
+ public static void main(String[] args) throws IOException {
+ final boolean isHSSF = args.length > 0 && args[0].equals("-xls");
+ try (Workbook wb = isHSSF ? new HSSFWorkbook() : new XSSFWorkbook()) {
+
+ 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"));
+ inList(wb.createSheet("In List"));
+ expiry(wb.createSheet("Expiry"));
+ shadeAlt(wb.createSheet("Shade Alt"));
+ shadeBands(wb.createSheet("Shade Bands"));
+ iconSets(wb.createSheet("Icon Sets"));
+ colourScales(wb.createSheet("Colour Scales"));
+ dataBars(wb.createSheet("Data Bars"));
+
+ // print overlapping rule results
+ evaluateRules(wb, "Overlapping");
+
+ // Write the output to a file
+ String file = "cf-poi.xls";
+ if (wb instanceof XSSFWorkbook) {
+ file += "x";
+ }
+ try (FileOutputStream out = new FileOutputStream(file)) {
+ wb.write(out);
+ }
+ System.out.println("Generated: " + file);
+ }
+ }
+
+ /**
+ * Highlight cells based on their values
+ */
+ static void sameCell(Sheet sheet) {
+ sheet.createRow(0).createCell(0).setCellValue(84);
+ sheet.createRow(1).createCell(0).setCellValue(74);
+ sheet.createRow(2).createCell(0).setCellValue(50);
+ sheet.createRow(3).createCell(0).setCellValue(51);
+ sheet.createRow(4).createCell(0).setCellValue(49);
+ sheet.createRow(5).createCell(0).setCellValue(41);
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Cell Value Is greater than 70 (Blue Fill)
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(ComparisonOperator.GT, "70");
+ PatternFormatting fill1 = rule1.createPatternFormatting();
+ fill1.setFillBackgroundColor(IndexedColors.BLUE.index);
+ fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
+
+ // Condition 2: Cell Value Is less than 50 (Green Fill)
+ ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.LT, "50");
+ PatternFormatting fill2 = rule2.createPatternFormatting();
+ fill2.setFillBackgroundColor(IndexedColors.GREEN.index);
+ fill2.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A1:A6")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1, rule2);
+
+ sheet.getRow(0).createCell(2).setCellValue("<== Condition 1: Cell Value Is greater than 70 (Blue Fill)");
+ sheet.getRow(4).createCell(2).setCellValue("<== Condition 2: Cell Value Is less than 50 (Green Fill)");
+ }
+
+ /**
+ * Highlight multiple cells based on a formula
+ */
+ static void multiCell(Sheet sheet) {
+ // header row
+ Row row0 = sheet.createRow(0);
+ row0.createCell(0).setCellValue("Units");
+ row0.createCell(1).setCellValue("Cost");
+ row0.createCell(2).setCellValue("Total");
+
+ Row row1 = sheet.createRow(1);
+ row1.createCell(0).setCellValue(71);
+ row1.createCell(1).setCellValue(29);
+ row1.createCell(2).setCellValue(2059);
+
+ Row row2 = sheet.createRow(2);
+ row2.createCell(0).setCellValue(85);
+ row2.createCell(1).setCellValue(29);
+ row2.createCell(2).setCellValue(2059);
+
+ Row row3 = sheet.createRow(3);
+ row3.createCell(0).setCellValue(71);
+ row3.createCell(1).setCellValue(29);
+ row3.createCell(2).setCellValue(2059);
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Formula Is =$B2>75 (Blue Fill)
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("$A2>75");
+ PatternFormatting fill1 = rule1.createPatternFormatting();
+ fill1.setFillBackgroundColor(IndexedColors.BLUE.index);
+ fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A2:C4")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ 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,
+ * and change the font colour to match the cell colour.
+ * In this example, if formula result is #DIV/0! then it will have white font colour.
+ */
+ static void errors(Sheet sheet) {
+ sheet.createRow(0).createCell(0).setCellValue(84);
+ sheet.createRow(1).createCell(0).setCellValue(0);
+ sheet.createRow(2).createCell(0).setCellFormula("ROUND(A1/A2,0)");
+ sheet.createRow(3).createCell(0).setCellValue(0);
+ sheet.createRow(4).createCell(0).setCellFormula("ROUND(A6/A4,0)");
+ sheet.createRow(5).createCell(0).setCellValue(41);
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Formula Is =ISERROR(C2) (White Font)
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("ISERROR(A1)");
+ FontFormatting font = rule1.createFontFormatting();
+ font.setFontColorIndex(IndexedColors.WHITE.index);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A1:A6")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ sheet.getRow(2).createCell(1).setCellValue("<== The error in this cell is hidden. Condition: Formula Is =ISERROR(C2) (White Font)");
+ sheet.getRow(4).createCell(1).setCellValue("<== The error in this cell is hidden. Condition: Formula Is =ISERROR(C2) (White Font)");
+ }
+
+ /**
+ * Use Excel conditional formatting to hide the duplicate values,
+ * and make the list easier to read. In this example, when the table is sorted by Region,
+ * the second (and subsequent) occurences of each region name will have white font colour.
+ */
+ static void hideDupplicates(Sheet sheet) {
+ sheet.createRow(0).createCell(0).setCellValue("City");
+ sheet.createRow(1).createCell(0).setCellValue("Boston");
+ sheet.createRow(2).createCell(0).setCellValue("Boston");
+ sheet.createRow(3).createCell(0).setCellValue("Chicago");
+ sheet.createRow(4).createCell(0).setCellValue("Chicago");
+ sheet.createRow(5).createCell(0).setCellValue("New York");
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Formula Is =A2=A1 (White Font)
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("A2=A1");
+ FontFormatting font = rule1.createFontFormatting();
+ font.setFontColorIndex(IndexedColors.WHITE.index);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A2:A6")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ sheet.getRow(1).createCell(1).setCellValue("<== the second (and subsequent) " +
+ "occurences of each region name will have white font colour. " +
+ "Condition: Formula Is =A2=A1 (White Font)");
+ }
+
+ /**
+ * Use Excel conditional formatting to highlight duplicate entries in a column.
+ */
+ static void formatDuplicates(Sheet sheet) {
+ sheet.createRow(0).createCell(0).setCellValue("Code");
+ sheet.createRow(1).createCell(0).setCellValue(4);
+ sheet.createRow(2).createCell(0).setCellValue(3);
+ sheet.createRow(3).createCell(0).setCellValue(6);
+ sheet.createRow(4).createCell(0).setCellValue(3);
+ sheet.createRow(5).createCell(0).setCellValue(5);
+ sheet.createRow(6).createCell(0).setCellValue(8);
+ sheet.createRow(7).createCell(0).setCellValue(0);
+ sheet.createRow(8).createCell(0).setCellValue(2);
+ sheet.createRow(9).createCell(0).setCellValue(8);
+ sheet.createRow(10).createCell(0).setCellValue(6);
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Formula Is =A2=A1 (White Font)
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($A$2:$A$11,A2)>1");
+ FontFormatting font = rule1.createFontFormatting();
+ font.setFontStyle(false, true);
+ font.setFontColorIndex(IndexedColors.BLUE.index);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A2:A11")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ sheet.getRow(2).createCell(1).setCellValue("<== Duplicates numbers in the column are highlighted. " +
+ "Condition: Formula Is =COUNTIF($A$2:$A$11,A2)>1 (Blue Font)");
+ }
+
+ /**
+ * Use Excel conditional formatting to highlight items that are in a list on the worksheet.
+ */
+ static void inList(Sheet sheet) {
+ sheet.createRow(0).createCell(0).setCellValue("Codes");
+ sheet.createRow(1).createCell(0).setCellValue("AA");
+ sheet.createRow(2).createCell(0).setCellValue("BB");
+ sheet.createRow(3).createCell(0).setCellValue("GG");
+ sheet.createRow(4).createCell(0).setCellValue("AA");
+ sheet.createRow(5).createCell(0).setCellValue("FF");
+ sheet.createRow(6).createCell(0).setCellValue("XX");
+ sheet.createRow(7).createCell(0).setCellValue("CC");
+
+ sheet.getRow(0).createCell(2).setCellValue("Valid");
+ sheet.getRow(1).createCell(2).setCellValue("AA");
+ sheet.getRow(2).createCell(2).setCellValue("BB");
+ sheet.getRow(3).createCell(2).setCellValue("CC");
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Formula Is =A2=A1 (White Font)
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($C$2:$C$4,A2)");
+ PatternFormatting fill1 = rule1.createPatternFormatting();
+ fill1.setFillBackgroundColor(IndexedColors.LIGHT_BLUE.index);
+ fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A2:A8")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ sheet.getRow(2).createCell(3).setCellValue("<== Use Excel conditional formatting to highlight items that are in a list on the worksheet");
+ }
+
+ /**
+ * Use Excel conditional formatting to highlight payments that are due in the next thirty days.
+ * In this example, Due dates are entered in cells A2:A4.
+ */
+ static void expiry(Sheet sheet) {
+ CellStyle style = sheet.getWorkbook().createCellStyle();
+ style.setDataFormat((short)BuiltinFormats.getBuiltinFormat("d-mmm"));
+
+ sheet.createRow(0).createCell(0).setCellValue("Date");
+ sheet.createRow(1).createCell(0).setCellFormula("TODAY()+29");
+ sheet.createRow(2).createCell(0).setCellFormula("A2+1");
+ sheet.createRow(3).createCell(0).setCellFormula("A3+1");
+
+ for(int rownum = 1; rownum <= 3; rownum++) {
+ sheet.getRow(rownum).getCell(0).setCellStyle(style);
+ }
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Formula Is =A2=A1 (White Font)
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("AND(A2-TODAY()>=0,A2-TODAY()<=30)");
+ FontFormatting font = rule1.createFontFormatting();
+ font.setFontStyle(false, true);
+ font.setFontColorIndex(IndexedColors.BLUE.index);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A2:A4")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ sheet.getRow(0).createCell(1).setCellValue("Dates within the next 30 days are highlighted");
+ }
+
+ /**
+ * Use Excel conditional formatting to shade alternating rows on the worksheet
+ */
+ static void shadeAlt(Sheet sheet) {
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ // Condition 1: Formula Is =A2=A1 (White Font)
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),2)");
+ PatternFormatting fill1 = rule1.createPatternFormatting();
+ fill1.setFillBackgroundColor(IndexedColors.LIGHT_GREEN.index);
+ fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A1:Z100")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ sheet.createRow(0).createCell(1).setCellValue("Shade Alternating Rows");
+ sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),2) (Light Green Fill)");
+ }
+
+ /**
+ * You can use Excel conditional formatting to shade bands of rows on the worksheet.
+ * In this example, 3 rows are shaded light grey, and 3 are left with no shading.
+ * In the MOD function, the total number of rows in the set of banded rows (6) is entered.
+ */
+ static void shadeBands(Sheet sheet) {
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),6)<3");
+ PatternFormatting fill1 = rule1.createPatternFormatting();
+ fill1.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index);
+ fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
+
+ CellRangeAddress[] regions = {
+ CellRangeAddress.valueOf("A1:Z100")
+ };
+
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ 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);
+ }
+
+ /**
+ * Color Scales / Colour Scales / Colour Gradients allow you shade the
+ * background colour of the cell based on the values, eg from Red to
+ * Yellow to Green.
+ */
+ static void colourScales(Sheet sheet) {
+ sheet.createRow(0).createCell(0).setCellValue("Colour Scales");
+ Row r = sheet.createRow(1);
+ r.createCell(0).setCellValue("Red-Yellow-Green");
+ for (int i=1; i<=7; i++) {
+ r.createCell(i).setCellValue((i-1)*5.0);
+ }
+ r = sheet.createRow(2);
+ r.createCell(0).setCellValue("Red-White-Blue");
+ for (int i=1; i<=9; i++) {
+ r.createCell(i).setCellValue((i-1)*5.0);
+ }
+ r = sheet.createRow(3);
+ r.createCell(0).setCellValue("Blue-Green");
+ for (int i=1; i<=16; i++) {
+ r.createCell(i).setCellValue((i-1));
+ }
+ sheet.setColumnWidth(0, 5000);
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:H2") };
+ ConditionalFormattingRule rule1 =
+ sheetCF.createConditionalFormattingColorScaleRule();
+ ColorScaleFormatting cs1 = rule1.getColorScaleFormatting();
+ cs1.getThresholds()[0].setRangeType(RangeType.MIN);
+ cs1.getThresholds()[1].setRangeType(RangeType.PERCENTILE);
+ cs1.getThresholds()[1].setValue(50d);
+ cs1.getThresholds()[2].setRangeType(RangeType.MAX);
+ ((ExtendedColor)cs1.getColors()[0]).setARGBHex("FFF8696B");
+ ((ExtendedColor)cs1.getColors()[1]).setARGBHex("FFFFEB84");
+ ((ExtendedColor)cs1.getColors()[2]).setARGBHex("FF63BE7B");
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B3:J3") };
+ ConditionalFormattingRule rule2 =
+ sheetCF.createConditionalFormattingColorScaleRule();
+ ColorScaleFormatting cs2 = rule2.getColorScaleFormatting();
+ cs2.getThresholds()[0].setRangeType(RangeType.MIN);
+ cs2.getThresholds()[1].setRangeType(RangeType.PERCENTILE);
+ cs2.getThresholds()[1].setValue(50d);
+ cs2.getThresholds()[2].setRangeType(RangeType.MAX);
+ ((ExtendedColor)cs2.getColors()[0]).setARGBHex("FFF8696B");
+ ((ExtendedColor)cs2.getColors()[1]).setARGBHex("FFFCFCFF");
+ ((ExtendedColor)cs2.getColors()[2]).setARGBHex("FF5A8AC6");
+ sheetCF.addConditionalFormatting(regions, rule2);
+
+ regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B4:Q4") };
+ ConditionalFormattingRule rule3=
+ sheetCF.createConditionalFormattingColorScaleRule();
+ ColorScaleFormatting cs3 = rule3.getColorScaleFormatting();
+ cs3.setNumControlPoints(2);
+ cs3.getThresholds()[0].setRangeType(RangeType.MIN);
+ cs3.getThresholds()[1].setRangeType(RangeType.MAX);
+ ((ExtendedColor)cs3.getColors()[0]).setARGBHex("FF5A8AC6");
+ ((ExtendedColor)cs3.getColors()[1]).setARGBHex("FF63BE7B");
+ sheetCF.addConditionalFormatting(regions, rule3);
+ }
+
+ /**
+ * DataBars / Data-Bars allow you to have bars shown vary
+ * based on the values, from full to empty
+ */
+ static void dataBars(Sheet sheet) {
+ sheet.createRow(0).createCell(0).setCellValue("Data Bars");
+ Row r = sheet.createRow(1);
+ r.createCell(1).setCellValue("Green Positive");
+ r.createCell(2).setCellValue("Blue Mix");
+ r.createCell(3).setCellValue("Red Negative");
+ r = sheet.createRow(2);
+ r.createCell(1).setCellValue(0);
+ r.createCell(2).setCellValue(0);
+ r.createCell(3).setCellValue(0);
+ r = sheet.createRow(3);
+ r.createCell(1).setCellValue(5);
+ r.createCell(2).setCellValue(-5);
+ r.createCell(3).setCellValue(-5);
+ r = sheet.createRow(4);
+ r.createCell(1).setCellValue(10);
+ r.createCell(2).setCellValue(10);
+ r.createCell(3).setCellValue(-10);
+ r = sheet.createRow(5);
+ r.createCell(1).setCellValue(5);
+ r.createCell(2).setCellValue(5);
+ r.createCell(3).setCellValue(-5);
+ r = sheet.createRow(6);
+ r.createCell(1).setCellValue(20);
+ r.createCell(2).setCellValue(-10);
+ r.createCell(3).setCellValue(-20);
+ sheet.setColumnWidth(0, 3000);
+ sheet.setColumnWidth(1, 5000);
+ sheet.setColumnWidth(2, 5000);
+ sheet.setColumnWidth(3, 5000);
+
+ SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ ExtendedColor color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
+ color.setARGBHex("FF63BE7B");
+ CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:B7") };
+ ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(color);
+ DataBarFormatting db1 = rule1.getDataBarFormatting();
+ db1.getMinThreshold().setRangeType(RangeType.MIN);
+ db1.getMaxThreshold().setRangeType(RangeType.MAX);
+ sheetCF.addConditionalFormatting(regions, rule1);
+
+ color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
+ color.setARGBHex("FF5A8AC6");
+ regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C2:C7") };
+ ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(color);
+ DataBarFormatting db2 = rule2.getDataBarFormatting();
+ db2.getMinThreshold().setRangeType(RangeType.MIN);
+ db2.getMaxThreshold().setRangeType(RangeType.MAX);
+ sheetCF.addConditionalFormatting(regions, rule2);
+
+ color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
+ color.setARGBHex("FFF8696B");
+ regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D2:D7") };
+ ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule(color);
+ DataBarFormatting db3 = rule3.getDataBarFormatting();
+ db3.getMinThreshold().setRangeType(RangeType.MIN);
+ db3.getMaxThreshold().setRangeType(RangeType.MAX);
+ sheetCF.addConditionalFormatting(regions, rule3);
+ }
+
+ /**
+ * Print out a summary of the conditional formatting rules applied to cells on the given sheet.
+ * Only cells with a matching rule are printed, and for those, all matching rules are sumarized.
+ */
+ static void evaluateRules(Workbook wb, String sheetName) {
+ final WorkbookEvaluatorProvider wbEvalProv = (WorkbookEvaluatorProvider) wb.getCreationHelper().createFormulaEvaluator();
+ final ConditionalFormattingEvaluator cfEval = new ConditionalFormattingEvaluator(wb, wbEvalProv);
+ // if cell values have changed, clear cached format results
+ cfEval.clearAllCachedValues();
+
+ final Sheet sheet = wb.getSheet(sheetName);
+ for (Row r : sheet) {
+ for (Cell c : r) {
+ final List<EvaluationConditionalFormatRule> rules = cfEval.getConditionalFormattingForCell(c);
+ // check rules list for null, although current implementation will return an empty list, not null, then do what you want with results
+ if (rules == null || rules.isEmpty()) {
+ continue;
+ }
+ final CellReference ref = ConditionalFormattingEvaluator.getRef(c);
+ if (rules.isEmpty()) {
+ continue;
+ }
+
+ System.out.println("\n"
+ + ref.formatAsString()
+ + " has conditional formatting.");
+
+ for (EvaluationConditionalFormatRule rule : rules) {
+ ConditionalFormattingRule cf = rule.getRule();
+
+ StringBuilder b = new StringBuilder();
+ b.append("\tRule ")
+ .append(rule.getFormattingIndex())
+ .append(": ");
+
+ // check for color scale
+ if (cf.getColorScaleFormatting() != null) {
+ b.append("\n\t\tcolor scale (caller must calculate bucket)");
+ }
+ // check for data bar
+ if (cf.getDataBarFormatting() != null) {
+ b.append("\n\t\tdata bar (caller must calculate bucket)");
+ }
+ // check for icon set
+ if (cf.getMultiStateFormatting() != null) {
+ b.append("\n\t\ticon set (caller must calculate icon bucket)");
+ }
+ // check for fill
+ if (cf.getPatternFormatting() != null) {
+ final PatternFormatting fill = cf.getPatternFormatting();
+ b.append("\n\t\tfill pattern ")
+ .append(fill.getFillPattern())
+ .append(" color index ")
+ .append(fill.getFillBackgroundColor());
+ }
+ // font stuff
+ if (cf.getFontFormatting() != null) {
+ final FontFormatting ff = cf.getFontFormatting();
+ b.append("\n\t\tfont format ")
+ .append("color index ")
+ .append(ff.getFontColorIndex());
+ if (ff.isBold()) {
+ b.append(" bold");
+ }
+ if (ff.isItalic()) {
+ b.append(" italic");
+ }
+ if (ff.isStruckout()) {
+ b.append(" strikeout");
+ }
+ b.append(" underline index ")
+ .append(ff.getUnderlineType());
+ }
+
+ System.out.println(b);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.ss;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.BorderExtent;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.PropertyTemplate;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Excel Border Drawing - examples
+ *
+ * <p>
+ * Partly based on the code snippets from
+ * org.apache.poi.ss.examples.ConditionalFormats
+ * </p>
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class DrawingBorders {
+
+ private DrawingBorders() {}
+
+ public static void main(String[] args) throws IOException {
+ try (Workbook wb = (args.length > 0 && args[0].equals("-xls"))
+ ? new HSSFWorkbook() : new XSSFWorkbook()) {
+ // add a sheet, and put some values into it
+ Sheet sh1 = wb.createSheet("Sheet1");
+ Row r = sh1.createRow(0);
+ Cell c = r.createCell(1);
+ c.setCellValue("All Borders Medium Width");
+ r = sh1.createRow(4);
+ c = r.createCell(1);
+ c.setCellValue("Medium Outside / Thin Inside Borders");
+ r = sh1.createRow(8);
+ c = r.createCell(1);
+ c.setCellValue("Colored Borders");
+
+ // draw borders (three 3x3 grids)
+ PropertyTemplate pt = new PropertyTemplate();
+ // #1) these borders will all be medium in default color
+ pt.drawBorders(new CellRangeAddress(1, 3, 1, 3),
+ BorderStyle.MEDIUM, BorderExtent.ALL);
+ // #2) these cells will have medium outside borders and thin inside borders
+ pt.drawBorders(new CellRangeAddress(5, 7, 1, 3),
+ BorderStyle.MEDIUM, BorderExtent.OUTSIDE);
+ pt.drawBorders(new CellRangeAddress(5, 7, 1, 3), BorderStyle.THIN,
+ BorderExtent.INSIDE);
+ // #3) these cells will all be medium weight with different colors for the
+ // outside, inside horizontal, and inside vertical borders. The center
+ // cell will have no borders.
+ pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
+ BorderStyle.MEDIUM, IndexedColors.RED.getIndex(),
+ BorderExtent.OUTSIDE);
+ pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
+ BorderStyle.MEDIUM, IndexedColors.BLUE.getIndex(),
+ BorderExtent.INSIDE_VERTICAL);
+ pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
+ BorderStyle.MEDIUM, IndexedColors.GREEN.getIndex(),
+ BorderExtent.INSIDE_HORIZONTAL);
+ pt.drawBorders(new CellRangeAddress(10, 10, 2, 2),
+ BorderStyle.NONE,
+ BorderExtent.ALL);
+
+ // apply borders to sheet
+ pt.applyBorders(sh1);
+
+ // add another sheet and apply the borders to it
+ Sheet sh2 = wb.createSheet("Sheet2");
+ pt.applyBorders(sh2);
+
+ // Write the output to a file
+ String file = "db-poi.xls" + (wb instanceof XSSFWorkbook ? "x" : "");
+ try (FileOutputStream out = new FileOutputStream(file)) {
+ wb.write(out);
+ }
+ System.out.println("Generated: " + file);
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.Color;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+
+/**
+ * Utility to compare Excel File Contents cell by cell for all sheets.
+ *
+ * <p>This utility will be used to compare Excel File Contents cell by cell for all sheets programmatically.</p>
+ *
+ * <p>Below are the list of Attribute comparison supported in this version.</p>
+ *
+ * <ul>
+ * <li>Cell Alignment</li>
+ * <li>Cell Border Attributes</li>
+ * <li>Cell Data</li>
+ * <li>Cell Data-Type</li>
+ * <li>Cell Fill Color</li>
+ * <li>Cell Fill pattern</li>
+ * <li>Cell Font Attributes</li>
+ * <li>Cell Font Family</li>
+ * <li>Cell Font Size</li>
+ * <li>Cell Protection</li>
+ * <li>Name of the sheets</li>
+ * <li>Number of Columns</li>
+ * <li>Number of Rows</li>
+ * <li>Number of Sheet</li>
+ * </ul>
+ *
+ * <p>(Some of the above attribute comparison only work for *.xlsx format currently. In future it can be enhanced.)</p>
+ *
+ * <p><b>Usage:</b></p>
+ *
+ * <pre>
+ * {@code
+ * Workbook wb1 = WorkbookFactory.create(new File("workBook1.xls"));
+ * Workbook wb2 = WorkbookFactory.create(new File("workBook2.xls"));
+ * List<String> listOfDifferences = ExcelComparator.compare(wb1, wb2);
+ * for (String differences : listOfDifferences)
+ * System.out.println(differences);
+ * System.out.println("DifferenceFound = "+ excelFileDifference.isDifferenceFound);
+ * }
+ * </pre>
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public class ExcelComparator {
+
+ private static final String CELL_DATA_DOES_NOT_MATCH = "Cell Data does not Match ::";
+ private static final String CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH = "Cell Font Attributes does not Match ::";
+
+ private static class Locator {
+ Workbook workbook;
+ Sheet sheet;
+ Row row;
+ Cell cell;
+ }
+
+ List<String> listOfDifferences = new ArrayList<>();
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 2 || !(new File(args[0]).exists()) || !(new File(args[1]).exists())) {
+ System.err.println("java -cp <classpath> "+ExcelComparator.class.getCanonicalName()+" <workbook1.xls/x> <workbook2.xls/x");
+ System.exit(-1);
+ }
+
+ try (Workbook wb1 = WorkbookFactory.create(new File(args[0]), null, true)) {
+ try (Workbook wb2 = WorkbookFactory.create(new File(args[1]), null, true)) {
+ for (String d : ExcelComparator.compare(wb1, wb2)) {
+ System.out.println(d);
+ }
+ }
+ }
+ }
+
+ /**
+ * Utility to compare Excel File Contents cell by cell for all sheets.
+ *
+ * @param wb1 the workbook1
+ * @param wb2 the workbook2
+ * @return the Excel file difference containing a flag and a list of differences
+ */
+ public static List<String> compare(Workbook wb1, Workbook wb2) {
+ Locator loc1 = new Locator();
+ Locator loc2 = new Locator();
+ loc1.workbook = wb1;
+ loc2.workbook = wb2;
+
+ ExcelComparator excelComparator = new ExcelComparator();
+ excelComparator.compareNumberOfSheets(loc1, loc2 );
+ excelComparator.compareSheetNames(loc1, loc2);
+ excelComparator.compareSheetData(loc1, loc2);
+
+ return excelComparator.listOfDifferences;
+ }
+
+ /**
+ * Compare data in all sheets.
+ */
+ private void compareDataInAllSheets(Locator loc1, Locator loc2) {
+ for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) {
+ if (loc2.workbook.getNumberOfSheets() <= i) {
+ return;
+ }
+
+ loc1.sheet = loc1.workbook.getSheetAt(i);
+ loc2.sheet = loc2.workbook.getSheetAt(i);
+
+ compareDataInSheet(loc1, loc2);
+ }
+ }
+
+ private void compareDataInSheet(Locator loc1, Locator loc2) {
+ for (int j = 0; j <= loc1.sheet.getLastRowNum(); j++) {
+ if (loc2.sheet.getLastRowNum() <= j) {
+ return;
+ }
+
+ loc1.row = loc1.sheet.getRow(j);
+ loc2.row = loc2.sheet.getRow(j);
+
+ if ((loc1.row == null) || (loc2.row == null)) {
+ continue;
+ }
+
+ compareDataInRow(loc1, loc2);
+ }
+ }
+
+ private void compareDataInRow(Locator loc1, Locator loc2) {
+ for (int k = 0; k <= loc1.row.getLastCellNum(); k++) {
+ if (loc2.row.getLastCellNum() <= k) {
+ return;
+ }
+
+ loc1.cell = loc1.row.getCell(k);
+ loc2.cell = loc2.row.getCell(k);
+
+ if ((loc1.cell == null) || (loc2.cell == null)) {
+ continue;
+ }
+
+ compareDataInCell(loc1, loc2);
+ }
+ }
+
+ private void compareDataInCell(Locator loc1, Locator loc2) {
+ if (isCellTypeMatches(loc1, loc2)) {
+ final CellType loc1cellType = loc1.cell.getCellType();
+ switch(loc1cellType) {
+ case BLANK:
+ case STRING:
+ case ERROR:
+ isCellContentMatches(loc1,loc2);
+ break;
+ case BOOLEAN:
+ isCellContentMatchesForBoolean(loc1,loc2);
+ break;
+ case FORMULA:
+ isCellContentMatchesForFormula(loc1,loc2);
+ break;
+ case NUMERIC:
+ if (DateUtil.isCellDateFormatted(loc1.cell)) {
+ isCellContentMatchesForDate(loc1,loc2);
+ } else {
+ isCellContentMatchesForNumeric(loc1,loc2);
+ }
+ break;
+ default:
+ throw new IllegalStateException("Unexpected cell type: " + loc1cellType);
+ }
+ }
+
+ isCellFillPatternMatches(loc1,loc2);
+ isCellAlignmentMatches(loc1,loc2);
+ isCellHiddenMatches(loc1,loc2);
+ isCellLockedMatches(loc1,loc2);
+ isCellFontFamilyMatches(loc1,loc2);
+ isCellFontSizeMatches(loc1,loc2);
+ isCellFontBoldMatches(loc1,loc2);
+ isCellUnderLineMatches(loc1,loc2);
+ isCellFontItalicsMatches(loc1,loc2);
+ isCellBorderMatches(loc1,loc2,'t');
+ isCellBorderMatches(loc1,loc2,'l');
+ isCellBorderMatches(loc1,loc2,'b');
+ isCellBorderMatches(loc1,loc2,'r');
+ isCellFillBackGroundMatches(loc1,loc2);
+ }
+
+ /**
+ * Compare number of columns in sheets.
+ */
+ private void compareNumberOfColumnsInSheets(Locator loc1, Locator loc2) {
+ for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) {
+ if (loc2.workbook.getNumberOfSheets() <= i) {
+ return;
+ }
+
+ loc1.sheet = loc1.workbook.getSheetAt(i);
+ loc2.sheet = loc2.workbook.getSheetAt(i);
+
+ Iterator<Row> ri1 = loc1.sheet.rowIterator();
+ Iterator<Row> ri2 = loc2.sheet.rowIterator();
+
+ int num1 = (ri1.hasNext()) ? ri1.next().getPhysicalNumberOfCells() : 0;
+ int num2 = (ri2.hasNext()) ? ri2.next().getPhysicalNumberOfCells() : 0;
+
+ if (num1 != num2) {
+ String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]",
+ "Number Of Columns does not Match ::",
+ loc1.sheet.getSheetName(), num1,
+ loc2.sheet.getSheetName(), num2
+ );
+ listOfDifferences.add(str);
+ }
+ }
+ }
+
+ /**
+ * Compare number of rows in sheets.
+ */
+ private void compareNumberOfRowsInSheets(Locator loc1, Locator loc2) {
+ for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) {
+ if (loc2.workbook.getNumberOfSheets() <= i) {
+ return;
+ }
+
+ loc1.sheet = loc1.workbook.getSheetAt(i);
+ loc2.sheet = loc2.workbook.getSheetAt(i);
+
+ int num1 = loc1.sheet.getPhysicalNumberOfRows();
+ int num2 = loc2.sheet.getPhysicalNumberOfRows();
+
+ if (num1 != num2) {
+ String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]",
+ "Number Of Rows does not Match ::",
+ loc1.sheet.getSheetName(), num1,
+ loc2.sheet.getSheetName(), num2
+ );
+ listOfDifferences.add(str);
+ }
+ }
+
+ }
+
+ /**
+ * Compare number of sheets.
+ */
+ private void compareNumberOfSheets(Locator loc1, Locator loc2) {
+ int num1 = loc1.workbook.getNumberOfSheets();
+ int num2 = loc2.workbook.getNumberOfSheets();
+ if (num1 != num2) {
+ String str = String.format(Locale.ROOT, "%s\nworkbook1 [%d] != workbook2 [%d]",
+ "Number of Sheets do not match ::",
+ num1, num2
+ );
+
+ listOfDifferences.add(str);
+
+ }
+ }
+
+ /**
+ * Compare sheet data.
+ */
+ private void compareSheetData(Locator loc1, Locator loc2) {
+ compareNumberOfRowsInSheets(loc1, loc2);
+ compareNumberOfColumnsInSheets(loc1, loc2);
+ compareDataInAllSheets(loc1, loc2);
+
+ }
+
+ /**
+ * Compare sheet names.
+ */
+ private void compareSheetNames(Locator loc1, Locator loc2) {
+ for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) {
+ String name1 = loc1.workbook.getSheetName(i);
+ String name2 = (loc2.workbook.getNumberOfSheets() > i) ? loc2.workbook.getSheetName(i) : "";
+
+ if (!name1.equals(name2)) {
+ String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]",
+ "Name of the sheets do not match ::", name1, i+1, name2, i+1
+ );
+ listOfDifferences.add(str);
+ }
+ }
+ }
+
+ /**
+ * Formats the message.
+ */
+ private void addMessage(Locator loc1, Locator loc2, String messageStart, String value1, String value2) {
+ String str =
+ String.format(Locale.ROOT, "%s\nworkbook1 -> %s -> %s [%s] != workbook2 -> %s -> %s [%s]",
+ messageStart,
+ loc1.sheet.getSheetName(), new CellReference(loc1.cell).formatAsString(), value1,
+ loc2.sheet.getSheetName(), new CellReference(loc2.cell).formatAsString(), value2
+ );
+ listOfDifferences.add(str);
+ }
+
+ /**
+ * Checks if cell alignment matches.
+ */
+ private void isCellAlignmentMatches(Locator loc1, Locator loc2) {
+ if(loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ HorizontalAlignment align1 = loc1.cell.getCellStyle().getAlignment();
+ HorizontalAlignment align2 = loc2.cell.getCellStyle().getAlignment();
+ if (align1 != align2) {
+ addMessage(loc1, loc2,
+ "Cell Alignment does not Match ::",
+ align1.name(),
+ align2.name()
+ );
+ }
+ }
+
+ /**
+ * Checks if cell border bottom matches.
+ */
+ private void isCellBorderMatches(Locator loc1, Locator loc2, char borderSide) {
+ if (!(loc1.cell instanceof XSSFCell) ||
+ loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ XSSFCellStyle style1 = ((XSSFCell)loc1.cell).getCellStyle();
+ XSSFCellStyle style2 = ((XSSFCell)loc2.cell).getCellStyle();
+ boolean b1, b2;
+ String borderName;
+ switch (borderSide) {
+ case 't': default:
+ b1 = style1.getBorderTop() == BorderStyle.THIN;
+ b2 = style2.getBorderTop() == BorderStyle.THIN;
+ borderName = "TOP";
+ break;
+ case 'b':
+ b1 = style1.getBorderBottom() == BorderStyle.THIN;
+ b2 = style2.getBorderBottom() == BorderStyle.THIN;
+ borderName = "BOTTOM";
+ break;
+ case 'l':
+ b1 = style1.getBorderLeft() == BorderStyle.THIN;
+ b2 = style2.getBorderLeft() == BorderStyle.THIN;
+ borderName = "LEFT";
+ break;
+ case 'r':
+ b1 = style1.getBorderRight() == BorderStyle.THIN;
+ b2 = style2.getBorderRight() == BorderStyle.THIN;
+ borderName = "RIGHT";
+ break;
+ }
+ if (b1 != b2) {
+ addMessage(loc1, loc2,
+ "Cell Border Attributes does not Match ::",
+ (b1 ? "" : "NOT ")+borderName+" BORDER",
+ (b2 ? "" : "NOT ")+borderName+" BORDER"
+ );
+ }
+ }
+
+ /**
+ * Checks if cell content matches.
+ */
+ private void isCellContentMatches(Locator loc1, Locator loc2) {
+ String str1 = loc1.cell.toString();
+ String str2 = loc2.cell.toString();
+ if (!str1.equals(str2)) {
+ addMessage(loc1,loc2,CELL_DATA_DOES_NOT_MATCH,str1,str2);
+ }
+ }
+
+ /**
+ * Checks if cell content matches for boolean.
+ */
+ private void isCellContentMatchesForBoolean(Locator loc1, Locator loc2) {
+ boolean b1 = loc1.cell.getBooleanCellValue();
+ boolean b2 = loc2.cell.getBooleanCellValue();
+ if (b1 != b2) {
+ addMessage(loc1,loc2,CELL_DATA_DOES_NOT_MATCH,Boolean.toString(b1),Boolean.toString(b2));
+ }
+ }
+
+ /**
+ * Checks if cell content matches for date.
+ */
+ private void isCellContentMatchesForDate(Locator loc1, Locator loc2) {
+ Date date1 = loc1.cell.getDateCellValue();
+ Date date2 = loc2.cell.getDateCellValue();
+ if (!date1.equals(date2)) {
+ addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, date1.toString(), date2.toString());
+ }
+ }
+
+
+ /**
+ * Checks if cell content matches for formula.
+ */
+ private void isCellContentMatchesForFormula(Locator loc1, Locator loc2) {
+ // TODO: actually evaluate the formula / NPE checks
+ String form1 = loc1.cell.getCellFormula();
+ String form2 = loc2.cell.getCellFormula();
+ if (!form1.equals(form2)) {
+ addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, form1, form2);
+ }
+ }
+
+ /**
+ * Checks if cell content matches for numeric.
+ */
+ private void isCellContentMatchesForNumeric(Locator loc1, Locator loc2) {
+ // TODO: Check for NaN
+ double num1 = loc1.cell.getNumericCellValue();
+ double num2 = loc2.cell.getNumericCellValue();
+ if (num1 != num2) {
+ addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, Double.toString(num1), Double.toString(num2));
+ }
+ }
+
+ private String getCellFillBackground(Locator loc) {
+ Color col = loc.cell.getCellStyle().getFillForegroundColorColor();
+ return (col instanceof XSSFColor) ? ((XSSFColor)col).getARGBHex() : "NO COLOR";
+ }
+
+ /**
+ * Checks if cell file back ground matches.
+ */
+ private void isCellFillBackGroundMatches(Locator loc1, Locator loc2) {
+ if(loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ String col1 = getCellFillBackground(loc1);
+ String col2 = getCellFillBackground(loc2);
+ if (!col1.equals(col2)) {
+ addMessage(loc1, loc2, "Cell Fill Color does not Match ::", col1, col2);
+ }
+ }
+ /**
+ * Checks if cell fill pattern matches.
+ */
+ private void isCellFillPatternMatches(Locator loc1, Locator loc2) {
+ if(loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ FillPatternType fill1 = loc1.cell.getCellStyle().getFillPattern();
+ FillPatternType fill2 = loc2.cell.getCellStyle().getFillPattern();
+ if (fill1 != fill2) {
+ addMessage(loc1, loc2,
+ "Cell Fill pattern does not Match ::",
+ fill1.name(),
+ fill2.name()
+ );
+ }
+ }
+
+ /**
+ * Checks if cell font bold matches.
+ */
+ private void isCellFontBoldMatches(Locator loc1, Locator loc2) {
+ if (!(loc1.cell instanceof XSSFCell) ||
+ loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ if(hasInvalidFontIndex(loc1, loc2)) {
+ return;
+ }
+
+ boolean b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getBold();
+ boolean b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getBold();
+ if (b1 != b2) {
+ addMessage(loc1, loc2,
+ CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH,
+ (b1 ? "" : "NOT ")+"BOLD",
+ (b2 ? "" : "NOT ")+"BOLD"
+ );
+ }
+ }
+
+ /**
+ * Checks if cell font family matches.
+ */
+ private void isCellFontFamilyMatches(Locator loc1, Locator loc2) {
+ if (!(loc1.cell instanceof XSSFCell) ||
+ loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ if(hasInvalidFontIndex(loc1, loc2)) {
+ return;
+ }
+
+ String family1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getFontName();
+ String family2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getFontName();
+ if (!family1.equals(family2)) {
+ addMessage(loc1, loc2, "Cell Font Family does not Match ::", family1, family2);
+ }
+ }
+
+ private boolean hasInvalidFontIndex(Locator loc1, Locator loc2) {
+ int fontIdx1 = loc1.cell.getCellStyle().getFontIndexAsInt();
+ int fontCount1 = ((XSSFWorkbook)loc1.workbook).getStylesSource().getFonts().size();
+ int fontIdx2 = loc2.cell.getCellStyle().getFontIndexAsInt();
+ int fontCount2 = ((XSSFWorkbook)loc2.workbook).getStylesSource().getFonts().size();
+
+ if(fontIdx1 >= fontCount1 || fontIdx2 >= fontCount2) {
+ addMessage(loc1, loc2, "Corrupted file, cell style references a font which is not defined", Integer.toString(fontIdx1), Integer.toString(fontIdx2));
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks if cell font italics matches.
+ */
+ private void isCellFontItalicsMatches(Locator loc1, Locator loc2) {
+ if (!(loc1.cell instanceof XSSFCell) ||
+ loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ if(hasInvalidFontIndex(loc1, loc2)) {
+ return;
+ }
+
+ boolean b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getItalic();
+ boolean b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getItalic();
+ if (b1 != b2) {
+ addMessage(loc1, loc2,
+ CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH,
+ (b1 ? "" : "NOT ")+"ITALICS",
+ (b2 ? "" : "NOT ")+"ITALICS"
+ );
+ }
+ }
+
+ /**
+ * Checks if cell font size matches.
+ */
+ private void isCellFontSizeMatches(Locator loc1, Locator loc2) {
+ if (!(loc1.cell instanceof XSSFCell) ||
+ loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ if(hasInvalidFontIndex(loc1, loc2)) {
+ return;
+ }
+
+ short size1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getFontHeightInPoints();
+ short size2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getFontHeightInPoints();
+ if (size1 != size2) {
+ addMessage(loc1, loc2,
+ "Cell Font Size does not Match ::",
+ Short.toString(size1),
+ Short.toString(size2)
+ );
+ }
+ }
+
+ /**
+ * Checks if cell hidden matches.
+ */
+ private void isCellHiddenMatches(Locator loc1, Locator loc2) {
+ if (loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ boolean b1 = loc1.cell.getCellStyle().getHidden();
+ boolean b2 = loc1.cell.getCellStyle().getHidden();
+ if (b1 != b2) {
+ addMessage(loc1, loc2,
+ "Cell Visibility does not Match ::",
+ (b1 ? "" : "NOT ")+"HIDDEN",
+ (b2 ? "" : "NOT ")+"HIDDEN"
+ );
+ }
+ }
+
+ /**
+ * Checks if cell locked matches.
+ */
+ private void isCellLockedMatches(Locator loc1, Locator loc2) {
+ if (loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ boolean b1 = loc1.cell.getCellStyle().getLocked();
+ boolean b2 = loc1.cell.getCellStyle().getLocked();
+ if (b1 != b2) {
+ addMessage(loc1, loc2,
+ "Cell Protection does not Match ::",
+ (b1 ? "" : "NOT ")+"LOCKED",
+ (b2 ? "" : "NOT ")+"LOCKED"
+ );
+ }
+ }
+
+ /**
+ * Checks if cell type matches.
+ */
+ private boolean isCellTypeMatches(Locator loc1, Locator loc2) {
+ CellType type1 = loc1.cell.getCellType();
+ CellType type2 = loc2.cell.getCellType();
+ if (type1 == type2) {
+ return true;
+ }
+
+ addMessage(loc1, loc2,
+ "Cell Data-Type does not Match in :: ",
+ type1.name(), type2.name()
+ );
+ return false;
+ }
+
+ /**
+ * Checks if cell under line matches.
+ */
+ private void isCellUnderLineMatches(Locator loc1, Locator loc2) {
+ // TODO: distinguish underline type
+
+ if (!(loc1.cell instanceof XSSFCell) ||
+ loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
+ return;
+ }
+
+ if(hasInvalidFontIndex(loc1, loc2)) {
+ return;
+ }
+
+ byte b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getUnderline();
+ byte b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getUnderline();
+ if (b1 != b2) {
+ addMessage(loc1, loc2,
+ CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH,
+ (b1 == 1 ? "" : "NOT ")+"UNDERLINE",
+ (b2 == 1 ? "" : "NOT ")+"UNDERLINE"
+ );
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+ /* ====================================================================
+ 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.examples.ss;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DataValidation;
+import org.apache.poi.ss.usermodel.DataValidationConstraint;
+import org.apache.poi.ss.usermodel.DataValidationHelper;
+import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates one technique that may be used to create linked or dependent
+ * drop down lists. This refers to a situation in which the selection made
+ * in one drop down list affects the options that are displayed in the second
+ * or subsequent drop down list(s). In this example, the value the user selects
+ * from the down list in cell A1 will affect the values displayed in the linked
+ * drop down list in cell B1. For the sake of simplicity, the data for the drop
+ * down lists is included on the same worksheet but this does not have to be the
+ * case; the data could appear on a separate sheet. If this were done, then the
+ * names for the regions would have to be different, they would have to include
+ * the name of the sheet.
+ *
+ * There are two keys to this technique. The first is the use of named area or
+ * regions of cells to hold the data for the drop down lists and the second is
+ * making use of the INDIRECT() function to convert a name into the addresses
+ * of the cells it refers to.
+ *
+ * Note that whilst this class builds just two linked drop down lists, there is
+ * nothing to prevent more being created. Quite simply, use the value selected
+ * by the user in one drop down list to determine what is shown in another and the
+ * value selected in that drop down list to determine what is shown in a third,
+ * and so on. Also, note that the data for the drop down lists is contained on
+ * contained on the same sheet as the validations themselves. This is done simply
+ * for simplicity and there is nothing to prevent a separate sheet being created
+ * and used to hold the data. If this is done then problems may be encountered
+ * if the sheet is opened with OpenOffice Calc. To prevent these problems, it is
+ * better to include the name of the sheet when calling the setRefersToFormula()
+ * method.
+ *
+ * @author Mark Beardsley [msb at apache.org]
+ * @version 1.00 30th March 2012
+ */
+public class LinkedDropDownLists {
+
+ LinkedDropDownLists(String workbookName) throws IOException {
+ // Using the ss.usermodel allows this class to support both binary
+ // and xml based workbooks. The choice of which one to create is
+ // made by checking the file extension.
+ try (Workbook workbook = workbookName.endsWith(".xlsx") ? new XSSFWorkbook() : new HSSFWorkbook()) {
+
+ // Build the sheet that will hold the data for the validations. This
+ // must be done first as it will create names that are referenced
+ // later.
+ Sheet sheet = workbook.createSheet("Linked Validations");
+ LinkedDropDownLists.buildDataSheet(sheet);
+
+ // Build the first data validation to occupy cell A1. Note
+ // that it retrieves it's data from the named area or region called
+ // CHOICES. Further information about this can be found in the
+ // static buildDataSheet() method below.
+ CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
+ DataValidationHelper dvHelper = sheet.getDataValidationHelper();
+ DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint("CHOICES");
+ DataValidation validation = dvHelper.createValidation(dvConstraint, addressList);
+ sheet.addValidationData(validation);
+
+ // Now, build the linked or dependent drop down list that will
+ // occupy cell B1. The key to the whole process is the use of the
+ // INDIRECT() function. In the buildDataSheet(0 method, a series of
+ // named regions are created and the names of three of them mirror
+ // the options available to the user in the first drop down list
+ // (in cell A1). Using the INDIRECT() function makes it possible
+ // to convert the selection the user makes in that first drop down
+ // into the addresses of a named region of cells and then to use
+ // those cells to populate the second drop down list.
+ addressList = new CellRangeAddressList(0, 0, 1, 1);
+ dvConstraint = dvHelper.createFormulaListConstraint(
+ "INDIRECT(UPPER($A$1))");
+ validation = dvHelper.createValidation(dvConstraint, addressList);
+ sheet.addValidationData(validation);
+
+ try (FileOutputStream fos = new FileOutputStream(workbookName)) {
+ workbook.write(fos);
+ }
+ }
+ }
+
+ /**
+ * Called to populate the named areas/regions. The contents of the cells on
+ * row one will be used to populate the first drop down list. The contents of
+ * the cells on rows two, three and four will be used to populate the second
+ * drop down list, just which row will be determined by the choice the user
+ * makes in the first drop down list.
+ *
+ * In all cases, the approach is to create a row, create and populate cells
+ * with data and then specify a name that identifies those cells. With the
+ * exception of the first range, the names that are chosen for each range
+ * of cells are quite important. In short, each of the options the user
+ * could select in the first drop down list is used as the name for another
+ * range of cells. Thus, in this example, the user can select either
+ * 'Animal', 'Vegetable' or 'Mineral' in the first drop down and so the
+ * sheet contains ranges named 'ANIMAL', 'VEGETABLE' and 'MINERAL'.
+ *
+ * @param dataSheet An instance of a class that implements the Sheet Sheet
+ * interface (HSSFSheet or XSSFSheet).
+ */
+ private static void buildDataSheet(Sheet dataSheet) {
+ Row row = null;
+ Cell cell = null;
+ Name name = null;
+
+ // The first row will hold the data for the first validation.
+ row = dataSheet.createRow(10);
+ cell = row.createCell(0);
+ cell.setCellValue("Animal");
+ cell = row.createCell(1);
+ cell.setCellValue("Vegetable");
+ cell = row.createCell(2);
+ cell.setCellValue("Mineral");
+ name = dataSheet.getWorkbook().createName();
+ name.setRefersToFormula("$A$11:$C$11");
+ name.setNameName("CHOICES");
+
+ // The next three rows will hold the data that will be used to
+ // populate the second, or linked, drop down list.
+ row = dataSheet.createRow(11);
+ cell = row.createCell(0);
+ cell.setCellValue("Lion");
+ cell = row.createCell(1);
+ cell.setCellValue("Tiger");
+ cell = row.createCell(2);
+ cell.setCellValue("Leopard");
+ cell = row.createCell(3);
+ cell.setCellValue("Elephant");
+ cell = row.createCell(4);
+ cell.setCellValue("Eagle");
+ cell = row.createCell(5);
+ cell.setCellValue("Horse");
+ cell = row.createCell(6);
+ cell.setCellValue("Zebra");
+ name = dataSheet.getWorkbook().createName();
+ name.setRefersToFormula("$A$12:$G$12");
+ name.setNameName("ANIMAL");
+
+ row = dataSheet.createRow(12);
+ cell = row.createCell(0);
+ cell.setCellValue("Cabbage");
+ cell = row.createCell(1);
+ cell.setCellValue("Cauliflower");
+ cell = row.createCell(2);
+ cell.setCellValue("Potato");
+ cell = row.createCell(3);
+ cell.setCellValue("Onion");
+ cell = row.createCell(4);
+ cell.setCellValue("Beetroot");
+ cell = row.createCell(5);
+ cell.setCellValue("Asparagus");
+ cell = row.createCell(6);
+ cell.setCellValue("Spinach");
+ cell = row.createCell(7);
+ cell.setCellValue("Chard");
+ name = dataSheet.getWorkbook().createName();
+ name.setRefersToFormula("$A$13:$H$13");
+ name.setNameName("VEGETABLE");
+
+ row = dataSheet.createRow(13);
+ cell = row.createCell(0);
+ cell.setCellValue("Bauxite");
+ cell = row.createCell(1);
+ cell.setCellValue("Quartz");
+ cell = row.createCell(2);
+ cell.setCellValue("Feldspar");
+ cell = row.createCell(3);
+ cell.setCellValue("Shist");
+ cell = row.createCell(4);
+ cell.setCellValue("Shale");
+ cell = row.createCell(5);
+ cell.setCellValue("Mica");
+ name = dataSheet.getWorkbook().createName();
+ name.setRefersToFormula("$A$14:$F$14");
+ name.setNameName("MINERAL");
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hssf.usermodel.HSSFObjectData;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.Entry;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.xmlbeans.XmlException;
+
+/**
+ * Loads embedded resources from Workbooks. Code taken from the website:
+ * https://poi.apache.org/spreadsheet/quick-guide.html#Embedded
+ */
+@SuppressWarnings({"java:S106","java:S4823"})
+public final class LoadEmbedded {
+ private LoadEmbedded() {}
+
+ public static void main(String[] args) throws IOException, EncryptedDocumentException, OpenXML4JException, XmlException {
+ Workbook wb = WorkbookFactory.create(new File(args[0]));
+ loadEmbedded(wb);
+ }
+
+ public static void loadEmbedded(Workbook wb) throws IOException, InvalidFormatException, OpenXML4JException, XmlException {
+ if (wb instanceof HSSFWorkbook) {
+ loadEmbedded((HSSFWorkbook)wb);
+ }
+ else if (wb instanceof XSSFWorkbook) {
+ loadEmbedded((XSSFWorkbook)wb);
+ }
+ else {
+ throw new IllegalArgumentException(wb.getClass().getName());
+ }
+ }
+
+ public static void loadEmbedded(HSSFWorkbook workbook) throws IOException {
+ for (HSSFObjectData obj : workbook.getAllEmbeddedObjects()) {
+ //the OLE2 Class Name of the object
+ String oleName = obj.getOLE2ClassName();
+ if (oleName.equals("Worksheet")) {
+ DirectoryNode dn = (DirectoryNode) obj.getDirectory();
+ HSSFWorkbook embeddedWorkbook = new HSSFWorkbook(dn, false);
+ embeddedWorkbook.close();
+ } else if (oleName.equals("Document")) {
+ DirectoryNode dn = (DirectoryNode) obj.getDirectory();
+ HWPFDocument embeddedWordDocument = new HWPFDocument(dn);
+ embeddedWordDocument.close();
+ } else if (oleName.equals("Presentation")) {
+ DirectoryNode dn = (DirectoryNode) obj.getDirectory();
+ SlideShow<?,?> embeddedSlieShow = new HSLFSlideShow(dn);
+ embeddedSlieShow.close();
+ } else {
+ if(obj.hasDirectoryEntry()){
+ // The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is
+ DirectoryNode dn = (DirectoryNode) obj.getDirectory();
+ for (Entry entry : dn) {
+ //System.out.println(oleName + "." + entry.getName());
+ }
+ } else {
+ // There is no DirectoryEntry
+ // Recover the object's data from the HSSFObjectData instance.
+ byte[] objectData = obj.getObjectData();
+ }
+ }
+ }
+ }
+
+ public static void loadEmbedded(XSSFWorkbook workbook) throws IOException, InvalidFormatException, OpenXML4JException, XmlException {
+ for (PackagePart pPart : workbook.getAllEmbeddedParts()) {
+ String contentType = pPart.getContentType();
+ if (contentType.equals("application/vnd.ms-excel")) {
+ // Excel Workbook - either binary or OpenXML
+ HSSFWorkbook embeddedWorkbook = new HSSFWorkbook(pPart.getInputStream());
+ embeddedWorkbook.close();
+ } else if (contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
+ // Excel Workbook - OpenXML file format
+ XSSFWorkbook embeddedWorkbook = new XSSFWorkbook(pPart.getInputStream());
+ embeddedWorkbook.close();
+ } else if (contentType.equals("application/msword")) {
+ // Word Document - binary (OLE2CDF) file format
+ HWPFDocument document = new HWPFDocument(pPart.getInputStream());
+ document.close();
+ } else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
+ // Word Document - OpenXML file format
+ XWPFDocument document = new XWPFDocument(pPart.getInputStream());
+ document.close();
+ } else if (contentType.equals("application/vnd.ms-powerpoint")) {
+ // PowerPoint Document - binary file format
+ HSLFSlideShow slideShow = new HSLFSlideShow(pPart.getInputStream());
+ slideShow.close();
+ } else if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) {
+ // PowerPoint Document - OpenXML file format
+ XMLSlideShow slideShow = new XMLSlideShow(pPart.getInputStream());
+ slideShow.close();
+ } else {
+ // Any other type of embedded object.
+ System.out.println("Unknown Embedded Document: " + contentType);
+ InputStream inputStream = pPart.getInputStream();
+ inputStream.close();
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+import java.io.FileOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.ss.usermodel.PrintSetup;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Simple Loan Calculator. Demonstrates advance usage of cell formulas and named ranges.
+ *
+ * Usage:
+ * LoanCalculator -xls|xlsx
+ *
+ * @author Yegor Kozlov
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class LoanCalculator {
+
+ private LoanCalculator() {}
+
+ public static void main(String[] args) throws Exception {
+ Workbook wb;
+
+ if(args.length > 0 && args[0].equals("-xls")) wb = new HSSFWorkbook();
+ else wb = new XSSFWorkbook();
+
+ Map<String, CellStyle> styles = createStyles(wb);
+ Sheet sheet = wb.createSheet("Loan Calculator");
+ sheet.setPrintGridlines(false);
+ sheet.setDisplayGridlines(false);
+
+ PrintSetup printSetup = sheet.getPrintSetup();
+ printSetup.setLandscape(true);
+ sheet.setFitToPage(true);
+ sheet.setHorizontallyCenter(true);
+
+ sheet.setColumnWidth(0, 3*256);
+ sheet.setColumnWidth(1, 3*256);
+ sheet.setColumnWidth(2, 11*256);
+ sheet.setColumnWidth(3, 14*256);
+ sheet.setColumnWidth(4, 14*256);
+ sheet.setColumnWidth(5, 14*256);
+ sheet.setColumnWidth(6, 14*256);
+
+ createNames(wb);
+
+ Row titleRow = sheet.createRow(0);
+ titleRow.setHeightInPoints(35);
+ for (int i = 1; i <= 7; i++) {
+ titleRow.createCell(i).setCellStyle(styles.get("title"));
+ }
+ Cell titleCell = titleRow.getCell(2);
+ titleCell.setCellValue("Simple Loan Calculator");
+ sheet.addMergedRegion(CellRangeAddress.valueOf("$C$1:$H$1"));
+
+ Row row = sheet.createRow(2);
+ Cell cell = row.createCell(4);
+ cell.setCellValue("Enter values");
+ cell.setCellStyle(styles.get("item_right"));
+
+ row = sheet.createRow(3);
+ cell = row.createCell(2);
+ cell.setCellValue("Loan amount");
+ cell.setCellStyle(styles.get("item_left"));
+ cell = row.createCell(4);
+ cell.setCellStyle(styles.get("input_$"));
+ cell.setAsActiveCell();
+
+ row = sheet.createRow(4);
+ cell = row.createCell(2);
+ cell.setCellValue("Annual interest rate");
+ cell.setCellStyle(styles.get("item_left"));
+ cell = row.createCell(4);
+ cell.setCellStyle(styles.get("input_%"));
+
+ row = sheet.createRow(5);
+ cell = row.createCell(2);
+ cell.setCellValue("Loan period in years");
+ cell.setCellStyle(styles.get("item_left"));
+ cell = row.createCell(4);
+ cell.setCellStyle(styles.get("input_i"));
+
+ row = sheet.createRow(6);
+ cell = row.createCell(2);
+ cell.setCellValue("Start date of loan");
+ cell.setCellStyle(styles.get("item_left"));
+ cell = row.createCell(4);
+ cell.setCellStyle(styles.get("input_d"));
+
+ row = sheet.createRow(8);
+ cell = row.createCell(2);
+ cell.setCellValue("Monthly payment");
+ cell.setCellStyle(styles.get("item_left"));
+ cell = row.createCell(4);
+ cell.setCellFormula("IF(Values_Entered,Monthly_Payment,\"\")");
+ cell.setCellStyle(styles.get("formula_$"));
+
+ row = sheet.createRow(9);
+ cell = row.createCell(2);
+ cell.setCellValue("Number of payments");
+ cell.setCellStyle(styles.get("item_left"));
+ cell = row.createCell(4);
+ cell.setCellFormula("IF(Values_Entered,Loan_Years*12,\"\")");
+ cell.setCellStyle(styles.get("formula_i"));
+
+ row = sheet.createRow(10);
+ cell = row.createCell(2);
+ cell.setCellValue("Total interest");
+ cell.setCellStyle(styles.get("item_left"));
+ cell = row.createCell(4);
+ cell.setCellFormula("IF(Values_Entered,Total_Cost-Loan_Amount,\"\")");
+ cell.setCellStyle(styles.get("formula_$"));
+
+ row = sheet.createRow(11);
+ cell = row.createCell(2);
+ cell.setCellValue("Total cost of loan");
+ cell.setCellStyle(styles.get("item_left"));
+ cell = row.createCell(4);
+ cell.setCellFormula("IF(Values_Entered,Monthly_Payment*Number_of_Payments,\"\")");
+ cell.setCellStyle(styles.get("formula_$"));
+
+
+ // Write the output to a file
+ String file = "loan-calculator.xls";
+ if(wb instanceof XSSFWorkbook) file += "x";
+ FileOutputStream out = new FileOutputStream(file);
+ wb.write(out);
+ out.close();
+ }
+
+ /**
+ * cell styles used for formatting calendar sheets
+ */
+ private static Map<String, CellStyle> createStyles(Workbook wb){
+ Map<String, CellStyle> styles = new HashMap<>();
+
+ CellStyle style;
+ Font titleFont = wb.createFont();
+ titleFont.setFontHeightInPoints((short)14);
+ titleFont.setFontName("Trebuchet MS");
+ style = wb.createCellStyle();
+ style.setFont(titleFont);
+ style.setBorderBottom(BorderStyle.DOTTED);
+ style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ styles.put("title", style);
+
+ Font itemFont = wb.createFont();
+ itemFont.setFontHeightInPoints((short)9);
+ itemFont.setFontName("Trebuchet MS");
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setFont(itemFont);
+ styles.put("item_left", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(itemFont);
+ styles.put("item_right", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(itemFont);
+ style.setBorderRight(BorderStyle.DOTTED);
+ style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.DOTTED);
+ style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.DOTTED);
+ style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.DOTTED);
+ style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setDataFormat(wb.createDataFormat().getFormat("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(@_)"));
+ styles.put("input_$", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(itemFont);
+ style.setBorderRight(BorderStyle.DOTTED);
+ style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.DOTTED);
+ style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.DOTTED);
+ style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.DOTTED);
+ style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setDataFormat(wb.createDataFormat().getFormat("0.000%"));
+ styles.put("input_%", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(itemFont);
+ style.setBorderRight(BorderStyle.DOTTED);
+ style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.DOTTED);
+ style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.DOTTED);
+ style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.DOTTED);
+ style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setDataFormat(wb.createDataFormat().getFormat("0"));
+ styles.put("input_i", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setFont(itemFont);
+ style.setDataFormat(wb.createDataFormat().getFormat("m/d/yy"));
+ styles.put("input_d", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(itemFont);
+ style.setBorderRight(BorderStyle.DOTTED);
+ style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.DOTTED);
+ style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.DOTTED);
+ style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.DOTTED);
+ style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setDataFormat(wb.createDataFormat().getFormat("$##,##0.00"));
+ style.setBorderBottom(BorderStyle.DOTTED);
+ style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ styles.put("formula_$", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.RIGHT);
+ style.setFont(itemFont);
+ style.setBorderRight(BorderStyle.DOTTED);
+ style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.DOTTED);
+ style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.DOTTED);
+ style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.DOTTED);
+ style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setDataFormat(wb.createDataFormat().getFormat("0"));
+ style.setBorderBottom(BorderStyle.DOTTED);
+ style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ styles.put("formula_i", style);
+
+ return styles;
+ }
+
+ //define named ranges for the inputs and formulas
+ public static void createNames(Workbook wb){
+ Name name;
+
+ name = wb.createName();
+ name.setNameName("Interest_Rate");
+ name.setRefersToFormula("'Loan Calculator'!$E$5");
+
+ name = wb.createName();
+ name.setNameName("Loan_Amount");
+ name.setRefersToFormula("'Loan Calculator'!$E$4");
+
+ name = wb.createName();
+ name.setNameName("Loan_Start");
+ name.setRefersToFormula("'Loan Calculator'!$E$7");
+
+ name = wb.createName();
+ name.setNameName("Loan_Years");
+ name.setRefersToFormula("'Loan Calculator'!$E$6");
+
+ name = wb.createName();
+ name.setNameName("Number_of_Payments");
+ name.setRefersToFormula("'Loan Calculator'!$E$10");
+
+ name = wb.createName();
+ name.setNameName("Monthly_Payment");
+ name.setRefersToFormula("-PMT(Interest_Rate/12,Number_of_Payments,Loan_Amount)");
+
+ name = wb.createName();
+ name.setNameName("Total_Cost");
+ name.setRefersToFormula("'Loan Calculator'!$E$12");
+
+ name = wb.createName();
+ name.setNameName("Total_Interest");
+ name.setRefersToFormula("'Loan Calculator'!$E$11");
+
+ name = wb.createName();
+ name.setNameName("Values_Entered");
+ name.setRefersToFormula("IF(Loan_Amount*Interest_Rate*Loan_Years*Loan_Start>0,1,0)");
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.ss;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ooxml.POIXMLTypeLoader;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class SSPerformanceTest {
+ private SSPerformanceTest() {}
+
+ public static void main(String[] args) throws IOException {
+ if (args.length < 4) {
+ usage("need at least four command arguments");
+ }
+
+ String type = args[0];
+ int rows = parseInt(args[1], "Failed to parse rows value as integer");
+ int cols = parseInt(args[2], "Failed to parse cols value as integer");
+ boolean saveFile = parseInt(args[3], "Failed to parse saveFile value as integer") != 0;
+
+ boolean warmup = false;
+ for(int arg = 4; arg < args.length;arg++) {
+ if(args[arg].equals("--unsynchronized-xmlbeans")) {
+ POIXMLTypeLoader.DEFAULT_XML_OPTIONS.setUnsynchronized();
+ }
+ if(args[arg].equals("--with-warmup-run")) {
+ warmup = true;
+ }
+ }
+
+ if(warmup) {
+ System.out.println("Performing a warmup run first");
+ runWithArgs(type, rows, cols, saveFile);
+ }
+
+ long timeStarted = System.currentTimeMillis();
+ runWithArgs(type, rows, cols, saveFile);
+ long timeFinished = System.currentTimeMillis();
+
+ System.out.printf("Elapsed %.2f seconds for arguments %s\n", ((double)timeFinished - timeStarted) / 1000, Arrays.toString(args));
+ }
+
+ private static void runWithArgs(String type, int rows, int cols, boolean saveFile) throws IOException {
+ try (Workbook workBook = createWorkbook(type)) {
+ boolean isHType = workBook instanceof HSSFWorkbook;
+ addContent(workBook, isHType, rows, cols);
+
+ if (saveFile) {
+ String fileName = type + "_" + rows + "_" + cols + "." + getFileSuffix(type);
+ saveFile(workBook, fileName);
+ }
+ }
+ }
+
+ private static void addContent(Workbook workBook, boolean isHType, int rows, int cols) {
+ Map<String, CellStyle> styles = createStyles(workBook);
+
+ Sheet sheet = workBook.createSheet("Main Sheet");
+
+ Cell headerCell = sheet.createRow(0).createCell(0);
+ headerCell.setCellValue("Header text is spanned across multiple cells");
+ headerCell.setCellStyle(styles.get("header"));
+ sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$F$1"));
+
+ int sheetNo = 0;
+ int rowIndexInSheet = 1;
+ double value = 0;
+ Calendar calendar = Calendar.getInstance();
+ for (int rowIndex = 0; rowIndex < rows; rowIndex++) {
+ if (isHType && sheetNo != rowIndex / 0x10000) {
+ sheet = workBook.createSheet("Spillover from sheet " + (++sheetNo));
+ headerCell.setCellValue("Header text is spanned across multiple cells");
+ headerCell.setCellStyle(styles.get("header"));
+ sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$F$1"));
+ rowIndexInSheet = 1;
+ }
+
+ Row row = sheet.createRow(rowIndexInSheet);
+ for (int colIndex = 0; colIndex < cols; colIndex++) {
+ value = populateCell(styles, value, calendar, rowIndex, row, colIndex);
+ }
+ rowIndexInSheet++;
+ }
+ }
+
+ private static double populateCell(Map<String, CellStyle> styles, double value, Calendar calendar, int rowIndex, Row row, int colIndex) {
+ Cell cell = row.createCell(colIndex);
+ String address = new CellReference(cell).formatAsString();
+ switch (colIndex){
+ case 0:
+ // column A: default number format
+ cell.setCellValue(value++);
+ break;
+ case 1:
+ // column B: #,##0
+ cell.setCellValue(value++);
+ cell.setCellStyle(styles.get("#,##0.00"));
+ break;
+ case 2:
+ // column C: $#,##0.00
+ cell.setCellValue(value++);
+ cell.setCellStyle(styles.get("$#,##0.00"));
+ break;
+ case 3:
+ // column D: red bold text on yellow background
+ cell.setCellValue(address);
+ cell.setCellStyle(styles.get("red-bold"));
+ break;
+ case 4:
+ // column E: boolean
+ // TODO booleans are shown as 1/0 instead of TRUE/FALSE
+ cell.setCellValue(rowIndex % 2 == 0);
+ break;
+ case 5:
+ // column F: date / time
+ cell.setCellValue(calendar);
+ cell.setCellStyle(styles.get("m/d/yyyy"));
+ calendar.roll(Calendar.DAY_OF_YEAR, -1);
+ break;
+ case 6:
+ // column F: formula
+ // TODO formulas are not yet supported in SXSSF
+ //cell.setCellFormula("SUM(A" + (rowIndex+1) + ":E" + (rowIndex+1)+ ")");
+ //break;
+ default:
+ cell.setCellValue(value++);
+ break;
+ }
+ return value;
+ }
+
+ private static void saveFile(Workbook workBook, String fileName) {
+ try {
+ FileOutputStream out = new FileOutputStream(fileName);
+ workBook.write(out);
+ out.close();
+ } catch (IOException ioe) {
+ System.err.println("Error: failed to write to file \"" + fileName + "\", reason=" + ioe.getMessage());
+ }
+ }
+
+ static Map<String, CellStyle> createStyles(Workbook wb) {
+ Map<String, CellStyle> styles = new HashMap<>();
+ CellStyle style;
+
+ Font headerFont = wb.createFont();
+ headerFont.setFontHeightInPoints((short) 14);
+ headerFont.setBold(true);
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFont(headerFont);
+ style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ styles.put("header", style);
+
+ Font monthFont = wb.createFont();
+ monthFont.setFontHeightInPoints((short)12);
+ monthFont.setColor(IndexedColors.RED.getIndex());
+ monthFont.setBold(true);
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFont(monthFont);
+ styles.put("red-bold", style);
+
+ String[] nfmt = {"#,##0.00", "$#,##0.00", "m/d/yyyy"};
+ for(String fmt : nfmt){
+ style = wb.createCellStyle();
+ style.setDataFormat(wb.createDataFormat().getFormat(fmt));
+ styles.put(fmt, style);
+ }
+
+ return styles;
+ }
+
+
+ static void usage(String message) {
+ System.err.println(message);
+ System.err.println("usage: java SSPerformanceTest HSSF|XSSF|SXSSF rows cols saveFile (0|1)? [--unsynchronized-xmlbeans] [--with-warmup-run]");
+ System.exit(1);
+ }
+
+ static Workbook createWorkbook(String type) {
+ if ("HSSF".equals(type))
+ return new HSSFWorkbook();
+ else if ("XSSF".equals(type))
+ return new XSSFWorkbook();
+ else if ("SXSSF".equals(type))
+ return new SXSSFWorkbook();
+
+ usage("Unknown type \"" + type + "\"");
+ throw new IllegalArgumentException("Should not reach this point");
+ }
+
+ static String getFileSuffix(String type) {
+ if ("HSSF".equals(type))
+ return "xls";
+ else if ("XSSF".equals(type))
+ return "xlsx";
+ else if ("SXSSF".equals(type))
+ return "xlsx";
+ return null;
+ }
+
+ static int parseInt(String value, String msg) {
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ usage(msg);
+ }
+ return 0;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+import java.io.FileOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.PrintSetup;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * A weekly timesheet created using Apache POI.
+ * Usage:
+ * TimesheetDemo -xls|xlsx
+ *
+ * @author Yegor Kozlov
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class TimesheetDemo {
+ private static final String[] titles = {
+ "Person", "ID", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",
+ "Total\nHrs", "Overtime\nHrs", "Regular\nHrs"
+ };
+
+ private static final Object[][] sample_data = {
+ {"Yegor Kozlov", "YK", 5.0, 8.0, 10.0, 5.0, 5.0, 7.0, 6.0},
+ {"Gisella Bronzetti", "GB", 4.0, 3.0, 1.0, 3.5, null, null, 4.0},
+ };
+
+ private TimesheetDemo() {}
+
+ public static void main(String[] args) throws Exception {
+ Workbook wb;
+
+ if(args.length > 0 && args[0].equals("-xls")) wb = new HSSFWorkbook();
+ else wb = new XSSFWorkbook();
+
+ Map<String, CellStyle> styles = createStyles(wb);
+
+ Sheet sheet = wb.createSheet("Timesheet");
+ PrintSetup printSetup = sheet.getPrintSetup();
+ printSetup.setLandscape(true);
+ sheet.setFitToPage(true);
+ sheet.setHorizontallyCenter(true);
+
+ //title row
+ Row titleRow = sheet.createRow(0);
+ titleRow.setHeightInPoints(45);
+ Cell titleCell = titleRow.createCell(0);
+ titleCell.setCellValue("Weekly Timesheet");
+ titleCell.setCellStyle(styles.get("title"));
+ sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$L$1"));
+
+ //header row
+ Row headerRow = sheet.createRow(1);
+ headerRow.setHeightInPoints(40);
+ Cell headerCell;
+ for (int i = 0; i < titles.length; i++) {
+ headerCell = headerRow.createCell(i);
+ headerCell.setCellValue(titles[i]);
+ headerCell.setCellStyle(styles.get("header"));
+ }
+
+ int rownum = 2;
+ for (int i = 0; i < 10; i++) {
+ Row row = sheet.createRow(rownum++);
+ for (int j = 0; j < titles.length; j++) {
+ Cell cell = row.createCell(j);
+ if(j == 9){
+ //the 10th cell contains sum over week days, e.g. SUM(C3:I3)
+ String ref = "C" +rownum+ ":I" + rownum;
+ cell.setCellFormula("SUM("+ref+")");
+ cell.setCellStyle(styles.get("formula"));
+ } else if (j == 11){
+ cell.setCellFormula("J" +rownum+ "-K" + rownum);
+ cell.setCellStyle(styles.get("formula"));
+ } else {
+ cell.setCellStyle(styles.get("cell"));
+ }
+ }
+ }
+
+ //row with totals below
+ Row sumRow = sheet.createRow(rownum++);
+ sumRow.setHeightInPoints(35);
+ Cell cell;
+ cell = sumRow.createCell(0);
+ cell.setCellStyle(styles.get("formula"));
+ cell = sumRow.createCell(1);
+ cell.setCellValue("Total Hrs:");
+ cell.setCellStyle(styles.get("formula"));
+
+ for (int j = 2; j < 12; j++) {
+ cell = sumRow.createCell(j);
+ String ref = (char)('A' + j) + "3:" + (char)('A' + j) + "12";
+ cell.setCellFormula("SUM(" + ref + ")");
+ if(j >= 9) cell.setCellStyle(styles.get("formula_2"));
+ else cell.setCellStyle(styles.get("formula"));
+ }
+ rownum++;
+ sumRow = sheet.createRow(rownum++);
+ sumRow.setHeightInPoints(25);
+ cell = sumRow.createCell(0);
+ cell.setCellValue("Total Regular Hours");
+ cell.setCellStyle(styles.get("formula"));
+ cell = sumRow.createCell(1);
+ cell.setCellFormula("L13");
+ cell.setCellStyle(styles.get("formula_2"));
+ sumRow = sheet.createRow(rownum++);
+ sumRow.setHeightInPoints(25);
+ cell = sumRow.createCell(0);
+ cell.setCellValue("Total Overtime Hours");
+ cell.setCellStyle(styles.get("formula"));
+ cell = sumRow.createCell(1);
+ cell.setCellFormula("K13");
+ cell.setCellStyle(styles.get("formula_2"));
+
+ //set sample data
+ for (int i = 0; i < sample_data.length; i++) {
+ Row row = sheet.getRow(2 + i);
+ for (int j = 0; j < sample_data[i].length; j++) {
+ if(sample_data[i][j] == null) continue;
+
+ if(sample_data[i][j] instanceof String) {
+ row.getCell(j).setCellValue((String)sample_data[i][j]);
+ } else {
+ row.getCell(j).setCellValue((Double)sample_data[i][j]);
+ }
+ }
+ }
+
+ //finally set column widths, the width is measured in units of 1/256th of a character width
+ sheet.setColumnWidth(0, 30*256); //30 characters wide
+ for (int i = 2; i < 9; i++) {
+ sheet.setColumnWidth(i, 6*256); //6 characters wide
+ }
+ sheet.setColumnWidth(10, 10*256); //10 characters wide
+
+ // Write the output to a file
+ String file = "timesheet.xls";
+ if(wb instanceof XSSFWorkbook) file += "x";
+ FileOutputStream out = new FileOutputStream(file);
+ wb.write(out);
+ out.close();
+ }
+
+ /**
+ * Create a library of cell styles
+ */
+ private static Map<String, CellStyle> createStyles(Workbook wb){
+ Map<String, CellStyle> styles = new HashMap<>();
+ CellStyle style;
+ Font titleFont = wb.createFont();
+ titleFont.setFontHeightInPoints((short)18);
+ titleFont.setBold(true);
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFont(titleFont);
+ styles.put("title", style);
+
+ Font monthFont = wb.createFont();
+ monthFont.setFontHeightInPoints((short)11);
+ monthFont.setColor(IndexedColors.WHITE.getIndex());
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFont(monthFont);
+ style.setWrapText(true);
+ styles.put("header", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setWrapText(true);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(IndexedColors.BLACK.getIndex());
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
+ style.setBorderTop(BorderStyle.THIN);
+ style.setTopBorderColor(IndexedColors.BLACK.getIndex());
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
+ styles.put("cell", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setDataFormat(wb.createDataFormat().getFormat("0.00"));
+ styles.put("formula", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setDataFormat(wb.createDataFormat().getFormat("0.00"));
+ styles.put("formula_2", style);
+
+ return styles;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss;
+
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+
+/**
+ * Demonstrates <em>one</em> way to convert an Excel spreadsheet into a CSV
+ * file. This class makes the following assumptions;
+ * <list>
+ * <li>1. Where the Excel workbook contains more that one worksheet, then a single
+ * CSV file will contain the data from all of the worksheets.</li>
+ * <li>2. The data matrix contained in the CSV file will be square. This means that
+ * the number of fields in each record of the CSV file will match the number
+ * of cells in the longest row found in the Excel workbook. Any short records
+ * will be 'padded' with empty fields - an empty field is represented in the
+ * the CSV file in this way - ,,.</li>
+ * <li>3. Empty fields will represent missing cells.</li>
+ * <li>4. A record consisting of empty fields will be used to represent an empty row
+ * in the Excel workbook.</li>
+ * </list>
+ * Therefore, if the worksheet looked like this;
+ *
+ * <pre>
+ * ___________________________________________
+ * | | | | | |
+ * | A | B | C | D | E |
+ * ___|_______|_______|_______|_______|_______|
+ * | | | | | |
+ * 1 | 1 | 2 | 3 | 4 | 5 |
+ * ___|_______|_______|_______|_______|_______|
+ * | | | | | |
+ * 2 | | | | | |
+ * ___|_______|_______|_______|_______|_______|
+ * | | | | | |
+ * 3 | | A | | B | |
+ * ___|_______|_______|_______|_______|_______|
+ * | | | | | |
+ * 4 | | | | | Z |
+ * ___|_______|_______|_______|_______|_______|
+ * | | | | | |
+ * 5 | 1,400 | | 250 | | |
+ * ___|_______|_______|_______|_______|_______|
+ *
+ * </pre>
+ *
+ * Then, the resulting CSV file will contain the following lines (records);
+ * <pre>
+ * 1,2,3,4,5
+ * ,,,,
+ * ,A,,B,
+ * ,,,,Z
+ * "1,400",,250,,
+ * </pre><p>
+ * Typically, the comma is used to separate each of the fields that, together,
+ * constitute a single record or line within the CSV file. This is not however
+ * a hard and fast rule and so this class allows the user to determine which
+ * character is used as the field separator and assumes the comma if none other
+ * is specified.
+ * </p><p>
+ * If a field contains the separator then it will be escaped. If the file should
+ * obey Excel's CSV formatting rules, then the field will be surrounded with
+ * speech marks whilst if it should obey UNIX conventions, each occurrence of
+ * the separator will be preceded by the backslash character.
+ * </p><p>
+ * If a field contains an end of line (EOL) character then it too will be
+ * escaped. If the file should obey Excel's CSV formatting rules then the field
+ * will again be surrounded by speech marks. On the other hand, if the file
+ * should follow UNIX conventions then a single backslash will precede the
+ * EOL character. There is no single applicable standard for UNIX and some
+ * appications replace the CR with \r and the LF with \n but this class will
+ * not do so.
+ * </p><p>
+ * If the field contains double quotes then that character will be escaped. It
+ * seems as though UNIX does not define a standard for this whilst Excel does.
+ * Should the CSV file have to obey Excel's formmating rules then the speech
+ * mark character will be escaped with a second set of speech marks. Finally, an
+ * enclosing set of speah marks will also surround the entire field. Thus, if
+ * the following line of text appeared in a cell - "Hello" he said - it would
+ * look like this when converted into a field within a CSV file - """Hello"" he
+ * said".
+ * </p><p>
+ * Finally, it is worth noting that talk of CSV 'standards' is really slightly
+ * missleading as there is no such thing. It may well be that the code in this
+ * class has to be modified to produce files to suit a specific application
+ * or requirement.
+ * </p>
+ * @author Mark B
+ * @version 1.00 9th April 2010
+ * 1.10 13th April 2010 - Added support for processing all Excel
+ * workbooks in a folder along with the ability
+ * to specify a field separator character.
+ * 2.00 14th April 2010 - Added support for embedded characters; the
+ * field separator, EOL and double quotes or
+ * speech marks. In addition, gave the client
+ * the ability to select how these are handled,
+ * either obeying Excel's or UNIX formatting
+ * conventions.
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public class ToCSV {
+
+ private Workbook workbook;
+ private ArrayList<ArrayList<String>> csvData;
+ private int maxRowWidth;
+ private int formattingConvention;
+ private DataFormatter formatter;
+ private FormulaEvaluator evaluator;
+ private String separator;
+
+ private static final String CSV_FILE_EXTENSION = ".csv";
+ private static final String DEFAULT_SEPARATOR = ",";
+
+ /**
+ * Identifies that the CSV file should obey Excel's formatting conventions
+ * with regard to escaping certain embedded characters - the field separator,
+ * speech mark and end of line (EOL) character
+ */
+ public static final int EXCEL_STYLE_ESCAPING = 0;
+
+ /**
+ * Identifies that the CSV file should obey UNIX formatting conventions
+ * with regard to escaping certain embedded characters - the field separator
+ * and end of line (EOL) character
+ */
+ public static final int UNIX_STYLE_ESCAPING = 1;
+
+ /**
+ * Process the contents of a folder, convert the contents of each Excel
+ * workbook into CSV format and save the resulting file to the specified
+ * folder using the same name as the original workbook with the .xls or
+ * .xlsx extension replaced by .csv. This method will ensure that the
+ * CSV file created contains the comma field separator and that embedded
+ * characters such as the field separator, the EOL and double quotes are
+ * escaped in accordance with Excel's convention.
+ *
+ * @param strSource An instance of the String class that encapsulates the
+ * name of and path to either a folder containing those Excel
+ * workbook(s) or the name of and path to an individual Excel workbook
+ * that is/are to be converted.
+ * @param strDestination An instance of the String class encapsulating the
+ * name of and path to a folder that will contain the resulting CSV
+ * files.
+ * @throws java.io.FileNotFoundException Thrown if any file cannot be located
+ * on the filesystem during processing.
+ * @throws java.io.IOException Thrown if the filesystem encounters any
+ * problems during processing.
+ * @throws java.lang.IllegalArgumentException Thrown if the values passed
+ * to the strSource parameter refers to a file or folder that does not
+ * exist or if the value passed to the strDestination paramater refers
+ * to a folder that does not exist or simply does not refer to a
+ * folder.
+ */
+ public void convertExcelToCSV(String strSource, String strDestination)
+ throws FileNotFoundException, IOException,
+ IllegalArgumentException {
+
+ // Simply chain the call to the overloaded convertExcelToCSV(String,
+ // String, String, int) method, pass the default separator and ensure
+ // that certain embedded characters are escaped in accordance with
+ // Excel's formatting conventions
+ this.convertExcelToCSV(strSource, strDestination,
+ ToCSV.DEFAULT_SEPARATOR, ToCSV.EXCEL_STYLE_ESCAPING);
+ }
+
+ /**
+ * Process the contents of a folder, convert the contents of each Excel
+ * workbook into CSV format and save the resulting file to the specified
+ * folder using the same name as the original workbook with the .xls or
+ * .xlsx extension replaced by .csv. This method allows the client to
+ * define the field separator but will ensure that embedded characters such
+ * as the field separator, the EOL and double quotes are escaped in
+ * accordance with Excel's convention.
+ *
+ * @param strSource An instance of the String class that encapsulates the
+ * name of and path to either a folder containing those Excel
+ * workbook(s) or the name of and path to an individual Excel workbook
+ * that is/are to be converted.
+ * @param strDestination An instance of the String class encapsulating the
+ * name of and path to a folder that will contain the resulting CSV
+ * files.
+ * @param separator An instance of the String class that encapsulates the
+ * character or characters the client wishes to use as the field
+ * separator.
+ * @throws java.io.FileNotFoundException Thrown if any file cannot be located
+ * on the filesystem during processing.
+ * @throws java.io.IOException Thrown if the filesystem encounters any
+ * problems during processing.
+ * @throws java.lang.IllegalArgumentException Thrown if the values passed
+ * to the strSource parameter refers to a file or folder that does not
+ * exist or if the value passed to the strDestination paramater refers
+ * to a folder that does not exist or simply does not refer to a
+ * folder.
+ */
+ public void convertExcelToCSV(String strSource, String strDestination,
+ String separator)
+ throws FileNotFoundException, IOException,
+ IllegalArgumentException {
+
+ // Simply chain the call to the overloaded convertExcelToCSV(String,
+ // String, String, int) method and ensure that certain embedded
+ // characters are escaped in accordance with Excel's formatting
+ // conventions
+ this.convertExcelToCSV(strSource, strDestination,
+ separator, ToCSV.EXCEL_STYLE_ESCAPING);
+ }
+
+ /**
+ * Process the contents of a folder, convert the contents of each Excel
+ * workbook into CSV format and save the resulting file to the specified
+ * folder using the same name as the original workbook with the .xls or
+ * .xlsx extension replaced by .csv
+ *
+ * @param strSource An instance of the String class that encapsulates the
+ * name of and path to either a folder containing those Excel
+ * workbook(s) or the name of and path to an individual Excel workbook
+ * that is/are to be converted.
+ * @param strDestination An instance of the String class encapsulating the name
+ * of and path to a folder that will contain the resulting CSV files.
+ * @param formattingConvention A primitive int whose value will determine
+ * whether certain embedded characters should be escaped in accordance
+ * with Excel's or UNIX formatting conventions. Two constants are
+ * defined to support this option; ToCSV.EXCEL_STYLE_ESCAPING and
+ * ToCSV.UNIX_STYLE_ESCAPING
+ * @param separator An instance of the String class encapsulating the
+ * characters or characters that should be used to separate items
+ * on a line within the CSV file.
+ * @throws java.io.FileNotFoundException Thrown if any file cannot be located
+ * on the filesystem during processing.
+ * @throws java.io.IOException Thrown if the filesystem encounters any
+ * problems during processing.
+ * @throws java.lang.IllegalArgumentException Thrown if the values passed
+ * to the strSource parameter refers to a file or folder that does not
+ * exist, if the value passed to the strDestination paramater refers
+ * to a folder that does not exist, if the value passed to the
+ * strDestination parameter does not refer to a folder or if the
+ * value passed to the formattingConvention parameter is other than
+ * one of the values defined by the constants ToCSV.EXCEL_STYLE_ESCAPING
+ * and ToCSV.UNIX_STYLE_ESCAPING.
+ */
+ public void convertExcelToCSV(String strSource, String strDestination,
+ String separator, int formattingConvention)
+ throws FileNotFoundException, IOException,
+ IllegalArgumentException {
+ // Check that the source file/folder exists.
+ File source = new File(strSource);
+ if(!source.exists()) {
+ throw new IllegalArgumentException("The source for the Excel " +
+ "file(s) cannot be found at " + source);
+ }
+
+ // Ensure thaat the folder the user has chosen to save the CSV files
+ // away into firstly exists and secondly is a folder rather than, for
+ // instance, a data file.
+ File destination = new File(strDestination);
+ if(!destination.exists()) {
+ throw new IllegalArgumentException("The destination directory " + destination + " for the " +
+ "converted CSV file(s) does not exist.");
+ }
+ if(!destination.isDirectory()) {
+ throw new IllegalArgumentException("The destination " + destination + " for the CSV " +
+ "file(s) is not a directory/folder.");
+ }
+
+ // Ensure the value passed to the formattingConvention parameter is
+ // within range.
+ if(formattingConvention != ToCSV.EXCEL_STYLE_ESCAPING &&
+ formattingConvention != ToCSV.UNIX_STYLE_ESCAPING) {
+ throw new IllegalArgumentException("The value passed to the " +
+ "formattingConvention parameter is out of range: " + formattingConvention + ", expecting one of " +
+ ToCSV.EXCEL_STYLE_ESCAPING + " or " + ToCSV.UNIX_STYLE_ESCAPING);
+ }
+
+ // Copy the spearator character and formatting convention into local
+ // variables for use in other methods.
+ this.separator = separator;
+ this.formattingConvention = formattingConvention;
+
+ // Check to see if the sourceFolder variable holds a reference to
+ // a file or a folder full of files.
+ final File[] filesList;
+ if(source.isDirectory()) {
+ // Get a list of all of the Excel spreadsheet files (workbooks) in
+ // the source folder/directory
+ filesList = source.listFiles(new ExcelFilenameFilter());
+ }
+ else {
+ // Assume that it must be a file handle - although there are other
+ // options the code should perhaps check - and store the reference
+ // into the filesList variable.
+ filesList = new File[]{source};
+ }
+
+ // Step through each of the files in the source folder and for each
+ // open the workbook, convert it's contents to CSV format and then
+ // save the resulting file away into the folder specified by the
+ // contents of the destination variable. Note that the name of the
+ // csv file will be created by taking the name of the Excel file,
+ // removing the extension and replacing it with .csv. Note that there
+ // is one drawback with this approach; if the folder holding the files
+ // contains two workbooks whose names match but one is a binary file
+ // (.xls) and the other a SpreadsheetML file (.xlsx), then the names
+ // for both CSV files will be identical and one CSV file will,
+ // therefore, over-write the other.
+ if (filesList != null) {
+ for(File excelFile : filesList) {
+ // Open the workbook
+ this.openWorkbook(excelFile);
+
+ // Convert it's contents into a CSV file
+ this.convertToCSV();
+
+ // Build the name of the csv folder from that of the Excel workbook.
+ // Simply replace the .xls or .xlsx file extension with .csv
+ String destinationFilename = excelFile.getName();
+ destinationFilename = destinationFilename.substring(
+ 0, destinationFilename.lastIndexOf('.')) +
+ ToCSV.CSV_FILE_EXTENSION;
+
+ // Save the CSV file away using the newly constricted file name
+ // and to the specified directory.
+ this.saveCSVFile(new File(destination, destinationFilename));
+ }
+ }
+ }
+
+ /**
+ * Open an Excel workbook ready for conversion.
+ *
+ * @param file An instance of the File class that encapsulates a handle
+ * to a valid Excel workbook. Note that the workbook can be in
+ * either binary (.xls) or SpreadsheetML (.xlsx) format.
+ * @throws java.io.FileNotFoundException Thrown if the file cannot be located.
+ * @throws java.io.IOException Thrown if a problem occurs in the file system.
+ */
+ private void openWorkbook(File file) throws FileNotFoundException,
+ IOException {
+ System.out.println("Opening workbook [" + file.getName() + "]");
+ try (FileInputStream fis = new FileInputStream(file)) {
+
+ // Open the workbook and then create the FormulaEvaluator and
+ // DataFormatter instances that will be needed to, respectively,
+ // force evaluation of forumlae found in cells and create a
+ // formatted String encapsulating the cells contents.
+ this.workbook = WorkbookFactory.create(fis);
+ this.evaluator = this.workbook.getCreationHelper().createFormulaEvaluator();
+ this.formatter = new DataFormatter(true);
+ }
+ }
+
+ /**
+ * Called to convert the contents of the currently opened workbook into
+ * a CSV file.
+ */
+ private void convertToCSV() {
+ Sheet sheet;
+ Row row;
+ int lastRowNum;
+ this.csvData = new ArrayList<>();
+
+ System.out.println("Converting files contents to CSV format.");
+
+ // Discover how many sheets there are in the workbook....
+ int numSheets = this.workbook.getNumberOfSheets();
+
+ // and then iterate through them.
+ for(int i = 0; i < numSheets; i++) {
+
+ // Get a reference to a sheet and check to see if it contains
+ // any rows.
+ sheet = this.workbook.getSheetAt(i);
+ if(sheet.getPhysicalNumberOfRows() > 0) {
+ // Note down the index number of the bottom-most row and
+ // then iterate through all of the rows on the sheet starting
+ // from the very first row - number 1 - even if it is missing.
+ // Recover a reference to the row and then call another method
+ // which will strip the data from the cells and build lines
+ // for inclusion in the resylting CSV file.
+ lastRowNum = sheet.getLastRowNum();
+ for(int j = 0; j <= lastRowNum; j++) {
+ row = sheet.getRow(j);
+ this.rowToCSV(row);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called to actually save the data recovered from the Excel workbook
+ * as a CSV file.
+ *
+ * @param file An instance of the File class that encapsulates a handle
+ * referring to the CSV file.
+ * @throws java.io.FileNotFoundException Thrown if the file cannot be found.
+ * @throws java.io.IOException Thrown to indicate and error occurred in the
+ * underylying file system.
+ */
+ private void saveCSVFile(File file) throws FileNotFoundException, IOException {
+ ArrayList<String> line;
+ StringBuilder buffer;
+ String csvLineElement;
+
+ // Open a writer onto the CSV file.
+ try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
+
+ System.out.println("Saving the CSV file [" + file.getName() + "]");
+
+ // Step through the elements of the ArrayList that was used to hold
+ // all of the data recovered from the Excel workbooks' sheets, rows
+ // and cells.
+ for(int i = 0; i < this.csvData.size(); i++) {
+ buffer = new StringBuilder();
+
+ // Get an element from the ArrayList that contains the data for
+ // the workbook. This element will itself be an ArrayList
+ // containing Strings and each String will hold the data recovered
+ // from a single cell. The for() loop is used to recover elements
+ // from this 'row' ArrayList one at a time and to write the Strings
+ // away to a StringBuilder thus assembling a single line for inclusion
+ // in the CSV file. If a row was empty or if it was short, then
+ // the ArrayList that contains it's data will also be shorter than
+ // some of the others. Therefore, it is necessary to check within
+ // the for loop to ensure that the ArrayList contains data to be
+ // processed. If it does, then an element will be recovered and
+ // appended to the StringBuilder.
+ line = this.csvData.get(i);
+ for(int j = 0; j < this.maxRowWidth; j++) {
+ if(line.size() > j) {
+ csvLineElement = line.get(j);
+ if(csvLineElement != null) {
+ buffer.append(this.escapeEmbeddedCharacters(
+ csvLineElement));
+ }
+ }
+ if(j < (this.maxRowWidth - 1)) {
+ buffer.append(this.separator);
+ }
+ }
+
+ // Once the line is built, write it away to the CSV file.
+ bw.write(buffer.toString().trim());
+
+ // Condition the inclusion of new line characters so as to
+ // avoid an additional, superfluous, new line at the end of
+ // the file.
+ if(i < (this.csvData.size() - 1)) {
+ bw.newLine();
+ }
+ }
+ }
+ }
+
+ /**
+ * Called to convert a row of cells into a line of data that can later be
+ * output to the CSV file.
+ *
+ * @param row An instance of either the HSSFRow or XSSFRow classes that
+ * encapsulates information about a row of cells recovered from
+ * an Excel workbook.
+ */
+ private void rowToCSV(Row row) {
+ Cell cell;
+ int lastCellNum;
+ ArrayList<String> csvLine = new ArrayList<>();
+
+ // Check to ensure that a row was recovered from the sheet as it is
+ // possible that one or more rows between other populated rows could be
+ // missing - blank. If the row does contain cells then...
+ if(row != null) {
+
+ // Get the index for the right most cell on the row and then
+ // step along the row from left to right recovering the contents
+ // of each cell, converting that into a formatted String and
+ // then storing the String into the csvLine ArrayList.
+ lastCellNum = row.getLastCellNum();
+ for(int i = 0; i <= lastCellNum; i++) {
+ cell = row.getCell(i);
+ if(cell == null) {
+ csvLine.add("");
+ }
+ else {
+ if(cell.getCellType() != CellType.FORMULA) {
+ csvLine.add(this.formatter.formatCellValue(cell));
+ }
+ else {
+ csvLine.add(this.formatter.formatCellValue(cell, this.evaluator));
+ }
+ }
+ }
+ // Make a note of the index number of the right most cell. This value
+ // will later be used to ensure that the matrix of data in the CSV file
+ // is square.
+ if(lastCellNum > this.maxRowWidth) {
+ this.maxRowWidth = lastCellNum;
+ }
+ }
+ this.csvData.add(csvLine);
+ }
+
+ /**
+ * Checks to see whether the field - which consists of the formatted
+ * contents of an Excel worksheet cell encapsulated within a String - contains
+ * any embedded characters that must be escaped. The method is able to
+ * comply with either Excel's or UNIX formatting conventions in the
+ * following manner;
+ *
+ * With regard to UNIX conventions, if the field contains any embedded
+ * field separator or EOL characters they will each be escaped by prefixing
+ * a leading backspace character. These are the only changes that have yet
+ * emerged following some research as being required.
+ *
+ * Excel has other embedded character escaping requirements, some that emerged
+ * from empirical testing, other through research. Firstly, with regards to
+ * any embedded speech marks ("), each occurrence should be escaped with
+ * another speech mark and the whole field then surrounded with speech marks.
+ * Thus if a field holds <em>"Hello" he said</em> then it should be modified
+ * to appear as <em>"""Hello"" he said"</em>. Furthermore, if the field
+ * contains either embedded separator or EOL characters, it should also
+ * be surrounded with speech marks. As a result <em>1,400</em> would become
+ * <em>"1,400"</em> assuming that the comma is the required field separator.
+ * This has one consequence in, if a field contains embedded speech marks
+ * and embedded separator characters, checks for both are not required as the
+ * additional set of speech marks that should be placed around ay field
+ * containing embedded speech marks will also account for the embedded
+ * separator.
+ *
+ * It is worth making one further note with regard to embedded EOL
+ * characters. If the data in a worksheet is exported as a CSV file using
+ * Excel itself, then the field will be surounded with speech marks. If the
+ * resulting CSV file is then re-imports into another worksheet, the EOL
+ * character will result in the original simgle field occupying more than
+ * one cell. This same 'feature' is replicated in this classes behaviour.
+ *
+ * @param field An instance of the String class encapsulating the formatted
+ * contents of a cell on an Excel worksheet.
+ * @return A String that encapsulates the formatted contents of that
+ * Excel worksheet cell but with any embedded separator, EOL or
+ * speech mark characters correctly escaped.
+ */
+ private String escapeEmbeddedCharacters(String field) {
+ StringBuilder buffer;
+
+ // If the fields contents should be formatted to confrom with Excel's
+ // convention....
+ if(this.formattingConvention == ToCSV.EXCEL_STYLE_ESCAPING) {
+
+ // Firstly, check if there are any speech marks (") in the field;
+ // each occurrence must be escaped with another set of spech marks
+ // and then the entire field should be enclosed within another
+ // set of speech marks. Thus, "Yes" he said would become
+ // """Yes"" he said"
+ if(field.contains("\"")) {
+ buffer = new StringBuilder(field.replaceAll("\"", "\\\"\\\""));
+ buffer.insert(0, "\"");
+ buffer.append("\"");
+ }
+ else {
+ // If the field contains either embedded separator or EOL
+ // characters, then escape the whole field by surrounding it
+ // with speech marks.
+ buffer = new StringBuilder(field);
+ if((buffer.indexOf(this.separator)) > -1 ||
+ (buffer.indexOf("\n")) > -1) {
+ buffer.insert(0, "\"");
+ buffer.append("\"");
+ }
+ }
+ return(buffer.toString().trim());
+ }
+ // The only other formatting convention this class obeys is the UNIX one
+ // where any occurrence of the field separator or EOL character will
+ // be escaped by preceding it with a backslash.
+ else {
+ if(field.contains(this.separator)) {
+ field = field.replaceAll(this.separator, ("\\\\" + this.separator));
+ }
+ if(field.contains("\n")) {
+ field = field.replaceAll("\n", "\\\\\n");
+ }
+ return(field);
+ }
+ }
+
+ /**
+ * The main() method contains code that demonstrates how to use the class.
+ *
+ * @param args An array containing zero, one or more elements all of type
+ * String. Each element will encapsulate an argument specified by the
+ * user when running the program from the command prompt.
+ */
+ public static void main(String[] args) {
+ // Check the number of arguments passed to the main method. There
+ // must be two, three or four; the name of and path to either the folder
+ // containing the Excel files or an individual Excel workbook that is/are
+ // to be converted, the name of and path to the folder to which the CSV
+ // files should be written, - optionally - the separator character
+ // that should be used to separate individual items (fields) on the
+ // lines (records) of the CSV file and - again optionally - an integer
+ // that idicates whether the CSV file ought to obey Excel's or UNIX
+ // convnetions with regard to formatting fields that contain embedded
+ // separator, Speech mark or EOL character(s).
+ //
+ // Note that the names of the CSV files will be derived from those
+ // of the Excel file(s). Put simply the .xls or .xlsx extension will be
+ // replaced with .csv. Therefore, if the source folder contains files
+ // with matching names but different extensions - Test.xls and Test.xlsx
+ // for example - then the CSV file generated from one will overwrite
+ // that generated from the other.
+ ToCSV converter;
+ boolean converted = true;
+ long startTime = System.currentTimeMillis();
+ try {
+ converter = new ToCSV();
+ if(args.length == 2) {
+ // Just the Source File/Folder and Destination Folder were
+ // passed to the main method.
+ converter.convertExcelToCSV(args[0], args[1]);
+ }
+ else if(args.length == 3) {
+ // The Source File/Folder, Destination Folder and Separator
+ // were passed to the main method.
+ converter.convertExcelToCSV(args[0], args[1], args[2]);
+ }
+ else if(args.length == 4) {
+ // The Source File/Folder, Destination Folder, Separator and
+ // Formatting Convnetion were passed to the main method.
+ converter.convertExcelToCSV(args[0], args[1],
+ args[2], Integer.parseInt(args[3]));
+ }
+ else {
+ // None or more than four parameters were passed so display
+ //a Usage message.
+ System.out.println("Usage: java ToCSV [Source File/Folder] " +
+ "[Destination Folder] [Separator] [Formatting Convention]\n" +
+ "\tSource File/Folder\tThis argument should contain the name of and\n" +
+ "\t\t\t\tpath to either a single Excel workbook or a\n" +
+ "\t\t\t\tfolder containing one or more Excel workbooks.\n" +
+ "\tDestination Folder\tThe name of and path to the folder that the\n" +
+ "\t\t\t\tCSV files should be written out into. The\n" +
+ "\t\t\t\tfolder must exist before running the ToCSV\n" +
+ "\t\t\t\tcode as it will not check for or create it.\n" +
+ "\tSeparator\t\tOptional. The character or characters that\n" +
+ "\t\t\t\tshould be used to separate fields in the CSV\n" +
+ "\t\t\t\trecord. If no value is passed then the comma\n" +
+ "\t\t\t\twill be assumed.\n" +
+ "\tFormatting Convention\tOptional. This argument can take one of two\n" +
+ "\t\t\t\tvalues. Passing 0 (zero) will result in a CSV\n" +
+ "\t\t\t\tfile that obeys Excel's formatting conventions\n" +
+ "\t\t\t\twhilst passing 1 (one) will result in a file\n" +
+ "\t\t\t\tthat obeys UNIX formatting conventions. If no\n" +
+ "\t\t\t\tvalue is passed, then the CSV file produced\n" +
+ "\t\t\t\twill obey Excel's formatting conventions.");
+ converted = false;
+ }
+ }
+ // It is not wise to have such a wide catch clause - Exception is very
+ // close to being at the top of the inheritance hierarchy - though it
+ // will suffice for this example as it is really not possible to recover
+ // easilly from an exceptional set of circumstances at this point in the
+ // program. It should however, ideally be replaced with one or more
+ // catch clauses optimised to handle more specific problems.
+ catch(Exception ex) {
+ System.out.println("Caught an: " + ex.getClass().getName());
+ System.out.println("Message: " + ex.getMessage());
+ System.out.println("Stacktrace follows:.....");
+ ex.printStackTrace(System.out);
+ converted = false;
+ }
+
+ if (converted) {
+ System.out.println("Conversion took " +
+ ((System.currentTimeMillis() - startTime)/1000) + " seconds");
+ }
+ }
+
+ /**
+ * An instance of this class can be used to control the files returned
+ * be a call to the listFiles() method when made on an instance of the
+ * File class and that object refers to a folder/directory
+ */
+ static class ExcelFilenameFilter implements FilenameFilter {
+
+ /**
+ * Determine those files that will be returned by a call to the
+ * listFiles() method. In this case, the name of the file must end with
+ * either of the following two extension; '.xls' or '.xlsx'. For the
+ * future, it is very possible to parameterise this and allow the
+ * containing class to pass, for example, an array of Strings to this
+ * class on instantiation. Each element in that array could encapsulate
+ * a valid file extension - '.xls', '.xlsx', '.xlt', '.xlst', etc. These
+ * could then be used to control which files were returned by the call
+ * to the listFiles() method.
+ *
+ * @param file An instance of the File class that encapsulates a handle
+ * referring to the folder/directory that contains the file.
+ * @param name An instance of the String class that encapsulates the
+ * name of the file.
+ * @return A boolean value that indicates whether the file should be
+ * included in the array retirned by the call to the listFiles()
+ * method. In this case true will be returned if the name of the
+ * file ends with either '.xls' or '.xlsx' and false will be
+ * returned in all other instances.
+ */
+ @Override
+ public boolean accept(File file, String name) {
+ return(name.endsWith(".xls") || name.endsWith(".xlsx"));
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss.formula;
+
+import org.apache.poi.ss.formula.OperationEvaluationContext;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.OperandResolver;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+
+/**
+ * A simple user-defined function to calculate principal and interest.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public class CalculateMortgage implements FreeRefFunction {
+
+ @Override
+ public ValueEval evaluate( ValueEval[] args, OperationEvaluationContext ec ) {
+
+ // verify that we have enough data
+ if (args.length != 3) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ // declare doubles for values
+ double principal, rate, years, result;
+ try {
+ // extract values as ValueEval
+ ValueEval v1 = OperandResolver.getSingleValue( args[0],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+ ValueEval v2 = OperandResolver.getSingleValue( args[1],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+ ValueEval v3 = OperandResolver.getSingleValue( args[2],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+
+ // get data as doubles
+ principal = OperandResolver.coerceValueToDouble( v1 ) ;
+ rate = OperandResolver.coerceValueToDouble( v2 ) ;
+ years = OperandResolver.coerceValueToDouble( v3 ) ;
+
+ result = calculateMortgagePayment( principal, rate, years ) ;
+ System.out.println( "Result = " + result ) ;
+
+ checkValue(result);
+
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+
+ return new NumberEval( result ) ;
+ }
+
+ public double calculateMortgagePayment( double p, double r, double y ) {
+ double i = r / 12 ;
+ double n = y * 12 ;
+
+ return p * (( i * Math.pow((1 + i),n ) ) / ( Math.pow((1 + i),n) - 1));
+ }
+ /**
+ * Excel does not support infinities and NaNs, rather, it gives a #NUM! error in these cases
+ *
+ * @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</> or <tt>Infinity</tt>
+ */
+ private void checkValue(double result) throws EvaluationException {
+ if (Double.isNaN(result) || Double.isInfinite(result)) {
+ throw new EvaluationException(ErrorEval.NUM_ERROR);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss.formula;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.poi.ss.formula.eval.NotImplementedException;
+import org.apache.poi.ss.formula.eval.NotImplementedFunctionException;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellReference;
+
+/**
+ * Attempts to re-evaluate all the formulas in the workbook, and
+ * reports what (if any) formula functions used are not (currently)
+ * supported by Apache POI.
+ *
+ * <p>This provides examples of how to evaluate formulas in excel
+ * files using Apache POI, along with how to handle errors whilst
+ * doing so.
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public class CheckFunctionsSupported {
+ public static void main(String[] args) throws Exception {
+ if (args.length < 1) {
+ System.err.println("Use:");
+ System.err.println(" CheckFunctionsSupported <filename>");
+ return;
+ }
+
+ Workbook wb = WorkbookFactory.create(new File(args[0]));
+ CheckFunctionsSupported check = new CheckFunctionsSupported(wb);
+
+ // Fetch all the problems
+ List<FormulaEvaluationProblems> problems = new ArrayList<>();
+ for (int sn=0; sn<wb.getNumberOfSheets(); sn++) {
+ problems.add(check.getEvaluationProblems(sn));
+ }
+
+ // Produce an overall summary
+ Set<String> unsupportedFunctions = new TreeSet<>();
+ for (FormulaEvaluationProblems p : problems) {
+ unsupportedFunctions.addAll(p.unsupportedFunctions);
+ }
+ if (unsupportedFunctions.isEmpty()) {
+ System.out.println("There are no unsupported formula functions used");
+ } else {
+ System.out.println("Unsupported formula functions:");
+ for (String function : unsupportedFunctions) {
+ System.out.println(" " + function);
+ }
+ System.out.println("Total unsupported functions = " + unsupportedFunctions.size());
+ }
+
+ // Report sheet by sheet
+ for (int sn=0; sn<wb.getNumberOfSheets(); sn++) {
+ String sheetName = wb.getSheetName(sn);
+ FormulaEvaluationProblems probs = problems.get(sn);
+
+ System.out.println();
+ System.out.println("Sheet = " + sheetName);
+
+ if (probs.unevaluatableCells.isEmpty()) {
+ System.out.println(" All cells evaluated without error");
+ } else {
+ for (CellReference cr : probs.unevaluatableCells.keySet()) {
+ System.out.println(" " + cr.formatAsString() + " - " +
+ probs.unevaluatableCells.get(cr));
+ }
+ }
+ }
+ }
+
+ private final Workbook workbook;
+ private final FormulaEvaluator evaluator;
+ public CheckFunctionsSupported(Workbook workbook) {
+ this.workbook = workbook;
+ this.evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+ }
+
+ public Set<String> getUnsupportedFunctions(String sheetName) {
+ return getUnsupportedFunctions(workbook.getSheet(sheetName));
+ }
+ public Set<String> getUnsupportedFunctions(int sheetIndex) {
+ return getUnsupportedFunctions(workbook.getSheetAt(sheetIndex));
+ }
+ public Set<String> getUnsupportedFunctions(Sheet sheet) {
+ FormulaEvaluationProblems problems = getEvaluationProblems(sheet);
+ return problems.unsupportedFunctions;
+ }
+
+ public FormulaEvaluationProblems getEvaluationProblems(String sheetName) {
+ return getEvaluationProblems(workbook.getSheet(sheetName));
+ }
+ public FormulaEvaluationProblems getEvaluationProblems(int sheetIndex) {
+ return getEvaluationProblems(workbook.getSheetAt(sheetIndex));
+ }
+ public FormulaEvaluationProblems getEvaluationProblems(Sheet sheet) {
+ Set<String> unsupportedFunctions = new HashSet<>();
+ Map<CellReference,Exception> unevaluatableCells = new HashMap<>();
+
+ for (Row r : sheet) {
+ for (Cell c : r) {
+ try {
+ evaluator.evaluate(c);
+ } catch (Exception e) {
+ if (e instanceof NotImplementedException && e.getCause() != null) {
+ // Has been wrapped with cell details, but we know those
+ e = (Exception)e.getCause();
+ }
+
+ if (e instanceof NotImplementedFunctionException) {
+ NotImplementedFunctionException nie = (NotImplementedFunctionException)e;
+ unsupportedFunctions.add(nie.getFunctionName());
+ }
+ unevaluatableCells.put(new CellReference(c), e);
+ }
+ }
+ }
+
+ return new FormulaEvaluationProblems(unsupportedFunctions, unevaluatableCells);
+ }
+
+ public static class FormulaEvaluationProblems {
+ /** Which used functions are unsupported by POI at this time */
+ private final Set<String> unsupportedFunctions;
+ /** Which cells had unevaluatable formulas, and why? */
+ private final Map<CellReference,Exception> unevaluatableCells;
+
+ protected FormulaEvaluationProblems(Set<String> unsupportedFunctions,
+ Map<CellReference, Exception> unevaluatableCells) {
+ this.unsupportedFunctions = Collections.unmodifiableSet(unsupportedFunctions);
+ this.unevaluatableCells = Collections.unmodifiableMap(unevaluatableCells);
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.ss.formula;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.poi.ss.formula.OperationEvaluationContext;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.formula.udf.UDFFinder;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates how to use functions provided by third-party add-ins, e.g. Bloomberg Excel Add-in.
+ *
+ * There can be situations when you are not interested in formula evaluation,
+ * you just need to set the formula and the workbook will be evaluation by the client.
+ */
+public class SettingExternalFunction {
+
+ /**
+ * wrap external functions in a plugin
+ */
+ public static class BloombergAddIn implements UDFFinder {
+ private final Map<String, FreeRefFunction> _functionsByName;
+
+ public BloombergAddIn() {
+ // dummy function that returns NA
+ // don't care about the implementation, we are not interested in evaluation
+ // and this method will never be called
+ FreeRefFunction NA = new FreeRefFunction() {
+ @Override
+ public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+ return ErrorEval.NA;
+ }
+ };
+ _functionsByName = new HashMap<>();
+ _functionsByName.put("BDP", NA);
+ _functionsByName.put("BDH", NA);
+ _functionsByName.put("BDS", NA);
+ }
+
+ @Override
+ public FreeRefFunction findFunction(String name) {
+ return _functionsByName.get(name.toUpperCase(Locale.ROOT));
+ }
+
+ }
+
+ public static void main( String[] args ) throws IOException {
+
+ try (Workbook wb = new XSSFWorkbook()) { // or new HSSFWorkbook()
+
+ // register the add-in
+ wb.addToolPack(new BloombergAddIn());
+
+ Sheet sheet = wb.createSheet();
+ Row row = sheet.createRow(0);
+ row.createCell(0).setCellFormula("BDP(\"GOOG Equity\",\"CHG_PCT_YTD\")/100");
+ row.createCell(1).setCellFormula("BDH(\"goog us equity\",\"EBIT\",\"1/1/2005\",\"12/31/2009\",\"per=cy\",\"curr=USD\") ");
+ row.createCell(2).setCellFormula("BDS(\"goog us equity\",\"top_20_holders_public_filings\") ");
+
+ try (FileOutputStream out = new FileOutputStream("bloomberg-demo.xlsx")) {
+ wb.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss.formula;
+
+import java.io.File;
+
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.formula.udf.DefaultUDFFinder;
+import org.apache.poi.ss.formula.udf.UDFFinder;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellReference;
+
+
+/**
+ * An example class of how to invoke a User Defined Function for a given
+ * XLS instance using POI's UDFFinder implementation.
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class UserDefinedFunctionExample {
+
+ private UserDefinedFunctionExample() {}
+
+ public static void main(String[] args ) throws Exception {
+
+ if( args.length != 2 ) {
+ // e.g. src/examples/src/org/apache/poi/ss/examples/formula/mortgage-calculation.xls Sheet1!B4
+ System.out.println( "usage: UserDefinedFunctionExample fileName cellId" ) ;
+ return;
+ }
+
+ System.out.println( "fileName: " + args[0] ) ;
+ System.out.println( "cell: " + args[1] ) ;
+
+ File workbookFile = new File( args[0] ) ;
+
+ try (Workbook workbook = WorkbookFactory.create(workbookFile, null, true)) {
+ String[] functionNames = {"calculatePayment"};
+ FreeRefFunction[] functionImpls = {new CalculateMortgage()};
+
+ UDFFinder udfToolpack = new DefaultUDFFinder(functionNames, functionImpls);
+
+ // register the user-defined function in the workbook
+ workbook.addToolPack(udfToolpack);
+
+ FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+
+ CellReference cr = new CellReference(args[1]);
+ String sheetName = cr.getSheetName();
+ Sheet sheet = workbook.getSheet(sheetName);
+ int rowIdx = cr.getRow();
+ int colIdx = cr.getCol();
+ Row row = sheet.getRow(rowIdx);
+ Cell cell = row.getCell(colIdx);
+
+ CellValue value = evaluator.evaluate(cell);
+
+ System.out.println("returns value: " + value);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss.html;
+
+import java.util.Formatter;
+
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFPalette;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor;
+import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
+import org.apache.poi.ss.usermodel.CellStyle;
+
+/**
+ * Implementation of {@link HtmlHelper} for HSSF files.
+ */
+public class HSSFHtmlHelper implements HtmlHelper {
+ private final HSSFWorkbook wb;
+ private final HSSFPalette colors;
+
+ private static final HSSFColor HSSF_AUTO = HSSFColorPredefined.AUTOMATIC.getColor();
+
+ public HSSFHtmlHelper(HSSFWorkbook wb) {
+ this.wb = wb;
+ // If there is no custom palette, then this creates a new one that is
+ // a copy of the default
+ colors = wb.getCustomPalette();
+ }
+
+ @Override
+ public void colorStyles(CellStyle style, Formatter out) {
+ HSSFCellStyle cs = (HSSFCellStyle) style;
+ out.format(" /* fill pattern = %d */%n", cs.getFillPattern().getCode());
+ styleColor(out, "background-color", cs.getFillForegroundColor());
+ styleColor(out, "color", cs.getFont(wb).getColor());
+ styleColor(out, "border-left-color", cs.getLeftBorderColor());
+ styleColor(out, "border-right-color", cs.getRightBorderColor());
+ styleColor(out, "border-top-color", cs.getTopBorderColor());
+ styleColor(out, "border-bottom-color", cs.getBottomBorderColor());
+ }
+
+ private void styleColor(Formatter out, String attr, short index) {
+ HSSFColor color = colors.getColor(index);
+ if (index == HSSF_AUTO.getIndex() || color == null) {
+ out.format(" /* %s: index = %d */%n", attr, index);
+ } else {
+ short[] rgb = color.getTriplet();
+ out.format(" %s: #%02x%02x%02x; /* index = %d */%n", attr, rgb[0],
+ rgb[1], rgb[2], index);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.examples.ss.html;
+
+import java.util.Formatter;
+
+import org.apache.poi.ss.usermodel.CellStyle;
+
+/**
+ * This interface is used where code wants to be independent of the workbook
+ * formats. If you are writing such code, you can add a method to this
+ * interface, and then implement it for both HSSF and XSSF workbooks, letting
+ * the driving code stay independent of format.
+ *
+ * @author Ken Arnold, Industrious Media LLC
+ */
+public interface HtmlHelper {
+ /**
+ * Outputs the appropriate CSS style for the given cell style.
+ *
+ * @param style The cell style.
+ * @param out The place to write the output.
+ */
+ void colorStyles(CellStyle style, Formatter out);
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss.html;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.format.CellFormat;
+import org.apache.poi.ss.format.CellFormatResult;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * This example shows how to display a spreadsheet in HTML using the classes for
+ * spreadsheet display.
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class ToHtml {
+ private final Workbook wb;
+ private final Appendable output;
+ private boolean completeHTML;
+ private Formatter out;
+ private boolean gotBounds;
+ private int firstColumn;
+ private int endColumn;
+ private HtmlHelper helper;
+
+ private static final String DEFAULTS_CLASS = "excelDefaults";
+ private static final String COL_HEAD_CLASS = "colHeader";
+ private static final String ROW_HEAD_CLASS = "rowHeader";
+
+ private static final Map<HorizontalAlignment, String> HALIGN = mapFor(
+ HorizontalAlignment.LEFT, "left",
+ HorizontalAlignment.CENTER, "center",
+ HorizontalAlignment.RIGHT, "right",
+ HorizontalAlignment.FILL, "left",
+ HorizontalAlignment.JUSTIFY, "left",
+ HorizontalAlignment.CENTER_SELECTION, "center");
+
+ private static final Map<VerticalAlignment, String> VALIGN = mapFor(
+ VerticalAlignment.BOTTOM, "bottom",
+ VerticalAlignment.CENTER, "middle",
+ VerticalAlignment.TOP, "top");
+
+ private static final Map<BorderStyle, String> BORDER = mapFor(
+ BorderStyle.DASH_DOT, "dashed 1pt",
+ BorderStyle.DASH_DOT_DOT, "dashed 1pt",
+ BorderStyle.DASHED, "dashed 1pt",
+ BorderStyle.DOTTED, "dotted 1pt",
+ BorderStyle.DOUBLE, "double 3pt",
+ BorderStyle.HAIR, "solid 1px",
+ BorderStyle.MEDIUM, "solid 2pt",
+ BorderStyle.MEDIUM_DASH_DOT, "dashed 2pt",
+ BorderStyle.MEDIUM_DASH_DOT_DOT, "dashed 2pt",
+ BorderStyle.MEDIUM_DASHED, "dashed 2pt",
+ BorderStyle.NONE, "none",
+ BorderStyle.SLANTED_DASH_DOT, "dashed 2pt",
+ BorderStyle.THICK, "solid 3pt",
+ BorderStyle.THIN, "dashed 1pt");
+
+ private static final int IDX_TABLE_WIDTH = -2;
+ private static final int IDX_HEADER_COL_WIDTH = -1;
+
+
+ @SuppressWarnings({"unchecked"})
+ private static <K, V> Map<K, V> mapFor(Object... mapping) {
+ Map<K, V> map = new HashMap<>();
+ for (int i = 0; i < mapping.length; i += 2) {
+ map.put((K) mapping[i], (V) mapping[i + 1]);
+ }
+ return map;
+ }
+
+ /**
+ * Creates a new examples to HTML for the given workbook.
+ *
+ * @param wb The workbook.
+ * @param output Where the HTML output will be written.
+ *
+ * @return An object for converting the workbook to HTML.
+ */
+ public static ToHtml create(Workbook wb, Appendable output) {
+ return new ToHtml(wb, output);
+ }
+
+ /**
+ * Creates a new examples to HTML for the given workbook. If the path ends
+ * with "<tt>.xlsx</tt>" an {@link XSSFWorkbook} will be used; otherwise
+ * this will use an {@link HSSFWorkbook}.
+ *
+ * @param path The file that has the workbook.
+ * @param output Where the HTML output will be written.
+ *
+ * @return An object for converting the workbook to HTML.
+ */
+ public static ToHtml create(String path, Appendable output)
+ throws IOException {
+ return create(new FileInputStream(path), output);
+ }
+
+ /**
+ * Creates a new examples to HTML for the given workbook. This attempts to
+ * detect whether the input is XML (so it should create an {@link
+ * XSSFWorkbook} or not (so it should create an {@link HSSFWorkbook}).
+ *
+ * @param in The input stream that has the workbook.
+ * @param output Where the HTML output will be written.
+ *
+ * @return An object for converting the workbook to HTML.
+ */
+ public static ToHtml create(InputStream in, Appendable output)
+ throws IOException {
+ Workbook wb = WorkbookFactory.create(in);
+ return create(wb, output);
+ }
+
+ private ToHtml(Workbook wb, Appendable output) {
+ if (wb == null) {
+ throw new NullPointerException("wb");
+ }
+ if (output == null) {
+ throw new NullPointerException("output");
+ }
+ this.wb = wb;
+ this.output = output;
+ setupColorMap();
+ }
+
+ private void setupColorMap() {
+ if (wb instanceof HSSFWorkbook) {
+ helper = new HSSFHtmlHelper((HSSFWorkbook) wb);
+ } else if (wb instanceof XSSFWorkbook) {
+ helper = new XSSFHtmlHelper();
+ } else {
+ throw new IllegalArgumentException(
+ "unknown workbook type: " + wb.getClass().getSimpleName());
+ }
+ }
+
+ /**
+ * Run this class as a program
+ *
+ * @param args The command line arguments.
+ *
+ * @throws Exception Exception we don't recover from.
+ */
+ public static void main(String[] args) throws Exception {
+ if(args.length < 2){
+ System.err.println("usage: ToHtml inputWorkbook outputHtmlFile");
+ return;
+ }
+
+ try (
+ FileWriter fw = new FileWriter(args[1]);
+ PrintWriter pw = new PrintWriter(fw)
+ ) {
+ ToHtml toHtml = create(args[0], pw);
+ toHtml.setCompleteHTML(true);
+ toHtml.printPage();
+ }
+ }
+
+ public void setCompleteHTML(boolean completeHTML) {
+ this.completeHTML = completeHTML;
+ }
+
+ public void printPage() throws IOException {
+ try {
+ ensureOut();
+ if (completeHTML) {
+ out.format(
+ "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>%n");
+ out.format("<html>%n");
+ out.format("<head>%n");
+ out.format("</head>%n");
+ out.format("<body>%n");
+ }
+
+ print();
+
+ if (completeHTML) {
+ out.format("</body>%n");
+ out.format("</html>%n");
+ }
+ } finally {
+ IOUtils.closeQuietly(out);
+ if (output instanceof Closeable) {
+ IOUtils.closeQuietly((Closeable) output);
+ }
+ }
+ }
+
+ public void print() {
+ printInlineStyle();
+ printSheets();
+ }
+
+ private void printInlineStyle() {
+ //out.format("<link href=\"excelStyle.css\" rel=\"stylesheet\" type=\"text/css\">%n");
+ out.format("<style type=\"text/css\">%n");
+ printStyles();
+ out.format("</style>%n");
+ }
+
+ private void ensureOut() {
+ if (out == null) {
+ out = new Formatter(output);
+ }
+ }
+
+ public void printStyles() {
+ ensureOut();
+
+ // First, copy the base css
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(
+ getClass().getResourceAsStream("excelStyle.css")))){
+ String line;
+ while ((line = in.readLine()) != null) {
+ out.format("%s%n", line);
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("Reading standard css", e);
+ }
+
+ // now add css for each used style
+ Set<CellStyle> seen = new HashSet<>();
+ for (int i = 0; i < wb.getNumberOfSheets(); i++) {
+ Sheet sheet = wb.getSheetAt(i);
+ Iterator<Row> rows = sheet.rowIterator();
+ while (rows.hasNext()) {
+ Row row = rows.next();
+ for (Cell cell : row) {
+ CellStyle style = cell.getCellStyle();
+ if (!seen.contains(style)) {
+ printStyle(style);
+ seen.add(style);
+ }
+ }
+ }
+ }
+ }
+
+ private void printStyle(CellStyle style) {
+ out.format(".%s .%s {%n", DEFAULTS_CLASS, styleName(style));
+ styleContents(style);
+ out.format("}%n");
+ }
+
+ private void styleContents(CellStyle style) {
+ styleOut("text-align", style.getAlignment(), HALIGN);
+ styleOut("vertical-align", style.getVerticalAlignment(), VALIGN);
+ fontStyle(style);
+ borderStyles(style);
+ helper.colorStyles(style, out);
+ }
+
+ private void borderStyles(CellStyle style) {
+ styleOut("border-left", style.getBorderLeft(), BORDER);
+ styleOut("border-right", style.getBorderRight(), BORDER);
+ styleOut("border-top", style.getBorderTop(), BORDER);
+ styleOut("border-bottom", style.getBorderBottom(), BORDER);
+ }
+
+ private void fontStyle(CellStyle style) {
+ Font font = wb.getFontAt(style.getFontIndexAsInt());
+
+ if (font.getBold()) {
+ out.format(" font-weight: bold;%n");
+ }
+ if (font.getItalic()) {
+ out.format(" font-style: italic;%n");
+ }
+
+ int fontheight = font.getFontHeightInPoints();
+ if (fontheight == 9) {
+ //fix for stupid ol Windows
+ fontheight = 10;
+ }
+ out.format(" font-size: %dpt;%n", fontheight);
+
+ // Font color is handled with the other colors
+ }
+
+ private String styleName(CellStyle style) {
+ if (style == null) {
+ style = wb.getCellStyleAt((short) 0);
+ }
+ StringBuilder sb = new StringBuilder();
+ try (Formatter fmt = new Formatter(sb)) {
+ fmt.format("style_%02x", style.getIndex());
+ return fmt.toString();
+ }
+ }
+
+ private <K> void styleOut(String attr, K key, Map<K, String> mapping) {
+ String value = mapping.get(key);
+ if (value != null) {
+ out.format(" %s: %s;%n", attr, value);
+ }
+ }
+
+ private static CellType ultimateCellType(Cell c) {
+ CellType type = c.getCellType();
+ if (type == CellType.FORMULA) {
+ type = c.getCachedFormulaResultType();
+ }
+ return type;
+ }
+
+ private void printSheets() {
+ ensureOut();
+ Sheet sheet = wb.getSheetAt(0);
+ printSheet(sheet);
+ }
+
+ public void printSheet(Sheet sheet) {
+ ensureOut();
+ Map<Integer, Integer> widths = computeWidths(sheet);
+ int tableWidth = widths.get(IDX_TABLE_WIDTH);
+ out.format("<table class=%s style=\"width:%dpx;\">%n", DEFAULTS_CLASS, tableWidth);
+ printCols(widths);
+ printSheetContent(sheet);
+ out.format("</table>%n");
+ }
+
+ /**
+ * computes the column widths, defined by the sheet.
+ *
+ * @param sheet The sheet for which to compute widths
+ * @return Map with key: column index; value: column width in pixels
+ * <br>special keys:
+ * <br>{@link #IDX_HEADER_COL_WIDTH} - width of the header column
+ * <br>{@link #IDX_TABLE_WIDTH} - width of the entire table
+ */
+ private Map<Integer, Integer> computeWidths(Sheet sheet) {
+ Map<Integer, Integer> ret = new TreeMap<>();
+ int tableWidth = 0;
+
+ ensureColumnBounds(sheet);
+
+ // compute width of the header column
+ int lastRowNum = sheet.getLastRowNum();
+ int headerCharCount = String.valueOf(lastRowNum).length();
+ int headerColWidth = widthToPixels((headerCharCount + 1) * 256.0);
+ ret.put(IDX_HEADER_COL_WIDTH, headerColWidth);
+ tableWidth += headerColWidth;
+
+ for (int i = firstColumn; i < endColumn; i++) {
+ int colWidth = widthToPixels(sheet.getColumnWidth(i));
+ ret.put(i, colWidth);
+ tableWidth += colWidth;
+ }
+
+ ret.put(IDX_TABLE_WIDTH, tableWidth);
+ return ret ;
+ }
+
+ /**
+ * Probably platform-specific, but appears to be a close approximation on some systems
+ * @param widthUnits POI's native width unit (twips)
+ * @return the approximate number of pixels for a typical display
+ */
+ protected int widthToPixels(final double widthUnits) {
+ return Math.toIntExact(Math.round(widthUnits * 9 / 256));
+ }
+
+ private void printCols(Map<Integer, Integer> widths) {
+ int headerColWidth = widths.get(IDX_HEADER_COL_WIDTH);
+ out.format("<col style=\"width:%dpx\"/>%n", headerColWidth);
+ for (int i = firstColumn; i < endColumn; i++) {
+ int colWidth = widths.get(i);
+ out.format("<col style=\"width:%dpx;\"/>%n", colWidth);
+ }
+ }
+
+ private void ensureColumnBounds(Sheet sheet) {
+ if (gotBounds) {
+ return;
+ }
+
+ Iterator<Row> iter = sheet.rowIterator();
+ firstColumn = (iter.hasNext() ? Integer.MAX_VALUE : 0);
+ endColumn = 0;
+ while (iter.hasNext()) {
+ Row row = iter.next();
+ short firstCell = row.getFirstCellNum();
+ if (firstCell >= 0) {
+ firstColumn = Math.min(firstColumn, firstCell);
+ endColumn = Math.max(endColumn, row.getLastCellNum());
+ }
+ }
+ gotBounds = true;
+ }
+
+ private void printColumnHeads() {
+ out.format("<thead>%n");
+ out.format(" <tr class=%s>%n", COL_HEAD_CLASS);
+ out.format(" <th class=%s>◊</th>%n", COL_HEAD_CLASS);
+ //noinspection UnusedDeclaration
+ StringBuilder colName = new StringBuilder();
+ for (int i = firstColumn; i < endColumn; i++) {
+ colName.setLength(0);
+ int cnum = i;
+ do {
+ colName.insert(0, (char) ('A' + cnum % 26));
+ cnum /= 26;
+ } while (cnum > 0);
+ out.format(" <th class=%s>%s</th>%n", COL_HEAD_CLASS, colName);
+ }
+ out.format(" </tr>%n");
+ out.format("</thead>%n");
+ }
+
+ private void printSheetContent(Sheet sheet) {
+ printColumnHeads();
+
+ out.format("<tbody>%n");
+ Iterator<Row> rows = sheet.rowIterator();
+ while (rows.hasNext()) {
+ Row row = rows.next();
+
+ out.format(" <tr>%n");
+ out.format(" <td class=%s>%d</td>%n", ROW_HEAD_CLASS,
+ row.getRowNum() + 1);
+ for (int i = firstColumn; i < endColumn; i++) {
+ String content = " ";
+ String attrs = "";
+ CellStyle style = null;
+ if (i >= row.getFirstCellNum() && i < row.getLastCellNum()) {
+ Cell cell = row.getCell(i);
+ if (cell != null) {
+ style = cell.getCellStyle();
+ attrs = tagStyle(cell, style);
+ //Set the value that is rendered for the cell
+ //also applies the format
+ CellFormat cf = CellFormat.getInstance(
+ style.getDataFormatString());
+ CellFormatResult result = cf.apply(cell);
+ content = result.text; //never null
+ if (content.isEmpty()) {
+ content = " ";
+ }
+ }
+ }
+ out.format(" <td class=%s %s>%s</td>%n", styleName(style),
+ attrs, content);
+ }
+ out.format(" </tr>%n");
+ }
+ out.format("</tbody>%n");
+ }
+
+ private String tagStyle(Cell cell, CellStyle style) {
+ if (style.getAlignment() == HorizontalAlignment.GENERAL) {
+ switch (ultimateCellType(cell)) {
+ case STRING:
+ return "style=\"text-align: left;\"";
+ case BOOLEAN:
+ case ERROR:
+ return "style=\"text-align: center;\"";
+ case NUMERIC:
+ default:
+ // "right" is the default
+ break;
+ }
+ }
+ return "";
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.ss.html;
+
+import java.util.Formatter;
+
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+
+/**
+ * Implementation of {@link HtmlHelper} for XSSF files.
+ *
+ * @author Ken Arnold, Industrious Media LLC
+ */
+public class XSSFHtmlHelper implements HtmlHelper {
+ @Override
+ public void colorStyles(CellStyle style, Formatter out) {
+ XSSFCellStyle cs = (XSSFCellStyle) style;
+ styleColor(out, "background-color", cs.getFillForegroundXSSFColor());
+ styleColor(out, "text-color", cs.getFont().getXSSFColor());
+ }
+
+ private void styleColor(Formatter out, String attr, XSSFColor color) {
+ if (color == null || color.isAuto()) {
+ return;
+ }
+
+ byte[] rgb = color.getRGB();
+ if (rgb == null) {
+ return;
+ }
+
+ // This is done twice -- rgba is new with CSS 3, and browser that don't
+ // support it will ignore the rgba specification and stick with the
+ // solid color, which is declared first
+ out.format(" %s: #%02x%02x%02x;%n", attr, rgb[0], rgb[1], rgb[2]);
+ byte[] argb = color.getARGB();
+ if (argb == null) {
+ return;
+ }
+ out.format(" %s: rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x);%n", attr,
+ argb[3], argb[0], argb[1], argb[2]);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ ====================================================================
+ 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.
+ ====================================================================
+ */
+/*
+ * This is the default style sheet for html generated by ToHtml
+ *
+ * @author Ken Arnold, Industrious Media LLC
+ */
+.excelDefaults {
+ background-color: white;
+ color: black;
+ text-decoration: none;
+ direction: ltr;
+ text-transform: none;
+ text-indent: 0;
+ letter-spacing: 0;
+ word-spacing: 0;
+ white-space: pre-wrap;
+ unicode-bidi: normal;
+ background-image: none;
+ text-shadow: none;
+ list-style-image: none;
+ list-style-type: none;
+ padding: 0;
+ margin: 0;
+ border-collapse: collapse;
+ vertical-align: bottom;
+ font-style: normal;
+ font-family: sans-serif;
+ font-variant: normal;
+ font-weight: normal;
+ font-size: 10pt;
+ text-align: right;
+ table-layout: fixed;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+}
+
+.excelDefaults td {
+ padding: 1px 5px;
+ border: 1px solid silver;
+}
+
+.excelDefaults .colHeader {
+ background-color: silver;
+ font-weight: bold;
+ border: 1px solid black;
+ text-align: center;
+ padding: 1px 5px;
+}
+
+.excelDefaults .rowHeader {
+ background-color: silver;
+ font-weight: bold;
+ border: 1px solid black;
+ text-align: right;
+ padding: 1px 5px;
+}
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+/**
+ * This package contains an example that uses POI to convert a workbook into
+ * an HTML representation of the data. It can use both XSSF and HSSF workbooks.
+ */
+package org.apache.poi.examples.ss.html;
\ No newline at end of file
+++ /dev/null
-/*
- * ====================================================================
- * 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.examples.util;
-
-import java.io.File;
-
-import org.apache.poi.util.TempFile;
-
-public final class TempFileUtils {
- private TempFileUtils() {
- }
-
- @SuppressWarnings("java:S106")
- public static void checkTempFiles() {
- String tmpDir = System.getProperty(TempFile.JAVA_IO_TMPDIR) + "/poifiles";
- File tempDir = new File(tmpDir);
- if(tempDir.exists()) {
- String[] tempFiles = tempDir.list();
- if(tempFiles != null && tempFiles.length > 0) {
- System.out.println("found files in poi temp dir " + tempDir.getAbsolutePath());
- for(String filename : tempFiles) {
- System.out.println("file: " + filename);
- }
- }
- } else {
- System.out.println("unable to find poi temp dir");
- }
- }
-}
--- /dev/null
+/*\r
+ * ====================================================================\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements. See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License. You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ==================================================================== \r
+ */\r
+\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import java.awt.Rectangle;\r
+import java.awt.image.BufferedImage;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.net.URL;\r
+import java.text.DecimalFormat;\r
+\r
+import javax.imageio.ImageIO;\r
+import javax.xml.namespace.QName;\r
+\r
+import org.apache.poi.openxml4j.opc.PackagePart;\r
+import org.apache.poi.openxml4j.opc.PackagePartName;\r
+import org.apache.poi.openxml4j.opc.PackageRelationship;\r
+import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
+import org.apache.poi.openxml4j.opc.TargetMode;\r
+import org.apache.poi.sl.usermodel.PictureData.PictureType;\r
+import org.apache.xmlbeans.XmlCursor;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;\r
+import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTExtension;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTTLCommonMediaNodeData;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTTLCommonTimeNodeData;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTTimeNodeList;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeIndefinite;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeFillType;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeRestartType;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeType;\r
+\r
+import com.xuggle.mediatool.IMediaReader;\r
+import com.xuggle.mediatool.MediaListenerAdapter;\r
+import com.xuggle.mediatool.ToolFactory;\r
+import com.xuggle.mediatool.event.IVideoPictureEvent;\r
+import com.xuggle.xuggler.Global;\r
+import com.xuggle.xuggler.IContainer;\r
+import com.xuggle.xuggler.io.InputOutputStreamHandler;\r
+\r
+/**\r
+ * Adding multiple videos to a slide\r
+ * \r
+ * need the Xuggler 5.4 jars:\r
+ * <repositories>\r
+ * <repository>\r
+ * <id>xuggle repo</id>\r
+ * <url>http://xuggle.googlecode.com/svn/trunk/repo/share/java/</url>\r
+ * </repository>\r
+ * </repositories>\r
+ * ...\r
+ * <dependency>\r
+ * <groupId>xuggle</groupId>\r
+ * <artifactId>xuggle-xuggler</artifactId>\r
+ * <version>5.4</version>\r
+ * </dependency>\r
+ * \r
+ * @see <a href="http://stackoverflow.com/questions/15197300/apache-poi-xslf-adding-movie-to-the-slide">Apache POI XSLF Adding movie to the slide</a>\r
+ * @see <a href="http://apache-poi.1045710.n5.nabble.com/Question-about-embedded-video-in-PPTX-files-tt5718461.html">Question about embedded video in PPTX files</a>\r
+ */\r
+public class AddVideoToPptx {\r
+ static DecimalFormat df_time = new DecimalFormat("0.####");\r
+\r
+ public static void main(String[] args) throws Exception {\r
+ URL video = new URL("http://archive.org/download/test-mpeg/test-mpeg.mpg");\r
+ // URL video = new URL("file:test-mpeg.mpg");\r
+\r
+ XMLSlideShow pptx = new XMLSlideShow();\r
+\r
+ // add video file\r
+ String videoFileName = video.getPath().substring(video.getPath().lastIndexOf('/')+1);\r
+ PackagePartName partName = PackagingURIHelper.createPartName("/ppt/media/"+videoFileName);\r
+ PackagePart part = pptx.getPackage().createPart(partName, "video/mpeg");\r
+ OutputStream partOs = part.getOutputStream();\r
+ InputStream fis = video.openStream();\r
+ byte buf[] = new byte[1024];\r
+ for (int readBytes; (readBytes = fis.read(buf)) != -1; partOs.write(buf, 0, readBytes));\r
+ fis.close();\r
+ partOs.close();\r
+\r
+ XSLFSlide slide1 = pptx.createSlide();\r
+ XSLFPictureShape pv1 = addPreview(pptx, slide1, part, 5, 50, 50);\r
+ addVideo(pptx, slide1, part, pv1, 5);\r
+ addTimingInfo(slide1, pv1);\r
+ XSLFPictureShape pv2 = addPreview(pptx, slide1, part, 9, 50, 250);\r
+ addVideo(pptx, slide1, part, pv2, 9);\r
+ addTimingInfo(slide1, pv2);\r
+\r
+ FileOutputStream fos = new FileOutputStream("pptx-with-video.pptx");\r
+ pptx.write(fos);\r
+ fos.close();\r
+ \r
+ pptx.close();\r
+ }\r
+\r
+ static XSLFPictureShape addPreview(XMLSlideShow pptx, XSLFSlide slide1, PackagePart videoPart, double seconds, int x, int y) throws IOException {\r
+ // get preview after 5 sec.\r
+ IContainer ic = IContainer.make();\r
+ InputOutputStreamHandler iosh = new InputOutputStreamHandler(videoPart.getInputStream());\r
+ if (ic.open(iosh, IContainer.Type.READ, null) < 0) return null;\r
+\r
+ IMediaReader mediaReader = ToolFactory.makeReader(ic);\r
+\r
+ // stipulate that we want BufferedImages created in BGR 24bit color space\r
+ mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);\r
+\r
+ ImageSnapListener isl = new ImageSnapListener(seconds);\r
+ mediaReader.addListener(isl);\r
+\r
+ // read out the contents of the media file and\r
+ // dispatch events to the attached listener\r
+ while (!isl.hasFired && mediaReader.readPacket() == null) ;\r
+\r
+ mediaReader.close();\r
+ ic.close();\r
+\r
+ // add snapshot\r
+ BufferedImage image1 = isl.image;\r
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
+ ImageIO.write(image1, "jpeg", bos);\r
+ XSLFPictureData snap = pptx.addPicture(bos.toByteArray(), PictureType.JPEG);\r
+ XSLFPictureShape pic1 = slide1.createPicture(snap);\r
+ pic1.setAnchor(new Rectangle(x, y, image1.getWidth(), image1.getHeight()));\r
+ return pic1;\r
+ }\r
+\r
+ static void addVideo(XMLSlideShow pptx, XSLFSlide slide1, PackagePart videoPart, XSLFPictureShape pic1, double seconds) throws IOException {\r
+\r
+ // add video shape\r
+ PackagePartName partName = videoPart.getPartName();\r
+ PackageRelationship prsEmbed1 = slide1.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.microsoft.com/office/2007/relationships/media");\r
+ PackageRelationship prsExec1 = slide1.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/video");\r
+ CTPicture xpic1 = (CTPicture)pic1.getXmlObject();\r
+ CTHyperlink link1 = xpic1.getNvPicPr().getCNvPr().addNewHlinkClick();\r
+ link1.setId("");\r
+ link1.setAction("ppaction://media");\r
+\r
+ // add video relation\r
+ CTApplicationNonVisualDrawingProps nvPr = xpic1.getNvPicPr().getNvPr();\r
+ nvPr.addNewVideoFile().setLink(prsExec1.getId());\r
+ CTExtension ext = nvPr.addNewExtLst().addNewExt();\r
+ // see http://msdn.microsoft.com/en-us/library/dd950140(v=office.12).aspx\r
+ ext.setUri("{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}");\r
+ String p14Ns = "http://schemas.microsoft.com/office/powerpoint/2010/main";\r
+ XmlCursor cur = ext.newCursor();\r
+ cur.toEndToken();\r
+ cur.beginElement(new QName(p14Ns, "media", "p14"));\r
+ cur.insertNamespace("p14", p14Ns);\r
+ cur.insertAttributeWithValue(new QName(STRelationshipId.type.getName().getNamespaceURI(), "embed"), prsEmbed1.getId());\r
+ cur.beginElement(new QName(p14Ns, "trim", "p14"));\r
+ cur.insertAttributeWithValue("st", df_time.format(seconds*1000.0));\r
+ cur.dispose();\r
+\r
+ }\r
+\r
+ static void addTimingInfo(XSLFSlide slide1, XSLFPictureShape pic1) {\r
+ // add slide timing information, so video can be controlled\r
+ CTSlide xslide = slide1.getXmlObject();\r
+ CTTimeNodeList ctnl;\r
+ if (!xslide.isSetTiming()) {\r
+ CTTLCommonTimeNodeData ctn = xslide.addNewTiming().addNewTnLst().addNewPar().addNewCTn();\r
+ ctn.setDur(STTLTimeIndefinite.INDEFINITE);\r
+ ctn.setRestart(STTLTimeNodeRestartType.NEVER);\r
+ ctn.setNodeType(STTLTimeNodeType.TM_ROOT);\r
+ ctnl = ctn.addNewChildTnLst();\r
+ } else {\r
+ ctnl = xslide.getTiming().getTnLst().getParArray(0).getCTn().getChildTnLst();\r
+ }\r
+\r
+ CTTLCommonMediaNodeData cmedia = ctnl.addNewVideo().addNewCMediaNode();\r
+ cmedia.setVol(80000);\r
+ CTTLCommonTimeNodeData ctn = cmedia.addNewCTn();\r
+ ctn.setFill(STTLTimeNodeFillType.HOLD);\r
+ ctn.setDisplay(false);\r
+ ctn.addNewStCondLst().addNewCond().setDelay(STTLTimeIndefinite.INDEFINITE);\r
+ cmedia.addNewTgtEl().addNewSpTgt().setSpid(""+pic1.getShapeId());\r
+ }\r
+\r
+\r
+ static class ImageSnapListener extends MediaListenerAdapter {\r
+ final double SECONDS_BETWEEN_FRAMES;\r
+ final long MICRO_SECONDS_BETWEEN_FRAMES;\r
+ boolean hasFired = false;\r
+ BufferedImage image = null;\r
+\r
+ // The video stream index, used to ensure we display frames from one and\r
+ // only one video stream from the media container.\r
+ int mVideoStreamIndex = -1;\r
+\r
+ // Time of last frame write\r
+ long mLastPtsWrite = Global.NO_PTS;\r
+\r
+ public ImageSnapListener(double seconds) {\r
+ SECONDS_BETWEEN_FRAMES = seconds;\r
+ MICRO_SECONDS_BETWEEN_FRAMES =\r
+ (long)(Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES);\r
+ }\r
+\r
+\r
+ @Override\r
+ public void onVideoPicture(IVideoPictureEvent event) {\r
+\r
+ if (event.getStreamIndex() != mVideoStreamIndex) {\r
+ // if the selected video stream id is not yet set, go ahead an\r
+ // select this lucky video stream\r
+ if (mVideoStreamIndex != -1) return;\r
+ mVideoStreamIndex = event.getStreamIndex();\r
+ }\r
+\r
+ long evtTS = event.getTimeStamp();\r
+\r
+ // if uninitialized, back date mLastPtsWrite to get the very first frame\r
+ if (mLastPtsWrite == Global.NO_PTS)\r
+ mLastPtsWrite = Math.max(0, evtTS - MICRO_SECONDS_BETWEEN_FRAMES);\r
+\r
+ // if it's time to write the next frame\r
+ if (evtTS - mLastPtsWrite >= MICRO_SECONDS_BETWEEN_FRAMES) {\r
+ if (!hasFired) {\r
+ image = event.getImage();\r
+ hasFired = true;\r
+ }\r
+ // update last write time\r
+ mLastPtsWrite += MICRO_SECONDS_BETWEEN_FRAMES;\r
+ }\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.ooxml.POIXMLDocumentPart;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.chart.AxisOrientation;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFChart;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+
+/**
+ * Build a bar chart from a template pptx
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class BarChartDemo {
+ private BarChartDemo() {}
+
+ private static void usage(){
+ System.out.println("Usage: BarChartDemo <bar-chart-template.pptx> <bar-chart-data.txt>");
+ System.out.println(" bar-chart-template.pptx template with a bar chart");
+ System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
+ "then go pairs {axis-label value}");
+ }
+
+ public static void main(String[] args) throws Exception {
+ if(args.length < 2) {
+ usage();
+ return;
+ }
+
+ try (FileInputStream argIS = new FileInputStream(args[0]);
+ BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
+
+ String chartTitle = modelReader.readLine(); // first line is chart title
+ String[] series = modelReader.readLine().split(",");
+
+ // Category Axis Data
+ List<String> listLanguages = new ArrayList<>(10);
+
+ // Values
+ List<Double> listCountries = new ArrayList<>(10);
+ List<Double> listSpeakers = new ArrayList<>(10);
+
+ // set model
+ String ln;
+ while((ln = modelReader.readLine()) != null) {
+ String[] vals = ln.split(",");
+ listCountries.add(Double.valueOf(vals[0]));
+ listSpeakers.add(Double.valueOf(vals[1]));
+ listLanguages.add(vals[2]);
+ }
+ String[] categories = listLanguages.toArray(new String[0]);
+ Double[] values1 = listCountries.toArray(new Double[0]);
+ Double[] values2 = listSpeakers.toArray(new Double[0]);
+
+ try (XMLSlideShow pptx = new XMLSlideShow(argIS)) {
+ XSLFSlide slide = pptx.getSlides().get(0);
+ setBarData(findChart(slide), chartTitle, series, categories, values1, values2);
+
+ XSLFChart chart = findChart(pptx.createSlide().importContent(slide));
+ setColumnData(chart, "Column variant");
+
+ // save the result
+ try (OutputStream out = new FileOutputStream("bar-chart-demo-output.pptx")) {
+ pptx.write(out);
+ }
+ }
+ }
+ }
+
+ private static void setBarData(XSLFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
+ final List<XDDFChartData> data = chart.getChartSeries();
+ final XDDFBarChartData bar = (XDDFBarChartData) data.get(0);
+
+ final int numOfPoints = categories.length;
+ final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_LANGUAGES, COLUMN_LANGUAGES));
+ final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_COUNTRIES, COLUMN_COUNTRIES));
+ final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_SPEAKERS, COLUMN_SPEAKERS));
+ final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, COLUMN_LANGUAGES);
+ final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, COLUMN_COUNTRIES);
+ values1[6] = 16.0; // if you ever want to change the underlying data, it has to be done before building the data source
+ final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, COLUMN_SPEAKERS);
+
+ XDDFChartData.Series series1 = bar.getSeries(0);
+ series1.replaceData(categoriesData, valuesData);
+ series1.setTitle(series[0], chart.setSheetTitle(series[0], COLUMN_COUNTRIES));
+ XDDFChartData.Series series2 = bar.addSeries(categoriesData, valuesData2);
+ series2.setTitle(series[1], chart.setSheetTitle(series[1], COLUMN_SPEAKERS));
+
+ chart.plot(bar);
+ chart.setTitleText(chartTitle); // https://stackoverflow.com/questions/30532612
+ // chart.setTitleOverlay(overlay);
+
+ // adjust font size for readability
+ bar.getCategoryAxis().getOrAddTextProperties().setFontSize(11.5);
+ chart.getTitle().getOrAddTextProperties().setFontSize(18.2);
+ }
+
+ private static void setColumnData(XSLFChart chart, String chartTitle) {
+ // Series Text
+ List<XDDFChartData> series = chart.getChartSeries();
+ XDDFBarChartData bar = (XDDFBarChartData) series.get(0);
+
+ // in order to transform a bar chart into a column chart, you just need to change the bar direction
+ bar.setBarDirection(BarDirection.COL);
+
+ // looking for "Stacked Bar Chart"? uncomment the following line
+ // bar.setBarGrouping(BarGrouping.STACKED);
+
+ // additionally, you can adjust the axes
+ bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN);
+ bar.getValueAxes().get(0).setPosition(AxisPosition.TOP);
+ }
+
+ private static XSLFChart findChart(XSLFSlide slide) {
+ // find chart in the slide
+ XSLFChart chart = null;
+ for(POIXMLDocumentPart part : slide.getRelations()){
+ if(part instanceof XSLFChart){
+ chart = (XSLFChart) part;
+ break;
+ }
+ }
+
+ if(chart == null) {
+ throw new IllegalStateException("chart not found in the template");
+ }
+ return chart;
+ }
+
+ private static final int COLUMN_LANGUAGES = 0;
+ private static final int COLUMN_COUNTRIES = 1;
+ private static final int COLUMN_SPEAKERS = 2;
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.awt.geom.Rectangle2D;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.util.Units;
+import org.apache.poi.xddf.usermodel.chart.AxisCrossBetween;
+import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.AxisTickMark;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.BarGrouping;
+import org.apache.poi.xddf.usermodel.chart.ChartTypes;
+import org.apache.poi.xddf.usermodel.chart.LegendPosition;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartAxis;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFChart;
+import org.apache.poi.xslf.usermodel.XSLFGraphicFrame;
+import org.apache.poi.xslf.usermodel.XSLFShape;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+
+/**
+ * Build a chart without reading template file
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class ChartFromScratch {
+ private ChartFromScratch() {}
+
+ private static void usage(){
+ System.out.println("Usage: ChartFromScratch <bar-chart-data.txt>");
+ System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
+ "then go pairs {axis-label value}");
+ }
+
+ public static void main(String[] args) throws Exception {
+ if(args.length < 1) {
+ usage();
+ return;
+ }
+
+ try (BufferedReader modelReader = new BufferedReader(new FileReader(args[0]))) {
+
+ String chartTitle = modelReader.readLine(); // first line is chart title
+ String[] series = modelReader.readLine().split(",");
+
+ // Category Axis Data
+ List<String> listLanguages = new ArrayList<>(10);
+
+ // Values
+ List<Double> listCountries = new ArrayList<>(10);
+ List<Double> listSpeakers = new ArrayList<>(10);
+
+ // set model
+ String ln;
+ while((ln = modelReader.readLine()) != null) {
+ String[] vals = ln.split(",");
+ listCountries.add(Double.valueOf(vals[0]));
+ listSpeakers.add(Double.valueOf(vals[1]));
+ listLanguages.add(vals[2]);
+ }
+
+ String[] categories = listLanguages.toArray(new String[0]);
+ Double[] values1 = listCountries.toArray(new Double[0]);
+ Double[] values2 = listSpeakers.toArray(new Double[0]);
+
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ createSlideWithChart(ppt, chartTitle, series, categories, values1, values2);
+ createSlideWithChart(ppt, chartTitle, series, categories, values1, values2);
+ createSlideWithChart(ppt, chartTitle, series, categories, values1, values2);
+ // save the result
+ try (OutputStream out = new FileOutputStream("chart-from-scratch.pptx")) {
+ ppt.write(out);
+ }
+ }
+ try (FileInputStream is = new FileInputStream("chart-from-scratch.pptx")) {
+ try (XMLSlideShow ppt = new XMLSlideShow(is)) {
+ for (XSLFSlide slide : ppt.getSlides()) {
+ for (XSLFShape shape : slide.getShapes()) {
+ if (shape instanceof XSLFGraphicFrame) {
+ XSLFGraphicFrame frame = (XSLFGraphicFrame) shape;
+ if (frame.hasChart()) {
+ System.out.println(frame.getChart().getTitleShape().getText());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ System.out.println("Done");
+ }
+
+ private static void createSlideWithChart(XMLSlideShow ppt, String chartTitle, String[] series, String[] categories,
+ Double[] values1, Double[] values2) {
+ XSLFSlide slide = ppt.createSlide();
+ XSLFChart chart = ppt.createChart();
+ Rectangle2D rect2D = new java.awt.Rectangle(fromCM(1.5), fromCM(4), fromCM(22), fromCM(14));
+ slide.addChart(chart, rect2D);
+ setBarData(chart, chartTitle, series, categories, values1, values2);
+ }
+
+ private static int fromCM(double cm) {
+ return (int) (Math.rint(cm * Units.EMU_PER_CENTIMETER));
+ }
+
+ private static void setBarData(XSLFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
+ // Use a category axis for the bottom axis.
+ XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
+ bottomAxis.setTitle(series[2]);
+ XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
+ leftAxis.setTitle(series[0]+","+series[1]);
+ leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
+ leftAxis.setMajorTickMark(AxisTickMark.OUT);
+ leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
+
+ final int numOfPoints = categories.length;
+ final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_LANGUAGES, COLUMN_LANGUAGES));
+ final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_COUNTRIES, COLUMN_COUNTRIES));
+ final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_SPEAKERS, COLUMN_SPEAKERS));
+ final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, COLUMN_LANGUAGES);
+ final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, COLUMN_COUNTRIES);
+ valuesData.setFormatCode("General");
+ values1[6] = 16.0; // if you ever want to change the underlying data, it has to be done before building the data source
+ final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, COLUMN_SPEAKERS);
+ valuesData2.setFormatCode("General");
+
+
+ XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
+ bar.setBarGrouping(BarGrouping.CLUSTERED);
+
+ XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
+ series1.setTitle(series[0], chart.setSheetTitle(series[0], COLUMN_COUNTRIES));
+
+ XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
+ series2.setTitle(series[1], chart.setSheetTitle(series[1], COLUMN_SPEAKERS));
+
+ bar.setVaryColors(true);
+ bar.setBarDirection(BarDirection.COL);
+ chart.plot(bar);
+
+ XDDFChartLegend legend = chart.getOrAddLegend();
+ legend.setPosition(LegendPosition.LEFT);
+ legend.setOverlay(false);
+
+ chart.setTitleText(chartTitle);
+ chart.setTitleOverlay(false);
+ chart.setAutoTitleDeleted(false);
+ }
+
+ private static final int COLUMN_LANGUAGES = 0;
+ private static final int COLUMN_COUNTRIES = 1;
+ private static final int COLUMN_SPEAKERS = 2;
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.awt.Dimension;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFPictureData;
+import org.apache.poi.xslf.usermodel.XSLFPictureShape;
+import org.apache.poi.xslf.usermodel.XSLFShape;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFTextShape;
+
+/**
+ * Demonstrates how you can extract data from a .pptx file
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class DataExtraction {
+ private DataExtraction() {}
+
+ public static void main(String[] args) throws IOException {
+
+ PrintStream out = System.out;
+
+ if (args.length == 0) {
+ out.println("Input file is required");
+ return;
+ }
+
+ FileInputStream is = new FileInputStream(args[0]);
+ try (XMLSlideShow ppt = new XMLSlideShow(is)) {
+ is.close();
+
+ // Get the document's embedded files.
+ for (PackagePart p : ppt.getAllEmbeddedParts()) {
+ String type = p.getContentType();
+ // typically file name
+ String name = p.getPartName().getName();
+ out.println("Embedded file (" + type + "): " + name);
+
+ InputStream pIs = p.getInputStream();
+ // make sense of the part data
+ pIs.close();
+
+ }
+
+ // Get the document's embedded files.
+ for (XSLFPictureData data : ppt.getPictureData()) {
+ String type = data.getContentType();
+ String name = data.getFileName();
+ out.println("Picture (" + type + "): " + name);
+
+ InputStream pIs = data.getInputStream();
+ // make sense of the image data
+ pIs.close();
+ }
+
+ // size of the canvas in points
+ Dimension pageSize = ppt.getPageSize();
+ out.println("Pagesize: " + pageSize);
+
+ for (XSLFSlide slide : ppt.getSlides()) {
+ for (XSLFShape shape : slide) {
+ if (shape instanceof XSLFTextShape) {
+ XSLFTextShape txShape = (XSLFTextShape) shape;
+ out.println(txShape.getText());
+ } else if (shape instanceof XSLFPictureShape) {
+ XSLFPictureShape pShape = (XSLFPictureShape) shape;
+ XSLFPictureData pData = pShape.getPictureData();
+ out.println(pData.getFileName());
+ } else {
+ out.println("Process me: " + shape.getClass());
+ }
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+
+/**
+ * Merge multiple pptx presentations together
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class MergePresentations {
+ private MergePresentations() {}
+
+ public static void main(String[] args) throws Exception {
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ for (String arg : args) {
+ try (FileInputStream is = new FileInputStream(arg);
+ XMLSlideShow src = new XMLSlideShow(is)) {
+ for (XSLFSlide srcSlide : src.getSlides()) {
+ ppt.createSlide().importContent(srcSlide);
+ }
+ }
+ }
+
+ try (FileOutputStream out = new FileOutputStream("merged.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.xslf.usermodel;
+
+import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.batik.transcoder.wmf.tosvg.WMFPainter;
+import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import javax.imageio.ImageIO;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.DataInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+/**
+ * Convert each slide of a .pptx presentation into SVG
+ *
+ * @author Yegor Kozlov
+ */
+public class PPTX2SVG {
+
+ static void usage() {
+ System.out.println("Usage: PPTX2SVG <pptx file>");
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ usage();
+ return;
+ }
+
+ String file = args[0];
+
+ System.out.println("Processing " + file);
+
+ // read the .pptx file
+ XMLSlideShow ppt = new XMLSlideShow(OPCPackage.open(file));
+
+ Dimension pgsize = ppt.getPageSize();
+
+ // convert each slide into a .svg file
+ XSLFSlide[] slide = ppt.getSlides();
+ for (int i = 0; i < slide.length; i++) {
+ // Create initial SVG DOM
+ DOMImplementation domImpl = SVGDOMImplementation.getDOMImplementation();
+ Document doc = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
+ //Use Batik SVG Graphics2D driver
+ SVGGraphics2D graphics = new SVGGraphics2D(doc);
+ graphics.setRenderingHint(XSLFRenderingHint.IMAGE_RENDERER, new WMFImageRender());
+ graphics.setSVGCanvasSize(pgsize);
+
+ String title = slide[i].getTitle();
+ System.out.println("Rendering slide " + (i + 1) + (title == null ? "" : ": " + title));
+
+ // draw stuff. All the heavy-lifting happens here
+ slide[i].draw(graphics);
+
+ // save the result.
+ int sep = file.lastIndexOf(".");
+ String fname = file.substring(0, sep == -1 ? file.length() : sep) + "-" + (i + 1) + ".svg";
+ OutputStreamWriter out =
+ new OutputStreamWriter(new FileOutputStream(fname), "UTF-8");
+ DOMSource domSource = new DOMSource(graphics.getRoot());
+ StreamResult streamResult = new StreamResult(out);
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer serializer = tf.newTransformer();
+ serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ serializer.setOutputProperty(OutputKeys.INDENT, "yes");
+ serializer.transform(domSource, streamResult);
+ out.flush();
+ out.close();
+ }
+ System.out.println("Done");
+ }
+
+ /**
+ * Image renderer with support for .wmf images
+ */
+ static class WMFImageRender extends XSLFImageRendener {
+
+ /**
+ * Use Apache Batik to render WMF,
+ * delegate all other types of images to the javax.imageio framework
+ */
+ @Override
+ public boolean drawImage(Graphics2D graphics, XSLFPictureData data,
+ Rectangle2D anchor) {
+ try {
+ // see what type of image we are
+ PackagePart part = data.getPackagePart();
+ String contentType = part.getContentType();
+ if (contentType.equals("image/x-wmf")) {
+ WMFRecordStore currentStore = new WMFRecordStore();
+ currentStore.read(new DataInputStream(part.getInputStream()));
+ int wmfwidth = currentStore.getWidthPixels();
+ float conv = (float) anchor.getWidth() / wmfwidth;
+
+ // Build a painter for the RecordStore
+ WMFPainter painter = new WMFPainter(currentStore,
+ (int) anchor.getX(), (int) anchor.getY(), conv);
+ painter.paint(graphics);
+ } else {
+ BufferedImage img = ImageIO.read(data.getPackagePart().getInputStream());
+ graphics.drawImage(img,
+ (int) anchor.getX(), (int) anchor.getY(),
+ (int) anchor.getWidth(), (int) anchor.getHeight(), null);
+ }
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Convert data form the supplied package part into a BufferedImage.
+ * This method is used to create texture paint.
+ */
+ @Override
+ public BufferedImage readImage(PackagePart packagePart) throws IOException {
+ String contentType = packagePart.getContentType();
+ if (contentType.equals("image/x-wmf")) {
+ try {
+ WMFRecordStore currentStore = new WMFRecordStore();
+ currentStore.read(new DataInputStream(packagePart.getInputStream()));
+ int wmfwidth = currentStore.getWidthPixels();
+ int wmfheight = currentStore.getHeightPixels();
+
+ BufferedImage img = new BufferedImage(wmfwidth, wmfheight, BufferedImage.TYPE_INT_RGB);
+ Graphics2D graphics = img.createGraphics();
+
+ // Build a painter for the RecordStore
+ WMFPainter painter = new WMFPainter(currentStore, 0, 0, 1.0f);
+ painter.paint(graphics);
+
+ return img;
+ } catch (IOException e) {
+ return null;
+ }
+ } else {
+ return ImageIO.read(packagePart.getInputStream());
+ }
+ }
+
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.ooxml.POIXMLDocumentPart;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFPieChartData;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFChart;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+
+/**
+ * Build a pie chart from a template pptx
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class PieChartDemo {
+ private PieChartDemo() {}
+
+ private static void usage(){
+ System.out.println("Usage: PieChartDemo <pie-chart-template.pptx> <pie-chart-data.txt>");
+ System.out.println(" pie-chart-template.pptx template with a pie chart");
+ System.out.println(" pie-chart-data.txt the model to set. First line is chart title, " +
+ "then go pairs {axis-label value}");
+ }
+
+ public static void main(String[] args) throws Exception {
+ if(args.length < 2) {
+ usage();
+ return;
+ }
+
+ try (FileInputStream argIS = new FileInputStream(args[0]);
+ BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
+ String chartTitle = modelReader.readLine(); // first line is chart title
+
+ try (XMLSlideShow pptx = new XMLSlideShow(argIS)) {
+ XSLFSlide slide = pptx.getSlides().get(0);
+
+ // find chart in the slide
+ XSLFChart chart = null;
+ for (POIXMLDocumentPart part : slide.getRelations()) {
+ if (part instanceof XSLFChart) {
+ chart = (XSLFChart) part;
+ break;
+ }
+ }
+
+ if(chart == null) {
+ throw new IllegalStateException("chart not found in the template");
+ }
+
+ // Series Text
+ List<XDDFChartData> series = chart.getChartSeries();
+ XDDFPieChartData pie = (XDDFPieChartData) series.get(0);
+
+ // Category Axis Data
+ List<String> listCategories = new ArrayList<>(3);
+
+ // Values
+ List<Double> listValues = new ArrayList<>(3);
+
+ // set model
+ String ln;
+ while((ln = modelReader.readLine()) != null){
+ String[] vals = ln.split("\\s+");
+ listCategories.add(vals[0]);
+ listValues.add(Double.valueOf(vals[1]));
+ }
+ String[] categories = listCategories.toArray(new String[0]);
+ Double[] values = listValues.toArray(new Double[0]);
+
+ final int numOfPoints = categories.length;
+ final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
+ final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
+ final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange);
+ final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange);
+
+ XDDFPieChartData.Series firstSeries = (XDDFPieChartData.Series) pie.getSeries(0);
+ firstSeries.replaceData(categoriesData, valuesData);
+ firstSeries.setTitle(chartTitle, chart.setSheetTitle(chartTitle, 0));
+ firstSeries.setExplosion(25L);
+ chart.plot(pie);
+
+ // save the result
+ try (OutputStream out = new FileOutputStream("pie-chart-demo-output.pptx")) {
+ pptx.write(out);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.xslf.usermodel.SlideLayout;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
+import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
+import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
+import org.apache.poi.xslf.usermodel.XSLFTextShape;
+
+/**
+ * Demonstrates how to create slides with predefined layout
+ * and fill the placeholder shapes
+ */
+public final class Tutorial1 {
+ private Tutorial1() {}
+
+ public static void main(String[] args) throws IOException{
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ // XSLFSlide#createSlide() with no arguments creates a blank slide
+ /*XSLFSlide blankSlide =*/
+ ppt.createSlide();
+
+
+ XSLFSlideMaster master = ppt.getSlideMasters().get(0);
+
+ XSLFSlideLayout layout1 = master.getLayout(SlideLayout.TITLE);
+ XSLFSlide slide1 = ppt.createSlide(layout1);
+ XSLFTextShape[] ph1 = slide1.getPlaceholders();
+ XSLFTextShape titlePlaceholder1 = ph1[0];
+ titlePlaceholder1.setText("This is a title");
+ XSLFTextShape subtitlePlaceholder1 = ph1[1];
+ subtitlePlaceholder1.setText("this is a subtitle");
+
+ XSLFSlideLayout layout2 = master.getLayout(SlideLayout.TITLE_AND_CONTENT);
+ XSLFSlide slide2 = ppt.createSlide(layout2);
+ XSLFTextShape[] ph2 = slide2.getPlaceholders();
+ XSLFTextShape titlePlaceholder2 = ph2[0];
+ titlePlaceholder2.setText("This is a title");
+ XSLFTextShape bodyPlaceholder = ph2[1];
+ // we are going to add text by paragraphs. Clear the default placehoder text before that
+ bodyPlaceholder.clearText();
+ XSLFTextParagraph p1 = bodyPlaceholder.addNewTextParagraph();
+ p1.setIndentLevel(0);
+ p1.addNewTextRun().setText("Level1 text");
+ XSLFTextParagraph p2 = bodyPlaceholder.addNewTextParagraph();
+ p2.setIndentLevel(1);
+ p2.addNewTextRun().setText("Level2 text");
+ XSLFTextParagraph p3 = bodyPlaceholder.addNewTextParagraph();
+ p3.setIndentLevel(2);
+ p3.addNewTextRun().setText("Level3 text");
+
+ try (FileOutputStream out = new FileOutputStream("slides.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFTextBox;
+import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
+import org.apache.poi.xslf.usermodel.XSLFTextRun;
+
+/**
+ * Basic paragraph and text formatting
+ */
+public final class Tutorial2 {
+ private Tutorial2() {}
+
+ public static void main(String[] args) throws IOException{
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ XSLFSlide slide1 = ppt.createSlide();
+ XSLFTextBox shape1 = slide1.createTextBox();
+ // initial height of the text box is 100 pt but
+ Rectangle anchor = new Rectangle(10, 100, 300, 100);
+ shape1.setAnchor(anchor);
+
+ XSLFTextParagraph p1 = shape1.addNewTextParagraph();
+ XSLFTextRun r1 = p1.addNewTextRun();
+ r1.setText("Paragraph Formatting");
+ r1.setFontSize(24d);
+ r1.setFontColor(new Color(85, 142, 213));
+
+ XSLFTextParagraph p2 = shape1.addNewTextParagraph();
+ // If spaceBefore >= 0, then space is a percentage of normal line height.
+ // If spaceBefore < 0, the absolute value of linespacing is the spacing in points
+ p2.setSpaceBefore(-20d); // 20 pt from the previous paragraph
+ p2.setSpaceAfter(300d); // 3 lines after the paragraph
+ XSLFTextRun r2 = p2.addNewTextRun();
+ r2.setText("Paragraph properties apply to all text residing within the corresponding paragraph.");
+ r2.setFontSize(16d);
+
+ XSLFTextParagraph p3 = shape1.addNewTextParagraph();
+
+ XSLFTextRun r3 = p3.addNewTextRun();
+ r3.setText("Run Formatting");
+ r3.setFontSize(24d);
+ r3.setFontColor(new Color(85, 142, 213));
+
+ XSLFTextParagraph p4 = shape1.addNewTextParagraph();
+ p4.setSpaceBefore(-20d); // 20 pt from the previous paragraph
+ p4.setSpaceAfter(300d); // 3 lines after the paragraph
+ XSLFTextRun r4 = p4.addNewTextRun();
+ r4.setFontSize(16d);
+ r4.setText(
+ "Run level formatting is the most granular property level and allows " +
+ "for the specifying of all low level text properties. The text run is " +
+ "what all paragraphs are derived from and thus specifying various " +
+ "properties per run will allow for a diversely formatted text paragraph.");
+
+ // resize the shape to fit text
+ shape1.resizeToFitText();
+
+ try (FileOutputStream out = new FileOutputStream("text.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.awt.Rectangle;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.sl.usermodel.Placeholder;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFTextShape;
+
+/**
+ * How to set slide title
+ */
+public final class Tutorial3 {
+ private Tutorial3() {}
+
+ public static void main(String[] args) throws IOException{
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ XSLFSlide slide = ppt.createSlide();
+
+ XSLFTextShape titleShape = slide.createTextBox();
+ titleShape.setPlaceholder(Placeholder.TITLE);
+ titleShape.setText("This is a slide title");
+ titleShape.setAnchor(new Rectangle(50, 50, 400, 100));
+
+ try (FileOutputStream out = new FileOutputStream("title.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.sl.usermodel.TableCell.BorderEdge;
+import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFTable;
+import org.apache.poi.xslf.usermodel.XSLFTableCell;
+import org.apache.poi.xslf.usermodel.XSLFTableRow;
+import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
+import org.apache.poi.xslf.usermodel.XSLFTextRun;
+
+/**
+ * PPTX Tables
+ */
+public final class Tutorial4 {
+ private Tutorial4() {}
+
+ public static void main(String[] args) throws IOException{
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ // XSLFSlide#createSlide() with no arguments creates a blank slide
+ XSLFSlide slide = ppt.createSlide();
+
+ XSLFTable tbl = slide.createTable();
+ tbl.setAnchor(new Rectangle(50, 50, 450, 300));
+
+ int numColumns = 3;
+ int numRows = 5;
+ XSLFTableRow headerRow = tbl.addRow();
+ headerRow.setHeight(50);
+ // header
+ for (int i = 0; i < numColumns; i++) {
+ XSLFTableCell th = headerRow.addCell();
+ XSLFTextParagraph p = th.addNewTextParagraph();
+ p.setTextAlign(TextAlign.CENTER);
+ XSLFTextRun r = p.addNewTextRun();
+ r.setText("Header " + (i + 1));
+ r.setBold(true);
+ r.setFontColor(Color.white);
+ th.setFillColor(new Color(79, 129, 189));
+ th.setBorderWidth(BorderEdge.bottom, 2.0);
+ th.setBorderColor(BorderEdge.bottom, Color.white);
+
+ tbl.setColumnWidth(i, 150); // all columns are equally sized
+ }
+
+ // rows
+
+ for (int rownum = 0; rownum < numRows; rownum++) {
+ XSLFTableRow tr = tbl.addRow();
+ tr.setHeight(50);
+ // header
+ for (int i = 0; i < numColumns; i++) {
+ XSLFTableCell cell = tr.addCell();
+ XSLFTextParagraph p = cell.addNewTextParagraph();
+ XSLFTextRun r = p.addNewTextRun();
+
+ r.setText("Cell " + (i + 1));
+ if (rownum % 2 == 0)
+ cell.setFillColor(new Color(208, 216, 232));
+ else
+ cell.setFillColor(new Color(233, 247, 244));
+
+ }
+ }
+
+ try (FileOutputStream out = new FileOutputStream("table.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFPictureData;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+
+/**
+ * Images
+ */
+public final class Tutorial5 {
+ private Tutorial5() {}
+
+ public static void main(String[] args) throws IOException{
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ XSLFSlide slide = ppt.createSlide();
+
+ File img = new File(System.getProperty("POI.testdata.path", "test-data"), "slideshow/clock.jpg");
+ XSLFPictureData pictureData = ppt.addPicture(img, PictureType.PNG);
+
+ /*XSLFPictureShape shape =*/
+ slide.createPicture(pictureData);
+
+ try (FileOutputStream out = new FileOutputStream("images.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.awt.Rectangle;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFHyperlink;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFTextBox;
+import org.apache.poi.xslf.usermodel.XSLFTextRun;
+
+/**
+ * Hyperlinks
+ */
+public final class Tutorial6 {
+ private Tutorial6() {}
+
+ public static void main(String[] args) throws IOException{
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ XSLFSlide slide1 = ppt.createSlide();
+ XSLFSlide slide2 = ppt.createSlide();
+
+ XSLFTextBox shape1 = slide1.createTextBox();
+ shape1.setAnchor(new Rectangle(50, 50, 200, 50));
+ XSLFTextRun r1 = shape1.addNewTextParagraph().addNewTextRun();
+ XSLFHyperlink link1 = r1.createHyperlink();
+ r1.setText("https://poi.apache.org"); // visible text
+ link1.setAddress("https://poi.apache.org"); // link address
+
+ XSLFTextBox shape2 = slide1.createTextBox();
+ shape2.setAnchor(new Rectangle(300, 50, 200, 50));
+ XSLFTextRun r2 = shape2.addNewTextParagraph().addNewTextRun();
+ XSLFHyperlink link2 = r2.createHyperlink();
+ r2.setText("Go to the second slide"); // visible text
+ link2.linkToSlide(slide2); // link address
+
+
+ try (FileOutputStream out = new FileOutputStream("hyperlinks.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.sl.usermodel.AutoNumberingScheme;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFTextBox;
+import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
+import org.apache.poi.xslf.usermodel.XSLFTextRun;
+
+/**
+ * Bullets and numbering
+ */
+public final class Tutorial7 {
+ private Tutorial7() {}
+
+ public static void main(String[] args) throws IOException {
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ XSLFSlide slide = ppt.createSlide();
+ XSLFTextBox shape = slide.createTextBox();
+ shape.setAnchor(new Rectangle(50, 50, 400, 200));
+
+ XSLFTextParagraph p1 = shape.addNewTextParagraph();
+ p1.setIndentLevel(0);
+ p1.setBullet(true);
+ XSLFTextRun r1 = p1.addNewTextRun();
+ r1.setText("Bullet1");
+
+ XSLFTextParagraph p2 = shape.addNewTextParagraph();
+ // indentation before text
+ p2.setLeftMargin(60d);
+ // the bullet is set 40 pt before the text
+ p2.setIndent(-40d);
+ p2.setBullet(true);
+ // customize bullets
+ p2.setBulletFontColor(Color.red);
+ p2.setBulletFont("Wingdings");
+ p2.setBulletCharacter("\u0075");
+ p2.setIndentLevel(1);
+ XSLFTextRun r2 = p2.addNewTextRun();
+ r2.setText("Bullet2");
+
+ // the next three paragraphs form an auto-numbered list
+ XSLFTextParagraph p3 = shape.addNewTextParagraph();
+ p3.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 1);
+ p3.setIndentLevel(2);
+ XSLFTextRun r3 = p3.addNewTextRun();
+ r3.setText("Numbered List Item - 1");
+
+ XSLFTextParagraph p4 = shape.addNewTextParagraph();
+ p4.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 2);
+ p4.setIndentLevel(2);
+ XSLFTextRun r4 = p4.addNewTextRun();
+ r4.setText("Numbered List Item - 2");
+
+ XSLFTextParagraph p5 = shape.addNewTextParagraph();
+ p5.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 3);
+ p5.setIndentLevel(2);
+ XSLFTextRun r5 = p5.addNewTextRun();
+ r5.setText("Numbered List Item - 3");
+
+ shape.resizeToFitText();
+
+ try (FileOutputStream out = new FileOutputStream("list.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+10 languages with most speakers as first language\r
+countries,speakers,language\r
+58,315,العربية\r
+4,243,বাংলা\r
+38,1299,中文\r
+118,378,English\r
+4,260,हिन्दी\r
+2,128,日本語\r
+15,223,português\r
+6,119,ਪੰਜਾਬੀ\r
+18,154,Русский язык\r
+31,442,español\r
--- /dev/null
+My Chart\r
+First 1.0\r
+Second 3.0\r
+Third 4.0
\ No newline at end of file
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf.tutorial;
+
+import java.io.FileInputStream;
+
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+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.XSLFTextRun;
+import org.apache.poi.xslf.usermodel.XSLFTextShape;
+
+/**
+ * Reading a .pptx presentation and printing basic shape properties
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class Step1 {
+ private Step1() {}
+
+ public static void main(String[] args) throws Exception {
+ if(args.length == 0) {
+ System.out.println("Input file is required");
+ return;
+ }
+
+ FileInputStream fis = new FileInputStream(args[0]);
+ try (XMLSlideShow ppt = new XMLSlideShow(fis)) {
+ fis.close();
+
+ for (XSLFSlide slide : ppt.getSlides()) {
+ System.out.println("Title: " + slide.getTitle());
+
+ for (XSLFShape shape : slide.getShapes()) {
+ if (shape instanceof XSLFTextShape) {
+ XSLFTextShape tsh = (XSLFTextShape) shape;
+ for (XSLFTextParagraph p : tsh) {
+ System.out.println("Paragraph level: " + p.getIndentLevel());
+ for (XSLFTextRun r : p) {
+ System.out.println(r.getRawText());
+ System.out.println(" bold: " + r.isBold());
+ System.out.println(" italic: " + r.isItalic());
+ System.out.println(" underline: " + r.isUnderlined());
+ System.out.println(" font.family: " + r.getFontFamily());
+ System.out.println(" font.size: " + r.getFontSize());
+ System.out.println(" font.color: " + r.getFontColor());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xslf.tutorial;
+
+import java.io.FileOutputStream;
+
+import org.apache.poi.xslf.usermodel.SlideLayout;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
+import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
+import org.apache.poi.xslf.usermodel.XSLFTextShape;
+
+/**
+ * Create slides from pre-defined slide layouts
+ */
+public final class Step2 {
+ private Step2() {}
+
+ public static void main(String[] args) throws Exception{
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+
+ // first see what slide layouts are available by default
+ System.out.println("Available slide layouts:");
+ for (XSLFSlideMaster master : ppt.getSlideMasters()) {
+ for (XSLFSlideLayout layout : master.getSlideLayouts()) {
+ System.out.println(layout.getType());
+ }
+ }
+
+ // blank slide
+ /*XSLFSlide blankSlide =*/
+ ppt.createSlide();
+
+ XSLFSlideMaster defaultMaster = ppt.getSlideMasters().get(0);
+
+ // title slide
+ XSLFSlideLayout titleLayout = defaultMaster.getLayout(SlideLayout.TITLE);
+ XSLFSlide slide1 = ppt.createSlide(titleLayout);
+ XSLFTextShape title1 = slide1.getPlaceholder(0);
+ title1.setText("First Title");
+
+ // title and content
+ XSLFSlideLayout titleBodyLayout = defaultMaster.getLayout(SlideLayout.TITLE_AND_CONTENT);
+ XSLFSlide slide2 = ppt.createSlide(titleBodyLayout);
+
+ XSLFTextShape title2 = slide2.getPlaceholder(0);
+ title2.setText("Second Title");
+
+ XSLFTextShape body2 = slide2.getPlaceholder(1);
+ body2.clearText(); // unset any existing text
+ body2.addNewTextParagraph().addNewTextRun().setText("First paragraph");
+ body2.addNewTextParagraph().addNewTextRun().setText("Second paragraph");
+ body2.addNewTextParagraph().addNewTextRun().setText("Third paragraph");
+
+
+ try (FileOutputStream out = new FileOutputStream("step2.pptx")) {
+ ppt.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.eventusermodel;
+
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackageAccess;
+import org.apache.poi.util.XMLHelper;
+import org.apache.poi.xssf.eventusermodel.XSSFReader;
+import org.apache.poi.xssf.model.SharedStringsTable;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * XSSF and SAX (Event API) basic example.
+ * See {@link XLSX2CSV} for a fuller example of doing
+ * XSLX processing with the XSSF Event code.
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public class FromHowTo {
+ public void processFirstSheet(String filename) throws Exception {
+ try (OPCPackage pkg = OPCPackage.open(filename, PackageAccess.READ)) {
+ XSSFReader r = new XSSFReader(pkg);
+ SharedStringsTable sst = r.getSharedStringsTable();
+
+ XMLReader parser = fetchSheetParser(sst);
+
+ // process the first sheet
+ try (InputStream sheet = r.getSheetsData().next()) {
+ InputSource sheetSource = new InputSource(sheet);
+ parser.parse(sheetSource);
+ }
+ }
+ }
+
+ public void processAllSheets(String filename) throws Exception {
+ try (OPCPackage pkg = OPCPackage.open(filename, PackageAccess.READ)) {
+ XSSFReader r = new XSSFReader(pkg);
+ SharedStringsTable sst = r.getSharedStringsTable();
+
+ XMLReader parser = fetchSheetParser(sst);
+
+ Iterator<InputStream> sheets = r.getSheetsData();
+ while (sheets.hasNext()) {
+ System.out.println("Processing new sheet:\n");
+ try (InputStream sheet = sheets.next()) {
+ InputSource sheetSource = new InputSource(sheet);
+ parser.parse(sheetSource);
+ }
+ System.out.println();
+ }
+ }
+ }
+
+ public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException, ParserConfigurationException {
+ XMLReader parser = XMLHelper.newXMLReader();
+ ContentHandler handler = new SheetHandler(sst);
+ parser.setContentHandler(handler);
+ return parser;
+ }
+
+ /**
+ * See org.xml.sax.helpers.DefaultHandler javadocs
+ */
+ private static class SheetHandler extends DefaultHandler {
+ private final SharedStringsTable sst;
+ private String lastContents;
+ private boolean nextIsString;
+ private boolean inlineStr;
+ private final LruCache<Integer,String> lruCache = new LruCache<>(50);
+
+ private static class LruCache<A,B> extends LinkedHashMap<A, B> {
+ private final int maxEntries;
+
+ public LruCache(final int maxEntries) {
+ super(maxEntries + 1, 1.0f, true);
+ this.maxEntries = maxEntries;
+ }
+
+ @Override
+ protected boolean removeEldestEntry(final Map.Entry<A, B> eldest) {
+ return super.size() > maxEntries;
+ }
+ }
+
+ private SheetHandler(SharedStringsTable sst) {
+ this.sst = sst;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String name,
+ Attributes attributes) throws SAXException {
+ // c => cell
+ if(name.equals("c")) {
+ // Print the cell reference
+ System.out.print(attributes.getValue("r") + " - ");
+ // Figure out if the value is an index in the SST
+ String cellType = attributes.getValue("t");
+ nextIsString = cellType != null && cellType.equals("s");
+ inlineStr = cellType != null && cellType.equals("inlineStr");
+ }
+ // Clear contents cache
+ lastContents = "";
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String name)
+ throws SAXException {
+ // Process the last contents as required.
+ // Do now, as characters() may be called more than once
+ if(nextIsString) {
+ Integer idx = Integer.valueOf(lastContents);
+ lastContents = lruCache.get(idx);
+ if (lastContents == null && !lruCache.containsKey(idx)) {
+ lastContents = sst.getItemAt(idx).getString();
+ lruCache.put(idx, lastContents);
+ }
+ nextIsString = false;
+ }
+
+ // v => contents of a cell
+ // Output after we've seen the string contents
+ if(name.equals("v") || (inlineStr && name.equals("c"))) {
+ System.out.println(lastContents);
+ }
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException { // NOSONAR
+ lastContents += new String(ch, start, length);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ FromHowTo howto = new FromHowTo();
+ howto.processFirstSheet(args[0]);
+ howto.processAllSheets(args[0]);
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xssf.eventusermodel;
+
+import java.io.InputStream;
+
+import org.apache.poi.examples.xssf.usermodel.LoadPasswordProtectedXlsx;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.poifs.crypt.temp.AesZipFileZipEntrySource;
+import org.apache.poi.xssf.eventusermodel.XSSFReader;
+import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator;
+
+/**
+ * An example that loads a password protected workbook and counts the sheets.
+ * The example highlights how to do this in streaming way.
+ * <p><ul>
+ * <li>The example demonstrates that all temp files are removed.
+ * <li><code>AesZipFileZipEntrySource</code> is used to ensure that temp files are encrypted.
+ * </ul><p>
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class LoadPasswordProtectedXlsxStreaming {
+
+ private LoadPasswordProtectedXlsxStreaming() {}
+
+ public static void main(String[] args) throws Exception {
+ LoadPasswordProtectedXlsx.execute(args, LoadPasswordProtectedXlsxStreaming::printSheetCount);
+ }
+
+ private static void printSheetCount(final InputStream inputStream) throws Exception {
+ try (AesZipFileZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(inputStream);
+ OPCPackage pkg = OPCPackage.open(source)) {
+ XSSFReader reader = new XSSFReader(pkg);
+ SheetIterator iter = (SheetIterator)reader.getSheetsData();
+ int count = 0;
+ while(iter.hasNext()) {
+ iter.next();
+ count++;
+ }
+ System.out.println("sheet count: " + count);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.eventusermodel;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+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.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.util.CellAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.util.XMLHelper;
+import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
+import org.apache.poi.xssf.eventusermodel.XSSFReader;
+import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
+import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
+import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor;
+import org.apache.poi.xssf.model.SharedStrings;
+import org.apache.poi.xssf.model.Styles;
+import org.apache.poi.xssf.model.StylesTable;
+import org.apache.poi.xssf.usermodel.XSSFComment;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/**
+ * A rudimentary XLSX -> CSV processor modeled on the
+ * POI sample program XLS2CSVmra from the package
+ * org.apache.poi.hssf.eventusermodel.examples.
+ * As with the HSSF version, this tries to spot missing
+ * rows and cells, and output empty entries for them.
+ * <p>
+ * Data sheets are read using a SAX parser to keep the
+ * memory footprint relatively small, so this should be
+ * able to read enormous workbooks. The styles table and
+ * the shared-string table must be kept in memory. The
+ * standard POI styles table class is used, but a custom
+ * (read-only) class is used for the shared string table
+ * because the standard POI SharedStringsTable grows very
+ * quickly with the number of unique strings.
+ * <p>
+ * For a more advanced implementation of SAX event parsing
+ * of XLSX files, see {@link XSSFEventBasedExcelExtractor}
+ * and {@link XSSFSheetXMLHandler}. Note that for many cases,
+ * it may be possible to simply use those with a custom
+ * {@link SheetContentsHandler} and no SAX code needed of
+ * your own!
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public class XLSX2CSV {
+ /**
+ * Uses the XSSF Event SAX helpers to do most of the work
+ * of parsing the Sheet XML, and outputs the contents
+ * as a (basic) CSV.
+ */
+ private class SheetToCSV implements SheetContentsHandler {
+ private boolean firstCellOfRow;
+ private int currentRow = -1;
+ private int currentCol = -1;
+
+ private void outputMissingRows(int number) {
+ for (int i=0; i<number; i++) {
+ for (int j=0; j<minColumns; j++) {
+ output.append(',');
+ }
+ output.append('\n');
+ }
+ }
+
+ @Override
+ public void startRow(int rowNum) {
+ // If there were gaps, output the missing rows
+ outputMissingRows(rowNum-currentRow-1);
+ // Prepare for this row
+ firstCellOfRow = true;
+ currentRow = rowNum;
+ currentCol = -1;
+ }
+
+ @Override
+ public void endRow(int rowNum) {
+ // Ensure the minimum number of columns
+ for (int i=currentCol; i<minColumns; i++) {
+ output.append(',');
+ }
+ output.append('\n');
+ }
+
+ @Override
+ public void cell(String cellReference, String formattedValue,
+ XSSFComment comment) {
+ if (firstCellOfRow) {
+ firstCellOfRow = false;
+ } else {
+ output.append(',');
+ }
+
+ // gracefully handle missing CellRef here in a similar way as XSSFCell does
+ if(cellReference == null) {
+ cellReference = new CellAddress(currentRow, currentCol).formatAsString();
+ }
+
+ // Did we miss any cells?
+ int thisCol = (new CellReference(cellReference)).getCol();
+ int missedCols = thisCol - currentCol - 1;
+ for (int i=0; i<missedCols; i++) {
+ output.append(',');
+ }
+ currentCol = thisCol;
+
+ // Number or string?
+ try {
+ //noinspection ResultOfMethodCallIgnored
+ Double.parseDouble(formattedValue);
+ output.append(formattedValue);
+ } catch (NumberFormatException e) {
+ output.append('"');
+ output.append(formattedValue);
+ output.append('"');
+ }
+ }
+ }
+
+
+ ///////////////////////////////////////
+
+ private final OPCPackage xlsxPackage;
+
+ /**
+ * Number of columns to read starting with leftmost
+ */
+ private final int minColumns;
+
+ /**
+ * Destination for data
+ */
+ private final PrintStream output;
+
+ /**
+ * Creates a new XLSX -> CSV examples
+ *
+ * @param pkg The XLSX package to process
+ * @param output The PrintStream to output the CSV to
+ * @param minColumns The minimum number of columns to output, or -1 for no minimum
+ */
+ public XLSX2CSV(OPCPackage pkg, PrintStream output, int minColumns) {
+ this.xlsxPackage = pkg;
+ this.output = output;
+ this.minColumns = minColumns;
+ }
+
+ /**
+ * Parses and shows the content of one sheet
+ * using the specified styles and shared-strings tables.
+ *
+ * @param styles The table of styles that may be referenced by cells in the sheet
+ * @param strings The table of strings that may be referenced by cells in the sheet
+ * @param sheetInputStream The stream to read the sheet-data from.
+
+ * @exception java.io.IOException An IO exception from the parser,
+ * possibly from a byte stream or character stream
+ * supplied by the application.
+ * @throws SAXException if parsing the XML data fails.
+ */
+ public void processSheet(
+ Styles styles,
+ SharedStrings strings,
+ SheetContentsHandler sheetHandler,
+ InputStream sheetInputStream) throws IOException, SAXException {
+ DataFormatter formatter = new DataFormatter();
+ InputSource sheetSource = new InputSource(sheetInputStream);
+ try {
+ XMLReader sheetParser = XMLHelper.newXMLReader();
+ ContentHandler handler = new XSSFSheetXMLHandler(
+ styles, null, strings, sheetHandler, formatter, false);
+ sheetParser.setContentHandler(handler);
+ sheetParser.parse(sheetSource);
+ } catch(ParserConfigurationException e) {
+ throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
+ }
+ }
+
+ /**
+ * Initiates the processing of the XLS workbook file to CSV.
+ *
+ * @throws IOException If reading the data from the package fails.
+ * @throws SAXException if parsing the XML data fails.
+ */
+ public void process() throws IOException, OpenXML4JException, SAXException {
+ ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(this.xlsxPackage);
+ XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
+ StylesTable styles = xssfReader.getStylesTable();
+ XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
+ int index = 0;
+ while (iter.hasNext()) {
+ try (InputStream stream = iter.next()) {
+ String sheetName = iter.getSheetName();
+ this.output.println();
+ this.output.println(sheetName + " [index=" + index + "]:");
+ processSheet(styles, strings, new SheetToCSV(), stream);
+ }
+ ++index;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length < 1) {
+ System.err.println("Use:");
+ System.err.println(" XLSX2CSV <xlsx file> [min columns]");
+ return;
+ }
+
+ File xlsxFile = new File(args[0]);
+ if (!xlsxFile.exists()) {
+ System.err.println("Not found or not a file: " + xlsxFile.getPath());
+ return;
+ }
+
+ int minColumns = -1;
+ if (args.length >= 2)
+ minColumns = Integer.parseInt(args[1]);
+
+ // The package open is instantaneous, as it should be.
+ try (OPCPackage p = OPCPackage.open(xlsxFile.getPath(), PackageAccess.READ)) {
+ XLSX2CSV xlsx2csv = new XLSX2CSV(p, System.out, minColumns);
+ xlsx2csv.process();
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.streaming;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
+import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
+import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
+import org.apache.poi.xssf.usermodel.XSSFComment;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;
+import org.xml.sax.SAXException;
+
+/**
+ * This demonstrates how a hybrid approach to workbook read can be taken, using
+ * a mix of traditional XSSF and streaming one particular worksheet (perhaps one
+ * which is too big for the ordinary DOM parse).
+ */
+public class HybridStreaming {
+
+ private static final String SHEET_TO_STREAM = "large sheet";
+
+ public static void main(String[] args) throws IOException, SAXException {
+ try (InputStream sourceBytes = new FileInputStream("workbook.xlsx")) {
+ XSSFWorkbook workbook = new XSSFWorkbook(sourceBytes) {
+ /**
+ * Avoid DOM parse of large sheet
+ */
+ @Override
+ public void parseSheet(java.util.Map<String, XSSFSheet> shIdMap, CTSheet ctSheet) {
+ if (!SHEET_TO_STREAM.equals(ctSheet.getName())) {
+ super.parseSheet(shIdMap, ctSheet);
+ }
+ }
+ };
+
+ // Having avoided a DOM-based parse of the sheet, we can stream it instead.
+ ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(workbook.getPackage());
+ new XSSFSheetXMLHandler(workbook.getStylesSource(), strings, createSheetContentsHandler(), false);
+ workbook.close();
+ }
+ }
+
+ private static SheetContentsHandler createSheetContentsHandler() {
+ return new SheetContentsHandler() {
+
+ @Override
+ public void startRow(int rowNum) {
+ }
+
+ @Override
+ public void endRow(int rowNum) {
+ }
+
+ @Override
+ public void cell(String cellReference, String formattedValue, XSSFComment comment) {
+ }
+ };
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.streaming;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+
+public class Outlining {
+
+ public static void main(String[] args) throws IOException {
+ Outlining o = new Outlining();
+ o.collapseRow();
+ }
+
+ private void collapseRow() throws IOException {
+ try (SXSSFWorkbook wb2 = new SXSSFWorkbook(100)) {
+ SXSSFSheet sheet2 = wb2.createSheet("new sheet");
+
+ int rowCount = 20;
+ for (int i = 0; i < rowCount; i++) {
+ sheet2.createRow(i);
+ }
+
+ sheet2.groupRow(4, 9);
+ sheet2.groupRow(11, 19);
+
+ sheet2.setRowGroupCollapsed(4, true);
+
+ try (FileOutputStream fileOut = new FileOutputStream("outlining_collapsed.xlsx")) {
+ wb2.write(fileOut);
+ } finally {
+ wb2.dispose();
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xssf.streaming;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+
+import org.apache.poi.examples.util.TempFileUtils;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.EncryptionMode;
+import org.apache.poi.poifs.crypt.Encryptor;
+import org.apache.poi.poifs.crypt.temp.EncryptedTempData;
+import org.apache.poi.poifs.crypt.temp.SXSSFWorkbookWithCustomZipEntrySource;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFCell;
+import org.apache.poi.xssf.streaming.SXSSFRow;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+
+/**
+ * An example that outputs a simple generated workbook that is password protected.
+ * The example highlights how to do this in streaming way.
+ * <p><ul>
+ * <li>The example demonstrates that all temp files are removed.
+ * <li><code>SXSSFWorkbookWithCustomZipEntrySource</code> extends SXSSFWorkbook to ensure temp files are encrypted.
+ * </ul><p>
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class SavePasswordProtectedXlsx {
+
+ private SavePasswordProtectedXlsx() {}
+
+ public static void main(String[] args) throws Exception {
+ if(args.length != 2) {
+ throw new IllegalArgumentException("Expected 2 params: filename and password");
+ }
+ TempFileUtils.checkTempFiles();
+ String filename = args[0];
+ String password = args[1];
+ SXSSFWorkbookWithCustomZipEntrySource wb = new SXSSFWorkbookWithCustomZipEntrySource();
+ try {
+ for(int i = 0; i < 10; i++) {
+ SXSSFSheet sheet = wb.createSheet("Sheet" + i);
+ for(int r = 0; r < 1000; r++) {
+ SXSSFRow row = sheet.createRow(r);
+ for(int c = 0; c < 100; c++) {
+ SXSSFCell cell = row.createCell(c);
+ cell.setCellValue("abcd");
+ }
+ }
+ }
+ EncryptedTempData tempData = new EncryptedTempData();
+ try {
+ wb.write(tempData.getOutputStream());
+ save(tempData.getInputStream(), filename, password);
+ System.out.println("Saved " + filename);
+ } finally {
+ tempData.dispose();
+ }
+ } finally {
+ wb.close();
+ wb.dispose();
+ }
+ TempFileUtils.checkTempFiles();
+ }
+
+ public static void save(final InputStream inputStream, final String filename, final String pwd)
+ throws InvalidFormatException, IOException, GeneralSecurityException {
+
+ try (POIFSFileSystem fs = new POIFSFileSystem();
+ OPCPackage opc = OPCPackage.open(inputStream);
+ FileOutputStream fos = new FileOutputStream(filename)) {
+ EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
+ Encryptor enc = Encryptor.getInstance(info);
+ enc.confirmPassword(pwd);
+ opc.save(enc.getDataStream(fs));
+ fs.writeFilesystem(fos);
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTRowImpl;
+
+/**
+ * Shows how various alignment options work.
+ *
+ * Modified by Cristian Petrula, Romania on May 26, 2010
+ * New method was added centerAcrossSelection to center a column content over
+ * one selection using {@link HorizontalAlignment#CENTER_SELECTION}
+ * To create this method example was change for XSSF only and the previous
+ * AligningCells.java example has been moved into the SS examples folder.
+ */
+public class AligningCells {
+
+ public static void main(String[] args) throws IOException {
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+
+ XSSFSheet sheet = wb.createSheet();
+ XSSFRow row = sheet.createRow(2);
+ row.setHeightInPoints(30);
+ for (int i = 0; i < 8; i++) {
+ //column width is set in units of 1/256th of a character width
+ sheet.setColumnWidth(i, 256 * 15);
+ }
+
+ createCell(wb, row, 0, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
+ createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.BOTTOM);
+ createCell(wb, row, 2, HorizontalAlignment.FILL, VerticalAlignment.CENTER);
+ createCell(wb, row, 3, HorizontalAlignment.GENERAL, VerticalAlignment.CENTER);
+ createCell(wb, row, 4, HorizontalAlignment.JUSTIFY, VerticalAlignment.JUSTIFY);
+ createCell(wb, row, 5, HorizontalAlignment.LEFT, VerticalAlignment.TOP);
+ createCell(wb, row, 6, HorizontalAlignment.RIGHT, VerticalAlignment.TOP);
+
+ //center text over B4, C4, D4
+ row = sheet.createRow(3);
+ centerAcrossSelection(wb, row, 1, 3, VerticalAlignment.CENTER);
+
+ // Write the output to a file
+ try (OutputStream fileOut = new FileOutputStream("xssf-align.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ /**
+ * Creates a cell and aligns it a certain way.
+ *
+ * @param wb the workbook
+ * @param row the row to create the cell in
+ * @param column the column number to create the cell in
+ * @param halign the horizontal alignment for the cell.
+ */
+ private static void createCell(XSSFWorkbook wb, XSSFRow row, int column,
+ HorizontalAlignment halign, VerticalAlignment valign) {
+ CreationHelper ch = wb.getCreationHelper();
+ XSSFCell cell = row.createCell(column);
+ cell.setCellValue(ch.createRichTextString("Align It"));
+ CellStyle cellStyle = wb.createCellStyle();
+ cellStyle.setAlignment(halign);
+ cellStyle.setVerticalAlignment(valign);
+ cell.setCellStyle(cellStyle);
+ }
+
+ /**
+ * Center a text over multiple columns using ALIGN_CENTER_SELECTION
+ *
+ * @param wb the workbook
+ * @param row the row to create the cell in
+ * @param start_column the column number to create the cell in and where the selection starts
+ * @param end_column the column number where the selection ends
+ * @param valign the horizontal alignment for the cell.
+ */
+ private static void centerAcrossSelection(XSSFWorkbook wb, XSSFRow row,
+ int start_column, int end_column, VerticalAlignment valign) {
+ CreationHelper ch = wb.getCreationHelper();
+
+ // Create cell style with ALIGN_CENTER_SELECTION
+ XSSFCellStyle cellStyle = wb.createCellStyle();
+ cellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);
+ cellStyle.setVerticalAlignment(valign);
+
+ // Create cells over the selected area
+ for (int i = start_column; i <= end_column; i++) {
+ XSSFCell cell = row.createCell(i);
+ cell.setCellStyle(cellStyle);
+ }
+
+ // Set value to the first cell
+ XSSFCell cell = row.getCell(start_column);
+ cell.setCellValue(ch.createRichTextString("Align It"));
+
+ // Make the selection
+ CTRowImpl ctRow = (CTRowImpl) row.getCTRow();
+
+ // 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<>();
+ spanList.add(span);
+
+ //add spns to the row
+ ctRow.setSpans(spanList);
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.util.Random;
+
+import org.apache.poi.common.usermodel.fonts.FontGroup;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xddf.usermodel.PresetColor;
+import org.apache.poi.xddf.usermodel.XDDFColor;
+import org.apache.poi.xddf.usermodel.XDDFFillProperties;
+import org.apache.poi.xddf.usermodel.XDDFLineProperties;
+import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
+import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.ChartTypes;
+import org.apache.poi.xddf.usermodel.chart.LayoutMode;
+import org.apache.poi.xddf.usermodel.chart.LegendPosition;
+import org.apache.poi.xddf.usermodel.chart.MarkerStyle;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
+import org.apache.poi.xddf.usermodel.chart.XDDFCategoryDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFLineChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFManualLayout;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
+import org.apache.poi.xddf.usermodel.text.UnderlineType;
+import org.apache.poi.xddf.usermodel.text.XDDFFont;
+import org.apache.poi.xddf.usermodel.text.XDDFRunProperties;
+import org.apache.poi.xddf.usermodel.text.XDDFTextParagraph;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFChart;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+// original contributions by Axel Richter on https://stackoverflow.com/questions/47065690
+// additional title formatting from https://stackoverflow.com/questions/50418856
+// and legend positioning from https://stackoverflow.com/questions/49615379
+// this would probably be an answer for https://stackoverflow.com/questions/36447925 too
+public final class BarAndLineChart {
+
+ private static final int NUM_OF_ROWS = 7;
+ private static final Random RNG = new Random();
+
+ private BarAndLineChart() {}
+
+ public static void main(String[] args) throws Exception {
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet("Sheet1");
+
+ XSSFRow row = sheet.createRow(0);
+ row.createCell(0);
+ row.createCell(1).setCellValue("Bars");
+ row.createCell(2).setCellValue("Lines");
+
+ XSSFCell cell;
+ for (int r = 1; r < NUM_OF_ROWS; r++) {
+ row = sheet.createRow(r);
+ cell = row.createCell(0);
+ cell.setCellValue("C" + r);
+ cell = row.createCell(1);
+ cell.setCellValue(RNG.nextDouble());
+ cell = row.createCell(2);
+ cell.setCellValue(RNG.nextDouble() * 10);
+ }
+
+ XSSFDrawing drawing = sheet.createDrawingPatriarch();
+ XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 4, 0, 11, 15);
+
+ XSSFChart chart = drawing.createChart(anchor);
+ chart.setTitleText("This is my title");
+ chart.setTitleOverlay(true);
+ XDDFRunProperties properties = new XDDFRunProperties();
+ properties.setBold(true);
+ properties.setItalic(true);
+ properties.setUnderline(UnderlineType.DOT_DOT_DASH_HEAVY);
+ properties.setFontSize(22.5);
+ XDDFFont[] fonts = new XDDFFont[] {
+ new XDDFFont(FontGroup.LATIN, "Calibri", null, null, null),
+ new XDDFFont(FontGroup.COMPLEX_SCRIPT, "Liberation Sans", null, null, null)
+ };
+ properties.setFonts(fonts);
+ properties.setLineProperties(new XDDFLineProperties(
+ new XDDFSolidFillProperties(XDDFColor.from(PresetColor.SIENNA))));
+ XDDFTextParagraph paragraph = chart.getTitle().getBody().getParagraph(0);
+ paragraph.setDefaultRunProperties(properties);
+
+ // the data sources
+ XDDFCategoryDataSource xs = XDDFDataSourcesFactory.fromStringCellRange(sheet,
+ new CellRangeAddress(1, NUM_OF_ROWS - 1, 0, 0));
+ XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
+ new CellRangeAddress(1, NUM_OF_ROWS - 1, 1, 1));
+ XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
+ new CellRangeAddress(1, NUM_OF_ROWS - 1, 2, 2));
+
+ // cat axis 1 (bars)
+ XDDFCategoryAxis barCategories = chart.createCategoryAxis(AxisPosition.BOTTOM);
+
+ // val axis 1 (left)
+ XDDFValueAxis leftValues = chart.createValueAxis(AxisPosition.LEFT);
+ leftValues.crossAxis(barCategories);
+ barCategories.crossAxis(leftValues);
+
+ // cat axis 2 (lines)
+ XDDFCategoryAxis lineCategories = chart.createCategoryAxis(AxisPosition.BOTTOM);
+ lineCategories.setVisible(false); // this cat axis is deleted
+
+ // val axis 2 (right)
+ XDDFValueAxis rightValues = chart.createValueAxis(AxisPosition.RIGHT);
+ // this value axis crosses its category axis at max value
+ rightValues.setCrosses(AxisCrosses.MAX);
+ rightValues.crossAxis(lineCategories);
+ lineCategories.crossAxis(rightValues);
+
+ // the bar chart
+ XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, barCategories, leftValues);
+ XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(xs, ys1);
+ series1.setTitle(null, new CellReference(sheet.getSheetName(), 0, 1, true,true));
+ bar.setVaryColors(true);
+ bar.setBarDirection(BarDirection.COL);
+ chart.plot(bar);
+
+ // the line chart on secondary axis
+ XDDFLineChartData lines = (XDDFLineChartData) chart.createData(ChartTypes.LINE, lineCategories,
+ rightValues);
+
+ //uncomment below line if only primary axis required and comment above line
+ // the line chart on primary axis
+ /*XDDFLineChartData lines = (XDDFLineChartData) chart.createData(ChartTypes.LINE, lineCategories,
+ leftValues);*/
+
+
+ XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) lines.addSeries(xs, ys2);
+ series2.setTitle(null, new CellReference(sheet.getSheetName(), 0, 2, true, true));
+ series2.setSmooth(false);
+ series2.setMarkerStyle(MarkerStyle.DIAMOND);
+ series2.setMarkerSize((short)14);
+ lines.setVaryColors(true);
+ chart.plot(lines);
+
+ // some colors
+ XDDFFillProperties solidChartreuse = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHARTREUSE));
+ XDDFFillProperties solidTurquoise = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.TURQUOISE));
+ XDDFLineProperties solidLines = new XDDFLineProperties(solidTurquoise);
+ series1.setFillProperties(solidChartreuse);
+ series1.setLineProperties(solidLines); // bar border color different from fill
+ series2.setLineProperties(solidLines);
+
+ // legend
+ XDDFChartLegend legend = chart.getOrAddLegend();
+ legend.setPosition(LegendPosition.LEFT);
+ legend.setOverlay(false);
+ XDDFManualLayout layout = legend.getOrAddManualLayout();
+ layout.setXMode(LayoutMode.EDGE);
+ layout.setYMode(LayoutMode.EDGE);
+ layout.setX(0.00); //left edge of the chart
+ layout.setY(0.25); //25% of chart's height from top edge of the chart
+
+ try (FileOutputStream fileOut = new FileOutputStream("BarAndLineChart.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.PresetColor;
+import org.apache.poi.xddf.usermodel.XDDFColor;
+import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
+import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
+import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.ChartTypes;
+import org.apache.poi.xddf.usermodel.chart.LegendPosition;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
+import org.apache.poi.xssf.usermodel.XSSFChart;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Line chart example.
+ */
+public final class BarChart {
+ private BarChart() {}
+
+ public static void main(String[] args) throws IOException {
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet("barchart");
+ final int NUM_OF_ROWS = 3;
+ final int NUM_OF_COLUMNS = 10;
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ Row row;
+ Cell cell;
+ for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
+ row = sheet.createRow((short) rowIndex);
+ for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
+ cell = row.createCell((short) colIndex);
+ cell.setCellValue(colIndex * (rowIndex + 1.0));
+ }
+ }
+
+ XSSFDrawing drawing = sheet.createDrawingPatriarch();
+ XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
+
+ XSSFChart chart = drawing.createChart(anchor);
+ chart.setTitleText("x = 2x and x = 3x");
+ chart.setTitleOverlay(false);
+ XDDFChartLegend legend = chart.getOrAddLegend();
+ legend.setPosition(LegendPosition.TOP_RIGHT);
+
+ // Use a category axis for the bottom axis.
+ XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
+ bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
+ XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
+ leftAxis.setTitle("f(x)");
+ leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
+
+ XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
+ XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
+ XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
+
+ XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
+ XDDFChartData.Series series1 = data.addSeries(xs, ys1);
+ series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
+ XDDFChartData.Series series2 = data.addSeries(xs, ys2);
+ series2.setTitle("3x", null);
+ chart.plot(data);
+
+ // in order to transform a bar chart into a column chart, you just need to change the bar direction
+ XDDFBarChartData bar = (XDDFBarChartData) data;
+ bar.setBarDirection(BarDirection.COL);
+ // looking for "Stacked Bar Chart"? uncomment the following line
+ // bar.setBarGrouping(BarGrouping.STACKED);
+
+ solidFillSeries(data, 0, PresetColor.CHARTREUSE);
+ solidFillSeries(data, 1, PresetColor.TURQUOISE);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml-bar-chart.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ private static void solidFillSeries(XDDFChartData data, int index, PresetColor color) {
+ XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
+ XDDFChartData.Series series = data.getSeries().get(index);
+ XDDFShapeProperties properties = series.getShapeProperties();
+ if (properties == null) {
+ properties = new XDDFShapeProperties();
+ }
+ properties.setFillProperties(fill);
+ series.setShapeProperties(properties);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Calendar;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.poi.openxml4j.opc.internal.ZipHelper;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFDataFormat;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates a workaround you can use to generate large workbooks and avoid OutOfMemory exception.
+ *
+ * Note - You probably <em>don't want to use this approach any more</em>! POI
+ * now includes the SXSSF which handles all of this for you, you should
+ * be using that instead! This code remains mostly for historical interest.
+ * <p>
+ * See <a "https://poi.apache.org/spreadsheet/how-to.html#sxssf">
+ * https://poi.apache.org/spreadsheet/how-to.html#sxssf</a>.
+ * <p>
+ * If you really want to use this approach, which is also the one that SXSSF
+ * does for you, it works as follows:
+ *
+ * 1. create a template workbook, create sheets and global objects such as cell styles, number formats, etc.
+ * 2. create an application that streams data in a text file
+ * 3. Substitute the sheet in the template with the generated data
+ *
+ * <p>
+ * Since 3.8 POI provides a low-memory footprint SXSSF API, which implements
+ * ths "BigGridDemo" strategy. SXSSF is an API-compatible streaming extension
+ * of XSSF to be used when very large spreadsheets have to be produced, and
+ * heap space is limited. SXSSF achieves its low memory footprint by limiting
+ * access to the rows that are within a sliding window, while XSSF gives access
+ * to all rows in the document. Older rows that are no longer in the window
+ * become inaccessible, as they are written to the disk.
+ * </p>
+ * See <a "https://poi.apache.org/spreadsheet/how-to.html#sxssf">
+ * https://poi.apache.org/spreadsheet/how-to.html#sxssf</a>.
+ */
+public final class BigGridDemo {
+ private static final String XML_ENCODING = "UTF-8";
+
+ private static final Random rnd = new Random();
+
+ private BigGridDemo() {}
+
+ public static void main(String[] args) throws Exception {
+
+ // Step 1. Create a template file. Setup sheets and workbook-level objects such as
+ // cell styles, number formats, etc.
+
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet("Big Grid");
+
+ Map<String, XSSFCellStyle> styles = createStyles(wb);
+ //name of the zip entry holding sheet data, e.g. /xl/worksheets/sheet1.xml
+ String sheetRef = sheet.getPackagePart().getPartName().getName();
+
+ //save the template
+ try (FileOutputStream os = new FileOutputStream("template.xlsx")) {
+ wb.write(os);
+ }
+
+ //Step 2. Generate XML file.
+ File tmp = File.createTempFile("sheet", ".xml");
+ try (
+ FileOutputStream stream = new FileOutputStream(tmp);
+ Writer fw = new OutputStreamWriter(stream, XML_ENCODING)
+ ) {
+ generate(fw, styles);
+ }
+
+ //Step 3. Substitute the template entry with the generated data
+ try (FileOutputStream out = new FileOutputStream("big-grid.xlsx")) {
+ substitute(new File("template.xlsx"), tmp, sheetRef.substring(1), out);
+ }
+ }
+ }
+
+ /**
+ * Create a library of cell styles.
+ */
+ private static Map<String, XSSFCellStyle> createStyles(XSSFWorkbook wb){
+ Map<String, XSSFCellStyle> styles = new HashMap<>();
+ XSSFDataFormat fmt = wb.createDataFormat();
+
+ XSSFCellStyle style1 = wb.createCellStyle();
+ style1.setAlignment(HorizontalAlignment.RIGHT);
+ style1.setDataFormat(fmt.getFormat("0.0%"));
+ styles.put("percent", style1);
+
+ XSSFCellStyle style2 = wb.createCellStyle();
+ style2.setAlignment(HorizontalAlignment.CENTER);
+ style2.setDataFormat(fmt.getFormat("0.0X"));
+ styles.put("coeff", style2);
+
+ XSSFCellStyle style3 = wb.createCellStyle();
+ style3.setAlignment(HorizontalAlignment.RIGHT);
+ style3.setDataFormat(fmt.getFormat("$#,##0.00"));
+ styles.put("currency", style3);
+
+ XSSFCellStyle style4 = wb.createCellStyle();
+ style4.setAlignment(HorizontalAlignment.RIGHT);
+ style4.setDataFormat(fmt.getFormat("mmm dd"));
+ styles.put("date", style4);
+
+ XSSFCellStyle style5 = wb.createCellStyle();
+ XSSFFont headerFont = wb.createFont();
+ headerFont.setBold(true);
+ style5.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ style5.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style5.setFont(headerFont);
+ styles.put("header", style5);
+
+ return styles;
+ }
+
+ private static void generate(Writer out, Map<String, XSSFCellStyle> styles) throws Exception {
+
+ Calendar calendar = Calendar.getInstance();
+
+ SpreadsheetWriter sw = new SpreadsheetWriter(out);
+ sw.beginSheet();
+
+ //insert header row
+ sw.insertRow(0);
+ int styleIndex = styles.get("header").getIndex();
+ sw.createCell(0, "Title", styleIndex);
+ sw.createCell(1, "% Change", styleIndex);
+ sw.createCell(2, "Ratio", styleIndex);
+ sw.createCell(3, "Expenses", styleIndex);
+ sw.createCell(4, "Date", styleIndex);
+
+ sw.endRow();
+
+ //write data rows
+ for (int rownum = 1; rownum < 100000; rownum++) {
+ sw.insertRow(rownum);
+
+ sw.createCell(0, "Hello, " + rownum + "!");
+ sw.createCell(1, (double)rnd.nextInt(100)/100, styles.get("percent").getIndex());
+ sw.createCell(2, (double)rnd.nextInt(10)/10, styles.get("coeff").getIndex());
+ sw.createCell(3, rnd.nextInt(10000), styles.get("currency").getIndex());
+ sw.createCell(4, calendar, styles.get("date").getIndex());
+
+ sw.endRow();
+
+ calendar.roll(Calendar.DAY_OF_YEAR, 1);
+ }
+ sw.endSheet();
+ }
+
+ /**
+ *
+ * @param zipfile the template file
+ * @param tmpfile the XML file with the sheet data
+ * @param entry the name of the sheet entry to substitute, e.g. xl/worksheets/sheet1.xml
+ * @param out the stream to write the result to
+ */
+ private static void substitute(File zipfile, File tmpfile, String entry, OutputStream out) throws IOException {
+ try (ZipFile zip = ZipHelper.openZipFile(zipfile)) {
+ try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(out)) {
+ Enumeration<? extends ZipArchiveEntry> en = zip.getEntries();
+ while (en.hasMoreElements()) {
+ ZipArchiveEntry ze = en.nextElement();
+ if (!ze.getName().equals(entry)) {
+ zos.putArchiveEntry(new ZipArchiveEntry(ze.getName()));
+ try (InputStream is = zip.getInputStream(ze)) {
+ copyStream(is, zos);
+ }
+ zos.closeArchiveEntry();
+ }
+ }
+ zos.putArchiveEntry(new ZipArchiveEntry(entry));
+ try (InputStream is = new FileInputStream(tmpfile)) {
+ copyStream(is, zos);
+ }
+ zos.closeArchiveEntry();
+ }
+ }
+ }
+
+ private static void copyStream(InputStream in, OutputStream out) throws IOException {
+ byte[] chunk = new byte[1024];
+ int count;
+ while ((count = in.read(chunk)) >=0 ) {
+ out.write(chunk,0,count);
+ }
+ }
+
+ /**
+ * Writes spreadsheet data in a Writer.
+ * (YK: in future it may evolve in a full-featured API for streaming data in Excel)
+ */
+ public static class SpreadsheetWriter {
+ private final Writer _out;
+ private int _rownum;
+
+ SpreadsheetWriter(Writer out){
+ _out = out;
+ }
+
+ void beginSheet() throws IOException {
+ _out.write("<?xml version=\"1.0\" encoding=\""+XML_ENCODING+"\"?>" +
+ "<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">" );
+ _out.write("<sheetData>\n");
+ }
+
+ void endSheet() throws IOException {
+ _out.write("</sheetData>");
+ _out.write("</worksheet>");
+ }
+
+ /**
+ * Insert a new row
+ *
+ * @param rownum 0-based row number
+ */
+ void insertRow(int rownum) throws IOException {
+ _out.write("<row r=\""+(rownum+1)+"\">\n");
+ this._rownum = rownum;
+ }
+
+ /**
+ * Insert row end marker
+ */
+ void endRow() throws IOException {
+ _out.write("</row>\n");
+ }
+
+ public void createCell(int columnIndex, String value, int styleIndex) throws IOException {
+ String ref = new CellReference(_rownum, columnIndex).formatAsString();
+ _out.write("<c r=\""+ref+"\" t=\"inlineStr\"");
+ if(styleIndex != -1) {
+ _out.write(" s=\""+styleIndex+"\"");
+ }
+ _out.write(">");
+ _out.write("<is><t>"+value+"</t></is>");
+ _out.write("</c>");
+ }
+
+ public void createCell(int columnIndex, String value) throws IOException {
+ createCell(columnIndex, value, -1);
+ }
+
+ public void createCell(int columnIndex, double value, int styleIndex) throws IOException {
+ String ref = new CellReference(_rownum, columnIndex).formatAsString();
+ _out.write("<c r=\""+ref+"\" t=\"n\"");
+ if(styleIndex != -1) {
+ _out.write(" s=\""+styleIndex+"\"");
+ }
+ _out.write(">");
+ _out.write("<v>"+value+"</v>");
+ _out.write("</c>");
+ }
+
+ public void createCell(int columnIndex, double value) throws IOException {
+ createCell(columnIndex, value, -1);
+ }
+
+ public void createCell(int columnIndex, Calendar value, int styleIndex) throws IOException {
+ createCell(columnIndex, DateUtil.getExcelDate(value, false), styleIndex);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.PrintOrientation;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFPrintSetup;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * A monthly calendar created using Apache POI. Each month is on a separate sheet.
+ * This is a version of org.apache.poi.ss.examples.CalendarDemo that demonstrates
+ * some XSSF features not avaiable when using common HSSF-XSSF interfaces.
+ *
+ * <pre>
+ * Usage:
+ * CalendarDemo <year>
+ * </pre>
+ *
+ * @author Yegor Kozlov
+ */
+public class CalendarDemo {
+
+ private static final String[] days = {
+ "Sunday", "Monday", "Tuesday",
+ "Wednesday", "Thursday", "Friday", "Saturday"};
+
+ private static final String[] months = {
+ "January", "February", "March","April", "May", "June","July", "August",
+ "September","October", "November", "December"};
+
+ public static void main(String[] args) throws Exception {
+
+ Calendar calendar = Calendar.getInstance();
+ if(args.length > 0) calendar.set(Calendar.YEAR, Integer.parseInt(args[0]));
+
+ int year = calendar.get(Calendar.YEAR);
+
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ Map<String, XSSFCellStyle> styles = createStyles(wb);
+
+ for (int month = 0; month < 12; month++) {
+ calendar.set(Calendar.MONTH, month);
+ calendar.set(Calendar.DAY_OF_MONTH, 1);
+ //create a sheet for each month
+ XSSFSheet sheet = wb.createSheet(months[month]);
+
+ //turn off gridlines
+ sheet.setDisplayGridlines(false);
+ sheet.setPrintGridlines(false);
+ XSSFPrintSetup printSetup = sheet.getPrintSetup();
+ printSetup.setOrientation(PrintOrientation.LANDSCAPE);
+ sheet.setFitToPage(true);
+ sheet.setHorizontallyCenter(true);
+
+ //the header row: centered text in 48pt font
+ XSSFRow headerRow = sheet.createRow(0);
+ headerRow.setHeightInPoints(80);
+ XSSFCell titleCell = headerRow.createCell(0);
+ titleCell.setCellValue(months[month] + " " + year);
+ titleCell.setCellStyle(styles.get("title"));
+ sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$N$1"));
+
+ //header with month titles
+ XSSFRow monthRow = sheet.createRow(1);
+ for (int i = 0; i < days.length; i++) {
+ //for compatibility with HSSF we have to set column width in units of 1/256th of a character width
+ sheet.setColumnWidth(i * 2, 5 * 256); //the column is 5 characters wide
+ sheet.setColumnWidth(i * 2 + 1, 13 * 256); //the column is 13 characters wide
+ sheet.addMergedRegion(new CellRangeAddress(1, 1, i * 2, i * 2 + 1));
+ XSSFCell monthCell = monthRow.createCell(i * 2);
+ monthCell.setCellValue(days[i]);
+ monthCell.setCellStyle(styles.get("month"));
+ }
+
+ int cnt = 1, day = 1;
+ int rownum = 2;
+ for (int j = 0; j < 6; j++) {
+ XSSFRow row = sheet.createRow(rownum++);
+ row.setHeightInPoints(100);
+ for (int i = 0; i < days.length; i++) {
+ XSSFCell dayCell_1 = row.createCell(i * 2);
+ XSSFCell dayCell_2 = row.createCell(i * 2 + 1);
+
+ int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
+ if (cnt >= day_of_week && calendar.get(Calendar.MONTH) == month) {
+ dayCell_1.setCellValue(day);
+ calendar.set(Calendar.DAY_OF_MONTH, ++day);
+
+ if (i == 0 || i == days.length - 1) {
+ dayCell_1.setCellStyle(styles.get("weekend_left"));
+ dayCell_2.setCellStyle(styles.get("weekend_right"));
+ } else {
+ dayCell_1.setCellStyle(styles.get("workday_left"));
+ dayCell_2.setCellStyle(styles.get("workday_right"));
+ }
+ } else {
+ dayCell_1.setCellStyle(styles.get("grey_left"));
+ dayCell_2.setCellStyle(styles.get("grey_right"));
+ }
+ cnt++;
+ }
+ if (calendar.get(Calendar.MONTH) > month) break;
+ }
+ }
+
+ // Write the output to a file
+ try (FileOutputStream out = new FileOutputStream("calendar-" + year + ".xlsx")) {
+ wb.write(out);
+ }
+
+ }
+ }
+
+ /**
+ * cell styles used for formatting calendar sheets
+ */
+ private static Map<String, XSSFCellStyle> createStyles(XSSFWorkbook wb){
+ Map<String, XSSFCellStyle> styles = new HashMap<>();
+
+ XSSFCellStyle style;
+ XSSFFont titleFont = wb.createFont();
+ titleFont.setFontHeightInPoints((short)48);
+ titleFont.setColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFont(titleFont);
+ styles.put("title", style);
+
+ XSSFFont monthFont = wb.createFont();
+ monthFont.setFontHeightInPoints((short)12);
+ monthFont.setColor(new XSSFColor(new java.awt.Color(255, 255, 255), wb.getStylesSource().getIndexedColors()));
+ monthFont.setBold(true);
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFillForegroundColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFont(monthFont);
+ styles.put("month", style);
+
+ XSSFFont dayFont = wb.createFont();
+ dayFont.setFontHeightInPoints((short)14);
+ dayFont.setBold(true);
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setVerticalAlignment(VerticalAlignment.TOP);
+ style.setFillForegroundColor(new XSSFColor(new java.awt.Color(228, 232, 243), wb.getStylesSource().getIndexedColors()));
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style.setFont(dayFont);
+ styles.put("weekend_left", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.TOP);
+ style.setFillForegroundColor(new XSSFColor(new java.awt.Color(228, 232, 243), wb.getStylesSource().getIndexedColors()));
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ styles.put("weekend_right", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.LEFT);
+ style.setVerticalAlignment(VerticalAlignment.TOP);
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 255, 255), wb.getStylesSource().getIndexedColors()));
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setLeftBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style.setFont(dayFont);
+ styles.put("workday_left", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.TOP);
+ style.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 255, 255), wb.getStylesSource().getIndexedColors()));
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ styles.put("workday_right", style);
+
+ style = wb.createCellStyle();
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setFillForegroundColor(new XSSFColor(new java.awt.Color(234, 234, 234), wb.getStylesSource().getIndexedColors()));
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ styles.put("grey_left", style);
+
+ style = wb.createCellStyle();
+ style.setFillForegroundColor(new XSSFColor(new java.awt.Color(234, 234, 234), wb.getStylesSource().getIndexedColors()));
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
+ styles.put("grey_right", style);
+
+ return styles;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.Comment;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.RichTextString;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates how to work with excel cell comments.
+ *
+ * <p>
+ * Excel comment is a kind of a text shape,
+ * so inserting a comment is very similar to placing a text box in a worksheet
+ * </p>
+ *
+ * @author Yegor Kozlov
+ */
+public class CellComments {
+ public static void main(String[] args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) {
+
+ CreationHelper factory = wb.getCreationHelper();
+
+ Sheet sheet = wb.createSheet();
+
+ Cell cell1 = sheet.createRow(3).createCell(5);
+ cell1.setCellValue("F4");
+
+ Drawing<?> drawing = sheet.createDrawingPatriarch();
+
+ ClientAnchor anchor = factory.createClientAnchor();
+
+ Comment comment1 = drawing.createCellComment(anchor);
+ RichTextString str1 = factory.createRichTextString("Hello, World!");
+ comment1.setString(str1);
+ comment1.setAuthor("Apache POI");
+ cell1.setCellComment(comment1);
+
+ Cell cell2 = sheet.createRow(2).createCell(2);
+ cell2.setCellValue("C3");
+
+ Comment comment2 = drawing.createCellComment(anchor);
+ RichTextString str2 = factory.createRichTextString("XSSF can set cell comments");
+ //apply custom font to the text in the comment
+ Font font = wb.createFont();
+ font.setFontName("Arial");
+ font.setFontHeightInPoints((short) 14);
+ font.setBold(true);
+ font.setColor(IndexedColors.RED.getIndex());
+ str2.applyFont(font);
+
+ comment2.setString(str2);
+ comment2.setAuthor("Apache POI");
+ comment2.setAddress(new CellAddress("C3"));
+
+ try (FileOutputStream out = new FileOutputStream("comments.xlsx")) {
+ wb.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.RichTextString;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Illustrates how to create cell and set values of different types.
+ */
+public class CreateCell {
+
+ public static void main(String[] args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ CreationHelper creationHelper = wb.getCreationHelper();
+ Sheet sheet = wb.createSheet("new sheet");
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ Row row = sheet.createRow((short) 0);
+ // Create a cell and put a value in it.
+ Cell cell = row.createCell((short) 0);
+ cell.setCellValue(1);
+
+ //numeric value
+ row.createCell(1).setCellValue(1.2);
+
+ //plain string value
+ row.createCell(2).setCellValue("This is a string cell");
+
+ //rich text string
+ RichTextString str = creationHelper.createRichTextString("Apache");
+ Font font = wb.createFont();
+ font.setItalic(true);
+ font.setUnderline(Font.U_SINGLE);
+ str.applyFont(font);
+ row.createCell(3).setCellValue(str);
+
+ //boolean value
+ row.createCell(4).setCellValue(true);
+
+ //formula
+ row.createCell(5).setCellFormula("SUM(A1:B1)");
+
+ //date
+ CellStyle style = wb.createCellStyle();
+ style.setDataFormat(creationHelper.createDataFormat().getFormat("m/d/yy h:mm"));
+ cell = row.createCell(6);
+ cell.setCellValue(new Date());
+ cell.setCellStyle(style);
+
+ //hyperlink
+ row.createCell(7).setCellFormula("SUM(A1:B1)");
+ cell.setCellFormula("HYPERLINK(\"http://google.com\",\"Google\")");
+
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml-cell.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DataConsolidateFunction;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFPivotTable;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public class CreatePivotTable {
+
+ public static void main(String[] args) throws FileNotFoundException, IOException, InvalidFormatException {
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet();
+
+ //Create some data to build the pivot table on
+ setCellData(sheet);
+
+ AreaReference source = new AreaReference("A1:D4", SpreadsheetVersion.EXCEL2007);
+ CellReference position = new CellReference("H5");
+ // Create a pivot table on this sheet, with H5 as the top-left cell..
+ // The pivot table's data source is on the same sheet in A1:D4
+ XSSFPivotTable pivotTable = sheet.createPivotTable(source, position);
+ //Configure the pivot table
+ //Use first column as row label
+ pivotTable.addRowLabel(0);
+ //Sum up the second column
+ pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1);
+ //Set the third column as filter
+ pivotTable.addColumnLabel(DataConsolidateFunction.AVERAGE, 2);
+ //Add filter on forth column
+ pivotTable.addReportFilter(3);
+
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml-pivottable.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ public static void setCellData(XSSFSheet sheet){
+ Row row1 = sheet.createRow(0);
+ // Create a cell and put a value in it.
+ Cell cell11 = row1.createCell(0);
+ cell11.setCellValue("Names");
+ Cell cell12 = row1.createCell(1);
+ cell12.setCellValue("#");
+ Cell cell13 = row1.createCell(2);
+ cell13.setCellValue("%");
+ Cell cell14 = row1.createCell(3);
+ cell14.setCellValue("Human");
+
+ Row row2 = sheet.createRow(1);
+ Cell cell21 = row2.createCell(0);
+ cell21.setCellValue("Jane");
+ Cell cell22 = row2.createCell(1);
+ cell22.setCellValue(10);
+ Cell cell23 = row2.createCell(2);
+ cell23.setCellValue(100);
+ Cell cell24 = row2.createCell(3);
+ cell24.setCellValue("Yes");
+
+ Row row3 = sheet.createRow(2);
+ Cell cell31 = row3.createCell(0);
+ cell31.setCellValue("Tarzan");
+ Cell cell32 = row3.createCell(1);
+ cell32.setCellValue(5);
+ Cell cell33 = row3.createCell(2);
+ cell33.setCellValue(90);
+ Cell cell34 = row3.createCell(3);
+ cell34.setCellValue("Yes");
+
+ Row row4 = sheet.createRow(3);
+ Cell cell41 = row4.createCell(0);
+ cell41.setCellValue("Terk");
+ Cell cell42 = row4.createCell(1);
+ cell42.setCellValue(10);
+ Cell cell43 = row4.createCell(2);
+ cell43.setCellValue(90);
+ Cell cell44 = row4.createCell(3);
+ cell44.setCellValue("No");
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.DataConsolidateFunction;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFPivotTable;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public class CreatePivotTable2 {
+
+ public static void main(String[] args) throws FileNotFoundException, IOException, InvalidFormatException {
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet();
+
+ //Create some data to build the pivot table on
+ setCellData(sheet);
+
+ AreaReference source = new AreaReference("A1:E7", SpreadsheetVersion.EXCEL2007);
+ CellReference position = new CellReference("H1");
+ // Create a pivot table on this sheet, with H1 as the top-left cell..
+ // The pivot table's data source is on the same sheet in A1:E7
+ XSSFPivotTable pivotTable = sheet.createPivotTable(source, position);
+ //Configure the pivot table
+ //Use first column as row label
+ pivotTable.addRowLabel(0);
+ //Sum up the second column with column title and data format
+ pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1, "Values", "#,##0.00");
+ //Use third column (month) as columns (side by side)
+ pivotTable.addColLabel(3, "DD.MM.YYYY");
+
+ //Add filter on forth column
+ pivotTable.addReportFilter(4);
+
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml-pivottable2.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ public static void setCellData(XSSFSheet sheet){
+ Calendar cal1 = Calendar.getInstance();
+ cal1.set(2017, 0, 1, 0, 0, 0);
+ Calendar cal2 = Calendar.getInstance();
+ cal2.set(2017, 1, 1, 0, 0, 0);
+ Row row1 = sheet.createRow(0);
+ // Create a cell and put a value in it.
+ // first row are column titles
+ Cell cell11 = row1.createCell(0);
+ cell11.setCellValue("Names");
+ Cell cell12 = row1.createCell(1);
+ cell12.setCellValue("Values");
+ Cell cell13 = row1.createCell(2);
+ cell13.setCellValue("%");
+ Cell cell14 = row1.createCell(3);
+ cell14.setCellValue("Month");
+ Cell cell15 = row1.createCell(4);
+ cell15.setCellValue("No");
+
+ CellStyle csDbl = sheet.getWorkbook().createCellStyle();
+ DataFormat dfDbl = sheet.getWorkbook().createDataFormat();
+ csDbl.setDataFormat(dfDbl.getFormat("#,##0.00"));
+
+ CellStyle csDt = sheet.getWorkbook().createCellStyle();
+ DataFormat dfDt = sheet.getWorkbook().createDataFormat();
+ csDt.setDataFormat(dfDt.getFormat("dd/MM/yyyy"));
+ // data
+ setDataRow(sheet, 1, "Jane", 1120.5, 100, cal1.getTime(), 1, csDbl, csDt);
+ setDataRow(sheet, 2, "Jane", 1453.2, 95, cal2.getTime(), 2, csDbl, csDt);
+
+ setDataRow(sheet, 3, "Tarzan", 1869.8, 88, cal1.getTime(), 1, csDbl, csDt);
+ setDataRow(sheet, 4, "Tarzan", 1536.2, 92, cal2.getTime(), 2, csDbl, csDt);
+
+ setDataRow(sheet, 5, "Terk", 1624.1, 75, cal1.getTime(), 1, csDbl, csDt);
+ setDataRow(sheet, 6, "Terk", 1569.3, 82, cal2.getTime(), 2, csDbl, csDt);
+ sheet.autoSizeColumn(3);
+ }
+
+ public static void setDataRow(XSSFSheet sheet, int rowNum, String name, double v1, int v2, Date dt, int no, CellStyle csDbl, CellStyle csDt){
+ Row row = sheet.createRow(rowNum);
+ // set the values for one row
+ Cell c1 = row.createCell(0);
+ c1.setCellValue(name);
+ Cell c2 = row.createCell(1);
+ c2.setCellValue(v1);
+ c2.setCellStyle(csDbl);
+ Cell c3 = row.createCell(2);
+ c3.setCellValue(v2);
+ Cell c4 = row.createCell(3);
+ c4.setCellValue(dt);
+ c4.setCellStyle(csDt);
+ Cell c5 = row.createCell(4);
+ c5.setCellValue(no);
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFTable;
+import org.apache.poi.xssf.usermodel.XSSFTableStyleInfo;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates how to create a simple table using Apache POI.
+ */
+public class CreateTable {
+
+ public static void main(String[] args) throws IOException {
+
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet();
+
+ // Set which area the table should be placed in
+ AreaReference reference = wb.getCreationHelper().createAreaReference(
+ new CellReference(0, 0), new CellReference(2, 2));
+
+ // Create
+ XSSFTable table = sheet.createTable(reference);
+ table.setName("Test");
+ table.setDisplayName("Test_Table");
+
+ // For now, create the initial style in a low-level way
+ table.getCTTable().addNewTableStyleInfo();
+ table.getCTTable().getTableStyleInfo().setName("TableStyleMedium2");
+
+ // Style the table
+ XSSFTableStyleInfo style = (XSSFTableStyleInfo) table.getStyle();
+ style.setName("TableStyleMedium2");
+ style.setShowColumnStripes(false);
+ style.setShowRowStripes(true);
+ style.setFirstColumn(false);
+ style.setLastColumn(false);
+ style.setShowRowStripes(true);
+ style.setShowColumnStripes(true);
+
+ // Set the values for the table
+ XSSFRow row;
+ XSSFCell cell;
+ for (int i = 0; i < 3; i++) {
+ // Create row
+ row = sheet.createRow(i);
+ for (int j = 0; j < 3; j++) {
+ // Create cell
+ cell = row.createCell(j);
+ if (i == 0) {
+ cell.setCellValue("Column" + (j + 1));
+ } else {
+ cell.setCellValue((i + 1.0) * (j + 1.0));
+ }
+ }
+ }
+
+ // Save
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml-table.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * How to set user-defined date formats
+ */
+public class CreateUserDefinedDataFormats {
+
+
+ public static void main(String[]args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet("format sheet");
+ CellStyle style;
+ DataFormat format = wb.createDataFormat();
+ Row row;
+ Cell cell;
+ short rowNum = 0;
+ short colNum = 0;
+
+ row = sheet.createRow(rowNum);
+ cell = row.createCell(colNum);
+ cell.setCellValue(11111.25);
+ style = wb.createCellStyle();
+ style.setDataFormat(format.getFormat("0.0"));
+ cell.setCellStyle(style);
+
+ row = sheet.createRow(++rowNum);
+ cell = row.createCell(colNum);
+ cell.setCellValue(11111.25);
+ style = wb.createCellStyle();
+ style.setDataFormat(format.getFormat("#,##0.0000"));
+ cell.setCellStyle(style);
+
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml_dataFormat.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.ByteArrayOutputStream;
+
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.xssf.extractor.XSSFExportToXml;
+import org.apache.poi.xssf.usermodel.XSSFMap;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Print all custom XML mappings registered in the given workbook
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class CustomXMLMapping {
+
+ private CustomXMLMapping() {}
+
+ public static void main(String[] args) throws Exception {
+ try (OPCPackage pkg = OPCPackage.open(args[0]);
+ XSSFWorkbook wb = new XSSFWorkbook(pkg)) {
+ for (XSSFMap map : wb.getCustomXMLMappings()) {
+ XSSFExportToXml exporter = new XSSFExportToXml(map);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ exporter.exportToXML(os, true);
+ String xml = os.toString("UTF-8");
+ System.out.println(xml);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.Closeable;
+import java.io.InputStream;
+
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+
+/**
+ * Demonstrates how you can extract embedded data from a .xlsx file
+ */
+public class EmbeddedObjects {
+ public static void main(String[] args) throws Exception {
+ try (XSSFWorkbook workbook = new XSSFWorkbook(args[0])) {
+ for (PackagePart pPart : workbook.getAllEmbeddedParts()) {
+ String contentType = pPart.getContentType();
+ try (InputStream is = pPart.getInputStream()) {
+ Closeable document;
+ if (contentType.equals("application/vnd.ms-excel")) {
+ // Excel Workbook - either binary or OpenXML
+ document = new HSSFWorkbook(is);
+ } else if (contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
+ // Excel Workbook - OpenXML file format
+ document = new XSSFWorkbook(is);
+ } else if (contentType.equals("application/msword")) {
+ // Word Document - binary (OLE2CDF) file format
+ document = new HWPFDocument(is);
+ } else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
+ // Word Document - OpenXML file format
+ document = new XWPFDocument(is);
+ } else if (contentType.equals("application/vnd.ms-powerpoint")) {
+ // PowerPoint Document - binary file format
+ document = new HSLFSlideShow(is);
+ } else if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) {
+ // PowerPoint Document - OpenXML file format
+ document = new XMLSlideShow(is);
+ } else {
+ // Any other type of embedded object.
+ document = is;
+ }
+ document.close();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xddf.usermodel.PresetColor;
+import org.apache.poi.xddf.usermodel.XDDFColor;
+import org.apache.poi.xddf.usermodel.XDDFFillProperties;
+import org.apache.poi.xddf.usermodel.XDDFLineProperties;
+import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
+import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.AxisTickLabelPosition;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.ChartTypes;
+import org.apache.poi.xddf.usermodel.chart.LegendPosition;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
+import org.apache.poi.xddf.usermodel.chart.XDDFCategoryDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFLegendEntry;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFScatterChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
+import org.apache.poi.xddf.usermodel.text.XDDFRunProperties;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFChart;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * This example is based on original contributions by Axel Richter on StackOverflow.
+ *
+ * <em>Note from original author</em>:
+ * This only works for Excel since OpenOffice or LibreOffice Calc is not able having series having literal numeric values set.
+ *
+ * @see <a href="https://stackoverflow.com/questions/50772989/">Create target marker in a bar chart with openxmlformats</a>
+ * @see <a href="https://stackoverflow.com/questions/50873700/">Change axis color and font of the chart in openxmlformats</a>
+ * @see <a href="https://stackoverflow.com/questions/51530552/">Change colors of line chart Apache POI</a>
+ */
+public final class ExcelChartWithTargetLine {
+ private ExcelChartWithTargetLine() {}
+
+ private static final int NUM_OF_ROWS = 6;
+
+ private static void createChart(XSSFChart chart, XSSFSheet sheet, int[] chartedCols, double target) {
+ // some colors
+ XDDFFillProperties[] fills = new XDDFFillProperties[] {
+ new XDDFSolidFillProperties(XDDFColor.from(PresetColor.TURQUOISE)),
+ new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHARTREUSE)),
+ new XDDFSolidFillProperties(XDDFColor.from(PresetColor.LAVENDER)),
+ new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHOCOLATE)),
+ new XDDFSolidFillProperties(XDDFColor.from(PresetColor.TOMATO)),
+ new XDDFSolidFillProperties(XDDFColor.from(PresetColor.PLUM))
+ };
+ XDDFLineProperties solidTurquoise = new XDDFLineProperties(fills[0]);
+ XDDFLineProperties solidTomato = new XDDFLineProperties(fills[4]);
+ XDDFLineProperties solidPlum = new XDDFLineProperties(fills[5]);
+ XDDFSolidFillProperties solidAlmond = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.BLANCHED_ALMOND));
+ XDDFSolidFillProperties solidGray = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.DARK_SLATE_GRAY));
+
+
+ // the bar chart
+
+ XDDFCategoryAxis barCategories = chart.createCategoryAxis(AxisPosition.BOTTOM);
+ XDDFValueAxis leftValues = chart.createValueAxis(AxisPosition.LEFT);
+ leftValues.crossAxis(barCategories);
+ barCategories.crossAxis(leftValues);
+
+ // from https://stackoverflow.com/questions/50873700/
+ // colored major grid lines
+ leftValues.getOrAddMajorGridProperties().setLineProperties(solidTomato);
+ //colored axis line
+ leftValues.getOrAddShapeProperties().setLineProperties(solidPlum);
+ // axis font
+ XDDFRunProperties props = leftValues.getOrAddTextProperties();
+ props.setFontSize(14.0);
+ props.setFillProperties(fills[5]);
+
+ XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, barCategories, leftValues);
+ bar.setVaryColors(true);
+ bar.setBarDirection(chartedCols.length > 1 ? BarDirection.COL : BarDirection.BAR);
+
+ for (int c : chartedCols) {
+ // the data sources
+ XDDFCategoryDataSource xs = XDDFDataSourcesFactory.fromStringCellRange(sheet,
+ new CellRangeAddress(1, NUM_OF_ROWS, 0, 0));
+ XDDFNumericalDataSource<Double> ys = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
+ new CellRangeAddress(1, NUM_OF_ROWS, c, c));
+ XDDFBarChartData.Series series = (XDDFBarChartData.Series) bar.addSeries(xs, ys);
+ series.setTitle(null, new CellReference(sheet.getSheetName(), 0, c, true, true));
+ series.setFillProperties(fills[c]);
+ series.setLineProperties(solidTurquoise); // bar border color different from fill
+ }
+ chart.plot(bar);
+
+
+ // target line
+ // line of a scatter chart from 0 (min) to 1 (max) having value of target
+
+ XDDFValueAxis scatterX = chart.createValueAxis(AxisPosition.TOP);
+ scatterX.setVisible(false);
+ scatterX.setTickLabelPosition(AxisTickLabelPosition.NONE);
+ XDDFValueAxis scatterY = chart.createValueAxis(AxisPosition.RIGHT);
+ scatterY.setVisible(false);
+ scatterY.setTickLabelPosition(AxisTickLabelPosition.NONE);
+ scatterX.crossAxis(scatterY);
+ scatterY.crossAxis(scatterX);
+ if (chartedCols.length > 1) {
+ scatterX.setMaximum(1.0);
+ } else {
+ scatterY.setMaximum(1.0);
+ }
+
+ XDDFScatterChartData scatter = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, scatterX, scatterY);
+ scatter.setVaryColors(true);
+
+ // This only works for Excel since OpenOffice or LibreOffice Calc does not support literal numeric data series.
+ XDDFNumericalDataSource<Double> targetDS = XDDFDataSourcesFactory.fromArray(new Double[] { target, target });
+ XDDFNumericalDataSource<Double> zeroOneDS = XDDFDataSourcesFactory.fromArray(new Double[] { 0.0, 1.0 });
+
+ if (chartedCols.length > 1) {
+ // BarDirection.COL then X axis is from 0 to 1 and Y axis is target axis
+ scatter.addSeries(zeroOneDS, targetDS).setLineProperties(solidTurquoise);
+ } else {
+ // BarDirection.BAR then X axis is target axis and Y axis is from 0 to 1
+ scatter.addSeries(targetDS, zeroOneDS).setLineProperties(solidTurquoise);
+ }
+
+ chart.plot(scatter);
+
+
+ // legend
+ if (chartedCols.length > 1) {
+ XDDFChartLegend legend = chart.getOrAddLegend();
+ legend.setPosition(LegendPosition.LEFT);
+ legend.setOverlay(false);
+
+ // delete additional target line series legend entry
+ XDDFLegendEntry entry = legend.addEntry();
+ entry.setIndex(0);
+ entry.setDelete(true);
+ }
+
+
+ // from https://stackoverflow.com/questions/51530552/
+ // customize the chart
+
+ // do not auto delete the title
+ chart.setAutoTitleDeleted(false);
+
+ // plot area background and border line
+ XDDFShapeProperties chartProps = chart.getOrAddShapeProperties();
+ chartProps.setFillProperties(solidAlmond);
+ chartProps.setLineProperties(new XDDFLineProperties(solidGray));
+
+ // line style of cat axis
+ XDDFLineProperties categoriesProps = new XDDFLineProperties(solidGray);
+ categoriesProps.setWidth(2.1);
+ barCategories.getOrAddShapeProperties().setLineProperties(categoriesProps);
+ }
+
+ private static XSSFClientAnchor createAnchor(XSSFDrawing drawing, int[] chartedCols) {
+ if (chartedCols.length > 1) {
+ return drawing.createAnchor(0, 0, 0, 0, 0, 8, 10, 23);
+ } else {
+ return drawing.createAnchor(0, 0, 0, 0, 0, 8, 5, 23);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ try (XSSFWorkbook workbook = new XSSFWorkbook()) {
+ XSSFSheet sheet = workbook.createSheet("targetline");
+ final int NUM_OF_COLUMNS = 4;
+
+ // create some data
+ XSSFRow row;
+ XSSFCell cell;
+ String[] headings = new String[] { "Year", "Male", "Female", "Other" };
+ int rowIndex = 0;
+ row = sheet.createRow(rowIndex);
+ for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
+ cell = row.createCell(colIndex);
+ cell.setCellValue(headings[colIndex]);
+ }
+ double[][] values = new double[][] { new double[] { 1980, 56.0, 44.1, 12.2 },
+ new double[] { 1985, 34.5, 41.0, 4 }, new double[] { 1990, 65.0, 68.5, 9.1 },
+ new double[] { 1995, 34.7, 47.6, 4.9 }, new double[] { 2000, 23.0, 64.5, 11.1 },
+ new double[] { 2005, 56.3, 69.8, 9.5 } };
+ for (; rowIndex < NUM_OF_ROWS; rowIndex++) {
+ row = sheet.createRow(rowIndex + 1);
+ for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
+ cell = row.createCell(colIndex);
+ cell.setCellValue(values[rowIndex][colIndex]);
+ }
+ }
+
+ int[] chartedCols = new int[] { 1, 2 , 3 };
+
+ XSSFDrawing drawing = sheet.createDrawingPatriarch();
+ XSSFClientAnchor anchor = createAnchor(drawing, chartedCols);
+ XSSFChart chart = drawing.createChart(anchor);
+ createChart(chart, sheet, chartedCols, 42.0);
+
+ try (FileOutputStream fos = new FileOutputStream("ExcelChartWithTargetLine.xlsx")) {
+ workbook.write(fos);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Fills and Colors
+ */
+public class FillsAndColors {
+ public static void main(String[] args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet("new sheet");
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ Row row = sheet.createRow(1);
+
+ // Aqua background
+ CellStyle style = wb.createCellStyle();
+ style.setFillBackgroundColor(IndexedColors.AQUA.getIndex());
+ style.setFillPattern(FillPatternType.BIG_SPOTS);
+ Cell cell = row.createCell(1);
+ cell.setCellValue(new XSSFRichTextString("X"));
+ cell.setCellStyle(style);
+
+ // Orange "foreground", foreground being the fill foreground not the font color.
+ style = wb.createCellStyle();
+ style.setFillForegroundColor(IndexedColors.ORANGE.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ cell = row.createCell(2);
+ cell.setCellValue(new XSSFRichTextString("X"));
+ cell.setCellStyle(style);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("fill_colors.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.PrintSetup;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public class FitSheetToOnePage {
+
+ public static void main(String[]args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet("format sheet");
+ PrintSetup ps = sheet.getPrintSetup();
+
+ sheet.setAutobreaks(true);
+
+ ps.setFitHeight((short) 1);
+ ps.setFitWidth((short) 1);
+
+ // Create various cells and rows for spreadsheet.
+
+ try (FileOutputStream fileOut = new FileOutputStream("fitSheetToOnePage.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Footer;
+import org.apache.poi.ss.usermodel.Header;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public class HeadersAndFooters {
+
+ public static void main(String[]args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet("first-header - format sheet");
+ sheet.createRow(0).createCell(0).setCellValue(123);
+
+ //set page numbers in the footer
+ Footer footer = sheet.getFooter();
+ //&P == current page number
+ //&N == page numbers
+ footer.setRight("Page &P of &N");
+
+
+ Header firstHeader = ((XSSFSheet) sheet).getFirstHeader();
+ //&F == workbook file name
+ firstHeader.setLeft("&F ......... first header");
+
+ for (int i = 0; i < 100; i = i + 10) {
+ sheet.createRow(i).createCell(0).setCellValue(123);
+ }
+
+
+ XSSFSheet sheet2 = (XSSFSheet) wb.createSheet("odd header-even footer");
+ Header oddHeader = sheet2.getOddHeader();
+ //&B == bold
+ //&E == double underline
+ //&D == date
+ oddHeader.setCenter("&B &E oddHeader &D ");
+
+ Footer evenFooter = sheet2.getEvenFooter();
+ evenFooter.setRight("even footer &P");
+ sheet2.createRow(10).createCell(0).setCellValue("Second sheet with an oddHeader and an evenFooter");
+
+ for (int i = 0; i < 200; i = i + 10) {
+ sheet2.createRow(i).createCell(0).setCellValue(123);
+ }
+
+ XSSFSheet sheet3 = (XSSFSheet) wb.createSheet("odd header- odd footer");
+ sheet3.createRow(10).createCell(0).setCellValue("Third sheet with oddHeader and oddFooter");
+ Header oddH = sheet3.getOddHeader();
+ //&C == centered
+ oddH.setCenter("centered oddHeader");
+ oddH.setLeft("left ");
+ oddH.setRight("right ");
+
+ Footer oddF = sheet3.getOddFooter();
+ oddF.setLeft("Page &P");
+ oddF.setRight("Pages &N ");
+
+ try (FileOutputStream fileOut = new FileOutputStream("headerFooter.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.common.usermodel.HyperlinkType;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.Hyperlink;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates how to create hyperlinks.
+ */
+public class HyperlinkExample {
+
+ public static void main(String[]args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ CreationHelper createHelper = wb.getCreationHelper();
+
+ //cell style for hyperlinks
+ //by default hyperlinks are blue and underlined
+ CellStyle hlink_style = wb.createCellStyle();
+ Font hlink_font = wb.createFont();
+ hlink_font.setUnderline(Font.U_SINGLE);
+ hlink_font.setColor(IndexedColors.BLUE.getIndex());
+ hlink_style.setFont(hlink_font);
+
+ Cell cell;
+ Sheet sheet = wb.createSheet("Hyperlinks");
+ //URL
+ cell = sheet.createRow(0).createCell(0);
+ cell.setCellValue("URL Link");
+
+ Hyperlink link = createHelper.createHyperlink(HyperlinkType.URL);
+ link.setAddress("https://poi.apache.org/");
+ cell.setHyperlink(link);
+ cell.setCellStyle(hlink_style);
+
+ //link to a file in the current directory
+ cell = sheet.createRow(1).createCell(0);
+ cell.setCellValue("File Link");
+ link = createHelper.createHyperlink(HyperlinkType.FILE);
+ link.setAddress("link1.xls");
+ cell.setHyperlink(link);
+ cell.setCellStyle(hlink_style);
+
+ //e-mail link
+ cell = sheet.createRow(2).createCell(0);
+ cell.setCellValue("Email Link");
+ link = createHelper.createHyperlink(HyperlinkType.EMAIL);
+ //note, if subject contains white spaces, make sure they are url-encoded
+ link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
+ cell.setHyperlink(link);
+ cell.setCellStyle(hlink_style);
+
+ //link to a place in this workbook
+
+ //create a target sheet and cell
+ Sheet sheet2 = wb.createSheet("Target Sheet");
+ sheet2.createRow(0).createCell(0).setCellValue("Target Cell");
+
+ cell = sheet.createRow(3).createCell(0);
+ cell.setCellValue("Worksheet Link");
+ Hyperlink link2 = createHelper.createHyperlink(HyperlinkType.DOCUMENT);
+ link2.setAddress("'Target Sheet'!A1");
+ cell.setHyperlink(link2);
+ cell.setCellStyle(hlink_style);
+
+ try (FileOutputStream out = new FileOutputStream("hyperinks.xlsx")) {
+ wb.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Iterate over rows and cells
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class IterateCells {
+
+ private IterateCells() {}
+
+ public static void main(String[] args) throws IOException {
+ try (
+ FileInputStream is = new FileInputStream(args[0]);
+ Workbook wb = new XSSFWorkbook(is)
+ ) {
+ for (int i = 0; i < wb.getNumberOfSheets(); i++) {
+ Sheet sheet = wb.getSheetAt(i);
+ System.out.println(wb.getSheetName(i));
+ for (Row row : sheet) {
+ System.out.println("rownum: " + row.getRowNum());
+ for (Cell cell : row) {
+ System.out.println(cell);
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.PresetColor;
+import org.apache.poi.xddf.usermodel.XDDFColor;
+import org.apache.poi.xddf.usermodel.XDDFLineProperties;
+import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
+import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
+import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.ChartTypes;
+import org.apache.poi.xddf.usermodel.chart.LegendPosition;
+import org.apache.poi.xddf.usermodel.chart.MarkerStyle;
+import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFLineChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
+import org.apache.poi.xssf.usermodel.XSSFChart;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Line chart example.
+ */
+public final class LineChart {
+ private LineChart() {}
+
+ public static void main(String[] args) throws IOException {
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet("linechart");
+ final int NUM_OF_ROWS = 3;
+ final int NUM_OF_COLUMNS = 10;
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ Row row;
+ Cell cell;
+ for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
+ row = sheet.createRow((short) rowIndex);
+ for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
+ cell = row.createCell((short) colIndex);
+ cell.setCellValue(colIndex * (rowIndex + 1.0));
+ }
+ }
+
+ XSSFDrawing drawing = sheet.createDrawingPatriarch();
+ XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
+
+ XSSFChart chart = drawing.createChart(anchor);
+ XDDFChartLegend legend = chart.getOrAddLegend();
+ legend.setPosition(LegendPosition.TOP_RIGHT);
+
+ // Use a category axis for the bottom axis.
+ XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
+ bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
+ XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
+ leftAxis.setTitle("f(x)");
+ leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
+
+ XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
+ XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
+ XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
+
+ XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
+ XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1);
+ series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
+ series1.setSmooth(false); // https://stackoverflow.com/questions/29014848
+ series1.setMarkerStyle(MarkerStyle.STAR); // https://stackoverflow.com/questions/39636138
+ XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2);
+ series2.setTitle("3x", null);
+ series2.setSmooth(true);
+ series2.setMarkerSize((short) 6);
+ series2.setMarkerStyle(MarkerStyle.TRIANGLE); // https://stackoverflow.com/questions/39636138
+ chart.plot(data);
+
+ // if your series have missing values like https://stackoverflow.com/questions/29014848
+ // chart.displayBlanksAs(DisplayBlanks.GAP);
+
+ // https://stackoverflow.com/questions/24676460
+ solidLineSeries(data, 0, PresetColor.CHARTREUSE);
+ solidLineSeries(data, 1, PresetColor.TURQUOISE);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
+ XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
+ XDDFLineProperties line = new XDDFLineProperties();
+ line.setFillProperties(fill);
+ XDDFChartData.Series series = data.getSeries().get(index);
+ XDDFShapeProperties properties = series.getShapeProperties();
+ if (properties == null) {
+ properties = new XDDFShapeProperties();
+ }
+ properties.setLineProperties(line);
+ series.setShapeProperties(properties);
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xssf.usermodel;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.apache.poi.examples.util.TempFileUtils;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.temp.AesZipFileZipEntrySource;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * An example that loads a password protected workbook and counts the sheets.
+ * <p><ul>
+ * <li>The example demonstrates that all temp files are removed.
+ * <li><code>AesZipFileZipEntrySource</code> is used to ensure that temp files are encrypted.
+ * </ul><p>
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class LoadPasswordProtectedXlsx {
+
+ private LoadPasswordProtectedXlsx() {}
+
+ public interface EncryptionHandler {
+ void handle(final InputStream inputStream) throws Exception;
+ }
+
+ public static void main(String[] args) throws Exception {
+ execute(args, LoadPasswordProtectedXlsx::printSheetCount);
+ }
+
+ public static void execute(String[] args, EncryptionHandler handler) throws Exception {
+ if(args.length != 2) {
+ throw new IllegalArgumentException("Expected 2 params: filename and password");
+ }
+ TempFileUtils.checkTempFiles();
+ String filename = args[0];
+ String password = args[1];
+ try (FileInputStream fis = new FileInputStream(filename);
+ POIFSFileSystem fs = new POIFSFileSystem(fis)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ Decryptor d = Decryptor.getInstance(info);
+ if (!d.verifyPassword(password)) {
+ throw new RuntimeException("incorrect password");
+ }
+ try (InputStream unencryptedStream = d.getDataStream(fs)) {
+ handler.handle(unencryptedStream);
+ }
+ }
+ TempFileUtils.checkTempFiles();
+ }
+
+
+ private static void printSheetCount(final InputStream inputStream) throws Exception {
+ try (AesZipFileZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(inputStream);
+ OPCPackage pkg = OPCPackage.open(source);
+ XSSFWorkbook workbook = new XSSFWorkbook(pkg)) {
+ System.out.println("sheet count: " + workbook.getNumberOfSheets());
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * An example of how to merge regions of cells.
+ */
+public class MergingCells {
+ public static void main(String[] args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet("new sheet");
+
+ Row row = sheet.createRow((short) 1);
+ Cell cell = row.createCell((short) 1);
+ cell.setCellValue(new XSSFRichTextString("This is a test of merging"));
+
+ sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, 2));
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("merging_cells.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * How to use newlines in cells
+ */
+public class NewLinesInCells {
+
+ public static void main(String[]args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet();
+
+ Row row = sheet.createRow(2);
+ Cell cell = row.createCell(2);
+ cell.setCellValue("Use \n with word wrap on to create a new line");
+
+ //to enable newlines you need set a cell styles with wrap=true
+ CellStyle cs = wb.createCellStyle();
+ cs.setWrapText(true);
+ cell.setCellStyle(cs);
+
+ //increase row height to accommodate two lines of text
+ row.setHeightInPoints(2 * sheet.getDefaultRowHeightInPoints());
+
+ //adjust column width to fit the content
+ sheet.autoSizeColumn(2);
+
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml-newlines.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public class Outlining {
+
+ public static void main(String[] args) throws IOException {
+ Outlining o=new Outlining();
+ o.groupRowColumn();
+ o.collapseExpandRowColumn();
+ }
+
+
+ private void groupRowColumn() throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) {
+ Sheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupRow(5, 14);
+ sheet1.groupRow(7, 14);
+ sheet1.groupRow(16, 19);
+
+ sheet1.groupColumn((short) 4, (short) 7);
+ sheet1.groupColumn((short) 9, (short) 12);
+ sheet1.groupColumn((short) 10, (short) 11);
+
+ try (OutputStream fileOut = new FileOutputStream("outlining.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ private void collapseExpandRowColumn() throws IOException {
+ try (Workbook wb2 = new XSSFWorkbook()) {
+ Sheet sheet2 = wb2.createSheet("new sheet");
+ sheet2.groupRow(5, 14);
+ sheet2.groupRow(7, 14);
+ sheet2.groupRow(16, 19);
+
+ sheet2.groupColumn((short) 4, (short) 7);
+ sheet2.groupColumn((short) 9, (short) 12);
+ sheet2.groupColumn((short) 10, (short) 11);
+
+
+ sheet2.setRowGroupCollapsed(7, true);
+ //sheet1.setRowGroupCollapsed(7,false);
+
+ sheet2.setColumnGroupCollapsed((short) 4, true);
+ sheet2.setColumnGroupCollapsed((short) 4, false);
+
+ try (OutputStream fileOut = new FileOutputStream("outlining_collapsed.xlsx")) {
+ wb2.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.PresetColor;
+import org.apache.poi.xddf.usermodel.XDDFColor;
+import org.apache.poi.xddf.usermodel.XDDFLineProperties;
+import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
+import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
+import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.ChartTypes;
+import org.apache.poi.xddf.usermodel.chart.LegendPosition;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFScatterChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
+import org.apache.poi.xssf.usermodel.XSSFChart;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Illustrates how to create a simple scatter chart.
+ */
+public final class ScatterChart {
+ private ScatterChart() {}
+
+ public static void main(String[] args) throws IOException {
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet("Sheet 1");
+ final int NUM_OF_ROWS = 3;
+ final int NUM_OF_COLUMNS = 10;
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ Row row;
+ Cell cell;
+ for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
+ row = sheet.createRow((short) rowIndex);
+ for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
+ cell = row.createCell((short) colIndex);
+ cell.setCellValue(colIndex * (rowIndex + 1.0));
+ }
+ }
+
+ XSSFDrawing drawing = sheet.createDrawingPatriarch();
+ XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
+
+ XSSFChart chart = drawing.createChart(anchor);
+ XDDFChartLegend legend = chart.getOrAddLegend();
+ legend.setPosition(LegendPosition.TOP_RIGHT);
+
+ XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM);
+ bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
+ XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
+ leftAxis.setTitle("f(x)");
+ leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
+
+ XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
+ XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
+ XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
+
+
+ XDDFScatterChartData data = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
+ XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) data.addSeries(xs, ys1);
+ series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
+ series1.setSmooth(false); // https://stackoverflow.com/questions/39636138
+ XDDFScatterChartData.Series series2 = (XDDFScatterChartData.Series) data.addSeries(xs, ys2);
+ series2.setTitle("3x", null);
+ chart.plot(data);
+
+ solidLineSeries(data, 0, PresetColor.CHARTREUSE);
+ solidLineSeries(data, 1, PresetColor.TURQUOISE);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("ooxml-scatter-chart.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+ private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
+ XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
+ XDDFLineProperties line = new XDDFLineProperties();
+ line.setFillProperties(fill);
+ XDDFChartData.Series series = data.getSeries().get(index);
+ XDDFShapeProperties properties = series.getShapeProperties();
+ if (properties == null) {
+ properties = new XDDFShapeProperties();
+ }
+ properties.setLineProperties(line);
+ series.setShapeProperties(properties);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public abstract class SelectedSheet {
+
+ public static void main(String[]args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+
+ wb.createSheet("row sheet");
+ wb.createSheet("another sheet");
+ Sheet sheet3 = wb.createSheet(" sheet 3 ");
+ sheet3.setSelected(true);
+ wb.setActiveSheet(2);
+
+ // Create various cells and rows for spreadsheet.
+
+ try (FileOutputStream fileOut = new FileOutputStream("selectedSheet.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * How to shift rows up or down
+ */
+public class ShiftRows {
+
+ public static void main(String[]args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet("Sheet1");
+
+ Row row1 = sheet.createRow(1);
+ row1.createCell(0).setCellValue(1);
+
+ Row row2 = sheet.createRow(4);
+ row2.createCell(1).setCellValue(2);
+
+ Row row3 = sheet.createRow(5);
+ row3.createCell(2).setCellValue(3);
+
+ Row row4 = sheet.createRow(6);
+ row4.createCell(3).setCellValue(4);
+
+ Row row5 = sheet.createRow(9);
+ row5.createCell(4).setCellValue(5);
+
+ // Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5)
+ sheet.shiftRows(5, 10, -4);
+
+ try (FileOutputStream fileOut = new FileOutputStream("shiftRows.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * How to set split and freeze panes
+ */
+public class SplitAndFreezePanes {
+ public static void main(String[]args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) {
+ Sheet sheet1 = wb.createSheet("new sheet");
+ Sheet sheet2 = wb.createSheet("second sheet");
+ Sheet sheet3 = wb.createSheet("third sheet");
+ Sheet sheet4 = wb.createSheet("fourth sheet");
+
+ // Freeze just one row
+ sheet1.createFreezePane(0, 1, 0, 1);
+ // Freeze just one column
+ sheet2.createFreezePane(1, 0, 1, 0);
+ // Freeze the columns and rows (forget about scrolling position of the lower right quadrant).
+ sheet3.createFreezePane(2, 2);
+ // Create a split with the lower left side being the active quadrant
+ sheet4.createSplitPane(2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT);
+
+ try (FileOutputStream fileOut = new FileOutputStream("splitFreezePane.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ooxml.POIXMLProperties;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * How to set extended and custom properties
+ */
+public class WorkbookProperties {
+
+ public static void main(String[]args) throws IOException {
+ try (XSSFWorkbook workbook = new XSSFWorkbook()) {
+ workbook.createSheet("Workbook Properties");
+
+ POIXMLProperties props = workbook.getProperties();
+
+ /*
+ * Extended properties are a predefined set of metadata properties
+ * that are specifically applicable to Office Open XML documents.
+ * Extended properties consist of 24 simple properties and 3 complex properties stored in the
+ * part targeted by the relationship of type
+ */
+ POIXMLProperties.ExtendedProperties ext = props.getExtendedProperties();
+ ext.getUnderlyingProperties().setCompany("Apache Software Foundation");
+ ext.getUnderlyingProperties().setTemplate("XSSF");
+
+ /*
+ * Custom properties enable users to define custom metadata properties.
+ */
+
+ POIXMLProperties.CustomProperties cust = props.getCustomProperties();
+ cust.addProperty("Author", "John Smith");
+ cust.addProperty("Year", 2009);
+ cust.addProperty("Price", 45.50);
+ cust.addProperty("Available", true);
+
+ try (FileOutputStream out = new FileOutputStream("workbook.xlsx")) {
+ workbook.write(out);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Working with borders
+ */
+public class WorkingWithBorders {
+ public static void main(String[] args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet("borders");
+
+ // Create a row and put some cells in it. Rows are 0 based.
+ Row row = sheet.createRow((short) 1);
+
+ // Create a cell and put a value in it.
+ Cell cell = row.createCell((short) 1);
+ cell.setCellValue(4);
+
+ // Style the cell with borders all around.
+ CellStyle style = wb.createCellStyle();
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(IndexedColors.GREEN.getIndex());
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(IndexedColors.BLUE.getIndex());
+ style.setBorderTop(BorderStyle.MEDIUM_DASHED);
+ style.setTopBorderColor(IndexedColors.BLACK.getIndex());
+ cell.setCellStyle(style);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("xssf-borders.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Working with Fonts
+ */
+public class WorkingWithFonts {
+ public static void main(String[] args) throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+ Sheet sheet = wb.createSheet("Fonts");
+
+ Font font0 = wb.createFont();
+ font0.setColor(IndexedColors.BROWN.getIndex());
+ CellStyle style0 = wb.createCellStyle();
+ style0.setFont(font0);
+
+ Font font1 = wb.createFont();
+ font1.setFontHeightInPoints((short) 14);
+ font1.setFontName("Courier New");
+ font1.setColor(IndexedColors.RED.getIndex());
+ CellStyle style1 = wb.createCellStyle();
+ style1.setFont(font1);
+
+ Font font2 = wb.createFont();
+ font2.setFontHeightInPoints((short) 16);
+ font2.setFontName("Arial");
+ font2.setColor(IndexedColors.GREEN.getIndex());
+ CellStyle style2 = wb.createCellStyle();
+ style2.setFont(font2);
+
+ Font font3 = wb.createFont();
+ font3.setFontHeightInPoints((short) 18);
+ font3.setFontName("Times New Roman");
+ font3.setColor(IndexedColors.LAVENDER.getIndex());
+ CellStyle style3 = wb.createCellStyle();
+ style3.setFont(font3);
+
+ Font font4 = wb.createFont();
+ font4.setFontHeightInPoints((short) 18);
+ font4.setFontName("Wingdings");
+ font4.setColor(IndexedColors.GOLD.getIndex());
+ CellStyle style4 = wb.createCellStyle();
+ style4.setFont(font4);
+
+ Font font5 = wb.createFont();
+ font5.setFontName("Symbol");
+ CellStyle style5 = wb.createCellStyle();
+ style5.setFont(font5);
+
+ Cell cell0 = sheet.createRow(0).createCell(1);
+ cell0.setCellValue("Default");
+ cell0.setCellStyle(style0);
+
+ Cell cell1 = sheet.createRow(1).createCell(1);
+ cell1.setCellValue("Courier");
+ cell1.setCellStyle(style1);
+
+ Cell cell2 = sheet.createRow(2).createCell(1);
+ cell2.setCellValue("Arial");
+ cell2.setCellStyle(style2);
+
+ Cell cell3 = sheet.createRow(3).createCell(1);
+ cell3.setCellValue("Times New Roman");
+ cell3.setCellStyle(style3);
+
+ Cell cell4 = sheet.createRow(4).createCell(1);
+ cell4.setCellValue("Wingdings");
+ cell4.setCellStyle(style4);
+
+ Cell cell5 = sheet.createRow(5).createCell(1);
+ cell5.setCellValue("Symbol");
+ cell5.setCellStyle(style5);
+
+ // Write the output to a file
+ try (FileOutputStream fileOut = new FileOutputStream("xssf-fonts.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates various settings avaiable in the Page Setup dialog
+ */
+public class WorkingWithPageSetup {
+
+ public static void main(String[]args) throws Exception {
+ try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
+
+ /*
+ * It's possible to set up repeating rows and columns in your printouts by using the setRepeatingRowsAndColumns() function in the Workbook object.
+ *
+ * This function Contains 5 parameters:
+ * The first parameter is the index to the sheet (0 = first sheet).
+ * The second and third parameters specify the range for the columns to repreat.
+ * To stop the columns from repeating pass in -1 as the start and end column.
+ * The fourth and fifth parameters specify the range for the rows to repeat.
+ * To stop the columns from repeating pass in -1 as the start and end rows.
+ */
+ Sheet sheet1 = wb.createSheet("new sheet");
+ Sheet sheet2 = wb.createSheet("second sheet");
+
+ // Set the columns to repeat from column 0 to 2 on the first sheet
+ Row row1 = sheet1.createRow(0);
+ row1.createCell(0).setCellValue(1);
+ row1.createCell(1).setCellValue(2);
+ row1.createCell(2).setCellValue(3);
+ Row row2 = sheet1.createRow(1);
+ row2.createCell(1).setCellValue(4);
+ row2.createCell(2).setCellValue(5);
+
+
+ Row row3 = sheet2.createRow(1);
+ row3.createCell(0).setCellValue(2.1);
+ row3.createCell(4).setCellValue(2.2);
+ row3.createCell(5).setCellValue(2.3);
+ Row row4 = sheet2.createRow(2);
+ row4.createCell(4).setCellValue(2.4);
+ row4.createCell(5).setCellValue(2.5);
+
+ // Set the columns to repeat from column 0 to 2 on the first sheet
+ sheet1.setRepeatingColumns(CellRangeAddress.valueOf("A:C"));
+ // Set the the repeating rows and columns on the second sheet.
+ CellRangeAddress cra = CellRangeAddress.valueOf("E2:F3");
+ sheet2.setRepeatingColumns(cra);
+ sheet2.setRepeatingRows(cra);
+
+ //set the print area for the first sheet
+ wb.setPrintArea(0, 1, 2, 0, 3);
+
+
+ try (FileOutputStream fileOut = new FileOutputStream("xssf-printsetup.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.Picture;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates how to insert pictures in a SpreadsheetML document
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class WorkingWithPictures {
+ private WorkingWithPictures() {}
+
+ public static void main(String[] args) throws IOException {
+
+ //create a new workbook
+ try (Workbook wb = new XSSFWorkbook()) {
+ CreationHelper helper = wb.getCreationHelper();
+
+ //add a picture in this workbook.
+ InputStream is = new FileInputStream(args[0]);
+ byte[] bytes = IOUtils.toByteArray(is);
+ is.close();
+ int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
+
+ //create sheet
+ Sheet sheet = wb.createSheet();
+
+ //create drawing
+ Drawing<?> drawing = sheet.createDrawingPatriarch();
+
+ //add a picture shape
+ ClientAnchor anchor = helper.createClientAnchor();
+ anchor.setCol1(1);
+ anchor.setRow1(1);
+ Picture pict = drawing.createPicture(anchor, pictureIdx);
+
+ //auto-size picture
+ pict.resize(2);
+
+ //save workbook
+ String file = "picture.xls";
+ if (wb instanceof XSSFWorkbook) {
+ file += "x"; // NOSONAR
+ }
+ try (OutputStream fileOut = new FileOutputStream(file)) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xssf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Demonstrates how to work with rich text
+ */
+public final class WorkingWithRichText {
+
+ private WorkingWithRichText() {}
+
+ public static void main(String[] args) throws Exception {
+ try (XSSFWorkbook wb = new XSSFWorkbook()) {
+ XSSFSheet sheet = wb.createSheet();
+ XSSFRow row = sheet.createRow(2);
+
+ XSSFCell cell = row.createCell(1);
+ XSSFRichTextString rt = new XSSFRichTextString("The quick brown fox");
+
+ XSSFFont font1 = wb.createFont();
+ font1.setBold(true);
+ font1.setColor(new XSSFColor(new java.awt.Color(255, 0, 0), wb.getStylesSource().getIndexedColors()));
+ rt.applyFont(0, 10, font1);
+
+ XSSFFont font2 = wb.createFont();
+ font2.setItalic(true);
+ font2.setUnderline(Font.U_DOUBLE);
+ font2.setColor(new XSSFColor(new java.awt.Color(0, 255, 0), wb.getStylesSource().getIndexedColors()));
+ rt.applyFont(10, 19, font2);
+
+ XSSFFont font3 = wb.createFont();
+ font3.setColor(new XSSFColor(new java.awt.Color(0, 0, 255), wb.getStylesSource().getIndexedColors()));
+ rt.append(" Jumped over the lazy dog", font3);
+
+ cell.setCellValue(rt);
+
+ // Write the output to a file
+ try (OutputStream fileOut = new FileOutputStream("xssf-richtext.xlsx")) {
+ wb.write(fileOut);
+ }
+ }
+ }
+}
--- /dev/null
+
+/*
+ * ====================================================================
+ * 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.examples.xwpf.usermodel;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.chart.AxisOrientation;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xwpf.usermodel.XWPFChart;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+
+/**
+ * Build a bar chart from a template docx
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class BarChartExample {
+ private BarChartExample() {}
+
+ private static void usage(){
+ System.out.println("Usage: BarChartExample <bar-chart-template.docx> <bar-chart-data.txt>");
+ System.out.println(" bar-chart-template.docx template with a bar chart");
+ System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
+ "then go pairs {axis-label value}");
+ }
+
+ public static void main(String[] args) throws Exception {
+ if(args.length < 2) {
+ usage();
+ return;
+ }
+
+ try (FileInputStream argIS = new FileInputStream(args[0]);
+ BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
+
+ String chartTitle = modelReader.readLine(); // first line is chart title
+ String[] series = modelReader.readLine().split(",");
+
+ // Category Axis Data
+ List<String> listLanguages = new ArrayList<>(10);
+
+ // Values
+ List<Double> listCountries = new ArrayList<>(10);
+ List<Double> listSpeakers = new ArrayList<>(10);
+
+ // set model
+ String ln;
+ while((ln = modelReader.readLine()) != null) {
+ String[] vals = ln.split(",");
+ listCountries.add(Double.valueOf(vals[0]));
+ listSpeakers.add(Double.valueOf(vals[1]));
+ listLanguages.add(vals[2]);
+ }
+ String[] categories = listLanguages.toArray(new String[0]);
+ Double[] values1 = listCountries.toArray(new Double[0]);
+ Double[] values2 = listSpeakers.toArray(new Double[0]);
+
+ try (XWPFDocument doc = new XWPFDocument(argIS)) {
+ XWPFChart chart = doc.getCharts().get(0);
+ setBarData(chart, chartTitle, series, categories, values1, values2);
+ chart = doc.getCharts().get(1);
+ setColumnData(chart, "Column variant");
+
+ // save the result
+ try (OutputStream out = new FileOutputStream("bar-chart-demo-output.docx")) {
+ doc.write(out);
+ }
+ }
+ }
+ System.out.println("Done");
+ }
+
+ private static void setBarData(XWPFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
+ final List<XDDFChartData> data = chart.getChartSeries();
+ final XDDFBarChartData bar = (XDDFBarChartData) data.get(0);
+
+ final int numOfPoints = categories.length;
+ final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
+ final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
+ final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
+ final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
+ final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1);
+ values1[6] = 16.0; // if you ever want to change the underlying data
+ final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);
+
+ XDDFChartData.Series series1 = bar.getSeries(0);
+ series1.replaceData(categoriesData, valuesData);
+ series1.setTitle(series[0], chart.setSheetTitle(series[0], 0));
+ XDDFChartData.Series series2 = bar.addSeries(categoriesData, valuesData2);
+ series2.setTitle(series[1], chart.setSheetTitle(series[1], 1));
+
+ chart.plot(bar);
+ chart.setTitleText(chartTitle); // https://stackoverflow.com/questions/30532612
+ chart.setTitleOverlay(false);
+ }
+
+ private static void setColumnData(XWPFChart chart, String chartTitle) {
+ // Series Text
+ List<XDDFChartData> series = chart.getChartSeries();
+ XDDFBarChartData bar = (XDDFBarChartData) series.get(0);
+
+ // in order to transform a bar chart into a column chart, you just need to change the bar direction
+ bar.setBarDirection(BarDirection.COL);
+
+ // looking for "Stacked Bar Chart"? uncomment the following line
+ // bar.setBarGrouping(BarGrouping.STACKED);
+
+ // additionally, you can adjust the axes
+ bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN);
+ bar.getValueAxes().get(0).setPosition(AxisPosition.TOP);
+ }
+}
+
--- /dev/null
+/* ====================================================================
+ 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.examples.xwpf.usermodel;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.poi.wp.usermodel.HeaderFooterType;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFFooter;
+import org.apache.poi.xwpf.usermodel.XWPFHeader;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+
+public class BetterHeaderFooterExample {
+
+ public static void main(String[] args) throws IOException {
+ try (XWPFDocument doc = new XWPFDocument()) {
+
+ XWPFParagraph p = doc.createParagraph();
+
+ XWPFRun r = p.createRun();
+ r.setText("Some Text");
+ r.setBold(true);
+ r = p.createRun();
+ r.setText("Goodbye");
+
+ // create header/footer functions insert an empty paragraph
+ XWPFHeader head = doc.createHeader(HeaderFooterType.DEFAULT);
+ head.createParagraph().createRun().setText("header");
+
+ XWPFFooter foot = doc.createFooter(HeaderFooterType.DEFAULT);
+ foot.createParagraph().createRun().setText("footer");
+
+ try (OutputStream os = new FileOutputStream(new File("header2.docx"))) {
+ doc.write(os);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xwpf.usermodel;
+
+import java.io.BufferedReader;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.chart.AxisCrossBetween;
+import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.AxisTickMark;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.BarGrouping;
+import org.apache.poi.xddf.usermodel.chart.ChartTypes;
+import org.apache.poi.xddf.usermodel.chart.LegendPosition;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFChart;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartAxis;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
+import org.apache.poi.xwpf.usermodel.XWPFChart;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+
+/**
+ * Build a chart without reading template file
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class ChartFromScratch {
+ private ChartFromScratch() {}
+
+ private static void usage(){
+ System.out.println("Usage: ChartFromScratch <bar-chart-data.txt>");
+ System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
+ "then go pairs {axis-label value}");
+ }
+
+ public static void main(String[] args) throws Exception {
+ if(args.length < 1) {
+ usage();
+ return;
+ }
+
+ try (BufferedReader modelReader = new BufferedReader(new FileReader(args[0]))) {
+
+ String chartTitle = modelReader.readLine(); // first line is chart title
+ String[] series = modelReader.readLine().split(",");
+
+ // Category Axis Data
+ List<String> listLanguages = new ArrayList<>(10);
+
+ // Values
+ List<Double> listCountries = new ArrayList<>(10);
+ List<Double> listSpeakers = new ArrayList<>(10);
+
+ // set model
+ String ln;
+ while((ln = modelReader.readLine()) != null) {
+ String[] vals = ln.split(",");
+ listCountries.add(Double.valueOf(vals[0]));
+ listSpeakers.add(Double.valueOf(vals[1]));
+ listLanguages.add(vals[2]);
+ }
+
+ String[] categories = listLanguages.toArray(new String[0]);
+ Double[] values1 = listCountries.toArray(new Double[0]);
+ Double[] values2 = listSpeakers.toArray(new Double[0]);
+
+ try (XWPFDocument doc = new XWPFDocument();
+ OutputStream out = new FileOutputStream("chart-from-scratch.docx")) {
+ XWPFChart chart = doc.createChart(XDDFChart.DEFAULT_WIDTH * 10, XDDFChart.DEFAULT_HEIGHT * 15);
+ setBarData(chart, chartTitle, series, categories, values1, values2);
+ // save the result
+ doc.write(out);
+ }
+ }
+ System.out.println("Done");
+ }
+
+ private static void setBarData(XWPFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
+ // Use a category axis for the bottom axis.
+ XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
+ bottomAxis.setTitle(series[2]);
+ XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
+ leftAxis.setTitle(series[0]+","+series[1]);
+ leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
+ leftAxis.setMajorTickMark(AxisTickMark.OUT);
+ leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
+
+ final int numOfPoints = categories.length;
+ final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_LANGUAGES, COLUMN_LANGUAGES));
+ final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_COUNTRIES, COLUMN_COUNTRIES));
+ final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_SPEAKERS, COLUMN_SPEAKERS));
+ final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, COLUMN_LANGUAGES);
+ final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, COLUMN_COUNTRIES);
+ valuesData.setFormatCode("General");
+ values1[6] = 16.0; // if you ever want to change the underlying data, it has to be done before building the data source
+ final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, COLUMN_SPEAKERS);
+ valuesData2.setFormatCode("General");
+
+
+ XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
+ bar.setBarGrouping(BarGrouping.CLUSTERED);
+
+ XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
+ series1.setTitle(series[0], chart.setSheetTitle(series[0], COLUMN_COUNTRIES));
+
+ XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
+ series2.setTitle(series[1], chart.setSheetTitle(series[1], COLUMN_SPEAKERS));
+
+ bar.setVaryColors(true);
+ bar.setBarDirection(BarDirection.COL);
+ chart.plot(bar);
+
+ XDDFChartLegend legend = chart.getOrAddLegend();
+ legend.setPosition(LegendPosition.LEFT);
+ legend.setOverlay(false);
+
+ chart.setTitleText(chartTitle);
+ chart.setTitleOverlay(false);
+ chart.setAutoTitleDeleted(false);
+ }
+
+ private static final int COLUMN_LANGUAGES = 0;
+ private static final int COLUMN_COUNTRIES = 1;
+ private static final int COLUMN_SPEAKERS = 2;
+}
+
--- /dev/null
+/* ====================================================================
+ 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.examples.xwpf.usermodel;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+import org.apache.poi.wp.usermodel.HeaderFooterType;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFFooter;
+import org.apache.poi.xwpf.usermodel.XWPFHeader;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+import org.apache.poi.xwpf.usermodel.XWPFTable;
+import org.apache.poi.xwpf.usermodel.XWPFTableCell;
+import org.apache.poi.xwpf.usermodel.XWPFTableRow;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblLayoutType;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblLayoutType;
+
+public class HeaderFooterTable {
+
+ public static void main(String[] args) throws IOException {
+ try (XWPFDocument doc = new XWPFDocument()) {
+
+ // Create a header with a 1 row, 3 column table
+ // changes made for issue 57366 allow a new header or footer
+ // to be created empty. This is a change. You will have to add
+ // either a paragraph or a table to the header or footer for
+ // the document to be considered valid.
+ XWPFHeader hdr = doc.createHeader(HeaderFooterType.DEFAULT);
+ XWPFTable tbl = hdr.createTable(1, 3);
+
+ // Set the padding around text in the cells to 1/10th of an inch
+ int pad = (int) (.1 * 1440);
+ tbl.setCellMargins(pad, pad, pad, pad);
+
+ // Set table width to 6.5 inches in 1440ths of a point
+ tbl.setWidth((int) (6.5 * 1440));
+ // Can not yet set table or cell width properly, tables default to
+ // autofit layout, and this requires fixed layout
+ CTTbl ctTbl = tbl.getCTTbl();
+ CTTblPr ctTblPr = ctTbl.addNewTblPr();
+ CTTblLayoutType layoutType = ctTblPr.addNewTblLayout();
+ layoutType.setType(STTblLayoutType.FIXED);
+
+ // Now set up a grid for the table, cells will fit into the grid
+ // Each cell width is 3120 in 1440ths of an inch, or 1/3rd of 6.5"
+ BigInteger w = new BigInteger("3120");
+ CTTblGrid grid = ctTbl.addNewTblGrid();
+ for (int i = 0; i < 3; i++) {
+ CTTblGridCol gridCol = grid.addNewGridCol();
+ gridCol.setW(w);
+ }
+
+ // Add paragraphs to the cells
+ XWPFTableRow row = tbl.getRow(0);
+ XWPFTableCell cell = row.getCell(0);
+ XWPFParagraph p = cell.getParagraphArray(0);
+ XWPFRun r = p.createRun();
+ r.setText("header left cell");
+
+ cell = row.getCell(1);
+ p = cell.getParagraphArray(0);
+ r = p.createRun();
+ r.setText("header center cell");
+
+ cell = row.getCell(2);
+ p = cell.getParagraphArray(0);
+ r = p.createRun();
+ r.setText("header right cell");
+
+ // Create a footer with a Paragraph
+ XWPFFooter ftr = doc.createFooter(HeaderFooterType.DEFAULT);
+ p = ftr.createParagraph();
+
+ r = p.createRun();
+ r.setText("footer text");
+
+ try (OutputStream os = new FileOutputStream(new File("headertable.docx"))) {
+ doc.write(os);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xwpf.usermodel;
+
+import java.io.FileOutputStream;
+
+import org.apache.poi.xwpf.usermodel.Borders;
+import org.apache.poi.xwpf.usermodel.BreakClear;
+import org.apache.poi.xwpf.usermodel.BreakType;
+import org.apache.poi.xwpf.usermodel.LineSpacingRule;
+import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
+import org.apache.poi.xwpf.usermodel.TextAlignment;
+import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
+import org.apache.poi.xwpf.usermodel.VerticalAlign;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+
+/**
+ * A simple WOrdprocessingML document created by POI XWPF API
+ */
+public class SimpleDocument {
+
+ public static void main(String[] args) throws Exception {
+ try (XWPFDocument doc = new XWPFDocument()) {
+
+ XWPFParagraph p1 = doc.createParagraph();
+ p1.setAlignment(ParagraphAlignment.CENTER);
+ p1.setBorderBottom(Borders.DOUBLE);
+ p1.setBorderTop(Borders.DOUBLE);
+
+ p1.setBorderRight(Borders.DOUBLE);
+ p1.setBorderLeft(Borders.DOUBLE);
+ p1.setBorderBetween(Borders.SINGLE);
+
+ p1.setVerticalAlignment(TextAlignment.TOP);
+
+ XWPFRun r1 = p1.createRun();
+ r1.setBold(true);
+ r1.setText("The quick brown fox");
+ r1.setBold(true);
+ r1.setFontFamily("Courier");
+ r1.setUnderline(UnderlinePatterns.DOT_DOT_DASH);
+ r1.setTextPosition(100);
+
+ XWPFParagraph p2 = doc.createParagraph();
+ p2.setAlignment(ParagraphAlignment.RIGHT);
+
+ //BORDERS
+ p2.setBorderBottom(Borders.DOUBLE);
+ p2.setBorderTop(Borders.DOUBLE);
+ p2.setBorderRight(Borders.DOUBLE);
+ p2.setBorderLeft(Borders.DOUBLE);
+ p2.setBorderBetween(Borders.SINGLE);
+
+ XWPFRun r2 = p2.createRun();
+ r2.setText("jumped over the lazy dog");
+ r2.setStrikeThrough(true);
+ r2.setFontSize(20);
+
+ XWPFRun r3 = p2.createRun();
+ r3.setText("and went away");
+ r3.setStrikeThrough(true);
+ r3.setFontSize(20);
+ r3.setSubscript(VerticalAlign.SUPERSCRIPT);
+
+ // hyperlink
+ XWPFHyperlinkRun hyperlink = p2.insertNewHyperlinkRun(0, "http://poi.apache.org/");
+ hyperlink.setUnderline(UnderlinePatterns.SINGLE);
+ hyperlink.setColor("0000ff");
+ hyperlink.setText("Apache POI");
+
+ XWPFParagraph p3 = doc.createParagraph();
+ p3.setWordWrapped(true);
+ p3.setPageBreak(true);
+
+ //p3.setAlignment(ParagraphAlignment.DISTRIBUTE);
+ p3.setAlignment(ParagraphAlignment.BOTH);
+ p3.setSpacingBetween(15, LineSpacingRule.EXACT);
+
+ p3.setIndentationFirstLine(600);
+
+
+ XWPFRun r4 = p3.createRun();
+ r4.setTextPosition(20);
+ r4.setText("To be, or not to be: that is the question: "
+ + "Whether 'tis nobler in the mind to suffer "
+ + "The slings and arrows of outrageous fortune, "
+ + "Or to take arms against a sea of troubles, "
+ + "And by opposing end them? To die: to sleep; ");
+ r4.addBreak(BreakType.PAGE);
+ r4.setText("No more; and by a sleep to say we end "
+ + "The heart-ache and the thousand natural shocks "
+ + "That flesh is heir to, 'tis a consummation "
+ + "Devoutly to be wish'd. To die, to sleep; "
+ + "To sleep: perchance to dream: ay, there's the rub; "
+ + ".......");
+ r4.setItalic(true);
+//This would imply that this break shall be treated as a simple line break, and break the line after that word:
+
+ XWPFRun r5 = p3.createRun();
+ r5.setTextPosition(-10);
+ r5.setText("For in that sleep of death what dreams may come");
+ r5.addCarriageReturn();
+ r5.setText("When we have shuffled off this mortal coil, "
+ + "Must give us pause: there's the respect "
+ + "That makes calamity of so long life;");
+ r5.addBreak();
+ r5.setText("For who would bear the whips and scorns of time, "
+ + "The oppressor's wrong, the proud man's contumely,");
+
+ r5.addBreak(BreakClear.ALL);
+ r5.setText("The pangs of despised love, the law's delay, "
+ + "The insolence of office and the spurns " + ".......");
+
+ try (FileOutputStream out = new FileOutputStream("simple.docx")) {
+ doc.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xwpf.usermodel;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
+
+/**
+ *
+ * @author Richard Ngo
+ *
+ */
+public class SimpleDocumentWithHeader {
+
+ public static void main(String[] args) throws IOException {
+ try (XWPFDocument doc = new XWPFDocument()) {
+
+ XWPFParagraph p = doc.createParagraph();
+
+ XWPFRun r = p.createRun();
+ r.setText("Some Text");
+ r.setBold(true);
+ r = p.createRun();
+ r.setText("Goodbye");
+
+ CTP ctP = CTP.Factory.newInstance();
+ CTText t = ctP.addNewR().addNewT();
+ t.setStringValue("header");
+ XWPFParagraph[] pars = new XWPFParagraph[1];
+ p = new XWPFParagraph(ctP, doc);
+ pars[0] = p;
+
+ XWPFHeaderFooterPolicy hfPolicy = doc.createHeaderFooterPolicy();
+ hfPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT, pars);
+
+ ctP = CTP.Factory.newInstance();
+ t = ctP.addNewR().addNewT();
+ t.setStringValue("My Footer");
+ pars[0] = new XWPFParagraph(ctP, doc);
+ hfPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT, pars);
+
+ try (OutputStream os = new FileOutputStream(new File("header.docx"))) {
+ doc.write(os);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xwpf.usermodel;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.util.Units;
+import org.apache.poi.xwpf.usermodel.BreakType;
+import org.apache.poi.xwpf.usermodel.Document;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+
+/**
+ * Demonstrates how to add pictures in a .docx document
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public final class SimpleImages {
+
+ private SimpleImages() {}
+
+ public static void main(String[] args) throws IOException, InvalidFormatException {
+ try (XWPFDocument doc = new XWPFDocument()) {
+ XWPFParagraph p = doc.createParagraph();
+
+ XWPFRun r = p.createRun();
+
+ for (String imgFile : args) {
+ int format;
+
+ if (imgFile.endsWith(".emf")) {
+ format = Document.PICTURE_TYPE_EMF;
+ } else if (imgFile.endsWith(".wmf")) {
+ format = Document.PICTURE_TYPE_WMF;
+ } else if (imgFile.endsWith(".pict")) {
+ format = Document.PICTURE_TYPE_PICT;
+ } else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) {
+ format = Document.PICTURE_TYPE_JPEG;
+ } else if (imgFile.endsWith(".png")) {
+ format = Document.PICTURE_TYPE_PNG;
+ } else if (imgFile.endsWith(".dib")) {
+ format = Document.PICTURE_TYPE_DIB;
+ } else if (imgFile.endsWith(".gif")) {
+ format = Document.PICTURE_TYPE_GIF;
+ } else if (imgFile.endsWith(".tiff")) {
+ format = Document.PICTURE_TYPE_TIFF;
+ } else if (imgFile.endsWith(".eps")) {
+ format = Document.PICTURE_TYPE_EPS;
+ } else if (imgFile.endsWith(".bmp")) {
+ format = Document.PICTURE_TYPE_BMP;
+ } else if (imgFile.endsWith(".wpg")) {
+ format = Document.PICTURE_TYPE_WPG;
+ } else {
+ System.err.println("Unsupported picture: " + imgFile +
+ ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
+ continue;
+ }
+
+ r.setText(imgFile);
+ r.addBreak();
+ try (FileInputStream is = new FileInputStream(imgFile)) {
+ r.addPicture(is, format, imgFile, Units.toEMU(200), Units.toEMU(200)); // 200x200 pixels
+ }
+ r.addBreak(BreakType.PAGE);
+ }
+
+ try (FileOutputStream out = new FileOutputStream("images.docx")) {
+ doc.write(out);
+ }
+ }
+ }
+
+
+}
--- /dev/null
+/* ====================================================================
+ 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.examples.xwpf.usermodel;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.List;
+
+import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
+import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+import org.apache.poi.xwpf.usermodel.XWPFTable;
+import org.apache.poi.xwpf.usermodel.XWPFTableCell;
+import org.apache.poi.xwpf.usermodel.XWPFTableRow;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHeight;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalJc;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.STShd;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
+
+/**
+ * This program creates a simple WordprocessingML table using POI XWPF API, and
+ * a more complex, styled table using both XWPF and ooxml-schema. It's possible
+ * that not all referenced wordprocessingml classes are defined in
+ * poi-ooxml-schemas-3.8-beta4. If this is the case, you'll need to use the full
+ * ooxml-schemas.jar library.
+ *
+ * @author gisella bronzetti (original)
+ * @author Gregg Morris (styled table)
+ */
+public class SimpleTable {
+
+ public static void main(String[] args) throws Exception {
+ try {
+ createSimpleTable();
+ }
+ catch(Exception e) {
+ System.out.println("Error trying to create simple table.");
+ throw(e);
+ }
+ try {
+ createStyledTable();
+ }
+ catch(Exception e) {
+ System.out.println("Error trying to create styled table.");
+ throw(e);
+ }
+ }
+
+ public static void createSimpleTable() throws Exception {
+ try (XWPFDocument doc = new XWPFDocument()) {
+ XWPFTable table = doc.createTable(3, 3);
+
+ table.getRow(1).getCell(1).setText("EXAMPLE OF TABLE");
+
+ // table cells have a list of paragraphs; there is an initial
+ // paragraph created when the cell is created. If you create a
+ // paragraph in the document to put in the cell, it will also
+ // appear in the document following the table, which is probably
+ // not the desired result.
+ XWPFParagraph p1 = table.getRow(0).getCell(0).getParagraphs().get(0);
+
+ XWPFRun r1 = p1.createRun();
+ r1.setBold(true);
+ r1.setText("The quick brown fox");
+ r1.setItalic(true);
+ r1.setFontFamily("Courier");
+ r1.setUnderline(UnderlinePatterns.DOT_DOT_DASH);
+ r1.setTextPosition(100);
+
+ table.getRow(2).getCell(2).setText("only text");
+
+ try (OutputStream out = new FileOutputStream("simpleTable.docx")) {
+ doc.write(out);
+ }
+ }
+ }
+
+ /**
+ * Create a table with some row and column styling. I "manually" add the
+ * style name to the table, but don't check to see if the style actually
+ * exists in the document. Since I'm creating it from scratch, it obviously
+ * won't exist. When opened in MS Word, the table style becomes "Normal".
+ * I manually set alternating row colors. This could be done using Themes,
+ * but that's left as an exercise for the reader. The cells in the last
+ * column of the table have 10pt. "Courier" font.
+ * I make no claims that this is the "right" way to do it, but it worked
+ * for me. Given the scarcity of XWPF examples, I thought this may prove
+ * instructive and give you ideas for your own solutions.
+ */
+ public static void createStyledTable() throws Exception {
+ // Create a new document from scratch
+
+ try (XWPFDocument doc = new XWPFDocument()) {
+ // -- OR --
+ // open an existing empty document with styles already defined
+ //XWPFDocument doc = new XWPFDocument(new FileInputStream("base_document.docx"));
+
+ // Create a new table with 6 rows and 3 columns
+ int nRows = 6;
+ int nCols = 3;
+ XWPFTable table = doc.createTable(nRows, nCols);
+
+ // Set the table style. If the style is not defined, the table style
+ // will become "Normal".
+ CTTblPr tblPr = table.getCTTbl().getTblPr();
+ CTString styleStr = tblPr.addNewTblStyle();
+ styleStr.setVal("StyledTable");
+
+ // Get a list of the rows in the table
+ List<XWPFTableRow> rows = table.getRows();
+ int rowCt = 0;
+ int colCt = 0;
+ for (XWPFTableRow row : rows) {
+ // get table row properties (trPr)
+ CTTrPr trPr = row.getCtRow().addNewTrPr();
+ // set row height; units = twentieth of a point, 360 = 0.25"
+ CTHeight ht = trPr.addNewTrHeight();
+ ht.setVal(BigInteger.valueOf(360));
+
+ // get the cells in this row
+ List<XWPFTableCell> cells = row.getTableCells();
+ // add content to each cell
+ for (XWPFTableCell cell : cells) {
+ // get a table cell properties element (tcPr)
+ CTTcPr tcpr = cell.getCTTc().addNewTcPr();
+ // set vertical alignment to "center"
+ CTVerticalJc va = tcpr.addNewVAlign();
+ va.setVal(STVerticalJc.CENTER);
+
+ // create cell color element
+ CTShd ctshd = tcpr.addNewShd();
+ ctshd.setColor("auto");
+ ctshd.setVal(STShd.CLEAR);
+ if (rowCt == 0) {
+ // header row
+ ctshd.setFill("A7BFDE");
+ } else if (rowCt % 2 == 0) {
+ // even row
+ ctshd.setFill("D3DFEE");
+ } else {
+ // odd row
+ ctshd.setFill("EDF2F8");
+ }
+
+ // get 1st paragraph in cell's paragraph list
+ XWPFParagraph para = cell.getParagraphs().get(0);
+ // create a run to contain the content
+ XWPFRun rh = para.createRun();
+ // style cell as desired
+ if (colCt == nCols - 1) {
+ // last column is 10pt Courier
+ rh.setFontSize(10);
+ rh.setFontFamily("Courier");
+ }
+ if (rowCt == 0) {
+ // header row
+ rh.setText("header row, col " + colCt);
+ rh.setBold(true);
+ para.setAlignment(ParagraphAlignment.CENTER);
+ } else {
+ // other rows
+ rh.setText("row " + rowCt + ", col " + colCt);
+ para.setAlignment(ParagraphAlignment.LEFT);
+ }
+ colCt++;
+ } // for cell
+ colCt = 0;
+ rowCt++;
+ } // for row
+
+ // write the file
+ try (OutputStream out = new FileOutputStream("styledTable.docx")) {
+ doc.write(out);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.examples.xwpf.usermodel;
+
+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.util.List;
+
+import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+
+/**
+ * Tests whether it is possible to successfully update an Excel workbook that is
+ * embedded into a WordprocessingML document. Note that the test has currently
+ * only been conducted with a binary Excel workbook and NOT yet with a
+ * SpreadsheetML workbook embedded into the document.<p>
+ *
+ * This code was successfully tested with the following file from the POI test collection:
+ * http://svn.apache.org/repos/asf/poi/trunk/test-data/document/EmbeddedDocument.docx
+ */
+@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
+public class UpdateEmbeddedDoc {
+
+ private XWPFDocument doc;
+ private File docFile;
+
+ private static final int SHEET_NUM = 0;
+ private static final int ROW_NUM = 0;
+ private static final int CELL_NUM = 0;
+ private static final double NEW_VALUE = 100.98D;
+ private static final String BINARY_EXTENSION = "xls";
+ private static final String OPENXML_EXTENSION = "xlsx";
+
+ /**
+ * Create a new instance of the UpdateEmbeddedDoc class using the following
+ * parameters;
+ *
+ * @param filename An instance of the String class that encapsulates the name
+ * of and path to a WordprocessingML Word document that contains an
+ * embedded binary Excel workbook.
+ * @throws java.io.FileNotFoundException Thrown if the file cannot be found
+ * on the underlying file system.
+ * @throws java.io.IOException Thrown if a problem occurs in the underlying
+ * file system.
+ */
+ public UpdateEmbeddedDoc(String filename) throws FileNotFoundException, IOException {
+ this.docFile = new File(filename);
+ if (!this.docFile.exists()) {
+ throw new FileNotFoundException("The Word document " + filename + " does not exist.");
+ }
+ try (FileInputStream fis = new FileInputStream(this.docFile)) {
+ // Open the Word document file and instantiate the XWPFDocument class.
+ this.doc = new XWPFDocument(fis);
+ }
+ }
+
+ /**
+ * Called to update the embedded Excel workbook. As the format and structure
+ * of the workbook are known in advance, all this code attempts to do is
+ * write a new value into the first cell on the first row of the first
+ * worksheet. Prior to executing this method, that cell will contain the
+ * value 1.
+ *
+ * @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException
+ * Rather
+ * than use the specific classes (HSSF/XSSF) to handle the embedded
+ * workbook this method uses those defined in the SS stream. As
+ * a result, it might be the case that a SpreadsheetML file is
+ * opened for processing, throwing this exception if that file is
+ * invalid.
+ * @throws java.io.IOException Thrown if a problem occurs in the underlying
+ * file system.
+ */
+ public void updateEmbeddedDoc() throws OpenXML4JException, IOException {
+ List<PackagePart> embeddedDocs = this.doc.getAllEmbeddedParts();
+ for (PackagePart pPart : embeddedDocs) {
+ String ext = pPart.getPartName().getExtension();
+ if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) {
+ // Get an InputStream from the package part and pass that
+ // to the create method of the WorkbookFactory class. Update
+ // the resulting Workbook and then stream that out again
+ // using an OutputStream obtained from the same PackagePart.
+ try (InputStream is = pPart.getInputStream();
+ Workbook workbook = WorkbookFactory.create(is);
+ OutputStream os = pPart.getOutputStream()) {
+ Sheet sheet = workbook.getSheetAt(SHEET_NUM);
+ Row row = sheet.getRow(ROW_NUM);
+ Cell cell = row.getCell(CELL_NUM);
+ cell.setCellValue(NEW_VALUE);
+ workbook.write(os);
+ }
+ }
+ }
+
+ if (!embeddedDocs.isEmpty()) {
+ // Finally, write the newly modified Word document out to file.
+ try (FileOutputStream fos = new FileOutputStream(this.docFile)) {
+ this.doc.write(fos);
+ }
+ }
+ }
+
+ /**
+ * Called to test whether or not the embedded workbook was correctly
+ * updated. This method simply recovers the first cell from the first row
+ * of the first workbook and tests the value it contains.
+ * <p>
+ * Note that execution will not continue up to the assertion as the
+ * embedded workbook is now corrupted and causes an IllegalArgumentException
+ * with the following message
+ * <p>
+ * <em>java.lang.IllegalArgumentException: Your InputStream was neither an
+ * OLE2 stream, nor an OOXML stream</em>
+ * <p>
+ * to be thrown when the WorkbookFactory.createWorkbook(InputStream) method
+ * is executed.
+ *
+ * @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException
+ * Rather
+ * than use the specific classes (HSSF/XSSF) to handle the embedded
+ * workbook this method uses those defined in the SS stream. As
+ * a result, it might be the case that a SpreadsheetML file is
+ * opened for processing, throwing this exception if that file is
+ * invalid.
+ * @throws java.io.IOException Thrown if a problem occurs in the underlying
+ * file system.
+ */
+ public void checkUpdatedDoc() throws OpenXML4JException, IOException {
+ for (PackagePart pPart : this.doc.getAllEmbeddedParts()) {
+ String ext = pPart.getPartName().getExtension();
+ if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) {
+ try (InputStream is = pPart.getInputStream();
+ Workbook workbook = WorkbookFactory.create(is)) {
+ Sheet sheet = workbook.getSheetAt(SHEET_NUM);
+ Row row = sheet.getRow(ROW_NUM);
+ Cell cell = row.getCell(CELL_NUM);
+ if(cell.getNumericCellValue() != NEW_VALUE) {
+ throw new IllegalStateException("Failed to validate document content.");
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Code to test updating of the embedded Excel workbook.
+ */
+ public static void main(String[] args) throws IOException, OpenXML4JException {
+ UpdateEmbeddedDoc ued = new UpdateEmbeddedDoc(args[0]);
+ ued.updateEmbeddedDoc();
+ ued.checkUpdatedDoc();
+ }
+}
--- /dev/null
+10 languages with most speakers as first language\r
+countries,speakers,language\r
+58,315,العربية\r
+4,243,বাংলা\r
+38,1299,中文\r
+118,378,English\r
+4,260,हिन्दी\r
+2,128,日本語\r
+15,223,português\r
+6,119,ਪੰਜਾਬੀ\r
+18,154,Русский язык\r
+31,442,español\r
+++ /dev/null
-/* ====================================================================
- 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.hpsf.examples;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-
-import org.apache.poi.hpsf.DocumentSummaryInformation;
-import org.apache.poi.hpsf.HPSFException;
-import org.apache.poi.hpsf.HPSFRuntimeException;
-import org.apache.poi.hpsf.PropertySet;
-import org.apache.poi.hpsf.PropertySetFactory;
-import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.hpsf.WritingNotSupportedException;
-import org.apache.poi.poifs.eventfilesystem.POIFSReader;
-import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
-import org.apache.poi.poifs.filesystem.DirectoryEntry;
-import org.apache.poi.poifs.filesystem.DocumentInputStream;
-import org.apache.poi.poifs.filesystem.EntryUtils;
-import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.util.TempFile;
-
-/**
- * <p>This class copies a POI file system to a new file and compares the copy
- * with the original.</p>
- * <p>
- * <p>Property set streams are copied logically, i.e. the application
- * establishes a {@link org.apache.poi.hpsf.PropertySet} of an original property
- * set, creates a {@link org.apache.poi.hpsf.PropertySet} and writes the
- * {@link org.apache.poi.hpsf.PropertySet} to the destination POI file
- * system. - Streams which are no property set streams are copied bit by
- * bit.</p>
- * <p>
- * <p>The comparison of the POI file systems is done logically. That means that
- * the two disk files containing the POI file systems do not need to be
- * exactly identical. However, both POI file systems must contain the same
- * files, and most of these files must be bitwise identical. Property set
- * streams, however, are compared logically: they must have the same sections
- * with the same attributes, and the sections must contain the same properties.
- * Details like the ordering of the properties do not matter.</p>
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class CopyCompare {
- private CopyCompare() {}
-
- /**
- * Runs the example program. The application expects one or two arguments:
- *
- * <ol>
- * <li>The first argument is the disk file name of the POI filesystem to copy.</li>
- * <li>The second argument is optional. If it is given, it is the name of
- * a disk file the copy of the POI filesystem will be written to. If it is
- * not given, the copy will be written to a temporary file which will be
- * deleted at the end of the program.</li>
- * </ol>
- *
- * @param args Command-line arguments.
- * @throws IOException if any I/O exception occurs.
- * @throws UnsupportedEncodingException if a character encoding is not
- * supported.
- */
- public static void main(final String[] args) throws IOException {
- String originalFileName = null;
- String copyFileName = null;
-
- // Check the command-line arguments.
- if (args.length == 1) {
- originalFileName = args[0];
- File f = TempFile.createTempFile("CopyOfPOIFileSystem-", ".ole2");
- f.deleteOnExit();
- copyFileName = f.getAbsolutePath();
- } else if (args.length == 2) {
- originalFileName = args[0];
- copyFileName = args[1];
- } else {
- System.err.println("Usage: CopyCompare originPOIFS [copyPOIFS]");
- System.exit(1);
- }
-
-
- // Read the origin POIFS using the eventing API.
- final POIFSReader r = new POIFSReader();
- try (final POIFSFileSystem poiFs = new POIFSFileSystem();
- OutputStream fos = new FileOutputStream(copyFileName)) {
- r.registerListener(e -> handleEvent(poiFs, e));
- r.setNotifyEmptyDirectories(true);
-
- r.read(new File(originalFileName));
-
- // Write the new POIFS to disk.
- poiFs.writeFilesystem(fos);
- }
-
- // Read all documents from the original POI file system and compare them with
- // the equivalent document from the copy.
- try (POIFSFileSystem opfs = new POIFSFileSystem(new File(originalFileName));
- POIFSFileSystem cpfs = new POIFSFileSystem(new File(copyFileName))) {
- final DirectoryEntry oRoot = opfs.getRoot();
- final DirectoryEntry cRoot = cpfs.getRoot();
- System.out.println(EntryUtils.areDirectoriesIdentical(oRoot, cRoot) ? "Equal" : "Not equal");
- }
- }
-
- private interface InputStreamSupplier {
- InputStream get() throws IOException, WritingNotSupportedException;
- }
-
- /**
- * The method is called by POI's eventing API for each file in the origin POIFS.
- */
- public static void handleEvent(final POIFSFileSystem poiFs, final POIFSReaderEvent event) {
- // The following declarations are shortcuts for accessing the "event" object.
- final DocumentInputStream stream = event.getStream();
-
- try {
-
- // Find out whether the current document is a property set stream or not.
- InputStreamSupplier su;
- if (stream != null && PropertySet.isPropertySetStream(stream)) {
- // Yes, the current document is a property set stream. Let's create
- // a PropertySet instance from it.
- PropertySet ps = PropertySetFactory.create(stream);
-
- // Copy the property set to the destination POI file system.
- final PropertySet mps;
- if (ps instanceof DocumentSummaryInformation) {
- mps = new DocumentSummaryInformation(ps);
- } else if (ps instanceof SummaryInformation) {
- mps = new SummaryInformation(ps);
- } else {
- mps = new PropertySet(ps);
- }
- su = mps::toInputStream;
- } else {
- // No, the current document is not a property set stream.
- // We copy it unmodified to the destination POIFS.
- su = event::getStream;
- }
-
- try (InputStream is = su.get()) {
- final POIFSDocumentPath path = event.getPath();
-
- // Ensures that the directory hierarchy for a document in a POI fileystem is in place.
- // Get the root directory. It does not have to be created since it always exists in a POIFS.
- DirectoryEntry de = poiFs.getRoot();
- if (File.separator.equals(path.toString())) {
- de.setStorageClsid(event.getStorageClassId());
- }
-
- for (int i=0; i<path.length(); i++) {
- String subDir = path.getComponent(i);
- if (de.hasEntry(subDir)) {
- de = (DirectoryEntry)de.getEntry(subDir);
- } else {
- de = de.createDirectory(subDir);
- if (i == path.length()-1) {
- de.setStorageClsid(event.getStorageClassId());
- }
- }
- }
-
- if (event.getName() != null) {
- de.createDocument(event.getName(), is);
- }
- }
-
- } catch (HPSFException | IOException ex) {
- // According to the definition of the processPOIFSReaderEvent method we cannot pass checked
- // exceptions to the caller.
- throw new HPSFRuntimeException("Could not read file " + event.getPath() + "/" + event.getName(), ex);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hpsf.examples;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.Date;
-
-import org.apache.poi.hpsf.CustomProperties;
-import org.apache.poi.hpsf.DocumentSummaryInformation;
-import org.apache.poi.hpsf.PropertySetFactory;
-import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.poifs.filesystem.DirectoryEntry;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-/**
- * <p>This is a sample application showing how to easily modify properties in
- * the summary information and in the document summary information. The
- * application reads the name of a POI filesystem from the command line and
- * performs the following actions:</p>
- *
- * <ul>
- *
- * <li><p>Open the POI filesystem.</p></li>
- *
- * <li><p>Read the summary information.</p></li>
- *
- * <li><p>Read and print the "author" property.</p></li>
- *
- * <li><p>Change the author to "Rainer Klute".</p></li>
- *
- * <li><p>Read the document summary information.</p></li>
- *
- * <li><p>Read and print the "category" property.</p></li>
- *
- * <li><p>Change the category to "POI example".</p></li>
- *
- * <li><p>Read the custom properties (if available).</p></li>
- *
- * <li><p>Insert a new custom property.</p></li>
- *
- * <li><p>Write the custom properties back to the document summary
- * information.</p></li>
- *
- * <li><p>Write the summary information to the POI filesystem.</p></li>
- *
- * <li><p>Write the document summary information to the POI filesystem.</p></li>
- *
- * <li><p>Write the POI filesystem back to the original file.</p></li>
- *
- * </ol>
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class ModifyDocumentSummaryInformation {
-
- private ModifyDocumentSummaryInformation() {}
-
- /**
- * <p>Main method - see class description.</p>
- *
- * @param args The command-line parameters.
- */
- public static void main(final String[] args) throws Exception {
- /* Read the name of the POI filesystem to modify from the command line.
- * For brevity to boundary check is performed on the command-line
- * arguments. */
- File summaryFile = new File(args[0]);
-
- /* Open the POI filesystem. */
- try (POIFSFileSystem poifs = new POIFSFileSystem(summaryFile, false)) {
-
- /* Read the summary information. */
- DirectoryEntry dir = poifs.getRoot();
- SummaryInformation si;
- try {
- si = (SummaryInformation) PropertySetFactory.create(
- dir, SummaryInformation.DEFAULT_STREAM_NAME);
- } catch (FileNotFoundException ex) {
- // There is no summary information yet. We have to create a new one
- si = PropertySetFactory.newSummaryInformation();
- }
- assert(si != null);
-
- /* Change the author to "Rainer Klute". Any former author value will
- * be lost. If there has been no author yet, it will be created. */
- si.setAuthor("Rainer Klute");
- System.out.println("Author changed to " + si.getAuthor() + ".");
-
-
- /* Handling the document summary information is analogous to handling
- * the summary information. An additional feature, however, are the
- * custom properties. */
-
- /* Read the document summary information. */
- DocumentSummaryInformation dsi;
- try {
- dsi = (DocumentSummaryInformation) PropertySetFactory.create(
- dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
- } catch (FileNotFoundException ex) {
- /* There is no document summary information yet. We have to create a
- * new one. */
- dsi = PropertySetFactory.newDocumentSummaryInformation();
- }
- assert(dsi != null);
-
- /* Change the category to "POI example". Any former category value will
- * be lost. If there has been no category yet, it will be created. */
- dsi.setCategory("POI example");
- System.out.println("Category changed to " + dsi.getCategory() + ".");
-
- /* Read the custom properties. If there are no custom properties yet,
- * the application has to create a new CustomProperties object. It will
- * serve as a container for custom properties. */
- CustomProperties customProperties = dsi.getCustomProperties();
- if (customProperties == null)
- customProperties = new CustomProperties();
-
- /* Insert some custom properties into the container. */
- customProperties.put("Key 1", "Value 1");
- customProperties.put("Schl\u00fcssel 2", "Wert 2");
- customProperties.put("Sample Number", 12345);
- customProperties.put("Sample Boolean", Boolean.TRUE);
- customProperties.put("Sample Date", new Date());
-
- /* Read a custom property. */
- Object value = customProperties.get("Sample Number");
- System.out.println("Custom Sample Number is now " + value);
-
- /* Write the custom properties back to the document summary
- * information. */
- dsi.setCustomProperties(customProperties);
-
- /* Write the summary information and the document summary information
- * to the POI filesystem. */
- si.write(dir, SummaryInformation.DEFAULT_STREAM_NAME);
- dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
-
- /* Write the POI filesystem back to the original file. Please note that
- * in production code you should take care when write directly to the
- * origin, to make sure you don't loose things on error */
- poifs.writeFilesystem();
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hpsf.examples;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.poi.hpsf.HPSFRuntimeException;
-import org.apache.poi.hpsf.NoPropertySetStreamException;
-import org.apache.poi.hpsf.Property;
-import org.apache.poi.hpsf.PropertySet;
-import org.apache.poi.hpsf.PropertySetFactory;
-import org.apache.poi.hpsf.Section;
-import org.apache.poi.poifs.eventfilesystem.POIFSReader;
-import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
-
-/**
- * <p>Sample application showing how to read a document's custom property set.
- * Call it with the document's file name as command-line parameter.</p>
- *
- * <p>Explanations can be found in the HPSF HOW-TO.</p>
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class ReadCustomPropertySets {
-
- private ReadCustomPropertySets() {}
-
- /**
- * <p>Runs the example program.</p>
- *
- * @param args Command-line arguments (unused).
- * @throws IOException if any I/O exception occurs.
- */
- public static void main(final String[] args) throws IOException {
- final String filename = args[0];
- POIFSReader r = new POIFSReader();
-
- /* Register a listener for *all* documents. */
- r.registerListener(ReadCustomPropertySets::processPOIFSReaderEvent);
- r.read(new File(filename));
- }
-
-
- public static void processPOIFSReaderEvent(final POIFSReaderEvent event) {
- final String streamName = event.getPath() + event.getName();
- PropertySet ps;
- try {
- ps = PropertySetFactory.create(event.getStream());
- } catch (NoPropertySetStreamException ex) {
- out("No property set stream: \"" + streamName + "\"");
- return;
- } catch (Exception ex) {
- throw new HPSFRuntimeException("Property set stream \"" + streamName + "\": " + ex);
- }
-
- /* Print the name of the property set stream: */
- out("Property set stream \"" + streamName + "\":");
-
- /* Print the number of sections: */
- final long sectionCount = ps.getSectionCount();
- out(" No. of sections: " + sectionCount);
-
- /* Print the list of sections: */
- List<Section> sections = ps.getSections();
- int nr = 0;
- for (Section sec : sections) {
- /* Print a single section: */
- out(" Section " + nr++ + ":");
- String s = sec.getFormatID().toString();
- s = s.substring(0, s.length() - 1);
- out(" Format ID: " + s);
-
- /* Print the number of properties in this section. */
- int propertyCount = sec.getPropertyCount();
- out(" No. of properties: " + propertyCount);
-
- /* Print the properties: */
- Property[] properties = sec.getProperties();
- for (Property p : properties) {
- /* Print a single property: */
- long id = p.getID();
- long type = p.getType();
- Object value = p.getValue();
- out(" Property ID: " + id + ", type: " + type +
- ", value: " + value);
- }
- }
- }
-
- private static void out(final String msg) {
- System.out.println(msg);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hpsf.examples;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.poi.hpsf.PropertySetFactory;
-import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.poifs.eventfilesystem.POIFSReader;
-import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
-
-/**
- * <p>Sample application showing how to read a OLE 2 document's
- * title. Call it with the document's file name as command line
- * parameter.</p>
- *
- * <p>Explanations can be found in the HPSF HOW-TO.</p>
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class ReadTitle {
- private ReadTitle() {}
-
- /**
- * <p>Runs the example program.</p>
- *
- * @param args Command-line arguments. The first command-line argument must
- * be the name of a POI filesystem to read.
- * @throws IOException if any I/O exception occurs.
- */
- public static void main(final String[] args) throws IOException {
- final String filename = args[0];
- POIFSReader r = new POIFSReader();
- r.registerListener(ReadTitle::processPOIFSReaderEvent, SummaryInformation.DEFAULT_STREAM_NAME);
- r.read(new File(filename));
- }
-
-
- private static void processPOIFSReaderEvent(final POIFSReaderEvent event) {
- SummaryInformation si;
- try {
- si = (SummaryInformation) PropertySetFactory.create(event.getStream());
- } catch (Exception ex) {
- throw new RuntimeException("Property set stream \"" + event.getPath() + event.getName() + "\": " + ex);
- }
- final String title = si.getTitle();
- System.out.println(title != null ? "Title: \"" + title + "\"" : "Document has no title.");
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hpsf.examples;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.poi.hpsf.HPSFRuntimeException;
-import org.apache.poi.hpsf.MarkUnsupportedException;
-import org.apache.poi.hpsf.NoPropertySetStreamException;
-import org.apache.poi.hpsf.PropertySet;
-import org.apache.poi.hpsf.PropertySetFactory;
-import org.apache.poi.hpsf.Section;
-import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.hpsf.Variant;
-import org.apache.poi.hpsf.WritingNotSupportedException;
-import org.apache.poi.hpsf.wellknown.PropertyIDMap;
-import org.apache.poi.poifs.eventfilesystem.POIFSReader;
-import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
-import org.apache.poi.poifs.filesystem.DirectoryEntry;
-import org.apache.poi.poifs.filesystem.DocumentInputStream;
-import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-/**
- * <p>This class is a sample application which shows how to write or modify the
- * author and title property of an OLE 2 document. This could be done in two
- * different ways:</p>
- *
- * <ul>
- *
- * <li><p>The first approach is to open the OLE 2 file as a POI filesystem
- * (see class {@link POIFSFileSystem}), read the summary information property
- * set (see classes {@link SummaryInformation} and {@link PropertySet}), write
- * the author and title properties into it and write the property set back into
- * the POI filesystem.</p></li>
- *
- * <li><p>The second approach does not modify the original POI filesystem, but
- * instead creates a new one. All documents from the original POIFS are copied
- * to the destination POIFS, except for the summary information stream. The
- * latter is modified by setting the author and title property before writing
- * it to the destination POIFS. It there are several summary information streams
- * in the original POIFS - e.g. in subordinate directories - they are modified
- * just the same.</p></li>
- *
- * </ul>
- *
- * <p>This sample application takes the second approach. It expects the name of
- * the existing POI filesystem's name as its first command-line parameter and
- * the name of the output POIFS as the second command-line argument. The
- * program then works as described above: It copies nearly all documents
- * unmodified from the input POI filesystem to the output POI filesystem. If it
- * encounters a summary information stream it reads its properties. Then it sets
- * the "author" and "title" properties to new values and writes the modified
- * summary information stream into the output file.</p>
- *
- * <p>Further explanations can be found in the HPSF HOW-TO.</p>
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class WriteAuthorAndTitle {
- private WriteAuthorAndTitle() {}
-
- /**
- * <p>Runs the example program.</p>
- *
- * @param args Command-line arguments. The first command-line argument must
- * be the name of a POI filesystem to read.
- * @throws IOException if any I/O exception occurs.
- */
- public static void main(final String[] args) throws IOException {
- /* Check whether we have exactly two command-line arguments. */
- if (args.length != 2) {
- System.err.println("Usage: WriteAuthorAndTitle originPOIFS destinationPOIFS");
- System.exit(1);
- }
-
- /* Read the names of the origin and destination POI filesystems. */
- final String srcName = args[0];
- final String dstName = args[1];
-
- /* Read the origin POIFS using the eventing API. The real work is done
- * in the class ModifySICopyTheRest which is registered here as a
- * POIFSReader. */
- try (POIFSFileSystem poifs = new POIFSFileSystem();
- OutputStream out = new FileOutputStream(dstName)) {
- final POIFSReader r = new POIFSReader();
- r.registerListener(e -> handleEvent(poifs, e));
- r.read(new File(srcName));
-
- /* Write the new POIFS to disk. */
- poifs.writeFilesystem(out);
- }
- }
-
- private interface InputStreamSupplier {
- InputStream get() throws IOException, WritingNotSupportedException;
- }
-
- /**
- * The method is called by POI's eventing API for each file in the origin POIFS.
- */
- private static void handleEvent(final POIFSFileSystem poiFs, final POIFSReaderEvent event) {
- // The following declarations are shortcuts for accessing the "event" object.
- final DocumentInputStream stream = event.getStream();
-
- try {
- final InputStreamSupplier isSup;
-
- // Find out whether the current document is a property set stream or not.
- if (PropertySet.isPropertySetStream(stream)) {
- // Yes, the current document is a property set stream. Let's create a PropertySet instance from it.
- PropertySet ps = PropertySetFactory.create(stream);
-
- // Now we know that we really have a property set.
- // The next step is to find out whether it is a summary information or not.
- if (ps.isSummaryInformation()) {
- // Create a mutable property set as a copy of the original read-only property set.
- ps = new PropertySet(ps);
-
- // Retrieve the section containing the properties to modify.
- // A summary information property set contains exactly one section.
- final Section s = ps.getSections().get(0);
-
- // Set the properties.
- s.setProperty(PropertyIDMap.PID_AUTHOR, Variant.VT_LPSTR, "Rainer Klute");
- s.setProperty(PropertyIDMap.PID_TITLE, Variant.VT_LPWSTR, "Test");
- }
-
- isSup = ps::toInputStream;
- } else {
- // No, the current document is not a property set stream. We copy it unmodified to the destination POIFS.
- isSup = event::getStream;
- }
-
- try (InputStream is = isSup.get()) {
- final POIFSDocumentPath path = event.getPath();
-
- // Ensures that the directory hierarchy for a document in a POI fileystem is in place.
- // Get the root directory. It does not have to be created since it always exists in a POIFS.
- DirectoryEntry de = poiFs.getRoot();
-
- for (int i=0; i<path.length(); i++) {
- String subDir = path.getComponent(i);
- de = (de.hasEntry(subDir)) ? (DirectoryEntry)de.getEntry(subDir) : de.createDirectory(subDir);
- }
-
- de.createDocument(event.getName(), is);
- }
-
- } catch (MarkUnsupportedException | WritingNotSupportedException | IOException | NoPropertySetStreamException ex) {
- // According to the definition of the processPOIFSReaderEvent method we cannot pass checked
- // exceptions to the caller.
- throw new HPSFRuntimeException("Could not read file " + event.getPath() + "/" + event.getName(), ex);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hpsf.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.hpsf.Property;
-import org.apache.poi.hpsf.PropertySet;
-import org.apache.poi.hpsf.Section;
-import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.hpsf.Variant;
-import org.apache.poi.hpsf.WritingNotSupportedException;
-import org.apache.poi.hpsf.wellknown.PropertyIDMap;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-/**
- * <p>This class is a simple sample application showing how to create a property
- * set and write it to disk.</p>
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class WriteTitle {
-
- private WriteTitle() {}
-
- /**
- * <p>Runs the example program.</p>
- *
- * @param args Command-line arguments. The first and only command-line
- * argument is the name of the POI file system to create.
- * @throws IOException if any I/O exception occurs.
- * @throws WritingNotSupportedException if HPSF does not (yet) support
- * writing a certain property type.
- */
- public static void main(final String[] args)
- throws WritingNotSupportedException, IOException
- {
- /* Check whether we have exactly one command-line argument. */
- if (args.length != 1)
- {
- System.err.println("Usage: " + WriteTitle.class.getName() + "destinationPOIFS");
- System.exit(1);
- }
-
- final String fileName = args[0];
-
- /* Create a mutable property set. Initially it contains a single section
- * with no properties. */
- final PropertySet mps = new PropertySet();
-
- /* Retrieve the section the property set already contains. */
- final Section ms = mps.getSections().get(0);
-
- /* Turn the property set into a summary information property. This is
- * done by setting the format ID of its first section to
- * SectionIDMap.SUMMARY_INFORMATION_ID. */
- ms.setFormatID(SummaryInformation.FORMAT_ID);
-
- /* Create an empty property. */
- final Property p = new Property();
-
- /* Fill the property with appropriate settings so that it specifies the
- * document's title. */
- p.setID(PropertyIDMap.PID_TITLE);
- p.setType(Variant.VT_LPWSTR);
- p.setValue("Sample title");
-
- /* Place the property into the section. */
- ms.setProperty(p);
-
- /* Create the POI file system the property set is to be written to.
- * For writing the property set into a POI file system it has to be
- * handed over to the POIFS.createDocument() method as an input stream
- * which produces the bytes making out the property set stream. */
- try (final POIFSFileSystem poiFs = new POIFSFileSystem();
- final InputStream is = mps.toInputStream();
- final FileOutputStream fos = new FileOutputStream(fileName)) {
-
- /* Create the summary information property set in the POI file
- * system. It is given the default name most (if not all) summary
- * information property sets have. */
- poiFs.createDocument(is, SummaryInformation.DEFAULT_STREAM_NAME);
-
- /* Write the whole POI file system to a disk file. */
- poiFs.writeFilesystem(fos);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.geom.Rectangle2D;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.sl.draw.DrawTableShape;
-import org.apache.poi.sl.draw.SLGraphics;
-import org.apache.poi.sl.usermodel.AutoShape;
-import org.apache.poi.sl.usermodel.GroupShape;
-import org.apache.poi.sl.usermodel.ShapeType;
-import org.apache.poi.sl.usermodel.Slide;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.sl.usermodel.TableCell;
-import org.apache.poi.sl.usermodel.TableShape;
-import org.apache.poi.sl.usermodel.TextBox;
-import org.apache.poi.sl.usermodel.TextParagraph;
-import org.apache.poi.sl.usermodel.TextRun;
-import org.apache.poi.sl.usermodel.TextShape.TextPlaceholder;
-import org.apache.poi.sl.usermodel.VerticalAlignment;
-
-/**
- * Presentation for Fast Feather Track on ApacheconEU 2008
- *
- * @author Yegor Kozlov
- */
-@SuppressWarnings("java:S1192")
-public final class ApacheconEU08 {
-
- private ApacheconEU08() {}
-
- public static void main(String[] args) throws IOException {
- // use HSLFSlideShow or XMLSlideShow
- try (SlideShow<?,?> ppt = new HSLFSlideShow()) {
- ppt.setPageSize(new Dimension(720, 540));
-
- slide1(ppt);
- slide2(ppt);
- slide3(ppt);
- slide4(ppt);
- slide5(ppt);
- slide6(ppt);
- slide7(ppt);
- slide8(ppt);
- slide9(ppt);
- slide10(ppt);
- slide11(ppt);
- slide12(ppt);
-
- String ext = ppt.getClass().getName().contains("HSLF") ? "ppt" : "pptx";
- try (FileOutputStream out = new FileOutputStream("apachecon_eu_08." + ext)) {
- ppt.write(out);
- }
- }
- }
-
- public static void slide1(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.CENTER_TITLE);
- box1.setText("POI-HSLF");
- box1.setAnchor(new Rectangle(54, 78, 612, 115));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.setTextPlaceholder(TextPlaceholder.CENTER_BODY);
- box2.setText("Java API To Access Microsoft PowerPoint Format Files");
- box2.setAnchor(new Rectangle(108, 204, 504, 138));
-
- TextBox<?,?> box3 = slide.createTextBox();
- box3.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(32d);
- box3.setText(
- "Yegor Kozlov\r" +
- "yegor - apache - org");
- box3.setHorizontalCentered(true);
- box3.setAnchor(new Rectangle(206, 348, 310, 84));
- }
-
- public static void slide2(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.TITLE);
- box1.setText("What is HSLF?");
- box1.setAnchor(new Rectangle(36, 21, 648, 90));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.setTextPlaceholder(TextPlaceholder.BODY);
- box2.setText("HorribleSLideshowFormat is the POI Project's pure Java implementation " +
- "of the Powerpoint binary file format. \r" +
- "POI sub-project since 2005\r" +
- "Started by Nick Burch, Yegor Kozlov joined soon after");
- box2.setAnchor(new Rectangle(36, 126, 648, 356));
- }
-
- public static void slide3(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.TITLE);
- box1.setText("HSLF in a Nutshell");
- box1.setAnchor(new Rectangle(36, 15, 648, 65));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.setTextPlaceholder(TextPlaceholder.BODY);
- box2.setText(
- "HSLF provides a way to read, create and modify MS PowerPoint presentations\r" +
- "Pure Java API - you don't need PowerPoint to read and write *.ppt files\r" +
- "Comprehensive support of PowerPoint objects\r" +
- "Rich text\r" +
- "Tables\r" +
- "Shapes\r" +
- "Pictures\r" +
- "Master slides\r" +
- "Access to low level data structures"
- );
-
- List<? extends TextParagraph<?,?,?>> tp = box2.getTextParagraphs();
- for (int i : new byte[]{0,1,2,8}) {
- tp.get(i).getTextRuns().get(0).setFontSize(28d);
- }
- for (int i : new byte[]{3,4,5,6,7}) {
- tp.get(i).getTextRuns().get(0).setFontSize(24d);
- tp.get(i).setIndentLevel(1);
- }
- box2.setAnchor(new Rectangle(36, 80, 648, 400));
- }
-
- public static void slide4(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- String[][] txt1 = {
- {"Note"},
- {"This presentation was created programmatically using POI HSLF"}
- };
- TableShape<?,?> table1 = slide.createTable(2, 1);
- for (int i = 0; i < txt1.length; i++) {
- for (int j = 0; j < txt1[i].length; j++) {
- TableCell<?,?> cell = table1.getCell(i, j);
- cell.setText(txt1[i][j]);
- TextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
- rt.setFontSize(10d);
- rt.setFontFamily("Arial");
- rt.setBold(true);
- if(i == 0){
- rt.setFontSize(32d);
- rt.setFontColor(Color.white);
- cell.setFillColor(new Color(0, 153, 204));
- } else {
- rt.setFontSize(28d);
- cell.setFillColor(new Color(235, 239, 241));
- }
- cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
- }
- }
-
- DrawTableShape dts = new DrawTableShape(table1);
- dts.setAllBorders(1.0, Color.black);
- dts.setOutsideBorders(4.0);
-
- table1.setColumnWidth(0, 450);
- table1.setRowHeight(0, 50);
- table1.setRowHeight(1, 80);
-
- Dimension dim = ppt.getPageSize();
- Rectangle2D oldAnchor = table1.getAnchor();
- table1.setAnchor(new Rectangle2D.Double((dim.width-450)/2d, 100, oldAnchor.getWidth(), oldAnchor.getHeight()));
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setHorizontalCentered(true);
- box1.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(24d);
- box1.setText("The source code is available at\r" +
- "http://people.apache.org/~yegor/apachecon_eu08/");
- box1.setAnchor(new Rectangle(80, 356, 553, 65));
- }
-
- public static void slide5(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.TITLE);
- box1.setText("HSLF in Action - 1\rData Extraction");
- box1.setAnchor(new Rectangle(36, 21, 648, 100));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.setTextPlaceholder(TextPlaceholder.BODY);
- box2.setText(
- "Text from slides and notes\r" +
- "Images\r" +
- "Shapes and their properties (type, position in the slide, color, font, etc.)");
- box2.setAnchor(new Rectangle(36, 150, 648, 300));
- }
-
- public static void slide6(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.TITLE);
- box1.setText("HSLF in Action - 2");
- box1.setAnchor(new Rectangle(36, 20, 648, 90));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18d);
- box2.setText("Creating a simple presentation from scratch");
- box2.setAnchor(new Rectangle(170, 100, 364, 30));
-
- TextBox<?,?> box3 = slide.createTextBox();
- TextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
- rt3.setFontFamily("Courier New");
- rt3.setFontSize(8d);
- box3.setText(
- "SlideShow ppt = new SlideShow();\u000b" +
- "Slide slide = ppt.createSlide();\u000b" +
- "\u000b" +
- "TextBox box2 = new TextBox();\u000b" +
- "box2.setHorizontalAlignment(TextBox.AlignCenter);\u000b" +
- "box2.setVerticalAlignment(TextBox.AnchorMiddle);\u000b" +
- "box2.getTextRun().setText(\"Java Code\");\u000b" +
- "box2.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
- "box2.setLineColor(Color.black);\u000b" +
- "box2.setLineWidth(0.75);\u000b" +
- "box2.setAnchor(new Rectangle(66, 243, 170, 170));\u000b" +
- "slide.addShape(box2);\u000b" +
- "\u000b" +
- "TextBox box3 = new TextBox();\u000b" +
- "box3.setHorizontalAlignment(TextBox.AlignCenter);\u000b" +
- "box3.setVerticalAlignment(TextBox.AnchorMiddle);\u000b" +
- "box3.getTextRun().setText(\"*.ppt file\");\u000b" +
- "box3.setLineWidth(0.75);\u000b" +
- "box3.setLineColor(Color.black);\u000b" +
- "box3.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
- "box3.setAnchor(new Rectangle(473, 243, 170, 170));\u000b" +
- "slide.addShape(box3);\u000b" +
- "\u000b" +
- "AutoShape box4 = new AutoShape(ShapeTypes.Arrow);\u000b" +
- "box4.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
- "box4.setLineWidth(0.75);\u000b" +
- "box4.setLineColor(Color.black);\u000b" +
- "box4.setAnchor(new Rectangle(253, 288, 198, 85));\u000b" +
- "slide.addShape(box4);\u000b" +
- "\u000b" +
- "FileOutputStream out = new FileOutputStream(\"hslf-demo.ppt\");\u000b" +
- "ppt.write(out);\u000b" +
- "out.close();");
- box3.setAnchor(new Rectangle(30, 150, 618, 411));
- box3.setHorizontalCentered(true);
- }
-
- public static void slide7(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.setHorizontalCentered(true);
- box2.setVerticalAlignment(VerticalAlignment.MIDDLE);
- box2.setText("Java Code");
- box2.setFillColor(new Color(187, 224, 227));
- box2.setStrokeStyle(0.75, Color.black);
- box2.setAnchor(new Rectangle(66, 243, 170, 170));
-
- TextBox<?,?> box3 = slide.createTextBox();
- box3.setHorizontalCentered(true);
- box3.setVerticalAlignment(VerticalAlignment.MIDDLE);
- box3.setText("*.ppt file");
- box3.setFillColor(new Color(187, 224, 227));
- box3.setStrokeStyle(0.75, Color.black);
- box3.setAnchor(new Rectangle(473, 243, 170, 170));
-
- AutoShape<?,?> box4 = slide.createAutoShape();
- box4.setShapeType(ShapeType.RIGHT_ARROW);
- box4.setFillColor(new Color(187, 224, 227));
- box4.setStrokeStyle(0.75, Color.black);
- box4.setAnchor(new Rectangle(253, 288, 198, 85));
- }
-
- public static void slide8(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.TITLE);
- box1.setText("Wait, there is more!");
- box1.setAnchor(new Rectangle(36, 21, 648, 90));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.setTextPlaceholder(TextPlaceholder.BODY);
- box2.setText(
- "Rich text\r" +
- "Tables\r" +
- "Pictures (JPEG, PNG, BMP, WMF, PICT)\r" +
- "Comprehensive formatting features");
- box2.setAnchor(new Rectangle(36, 126, 648, 356));
- }
-
- public static void slide9(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.TITLE);
- box1.setText("HSLF in Action - 3");
- box1.setAnchor(new Rectangle(36, 20, 648, 50));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18d);
- box2.setText("PPGraphics2D: PowerPoint Graphics2D driver");
- box2.setAnchor(new Rectangle(178, 70, 387, 30));
-
- TextBox<?,?> box3 = slide.createTextBox();
- TextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
- rt3.setFontFamily("Courier New");
- rt3.setFontSize(8d);
- box3.setText(
- "//bar chart data. The first value is the bar color, the second is the width\u000b" +
- "Object[] def = new Object[]{\u000b" +
- " Color.yellow, new Integer(100),\u000b" +
- " Color.green, new Integer(150),\u000b" +
- " Color.gray, new Integer(75),\u000b" +
- " Color.red, new Integer(200),\u000b" +
- "};\u000b" +
- "\u000b" +
- "SlideShow ppt = new SlideShow();\u000b" +
- "Slide slide = ppt.createSlide();\u000b" +
- "\u000b" +
- "ShapeGroup group = new ShapeGroup();\u000b" +
- "//define position of the drawing in the slide\u000b" +
- "Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);\u000b" +
- "group.setAnchor(bounds);\u000b" +
- "slide.addShape(group);\u000b" +
- "Graphics2D graphics = new PPGraphics2D(group);\u000b" +
- "\u000b" +
- "//draw a simple bar graph\u000b" +
- "int x = bounds.x + 50, y = bounds.y + 50;\u000b" +
- "graphics.setFont(new Font(\"Arial\", Font.BOLD, 10));\u000b" +
- "for (int i = 0, idx = 1; i < def.length; i+=2, idx++) {\u000b" +
- " graphics.setColor(Color.black);\u000b" +
- " int width = ((Integer)def[i+1]).intValue();\u000b" +
- " graphics.drawString(\"Q\" + idx, x-20, y+20);\u000b" +
- " graphics.drawString(width + \"%\", x + width + 10, y + 20);\u000b" +
- " graphics.setColor((Color)def[i]);\u000b" +
- " graphics.fill(new Rectangle(x, y, width, 30));\u000b" +
- " y += 40;\u000b" +
- "}\u000b" +
- "graphics.setColor(Color.black);\u000b" +
- "graphics.setFont(new Font(\"Arial\", Font.BOLD, 14));\u000b" +
- "graphics.draw(bounds);\u000b" +
- "graphics.drawString(\"Performance\", x + 70, y + 40);\u000b" +
- "\u000b" +
- "FileOutputStream out = new FileOutputStream(\"hslf-demo.ppt\");\u000b" +
- "ppt.write(out);\u000b" +
- "out.close();");
- box3.setAnchor(new Rectangle(96, 110, 499, 378));
- box3.setHorizontalCentered(true);
- }
-
- public static void slide10(SlideShow<?,?> ppt) throws IOException {
- //bar chart data. The first value is the bar color, the second is the width
- Object[] def = new Object[]{
- Color.yellow, 100,
- Color.green, 150,
- Color.gray, 75,
- Color.red, 200,
- };
-
- Slide<?,?> slide = ppt.createSlide();
-
- GroupShape<?,?> group = slide.createGroup();
- //define position of the drawing in the slide
- Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);
- group.setAnchor(bounds);
- Graphics2D graphics = new SLGraphics(group);
-
- //draw a simple bar graph
- int x = bounds.x + 50;
- int y = bounds.y + 50;
- graphics.setFont(new Font("Arial", Font.BOLD, 10));
- for (int i = 0, idx = 1; i < def.length; i+=2, idx++) {
- graphics.setColor(Color.black);
- int width = (Integer) def[i + 1];
- graphics.drawString("Q" + idx, x-20, y+20);
- graphics.drawString(width + "%", x + width + 10, y + 20);
- graphics.setColor((Color)def[i]);
- graphics.fill(new Rectangle(x, y, width, 30));
- y += 40;
- }
- graphics.setColor(Color.black);
- graphics.setFont(new Font("Arial", Font.BOLD, 14));
- graphics.draw(bounds);
- graphics.drawString("Performance", x + 70, y + 40);
-
- }
-
- public static void slide11(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.TITLE);
- box1.setText("HSLF Development Plans");
- box1.setAnchor(new Rectangle(36, 21, 648, 90));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.setTextPlaceholder(TextPlaceholder.BODY);
- box2.setText(
- "Support for more PowerPoint functionality\r" +
- "Rendering slides into java.awt.Graphics2D\r" +
- "A way to export slides into images or other formats\r" +
- "Integration with Apache FOP - Formatting Objects Processor\r" +
- "Transformation of XSL-FO into PPT\r" +
- "PPT2PDF transcoder"
- );
-
- List<? extends TextParagraph<?,?,?>> tp = box2.getTextParagraphs();
- for (int i : new byte[]{0,1,3}) {
- tp.get(i).getTextRuns().get(0).setFontSize(28d);
- }
- for (int i : new byte[]{2,4,5}) {
- tp.get(i).getTextRuns().get(0).setFontSize(24d);
- tp.get(i).setIndentLevel(1);
- }
-
- box2.setAnchor(new Rectangle(36, 126, 648, 400));
- }
-
- public static void slide12(SlideShow<?,?> ppt) throws IOException {
- Slide<?,?> slide = ppt.createSlide();
-
- TextBox<?,?> box1 = slide.createTextBox();
- box1.setTextPlaceholder(TextPlaceholder.CENTER_TITLE);
- box1.setText("Questions?");
- box1.setAnchor(new Rectangle(54, 167, 612, 115));
-
- TextBox<?,?> box2 = slide.createTextBox();
- box2.setTextPlaceholder(TextPlaceholder.CENTER_BODY);
- box2.setText(
- "https://poi.apache.org/hslf/\r" +
- "http://people.apache.org/~yegor");
- box2.setAnchor(new Rectangle(108, 306, 504, 138));
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hslf.usermodel.HSLFSlide;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFTextBox;
-import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
-
-/**
- * How to create a single-level bulleted list
- * and change some of the bullet attributes
- */
-public final class BulletsDemo {
-
- public static void main(String[] args) throws IOException {
- try (HSLFSlideShow ppt = new HSLFSlideShow()) {
- HSLFSlide slide = ppt.createSlide();
-
- HSLFTextBox shape = new HSLFTextBox();
- HSLFTextParagraph rt = shape.getTextParagraphs().get(0);
- rt.getTextRuns().get(0).setFontSize(42d);
- rt.setBullet(true);
- rt.setIndent(0d); //bullet offset
- rt.setLeftMargin(50d); //text offset (should be greater than bullet offset)
- rt.setBulletChar('\u263A'); //bullet character
- shape.setText(
- "January\r" +
- "February\r" +
- "March\r" +
- "April");
- slide.addShape(shape);
-
- shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); //position of the text box in the slide
- slide.addShape(shape);
-
- try (FileOutputStream out = new FileOutputStream("bullets.ppt")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-
-import java.awt.Rectangle;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hslf.usermodel.HSLFHyperlink;
-import org.apache.poi.hslf.usermodel.HSLFSlide;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFTextBox;
-
-/**
- * Demonstrates how to create hyperlinks in PowerPoint presentations
- */
-public final class CreateHyperlink {
-
- private CreateHyperlink() {}
-
- public static void main(String[] args) throws IOException {
- try (HSLFSlideShow ppt = new HSLFSlideShow()) {
- HSLFSlide slideA = ppt.createSlide();
- ppt.createSlide();
- HSLFSlide slideC = ppt.createSlide();
-
- // link to a URL
- HSLFTextBox textBox1 = slideA.createTextBox();
- textBox1.setText("Apache POI");
- textBox1.setAnchor(new Rectangle(100, 100, 200, 50));
-
- HSLFHyperlink link1 = textBox1.getTextParagraphs().get(0).getTextRuns().get(0).createHyperlink();
- link1.linkToUrl("http://www.apache.org");
- link1.setLabel(textBox1.getText());
-
- // link to another slide
- HSLFTextBox textBox2 = slideA.createTextBox();
- textBox2.setText("Go to slide #3");
- textBox2.setAnchor(new Rectangle(100, 300, 200, 50));
-
- HSLFHyperlink link2 = textBox2.getTextParagraphs().get(0).getTextRuns().get(0).createHyperlink();
- link2.linkToSlide(slideC);
-
- try (FileOutputStream out = new FileOutputStream("hyperlink.ppt")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.hslf.usermodel.HSLFObjectData;
-import org.apache.poi.hslf.usermodel.HSLFObjectShape;
-import org.apache.poi.hslf.usermodel.HSLFPictureData;
-import org.apache.poi.hslf.usermodel.HSLFPictureShape;
-import org.apache.poi.hslf.usermodel.HSLFShape;
-import org.apache.poi.hslf.usermodel.HSLFSlide;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFSoundData;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hwpf.HWPFDocument;
-import org.apache.poi.hwpf.usermodel.Paragraph;
-import org.apache.poi.hwpf.usermodel.Range;
-import org.apache.poi.util.IOUtils;
-
-/**
- * Demonstrates how you can extract misc embedded data from a ppt file
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class DataExtraction {
-
- private DataExtraction() {}
-
- public static void main(String[] args) throws Exception {
-
- if (args.length == 0) {
- usage();
- return;
- }
-
- try (FileInputStream fis = new FileInputStream(args[0]);
- HSLFSlideShow ppt = new HSLFSlideShow(fis)) {
-
- //extract all sound files embedded in this presentation
- HSLFSoundData[] sound = ppt.getSoundData();
- for (HSLFSoundData aSound : sound) {
- handleSound(aSound);
- }
-
- int oleIdx = -1;
- int picIdx = -1;
- for (HSLFSlide slide : ppt.getSlides()) {
- //extract embedded OLE documents
- for (HSLFShape shape : slide.getShapes()) {
- if (shape instanceof HSLFObjectShape) {
- handleShape((HSLFObjectShape) shape, ++oleIdx);
- } else if (shape instanceof HSLFPictureShape) {
- handlePicture((HSLFPictureShape) shape, ++picIdx);
- }
- }
- }
- }
- }
-
- private static void handleShape(HSLFObjectShape ole, int oleIdx) throws IOException {
- HSLFObjectData data = ole.getObjectData();
- String name = ole.getInstanceName();
- switch (name == null ? "" : name) {
- case "Worksheet":
- //read xls
- handleWorkbook(data, name, oleIdx);
- break;
- case "Document":
- //read the word document
- handleDocument(data, name, oleIdx);
- break;
- default:
- handleUnknown(data, ole.getProgId(), oleIdx);
- break;
- }
-
- }
-
- private static void handleWorkbook(HSLFObjectData data, String name, int oleIdx) throws IOException {
- try (InputStream is = data.getInputStream();
- HSSFWorkbook wb = new HSSFWorkbook(is);
- FileOutputStream out = new FileOutputStream(name + "-(" + (oleIdx) + ").xls")) {
- wb.write(out);
- }
- }
-
- private static void handleDocument(HSLFObjectData data, String name, int oleIdx) throws IOException {
- try (InputStream is = data.getInputStream();
- HWPFDocument doc = new HWPFDocument(is);
- FileOutputStream out = new FileOutputStream(name + "-(" + (oleIdx) + ").doc")) {
- Range r = doc.getRange();
- for (int k = 0; k < r.numParagraphs(); k++) {
- Paragraph p = r.getParagraph(k);
- System.out.println(p.text());
- }
-
- //save on disk
- doc.write(out);
- }
- }
-
- private static void handleUnknown(HSLFObjectData data, String name, int oleIdx) throws IOException {
- try (InputStream is = data.getInputStream();
- FileOutputStream out = new FileOutputStream(name + "-" + (oleIdx + 1) + ".dat")) {
- IOUtils.copy(is, out);
- }
- }
-
- private static void handlePicture(HSLFPictureShape p, int picIdx) throws IOException {
- HSLFPictureData data = p.getPictureData();
- String ext = data.getType().extension;
- try (FileOutputStream out = new FileOutputStream("pict-" + picIdx + ext)) {
- out.write(data.getData());
- }
- }
-
- private static void handleSound(HSLFSoundData aSound) throws IOException {
- String type = aSound.getSoundType(); //*.wav
- String name = aSound.getSoundName(); //typically file name
-
- //save the sound on disk
- try (FileOutputStream out = new FileOutputStream(name + type)) {
- out.write(aSound.getData());
- }
- }
-
- private static void usage(){
- System.out.println("Usage: DataExtraction ppt");
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.io.FileOutputStream;
-
-import org.apache.poi.hslf.usermodel.HSLFGroupShape;
-import org.apache.poi.hslf.usermodel.HSLFSlide;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.sl.draw.SLGraphics;
-
-/**
- * Demonstrates how to draw into a slide using the HSLF Graphics2D driver.
- */
-public final class Graphics2DDemo {
-
- private Graphics2DDemo() {}
-
- /**
- * A simple bar chart demo
- */
- public static void main(String[] args) throws Exception {
- try (HSLFSlideShow ppt = new HSLFSlideShow();
- FileOutputStream out = new FileOutputStream("hslf-graphics.ppt")) {
- //bar chart data. The first value is the bar color, the second is the width
- Object[] def = {
- Color.yellow, 40,
- Color.green, 60,
- Color.gray, 30,
- Color.red, 80,
- };
-
- HSLFSlide slide = ppt.createSlide();
-
- HSLFGroupShape group = new HSLFGroupShape();
- //define position of the drawing in the slide
- Rectangle bounds = new Rectangle(200, 100, 350, 300);
- group.setAnchor(bounds);
- group.setInteriorAnchor(new Rectangle(0, 0, 100, 100));
- slide.addShape(group);
- Graphics2D graphics = new SLGraphics(group);
-
- //draw a simple bar graph
- int x = 10, y = 10;
- graphics.setFont(new Font("Arial", Font.BOLD, 10));
- for (int i = 0, idx = 1; i < def.length; i += 2, idx++) {
- graphics.setColor(Color.black);
- int width = (Integer) def[i + 1];
- graphics.drawString("Q" + idx, x - 5, y + 10);
- graphics.drawString(width + "%", x + width + 3, y + 10);
- graphics.setColor((Color) def[i]);
- graphics.fill(new Rectangle(x, y, width, 10));
- y += 15;
- }
- graphics.setColor(Color.black);
- graphics.setFont(new Font("Arial", Font.BOLD, 14));
- graphics.draw(group.getInteriorAnchor());
- graphics.drawString("Performance", x + 30, y + 10);
-
- ppt.write(out);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hslf.model.HeadersFooters;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-
-/**
- * Demonstrates how to set headers / footers
- */
-public final class HeadersFootersDemo {
- private HeadersFootersDemo() {}
-
- public static void main(String[] args) throws IOException {
- try (HSLFSlideShow ppt = new HSLFSlideShow()) {
- HeadersFooters slideHeaders = ppt.getSlideHeadersFooters();
- slideHeaders.setFootersText("Created by POI-HSLF");
- slideHeaders.setSlideNumberVisible(true);
- slideHeaders.setDateTimeText("custom date time");
-
- HeadersFooters notesHeaders = ppt.getNotesHeadersFooters();
- notesHeaders.setFootersText("My notes footers");
- notesHeaders.setHeaderText("My notes header");
-
- ppt.createSlide();
-
- try (FileOutputStream out = new FileOutputStream("headers_footers.ppt")) {
- ppt.write(out);
- }
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-
-import java.io.FileInputStream;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.poi.hslf.usermodel.HSLFHyperlink;
-import org.apache.poi.hslf.usermodel.HSLFSimpleShape;
-import org.apache.poi.hslf.usermodel.HSLFSlide;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
-import org.apache.poi.hslf.usermodel.HSLFTextRun;
-
-/**
- * Demonstrates how to read hyperlinks from a presentation
- */
-@SuppressWarnings({"java:S106", "java:S4823"})
-public final class Hyperlinks {
-
- private Hyperlinks() {}
-
- public static void main(String[] args) throws Exception {
- for (String arg : args) {
- try (FileInputStream is = new FileInputStream(arg);
- HSLFSlideShow ppt = new HSLFSlideShow(is)) {
-
- for (HSLFSlide slide : ppt.getSlides()) {
- System.out.println("\nslide " + slide.getSlideNumber());
-
- // read hyperlinks from the slide's text runs
- System.out.println("- reading hyperlinks from the text runs");
- slide.getTextParagraphs().stream().
- flatMap(List::stream).
- map(HSLFTextParagraph::getTextRuns).
- flatMap(List::stream).
- forEach(run -> out(run.getHyperlink(), run));
-
- // in PowerPoint you can assign a hyperlink to a shape without text,
- // for example to a Line object. The code below demonstrates how to
- // read such hyperlinks
- System.out.println("- reading hyperlinks from the slide's shapes");
- slide.getShapes().stream().
- filter(sh -> sh instanceof HSLFSimpleShape).
- forEach(sh -> out(((HSLFSimpleShape) sh).getHyperlink(), null));
- }
- }
- }
- }
-
- private static void out(HSLFHyperlink link, HSLFTextRun run) {
- if (link == null) {
- return;
- }
- String rawText = run == null ? null : run.getRawText();
- //in ppt end index is inclusive
- String formatStr = "title: %1$s, address: %2$s" + (rawText == null ? "" : ", start: %3$s, end: %4$s, substring: %5$s");
- String line = String.format(Locale.ROOT, formatStr, link.getLabel(), link.getAddress(), link.getStartIndex(), link.getEndIndex(), rawText);
- System.out.println(line);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-import org.apache.poi.hslf.record.InteractiveInfoAtom;
-import org.apache.poi.hslf.record.RecordTypes;
-import org.apache.poi.hslf.usermodel.HSLFShape;
-import org.apache.poi.hslf.usermodel.HSLFSlide;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFSoundData;
-
-/**
- * For each slide iterate over shapes and found associated sound data.
- */
-@SuppressWarnings({"java:S106", "java:S4823"})
-public final class SoundFinder {
- private SoundFinder() {}
-
- public static void main(String[] args) throws IOException {
- try (FileInputStream fis = new FileInputStream(args[0])) {
- try (HSLFSlideShow ppt = new HSLFSlideShow(fis)) {
- HSLFSoundData[] sounds = ppt.getSoundData();
-
- for (HSLFSlide slide : ppt.getSlides()) {
- for (HSLFShape shape : slide.getShapes()) {
- int soundRef = getSoundReference(shape);
- if (soundRef == -1) continue;
-
-
- System.out.println("Slide[" + slide.getSlideNumber() + "], shape[" + shape.getShapeId() + "], soundRef: " + soundRef);
- System.out.println(" " + sounds[soundRef].getSoundName());
- System.out.println(" " + sounds[soundRef].getSoundType());
- }
- }
- }
- }
- }
-
- /**
- * Check if a given shape is associated with a sound.
- * @return 0-based reference to a sound in the sound collection
- * or -1 if the shape is not associated with a sound
- */
- private static int getSoundReference(HSLFShape shape){
- int soundRef = -1;
- //dive into the shape container and search for InteractiveInfoAtom
- InteractiveInfoAtom info = shape.getClientDataRecord(RecordTypes.InteractiveInfo.typeID);
- if (info != null && info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) {
- soundRef = info.getSoundRef();
- }
- return soundRef;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hslf.examples;
-
-import java.awt.Color;
-import java.io.FileOutputStream;
-
-import org.apache.poi.hslf.usermodel.HSLFSlide;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFTable;
-import org.apache.poi.hslf.usermodel.HSLFTableCell;
-import org.apache.poi.hslf.usermodel.HSLFTextRun;
-import org.apache.poi.sl.draw.DrawTableShape;
-import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
-import org.apache.poi.sl.usermodel.VerticalAlignment;
-
-/**
- * Demonstrates how to create tables
- */
-public final class TableDemo {
-
- //test data for the first table
- static final String[][] txt1 = {
- {"INPUT FILE", "NUMBER OF RECORDS"},
- {"Item File", "11,559"},
- {"Vendor File", "502"},
- {"Purchase History File - # of PO\u2019s\r(12/01/04 - 05/31/06)", "12,852"},
- {"Purchase History File - # of PO Lines\r(12/01/04 - 05/31/06)", "53,523" },
- {"Total PO History Spend", "$10,172,038"}
- };
-
- //test data for the second taable
- static final String[][] txt2 = {
- {"Data Source"},
- {"CAS Internal Metrics - Item Master Summary\r" +
- "CAS Internal Metrics - Vendor Summary\r" +
- "CAS Internal Metrics - PO History Summary"}
- };
-
-
- public static void main(String[] args) throws Exception {
- try (HSLFSlideShow ppt = new HSLFSlideShow()) {
- HSLFSlide slide = ppt.createSlide();
- create1stTable(slide);
- create2ndTable(slide);
-
- try (FileOutputStream out = new FileOutputStream("hslf-table.ppt")) {
- ppt.write(out);
- }
- }
- }
-
- static void create1stTable(HSLFSlide slide) {
- //six rows, two columns
- HSLFTable table1 = slide.createTable(6, 2);
- for (int i = 0; i < txt1.length; i++) {
- for (int j = 0; j < txt1[i].length; j++) {
- HSLFTableCell cell = table1.getCell(i, j);
- HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
- rt.setFontFamily("Arial");
- rt.setFontSize(10d);
- if(i == 0){
- cell.getFill().setForegroundColor(new Color(227, 227, 227));
- } else {
- rt.setBold(true);
- }
- cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
- cell.setHorizontalCentered(true);
- cell.setText(txt1[i][j]);
- }
- }
-
- DrawTableShape dts1 = new DrawTableShape(table1);
- dts1.setAllBorders(1.0, Color.black);
-
- table1.setColumnWidth(0, 300);
- table1.setColumnWidth(1, 150);
-
- int pgWidth = slide.getSlideShow().getPageSize().width;
- table1.moveTo((pgWidth - table1.getAnchor().getWidth())/2., 100.);
- }
-
- static void create2ndTable(HSLFSlide slide) {
- //two rows, one column
- HSLFTable table2 = slide.createTable(2, 1);
- for (int i = 0; i < txt2.length; i++) {
- for (int j = 0; j < txt2[i].length; j++) {
- HSLFTableCell cell = table2.getCell(i, j);
- HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
- rt.setFontSize(10d);
- rt.setFontFamily("Arial");
- if(i == 0){
- cell.getFill().setForegroundColor(new Color(0, 51, 102));
- rt.setFontColor(Color.white);
- rt.setBold(true);
- rt.setFontSize(14d);
- cell.setHorizontalCentered(true);
- } else {
- rt.getTextParagraph().setBullet(true);
- rt.setFontSize(12d);
- rt.getTextParagraph().setTextAlign(TextAlign.LEFT);
- cell.setHorizontalCentered(false);
- }
- cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
- cell.setText(txt2[i][j]);
- }
- }
- table2.setColumnWidth(0, 300);
- table2.setRowHeight(0, 30);
- table2.setRowHeight(1, 70);
-
- DrawTableShape dts2 = new DrawTableShape(table2);
- dts2.setOutsideBorders(Color.black, 1.0);
-
- table2.moveTo(200, 400);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hsmf.examples;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-
-import org.apache.poi.hsmf.MAPIMessage;
-import org.apache.poi.hsmf.datatypes.AttachmentChunks;
-import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
-
-/**
- * Reads one or several Outlook MSG files and for each of them creates
- * a text file from available chunks and a directory that contains
- * attachments.
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public class Msg2txt {
-
- /**
- * The stem used to create file names for the text file and the directory
- * that contains the attachments.
- */
- private String fileNameStem;
-
- /**
- * The Outlook MSG file being processed.
- */
- private MAPIMessage msg;
-
- public Msg2txt(String fileName) throws IOException {
- fileNameStem = fileName;
- if(fileNameStem.endsWith(".msg") || fileNameStem.endsWith(".MSG")) {
- fileNameStem = fileNameStem.substring(0, fileNameStem.length() - 4);
- }
- msg = new MAPIMessage(fileName);
- }
-
- /**
- * Processes the message.
- *
- * @throws IOException if an exception occurs while writing the message out
- */
- public void processMessage() throws IOException {
- String txtFileName = fileNameStem + ".txt";
- String attDirName = fileNameStem + "-att";
- try (PrintWriter txtOut = new PrintWriter(txtFileName)) {
- try {
- String displayFrom = msg.getDisplayFrom();
- txtOut.println("From: " + displayFrom);
- } catch (ChunkNotFoundException e) {
- // ignore
- }
- try {
- String displayTo = msg.getDisplayTo();
- txtOut.println("To: " + displayTo);
- } catch (ChunkNotFoundException e) {
- // ignore
- }
- try {
- String displayCC = msg.getDisplayCC();
- txtOut.println("CC: " + displayCC);
- } catch (ChunkNotFoundException e) {
- // ignore
- }
- try {
- String displayBCC = msg.getDisplayBCC();
- txtOut.println("BCC: " + displayBCC);
- } catch (ChunkNotFoundException e) {
- // ignore
- }
- try {
- String subject = msg.getSubject();
- txtOut.println("Subject: " + subject);
- } catch (ChunkNotFoundException e) {
- // ignore
- }
- try {
- String body = msg.getTextBody();
- txtOut.println(body);
- } catch (ChunkNotFoundException e) {
- System.err.println("No message body");
- }
-
- AttachmentChunks[] attachments = msg.getAttachmentFiles();
- if (attachments.length > 0) {
- File d = new File(attDirName);
- if (d.mkdir()) {
- for (AttachmentChunks attachment : attachments) {
- processAttachment(attachment, d);
- }
- } else {
- System.err.println("Can't create directory " + attDirName);
- }
- }
- }
- }
-
- /**
- * Processes a single attachment: reads it from the Outlook MSG file and
- * writes it to disk as an individual file.
- *
- * @param attachment the chunk group describing the attachment
- * @param dir the directory in which to write the attachment file
- * @throws IOException when any of the file operations fails
- */
- public void processAttachment(AttachmentChunks attachment,
- File dir) throws IOException {
- String fileName = attachment.getAttachFileName().toString();
- if(attachment.getAttachLongFileName() != null) {
- fileName = attachment.getAttachLongFileName().toString();
- }
-
- File f = new File(dir, fileName);
- try (OutputStream fileOut = new FileOutputStream(f)) {
- fileOut.write(attachment.getAttachData().getValue());
- }
- }
-
- /**
- * Processes the list of arguments as a list of names of Outlook MSG files.
- *
- * @param args the list of MSG files to process
- */
- public static void main(String[] args) {
- if(args.length <= 0) {
- System.err.println("No files names provided");
- } else {
- for (String arg : args) {
- try {
- Msg2txt processor = new Msg2txt(arg);
- processor.processMessage();
- } catch (IOException e) {
- System.err.println("Could not process " + arg + ": " + e);
- }
- }
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.eventusermodel.examples;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder.SheetRecordCollectingListener;
-import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
-import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
-import org.apache.poi.hssf.eventusermodel.HSSFListener;
-import org.apache.poi.hssf.eventusermodel.HSSFRequest;
-import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener;
-import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
-import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
-import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.record.BOFRecord;
-import org.apache.poi.hssf.record.BlankRecord;
-import org.apache.poi.hssf.record.BoolErrRecord;
-import org.apache.poi.hssf.record.BoundSheetRecord;
-import org.apache.poi.hssf.record.FormulaRecord;
-import org.apache.poi.hssf.record.LabelRecord;
-import org.apache.poi.hssf.record.LabelSSTRecord;
-import org.apache.poi.hssf.record.NoteRecord;
-import org.apache.poi.hssf.record.NumberRecord;
-import org.apache.poi.hssf.record.RKRecord;
-import org.apache.poi.hssf.record.SSTRecord;
-import org.apache.poi.hssf.record.StringRecord;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-/**
- * A XLS -> CSV processor, that uses the MissingRecordAware
- * EventModel code to ensure it outputs all columns and rows.
- * @author Nick Burch
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public class XLS2CSVmra implements HSSFListener {
- private int minColumns;
- private POIFSFileSystem fs;
- private PrintStream output;
-
- private int lastRowNumber;
- private int lastColumnNumber;
-
- /** Should we output the formula, or the value it has? */
- private boolean outputFormulaValues = true;
-
- /** For parsing Formulas */
- private SheetRecordCollectingListener workbookBuildingListener;
- private HSSFWorkbook stubWorkbook;
-
- // Records we pick up as we process
- private SSTRecord sstRecord;
- private FormatTrackingHSSFListener formatListener;
-
- /** So we known which sheet we're on */
- private int sheetIndex = -1;
- private BoundSheetRecord[] orderedBSRs;
- private List<BoundSheetRecord> boundSheetRecords = new ArrayList<>();
-
- // For handling formulas with string results
- private int nextRow;
- private int nextColumn;
- private boolean outputNextStringRecord;
-
- /**
- * Creates a new XLS -> CSV converter
- * @param fs The POIFSFileSystem to process
- * @param output The PrintStream to output the CSV to
- * @param minColumns The minimum number of columns to output, or -1 for no minimum
- */
- public XLS2CSVmra(POIFSFileSystem fs, PrintStream output, int minColumns) {
- this.fs = fs;
- this.output = output;
- this.minColumns = minColumns;
- }
-
- /**
- * Creates a new XLS -> CSV converter
- * @param filename The file to process
- * @param minColumns The minimum number of columns to output, or -1 for no minimum
- */
- public XLS2CSVmra(String filename, int minColumns) throws IOException, FileNotFoundException {
- this(
- new POIFSFileSystem(new FileInputStream(filename)),
- System.out, minColumns
- );
- }
-
- /**
- * Initiates the processing of the XLS file to CSV
- */
- public void process() throws IOException {
- MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);
- formatListener = new FormatTrackingHSSFListener(listener);
-
- HSSFEventFactory factory = new HSSFEventFactory();
- HSSFRequest request = new HSSFRequest();
-
- if(outputFormulaValues) {
- request.addListenerForAllRecords(formatListener);
- } else {
- workbookBuildingListener = new SheetRecordCollectingListener(formatListener);
- request.addListenerForAllRecords(workbookBuildingListener);
- }
-
- factory.processWorkbookEvents(request, fs);
- }
-
- /**
- * Main HSSFListener method, processes events, and outputs the
- * CSV as the file is processed.
- */
- @Override
- public void processRecord(org.apache.poi.hssf.record.Record record) {
- int thisRow = -1;
- int thisColumn = -1;
- String thisStr = null;
-
- switch (record.getSid())
- {
- case BoundSheetRecord.sid:
- boundSheetRecords.add((BoundSheetRecord)record);
- break;
- case BOFRecord.sid:
- BOFRecord br = (BOFRecord)record;
- if(br.getType() == BOFRecord.TYPE_WORKSHEET) {
- // Create sub workbook if required
- if(workbookBuildingListener != null && stubWorkbook == null) {
- stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();
- }
-
- // Output the worksheet name
- // Works by ordering the BSRs by the location of
- // their BOFRecords, and then knowing that we
- // process BOFRecords in byte offset order
- sheetIndex++;
- if(orderedBSRs == null) {
- orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
- }
- output.println();
- output.println(
- orderedBSRs[sheetIndex].getSheetname() +
- " [" + (sheetIndex+1) + "]:"
- );
- }
- break;
-
- case SSTRecord.sid:
- sstRecord = (SSTRecord) record;
- break;
-
- case BlankRecord.sid:
- BlankRecord brec = (BlankRecord) record;
-
- thisRow = brec.getRow();
- thisColumn = brec.getColumn();
- thisStr = "";
- break;
- case BoolErrRecord.sid:
- BoolErrRecord berec = (BoolErrRecord) record;
-
- thisRow = berec.getRow();
- thisColumn = berec.getColumn();
- thisStr = "";
- break;
-
- case FormulaRecord.sid:
- FormulaRecord frec = (FormulaRecord) record;
-
- thisRow = frec.getRow();
- thisColumn = frec.getColumn();
-
- if(outputFormulaValues) {
- if(Double.isNaN( frec.getValue() )) {
- // Formula result is a string
- // This is stored in the next record
- outputNextStringRecord = true;
- nextRow = frec.getRow();
- nextColumn = frec.getColumn();
- } else {
- thisStr = formatListener.formatNumberDateCell(frec);
- }
- } else {
- thisStr = '"' +
- HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression()) + '"';
- }
- break;
- case StringRecord.sid:
- if(outputNextStringRecord) {
- // String for formula
- StringRecord srec = (StringRecord)record;
- thisStr = srec.getString();
- thisRow = nextRow;
- thisColumn = nextColumn;
- outputNextStringRecord = false;
- }
- break;
-
- case LabelRecord.sid:
- LabelRecord lrec = (LabelRecord) record;
-
- thisRow = lrec.getRow();
- thisColumn = lrec.getColumn();
- thisStr = '"' + lrec.getValue() + '"';
- break;
- case LabelSSTRecord.sid:
- LabelSSTRecord lsrec = (LabelSSTRecord) record;
-
- thisRow = lsrec.getRow();
- thisColumn = lsrec.getColumn();
- if(sstRecord == null) {
- thisStr = '"' + "(No SST Record, can't identify string)" + '"';
- } else {
- thisStr = '"' + sstRecord.getString(lsrec.getSSTIndex()).toString() + '"';
- }
- break;
- case NoteRecord.sid:
- NoteRecord nrec = (NoteRecord) record;
-
- thisRow = nrec.getRow();
- thisColumn = nrec.getColumn();
- // TODO: Find object to match nrec.getShapeId()
- thisStr = '"' + "(TODO)" + '"';
- break;
- case NumberRecord.sid:
- NumberRecord numrec = (NumberRecord) record;
-
- thisRow = numrec.getRow();
- thisColumn = numrec.getColumn();
-
- // Format
- thisStr = formatListener.formatNumberDateCell(numrec);
- break;
- case RKRecord.sid:
- RKRecord rkrec = (RKRecord) record;
-
- thisRow = rkrec.getRow();
- thisColumn = rkrec.getColumn();
- thisStr = '"' + "(TODO)" + '"';
- break;
- default:
- break;
- }
-
- // Handle new row
- if(thisRow != -1 && thisRow != lastRowNumber) {
- lastColumnNumber = -1;
- }
-
- // Handle missing column
- if(record instanceof MissingCellDummyRecord) {
- MissingCellDummyRecord mc = (MissingCellDummyRecord)record;
- thisRow = mc.getRow();
- thisColumn = mc.getColumn();
- thisStr = "";
- }
-
- // If we got something to print out, do so
- if(thisStr != null) {
- if(thisColumn > 0) {
- output.print(',');
- }
- output.print(thisStr);
- }
-
- // Update column and row count
- if(thisRow > -1)
- lastRowNumber = thisRow;
- if(thisColumn > -1)
- lastColumnNumber = thisColumn;
-
- // Handle end of row
- if(record instanceof LastCellOfRowDummyRecord) {
- // Print out any missing commas if needed
- if(minColumns > 0) {
- // Columns are 0 based
- if(lastColumnNumber == -1) { lastColumnNumber = 0; }
- for(int i=lastColumnNumber; i<(minColumns); i++) {
- output.print(',');
- }
- }
-
- // We're onto a new row
- lastColumnNumber = -1;
-
- // End the row
- output.println();
- }
- }
-
- public static void main(String[] args) throws Exception {
- if(args.length < 1) {
- System.err.println("Use:");
- System.err.println(" XLS2CSVmra <xls file> [min columns]");
- System.exit(1);
- }
-
- int minColumns = -1;
- if(args.length >= 2) {
- minColumns = Integer.parseInt(args[1]);
- }
-
- XLS2CSVmra xls2csv = new XLS2CSVmra(args[0], minColumns);
- xls2csv.process();
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-/* Placeholder - this is now handled in the Common SS example **/
-public class AddDimensionedImage extends org.apache.poi.ss.examples.AddDimensionedImage {
-}
\ No newline at end of file
+++ /dev/null
-
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-
-/**
- * Shows how various alignment options work.
- *
- * @author Glen Stampoultzis (glens at apache.org)
- */
-public class Alignment {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
- HSSFRow row = sheet.createRow(2);
- createCell(wb, row, 0, HorizontalAlignment.CENTER);
- createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION);
- createCell(wb, row, 2, HorizontalAlignment.FILL);
- createCell(wb, row, 3, HorizontalAlignment.GENERAL);
- createCell(wb, row, 4, HorizontalAlignment.JUSTIFY);
- createCell(wb, row, 5, HorizontalAlignment.LEFT);
- createCell(wb, row, 6, HorizontalAlignment.RIGHT);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-
- /**
- * Creates a cell and aligns it a certain way.
- *
- * @param wb the workbook
- * @param row the row to create the cell in
- * @param column the column number to create the cell in
- * @param align the alignment for the cell.
- */
- private static void createCell(HSSFWorkbook wb, HSSFRow row, int column, HorizontalAlignment align) {
- HSSFCell cell = row.createCell(column);
- cell.setCellValue("Align It");
- HSSFCellStyle cellStyle = wb.createCellStyle();
- cellStyle.setAlignment(align);
- cell.setCellStyle(cellStyle);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFDataFormat;
-import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-
-/**
- * Demonstrates many features of the user API at once. Used in the HOW-TO guide.
- */
-public class BigExample {
- public static void main(String[] args) throws IOException {
- int rownum;
-
- // create a new workbook
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- // create a new sheet
- HSSFSheet s = wb.createSheet();
- // declare a row object reference
- HSSFRow r;
- // declare a cell object reference
- HSSFCell c;
- // create 3 cell styles
- HSSFCellStyle cs = wb.createCellStyle();
- HSSFCellStyle cs2 = wb.createCellStyle();
- HSSFCellStyle cs3 = wb.createCellStyle();
- // create 2 fonts objects
- HSSFFont f = wb.createFont();
- HSSFFont f2 = wb.createFont();
-
- //set font 1 to 12 point type
- f.setFontHeightInPoints((short) 12);
- //make it red
- f.setColor(HSSFColorPredefined.RED.getIndex());
- // make it bold
- //arial is the default font
- f.setBold(true);
-
- //set font 2 to 10 point type
- f2.setFontHeightInPoints((short) 10);
- //make it the color at palette index 0xf (white)
- f2.setColor(HSSFColorPredefined.WHITE.getIndex());
- //make it bold
- f2.setBold(true);
-
- //set cell style
- cs.setFont(f);
- //set the cell format see HSSFDataFormat for a full list
- cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("($#,##0_);[Red]($#,##0)"));
-
- //set a thin border
- cs2.setBorderBottom(BorderStyle.THIN);
- //fill w fg fill color
- cs2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- // set foreground fill to red
- cs2.setFillForegroundColor(HSSFColorPredefined.RED.getIndex());
-
- // set the font
- cs2.setFont(f2);
-
- // set the sheet name to HSSF Test
- wb.setSheetName(0, "HSSF Test");
- // create a sheet with 300 rows (0-299)
- for (rownum = 0; rownum < 300; rownum++) {
- // create a row
- r = s.createRow(rownum);
- // on every other row
- if ((rownum % 2) == 0) {
- // make the row height bigger (in twips - 1/20 of a point)
- r.setHeight((short) 0x249);
- }
-
- // create 50 cells (0-49) (the += 2 becomes apparent later
- for (int cellnum = 0; cellnum < 50; cellnum += 2) {
- // create a numeric cell
- c = r.createCell(cellnum);
- // do some goofy math to demonstrate decimals
- c.setCellValue((rownum * 10000.0) + cellnum
- + (rownum / 1000.0)
- + (cellnum / 10000.0));
-
- // on every other row
- if ((rownum % 2) == 0) {
- // set this cell to the first cell style we defined
- c.setCellStyle(cs);
- }
-
- // create a string cell (see why += 2 in the
- c = r.createCell(cellnum + 1);
-
- // set the cell's string value to "TEST"
- c.setCellValue("TEST");
- // make this column a bit wider
- s.setColumnWidth(cellnum + 1, (int) ((50 * 8) / ((double) 1 / 20)));
-
- // on every other row
- if ((rownum % 2) == 0) {
- // set this to the white on red cell style
- // we defined above
- c.setCellStyle(cs2);
- }
-
- }
- }
-
- //draw a thick black border on the row at the bottom using BLANKS
- // advance 2 rows
- rownum++;
- rownum++;
-
- r = s.createRow(rownum);
-
- // define the third style to be the default
- // except with a thick black border at the bottom
- cs3.setBorderBottom(BorderStyle.THICK);
-
- //create 50 cells
- for (int cellnum = 0; cellnum < 50; cellnum++) {
- //create a blank type cell (no value)
- c = r.createCell(cellnum);
- // set it to the thick black border style
- c.setCellStyle(cs3);
- }
-
- //end draw thick black border
-
-
- // demonstrate adding/naming and deleting a sheet
- // create a sheet, set its title then delete it
- wb.createSheet();
- wb.setSheetName(1, "DeletedSheet");
- wb.removeSheetAt(1);
- //end deleted sheet
-
- // create a new file
- try (FileOutputStream out = new FileOutputStream("workbook.xls")) {
- // write the workbook to the output stream
- // close our file (don't blow out our file handles
- wb.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
-import org.apache.poi.ss.usermodel.BorderStyle;
-
-/**
- * Demonstrates how to create borders around cells.
- */
-public class Borders {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
-
- // Create a row and put some cells in it. Rows are 0 based.
- HSSFRow row = sheet.createRow(1);
-
- // Create a cell and put a value in it.
- HSSFCell cell = row.createCell(1);
- cell.setCellValue(4);
-
- // Style the cell with borders all around.
- HSSFCellStyle style = wb.createCellStyle();
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(HSSFColorPredefined.BLACK.getIndex());
- style.setBorderLeft(BorderStyle.THIN);
- style.setLeftBorderColor(HSSFColorPredefined.GREEN.getIndex());
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(HSSFColorPredefined.BLUE.getIndex());
- style.setBorderTop(BorderStyle.MEDIUM_DASHED);
- style.setTopBorderColor(HSSFColorPredefined.ORANGE.getIndex());
- cell.setCellStyle(style);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import org.apache.poi.hssf.usermodel.HSSFComment;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.ClientAnchor;
-import org.apache.poi.ss.usermodel.Comment;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.Drawing;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.RichTextString;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Demonstrates how to work with excel cell comments.<p>
- *
- * Excel comment is a kind of a text shape,
- * so inserting a comment is very similar to placing a text box in a worksheet
- */
-public class CellComments {
-
- public static void main(String[] args) throws IOException {
- createWorkbook(false, ".xls");
- createWorkbook(true, ".xlsx");
- }
-
- private static void createWorkbook(boolean xssf, String extension) throws IOException {
- try (Workbook wb = WorkbookFactory.create(xssf)) {
- Sheet sheet = wb.createSheet("Cell comments in POI " + extension);
- CreationHelper creationHelper = wb.getCreationHelper();
-
- // Create the drawing patriarch. This is the top level container for all shapes including cell comments.
- Drawing<?> patr = sheet.createDrawingPatriarch();
-
- //create a cell in row 3
- Cell cell1 = sheet.createRow(3).createCell(1);
- cell1.setCellValue(creationHelper.createRichTextString("Hello, World"));
-
- //anchor defines size and position of the comment in worksheet
- ClientAnchor clientAnchor = creationHelper.createClientAnchor();
- clientAnchor.setCol1(4);
- clientAnchor.setRow1(2);
- clientAnchor.setCol2(6);
- clientAnchor.setRow2(5);
- Comment comment1 = patr.createCellComment(clientAnchor);
-
- // set text in the comment
- comment1.setString(creationHelper.createRichTextString("We can set comments in POI"));
-
- //set comment author.
- //you can see it in the status bar when moving mouse over the commented cell
- comment1.setAuthor("Apache Software Foundation");
-
- // The first way to assign comment to a cell is via Cell.setCellComment method
- cell1.setCellComment(comment1);
-
- //create another cell in row 6
- Cell cell2 = sheet.createRow(6).createCell(1);
- cell2.setCellValue(36.6);
-
-
- clientAnchor = creationHelper.createClientAnchor();
- clientAnchor.setCol1(4);
- clientAnchor.setRow1(8);
- clientAnchor.setCol2(6);
- clientAnchor.setRow2(11);
- Comment comment2 = patr.createCellComment(clientAnchor);
- //modify background color of the comment, only available in HSSF currently
- if (wb instanceof HSSFWorkbook) {
- ((HSSFComment) comment2).setFillColor(204, 236, 255);
- }
-
- RichTextString string = creationHelper.createRichTextString("Normal body temperature");
-
- //apply custom font to the text in the comment
- Font font = wb.createFont();
- font.setFontName("Arial");
- font.setFontHeightInPoints((short) 10);
- font.setBold(true);
- font.setColor(IndexedColors.RED.getIndex());
- string.applyFont(font);
-
- comment2.setString(string);
- comment2.setVisible(true); //by default comments are hidden. This one is always visible.
-
- comment2.setAuthor("Bill Gates");
-
- /*
- * The second way to assign comment to a cell is to implicitly specify its row and column.
- * Note, it is possible to set row and column of a non-existing cell.
- * It works, the comment is visible.
- */
- comment2.setRow(6);
- comment2.setColumn(1);
-
- try (FileOutputStream out = new FileOutputStream("poi_comment" + extension)) {
- wb.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Date;
-
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.FormulaError;
-
-public class CellTypes {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
- HSSFRow row = sheet.createRow(2);
- row.createCell(0).setCellValue(1.1);
- row.createCell(1).setCellValue(new Date());
- row.createCell(2).setCellValue("a string");
- row.createCell(3).setCellValue(true);
- row.createCell(4).setCellErrorValue(FormulaError.NUM);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Illustrates how to create cell values.
- *
- * @author Glen Stampoultzis (glens at apache.org)
- */
-public class CreateCells {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
-
- // Create a row and put some cells in it. Rows are 0 based.
- HSSFRow row = sheet.createRow(0);
- // Create a cell and put a value in it.
- HSSFCell cell = row.createCell(0);
- cell.setCellValue(1);
-
- // Or do it on one line.
- row.createCell(1).setCellValue(1.2);
- row.createCell(2).setCellValue("This is a string");
- row.createCell(3).setCellValue(true);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Date;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFDataFormat;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * An example on how to cells with dates. The important thing to note
- * about dates is that they are really normal numeric cells that are
- * formatted specially.
- */
-public class CreateDateCells {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
-
- // Create a row and put some cells in it. Rows are 0 based.
- HSSFRow row = sheet.createRow(0);
-
- // Create a cell and put a date value in it. The first cell is not styled as a date.
- HSSFCell cell = row.createCell(0);
- cell.setCellValue(new Date());
-
- // we style the second cell as a date (and time). It is important to create a new cell style from the workbook
- // otherwise you can end up modifying the built in style and effecting not only this cell but other cells.
- HSSFCellStyle cellStyle = wb.createCellStyle();
- cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));
- cell = row.createCell(1);
- cell.setCellValue(new Date());
- cell.setCellStyle(cellStyle);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.Closeable;
-import java.io.FileInputStream;
-
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hssf.usermodel.HSSFObjectData;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hwpf.HWPFDocument;
-import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.poifs.filesystem.Entry;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-/**
- * Demonstrates how you can extract embedded data from a .xls file
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class EmbeddedObjects {
- private EmbeddedObjects() {}
-
- @SuppressWarnings("unused")
- public static void main(String[] args) throws Exception {
- try (
- FileInputStream fis = new FileInputStream(args[0]);
- POIFSFileSystem fs = new POIFSFileSystem(fis);
- HSSFWorkbook workbook = new HSSFWorkbook(fs)
- ) {
- for (HSSFObjectData obj : workbook.getAllEmbeddedObjects()) {
- //the OLE2 Class Name of the object
- String oleName = obj.getOLE2ClassName();
- DirectoryNode dn = (obj.hasDirectoryEntry()) ? (DirectoryNode) obj.getDirectory() : null;
- Closeable document = null;
- switch (oleName) {
- case "Worksheet":
- document = new HSSFWorkbook(dn, fs, false);
- break;
- case "Document":
- document = new HWPFDocument(dn);
- break;
- case "Presentation":
- document = new HSLFSlideShow(dn);
- break;
- default:
- if (dn != null) {
- // The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is
- for (Entry entry : dn) {
- String name = entry.getName();
- }
- } else {
- // There is no DirectoryEntry
- // Recover the object's data from the HSSFObjectData instance.
- byte[] objectData = obj.getObjectData();
- }
- break;
- }
- if (document != null) {
- document.close();
- }
- }
- }
- }
-}
+++ /dev/null
-
-/* ====================================================================
- 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.examples;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
-import org.apache.poi.hssf.eventusermodel.HSSFListener;
-import org.apache.poi.hssf.eventusermodel.HSSFRequest;
-import org.apache.poi.hssf.record.BOFRecord;
-import org.apache.poi.hssf.record.BoundSheetRecord;
-import org.apache.poi.hssf.record.LabelSSTRecord;
-import org.apache.poi.hssf.record.NumberRecord;
-import org.apache.poi.hssf.record.RowRecord;
-import org.apache.poi.hssf.record.SSTRecord;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-/**
- * This example shows how to use the event API for reading a file.
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public class EventExample implements HSSFListener {
- private SSTRecord sstrec;
-
- /**
- * This method listens for incoming records and handles them as required.
- * @param record The record that was found while reading.
- */
- @Override
- public void processRecord(org.apache.poi.hssf.record.Record record)
- {
- switch (record.getSid())
- {
- // the BOFRecord can represent either the beginning of a sheet or the workbook
- case BOFRecord.sid:
- BOFRecord bof = (BOFRecord) record;
- if (bof.getType() == BOFRecord.TYPE_WORKBOOK)
- {
- System.out.println("Encountered workbook");
- // assigned to the class level member
- } else if (bof.getType() == BOFRecord.TYPE_WORKSHEET)
- {
- System.out.println("Encountered sheet reference");
- }
- break;
- case BoundSheetRecord.sid:
- BoundSheetRecord bsr = (BoundSheetRecord) record;
- System.out.println("New sheet named: " + bsr.getSheetname());
- break;
- case RowRecord.sid:
- RowRecord rowrec = (RowRecord) record;
- System.out.println("Row found, first column at "
- + rowrec.getFirstCol() + " last column at " + rowrec.getLastCol());
- break;
- case NumberRecord.sid:
- NumberRecord numrec = (NumberRecord) record;
- System.out.println("Cell found with value " + numrec.getValue()
- + " at row " + numrec.getRow() + " and column " + numrec.getColumn());
- break;
- // SSTRecords store a array of unique strings used in Excel.
- case SSTRecord.sid:
- sstrec = (SSTRecord) record;
- for (int k = 0; k < sstrec.getNumUniqueStrings(); k++)
- {
- System.out.println("String table value " + k + " = " + sstrec.getString(k));
- }
- break;
- case LabelSSTRecord.sid:
- LabelSSTRecord lrec = (LabelSSTRecord) record;
- System.out.println("String cell found with value "
- + sstrec.getString(lrec.getSSTIndex()));
- break;
- }
- }
-
- /**
- * Read an excel file and spit out what we find.
- *
- * @param args Expect one argument that is the file to read.
- * @throws IOException When there is an error processing the file.
- */
- public static void main(String[] args) throws IOException
- {
- // create a new file input stream with the input file specified
- // at the command line
- try (FileInputStream fin = new FileInputStream(args[0])) {
- // create a new org.apache.poi.poifs.filesystem.Filesystem
- try (POIFSFileSystem poifs = new POIFSFileSystem(fin)) {
- // get the Workbook (excel part) stream in a InputStream
- try (InputStream din = poifs.createDocumentInputStream("Workbook")) {
- // construct out HSSFRequest object
- HSSFRequest req = new HSSFRequest();
- // lazy listen for ALL records with the listener shown above
- req.addListenerForAllRecords(new EventExample());
- // create our event factory
- HSSFEventFactory factory = new HSSFEventFactory();
- // process our events based on the document input stream
- factory.processEvents(req, din);
- }
- }
- }
- System.out.println("done.");
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
-import org.apache.poi.ss.usermodel.FillPatternType;
-
-/**
- * Shows how to use various fills.
- */
-public class FrillsAndFills {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
-
- // Create a row and put some cells in it. Rows are 0 based.
- HSSFRow row = sheet.createRow(1);
-
- // Aqua background
- HSSFCellStyle style = wb.createCellStyle();
- style.setFillBackgroundColor(HSSFColorPredefined.AQUA.getIndex());
- style.setFillPattern(FillPatternType.BIG_SPOTS);
- HSSFCell cell = row.createCell(1);
- cell.setCellValue("X");
- cell.setCellStyle(style);
-
- // Orange "foreground", foreground being the fill foreground not the font color.
- style = wb.createCellStyle();
- style.setFillForegroundColor(HSSFColorPredefined.ORANGE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- cell = row.createCell(2);
- cell.setCellValue("X");
- cell.setCellStyle(style);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFDataFormat;
-import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.hssf.usermodel.HSSFRichTextString;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.util.CellRangeAddress;
-
-/**
- * File for HSSF testing/examples
- *
- * THIS IS NOT THE MAIN HSSF FILE!! This is a utility for testing functionality.
- * It does contain sample API usage that may be educational to regular API
- * users.
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class HSSFReadWrite {
-
- private HSSFReadWrite() {}
-
- /**
- * creates an {@link HSSFWorkbook} with the specified OS filename.
- */
- private static HSSFWorkbook readFile(String filename) throws IOException {
- try (FileInputStream fis = new FileInputStream(filename)) {
- return new HSSFWorkbook(fis); // NOSONAR - should not be closed here
- }
- }
-
- /**
- * given a filename this outputs a sample sheet with just a set of
- * rows/cells.
- */
- private static void testCreateSampleSheet(String outputFilename) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook();
- FileOutputStream out = new FileOutputStream(outputFilename)) {
- HSSFSheet s = wb.createSheet();
- HSSFCellStyle cs = wb.createCellStyle();
- HSSFCellStyle cs2 = wb.createCellStyle();
- HSSFCellStyle cs3 = wb.createCellStyle();
- HSSFFont f = wb.createFont();
- HSSFFont f2 = wb.createFont();
-
- f.setFontHeightInPoints((short) 12);
- f.setColor((short) 0xA);
- f.setBold(true);
- f2.setFontHeightInPoints((short) 10);
- f2.setColor((short) 0xf);
- f2.setBold(true);
- cs.setFont(f);
- cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("($#,##0_);[Red]($#,##0)"));
- cs2.setBorderBottom(BorderStyle.THIN);
- cs2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- cs2.setFillForegroundColor((short) 0xA);
- cs2.setFont(f2);
- wb.setSheetName(0, "HSSF Test");
- int rownum;
- for (rownum = 0; rownum < 300; rownum++) {
- HSSFRow r = s.createRow(rownum);
- if ((rownum % 2) == 0) {
- r.setHeight((short) 0x249);
- }
-
- for (int cellnum = 0; cellnum < 50; cellnum += 2) {
- HSSFCell c = r.createCell(cellnum);
- c.setCellValue((rownum * 10000.0) + cellnum
- + (rownum / 1000.0) + (cellnum / 10000.0));
- if ((rownum % 2) == 0) {
- c.setCellStyle(cs);
- }
- c = r.createCell(cellnum + 1);
- c.setCellValue(new HSSFRichTextString("TEST"));
- // 50 characters divided by 1/20th of a point
- s.setColumnWidth(cellnum + 1, (int) (50 * 8 / 0.05));
- if ((rownum % 2) == 0) {
- c.setCellStyle(cs2);
- }
- }
- }
-
- // draw a thick black border on the row at the bottom using BLANKS
- rownum++;
- rownum++;
- HSSFRow r = s.createRow(rownum);
- cs3.setBorderBottom(BorderStyle.THICK);
- for (int cellnum = 0; cellnum < 50; cellnum++) {
- HSSFCell c = r.createCell(cellnum);
- c.setCellStyle(cs3);
- }
- s.addMergedRegion(new CellRangeAddress(0, 3, 0, 3));
- s.addMergedRegion(new CellRangeAddress(100, 110, 100, 110));
-
- // end draw thick black border
- // create a sheet, set its title then delete it
- wb.createSheet();
- wb.setSheetName(1, "DeletedSheet");
- wb.removeSheetAt(1);
-
- // end deleted sheet
- wb.write(out);
- }
- }
-
- /**
- * Method main
- *
- * Given 1 argument takes that as the filename, inputs it and dumps the
- * cell values/types out to sys.out.<br>
- *
- * given 2 arguments where the second argument is the word "write" and the
- * first is the filename - writes out a sample (test) spreadsheet
- * see {@link HSSFReadWrite#testCreateSampleSheet(String)}.<br>
- *
- * given 2 arguments where the first is an input filename and the second
- * an output filename (not write), attempts to fully read in the
- * spreadsheet and fully write it out.<br>
- *
- * given 3 arguments where the first is an input filename and the second an
- * output filename (not write) and the third is "modify1", attempts to read in the
- * spreadsheet, deletes rows 0-24, 74-99. Changes cell at row 39, col 3 to
- * "MODIFIED CELL" then writes it out. Hence this is "modify test 1". If you
- * take the output from the write test, you'll have a valid scenario.
- */
- public static void main(String[] args) throws Exception {
- if (args.length < 1) {
- System.err.println("At least one argument expected");
- return;
- }
-
- String fileName = args[0];
- if (args.length < 2) {
-
- try (HSSFWorkbook wb = HSSFReadWrite.readFile(fileName)) {
- System.out.println("Data dump:\n");
-
- for (int k = 0; k < wb.getNumberOfSheets(); k++) {
- HSSFSheet sheet = wb.getSheetAt(k);
- int rows = sheet.getPhysicalNumberOfRows();
- System.out.println("Sheet " + k + " \"" + wb.getSheetName(k) + "\" has " + rows + " row(s).");
- for (int r = 0; r < rows; r++) {
- HSSFRow row = sheet.getRow(r);
- if (row == null) {
- continue;
- }
-
- System.out.println("\nROW " + row.getRowNum() + " has " + row.getPhysicalNumberOfCells() + " cell(s).");
- for (int c = 0; c < row.getLastCellNum(); c++) {
- HSSFCell cell = row.getCell(c);
- String value;
-
- if (cell != null) {
- switch (cell.getCellType()) {
-
- case FORMULA:
- value = "FORMULA value=" + cell.getCellFormula();
- break;
-
- case NUMERIC:
- value = "NUMERIC value=" + cell.getNumericCellValue();
- break;
-
- case STRING:
- value = "STRING value=" + cell.getStringCellValue();
- break;
-
- case BLANK:
- value = "<BLANK>";
- break;
-
- case BOOLEAN:
- value = "BOOLEAN value-" + cell.getBooleanCellValue();
- break;
-
- case ERROR:
- value = "ERROR value=" + cell.getErrorCellValue();
- break;
-
- default:
- value = "UNKNOWN value of type " + cell.getCellType();
- }
- System.out.println("CELL col=" + cell.getColumnIndex() + " VALUE=" + value);
- }
- }
- }
- }
- }
- } else if (args.length == 2) {
- if ("write".equalsIgnoreCase(args[1])) {
- System.out.println("Write mode");
- long time = System.currentTimeMillis();
- HSSFReadWrite.testCreateSampleSheet(fileName);
-
- System.out.println("" + (System.currentTimeMillis() - time) + " ms generation time");
- } else {
- System.out.println("readwrite test");
- try (HSSFWorkbook wb = HSSFReadWrite.readFile(fileName);
- FileOutputStream stream = new FileOutputStream(args[1])) {
- wb.write(stream);
- }
- }
- } else if (args.length == 3 && "modify1".equalsIgnoreCase(args[2])) {
- // delete row 0-24, row 74 - 99 && change cell 3 on row 39 to string "MODIFIED CELL!!"
-
- try (HSSFWorkbook wb = HSSFReadWrite.readFile(fileName);
- FileOutputStream stream = new FileOutputStream(args[1])) {
- HSSFSheet sheet = wb.getSheetAt(0);
-
- for (int k = 0; k < 25; k++) {
- HSSFRow row = sheet.getRow(k);
- sheet.removeRow(row);
- }
- for (int k = 74; k < 100; k++) {
- HSSFRow row = sheet.getRow(k);
- sheet.removeRow(row);
- }
- HSSFRow row = sheet.getRow(39);
- HSSFCell cell = row.getCell(3);
- cell.setCellValue("MODIFIED CELL!!!!!");
-
- wb.write(stream);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * Test if hyperlink formula, with url that got more than 127 characters, works
- */
-public class HyperlinkFormula {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
- HSSFRow row = sheet.createRow(0);
-
- HSSFCell cell = row.createCell(0);
- cell.setCellFormula("HYPERLINK(\"http://127.0.0.1:8080/toto/truc/index.html?test=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\", \"test\")");
-
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.common.usermodel.HyperlinkType;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFCreationHelper;
-import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.hssf.usermodel.HSSFHyperlink;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
-import org.apache.poi.ss.usermodel.Font;
-
-/**
- * Demonstrates how to create hyperlinks.
- */
-public class Hyperlinks {
-
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFCreationHelper helper = wb.getCreationHelper();
-
- //cell style for hyperlinks
- //by default hyperlinks are blue and underlined
- HSSFCellStyle hlinkStyle = wb.createCellStyle();
- HSSFFont hlinkFont = wb.createFont();
- hlinkFont.setUnderline(Font.U_SINGLE);
- hlinkFont.setColor(HSSFColorPredefined.BLUE.getIndex());
- hlinkStyle.setFont(hlinkFont);
-
- HSSFCell cell;
- HSSFSheet sheet = wb.createSheet("Hyperlinks");
-
- //URL
- cell = sheet.createRow(0).createCell(0);
- cell.setCellValue("URL Link");
- HSSFHyperlink link = helper.createHyperlink(HyperlinkType.URL);
- link.setAddress("https://poi.apache.org/");
- cell.setHyperlink(link);
- cell.setCellStyle(hlinkStyle);
-
- //link to a file in the current directory
- cell = sheet.createRow(1).createCell(0);
- cell.setCellValue("File Link");
- link = helper.createHyperlink(HyperlinkType.FILE);
- link.setAddress("link1.xls");
- cell.setHyperlink(link);
- cell.setCellStyle(hlinkStyle);
-
- //e-mail link
- cell = sheet.createRow(2).createCell(0);
- cell.setCellValue("Email Link");
- link = helper.createHyperlink(HyperlinkType.EMAIL);
- //note, if subject contains white spaces, make sure they are url-encoded
- link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
- cell.setHyperlink(link);
- cell.setCellStyle(hlinkStyle);
-
- //link to a place in this workbook
-
- //create a target sheet and cell
- HSSFSheet sheet2 = wb.createSheet("Target Sheet");
- sheet2.createRow(0).createCell(0).setCellValue("Target Cell");
-
- cell = sheet.createRow(3).createCell(0);
- cell.setCellValue("Worksheet Link");
- link = helper.createHyperlink(HyperlinkType.DOCUMENT);
- link.setAddress("'Target Sheet'!A1");
- cell.setHyperlink(link);
- cell.setCellStyle(hlinkStyle);
-
- try (FileOutputStream out = new FileOutputStream("hssf-links.xls")) {
- wb.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFDataFormat;
-import org.apache.poi.hssf.usermodel.HSSFRichTextString;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * This class contains code that demonstrates how to insert plain, numbered
- * and bulleted lists into an Excel spreadsheet cell.
- *
- * Look at the code contained in the demonstrateMethodCalls() method. It calls
- * other methods that create plain, numbered and bulleted single and
- * multi-level lists. The demonstrateMethodCalls() method appears at the top
- * of the class definition.
- *
- * Though different methods are provided to construct single and multi-level
- * plain, numbered and bulleted lists, close examination will reveal that they
- * are not strictly necessary. If the inputs to the listInCell() and
- * multilLevelListInCell() methods are constructed to include the bullet
- * character or the item numbers then these methods alone may be sufficient.
- *
- * @author Mark Beardsley [msb at apache.org]
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public class InCellLists {
-
- // This character looks like a solid, black, loser case letter 'o'
- // positioned up from the base line of the text.
- private static final char BULLET_CHARACTER = '\u2022';
-
- // The tab character - \t - cannot be used to create a tab space
- // within a cell as it is rendered as a square. Therefore, four
- // spaces are used to simulate that character.
- private static final String TAB = " ";
-
- /**
- * Call each of the list creation methods.
- *
- * @param outputFilename A String that encapsulates the name of and path to
- * the Excel spreadsheet file this code will create.
- */
- public void demonstrateMethodCalls(String outputFilename) throws IOException {
- try (HSSFWorkbook workbook = new HSSFWorkbook()) {
- HSSFSheet sheet = workbook.createSheet("In Cell Lists");
- HSSFRow row = sheet.createRow(0);
-
- // Create a cell at A1 and insert a single, bulleted, item into
- // that cell.
- HSSFCell cell = row.createCell(0);
- this.bulletedItemInCell(workbook, "List Item", cell);
-
- // Create a cell at A2 and insert a plain list - that is one
- // whose items are neither bulleted or numbered - into that cell.
- row = sheet.createRow(1);
- cell = row.createCell(0);
- List<String> listItems = new ArrayList<>();
- listItems.add("List Item One.");
- listItems.add("List Item Two.");
- listItems.add("List Item Three.");
- listItems.add("List Item Four.");
- this.listInCell(workbook, listItems, cell);
- // The row height and cell width are set here to ensure that the
- // list may be seen.
- row.setHeight((short) 1100);
- sheet.setColumnWidth(0, 9500);
-
- // Create a cell at A3 and insert a numbered list into that cell.
- // Note that a couple of items have been added to the listItems
- // ArrayList
- row = sheet.createRow(2);
- cell = row.createCell(0);
- listItems.add("List Item Five.");
- listItems.add("List Item Six.");
- this.numberedListInCell(workbook, listItems, cell, 1, 2);
- row.setHeight((short) 1550);
-
- // Create a cell at A4 and insert a numbered list into that cell.
- // Note that a couple of items have been added to the listItems
- // ArrayList
- row = sheet.createRow(3);
- cell = row.createCell(0);
- listItems.add("List Item Seven.");
- listItems.add("List Item Eight.");
- listItems.add("List Item Nine.");
- listItems.add("List Item Ten.");
- this.bulletedListInCell(workbook, listItems, cell);
- row.setHeight((short) 2550);
-
- // Insert a plain, multi-level list into cell A5. Note that
- // the major difference here is that the list items are passed as
- // an ArrayList of MultiLevelListItems. Note that an ArrayList
- // of instances of an inner class was used here in preference to
- // a Hashtable or HashMap as the ArrayList will preserve the
- // ordering of the items added to it; the first item added will
- // be the first item recovered and the last item added, the last
- // item recovered. Alternatively, a LinkedHashMap could be used
- // to preserve order.
- row = sheet.createRow(4);
- cell = row.createCell(0);
- List<MultiLevelListItem> multiLevelListItems = new ArrayList<>();
- listItems = new ArrayList<>();
- listItems.add("ML List Item One - Sub Item One.");
- listItems.add("ML List Item One - Sub Item Two.");
- listItems.add("ML List Item One - Sub Item Three.");
- listItems.add("ML List Item One - Sub Item Four.");
- multiLevelListItems.add(new MultiLevelListItem("List Item One.", listItems));
- // Passing either null or an empty ArrayList will signal that
- // there are no lower level items associated with the top level
- // item
- multiLevelListItems.add(new MultiLevelListItem("List Item Two.", null));
- multiLevelListItems.add(new MultiLevelListItem("List Item Three.", null));
- listItems = new ArrayList<>();
- listItems.add("ML List Item Four - Sub Item One.");
- listItems.add("ML List Item Four - Sub Item Two.");
- listItems.add("ML List Item Four - Sub Item Three.");
- multiLevelListItems.add(new MultiLevelListItem("List Item Four.", listItems));
- this.multiLevelListInCell(workbook, multiLevelListItems, cell);
- row.setHeight((short) 2800);
-
- // Insert a numbered multi-level list into cell A6. Note that the
- // same ArrayList as constructed for the above plain multi-level
- // list example will be re-used
- row = sheet.createRow(5);
- cell = row.createCell(0);
- this.multiLevelNumberedListInCell(workbook, multiLevelListItems,
- cell, 1, 1, 1, 2);
- row.setHeight((short) 2800);
-
- // Insert a numbered multi-level list into cell A7. Note that the
- // same ArrayList as constructed for the plain multi-level list
- // example will be re-used
- row = sheet.createRow(6);
- cell = row.createCell(0);
- this.multiLevelBulletedListInCell(workbook, multiLevelListItems, cell);
- row.setHeight((short) 2800);
-
- // Save the completed workbook
- try (FileOutputStream fos = new FileOutputStream(new File(outputFilename))) {
- workbook.write(fos);
- }
- } catch (IOException ioEx) {
- System.out.println("Caught a: " + ioEx.getClass().getName());
- System.out.println("Message: " + ioEx.getMessage());
- System.out.println("Stacktrace follows...........");
- ioEx.printStackTrace(System.out);
- }
- }
-
- /**
- * Inserts a single bulleted item into a cell.
- *
- * @param workbook A reference to the HSSFWorkbook that 'contains' the
- * cell.
- * @param listItem An instance of the String class encapsulating the
- * items text.
- * @param cell An instance of the HSSFCell class that encapsulates a
- * reference to the spreadsheet cell into which the list item
- * will be written.
- */
- public void bulletedItemInCell(HSSFWorkbook workbook, String listItem, HSSFCell cell) {
- // A format String must be built to ensure that the contents of the
- // cell appear as a bulleted item.
- HSSFDataFormat format = workbook.createDataFormat();
- String formatString = InCellLists.BULLET_CHARACTER + " @";
- int formatIndex = format.getFormat(formatString);
-
- // Construct an HSSFCellStyle and set it's data formt to use the
- // object created above.
- HSSFCellStyle bulletStyle = workbook.createCellStyle();
- bulletStyle.setDataFormat((short)formatIndex);
-
- // Set the cells contents and style.
- cell.setCellValue(new HSSFRichTextString(listItem));
- cell.setCellStyle(bulletStyle);
- }
-
- /**
- * Inserts a list of plain items - that is items that are neither
- * numbered or bulleted - into a single cell.
- *
- * @param workbook A reference to the HSSFWorkbook that 'contains' the
- * cell.
- * @param listItems An ArrayList whose elements encapsulate the text for
- * the list's items.
- * @param cell An instance of the HSSFCell class that encapsulates a
- * reference to the spreadsheet cell into which the list
- * will be written.
- */
- public void listInCell(HSSFWorkbook workbook, List<String> listItems, HSSFCell cell) {
- StringBuilder buffer = new StringBuilder();
- HSSFCellStyle wrapStyle = workbook.createCellStyle();
- wrapStyle.setWrapText(true);
- for(String listItem : listItems) {
- buffer.append(listItem);
- buffer.append("\n");
- }
- // The StringBuilder's contents are the source for the contents
- // of the cell.
- cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
- cell.setCellStyle(wrapStyle);
- }
-
- /**
- * Inserts a numbered list into a single cell.
- *
- * @param workbook A reference to the HSSFWorkbook that 'contains' the
- * cell.
- * @param listItems An ArrayList whose elements encapsulate the text for
- * the lists items.
- * @param cell An instance of the HSSFCell class that encapsulates a
- * reference to the spreadsheet cell into which the list
- * will be written.
- * @param startingValue A primitive int containing the number for the first
- * item in the list.
- * @param increment A primitive int containing the value that should be used
- * to calculate subsequent item numbers.
- */
- public void numberedListInCell(HSSFWorkbook workbook,
- List<String> listItems,
- HSSFCell cell,
- int startingValue,
- int increment) {
- StringBuilder buffer = new StringBuilder();
- int itemNumber = startingValue;
- // Note that again, an HSSFCellStye object is required and that
- // it's wrap text property should be set to 'true'
- HSSFCellStyle wrapStyle = workbook.createCellStyle();
- wrapStyle.setWrapText(true);
- // Note that the basic method is identical to the listInCell() method
- // with one difference; a number prefixed to the items text.
- for(String listItem : listItems) {
- buffer.append(itemNumber).append(". ");
- buffer.append(listItem);
- buffer.append("\n");
- itemNumber += increment;
- }
- // The StringBuilder's contents are the source for the contents
- // of the cell.
- cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
- cell.setCellStyle(wrapStyle);
- }
-
- /**
- * Insert a bulleted list into a cell.
- *
- * @param workbook A reference to the HSSFWorkbook that 'contains' the
- * cell.
- * @param listItems An ArrayList whose elements encapsulate the text for
- * the lists items.
- * @param cell An instance of the HSSFCell class that encapsulates a
- * reference to the spreadsheet cell into which the list
- * will be written.
- */
- public void bulletedListInCell(HSSFWorkbook workbook,
- List<String> listItems,
- HSSFCell cell) {
- StringBuilder buffer = new StringBuilder();
- // Note that again, an HSSFCellStye object is required and that
- // it's wrap text property should be set to 'true'
- HSSFCellStyle wrapStyle = workbook.createCellStyle();
- wrapStyle.setWrapText(true);
- // Note that the basic method is identical to the listInCell() method
- // with one difference; the bullet character prefixed to the items text.
- for(String listItem : listItems) {
- buffer.append(InCellLists.BULLET_CHARACTER + " ");
- buffer.append(listItem);
- buffer.append("\n");
- }
- // The StringBuilder's contents are the source for the contents
- // of the cell.
- cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
- cell.setCellStyle(wrapStyle);
- }
-
- /**
- * Insert a multi-level list into a cell.
- *
- * @param workbook A reference to the HSSFWorkbook that 'contains' the
- * cell.
- * @param multiLevelListItems An ArrayList whose elements contain instances
- * of the MultiLevelListItem class. Each element
- * encapsulates the text for the high level item
- * along with an ArrayList. Each element of this
- * ArrayList encapsulates the text for a lower
- * level item.
- * @param cell An instance of the HSSFCell class that encapsulates a
- * reference to the spreadsheet cell into which the list
- * will be written.
- */
- public void multiLevelListInCell(HSSFWorkbook workbook,
- List<MultiLevelListItem> multiLevelListItems,
- HSSFCell cell) {
- StringBuilder buffer = new StringBuilder();
- // Note that again, an HSSFCellStye object is required and that
- // it's wrap text property should be set to 'true'
- HSSFCellStyle wrapStyle = workbook.createCellStyle();
- wrapStyle.setWrapText(true);
- // Step through the ArrayList of MultilLevelListItem instances.
- for(MultiLevelListItem multiLevelListItem : multiLevelListItems) {
- // For each element in the ArrayList, get the text for the high
- // level list item......
- buffer.append(multiLevelListItem.getItemText());
- buffer.append("\n");
- // and then an ArrayList whose elements encapsulate the text
- // for the lower level list items.
- List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
- if (lowerLevelItems == null || lowerLevelItems.isEmpty()) {
- continue;
- }
- for(String item : lowerLevelItems) {
- buffer.append(InCellLists.TAB);
- buffer.append(item);
- buffer.append("\n");
- }
- }
- // The StringBuilder's contents are the source for the contents
- // of the cell.
- cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
- cell.setCellStyle(wrapStyle);
- }
-
- /**
- * Insert a multi-level list into a cell.
- *
- * @param workbook A reference to the HSSFWorkbook that 'contains' the
- * cell.
- * @param multiLevelListItems An ArrayList whose elements contain instances
- * of the MultiLevelListItem class. Each element
- * encapsulates the text for the high level item
- * along with an ArrayList. Each element of this
- * ArrayList encapsulates the text for a lower
- * level item.
- * @param cell An instance of the HSSFCell class that encapsulates a
- * reference to the spreadsheet cell into which the list
- * will be written.
- * @param highLevelStartingValue A primitive int containing the number
- * for the first high level item in the list.
- * @param highLevelIncrement A primitive int containing the value that
- * should be used to calculate the number of
- * subsequent high level item.
- * @param lowLevelStartingValue A primitive int will containing the number
- * for the first low level item associated
- * with a high level item.
- * @param lowLevelIncrement A primitive int containing the value that
- * should be used to calculate the number of
- * subsequent low level item.
- */
- public void multiLevelNumberedListInCell(HSSFWorkbook workbook,
- List<MultiLevelListItem> multiLevelListItems,
- HSSFCell cell,
- int highLevelStartingValue,
- int highLevelIncrement,
- int lowLevelStartingValue,
- int lowLevelIncrement) {
- StringBuilder buffer = new StringBuilder();
- int highLevelItemNumber = highLevelStartingValue;
- // Note that again, an HSSFCellStye object is required and that
- // it's wrap text property should be set to 'true'
- HSSFCellStyle wrapStyle = workbook.createCellStyle();
- wrapStyle.setWrapText(true);
- // Step through the ArrayList of MultilLevelListItem instances.
- for(MultiLevelListItem multiLevelListItem : multiLevelListItems) {
- // For each element in the ArrayList, get the text for the high
- // level list item......
- buffer.append(highLevelItemNumber);
- buffer.append(". ");
- buffer.append(multiLevelListItem.getItemText());
- buffer.append("\n");
- // and then an ArrayList whose elements encapsulate the text
- // for the lower level list items.
- List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
- if(lowerLevelItems != null && !lowerLevelItems.isEmpty()) {
- int lowLevelItemNumber = lowLevelStartingValue;
- for(String item : lowerLevelItems) {
- buffer.append(InCellLists.TAB);
- buffer.append(highLevelItemNumber);
- buffer.append(".");
- buffer.append(lowLevelItemNumber);
- buffer.append(" ");
- buffer.append(item);
- buffer.append("\n");
- lowLevelItemNumber += lowLevelIncrement;
- }
- }
- highLevelItemNumber += highLevelIncrement;
- }
- // The StringBuilder's contents are the source for the contents
- // of the cell.
- cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
- cell.setCellStyle(wrapStyle);
- }
-
- /**
- * Insert a bulleted multi-level list into a cell.
- *
- * @param workbook A reference to the HSSFWorkbook that 'contains' the
- * cell.
- * @param multiLevelListItems An ArrayList whose elements contain instances
- * of the MultiLevelListItem class. Each element
- * encapsulates the text for the high level item
- * along with an ArrayList. Each element of this
- * ArrayList encapsulates the text for a lower
- * level item.
- * @param cell An instance of the HSSFCell class that encapsulates a
- * reference to the spreadsheet cell into which the list
- * will be written.
- */
- public void multiLevelBulletedListInCell(HSSFWorkbook workbook,
- List<MultiLevelListItem> multiLevelListItems,
- HSSFCell cell) {
- StringBuilder buffer = new StringBuilder();
- // Note that again, an HSSFCellStye object is required and that
- // it's wrap text property should be set to 'true'
- HSSFCellStyle wrapStyle = workbook.createCellStyle();
- wrapStyle.setWrapText(true);
- // Step through the ArrayList of MultilLevelListItem instances.
- for(MultiLevelListItem multiLevelListItem : multiLevelListItems) {
- // For each element in the ArrayList, get the text for the high
- // level list item......
- buffer.append(InCellLists.BULLET_CHARACTER);
- buffer.append(" ");
- buffer.append(multiLevelListItem.getItemText());
- buffer.append("\n");
- // and then an ArrayList whose elements encapsulate the text
- // for the lower level list items.
- List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
- if(lowerLevelItems != null && !lowerLevelItems.isEmpty()) {
- for(String item : lowerLevelItems) {
- buffer.append(InCellLists.TAB);
- buffer.append(InCellLists.BULLET_CHARACTER);
- buffer.append(" ");
- buffer.append(item);
- buffer.append("\n");
- }
- }
- }
- // The StringBuilder's contents are the source for the contents
- // of the cell.
- cell.setCellValue(new HSSFRichTextString(buffer.toString().trim()));
- cell.setCellStyle(wrapStyle);
- }
-
- /**
- * The main entry point to the program. Demonstrates how to call the method
- * that will create an Excel workbook containing many different sorts of
- * lists.
- *
- * @param args the command line arguments.
- */
- public static void main(String[] args) throws IOException {
- new InCellLists().demonstrateMethodCalls("Latest In Cell List.xls");
- }
-
- /**
- * An instance of this inner class models an item or element in a
- * multi-level list. Each multi-level list item consists of the text for the
- * high level items and an ArrayList containing the text for each of the
- * associated lower level items. When written into a cell, each multi-level
- * list item will have this general appearance.
- *
- * Item One
- * Sub Item One.
- * Sub Item Two.
- * Item Two
- * Sub Item One.
- * Sub Item Two.
- * etc.
- *
- * It would be quite possible to modify this class to model much more
- * complex list structures descending through two, three or even more
- * levels.
- */
- public final class MultiLevelListItem {
-
- private String itemText;
- private List<String> lowerLevelItems;
-
- /**
- * Create a new instance of the MultiLevelListItem class using the
- * following parameters.
- *
- * @param itemText A String that encapsulates the text for the high
- * level list item.
- * @param lowerLevelItems An ArrayList whose elements encapsulate the
- * text for the associated lower level list
- * items.
- */
- public MultiLevelListItem(String itemText, List<String> lowerLevelItems) {
- this.itemText = itemText;
- this.lowerLevelItems = lowerLevelItems;
- }
-
- /**
- * Get the text for the high level list item.
- *
- * @return A String that encapsulates the text for the high level list
- * item.
- */
- public String getItemText() {
- return(this.itemText);
- }
-
- /**
- * Get the text for the associated lower level list items.
- *
- * @return An ArrayList whose elements each encapsulate the text for a
- * single associated lower level list item.
- */
- public List<String> getLowerLevelItems() {
- return lowerLevelItems;
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-
-/**
- * An example of how to merge regions of cells.
- */
-public class MergedCells {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
-
- HSSFRow row = sheet.createRow(1);
- HSSFCell cell = row.createCell(1);
- cell.setCellValue("This is a test of merging");
-
- sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, 2));
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * Demonstrates how to use newlines in cells.
- */
-public class NewLinesInCells {
- public static void main( String[] args ) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet s = wb.createSheet();
- HSSFFont f2 = wb.createFont();
-
- HSSFCellStyle cs = wb.createCellStyle();
-
- cs.setFont(f2);
- // Word Wrap MUST be turned on
- cs.setWrapText(true);
-
- HSSFRow r = s.createRow(2);
- r.setHeight((short) 0x349);
- HSSFCell c = r.createCell(2);
- c.setCellValue("Use \n with word wrap on to create a new line");
- c.setCellStyle(cs);
- s.setColumnWidth(2, (int) ((50 * 8) / ((double) 1 / 20)));
-
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.util.WorkbookUtil;
-
-/**
- * Creates a new workbook with a sheet that's been explicitly defined.
- */
-public abstract class NewSheet {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- wb.createSheet("new sheet");
- // create with default name
- wb.createSheet();
- final String name = "second sheet";
- // setting sheet name later
- wb.setSheetName(1, WorkbookUtil.createSafeSheetName(name));
-
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * This example creates a new blank workbook. This workbook will contain a single blank sheet.
- */
-public class NewWorkbook {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFChildAnchor;
-import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
-import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.hssf.usermodel.HSSFPatriarch;
-import org.apache.poi.hssf.usermodel.HSSFPicture;
-import org.apache.poi.hssf.usermodel.HSSFPolygon;
-import org.apache.poi.hssf.usermodel.HSSFRichTextString;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFShape;
-import org.apache.poi.hssf.usermodel.HSSFShapeGroup;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFSimpleShape;
-import org.apache.poi.hssf.usermodel.HSSFTextbox;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.Workbook;
-
-/**
- * Demonstrates how to use the office drawing capabilities of POI.
- */
-public final class OfficeDrawing {
- private OfficeDrawing() {}
-
- public static void main(String[] args) throws IOException {
- // Create the workbook and sheets.
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet1 = wb.createSheet("new sheet");
- HSSFSheet sheet2 = wb.createSheet("second sheet");
- HSSFSheet sheet3 = wb.createSheet("third sheet");
- HSSFSheet sheet4 = wb.createSheet("fourth sheet");
- HSSFSheet sheet5 = wb.createSheet("fifth sheet");
-
- // Draw stuff in them
- drawSheet1(sheet1);
- drawSheet2(sheet2);
- drawSheet3(sheet3);
- drawSheet4(sheet4, wb);
- drawSheet5(sheet5, wb);
-
- // Write the file out.
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-
- private static void drawSheet1( HSSFSheet sheet1 )
- {
- // Create a row and size one of the cells reasonably large.
- HSSFRow row = sheet1.createRow(2);
- row.setHeight((short) 2800);
- row.createCell(1);
- sheet1.setColumnWidth(2, 9000);
-
- // Create the drawing patriarch. This is the top level container for
- // all shapes.
- HSSFPatriarch patriarch = sheet1.createDrawingPatriarch();
-
- // Draw some lines and an oval.
- drawLinesToCenter( patriarch );
- drawManyLines( patriarch );
- drawOval( patriarch );
- drawPolygon( patriarch );
-
- // Draw a rectangle.
- HSSFSimpleShape rect = patriarch.createSimpleShape( new HSSFClientAnchor(100, 100, 900, 200, (short)0, 0, (short)0, 0) );
- rect.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
- }
-
- private static void drawSheet2( HSSFSheet sheet2 )
- {
- // Create a row and size one of the cells reasonably large.
- HSSFRow row = sheet2.createRow(2);
- row.createCell(1);
- row.setHeightInPoints(240);
- sheet2.setColumnWidth(2, 9000);
-
- // Create the drawing patriarch. This is the top level container for
- // all shapes. This will clear out any existing shapes for that sheet.
- HSSFPatriarch patriarch = sheet2.createDrawingPatriarch();
-
- // Draw a grid in one of the cells.
- drawGrid( patriarch );
- }
-
- private static void drawSheet3( HSSFSheet sheet3 )
- {
- // Create a row and size one of the cells reasonably large
- HSSFRow row = sheet3.createRow(2);
- row.setHeightInPoints(140);
- row.createCell(1);
- sheet3.setColumnWidth(2, 9000);
-
- // Create the drawing patriarch. This is the top level container for
- // all shapes. This will clear out any existing shapes for that sheet.
- HSSFPatriarch patriarch = sheet3.createDrawingPatriarch();
-
- // Create a shape group.
- HSSFShapeGroup group = patriarch.createGroup(
- new HSSFClientAnchor(0,0,900,200,(short)2,2,(short)2,2));
-
- // Create a couple of lines in the group.
- HSSFSimpleShape shape1 = group.createShape(new HSSFChildAnchor(3,3,500,500));
- shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
- ( (HSSFChildAnchor) shape1.getAnchor() ).setAnchor((short)3,3,500,500);
- HSSFSimpleShape shape2 = group.createShape(new HSSFChildAnchor((short)1,200,400,600));
- shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
-
- }
-
- private static void drawSheet4( HSSFSheet sheet4, HSSFWorkbook wb )
- {
- // Create the drawing patriarch. This is the top level container for
- // all shapes. This will clear out any existing shapes for that sheet.
- HSSFPatriarch patriarch = sheet4.createDrawingPatriarch();
-
- // Create a couple of textboxes
- HSSFTextbox textbox1 = patriarch.createTextbox(
- new HSSFClientAnchor(0,0,0,0,(short)1,1,(short)2,2));
- textbox1.setString(new HSSFRichTextString("This is a test") );
- HSSFTextbox textbox2 = patriarch.createTextbox(
- new HSSFClientAnchor(0,0,900,100,(short)3,3,(short)3,4));
- textbox2.setString(new HSSFRichTextString("Woo") );
- textbox2.setFillColor(200,0,0);
- textbox2.setLineStyle(HSSFShape.LINESTYLE_DOTGEL);
-
- // Create third one with some fancy font styling.
- HSSFTextbox textbox3 = patriarch.createTextbox(
- new HSSFClientAnchor(0,0,900,100,(short)4,4,(short)5,4+1));
- HSSFFont font = wb.createFont();
- font.setItalic(true);
- font.setUnderline(Font.U_DOUBLE);
- HSSFRichTextString string = new HSSFRichTextString("Woo!!!");
- string.applyFont(2,5,font);
- textbox3.setString(string );
- textbox3.setFillColor(0x08000030);
- textbox3.setLineStyle(HSSFShape.LINESTYLE_NONE); // no line around the textbox.
- textbox3.setNoFill(true); // make it transparent
- }
-
- private static void drawSheet5( HSSFSheet sheet5, HSSFWorkbook wb ) throws IOException
- {
-
- // Create the drawing patriarch. This is the top level container for
- // all shapes. This will clear out any existing shapes for that sheet.
- HSSFPatriarch patriarch = sheet5.createDrawingPatriarch();
-
- HSSFClientAnchor anchor;
- anchor = new HSSFClientAnchor(0,0,0,255,(short)2,2,(short)4,7);
- anchor.setAnchorType( AnchorType.MOVE_DONT_RESIZE );
- patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4.png", wb ));
-
- anchor = new HSSFClientAnchor(0,0,0,255,(short)4,2,(short)5,7);
- anchor.setAnchorType( AnchorType.MOVE_DONT_RESIZE );
- patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4edited.png", wb ));
-
- anchor = new HSSFClientAnchor(0,0,1023,255,(short)6,2,(short)8,7);
- anchor.setAnchorType( AnchorType.MOVE_DONT_RESIZE );
- HSSFPicture picture = patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4s.png", wb ));
- //Reset the image to the original size.
- picture.resize();
- picture.setLineStyle( HSSFShape.LINESTYLE_DASHDOTGEL );
-
- }
-
- private static int loadPicture( String path, HSSFWorkbook wb ) throws IOException
- {
- int pictureIndex;
- try (FileInputStream fis = new FileInputStream(path);
- ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
- int c;
- while ((c = fis.read()) != -1)
- bos.write(c);
- pictureIndex = wb.addPicture(bos.toByteArray(), Workbook.PICTURE_TYPE_PNG);
- }
- return pictureIndex;
- }
-
- private static void drawOval( HSSFPatriarch patriarch )
- {
- // Create an oval and style to taste.
- HSSFClientAnchor a = new HSSFClientAnchor();
- a.setAnchor((short)2, 2, 20, 20, (short) 2, 2, 190, 80);
- HSSFSimpleShape s = patriarch.createSimpleShape(a);
- s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_OVAL);
- s.setLineStyleColor(10,10,10);
- s.setFillColor(90,10,200);
- s.setLineWidth(HSSFShape.LINEWIDTH_ONE_PT * 3);
- s.setLineStyle(HSSFShape.LINESTYLE_DOTSYS);
- }
-
- private static void drawPolygon( HSSFPatriarch patriarch )
- {
- // HSSFClientAnchor a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 2, 2, (short) 3, 3 );
- // HSSFPolygon p = patriarch.createPolygon(a);
- // p.setPolygonDrawArea(100,100);
- // p.setPoints( new int[]{30, 90, 50}, new int[]{88, 5, 44} );
-
-
- HSSFClientAnchor a = new HSSFClientAnchor();
- a.setAnchor( (short) 2, 2, 0, 0, (short) 3, 3, 1023, 255 );
- HSSFShapeGroup g = patriarch.createGroup( a );
- g.setCoordinates(0,0,200,200);
- HSSFPolygon p1 = g.createPolygon( new HSSFChildAnchor( 0, 0, 200, 200 ) );
- p1.setPolygonDrawArea( 100, 100 );
- p1.setPoints( new int[]{0, 90, 50}, new int[]{5, 5, 44} );
- p1.setFillColor( 0, 255, 0 );
- HSSFPolygon p2 = g.createPolygon( new HSSFChildAnchor( 20, 20, 200, 200 ) );
- p2.setPolygonDrawArea( 200, 200 );
- p2.setPoints( new int[]{120, 20, 150}, new int[]{105, 30, 195} );
- p2.setFillColor( 255, 0, 0 );
- }
-
- private static void drawManyLines( HSSFPatriarch patriarch )
- {
- // Draw bunch of lines
- int x1 = 100;
- int y1 = 100;
- int x2 = 800;
- int y2 = 200;
- int color = 0;
- for (int i = 0; i < 10; i++)
- {
- HSSFClientAnchor a2 = new HSSFClientAnchor();
- a2.setAnchor((short) 2, 2, x1, y1, (short) 2, 2, x2, y2);
- HSSFSimpleShape shape2 = patriarch.createSimpleShape(a2);
- shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
- shape2.setLineStyleColor(color);
- y1 -= 10;
- y2 -= 10;
- color += 30;
- }
- }
-
- private static void drawGrid( HSSFPatriarch patriarch )
- {
- // This draws a grid of lines. Since the coordinates space fixed at
- // 1024 by 256 we use a ratio to get a reasonably square grids.
-
- double xRatio = 3.22;
- double yRatio = 0.6711;
-
- int x1 = 0;
- int y1 = 0;
- int x2 = 0;
- int y2 = 200;
- for (int i = 0; i < 20; i++)
- {
- HSSFClientAnchor a2 = new HSSFClientAnchor();
- a2.setAnchor((short) 2, 2, (int) ( x1 * xRatio ), (int) ( y1 * yRatio ),
- (short) 2, 2, (int) ( x2 * xRatio ), (int) ( y2 * yRatio ));
- HSSFSimpleShape shape2 = patriarch.createSimpleShape(a2);
- shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
-
- x1 += 10;
- x2 += 10;
- }
-
- x1 = 0;
- y1 = 0;
- x2 = 200;
- y2 = 0;
- for (int i = 0; i < 20; i++)
- {
- HSSFClientAnchor a2 = new HSSFClientAnchor();
- a2.setAnchor((short) 2, 2, (int) ( x1 * xRatio ), (int) ( y1 * yRatio ),
- (short) 2, 2, (int) ( x2 * xRatio ), (int) ( y2 * yRatio ));
- HSSFSimpleShape shape2 = patriarch.createSimpleShape(a2);
- shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
-
- y1 += 10;
- y2 += 10;
- }
- }
-
- private static void drawLinesToCenter( HSSFPatriarch patriarch )
- {
- // Draw some lines from and to the corners
- {
- HSSFClientAnchor a1 = new HSSFClientAnchor();
- a1.setAnchor( (short)2, 2, 0, 0, (short) 2, 2, 512, 128);
- HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
- shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
- }
- {
- HSSFClientAnchor a1 = new HSSFClientAnchor();
- a1.setAnchor( (short)2, 2, 512, 128, (short) 2, 2, 1024, 0);
- HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
- shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
- }
- {
- HSSFClientAnchor a1 = new HSSFClientAnchor();
- a1.setAnchor( (short)1, 1, 0, 0, (short) 1, 1, 512, 100);
- HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
- shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
- }
- {
- HSSFClientAnchor a1 = new HSSFClientAnchor();
- a1.setAnchor( (short)1, 1, 512, 100, (short) 1, 1, 1024, 0);
- HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
- shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
- }
-
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import org.apache.poi.hssf.usermodel.*;
-
-import java.awt.*;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Demonstrates the use of the EscherGraphics2d library.
- *
- * @author Glen Stampoultzis (glens at apache.org)
- */
-public class OfficeDrawingWithGraphics {
- public static void main( String[] args ) throws IOException {
- // Create a workbook with one sheet and size the first three somewhat
- // larger so we can fit the chemical structure diagram in.
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("my drawing");
- sheet.setColumnWidth(1, 256 * 27);
- HSSFRow row1 = sheet.createRow(0);
- row1.setHeightInPoints(10 * 15f);
- HSSFRow row2 = sheet.createRow(1);
- row2.setHeightInPoints(5 * 15f);
- HSSFRow row3 = sheet.createRow(2);
- row3.setHeightInPoints(10 * 15f);
-
- // Add some cells so we can test that the anchoring works when we
- // sort them.
- row1.createCell(0).setCellValue("C");
- row2.createCell(0).setCellValue("A");
- row3.createCell(0).setCellValue("B");
-
- // Create the top level drawing patriarch.
- HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
-
- HSSFClientAnchor a;
- HSSFShapeGroup group;
- EscherGraphics g;
- EscherGraphics2d g2d;
- // Anchor entirely within one cell.
- a = new HSSFClientAnchor(0, 0, 1023, 255, (short) 1, 0, (short) 1, 0);
- group = patriarch.createGroup(a);
- group.setCoordinates(0, 0, 320, 276);
- float verticalPointsPerPixel = a.getAnchorHeightInPoints(sheet) / Math.abs(group.getY2() - group.getY1());
- g = new EscherGraphics(group, wb, Color.black, verticalPointsPerPixel);
- g2d = new EscherGraphics2d(g);
- drawStar(g2d);
-
- a = new HSSFClientAnchor(0, 0, 1023, 255, (short) 1, 1, (short) 1, 1);
- group = patriarch.createGroup(a);
- group.setCoordinates(0, 0, 640, 276);
- verticalPointsPerPixel = a.getAnchorHeightInPoints(sheet) / Math.abs(group.getY2() - group.getY1());
-// verticalPixelsPerPoint = (float)Math.abs(group.getY2() - group.getY1()) / a.getAnchorHeightInPoints(sheet);
- g = new EscherGraphics(group, wb, Color.black, verticalPointsPerPixel);
- g2d = new EscherGraphics2d(g);
- drawStar(g2d);
-
- try (FileOutputStream out = new FileOutputStream("workbook.xls")) {
- wb.write(out);
- }
- }
- }
-
- private static void drawStar( EscherGraphics2d g2d )
- {
- g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
- for (double i = 0; i < Math.PI; i += 0.1)
- {
- g2d.setColor( new Color((int)(i * 5343062d) ) );
- int x1 = (int) ( Math.cos(i) * 160.0 ) + 160;
- int y1 = (int) ( Math.sin(i) * 138.0 ) + 138;
- int x2 = (int) ( -Math.cos(i) * 160.0 ) + 160;
- int y2 = (int) ( -Math.sin(i) * 138.0 ) + 138;
- g2d.setStroke(new BasicStroke(2));
- g2d.drawLine(x1,y1,x2,y2);
- }
- g2d.setFont(new Font("SansSerif",Font.BOLD | Font.ITALIC, 20));
- g2d.drawString("EscherGraphics2d",70,100);
- g2d.setColor(Color.yellow);
- g2d.fillOval( 160-20,138-20,40,40);
- g2d.setColor(Color.black);
- g2d.fillPolygon(new int[] {-10+160,0+160,10+160,0+160}, new int[] {0+138,10+138,0+138,-10+138}, 4);
- g2d.drawPolygon(new int[] {-160+160,0+160,160+160,0+160}, new int[] {0+138,138+138,0+138,-138+138}, 4);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.Closeable;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-
-/**
- * Creates outlines.
- */
-public class Outlines implements Closeable {
- public static void main(String[] args)
- throws IOException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- POILogger LOGGER = POILogFactory.getLogger(Outlines.class);
- for (int i=1; i<=13; i++) {
- try (Outlines o = new Outlines()) {
- String log = (String) Outlines.class.getDeclaredMethod("test" + i).invoke(o);
- String filename = "outline" + i + ".xls";
- o.writeOut(filename);
- LOGGER.log(POILogger.INFO, filename + " written. " + log);
- }
- }
- }
-
- private final HSSFWorkbook wb = new HSSFWorkbook();
- private final HSSFSheet sheet1 = wb.createSheet("new sheet");
-
- public void writeOut(String filename) throws IOException {
- try (FileOutputStream fileOut = new FileOutputStream(filename)) {
- wb.write(fileOut);
- }
- }
-
- @Override
- public void close() throws IOException {
- wb.close();
- }
-
- public String test1() {
- sheet1.groupColumn(4, 7);
-
- for (int row = 0; row < 200; row++) {
- HSSFRow r = sheet1.createRow(row);
- for (int column = 0; column < 200; column++) {
- HSSFCell c = r.createCell(column);
- c.setCellValue(column);
- }
- }
- return "Two expanded groups.";
- }
-
- public String test2() {
- sheet1.groupColumn(2, 10);
- sheet1.groupColumn(4, 7);
- sheet1.setColumnGroupCollapsed(4, true);
- return "Two groups. Inner group collapsed.";
- }
-
- public String test3() {
- sheet1.groupColumn(2, 10);
- sheet1.groupColumn(4, 7);
- sheet1.setColumnGroupCollapsed(4, true);
- sheet1.setColumnGroupCollapsed(2, true);
- return "Two groups. Both collapsed.";
- }
-
- public String test4() {
- sheet1.groupColumn(2, 10);
- sheet1.groupColumn(4, 7);
- sheet1.setColumnGroupCollapsed(4, true);
- sheet1.setColumnGroupCollapsed(2, true);
-
- sheet1.setColumnGroupCollapsed(4, false);
- return "Two groups. Collapsed then inner group expanded.";
- }
-
- public String test5() {
- sheet1.groupColumn(2, 10);
- sheet1.groupColumn(4, 7);
- sheet1.setColumnGroupCollapsed(4, true);
- sheet1.setColumnGroupCollapsed(2, true);
-
- sheet1.setColumnGroupCollapsed(4, false);
- sheet1.setColumnGroupCollapsed(3, false);
- return "Two groups. Collapsed then reexpanded.";
- }
-
- public String test6() {
- sheet1.groupColumn(2, 10);
- sheet1.groupColumn(4, 10);
- sheet1.setColumnGroupCollapsed(4, true);
- sheet1.setColumnGroupCollapsed(2, true);
-
- sheet1.setColumnGroupCollapsed(3, false);
- return "Two groups with matching end points. Second group collapsed.";
- }
-
- public String test7() {
- sheet1.groupRow(5, 14);
- sheet1.groupRow(7, 10);
- return "Row outlines.";
- }
-
- public String test8() {
- sheet1.groupRow(5, 14);
- sheet1.groupRow(7, 10);
- sheet1.setRowGroupCollapsed(7, true);
- return "Row outlines. Inner group collapsed.";
- }
-
- public String test9() {
- sheet1.groupRow(5, 14);
- sheet1.groupRow(7, 10);
- sheet1.setRowGroupCollapsed(7, true);
- sheet1.setRowGroupCollapsed(5, true);
- return "Row outlines. Both collapsed.";
- }
-
- public String test10() {
- sheet1.groupRow(5, 14);
- sheet1.groupRow(7, 10);
- sheet1.setRowGroupCollapsed(7, true);
- sheet1.setRowGroupCollapsed(5, true);
- sheet1.setRowGroupCollapsed(8, false);
- return "Row outlines. Collapsed then inner group expanded.";
- }
-
- public String test11() {
- sheet1.groupRow(5, 14);
- sheet1.groupRow(7, 10);
- sheet1.setRowGroupCollapsed(7, true);
- sheet1.setRowGroupCollapsed(5, true);
- sheet1.setRowGroupCollapsed(8, false);
- sheet1.setRowGroupCollapsed(14, false);
- return "Row outlines. Collapsed then expanded.";
- }
-
- public String test12() {
- sheet1.groupRow(5, 14);
- sheet1.groupRow(7, 14);
- sheet1.setRowGroupCollapsed(7, true);
- sheet1.setRowGroupCollapsed(5, true);
- sheet1.setRowGroupCollapsed(6, false);
- return "Row outlines. Two row groups with matching end points. Second group collapsed.";
- }
-
- public String test13() {
- sheet1.groupRow(5, 14);
- sheet1.groupRow(7, 14);
- sheet1.groupRow(16, 19);
-
- sheet1.groupColumn(4, 7);
- sheet1.groupColumn(9, 12);
- sheet1.groupColumn(10, 11);
- return "Mixed bag.";
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-/**
- * This example demonstrates opening a workbook, modifying it and writing
- * the results back out.
- *
- * @author Glen Stampoultzis (glens at apache.org)
- */
-public class ReadWriteWorkbook {
- public static void main(String[] args) throws IOException {
- try (FileInputStream fileIn = new FileInputStream("workbook.xls")) {
- POIFSFileSystem fs = new POIFSFileSystem(fileIn);
- HSSFWorkbook wb = new HSSFWorkbook(fs);
- HSSFSheet sheet = wb.getSheetAt(0);
- HSSFRow row = sheet.getRow(2);
- if (row == null)
- row = sheet.createRow(2);
- HSSFCell cell = row.getCell(3);
- if (cell == null)
- cell = row.createCell(3);
- cell.setCellValue("a test");
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbookout.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-
-public class RepeatingRowsAndColumns {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet1 = wb.createSheet("first sheet");
- HSSFSheet sheet2 = wb.createSheet("second sheet");
- HSSFSheet sheet3 = wb.createSheet("third sheet");
-
- HSSFFont boldFont = wb.createFont();
- boldFont.setFontHeightInPoints((short) 22);
- boldFont.setBold(true);
-
- HSSFCellStyle boldStyle = wb.createCellStyle();
- boldStyle.setFont(boldFont);
-
- HSSFRow row = sheet1.createRow(1);
- HSSFCell cell = row.createCell(0);
- cell.setCellValue("This quick brown fox");
- cell.setCellStyle(boldStyle);
-
- // Set the columns to repeat from column 0 to 2 on the first sheet
- sheet1.setRepeatingColumns(CellRangeAddress.valueOf("A:C"));
- // Set the rows to repeat from row 0 to 2 on the second sheet.
- sheet2.setRepeatingRows(CellRangeAddress.valueOf("1:3"));
- // Set the the repeating rows and columns on the third sheet.
- CellRangeAddress cra = CellRangeAddress.valueOf("D1:E2");
- sheet3.setRepeatingColumns(cra);
- sheet3.setRepeatingRows(cra);
-
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.Sheet;
-
-public class SplitAndFreezePanes {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet1 = wb.createSheet("new sheet");
- HSSFSheet sheet2 = wb.createSheet("second sheet");
- HSSFSheet sheet3 = wb.createSheet("third sheet");
- HSSFSheet sheet4 = wb.createSheet("fourth sheet");
-
- // Freeze just one row
- sheet1.createFreezePane(0, 1, 0, 1);
- // Freeze just one column
- sheet2.createFreezePane(1, 0, 1, 0);
- // Freeze the columns and rows (forget about scrolling position of the lower right quadrant).
- sheet3.createFreezePane(2, 2);
- // Create a split with the lower left side being the active quadrant
- sheet4.createSplitPane(2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT);
-
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * Demonstrates how to create and use fonts.
- */
-public class WorkingWithFonts {
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet = wb.createSheet("new sheet");
-
- // Create a row and put some cells in it. Rows are 0 based.
- HSSFRow row = sheet.createRow(1);
-
- // Create a new font and alter it.
- HSSFFont font = wb.createFont();
- font.setFontHeightInPoints((short) 24);
- font.setFontName("Courier New");
- font.setItalic(true);
- font.setStrikeout(true);
-
- // Fonts are set into a style so create a new one to use.
- HSSFCellStyle style = wb.createCellStyle();
- style.setFont(font);
-
- // Create a cell and put a value in it.
- HSSFCell cell = row.createCell(1);
- cell.setCellValue("This is a test of fonts");
- cell.setCellStyle(style);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-
-/* ====================================================================
- 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.examples;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-
-import java.io.IOException;
-import java.io.FileOutputStream;
-
-/**
- * Sets the zoom magnication for a sheet.
- *
- * @author Glen Stampoultzis (glens at apache.org)
- */
-public class ZoomSheet
-{
- public static void main(String[] args) throws IOException {
- try (HSSFWorkbook wb = new HSSFWorkbook()) {
- HSSFSheet sheet1 = wb.createSheet("new sheet");
- sheet1.setZoom(75); // 75 percent magnification
-
- try (FileOutputStream fileOut = new FileOutputStream("workbook.xls")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.hwpf;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.poi.hwpf.model.StyleDescription;
-import org.apache.poi.hwpf.model.StyleSheet;
-import org.apache.poi.hwpf.usermodel.CharacterRun;
-import org.apache.poi.hwpf.usermodel.Paragraph;
-import org.apache.poi.hwpf.usermodel.Range;
-
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class Word2Forrest
-{
- Writer _out;
- HWPFDocument _doc;
-
- @SuppressWarnings("unused")
- public Word2Forrest(HWPFDocument doc, OutputStream stream) throws IOException
- {
- _out = new OutputStreamWriter (stream, StandardCharsets.UTF_8);
- _doc = doc;
-
- init ();
- openDocument ();
- openBody ();
-
- Range r = doc.getRange ();
- StyleSheet styleSheet = doc.getStyleSheet ();
-
- int sectionLevel = 0;
- int lenParagraph = r.numParagraphs ();
- boolean inCode = false;
- for (int x = 0; x < lenParagraph; x++)
- {
- Paragraph p = r.getParagraph (x);
- String text = p.text ();
- if (text.trim ().length () == 0)
- {
- continue;
- }
- StyleDescription paragraphStyle = styleSheet.getStyleDescription (p.
- getStyleIndex ());
- String styleName = paragraphStyle.getName();
- if (styleName.startsWith ("Heading"))
- {
- if (inCode)
- {
- closeSource();
- inCode = false;
- }
-
- int headerLevel = Integer.parseInt (styleName.substring (8));
- if (headerLevel > sectionLevel)
- {
- openSection ();
- }
- else
- {
- for (int y = 0; y < (sectionLevel - headerLevel) + 1; y++)
- {
- closeSection ();
- }
- openSection ();
- }
- sectionLevel = headerLevel;
- openTitle ();
- writePlainText (text);
- closeTitle ();
- }
- else
- {
- int cruns = p.numCharacterRuns ();
- CharacterRun run = p.getCharacterRun (0);
- String fontName = run.getFontName();
- if (fontName.startsWith ("Courier"))
- {
- if (!inCode)
- {
- openSource ();
- inCode = true;
- }
- writePlainText (p.text());
- }
- else
- {
- if (inCode)
- {
- inCode = false;
- closeSource();
- }
- openParagraph();
- writePlainText(p.text());
- closeParagraph();
- }
- }
- }
- for (int x = 0; x < sectionLevel; x++)
- {
- closeSection();
- }
- closeBody();
- closeDocument();
- _out.flush();
-
- }
-
- public void init ()
- throws IOException
- {
- _out.write ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
- _out.write ("<!DOCTYPE document PUBLIC \"-//APACHE//DTD Documentation V1.1//EN\" \"./dtd/document-v11.dtd\">\r\n");
- }
-
- public void openDocument ()
- throws IOException
- {
- _out.write ("<document>\r\n");
- }
- public void closeDocument ()
- throws IOException
- {
- _out.write ("</document>\r\n");
- }
-
-
- public void openBody ()
- throws IOException
- {
- _out.write ("<body>\r\n");
- }
-
- public void closeBody ()
- throws IOException
- {
- _out.write ("</body>\r\n");
- }
-
-
- public void openSection ()
- throws IOException
- {
- _out.write ("<section>");
-
- }
-
- public void closeSection ()
- throws IOException
- {
- _out.write ("</section>");
-
- }
-
- public void openTitle ()
- throws IOException
- {
- _out.write ("<title>");
- }
-
- public void closeTitle ()
- throws IOException
- {
- _out.write ("</title>");
- }
-
- public void writePlainText (String text)
- throws IOException
- {
- _out.write (text);
- }
-
- public void openParagraph ()
- throws IOException
- {
- _out.write ("<p>");
- }
-
- public void closeParagraph ()
- throws IOException
- {
- _out.write ("</p>");
- }
-
- public void openSource ()
- throws IOException
- {
- _out.write ("<source><![CDATA[");
- }
- public void closeSource ()
- throws IOException
- {
- _out.write ("]]></source>");
- }
-
-
- public static void main(String[] args) throws IOException {
- try (InputStream is = new FileInputStream(args[0]);
- OutputStream out = new FileOutputStream("test.xml")) {
- new Word2Forrest(new HWPFDocument(is), out);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Locale;
-
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.ClientAnchor;
-import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
-import org.apache.poi.ss.usermodel.Drawing;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.util.IOUtils;
-
-
-/**
- * Demonstrates how to add an image to a worksheet and set that images size
- * to a specific number of millimetres irrespective of the width of the columns
- * or height of the rows. Overridden methods are provided so that the location
- * of the image - the cells row and column coordinates that define the top
- * left hand corners of the image - can be identified either in the familiar
- * Excel manner - A1 for instance - or using POI's methodology of a column and
- * row index where 0, 0 would indicate cell A1.
- *
- * The best way to make use of these techniques is to delay adding the image to
- * the sheet until all other work has been completed. That way, the sizes of
- * all rows and columns will have been adjusted - assuming that step was
- * necessary. Even though the anchors type is set to prevent the image moving
- * or re-sizing, this setting does not have any effect until the sheet is being
- * viewed using the Excel application.
- *
- * The key to the process is the ClientAnchor class. It defines methods that allow
- * us to define the location of an image by specifying the following;
- *
- * * How far - in terms of coordinate positions - the image should be inset
- * from the left hand border of a cell.
- * * How far - in terms of coordinate positions - the image should be inset
- * from the from the top of the cell.
- * * How far - in terms of coordinate positions - the right hand edge of
- * the image should protrude into a cell (measured from the cells left hand
- * edge to the images right hand edge).
- * * How far - in terms of coordinate positions - the bottom edge of the
- * image should protrude into a row (measured from the cells top edge to
- * the images bottom edge).
- * * The index of the column that contains the cell whose top left hand
- * corner should be aligned with the top left hand corner of the image.
- * * The index of the row that contains the cell whose top left hand corner
- * should be aligned with the images top left hand corner.
- * * The index of the column that contains the cell whose top left hand
- * corner should be aligned with the images bottom right hand corner
- * * The index number of the row that contains the cell whose top left
- * hand corner should be aligned with the images bottom right hand corner.
- *
- * It can be used to add an image into cell A1, for example, in the following
- * manner;
- *
- * ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();
- *
- * anchor.setDx1(0);
- * anchor.setDy1(0);
- * anchor.setDx2(0);
- * anchor.setDy2(0);
- * anchor.setCol1(0);
- * anchor.setRow1(0);
- * anchor.setCol2(1);
- * anchor.setRow2(1);
- *
- * Taken together, the first four methods define the locations of the top left
- * and bottom right hand corners of the image if you imagine that the image is
- * represented by a simple rectangle. The setDx1() and setDy1() methods locate
- * the top left hand corner of the image while setDx2() and and Dy2() locate the
- * bottom right hand corner of the image. An individual image can be inserted
- * into a single cell or is can lie across many cells and the latter four methods
- * are used to define just where the image should be positioned. They do this by
- * again by identifying where the top left and bottom right hand corners of the
- * image should be located but this time in terms of the indexes of the cells
- * in which those corners should be located. The setCol1() and setRow1() methods
- * together identify the cell that should contain the top left hand corner of
- * the image while setCol2() and setRow2() do the same for the images bottom
- * right hand corner.
- *
- * Knowing that, it is possible to look again at the example above and to see
- * that the top left hand corner of the image will be located in cell A1 (0, 0)
- * and it will be aligned with the very top left hand corner of the cell. Likewise,
- * the bottom right hand corner of the image will be located in cell B2 (1, 1) and
- * it will again be aligned with the top left hand corner of the cell. This has the
- * effect of making the image seem to occupy the whole of cell A1. Interestingly, it
- * also has an effect on the images resizing behaviour because testing has
- * demonstrated that if the image is wholly contained within one cell and is not
- * 'attached' for want of a better word, to a neighbouring cell, then that image
- * will not increase in size in response to the user dragging the column wider
- * or the cell higher.
- *
- * The following example demonstrates a slightly different way to insert an
- * image into cell A1 and to ensure that it occupies the whole of the cell. This
- * is accomplished by specifying the the images bottom right hand corner should be
- * aligned with the bottom right hand corner of the cell. It is also a case
- * where the image will not increase in size if the user increases the size of
- * the enclosing cell - irrespective of the anchors type - but it will reduce in
- * size if the cell is made smaller.
- *
- * ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();
- *
- * anchor.setDx1(0);
- * anchor.setDy1(0);
- * anchor.setDx2(1023);
- * anchor.setDy2(255);
- * anchor.setCol1(0);
- * anchor.setRow1(0);
- * anchor.setCol2(0);
- * anchor.setRow2(0);
- *
- * Note that the final four method calls all pass the same value and seem to
- * indicate that the images top left hand corner is aligned with the top left
- * hand corner of cell A1 and that it's bottom right hand corner is also
- * aligned with the top left hand corner of cell A1. Yet, running this code
- * would see the image fully occupying cell A1. That is the result of the
- * values passed to parameters three and four; these I have referred to as
- * determining the images coordinates within the cell. They indicate that the
- * image should occupy - in order - the full width of the column and the full
- * height of the row.
- *
- * The co-ordinate values shown are the maxima; and they are independent of
- * row height/column width and of the font used. Passing 255 will always result
- * in the image occupying the full height of the row and passing 1023 will
- * always result in the image occupying the full width of the column. They help
- * in situations where an image is larger than a column/row and must overlap
- * into the next column/row. Using them does mean, however, that it is often
- * necessary to perform conversions between Excels characters units, points,
- * pixels and millimetres in order to establish how many rows/columns an image
- * should occupy and just what the various insets ought to be.
- *
- * Note that the setDx1(int) and setDy1(int) methods of the ClientAchor class
- * are not made use of in the code that follows. It would be fairly trivial
- * however to extend this example further and provide methods that would centre
- * an image within a cell or allow the user to specify that a plain border a
- * fixed number of millimetres wide should wrap around the image. Those first
- * two parameters would make this sort of functionality perfectly possible.
- *
- * Owing to the various conversions used, the actual size of the image may vary
- * from that required; testing has so far found this to be in the region of
- * plus or minus two millimetres. Most likely by modifying the way the
- * calculations are performed - possibly using double(s) throughout and
- * rounding the values at the correct point - it is likely that these errors
- * could be reduced or removed.
- *
- * A note concerning Excels image resizing behaviour. The ClientAnchor
- * class contains a method called setAnchorType(int) which can be used to
- * determine how Excel will resize an image in response to the user increasing
- * or decreasing the dimensions of the cell containing the image. There are
- * three values that can be passed to this method; 0 = To move and size the
- * image with the cell, 2 = To move but don't size the image with the cell,
- * 3 = To prevent the image from moving or being resized along with the cell. If
- * an image is inserted using this class and placed into a single cell then if
- * the setAnchorType(int) method is called and a value of either 0 or 2 passed
- * to it, the resultant resizing behaviour may be a surprise. The image will not
- * grow in size of the column is made wider or the row higher but it will shrink
- * if the columns width or rows height are reduced.
- *
- * @author Mark Beardsley [msb at apache.org] and Mark Southern [southern at scripps.edu]
- * @version 1.00 5th August 2009.
- * 2.00 26th February 2010.
- * Ported to make use of the the SS usermodel classes.
- * Ability to reuse the Drawing Patriarch so that multiple images
- * can be inserted without unintentionally erasing earlier images.
- * Check on image type added; i.e. jpg, jpeg or png.
- * The String used to contain the files name is now converted
- * into a URL.
- * 2.10 17th May 2012
- * Corrected gross error that occurred when using the code with
- * XSSF or SXSSF workbooks. In short, the code did not correctly
- * calculate the size of the image(s) owing to the use of EMUs
- * within the OOXML file format. That problem has largely been
- * corrected although it should be mentioned that images are not
- * sized with the same level of accuracy. Discrepancies of up to
- * 2mm have been noted in testing. Further investigation will
- * continue to rectify this issue.
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public class AddDimensionedImage {
-
- // Four constants that determine how - and indeed whether - the rows
- // and columns an image may overlie should be expanded to accommodate that
- // image.
- // Passing EXPAND_ROW will result in the height of a row being increased
- // to accommodate the image if it is not already larger. The image will
- // be layed across one or more columns.
- // Passing EXPAND_COLUMN will result in the width of the column being
- // increased to accommodate the image if it is not already larger. The image
- // will be layed across one or many rows.
- // Passing EXPAND_ROW_AND_COLUMN will result in the height of the row
- // bing increased along with the width of the column to accomdate the
- // image if either is not already larger.
- // Passing OVERLAY_ROW_AND_COLUMN will result in the image being layed
- // over one or more rows and columns. No row or column will be resized,
- // instead, code will determine how many rows and columns the image should
- // overlie.
- public static final int EXPAND_ROW = 1;
- public static final int EXPAND_COLUMN = 2;
- public static final int EXPAND_ROW_AND_COLUMN = 3;
- public static final int OVERLAY_ROW_AND_COLUMN = 7;
-
- // Modified to support EMU - English Metric Units - used within the OOXML
- // workbooks, this multoplier is used to convert between measurements in
- // millimetres and in EMUs
- private static final int EMU_PER_MM = 36000;
-
- /**
- * Add an image to a worksheet.
- *
- * @param cellNumber A String that contains the location of the cell whose
- * top left hand corner should be aligned with the top
- * left hand corner of the image; for example "A1", "A2"
- * etc. This is to support the familiar Excel syntax.
- * Whilst images are are not actually inserted into cells
- * this provides a convenient method of indicating where
- * the image should be positioned on the sheet.
- * @param sheet A reference to the sheet that contains the cell referenced
- * above.
- * @param drawing An instance of the DrawingPatriarch class. This is now
- * passed into the method where it was, previously, recovered
- * from the sheet in order to allow multiple pictures be
- * inserted. If the patriarch was not 'cached in this manner
- * each time it was created any previously positioned images
- * would be simply over-written.
- * @param imageFile An instance of the URL class that encapsulates the name
- * of and path to the image that is to be 'inserted into'
- * the sheet.
- * @param reqImageWidthMM A primitive double that contains the required
- * width of the image in millimetres.
- * @param reqImageHeightMM A primitive double that contains the required
- * height of the image in millimetres.
- * @param resizeBehaviour A primitive int whose value will determine how
- * the code should react if the image is larger than
- * the cell referenced by the cellNumber parameter.
- * Four constants are provided to determine what
- * should happen;
- * AddDimensionedImage.EXPAND_ROW
- * AddDimensionedImage.EXPAND_COLUMN
- * AddDimensionedImage.EXPAND_ROW_AND_COLUMN
- * AddDimensionedImage.OVERLAY_ROW_AND_COLUMN
- * @throws java.io.FileNotFoundException If the file containing the image
- * cannot be located.
- * @throws java.io.IOException If a problem occurs whilst reading the file
- * of image data.
- * @throws java.lang.IllegalArgumentException If an invalid value is passed
- * to the resizeBehaviour
- * parameter.
- */
- public void addImageToSheet(String cellNumber, Sheet sheet, Drawing<?> drawing,
- URL imageFile, double reqImageWidthMM, double reqImageHeightMM,
- int resizeBehaviour) throws IOException, IllegalArgumentException {
- // Convert the String into column and row indices then chain the
- // call to the overridden addImageToSheet() method.
- CellReference cellRef = new CellReference(cellNumber);
- this.addImageToSheet(cellRef.getCol(), cellRef.getRow(), sheet, drawing,
- imageFile, reqImageWidthMM, reqImageHeightMM,resizeBehaviour);
- }
-
- /**
- * Add an image to a worksheet.
- *
- * @param colNumber A primitive int that contains the index number of a
- * column on the worksheet; POI column indices are zero
- * based. Together with the rowNumber parameter's value,
- * this parameter identifies a cell on the worksheet. The
- * images top left hand corner will be aligned with the
- * top left hand corner of this cell.
- * @param rowNumber A primitive int that contains the index number of a row
- * on the worksheet; POI row indices are zero based.
- * Together with the rowNumber parameter's value, this
- * parameter identifies a cell on the worksheet. The
- * images top left hand corner will be aligned with the
- * top left hand corner of this cell.
- * @param sheet A reference to the sheet that contains the cell identified
- * by the two parameters above.
- * @param drawing An instance of the DrawingPatriarch class. This is now
- * passed into the method where it was, previously, recovered
- * from the sheet in order to allow multiple pictures be
- * inserted. If the patriarch was not 'cached in this manner
- * each time it was created any previously positioned images
- * would be simply over-written.
- * @param imageFile An instance of the URL class that encapsulates the name
- * of and path to the image that is to be 'inserted into'
- * the sheet.
- * @param reqImageWidthMM A primitive double that contains the required
- * width of the image in millimetres.
- * @param reqImageHeightMM A primitive double that contains the required
- * height of the image in millimetres.
- * @param resizeBehaviour A primitive int whose value will determine how
- * the code should react if the image is larger than
- * the cell referenced by the colNumber and
- * rowNumber parameters. Four constants are provided
- * to determine what should happen;
- * AddDimensionedImage.EXPAND_ROW
- * AddDimensionedImage.EXPAND_COLUMN
- * AddDimensionedImage.EXPAND_ROW_AND_COLUMN
- * AddDimensionedImage.OVERLAY_ROW_AND_COLUMN
- * @throws java.io.FileNotFoundException If the file containing the image
- * cannot be located.
- * @throws java.io.IOException If a problem occurs whilst reading the file
- * of image data.
- * @throws java.lang.IllegalArgumentException If an invalid value is passed
- * to the resizeBehaviour
- * parameter or if the extension
- * of the image file indicates that
- * it is of a type that cannot
- * currently be added to the worksheet.
- */
- public void addImageToSheet(int colNumber, int rowNumber, Sheet sheet, Drawing<?> drawing,
- URL imageFile, double reqImageWidthMM, double reqImageHeightMM,
- int resizeBehaviour) throws IOException,
- IllegalArgumentException {
- ClientAnchor anchor;
- ClientAnchorDetail rowClientAnchorDetail;
- ClientAnchorDetail colClientAnchorDetail;
- int imageType;
-
- // Validate the resizeBehaviour parameter.
- if((resizeBehaviour != AddDimensionedImage.EXPAND_COLUMN) &&
- (resizeBehaviour != AddDimensionedImage.EXPAND_ROW) &&
- (resizeBehaviour != AddDimensionedImage.EXPAND_ROW_AND_COLUMN) &&
- (resizeBehaviour != AddDimensionedImage.OVERLAY_ROW_AND_COLUMN)) {
- throw new IllegalArgumentException("Invalid value passed to the " +
- "resizeBehaviour parameter of AddDimensionedImage.addImageToSheet()");
- }
-
- // Call methods to calculate how the image and sheet should be
- // manipulated to accommodate the image; columns and then rows.
- colClientAnchorDetail = this.fitImageToColumns(sheet, colNumber,
- reqImageWidthMM, resizeBehaviour);
- rowClientAnchorDetail = this.fitImageToRows(sheet, rowNumber,
- reqImageHeightMM, resizeBehaviour);
-
- // Having determined if and how to resize the rows, columns and/or the
- // image, create the ClientAnchor object to position the image on
- // the worksheet. Note how the two ClientAnchorDetail records are
- // interrogated to recover the row/column co-ordinates and any insets.
- // The first two parameters are not used currently but could be if the
- // need arose to extend the functionality of this code by adding the
- // ability to specify that a clear 'border' be placed around the image.
- anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();
-
- anchor.setDx1(0);
- anchor.setDy1(0);
- if (colClientAnchorDetail != null) {
- anchor.setDx2(colClientAnchorDetail.getInset());
- anchor.setCol1(colClientAnchorDetail.getFromIndex());
- anchor.setCol2(colClientAnchorDetail.getToIndex());
- }
- if (rowClientAnchorDetail != null) {
- anchor.setDy2(rowClientAnchorDetail.getInset());
- anchor.setRow1(rowClientAnchorDetail.getFromIndex());
- anchor.setRow2(rowClientAnchorDetail.getToIndex());
- }
-
- // For now, set the anchor type to do not move or resize the
- // image as the size of the row/column is adjusted. This could easily
- // become another parameter passed to the method. Please read the note
- // above regarding the behaviour of image resizing.
- anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE);
-
- // Now, add the picture to the workbook. Note that unlike the similar
- // method in the HSSF Examples section, the image type is checked. First,
- // the image files location is identified by interrogating the URL passed
- // to the method, the images type is identified before it is added to the
- // sheet.
- String sURL = imageFile.toString().toLowerCase(Locale.ROOT);
- if( sURL.endsWith(".png") ) {
- imageType = Workbook.PICTURE_TYPE_PNG;
- }
- else if( sURL.endsWith(".jpg") || sURL.endsWith(".jpeg") ) {
- imageType = Workbook.PICTURE_TYPE_JPEG;
- }
- else {
- throw new IllegalArgumentException("Invalid Image file : " +
- sURL);
- }
- int index = sheet.getWorkbook().addPicture(
- IOUtils.toByteArray(imageFile.openStream()), imageType);
- drawing.createPicture(anchor, index);
- }
-
- /**
- * Determines whether the sheets columns should be re-sized to accommodate
- * the image, adjusts the columns width if necessary and creates then
- * returns a ClientAnchorDetail object that facilitates construction of
- * an ClientAnchor that will fix the image on the sheet and establish
- * it's size.
- *
- * @param sheet A reference to the sheet that will 'contain' the image.
- * @param colNumber A primitive int that contains the index number of a
- * column on the sheet.
- * @param reqImageWidthMM A primitive double that contains the required
- * width of the image in millimetres
- * @param resizeBehaviour A primitive int whose value will indicate how the
- * width of the column should be adjusted if the
- * required width of the image is greater than the
- * width of the column.
- * @return An instance of the ClientAnchorDetail class that will contain
- * the index number of the column containing the cell whose top
- * left hand corner also defines the top left hand corner of the
- * image, the index number column containing the cell whose top
- * left hand corner also defines the bottom right hand corner of
- * the image and an inset that determines how far the right hand
- * edge of the image can protrude into the next column - expressed
- * as a specific number of coordinate positions.
- */
- private ClientAnchorDetail fitImageToColumns(Sheet sheet, int colNumber,
- double reqImageWidthMM, int resizeBehaviour) {
-
- double colWidthMM;
- double colCoordinatesPerMM;
- int pictureWidthCoordinates;
- ClientAnchorDetail colClientAnchorDetail = null;
-
- // Get the colum's width in millimetres
- colWidthMM = ConvertImageUnits.widthUnits2Millimetres(
- (short)sheet.getColumnWidth(colNumber));
-
- // Check that the column's width will accommodate the image at the
- // required dimension. If the width of the column is LESS than the
- // required width of the image, decide how the application should
- // respond - resize the column or overlay the image across one or more
- // columns.
- if(colWidthMM < reqImageWidthMM) {
-
- // Should the column's width simply be expanded?
- if((resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN) ||
- (resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) {
- // Set the width of the column by converting the required image
- // width from millimetres into Excel's column width units.
- sheet.setColumnWidth(colNumber,
- ConvertImageUnits.millimetres2WidthUnits(reqImageWidthMM));
- // To make the image occupy the full width of the column, convert
- // the required width of the image into co-ordinates. This value
- // will become the inset for the ClientAnchorDetail class that
- // is then instantiated.
- if(sheet instanceof HSSFSheet) {
- colWidthMM = reqImageWidthMM;
- colCoordinatesPerMM = colWidthMM == 0 ? 0
- : ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colWidthMM;
- pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM);
-
- }
- else {
- pictureWidthCoordinates = (int)reqImageWidthMM * AddDimensionedImage.EMU_PER_MM;
- }
- colClientAnchorDetail = new ClientAnchorDetail(colNumber,
- colNumber, pictureWidthCoordinates);
- }
- // If the user has chosen to overlay both rows and columns or just
- // to expand ONLY the size of the rows, then calculate how to lay
- // the image out across one or more columns.
- else if ((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) ||
- (resizeBehaviour == AddDimensionedImage.EXPAND_ROW)) {
- colClientAnchorDetail = this.calculateColumnLocation(sheet,
- colNumber, reqImageWidthMM);
- }
- }
- // If the column is wider than the image.
- else {
- if(sheet instanceof HSSFSheet) {
- // Mow many co-ordinate positions are there per millimetre?
- colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS /
- colWidthMM;
- // Given the width of the image, what should be it's co-ordinate?
- pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM);
- }
- else {
- pictureWidthCoordinates = (int)reqImageWidthMM *
- AddDimensionedImage.EMU_PER_MM;
- }
- colClientAnchorDetail = new ClientAnchorDetail(colNumber,
- colNumber, pictureWidthCoordinates);
- }
- return(colClientAnchorDetail);
- }
-
- /**
- * Determines whether the sheets row should be re-sized to accommodate
- * the image, adjusts the rows height if necessary and creates then
- * returns a ClientAnchorDetail object that facilitates construction of
- * a ClientAnchor that will fix the image on the sheet and establish
- * it's size.
- *
- * @param sheet A reference to the sheet that will 'contain' the image.
- * @param rowNumber A primitive int that contains the index number of a
- * row on the sheet.
- * @param reqImageHeightMM A primitive double that contains the required
- * height of the image in millimetres
- * @param resizeBehaviour A primitive int whose value will indicate how the
- * height of the row should be adjusted if the
- * required height of the image is greater than the
- * height of the row.
- * @return An instance of the ClientAnchorDetail class that will contain
- * the index number of the row containing the cell whose top
- * left hand corner also defines the top left hand corner of the
- * image, the index number of the row containing the cell whose
- * top left hand corner also defines the bottom right hand
- * corner of the image and an inset that determines how far the
- * bottom edge of the image can protrude into the next (lower)
- * row - expressed as a specific number of coordinate positions.
- */
- private ClientAnchorDetail fitImageToRows(Sheet sheet, int rowNumber,
- double reqImageHeightMM, int resizeBehaviour) {
- Row row;
- double rowHeightMM;
- double rowCoordinatesPerMM;
- int pictureHeightCoordinates;
- ClientAnchorDetail rowClientAnchorDetail = null;
-
- // Get the row and it's height
- row = sheet.getRow(rowNumber);
- if(row == null) {
- // Create row if it does not exist.
- row = sheet.createRow(rowNumber);
- }
-
- // Get the row's height in millimetres
- rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE;
-
- // Check that the row's height will accommodate the image at the required
- // dimensions. If the height of the row is LESS than the required height
- // of the image, decide how the application should respond - resize the
- // row or overlay the image across a series of rows.
- if(rowHeightMM < reqImageHeightMM) {
- if((resizeBehaviour == AddDimensionedImage.EXPAND_ROW) ||
- (resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) {
- row.setHeightInPoints((float)(reqImageHeightMM *
- ConvertImageUnits.POINTS_PER_MILLIMETRE));
- if(sheet instanceof HSSFSheet) {
- rowHeightMM = reqImageHeightMM;
- rowCoordinatesPerMM = rowHeightMM == 0 ? 0
- : ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowHeightMM;
- pictureHeightCoordinates = (int)(reqImageHeightMM *
- rowCoordinatesPerMM);
- }
- else {
- pictureHeightCoordinates = (int)(reqImageHeightMM *
- AddDimensionedImage.EMU_PER_MM);
- }
- rowClientAnchorDetail = new ClientAnchorDetail(rowNumber,
- rowNumber, pictureHeightCoordinates);
- }
- // If the user has chosen to overlay both rows and columns or just
- // to expand ONLY the size of the columns, then calculate how to lay
- // the image out ver one or more rows.
- else if((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) ||
- (resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN)) {
- rowClientAnchorDetail = this.calculateRowLocation(sheet,
- rowNumber, reqImageHeightMM);
- }
- }
- // Else, if the image is smaller than the space available
- else {
- if(sheet instanceof HSSFSheet) {
- rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS /
- rowHeightMM;
- pictureHeightCoordinates = (int)(reqImageHeightMM * rowCoordinatesPerMM);
- }
- else {
- pictureHeightCoordinates = (int)(reqImageHeightMM *
- AddDimensionedImage.EMU_PER_MM);
- }
- rowClientAnchorDetail = new ClientAnchorDetail(rowNumber,
- rowNumber, pictureHeightCoordinates);
- }
- return(rowClientAnchorDetail);
- }
-
- /**
- * If the image is to overlie more than one column, calculations need to be
- * performed to determine how many columns and whether the image will
- * overlie just a part of one column in order to be presented at the
- * required size.
- *
- * @param sheet The sheet that will 'contain' the image.
- * @param startingColumn A primitive int whose value is the index of the
- * column that contains the cell whose top left hand
- * corner should be aligned with the top left hand
- * corner of the image.
- * @param reqImageWidthMM A primitive double whose value will indicate the
- * required width of the image in millimetres.
- * @return An instance of the ClientAnchorDetail class that will contain
- * the index number of the column containing the cell whose top
- * left hand corner also defines the top left hand corner of the
- * image, the index number column containing the cell whose top
- * left hand corner also defines the bottom right hand corner of
- * the image and an inset that determines how far the right hand
- * edge of the image can protrude into the next column - expressed
- * as a specific number of coordinate positions.
- */
- private ClientAnchorDetail calculateColumnLocation(Sheet sheet,
- int startingColumn,
- double reqImageWidthMM) {
- ClientAnchorDetail anchorDetail;
- double totalWidthMM = 0.0D;
- double colWidthMM = 0.0D;
- double overlapMM;
- double coordinatePositionsPerMM;
- int toColumn = startingColumn;
- int inset;
-
- // Calculate how many columns the image will have to
- // span in order to be presented at the required size.
- while(totalWidthMM < reqImageWidthMM) {
- colWidthMM = ConvertImageUnits.widthUnits2Millimetres(
- (short)(sheet.getColumnWidth(toColumn)));
- // Note use of the cell border width constant. Testing with an image
- // declared to fit exactly into one column demonstrated that it's
- // width was greater than the width of the column the POI returned.
- // Further, this difference was a constant value that I am assuming
- // related to the cell's borders. Either way, that difference needs
- // to be allowed for in this calculation.
- totalWidthMM += (colWidthMM + ConvertImageUnits.CELL_BORDER_WIDTH_MILLIMETRES);
- toColumn++;
- }
- // De-crement by one the last column value.
- toColumn--;
- // Highly unlikely that this will be true but, if the width of a series
- // of columns is exactly equal to the required width of the image, then
- // simply build a ClientAnchorDetail object with an inset equal to the
- // total number of co-ordinate positions available in a column, a
- // from column co-ordinate (top left hand corner) equal to the value
- // of the startingColumn parameter and a to column co-ordinate equal
- // to the toColumn variable.
- //
- // Convert both values to ints to perform the test.
- if((int)totalWidthMM == (int)reqImageWidthMM) {
- // A problem could occur if the image is sized to fit into one or
- // more columns. If that occurs, the value in the toColumn variable
- // will be in error. To overcome this, there are two options, to
- // ibcrement the toColumn variable's value by one or to pass the
- // total number of co-ordinate positions to the third paramater
- // of the ClientAnchorDetail constructor. For no sepcific reason,
- // the latter option is used below.
- if(sheet instanceof HSSFSheet) {
- anchorDetail = new ClientAnchorDetail(startingColumn,
- toColumn, ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS);
- }
- else {
- anchorDetail = new ClientAnchorDetail(startingColumn,
- toColumn, (int)reqImageWidthMM * AddDimensionedImage.EMU_PER_MM);
- }
- }
- // In this case, the image will overlap part of another column and it is
- // necessary to calculate just how much - this will become the inset
- // for the ClientAnchorDetail object.
- else {
- // Firstly, claculate how much of the image should overlap into
- // the next column.
- overlapMM = reqImageWidthMM - (totalWidthMM - colWidthMM);
-
- // When the required size is very close indded to the column size,
- // the calcaulation above can produce a negative value. To prevent
- // problems occuring in later caculations, this is simply removed
- // be setting the overlapMM value to zero.
- if(overlapMM < 0) {
- overlapMM = 0.0D;
- }
-
- if(sheet instanceof HSSFSheet) {
- // Next, from the columns width, calculate how many co-ordinate
- // positons there are per millimetre
- coordinatePositionsPerMM = (colWidthMM == 0) ? 0
- : ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colWidthMM;
- // From this figure, determine how many co-ordinat positions to
- // inset the left hand or bottom edge of the image.
- inset = (int)(coordinatePositionsPerMM * overlapMM);
- }
- else {
- inset = (int)overlapMM * AddDimensionedImage.EMU_PER_MM;
- }
-
- // Now create the ClientAnchorDetail object, setting the from and to
- // columns and the inset.
- anchorDetail = new ClientAnchorDetail(startingColumn, toColumn, inset);
- }
- return(anchorDetail);
- }
-
- /**
- * If the image is to overlie more than one rows, calculations need to be
- * performed to determine how many rows and whether the image will
- * overlie just a part of one row in order to be presented at the
- * required size.
- *
- * @param sheet The sheet that will 'contain' the image.
- * @param startingRow A primitive int whose value is the index of the row
- * that contains the cell whose top left hand corner
- * should be aligned with the top left hand corner of
- * the image.
- * @param reqImageHeightMM A primitive double whose value will indicate the
- * required height of the image in millimetres.
- * @return An instance of the ClientAnchorDetail class that will contain
- * the index number of the row containing the cell whose top
- * left hand corner also defines the top left hand corner of the
- * image, the index number of the row containing the cell whose top
- * left hand corner also defines the bottom right hand corner of
- * the image and an inset that determines how far the bottom edge
- * can protrude into the next (lower) row - expressed as a specific
- * number of co-ordinate positions.
- */
- private ClientAnchorDetail calculateRowLocation(Sheet sheet,
- int startingRow, double reqImageHeightMM) {
- ClientAnchorDetail clientAnchorDetail;
- Row row;
- double rowHeightMM = 0.0D;
- double totalRowHeightMM = 0.0D;
- double overlapMM;
- double rowCoordinatesPerMM;
- int toRow = startingRow;
- int inset;
-
- // Step through the rows in the sheet and accumulate a total of their
- // heights.
- while(totalRowHeightMM < reqImageHeightMM) {
- row = sheet.getRow(toRow);
- // Note, if the row does not already exist on the sheet then create
- // it here.
- if(row == null) {
- row = sheet.createRow(toRow);
- }
- // Get the row's height in millimetres and add to the running total.
- rowHeightMM = row.getHeightInPoints() /
- ConvertImageUnits.POINTS_PER_MILLIMETRE;
- totalRowHeightMM += rowHeightMM;
- toRow++;
- }
- // Owing to the way the loop above works, the rowNumber will have been
- // incremented one row too far. Undo that here.
- toRow--;
- // Check to see whether the image should occupy an exact number of
- // rows. If so, build the ClientAnchorDetail record to point
- // to those rows and with an inset of the total number of co-ordinate
- // position in the row.
- //
- // To overcome problems that can occur with comparing double values for
- // equality, cast both to int(s) to truncate the value; VERY crude and
- // I do not really like it!!
- if((int)totalRowHeightMM == (int)reqImageHeightMM) {
- if(sheet instanceof HSSFSheet) {
- clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow,
- ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS);
- }
- else {
- clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow,
- (int)reqImageHeightMM * AddDimensionedImage.EMU_PER_MM);
- }
- }
- else {
- // Calculate how far the image will project into the next row. Note
- // that the height of the last row assessed is subtracted from the
- // total height of all rows assessed so far.
- overlapMM = reqImageHeightMM - (totalRowHeightMM - rowHeightMM);
-
- // To prevent an exception being thrown when the required width of
- // the image is very close indeed to the column size.
- if(overlapMM < 0) {
- overlapMM = 0.0D;
- }
-
- if(sheet instanceof HSSFSheet) {
- rowCoordinatesPerMM = (rowHeightMM == 0) ? 0
- : ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowHeightMM;
- inset = (int)(overlapMM * rowCoordinatesPerMM);
- }
- else {
- inset = (int)overlapMM * AddDimensionedImage.EMU_PER_MM;
- }
- clientAnchorDetail = new ClientAnchorDetail(startingRow,
- toRow, inset);
- }
- return(clientAnchorDetail);
- }
-
- /**
- * The main entry point to the program. It contains code that demonstrates
- * one way to use the program.
- *
- * Note, the code is not restricted to use on new workbooks only. If an
- * image is to be inserted into an existing workbook. just open that
- * workbook, gat a reference to a sheet and pass that;
- *
- * AddDimensionedImage addImage = new AddDimensionedImage();
- *
- * File file = new File("....... Existing Workbook .......");
- * FileInputStream fis = new FileInputStream(file);
- * Workbook workbook = new HSSFWorkbook(fis);
- * HSSFSheet sheet = workbook.getSheetAt(0);
- * addImage.addImageToSheet("C3", sheet, "image.jpg", 30, 20,
- * AddDimensionedImage.EXPAND.ROW);
- *
- * @param args the command line arguments
- */
- public static void main(String[] args) throws IOException {
- if(args.length < 2){
- System.err.println("Usage: AddDimensionedImage imageFile outputFile");
- return;
- }
-
- final String imageFile = args[0];
- final String outputFile = args[1];
-
- try (final Workbook workbook = new HSSFWorkbook();
- final FileOutputStream fos = new FileOutputStream(outputFile)) { // OR XSSFWorkbook
- Sheet sheet = workbook.createSheet("Picture Test");
- new AddDimensionedImage().addImageToSheet("B5", sheet, sheet.createDrawingPatriarch(),
- new File(imageFile).toURI().toURL(), 100, 40,
- AddDimensionedImage.EXPAND_ROW_AND_COLUMN);
- workbook.write(fos);
- }
- }
-
- /**
- * The HSSFClientAnchor class accepts eight arguments. In order, these are;
- *
- * * How far the left hand edge of the image is inset from the left hand
- * edge of the cell
- * * How far the top edge of the image is inset from the top of the cell
- * * How far the right hand edge of the image is inset from the left
- * hand edge of the cell
- * * How far the bottom edge of the image is inset from the top of the
- * cell.
- * * Together, arguments five and six determine the column and row
- * coordinates of the cell whose top left hand corner will be aligned
- * with the images top left hand corner.
- * * Together, arguments seven and eight determine the column and row
- * coordinates of the cell whose top left hand corner will be aligned
- * with the images bottom right hand corner.
- *
- * An instance of the ClientAnchorDetail class provides three of the eight
- * parameters, one of the coordinates for the images top left hand corner,
- * one of the coordinates for the images bottom right hand corner and
- * either how far the image should be inset from the top or the left hand
- * edge of the cell.
- *
- * @author Mark Beardsley [msb at apache.org]
- * @version 1.00 5th August 2009.
- */
- public class ClientAnchorDetail {
-
- private int fromIndex;
- private int toIndex;
- private int inset;
-
- /**
- * Create a new instance of the ClientAnchorDetail class using the
- * following parameters.
- *
- * @param fromIndex A primitive int that contains one of the
- * coordinates (row or column index) for the top left
- * hand corner of the image.
- * @param toIndex A primitive int that contains one of the
- * coordinates (row or column index) for the bottom
- * right hand corner of the image.
- * @param inset A primitive int that contains a value which indicates
- * how far the image should be inset from the top or the
- * left hand edge of a cell.
- */
- public ClientAnchorDetail(int fromIndex, int toIndex, int inset) {
- this.fromIndex = fromIndex;
- this.toIndex = toIndex;
- this.inset = inset;
- }
-
- /**
- * Get one of the number of the column or row that contains the cell
- * whose top left hand corner will be aligned with the top left hand
- * corner of the image.
- *
- * @return The value - row or column index - for one of the coordinates
- * of the top left hand corner of the image.
- */
- public int getFromIndex() {
- return(this.fromIndex);
- }
-
- /**
- * Get one of the number of the column or row that contains the cell
- * whose top left hand corner will be aligned with the bottom right hand
- * corner of the image.
- *
- * @return The value - row or column index - for one of the coordinates
- * of the bottom right hand corner of the image.
- */
- public int getToIndex() {
- return(this.toIndex);
- }
-
- /**
- * Get the images offset from the edge of a cell.
- *
- * @return How far either the right hand or bottom edge of the image is
- * inset from the left hand or top edge of a cell.
- */
- public int getInset() {
- return(this.inset);
- }
- }
-
- /**
- * Utility methods used to convert Excels character based column and row
- * size measurements into pixels and/or millimetres. The class also contains
- * various constants that are required in other calculations.
- *
- * @author xio[darjino@hotmail.com]
- * @version 1.01 30th July 2009.
- * Added by Mark Beardsley [msb at apache.org].
- * Additional constants.
- * widthUnits2Millimetres() and millimetres2Units() methods.
- */
- public static class ConvertImageUnits {
-
- // Each cell conatins a fixed number of co-ordinate points; this number
- // does not vary with row height or column width or with font. These two
- // constants are defined below.
- public static final int TOTAL_COLUMN_COORDINATE_POSITIONS = 1023;
- public static final int TOTAL_ROW_COORDINATE_POSITIONS = 255;
- // The resoultion of an image can be expressed as a specific number
- // of pixels per inch. Displays and printers differ but 96 pixels per
- // inch is an acceptable standard to beging with.
- public static final int PIXELS_PER_INCH = 96;
- // Cnstants that defines how many pixels and points there are in a
- // millimetre. These values are required for the conversion algorithm.
- public static final double PIXELS_PER_MILLIMETRES = 3.78;
- public static final double POINTS_PER_MILLIMETRE = 2.83;
- // The column width returned by HSSF and the width of a picture when
- // positioned to exactly cover one cell are different by almost exactly
- // 2mm - give or take rounding errors. This constant allows that
- // additional amount to be accounted for when calculating how many
- // celles the image ought to overlie.
- public static final double CELL_BORDER_WIDTH_MILLIMETRES = 2.0D;
- public static final short EXCEL_COLUMN_WIDTH_FACTOR = 256;
- public static final int UNIT_OFFSET_LENGTH = 7;
- private static final int[] UNIT_OFFSET_MAP = { 0, 36, 73, 109, 146, 182, 219 };
-
- /**
- * pixel units to excel width units(units of 1/256th of a character width)
- */
- public static short pixel2WidthUnits(int pxs) {
- short widthUnits = (short) (EXCEL_COLUMN_WIDTH_FACTOR *
- (pxs / UNIT_OFFSET_LENGTH));
- widthUnits += UNIT_OFFSET_MAP[(pxs % UNIT_OFFSET_LENGTH)];
- return widthUnits;
- }
-
- /**
- * excel width units(units of 1/256th of a character width) to pixel
- * units.
- */
- public static int widthUnits2Pixel(short widthUnits) {
- int pixels = (widthUnits / EXCEL_COLUMN_WIDTH_FACTOR)
- * UNIT_OFFSET_LENGTH;
- int offsetWidthUnits = widthUnits % EXCEL_COLUMN_WIDTH_FACTOR;
- pixels += Math.round(offsetWidthUnits /
- ((float) EXCEL_COLUMN_WIDTH_FACTOR / UNIT_OFFSET_LENGTH));
- return pixels;
- }
-
- /**
- * Convert Excels width units into millimetres.
- *
- * @param widthUnits The width of the column or the height of the
- * row in Excels units.
- * @return A primitive double that contains the columns width or rows
- * height in millimetres.
- */
- public static double widthUnits2Millimetres(short widthUnits) {
- return(ConvertImageUnits.widthUnits2Pixel(widthUnits) /
- ConvertImageUnits.PIXELS_PER_MILLIMETRES);
- }
-
- /**
- * Convert into millimetres Excels width units..
- *
- * @param millimetres A primitive double that contains the columns
- * width or rows height in millimetres.
- * @return A primitive int that contains the columns width or rows
- * height in Excels units.
- */
- public static int millimetres2WidthUnits(double millimetres) {
- return(ConvertImageUnits.pixel2WidthUnits((int)(millimetres *
- ConvertImageUnits.PIXELS_PER_MILLIMETRES)));
- }
- }
-}
+++ /dev/null
-/* ====================================================================
-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.ss.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Shows how various alignment options work.
- */
-public class AligningCells {
-
- public static void main(String[] args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
-
- Sheet sheet = wb.createSheet();
- Row row = sheet.createRow(2);
- row.setHeightInPoints(30);
- for (int i = 0; i < 8; i++) {
- //column width is set in units of 1/256th of a character width
- sheet.setColumnWidth(i, 256 * 15);
- }
-
- createCell(wb, row, 0, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
- createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.BOTTOM);
- createCell(wb, row, 2, HorizontalAlignment.FILL, VerticalAlignment.CENTER);
- createCell(wb, row, 3, HorizontalAlignment.GENERAL, VerticalAlignment.CENTER);
- createCell(wb, row, 4, HorizontalAlignment.JUSTIFY, VerticalAlignment.JUSTIFY);
- createCell(wb, row, 5, HorizontalAlignment.LEFT, VerticalAlignment.TOP);
- createCell(wb, row, 6, HorizontalAlignment.RIGHT, VerticalAlignment.TOP);
-
- // Write the output to a file
- try (OutputStream fileOut = new FileOutputStream("ss-example-align.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
- /**
- * Creates a cell and aligns it a certain way.
- *
- * @param wb the workbook
- * @param row the row to create the cell in
- * @param column the column number to create the cell in
- * @param halign the horizontal alignment for the cell.
- */
- private static void createCell(Workbook wb, Row row, int column, HorizontalAlignment halign, VerticalAlignment valign) {
- CreationHelper ch = wb.getCreationHelper();
- Cell cell = row.createCell(column);
- cell.setCellValue(ch.createRichTextString("Align It"));
- CellStyle cellStyle = wb.createCellStyle();
- cellStyle.setAlignment(halign);
- cellStyle.setVerticalAlignment(valign);
- cell.setCellStyle(cellStyle);
- }
-}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-import java.io.FileOutputStream;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.DataFormat;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.PrintSetup;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * A business plan demo
- * Usage:
- * BusinessPlan -xls|xlsx
- *
- * @author Yegor Kozlov
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class BusinessPlan {
-
- private static final String[] titles = {
- "ID", "Project Name", "Owner", "Days", "Start", "End"};
-
- //sample data to fill the sheet.
- private static final String[][] data = {
- {"1.0", "Marketing Research Tactical Plan", "J. Dow", "70", "9-Jul", null,
- "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x"},
- null,
- {"1.1", "Scope Definition Phase", "J. Dow", "10", "9-Jul", null,
- "x", "x", null, null, null, null, null, null, null, null, null},
- {"1.1.1", "Define research objectives", "J. Dow", "3", "9-Jul", null,
- "x", null, null, null, null, null, null, null, null, null, null},
- {"1.1.2", "Define research requirements", "S. Jones", "7", "10-Jul", null,
- "x", "x", null, null, null, null, null, null, null, null, null},
- {"1.1.3", "Determine in-house resource or hire vendor", "J. Dow", "2", "15-Jul", null,
- "x", "x", null, null, null, null, null, null, null, null, null},
- null,
- {"1.2", "Vendor Selection Phase", "J. Dow", "19", "19-Jul", null,
- null, "x", "x", "x", "x", null, null, null, null, null, null},
- {"1.2.1", "Define vendor selection criteria", "J. Dow", "3", "19-Jul", null,
- null, "x", null, null, null, null, null, null, null, null, null},
- {"1.2.2", "Develop vendor selection questionnaire", "S. Jones, T. Wates", "2", "22-Jul", null,
- null, "x", "x", null, null, null, null, null, null, null, null},
- {"1.2.3", "Develop Statement of Work", "S. Jones", "4", "26-Jul", null,
- null, null, "x", "x", null, null, null, null, null, null, null},
- {"1.2.4", "Evaluate proposal", "J. Dow, S. Jones", "4", "2-Aug", null,
- null, null, null, "x", "x", null, null, null, null, null, null},
- {"1.2.5", "Select vendor", "J. Dow", "1", "6-Aug", null,
- null, null, null, null, "x", null, null, null, null, null, null},
- null,
- {"1.3", "Research Phase", "G. Lee", "47", "9-Aug", null,
- null, null, null, null, "x", "x", "x", "x", "x", "x", "x"},
- {"1.3.1", "Develop market research information needs questionnaire", "G. Lee", "2", "9-Aug", null,
- null, null, null, null, "x", null, null, null, null, null, null},
- {"1.3.2", "Interview marketing group for market research needs", "G. Lee", "2", "11-Aug", null,
- null, null, null, null, "x", "x", null, null, null, null, null},
- {"1.3.3", "Document information needs", "G. Lee, S. Jones", "1", "13-Aug", null,
- null, null, null, null, null, "x", null, null, null, null, null},
- };
-
- private BusinessPlan() {}
-
- public static void main(String[] args) throws Exception {
- Workbook wb;
-
- if(args.length > 0 && args[0].equals("-xls")) wb = new HSSFWorkbook();
- else wb = new XSSFWorkbook();
-
- final SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM");
-
- Map<String, CellStyle> styles = createStyles(wb);
-
- Sheet sheet = wb.createSheet("Business Plan");
-
- //turn off gridlines
- sheet.setDisplayGridlines(false);
- sheet.setPrintGridlines(false);
- sheet.setFitToPage(true);
- sheet.setHorizontallyCenter(true);
- PrintSetup printSetup = sheet.getPrintSetup();
- printSetup.setLandscape(true);
-
- //the following three statements are required only for HSSF
- sheet.setAutobreaks(true);
- printSetup.setFitHeight((short)1);
- printSetup.setFitWidth((short)1);
-
- //the header row: centered text in 48pt font
- Row headerRow = sheet.createRow(0);
- headerRow.setHeightInPoints(12.75f);
- for (int i = 0; i < titles.length; i++) {
- Cell cell = headerRow.createCell(i);
- cell.setCellValue(titles[i]);
- cell.setCellStyle(styles.get("header"));
- }
- //columns for 11 weeks starting from 9-Jul
- Calendar calendar = Calendar.getInstance();
- int year = calendar.get(Calendar.YEAR);
-
- calendar.setTime(fmt.parse("9-Jul"));
- calendar.set(Calendar.YEAR, year);
- for (int i = 0; i < 11; i++) {
- Cell cell = headerRow.createCell(titles.length + i);
- cell.setCellValue(calendar);
- cell.setCellStyle(styles.get("header_date"));
- calendar.roll(Calendar.WEEK_OF_YEAR, true);
- }
- //freeze the first row
- sheet.createFreezePane(0, 1);
-
- Row row;
- Cell cell;
- int rownum = 1;
- for (int i = 0; i < data.length; i++, rownum++) {
- row = sheet.createRow(rownum);
- if(data[i] == null) continue;
-
- for (int j = 0; j < data[i].length; j++) {
- cell = row.createCell(j);
- String styleName;
- boolean isHeader = i == 0 || data[i-1] == null;
- switch(j){
- case 0:
- if(isHeader) {
- styleName = "cell_b";
- cell.setCellValue(Double.parseDouble(data[i][j]));
- } else {
- styleName = "cell_normal";
- cell.setCellValue(data[i][j]);
- }
- break;
- case 1:
- if(isHeader) {
- styleName = i == 0 ? "cell_h" : "cell_bb";
- } else {
- styleName = "cell_indented";
- }
- cell.setCellValue(data[i][j]);
- break;
- case 2:
- styleName = isHeader ? "cell_b" : "cell_normal";
- cell.setCellValue(data[i][j]);
- break;
- case 3:
- styleName = isHeader ? "cell_b_centered" : "cell_normal_centered";
- cell.setCellValue(Integer.parseInt(data[i][j]));
- break;
- case 4: {
- calendar.setTime(fmt.parse(data[i][j]));
- calendar.set(Calendar.YEAR, year);
- cell.setCellValue(calendar);
- styleName = isHeader ? "cell_b_date" : "cell_normal_date";
- break;
- }
- case 5: {
- int r = rownum + 1;
- String fmla = "IF(AND(D"+r+",E"+r+"),E"+r+"+D"+r+",\"\")";
- cell.setCellFormula(fmla);
- styleName = isHeader ? "cell_bg" : "cell_g";
- break;
- }
- default:
- styleName = data[i][j] != null ? "cell_blue" : "cell_normal";
- }
-
- cell.setCellStyle(styles.get(styleName));
- }
- }
-
- //group rows for each phase, row numbers are 0-based
- sheet.groupRow(4, 6);
- sheet.groupRow(9, 13);
- sheet.groupRow(16, 18);
-
- //set column widths, the width is measured in units of 1/256th of a character width
- sheet.setColumnWidth(0, 256*6);
- sheet.setColumnWidth(1, 256*33);
- sheet.setColumnWidth(2, 256*20);
- sheet.setZoom(75); //75% scale
-
-
- // Write the output to a file
- String file = "businessplan.xls";
- if(wb instanceof XSSFWorkbook) file += "x";
- FileOutputStream out = new FileOutputStream(file);
- wb.write(out);
- out.close();
-
- wb.close();
- }
-
- /**
- * create a library of cell styles
- */
- private static Map<String, CellStyle> createStyles(Workbook wb){
- Map<String, CellStyle> styles = new HashMap<>();
- DataFormat df = wb.createDataFormat();
-
- CellStyle style;
- Font headerFont = wb.createFont();
- headerFont.setBold(true);
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setFont(headerFont);
- styles.put("header", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setFont(headerFont);
- style.setDataFormat(df.getFormat("d-mmm"));
- styles.put("header_date", style);
-
- Font font1 = wb.createFont();
- font1.setBold(true);
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setFont(font1);
- styles.put("cell_b", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setFont(font1);
- styles.put("cell_b_centered", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(font1);
- style.setDataFormat(df.getFormat("d-mmm"));
- styles.put("cell_b_date", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(font1);
- style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setDataFormat(df.getFormat("d-mmm"));
- styles.put("cell_g", style);
-
- Font font2 = wb.createFont();
- font2.setColor(IndexedColors.BLUE.getIndex());
- font2.setBold(true);
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setFont(font2);
- styles.put("cell_bb", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(font1);
- style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setDataFormat(df.getFormat("d-mmm"));
- styles.put("cell_bg", style);
-
- Font font3 = wb.createFont();
- font3.setFontHeightInPoints((short)14);
- font3.setColor(IndexedColors.DARK_BLUE.getIndex());
- font3.setBold(true);
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setFont(font3);
- style.setWrapText(true);
- styles.put("cell_h", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setWrapText(true);
- styles.put("cell_normal", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setWrapText(true);
- styles.put("cell_normal_centered", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setWrapText(true);
- style.setDataFormat(df.getFormat("d-mmm"));
- styles.put("cell_normal_date", style);
-
- style = createBorderedStyle(wb);
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setIndention((short)1);
- style.setWrapText(true);
- styles.put("cell_indented", style);
-
- style = createBorderedStyle(wb);
- style.setFillForegroundColor(IndexedColors.BLUE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- styles.put("cell_blue", style);
-
- return styles;
- }
-
- private static CellStyle createBorderedStyle(Workbook wb){
- BorderStyle thin = BorderStyle.THIN;
- short black = IndexedColors.BLACK.getIndex();
-
- CellStyle style = wb.createCellStyle();
- style.setBorderRight(thin);
- style.setRightBorderColor(black);
- style.setBorderBottom(thin);
- style.setBottomBorderColor(black);
- style.setBorderLeft(thin);
- style.setLeftBorderColor(black);
- style.setBorderTop(thin);
- style.setTopBorderColor(black);
- return style;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-import java.io.FileOutputStream;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.PrintSetup;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.VerticalAlignment;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * A monthly calendar created using Apache POI. Each month is on a separate sheet.
- * <pre>
- * Usage:
- * CalendarDemo -xls|xlsx <year>
- * </pre>
- *
- * @author Yegor Kozlov
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class CalendarDemo {
-
- private static final String[] days = {
- "Sunday", "Monday", "Tuesday",
- "Wednesday", "Thursday", "Friday", "Saturday"};
-
- private static final String[] months = {
- "January", "February", "March","April", "May", "June","July", "August",
- "September","October", "November", "December"};
-
- private CalendarDemo() {}
-
- public static void main(String[] args) throws Exception {
-
- Calendar calendar = Calendar.getInstance();
- boolean xlsx = true;
- for (String arg : args) {
- if (arg.charAt(0) == '-') {
- xlsx = arg.equals("-xlsx");
- } else {
- calendar.set(Calendar.YEAR, Integer.parseInt(arg));
- }
- }
- int year = calendar.get(Calendar.YEAR);
-
- try (Workbook wb = xlsx ? new XSSFWorkbook() : new HSSFWorkbook()) {
-
- Map<String, CellStyle> styles = createStyles(wb);
-
- for (int month = 0; month < 12; month++) {
- calendar.set(Calendar.MONTH, month);
- calendar.set(Calendar.DAY_OF_MONTH, 1);
- //create a sheet for each month
- Sheet sheet = wb.createSheet(months[month]);
-
- //turn off gridlines
- sheet.setDisplayGridlines(false);
- sheet.setPrintGridlines(false);
- sheet.setFitToPage(true);
- sheet.setHorizontallyCenter(true);
- PrintSetup printSetup = sheet.getPrintSetup();
- printSetup.setLandscape(true);
-
- //the following three statements are required only for HSSF
- sheet.setAutobreaks(true);
- printSetup.setFitHeight((short) 1);
- printSetup.setFitWidth((short) 1);
-
- //the header row: centered text in 48pt font
- Row headerRow = sheet.createRow(0);
- headerRow.setHeightInPoints(80);
- Cell titleCell = headerRow.createCell(0);
- titleCell.setCellValue(months[month] + " " + year);
- titleCell.setCellStyle(styles.get("title"));
- sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$N$1"));
-
- //header with month titles
- Row monthRow = sheet.createRow(1);
- for (int i = 0; i < days.length; i++) {
- //set column widths, the width is measured in units of 1/256th of a character width
- sheet.setColumnWidth(i * 2, 5 * 256); //the column is 5 characters wide
- sheet.setColumnWidth(i * 2 + 1, 13 * 256); //the column is 13 characters wide
- sheet.addMergedRegion(new CellRangeAddress(1, 1, i * 2, i * 2 + 1));
- Cell monthCell = monthRow.createCell(i * 2);
- monthCell.setCellValue(days[i]);
- monthCell.setCellStyle(styles.get("month"));
- }
-
- int cnt = 1, day = 1;
- int rownum = 2;
- for (int j = 0; j < 6; j++) {
- Row row = sheet.createRow(rownum++);
- row.setHeightInPoints(100);
- for (int i = 0; i < days.length; i++) {
- Cell dayCell_1 = row.createCell(i * 2);
- Cell dayCell_2 = row.createCell(i * 2 + 1);
-
- int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
- if (cnt >= day_of_week && calendar.get(Calendar.MONTH) == month) {
- dayCell_1.setCellValue(day);
- calendar.set(Calendar.DAY_OF_MONTH, ++day);
-
- if (i == 0 || i == days.length - 1) {
- dayCell_1.setCellStyle(styles.get("weekend_left"));
- dayCell_2.setCellStyle(styles.get("weekend_right"));
- } else {
- dayCell_1.setCellStyle(styles.get("workday_left"));
- dayCell_2.setCellStyle(styles.get("workday_right"));
- }
- } else {
- dayCell_1.setCellStyle(styles.get("grey_left"));
- dayCell_2.setCellStyle(styles.get("grey_right"));
- }
- cnt++;
- }
- if (calendar.get(Calendar.MONTH) > month) break;
- }
- }
-
- // Write the output to a file
- String file = "calendar.xls";
- if (wb instanceof XSSFWorkbook) file += "x";
-
- try (FileOutputStream out = new FileOutputStream(file)) {
- wb.write(out);
- }
- }
- }
-
- /**
- * cell styles used for formatting calendar sheets
- */
- private static Map<String, CellStyle> createStyles(Workbook wb){
- Map<String, CellStyle> styles = new HashMap<>();
-
- short borderColor = IndexedColors.GREY_50_PERCENT.getIndex();
-
- CellStyle style;
- Font titleFont = wb.createFont();
- titleFont.setFontHeightInPoints((short)48);
- titleFont.setColor(IndexedColors.DARK_BLUE.getIndex());
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFont(titleFont);
- styles.put("title", style);
-
- Font monthFont = wb.createFont();
- monthFont.setFontHeightInPoints((short)12);
- monthFont.setColor(IndexedColors.WHITE.getIndex());
- monthFont.setBold(true);
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setFont(monthFont);
- styles.put("month", style);
-
- Font dayFont = wb.createFont();
- dayFont.setFontHeightInPoints((short)14);
- dayFont.setBold(true);
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setVerticalAlignment(VerticalAlignment.TOP);
- style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderLeft(BorderStyle.THIN);
- style.setLeftBorderColor(borderColor);
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(borderColor);
- style.setFont(dayFont);
- styles.put("weekend_left", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.TOP);
- style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(borderColor);
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(borderColor);
- styles.put("weekend_right", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setVerticalAlignment(VerticalAlignment.TOP);
- style.setBorderLeft(BorderStyle.THIN);
- style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setLeftBorderColor(borderColor);
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(borderColor);
- style.setFont(dayFont);
- styles.put("workday_left", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.TOP);
- style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(borderColor);
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(borderColor);
- styles.put("workday_right", style);
-
- style = wb.createCellStyle();
- style.setBorderLeft(BorderStyle.THIN);
- style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(borderColor);
- styles.put("grey_left", style);
-
- style = wb.createCellStyle();
- style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(borderColor);
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(borderColor);
- styles.put("grey_right", style);
-
- return styles;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-import java.io.File;
-
-import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.HSSFColor;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Color;
-import org.apache.poi.ss.usermodel.DataFormatter;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.usermodel.XSSFColor;
-import org.apache.poi.xssf.usermodel.XSSFFont;
-
-/**
- * Demonstrates how to read excel styles for cells
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class CellStyleDetails {
- private CellStyleDetails() {}
-
- public static void main(String[] args) throws Exception {
- if(args.length == 0) {
- throw new IllegalArgumentException("Filename must be given");
- }
-
- try (Workbook wb = WorkbookFactory.create(new File(args[0]))) {
- DataFormatter formatter = new DataFormatter();
-
- for (int sn = 0; sn < wb.getNumberOfSheets(); sn++) {
- Sheet sheet = wb.getSheetAt(sn);
- System.out.println("Sheet #" + sn + " : " + sheet.getSheetName());
-
- for (Row row : sheet) {
- System.out.println(" Row " + row.getRowNum());
-
- for (Cell cell : row) {
- CellReference ref = new CellReference(cell);
- System.out.print(" " + ref.formatAsString());
- System.out.print(" (" + cell.getColumnIndex() + ") ");
-
- CellStyle style = cell.getCellStyle();
- System.out.print("Format=" + style.getDataFormatString() + " ");
- System.out.print("FG=" + renderColor(style.getFillForegroundColorColor()) + " ");
- System.out.print("BG=" + renderColor(style.getFillBackgroundColorColor()) + " ");
-
- Font font = wb.getFontAt(style.getFontIndexAsInt());
- System.out.print("Font=" + font.getFontName() + " ");
- System.out.print("FontColor=");
- if (font instanceof HSSFFont) {
- System.out.print(renderColor(((HSSFFont) font).getHSSFColor((HSSFWorkbook) wb)));
- }
- if (font instanceof XSSFFont) {
- System.out.print(renderColor(((XSSFFont) font).getXSSFColor()));
- }
-
- System.out.println();
- System.out.println(" " + formatter.formatCellValue(cell));
- }
- }
-
- System.out.println();
- }
- }
- }
-
- private static String renderColor(Color color) {
- if(color instanceof HSSFColor) {
- return ((HSSFColor)color).getHexString();
- } else if(color instanceof XSSFColor) {
- return ((XSSFColor)color).getARGBHex();
- } else {
- return "(none)";
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.formula.ConditionalFormattingEvaluator;
-import org.apache.poi.ss.formula.EvaluationConditionalFormatRule;
-import org.apache.poi.ss.formula.WorkbookEvaluatorProvider;
-import org.apache.poi.ss.usermodel.BuiltinFormats;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.ColorScaleFormatting;
-import org.apache.poi.ss.usermodel.ComparisonOperator;
-import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
-import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
-import org.apache.poi.ss.usermodel.DataBarFormatting;
-import org.apache.poi.ss.usermodel.ExtendedColor;
-import org.apache.poi.ss.usermodel.FontFormatting;
-import org.apache.poi.ss.usermodel.IconMultiStateFormatting;
-import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.PatternFormatting;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Excel Conditional Formatting -- Examples
- *
- * <p>
- * Partly based on the code snippets from
- * http://www.contextures.com/xlcondformat03.html
- * </p>
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class ConditionalFormats {
-
- private ConditionalFormats() {}
-
- /**
- * generates a sample workbook with conditional formatting,
- * and prints out a summary of applied formats for one sheet
- * @param args pass "-xls" to generate an HSSF workbook, default is XSSF
- */
- public static void main(String[] args) throws IOException {
- final boolean isHSSF = args.length > 0 && args[0].equals("-xls");
- try (Workbook wb = isHSSF ? new HSSFWorkbook() : new XSSFWorkbook()) {
-
- 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"));
- inList(wb.createSheet("In List"));
- expiry(wb.createSheet("Expiry"));
- shadeAlt(wb.createSheet("Shade Alt"));
- shadeBands(wb.createSheet("Shade Bands"));
- iconSets(wb.createSheet("Icon Sets"));
- colourScales(wb.createSheet("Colour Scales"));
- dataBars(wb.createSheet("Data Bars"));
-
- // print overlapping rule results
- evaluateRules(wb, "Overlapping");
-
- // Write the output to a file
- String file = "cf-poi.xls";
- if (wb instanceof XSSFWorkbook) {
- file += "x";
- }
- try (FileOutputStream out = new FileOutputStream(file)) {
- wb.write(out);
- }
- System.out.println("Generated: " + file);
- }
- }
-
- /**
- * Highlight cells based on their values
- */
- static void sameCell(Sheet sheet) {
- sheet.createRow(0).createCell(0).setCellValue(84);
- sheet.createRow(1).createCell(0).setCellValue(74);
- sheet.createRow(2).createCell(0).setCellValue(50);
- sheet.createRow(3).createCell(0).setCellValue(51);
- sheet.createRow(4).createCell(0).setCellValue(49);
- sheet.createRow(5).createCell(0).setCellValue(41);
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- // Condition 1: Cell Value Is greater than 70 (Blue Fill)
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(ComparisonOperator.GT, "70");
- PatternFormatting fill1 = rule1.createPatternFormatting();
- fill1.setFillBackgroundColor(IndexedColors.BLUE.index);
- fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
-
- // Condition 2: Cell Value Is less than 50 (Green Fill)
- ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.LT, "50");
- PatternFormatting fill2 = rule2.createPatternFormatting();
- fill2.setFillBackgroundColor(IndexedColors.GREEN.index);
- fill2.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A1:A6")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1, rule2);
-
- sheet.getRow(0).createCell(2).setCellValue("<== Condition 1: Cell Value Is greater than 70 (Blue Fill)");
- sheet.getRow(4).createCell(2).setCellValue("<== Condition 2: Cell Value Is less than 50 (Green Fill)");
- }
-
- /**
- * Highlight multiple cells based on a formula
- */
- static void multiCell(Sheet sheet) {
- // header row
- Row row0 = sheet.createRow(0);
- row0.createCell(0).setCellValue("Units");
- row0.createCell(1).setCellValue("Cost");
- row0.createCell(2).setCellValue("Total");
-
- Row row1 = sheet.createRow(1);
- row1.createCell(0).setCellValue(71);
- row1.createCell(1).setCellValue(29);
- row1.createCell(2).setCellValue(2059);
-
- Row row2 = sheet.createRow(2);
- row2.createCell(0).setCellValue(85);
- row2.createCell(1).setCellValue(29);
- row2.createCell(2).setCellValue(2059);
-
- Row row3 = sheet.createRow(3);
- row3.createCell(0).setCellValue(71);
- row3.createCell(1).setCellValue(29);
- row3.createCell(2).setCellValue(2059);
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- // Condition 1: Formula Is =$B2>75 (Blue Fill)
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("$A2>75");
- PatternFormatting fill1 = rule1.createPatternFormatting();
- fill1.setFillBackgroundColor(IndexedColors.BLUE.index);
- fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A2:C4")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1);
-
- 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,
- * and change the font colour to match the cell colour.
- * In this example, if formula result is #DIV/0! then it will have white font colour.
- */
- static void errors(Sheet sheet) {
- sheet.createRow(0).createCell(0).setCellValue(84);
- sheet.createRow(1).createCell(0).setCellValue(0);
- sheet.createRow(2).createCell(0).setCellFormula("ROUND(A1/A2,0)");
- sheet.createRow(3).createCell(0).setCellValue(0);
- sheet.createRow(4).createCell(0).setCellFormula("ROUND(A6/A4,0)");
- sheet.createRow(5).createCell(0).setCellValue(41);
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- // Condition 1: Formula Is =ISERROR(C2) (White Font)
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("ISERROR(A1)");
- FontFormatting font = rule1.createFontFormatting();
- font.setFontColorIndex(IndexedColors.WHITE.index);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A1:A6")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1);
-
- sheet.getRow(2).createCell(1).setCellValue("<== The error in this cell is hidden. Condition: Formula Is =ISERROR(C2) (White Font)");
- sheet.getRow(4).createCell(1).setCellValue("<== The error in this cell is hidden. Condition: Formula Is =ISERROR(C2) (White Font)");
- }
-
- /**
- * Use Excel conditional formatting to hide the duplicate values,
- * and make the list easier to read. In this example, when the table is sorted by Region,
- * the second (and subsequent) occurences of each region name will have white font colour.
- */
- static void hideDupplicates(Sheet sheet) {
- sheet.createRow(0).createCell(0).setCellValue("City");
- sheet.createRow(1).createCell(0).setCellValue("Boston");
- sheet.createRow(2).createCell(0).setCellValue("Boston");
- sheet.createRow(3).createCell(0).setCellValue("Chicago");
- sheet.createRow(4).createCell(0).setCellValue("Chicago");
- sheet.createRow(5).createCell(0).setCellValue("New York");
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- // Condition 1: Formula Is =A2=A1 (White Font)
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("A2=A1");
- FontFormatting font = rule1.createFontFormatting();
- font.setFontColorIndex(IndexedColors.WHITE.index);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A2:A6")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1);
-
- sheet.getRow(1).createCell(1).setCellValue("<== the second (and subsequent) " +
- "occurences of each region name will have white font colour. " +
- "Condition: Formula Is =A2=A1 (White Font)");
- }
-
- /**
- * Use Excel conditional formatting to highlight duplicate entries in a column.
- */
- static void formatDuplicates(Sheet sheet) {
- sheet.createRow(0).createCell(0).setCellValue("Code");
- sheet.createRow(1).createCell(0).setCellValue(4);
- sheet.createRow(2).createCell(0).setCellValue(3);
- sheet.createRow(3).createCell(0).setCellValue(6);
- sheet.createRow(4).createCell(0).setCellValue(3);
- sheet.createRow(5).createCell(0).setCellValue(5);
- sheet.createRow(6).createCell(0).setCellValue(8);
- sheet.createRow(7).createCell(0).setCellValue(0);
- sheet.createRow(8).createCell(0).setCellValue(2);
- sheet.createRow(9).createCell(0).setCellValue(8);
- sheet.createRow(10).createCell(0).setCellValue(6);
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- // Condition 1: Formula Is =A2=A1 (White Font)
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($A$2:$A$11,A2)>1");
- FontFormatting font = rule1.createFontFormatting();
- font.setFontStyle(false, true);
- font.setFontColorIndex(IndexedColors.BLUE.index);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A2:A11")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1);
-
- sheet.getRow(2).createCell(1).setCellValue("<== Duplicates numbers in the column are highlighted. " +
- "Condition: Formula Is =COUNTIF($A$2:$A$11,A2)>1 (Blue Font)");
- }
-
- /**
- * Use Excel conditional formatting to highlight items that are in a list on the worksheet.
- */
- static void inList(Sheet sheet) {
- sheet.createRow(0).createCell(0).setCellValue("Codes");
- sheet.createRow(1).createCell(0).setCellValue("AA");
- sheet.createRow(2).createCell(0).setCellValue("BB");
- sheet.createRow(3).createCell(0).setCellValue("GG");
- sheet.createRow(4).createCell(0).setCellValue("AA");
- sheet.createRow(5).createCell(0).setCellValue("FF");
- sheet.createRow(6).createCell(0).setCellValue("XX");
- sheet.createRow(7).createCell(0).setCellValue("CC");
-
- sheet.getRow(0).createCell(2).setCellValue("Valid");
- sheet.getRow(1).createCell(2).setCellValue("AA");
- sheet.getRow(2).createCell(2).setCellValue("BB");
- sheet.getRow(3).createCell(2).setCellValue("CC");
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- // Condition 1: Formula Is =A2=A1 (White Font)
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($C$2:$C$4,A2)");
- PatternFormatting fill1 = rule1.createPatternFormatting();
- fill1.setFillBackgroundColor(IndexedColors.LIGHT_BLUE.index);
- fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A2:A8")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1);
-
- sheet.getRow(2).createCell(3).setCellValue("<== Use Excel conditional formatting to highlight items that are in a list on the worksheet");
- }
-
- /**
- * Use Excel conditional formatting to highlight payments that are due in the next thirty days.
- * In this example, Due dates are entered in cells A2:A4.
- */
- static void expiry(Sheet sheet) {
- CellStyle style = sheet.getWorkbook().createCellStyle();
- style.setDataFormat((short)BuiltinFormats.getBuiltinFormat("d-mmm"));
-
- sheet.createRow(0).createCell(0).setCellValue("Date");
- sheet.createRow(1).createCell(0).setCellFormula("TODAY()+29");
- sheet.createRow(2).createCell(0).setCellFormula("A2+1");
- sheet.createRow(3).createCell(0).setCellFormula("A3+1");
-
- for(int rownum = 1; rownum <= 3; rownum++) {
- sheet.getRow(rownum).getCell(0).setCellStyle(style);
- }
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- // Condition 1: Formula Is =A2=A1 (White Font)
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("AND(A2-TODAY()>=0,A2-TODAY()<=30)");
- FontFormatting font = rule1.createFontFormatting();
- font.setFontStyle(false, true);
- font.setFontColorIndex(IndexedColors.BLUE.index);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A2:A4")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1);
-
- sheet.getRow(0).createCell(1).setCellValue("Dates within the next 30 days are highlighted");
- }
-
- /**
- * Use Excel conditional formatting to shade alternating rows on the worksheet
- */
- static void shadeAlt(Sheet sheet) {
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- // Condition 1: Formula Is =A2=A1 (White Font)
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),2)");
- PatternFormatting fill1 = rule1.createPatternFormatting();
- fill1.setFillBackgroundColor(IndexedColors.LIGHT_GREEN.index);
- fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A1:Z100")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1);
-
- sheet.createRow(0).createCell(1).setCellValue("Shade Alternating Rows");
- sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),2) (Light Green Fill)");
- }
-
- /**
- * You can use Excel conditional formatting to shade bands of rows on the worksheet.
- * In this example, 3 rows are shaded light grey, and 3 are left with no shading.
- * In the MOD function, the total number of rows in the set of banded rows (6) is entered.
- */
- static void shadeBands(Sheet sheet) {
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),6)<3");
- PatternFormatting fill1 = rule1.createPatternFormatting();
- fill1.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index);
- fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
-
- CellRangeAddress[] regions = {
- CellRangeAddress.valueOf("A1:Z100")
- };
-
- sheetCF.addConditionalFormatting(regions, rule1);
-
- 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);
- }
-
- /**
- * Color Scales / Colour Scales / Colour Gradients allow you shade the
- * background colour of the cell based on the values, eg from Red to
- * Yellow to Green.
- */
- static void colourScales(Sheet sheet) {
- sheet.createRow(0).createCell(0).setCellValue("Colour Scales");
- Row r = sheet.createRow(1);
- r.createCell(0).setCellValue("Red-Yellow-Green");
- for (int i=1; i<=7; i++) {
- r.createCell(i).setCellValue((i-1)*5.0);
- }
- r = sheet.createRow(2);
- r.createCell(0).setCellValue("Red-White-Blue");
- for (int i=1; i<=9; i++) {
- r.createCell(i).setCellValue((i-1)*5.0);
- }
- r = sheet.createRow(3);
- r.createCell(0).setCellValue("Blue-Green");
- for (int i=1; i<=16; i++) {
- r.createCell(i).setCellValue((i-1));
- }
- sheet.setColumnWidth(0, 5000);
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:H2") };
- ConditionalFormattingRule rule1 =
- sheetCF.createConditionalFormattingColorScaleRule();
- ColorScaleFormatting cs1 = rule1.getColorScaleFormatting();
- cs1.getThresholds()[0].setRangeType(RangeType.MIN);
- cs1.getThresholds()[1].setRangeType(RangeType.PERCENTILE);
- cs1.getThresholds()[1].setValue(50d);
- cs1.getThresholds()[2].setRangeType(RangeType.MAX);
- ((ExtendedColor)cs1.getColors()[0]).setARGBHex("FFF8696B");
- ((ExtendedColor)cs1.getColors()[1]).setARGBHex("FFFFEB84");
- ((ExtendedColor)cs1.getColors()[2]).setARGBHex("FF63BE7B");
- sheetCF.addConditionalFormatting(regions, rule1);
-
- regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B3:J3") };
- ConditionalFormattingRule rule2 =
- sheetCF.createConditionalFormattingColorScaleRule();
- ColorScaleFormatting cs2 = rule2.getColorScaleFormatting();
- cs2.getThresholds()[0].setRangeType(RangeType.MIN);
- cs2.getThresholds()[1].setRangeType(RangeType.PERCENTILE);
- cs2.getThresholds()[1].setValue(50d);
- cs2.getThresholds()[2].setRangeType(RangeType.MAX);
- ((ExtendedColor)cs2.getColors()[0]).setARGBHex("FFF8696B");
- ((ExtendedColor)cs2.getColors()[1]).setARGBHex("FFFCFCFF");
- ((ExtendedColor)cs2.getColors()[2]).setARGBHex("FF5A8AC6");
- sheetCF.addConditionalFormatting(regions, rule2);
-
- regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B4:Q4") };
- ConditionalFormattingRule rule3=
- sheetCF.createConditionalFormattingColorScaleRule();
- ColorScaleFormatting cs3 = rule3.getColorScaleFormatting();
- cs3.setNumControlPoints(2);
- cs3.getThresholds()[0].setRangeType(RangeType.MIN);
- cs3.getThresholds()[1].setRangeType(RangeType.MAX);
- ((ExtendedColor)cs3.getColors()[0]).setARGBHex("FF5A8AC6");
- ((ExtendedColor)cs3.getColors()[1]).setARGBHex("FF63BE7B");
- sheetCF.addConditionalFormatting(regions, rule3);
- }
-
- /**
- * DataBars / Data-Bars allow you to have bars shown vary
- * based on the values, from full to empty
- */
- static void dataBars(Sheet sheet) {
- sheet.createRow(0).createCell(0).setCellValue("Data Bars");
- Row r = sheet.createRow(1);
- r.createCell(1).setCellValue("Green Positive");
- r.createCell(2).setCellValue("Blue Mix");
- r.createCell(3).setCellValue("Red Negative");
- r = sheet.createRow(2);
- r.createCell(1).setCellValue(0);
- r.createCell(2).setCellValue(0);
- r.createCell(3).setCellValue(0);
- r = sheet.createRow(3);
- r.createCell(1).setCellValue(5);
- r.createCell(2).setCellValue(-5);
- r.createCell(3).setCellValue(-5);
- r = sheet.createRow(4);
- r.createCell(1).setCellValue(10);
- r.createCell(2).setCellValue(10);
- r.createCell(3).setCellValue(-10);
- r = sheet.createRow(5);
- r.createCell(1).setCellValue(5);
- r.createCell(2).setCellValue(5);
- r.createCell(3).setCellValue(-5);
- r = sheet.createRow(6);
- r.createCell(1).setCellValue(20);
- r.createCell(2).setCellValue(-10);
- r.createCell(3).setCellValue(-20);
- sheet.setColumnWidth(0, 3000);
- sheet.setColumnWidth(1, 5000);
- sheet.setColumnWidth(2, 5000);
- sheet.setColumnWidth(3, 5000);
-
- SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
-
- ExtendedColor color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
- color.setARGBHex("FF63BE7B");
- CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:B7") };
- ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(color);
- DataBarFormatting db1 = rule1.getDataBarFormatting();
- db1.getMinThreshold().setRangeType(RangeType.MIN);
- db1.getMaxThreshold().setRangeType(RangeType.MAX);
- sheetCF.addConditionalFormatting(regions, rule1);
-
- color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
- color.setARGBHex("FF5A8AC6");
- regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C2:C7") };
- ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(color);
- DataBarFormatting db2 = rule2.getDataBarFormatting();
- db2.getMinThreshold().setRangeType(RangeType.MIN);
- db2.getMaxThreshold().setRangeType(RangeType.MAX);
- sheetCF.addConditionalFormatting(regions, rule2);
-
- color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
- color.setARGBHex("FFF8696B");
- regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D2:D7") };
- ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule(color);
- DataBarFormatting db3 = rule3.getDataBarFormatting();
- db3.getMinThreshold().setRangeType(RangeType.MIN);
- db3.getMaxThreshold().setRangeType(RangeType.MAX);
- sheetCF.addConditionalFormatting(regions, rule3);
- }
-
- /**
- * Print out a summary of the conditional formatting rules applied to cells on the given sheet.
- * Only cells with a matching rule are printed, and for those, all matching rules are sumarized.
- */
- static void evaluateRules(Workbook wb, String sheetName) {
- final WorkbookEvaluatorProvider wbEvalProv = (WorkbookEvaluatorProvider) wb.getCreationHelper().createFormulaEvaluator();
- final ConditionalFormattingEvaluator cfEval = new ConditionalFormattingEvaluator(wb, wbEvalProv);
- // if cell values have changed, clear cached format results
- cfEval.clearAllCachedValues();
-
- final Sheet sheet = wb.getSheet(sheetName);
- for (Row r : sheet) {
- for (Cell c : r) {
- final List<EvaluationConditionalFormatRule> rules = cfEval.getConditionalFormattingForCell(c);
- // check rules list for null, although current implementation will return an empty list, not null, then do what you want with results
- if (rules == null || rules.isEmpty()) {
- continue;
- }
- final CellReference ref = ConditionalFormattingEvaluator.getRef(c);
- if (rules.isEmpty()) {
- continue;
- }
-
- System.out.println("\n"
- + ref.formatAsString()
- + " has conditional formatting.");
-
- for (EvaluationConditionalFormatRule rule : rules) {
- ConditionalFormattingRule cf = rule.getRule();
-
- StringBuilder b = new StringBuilder();
- b.append("\tRule ")
- .append(rule.getFormattingIndex())
- .append(": ");
-
- // check for color scale
- if (cf.getColorScaleFormatting() != null) {
- b.append("\n\t\tcolor scale (caller must calculate bucket)");
- }
- // check for data bar
- if (cf.getDataBarFormatting() != null) {
- b.append("\n\t\tdata bar (caller must calculate bucket)");
- }
- // check for icon set
- if (cf.getMultiStateFormatting() != null) {
- b.append("\n\t\ticon set (caller must calculate icon bucket)");
- }
- // check for fill
- if (cf.getPatternFormatting() != null) {
- final PatternFormatting fill = cf.getPatternFormatting();
- b.append("\n\t\tfill pattern ")
- .append(fill.getFillPattern())
- .append(" color index ")
- .append(fill.getFillBackgroundColor());
- }
- // font stuff
- if (cf.getFontFormatting() != null) {
- final FontFormatting ff = cf.getFontFormatting();
- b.append("\n\t\tfont format ")
- .append("color index ")
- .append(ff.getFontColorIndex());
- if (ff.isBold()) {
- b.append(" bold");
- }
- if (ff.isItalic()) {
- b.append(" italic");
- }
- if (ff.isStruckout()) {
- b.append(" strikeout");
- }
- b.append(" underline index ")
- .append(ff.getUnderlineType());
- }
-
- System.out.println(b);
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.BorderExtent;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.PropertyTemplate;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Excel Border Drawing - examples
- *
- * <p>
- * Partly based on the code snippets from
- * org.apache.poi.ss.examples.ConditionalFormats
- * </p>
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class DrawingBorders {
-
- private DrawingBorders() {}
-
- public static void main(String[] args) throws IOException {
- try (Workbook wb = (args.length > 0 && args[0].equals("-xls"))
- ? new HSSFWorkbook() : new XSSFWorkbook()) {
- // add a sheet, and put some values into it
- Sheet sh1 = wb.createSheet("Sheet1");
- Row r = sh1.createRow(0);
- Cell c = r.createCell(1);
- c.setCellValue("All Borders Medium Width");
- r = sh1.createRow(4);
- c = r.createCell(1);
- c.setCellValue("Medium Outside / Thin Inside Borders");
- r = sh1.createRow(8);
- c = r.createCell(1);
- c.setCellValue("Colored Borders");
-
- // draw borders (three 3x3 grids)
- PropertyTemplate pt = new PropertyTemplate();
- // #1) these borders will all be medium in default color
- pt.drawBorders(new CellRangeAddress(1, 3, 1, 3),
- BorderStyle.MEDIUM, BorderExtent.ALL);
- // #2) these cells will have medium outside borders and thin inside borders
- pt.drawBorders(new CellRangeAddress(5, 7, 1, 3),
- BorderStyle.MEDIUM, BorderExtent.OUTSIDE);
- pt.drawBorders(new CellRangeAddress(5, 7, 1, 3), BorderStyle.THIN,
- BorderExtent.INSIDE);
- // #3) these cells will all be medium weight with different colors for the
- // outside, inside horizontal, and inside vertical borders. The center
- // cell will have no borders.
- pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
- BorderStyle.MEDIUM, IndexedColors.RED.getIndex(),
- BorderExtent.OUTSIDE);
- pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
- BorderStyle.MEDIUM, IndexedColors.BLUE.getIndex(),
- BorderExtent.INSIDE_VERTICAL);
- pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
- BorderStyle.MEDIUM, IndexedColors.GREEN.getIndex(),
- BorderExtent.INSIDE_HORIZONTAL);
- pt.drawBorders(new CellRangeAddress(10, 10, 2, 2),
- BorderStyle.NONE,
- BorderExtent.ALL);
-
- // apply borders to sheet
- pt.applyBorders(sh1);
-
- // add another sheet and apply the borders to it
- Sheet sh2 = wb.createSheet("Sheet2");
- pt.applyBorders(sh2);
-
- // Write the output to a file
- String file = "db-poi.xls" + (wb instanceof XSSFWorkbook ? "x" : "");
- try (FileOutputStream out = new FileOutputStream(file)) {
- wb.write(out);
- }
- System.out.println("Generated: " + file);
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.Color;
-import org.apache.poi.ss.usermodel.DateUtil;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFCellStyle;
-import org.apache.poi.xssf.usermodel.XSSFColor;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-
-/**
- * Utility to compare Excel File Contents cell by cell for all sheets.
- *
- * <p>This utility will be used to compare Excel File Contents cell by cell for all sheets programmatically.</p>
- *
- * <p>Below are the list of Attribute comparison supported in this version.</p>
- *
- * <ul>
- * <li>Cell Alignment</li>
- * <li>Cell Border Attributes</li>
- * <li>Cell Data</li>
- * <li>Cell Data-Type</li>
- * <li>Cell Fill Color</li>
- * <li>Cell Fill pattern</li>
- * <li>Cell Font Attributes</li>
- * <li>Cell Font Family</li>
- * <li>Cell Font Size</li>
- * <li>Cell Protection</li>
- * <li>Name of the sheets</li>
- * <li>Number of Columns</li>
- * <li>Number of Rows</li>
- * <li>Number of Sheet</li>
- * </ul>
- *
- * <p>(Some of the above attribute comparison only work for *.xlsx format currently. In future it can be enhanced.)</p>
- *
- * <p><b>Usage:</b></p>
- *
- * <pre>
- * {@code
- * Workbook wb1 = WorkbookFactory.create(new File("workBook1.xls"));
- * Workbook wb2 = WorkbookFactory.create(new File("workBook2.xls"));
- * List<String> listOfDifferences = ExcelComparator.compare(wb1, wb2);
- * for (String differences : listOfDifferences)
- * System.out.println(differences);
- * System.out.println("DifferenceFound = "+ excelFileDifference.isDifferenceFound);
- * }
- * </pre>
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public class ExcelComparator {
-
- private static final String CELL_DATA_DOES_NOT_MATCH = "Cell Data does not Match ::";
- private static final String CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH = "Cell Font Attributes does not Match ::";
-
- private static class Locator {
- Workbook workbook;
- Sheet sheet;
- Row row;
- Cell cell;
- }
-
- List<String> listOfDifferences = new ArrayList<>();
-
- public static void main(String[] args) throws Exception {
- if (args.length != 2 || !(new File(args[0]).exists()) || !(new File(args[1]).exists())) {
- System.err.println("java -cp <classpath> "+ExcelComparator.class.getCanonicalName()+" <workbook1.xls/x> <workbook2.xls/x");
- System.exit(-1);
- }
-
- try (Workbook wb1 = WorkbookFactory.create(new File(args[0]), null, true)) {
- try (Workbook wb2 = WorkbookFactory.create(new File(args[1]), null, true)) {
- for (String d : ExcelComparator.compare(wb1, wb2)) {
- System.out.println(d);
- }
- }
- }
- }
-
- /**
- * Utility to compare Excel File Contents cell by cell for all sheets.
- *
- * @param wb1 the workbook1
- * @param wb2 the workbook2
- * @return the Excel file difference containing a flag and a list of differences
- */
- public static List<String> compare(Workbook wb1, Workbook wb2) {
- Locator loc1 = new Locator();
- Locator loc2 = new Locator();
- loc1.workbook = wb1;
- loc2.workbook = wb2;
-
- ExcelComparator excelComparator = new ExcelComparator();
- excelComparator.compareNumberOfSheets(loc1, loc2 );
- excelComparator.compareSheetNames(loc1, loc2);
- excelComparator.compareSheetData(loc1, loc2);
-
- return excelComparator.listOfDifferences;
- }
-
- /**
- * Compare data in all sheets.
- */
- private void compareDataInAllSheets(Locator loc1, Locator loc2) {
- for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) {
- if (loc2.workbook.getNumberOfSheets() <= i) {
- return;
- }
-
- loc1.sheet = loc1.workbook.getSheetAt(i);
- loc2.sheet = loc2.workbook.getSheetAt(i);
-
- compareDataInSheet(loc1, loc2);
- }
- }
-
- private void compareDataInSheet(Locator loc1, Locator loc2) {
- for (int j = 0; j <= loc1.sheet.getLastRowNum(); j++) {
- if (loc2.sheet.getLastRowNum() <= j) {
- return;
- }
-
- loc1.row = loc1.sheet.getRow(j);
- loc2.row = loc2.sheet.getRow(j);
-
- if ((loc1.row == null) || (loc2.row == null)) {
- continue;
- }
-
- compareDataInRow(loc1, loc2);
- }
- }
-
- private void compareDataInRow(Locator loc1, Locator loc2) {
- for (int k = 0; k <= loc1.row.getLastCellNum(); k++) {
- if (loc2.row.getLastCellNum() <= k) {
- return;
- }
-
- loc1.cell = loc1.row.getCell(k);
- loc2.cell = loc2.row.getCell(k);
-
- if ((loc1.cell == null) || (loc2.cell == null)) {
- continue;
- }
-
- compareDataInCell(loc1, loc2);
- }
- }
-
- private void compareDataInCell(Locator loc1, Locator loc2) {
- if (isCellTypeMatches(loc1, loc2)) {
- final CellType loc1cellType = loc1.cell.getCellType();
- switch(loc1cellType) {
- case BLANK:
- case STRING:
- case ERROR:
- isCellContentMatches(loc1,loc2);
- break;
- case BOOLEAN:
- isCellContentMatchesForBoolean(loc1,loc2);
- break;
- case FORMULA:
- isCellContentMatchesForFormula(loc1,loc2);
- break;
- case NUMERIC:
- if (DateUtil.isCellDateFormatted(loc1.cell)) {
- isCellContentMatchesForDate(loc1,loc2);
- } else {
- isCellContentMatchesForNumeric(loc1,loc2);
- }
- break;
- default:
- throw new IllegalStateException("Unexpected cell type: " + loc1cellType);
- }
- }
-
- isCellFillPatternMatches(loc1,loc2);
- isCellAlignmentMatches(loc1,loc2);
- isCellHiddenMatches(loc1,loc2);
- isCellLockedMatches(loc1,loc2);
- isCellFontFamilyMatches(loc1,loc2);
- isCellFontSizeMatches(loc1,loc2);
- isCellFontBoldMatches(loc1,loc2);
- isCellUnderLineMatches(loc1,loc2);
- isCellFontItalicsMatches(loc1,loc2);
- isCellBorderMatches(loc1,loc2,'t');
- isCellBorderMatches(loc1,loc2,'l');
- isCellBorderMatches(loc1,loc2,'b');
- isCellBorderMatches(loc1,loc2,'r');
- isCellFillBackGroundMatches(loc1,loc2);
- }
-
- /**
- * Compare number of columns in sheets.
- */
- private void compareNumberOfColumnsInSheets(Locator loc1, Locator loc2) {
- for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) {
- if (loc2.workbook.getNumberOfSheets() <= i) {
- return;
- }
-
- loc1.sheet = loc1.workbook.getSheetAt(i);
- loc2.sheet = loc2.workbook.getSheetAt(i);
-
- Iterator<Row> ri1 = loc1.sheet.rowIterator();
- Iterator<Row> ri2 = loc2.sheet.rowIterator();
-
- int num1 = (ri1.hasNext()) ? ri1.next().getPhysicalNumberOfCells() : 0;
- int num2 = (ri2.hasNext()) ? ri2.next().getPhysicalNumberOfCells() : 0;
-
- if (num1 != num2) {
- String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]",
- "Number Of Columns does not Match ::",
- loc1.sheet.getSheetName(), num1,
- loc2.sheet.getSheetName(), num2
- );
- listOfDifferences.add(str);
- }
- }
- }
-
- /**
- * Compare number of rows in sheets.
- */
- private void compareNumberOfRowsInSheets(Locator loc1, Locator loc2) {
- for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) {
- if (loc2.workbook.getNumberOfSheets() <= i) {
- return;
- }
-
- loc1.sheet = loc1.workbook.getSheetAt(i);
- loc2.sheet = loc2.workbook.getSheetAt(i);
-
- int num1 = loc1.sheet.getPhysicalNumberOfRows();
- int num2 = loc2.sheet.getPhysicalNumberOfRows();
-
- if (num1 != num2) {
- String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]",
- "Number Of Rows does not Match ::",
- loc1.sheet.getSheetName(), num1,
- loc2.sheet.getSheetName(), num2
- );
- listOfDifferences.add(str);
- }
- }
-
- }
-
- /**
- * Compare number of sheets.
- */
- private void compareNumberOfSheets(Locator loc1, Locator loc2) {
- int num1 = loc1.workbook.getNumberOfSheets();
- int num2 = loc2.workbook.getNumberOfSheets();
- if (num1 != num2) {
- String str = String.format(Locale.ROOT, "%s\nworkbook1 [%d] != workbook2 [%d]",
- "Number of Sheets do not match ::",
- num1, num2
- );
-
- listOfDifferences.add(str);
-
- }
- }
-
- /**
- * Compare sheet data.
- */
- private void compareSheetData(Locator loc1, Locator loc2) {
- compareNumberOfRowsInSheets(loc1, loc2);
- compareNumberOfColumnsInSheets(loc1, loc2);
- compareDataInAllSheets(loc1, loc2);
-
- }
-
- /**
- * Compare sheet names.
- */
- private void compareSheetNames(Locator loc1, Locator loc2) {
- for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) {
- String name1 = loc1.workbook.getSheetName(i);
- String name2 = (loc2.workbook.getNumberOfSheets() > i) ? loc2.workbook.getSheetName(i) : "";
-
- if (!name1.equals(name2)) {
- String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]",
- "Name of the sheets do not match ::", name1, i+1, name2, i+1
- );
- listOfDifferences.add(str);
- }
- }
- }
-
- /**
- * Formats the message.
- */
- private void addMessage(Locator loc1, Locator loc2, String messageStart, String value1, String value2) {
- String str =
- String.format(Locale.ROOT, "%s\nworkbook1 -> %s -> %s [%s] != workbook2 -> %s -> %s [%s]",
- messageStart,
- loc1.sheet.getSheetName(), new CellReference(loc1.cell).formatAsString(), value1,
- loc2.sheet.getSheetName(), new CellReference(loc2.cell).formatAsString(), value2
- );
- listOfDifferences.add(str);
- }
-
- /**
- * Checks if cell alignment matches.
- */
- private void isCellAlignmentMatches(Locator loc1, Locator loc2) {
- if(loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- HorizontalAlignment align1 = loc1.cell.getCellStyle().getAlignment();
- HorizontalAlignment align2 = loc2.cell.getCellStyle().getAlignment();
- if (align1 != align2) {
- addMessage(loc1, loc2,
- "Cell Alignment does not Match ::",
- align1.name(),
- align2.name()
- );
- }
- }
-
- /**
- * Checks if cell border bottom matches.
- */
- private void isCellBorderMatches(Locator loc1, Locator loc2, char borderSide) {
- if (!(loc1.cell instanceof XSSFCell) ||
- loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- XSSFCellStyle style1 = ((XSSFCell)loc1.cell).getCellStyle();
- XSSFCellStyle style2 = ((XSSFCell)loc2.cell).getCellStyle();
- boolean b1, b2;
- String borderName;
- switch (borderSide) {
- case 't': default:
- b1 = style1.getBorderTop() == BorderStyle.THIN;
- b2 = style2.getBorderTop() == BorderStyle.THIN;
- borderName = "TOP";
- break;
- case 'b':
- b1 = style1.getBorderBottom() == BorderStyle.THIN;
- b2 = style2.getBorderBottom() == BorderStyle.THIN;
- borderName = "BOTTOM";
- break;
- case 'l':
- b1 = style1.getBorderLeft() == BorderStyle.THIN;
- b2 = style2.getBorderLeft() == BorderStyle.THIN;
- borderName = "LEFT";
- break;
- case 'r':
- b1 = style1.getBorderRight() == BorderStyle.THIN;
- b2 = style2.getBorderRight() == BorderStyle.THIN;
- borderName = "RIGHT";
- break;
- }
- if (b1 != b2) {
- addMessage(loc1, loc2,
- "Cell Border Attributes does not Match ::",
- (b1 ? "" : "NOT ")+borderName+" BORDER",
- (b2 ? "" : "NOT ")+borderName+" BORDER"
- );
- }
- }
-
- /**
- * Checks if cell content matches.
- */
- private void isCellContentMatches(Locator loc1, Locator loc2) {
- String str1 = loc1.cell.toString();
- String str2 = loc2.cell.toString();
- if (!str1.equals(str2)) {
- addMessage(loc1,loc2,CELL_DATA_DOES_NOT_MATCH,str1,str2);
- }
- }
-
- /**
- * Checks if cell content matches for boolean.
- */
- private void isCellContentMatchesForBoolean(Locator loc1, Locator loc2) {
- boolean b1 = loc1.cell.getBooleanCellValue();
- boolean b2 = loc2.cell.getBooleanCellValue();
- if (b1 != b2) {
- addMessage(loc1,loc2,CELL_DATA_DOES_NOT_MATCH,Boolean.toString(b1),Boolean.toString(b2));
- }
- }
-
- /**
- * Checks if cell content matches for date.
- */
- private void isCellContentMatchesForDate(Locator loc1, Locator loc2) {
- Date date1 = loc1.cell.getDateCellValue();
- Date date2 = loc2.cell.getDateCellValue();
- if (!date1.equals(date2)) {
- addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, date1.toString(), date2.toString());
- }
- }
-
-
- /**
- * Checks if cell content matches for formula.
- */
- private void isCellContentMatchesForFormula(Locator loc1, Locator loc2) {
- // TODO: actually evaluate the formula / NPE checks
- String form1 = loc1.cell.getCellFormula();
- String form2 = loc2.cell.getCellFormula();
- if (!form1.equals(form2)) {
- addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, form1, form2);
- }
- }
-
- /**
- * Checks if cell content matches for numeric.
- */
- private void isCellContentMatchesForNumeric(Locator loc1, Locator loc2) {
- // TODO: Check for NaN
- double num1 = loc1.cell.getNumericCellValue();
- double num2 = loc2.cell.getNumericCellValue();
- if (num1 != num2) {
- addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, Double.toString(num1), Double.toString(num2));
- }
- }
-
- private String getCellFillBackground(Locator loc) {
- Color col = loc.cell.getCellStyle().getFillForegroundColorColor();
- return (col instanceof XSSFColor) ? ((XSSFColor)col).getARGBHex() : "NO COLOR";
- }
-
- /**
- * Checks if cell file back ground matches.
- */
- private void isCellFillBackGroundMatches(Locator loc1, Locator loc2) {
- if(loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- String col1 = getCellFillBackground(loc1);
- String col2 = getCellFillBackground(loc2);
- if (!col1.equals(col2)) {
- addMessage(loc1, loc2, "Cell Fill Color does not Match ::", col1, col2);
- }
- }
- /**
- * Checks if cell fill pattern matches.
- */
- private void isCellFillPatternMatches(Locator loc1, Locator loc2) {
- if(loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- FillPatternType fill1 = loc1.cell.getCellStyle().getFillPattern();
- FillPatternType fill2 = loc2.cell.getCellStyle().getFillPattern();
- if (fill1 != fill2) {
- addMessage(loc1, loc2,
- "Cell Fill pattern does not Match ::",
- fill1.name(),
- fill2.name()
- );
- }
- }
-
- /**
- * Checks if cell font bold matches.
- */
- private void isCellFontBoldMatches(Locator loc1, Locator loc2) {
- if (!(loc1.cell instanceof XSSFCell) ||
- loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- if(hasInvalidFontIndex(loc1, loc2)) {
- return;
- }
-
- boolean b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getBold();
- boolean b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getBold();
- if (b1 != b2) {
- addMessage(loc1, loc2,
- CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH,
- (b1 ? "" : "NOT ")+"BOLD",
- (b2 ? "" : "NOT ")+"BOLD"
- );
- }
- }
-
- /**
- * Checks if cell font family matches.
- */
- private void isCellFontFamilyMatches(Locator loc1, Locator loc2) {
- if (!(loc1.cell instanceof XSSFCell) ||
- loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- if(hasInvalidFontIndex(loc1, loc2)) {
- return;
- }
-
- String family1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getFontName();
- String family2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getFontName();
- if (!family1.equals(family2)) {
- addMessage(loc1, loc2, "Cell Font Family does not Match ::", family1, family2);
- }
- }
-
- private boolean hasInvalidFontIndex(Locator loc1, Locator loc2) {
- int fontIdx1 = loc1.cell.getCellStyle().getFontIndexAsInt();
- int fontCount1 = ((XSSFWorkbook)loc1.workbook).getStylesSource().getFonts().size();
- int fontIdx2 = loc2.cell.getCellStyle().getFontIndexAsInt();
- int fontCount2 = ((XSSFWorkbook)loc2.workbook).getStylesSource().getFonts().size();
-
- if(fontIdx1 >= fontCount1 || fontIdx2 >= fontCount2) {
- addMessage(loc1, loc2, "Corrupted file, cell style references a font which is not defined", Integer.toString(fontIdx1), Integer.toString(fontIdx2));
- return true;
- }
-
- return false;
- }
-
- /**
- * Checks if cell font italics matches.
- */
- private void isCellFontItalicsMatches(Locator loc1, Locator loc2) {
- if (!(loc1.cell instanceof XSSFCell) ||
- loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- if(hasInvalidFontIndex(loc1, loc2)) {
- return;
- }
-
- boolean b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getItalic();
- boolean b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getItalic();
- if (b1 != b2) {
- addMessage(loc1, loc2,
- CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH,
- (b1 ? "" : "NOT ")+"ITALICS",
- (b2 ? "" : "NOT ")+"ITALICS"
- );
- }
- }
-
- /**
- * Checks if cell font size matches.
- */
- private void isCellFontSizeMatches(Locator loc1, Locator loc2) {
- if (!(loc1.cell instanceof XSSFCell) ||
- loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- if(hasInvalidFontIndex(loc1, loc2)) {
- return;
- }
-
- short size1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getFontHeightInPoints();
- short size2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getFontHeightInPoints();
- if (size1 != size2) {
- addMessage(loc1, loc2,
- "Cell Font Size does not Match ::",
- Short.toString(size1),
- Short.toString(size2)
- );
- }
- }
-
- /**
- * Checks if cell hidden matches.
- */
- private void isCellHiddenMatches(Locator loc1, Locator loc2) {
- if (loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- boolean b1 = loc1.cell.getCellStyle().getHidden();
- boolean b2 = loc1.cell.getCellStyle().getHidden();
- if (b1 != b2) {
- addMessage(loc1, loc2,
- "Cell Visibility does not Match ::",
- (b1 ? "" : "NOT ")+"HIDDEN",
- (b2 ? "" : "NOT ")+"HIDDEN"
- );
- }
- }
-
- /**
- * Checks if cell locked matches.
- */
- private void isCellLockedMatches(Locator loc1, Locator loc2) {
- if (loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- boolean b1 = loc1.cell.getCellStyle().getLocked();
- boolean b2 = loc1.cell.getCellStyle().getLocked();
- if (b1 != b2) {
- addMessage(loc1, loc2,
- "Cell Protection does not Match ::",
- (b1 ? "" : "NOT ")+"LOCKED",
- (b2 ? "" : "NOT ")+"LOCKED"
- );
- }
- }
-
- /**
- * Checks if cell type matches.
- */
- private boolean isCellTypeMatches(Locator loc1, Locator loc2) {
- CellType type1 = loc1.cell.getCellType();
- CellType type2 = loc2.cell.getCellType();
- if (type1 == type2) {
- return true;
- }
-
- addMessage(loc1, loc2,
- "Cell Data-Type does not Match in :: ",
- type1.name(), type2.name()
- );
- return false;
- }
-
- /**
- * Checks if cell under line matches.
- */
- private void isCellUnderLineMatches(Locator loc1, Locator loc2) {
- // TODO: distinguish underline type
-
- if (!(loc1.cell instanceof XSSFCell) ||
- loc1.cell.getCellStyle() == null || loc2.cell.getCellStyle() == null) {
- return;
- }
-
- if(hasInvalidFontIndex(loc1, loc2)) {
- return;
- }
-
- byte b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getUnderline();
- byte b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getUnderline();
- if (b1 != b2) {
- addMessage(loc1, loc2,
- CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH,
- (b1 == 1 ? "" : "NOT ")+"UNDERLINE",
- (b2 == 1 ? "" : "NOT ")+"UNDERLINE"
- );
- }
- }
-}
\ No newline at end of file
+++ /dev/null
- /* ====================================================================
- 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.ss.examples;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.DataValidation;
-import org.apache.poi.ss.usermodel.DataValidationConstraint;
-import org.apache.poi.ss.usermodel.DataValidationHelper;
-import org.apache.poi.ss.usermodel.Name;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddressList;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates one technique that may be used to create linked or dependent
- * drop down lists. This refers to a situation in which the selection made
- * in one drop down list affects the options that are displayed in the second
- * or subsequent drop down list(s). In this example, the value the user selects
- * from the down list in cell A1 will affect the values displayed in the linked
- * drop down list in cell B1. For the sake of simplicity, the data for the drop
- * down lists is included on the same worksheet but this does not have to be the
- * case; the data could appear on a separate sheet. If this were done, then the
- * names for the regions would have to be different, they would have to include
- * the name of the sheet.
- *
- * There are two keys to this technique. The first is the use of named area or
- * regions of cells to hold the data for the drop down lists and the second is
- * making use of the INDIRECT() function to convert a name into the addresses
- * of the cells it refers to.
- *
- * Note that whilst this class builds just two linked drop down lists, there is
- * nothing to prevent more being created. Quite simply, use the value selected
- * by the user in one drop down list to determine what is shown in another and the
- * value selected in that drop down list to determine what is shown in a third,
- * and so on. Also, note that the data for the drop down lists is contained on
- * contained on the same sheet as the validations themselves. This is done simply
- * for simplicity and there is nothing to prevent a separate sheet being created
- * and used to hold the data. If this is done then problems may be encountered
- * if the sheet is opened with OpenOffice Calc. To prevent these problems, it is
- * better to include the name of the sheet when calling the setRefersToFormula()
- * method.
- *
- * @author Mark Beardsley [msb at apache.org]
- * @version 1.00 30th March 2012
- */
-public class LinkedDropDownLists {
-
- LinkedDropDownLists(String workbookName) throws IOException {
- // Using the ss.usermodel allows this class to support both binary
- // and xml based workbooks. The choice of which one to create is
- // made by checking the file extension.
- try (Workbook workbook = workbookName.endsWith(".xlsx") ? new XSSFWorkbook() : new HSSFWorkbook()) {
-
- // Build the sheet that will hold the data for the validations. This
- // must be done first as it will create names that are referenced
- // later.
- Sheet sheet = workbook.createSheet("Linked Validations");
- LinkedDropDownLists.buildDataSheet(sheet);
-
- // Build the first data validation to occupy cell A1. Note
- // that it retrieves it's data from the named area or region called
- // CHOICES. Further information about this can be found in the
- // static buildDataSheet() method below.
- CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
- DataValidationHelper dvHelper = sheet.getDataValidationHelper();
- DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint("CHOICES");
- DataValidation validation = dvHelper.createValidation(dvConstraint, addressList);
- sheet.addValidationData(validation);
-
- // Now, build the linked or dependent drop down list that will
- // occupy cell B1. The key to the whole process is the use of the
- // INDIRECT() function. In the buildDataSheet(0 method, a series of
- // named regions are created and the names of three of them mirror
- // the options available to the user in the first drop down list
- // (in cell A1). Using the INDIRECT() function makes it possible
- // to convert the selection the user makes in that first drop down
- // into the addresses of a named region of cells and then to use
- // those cells to populate the second drop down list.
- addressList = new CellRangeAddressList(0, 0, 1, 1);
- dvConstraint = dvHelper.createFormulaListConstraint(
- "INDIRECT(UPPER($A$1))");
- validation = dvHelper.createValidation(dvConstraint, addressList);
- sheet.addValidationData(validation);
-
- try (FileOutputStream fos = new FileOutputStream(workbookName)) {
- workbook.write(fos);
- }
- }
- }
-
- /**
- * Called to populate the named areas/regions. The contents of the cells on
- * row one will be used to populate the first drop down list. The contents of
- * the cells on rows two, three and four will be used to populate the second
- * drop down list, just which row will be determined by the choice the user
- * makes in the first drop down list.
- *
- * In all cases, the approach is to create a row, create and populate cells
- * with data and then specify a name that identifies those cells. With the
- * exception of the first range, the names that are chosen for each range
- * of cells are quite important. In short, each of the options the user
- * could select in the first drop down list is used as the name for another
- * range of cells. Thus, in this example, the user can select either
- * 'Animal', 'Vegetable' or 'Mineral' in the first drop down and so the
- * sheet contains ranges named 'ANIMAL', 'VEGETABLE' and 'MINERAL'.
- *
- * @param dataSheet An instance of a class that implements the Sheet Sheet
- * interface (HSSFSheet or XSSFSheet).
- */
- private static void buildDataSheet(Sheet dataSheet) {
- Row row = null;
- Cell cell = null;
- Name name = null;
-
- // The first row will hold the data for the first validation.
- row = dataSheet.createRow(10);
- cell = row.createCell(0);
- cell.setCellValue("Animal");
- cell = row.createCell(1);
- cell.setCellValue("Vegetable");
- cell = row.createCell(2);
- cell.setCellValue("Mineral");
- name = dataSheet.getWorkbook().createName();
- name.setRefersToFormula("$A$11:$C$11");
- name.setNameName("CHOICES");
-
- // The next three rows will hold the data that will be used to
- // populate the second, or linked, drop down list.
- row = dataSheet.createRow(11);
- cell = row.createCell(0);
- cell.setCellValue("Lion");
- cell = row.createCell(1);
- cell.setCellValue("Tiger");
- cell = row.createCell(2);
- cell.setCellValue("Leopard");
- cell = row.createCell(3);
- cell.setCellValue("Elephant");
- cell = row.createCell(4);
- cell.setCellValue("Eagle");
- cell = row.createCell(5);
- cell.setCellValue("Horse");
- cell = row.createCell(6);
- cell.setCellValue("Zebra");
- name = dataSheet.getWorkbook().createName();
- name.setRefersToFormula("$A$12:$G$12");
- name.setNameName("ANIMAL");
-
- row = dataSheet.createRow(12);
- cell = row.createCell(0);
- cell.setCellValue("Cabbage");
- cell = row.createCell(1);
- cell.setCellValue("Cauliflower");
- cell = row.createCell(2);
- cell.setCellValue("Potato");
- cell = row.createCell(3);
- cell.setCellValue("Onion");
- cell = row.createCell(4);
- cell.setCellValue("Beetroot");
- cell = row.createCell(5);
- cell.setCellValue("Asparagus");
- cell = row.createCell(6);
- cell.setCellValue("Spinach");
- cell = row.createCell(7);
- cell.setCellValue("Chard");
- name = dataSheet.getWorkbook().createName();
- name.setRefersToFormula("$A$13:$H$13");
- name.setNameName("VEGETABLE");
-
- row = dataSheet.createRow(13);
- cell = row.createCell(0);
- cell.setCellValue("Bauxite");
- cell = row.createCell(1);
- cell.setCellValue("Quartz");
- cell = row.createCell(2);
- cell.setCellValue("Feldspar");
- cell = row.createCell(3);
- cell.setCellValue("Shist");
- cell = row.createCell(4);
- cell.setCellValue("Shale");
- cell = row.createCell(5);
- cell.setCellValue("Mica");
- name = dataSheet.getWorkbook().createName();
- name.setRefersToFormula("$A$14:$F$14");
- name.setNameName("MINERAL");
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hssf.usermodel.HSSFObjectData;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hwpf.HWPFDocument;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.poifs.filesystem.Entry;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.xmlbeans.XmlException;
-
-/**
- * Loads embedded resources from Workbooks. Code taken from the website:
- * https://poi.apache.org/spreadsheet/quick-guide.html#Embedded
- */
-@SuppressWarnings({"java:S106","java:S4823"})
-public final class LoadEmbedded {
- private LoadEmbedded() {}
-
- public static void main(String[] args) throws IOException, EncryptedDocumentException, OpenXML4JException, XmlException {
- Workbook wb = WorkbookFactory.create(new File(args[0]));
- loadEmbedded(wb);
- }
-
- public static void loadEmbedded(Workbook wb) throws IOException, InvalidFormatException, OpenXML4JException, XmlException {
- if (wb instanceof HSSFWorkbook) {
- loadEmbedded((HSSFWorkbook)wb);
- }
- else if (wb instanceof XSSFWorkbook) {
- loadEmbedded((XSSFWorkbook)wb);
- }
- else {
- throw new IllegalArgumentException(wb.getClass().getName());
- }
- }
-
- public static void loadEmbedded(HSSFWorkbook workbook) throws IOException {
- for (HSSFObjectData obj : workbook.getAllEmbeddedObjects()) {
- //the OLE2 Class Name of the object
- String oleName = obj.getOLE2ClassName();
- if (oleName.equals("Worksheet")) {
- DirectoryNode dn = (DirectoryNode) obj.getDirectory();
- HSSFWorkbook embeddedWorkbook = new HSSFWorkbook(dn, false);
- embeddedWorkbook.close();
- } else if (oleName.equals("Document")) {
- DirectoryNode dn = (DirectoryNode) obj.getDirectory();
- HWPFDocument embeddedWordDocument = new HWPFDocument(dn);
- embeddedWordDocument.close();
- } else if (oleName.equals("Presentation")) {
- DirectoryNode dn = (DirectoryNode) obj.getDirectory();
- SlideShow<?,?> embeddedSlieShow = new HSLFSlideShow(dn);
- embeddedSlieShow.close();
- } else {
- if(obj.hasDirectoryEntry()){
- // The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is
- DirectoryNode dn = (DirectoryNode) obj.getDirectory();
- for (Entry entry : dn) {
- //System.out.println(oleName + "." + entry.getName());
- }
- } else {
- // There is no DirectoryEntry
- // Recover the object's data from the HSSFObjectData instance.
- byte[] objectData = obj.getObjectData();
- }
- }
- }
- }
-
- public static void loadEmbedded(XSSFWorkbook workbook) throws IOException, InvalidFormatException, OpenXML4JException, XmlException {
- for (PackagePart pPart : workbook.getAllEmbeddedParts()) {
- String contentType = pPart.getContentType();
- if (contentType.equals("application/vnd.ms-excel")) {
- // Excel Workbook - either binary or OpenXML
- HSSFWorkbook embeddedWorkbook = new HSSFWorkbook(pPart.getInputStream());
- embeddedWorkbook.close();
- } else if (contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
- // Excel Workbook - OpenXML file format
- XSSFWorkbook embeddedWorkbook = new XSSFWorkbook(pPart.getInputStream());
- embeddedWorkbook.close();
- } else if (contentType.equals("application/msword")) {
- // Word Document - binary (OLE2CDF) file format
- HWPFDocument document = new HWPFDocument(pPart.getInputStream());
- document.close();
- } else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
- // Word Document - OpenXML file format
- XWPFDocument document = new XWPFDocument(pPart.getInputStream());
- document.close();
- } else if (contentType.equals("application/vnd.ms-powerpoint")) {
- // PowerPoint Document - binary file format
- HSLFSlideShow slideShow = new HSLFSlideShow(pPart.getInputStream());
- slideShow.close();
- } else if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) {
- // PowerPoint Document - OpenXML file format
- XMLSlideShow slideShow = new XMLSlideShow(pPart.getInputStream());
- slideShow.close();
- } else {
- // Any other type of embedded object.
- System.out.println("Unknown Embedded Document: " + contentType);
- InputStream inputStream = pPart.getInputStream();
- inputStream.close();
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-import java.io.FileOutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Name;
-import org.apache.poi.ss.usermodel.PrintSetup;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Simple Loan Calculator. Demonstrates advance usage of cell formulas and named ranges.
- *
- * Usage:
- * LoanCalculator -xls|xlsx
- *
- * @author Yegor Kozlov
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class LoanCalculator {
-
- private LoanCalculator() {}
-
- public static void main(String[] args) throws Exception {
- Workbook wb;
-
- if(args.length > 0 && args[0].equals("-xls")) wb = new HSSFWorkbook();
- else wb = new XSSFWorkbook();
-
- Map<String, CellStyle> styles = createStyles(wb);
- Sheet sheet = wb.createSheet("Loan Calculator");
- sheet.setPrintGridlines(false);
- sheet.setDisplayGridlines(false);
-
- PrintSetup printSetup = sheet.getPrintSetup();
- printSetup.setLandscape(true);
- sheet.setFitToPage(true);
- sheet.setHorizontallyCenter(true);
-
- sheet.setColumnWidth(0, 3*256);
- sheet.setColumnWidth(1, 3*256);
- sheet.setColumnWidth(2, 11*256);
- sheet.setColumnWidth(3, 14*256);
- sheet.setColumnWidth(4, 14*256);
- sheet.setColumnWidth(5, 14*256);
- sheet.setColumnWidth(6, 14*256);
-
- createNames(wb);
-
- Row titleRow = sheet.createRow(0);
- titleRow.setHeightInPoints(35);
- for (int i = 1; i <= 7; i++) {
- titleRow.createCell(i).setCellStyle(styles.get("title"));
- }
- Cell titleCell = titleRow.getCell(2);
- titleCell.setCellValue("Simple Loan Calculator");
- sheet.addMergedRegion(CellRangeAddress.valueOf("$C$1:$H$1"));
-
- Row row = sheet.createRow(2);
- Cell cell = row.createCell(4);
- cell.setCellValue("Enter values");
- cell.setCellStyle(styles.get("item_right"));
-
- row = sheet.createRow(3);
- cell = row.createCell(2);
- cell.setCellValue("Loan amount");
- cell.setCellStyle(styles.get("item_left"));
- cell = row.createCell(4);
- cell.setCellStyle(styles.get("input_$"));
- cell.setAsActiveCell();
-
- row = sheet.createRow(4);
- cell = row.createCell(2);
- cell.setCellValue("Annual interest rate");
- cell.setCellStyle(styles.get("item_left"));
- cell = row.createCell(4);
- cell.setCellStyle(styles.get("input_%"));
-
- row = sheet.createRow(5);
- cell = row.createCell(2);
- cell.setCellValue("Loan period in years");
- cell.setCellStyle(styles.get("item_left"));
- cell = row.createCell(4);
- cell.setCellStyle(styles.get("input_i"));
-
- row = sheet.createRow(6);
- cell = row.createCell(2);
- cell.setCellValue("Start date of loan");
- cell.setCellStyle(styles.get("item_left"));
- cell = row.createCell(4);
- cell.setCellStyle(styles.get("input_d"));
-
- row = sheet.createRow(8);
- cell = row.createCell(2);
- cell.setCellValue("Monthly payment");
- cell.setCellStyle(styles.get("item_left"));
- cell = row.createCell(4);
- cell.setCellFormula("IF(Values_Entered,Monthly_Payment,\"\")");
- cell.setCellStyle(styles.get("formula_$"));
-
- row = sheet.createRow(9);
- cell = row.createCell(2);
- cell.setCellValue("Number of payments");
- cell.setCellStyle(styles.get("item_left"));
- cell = row.createCell(4);
- cell.setCellFormula("IF(Values_Entered,Loan_Years*12,\"\")");
- cell.setCellStyle(styles.get("formula_i"));
-
- row = sheet.createRow(10);
- cell = row.createCell(2);
- cell.setCellValue("Total interest");
- cell.setCellStyle(styles.get("item_left"));
- cell = row.createCell(4);
- cell.setCellFormula("IF(Values_Entered,Total_Cost-Loan_Amount,\"\")");
- cell.setCellStyle(styles.get("formula_$"));
-
- row = sheet.createRow(11);
- cell = row.createCell(2);
- cell.setCellValue("Total cost of loan");
- cell.setCellStyle(styles.get("item_left"));
- cell = row.createCell(4);
- cell.setCellFormula("IF(Values_Entered,Monthly_Payment*Number_of_Payments,\"\")");
- cell.setCellStyle(styles.get("formula_$"));
-
-
- // Write the output to a file
- String file = "loan-calculator.xls";
- if(wb instanceof XSSFWorkbook) file += "x";
- FileOutputStream out = new FileOutputStream(file);
- wb.write(out);
- out.close();
- }
-
- /**
- * cell styles used for formatting calendar sheets
- */
- private static Map<String, CellStyle> createStyles(Workbook wb){
- Map<String, CellStyle> styles = new HashMap<>();
-
- CellStyle style;
- Font titleFont = wb.createFont();
- titleFont.setFontHeightInPoints((short)14);
- titleFont.setFontName("Trebuchet MS");
- style = wb.createCellStyle();
- style.setFont(titleFont);
- style.setBorderBottom(BorderStyle.DOTTED);
- style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- styles.put("title", style);
-
- Font itemFont = wb.createFont();
- itemFont.setFontHeightInPoints((short)9);
- itemFont.setFontName("Trebuchet MS");
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setFont(itemFont);
- styles.put("item_left", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(itemFont);
- styles.put("item_right", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(itemFont);
- style.setBorderRight(BorderStyle.DOTTED);
- style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderBottom(BorderStyle.DOTTED);
- style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderLeft(BorderStyle.DOTTED);
- style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderTop(BorderStyle.DOTTED);
- style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setDataFormat(wb.createDataFormat().getFormat("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(@_)"));
- styles.put("input_$", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(itemFont);
- style.setBorderRight(BorderStyle.DOTTED);
- style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderBottom(BorderStyle.DOTTED);
- style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderLeft(BorderStyle.DOTTED);
- style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderTop(BorderStyle.DOTTED);
- style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setDataFormat(wb.createDataFormat().getFormat("0.000%"));
- styles.put("input_%", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(itemFont);
- style.setBorderRight(BorderStyle.DOTTED);
- style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderBottom(BorderStyle.DOTTED);
- style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderLeft(BorderStyle.DOTTED);
- style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderTop(BorderStyle.DOTTED);
- style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setDataFormat(wb.createDataFormat().getFormat("0"));
- styles.put("input_i", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setFont(itemFont);
- style.setDataFormat(wb.createDataFormat().getFormat("m/d/yy"));
- styles.put("input_d", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(itemFont);
- style.setBorderRight(BorderStyle.DOTTED);
- style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderBottom(BorderStyle.DOTTED);
- style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderLeft(BorderStyle.DOTTED);
- style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderTop(BorderStyle.DOTTED);
- style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setDataFormat(wb.createDataFormat().getFormat("$##,##0.00"));
- style.setBorderBottom(BorderStyle.DOTTED);
- style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- styles.put("formula_$", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.RIGHT);
- style.setFont(itemFont);
- style.setBorderRight(BorderStyle.DOTTED);
- style.setRightBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderBottom(BorderStyle.DOTTED);
- style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderLeft(BorderStyle.DOTTED);
- style.setLeftBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setBorderTop(BorderStyle.DOTTED);
- style.setTopBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setDataFormat(wb.createDataFormat().getFormat("0"));
- style.setBorderBottom(BorderStyle.DOTTED);
- style.setBottomBorderColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- styles.put("formula_i", style);
-
- return styles;
- }
-
- //define named ranges for the inputs and formulas
- public static void createNames(Workbook wb){
- Name name;
-
- name = wb.createName();
- name.setNameName("Interest_Rate");
- name.setRefersToFormula("'Loan Calculator'!$E$5");
-
- name = wb.createName();
- name.setNameName("Loan_Amount");
- name.setRefersToFormula("'Loan Calculator'!$E$4");
-
- name = wb.createName();
- name.setNameName("Loan_Start");
- name.setRefersToFormula("'Loan Calculator'!$E$7");
-
- name = wb.createName();
- name.setNameName("Loan_Years");
- name.setRefersToFormula("'Loan Calculator'!$E$6");
-
- name = wb.createName();
- name.setNameName("Number_of_Payments");
- name.setRefersToFormula("'Loan Calculator'!$E$10");
-
- name = wb.createName();
- name.setNameName("Monthly_Payment");
- name.setRefersToFormula("-PMT(Interest_Rate/12,Number_of_Payments,Loan_Amount)");
-
- name = wb.createName();
- name.setNameName("Total_Cost");
- name.setRefersToFormula("'Loan Calculator'!$E$12");
-
- name = wb.createName();
- name.setNameName("Total_Interest");
- name.setRefersToFormula("'Loan Calculator'!$E$11");
-
- name = wb.createName();
- name.setNameName("Values_Entered");
- name.setRefersToFormula("IF(Loan_Amount*Interest_Rate*Loan_Years*Loan_Start>0,1,0)");
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ooxml.POIXMLTypeLoader;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.VerticalAlignment;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class SSPerformanceTest {
- private SSPerformanceTest() {}
-
- public static void main(String[] args) throws IOException {
- if (args.length < 4) {
- usage("need at least four command arguments");
- }
-
- String type = args[0];
- int rows = parseInt(args[1], "Failed to parse rows value as integer");
- int cols = parseInt(args[2], "Failed to parse cols value as integer");
- boolean saveFile = parseInt(args[3], "Failed to parse saveFile value as integer") != 0;
-
- boolean warmup = false;
- for(int arg = 4; arg < args.length;arg++) {
- if(args[arg].equals("--unsynchronized-xmlbeans")) {
- POIXMLTypeLoader.DEFAULT_XML_OPTIONS.setUnsynchronized();
- }
- if(args[arg].equals("--with-warmup-run")) {
- warmup = true;
- }
- }
-
- if(warmup) {
- System.out.println("Performing a warmup run first");
- runWithArgs(type, rows, cols, saveFile);
- }
-
- long timeStarted = System.currentTimeMillis();
- runWithArgs(type, rows, cols, saveFile);
- long timeFinished = System.currentTimeMillis();
-
- System.out.printf("Elapsed %.2f seconds for arguments %s\n", ((double)timeFinished - timeStarted) / 1000, Arrays.toString(args));
- }
-
- private static void runWithArgs(String type, int rows, int cols, boolean saveFile) throws IOException {
- try (Workbook workBook = createWorkbook(type)) {
- boolean isHType = workBook instanceof HSSFWorkbook;
- addContent(workBook, isHType, rows, cols);
-
- if (saveFile) {
- String fileName = type + "_" + rows + "_" + cols + "." + getFileSuffix(type);
- saveFile(workBook, fileName);
- }
- }
- }
-
- private static void addContent(Workbook workBook, boolean isHType, int rows, int cols) {
- Map<String, CellStyle> styles = createStyles(workBook);
-
- Sheet sheet = workBook.createSheet("Main Sheet");
-
- Cell headerCell = sheet.createRow(0).createCell(0);
- headerCell.setCellValue("Header text is spanned across multiple cells");
- headerCell.setCellStyle(styles.get("header"));
- sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$F$1"));
-
- int sheetNo = 0;
- int rowIndexInSheet = 1;
- double value = 0;
- Calendar calendar = Calendar.getInstance();
- for (int rowIndex = 0; rowIndex < rows; rowIndex++) {
- if (isHType && sheetNo != rowIndex / 0x10000) {
- sheet = workBook.createSheet("Spillover from sheet " + (++sheetNo));
- headerCell.setCellValue("Header text is spanned across multiple cells");
- headerCell.setCellStyle(styles.get("header"));
- sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$F$1"));
- rowIndexInSheet = 1;
- }
-
- Row row = sheet.createRow(rowIndexInSheet);
- for (int colIndex = 0; colIndex < cols; colIndex++) {
- value = populateCell(styles, value, calendar, rowIndex, row, colIndex);
- }
- rowIndexInSheet++;
- }
- }
-
- private static double populateCell(Map<String, CellStyle> styles, double value, Calendar calendar, int rowIndex, Row row, int colIndex) {
- Cell cell = row.createCell(colIndex);
- String address = new CellReference(cell).formatAsString();
- switch (colIndex){
- case 0:
- // column A: default number format
- cell.setCellValue(value++);
- break;
- case 1:
- // column B: #,##0
- cell.setCellValue(value++);
- cell.setCellStyle(styles.get("#,##0.00"));
- break;
- case 2:
- // column C: $#,##0.00
- cell.setCellValue(value++);
- cell.setCellStyle(styles.get("$#,##0.00"));
- break;
- case 3:
- // column D: red bold text on yellow background
- cell.setCellValue(address);
- cell.setCellStyle(styles.get("red-bold"));
- break;
- case 4:
- // column E: boolean
- // TODO booleans are shown as 1/0 instead of TRUE/FALSE
- cell.setCellValue(rowIndex % 2 == 0);
- break;
- case 5:
- // column F: date / time
- cell.setCellValue(calendar);
- cell.setCellStyle(styles.get("m/d/yyyy"));
- calendar.roll(Calendar.DAY_OF_YEAR, -1);
- break;
- case 6:
- // column F: formula
- // TODO formulas are not yet supported in SXSSF
- //cell.setCellFormula("SUM(A" + (rowIndex+1) + ":E" + (rowIndex+1)+ ")");
- //break;
- default:
- cell.setCellValue(value++);
- break;
- }
- return value;
- }
-
- private static void saveFile(Workbook workBook, String fileName) {
- try {
- FileOutputStream out = new FileOutputStream(fileName);
- workBook.write(out);
- out.close();
- } catch (IOException ioe) {
- System.err.println("Error: failed to write to file \"" + fileName + "\", reason=" + ioe.getMessage());
- }
- }
-
- static Map<String, CellStyle> createStyles(Workbook wb) {
- Map<String, CellStyle> styles = new HashMap<>();
- CellStyle style;
-
- Font headerFont = wb.createFont();
- headerFont.setFontHeightInPoints((short) 14);
- headerFont.setBold(true);
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFont(headerFont);
- style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- styles.put("header", style);
-
- Font monthFont = wb.createFont();
- monthFont.setFontHeightInPoints((short)12);
- monthFont.setColor(IndexedColors.RED.getIndex());
- monthFont.setBold(true);
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setFont(monthFont);
- styles.put("red-bold", style);
-
- String[] nfmt = {"#,##0.00", "$#,##0.00", "m/d/yyyy"};
- for(String fmt : nfmt){
- style = wb.createCellStyle();
- style.setDataFormat(wb.createDataFormat().getFormat(fmt));
- styles.put(fmt, style);
- }
-
- return styles;
- }
-
-
- static void usage(String message) {
- System.err.println(message);
- System.err.println("usage: java SSPerformanceTest HSSF|XSSF|SXSSF rows cols saveFile (0|1)? [--unsynchronized-xmlbeans] [--with-warmup-run]");
- System.exit(1);
- }
-
- static Workbook createWorkbook(String type) {
- if ("HSSF".equals(type))
- return new HSSFWorkbook();
- else if ("XSSF".equals(type))
- return new XSSFWorkbook();
- else if ("SXSSF".equals(type))
- return new SXSSFWorkbook();
-
- usage("Unknown type \"" + type + "\"");
- throw new IllegalArgumentException("Should not reach this point");
- }
-
- static String getFileSuffix(String type) {
- if ("HSSF".equals(type))
- return "xls";
- else if ("XSSF".equals(type))
- return "xlsx";
- else if ("SXSSF".equals(type))
- return "xlsx";
- return null;
- }
-
- static int parseInt(String value, String msg) {
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- usage(msg);
- }
- return 0;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-import java.io.FileOutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.PrintSetup;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.VerticalAlignment;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * A weekly timesheet created using Apache POI.
- * Usage:
- * TimesheetDemo -xls|xlsx
- *
- * @author Yegor Kozlov
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class TimesheetDemo {
- private static final String[] titles = {
- "Person", "ID", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",
- "Total\nHrs", "Overtime\nHrs", "Regular\nHrs"
- };
-
- private static final Object[][] sample_data = {
- {"Yegor Kozlov", "YK", 5.0, 8.0, 10.0, 5.0, 5.0, 7.0, 6.0},
- {"Gisella Bronzetti", "GB", 4.0, 3.0, 1.0, 3.5, null, null, 4.0},
- };
-
- private TimesheetDemo() {}
-
- public static void main(String[] args) throws Exception {
- Workbook wb;
-
- if(args.length > 0 && args[0].equals("-xls")) wb = new HSSFWorkbook();
- else wb = new XSSFWorkbook();
-
- Map<String, CellStyle> styles = createStyles(wb);
-
- Sheet sheet = wb.createSheet("Timesheet");
- PrintSetup printSetup = sheet.getPrintSetup();
- printSetup.setLandscape(true);
- sheet.setFitToPage(true);
- sheet.setHorizontallyCenter(true);
-
- //title row
- Row titleRow = sheet.createRow(0);
- titleRow.setHeightInPoints(45);
- Cell titleCell = titleRow.createCell(0);
- titleCell.setCellValue("Weekly Timesheet");
- titleCell.setCellStyle(styles.get("title"));
- sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$L$1"));
-
- //header row
- Row headerRow = sheet.createRow(1);
- headerRow.setHeightInPoints(40);
- Cell headerCell;
- for (int i = 0; i < titles.length; i++) {
- headerCell = headerRow.createCell(i);
- headerCell.setCellValue(titles[i]);
- headerCell.setCellStyle(styles.get("header"));
- }
-
- int rownum = 2;
- for (int i = 0; i < 10; i++) {
- Row row = sheet.createRow(rownum++);
- for (int j = 0; j < titles.length; j++) {
- Cell cell = row.createCell(j);
- if(j == 9){
- //the 10th cell contains sum over week days, e.g. SUM(C3:I3)
- String ref = "C" +rownum+ ":I" + rownum;
- cell.setCellFormula("SUM("+ref+")");
- cell.setCellStyle(styles.get("formula"));
- } else if (j == 11){
- cell.setCellFormula("J" +rownum+ "-K" + rownum);
- cell.setCellStyle(styles.get("formula"));
- } else {
- cell.setCellStyle(styles.get("cell"));
- }
- }
- }
-
- //row with totals below
- Row sumRow = sheet.createRow(rownum++);
- sumRow.setHeightInPoints(35);
- Cell cell;
- cell = sumRow.createCell(0);
- cell.setCellStyle(styles.get("formula"));
- cell = sumRow.createCell(1);
- cell.setCellValue("Total Hrs:");
- cell.setCellStyle(styles.get("formula"));
-
- for (int j = 2; j < 12; j++) {
- cell = sumRow.createCell(j);
- String ref = (char)('A' + j) + "3:" + (char)('A' + j) + "12";
- cell.setCellFormula("SUM(" + ref + ")");
- if(j >= 9) cell.setCellStyle(styles.get("formula_2"));
- else cell.setCellStyle(styles.get("formula"));
- }
- rownum++;
- sumRow = sheet.createRow(rownum++);
- sumRow.setHeightInPoints(25);
- cell = sumRow.createCell(0);
- cell.setCellValue("Total Regular Hours");
- cell.setCellStyle(styles.get("formula"));
- cell = sumRow.createCell(1);
- cell.setCellFormula("L13");
- cell.setCellStyle(styles.get("formula_2"));
- sumRow = sheet.createRow(rownum++);
- sumRow.setHeightInPoints(25);
- cell = sumRow.createCell(0);
- cell.setCellValue("Total Overtime Hours");
- cell.setCellStyle(styles.get("formula"));
- cell = sumRow.createCell(1);
- cell.setCellFormula("K13");
- cell.setCellStyle(styles.get("formula_2"));
-
- //set sample data
- for (int i = 0; i < sample_data.length; i++) {
- Row row = sheet.getRow(2 + i);
- for (int j = 0; j < sample_data[i].length; j++) {
- if(sample_data[i][j] == null) continue;
-
- if(sample_data[i][j] instanceof String) {
- row.getCell(j).setCellValue((String)sample_data[i][j]);
- } else {
- row.getCell(j).setCellValue((Double)sample_data[i][j]);
- }
- }
- }
-
- //finally set column widths, the width is measured in units of 1/256th of a character width
- sheet.setColumnWidth(0, 30*256); //30 characters wide
- for (int i = 2; i < 9; i++) {
- sheet.setColumnWidth(i, 6*256); //6 characters wide
- }
- sheet.setColumnWidth(10, 10*256); //10 characters wide
-
- // Write the output to a file
- String file = "timesheet.xls";
- if(wb instanceof XSSFWorkbook) file += "x";
- FileOutputStream out = new FileOutputStream(file);
- wb.write(out);
- out.close();
- }
-
- /**
- * Create a library of cell styles
- */
- private static Map<String, CellStyle> createStyles(Workbook wb){
- Map<String, CellStyle> styles = new HashMap<>();
- CellStyle style;
- Font titleFont = wb.createFont();
- titleFont.setFontHeightInPoints((short)18);
- titleFont.setBold(true);
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFont(titleFont);
- styles.put("title", style);
-
- Font monthFont = wb.createFont();
- monthFont.setFontHeightInPoints((short)11);
- monthFont.setColor(IndexedColors.WHITE.getIndex());
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setFont(monthFont);
- style.setWrapText(true);
- styles.put("header", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setWrapText(true);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(IndexedColors.BLACK.getIndex());
- style.setBorderLeft(BorderStyle.THIN);
- style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
- style.setBorderTop(BorderStyle.THIN);
- style.setTopBorderColor(IndexedColors.BLACK.getIndex());
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
- styles.put("cell", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setDataFormat(wb.createDataFormat().getFormat("0.00"));
- styles.put("formula", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setDataFormat(wb.createDataFormat().getFormat("0.00"));
- styles.put("formula_2", style);
-
- return styles;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples;
-
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.ArrayList;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.DataFormatter;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-
-/**
- * Demonstrates <em>one</em> way to convert an Excel spreadsheet into a CSV
- * file. This class makes the following assumptions;
- * <list>
- * <li>1. Where the Excel workbook contains more that one worksheet, then a single
- * CSV file will contain the data from all of the worksheets.</li>
- * <li>2. The data matrix contained in the CSV file will be square. This means that
- * the number of fields in each record of the CSV file will match the number
- * of cells in the longest row found in the Excel workbook. Any short records
- * will be 'padded' with empty fields - an empty field is represented in the
- * the CSV file in this way - ,,.</li>
- * <li>3. Empty fields will represent missing cells.</li>
- * <li>4. A record consisting of empty fields will be used to represent an empty row
- * in the Excel workbook.</li>
- * </list>
- * Therefore, if the worksheet looked like this;
- *
- * <pre>
- * ___________________________________________
- * | | | | | |
- * | A | B | C | D | E |
- * ___|_______|_______|_______|_______|_______|
- * | | | | | |
- * 1 | 1 | 2 | 3 | 4 | 5 |
- * ___|_______|_______|_______|_______|_______|
- * | | | | | |
- * 2 | | | | | |
- * ___|_______|_______|_______|_______|_______|
- * | | | | | |
- * 3 | | A | | B | |
- * ___|_______|_______|_______|_______|_______|
- * | | | | | |
- * 4 | | | | | Z |
- * ___|_______|_______|_______|_______|_______|
- * | | | | | |
- * 5 | 1,400 | | 250 | | |
- * ___|_______|_______|_______|_______|_______|
- *
- * </pre>
- *
- * Then, the resulting CSV file will contain the following lines (records);
- * <pre>
- * 1,2,3,4,5
- * ,,,,
- * ,A,,B,
- * ,,,,Z
- * "1,400",,250,,
- * </pre><p>
- * Typically, the comma is used to separate each of the fields that, together,
- * constitute a single record or line within the CSV file. This is not however
- * a hard and fast rule and so this class allows the user to determine which
- * character is used as the field separator and assumes the comma if none other
- * is specified.
- * </p><p>
- * If a field contains the separator then it will be escaped. If the file should
- * obey Excel's CSV formatting rules, then the field will be surrounded with
- * speech marks whilst if it should obey UNIX conventions, each occurrence of
- * the separator will be preceded by the backslash character.
- * </p><p>
- * If a field contains an end of line (EOL) character then it too will be
- * escaped. If the file should obey Excel's CSV formatting rules then the field
- * will again be surrounded by speech marks. On the other hand, if the file
- * should follow UNIX conventions then a single backslash will precede the
- * EOL character. There is no single applicable standard for UNIX and some
- * appications replace the CR with \r and the LF with \n but this class will
- * not do so.
- * </p><p>
- * If the field contains double quotes then that character will be escaped. It
- * seems as though UNIX does not define a standard for this whilst Excel does.
- * Should the CSV file have to obey Excel's formmating rules then the speech
- * mark character will be escaped with a second set of speech marks. Finally, an
- * enclosing set of speah marks will also surround the entire field. Thus, if
- * the following line of text appeared in a cell - "Hello" he said - it would
- * look like this when converted into a field within a CSV file - """Hello"" he
- * said".
- * </p><p>
- * Finally, it is worth noting that talk of CSV 'standards' is really slightly
- * missleading as there is no such thing. It may well be that the code in this
- * class has to be modified to produce files to suit a specific application
- * or requirement.
- * </p>
- * @author Mark B
- * @version 1.00 9th April 2010
- * 1.10 13th April 2010 - Added support for processing all Excel
- * workbooks in a folder along with the ability
- * to specify a field separator character.
- * 2.00 14th April 2010 - Added support for embedded characters; the
- * field separator, EOL and double quotes or
- * speech marks. In addition, gave the client
- * the ability to select how these are handled,
- * either obeying Excel's or UNIX formatting
- * conventions.
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public class ToCSV {
-
- private Workbook workbook;
- private ArrayList<ArrayList<String>> csvData;
- private int maxRowWidth;
- private int formattingConvention;
- private DataFormatter formatter;
- private FormulaEvaluator evaluator;
- private String separator;
-
- private static final String CSV_FILE_EXTENSION = ".csv";
- private static final String DEFAULT_SEPARATOR = ",";
-
- /**
- * Identifies that the CSV file should obey Excel's formatting conventions
- * with regard to escaping certain embedded characters - the field separator,
- * speech mark and end of line (EOL) character
- */
- public static final int EXCEL_STYLE_ESCAPING = 0;
-
- /**
- * Identifies that the CSV file should obey UNIX formatting conventions
- * with regard to escaping certain embedded characters - the field separator
- * and end of line (EOL) character
- */
- public static final int UNIX_STYLE_ESCAPING = 1;
-
- /**
- * Process the contents of a folder, convert the contents of each Excel
- * workbook into CSV format and save the resulting file to the specified
- * folder using the same name as the original workbook with the .xls or
- * .xlsx extension replaced by .csv. This method will ensure that the
- * CSV file created contains the comma field separator and that embedded
- * characters such as the field separator, the EOL and double quotes are
- * escaped in accordance with Excel's convention.
- *
- * @param strSource An instance of the String class that encapsulates the
- * name of and path to either a folder containing those Excel
- * workbook(s) or the name of and path to an individual Excel workbook
- * that is/are to be converted.
- * @param strDestination An instance of the String class encapsulating the
- * name of and path to a folder that will contain the resulting CSV
- * files.
- * @throws java.io.FileNotFoundException Thrown if any file cannot be located
- * on the filesystem during processing.
- * @throws java.io.IOException Thrown if the filesystem encounters any
- * problems during processing.
- * @throws java.lang.IllegalArgumentException Thrown if the values passed
- * to the strSource parameter refers to a file or folder that does not
- * exist or if the value passed to the strDestination paramater refers
- * to a folder that does not exist or simply does not refer to a
- * folder.
- */
- public void convertExcelToCSV(String strSource, String strDestination)
- throws FileNotFoundException, IOException,
- IllegalArgumentException {
-
- // Simply chain the call to the overloaded convertExcelToCSV(String,
- // String, String, int) method, pass the default separator and ensure
- // that certain embedded characters are escaped in accordance with
- // Excel's formatting conventions
- this.convertExcelToCSV(strSource, strDestination,
- ToCSV.DEFAULT_SEPARATOR, ToCSV.EXCEL_STYLE_ESCAPING);
- }
-
- /**
- * Process the contents of a folder, convert the contents of each Excel
- * workbook into CSV format and save the resulting file to the specified
- * folder using the same name as the original workbook with the .xls or
- * .xlsx extension replaced by .csv. This method allows the client to
- * define the field separator but will ensure that embedded characters such
- * as the field separator, the EOL and double quotes are escaped in
- * accordance with Excel's convention.
- *
- * @param strSource An instance of the String class that encapsulates the
- * name of and path to either a folder containing those Excel
- * workbook(s) or the name of and path to an individual Excel workbook
- * that is/are to be converted.
- * @param strDestination An instance of the String class encapsulating the
- * name of and path to a folder that will contain the resulting CSV
- * files.
- * @param separator An instance of the String class that encapsulates the
- * character or characters the client wishes to use as the field
- * separator.
- * @throws java.io.FileNotFoundException Thrown if any file cannot be located
- * on the filesystem during processing.
- * @throws java.io.IOException Thrown if the filesystem encounters any
- * problems during processing.
- * @throws java.lang.IllegalArgumentException Thrown if the values passed
- * to the strSource parameter refers to a file or folder that does not
- * exist or if the value passed to the strDestination paramater refers
- * to a folder that does not exist or simply does not refer to a
- * folder.
- */
- public void convertExcelToCSV(String strSource, String strDestination,
- String separator)
- throws FileNotFoundException, IOException,
- IllegalArgumentException {
-
- // Simply chain the call to the overloaded convertExcelToCSV(String,
- // String, String, int) method and ensure that certain embedded
- // characters are escaped in accordance with Excel's formatting
- // conventions
- this.convertExcelToCSV(strSource, strDestination,
- separator, ToCSV.EXCEL_STYLE_ESCAPING);
- }
-
- /**
- * Process the contents of a folder, convert the contents of each Excel
- * workbook into CSV format and save the resulting file to the specified
- * folder using the same name as the original workbook with the .xls or
- * .xlsx extension replaced by .csv
- *
- * @param strSource An instance of the String class that encapsulates the
- * name of and path to either a folder containing those Excel
- * workbook(s) or the name of and path to an individual Excel workbook
- * that is/are to be converted.
- * @param strDestination An instance of the String class encapsulating the name
- * of and path to a folder that will contain the resulting CSV files.
- * @param formattingConvention A primitive int whose value will determine
- * whether certain embedded characters should be escaped in accordance
- * with Excel's or UNIX formatting conventions. Two constants are
- * defined to support this option; ToCSV.EXCEL_STYLE_ESCAPING and
- * ToCSV.UNIX_STYLE_ESCAPING
- * @param separator An instance of the String class encapsulating the
- * characters or characters that should be used to separate items
- * on a line within the CSV file.
- * @throws java.io.FileNotFoundException Thrown if any file cannot be located
- * on the filesystem during processing.
- * @throws java.io.IOException Thrown if the filesystem encounters any
- * problems during processing.
- * @throws java.lang.IllegalArgumentException Thrown if the values passed
- * to the strSource parameter refers to a file or folder that does not
- * exist, if the value passed to the strDestination paramater refers
- * to a folder that does not exist, if the value passed to the
- * strDestination parameter does not refer to a folder or if the
- * value passed to the formattingConvention parameter is other than
- * one of the values defined by the constants ToCSV.EXCEL_STYLE_ESCAPING
- * and ToCSV.UNIX_STYLE_ESCAPING.
- */
- public void convertExcelToCSV(String strSource, String strDestination,
- String separator, int formattingConvention)
- throws FileNotFoundException, IOException,
- IllegalArgumentException {
- // Check that the source file/folder exists.
- File source = new File(strSource);
- if(!source.exists()) {
- throw new IllegalArgumentException("The source for the Excel " +
- "file(s) cannot be found at " + source);
- }
-
- // Ensure thaat the folder the user has chosen to save the CSV files
- // away into firstly exists and secondly is a folder rather than, for
- // instance, a data file.
- File destination = new File(strDestination);
- if(!destination.exists()) {
- throw new IllegalArgumentException("The destination directory " + destination + " for the " +
- "converted CSV file(s) does not exist.");
- }
- if(!destination.isDirectory()) {
- throw new IllegalArgumentException("The destination " + destination + " for the CSV " +
- "file(s) is not a directory/folder.");
- }
-
- // Ensure the value passed to the formattingConvention parameter is
- // within range.
- if(formattingConvention != ToCSV.EXCEL_STYLE_ESCAPING &&
- formattingConvention != ToCSV.UNIX_STYLE_ESCAPING) {
- throw new IllegalArgumentException("The value passed to the " +
- "formattingConvention parameter is out of range: " + formattingConvention + ", expecting one of " +
- ToCSV.EXCEL_STYLE_ESCAPING + " or " + ToCSV.UNIX_STYLE_ESCAPING);
- }
-
- // Copy the spearator character and formatting convention into local
- // variables for use in other methods.
- this.separator = separator;
- this.formattingConvention = formattingConvention;
-
- // Check to see if the sourceFolder variable holds a reference to
- // a file or a folder full of files.
- final File[] filesList;
- if(source.isDirectory()) {
- // Get a list of all of the Excel spreadsheet files (workbooks) in
- // the source folder/directory
- filesList = source.listFiles(new ExcelFilenameFilter());
- }
- else {
- // Assume that it must be a file handle - although there are other
- // options the code should perhaps check - and store the reference
- // into the filesList variable.
- filesList = new File[]{source};
- }
-
- // Step through each of the files in the source folder and for each
- // open the workbook, convert it's contents to CSV format and then
- // save the resulting file away into the folder specified by the
- // contents of the destination variable. Note that the name of the
- // csv file will be created by taking the name of the Excel file,
- // removing the extension and replacing it with .csv. Note that there
- // is one drawback with this approach; if the folder holding the files
- // contains two workbooks whose names match but one is a binary file
- // (.xls) and the other a SpreadsheetML file (.xlsx), then the names
- // for both CSV files will be identical and one CSV file will,
- // therefore, over-write the other.
- if (filesList != null) {
- for(File excelFile : filesList) {
- // Open the workbook
- this.openWorkbook(excelFile);
-
- // Convert it's contents into a CSV file
- this.convertToCSV();
-
- // Build the name of the csv folder from that of the Excel workbook.
- // Simply replace the .xls or .xlsx file extension with .csv
- String destinationFilename = excelFile.getName();
- destinationFilename = destinationFilename.substring(
- 0, destinationFilename.lastIndexOf('.')) +
- ToCSV.CSV_FILE_EXTENSION;
-
- // Save the CSV file away using the newly constricted file name
- // and to the specified directory.
- this.saveCSVFile(new File(destination, destinationFilename));
- }
- }
- }
-
- /**
- * Open an Excel workbook ready for conversion.
- *
- * @param file An instance of the File class that encapsulates a handle
- * to a valid Excel workbook. Note that the workbook can be in
- * either binary (.xls) or SpreadsheetML (.xlsx) format.
- * @throws java.io.FileNotFoundException Thrown if the file cannot be located.
- * @throws java.io.IOException Thrown if a problem occurs in the file system.
- */
- private void openWorkbook(File file) throws FileNotFoundException,
- IOException {
- System.out.println("Opening workbook [" + file.getName() + "]");
- try (FileInputStream fis = new FileInputStream(file)) {
-
- // Open the workbook and then create the FormulaEvaluator and
- // DataFormatter instances that will be needed to, respectively,
- // force evaluation of forumlae found in cells and create a
- // formatted String encapsulating the cells contents.
- this.workbook = WorkbookFactory.create(fis);
- this.evaluator = this.workbook.getCreationHelper().createFormulaEvaluator();
- this.formatter = new DataFormatter(true);
- }
- }
-
- /**
- * Called to convert the contents of the currently opened workbook into
- * a CSV file.
- */
- private void convertToCSV() {
- Sheet sheet;
- Row row;
- int lastRowNum;
- this.csvData = new ArrayList<>();
-
- System.out.println("Converting files contents to CSV format.");
-
- // Discover how many sheets there are in the workbook....
- int numSheets = this.workbook.getNumberOfSheets();
-
- // and then iterate through them.
- for(int i = 0; i < numSheets; i++) {
-
- // Get a reference to a sheet and check to see if it contains
- // any rows.
- sheet = this.workbook.getSheetAt(i);
- if(sheet.getPhysicalNumberOfRows() > 0) {
- // Note down the index number of the bottom-most row and
- // then iterate through all of the rows on the sheet starting
- // from the very first row - number 1 - even if it is missing.
- // Recover a reference to the row and then call another method
- // which will strip the data from the cells and build lines
- // for inclusion in the resylting CSV file.
- lastRowNum = sheet.getLastRowNum();
- for(int j = 0; j <= lastRowNum; j++) {
- row = sheet.getRow(j);
- this.rowToCSV(row);
- }
- }
- }
- }
-
- /**
- * Called to actually save the data recovered from the Excel workbook
- * as a CSV file.
- *
- * @param file An instance of the File class that encapsulates a handle
- * referring to the CSV file.
- * @throws java.io.FileNotFoundException Thrown if the file cannot be found.
- * @throws java.io.IOException Thrown to indicate and error occurred in the
- * underylying file system.
- */
- private void saveCSVFile(File file) throws FileNotFoundException, IOException {
- ArrayList<String> line;
- StringBuilder buffer;
- String csvLineElement;
-
- // Open a writer onto the CSV file.
- try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
-
- System.out.println("Saving the CSV file [" + file.getName() + "]");
-
- // Step through the elements of the ArrayList that was used to hold
- // all of the data recovered from the Excel workbooks' sheets, rows
- // and cells.
- for(int i = 0; i < this.csvData.size(); i++) {
- buffer = new StringBuilder();
-
- // Get an element from the ArrayList that contains the data for
- // the workbook. This element will itself be an ArrayList
- // containing Strings and each String will hold the data recovered
- // from a single cell. The for() loop is used to recover elements
- // from this 'row' ArrayList one at a time and to write the Strings
- // away to a StringBuilder thus assembling a single line for inclusion
- // in the CSV file. If a row was empty or if it was short, then
- // the ArrayList that contains it's data will also be shorter than
- // some of the others. Therefore, it is necessary to check within
- // the for loop to ensure that the ArrayList contains data to be
- // processed. If it does, then an element will be recovered and
- // appended to the StringBuilder.
- line = this.csvData.get(i);
- for(int j = 0; j < this.maxRowWidth; j++) {
- if(line.size() > j) {
- csvLineElement = line.get(j);
- if(csvLineElement != null) {
- buffer.append(this.escapeEmbeddedCharacters(
- csvLineElement));
- }
- }
- if(j < (this.maxRowWidth - 1)) {
- buffer.append(this.separator);
- }
- }
-
- // Once the line is built, write it away to the CSV file.
- bw.write(buffer.toString().trim());
-
- // Condition the inclusion of new line characters so as to
- // avoid an additional, superfluous, new line at the end of
- // the file.
- if(i < (this.csvData.size() - 1)) {
- bw.newLine();
- }
- }
- }
- }
-
- /**
- * Called to convert a row of cells into a line of data that can later be
- * output to the CSV file.
- *
- * @param row An instance of either the HSSFRow or XSSFRow classes that
- * encapsulates information about a row of cells recovered from
- * an Excel workbook.
- */
- private void rowToCSV(Row row) {
- Cell cell;
- int lastCellNum;
- ArrayList<String> csvLine = new ArrayList<>();
-
- // Check to ensure that a row was recovered from the sheet as it is
- // possible that one or more rows between other populated rows could be
- // missing - blank. If the row does contain cells then...
- if(row != null) {
-
- // Get the index for the right most cell on the row and then
- // step along the row from left to right recovering the contents
- // of each cell, converting that into a formatted String and
- // then storing the String into the csvLine ArrayList.
- lastCellNum = row.getLastCellNum();
- for(int i = 0; i <= lastCellNum; i++) {
- cell = row.getCell(i);
- if(cell == null) {
- csvLine.add("");
- }
- else {
- if(cell.getCellType() != CellType.FORMULA) {
- csvLine.add(this.formatter.formatCellValue(cell));
- }
- else {
- csvLine.add(this.formatter.formatCellValue(cell, this.evaluator));
- }
- }
- }
- // Make a note of the index number of the right most cell. This value
- // will later be used to ensure that the matrix of data in the CSV file
- // is square.
- if(lastCellNum > this.maxRowWidth) {
- this.maxRowWidth = lastCellNum;
- }
- }
- this.csvData.add(csvLine);
- }
-
- /**
- * Checks to see whether the field - which consists of the formatted
- * contents of an Excel worksheet cell encapsulated within a String - contains
- * any embedded characters that must be escaped. The method is able to
- * comply with either Excel's or UNIX formatting conventions in the
- * following manner;
- *
- * With regard to UNIX conventions, if the field contains any embedded
- * field separator or EOL characters they will each be escaped by prefixing
- * a leading backspace character. These are the only changes that have yet
- * emerged following some research as being required.
- *
- * Excel has other embedded character escaping requirements, some that emerged
- * from empirical testing, other through research. Firstly, with regards to
- * any embedded speech marks ("), each occurrence should be escaped with
- * another speech mark and the whole field then surrounded with speech marks.
- * Thus if a field holds <em>"Hello" he said</em> then it should be modified
- * to appear as <em>"""Hello"" he said"</em>. Furthermore, if the field
- * contains either embedded separator or EOL characters, it should also
- * be surrounded with speech marks. As a result <em>1,400</em> would become
- * <em>"1,400"</em> assuming that the comma is the required field separator.
- * This has one consequence in, if a field contains embedded speech marks
- * and embedded separator characters, checks for both are not required as the
- * additional set of speech marks that should be placed around ay field
- * containing embedded speech marks will also account for the embedded
- * separator.
- *
- * It is worth making one further note with regard to embedded EOL
- * characters. If the data in a worksheet is exported as a CSV file using
- * Excel itself, then the field will be surounded with speech marks. If the
- * resulting CSV file is then re-imports into another worksheet, the EOL
- * character will result in the original simgle field occupying more than
- * one cell. This same 'feature' is replicated in this classes behaviour.
- *
- * @param field An instance of the String class encapsulating the formatted
- * contents of a cell on an Excel worksheet.
- * @return A String that encapsulates the formatted contents of that
- * Excel worksheet cell but with any embedded separator, EOL or
- * speech mark characters correctly escaped.
- */
- private String escapeEmbeddedCharacters(String field) {
- StringBuilder buffer;
-
- // If the fields contents should be formatted to confrom with Excel's
- // convention....
- if(this.formattingConvention == ToCSV.EXCEL_STYLE_ESCAPING) {
-
- // Firstly, check if there are any speech marks (") in the field;
- // each occurrence must be escaped with another set of spech marks
- // and then the entire field should be enclosed within another
- // set of speech marks. Thus, "Yes" he said would become
- // """Yes"" he said"
- if(field.contains("\"")) {
- buffer = new StringBuilder(field.replaceAll("\"", "\\\"\\\""));
- buffer.insert(0, "\"");
- buffer.append("\"");
- }
- else {
- // If the field contains either embedded separator or EOL
- // characters, then escape the whole field by surrounding it
- // with speech marks.
- buffer = new StringBuilder(field);
- if((buffer.indexOf(this.separator)) > -1 ||
- (buffer.indexOf("\n")) > -1) {
- buffer.insert(0, "\"");
- buffer.append("\"");
- }
- }
- return(buffer.toString().trim());
- }
- // The only other formatting convention this class obeys is the UNIX one
- // where any occurrence of the field separator or EOL character will
- // be escaped by preceding it with a backslash.
- else {
- if(field.contains(this.separator)) {
- field = field.replaceAll(this.separator, ("\\\\" + this.separator));
- }
- if(field.contains("\n")) {
- field = field.replaceAll("\n", "\\\\\n");
- }
- return(field);
- }
- }
-
- /**
- * The main() method contains code that demonstrates how to use the class.
- *
- * @param args An array containing zero, one or more elements all of type
- * String. Each element will encapsulate an argument specified by the
- * user when running the program from the command prompt.
- */
- public static void main(String[] args) {
- // Check the number of arguments passed to the main method. There
- // must be two, three or four; the name of and path to either the folder
- // containing the Excel files or an individual Excel workbook that is/are
- // to be converted, the name of and path to the folder to which the CSV
- // files should be written, - optionally - the separator character
- // that should be used to separate individual items (fields) on the
- // lines (records) of the CSV file and - again optionally - an integer
- // that idicates whether the CSV file ought to obey Excel's or UNIX
- // convnetions with regard to formatting fields that contain embedded
- // separator, Speech mark or EOL character(s).
- //
- // Note that the names of the CSV files will be derived from those
- // of the Excel file(s). Put simply the .xls or .xlsx extension will be
- // replaced with .csv. Therefore, if the source folder contains files
- // with matching names but different extensions - Test.xls and Test.xlsx
- // for example - then the CSV file generated from one will overwrite
- // that generated from the other.
- ToCSV converter;
- boolean converted = true;
- long startTime = System.currentTimeMillis();
- try {
- converter = new ToCSV();
- if(args.length == 2) {
- // Just the Source File/Folder and Destination Folder were
- // passed to the main method.
- converter.convertExcelToCSV(args[0], args[1]);
- }
- else if(args.length == 3) {
- // The Source File/Folder, Destination Folder and Separator
- // were passed to the main method.
- converter.convertExcelToCSV(args[0], args[1], args[2]);
- }
- else if(args.length == 4) {
- // The Source File/Folder, Destination Folder, Separator and
- // Formatting Convnetion were passed to the main method.
- converter.convertExcelToCSV(args[0], args[1],
- args[2], Integer.parseInt(args[3]));
- }
- else {
- // None or more than four parameters were passed so display
- //a Usage message.
- System.out.println("Usage: java ToCSV [Source File/Folder] " +
- "[Destination Folder] [Separator] [Formatting Convention]\n" +
- "\tSource File/Folder\tThis argument should contain the name of and\n" +
- "\t\t\t\tpath to either a single Excel workbook or a\n" +
- "\t\t\t\tfolder containing one or more Excel workbooks.\n" +
- "\tDestination Folder\tThe name of and path to the folder that the\n" +
- "\t\t\t\tCSV files should be written out into. The\n" +
- "\t\t\t\tfolder must exist before running the ToCSV\n" +
- "\t\t\t\tcode as it will not check for or create it.\n" +
- "\tSeparator\t\tOptional. The character or characters that\n" +
- "\t\t\t\tshould be used to separate fields in the CSV\n" +
- "\t\t\t\trecord. If no value is passed then the comma\n" +
- "\t\t\t\twill be assumed.\n" +
- "\tFormatting Convention\tOptional. This argument can take one of two\n" +
- "\t\t\t\tvalues. Passing 0 (zero) will result in a CSV\n" +
- "\t\t\t\tfile that obeys Excel's formatting conventions\n" +
- "\t\t\t\twhilst passing 1 (one) will result in a file\n" +
- "\t\t\t\tthat obeys UNIX formatting conventions. If no\n" +
- "\t\t\t\tvalue is passed, then the CSV file produced\n" +
- "\t\t\t\twill obey Excel's formatting conventions.");
- converted = false;
- }
- }
- // It is not wise to have such a wide catch clause - Exception is very
- // close to being at the top of the inheritance hierarchy - though it
- // will suffice for this example as it is really not possible to recover
- // easilly from an exceptional set of circumstances at this point in the
- // program. It should however, ideally be replaced with one or more
- // catch clauses optimised to handle more specific problems.
- catch(Exception ex) {
- System.out.println("Caught an: " + ex.getClass().getName());
- System.out.println("Message: " + ex.getMessage());
- System.out.println("Stacktrace follows:.....");
- ex.printStackTrace(System.out);
- converted = false;
- }
-
- if (converted) {
- System.out.println("Conversion took " +
- ((System.currentTimeMillis() - startTime)/1000) + " seconds");
- }
- }
-
- /**
- * An instance of this class can be used to control the files returned
- * be a call to the listFiles() method when made on an instance of the
- * File class and that object refers to a folder/directory
- */
- static class ExcelFilenameFilter implements FilenameFilter {
-
- /**
- * Determine those files that will be returned by a call to the
- * listFiles() method. In this case, the name of the file must end with
- * either of the following two extension; '.xls' or '.xlsx'. For the
- * future, it is very possible to parameterise this and allow the
- * containing class to pass, for example, an array of Strings to this
- * class on instantiation. Each element in that array could encapsulate
- * a valid file extension - '.xls', '.xlsx', '.xlt', '.xlst', etc. These
- * could then be used to control which files were returned by the call
- * to the listFiles() method.
- *
- * @param file An instance of the File class that encapsulates a handle
- * referring to the folder/directory that contains the file.
- * @param name An instance of the String class that encapsulates the
- * name of the file.
- * @return A boolean value that indicates whether the file should be
- * included in the array retirned by the call to the listFiles()
- * method. In this case true will be returned if the name of the
- * file ends with either '.xls' or '.xlsx' and false will be
- * returned in all other instances.
- */
- @Override
- public boolean accept(File file, String name) {
- return(name.endsWith(".xls") || name.endsWith(".xlsx"));
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.formula;
-
-import org.apache.poi.ss.formula.OperationEvaluationContext ;
-import org.apache.poi.ss.formula.eval.ErrorEval ;
-import org.apache.poi.ss.formula.eval.EvaluationException ;
-import org.apache.poi.ss.formula.eval.NumberEval ;
-import org.apache.poi.ss.formula.eval.OperandResolver ;
-import org.apache.poi.ss.formula.eval.ValueEval ;
-import org.apache.poi.ss.formula.functions.FreeRefFunction ;
-
-/**
- * A simple user-defined function to calculate principal and interest.
- *
- * @author Jon Svede ( jon [at] loquatic [dot] com )
- * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
- *
- */
-public class CalculateMortgage implements FreeRefFunction {
-
- @Override
- public ValueEval evaluate( ValueEval[] args, OperationEvaluationContext ec ) {
-
- // verify that we have enough data
- if (args.length != 3) {
- return ErrorEval.VALUE_INVALID;
- }
-
- // declare doubles for values
- double principal, rate, years, result;
- try {
- // extract values as ValueEval
- ValueEval v1 = OperandResolver.getSingleValue( args[0],
- ec.getRowIndex(),
- ec.getColumnIndex() ) ;
- ValueEval v2 = OperandResolver.getSingleValue( args[1],
- ec.getRowIndex(),
- ec.getColumnIndex() ) ;
- ValueEval v3 = OperandResolver.getSingleValue( args[2],
- ec.getRowIndex(),
- ec.getColumnIndex() ) ;
-
- // get data as doubles
- principal = OperandResolver.coerceValueToDouble( v1 ) ;
- rate = OperandResolver.coerceValueToDouble( v2 ) ;
- years = OperandResolver.coerceValueToDouble( v3 ) ;
-
- result = calculateMortgagePayment( principal, rate, years ) ;
- System.out.println( "Result = " + result ) ;
-
- checkValue(result);
-
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
-
- return new NumberEval( result ) ;
- }
-
- public double calculateMortgagePayment( double p, double r, double y ) {
- double i = r / 12 ;
- double n = y * 12 ;
-
- return p * (( i * Math.pow((1 + i),n ) ) / ( Math.pow((1 + i),n) - 1));
- }
- /**
- * Excel does not support infinities and NaNs, rather, it gives a #NUM! error in these cases
- *
- * @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</> or <tt>Infinity</tt>
- */
- private void checkValue(double result) throws EvaluationException {
- if (Double.isNaN(result) || Double.isInfinite(result)) {
- throw new EvaluationException(ErrorEval.NUM_ERROR);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.formula;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.apache.poi.ss.formula.eval.NotImplementedException;
-import org.apache.poi.ss.formula.eval.NotImplementedFunctionException;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.ss.util.CellReference;
-
-/**
- * Attempts to re-evaluate all the formulas in the workbook, and
- * reports what (if any) formula functions used are not (currently)
- * supported by Apache POI.
- *
- * <p>This provides examples of how to evaluate formulas in excel
- * files using Apache POI, along with how to handle errors whilst
- * doing so.
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public class CheckFunctionsSupported {
- public static void main(String[] args) throws Exception {
- if (args.length < 1) {
- System.err.println("Use:");
- System.err.println(" CheckFunctionsSupported <filename>");
- return;
- }
-
- Workbook wb = WorkbookFactory.create(new File(args[0]));
- CheckFunctionsSupported check = new CheckFunctionsSupported(wb);
-
- // Fetch all the problems
- List<FormulaEvaluationProblems> problems = new ArrayList<>();
- for (int sn=0; sn<wb.getNumberOfSheets(); sn++) {
- problems.add(check.getEvaluationProblems(sn));
- }
-
- // Produce an overall summary
- Set<String> unsupportedFunctions = new TreeSet<>();
- for (FormulaEvaluationProblems p : problems) {
- unsupportedFunctions.addAll(p.unsupportedFunctions);
- }
- if (unsupportedFunctions.isEmpty()) {
- System.out.println("There are no unsupported formula functions used");
- } else {
- System.out.println("Unsupported formula functions:");
- for (String function : unsupportedFunctions) {
- System.out.println(" " + function);
- }
- System.out.println("Total unsupported functions = " + unsupportedFunctions.size());
- }
-
- // Report sheet by sheet
- for (int sn=0; sn<wb.getNumberOfSheets(); sn++) {
- String sheetName = wb.getSheetName(sn);
- FormulaEvaluationProblems probs = problems.get(sn);
-
- System.out.println();
- System.out.println("Sheet = " + sheetName);
-
- if (probs.unevaluatableCells.isEmpty()) {
- System.out.println(" All cells evaluated without error");
- } else {
- for (CellReference cr : probs.unevaluatableCells.keySet()) {
- System.out.println(" " + cr.formatAsString() + " - " +
- probs.unevaluatableCells.get(cr));
- }
- }
- }
- }
-
- private final Workbook workbook;
- private final FormulaEvaluator evaluator;
- public CheckFunctionsSupported(Workbook workbook) {
- this.workbook = workbook;
- this.evaluator = workbook.getCreationHelper().createFormulaEvaluator();
- }
-
- public Set<String> getUnsupportedFunctions(String sheetName) {
- return getUnsupportedFunctions(workbook.getSheet(sheetName));
- }
- public Set<String> getUnsupportedFunctions(int sheetIndex) {
- return getUnsupportedFunctions(workbook.getSheetAt(sheetIndex));
- }
- public Set<String> getUnsupportedFunctions(Sheet sheet) {
- FormulaEvaluationProblems problems = getEvaluationProblems(sheet);
- return problems.unsupportedFunctions;
- }
-
- public FormulaEvaluationProblems getEvaluationProblems(String sheetName) {
- return getEvaluationProblems(workbook.getSheet(sheetName));
- }
- public FormulaEvaluationProblems getEvaluationProblems(int sheetIndex) {
- return getEvaluationProblems(workbook.getSheetAt(sheetIndex));
- }
- public FormulaEvaluationProblems getEvaluationProblems(Sheet sheet) {
- Set<String> unsupportedFunctions = new HashSet<>();
- Map<CellReference,Exception> unevaluatableCells = new HashMap<>();
-
- for (Row r : sheet) {
- for (Cell c : r) {
- try {
- evaluator.evaluate(c);
- } catch (Exception e) {
- if (e instanceof NotImplementedException && e.getCause() != null) {
- // Has been wrapped with cell details, but we know those
- e = (Exception)e.getCause();
- }
-
- if (e instanceof NotImplementedFunctionException) {
- NotImplementedFunctionException nie = (NotImplementedFunctionException)e;
- unsupportedFunctions.add(nie.getFunctionName());
- }
- unevaluatableCells.put(new CellReference(c), e);
- }
- }
- }
-
- return new FormulaEvaluationProblems(unsupportedFunctions, unevaluatableCells);
- }
-
- public static class FormulaEvaluationProblems {
- /** Which used functions are unsupported by POI at this time */
- private final Set<String> unsupportedFunctions;
- /** Which cells had unevaluatable formulas, and why? */
- private final Map<CellReference,Exception> unevaluatableCells;
-
- protected FormulaEvaluationProblems(Set<String> unsupportedFunctions,
- Map<CellReference, Exception> unevaluatableCells) {
- this.unsupportedFunctions = Collections.unmodifiableSet(unsupportedFunctions);
- this.unevaluatableCells = Collections.unmodifiableMap(unevaluatableCells);
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.examples.formula;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.poi.ss.formula.OperationEvaluationContext;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.ss.formula.eval.ValueEval;
-import org.apache.poi.ss.formula.functions.FreeRefFunction;
-import org.apache.poi.ss.formula.udf.UDFFinder;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates how to use functions provided by third-party add-ins, e.g. Bloomberg Excel Add-in.
- *
- * There can be situations when you are not interested in formula evaluation,
- * you just need to set the formula and the workbook will be evaluation by the client.
- */
-public class SettingExternalFunction {
-
- /**
- * wrap external functions in a plugin
- */
- public static class BloombergAddIn implements UDFFinder {
- private final Map<String, FreeRefFunction> _functionsByName;
-
- public BloombergAddIn() {
- // dummy function that returns NA
- // don't care about the implementation, we are not interested in evaluation
- // and this method will never be called
- FreeRefFunction NA = new FreeRefFunction() {
- @Override
- public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
- return ErrorEval.NA;
- }
- };
- _functionsByName = new HashMap<>();
- _functionsByName.put("BDP", NA);
- _functionsByName.put("BDH", NA);
- _functionsByName.put("BDS", NA);
- }
-
- @Override
- public FreeRefFunction findFunction(String name) {
- return _functionsByName.get(name.toUpperCase(Locale.ROOT));
- }
-
- }
-
- public static void main( String[] args ) throws IOException {
-
- try (Workbook wb = new XSSFWorkbook()) { // or new HSSFWorkbook()
-
- // register the add-in
- wb.addToolPack(new BloombergAddIn());
-
- Sheet sheet = wb.createSheet();
- Row row = sheet.createRow(0);
- row.createCell(0).setCellFormula("BDP(\"GOOG Equity\",\"CHG_PCT_YTD\")/100");
- row.createCell(1).setCellFormula("BDH(\"goog us equity\",\"EBIT\",\"1/1/2005\",\"12/31/2009\",\"per=cy\",\"curr=USD\") ");
- row.createCell(2).setCellFormula("BDS(\"goog us equity\",\"top_20_holders_public_filings\") ");
-
- try (FileOutputStream out = new FileOutputStream("bloomberg-demo.xlsx")) {
- wb.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.formula;
-
-import java.io.File;
-
-import org.apache.poi.ss.formula.functions.FreeRefFunction;
-import org.apache.poi.ss.formula.udf.DefaultUDFFinder;
-import org.apache.poi.ss.formula.udf.UDFFinder;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.ss.util.CellReference;
-
-
-/**
- * An example class of how to invoke a User Defined Function for a given
- * XLS instance using POI's UDFFinder implementation.
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class UserDefinedFunctionExample {
-
- private UserDefinedFunctionExample() {}
-
- public static void main(String[] args ) throws Exception {
-
- if( args.length != 2 ) {
- // e.g. src/examples/src/org/apache/poi/ss/examples/formula/mortgage-calculation.xls Sheet1!B4
- System.out.println( "usage: UserDefinedFunctionExample fileName cellId" ) ;
- return;
- }
-
- System.out.println( "fileName: " + args[0] ) ;
- System.out.println( "cell: " + args[1] ) ;
-
- File workbookFile = new File( args[0] ) ;
-
- try (Workbook workbook = WorkbookFactory.create(workbookFile, null, true)) {
- String[] functionNames = {"calculatePayment"};
- FreeRefFunction[] functionImpls = {new CalculateMortgage()};
-
- UDFFinder udfToolpack = new DefaultUDFFinder(functionNames, functionImpls);
-
- // register the user-defined function in the workbook
- workbook.addToolPack(udfToolpack);
-
- FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
-
- CellReference cr = new CellReference(args[1]);
- String sheetName = cr.getSheetName();
- Sheet sheet = workbook.getSheet(sheetName);
- int rowIdx = cr.getRow();
- int colIdx = cr.getCol();
- Row row = sheet.getRow(rowIdx);
- Cell cell = row.getCell(colIdx);
-
- CellValue value = evaluator.evaluate(cell);
-
- System.out.println("returns value: " + value);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.html;
-
-import java.util.Formatter;
-
-import org.apache.poi.hssf.usermodel.HSSFCellStyle;
-import org.apache.poi.hssf.usermodel.HSSFPalette;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.HSSFColor;
-import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
-import org.apache.poi.ss.usermodel.CellStyle;
-
-/**
- * Implementation of {@link HtmlHelper} for HSSF files.
- */
-public class HSSFHtmlHelper implements HtmlHelper {
- private final HSSFWorkbook wb;
- private final HSSFPalette colors;
-
- private static final HSSFColor HSSF_AUTO = HSSFColorPredefined.AUTOMATIC.getColor();
-
- public HSSFHtmlHelper(HSSFWorkbook wb) {
- this.wb = wb;
- // If there is no custom palette, then this creates a new one that is
- // a copy of the default
- colors = wb.getCustomPalette();
- }
-
- @Override
- public void colorStyles(CellStyle style, Formatter out) {
- HSSFCellStyle cs = (HSSFCellStyle) style;
- out.format(" /* fill pattern = %d */%n", cs.getFillPattern().getCode());
- styleColor(out, "background-color", cs.getFillForegroundColor());
- styleColor(out, "color", cs.getFont(wb).getColor());
- styleColor(out, "border-left-color", cs.getLeftBorderColor());
- styleColor(out, "border-right-color", cs.getRightBorderColor());
- styleColor(out, "border-top-color", cs.getTopBorderColor());
- styleColor(out, "border-bottom-color", cs.getBottomBorderColor());
- }
-
- private void styleColor(Formatter out, String attr, short index) {
- HSSFColor color = colors.getColor(index);
- if (index == HSSF_AUTO.getIndex() || color == null) {
- out.format(" /* %s: index = %d */%n", attr, index);
- } else {
- short[] rgb = color.getTriplet();
- out.format(" %s: #%02x%02x%02x; /* index = %d */%n", attr, rgb[0],
- rgb[1], rgb[2], index);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.html;
-
-import org.apache.poi.ss.usermodel.CellStyle;
-
-import java.util.Formatter;
-
-/**
- * This interface is used where code wants to be independent of the workbook
- * formats. If you are writing such code, you can add a method to this
- * interface, and then implement it for both HSSF and XSSF workbooks, letting
- * the driving code stay independent of format.
- *
- * @author Ken Arnold, Industrious Media LLC
- */
-public interface HtmlHelper {
- /**
- * Outputs the appropriate CSS style for the given cell style.
- *
- * @param style The cell style.
- * @param out The place to write the output.
- */
- void colorStyles(CellStyle style, Formatter out);
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.html;
-
-import java.io.BufferedReader;
-import java.io.Closeable;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.format.CellFormat;
-import org.apache.poi.ss.format.CellFormatResult;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.VerticalAlignment;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * This example shows how to display a spreadsheet in HTML using the classes for
- * spreadsheet display.
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class ToHtml {
- private final Workbook wb;
- private final Appendable output;
- private boolean completeHTML;
- private Formatter out;
- private boolean gotBounds;
- private int firstColumn;
- private int endColumn;
- private HtmlHelper helper;
-
- private static final String DEFAULTS_CLASS = "excelDefaults";
- private static final String COL_HEAD_CLASS = "colHeader";
- private static final String ROW_HEAD_CLASS = "rowHeader";
-
- private static final Map<HorizontalAlignment, String> HALIGN = mapFor(
- HorizontalAlignment.LEFT, "left",
- HorizontalAlignment.CENTER, "center",
- HorizontalAlignment.RIGHT, "right",
- HorizontalAlignment.FILL, "left",
- HorizontalAlignment.JUSTIFY, "left",
- HorizontalAlignment.CENTER_SELECTION, "center");
-
- private static final Map<VerticalAlignment, String> VALIGN = mapFor(
- VerticalAlignment.BOTTOM, "bottom",
- VerticalAlignment.CENTER, "middle",
- VerticalAlignment.TOP, "top");
-
- private static final Map<BorderStyle, String> BORDER = mapFor(
- BorderStyle.DASH_DOT, "dashed 1pt",
- BorderStyle.DASH_DOT_DOT, "dashed 1pt",
- BorderStyle.DASHED, "dashed 1pt",
- BorderStyle.DOTTED, "dotted 1pt",
- BorderStyle.DOUBLE, "double 3pt",
- BorderStyle.HAIR, "solid 1px",
- BorderStyle.MEDIUM, "solid 2pt",
- BorderStyle.MEDIUM_DASH_DOT, "dashed 2pt",
- BorderStyle.MEDIUM_DASH_DOT_DOT, "dashed 2pt",
- BorderStyle.MEDIUM_DASHED, "dashed 2pt",
- BorderStyle.NONE, "none",
- BorderStyle.SLANTED_DASH_DOT, "dashed 2pt",
- BorderStyle.THICK, "solid 3pt",
- BorderStyle.THIN, "dashed 1pt");
-
- private static final int IDX_TABLE_WIDTH = -2;
- private static final int IDX_HEADER_COL_WIDTH = -1;
-
-
- @SuppressWarnings({"unchecked"})
- private static <K, V> Map<K, V> mapFor(Object... mapping) {
- Map<K, V> map = new HashMap<>();
- for (int i = 0; i < mapping.length; i += 2) {
- map.put((K) mapping[i], (V) mapping[i + 1]);
- }
- return map;
- }
-
- /**
- * Creates a new examples to HTML for the given workbook.
- *
- * @param wb The workbook.
- * @param output Where the HTML output will be written.
- *
- * @return An object for converting the workbook to HTML.
- */
- public static ToHtml create(Workbook wb, Appendable output) {
- return new ToHtml(wb, output);
- }
-
- /**
- * Creates a new examples to HTML for the given workbook. If the path ends
- * with "<tt>.xlsx</tt>" an {@link XSSFWorkbook} will be used; otherwise
- * this will use an {@link HSSFWorkbook}.
- *
- * @param path The file that has the workbook.
- * @param output Where the HTML output will be written.
- *
- * @return An object for converting the workbook to HTML.
- */
- public static ToHtml create(String path, Appendable output)
- throws IOException {
- return create(new FileInputStream(path), output);
- }
-
- /**
- * Creates a new examples to HTML for the given workbook. This attempts to
- * detect whether the input is XML (so it should create an {@link
- * XSSFWorkbook} or not (so it should create an {@link HSSFWorkbook}).
- *
- * @param in The input stream that has the workbook.
- * @param output Where the HTML output will be written.
- *
- * @return An object for converting the workbook to HTML.
- */
- public static ToHtml create(InputStream in, Appendable output)
- throws IOException {
- Workbook wb = WorkbookFactory.create(in);
- return create(wb, output);
- }
-
- private ToHtml(Workbook wb, Appendable output) {
- if (wb == null) {
- throw new NullPointerException("wb");
- }
- if (output == null) {
- throw new NullPointerException("output");
- }
- this.wb = wb;
- this.output = output;
- setupColorMap();
- }
-
- private void setupColorMap() {
- if (wb instanceof HSSFWorkbook) {
- helper = new HSSFHtmlHelper((HSSFWorkbook) wb);
- } else if (wb instanceof XSSFWorkbook) {
- helper = new XSSFHtmlHelper();
- } else {
- throw new IllegalArgumentException(
- "unknown workbook type: " + wb.getClass().getSimpleName());
- }
- }
-
- /**
- * Run this class as a program
- *
- * @param args The command line arguments.
- *
- * @throws Exception Exception we don't recover from.
- */
- public static void main(String[] args) throws Exception {
- if(args.length < 2){
- System.err.println("usage: ToHtml inputWorkbook outputHtmlFile");
- return;
- }
-
- try (
- FileWriter fw = new FileWriter(args[1]);
- PrintWriter pw = new PrintWriter(fw)
- ) {
- ToHtml toHtml = create(args[0], pw);
- toHtml.setCompleteHTML(true);
- toHtml.printPage();
- }
- }
-
- public void setCompleteHTML(boolean completeHTML) {
- this.completeHTML = completeHTML;
- }
-
- public void printPage() throws IOException {
- try {
- ensureOut();
- if (completeHTML) {
- out.format(
- "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>%n");
- out.format("<html>%n");
- out.format("<head>%n");
- out.format("</head>%n");
- out.format("<body>%n");
- }
-
- print();
-
- if (completeHTML) {
- out.format("</body>%n");
- out.format("</html>%n");
- }
- } finally {
- IOUtils.closeQuietly(out);
- if (output instanceof Closeable) {
- IOUtils.closeQuietly((Closeable) output);
- }
- }
- }
-
- public void print() {
- printInlineStyle();
- printSheets();
- }
-
- private void printInlineStyle() {
- //out.format("<link href=\"excelStyle.css\" rel=\"stylesheet\" type=\"text/css\">%n");
- out.format("<style type=\"text/css\">%n");
- printStyles();
- out.format("</style>%n");
- }
-
- private void ensureOut() {
- if (out == null) {
- out = new Formatter(output);
- }
- }
-
- public void printStyles() {
- ensureOut();
-
- // First, copy the base css
- try (BufferedReader in = new BufferedReader(new InputStreamReader(
- getClass().getResourceAsStream("excelStyle.css")))){
- String line;
- while ((line = in.readLine()) != null) {
- out.format("%s%n", line);
- }
- } catch (IOException e) {
- throw new IllegalStateException("Reading standard css", e);
- }
-
- // now add css for each used style
- Set<CellStyle> seen = new HashSet<>();
- for (int i = 0; i < wb.getNumberOfSheets(); i++) {
- Sheet sheet = wb.getSheetAt(i);
- Iterator<Row> rows = sheet.rowIterator();
- while (rows.hasNext()) {
- Row row = rows.next();
- for (Cell cell : row) {
- CellStyle style = cell.getCellStyle();
- if (!seen.contains(style)) {
- printStyle(style);
- seen.add(style);
- }
- }
- }
- }
- }
-
- private void printStyle(CellStyle style) {
- out.format(".%s .%s {%n", DEFAULTS_CLASS, styleName(style));
- styleContents(style);
- out.format("}%n");
- }
-
- private void styleContents(CellStyle style) {
- styleOut("text-align", style.getAlignment(), HALIGN);
- styleOut("vertical-align", style.getVerticalAlignment(), VALIGN);
- fontStyle(style);
- borderStyles(style);
- helper.colorStyles(style, out);
- }
-
- private void borderStyles(CellStyle style) {
- styleOut("border-left", style.getBorderLeft(), BORDER);
- styleOut("border-right", style.getBorderRight(), BORDER);
- styleOut("border-top", style.getBorderTop(), BORDER);
- styleOut("border-bottom", style.getBorderBottom(), BORDER);
- }
-
- private void fontStyle(CellStyle style) {
- Font font = wb.getFontAt(style.getFontIndexAsInt());
-
- if (font.getBold()) {
- out.format(" font-weight: bold;%n");
- }
- if (font.getItalic()) {
- out.format(" font-style: italic;%n");
- }
-
- int fontheight = font.getFontHeightInPoints();
- if (fontheight == 9) {
- //fix for stupid ol Windows
- fontheight = 10;
- }
- out.format(" font-size: %dpt;%n", fontheight);
-
- // Font color is handled with the other colors
- }
-
- private String styleName(CellStyle style) {
- if (style == null) {
- style = wb.getCellStyleAt((short) 0);
- }
- StringBuilder sb = new StringBuilder();
- try (Formatter fmt = new Formatter(sb)) {
- fmt.format("style_%02x", style.getIndex());
- return fmt.toString();
- }
- }
-
- private <K> void styleOut(String attr, K key, Map<K, String> mapping) {
- String value = mapping.get(key);
- if (value != null) {
- out.format(" %s: %s;%n", attr, value);
- }
- }
-
- private static CellType ultimateCellType(Cell c) {
- CellType type = c.getCellType();
- if (type == CellType.FORMULA) {
- type = c.getCachedFormulaResultType();
- }
- return type;
- }
-
- private void printSheets() {
- ensureOut();
- Sheet sheet = wb.getSheetAt(0);
- printSheet(sheet);
- }
-
- public void printSheet(Sheet sheet) {
- ensureOut();
- Map<Integer, Integer> widths = computeWidths(sheet);
- int tableWidth = widths.get(IDX_TABLE_WIDTH);
- out.format("<table class=%s style=\"width:%dpx;\">%n", DEFAULTS_CLASS, tableWidth);
- printCols(widths);
- printSheetContent(sheet);
- out.format("</table>%n");
- }
-
- /**
- * computes the column widths, defined by the sheet.
- *
- * @param sheet The sheet for which to compute widths
- * @return Map with key: column index; value: column width in pixels
- * <br>special keys:
- * <br>{@link #IDX_HEADER_COL_WIDTH} - width of the header column
- * <br>{@link #IDX_TABLE_WIDTH} - width of the entire table
- */
- private Map<Integer, Integer> computeWidths(Sheet sheet) {
- Map<Integer, Integer> ret = new TreeMap<>();
- int tableWidth = 0;
-
- ensureColumnBounds(sheet);
-
- // compute width of the header column
- int lastRowNum = sheet.getLastRowNum();
- int headerCharCount = String.valueOf(lastRowNum).length();
- int headerColWidth = widthToPixels((headerCharCount + 1) * 256.0);
- ret.put(IDX_HEADER_COL_WIDTH, headerColWidth);
- tableWidth += headerColWidth;
-
- for (int i = firstColumn; i < endColumn; i++) {
- int colWidth = widthToPixels(sheet.getColumnWidth(i));
- ret.put(i, colWidth);
- tableWidth += colWidth;
- }
-
- ret.put(IDX_TABLE_WIDTH, tableWidth);
- return ret ;
- }
-
- /**
- * Probably platform-specific, but appears to be a close approximation on some systems
- * @param widthUnits POI's native width unit (twips)
- * @return the approximate number of pixels for a typical display
- */
- protected int widthToPixels(final double widthUnits) {
- return Math.toIntExact(Math.round(widthUnits * 9 / 256));
- }
-
- private void printCols(Map<Integer, Integer> widths) {
- int headerColWidth = widths.get(IDX_HEADER_COL_WIDTH);
- out.format("<col style=\"width:%dpx\"/>%n", headerColWidth);
- for (int i = firstColumn; i < endColumn; i++) {
- int colWidth = widths.get(i);
- out.format("<col style=\"width:%dpx;\"/>%n", colWidth);
- }
- }
-
- private void ensureColumnBounds(Sheet sheet) {
- if (gotBounds) {
- return;
- }
-
- Iterator<Row> iter = sheet.rowIterator();
- firstColumn = (iter.hasNext() ? Integer.MAX_VALUE : 0);
- endColumn = 0;
- while (iter.hasNext()) {
- Row row = iter.next();
- short firstCell = row.getFirstCellNum();
- if (firstCell >= 0) {
- firstColumn = Math.min(firstColumn, firstCell);
- endColumn = Math.max(endColumn, row.getLastCellNum());
- }
- }
- gotBounds = true;
- }
-
- private void printColumnHeads() {
- out.format("<thead>%n");
- out.format(" <tr class=%s>%n", COL_HEAD_CLASS);
- out.format(" <th class=%s>◊</th>%n", COL_HEAD_CLASS);
- //noinspection UnusedDeclaration
- StringBuilder colName = new StringBuilder();
- for (int i = firstColumn; i < endColumn; i++) {
- colName.setLength(0);
- int cnum = i;
- do {
- colName.insert(0, (char) ('A' + cnum % 26));
- cnum /= 26;
- } while (cnum > 0);
- out.format(" <th class=%s>%s</th>%n", COL_HEAD_CLASS, colName);
- }
- out.format(" </tr>%n");
- out.format("</thead>%n");
- }
-
- private void printSheetContent(Sheet sheet) {
- printColumnHeads();
-
- out.format("<tbody>%n");
- Iterator<Row> rows = sheet.rowIterator();
- while (rows.hasNext()) {
- Row row = rows.next();
-
- out.format(" <tr>%n");
- out.format(" <td class=%s>%d</td>%n", ROW_HEAD_CLASS,
- row.getRowNum() + 1);
- for (int i = firstColumn; i < endColumn; i++) {
- String content = " ";
- String attrs = "";
- CellStyle style = null;
- if (i >= row.getFirstCellNum() && i < row.getLastCellNum()) {
- Cell cell = row.getCell(i);
- if (cell != null) {
- style = cell.getCellStyle();
- attrs = tagStyle(cell, style);
- //Set the value that is rendered for the cell
- //also applies the format
- CellFormat cf = CellFormat.getInstance(
- style.getDataFormatString());
- CellFormatResult result = cf.apply(cell);
- content = result.text; //never null
- if (content.isEmpty()) {
- content = " ";
- }
- }
- }
- out.format(" <td class=%s %s>%s</td>%n", styleName(style),
- attrs, content);
- }
- out.format(" </tr>%n");
- }
- out.format("</tbody>%n");
- }
-
- private String tagStyle(Cell cell, CellStyle style) {
- if (style.getAlignment() == HorizontalAlignment.GENERAL) {
- switch (ultimateCellType(cell)) {
- case STRING:
- return "style=\"text-align: left;\"";
- case BOOLEAN:
- case ERROR:
- return "style=\"text-align: center;\"";
- case NUMERIC:
- default:
- // "right" is the default
- break;
- }
- }
- return "";
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.html;
-
-import java.util.Formatter;
-
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.xssf.usermodel.XSSFCellStyle;
-import org.apache.poi.xssf.usermodel.XSSFColor;
-
-/**
- * Implementation of {@link HtmlHelper} for XSSF files.
- *
- * @author Ken Arnold, Industrious Media LLC
- */
-public class XSSFHtmlHelper implements HtmlHelper {
- @Override
- public void colorStyles(CellStyle style, Formatter out) {
- XSSFCellStyle cs = (XSSFCellStyle) style;
- styleColor(out, "background-color", cs.getFillForegroundXSSFColor());
- styleColor(out, "text-color", cs.getFont().getXSSFColor());
- }
-
- private void styleColor(Formatter out, String attr, XSSFColor color) {
- if (color == null || color.isAuto()) {
- return;
- }
-
- byte[] rgb = color.getRGB();
- if (rgb == null) {
- return;
- }
-
- // This is done twice -- rgba is new with CSS 3, and browser that don't
- // support it will ignore the rgba specification and stick with the
- // solid color, which is declared first
- out.format(" %s: #%02x%02x%02x;%n", attr, rgb[0], rgb[1], rgb[2]);
- byte[] argb = color.getARGB();
- if (argb == null) {
- return;
- }
- out.format(" %s: rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x);%n", attr,
- argb[3], argb[0], argb[1], argb[2]);
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- ====================================================================
- 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.
- ====================================================================
- */
-/*
- * This is the default style sheet for html generated by ToHtml
- *
- * @author Ken Arnold, Industrious Media LLC
- */
-.excelDefaults {
- background-color: white;
- color: black;
- text-decoration: none;
- direction: ltr;
- text-transform: none;
- text-indent: 0;
- letter-spacing: 0;
- word-spacing: 0;
- white-space: pre-wrap;
- unicode-bidi: normal;
- background-image: none;
- text-shadow: none;
- list-style-image: none;
- list-style-type: none;
- padding: 0;
- margin: 0;
- border-collapse: collapse;
- vertical-align: bottom;
- font-style: normal;
- font-family: sans-serif;
- font-variant: normal;
- font-weight: normal;
- font-size: 10pt;
- text-align: right;
- table-layout: fixed;
- word-wrap: break-word;
- overflow-wrap: break-word;
-}
-
-.excelDefaults td {
- padding: 1px 5px;
- border: 1px solid silver;
-}
-
-.excelDefaults .colHeader {
- background-color: silver;
- font-weight: bold;
- border: 1px solid black;
- text-align: center;
- padding: 1px 5px;
-}
-
-.excelDefaults .rowHeader {
- background-color: silver;
- font-weight: bold;
- border: 1px solid black;
- text-align: right;
- padding: 1px 5px;
-}
+++ /dev/null
-/* ====================================================================
- 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.
-==================================================================== */
-
-/**
- * This package contains an example that uses POI to convert a workbook into
- * an HTML representation of the data. It can use both XSSF and HSSF workbooks.
- */
-package org.apache.poi.ss.examples.html;
\ No newline at end of file
+++ /dev/null
-/*\r
- * ====================================================================\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements. See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License. You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ==================================================================== \r
- */\r
-\r
-package org.apache.poi.xslf.usermodel;\r
-\r
-import java.awt.Rectangle;\r
-import java.awt.image.BufferedImage;\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.OutputStream;\r
-import java.net.URL;\r
-import java.text.DecimalFormat;\r
-\r
-import javax.imageio.ImageIO;\r
-import javax.xml.namespace.QName;\r
-\r
-import org.apache.poi.openxml4j.opc.PackagePart;\r
-import org.apache.poi.openxml4j.opc.PackagePartName;\r
-import org.apache.poi.openxml4j.opc.PackageRelationship;\r
-import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
-import org.apache.poi.openxml4j.opc.TargetMode;\r
-import org.apache.poi.sl.usermodel.PictureData.PictureType;\r
-import org.apache.xmlbeans.XmlCursor;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;\r
-import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.CTExtension;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.CTTLCommonMediaNodeData;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.CTTLCommonTimeNodeData;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.CTTimeNodeList;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeIndefinite;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeFillType;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeRestartType;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeType;\r
-\r
-import com.xuggle.mediatool.IMediaReader;\r
-import com.xuggle.mediatool.MediaListenerAdapter;\r
-import com.xuggle.mediatool.ToolFactory;\r
-import com.xuggle.mediatool.event.IVideoPictureEvent;\r
-import com.xuggle.xuggler.Global;\r
-import com.xuggle.xuggler.IContainer;\r
-import com.xuggle.xuggler.io.InputOutputStreamHandler;\r
-\r
-/**\r
- * Adding multiple videos to a slide\r
- * \r
- * need the Xuggler 5.4 jars:\r
- * <repositories>\r
- * <repository>\r
- * <id>xuggle repo</id>\r
- * <url>http://xuggle.googlecode.com/svn/trunk/repo/share/java/</url>\r
- * </repository>\r
- * </repositories>\r
- * ...\r
- * <dependency>\r
- * <groupId>xuggle</groupId>\r
- * <artifactId>xuggle-xuggler</artifactId>\r
- * <version>5.4</version>\r
- * </dependency>\r
- * \r
- * @see <a href="http://stackoverflow.com/questions/15197300/apache-poi-xslf-adding-movie-to-the-slide">Apache POI XSLF Adding movie to the slide</a>\r
- * @see <a href="http://apache-poi.1045710.n5.nabble.com/Question-about-embedded-video-in-PPTX-files-tt5718461.html">Question about embedded video in PPTX files</a>\r
- */\r
-public class AddVideoToPptx {\r
- static DecimalFormat df_time = new DecimalFormat("0.####");\r
-\r
- public static void main(String[] args) throws Exception {\r
- URL video = new URL("http://archive.org/download/test-mpeg/test-mpeg.mpg");\r
- // URL video = new URL("file:test-mpeg.mpg");\r
-\r
- XMLSlideShow pptx = new XMLSlideShow();\r
-\r
- // add video file\r
- String videoFileName = video.getPath().substring(video.getPath().lastIndexOf('/')+1);\r
- PackagePartName partName = PackagingURIHelper.createPartName("/ppt/media/"+videoFileName);\r
- PackagePart part = pptx.getPackage().createPart(partName, "video/mpeg");\r
- OutputStream partOs = part.getOutputStream();\r
- InputStream fis = video.openStream();\r
- byte buf[] = new byte[1024];\r
- for (int readBytes; (readBytes = fis.read(buf)) != -1; partOs.write(buf, 0, readBytes));\r
- fis.close();\r
- partOs.close();\r
-\r
- XSLFSlide slide1 = pptx.createSlide();\r
- XSLFPictureShape pv1 = addPreview(pptx, slide1, part, 5, 50, 50);\r
- addVideo(pptx, slide1, part, pv1, 5);\r
- addTimingInfo(slide1, pv1);\r
- XSLFPictureShape pv2 = addPreview(pptx, slide1, part, 9, 50, 250);\r
- addVideo(pptx, slide1, part, pv2, 9);\r
- addTimingInfo(slide1, pv2);\r
-\r
- FileOutputStream fos = new FileOutputStream("pptx-with-video.pptx");\r
- pptx.write(fos);\r
- fos.close();\r
- \r
- pptx.close();\r
- }\r
-\r
- static XSLFPictureShape addPreview(XMLSlideShow pptx, XSLFSlide slide1, PackagePart videoPart, double seconds, int x, int y) throws IOException {\r
- // get preview after 5 sec.\r
- IContainer ic = IContainer.make();\r
- InputOutputStreamHandler iosh = new InputOutputStreamHandler(videoPart.getInputStream());\r
- if (ic.open(iosh, IContainer.Type.READ, null) < 0) return null;\r
-\r
- IMediaReader mediaReader = ToolFactory.makeReader(ic);\r
-\r
- // stipulate that we want BufferedImages created in BGR 24bit color space\r
- mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);\r
-\r
- ImageSnapListener isl = new ImageSnapListener(seconds);\r
- mediaReader.addListener(isl);\r
-\r
- // read out the contents of the media file and\r
- // dispatch events to the attached listener\r
- while (!isl.hasFired && mediaReader.readPacket() == null) ;\r
-\r
- mediaReader.close();\r
- ic.close();\r
-\r
- // add snapshot\r
- BufferedImage image1 = isl.image;\r
- ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
- ImageIO.write(image1, "jpeg", bos);\r
- XSLFPictureData snap = pptx.addPicture(bos.toByteArray(), PictureType.JPEG);\r
- XSLFPictureShape pic1 = slide1.createPicture(snap);\r
- pic1.setAnchor(new Rectangle(x, y, image1.getWidth(), image1.getHeight()));\r
- return pic1;\r
- }\r
-\r
- static void addVideo(XMLSlideShow pptx, XSLFSlide slide1, PackagePart videoPart, XSLFPictureShape pic1, double seconds) throws IOException {\r
-\r
- // add video shape\r
- PackagePartName partName = videoPart.getPartName();\r
- PackageRelationship prsEmbed1 = slide1.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.microsoft.com/office/2007/relationships/media");\r
- PackageRelationship prsExec1 = slide1.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/video");\r
- CTPicture xpic1 = (CTPicture)pic1.getXmlObject();\r
- CTHyperlink link1 = xpic1.getNvPicPr().getCNvPr().addNewHlinkClick();\r
- link1.setId("");\r
- link1.setAction("ppaction://media");\r
-\r
- // add video relation\r
- CTApplicationNonVisualDrawingProps nvPr = xpic1.getNvPicPr().getNvPr();\r
- nvPr.addNewVideoFile().setLink(prsExec1.getId());\r
- CTExtension ext = nvPr.addNewExtLst().addNewExt();\r
- // see http://msdn.microsoft.com/en-us/library/dd950140(v=office.12).aspx\r
- ext.setUri("{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}");\r
- String p14Ns = "http://schemas.microsoft.com/office/powerpoint/2010/main";\r
- XmlCursor cur = ext.newCursor();\r
- cur.toEndToken();\r
- cur.beginElement(new QName(p14Ns, "media", "p14"));\r
- cur.insertNamespace("p14", p14Ns);\r
- cur.insertAttributeWithValue(new QName(STRelationshipId.type.getName().getNamespaceURI(), "embed"), prsEmbed1.getId());\r
- cur.beginElement(new QName(p14Ns, "trim", "p14"));\r
- cur.insertAttributeWithValue("st", df_time.format(seconds*1000.0));\r
- cur.dispose();\r
-\r
- }\r
-\r
- static void addTimingInfo(XSLFSlide slide1, XSLFPictureShape pic1) {\r
- // add slide timing information, so video can be controlled\r
- CTSlide xslide = slide1.getXmlObject();\r
- CTTimeNodeList ctnl;\r
- if (!xslide.isSetTiming()) {\r
- CTTLCommonTimeNodeData ctn = xslide.addNewTiming().addNewTnLst().addNewPar().addNewCTn();\r
- ctn.setDur(STTLTimeIndefinite.INDEFINITE);\r
- ctn.setRestart(STTLTimeNodeRestartType.NEVER);\r
- ctn.setNodeType(STTLTimeNodeType.TM_ROOT);\r
- ctnl = ctn.addNewChildTnLst();\r
- } else {\r
- ctnl = xslide.getTiming().getTnLst().getParArray(0).getCTn().getChildTnLst();\r
- }\r
-\r
- CTTLCommonMediaNodeData cmedia = ctnl.addNewVideo().addNewCMediaNode();\r
- cmedia.setVol(80000);\r
- CTTLCommonTimeNodeData ctn = cmedia.addNewCTn();\r
- ctn.setFill(STTLTimeNodeFillType.HOLD);\r
- ctn.setDisplay(false);\r
- ctn.addNewStCondLst().addNewCond().setDelay(STTLTimeIndefinite.INDEFINITE);\r
- cmedia.addNewTgtEl().addNewSpTgt().setSpid(""+pic1.getShapeId());\r
- }\r
-\r
-\r
- static class ImageSnapListener extends MediaListenerAdapter {\r
- final double SECONDS_BETWEEN_FRAMES;\r
- final long MICRO_SECONDS_BETWEEN_FRAMES;\r
- boolean hasFired = false;\r
- BufferedImage image = null;\r
-\r
- // The video stream index, used to ensure we display frames from one and\r
- // only one video stream from the media container.\r
- int mVideoStreamIndex = -1;\r
-\r
- // Time of last frame write\r
- long mLastPtsWrite = Global.NO_PTS;\r
-\r
- public ImageSnapListener(double seconds) {\r
- SECONDS_BETWEEN_FRAMES = seconds;\r
- MICRO_SECONDS_BETWEEN_FRAMES =\r
- (long)(Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES);\r
- }\r
-\r
-\r
- @Override\r
- public void onVideoPicture(IVideoPictureEvent event) {\r
-\r
- if (event.getStreamIndex() != mVideoStreamIndex) {\r
- // if the selected video stream id is not yet set, go ahead an\r
- // select this lucky video stream\r
- if (mVideoStreamIndex != -1) return;\r
- mVideoStreamIndex = event.getStreamIndex();\r
- }\r
-\r
- long evtTS = event.getTimeStamp();\r
-\r
- // if uninitialized, back date mLastPtsWrite to get the very first frame\r
- if (mLastPtsWrite == Global.NO_PTS)\r
- mLastPtsWrite = Math.max(0, evtTS - MICRO_SECONDS_BETWEEN_FRAMES);\r
-\r
- // if it's time to write the next frame\r
- if (evtTS - mLastPtsWrite >= MICRO_SECONDS_BETWEEN_FRAMES) {\r
- if (!hasFired) {\r
- image = event.getImage();\r
- hasFired = true;\r
- }\r
- // update last write time\r
- mLastPtsWrite += MICRO_SECONDS_BETWEEN_FRAMES;\r
- }\r
- }\r
- }\r
-\r
-}\r
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.ooxml.POIXMLDocumentPart;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xddf.usermodel.chart.AxisOrientation;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.BarDirection;
-import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-
-/**
- * Build a bar chart from a template pptx
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class BarChartDemo {
- private BarChartDemo() {}
-
- private static void usage(){
- System.out.println("Usage: BarChartDemo <bar-chart-template.pptx> <bar-chart-data.txt>");
- System.out.println(" bar-chart-template.pptx template with a bar chart");
- System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
- "then go pairs {axis-label value}");
- }
-
- public static void main(String[] args) throws Exception {
- if(args.length < 2) {
- usage();
- return;
- }
-
- try (FileInputStream argIS = new FileInputStream(args[0]);
- BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
-
- String chartTitle = modelReader.readLine(); // first line is chart title
- String[] series = modelReader.readLine().split(",");
-
- // Category Axis Data
- List<String> listLanguages = new ArrayList<>(10);
-
- // Values
- List<Double> listCountries = new ArrayList<>(10);
- List<Double> listSpeakers = new ArrayList<>(10);
-
- // set model
- String ln;
- while((ln = modelReader.readLine()) != null) {
- String[] vals = ln.split(",");
- listCountries.add(Double.valueOf(vals[0]));
- listSpeakers.add(Double.valueOf(vals[1]));
- listLanguages.add(vals[2]);
- }
- String[] categories = listLanguages.toArray(new String[0]);
- Double[] values1 = listCountries.toArray(new Double[0]);
- Double[] values2 = listSpeakers.toArray(new Double[0]);
-
- try (XMLSlideShow pptx = new XMLSlideShow(argIS)) {
- XSLFSlide slide = pptx.getSlides().get(0);
- setBarData(findChart(slide), chartTitle, series, categories, values1, values2);
-
- XSLFChart chart = findChart(pptx.createSlide().importContent(slide));
- setColumnData(chart, "Column variant");
-
- // save the result
- try (OutputStream out = new FileOutputStream("bar-chart-demo-output.pptx")) {
- pptx.write(out);
- }
- }
- }
- }
-
- private static void setBarData(XSLFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
- final List<XDDFChartData> data = chart.getChartSeries();
- final XDDFBarChartData bar = (XDDFBarChartData) data.get(0);
-
- final int numOfPoints = categories.length;
- final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_LANGUAGES, COLUMN_LANGUAGES));
- final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_COUNTRIES, COLUMN_COUNTRIES));
- final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_SPEAKERS, COLUMN_SPEAKERS));
- final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, COLUMN_LANGUAGES);
- final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, COLUMN_COUNTRIES);
- values1[6] = 16.0; // if you ever want to change the underlying data, it has to be done before building the data source
- final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, COLUMN_SPEAKERS);
-
- XDDFChartData.Series series1 = bar.getSeries(0);
- series1.replaceData(categoriesData, valuesData);
- series1.setTitle(series[0], chart.setSheetTitle(series[0], COLUMN_COUNTRIES));
- XDDFChartData.Series series2 = bar.addSeries(categoriesData, valuesData2);
- series2.setTitle(series[1], chart.setSheetTitle(series[1], COLUMN_SPEAKERS));
-
- chart.plot(bar);
- chart.setTitleText(chartTitle); // https://stackoverflow.com/questions/30532612
- // chart.setTitleOverlay(overlay);
-
- // adjust font size for readability
- bar.getCategoryAxis().getOrAddTextProperties().setFontSize(11.5);
- chart.getTitle().getOrAddTextProperties().setFontSize(18.2);
- }
-
- private static void setColumnData(XSLFChart chart, String chartTitle) {
- // Series Text
- List<XDDFChartData> series = chart.getChartSeries();
- XDDFBarChartData bar = (XDDFBarChartData) series.get(0);
-
- // in order to transform a bar chart into a column chart, you just need to change the bar direction
- bar.setBarDirection(BarDirection.COL);
-
- // looking for "Stacked Bar Chart"? uncomment the following line
- // bar.setBarGrouping(BarGrouping.STACKED);
-
- // additionally, you can adjust the axes
- bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN);
- bar.getValueAxes().get(0).setPosition(AxisPosition.TOP);
- }
-
- private static XSLFChart findChart(XSLFSlide slide) {
- // find chart in the slide
- XSLFChart chart = null;
- for(POIXMLDocumentPart part : slide.getRelations()){
- if(part instanceof XSLFChart){
- chart = (XSLFChart) part;
- break;
- }
- }
-
- if(chart == null) {
- throw new IllegalStateException("chart not found in the template");
- }
- return chart;
- }
-
- private static final int COLUMN_LANGUAGES = 0;
- private static final int COLUMN_COUNTRIES = 1;
- private static final int COLUMN_SPEAKERS = 2;
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.awt.geom.Rectangle2D;
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.util.Units;
-import org.apache.poi.xddf.usermodel.chart.AxisCrossBetween;
-import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.AxisTickMark;
-import org.apache.poi.xddf.usermodel.chart.BarDirection;
-import org.apache.poi.xddf.usermodel.chart.BarGrouping;
-import org.apache.poi.xddf.usermodel.chart.ChartTypes;
-import org.apache.poi.xddf.usermodel.chart.LegendPosition;
-import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartAxis;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
-
-/**
- * Build a chart without reading template file
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class ChartFromScratch {
- private ChartFromScratch() {}
-
- private static void usage(){
- System.out.println("Usage: ChartFromScratch <bar-chart-data.txt>");
- System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
- "then go pairs {axis-label value}");
- }
-
- public static void main(String[] args) throws Exception {
- if(args.length < 1) {
- usage();
- return;
- }
-
- try (BufferedReader modelReader = new BufferedReader(new FileReader(args[0]))) {
-
- String chartTitle = modelReader.readLine(); // first line is chart title
- String[] series = modelReader.readLine().split(",");
-
- // Category Axis Data
- List<String> listLanguages = new ArrayList<>(10);
-
- // Values
- List<Double> listCountries = new ArrayList<>(10);
- List<Double> listSpeakers = new ArrayList<>(10);
-
- // set model
- String ln;
- while((ln = modelReader.readLine()) != null) {
- String[] vals = ln.split(",");
- listCountries.add(Double.valueOf(vals[0]));
- listSpeakers.add(Double.valueOf(vals[1]));
- listLanguages.add(vals[2]);
- }
-
- String[] categories = listLanguages.toArray(new String[0]);
- Double[] values1 = listCountries.toArray(new Double[0]);
- Double[] values2 = listSpeakers.toArray(new Double[0]);
-
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- createSlideWithChart(ppt, chartTitle, series, categories, values1, values2);
- createSlideWithChart(ppt, chartTitle, series, categories, values1, values2);
- createSlideWithChart(ppt, chartTitle, series, categories, values1, values2);
- // save the result
- try (OutputStream out = new FileOutputStream("chart-from-scratch.pptx")) {
- ppt.write(out);
- }
- }
- try (FileInputStream is = new FileInputStream("chart-from-scratch.pptx")) {
- try (XMLSlideShow ppt = new XMLSlideShow(is)) {
- for (XSLFSlide slide : ppt.getSlides()) {
- for (XSLFShape shape : slide.getShapes()) {
- if (shape instanceof XSLFGraphicFrame) {
- XSLFGraphicFrame frame = (XSLFGraphicFrame) shape;
- if (frame.hasChart()) {
- System.out.println(frame.getChart().getTitleShape().getText());
- }
- }
- }
- }
- }
- }
- }
- System.out.println("Done");
- }
-
- private static void createSlideWithChart(XMLSlideShow ppt, String chartTitle, String[] series, String[] categories,
- Double[] values1, Double[] values2) {
- XSLFSlide slide = ppt.createSlide();
- XSLFChart chart = ppt.createChart();
- Rectangle2D rect2D = new java.awt.Rectangle(fromCM(1.5), fromCM(4), fromCM(22), fromCM(14));
- slide.addChart(chart, rect2D);
- setBarData(chart, chartTitle, series, categories, values1, values2);
- }
-
- private static int fromCM(double cm) {
- return (int) (Math.rint(cm * Units.EMU_PER_CENTIMETER));
- }
-
- private static void setBarData(XSLFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
- // Use a category axis for the bottom axis.
- XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
- bottomAxis.setTitle(series[2]);
- XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
- leftAxis.setTitle(series[0]+","+series[1]);
- leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
- leftAxis.setMajorTickMark(AxisTickMark.OUT);
- leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
-
- final int numOfPoints = categories.length;
- final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_LANGUAGES, COLUMN_LANGUAGES));
- final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_COUNTRIES, COLUMN_COUNTRIES));
- final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_SPEAKERS, COLUMN_SPEAKERS));
- final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, COLUMN_LANGUAGES);
- final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, COLUMN_COUNTRIES);
- valuesData.setFormatCode("General");
- values1[6] = 16.0; // if you ever want to change the underlying data, it has to be done before building the data source
- final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, COLUMN_SPEAKERS);
- valuesData2.setFormatCode("General");
-
-
- XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
- bar.setBarGrouping(BarGrouping.CLUSTERED);
-
- XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
- series1.setTitle(series[0], chart.setSheetTitle(series[0], COLUMN_COUNTRIES));
-
- XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
- series2.setTitle(series[1], chart.setSheetTitle(series[1], COLUMN_SPEAKERS));
-
- bar.setVaryColors(true);
- bar.setBarDirection(BarDirection.COL);
- chart.plot(bar);
-
- XDDFChartLegend legend = chart.getOrAddLegend();
- legend.setPosition(LegendPosition.LEFT);
- legend.setOverlay(false);
-
- chart.setTitleText(chartTitle);
- chart.setTitleOverlay(false);
- chart.setAutoTitleDeleted(false);
- }
-
- private static final int COLUMN_LANGUAGES = 0;
- private static final int COLUMN_COUNTRIES = 1;
- private static final int COLUMN_SPEAKERS = 2;
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.awt.Dimension;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-
-import org.apache.poi.openxml4j.opc.PackagePart;
-
-/**
- * Demonstrates how you can extract data from a .pptx file
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class DataExtraction {
- private DataExtraction() {}
-
- public static void main(String[] args) throws IOException {
-
- PrintStream out = System.out;
-
- if (args.length == 0) {
- out.println("Input file is required");
- return;
- }
-
- FileInputStream is = new FileInputStream(args[0]);
- try (XMLSlideShow ppt = new XMLSlideShow(is)) {
- is.close();
-
- // Get the document's embedded files.
- for (PackagePart p : ppt.getAllEmbeddedParts()) {
- String type = p.getContentType();
- // typically file name
- String name = p.getPartName().getName();
- out.println("Embedded file (" + type + "): " + name);
-
- InputStream pIs = p.getInputStream();
- // make sense of the part data
- pIs.close();
-
- }
-
- // Get the document's embedded files.
- for (XSLFPictureData data : ppt.getPictureData()) {
- String type = data.getContentType();
- String name = data.getFileName();
- out.println("Picture (" + type + "): " + name);
-
- InputStream pIs = data.getInputStream();
- // make sense of the image data
- pIs.close();
- }
-
- // size of the canvas in points
- Dimension pageSize = ppt.getPageSize();
- out.println("Pagesize: " + pageSize);
-
- for (XSLFSlide slide : ppt.getSlides()) {
- for (XSLFShape shape : slide) {
- if (shape instanceof XSLFTextShape) {
- XSLFTextShape txShape = (XSLFTextShape) shape;
- out.println(txShape.getText());
- } else if (shape instanceof XSLFPictureShape) {
- XSLFPictureShape pShape = (XSLFPictureShape) shape;
- XSLFPictureData pData = pShape.getPictureData();
- out.println(pData.getFileName());
- } else {
- out.println("Process me: " + shape.getClass());
- }
- }
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-
-/**
- * Merge multiple pptx presentations together
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class MergePresentations {
- private MergePresentations() {}
-
- public static void main(String[] args) throws Exception {
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- for (String arg : args) {
- try (FileInputStream is = new FileInputStream(arg);
- XMLSlideShow src = new XMLSlideShow(is)) {
- for (XSLFSlide srcSlide : src.getSlides()) {
- ppt.createSlide().importContent(srcSlide);
- }
- }
- }
-
- try (FileOutputStream out = new FileOutputStream("merged.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import org.apache.batik.dom.svg.SVGDOMImplementation;
-import org.apache.batik.svggen.SVGGraphics2D;
-import org.apache.batik.transcoder.wmf.tosvg.WMFPainter;
-import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.Document;
-
-import javax.imageio.ImageIO;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.awt.Dimension;
-import java.awt.Graphics2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.io.DataInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-
-/**
- * Convert each slide of a .pptx presentation into SVG
- *
- * @author Yegor Kozlov
- */
-public class PPTX2SVG {
-
- static void usage() {
- System.out.println("Usage: PPTX2SVG <pptx file>");
- }
-
- public static void main(String[] args) throws Exception {
- if (args.length == 0) {
- usage();
- return;
- }
-
- String file = args[0];
-
- System.out.println("Processing " + file);
-
- // read the .pptx file
- XMLSlideShow ppt = new XMLSlideShow(OPCPackage.open(file));
-
- Dimension pgsize = ppt.getPageSize();
-
- // convert each slide into a .svg file
- XSLFSlide[] slide = ppt.getSlides();
- for (int i = 0; i < slide.length; i++) {
- // Create initial SVG DOM
- DOMImplementation domImpl = SVGDOMImplementation.getDOMImplementation();
- Document doc = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
- //Use Batik SVG Graphics2D driver
- SVGGraphics2D graphics = new SVGGraphics2D(doc);
- graphics.setRenderingHint(XSLFRenderingHint.IMAGE_RENDERER, new WMFImageRender());
- graphics.setSVGCanvasSize(pgsize);
-
- String title = slide[i].getTitle();
- System.out.println("Rendering slide " + (i + 1) + (title == null ? "" : ": " + title));
-
- // draw stuff. All the heavy-lifting happens here
- slide[i].draw(graphics);
-
- // save the result.
- int sep = file.lastIndexOf(".");
- String fname = file.substring(0, sep == -1 ? file.length() : sep) + "-" + (i + 1) + ".svg";
- OutputStreamWriter out =
- new OutputStreamWriter(new FileOutputStream(fname), "UTF-8");
- DOMSource domSource = new DOMSource(graphics.getRoot());
- StreamResult streamResult = new StreamResult(out);
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer serializer = tf.newTransformer();
- serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
- serializer.setOutputProperty(OutputKeys.INDENT, "yes");
- serializer.transform(domSource, streamResult);
- out.flush();
- out.close();
- }
- System.out.println("Done");
- }
-
- /**
- * Image renderer with support for .wmf images
- */
- static class WMFImageRender extends XSLFImageRendener {
-
- /**
- * Use Apache Batik to render WMF,
- * delegate all other types of images to the javax.imageio framework
- */
- @Override
- public boolean drawImage(Graphics2D graphics, XSLFPictureData data,
- Rectangle2D anchor) {
- try {
- // see what type of image we are
- PackagePart part = data.getPackagePart();
- String contentType = part.getContentType();
- if (contentType.equals("image/x-wmf")) {
- WMFRecordStore currentStore = new WMFRecordStore();
- currentStore.read(new DataInputStream(part.getInputStream()));
- int wmfwidth = currentStore.getWidthPixels();
- float conv = (float) anchor.getWidth() / wmfwidth;
-
- // Build a painter for the RecordStore
- WMFPainter painter = new WMFPainter(currentStore,
- (int) anchor.getX(), (int) anchor.getY(), conv);
- painter.paint(graphics);
- } else {
- BufferedImage img = ImageIO.read(data.getPackagePart().getInputStream());
- graphics.drawImage(img,
- (int) anchor.getX(), (int) anchor.getY(),
- (int) anchor.getWidth(), (int) anchor.getHeight(), null);
- }
- } catch (Exception e) {
- return false;
- }
- return true;
- }
-
- /**
- * Convert data form the supplied package part into a BufferedImage.
- * This method is used to create texture paint.
- */
- @Override
- public BufferedImage readImage(PackagePart packagePart) throws IOException {
- String contentType = packagePart.getContentType();
- if (contentType.equals("image/x-wmf")) {
- try {
- WMFRecordStore currentStore = new WMFRecordStore();
- currentStore.read(new DataInputStream(packagePart.getInputStream()));
- int wmfwidth = currentStore.getWidthPixels();
- int wmfheight = currentStore.getHeightPixels();
-
- BufferedImage img = new BufferedImage(wmfwidth, wmfheight, BufferedImage.TYPE_INT_RGB);
- Graphics2D graphics = img.createGraphics();
-
- // Build a painter for the RecordStore
- WMFPainter painter = new WMFPainter(currentStore, 0, 0, 1.0f);
- painter.paint(graphics);
-
- return img;
- } catch (IOException e) {
- return null;
- }
- } else {
- return ImageIO.read(packagePart.getInputStream());
- }
- }
-
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.ooxml.POIXMLDocumentPart;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFPieChartData;
-
-/**
- * Build a pie chart from a template pptx
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class PieChartDemo {
- private PieChartDemo() {}
-
- private static void usage(){
- System.out.println("Usage: PieChartDemo <pie-chart-template.pptx> <pie-chart-data.txt>");
- System.out.println(" pie-chart-template.pptx template with a pie chart");
- System.out.println(" pie-chart-data.txt the model to set. First line is chart title, " +
- "then go pairs {axis-label value}");
- }
-
- public static void main(String[] args) throws Exception {
- if(args.length < 2) {
- usage();
- return;
- }
-
- try (FileInputStream argIS = new FileInputStream(args[0]);
- BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
- String chartTitle = modelReader.readLine(); // first line is chart title
-
- try (XMLSlideShow pptx = new XMLSlideShow(argIS)) {
- XSLFSlide slide = pptx.getSlides().get(0);
-
- // find chart in the slide
- XSLFChart chart = null;
- for (POIXMLDocumentPart part : slide.getRelations()) {
- if (part instanceof XSLFChart) {
- chart = (XSLFChart) part;
- break;
- }
- }
-
- if(chart == null) {
- throw new IllegalStateException("chart not found in the template");
- }
-
- // Series Text
- List<XDDFChartData> series = chart.getChartSeries();
- XDDFPieChartData pie = (XDDFPieChartData) series.get(0);
-
- // Category Axis Data
- List<String> listCategories = new ArrayList<>(3);
-
- // Values
- List<Double> listValues = new ArrayList<>(3);
-
- // set model
- String ln;
- while((ln = modelReader.readLine()) != null){
- String[] vals = ln.split("\\s+");
- listCategories.add(vals[0]);
- listValues.add(Double.valueOf(vals[1]));
- }
- String[] categories = listCategories.toArray(new String[0]);
- Double[] values = listValues.toArray(new Double[0]);
-
- final int numOfPoints = categories.length;
- final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
- final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
- final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange);
- final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange);
-
- XDDFPieChartData.Series firstSeries = (XDDFPieChartData.Series) pie.getSeries(0);
- firstSeries.replaceData(categoriesData, valuesData);
- firstSeries.setTitle(chartTitle, chart.setSheetTitle(chartTitle, 0));
- firstSeries.setExplosion(25L);
- chart.plot(pie);
-
- // save the result
- try (OutputStream out = new FileOutputStream("pie-chart-demo-output.pptx")) {
- pptx.write(out);
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Demonstrates how to create slides with predefined layout
- * and fill the placeholder shapes
- */
-public final class Tutorial1 {
- private Tutorial1() {}
-
- public static void main(String[] args) throws IOException{
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- // XSLFSlide#createSlide() with no arguments creates a blank slide
- /*XSLFSlide blankSlide =*/
- ppt.createSlide();
-
-
- XSLFSlideMaster master = ppt.getSlideMasters().get(0);
-
- XSLFSlideLayout layout1 = master.getLayout(SlideLayout.TITLE);
- XSLFSlide slide1 = ppt.createSlide(layout1);
- XSLFTextShape[] ph1 = slide1.getPlaceholders();
- XSLFTextShape titlePlaceholder1 = ph1[0];
- titlePlaceholder1.setText("This is a title");
- XSLFTextShape subtitlePlaceholder1 = ph1[1];
- subtitlePlaceholder1.setText("this is a subtitle");
-
- XSLFSlideLayout layout2 = master.getLayout(SlideLayout.TITLE_AND_CONTENT);
- XSLFSlide slide2 = ppt.createSlide(layout2);
- XSLFTextShape[] ph2 = slide2.getPlaceholders();
- XSLFTextShape titlePlaceholder2 = ph2[0];
- titlePlaceholder2.setText("This is a title");
- XSLFTextShape bodyPlaceholder = ph2[1];
- // we are going to add text by paragraphs. Clear the default placehoder text before that
- bodyPlaceholder.clearText();
- XSLFTextParagraph p1 = bodyPlaceholder.addNewTextParagraph();
- p1.setIndentLevel(0);
- p1.addNewTextRun().setText("Level1 text");
- XSLFTextParagraph p2 = bodyPlaceholder.addNewTextParagraph();
- p2.setIndentLevel(1);
- p2.addNewTextRun().setText("Level2 text");
- XSLFTextParagraph p3 = bodyPlaceholder.addNewTextParagraph();
- p3.setIndentLevel(2);
- p3.addNewTextRun().setText("Level3 text");
-
- try (FileOutputStream out = new FileOutputStream("slides.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.awt.Color;
-import java.awt.Rectangle;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Basic paragraph and text formatting
- */
-public final class Tutorial2 {
- private Tutorial2() {}
-
- public static void main(String[] args) throws IOException{
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- XSLFSlide slide1 = ppt.createSlide();
- XSLFTextBox shape1 = slide1.createTextBox();
- // initial height of the text box is 100 pt but
- Rectangle anchor = new Rectangle(10, 100, 300, 100);
- shape1.setAnchor(anchor);
-
- XSLFTextParagraph p1 = shape1.addNewTextParagraph();
- XSLFTextRun r1 = p1.addNewTextRun();
- r1.setText("Paragraph Formatting");
- r1.setFontSize(24d);
- r1.setFontColor(new Color(85, 142, 213));
-
- XSLFTextParagraph p2 = shape1.addNewTextParagraph();
- // If spaceBefore >= 0, then space is a percentage of normal line height.
- // If spaceBefore < 0, the absolute value of linespacing is the spacing in points
- p2.setSpaceBefore(-20d); // 20 pt from the previous paragraph
- p2.setSpaceAfter(300d); // 3 lines after the paragraph
- XSLFTextRun r2 = p2.addNewTextRun();
- r2.setText("Paragraph properties apply to all text residing within the corresponding paragraph.");
- r2.setFontSize(16d);
-
- XSLFTextParagraph p3 = shape1.addNewTextParagraph();
-
- XSLFTextRun r3 = p3.addNewTextRun();
- r3.setText("Run Formatting");
- r3.setFontSize(24d);
- r3.setFontColor(new Color(85, 142, 213));
-
- XSLFTextParagraph p4 = shape1.addNewTextParagraph();
- p4.setSpaceBefore(-20d); // 20 pt from the previous paragraph
- p4.setSpaceAfter(300d); // 3 lines after the paragraph
- XSLFTextRun r4 = p4.addNewTextRun();
- r4.setFontSize(16d);
- r4.setText(
- "Run level formatting is the most granular property level and allows " +
- "for the specifying of all low level text properties. The text run is " +
- "what all paragraphs are derived from and thus specifying various " +
- "properties per run will allow for a diversely formatted text paragraph.");
-
- // resize the shape to fit text
- shape1.resizeToFitText();
-
- try (FileOutputStream out = new FileOutputStream("text.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.awt.Rectangle;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.sl.usermodel.Placeholder;
-
-/**
- * How to set slide title
- */
-public final class Tutorial3 {
- private Tutorial3() {}
-
- public static void main(String[] args) throws IOException{
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- XSLFSlide slide = ppt.createSlide();
-
- XSLFTextShape titleShape = slide.createTextBox();
- titleShape.setPlaceholder(Placeholder.TITLE);
- titleShape.setText("This is a slide title");
- titleShape.setAnchor(new Rectangle(50, 50, 400, 100));
-
- try (FileOutputStream out = new FileOutputStream("title.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.awt.Color;
-import java.awt.Rectangle;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.sl.usermodel.TableCell.BorderEdge;
-import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
-
-/**
- * PPTX Tables
- */
-public final class Tutorial4 {
- private Tutorial4() {}
-
- public static void main(String[] args) throws IOException{
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- // XSLFSlide#createSlide() with no arguments creates a blank slide
- XSLFSlide slide = ppt.createSlide();
-
- XSLFTable tbl = slide.createTable();
- tbl.setAnchor(new Rectangle(50, 50, 450, 300));
-
- int numColumns = 3;
- int numRows = 5;
- XSLFTableRow headerRow = tbl.addRow();
- headerRow.setHeight(50);
- // header
- for (int i = 0; i < numColumns; i++) {
- XSLFTableCell th = headerRow.addCell();
- XSLFTextParagraph p = th.addNewTextParagraph();
- p.setTextAlign(TextAlign.CENTER);
- XSLFTextRun r = p.addNewTextRun();
- r.setText("Header " + (i + 1));
- r.setBold(true);
- r.setFontColor(Color.white);
- th.setFillColor(new Color(79, 129, 189));
- th.setBorderWidth(BorderEdge.bottom, 2.0);
- th.setBorderColor(BorderEdge.bottom, Color.white);
-
- tbl.setColumnWidth(i, 150); // all columns are equally sized
- }
-
- // rows
-
- for (int rownum = 0; rownum < numRows; rownum++) {
- XSLFTableRow tr = tbl.addRow();
- tr.setHeight(50);
- // header
- for (int i = 0; i < numColumns; i++) {
- XSLFTableCell cell = tr.addCell();
- XSLFTextParagraph p = cell.addNewTextParagraph();
- XSLFTextRun r = p.addNewTextRun();
-
- r.setText("Cell " + (i + 1));
- if (rownum % 2 == 0)
- cell.setFillColor(new Color(208, 216, 232));
- else
- cell.setFillColor(new Color(233, 247, 244));
-
- }
- }
-
- try (FileOutputStream out = new FileOutputStream("table.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.sl.usermodel.PictureData.PictureType;
-
-/**
- * Images
- */
-public final class Tutorial5 {
- private Tutorial5() {}
-
- public static void main(String[] args) throws IOException{
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- XSLFSlide slide = ppt.createSlide();
-
- File img = new File(System.getProperty("POI.testdata.path", "test-data"), "slideshow/clock.jpg");
- XSLFPictureData pictureData = ppt.addPicture(img, PictureType.PNG);
-
- /*XSLFPictureShape shape =*/
- slide.createPicture(pictureData);
-
- try (FileOutputStream out = new FileOutputStream("images.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.awt.Rectangle;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Hyperlinks
- */
-public final class Tutorial6 {
- private Tutorial6() {}
-
- public static void main(String[] args) throws IOException{
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- XSLFSlide slide1 = ppt.createSlide();
- XSLFSlide slide2 = ppt.createSlide();
-
- XSLFTextBox shape1 = slide1.createTextBox();
- shape1.setAnchor(new Rectangle(50, 50, 200, 50));
- XSLFTextRun r1 = shape1.addNewTextParagraph().addNewTextRun();
- XSLFHyperlink link1 = r1.createHyperlink();
- r1.setText("https://poi.apache.org"); // visible text
- link1.setAddress("https://poi.apache.org"); // link address
-
- XSLFTextBox shape2 = slide1.createTextBox();
- shape2.setAnchor(new Rectangle(300, 50, 200, 50));
- XSLFTextRun r2 = shape2.addNewTextParagraph().addNewTextRun();
- XSLFHyperlink link2 = r2.createHyperlink();
- r2.setText("Go to the second slide"); // visible text
- link2.linkToSlide(slide2); // link address
-
-
- try (FileOutputStream out = new FileOutputStream("hyperlinks.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel;
-
-import java.awt.Color;
-import java.awt.Rectangle;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.sl.usermodel.AutoNumberingScheme;
-
-/**
- * Bullets and numbering
- */
-public final class Tutorial7 {
- private Tutorial7() {}
-
- public static void main(String[] args) throws IOException {
- try (XMLSlideShow ppt = new XMLSlideShow()) {
- XSLFSlide slide = ppt.createSlide();
- XSLFTextBox shape = slide.createTextBox();
- shape.setAnchor(new Rectangle(50, 50, 400, 200));
-
- XSLFTextParagraph p1 = shape.addNewTextParagraph();
- p1.setIndentLevel(0);
- p1.setBullet(true);
- XSLFTextRun r1 = p1.addNewTextRun();
- r1.setText("Bullet1");
-
- XSLFTextParagraph p2 = shape.addNewTextParagraph();
- // indentation before text
- p2.setLeftMargin(60d);
- // the bullet is set 40 pt before the text
- p2.setIndent(-40d);
- p2.setBullet(true);
- // customize bullets
- p2.setBulletFontColor(Color.red);
- p2.setBulletFont("Wingdings");
- p2.setBulletCharacter("\u0075");
- p2.setIndentLevel(1);
- XSLFTextRun r2 = p2.addNewTextRun();
- r2.setText("Bullet2");
-
- // the next three paragraphs form an auto-numbered list
- XSLFTextParagraph p3 = shape.addNewTextParagraph();
- p3.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 1);
- p3.setIndentLevel(2);
- XSLFTextRun r3 = p3.addNewTextRun();
- r3.setText("Numbered List Item - 1");
-
- XSLFTextParagraph p4 = shape.addNewTextParagraph();
- p4.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 2);
- p4.setIndentLevel(2);
- XSLFTextRun r4 = p4.addNewTextRun();
- r4.setText("Numbered List Item - 2");
-
- XSLFTextParagraph p5 = shape.addNewTextParagraph();
- p5.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 3);
- p5.setIndentLevel(2);
- XSLFTextRun r5 = p5.addNewTextRun();
- r5.setText("Numbered List Item - 3");
-
- shape.resizeToFitText();
-
- try (FileOutputStream out = new FileOutputStream("list.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-10 languages with most speakers as first language\r
-countries,speakers,language\r
-58,315,العربية\r
-4,243,বাংলা\r
-38,1299,中文\r
-118,378,English\r
-4,260,हिन्दी\r
-2,128,日本語\r
-15,223,português\r
-6,119,ਪੰਜਾਬੀ\r
-18,154,Русский язык\r
-31,442,español\r
+++ /dev/null
-My Chart\r
-First 1.0\r
-Second 3.0\r
-Third 4.0
\ No newline at end of file
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel.tutorial;
-
-import java.io.FileInputStream;
-
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-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.XSLFTextRun;
-import org.apache.poi.xslf.usermodel.XSLFTextShape;
-
-/**
- * Reading a .pptx presentation and printing basic shape properties
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class Step1 {
- private Step1() {}
-
- public static void main(String[] args) throws Exception {
- if(args.length == 0) {
- System.out.println("Input file is required");
- return;
- }
-
- FileInputStream fis = new FileInputStream(args[0]);
- try (XMLSlideShow ppt = new XMLSlideShow(fis)) {
- fis.close();
-
- for (XSLFSlide slide : ppt.getSlides()) {
- System.out.println("Title: " + slide.getTitle());
-
- for (XSLFShape shape : slide.getShapes()) {
- if (shape instanceof XSLFTextShape) {
- XSLFTextShape tsh = (XSLFTextShape) shape;
- for (XSLFTextParagraph p : tsh) {
- System.out.println("Paragraph level: " + p.getIndentLevel());
- for (XSLFTextRun r : p) {
- System.out.println(r.getRawText());
- System.out.println(" bold: " + r.isBold());
- System.out.println(" italic: " + r.isItalic());
- System.out.println(" underline: " + r.isUnderlined());
- System.out.println(" font.family: " + r.getFontFamily());
- System.out.println(" font.size: " + r.getFontSize());
- System.out.println(" font.color: " + r.getFontColor());
- }
- }
- }
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.usermodel.tutorial;
-
-import org.apache.poi.xslf.usermodel.SlideLayout;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.apache.poi.xslf.usermodel.XSLFSlide;
-import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
-import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
-import org.apache.poi.xslf.usermodel.XSLFTextShape;
-
-import java.io.FileOutputStream;
-
-/**
- * Create slides from pre-defined slide layouts
- */
-public final class Step2 {
- private Step2() {}
-
- public static void main(String[] args) throws Exception{
- try (XMLSlideShow ppt = new XMLSlideShow()) {
-
- // first see what slide layouts are available by default
- System.out.println("Available slide layouts:");
- for (XSLFSlideMaster master : ppt.getSlideMasters()) {
- for (XSLFSlideLayout layout : master.getSlideLayouts()) {
- System.out.println(layout.getType());
- }
- }
-
- // blank slide
- /*XSLFSlide blankSlide =*/
- ppt.createSlide();
-
- XSLFSlideMaster defaultMaster = ppt.getSlideMasters().get(0);
-
- // title slide
- XSLFSlideLayout titleLayout = defaultMaster.getLayout(SlideLayout.TITLE);
- XSLFSlide slide1 = ppt.createSlide(titleLayout);
- XSLFTextShape title1 = slide1.getPlaceholder(0);
- title1.setText("First Title");
-
- // title and content
- XSLFSlideLayout titleBodyLayout = defaultMaster.getLayout(SlideLayout.TITLE_AND_CONTENT);
- XSLFSlide slide2 = ppt.createSlide(titleBodyLayout);
-
- XSLFTextShape title2 = slide2.getPlaceholder(0);
- title2.setText("Second Title");
-
- XSLFTextShape body2 = slide2.getPlaceholder(1);
- body2.clearText(); // unset any existing text
- body2.addNewTextParagraph().addNewTextRun().setText("First paragraph");
- body2.addNewTextParagraph().addNewTextRun().setText("Second paragraph");
- body2.addNewTextParagraph().addNewTextRun().setText("Third paragraph");
-
-
- try (FileOutputStream out = new FileOutputStream("step2.pptx")) {
- ppt.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.eventusermodel;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-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.ss.usermodel.DataFormatter;
-import org.apache.poi.ss.util.CellAddress;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.util.XMLHelper;
-import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
-import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor;
-import org.apache.poi.xssf.model.SharedStrings;
-import org.apache.poi.xssf.model.Styles;
-import org.apache.poi.xssf.model.StylesTable;
-import org.apache.poi.xssf.usermodel.XSSFComment;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-
-/**
- * A rudimentary XLSX -> CSV processor modeled on the
- * POI sample program XLS2CSVmra from the package
- * org.apache.poi.hssf.eventusermodel.examples.
- * As with the HSSF version, this tries to spot missing
- * rows and cells, and output empty entries for them.
- * <p>
- * Data sheets are read using a SAX parser to keep the
- * memory footprint relatively small, so this should be
- * able to read enormous workbooks. The styles table and
- * the shared-string table must be kept in memory. The
- * standard POI styles table class is used, but a custom
- * (read-only) class is used for the shared string table
- * because the standard POI SharedStringsTable grows very
- * quickly with the number of unique strings.
- * <p>
- * For a more advanced implementation of SAX event parsing
- * of XLSX files, see {@link XSSFEventBasedExcelExtractor}
- * and {@link XSSFSheetXMLHandler}. Note that for many cases,
- * it may be possible to simply use those with a custom
- * {@link SheetContentsHandler} and no SAX code needed of
- * your own!
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public class XLSX2CSV {
- /**
- * Uses the XSSF Event SAX helpers to do most of the work
- * of parsing the Sheet XML, and outputs the contents
- * as a (basic) CSV.
- */
- private class SheetToCSV implements SheetContentsHandler {
- private boolean firstCellOfRow;
- private int currentRow = -1;
- private int currentCol = -1;
-
- private void outputMissingRows(int number) {
- for (int i=0; i<number; i++) {
- for (int j=0; j<minColumns; j++) {
- output.append(',');
- }
- output.append('\n');
- }
- }
-
- @Override
- public void startRow(int rowNum) {
- // If there were gaps, output the missing rows
- outputMissingRows(rowNum-currentRow-1);
- // Prepare for this row
- firstCellOfRow = true;
- currentRow = rowNum;
- currentCol = -1;
- }
-
- @Override
- public void endRow(int rowNum) {
- // Ensure the minimum number of columns
- for (int i=currentCol; i<minColumns; i++) {
- output.append(',');
- }
- output.append('\n');
- }
-
- @Override
- public void cell(String cellReference, String formattedValue,
- XSSFComment comment) {
- if (firstCellOfRow) {
- firstCellOfRow = false;
- } else {
- output.append(',');
- }
-
- // gracefully handle missing CellRef here in a similar way as XSSFCell does
- if(cellReference == null) {
- cellReference = new CellAddress(currentRow, currentCol).formatAsString();
- }
-
- // Did we miss any cells?
- int thisCol = (new CellReference(cellReference)).getCol();
- int missedCols = thisCol - currentCol - 1;
- for (int i=0; i<missedCols; i++) {
- output.append(',');
- }
- currentCol = thisCol;
-
- // Number or string?
- try {
- //noinspection ResultOfMethodCallIgnored
- Double.parseDouble(formattedValue);
- output.append(formattedValue);
- } catch (Exception e) {
- output.append('"');
- output.append(formattedValue);
- output.append('"');
- }
- }
- }
-
-
- ///////////////////////////////////////
-
- private final OPCPackage xlsxPackage;
-
- /**
- * Number of columns to read starting with leftmost
- */
- private final int minColumns;
-
- /**
- * Destination for data
- */
- private final PrintStream output;
-
- /**
- * Creates a new XLSX -> CSV examples
- *
- * @param pkg The XLSX package to process
- * @param output The PrintStream to output the CSV to
- * @param minColumns The minimum number of columns to output, or -1 for no minimum
- */
- public XLSX2CSV(OPCPackage pkg, PrintStream output, int minColumns) {
- this.xlsxPackage = pkg;
- this.output = output;
- this.minColumns = minColumns;
- }
-
- /**
- * Parses and shows the content of one sheet
- * using the specified styles and shared-strings tables.
- *
- * @param styles The table of styles that may be referenced by cells in the sheet
- * @param strings The table of strings that may be referenced by cells in the sheet
- * @param sheetInputStream The stream to read the sheet-data from.
-
- * @exception java.io.IOException An IO exception from the parser,
- * possibly from a byte stream or character stream
- * supplied by the application.
- * @throws SAXException if parsing the XML data fails.
- */
- public void processSheet(
- Styles styles,
- SharedStrings strings,
- SheetContentsHandler sheetHandler,
- InputStream sheetInputStream) throws IOException, SAXException {
- DataFormatter formatter = new DataFormatter();
- InputSource sheetSource = new InputSource(sheetInputStream);
- try {
- XMLReader sheetParser = XMLHelper.newXMLReader();
- ContentHandler handler = new XSSFSheetXMLHandler(
- styles, null, strings, sheetHandler, formatter, false);
- sheetParser.setContentHandler(handler);
- sheetParser.parse(sheetSource);
- } catch(ParserConfigurationException e) {
- throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
- }
- }
-
- /**
- * Initiates the processing of the XLS workbook file to CSV.
- *
- * @throws IOException If reading the data from the package fails.
- * @throws SAXException if parsing the XML data fails.
- */
- public void process() throws IOException, OpenXML4JException, SAXException {
- ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(this.xlsxPackage);
- XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
- StylesTable styles = xssfReader.getStylesTable();
- XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
- int index = 0;
- while (iter.hasNext()) {
- try (InputStream stream = iter.next()) {
- String sheetName = iter.getSheetName();
- this.output.println();
- this.output.println(sheetName + " [index=" + index + "]:");
- processSheet(styles, strings, new SheetToCSV(), stream);
- }
- ++index;
- }
- }
-
- public static void main(String[] args) throws Exception {
- if (args.length < 1) {
- System.err.println("Use:");
- System.err.println(" XLSX2CSV <xlsx file> [min columns]");
- return;
- }
-
- File xlsxFile = new File(args[0]);
- if (!xlsxFile.exists()) {
- System.err.println("Not found or not a file: " + xlsxFile.getPath());
- return;
- }
-
- int minColumns = -1;
- if (args.length >= 2)
- minColumns = Integer.parseInt(args[1]);
-
- // The package open is instantaneous, as it should be.
- try (OPCPackage p = OPCPackage.open(xlsxFile.getPath(), PackageAccess.READ)) {
- XLSX2CSV xlsx2csv = new XLSX2CSV(p, System.out, minColumns);
- xlsx2csv.process();
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.eventusermodel.examples;
-
-import java.io.InputStream;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.util.XMLHelper;
-import org.apache.poi.xssf.eventusermodel.XLSX2CSV;
-import org.apache.poi.xssf.eventusermodel.XSSFReader;
-import org.apache.poi.xssf.model.SharedStringsTable;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.DefaultHandler;
-
-/**
- * XSSF and SAX (Event API) basic example.
- * See {@link XLSX2CSV} for a fuller example of doing
- * XSLX processing with the XSSF Event code.
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public class FromHowTo {
- public void processFirstSheet(String filename) throws Exception {
- try (OPCPackage pkg = OPCPackage.open(filename, PackageAccess.READ)) {
- XSSFReader r = new XSSFReader(pkg);
- SharedStringsTable sst = r.getSharedStringsTable();
-
- XMLReader parser = fetchSheetParser(sst);
-
- // process the first sheet
- try (InputStream sheet = r.getSheetsData().next()) {
- InputSource sheetSource = new InputSource(sheet);
- parser.parse(sheetSource);
- }
- }
- }
-
- public void processAllSheets(String filename) throws Exception {
- try (OPCPackage pkg = OPCPackage.open(filename, PackageAccess.READ)) {
- XSSFReader r = new XSSFReader(pkg);
- SharedStringsTable sst = r.getSharedStringsTable();
-
- XMLReader parser = fetchSheetParser(sst);
-
- Iterator<InputStream> sheets = r.getSheetsData();
- while (sheets.hasNext()) {
- System.out.println("Processing new sheet:\n");
- try (InputStream sheet = sheets.next()) {
- InputSource sheetSource = new InputSource(sheet);
- parser.parse(sheetSource);
- }
- System.out.println();
- }
- }
- }
-
- public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException, ParserConfigurationException {
- XMLReader parser = XMLHelper.newXMLReader();
- ContentHandler handler = new SheetHandler(sst);
- parser.setContentHandler(handler);
- return parser;
- }
-
- /**
- * See org.xml.sax.helpers.DefaultHandler javadocs
- */
- private static class SheetHandler extends DefaultHandler {
- private final SharedStringsTable sst;
- private String lastContents;
- private boolean nextIsString;
- private boolean inlineStr;
- private final LruCache<Integer,String> lruCache = new LruCache<>(50);
-
- private static class LruCache<A,B> extends LinkedHashMap<A, B> {
- private final int maxEntries;
-
- public LruCache(final int maxEntries) {
- super(maxEntries + 1, 1.0f, true);
- this.maxEntries = maxEntries;
- }
-
- @Override
- protected boolean removeEldestEntry(final Map.Entry<A, B> eldest) {
- return super.size() > maxEntries;
- }
- }
-
- private SheetHandler(SharedStringsTable sst) {
- this.sst = sst;
- }
-
- @Override
- public void startElement(String uri, String localName, String name,
- Attributes attributes) throws SAXException {
- // c => cell
- if(name.equals("c")) {
- // Print the cell reference
- System.out.print(attributes.getValue("r") + " - ");
- // Figure out if the value is an index in the SST
- String cellType = attributes.getValue("t");
- nextIsString = cellType != null && cellType.equals("s");
- inlineStr = cellType != null && cellType.equals("inlineStr");
- }
- // Clear contents cache
- lastContents = "";
- }
-
- @Override
- public void endElement(String uri, String localName, String name)
- throws SAXException {
- // Process the last contents as required.
- // Do now, as characters() may be called more than once
- if(nextIsString && !lastContents.trim().isEmpty()) {
- Integer idx = Integer.valueOf(lastContents);
- lastContents = lruCache.get(idx);
- if (lastContents == null && !lruCache.containsKey(idx)) {
- lastContents = sst.getItemAt(idx).toString();
- lruCache.put(idx, lastContents);
- }
- nextIsString = false;
- }
-
- // v => contents of a cell
- // Output after we've seen the string contents
- if(name.equals("v") || (inlineStr && name.equals("c"))) {
- System.out.println(lastContents);
- }
- }
-
- @Override
- public void characters(char[] ch, int start, int length) throws SAXException { // NOSONAR
- lastContents += new String(ch, start, length);
- }
- }
-
- public static void main(String[] args) throws Exception {
- FromHowTo howto = new FromHowTo();
- howto.processFirstSheet(args[0]);
- howto.processAllSheets(args[0]);
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xssf.eventusermodel.examples;
-
-import java.io.InputStream;
-
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.poifs.crypt.temp.AesZipFileZipEntrySource;
-import org.apache.poi.xssf.eventusermodel.XSSFReader;
-import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator;
-import org.apache.poi.xssf.usermodel.examples.LoadPasswordProtectedXlsx;
-
-/**
- * An example that loads a password protected workbook and counts the sheets.
- * The example highlights how to do this in streaming way.
- * <p><ul>
- * <li>The example demonstrates that all temp files are removed.
- * <li><code>AesZipFileZipEntrySource</code> is used to ensure that temp files are encrypted.
- * </ul><p>
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class LoadPasswordProtectedXlsxStreaming {
-
- private LoadPasswordProtectedXlsxStreaming() {}
-
- public static void main(String[] args) throws Exception {
- LoadPasswordProtectedXlsx.execute(args, LoadPasswordProtectedXlsxStreaming::printSheetCount);
- }
-
- private static void printSheetCount(final InputStream inputStream) throws Exception {
- try (AesZipFileZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(inputStream);
- OPCPackage pkg = OPCPackage.open(source)) {
- XSSFReader reader = new XSSFReader(pkg);
- SheetIterator iter = (SheetIterator)reader.getSheetsData();
- int count = 0;
- while(iter.hasNext()) {
- iter.next();
- count++;
- }
- System.out.println("sheet count: " + count);
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xssf.streaming.examples;
-
-import org.apache.poi.xssf.streaming.DeferredSXSSFSheet;
-import org.apache.poi.xssf.streaming.DeferredSXSSFWorkbook;
-import org.apache.poi.xssf.streaming.SXSSFCell;
-import org.apache.poi.xssf.streaming.SXSSFRow;
-
-import java.io.FileOutputStream;
-
-/**
- * An example that outputs a simple generated workbook that uses deferred creation of the rows in the sheets.
- * When the workbook is written to an output stream, the output data is streamed immediately.
- * There is no collation of the data in temp files prior to writing the overall file.
- * This depends on how efficient the row generating functions are.
- */
-public final class DeferredGeneration {
-
- private DeferredGeneration() {}
-
- public static void main(String[] args) throws Exception {
- String filename;
- if(args.length == 0) {
- filename = "deferred-generation.xlsx";
- } else {
- filename = args[0];
- }
- try (DeferredSXSSFWorkbook wb = new DeferredSXSSFWorkbook()){
- for(int i = 0; i < 10; i++) {
- DeferredSXSSFSheet sheet = wb.createSheet("Sheet" + i);
- sheet.setRowGenerator((sh) -> {
- for (int r = 0; r < 1000; r++) {
- SXSSFRow row = sheet.createRow(r);
- for (int c = 0; c < 100; c++) {
- SXSSFCell cell = row.createCell(c);
- cell.setCellValue("abcd");
- }
- }
- });
- }
- wb.write(new FileOutputStream(filename));
- System.out.println("wrote " + filename);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.streaming.examples;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
-import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
-import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
-import org.apache.poi.xssf.usermodel.XSSFComment;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;
-import org.xml.sax.SAXException;
-
-/**
- * This demonstrates how a hybrid approach to workbook read can be taken, using
- * a mix of traditional XSSF and streaming one particular worksheet (perhaps one
- * which is too big for the ordinary DOM parse).
- */
-public class HybridStreaming {
-
- private static final String SHEET_TO_STREAM = "large sheet";
-
- public static void main(String[] args) throws IOException, SAXException {
- try (InputStream sourceBytes = new FileInputStream("workbook.xlsx")) {
- XSSFWorkbook workbook = new XSSFWorkbook(sourceBytes) {
- /**
- * Avoid DOM parse of large sheet
- */
- @Override
- public void parseSheet(java.util.Map<String, XSSFSheet> shIdMap, CTSheet ctSheet) {
- if (!SHEET_TO_STREAM.equals(ctSheet.getName())) {
- super.parseSheet(shIdMap, ctSheet);
- }
- }
- };
-
- // Having avoided a DOM-based parse of the sheet, we can stream it instead.
- ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(workbook.getPackage());
- new XSSFSheetXMLHandler(workbook.getStylesSource(), strings, createSheetContentsHandler(), false);
- workbook.close();
- }
- }
-
- private static SheetContentsHandler createSheetContentsHandler() {
- return new SheetContentsHandler() {
-
- @Override
- public void startRow(int rowNum) {
- }
-
- @Override
- public void endRow(int rowNum) {
- }
-
- @Override
- public void cell(String cellReference, String formattedValue, XSSFComment comment) {
- }
- };
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.streaming.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.xssf.streaming.SXSSFSheet;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-
-public class Outlining {
-
- public static void main(String[] args) throws IOException {
- Outlining o = new Outlining();
- o.collapseRow();
- }
-
- private void collapseRow() throws IOException {
- try (SXSSFWorkbook wb2 = new SXSSFWorkbook(100)) {
- SXSSFSheet sheet2 = wb2.createSheet("new sheet");
-
- int rowCount = 20;
- for (int i = 0; i < rowCount; i++) {
- sheet2.createRow(i);
- }
-
- sheet2.groupRow(4, 9);
- sheet2.groupRow(11, 19);
-
- sheet2.setRowGroupCollapsed(4, true);
-
- try (FileOutputStream fileOut = new FileOutputStream("outlining_collapsed.xlsx")) {
- wb2.write(fileOut);
- } finally {
- wb2.dispose();
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xssf.streaming.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.GeneralSecurityException;
-
-import org.apache.poi.examples.util.TempFileUtils;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.poifs.crypt.EncryptionMode;
-import org.apache.poi.poifs.crypt.Encryptor;
-import org.apache.poi.poifs.crypt.temp.EncryptedTempData;
-import org.apache.poi.poifs.crypt.temp.SXSSFWorkbookWithCustomZipEntrySource;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.xssf.streaming.SXSSFCell;
-import org.apache.poi.xssf.streaming.SXSSFRow;
-import org.apache.poi.xssf.streaming.SXSSFSheet;
-
-/**
- * An example that outputs a simple generated workbook that is password protected.
- * The example highlights how to do this in streaming way.
- * <p><ul>
- * <li>The example demonstrates that all temp files are removed.
- * <li><code>SXSSFWorkbookWithCustomZipEntrySource</code> extends SXSSFWorkbook to ensure temp files are encrypted.
- * </ul><p>
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class SavePasswordProtectedXlsx {
-
- private SavePasswordProtectedXlsx() {}
-
- public static void main(String[] args) throws Exception {
- if(args.length != 2) {
- throw new IllegalArgumentException("Expected 2 params: filename and password");
- }
- TempFileUtils.checkTempFiles();
- String filename = args[0];
- String password = args[1];
- SXSSFWorkbookWithCustomZipEntrySource wb = new SXSSFWorkbookWithCustomZipEntrySource();
- try {
- for(int i = 0; i < 10; i++) {
- SXSSFSheet sheet = wb.createSheet("Sheet" + i);
- for(int r = 0; r < 1000; r++) {
- SXSSFRow row = sheet.createRow(r);
- for(int c = 0; c < 100; c++) {
- SXSSFCell cell = row.createCell(c);
- cell.setCellValue("abcd");
- }
- }
- }
- EncryptedTempData tempData = new EncryptedTempData();
- try {
- wb.write(tempData.getOutputStream());
- save(tempData.getInputStream(), filename, password);
- System.out.println("Saved " + filename);
- } finally {
- tempData.dispose();
- }
- } finally {
- wb.close();
- wb.dispose();
- }
- TempFileUtils.checkTempFiles();
- }
-
- public static void save(final InputStream inputStream, final String filename, final String pwd)
- throws InvalidFormatException, IOException, GeneralSecurityException {
-
- try (POIFSFileSystem fs = new POIFSFileSystem();
- OPCPackage opc = OPCPackage.open(inputStream);
- FileOutputStream fos = new FileOutputStream(filename)) {
- EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
- Encryptor enc = Encryptor.getInstance(info);
- enc.confirmPassword(pwd);
- opc.save(enc.getDataStream(fs));
- fs.writeFilesystem(fos);
- } finally {
- IOUtils.closeQuietly(inputStream);
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
-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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.VerticalAlignment;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFCellStyle;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTRowImpl;
-
-/**
- * Shows how various alignment options work.
- *
- * Modified by Cristian Petrula, Romania on May 26, 2010
- * New method was added centerAcrossSelection to center a column content over
- * one selection using {@link HorizontalAlignment#CENTER_SELECTION}
- * To create this method example was change for XSSF only and the previous
- * AligningCells.java example has been moved into the SS examples folder.
- */
-public class AligningCells {
-
- public static void main(String[] args) throws IOException {
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
-
- XSSFSheet sheet = wb.createSheet();
- XSSFRow row = sheet.createRow(2);
- row.setHeightInPoints(30);
- for (int i = 0; i < 8; i++) {
- //column width is set in units of 1/256th of a character width
- sheet.setColumnWidth(i, 256 * 15);
- }
-
- createCell(wb, row, 0, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
- createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.BOTTOM);
- createCell(wb, row, 2, HorizontalAlignment.FILL, VerticalAlignment.CENTER);
- createCell(wb, row, 3, HorizontalAlignment.GENERAL, VerticalAlignment.CENTER);
- createCell(wb, row, 4, HorizontalAlignment.JUSTIFY, VerticalAlignment.JUSTIFY);
- createCell(wb, row, 5, HorizontalAlignment.LEFT, VerticalAlignment.TOP);
- createCell(wb, row, 6, HorizontalAlignment.RIGHT, VerticalAlignment.TOP);
-
- //center text over B4, C4, D4
- row = sheet.createRow(3);
- centerAcrossSelection(wb, row, 1, 3, VerticalAlignment.CENTER);
-
- // Write the output to a file
- try (OutputStream fileOut = new FileOutputStream("xssf-align.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
- /**
- * Creates a cell and aligns it a certain way.
- *
- * @param wb the workbook
- * @param row the row to create the cell in
- * @param column the column number to create the cell in
- * @param halign the horizontal alignment for the cell.
- */
- private static void createCell(XSSFWorkbook wb, XSSFRow row, int column,
- HorizontalAlignment halign, VerticalAlignment valign) {
- CreationHelper ch = wb.getCreationHelper();
- XSSFCell cell = row.createCell(column);
- cell.setCellValue(ch.createRichTextString("Align It"));
- CellStyle cellStyle = wb.createCellStyle();
- cellStyle.setAlignment(halign);
- cellStyle.setVerticalAlignment(valign);
- cell.setCellStyle(cellStyle);
- }
-
- /**
- * Center a text over multiple columns using ALIGN_CENTER_SELECTION
- *
- * @param wb the workbook
- * @param row the row to create the cell in
- * @param start_column the column number to create the cell in and where the selection starts
- * @param end_column the column number where the selection ends
- * @param valign the horizontal alignment for the cell.
- */
- private static void centerAcrossSelection(XSSFWorkbook wb, XSSFRow row,
- int start_column, int end_column, VerticalAlignment valign) {
- CreationHelper ch = wb.getCreationHelper();
-
- // Create cell style with ALIGN_CENTER_SELECTION
- XSSFCellStyle cellStyle = wb.createCellStyle();
- cellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);
- cellStyle.setVerticalAlignment(valign);
-
- // Create cells over the selected area
- for (int i = start_column; i <= end_column; i++) {
- XSSFCell cell = row.createCell(i);
- cell.setCellStyle(cellStyle);
- }
-
- // Set value to the first cell
- XSSFCell cell = row.getCell(start_column);
- cell.setCellValue(ch.createRichTextString("Align It"));
-
- // Make the selection
- CTRowImpl ctRow = (CTRowImpl) row.getCTRow();
-
- // 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<>();
- spanList.add(span);
-
- //add spns to the row
- ctRow.setSpans(spanList);
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.util.Random;
-
-import org.apache.poi.common.usermodel.fonts.FontGroup;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xddf.usermodel.PresetColor;
-import org.apache.poi.xddf.usermodel.XDDFColor;
-import org.apache.poi.xddf.usermodel.XDDFFillProperties;
-import org.apache.poi.xddf.usermodel.XDDFLineProperties;
-import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
-import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.BarDirection;
-import org.apache.poi.xddf.usermodel.chart.ChartTypes;
-import org.apache.poi.xddf.usermodel.chart.LayoutMode;
-import org.apache.poi.xddf.usermodel.chart.LegendPosition;
-import org.apache.poi.xddf.usermodel.chart.MarkerStyle;
-import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
-import org.apache.poi.xddf.usermodel.chart.XDDFCategoryDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFLineChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFManualLayout;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
-import org.apache.poi.xddf.usermodel.text.UnderlineType;
-import org.apache.poi.xddf.usermodel.text.XDDFFont;
-import org.apache.poi.xddf.usermodel.text.XDDFRunProperties;
-import org.apache.poi.xddf.usermodel.text.XDDFTextParagraph;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFChart;
-import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
-import org.apache.poi.xssf.usermodel.XSSFDrawing;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-// original contributions by Axel Richter on https://stackoverflow.com/questions/47065690
-// additional title formatting from https://stackoverflow.com/questions/50418856
-// and legend positioning from https://stackoverflow.com/questions/49615379
-// this would probably be an answer for https://stackoverflow.com/questions/36447925 too
-public final class BarAndLineChart {
-
- private static final int NUM_OF_ROWS = 7;
- private static final Random RNG = new Random();
-
- private BarAndLineChart() {}
-
- public static void main(String[] args) throws Exception {
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet("Sheet1");
-
- XSSFRow row = sheet.createRow(0);
- row.createCell(0);
- row.createCell(1).setCellValue("Bars");
- row.createCell(2).setCellValue("Lines");
-
- XSSFCell cell;
- for (int r = 1; r < NUM_OF_ROWS; r++) {
- row = sheet.createRow(r);
- cell = row.createCell(0);
- cell.setCellValue("C" + r);
- cell = row.createCell(1);
- cell.setCellValue(RNG.nextDouble());
- cell = row.createCell(2);
- cell.setCellValue(RNG.nextDouble() * 10);
- }
-
- XSSFDrawing drawing = sheet.createDrawingPatriarch();
- XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 4, 0, 11, 15);
-
- XSSFChart chart = drawing.createChart(anchor);
- chart.setTitleText("This is my title");
- chart.setTitleOverlay(true);
- XDDFRunProperties properties = new XDDFRunProperties();
- properties.setBold(true);
- properties.setItalic(true);
- properties.setUnderline(UnderlineType.DOT_DOT_DASH_HEAVY);
- properties.setFontSize(22.5);
- XDDFFont[] fonts = new XDDFFont[] {
- new XDDFFont(FontGroup.LATIN, "Calibri", null, null, null),
- new XDDFFont(FontGroup.COMPLEX_SCRIPT, "Liberation Sans", null, null, null)
- };
- properties.setFonts(fonts);
- properties.setLineProperties(new XDDFLineProperties(
- new XDDFSolidFillProperties(XDDFColor.from(PresetColor.SIENNA))));
- XDDFTextParagraph paragraph = chart.getTitle().getBody().getParagraph(0);
- paragraph.setDefaultRunProperties(properties);
-
- // the data sources
- XDDFCategoryDataSource xs = XDDFDataSourcesFactory.fromStringCellRange(sheet,
- new CellRangeAddress(1, NUM_OF_ROWS - 1, 0, 0));
- XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
- new CellRangeAddress(1, NUM_OF_ROWS - 1, 1, 1));
- XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
- new CellRangeAddress(1, NUM_OF_ROWS - 1, 2, 2));
-
- // cat axis 1 (bars)
- XDDFCategoryAxis barCategories = chart.createCategoryAxis(AxisPosition.BOTTOM);
-
- // val axis 1 (left)
- XDDFValueAxis leftValues = chart.createValueAxis(AxisPosition.LEFT);
- leftValues.crossAxis(barCategories);
- barCategories.crossAxis(leftValues);
-
- // cat axis 2 (lines)
- XDDFCategoryAxis lineCategories = chart.createCategoryAxis(AxisPosition.BOTTOM);
- lineCategories.setVisible(false); // this cat axis is deleted
-
- // val axis 2 (right)
- XDDFValueAxis rightValues = chart.createValueAxis(AxisPosition.RIGHT);
- // this value axis crosses its category axis at max value
- rightValues.setCrosses(AxisCrosses.MAX);
- rightValues.crossAxis(lineCategories);
- lineCategories.crossAxis(rightValues);
-
- // the bar chart
- XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, barCategories, leftValues);
- XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(xs, ys1);
- series1.setTitle(null, new CellReference(sheet.getSheetName(), 0, 1, true,true));
- bar.setVaryColors(true);
- bar.setBarDirection(BarDirection.COL);
- chart.plot(bar);
-
- // the line chart on secondary axis
- XDDFLineChartData lines = (XDDFLineChartData) chart.createData(ChartTypes.LINE, lineCategories,
- rightValues);
-
- //uncomment below line if only primary axis required and comment above line
- // the line chart on primary axis
- /*XDDFLineChartData lines = (XDDFLineChartData) chart.createData(ChartTypes.LINE, lineCategories,
- leftValues);*/
-
-
- XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) lines.addSeries(xs, ys2);
- series2.setTitle(null, new CellReference(sheet.getSheetName(), 0, 2, true, true));
- series2.setSmooth(false);
- series2.setMarkerStyle(MarkerStyle.DIAMOND);
- series2.setMarkerSize((short)14);
- lines.setVaryColors(true);
- chart.plot(lines);
-
- // some colors
- XDDFFillProperties solidChartreuse = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHARTREUSE));
- XDDFFillProperties solidTurquoise = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.TURQUOISE));
- XDDFLineProperties solidLines = new XDDFLineProperties(solidTurquoise);
- series1.setFillProperties(solidChartreuse);
- series1.setLineProperties(solidLines); // bar border color different from fill
- series2.setLineProperties(solidLines);
-
- // legend
- XDDFChartLegend legend = chart.getOrAddLegend();
- legend.setPosition(LegendPosition.LEFT);
- legend.setOverlay(false);
- XDDFManualLayout layout = legend.getOrAddManualLayout();
- layout.setXMode(LayoutMode.EDGE);
- layout.setYMode(LayoutMode.EDGE);
- layout.setX(0.00); //left edge of the chart
- layout.setY(0.25); //25% of chart's height from top edge of the chart
-
- try (FileOutputStream fileOut = new FileOutputStream("BarAndLineChart.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xddf.usermodel.PresetColor;
-import org.apache.poi.xddf.usermodel.XDDFColor;
-import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
-import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.BarDirection;
-import org.apache.poi.xddf.usermodel.chart.ChartTypes;
-import org.apache.poi.xddf.usermodel.chart.LegendPosition;
-import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
-import org.apache.poi.xssf.usermodel.XSSFChart;
-import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
-import org.apache.poi.xssf.usermodel.XSSFDrawing;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Line chart example.
- */
-public final class BarChart {
- private BarChart() {}
-
- public static void main(String[] args) throws IOException {
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet("barchart");
- final int NUM_OF_ROWS = 3;
- final int NUM_OF_COLUMNS = 10;
-
- // Create a row and put some cells in it. Rows are 0 based.
- Row row;
- Cell cell;
- for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
- row = sheet.createRow((short) rowIndex);
- for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
- cell = row.createCell((short) colIndex);
- cell.setCellValue(colIndex * (rowIndex + 1.0));
- }
- }
-
- XSSFDrawing drawing = sheet.createDrawingPatriarch();
- XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
-
- XSSFChart chart = drawing.createChart(anchor);
- chart.setTitleText("x = 2x and x = 3x");
- chart.setTitleOverlay(false);
- XDDFChartLegend legend = chart.getOrAddLegend();
- legend.setPosition(LegendPosition.TOP_RIGHT);
-
- // Use a category axis for the bottom axis.
- XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
- bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
- XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
- leftAxis.setTitle("f(x)");
- leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
-
- XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
- XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
- XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
-
- XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
- XDDFChartData.Series series1 = data.addSeries(xs, ys1);
- series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
- XDDFChartData.Series series2 = data.addSeries(xs, ys2);
- series2.setTitle("3x", null);
- chart.plot(data);
-
- // in order to transform a bar chart into a column chart, you just need to change the bar direction
- XDDFBarChartData bar = (XDDFBarChartData) data;
- bar.setBarDirection(BarDirection.COL);
- // looking for "Stacked Bar Chart"? uncomment the following line
- // bar.setBarGrouping(BarGrouping.STACKED);
-
- solidFillSeries(data, 0, PresetColor.CHARTREUSE);
- solidFillSeries(data, 1, PresetColor.TURQUOISE);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("ooxml-bar-chart.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
- private static void solidFillSeries(XDDFChartData data, int index, PresetColor color) {
- XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
- XDDFChartData.Series series = data.getSeries().get(index);
- XDDFShapeProperties properties = series.getShapeProperties();
- if (properties == null) {
- properties = new XDDFShapeProperties();
- }
- properties.setFillProperties(fill);
- series.setShapeProperties(properties);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.Calendar;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-
-import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
-import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
-import org.apache.commons.compress.archivers.zip.ZipFile;
-import org.apache.poi.openxml4j.opc.internal.ZipHelper;
-import org.apache.poi.ss.usermodel.DateUtil;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.usermodel.XSSFCellStyle;
-import org.apache.poi.xssf.usermodel.XSSFDataFormat;
-import org.apache.poi.xssf.usermodel.XSSFFont;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates a workaround you can use to generate large workbooks and avoid OutOfMemory exception.
- *
- * Note - You probably <em>don't want to use this approach any more</em>! POI
- * now includes the SXSSF which handles all of this for you, you should
- * be using that instead! This code remains mostly for historical interest.
- * <p>
- * See <a "https://poi.apache.org/spreadsheet/how-to.html#sxssf">
- * https://poi.apache.org/spreadsheet/how-to.html#sxssf</a>.
- * <p>
- * If you really want to use this approach, which is also the one that SXSSF
- * does for you, it works as follows:
- *
- * 1. create a template workbook, create sheets and global objects such as cell styles, number formats, etc.
- * 2. create an application that streams data in a text file
- * 3. Substitute the sheet in the template with the generated data
- *
- * <p>
- * Since 3.8 POI provides a low-memory footprint SXSSF API, which implements
- * ths "BigGridDemo" strategy. SXSSF is an API-compatible streaming extension
- * of XSSF to be used when very large spreadsheets have to be produced, and
- * heap space is limited. SXSSF achieves its low memory footprint by limiting
- * access to the rows that are within a sliding window, while XSSF gives access
- * to all rows in the document. Older rows that are no longer in the window
- * become inaccessible, as they are written to the disk.
- * </p>
- * See <a "https://poi.apache.org/spreadsheet/how-to.html#sxssf">
- * https://poi.apache.org/spreadsheet/how-to.html#sxssf</a>.
- */
-public final class BigGridDemo {
- private static final String XML_ENCODING = "UTF-8";
-
- private static final Random rnd = new Random();
-
- private BigGridDemo() {}
-
- public static void main(String[] args) throws Exception {
-
- // Step 1. Create a template file. Setup sheets and workbook-level objects such as
- // cell styles, number formats, etc.
-
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet("Big Grid");
-
- Map<String, XSSFCellStyle> styles = createStyles(wb);
- //name of the zip entry holding sheet data, e.g. /xl/worksheets/sheet1.xml
- String sheetRef = sheet.getPackagePart().getPartName().getName();
-
- //save the template
- try (FileOutputStream os = new FileOutputStream("template.xlsx")) {
- wb.write(os);
- }
-
- //Step 2. Generate XML file.
- File tmp = File.createTempFile("sheet", ".xml");
- try (
- FileOutputStream stream = new FileOutputStream(tmp);
- Writer fw = new OutputStreamWriter(stream, XML_ENCODING)
- ) {
- generate(fw, styles);
- }
-
- //Step 3. Substitute the template entry with the generated data
- try (FileOutputStream out = new FileOutputStream("big-grid.xlsx")) {
- substitute(new File("template.xlsx"), tmp, sheetRef.substring(1), out);
- }
- }
- }
-
- /**
- * Create a library of cell styles.
- */
- private static Map<String, XSSFCellStyle> createStyles(XSSFWorkbook wb){
- Map<String, XSSFCellStyle> styles = new HashMap<>();
- XSSFDataFormat fmt = wb.createDataFormat();
-
- XSSFCellStyle style1 = wb.createCellStyle();
- style1.setAlignment(HorizontalAlignment.RIGHT);
- style1.setDataFormat(fmt.getFormat("0.0%"));
- styles.put("percent", style1);
-
- XSSFCellStyle style2 = wb.createCellStyle();
- style2.setAlignment(HorizontalAlignment.CENTER);
- style2.setDataFormat(fmt.getFormat("0.0X"));
- styles.put("coeff", style2);
-
- XSSFCellStyle style3 = wb.createCellStyle();
- style3.setAlignment(HorizontalAlignment.RIGHT);
- style3.setDataFormat(fmt.getFormat("$#,##0.00"));
- styles.put("currency", style3);
-
- XSSFCellStyle style4 = wb.createCellStyle();
- style4.setAlignment(HorizontalAlignment.RIGHT);
- style4.setDataFormat(fmt.getFormat("mmm dd"));
- styles.put("date", style4);
-
- XSSFCellStyle style5 = wb.createCellStyle();
- XSSFFont headerFont = wb.createFont();
- headerFont.setBold(true);
- style5.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
- style5.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style5.setFont(headerFont);
- styles.put("header", style5);
-
- return styles;
- }
-
- private static void generate(Writer out, Map<String, XSSFCellStyle> styles) throws Exception {
-
- Calendar calendar = Calendar.getInstance();
-
- SpreadsheetWriter sw = new SpreadsheetWriter(out);
- sw.beginSheet();
-
- //insert header row
- sw.insertRow(0);
- int styleIndex = styles.get("header").getIndex();
- sw.createCell(0, "Title", styleIndex);
- sw.createCell(1, "% Change", styleIndex);
- sw.createCell(2, "Ratio", styleIndex);
- sw.createCell(3, "Expenses", styleIndex);
- sw.createCell(4, "Date", styleIndex);
-
- sw.endRow();
-
- //write data rows
- for (int rownum = 1; rownum < 100000; rownum++) {
- sw.insertRow(rownum);
-
- sw.createCell(0, "Hello, " + rownum + "!");
- sw.createCell(1, (double)rnd.nextInt(100)/100, styles.get("percent").getIndex());
- sw.createCell(2, (double)rnd.nextInt(10)/10, styles.get("coeff").getIndex());
- sw.createCell(3, rnd.nextInt(10000), styles.get("currency").getIndex());
- sw.createCell(4, calendar, styles.get("date").getIndex());
-
- sw.endRow();
-
- calendar.roll(Calendar.DAY_OF_YEAR, 1);
- }
- sw.endSheet();
- }
-
- /**
- *
- * @param zipfile the template file
- * @param tmpfile the XML file with the sheet data
- * @param entry the name of the sheet entry to substitute, e.g. xl/worksheets/sheet1.xml
- * @param out the stream to write the result to
- */
- private static void substitute(File zipfile, File tmpfile, String entry, OutputStream out) throws IOException {
- try (ZipFile zip = ZipHelper.openZipFile(zipfile)) {
- try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(out)) {
- Enumeration<? extends ZipArchiveEntry> en = zip.getEntries();
- while (en.hasMoreElements()) {
- ZipArchiveEntry ze = en.nextElement();
- if (!ze.getName().equals(entry)) {
- zos.putArchiveEntry(new ZipArchiveEntry(ze.getName()));
- try (InputStream is = zip.getInputStream(ze)) {
- copyStream(is, zos);
- }
- zos.closeArchiveEntry();
- }
- }
- zos.putArchiveEntry(new ZipArchiveEntry(entry));
- try (InputStream is = new FileInputStream(tmpfile)) {
- copyStream(is, zos);
- }
- zos.closeArchiveEntry();
- }
- }
- }
-
- private static void copyStream(InputStream in, OutputStream out) throws IOException {
- byte[] chunk = new byte[1024];
- int count;
- while ((count = in.read(chunk)) >=0 ) {
- out.write(chunk,0,count);
- }
- }
-
- /**
- * Writes spreadsheet data in a Writer.
- * (YK: in future it may evolve in a full-featured API for streaming data in Excel)
- */
- public static class SpreadsheetWriter {
- private final Writer _out;
- private int _rownum;
-
- SpreadsheetWriter(Writer out){
- _out = out;
- }
-
- void beginSheet() throws IOException {
- _out.write("<?xml version=\"1.0\" encoding=\""+XML_ENCODING+"\"?>" +
- "<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">" );
- _out.write("<sheetData>\n");
- }
-
- void endSheet() throws IOException {
- _out.write("</sheetData>");
- _out.write("</worksheet>");
- }
-
- /**
- * Insert a new row
- *
- * @param rownum 0-based row number
- */
- void insertRow(int rownum) throws IOException {
- _out.write("<row r=\""+(rownum+1)+"\">\n");
- this._rownum = rownum;
- }
-
- /**
- * Insert row end marker
- */
- void endRow() throws IOException {
- _out.write("</row>\n");
- }
-
- public void createCell(int columnIndex, String value, int styleIndex) throws IOException {
- String ref = new CellReference(_rownum, columnIndex).formatAsString();
- _out.write("<c r=\""+ref+"\" t=\"inlineStr\"");
- if(styleIndex != -1) {
- _out.write(" s=\""+styleIndex+"\"");
- }
- _out.write(">");
- _out.write("<is><t>"+value+"</t></is>");
- _out.write("</c>");
- }
-
- public void createCell(int columnIndex, String value) throws IOException {
- createCell(columnIndex, value, -1);
- }
-
- public void createCell(int columnIndex, double value, int styleIndex) throws IOException {
- String ref = new CellReference(_rownum, columnIndex).formatAsString();
- _out.write("<c r=\""+ref+"\" t=\"n\"");
- if(styleIndex != -1) {
- _out.write(" s=\""+styleIndex+"\"");
- }
- _out.write(">");
- _out.write("<v>"+value+"</v>");
- _out.write("</c>");
- }
-
- public void createCell(int columnIndex, double value) throws IOException {
- createCell(columnIndex, value, -1);
- }
-
- public void createCell(int columnIndex, Calendar value, int styleIndex) throws IOException {
- createCell(columnIndex, DateUtil.getExcelDate(value, false), styleIndex);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import org.apache.poi.xssf.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.usermodel.*;
-
-import java.io.FileOutputStream;
-import java.util.Calendar;
-import java.util.Map;
-import java.util.HashMap;
-
-/**
- * A monthly calendar created using Apache POI. Each month is on a separate sheet.
- * This is a version of org.apache.poi.ss.examples.CalendarDemo that demonstrates
- * some XSSF features not avaiable when using common HSSF-XSSF interfaces.
- *
- * <pre>
- * Usage:
- * CalendarDemo <year>
- * </pre>
- *
- * @author Yegor Kozlov
- */
-public class CalendarDemo {
-
- private static final String[] days = {
- "Sunday", "Monday", "Tuesday",
- "Wednesday", "Thursday", "Friday", "Saturday"};
-
- private static final String[] months = {
- "January", "February", "March","April", "May", "June","July", "August",
- "September","October", "November", "December"};
-
- public static void main(String[] args) throws Exception {
-
- Calendar calendar = Calendar.getInstance();
- if(args.length > 0) calendar.set(Calendar.YEAR, Integer.parseInt(args[0]));
-
- int year = calendar.get(Calendar.YEAR);
-
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- Map<String, XSSFCellStyle> styles = createStyles(wb);
-
- for (int month = 0; month < 12; month++) {
- calendar.set(Calendar.MONTH, month);
- calendar.set(Calendar.DAY_OF_MONTH, 1);
- //create a sheet for each month
- XSSFSheet sheet = wb.createSheet(months[month]);
-
- //turn off gridlines
- sheet.setDisplayGridlines(false);
- sheet.setPrintGridlines(false);
- XSSFPrintSetup printSetup = sheet.getPrintSetup();
- printSetup.setOrientation(PrintOrientation.LANDSCAPE);
- sheet.setFitToPage(true);
- sheet.setHorizontallyCenter(true);
-
- //the header row: centered text in 48pt font
- XSSFRow headerRow = sheet.createRow(0);
- headerRow.setHeightInPoints(80);
- XSSFCell titleCell = headerRow.createCell(0);
- titleCell.setCellValue(months[month] + " " + year);
- titleCell.setCellStyle(styles.get("title"));
- sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$N$1"));
-
- //header with month titles
- XSSFRow monthRow = sheet.createRow(1);
- for (int i = 0; i < days.length; i++) {
- //for compatibility with HSSF we have to set column width in units of 1/256th of a character width
- sheet.setColumnWidth(i * 2, 5 * 256); //the column is 5 characters wide
- sheet.setColumnWidth(i * 2 + 1, 13 * 256); //the column is 13 characters wide
- sheet.addMergedRegion(new CellRangeAddress(1, 1, i * 2, i * 2 + 1));
- XSSFCell monthCell = monthRow.createCell(i * 2);
- monthCell.setCellValue(days[i]);
- monthCell.setCellStyle(styles.get("month"));
- }
-
- int cnt = 1, day = 1;
- int rownum = 2;
- for (int j = 0; j < 6; j++) {
- XSSFRow row = sheet.createRow(rownum++);
- row.setHeightInPoints(100);
- for (int i = 0; i < days.length; i++) {
- XSSFCell dayCell_1 = row.createCell(i * 2);
- XSSFCell dayCell_2 = row.createCell(i * 2 + 1);
-
- int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
- if (cnt >= day_of_week && calendar.get(Calendar.MONTH) == month) {
- dayCell_1.setCellValue(day);
- calendar.set(Calendar.DAY_OF_MONTH, ++day);
-
- if (i == 0 || i == days.length - 1) {
- dayCell_1.setCellStyle(styles.get("weekend_left"));
- dayCell_2.setCellStyle(styles.get("weekend_right"));
- } else {
- dayCell_1.setCellStyle(styles.get("workday_left"));
- dayCell_2.setCellStyle(styles.get("workday_right"));
- }
- } else {
- dayCell_1.setCellStyle(styles.get("grey_left"));
- dayCell_2.setCellStyle(styles.get("grey_right"));
- }
- cnt++;
- }
- if (calendar.get(Calendar.MONTH) > month) break;
- }
- }
-
- // Write the output to a file
- try (FileOutputStream out = new FileOutputStream("calendar-" + year + ".xlsx")) {
- wb.write(out);
- }
-
- }
- }
-
- /**
- * cell styles used for formatting calendar sheets
- */
- private static Map<String, XSSFCellStyle> createStyles(XSSFWorkbook wb){
- Map<String, XSSFCellStyle> styles = new HashMap<>();
-
- XSSFCellStyle style;
- XSSFFont titleFont = wb.createFont();
- titleFont.setFontHeightInPoints((short)48);
- titleFont.setColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFont(titleFont);
- styles.put("title", style);
-
- XSSFFont monthFont = wb.createFont();
- monthFont.setFontHeightInPoints((short)12);
- monthFont.setColor(new XSSFColor(new java.awt.Color(255, 255, 255), wb.getStylesSource().getIndexedColors()));
- monthFont.setBold(true);
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.CENTER);
- style.setFillForegroundColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setFont(monthFont);
- styles.put("month", style);
-
- XSSFFont dayFont = wb.createFont();
- dayFont.setFontHeightInPoints((short)14);
- dayFont.setBold(true);
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setVerticalAlignment(VerticalAlignment.TOP);
- style.setFillForegroundColor(new XSSFColor(new java.awt.Color(228, 232, 243), wb.getStylesSource().getIndexedColors()));
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderLeft(BorderStyle.THIN);
- style.setLeftBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style.setFont(dayFont);
- styles.put("weekend_left", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.TOP);
- style.setFillForegroundColor(new XSSFColor(new java.awt.Color(228, 232, 243), wb.getStylesSource().getIndexedColors()));
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- styles.put("weekend_right", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.LEFT);
- style.setVerticalAlignment(VerticalAlignment.TOP);
- style.setBorderLeft(BorderStyle.THIN);
- style.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 255, 255), wb.getStylesSource().getIndexedColors()));
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setLeftBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style.setFont(dayFont);
- styles.put("workday_left", style);
-
- style = wb.createCellStyle();
- style.setAlignment(HorizontalAlignment.CENTER);
- style.setVerticalAlignment(VerticalAlignment.TOP);
- style.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 255, 255), wb.getStylesSource().getIndexedColors()));
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- styles.put("workday_right", style);
-
- style = wb.createCellStyle();
- style.setBorderLeft(BorderStyle.THIN);
- style.setFillForegroundColor(new XSSFColor(new java.awt.Color(234, 234, 234), wb.getStylesSource().getIndexedColors()));
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- styles.put("grey_left", style);
-
- style = wb.createCellStyle();
- style.setFillForegroundColor(new XSSFColor(new java.awt.Color(234, 234, 234), wb.getStylesSource().getIndexedColors()));
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(new XSSFColor(new java.awt.Color(39, 51, 89), wb.getStylesSource().getIndexedColors()));
- styles.put("grey_right", style);
-
- return styles;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.ClientAnchor;
-import org.apache.poi.ss.usermodel.Comment;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.Drawing;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.RichTextString;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellAddress;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates how to work with excel cell comments.
- *
- * <p>
- * Excel comment is a kind of a text shape,
- * so inserting a comment is very similar to placing a text box in a worksheet
- * </p>
- *
- * @author Yegor Kozlov
- */
-public class CellComments {
- public static void main(String[] args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) {
-
- CreationHelper factory = wb.getCreationHelper();
-
- Sheet sheet = wb.createSheet();
-
- Cell cell1 = sheet.createRow(3).createCell(5);
- cell1.setCellValue("F4");
-
- Drawing<?> drawing = sheet.createDrawingPatriarch();
-
- ClientAnchor anchor = factory.createClientAnchor();
-
- Comment comment1 = drawing.createCellComment(anchor);
- RichTextString str1 = factory.createRichTextString("Hello, World!");
- comment1.setString(str1);
- comment1.setAuthor("Apache POI");
- cell1.setCellComment(comment1);
-
- Cell cell2 = sheet.createRow(2).createCell(2);
- cell2.setCellValue("C3");
-
- Comment comment2 = drawing.createCellComment(anchor);
- RichTextString str2 = factory.createRichTextString("XSSF can set cell comments");
- //apply custom font to the text in the comment
- Font font = wb.createFont();
- font.setFontName("Arial");
- font.setFontHeightInPoints((short) 14);
- font.setBold(true);
- font.setColor(IndexedColors.RED.getIndex());
- str2.applyFont(font);
-
- comment2.setString(str2);
- comment2.setAuthor("Apache POI");
- comment2.setAddress(new CellAddress("C3"));
-
- try (FileOutputStream out = new FileOutputStream("comments.xlsx")) {
- wb.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Date;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.RichTextString;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Illustrates how to create cell and set values of different types.
- */
-public class CreateCell {
-
- public static void main(String[] args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- CreationHelper creationHelper = wb.getCreationHelper();
- Sheet sheet = wb.createSheet("new sheet");
-
- // Create a row and put some cells in it. Rows are 0 based.
- Row row = sheet.createRow((short) 0);
- // Create a cell and put a value in it.
- Cell cell = row.createCell((short) 0);
- cell.setCellValue(1);
-
- //numeric value
- row.createCell(1).setCellValue(1.2);
-
- //plain string value
- row.createCell(2).setCellValue("This is a string cell");
-
- //rich text string
- RichTextString str = creationHelper.createRichTextString("Apache");
- Font font = wb.createFont();
- font.setItalic(true);
- font.setUnderline(Font.U_SINGLE);
- str.applyFont(font);
- row.createCell(3).setCellValue(str);
-
- //boolean value
- row.createCell(4).setCellValue(true);
-
- //formula
- row.createCell(5).setCellFormula("SUM(A1:B1)");
-
- //date
- CellStyle style = wb.createCellStyle();
- style.setDataFormat(creationHelper.createDataFormat().getFormat("m/d/yy h:mm"));
- cell = row.createCell(6);
- cell.setCellValue(new Date());
- cell.setCellStyle(style);
-
- //hyperlink
- row.createCell(7).setCellFormula("SUM(A1:B1)");
- cell.setCellFormula("HYPERLINK(\"http://google.com\",\"Google\")");
-
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("ooxml-cell.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.ss.SpreadsheetVersion;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.DataConsolidateFunction;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.usermodel.XSSFPivotTable;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-public class CreatePivotTable {
-
- public static void main(String[] args) throws FileNotFoundException, IOException, InvalidFormatException {
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet();
-
- //Create some data to build the pivot table on
- setCellData(sheet);
-
- AreaReference source = new AreaReference("A1:D4", SpreadsheetVersion.EXCEL2007);
- CellReference position = new CellReference("H5");
- // Create a pivot table on this sheet, with H5 as the top-left cell..
- // The pivot table's data source is on the same sheet in A1:D4
- XSSFPivotTable pivotTable = sheet.createPivotTable(source, position);
- //Configure the pivot table
- //Use first column as row label
- pivotTable.addRowLabel(0);
- //Sum up the second column
- pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1);
- //Set the third column as filter
- pivotTable.addColumnLabel(DataConsolidateFunction.AVERAGE, 2);
- //Add filter on forth column
- pivotTable.addReportFilter(3);
-
- try (FileOutputStream fileOut = new FileOutputStream("ooxml-pivottable.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
- public static void setCellData(XSSFSheet sheet){
- Row row1 = sheet.createRow(0);
- // Create a cell and put a value in it.
- Cell cell11 = row1.createCell(0);
- cell11.setCellValue("Names");
- Cell cell12 = row1.createCell(1);
- cell12.setCellValue("#");
- Cell cell13 = row1.createCell(2);
- cell13.setCellValue("%");
- Cell cell14 = row1.createCell(3);
- cell14.setCellValue("Human");
-
- Row row2 = sheet.createRow(1);
- Cell cell21 = row2.createCell(0);
- cell21.setCellValue("Jane");
- Cell cell22 = row2.createCell(1);
- cell22.setCellValue(10);
- Cell cell23 = row2.createCell(2);
- cell23.setCellValue(100);
- Cell cell24 = row2.createCell(3);
- cell24.setCellValue("Yes");
-
- Row row3 = sheet.createRow(2);
- Cell cell31 = row3.createCell(0);
- cell31.setCellValue("Tarzan");
- Cell cell32 = row3.createCell(1);
- cell32.setCellValue(5);
- Cell cell33 = row3.createCell(2);
- cell33.setCellValue(90);
- Cell cell34 = row3.createCell(3);
- cell34.setCellValue("Yes");
-
- Row row4 = sheet.createRow(3);
- Cell cell41 = row4.createCell(0);
- cell41.setCellValue("Terk");
- Cell cell42 = row4.createCell(1);
- cell42.setCellValue(10);
- Cell cell43 = row4.createCell(2);
- cell43.setCellValue(90);
- Cell cell44 = row4.createCell(3);
- cell44.setCellValue("No");
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Date;
-import java.util.Calendar;
-
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.ss.SpreadsheetVersion;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.DataConsolidateFunction;
-import org.apache.poi.ss.usermodel.DataFormat;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.usermodel.XSSFPivotTable;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-public class CreatePivotTable2 {
-
- public static void main(String[] args) throws FileNotFoundException, IOException, InvalidFormatException {
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet();
-
- //Create some data to build the pivot table on
- setCellData(sheet);
-
- AreaReference source = new AreaReference("A1:E7", SpreadsheetVersion.EXCEL2007);
- CellReference position = new CellReference("H1");
- // Create a pivot table on this sheet, with H1 as the top-left cell..
- // The pivot table's data source is on the same sheet in A1:E7
- XSSFPivotTable pivotTable = sheet.createPivotTable(source, position);
- //Configure the pivot table
- //Use first column as row label
- pivotTable.addRowLabel(0);
- //Sum up the second column with column title and data format
- pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1, "Values", "#,##0.00");
- //Use third column (month) as columns (side by side)
- pivotTable.addColLabel(3, "DD.MM.YYYY");
-
- //Add filter on forth column
- pivotTable.addReportFilter(4);
-
- try (FileOutputStream fileOut = new FileOutputStream("ooxml-pivottable2.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
- public static void setCellData(XSSFSheet sheet){
- Calendar cal1 = Calendar.getInstance();
- cal1.set(2017, 0, 1, 0, 0, 0);
- Calendar cal2 = Calendar.getInstance();
- cal2.set(2017, 1, 1, 0, 0, 0);
- Row row1 = sheet.createRow(0);
- // Create a cell and put a value in it.
- // first row are column titles
- Cell cell11 = row1.createCell(0);
- cell11.setCellValue("Names");
- Cell cell12 = row1.createCell(1);
- cell12.setCellValue("Values");
- Cell cell13 = row1.createCell(2);
- cell13.setCellValue("%");
- Cell cell14 = row1.createCell(3);
- cell14.setCellValue("Month");
- Cell cell15 = row1.createCell(4);
- cell15.setCellValue("No");
-
- CellStyle csDbl = sheet.getWorkbook().createCellStyle();
- DataFormat dfDbl = sheet.getWorkbook().createDataFormat();
- csDbl.setDataFormat(dfDbl.getFormat("#,##0.00"));
-
- CellStyle csDt = sheet.getWorkbook().createCellStyle();
- DataFormat dfDt = sheet.getWorkbook().createDataFormat();
- csDt.setDataFormat(dfDt.getFormat("dd/MM/yyyy"));
- // data
- setDataRow(sheet, 1, "Jane", 1120.5, 100, cal1.getTime(), 1, csDbl, csDt);
- setDataRow(sheet, 2, "Jane", 1453.2, 95, cal2.getTime(), 2, csDbl, csDt);
-
- setDataRow(sheet, 3, "Tarzan", 1869.8, 88, cal1.getTime(), 1, csDbl, csDt);
- setDataRow(sheet, 4, "Tarzan", 1536.2, 92, cal2.getTime(), 2, csDbl, csDt);
-
- setDataRow(sheet, 5, "Terk", 1624.1, 75, cal1.getTime(), 1, csDbl, csDt);
- setDataRow(sheet, 6, "Terk", 1569.3, 82, cal2.getTime(), 2, csDbl, csDt);
- sheet.autoSizeColumn(3);
- }
-
- public static void setDataRow(XSSFSheet sheet, int rowNum, String name, double v1, int v2, Date dt, int no, CellStyle csDbl, CellStyle csDt){
- Row row = sheet.createRow(rowNum);
- // set the values for one row
- Cell c1 = row.createCell(0);
- c1.setCellValue(name);
- Cell c2 = row.createCell(1);
- c2.setCellValue(v1);
- c2.setCellStyle(csDbl);
- Cell c3 = row.createCell(2);
- c3.setCellValue(v2);
- Cell c4 = row.createCell(3);
- c4.setCellValue(dt);
- c4.setCellStyle(csDt);
- Cell c5 = row.createCell(4);
- c5.setCellValue(no);
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFTable;
-import org.apache.poi.xssf.usermodel.XSSFTableStyleInfo;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates how to create a simple table using Apache POI.
- */
-public class CreateTable {
-
- public static void main(String[] args) throws IOException {
-
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet();
-
- // Set which area the table should be placed in
- AreaReference reference = wb.getCreationHelper().createAreaReference(
- new CellReference(0, 0), new CellReference(2, 2));
-
- // Create
- XSSFTable table = sheet.createTable(reference);
- table.setName("Test");
- table.setDisplayName("Test_Table");
-
- // For now, create the initial style in a low-level way
- table.getCTTable().addNewTableStyleInfo();
- table.getCTTable().getTableStyleInfo().setName("TableStyleMedium2");
-
- // Style the table
- XSSFTableStyleInfo style = (XSSFTableStyleInfo) table.getStyle();
- style.setName("TableStyleMedium2");
- style.setShowColumnStripes(false);
- style.setShowRowStripes(true);
- style.setFirstColumn(false);
- style.setLastColumn(false);
- style.setShowRowStripes(true);
- style.setShowColumnStripes(true);
-
- // Set the values for the table
- XSSFRow row;
- XSSFCell cell;
- for (int i = 0; i < 3; i++) {
- // Create row
- row = sheet.createRow(i);
- for (int j = 0; j < 3; j++) {
- // Create cell
- cell = row.createCell(j);
- if (i == 0) {
- cell.setCellValue("Column" + (j + 1));
- } else {
- cell.setCellValue((i + 1.0) * (j + 1.0));
- }
- }
- }
-
- // Save
- try (FileOutputStream fileOut = new FileOutputStream("ooxml-table.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.DataFormat;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * How to set user-defined date formats
- */
-public class CreateUserDefinedDataFormats {
-
-
- public static void main(String[]args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet("format sheet");
- CellStyle style;
- DataFormat format = wb.createDataFormat();
- Row row;
- Cell cell;
- short rowNum = 0;
- short colNum = 0;
-
- row = sheet.createRow(rowNum);
- cell = row.createCell(colNum);
- cell.setCellValue(11111.25);
- style = wb.createCellStyle();
- style.setDataFormat(format.getFormat("0.0"));
- cell.setCellStyle(style);
-
- row = sheet.createRow(++rowNum);
- cell = row.createCell(colNum);
- cell.setCellValue(11111.25);
- style = wb.createCellStyle();
- style.setDataFormat(format.getFormat("#,##0.0000"));
- cell.setCellStyle(style);
-
- try (FileOutputStream fileOut = new FileOutputStream("ooxml_dataFormat.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.ByteArrayOutputStream;
-
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.xssf.extractor.XSSFExportToXml;
-import org.apache.poi.xssf.usermodel.XSSFMap;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Print all custom XML mappings registered in the given workbook
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class CustomXMLMapping {
-
- private CustomXMLMapping() {}
-
- public static void main(String[] args) throws Exception {
- try (OPCPackage pkg = OPCPackage.open(args[0]);
- XSSFWorkbook wb = new XSSFWorkbook(pkg)) {
- for (XSSFMap map : wb.getCustomXMLMappings()) {
- XSSFExportToXml exporter = new XSSFExportToXml(map);
-
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- exporter.exportToXML(os, true);
- String xml = os.toString("UTF-8");
- System.out.println(xml);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.Closeable;
-import java.io.InputStream;
-
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hwpf.HWPFDocument;
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-
-/**
- * Demonstrates how you can extract embedded data from a .xlsx file
- */
-public class EmbeddedObjects {
- public static void main(String[] args) throws Exception {
- try (XSSFWorkbook workbook = new XSSFWorkbook(args[0])) {
- for (PackagePart pPart : workbook.getAllEmbeddedParts()) {
- String contentType = pPart.getContentType();
- try (InputStream is = pPart.getInputStream()) {
- Closeable document;
- if (contentType.equals("application/vnd.ms-excel")) {
- // Excel Workbook - either binary or OpenXML
- document = new HSSFWorkbook(is);
- } else if (contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
- // Excel Workbook - OpenXML file format
- document = new XSSFWorkbook(is);
- } else if (contentType.equals("application/msword")) {
- // Word Document - binary (OLE2CDF) file format
- document = new HWPFDocument(is);
- } else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
- // Word Document - OpenXML file format
- document = new XWPFDocument(is);
- } else if (contentType.equals("application/vnd.ms-powerpoint")) {
- // PowerPoint Document - binary file format
- document = new HSLFSlideShow(is);
- } else if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) {
- // PowerPoint Document - OpenXML file format
- document = new XMLSlideShow(is);
- } else {
- // Any other type of embedded object.
- document = is;
- }
- document.close();
- }
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * ====================================================================
- * 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xddf.usermodel.PresetColor;
-import org.apache.poi.xddf.usermodel.XDDFColor;
-import org.apache.poi.xddf.usermodel.XDDFFillProperties;
-import org.apache.poi.xddf.usermodel.XDDFLineProperties;
-import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.AxisTickLabelPosition;
-import org.apache.poi.xddf.usermodel.chart.BarDirection;
-import org.apache.poi.xddf.usermodel.chart.ChartTypes;
-import org.apache.poi.xddf.usermodel.chart.LegendPosition;
-import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
-import org.apache.poi.xddf.usermodel.chart.XDDFCategoryDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFLegendEntry;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFScatterChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
-import org.apache.poi.xddf.usermodel.text.XDDFRunProperties;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFChart;
-import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
-import org.apache.poi.xssf.usermodel.XSSFDrawing;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * This example is based on original contributions by Axel Richter on StackOverflow.
- *
- * <em>Note from original author</em>:
- * This only works for Excel since OpenOffice or LibreOffice Calc is not able having series having literal numeric values set.
- *
- * @see <a href="https://stackoverflow.com/questions/50772989/">Create target marker in a bar chart with openxmlformats</a>
- * @see <a href="https://stackoverflow.com/questions/50873700/">Change axis color and font of the chart in openxmlformats</a>
- * @see <a href="https://stackoverflow.com/questions/51530552/">Change colors of line chart Apache POI</a>
- */
-public final class ExcelChartWithTargetLine {
- private ExcelChartWithTargetLine() {}
-
- private static final int NUM_OF_ROWS = 6;
-
- private static void createChart(XSSFChart chart, XSSFSheet sheet, int[] chartedCols, double target) {
- // some colors
- XDDFFillProperties[] fills = new XDDFFillProperties[] {
- new XDDFSolidFillProperties(XDDFColor.from(PresetColor.TURQUOISE)),
- new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHARTREUSE)),
- new XDDFSolidFillProperties(XDDFColor.from(PresetColor.LAVENDER)),
- new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHOCOLATE)),
- new XDDFSolidFillProperties(XDDFColor.from(PresetColor.TOMATO)),
- new XDDFSolidFillProperties(XDDFColor.from(PresetColor.PLUM))
- };
- XDDFLineProperties solidTurquoise = new XDDFLineProperties(fills[0]);
- XDDFLineProperties solidTomato = new XDDFLineProperties(fills[4]);
- XDDFLineProperties solidPlum = new XDDFLineProperties(fills[5]);
- XDDFSolidFillProperties solidAlmond = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.BLANCHED_ALMOND));
- XDDFSolidFillProperties solidGray = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.DARK_SLATE_GRAY));
-
-
- // the bar chart
-
- XDDFCategoryAxis barCategories = chart.createCategoryAxis(AxisPosition.BOTTOM);
- XDDFValueAxis leftValues = chart.createValueAxis(AxisPosition.LEFT);
- leftValues.crossAxis(barCategories);
- barCategories.crossAxis(leftValues);
-
- // from https://stackoverflow.com/questions/50873700/
- // colored major grid lines
- leftValues.getOrAddMajorGridProperties().setLineProperties(solidTomato);
- //colored axis line
- leftValues.getOrAddShapeProperties().setLineProperties(solidPlum);
- // axis font
- XDDFRunProperties props = leftValues.getOrAddTextProperties();
- props.setFontSize(14.0);
- props.setFillProperties(fills[5]);
-
- XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, barCategories, leftValues);
- bar.setVaryColors(true);
- bar.setBarDirection(chartedCols.length > 1 ? BarDirection.COL : BarDirection.BAR);
-
- for (int c : chartedCols) {
- // the data sources
- XDDFCategoryDataSource xs = XDDFDataSourcesFactory.fromStringCellRange(sheet,
- new CellRangeAddress(1, NUM_OF_ROWS, 0, 0));
- XDDFNumericalDataSource<Double> ys = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
- new CellRangeAddress(1, NUM_OF_ROWS, c, c));
- XDDFBarChartData.Series series = (XDDFBarChartData.Series) bar.addSeries(xs, ys);
- series.setTitle(null, new CellReference(sheet.getSheetName(), 0, c, true, true));
- series.setFillProperties(fills[c]);
- series.setLineProperties(solidTurquoise); // bar border color different from fill
- }
- chart.plot(bar);
-
-
- // target line
- // line of a scatter chart from 0 (min) to 1 (max) having value of target
-
- XDDFValueAxis scatterX = chart.createValueAxis(AxisPosition.TOP);
- scatterX.setVisible(false);
- scatterX.setTickLabelPosition(AxisTickLabelPosition.NONE);
- XDDFValueAxis scatterY = chart.createValueAxis(AxisPosition.RIGHT);
- scatterY.setVisible(false);
- scatterY.setTickLabelPosition(AxisTickLabelPosition.NONE);
- scatterX.crossAxis(scatterY);
- scatterY.crossAxis(scatterX);
- if (chartedCols.length > 1) {
- scatterX.setMaximum(1.0);
- } else {
- scatterY.setMaximum(1.0);
- }
-
- XDDFScatterChartData scatter = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, scatterX, scatterY);
- scatter.setVaryColors(true);
-
- // This only works for Excel since OpenOffice or LibreOffice Calc does not support literal numeric data series.
- XDDFNumericalDataSource<Double> targetDS = XDDFDataSourcesFactory.fromArray(new Double[] { target, target });
- XDDFNumericalDataSource<Double> zeroOneDS = XDDFDataSourcesFactory.fromArray(new Double[] { 0.0, 1.0 });
-
- if (chartedCols.length > 1) {
- // BarDirection.COL then X axis is from 0 to 1 and Y axis is target axis
- scatter.addSeries(zeroOneDS, targetDS).setLineProperties(solidTurquoise);
- } else {
- // BarDirection.BAR then X axis is target axis and Y axis is from 0 to 1
- scatter.addSeries(targetDS, zeroOneDS).setLineProperties(solidTurquoise);
- }
-
- chart.plot(scatter);
-
-
- // legend
- if (chartedCols.length > 1) {
- XDDFChartLegend legend = chart.getOrAddLegend();
- legend.setPosition(LegendPosition.LEFT);
- legend.setOverlay(false);
-
- // delete additional target line series legend entry
- XDDFLegendEntry entry = legend.addEntry();
- entry.setIndex(0);
- entry.setDelete(true);
- }
-
-
- // from https://stackoverflow.com/questions/51530552/
- // customize the chart
-
- // do not auto delete the title
- chart.setAutoTitleDeleted(false);
-
- // plot area background and border line
- XDDFShapeProperties chartProps = chart.getOrAddShapeProperties();
- chartProps.setFillProperties(solidAlmond);
- chartProps.setLineProperties(new XDDFLineProperties(solidGray));
-
- // line style of cat axis
- XDDFLineProperties categoriesProps = new XDDFLineProperties(solidGray);
- categoriesProps.setWidth(2.1);
- barCategories.getOrAddShapeProperties().setLineProperties(categoriesProps);
- }
-
- private static XSSFClientAnchor createAnchor(XSSFDrawing drawing, int[] chartedCols) {
- if (chartedCols.length > 1) {
- return drawing.createAnchor(0, 0, 0, 0, 0, 8, 10, 23);
- } else {
- return drawing.createAnchor(0, 0, 0, 0, 0, 8, 5, 23);
- }
- }
-
- public static void main(String[] args) throws Exception {
- try (XSSFWorkbook workbook = new XSSFWorkbook()) {
- XSSFSheet sheet = workbook.createSheet("targetline");
- final int NUM_OF_COLUMNS = 4;
-
- // create some data
- XSSFRow row;
- XSSFCell cell;
- String[] headings = new String[] { "Year", "Male", "Female", "Other" };
- int rowIndex = 0;
- row = sheet.createRow(rowIndex);
- for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
- cell = row.createCell(colIndex);
- cell.setCellValue(headings[colIndex]);
- }
- double[][] values = new double[][] { new double[] { 1980, 56.0, 44.1, 12.2 },
- new double[] { 1985, 34.5, 41.0, 4 }, new double[] { 1990, 65.0, 68.5, 9.1 },
- new double[] { 1995, 34.7, 47.6, 4.9 }, new double[] { 2000, 23.0, 64.5, 11.1 },
- new double[] { 2005, 56.3, 69.8, 9.5 } };
- for (; rowIndex < NUM_OF_ROWS; rowIndex++) {
- row = sheet.createRow(rowIndex + 1);
- for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
- cell = row.createCell(colIndex);
- cell.setCellValue(values[rowIndex][colIndex]);
- }
- }
-
- int[] chartedCols = new int[] { 1, 2 , 3 };
-
- XSSFDrawing drawing = sheet.createDrawingPatriarch();
- XSSFClientAnchor anchor = createAnchor(drawing, chartedCols);
- XSSFChart chart = drawing.createChart(anchor);
- createChart(chart, sheet, chartedCols, 42.0);
-
- try (FileOutputStream fos = new FileOutputStream("ExcelChartWithTargetLine.xlsx")) {
- workbook.write(fos);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFRichTextString;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Fills and Colors
- */
-public class FillsAndColors {
- public static void main(String[] args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet("new sheet");
-
- // Create a row and put some cells in it. Rows are 0 based.
- Row row = sheet.createRow(1);
-
- // Aqua background
- CellStyle style = wb.createCellStyle();
- style.setFillBackgroundColor(IndexedColors.AQUA.getIndex());
- style.setFillPattern(FillPatternType.BIG_SPOTS);
- Cell cell = row.createCell(1);
- cell.setCellValue(new XSSFRichTextString("X"));
- cell.setCellStyle(style);
-
- // Orange "foreground", foreground being the fill foreground not the font color.
- style = wb.createCellStyle();
- style.setFillForegroundColor(IndexedColors.ORANGE.getIndex());
- style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
- cell = row.createCell(2);
- cell.setCellValue(new XSSFRichTextString("X"));
- cell.setCellStyle(style);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("fill_colors.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.PrintSetup;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-public class FitSheetToOnePage {
-
- public static void main(String[]args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet("format sheet");
- PrintSetup ps = sheet.getPrintSetup();
-
- sheet.setAutobreaks(true);
-
- ps.setFitHeight((short) 1);
- ps.setFitWidth((short) 1);
-
- // Create various cells and rows for spreadsheet.
-
- try (FileOutputStream fileOut = new FileOutputStream("fitSheetToOnePage.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Footer;
-import org.apache.poi.ss.usermodel.Header;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-public class HeadersAndFooters {
-
- public static void main(String[]args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet("first-header - format sheet");
- sheet.createRow(0).createCell(0).setCellValue(123);
-
- //set page numbers in the footer
- Footer footer = sheet.getFooter();
- //&P == current page number
- //&N == page numbers
- footer.setRight("Page &P of &N");
-
-
- Header firstHeader = ((XSSFSheet) sheet).getFirstHeader();
- //&F == workbook file name
- firstHeader.setLeft("&F ......... first header");
-
- for (int i = 0; i < 100; i = i + 10) {
- sheet.createRow(i).createCell(0).setCellValue(123);
- }
-
-
- XSSFSheet sheet2 = (XSSFSheet) wb.createSheet("odd header-even footer");
- Header oddHeader = sheet2.getOddHeader();
- //&B == bold
- //&E == double underline
- //&D == date
- oddHeader.setCenter("&B &E oddHeader &D ");
-
- Footer evenFooter = sheet2.getEvenFooter();
- evenFooter.setRight("even footer &P");
- sheet2.createRow(10).createCell(0).setCellValue("Second sheet with an oddHeader and an evenFooter");
-
- for (int i = 0; i < 200; i = i + 10) {
- sheet2.createRow(i).createCell(0).setCellValue(123);
- }
-
- XSSFSheet sheet3 = (XSSFSheet) wb.createSheet("odd header- odd footer");
- sheet3.createRow(10).createCell(0).setCellValue("Third sheet with oddHeader and oddFooter");
- Header oddH = sheet3.getOddHeader();
- //&C == centered
- oddH.setCenter("centered oddHeader");
- oddH.setLeft("left ");
- oddH.setRight("right ");
-
- Footer oddF = sheet3.getOddFooter();
- oddF.setLeft("Page &P");
- oddF.setRight("Pages &N ");
-
- try (FileOutputStream fileOut = new FileOutputStream("headerFooter.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.common.usermodel.HyperlinkType;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.Hyperlink;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates how to create hyperlinks.
- */
-public class HyperlinkExample {
-
- public static void main(String[]args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- CreationHelper createHelper = wb.getCreationHelper();
-
- //cell style for hyperlinks
- //by default hyperlinks are blue and underlined
- CellStyle hlink_style = wb.createCellStyle();
- Font hlink_font = wb.createFont();
- hlink_font.setUnderline(Font.U_SINGLE);
- hlink_font.setColor(IndexedColors.BLUE.getIndex());
- hlink_style.setFont(hlink_font);
-
- Cell cell;
- Sheet sheet = wb.createSheet("Hyperlinks");
- //URL
- cell = sheet.createRow(0).createCell(0);
- cell.setCellValue("URL Link");
-
- Hyperlink link = createHelper.createHyperlink(HyperlinkType.URL);
- link.setAddress("https://poi.apache.org/");
- cell.setHyperlink(link);
- cell.setCellStyle(hlink_style);
-
- //link to a file in the current directory
- cell = sheet.createRow(1).createCell(0);
- cell.setCellValue("File Link");
- link = createHelper.createHyperlink(HyperlinkType.FILE);
- link.setAddress("link1.xls");
- cell.setHyperlink(link);
- cell.setCellStyle(hlink_style);
-
- //e-mail link
- cell = sheet.createRow(2).createCell(0);
- cell.setCellValue("Email Link");
- link = createHelper.createHyperlink(HyperlinkType.EMAIL);
- //note, if subject contains white spaces, make sure they are url-encoded
- link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
- cell.setHyperlink(link);
- cell.setCellStyle(hlink_style);
-
- //link to a place in this workbook
-
- //create a target sheet and cell
- Sheet sheet2 = wb.createSheet("Target Sheet");
- sheet2.createRow(0).createCell(0).setCellValue("Target Cell");
-
- cell = sheet.createRow(3).createCell(0);
- cell.setCellValue("Worksheet Link");
- Hyperlink link2 = createHelper.createHyperlink(HyperlinkType.DOCUMENT);
- link2.setAddress("'Target Sheet'!A1");
- cell.setHyperlink(link2);
- cell.setCellStyle(hlink_style);
-
- try (FileOutputStream out = new FileOutputStream("hyperinks.xlsx")) {
- wb.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Iterate over rows and cells
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class IterateCells {
-
- private IterateCells() {}
-
- public static void main(String[] args) throws IOException {
- try (
- FileInputStream is = new FileInputStream(args[0]);
- Workbook wb = new XSSFWorkbook(is)
- ) {
- for (int i = 0; i < wb.getNumberOfSheets(); i++) {
- Sheet sheet = wb.getSheetAt(i);
- System.out.println(wb.getSheetName(i));
- for (Row row : sheet) {
- System.out.println("rownum: " + row.getRowNum());
- for (Cell cell : row) {
- System.out.println(cell);
- }
- }
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xddf.usermodel.PresetColor;
-import org.apache.poi.xddf.usermodel.XDDFColor;
-import org.apache.poi.xddf.usermodel.XDDFLineProperties;
-import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
-import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.ChartTypes;
-import org.apache.poi.xddf.usermodel.chart.LegendPosition;
-import org.apache.poi.xddf.usermodel.chart.MarkerStyle;
-import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFLineChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
-import org.apache.poi.xssf.usermodel.XSSFChart;
-import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
-import org.apache.poi.xssf.usermodel.XSSFDrawing;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Line chart example.
- */
-public final class LineChart {
- private LineChart() {}
-
- public static void main(String[] args) throws IOException {
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet("linechart");
- final int NUM_OF_ROWS = 3;
- final int NUM_OF_COLUMNS = 10;
-
- // Create a row and put some cells in it. Rows are 0 based.
- Row row;
- Cell cell;
- for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
- row = sheet.createRow((short) rowIndex);
- for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
- cell = row.createCell((short) colIndex);
- cell.setCellValue(colIndex * (rowIndex + 1.0));
- }
- }
-
- XSSFDrawing drawing = sheet.createDrawingPatriarch();
- XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
-
- XSSFChart chart = drawing.createChart(anchor);
- XDDFChartLegend legend = chart.getOrAddLegend();
- legend.setPosition(LegendPosition.TOP_RIGHT);
-
- // Use a category axis for the bottom axis.
- XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
- bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
- XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
- leftAxis.setTitle("f(x)");
- leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
-
- XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
- XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
- XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
-
- XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
- XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1);
- series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
- series1.setSmooth(false); // https://stackoverflow.com/questions/29014848
- series1.setMarkerStyle(MarkerStyle.STAR); // https://stackoverflow.com/questions/39636138
- XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2);
- series2.setTitle("3x", null);
- series2.setSmooth(true);
- series2.setMarkerSize((short) 6);
- series2.setMarkerStyle(MarkerStyle.TRIANGLE); // https://stackoverflow.com/questions/39636138
- chart.plot(data);
-
- // if your series have missing values like https://stackoverflow.com/questions/29014848
- // chart.displayBlanksAs(DisplayBlanks.GAP);
-
- // https://stackoverflow.com/questions/24676460
- solidLineSeries(data, 0, PresetColor.CHARTREUSE);
- solidLineSeries(data, 1, PresetColor.TURQUOISE);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
- private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
- XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
- XDDFLineProperties line = new XDDFLineProperties();
- line.setFillProperties(fill);
- XDDFChartData.Series series = data.getSeries().get(index);
- XDDFShapeProperties properties = series.getShapeProperties();
- if (properties == null) {
- properties = new XDDFShapeProperties();
- }
- properties.setLineProperties(line);
- series.setShapeProperties(properties);
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xssf.usermodel.examples;
-
-import java.io.FileInputStream;
-import java.io.InputStream;
-
-import org.apache.poi.examples.util.TempFileUtils;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.poifs.crypt.Decryptor;
-import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.poifs.crypt.temp.AesZipFileZipEntrySource;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * An example that loads a password protected workbook and counts the sheets.
- * <p><ul>
- * <li>The example demonstrates that all temp files are removed.
- * <li><code>AesZipFileZipEntrySource</code> is used to ensure that temp files are encrypted.
- * </ul><p>
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class LoadPasswordProtectedXlsx {
-
- private LoadPasswordProtectedXlsx() {}
-
- public interface EncryptionHandler {
- void handle(final InputStream inputStream) throws Exception;
- }
-
- public static void main(String[] args) throws Exception {
- execute(args, LoadPasswordProtectedXlsx::printSheetCount);
- }
-
- public static void execute(String[] args, EncryptionHandler handler) throws Exception {
- if(args.length != 2) {
- throw new IllegalArgumentException("Expected 2 params: filename and password");
- }
- TempFileUtils.checkTempFiles();
- String filename = args[0];
- String password = args[1];
- try (FileInputStream fis = new FileInputStream(filename);
- POIFSFileSystem fs = new POIFSFileSystem(fis)) {
- EncryptionInfo info = new EncryptionInfo(fs);
- Decryptor d = Decryptor.getInstance(info);
- if (!d.verifyPassword(password)) {
- throw new RuntimeException("incorrect password");
- }
- try (InputStream unencryptedStream = d.getDataStream(fs)) {
- handler.handle(unencryptedStream);
- }
- }
- TempFileUtils.checkTempFiles();
- }
-
-
- private static void printSheetCount(final InputStream inputStream) throws Exception {
- try (AesZipFileZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(inputStream);
- OPCPackage pkg = OPCPackage.open(source);
- XSSFWorkbook workbook = new XSSFWorkbook(pkg)) {
- System.out.println("sheet count: " + workbook.getNumberOfSheets());
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.usermodel.XSSFRichTextString;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * An example of how to merge regions of cells.
- */
-public class MergingCells {
- public static void main(String[] args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet("new sheet");
-
- Row row = sheet.createRow((short) 1);
- Cell cell = row.createCell((short) 1);
- cell.setCellValue(new XSSFRichTextString("This is a test of merging"));
-
- sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, 2));
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("merging_cells.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * How to use newlines in cells
- */
-public class NewLinesInCells {
-
- public static void main(String[]args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet();
-
- Row row = sheet.createRow(2);
- Cell cell = row.createCell(2);
- cell.setCellValue("Use \n with word wrap on to create a new line");
-
- //to enable newlines you need set a cell styles with wrap=true
- CellStyle cs = wb.createCellStyle();
- cs.setWrapText(true);
- cell.setCellStyle(cs);
-
- //increase row height to accommodate two lines of text
- row.setHeightInPoints(2 * sheet.getDefaultRowHeightInPoints());
-
- //adjust column width to fit the content
- sheet.autoSizeColumn(2);
-
- try (FileOutputStream fileOut = new FileOutputStream("ooxml-newlines.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-public class Outlining {
-
- public static void main(String[] args) throws IOException {
- Outlining o=new Outlining();
- o.groupRowColumn();
- o.collapseExpandRowColumn();
- }
-
-
- private void groupRowColumn() throws IOException {
- try (Workbook wb = new XSSFWorkbook()) {
- Sheet sheet1 = wb.createSheet("new sheet");
-
- sheet1.groupRow(5, 14);
- sheet1.groupRow(7, 14);
- sheet1.groupRow(16, 19);
-
- sheet1.groupColumn((short) 4, (short) 7);
- sheet1.groupColumn((short) 9, (short) 12);
- sheet1.groupColumn((short) 10, (short) 11);
-
- try (OutputStream fileOut = new FileOutputStream("outlining.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
- private void collapseExpandRowColumn() throws IOException {
- try (Workbook wb2 = new XSSFWorkbook()) {
- Sheet sheet2 = wb2.createSheet("new sheet");
- sheet2.groupRow(5, 14);
- sheet2.groupRow(7, 14);
- sheet2.groupRow(16, 19);
-
- sheet2.groupColumn((short) 4, (short) 7);
- sheet2.groupColumn((short) 9, (short) 12);
- sheet2.groupColumn((short) 10, (short) 11);
-
-
- sheet2.setRowGroupCollapsed(7, true);
- //sheet1.setRowGroupCollapsed(7,false);
-
- sheet2.setColumnGroupCollapsed((short) 4, true);
- sheet2.setColumnGroupCollapsed((short) 4, false);
-
- try (OutputStream fileOut = new FileOutputStream("outlining_collapsed.xlsx")) {
- wb2.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xddf.usermodel.PresetColor;
-import org.apache.poi.xddf.usermodel.XDDFColor;
-import org.apache.poi.xddf.usermodel.XDDFLineProperties;
-import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
-import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.ChartTypes;
-import org.apache.poi.xddf.usermodel.chart.LegendPosition;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFScatterChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
-import org.apache.poi.xssf.usermodel.XSSFChart;
-import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
-import org.apache.poi.xssf.usermodel.XSSFDrawing;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Illustrates how to create a simple scatter chart.
- */
-public final class ScatterChart {
- private ScatterChart() {}
-
- public static void main(String[] args) throws IOException {
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet("Sheet 1");
- final int NUM_OF_ROWS = 3;
- final int NUM_OF_COLUMNS = 10;
-
- // Create a row and put some cells in it. Rows are 0 based.
- Row row;
- Cell cell;
- for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
- row = sheet.createRow((short) rowIndex);
- for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
- cell = row.createCell((short) colIndex);
- cell.setCellValue(colIndex * (rowIndex + 1.0));
- }
- }
-
- XSSFDrawing drawing = sheet.createDrawingPatriarch();
- XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
-
- XSSFChart chart = drawing.createChart(anchor);
- XDDFChartLegend legend = chart.getOrAddLegend();
- legend.setPosition(LegendPosition.TOP_RIGHT);
-
- XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM);
- bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
- XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
- leftAxis.setTitle("f(x)");
- leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
-
- XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
- XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
- XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
-
-
- XDDFScatterChartData data = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
- XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) data.addSeries(xs, ys1);
- series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
- series1.setSmooth(false); // https://stackoverflow.com/questions/39636138
- XDDFScatterChartData.Series series2 = (XDDFScatterChartData.Series) data.addSeries(xs, ys2);
- series2.setTitle("3x", null);
- chart.plot(data);
-
- solidLineSeries(data, 0, PresetColor.CHARTREUSE);
- solidLineSeries(data, 1, PresetColor.TURQUOISE);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("ooxml-scatter-chart.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
- private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
- XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
- XDDFLineProperties line = new XDDFLineProperties();
- line.setFillProperties(fill);
- XDDFChartData.Series series = data.getSeries().get(index);
- XDDFShapeProperties properties = series.getShapeProperties();
- if (properties == null) {
- properties = new XDDFShapeProperties();
- }
- properties.setLineProperties(line);
- series.setShapeProperties(properties);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-public abstract class SelectedSheet {
-
- public static void main(String[]args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
-
- wb.createSheet("row sheet");
- wb.createSheet("another sheet");
- Sheet sheet3 = wb.createSheet(" sheet 3 ");
- sheet3.setSelected(true);
- wb.setActiveSheet(2);
-
- // Create various cells and rows for spreadsheet.
-
- try (FileOutputStream fileOut = new FileOutputStream("selectedSheet.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * How to shift rows up or down
- */
-public class ShiftRows {
-
- public static void main(String[]args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet("Sheet1");
-
- Row row1 = sheet.createRow(1);
- row1.createCell(0).setCellValue(1);
-
- Row row2 = sheet.createRow(4);
- row2.createCell(1).setCellValue(2);
-
- Row row3 = sheet.createRow(5);
- row3.createCell(2).setCellValue(3);
-
- Row row4 = sheet.createRow(6);
- row4.createCell(3).setCellValue(4);
-
- Row row5 = sheet.createRow(9);
- row5.createCell(4).setCellValue(5);
-
- // Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5)
- sheet.shiftRows(5, 10, -4);
-
- try (FileOutputStream fileOut = new FileOutputStream("shiftRows.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * How to set split and freeze panes
- */
-public class SplitAndFreezePanes {
- public static void main(String[]args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) {
- Sheet sheet1 = wb.createSheet("new sheet");
- Sheet sheet2 = wb.createSheet("second sheet");
- Sheet sheet3 = wb.createSheet("third sheet");
- Sheet sheet4 = wb.createSheet("fourth sheet");
-
- // Freeze just one row
- sheet1.createFreezePane(0, 1, 0, 1);
- // Freeze just one column
- sheet2.createFreezePane(1, 0, 1, 0);
- // Freeze the columns and rows (forget about scrolling position of the lower right quadrant).
- sheet3.createFreezePane(2, 2);
- // Create a split with the lower left side being the active quadrant
- sheet4.createSplitPane(2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT);
-
- try (FileOutputStream fileOut = new FileOutputStream("splitFreezePane.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ooxml.POIXMLProperties;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * How to set extended and custom properties
- */
-public class WorkbookProperties {
-
- public static void main(String[]args) throws IOException {
- try (XSSFWorkbook workbook = new XSSFWorkbook()) {
- workbook.createSheet("Workbook Properties");
-
- POIXMLProperties props = workbook.getProperties();
-
- /*
- * Extended properties are a predefined set of metadata properties
- * that are specifically applicable to Office Open XML documents.
- * Extended properties consist of 24 simple properties and 3 complex properties stored in the
- * part targeted by the relationship of type
- */
- POIXMLProperties.ExtendedProperties ext = props.getExtendedProperties();
- ext.getUnderlyingProperties().setCompany("Apache Software Foundation");
- ext.getUnderlyingProperties().setTemplate("XSSF");
-
- /*
- * Custom properties enable users to define custom metadata properties.
- */
-
- POIXMLProperties.CustomProperties cust = props.getCustomProperties();
- cust.addProperty("Author", "John Smith");
- cust.addProperty("Year", 2009);
- cust.addProperty("Price", 45.50);
- cust.addProperty("Available", true);
-
- try (FileOutputStream out = new FileOutputStream("workbook.xlsx")) {
- workbook.write(out);
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Working with borders
- */
-public class WorkingWithBorders {
- public static void main(String[] args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet("borders");
-
- // Create a row and put some cells in it. Rows are 0 based.
- Row row = sheet.createRow((short) 1);
-
- // Create a cell and put a value in it.
- Cell cell = row.createCell((short) 1);
- cell.setCellValue(4);
-
- // Style the cell with borders all around.
- CellStyle style = wb.createCellStyle();
- style.setBorderBottom(BorderStyle.THIN);
- style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
- style.setBorderLeft(BorderStyle.THIN);
- style.setLeftBorderColor(IndexedColors.GREEN.getIndex());
- style.setBorderRight(BorderStyle.THIN);
- style.setRightBorderColor(IndexedColors.BLUE.getIndex());
- style.setBorderTop(BorderStyle.MEDIUM_DASHED);
- style.setTopBorderColor(IndexedColors.BLACK.getIndex());
- cell.setCellStyle(style);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("xssf-borders.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Working with Fonts
- */
-public class WorkingWithFonts {
- public static void main(String[] args) throws IOException {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
- Sheet sheet = wb.createSheet("Fonts");
-
- Font font0 = wb.createFont();
- font0.setColor(IndexedColors.BROWN.getIndex());
- CellStyle style0 = wb.createCellStyle();
- style0.setFont(font0);
-
- Font font1 = wb.createFont();
- font1.setFontHeightInPoints((short) 14);
- font1.setFontName("Courier New");
- font1.setColor(IndexedColors.RED.getIndex());
- CellStyle style1 = wb.createCellStyle();
- style1.setFont(font1);
-
- Font font2 = wb.createFont();
- font2.setFontHeightInPoints((short) 16);
- font2.setFontName("Arial");
- font2.setColor(IndexedColors.GREEN.getIndex());
- CellStyle style2 = wb.createCellStyle();
- style2.setFont(font2);
-
- Font font3 = wb.createFont();
- font3.setFontHeightInPoints((short) 18);
- font3.setFontName("Times New Roman");
- font3.setColor(IndexedColors.LAVENDER.getIndex());
- CellStyle style3 = wb.createCellStyle();
- style3.setFont(font3);
-
- Font font4 = wb.createFont();
- font4.setFontHeightInPoints((short) 18);
- font4.setFontName("Wingdings");
- font4.setColor(IndexedColors.GOLD.getIndex());
- CellStyle style4 = wb.createCellStyle();
- style4.setFont(font4);
-
- Font font5 = wb.createFont();
- font5.setFontName("Symbol");
- CellStyle style5 = wb.createCellStyle();
- style5.setFont(font5);
-
- Cell cell0 = sheet.createRow(0).createCell(1);
- cell0.setCellValue("Default");
- cell0.setCellStyle(style0);
-
- Cell cell1 = sheet.createRow(1).createCell(1);
- cell1.setCellValue("Courier");
- cell1.setCellStyle(style1);
-
- Cell cell2 = sheet.createRow(2).createCell(1);
- cell2.setCellValue("Arial");
- cell2.setCellStyle(style2);
-
- Cell cell3 = sheet.createRow(3).createCell(1);
- cell3.setCellValue("Times New Roman");
- cell3.setCellStyle(style3);
-
- Cell cell4 = sheet.createRow(4).createCell(1);
- cell4.setCellValue("Wingdings");
- cell4.setCellStyle(style4);
-
- Cell cell5 = sheet.createRow(5).createCell(1);
- cell5.setCellValue("Symbol");
- cell5.setCellStyle(style5);
-
- // Write the output to a file
- try (FileOutputStream fileOut = new FileOutputStream("xssf-fonts.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates various settings avaiable in the Page Setup dialog
- */
-public class WorkingWithPageSetup {
-
- public static void main(String[]args) throws Exception {
- try (Workbook wb = new XSSFWorkbook()) { //or new HSSFWorkbook();
-
- /*
- * It's possible to set up repeating rows and columns in your printouts by using the setRepeatingRowsAndColumns() function in the Workbook object.
- *
- * This function Contains 5 parameters:
- * The first parameter is the index to the sheet (0 = first sheet).
- * The second and third parameters specify the range for the columns to repreat.
- * To stop the columns from repeating pass in -1 as the start and end column.
- * The fourth and fifth parameters specify the range for the rows to repeat.
- * To stop the columns from repeating pass in -1 as the start and end rows.
- */
- Sheet sheet1 = wb.createSheet("new sheet");
- Sheet sheet2 = wb.createSheet("second sheet");
-
- // Set the columns to repeat from column 0 to 2 on the first sheet
- Row row1 = sheet1.createRow(0);
- row1.createCell(0).setCellValue(1);
- row1.createCell(1).setCellValue(2);
- row1.createCell(2).setCellValue(3);
- Row row2 = sheet1.createRow(1);
- row2.createCell(1).setCellValue(4);
- row2.createCell(2).setCellValue(5);
-
-
- Row row3 = sheet2.createRow(1);
- row3.createCell(0).setCellValue(2.1);
- row3.createCell(4).setCellValue(2.2);
- row3.createCell(5).setCellValue(2.3);
- Row row4 = sheet2.createRow(2);
- row4.createCell(4).setCellValue(2.4);
- row4.createCell(5).setCellValue(2.5);
-
- // Set the columns to repeat from column 0 to 2 on the first sheet
- sheet1.setRepeatingColumns(CellRangeAddress.valueOf("A:C"));
- // Set the the repeating rows and columns on the second sheet.
- CellRangeAddress cra = CellRangeAddress.valueOf("E2:F3");
- sheet2.setRepeatingColumns(cra);
- sheet2.setRepeatingRows(cra);
-
- //set the print area for the first sheet
- wb.setPrintArea(0, 1, 2, 0, 3);
-
-
- try (FileOutputStream fileOut = new FileOutputStream("xssf-printsetup.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.poi.ss.usermodel.ClientAnchor;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.Drawing;
-import org.apache.poi.ss.usermodel.Picture;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates how to insert pictures in a SpreadsheetML document
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class WorkingWithPictures {
- private WorkingWithPictures() {}
-
- public static void main(String[] args) throws IOException {
-
- //create a new workbook
- try (Workbook wb = new XSSFWorkbook()) {
- CreationHelper helper = wb.getCreationHelper();
-
- //add a picture in this workbook.
- InputStream is = new FileInputStream(args[0]);
- byte[] bytes = IOUtils.toByteArray(is);
- is.close();
- int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
-
- //create sheet
- Sheet sheet = wb.createSheet();
-
- //create drawing
- Drawing<?> drawing = sheet.createDrawingPatriarch();
-
- //add a picture shape
- ClientAnchor anchor = helper.createClientAnchor();
- anchor.setCol1(1);
- anchor.setRow1(1);
- Picture pict = drawing.createPicture(anchor, pictureIdx);
-
- //auto-size picture
- pict.resize(2);
-
- //save workbook
- String file = "picture.xls";
- if (wb instanceof XSSFWorkbook) {
- file += "x"; // NOSONAR
- }
- try (OutputStream fileOut = new FileOutputStream(file)) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xssf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFColor;
-import org.apache.poi.xssf.usermodel.XSSFFont;
-import org.apache.poi.xssf.usermodel.XSSFRichTextString;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Demonstrates how to work with rich text
- */
-public final class WorkingWithRichText {
-
- private WorkingWithRichText() {}
-
- public static void main(String[] args) throws Exception {
- try (XSSFWorkbook wb = new XSSFWorkbook()) {
- XSSFSheet sheet = wb.createSheet();
- XSSFRow row = sheet.createRow(2);
-
- XSSFCell cell = row.createCell(1);
- XSSFRichTextString rt = new XSSFRichTextString("The quick brown fox");
-
- XSSFFont font1 = wb.createFont();
- font1.setBold(true);
- font1.setColor(new XSSFColor(new java.awt.Color(255, 0, 0), wb.getStylesSource().getIndexedColors()));
- rt.applyFont(0, 10, font1);
-
- XSSFFont font2 = wb.createFont();
- font2.setItalic(true);
- font2.setUnderline(Font.U_DOUBLE);
- font2.setColor(new XSSFColor(new java.awt.Color(0, 255, 0), wb.getStylesSource().getIndexedColors()));
- rt.applyFont(10, 19, font2);
-
- XSSFFont font3 = wb.createFont();
- font3.setColor(new XSSFColor(new java.awt.Color(0, 0, 255), wb.getStylesSource().getIndexedColors()));
- rt.append(" Jumped over the lazy dog", font3);
-
- cell.setCellValue(rt);
-
- // Write the output to a file
- try (OutputStream fileOut = new FileOutputStream("xssf-richtext.xlsx")) {
- wb.write(fileOut);
- }
- }
- }
-}
+++ /dev/null
-
-/*
- * ====================================================================
- * 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.xwpf.usermodel.examples;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xddf.usermodel.chart.AxisOrientation;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.BarDirection;
-import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xwpf.usermodel.XWPFChart;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-
-/**
- * Build a bar chart from a template docx
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class BarChartExample {
- private BarChartExample() {}
-
- private static void usage(){
- System.out.println("Usage: BarChartExample <bar-chart-template.docx> <bar-chart-data.txt>");
- System.out.println(" bar-chart-template.docx template with a bar chart");
- System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
- "then go pairs {axis-label value}");
- }
-
- public static void main(String[] args) throws Exception {
- if(args.length < 2) {
- usage();
- return;
- }
-
- try (FileInputStream argIS = new FileInputStream(args[0]);
- BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
-
- String chartTitle = modelReader.readLine(); // first line is chart title
- String[] series = modelReader.readLine().split(",");
-
- // Category Axis Data
- List<String> listLanguages = new ArrayList<>(10);
-
- // Values
- List<Double> listCountries = new ArrayList<>(10);
- List<Double> listSpeakers = new ArrayList<>(10);
-
- // set model
- String ln;
- while((ln = modelReader.readLine()) != null) {
- String[] vals = ln.split(",");
- listCountries.add(Double.valueOf(vals[0]));
- listSpeakers.add(Double.valueOf(vals[1]));
- listLanguages.add(vals[2]);
- }
- String[] categories = listLanguages.toArray(new String[0]);
- Double[] values1 = listCountries.toArray(new Double[0]);
- Double[] values2 = listSpeakers.toArray(new Double[0]);
-
- try (XWPFDocument doc = new XWPFDocument(argIS)) {
- XWPFChart chart = doc.getCharts().get(0);
- setBarData(chart, chartTitle, series, categories, values1, values2);
- chart = doc.getCharts().get(1);
- setColumnData(chart, "Column variant");
-
- // save the result
- try (OutputStream out = new FileOutputStream("bar-chart-demo-output.docx")) {
- doc.write(out);
- }
- }
- }
- System.out.println("Done");
- }
-
- private static void setBarData(XWPFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
- final List<XDDFChartData> data = chart.getChartSeries();
- final XDDFBarChartData bar = (XDDFBarChartData) data.get(0);
-
- final int numOfPoints = categories.length;
- final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
- final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
- final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
- final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
- final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1);
- values1[6] = 16.0; // if you ever want to change the underlying data
- final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);
-
- XDDFChartData.Series series1 = bar.getSeries(0);
- series1.replaceData(categoriesData, valuesData);
- series1.setTitle(series[0], chart.setSheetTitle(series[0], 0));
- XDDFChartData.Series series2 = bar.addSeries(categoriesData, valuesData2);
- series2.setTitle(series[1], chart.setSheetTitle(series[1], 1));
-
- chart.plot(bar);
- chart.setTitleText(chartTitle); // https://stackoverflow.com/questions/30532612
- chart.setTitleOverlay(false);
- }
-
- private static void setColumnData(XWPFChart chart, String chartTitle) {
- // Series Text
- List<XDDFChartData> series = chart.getChartSeries();
- XDDFBarChartData bar = (XDDFBarChartData) series.get(0);
-
- // in order to transform a bar chart into a column chart, you just need to change the bar direction
- bar.setBarDirection(BarDirection.COL);
-
- // looking for "Stacked Bar Chart"? uncomment the following line
- // bar.setBarGrouping(BarGrouping.STACKED);
-
- // additionally, you can adjust the axes
- bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN);
- bar.getValueAxes().get(0).setPosition(AxisPosition.TOP);
- }
-}
-
+++ /dev/null
-/* ====================================================================
- 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.xwpf.usermodel.examples;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.poi.wp.usermodel.HeaderFooterType;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFFooter;
-import org.apache.poi.xwpf.usermodel.XWPFHeader;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
-
-public class BetterHeaderFooterExample {
-
- public static void main(String[] args) throws IOException {
- try (XWPFDocument doc = new XWPFDocument()) {
-
- XWPFParagraph p = doc.createParagraph();
-
- XWPFRun r = p.createRun();
- r.setText("Some Text");
- r.setBold(true);
- r = p.createRun();
- r.setText("Goodbye");
-
- // create header/footer functions insert an empty paragraph
- XWPFHeader head = doc.createHeader(HeaderFooterType.DEFAULT);
- head.createParagraph().createRun().setText("header");
-
- XWPFFooter foot = doc.createFooter(HeaderFooterType.DEFAULT);
- foot.createParagraph().createRun().setText("footer");
-
- try (OutputStream os = new FileOutputStream(new File("header2.docx"))) {
- doc.write(os);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xwpf.usermodel.examples;
-
-import java.io.BufferedReader;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xddf.usermodel.chart.AxisCrossBetween;
-import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
-import org.apache.poi.xddf.usermodel.chart.AxisPosition;
-import org.apache.poi.xddf.usermodel.chart.AxisTickMark;
-import org.apache.poi.xddf.usermodel.chart.BarDirection;
-import org.apache.poi.xddf.usermodel.chart.BarGrouping;
-import org.apache.poi.xddf.usermodel.chart.ChartTypes;
-import org.apache.poi.xddf.usermodel.chart.LegendPosition;
-import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
-import org.apache.poi.xddf.usermodel.chart.XDDFChart;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartAxis;
-import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
-import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
-import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
-import org.apache.poi.xwpf.usermodel.XWPFChart;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-
-/**
- * Build a chart without reading template file
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class ChartFromScratch {
- private ChartFromScratch() {}
-
- private static void usage(){
- System.out.println("Usage: ChartFromScratch <bar-chart-data.txt>");
- System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
- "then go pairs {axis-label value}");
- }
-
- public static void main(String[] args) throws Exception {
- if(args.length < 1) {
- usage();
- return;
- }
-
- try (BufferedReader modelReader = new BufferedReader(new FileReader(args[0]))) {
-
- String chartTitle = modelReader.readLine(); // first line is chart title
- String[] series = modelReader.readLine().split(",");
-
- // Category Axis Data
- List<String> listLanguages = new ArrayList<>(10);
-
- // Values
- List<Double> listCountries = new ArrayList<>(10);
- List<Double> listSpeakers = new ArrayList<>(10);
-
- // set model
- String ln;
- while((ln = modelReader.readLine()) != null) {
- String[] vals = ln.split(",");
- listCountries.add(Double.valueOf(vals[0]));
- listSpeakers.add(Double.valueOf(vals[1]));
- listLanguages.add(vals[2]);
- }
-
- String[] categories = listLanguages.toArray(new String[0]);
- Double[] values1 = listCountries.toArray(new Double[0]);
- Double[] values2 = listSpeakers.toArray(new Double[0]);
-
- try (XWPFDocument doc = new XWPFDocument();
- OutputStream out = new FileOutputStream("chart-from-scratch.docx")) {
- XWPFChart chart = doc.createChart(XDDFChart.DEFAULT_WIDTH * 10, XDDFChart.DEFAULT_HEIGHT * 15);
- setBarData(chart, chartTitle, series, categories, values1, values2);
- // save the result
- doc.write(out);
- }
- }
- System.out.println("Done");
- }
-
- private static void setBarData(XWPFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
- // Use a category axis for the bottom axis.
- XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
- bottomAxis.setTitle(series[2]);
- XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
- leftAxis.setTitle(series[0]+","+series[1]);
- leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
- leftAxis.setMajorTickMark(AxisTickMark.OUT);
- leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
-
- final int numOfPoints = categories.length;
- final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_LANGUAGES, COLUMN_LANGUAGES));
- final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_COUNTRIES, COLUMN_COUNTRIES));
- final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, COLUMN_SPEAKERS, COLUMN_SPEAKERS));
- final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, COLUMN_LANGUAGES);
- final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, COLUMN_COUNTRIES);
- valuesData.setFormatCode("General");
- values1[6] = 16.0; // if you ever want to change the underlying data, it has to be done before building the data source
- final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, COLUMN_SPEAKERS);
- valuesData2.setFormatCode("General");
-
-
- XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
- bar.setBarGrouping(BarGrouping.CLUSTERED);
-
- XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
- series1.setTitle(series[0], chart.setSheetTitle(series[0], COLUMN_COUNTRIES));
-
- XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
- series2.setTitle(series[1], chart.setSheetTitle(series[1], COLUMN_SPEAKERS));
-
- bar.setVaryColors(true);
- bar.setBarDirection(BarDirection.COL);
- chart.plot(bar);
-
- XDDFChartLegend legend = chart.getOrAddLegend();
- legend.setPosition(LegendPosition.LEFT);
- legend.setOverlay(false);
-
- chart.setTitleText(chartTitle);
- chart.setTitleOverlay(false);
- chart.setAutoTitleDeleted(false);
- }
-
- private static final int COLUMN_LANGUAGES = 0;
- private static final int COLUMN_COUNTRIES = 1;
- private static final int COLUMN_SPEAKERS = 2;
-}
-
+++ /dev/null
-/* ====================================================================
- 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.xwpf.usermodel.examples;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.math.BigInteger;
-
-import org.apache.poi.wp.usermodel.HeaderFooterType;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFFooter;
-import org.apache.poi.xwpf.usermodel.XWPFHeader;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
-import org.apache.poi.xwpf.usermodel.XWPFTable;
-import org.apache.poi.xwpf.usermodel.XWPFTableCell;
-import org.apache.poi.xwpf.usermodel.XWPFTableRow;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblLayoutType;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblLayoutType;
-
-public class HeaderFooterTable {
-
- public static void main(String[] args) throws IOException {
- try (XWPFDocument doc = new XWPFDocument()) {
-
- // Create a header with a 1 row, 3 column table
- // changes made for issue 57366 allow a new header or footer
- // to be created empty. This is a change. You will have to add
- // either a paragraph or a table to the header or footer for
- // the document to be considered valid.
- XWPFHeader hdr = doc.createHeader(HeaderFooterType.DEFAULT);
- XWPFTable tbl = hdr.createTable(1, 3);
-
- // Set the padding around text in the cells to 1/10th of an inch
- int pad = (int) (.1 * 1440);
- tbl.setCellMargins(pad, pad, pad, pad);
-
- // Set table width to 6.5 inches in 1440ths of a point
- tbl.setWidth((int) (6.5 * 1440));
- // Can not yet set table or cell width properly, tables default to
- // autofit layout, and this requires fixed layout
- CTTbl ctTbl = tbl.getCTTbl();
- CTTblPr ctTblPr = ctTbl.addNewTblPr();
- CTTblLayoutType layoutType = ctTblPr.addNewTblLayout();
- layoutType.setType(STTblLayoutType.FIXED);
-
- // Now set up a grid for the table, cells will fit into the grid
- // Each cell width is 3120 in 1440ths of an inch, or 1/3rd of 6.5"
- BigInteger w = BigInteger.valueOf(3120);
- CTTblGrid grid = ctTbl.addNewTblGrid();
- for (int i = 0; i < 3; i++) {
- CTTblGridCol gridCol = grid.addNewGridCol();
- gridCol.setW(w);
- }
-
- // Add paragraphs to the cells
- XWPFTableRow row = tbl.getRow(0);
- XWPFTableCell cell = row.getCell(0);
- XWPFParagraph p = cell.getParagraphArray(0);
- XWPFRun r = p.createRun();
- r.setText("header left cell");
-
- cell = row.getCell(1);
- p = cell.getParagraphArray(0);
- r = p.createRun();
- r.setText("header center cell");
-
- cell = row.getCell(2);
- p = cell.getParagraphArray(0);
- r = p.createRun();
- r.setText("header right cell");
-
- // Create a footer with a Paragraph
- XWPFFooter ftr = doc.createFooter(HeaderFooterType.DEFAULT);
- p = ftr.createParagraph();
-
- r = p.createRun();
- r.setText("footer text");
-
- try (OutputStream os = new FileOutputStream(new File("headertable.docx"))) {
- doc.write(os);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xwpf.usermodel.examples;
-
-import java.io.FileOutputStream;
-
-import org.apache.poi.xwpf.usermodel.Borders;
-import org.apache.poi.xwpf.usermodel.BreakClear;
-import org.apache.poi.xwpf.usermodel.BreakType;
-import org.apache.poi.xwpf.usermodel.LineSpacingRule;
-import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
-import org.apache.poi.xwpf.usermodel.TextAlignment;
-import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
-import org.apache.poi.xwpf.usermodel.VerticalAlign;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
-
-/**
- * A simple WOrdprocessingML document created by POI XWPF API
- */
-public class SimpleDocument {
-
- public static void main(String[] args) throws Exception {
- try (XWPFDocument doc = new XWPFDocument()) {
-
- XWPFParagraph p1 = doc.createParagraph();
- p1.setAlignment(ParagraphAlignment.CENTER);
- p1.setBorderBottom(Borders.DOUBLE);
- p1.setBorderTop(Borders.DOUBLE);
-
- p1.setBorderRight(Borders.DOUBLE);
- p1.setBorderLeft(Borders.DOUBLE);
- p1.setBorderBetween(Borders.SINGLE);
-
- p1.setVerticalAlignment(TextAlignment.TOP);
-
- XWPFRun r1 = p1.createRun();
- r1.setBold(true);
- r1.setText("The quick brown fox");
- r1.setBold(true);
- r1.setFontFamily("Courier");
- r1.setUnderline(UnderlinePatterns.DOT_DOT_DASH);
- r1.setTextPosition(100);
-
- XWPFParagraph p2 = doc.createParagraph();
- p2.setAlignment(ParagraphAlignment.RIGHT);
-
- //BORDERS
- p2.setBorderBottom(Borders.DOUBLE);
- p2.setBorderTop(Borders.DOUBLE);
- p2.setBorderRight(Borders.DOUBLE);
- p2.setBorderLeft(Borders.DOUBLE);
- p2.setBorderBetween(Borders.SINGLE);
-
- XWPFRun r2 = p2.createRun();
- r2.setText("jumped over the lazy dog");
- r2.setStrikeThrough(true);
- r2.setFontSize(20);
-
- XWPFRun r3 = p2.createRun();
- r3.setText("and went away");
- r3.setStrikeThrough(true);
- r3.setFontSize(20);
- r3.setSubscript(VerticalAlign.SUPERSCRIPT);
-
- // hyperlink
- XWPFHyperlinkRun hyperlink = p2.insertNewHyperlinkRun(0, "http://poi.apache.org/");
- hyperlink.setUnderline(UnderlinePatterns.SINGLE);
- hyperlink.setColor("0000ff");
- hyperlink.setText("Apache POI");
-
- XWPFParagraph p3 = doc.createParagraph();
- p3.setWordWrapped(true);
- p3.setPageBreak(true);
-
- //p3.setAlignment(ParagraphAlignment.DISTRIBUTE);
- p3.setAlignment(ParagraphAlignment.BOTH);
- p3.setSpacingBetween(15, LineSpacingRule.EXACT);
-
- p3.setIndentationFirstLine(600);
-
-
- XWPFRun r4 = p3.createRun();
- r4.setTextPosition(20);
- r4.setText("To be, or not to be: that is the question: "
- + "Whether 'tis nobler in the mind to suffer "
- + "The slings and arrows of outrageous fortune, "
- + "Or to take arms against a sea of troubles, "
- + "And by opposing end them? To die: to sleep; ");
- r4.addBreak(BreakType.PAGE);
- r4.setText("No more; and by a sleep to say we end "
- + "The heart-ache and the thousand natural shocks "
- + "That flesh is heir to, 'tis a consummation "
- + "Devoutly to be wish'd. To die, to sleep; "
- + "To sleep: perchance to dream: ay, there's the rub; "
- + ".......");
- r4.setItalic(true);
-//This would imply that this break shall be treated as a simple line break, and break the line after that word:
-
- XWPFRun r5 = p3.createRun();
- r5.setTextPosition(-10);
- r5.setText("For in that sleep of death what dreams may come");
- r5.addCarriageReturn();
- r5.setText("When we have shuffled off this mortal coil, "
- + "Must give us pause: there's the respect "
- + "That makes calamity of so long life;");
- r5.addBreak();
- r5.setText("For who would bear the whips and scorns of time, "
- + "The oppressor's wrong, the proud man's contumely,");
-
- r5.addBreak(BreakClear.ALL);
- r5.setText("The pangs of despised love, the law's delay, "
- + "The insolence of office and the spurns " + ".......");
-
- try (FileOutputStream out = new FileOutputStream("simple.docx")) {
- doc.write(out);
- }
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.xwpf.usermodel.examples;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
-
-/**
- *
- * @author Richard Ngo
- *
- */
-public class SimpleDocumentWithHeader {
-
- public static void main(String[] args) throws IOException {
- try (XWPFDocument doc = new XWPFDocument()) {
-
- XWPFParagraph p = doc.createParagraph();
-
- XWPFRun r = p.createRun();
- r.setText("Some Text");
- r.setBold(true);
- r = p.createRun();
- r.setText("Goodbye");
-
- CTP ctP = CTP.Factory.newInstance();
- CTText t = ctP.addNewR().addNewT();
- t.setStringValue("header");
- XWPFParagraph[] pars = new XWPFParagraph[1];
- p = new XWPFParagraph(ctP, doc);
- pars[0] = p;
-
- XWPFHeaderFooterPolicy hfPolicy = doc.createHeaderFooterPolicy();
- hfPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT, pars);
-
- ctP = CTP.Factory.newInstance();
- t = ctP.addNewR().addNewT();
- t.setStringValue("My Footer");
- pars[0] = new XWPFParagraph(ctP, doc);
- hfPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT, pars);
-
- try (OutputStream os = new FileOutputStream(new File("header.docx"))) {
- doc.write(os);
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * ====================================================================
- * 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.xwpf.usermodel.examples;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.util.Units;
-import org.apache.poi.xwpf.usermodel.BreakType;
-import org.apache.poi.xwpf.usermodel.Document;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
-
-/**
- * Demonstrates how to add pictures in a .docx document
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public final class SimpleImages {
-
- private SimpleImages() {}
-
- public static void main(String[] args) throws IOException, InvalidFormatException {
- try (XWPFDocument doc = new XWPFDocument()) {
- XWPFParagraph p = doc.createParagraph();
-
- XWPFRun r = p.createRun();
-
- for (String imgFile : args) {
- int format;
-
- if (imgFile.endsWith(".emf")) {
- format = Document.PICTURE_TYPE_EMF;
- } else if (imgFile.endsWith(".wmf")) {
- format = Document.PICTURE_TYPE_WMF;
- } else if (imgFile.endsWith(".pict")) {
- format = Document.PICTURE_TYPE_PICT;
- } else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) {
- format = Document.PICTURE_TYPE_JPEG;
- } else if (imgFile.endsWith(".png")) {
- format = Document.PICTURE_TYPE_PNG;
- } else if (imgFile.endsWith(".dib")) {
- format = Document.PICTURE_TYPE_DIB;
- } else if (imgFile.endsWith(".gif")) {
- format = Document.PICTURE_TYPE_GIF;
- } else if (imgFile.endsWith(".tiff")) {
- format = Document.PICTURE_TYPE_TIFF;
- } else if (imgFile.endsWith(".eps")) {
- format = Document.PICTURE_TYPE_EPS;
- } else if (imgFile.endsWith(".bmp")) {
- format = Document.PICTURE_TYPE_BMP;
- } else if (imgFile.endsWith(".wpg")) {
- format = Document.PICTURE_TYPE_WPG;
- } else {
- System.err.println("Unsupported picture: " + imgFile +
- ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
- continue;
- }
-
- r.setText(imgFile);
- r.addBreak();
- try (FileInputStream is = new FileInputStream(imgFile)) {
- r.addPicture(is, format, imgFile, Units.toEMU(200), Units.toEMU(200)); // 200x200 pixels
- }
- r.addBreak(BreakType.PAGE);
- }
-
- try (FileOutputStream out = new FileOutputStream("images.docx")) {
- doc.write(out);
- }
- }
- }
-
-
-}
+++ /dev/null
-/* ====================================================================
- 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.xwpf.usermodel.examples;
-
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import java.math.BigInteger;
-import java.util.List;
-
-import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
-import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
-import org.apache.poi.xwpf.usermodel.XWPFTable;
-import org.apache.poi.xwpf.usermodel.XWPFTableCell;
-import org.apache.poi.xwpf.usermodel.XWPFTableRow;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHeight;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalJc;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.STShd;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
-
-/**
- * This program creates a simple WordprocessingML table using POI XWPF API, and
- * a more complex, styled table using both XWPF and ooxml-schema. It's possible
- * that not all referenced wordprocessingml classes are defined in
- * poi-ooxml-schemas-3.8-beta4. If this is the case, you'll need to use the full
- * ooxml-schemas.jar library.
- *
- * @author gisella bronzetti (original)
- * @author Gregg Morris (styled table)
- */
-public class SimpleTable {
-
- public static void main(String[] args) throws Exception {
- try {
- createSimpleTable();
- }
- catch(Exception e) {
- System.out.println("Error trying to create simple table.");
- throw(e);
- }
- try {
- createStyledTable();
- }
- catch(Exception e) {
- System.out.println("Error trying to create styled table.");
- throw(e);
- }
- }
-
- public static void createSimpleTable() throws Exception {
- try (XWPFDocument doc = new XWPFDocument()) {
- XWPFTable table = doc.createTable(3, 3);
-
- table.getRow(1).getCell(1).setText("EXAMPLE OF TABLE");
-
- // table cells have a list of paragraphs; there is an initial
- // paragraph created when the cell is created. If you create a
- // paragraph in the document to put in the cell, it will also
- // appear in the document following the table, which is probably
- // not the desired result.
- XWPFParagraph p1 = table.getRow(0).getCell(0).getParagraphs().get(0);
-
- XWPFRun r1 = p1.createRun();
- r1.setBold(true);
- r1.setText("The quick brown fox");
- r1.setItalic(true);
- r1.setFontFamily("Courier");
- r1.setUnderline(UnderlinePatterns.DOT_DOT_DASH);
- r1.setTextPosition(100);
-
- table.getRow(2).getCell(2).setText("only text");
-
- try (OutputStream out = new FileOutputStream("simpleTable.docx")) {
- doc.write(out);
- }
- }
- }
-
- /**
- * Create a table with some row and column styling. I "manually" add the
- * style name to the table, but don't check to see if the style actually
- * exists in the document. Since I'm creating it from scratch, it obviously
- * won't exist. When opened in MS Word, the table style becomes "Normal".
- * I manually set alternating row colors. This could be done using Themes,
- * but that's left as an exercise for the reader. The cells in the last
- * column of the table have 10pt. "Courier" font.
- * I make no claims that this is the "right" way to do it, but it worked
- * for me. Given the scarcity of XWPF examples, I thought this may prove
- * instructive and give you ideas for your own solutions.
- */
- public static void createStyledTable() throws Exception {
- // Create a new document from scratch
-
- try (XWPFDocument doc = new XWPFDocument()) {
- // -- OR --
- // open an existing empty document with styles already defined
- //XWPFDocument doc = new XWPFDocument(new FileInputStream("base_document.docx"));
-
- // Create a new table with 6 rows and 3 columns
- int nRows = 6;
- int nCols = 3;
- XWPFTable table = doc.createTable(nRows, nCols);
-
- // Set the table style. If the style is not defined, the table style
- // will become "Normal".
- CTTblPr tblPr = table.getCTTbl().getTblPr();
- CTString styleStr = tblPr.addNewTblStyle();
- styleStr.setVal("StyledTable");
-
- // Get a list of the rows in the table
- List<XWPFTableRow> rows = table.getRows();
- int rowCt = 0;
- int colCt = 0;
- for (XWPFTableRow row : rows) {
- // get table row properties (trPr)
- CTTrPr trPr = row.getCtRow().addNewTrPr();
- // set row height; units = twentieth of a point, 360 = 0.25"
- CTHeight ht = trPr.addNewTrHeight();
- ht.setVal(BigInteger.valueOf(360));
-
- // get the cells in this row
- List<XWPFTableCell> cells = row.getTableCells();
- // add content to each cell
- for (XWPFTableCell cell : cells) {
- // get a table cell properties element (tcPr)
- CTTcPr tcpr = cell.getCTTc().addNewTcPr();
- // set vertical alignment to "center"
- CTVerticalJc va = tcpr.addNewVAlign();
- va.setVal(STVerticalJc.CENTER);
-
- // create cell color element
- CTShd ctshd = tcpr.addNewShd();
- ctshd.setColor("auto");
- ctshd.setVal(STShd.CLEAR);
- if (rowCt == 0) {
- // header row
- ctshd.setFill("A7BFDE");
- } else if (rowCt % 2 == 0) {
- // even row
- ctshd.setFill("D3DFEE");
- } else {
- // odd row
- ctshd.setFill("EDF2F8");
- }
-
- // get 1st paragraph in cell's paragraph list
- XWPFParagraph para = cell.getParagraphs().get(0);
- // create a run to contain the content
- XWPFRun rh = para.createRun();
- // style cell as desired
- if (colCt == nCols - 1) {
- // last column is 10pt Courier
- rh.setFontSize(10);
- rh.setFontFamily("Courier");
- }
- if (rowCt == 0) {
- // header row
- rh.setText("header row, col " + colCt);
- rh.setBold(true);
- para.setAlignment(ParagraphAlignment.CENTER);
- } else {
- // other rows
- rh.setText("row " + rowCt + ", col " + colCt);
- para.setAlignment(ParagraphAlignment.LEFT);
- }
- colCt++;
- } // for cell
- colCt = 0;
- rowCt++;
- } // for row
-
- // write the file
- try (OutputStream out = new FileOutputStream("styledTable.docx")) {
- doc.write(out);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xwpf.usermodel.examples;
-
-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.util.List;
-
-import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-
-/**
- * Tests whether it is possible to successfully update an Excel workbook that is
- * embedded into a WordprocessingML document. Note that the test has currently
- * only been conducted with a binary Excel workbook and NOT yet with a
- * SpreadsheetML workbook embedded into the document.<p>
- *
- * This code was successfully tested with the following file from the POI test collection:
- * http://svn.apache.org/repos/asf/poi/trunk/test-data/document/EmbeddedDocument.docx
- */
-@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
-public class UpdateEmbeddedDoc {
-
- private XWPFDocument doc;
- private File docFile;
-
- private static final int SHEET_NUM = 0;
- private static final int ROW_NUM = 0;
- private static final int CELL_NUM = 0;
- private static final double NEW_VALUE = 100.98D;
- private static final String BINARY_EXTENSION = "xls";
- private static final String OPENXML_EXTENSION = "xlsx";
-
- /**
- * Create a new instance of the UpdateEmbeddedDoc class using the following
- * parameters;
- *
- * @param filename An instance of the String class that encapsulates the name
- * of and path to a WordprocessingML Word document that contains an
- * embedded binary Excel workbook.
- * @throws java.io.FileNotFoundException Thrown if the file cannot be found
- * on the underlying file system.
- * @throws java.io.IOException Thrown if a problem occurs in the underlying
- * file system.
- */
- public UpdateEmbeddedDoc(String filename) throws FileNotFoundException, IOException {
- this.docFile = new File(filename);
- if (!this.docFile.exists()) {
- throw new FileNotFoundException("The Word document " + filename + " does not exist.");
- }
- try (FileInputStream fis = new FileInputStream(this.docFile)) {
- // Open the Word document file and instantiate the XWPFDocument class.
- this.doc = new XWPFDocument(fis);
- }
- }
-
- /**
- * Called to update the embedded Excel workbook. As the format and structure
- * of the workbook are known in advance, all this code attempts to do is
- * write a new value into the first cell on the first row of the first
- * worksheet. Prior to executing this method, that cell will contain the
- * value 1.
- *
- * @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException
- * Rather
- * than use the specific classes (HSSF/XSSF) to handle the embedded
- * workbook this method uses those defined in the SS stream. As
- * a result, it might be the case that a SpreadsheetML file is
- * opened for processing, throwing this exception if that file is
- * invalid.
- * @throws java.io.IOException Thrown if a problem occurs in the underlying
- * file system.
- */
- public void updateEmbeddedDoc() throws OpenXML4JException, IOException {
- List<PackagePart> embeddedDocs = this.doc.getAllEmbeddedParts();
- for (PackagePart pPart : embeddedDocs) {
- String ext = pPart.getPartName().getExtension();
- if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) {
- // Get an InputStream from the package part and pass that
- // to the create method of the WorkbookFactory class. Update
- // the resulting Workbook and then stream that out again
- // using an OutputStream obtained from the same PackagePart.
- try (InputStream is = pPart.getInputStream();
- Workbook workbook = WorkbookFactory.create(is);
- OutputStream os = pPart.getOutputStream()) {
- Sheet sheet = workbook.getSheetAt(SHEET_NUM);
- Row row = sheet.getRow(ROW_NUM);
- Cell cell = row.getCell(CELL_NUM);
- cell.setCellValue(NEW_VALUE);
- workbook.write(os);
- }
- }
- }
-
- if (!embeddedDocs.isEmpty()) {
- // Finally, write the newly modified Word document out to file.
- try (FileOutputStream fos = new FileOutputStream(this.docFile)) {
- this.doc.write(fos);
- }
- }
- }
-
- /**
- * Called to test whether or not the embedded workbook was correctly
- * updated. This method simply recovers the first cell from the first row
- * of the first workbook and tests the value it contains.
- * <p>
- * Note that execution will not continue up to the assertion as the
- * embedded workbook is now corrupted and causes an IllegalArgumentException
- * with the following message
- * <p>
- * <em>java.lang.IllegalArgumentException: Your InputStream was neither an
- * OLE2 stream, nor an OOXML stream</em>
- * <p>
- * to be thrown when the WorkbookFactory.createWorkbook(InputStream) method
- * is executed.
- *
- * @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException
- * Rather
- * than use the specific classes (HSSF/XSSF) to handle the embedded
- * workbook this method uses those defined in the SS stream. As
- * a result, it might be the case that a SpreadsheetML file is
- * opened for processing, throwing this exception if that file is
- * invalid.
- * @throws java.io.IOException Thrown if a problem occurs in the underlying
- * file system.
- */
- public void checkUpdatedDoc() throws OpenXML4JException, IOException {
- for (PackagePart pPart : this.doc.getAllEmbeddedParts()) {
- String ext = pPart.getPartName().getExtension();
- if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) {
- try (InputStream is = pPart.getInputStream();
- Workbook workbook = WorkbookFactory.create(is)) {
- Sheet sheet = workbook.getSheetAt(SHEET_NUM);
- Row row = sheet.getRow(ROW_NUM);
- Cell cell = row.getCell(CELL_NUM);
- if(cell.getNumericCellValue() != NEW_VALUE) {
- throw new IllegalStateException("Failed to validate document content.");
- }
- }
- }
- }
- }
-
- /**
- * Code to test updating of the embedded Excel workbook.
- */
- public static void main(String[] args) throws IOException, OpenXML4JException {
- UpdateEmbeddedDoc ued = new UpdateEmbeddedDoc(args[0]);
- ued.updateEmbeddedDoc();
- ued.checkUpdatedDoc();
- }
-}
+++ /dev/null
-10 languages with most speakers as first language\r
-countries,speakers,language\r
-58,315,العربية\r
-4,243,বাংলা\r
-38,1299,中文\r
-118,378,English\r
-4,260,हिन्दी\r
-2,128,日本語\r
-15,223,português\r
-6,119,ਪੰਜਾਬੀ\r
-18,154,Русский язык\r
-31,442,español\r
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.formula;
-
-import org.apache.poi.ss.formula.OperationEvaluationContext ;
-import org.apache.poi.ss.formula.eval.ErrorEval ;
-import org.apache.poi.ss.formula.eval.EvaluationException ;
-import org.apache.poi.ss.formula.eval.NumberEval ;
-import org.apache.poi.ss.formula.eval.OperandResolver ;
-import org.apache.poi.ss.formula.eval.ValueEval ;
-import org.apache.poi.ss.formula.functions.FreeRefFunction ;
-
-/**
- * A simple user-defined function to calculate principal and interest.
- *
- * Used by {@link org.apache.poi.ss.excelant.util.TestExcelAntWorkbookUtil}.
- *
- * @author Jon Svede ( jon [at] loquatic [dot] com )
- * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
- *
- */
-public class CalculateMortgageFunction implements FreeRefFunction {
-
- @Override
- public ValueEval evaluate( ValueEval[] args, OperationEvaluationContext ec ) {
-
- // verify that we have enough data
- if (args.length != 3) {
- return ErrorEval.VALUE_INVALID;
- }
-
- // declare doubles for values
- double principal, rate, years, result;
- try {
- // extract values as ValueEval
- ValueEval v1 = OperandResolver.getSingleValue( args[0],
- ec.getRowIndex(),
- ec.getColumnIndex() ) ;
- ValueEval v2 = OperandResolver.getSingleValue( args[1],
- ec.getRowIndex(),
- ec.getColumnIndex() ) ;
- ValueEval v3 = OperandResolver.getSingleValue( args[2],
- ec.getRowIndex(),
- ec.getColumnIndex() ) ;
-
- // get data as doubles
- principal = OperandResolver.coerceValueToDouble( v1 ) ;
- rate = OperandResolver.coerceValueToDouble( v2 ) ;
- years = OperandResolver.coerceValueToDouble( v3 ) ;
-
- result = calculateMortgagePayment( principal, rate, years ) ;
- System.out.println( "Result = " + result ) ;
-
- checkValue(result);
-
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
-
- return new NumberEval( result ) ;
- }
-
- public double calculateMortgagePayment( double p, double r, double y ) {
- double i = r / 12 ;
- double n = y * 12 ;
-
- return p * (( i * Math.pow((1 + i),n ) ) / ( Math.pow((1 + i),n) - 1));
- }
- /**
- * Excel does not support infinities and NaNs, rather, it gives a #NUM! error in these cases
- *
- * @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</> or <tt>Infinity</tt>
- */
- private void checkValue(double result) throws EvaluationException {
- if (Double.isNaN(result) || Double.isInfinite(result)) {
- throw new EvaluationException(ErrorEval.NUM_ERROR);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.formula;
-
-import org.apache.poi.ss.excelant.ExcelAntUserDefinedFunction;
-
-public class ExcelAntUserDefinedFunctionTestHelper extends
- ExcelAntUserDefinedFunction {
-
- @Override
- protected String getFunctionAlias() {
- // TODO Auto-generated method stub
- return super.getFunctionAlias();
- }
-
- @Override
- protected String getClassName() {
- // TODO Auto-generated method stub
- return super.getClassName();
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.examples.formula;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestExcelAntUserDefinedFunction {
-
- private ExcelAntUserDefinedFunctionTestHelper fixture ;
-
- @Before
- public void setUp() {
- fixture = new ExcelAntUserDefinedFunctionTestHelper() ;
- }
-
- @Test
- public void testSetClassName() {
- String className = "simple.class.name" ;
-
- fixture.setClassName( className ) ;
- String value = fixture.getClassName() ;
-
- assertNotNull( value ) ;
- assertEquals( className, value ) ;
- }
-
- @Test
- public void testSetFunction() {
- String functionAlias = "alias" ;
-
- fixture.setFunctionAlias( functionAlias ) ;
-
- String alias = fixture.getFunctionAlias() ;
-
- assertNotNull( alias ) ;
- assertEquals( functionAlias, alias ) ;
- }
-
-}
--- /dev/null
+/* ====================================================================
+ 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.ss.excelant;
+
+import org.apache.poi.ss.formula.OperationEvaluationContext;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.OperandResolver;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+
+/**
+ * A simple user-defined function to calculate principal and interest.
+ *
+ * Used by {@link org.apache.poi.ss.excelant.util.TestExcelAntWorkbookUtil}.
+ *
+ * @author Jon Svede ( jon [at] loquatic [dot] com )
+ * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
+ *
+ */
+public class CalculateMortgageFunction implements FreeRefFunction {
+
+ @Override
+ public ValueEval evaluate( ValueEval[] args, OperationEvaluationContext ec ) {
+
+ // verify that we have enough data
+ if (args.length != 3) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ // declare doubles for values
+ double principal, rate, years, result;
+ try {
+ // extract values as ValueEval
+ ValueEval v1 = OperandResolver.getSingleValue( args[0],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+ ValueEval v2 = OperandResolver.getSingleValue( args[1],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+ ValueEval v3 = OperandResolver.getSingleValue( args[2],
+ ec.getRowIndex(),
+ ec.getColumnIndex() ) ;
+
+ // get data as doubles
+ principal = OperandResolver.coerceValueToDouble( v1 ) ;
+ rate = OperandResolver.coerceValueToDouble( v2 ) ;
+ years = OperandResolver.coerceValueToDouble( v3 ) ;
+
+ result = calculateMortgagePayment( principal, rate, years ) ;
+ System.out.println( "Result = " + result ) ;
+
+ checkValue(result);
+
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+
+ return new NumberEval( result ) ;
+ }
+
+ public double calculateMortgagePayment( double p, double r, double y ) {
+ double i = r / 12 ;
+ double n = y * 12 ;
+
+ return p * (( i * Math.pow((1 + i),n ) ) / ( Math.pow((1 + i),n) - 1));
+ }
+ /**
+ * Excel does not support infinities and NaNs, rather, it gives a #NUM! error in these cases
+ *
+ * @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</> or <tt>Infinity</tt>
+ */
+ private void checkValue(double result) throws EvaluationException {
+ if (Double.isNaN(result) || Double.isInfinite(result)) {
+ throw new EvaluationException(ErrorEval.NUM_ERROR);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.excelant;
+
+public class ExcelAntUserDefinedFunctionTestHelper extends
+ ExcelAntUserDefinedFunction {
+
+ @Override
+ protected String getFunctionAlias() {
+ // TODO Auto-generated method stub
+ return super.getFunctionAlias();
+ }
+
+ @Override
+ protected String getClassName() {
+ // TODO Auto-generated method stub
+ return super.getClassName();
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.excelant;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestExcelAntUserDefinedFunction {
+
+ private ExcelAntUserDefinedFunctionTestHelper fixture ;
+
+ @Before
+ public void setUp() {
+ fixture = new ExcelAntUserDefinedFunctionTestHelper() ;
+ }
+
+ @Test
+ public void testSetClassName() {
+ String className = "simple.class.name" ;
+
+ fixture.setClassName( className ) ;
+ String value = fixture.getClassName() ;
+
+ assertNotNull( value ) ;
+ assertEquals( className, value ) ;
+ }
+
+ @Test
+ public void testSetFunction() {
+ String functionAlias = "alias" ;
+
+ fixture.setFunctionAlias( functionAlias ) ;
+
+ String alias = fixture.getFunctionAlias() ;
+
+ assertNotNull( alias ) ;
+ assertEquals( functionAlias, alias ) ;
+ }
+
+}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<!--
+<!--
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
<target name="test-udf">
<poi:excelant fileName="${data.dir.name}/spreadsheet/excelant.xls">
<poi:udf functionAlias="calculatePayment"
- className="org.apache.poi.ss.examples.formula.CalculateMortgageFunction"/>
+ className="org.apache.poi.ss.excelant.CalculateMortgageFunction"/>
<poi:test>
<poi:setDouble cell="'MortageCalculatorFunction'!$B$1" value="240000"/>
<poi:setDouble cell="'MortageCalculatorFunction'!$B$2" value ="0.11"/>
import java.util.Date;
import java.util.List;
-import org.apache.poi.ss.examples.formula.CalculateMortgageFunction;
+import org.apache.poi.ss.excelant.CalculateMortgageFunction;
import org.apache.poi.ss.excelant.TestBuildFile;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.DateUtil;
+++ /dev/null
-/* ====================================================================
- 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;
-
-import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
-import org.apache.poi.stress.FileHandler;
-import org.apache.poi.stress.HSLFFileHandler;
-import org.apache.poi.stress.HSSFFileHandler;
-import org.apache.poi.stress.HWPFFileHandler;
-import org.apache.poi.stress.XSLFFileHandler;
-import org.apache.poi.stress.XSSFFileHandler;
-import org.apache.poi.stress.XWPFFileHandler;
-import org.junit.Assume;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.zip.ZipException;
-
-import static org.junit.Assert.assertNotNull;
-
-/**
- * This class is used for mass-regression testing via a
- * separate project, this class provides functionality to
- * run integration tests on one file and handle some
- * types of files/exceptions, e.g. old file formats.
- *
- */
-public class BaseIntegrationTest {
- private final File rootDir;
- private String file;
- private FileHandler handler;
-
- public BaseIntegrationTest(File rootDir, String file, FileHandler handler) {
- this.rootDir = rootDir;
- this.file = file;
- this.handler = handler;
- }
-
- public void test() throws Exception {
- assertNotNull("Unknown file extension for file: " + file + ": " + TestAllFiles.getExtension(file), handler);
- testOneFile(new File(rootDir, file));
- }
-
- protected void testOneFile(File inputFile) throws Exception {
- try {
- handleFile(inputFile);
- } catch (OfficeXmlFileException e) {
- // switch XWPF and HWPF and so forth depending on the error message
- handleWrongOLE2XMLExtension(inputFile, e);
- } catch (OldFileFormatException e) {
- // Not even text extraction is supported for these: handler.handleExtracting(inputFile);
- Assume.assumeFalse("File " + file + " excluded because it is unsupported old Excel format", true);
- } catch (EncryptedDocumentException e) {
- // Do not try to read encrypted files
- Assume.assumeFalse("File " + file + " excluded because it is password-encrypted", true);
- } catch (ZipException e) {
- // some files are corrupted
- if (e.getMessage().equals("unexpected EOF") || e.getMessage().equals("Truncated ZIP file")) {
- Assume.assumeFalse("File " + file + " excluded because the Zip file is incomplete", true);
- }
-
- throw e;
- } catch (IOException e) {
- // ignore some other ways of corrupted files
- String message = e.getMessage();
- if(message != null && message.contains("Truncated ZIP file")) {
- Assume.assumeFalse("File " + file + " excluded because the Zip file is incomplete", true);
- }
-
- // sometimes binary format has XML-format-extension...
- if(message != null && message.contains("rong file format or file extension for OO XML file")) {
- handleWrongOLE2XMLExtension(inputFile, e);
- return;
- }
-
- throw e;
- } catch (IllegalArgumentException e) {
- // ignore errors for documents with incorrect extension
- String message = e.getMessage();
- if(message != null && (message.equals("The document is really a RTF file") ||
- message.equals("The document is really a PDF file") ||
- message.equals("The document is really a HTML file"))) {
- Assume.assumeFalse("File " + file + " excluded because it is actually a PDF/RTF/HTML file", true);
- }
-
- if(message != null && message.equals("The document is really a OOXML file")) {
- handleWrongOLE2XMLExtension(inputFile, e);
- return;
- }
-
- throw e;
- }
-
- try {
- handler.handleExtracting(inputFile);
- } catch (EncryptedDocumentException e) {
- // Do not try to read encrypted files
- Assume.assumeFalse("File " + file + " excluded because it is password-encrypted", true);
- }
- }
-
- void handleWrongOLE2XMLExtension(File inputFile, Exception e) throws Exception {
- // we sometimes have wrong extensions, so for some exceptions we try to handle it
- // with the correct FileHandler instead
- String message = e.getMessage();
-
- // ignore some file-types that we do not want to handle here
- Assume.assumeFalse("File " + file + " excluded because it is actually a PDF/RTF/HTML file",
- message != null && (message.equals("The document is really a RTF file") ||
- message.equals("The document is really a PDF file") ||
- message.equals("The document is really a HTML file")));
-
- if(message != null && (message.equals("The document is really a XLS file"))) {
- handler = TestAllFiles.HANDLERS.get(".xls");
- handleFile(inputFile);
- } else if(message != null && (message.equals("The document is really a PPT file"))) {
- handler = TestAllFiles.HANDLERS.get(".ppt");
- handleFile(inputFile);
- } else if(message != null && (message.equals("The document is really a DOC file"))) {
- handler = TestAllFiles.HANDLERS.get(".doc");
- handleFile(inputFile);
- } else if(message != null && (message.equals("The document is really a VSD file"))) {
- handler = TestAllFiles.HANDLERS.get(".vsd");
- handleFile(inputFile);
-
- // use XWPF instead of HWPF and XSSF instead of HSSF as the file seems to have the wrong extension
- } else if (handler instanceof HWPFFileHandler) {
- handler = TestAllFiles.HANDLERS.get(".docx");
- handleFile(inputFile);
- } else if (handler instanceof HSSFFileHandler) {
- handler = TestAllFiles.HANDLERS.get(".xlsx");
- handleFile(inputFile);
- } else if (handler instanceof HSLFFileHandler) {
- handler = TestAllFiles.HANDLERS.get(".pptx");
- handleFile(inputFile);
-
- // and the other way around, use HWPF instead of XWPF and so forth
- } else if(handler instanceof XWPFFileHandler) {
- handler = TestAllFiles.HANDLERS.get(".doc");
- handleFile(inputFile);
- } else if(handler instanceof XSSFFileHandler) {
- handler = TestAllFiles.HANDLERS.get(".xls");
- handleFile(inputFile);
- } else if(handler instanceof XSLFFileHandler) {
- handler = TestAllFiles.HANDLERS.get(".ppt");
- handleFile(inputFile);
- } else {
- // nothing matched => throw the exception to the outside
- throw e;
- }
- }
-
- private void handleFile(File inputFile) throws Exception {
- try (InputStream newStream = new BufferedInputStream(new FileInputStream(inputFile), 64*1024)) {
- handler.handleFile(newStream, inputFile.getAbsolutePath());
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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;
-
-import com.sun.management.HotSpotDiagnosticMXBean;
-
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-
-public class HeapDump {
- // This is the name of the HotSpot Diagnostic MBean
- private static final String HOTSPOT_BEAN_NAME =
- "com.sun.management:type=HotSpotDiagnostic";
-
- // field to store the hotspot diagnostic MBean
- private static volatile HotSpotDiagnosticMXBean hotspotMBean;
-
- /**
- * Call this method from your application whenever you
- * want to dump the heap snapshot into a file.
- *
- * @param fileName name of the heap dump file
- * @param live flag that tells whether to dump
- * only the live objects
- */
- public static void dumpHeap(String fileName, boolean live) throws IOException {
- // initialize hotspot diagnostic MBean
- initHotspotMBean();
- hotspotMBean.dumpHeap(fileName, live);
- }
-
- // initialize the hotspot diagnostic MBean field
- private static void initHotspotMBean() throws IOException {
- if (hotspotMBean == null) {
- synchronized (HeapDump.class) {
- if (hotspotMBean == null) {
- hotspotMBean = getHotspotMBean();
- }
- }
- }
- }
-
- // get the hotspot diagnostic MBean from the platform MBean server
- private static HotSpotDiagnosticMXBean getHotspotMBean() throws IOException {
- return ManagementFactory.newPlatformMXBeanProxy(ManagementFactory.getPlatformMBeanServer(),
- HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hwpf.HWPFDocument;
-import org.apache.poi.poifs.filesystem.FileMagic;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.stress.FileHandler;
-import org.apache.poi.stress.XSSFFileHandler;
-import org.apache.poi.util.SuppressForbidden;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.tools.ant.DirectoryScanner;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Helper class to scan a folder for files and return a collection of
- * found files together with the matching {@link FileHandler}.
- *
- * Can also be used to get the appropriate FileHandler for a single file.
- */
-public class POIFileScanner {
- private final static File ROOT_DIR;
- static {
- // when running in Gradle, current directory might be "build/integrationtest"
- if(new File("../../test-data").exists()) {
- ROOT_DIR = new File("../../test-data");
- } else {
- ROOT_DIR = new File("test-data");
- }
- }
-
- /**
- * Scan a folder for files and return a collection of
- * found files together with the matching {@link FileHandler}.
- *
- * Note: unknown files will be assigned to {@link org.apache.poi.TestAllFiles.NullFileHandler}
- *
- * @param rootDir The directory to scan
- * @return A collection with file-FileHandler pairs which can be used for running tests on that file
- * @throws IOException If determining the file-type fails
- */
- public static Collection<Map.Entry<String, FileHandler>> scan(File rootDir) throws IOException {
- DirectoryScanner scanner = new DirectoryScanner();
- scanner.setBasedir(rootDir);
-
- scanner.setExcludes(TestAllFiles.SCAN_EXCLUDES);
-
- System.out.println("Scanning for files in " + rootDir);
-
- scanner.scan();
-
- String[] includedFiles = scanner.getIncludedFiles();
- System.out.println("Handling " + includedFiles.length + " files");
-
- List<Map.Entry<String, FileHandler>> files = new ArrayList<>();
- for(String file : includedFiles) {
- // breaks files with slash in their name on Linux:
- // file = file.replace('\\', '/'); // ... failures/handlers lookup doesn't work on windows otherwise
-
- FileHandler fileHandler = getFileHandler(rootDir, file);
-
- files.add(new AbstractMap.SimpleImmutableEntry<>(file, fileHandler));
-
- if(files.size() % 100 == 0) {
- System.out.print(".");
- if(files.size() % 100_000 == 0) {
- System.out.println(file);
- }
- }
- }
- System.out.println();
-
- return files;
- }
-
- /**
- * Get the FileHandler for a single file
- *
- * @param rootDir The directory where the file resides
- * @param file The name of the file without directory
- * @return The matching {@link FileHandler}, A {@link org.apache.poi.TestAllFiles.NullFileHandler}
- * is returned if no match is found
- * @throws IOException If determining the file-type fails
- */
- protected static FileHandler getFileHandler(File rootDir, String file) throws IOException {
- FileHandler fileHandler = TestAllFiles.HANDLERS.get(TestAllFiles.getExtension(file));
- if(fileHandler == null) {
- // we could not detect a type of file based on the extension, so we
- // need to take a close look at the file
- fileHandler = detectUnnamedFile(rootDir, file);
- }
- return fileHandler;
- }
-
- private static FileHandler detectUnnamedFile(File rootDir, String file) throws IOException {
- File testFile = new File(rootDir, file);
-
- // find out if it looks like OLE2 (HSSF, HSLF, HWPF, ...) or OOXML (XSSF, XSLF, XWPF, ...)
- // and then determine the file type accordingly
- FileMagic magic = FileMagic.valueOf(testFile);
- switch (magic) {
- case OLE2: {
- try {
- try (POIFSFileSystem fs = new POIFSFileSystem(testFile, true)) {
- HSSFWorkbook.getWorkbookDirEntryName(fs.getRoot());
- }
-
- // we did not get an exception, so it seems this is a HSSFWorkbook
- return TestAllFiles.HANDLERS.get(".xls");
- } catch (IOException | RuntimeException e) {
- try {
- try (FileInputStream istream = new FileInputStream(testFile)) {
- try (HWPFDocument ignored = new HWPFDocument(istream)) {
- // seems to be a valid document
- return TestAllFiles.HANDLERS.get(".doc");
- }
- }
- } catch (IOException | RuntimeException e2) {
- System.out.println("Could not open POIFSFileSystem for OLE2 file " + testFile + ": " + e + " and " + e2);
- return TestAllFiles.NullFileHandler.instance;
- }
- }
- }
- case OOXML: {
- try {
- try (Workbook ignored = WorkbookFactory.create(testFile, null, true)) {
- // seems to be a valid workbook
- return TestAllFiles.HANDLERS.get(".xlsx");
- }
- } catch (IOException | RuntimeException e) {
- try {
- try (FileInputStream is = new FileInputStream(testFile)) {
- try (XWPFDocument ignored = new XWPFDocument(is)) {
- // seems to be a valid document
- return TestAllFiles.HANDLERS.get(".docx");
- }
- }
- } catch (IOException | RuntimeException e2) {
- System.out.println("Could not open POIFSFileSystem for OOXML file " + testFile + ": " + e + " and " + e2);
- return TestAllFiles.NullFileHandler.instance;
- }
- }
- }
-
- // do not warn about a few detected file types
- case RTF:
- case PDF:
- case HTML:
- case XML:
- case JPEG:
- case GIF:
- case TIFF:
- case WMF:
- case EMF:
- case BMP:
- return TestAllFiles.NullFileHandler.instance;
- }
-
- System.out.println("Did not get a handler for extension " + TestAllFiles.getExtension(file) +
- " of file " + file + ": " + magic);
- return TestAllFiles.NullFileHandler.instance;
- }
-
- @Ignore
- @Test
- @SuppressForbidden("Just an ignored test")
- public void testInvalidFile() throws IOException, InterruptedException {
- FileHandler fileHandler = POIFileScanner.getFileHandler(new File("/usbc/CommonCrawl"),
- "www.bgs.ac.uk_downloads_directdownload.cfm_id=2362&noexcl=true&t=west_20sussex_20-_20building_20stone_20quarries");
-
- assertEquals(XSSFFileHandler.class, fileHandler.getClass());
-
- // to show the output from ZipFile() from commons-compress
- // although I did not find out yet why the ZipFile is not closed here
- System.gc();
- Thread.sleep(1000);
- System.gc();
- Thread.sleep(1000);
- }
-
- @Test
- public void testDetectUnnamedFile() throws IOException {
- POIFileScanner.detectUnnamedFile(new File(ROOT_DIR, "spreadsheet"), "49156.xlsx");
- }
-
- @Test
- public void test() throws IOException {
- POIFileScanner.scan(ROOT_DIR);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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;
-
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
-import org.apache.poi.poifs.crypt.Decryptor;
-import org.apache.poi.stress.AbstractFileHandler;
-import org.apache.poi.stress.FileHandler;
-import org.apache.poi.stress.HDGFFileHandler;
-import org.apache.poi.stress.HMEFFileHandler;
-import org.apache.poi.stress.HPBFFileHandler;
-import org.apache.poi.stress.HPSFFileHandler;
-import org.apache.poi.stress.HSLFFileHandler;
-import org.apache.poi.stress.HSMFFileHandler;
-import org.apache.poi.stress.HSSFFileHandler;
-import org.apache.poi.stress.HWPFFileHandler;
-import org.apache.poi.stress.OPCFileHandler;
-import org.apache.poi.stress.POIFSFileHandler;
-import org.apache.poi.stress.XDGFFileHandler;
-import org.apache.poi.stress.XSLFFileHandler;
-import org.apache.poi.stress.XSSFBFileHandler;
-import org.apache.poi.stress.XSSFFileHandler;
-import org.apache.poi.stress.XWPFFileHandler;
-import org.apache.tools.ant.DirectoryScanner;
-import org.junit.AssumptionViolatedException;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * This is an integration test which performs various actions on all stored test-files and tries
- * to reveal problems which are introduced, but not covered (yet) by unit tests.
- *
- * This test looks for any file under the test-data directory and tries to do some useful
- * processing with it based on it's type.
- *
- * The test is implemented as a junit {@link Parameterized} test, which leads
- * to one test-method call for each file (currently around 950 files are handled).
- *
- * There is a a mapping of extension to implementations of the interface
- * {@link FileHandler} which defines how the file is loaded and which actions are
- * tried with the file.
- *
- * The test can be expanded by adding more actions to the FileHandlers, this automatically
- * applies the action to any such file in our test-data repository.
- *
- * There is also a list of files that should actually fail.
- *
- * Note: It is also a test-failure if a file that is expected to fail now actually works,
- * i.e. if a bug was fixed in POI itself, the file should be removed from the expected-failures
- * here as well! This is to ensure that files that should not work really do not work, e.g.
- * that we do not remove expected sanity checks.
- */
-@RunWith(Parameterized.class)
-public class TestAllFiles {
- private static final File ROOT_DIR = new File("test-data");
- private static final boolean IGNORE_SCRATCHPAD = Boolean.getBoolean("scratchpad.ignore");
-
- public static final String[] SCAN_EXCLUDES = new String[] { "**/.svn/**", "lost+found", "**/.git/**" };
-
- private static final Map<String,String> FILE_PASSWORD;
-
-
- // map file extensions to the actual mappers
- public static final Map<String, FileHandler> HANDLERS = new HashMap<>();
-
- 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 XSSFBFileHandler());
-
- // Word
- HANDLERS.put(".doc", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HWPFFileHandler());
- HANDLERS.put(".docx", new XWPFFileHandler());
- HANDLERS.put(".dotx", new XWPFFileHandler());
- HANDLERS.put(".docm", new XWPFFileHandler());
-
- // OpenXML4J files
- HANDLERS.put(".ooxml", new OPCFileHandler());
- HANDLERS.put(".zip", new OPCFileHandler());
-
- // Powerpoint
- HANDLERS.put(".ppt", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HSLFFileHandler());
- HANDLERS.put(".pot", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : 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());
- HANDLERS.put(".potx", new XSLFFileHandler());
-
- // Outlook
- HANDLERS.put(".msg", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HSMFFileHandler());
-
- // Publisher
- HANDLERS.put(".pub", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HPBFFileHandler());
-
- // Visio - binary
- HANDLERS.put(".vsd", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HDGFFileHandler());
-
- // Visio - ooxml
- HANDLERS.put(".vsdm", new XDGFFileHandler());
- HANDLERS.put(".vsdx", new XDGFFileHandler());
- HANDLERS.put(".vssm", new XDGFFileHandler());
- HANDLERS.put(".vssx", new XDGFFileHandler());
- HANDLERS.put(".vstm", new XDGFFileHandler());
- HANDLERS.put(".vstx", new XDGFFileHandler());
-
- // Visio - not handled yet
- HANDLERS.put(".vst", NullFileHandler.instance);
- HANDLERS.put(".vss", NullFileHandler.instance);
-
- // POIFS
- HANDLERS.put(".ole2", new POIFSFileHandler());
-
- // Microsoft Admin Template?
- HANDLERS.put(".adm", new HPSFFileHandler());
-
- // Microsoft TNEF
- HANDLERS.put(".dat", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HMEFFileHandler());
-
- // TODO: are these readable by some of the formats?
- HANDLERS.put(".wri", NullFileHandler.instance);
- HANDLERS.put(".shw", NullFileHandler.instance);
- HANDLERS.put(".zvi", NullFileHandler.instance);
- HANDLERS.put(".mpp", NullFileHandler.instance);
- HANDLERS.put(".qwp", NullFileHandler.instance);
- HANDLERS.put(".wps", NullFileHandler.instance);
- HANDLERS.put(".bin", NullFileHandler.instance);
- HANDLERS.put(".xps", NullFileHandler.instance);
- HANDLERS.put(".sldprt", NullFileHandler.instance);
- HANDLERS.put(".mdb", NullFileHandler.instance);
- HANDLERS.put(".vml", NullFileHandler.instance);
-
- // ignore some file types, images, other formats, ...
- HANDLERS.put(".txt", NullFileHandler.instance);
- HANDLERS.put(".pdf", NullFileHandler.instance);
- HANDLERS.put(".rtf", NullFileHandler.instance);
- HANDLERS.put(".gif", NullFileHandler.instance);
- HANDLERS.put(".html", NullFileHandler.instance);
- HANDLERS.put(".png", NullFileHandler.instance);
- HANDLERS.put(".wmf", NullFileHandler.instance);
- HANDLERS.put(".emf", NullFileHandler.instance);
- HANDLERS.put(".dib", NullFileHandler.instance);
- HANDLERS.put(".svg", NullFileHandler.instance);
- HANDLERS.put(".pict", NullFileHandler.instance);
- HANDLERS.put(".jpg", NullFileHandler.instance);
- HANDLERS.put(".jpeg", NullFileHandler.instance);
- HANDLERS.put(".tif", NullFileHandler.instance);
- HANDLERS.put(".tiff", NullFileHandler.instance);
- HANDLERS.put(".wav", NullFileHandler.instance);
- HANDLERS.put(".xml", NullFileHandler.instance);
- HANDLERS.put(".csv", NullFileHandler.instance);
- HANDLERS.put(".ods", NullFileHandler.instance);
- HANDLERS.put(".ttf", NullFileHandler.instance);
- HANDLERS.put(".fntdata", NullFileHandler.instance);
- // VBA source files
- HANDLERS.put(".vba", NullFileHandler.instance);
- HANDLERS.put(".bas", NullFileHandler.instance);
- HANDLERS.put(".frm", NullFileHandler.instance);
- HANDLERS.put(".frx", NullFileHandler.instance); //binary
- HANDLERS.put(".cls", NullFileHandler.instance);
-
- // map some files without extension
- HANDLERS.put("spreadsheet/BigSSTRecord", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecord2", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecord2CR1", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecord2CR2", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecord2CR3", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecord2CR4", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecord2CR5", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecord2CR6", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecord2CR7", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/BigSSTRecordCR", NullFileHandler.instance);
- HANDLERS.put("spreadsheet/test_properties1", NullFileHandler.instance);
-
- // keystore files
- HANDLERS.put(".pfx", NullFileHandler.instance);
- HANDLERS.put(".pem", NullFileHandler.instance);
- HANDLERS.put(".jks", NullFileHandler.instance);
- HANDLERS.put(".pkcs12", NullFileHandler.instance);
-
- Map<String,String> passmap = new HashMap<>();
- passmap.put("slideshow/Password_Protected-hello.ppt", "hello");
- passmap.put("slideshow/Password_Protected-56-hello.ppt", "hello");
- passmap.put("slideshow/Password_Protected-np-hello.ppt", "hello");
- passmap.put("slideshow/cryptoapi-proc2356.ppt", "crypto");
- passmap.put("spreadsheet/xor-encryption-abc.xls", "abc");
- passmap.put("spreadsheet/35897-type4.xls", "freedom");
- passmap.put("spreadsheet/58616.xlsx", Decryptor.DEFAULT_PASSWORD);
- passmap.put("spreadsheet/password.xls", "password");
- passmap.put("spreadsheet/protected_passtika.xlsx", "tika");
- passmap.put("document/bug53475-password-is-pass.docx", "pass");
- passmap.put("document/bug53475-password-is-solrcell.docx", "solrcell");
- passmap.put("document/password_password_cryptoapi.doc", "password");
- passmap.put("document/password_tika_binaryrc4.doc", "tika");
- passmap.put("poifs/protect.xlsx", Decryptor.DEFAULT_PASSWORD);
- passmap.put("poifs/extenxls_pwd123.xlsx", "pwd123");
- passmap.put("poifs/protected_agile.docx", Decryptor.DEFAULT_PASSWORD);
- passmap.put("poifs/60320-protected.xlsx", "Test001!!");
- passmap.put("poifs/protected_sha512.xlsx", "this is a test");
-
- FILE_PASSWORD = Collections.unmodifiableMap(passmap);
- }
-
- private static Set<String> unmodifiableHashSet(String... a) {
- return Collections.unmodifiableSet(hashSet(a));
- }
- private static Set<String> hashSet(String... a) {
- return new HashSet<>(Arrays.asList(a));
- }
-
- // Old Word Documents where we can at least extract some text
- private static final Set<String> OLD_FILES_HWPF = unmodifiableHashSet(
- "document/Bug49933.doc",
- "document/Bug51944.doc",
- "document/Word6.doc",
- "document/Word6_sections.doc",
- "document/Word6_sections2.doc",
- "document/Word95.doc",
- "document/word95err.doc",
- "document/Bug60936.doc",
- "document/Bug60942.doc",
- "document/Bug60942b.doc",
- "document/cn.orthodox.www_divenbog_APRIL_30-APRIL.DOC",
- "hpsf/TestMickey.doc",
- "document/52117.doc",
- "hpsf/TestInvertedClassID.doc",
- "hpsf/TestBug52117.doc"
- );
-
- private static final Set<String> EXPECTED_FAILURES = unmodifiableHashSet(
- // password protected files without known password
- "spreadsheet/51832.xls",
- "document/PasswordProtected.doc",
-
- // TODO: fails XMLExportTest, is this ok?
- "spreadsheet/CustomXMLMapping-singleattributenamespace.xlsx",
- "spreadsheet/55864.xlsx",
- "spreadsheet/57890.xlsx",
- "spreadsheet/xxe_in_schema.xlsx",
-
- // TODO: these fail now with some NPE/file read error because we now try to compute every value via Cell.toString()!
- "spreadsheet/44958.xls",
- "spreadsheet/44958_1.xls",
- "spreadsheet/testArraysAndTables.xls",
-
- // TODO: good to ignore?
- "spreadsheet/sample-beta.xlsx",
- "document/cpansearch.perl.org_src_tobyink_acme-rundoc-0.001_word-lib_hello_world.docm",
-
- // This is actually a spreadsheet!
- "hpsf/TestRobert_Flaherty.doc",
-
- // some files that are broken, eg Word 95, ...
- "spreadsheet/43493.xls",
- "spreadsheet/46904.xls",
- "document/Bug50955.doc",
- "document/57843.doc",
- "slideshow/PPT95.ppt",
- "slideshow/pp40only.ppt",
- "slideshow/Divino_Revelado.pptx",
- "openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx",
- "openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx",
- "openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_NotPresentFAIL.docx",
- "openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx",
- "openxml4j/OPCCompliance_CoreProperties_OnlyOneCorePropertiesPartFAIL.docx",
- "openxml4j/OPCCompliance_CoreProperties_UnauthorizedXMLLangAttributeFAIL.docx",
- "openxml4j/OPCCompliance_DerivedPartNameFAIL.docx",
- "openxml4j/invalid.xlsx",
- "openxml4j/62592.thmx",
- "spreadsheet/54764-2.xlsx", // see TestXSSFBugs.bug54764()
- "spreadsheet/54764.xlsx", // see TestXSSFBugs.bug54764()
- "poifs/unknown_properties.msg", // POIFS properties corrupted
- (IGNORE_SCRATCHPAD ? "" : "poifs/only-zero-byte-streams.ole2"), // No actual contents
- "spreadsheet/poc-xmlbomb.xlsx", // contains xml-entity-expansion
- "spreadsheet/poc-xmlbomb-empty.xlsx", // contains xml-entity-expansion
- "spreadsheet/poc-shared-strings.xlsx", // contains shared-string-entity-expansion
- "document/61612a.docx",
- "document/word2.doc",
- "spreadsheet/xlsx-corrupted.xlsx",
-
- // old Excel files, which we only support simple text extraction of
- "spreadsheet/testEXCEL_2.xls",
- "spreadsheet/testEXCEL_3.xls",
- "spreadsheet/testEXCEL_4.xls",
- "spreadsheet/testEXCEL_5.xls",
- "spreadsheet/testEXCEL_95.xls",
- "spreadsheet/59074.xls",
- "spreadsheet/60284.xls",
- "spreadsheet/64130.xls",
-
- // OOXML Strict is not yet supported, see bug #57699
- "spreadsheet/SampleSS.strict.xlsx",
- "spreadsheet/SimpleStrict.xlsx",
- "spreadsheet/sample.strict.xlsx",
- "spreadsheet/57914.xlsx",
-
- // files with XML entities
- "openxml4j/ContentTypeHasEntities.ooxml",
-
- // non-TNEF files
- "ddf/Container.dat",
- "ddf/47143.dat",
-
- // sheet cloning errors
- "spreadsheet/56450.xls",
- // "spreadsheet/OddStyleRecord.xls",
-
- // msg files with non-standard encodings
- "hsmf/ASCII_CP1251_LCID1049.msg",
- "hsmf/ASCII_UTF-8_CP1252_LCID1031.msg",
- "hsmf/ASCII_UTF-8_CP1252_LCID1031_HTML.msg",
- "hsmf/HTMLBodyBinary_CP1251.msg",
- "hsmf/HTMLBodyBinary_UTF-8.msg"
- );
-
- private static final Set<String> IGNORED = unmodifiableHashSet(
- // OPC handler works / XSSF handler fails
- "spreadsheet/57181.xlsm",
- "spreadsheet/61300.xls"//intentionally fuzzed -- used to cause infinite loop
- );
-
- @Parameters(name="{index}: {0} using {1}")
- public static Iterable<Object[]> files() {
- DirectoryScanner scanner = new DirectoryScanner();
- scanner.setBasedir(ROOT_DIR);
- scanner.setExcludes(SCAN_EXCLUDES);
-
- scanner.scan();
-
- System.out.println("Handling " + scanner.getIncludedFiles().length + " files");
-
- List<Object[]> files = new ArrayList<>();
- for(String file : scanner.getIncludedFiles()) {
- file = file.replace('\\', '/'); // ... failures/handlers lookup doesn't work on windows otherwise
- if (IGNORED.contains(file)) {
- System.out.println("Ignoring " + file);
- continue;
- }
- FileHandler handler = HANDLERS.get(getExtension(file));
- files.add(new Object[] { file, handler });
-
- // for some file-types also run OPCFileHandler
- if(handler instanceof XSSFFileHandler ||
- handler instanceof XWPFFileHandler ||
- handler instanceof XSLFFileHandler ||
- handler instanceof XDGFFileHandler) {
- files.add(new Object[] { file, new OPCFileHandler() });
- }
-
- if (handler instanceof HSSFFileHandler ||
- handler instanceof HSLFFileHandler ||
- handler instanceof HWPFFileHandler ||
- handler instanceof HDGFFileHandler) {
- files.add(new Object[] { file, new HPSFFileHandler() });
- }
- }
-
- return files;
- }
-
- @SuppressWarnings("DefaultAnnotationParam")
- @Parameter(value=0)
- public String file;
-
- @Parameter(value=1)
- public FileHandler handler;
-
- @Before
- public void setPassword() {
- // this also removes the password for non encrypted files
- String pass = TestAllFiles.FILE_PASSWORD.get(file);
- Biff8EncryptionKey.setCurrentUserPassword(pass);
- }
-
- @Test
- public void testAllFiles() throws Exception {
- if(handler == null) {
- fail("Did not find a handler for file " + file);
- }
-
- System.out.println("Reading " + file + " with " + handler.getClass().getSimpleName());
- assertNotNull("Unknown file extension for file: " + file + ": " + getExtension(file), handler);
- File inputFile = new File(ROOT_DIR, file);
-
- // special cases where docx-handling breaks, but OPCPackage handling works
- boolean ignoredOPC = (file.endsWith(".docx") || file.endsWith(".xlsx") ||
- file.endsWith(".xlsb") || file.endsWith(".pptx")) &&
- handler instanceof OPCFileHandler;
- boolean ignoreHPSF = (handler instanceof HPSFFileHandler);
-
- try {
- try (InputStream stream = new BufferedInputStream(new FileInputStream(inputFile), 64 * 1024)) {
- handler.handleFile(stream, file);
- assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!",
- OLD_FILES_HWPF.contains(file) && !ignoreHPSF);
- }
-
- handler.handleExtracting(inputFile);
-
- assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!",
- EXPECTED_FAILURES.contains(file) && !ignoredOPC && !ignoreHPSF);
- } catch (OldFileFormatException e) {
- // for old word files we should still support extracting text
- if(OLD_FILES_HWPF.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 (AssumptionViolatedException e) {
- // file handler ignored this file
- } 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);
- }
- }
-
- try {
- // let some file handlers do additional stuff
- handler.handleAdditional(inputFile);
- } catch (AssumptionViolatedException e) {
- // file handler ignored this file
- } catch (Exception e) {
- if(!EXPECTED_FAILURES.contains(file) && !AbstractFileHandler.EXPECTED_EXTRACTOR_FAILURES.contains(file)) {
- System.out.println("Failed: " + file);
- throw new Exception("While handling " + file, e);
- }
- }
- }
-
- public static String getExtension(String file) {
- int pos = file.lastIndexOf('.');
- if(pos == -1 || pos == file.length()-1) {
- return file;
- }
-
- return file.substring(pos).toLowerCase(Locale.ROOT);
- }
-
- public static class NullFileHandler implements FileHandler {
- public static final FileHandler instance = new NullFileHandler();
-
- @Override
- public void handleFile(InputStream stream, String path) {
- }
-
- @Override
- public void handleExtracting(File file) {
- }
-
- @Override
- public void handleAdditional(File file) {
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.util.List;
-
-import org.apache.poi.hssf.record.Record;
-import org.junit.Test;
-
-/**
- * Needs to be implemented in this package to have access to
- * HSSFWorkbook.getWorkbook()
- */
-public class RecordsStresser {
- public static void handleWorkbook(HSSFWorkbook wb) {
- List<org.apache.poi.hssf.record.Record> records = wb.getWorkbook().getRecords();
- for(org.apache.poi.hssf.record.Record record : records) {
- // some Records do not implement clone ?!
- // equals instead of instanceof is on purpose here to only skip exactly this class and not any derived ones
-// if(record.getClass().equals(InterfaceHdrRecord.class) ||
-// record.getClass().equals(MMSRecord.class) ||
-// record.getClass().equals(InterfaceEndRecord.class) ||
-// record.getClass().equals(WriteAccessRecord.class) ||
-// record.getClass().equals(CodepageRecord.class) ||
-// record.getClass().equals(DSFRecord.class)) {
-// continue;
-// }
- try {
- Record newRecord = record.copy();
-
- assertEquals("Expecting the same class back from clone(), but had Record of type " + record.getClass() + " and got back a " + newRecord.getClass() + " from clone()",
- record.getClass(), newRecord.getClass());
-
- byte[] origBytes = record.serialize();
- byte[] newBytes = newRecord.serialize();
-
- assertArrayEquals("Record of type " + record.getClass() + " should return the same byte array via the clone() method, but did return a different array",
- origBytes, newBytes);
- } catch (RuntimeException e) {
- // some Records do not implement clone, ignore those for now
- assertTrue(e.getMessage().contains("needs to define a clone method"));
- }
- }
- }
-
- // a test-case to test this locally without executing the full TestAllFiles
- @Test
- public void test() throws Exception {
- try (InputStream stream = new FileInputStream("test-data/spreadsheet/15556.xls")) {
- HSSFWorkbook wb = new HSSFWorkbook(stream);
- handleWorkbook(wb);
- wb.close();
- }
- }
-}
--- /dev/null
+/* ====================================================================
+ 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.assertNotNull;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipException;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.OldFileFormatException;
+import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
+import org.junit.Assume;
+
+/**
+ * This class is used for mass-regression testing via a
+ * separate project, this class provides functionality to
+ * run integration tests on one file and handle some
+ * types of files/exceptions, e.g. old file formats.
+ *
+ */
+public class BaseIntegrationTest {
+ private final File rootDir;
+ private String file;
+ private FileHandler handler;
+
+ public BaseIntegrationTest(File rootDir, String file, FileHandler handler) {
+ this.rootDir = rootDir;
+ this.file = file;
+ this.handler = handler;
+ }
+
+ public void test() throws Exception {
+ assertNotNull("Unknown file extension for file: " + file + ": " + TestAllFiles.getExtension(file), handler);
+ testOneFile(new File(rootDir, file));
+ }
+
+ protected void testOneFile(File inputFile) throws Exception {
+ try {
+ handleFile(inputFile);
+ } catch (OfficeXmlFileException e) {
+ // switch XWPF and HWPF and so forth depending on the error message
+ handleWrongOLE2XMLExtension(inputFile, e);
+ } catch (OldFileFormatException e) {
+ // Not even text extraction is supported for these: handler.handleExtracting(inputFile);
+ Assume.assumeFalse("File " + file + " excluded because it is unsupported old Excel format", true);
+ } catch (EncryptedDocumentException e) {
+ // Do not try to read encrypted files
+ Assume.assumeFalse("File " + file + " excluded because it is password-encrypted", true);
+ } catch (ZipException e) {
+ // some files are corrupted
+ if (e.getMessage().equals("unexpected EOF") || e.getMessage().equals("Truncated ZIP file")) {
+ Assume.assumeFalse("File " + file + " excluded because the Zip file is incomplete", true);
+ }
+
+ throw e;
+ } catch (IOException e) {
+ // ignore some other ways of corrupted files
+ String message = e.getMessage();
+ if(message != null && message.contains("Truncated ZIP file")) {
+ Assume.assumeFalse("File " + file + " excluded because the Zip file is incomplete", true);
+ }
+
+ // sometimes binary format has XML-format-extension...
+ if(message != null && message.contains("rong file format or file extension for OO XML file")) {
+ handleWrongOLE2XMLExtension(inputFile, e);
+ return;
+ }
+
+ throw e;
+ } catch (IllegalArgumentException e) {
+ // ignore errors for documents with incorrect extension
+ String message = e.getMessage();
+ if(message != null && (message.equals("The document is really a RTF file") ||
+ message.equals("The document is really a PDF file") ||
+ message.equals("The document is really a HTML file"))) {
+ Assume.assumeFalse("File " + file + " excluded because it is actually a PDF/RTF/HTML file", true);
+ }
+
+ if(message != null && message.equals("The document is really a OOXML file")) {
+ handleWrongOLE2XMLExtension(inputFile, e);
+ return;
+ }
+
+ throw e;
+ }
+
+ try {
+ handler.handleExtracting(inputFile);
+ } catch (EncryptedDocumentException e) {
+ // Do not try to read encrypted files
+ Assume.assumeFalse("File " + file + " excluded because it is password-encrypted", true);
+ }
+ }
+
+ void handleWrongOLE2XMLExtension(File inputFile, Exception e) throws Exception {
+ // we sometimes have wrong extensions, so for some exceptions we try to handle it
+ // with the correct FileHandler instead
+ String message = e.getMessage();
+
+ // ignore some file-types that we do not want to handle here
+ Assume.assumeFalse("File " + file + " excluded because it is actually a PDF/RTF/HTML file",
+ message != null && (message.equals("The document is really a RTF file") ||
+ message.equals("The document is really a PDF file") ||
+ message.equals("The document is really a HTML file")));
+
+ if(message != null && (message.equals("The document is really a XLS file"))) {
+ handler = TestAllFiles.HANDLERS.get(".xls");
+ handleFile(inputFile);
+ } else if(message != null && (message.equals("The document is really a PPT file"))) {
+ handler = TestAllFiles.HANDLERS.get(".ppt");
+ handleFile(inputFile);
+ } else if(message != null && (message.equals("The document is really a DOC file"))) {
+ handler = TestAllFiles.HANDLERS.get(".doc");
+ handleFile(inputFile);
+ } else if(message != null && (message.equals("The document is really a VSD file"))) {
+ handler = TestAllFiles.HANDLERS.get(".vsd");
+ handleFile(inputFile);
+
+ // use XWPF instead of HWPF and XSSF instead of HSSF as the file seems to have the wrong extension
+ } else if (handler instanceof HWPFFileHandler) {
+ handler = TestAllFiles.HANDLERS.get(".docx");
+ handleFile(inputFile);
+ } else if (handler instanceof HSSFFileHandler) {
+ handler = TestAllFiles.HANDLERS.get(".xlsx");
+ handleFile(inputFile);
+ } else if (handler instanceof HSLFFileHandler) {
+ handler = TestAllFiles.HANDLERS.get(".pptx");
+ handleFile(inputFile);
+
+ // and the other way around, use HWPF instead of XWPF and so forth
+ } else if(handler instanceof XWPFFileHandler) {
+ handler = TestAllFiles.HANDLERS.get(".doc");
+ handleFile(inputFile);
+ } else if(handler instanceof XSSFFileHandler) {
+ handler = TestAllFiles.HANDLERS.get(".xls");
+ handleFile(inputFile);
+ } else if(handler instanceof XSLFFileHandler) {
+ handler = TestAllFiles.HANDLERS.get(".ppt");
+ handleFile(inputFile);
+ } else {
+ // nothing matched => throw the exception to the outside
+ throw e;
+ }
+ }
+
+ private void handleFile(File inputFile) throws Exception {
+ try (InputStream newStream = new BufferedInputStream(new FileInputStream(inputFile), 64*1024)) {
+ handler.handleFile(newStream, inputFile.getAbsolutePath());
+ }
+ }
+}
import java.util.HashSet;
import java.util.Set;
+import org.apache.poi.examples.hpsf.CopyCompare;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument;
import org.apache.poi.hpsf.MarkUnsupportedException;
import org.apache.poi.hpsf.PropertySet;
import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.hpsf.examples.CopyCompare;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
--- /dev/null
+/* ====================================================================
+ 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.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.poi.hssf.record.Record;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.junit.Test;
+
+/**
+ * Needs to be implemented in this package to have access to
+ * HSSFWorkbook.getWorkbook()
+ */
+public class HSSFRecordsStresser {
+ public static void handleWorkbook(HSSFWorkbook wb) {
+ List<org.apache.poi.hssf.record.Record> records = wb.getWorkbook().getRecords();
+ for(org.apache.poi.hssf.record.Record record : records) {
+ // some Records do not implement clone ?!
+ // equals instead of instanceof is on purpose here to only skip exactly this class and not any derived ones
+// if(record.getClass().equals(InterfaceHdrRecord.class) ||
+// record.getClass().equals(MMSRecord.class) ||
+// record.getClass().equals(InterfaceEndRecord.class) ||
+// record.getClass().equals(WriteAccessRecord.class) ||
+// record.getClass().equals(CodepageRecord.class) ||
+// record.getClass().equals(DSFRecord.class)) {
+// continue;
+// }
+ try {
+ Record newRecord = record.copy();
+
+ assertEquals("Expecting the same class back from clone(), but had Record of type " + record.getClass() + " and got back a " + newRecord.getClass() + " from clone()",
+ record.getClass(), newRecord.getClass());
+
+ byte[] origBytes = record.serialize();
+ byte[] newBytes = newRecord.serialize();
+
+ assertArrayEquals("Record of type " + record.getClass() + " should return the same byte array via the clone() method, but did return a different array",
+ origBytes, newBytes);
+ } catch (RuntimeException e) {
+ // some Records do not implement clone, ignore those for now
+ assertTrue(e.getMessage().contains("needs to define a clone method"));
+ }
+ }
+ }
+
+ // a test-case to test this locally without executing the full TestAllFiles
+ @Test
+ public void test() throws Exception {
+ try (InputStream stream = new FileInputStream("test-data/spreadsheet/15556.xls")) {
+ HSSFWorkbook wb = new HSSFWorkbook(stream);
+ handleWorkbook(wb);
+ wb.close();
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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 java.io.IOException;
+import java.lang.management.ManagementFactory;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+
+public class HeapDump {
+ // This is the name of the HotSpot Diagnostic MBean
+ private static final String HOTSPOT_BEAN_NAME =
+ "com.sun.management:type=HotSpotDiagnostic";
+
+ // field to store the hotspot diagnostic MBean
+ private static volatile HotSpotDiagnosticMXBean hotspotMBean;
+
+ /**
+ * Call this method from your application whenever you
+ * want to dump the heap snapshot into a file.
+ *
+ * @param fileName name of the heap dump file
+ * @param live flag that tells whether to dump
+ * only the live objects
+ */
+ public static void dumpHeap(String fileName, boolean live) throws IOException {
+ // initialize hotspot diagnostic MBean
+ initHotspotMBean();
+ hotspotMBean.dumpHeap(fileName, live);
+ }
+
+ // initialize the hotspot diagnostic MBean field
+ private static void initHotspotMBean() throws IOException {
+ if (hotspotMBean == null) {
+ synchronized (HeapDump.class) {
+ if (hotspotMBean == null) {
+ hotspotMBean = getHotspotMBean();
+ }
+ }
+ }
+ }
+
+ // get the hotspot diagnostic MBean from the platform MBean server
+ private static HotSpotDiagnosticMXBean getHotspotMBean() throws IOException {
+ return ManagementFactory.newPlatformMXBeanProxy(ManagementFactory.getPlatformMBeanServer(),
+ HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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 java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.poifs.filesystem.FileMagic;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.util.SuppressForbidden;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.tools.ant.DirectoryScanner;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Helper class to scan a folder for files and return a collection of
+ * found files together with the matching {@link FileHandler}.
+ *
+ * Can also be used to get the appropriate FileHandler for a single file.
+ */
+public class POIFileScanner {
+ private final static File ROOT_DIR;
+ static {
+ // when running in Gradle, current directory might be "build/integrationtest"
+ if(new File("../../test-data").exists()) {
+ ROOT_DIR = new File("../../test-data");
+ } else {
+ ROOT_DIR = new File("test-data");
+ }
+ }
+
+ /**
+ * Scan a folder for files and return a collection of
+ * found files together with the matching {@link FileHandler}.
+ *
+ * Note: unknown files will be assigned to {@link TestAllFiles.NullFileHandler}
+ *
+ * @param rootDir The directory to scan
+ * @return A collection with file-FileHandler pairs which can be used for running tests on that file
+ * @throws IOException If determining the file-type fails
+ */
+ public static Collection<Map.Entry<String, FileHandler>> scan(File rootDir) throws IOException {
+ DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setBasedir(rootDir);
+
+ scanner.setExcludes(TestAllFiles.SCAN_EXCLUDES);
+
+ System.out.println("Scanning for files in " + rootDir);
+
+ scanner.scan();
+
+ String[] includedFiles = scanner.getIncludedFiles();
+ System.out.println("Handling " + includedFiles.length + " files");
+
+ List<Map.Entry<String, FileHandler>> files = new ArrayList<>();
+ for(String file : includedFiles) {
+ // breaks files with slash in their name on Linux:
+ // file = file.replace('\\', '/'); // ... failures/handlers lookup doesn't work on windows otherwise
+
+ FileHandler fileHandler = getFileHandler(rootDir, file);
+
+ files.add(new AbstractMap.SimpleImmutableEntry<>(file, fileHandler));
+
+ if(files.size() % 100 == 0) {
+ System.out.print(".");
+ if(files.size() % 100_000 == 0) {
+ System.out.println(file);
+ }
+ }
+ }
+ System.out.println();
+
+ return files;
+ }
+
+ /**
+ * Get the FileHandler for a single file
+ *
+ * @param rootDir The directory where the file resides
+ * @param file The name of the file without directory
+ * @return The matching {@link FileHandler}, A {@link TestAllFiles.NullFileHandler}
+ * is returned if no match is found
+ * @throws IOException If determining the file-type fails
+ */
+ protected static FileHandler getFileHandler(File rootDir, String file) throws IOException {
+ FileHandler fileHandler = TestAllFiles.HANDLERS.get(TestAllFiles.getExtension(file));
+ if(fileHandler == null) {
+ // we could not detect a type of file based on the extension, so we
+ // need to take a close look at the file
+ fileHandler = detectUnnamedFile(rootDir, file);
+ }
+ return fileHandler;
+ }
+
+ private static FileHandler detectUnnamedFile(File rootDir, String file) throws IOException {
+ File testFile = new File(rootDir, file);
+
+ // find out if it looks like OLE2 (HSSF, HSLF, HWPF, ...) or OOXML (XSSF, XSLF, XWPF, ...)
+ // and then determine the file type accordingly
+ FileMagic magic = FileMagic.valueOf(testFile);
+ switch (magic) {
+ case OLE2: {
+ try {
+ try (POIFSFileSystem fs = new POIFSFileSystem(testFile, true)) {
+ HSSFWorkbook.getWorkbookDirEntryName(fs.getRoot());
+ }
+
+ // we did not get an exception, so it seems this is a HSSFWorkbook
+ return TestAllFiles.HANDLERS.get(".xls");
+ } catch (IOException | RuntimeException e) {
+ try {
+ try (FileInputStream istream = new FileInputStream(testFile)) {
+ try (HWPFDocument ignored = new HWPFDocument(istream)) {
+ // seems to be a valid document
+ return TestAllFiles.HANDLERS.get(".doc");
+ }
+ }
+ } catch (IOException | RuntimeException e2) {
+ System.out.println("Could not open POIFSFileSystem for OLE2 file " + testFile + ": " + e + " and " + e2);
+ return TestAllFiles.NullFileHandler.instance;
+ }
+ }
+ }
+ case OOXML: {
+ try {
+ try (Workbook ignored = WorkbookFactory.create(testFile, null, true)) {
+ // seems to be a valid workbook
+ return TestAllFiles.HANDLERS.get(".xlsx");
+ }
+ } catch (IOException | RuntimeException e) {
+ try {
+ try (FileInputStream is = new FileInputStream(testFile)) {
+ try (XWPFDocument ignored = new XWPFDocument(is)) {
+ // seems to be a valid document
+ return TestAllFiles.HANDLERS.get(".docx");
+ }
+ }
+ } catch (IOException | RuntimeException e2) {
+ System.out.println("Could not open POIFSFileSystem for OOXML file " + testFile + ": " + e + " and " + e2);
+ return TestAllFiles.NullFileHandler.instance;
+ }
+ }
+ }
+
+ // do not warn about a few detected file types
+ case RTF:
+ case PDF:
+ case HTML:
+ case XML:
+ case JPEG:
+ case GIF:
+ case TIFF:
+ case WMF:
+ case EMF:
+ case BMP:
+ return TestAllFiles.NullFileHandler.instance;
+ }
+
+ System.out.println("Did not get a handler for extension " + TestAllFiles.getExtension(file) +
+ " of file " + file + ": " + magic);
+ return TestAllFiles.NullFileHandler.instance;
+ }
+
+ @Ignore
+ @Test
+ @SuppressForbidden("Just an ignored test")
+ public void testInvalidFile() throws IOException, InterruptedException {
+ FileHandler fileHandler = POIFileScanner.getFileHandler(new File("/usbc/CommonCrawl"),
+ "www.bgs.ac.uk_downloads_directdownload.cfm_id=2362&noexcl=true&t=west_20sussex_20-_20building_20stone_20quarries");
+
+ assertEquals(XSSFFileHandler.class, fileHandler.getClass());
+
+ // to show the output from ZipFile() from commons-compress
+ // although I did not find out yet why the ZipFile is not closed here
+ System.gc();
+ Thread.sleep(1000);
+ System.gc();
+ Thread.sleep(1000);
+ }
+
+ @Test
+ public void testDetectUnnamedFile() throws IOException {
+ POIFileScanner.detectUnnamedFile(new File(ROOT_DIR, "spreadsheet"), "49156.xlsx");
+ }
+
+ @Test
+ public void test() throws IOException {
+ POIFileScanner.scan(ROOT_DIR);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.poi.OldFileFormatException;
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.tools.ant.DirectoryScanner;
+import org.junit.AssumptionViolatedException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * This is an integration test which performs various actions on all stored test-files and tries
+ * to reveal problems which are introduced, but not covered (yet) by unit tests.
+ *
+ * This test looks for any file under the test-data directory and tries to do some useful
+ * processing with it based on it's type.
+ *
+ * The test is implemented as a junit {@link Parameterized} test, which leads
+ * to one test-method call for each file (currently around 950 files are handled).
+ *
+ * There is a a mapping of extension to implementations of the interface
+ * {@link FileHandler} which defines how the file is loaded and which actions are
+ * tried with the file.
+ *
+ * The test can be expanded by adding more actions to the FileHandlers, this automatically
+ * applies the action to any such file in our test-data repository.
+ *
+ * There is also a list of files that should actually fail.
+ *
+ * Note: It is also a test-failure if a file that is expected to fail now actually works,
+ * i.e. if a bug was fixed in POI itself, the file should be removed from the expected-failures
+ * here as well! This is to ensure that files that should not work really do not work, e.g.
+ * that we do not remove expected sanity checks.
+ */
+@RunWith(Parameterized.class)
+public class TestAllFiles {
+ private static final File ROOT_DIR = new File("test-data");
+ private static final boolean IGNORE_SCRATCHPAD = Boolean.getBoolean("scratchpad.ignore");
+
+ public static final String[] SCAN_EXCLUDES = new String[] { "**/.svn/**", "lost+found", "**/.git/**" };
+
+ private static final Map<String,String> FILE_PASSWORD;
+
+
+ // map file extensions to the actual mappers
+ public static final Map<String, FileHandler> HANDLERS = new HashMap<>();
+
+ 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 XSSFBFileHandler());
+
+ // Word
+ HANDLERS.put(".doc", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HWPFFileHandler());
+ HANDLERS.put(".docx", new XWPFFileHandler());
+ HANDLERS.put(".dotx", new XWPFFileHandler());
+ HANDLERS.put(".docm", new XWPFFileHandler());
+
+ // OpenXML4J files
+ HANDLERS.put(".ooxml", new OPCFileHandler());
+ HANDLERS.put(".zip", new OPCFileHandler());
+
+ // Powerpoint
+ HANDLERS.put(".ppt", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HSLFFileHandler());
+ HANDLERS.put(".pot", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : 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());
+ HANDLERS.put(".potx", new XSLFFileHandler());
+
+ // Outlook
+ HANDLERS.put(".msg", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HSMFFileHandler());
+
+ // Publisher
+ HANDLERS.put(".pub", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HPBFFileHandler());
+
+ // Visio - binary
+ HANDLERS.put(".vsd", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HDGFFileHandler());
+
+ // Visio - ooxml
+ HANDLERS.put(".vsdm", new XDGFFileHandler());
+ HANDLERS.put(".vsdx", new XDGFFileHandler());
+ HANDLERS.put(".vssm", new XDGFFileHandler());
+ HANDLERS.put(".vssx", new XDGFFileHandler());
+ HANDLERS.put(".vstm", new XDGFFileHandler());
+ HANDLERS.put(".vstx", new XDGFFileHandler());
+
+ // Visio - not handled yet
+ HANDLERS.put(".vst", NullFileHandler.instance);
+ HANDLERS.put(".vss", NullFileHandler.instance);
+
+ // POIFS
+ HANDLERS.put(".ole2", new POIFSFileHandler());
+
+ // Microsoft Admin Template?
+ HANDLERS.put(".adm", new HPSFFileHandler());
+
+ // Microsoft TNEF
+ HANDLERS.put(".dat", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HMEFFileHandler());
+
+ // TODO: are these readable by some of the formats?
+ HANDLERS.put(".wri", NullFileHandler.instance);
+ HANDLERS.put(".shw", NullFileHandler.instance);
+ HANDLERS.put(".zvi", NullFileHandler.instance);
+ HANDLERS.put(".mpp", NullFileHandler.instance);
+ HANDLERS.put(".qwp", NullFileHandler.instance);
+ HANDLERS.put(".wps", NullFileHandler.instance);
+ HANDLERS.put(".bin", NullFileHandler.instance);
+ HANDLERS.put(".xps", NullFileHandler.instance);
+ HANDLERS.put(".sldprt", NullFileHandler.instance);
+ HANDLERS.put(".mdb", NullFileHandler.instance);
+ HANDLERS.put(".vml", NullFileHandler.instance);
+
+ // ignore some file types, images, other formats, ...
+ HANDLERS.put(".txt", NullFileHandler.instance);
+ HANDLERS.put(".pdf", NullFileHandler.instance);
+ HANDLERS.put(".rtf", NullFileHandler.instance);
+ HANDLERS.put(".gif", NullFileHandler.instance);
+ HANDLERS.put(".html", NullFileHandler.instance);
+ HANDLERS.put(".png", NullFileHandler.instance);
+ HANDLERS.put(".wmf", NullFileHandler.instance);
+ HANDLERS.put(".emf", NullFileHandler.instance);
+ HANDLERS.put(".dib", NullFileHandler.instance);
+ HANDLERS.put(".svg", NullFileHandler.instance);
+ HANDLERS.put(".pict", NullFileHandler.instance);
+ HANDLERS.put(".jpg", NullFileHandler.instance);
+ HANDLERS.put(".jpeg", NullFileHandler.instance);
+ HANDLERS.put(".tif", NullFileHandler.instance);
+ HANDLERS.put(".tiff", NullFileHandler.instance);
+ HANDLERS.put(".wav", NullFileHandler.instance);
+ HANDLERS.put(".xml", NullFileHandler.instance);
+ HANDLERS.put(".csv", NullFileHandler.instance);
+ HANDLERS.put(".ods", NullFileHandler.instance);
+ HANDLERS.put(".ttf", NullFileHandler.instance);
+ HANDLERS.put(".fntdata", NullFileHandler.instance);
+ // VBA source files
+ HANDLERS.put(".vba", NullFileHandler.instance);
+ HANDLERS.put(".bas", NullFileHandler.instance);
+ HANDLERS.put(".frm", NullFileHandler.instance);
+ HANDLERS.put(".frx", NullFileHandler.instance); //binary
+ HANDLERS.put(".cls", NullFileHandler.instance);
+
+ // map some files without extension
+ HANDLERS.put("spreadsheet/BigSSTRecord", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecord2", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecord2CR1", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecord2CR2", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecord2CR3", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecord2CR4", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecord2CR5", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecord2CR6", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecord2CR7", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/BigSSTRecordCR", NullFileHandler.instance);
+ HANDLERS.put("spreadsheet/test_properties1", NullFileHandler.instance);
+
+ // keystore files
+ HANDLERS.put(".pfx", NullFileHandler.instance);
+ HANDLERS.put(".pem", NullFileHandler.instance);
+ HANDLERS.put(".jks", NullFileHandler.instance);
+ HANDLERS.put(".pkcs12", NullFileHandler.instance);
+
+ Map<String,String> passmap = new HashMap<>();
+ passmap.put("slideshow/Password_Protected-hello.ppt", "hello");
+ passmap.put("slideshow/Password_Protected-56-hello.ppt", "hello");
+ passmap.put("slideshow/Password_Protected-np-hello.ppt", "hello");
+ passmap.put("slideshow/cryptoapi-proc2356.ppt", "crypto");
+ passmap.put("spreadsheet/xor-encryption-abc.xls", "abc");
+ passmap.put("spreadsheet/35897-type4.xls", "freedom");
+ passmap.put("spreadsheet/58616.xlsx", Decryptor.DEFAULT_PASSWORD);
+ passmap.put("spreadsheet/password.xls", "password");
+ passmap.put("spreadsheet/protected_passtika.xlsx", "tika");
+ passmap.put("document/bug53475-password-is-pass.docx", "pass");
+ passmap.put("document/bug53475-password-is-solrcell.docx", "solrcell");
+ passmap.put("document/password_password_cryptoapi.doc", "password");
+ passmap.put("document/password_tika_binaryrc4.doc", "tika");
+ passmap.put("poifs/protect.xlsx", Decryptor.DEFAULT_PASSWORD);
+ passmap.put("poifs/extenxls_pwd123.xlsx", "pwd123");
+ passmap.put("poifs/protected_agile.docx", Decryptor.DEFAULT_PASSWORD);
+ passmap.put("poifs/60320-protected.xlsx", "Test001!!");
+ passmap.put("poifs/protected_sha512.xlsx", "this is a test");
+
+ FILE_PASSWORD = Collections.unmodifiableMap(passmap);
+ }
+
+ private static Set<String> unmodifiableHashSet(String... a) {
+ return Collections.unmodifiableSet(hashSet(a));
+ }
+ private static Set<String> hashSet(String... a) {
+ return new HashSet<>(Arrays.asList(a));
+ }
+
+ // Old Word Documents where we can at least extract some text
+ private static final Set<String> OLD_FILES_HWPF = unmodifiableHashSet(
+ "document/Bug49933.doc",
+ "document/Bug51944.doc",
+ "document/Word6.doc",
+ "document/Word6_sections.doc",
+ "document/Word6_sections2.doc",
+ "document/Word95.doc",
+ "document/word95err.doc",
+ "document/Bug60936.doc",
+ "document/Bug60942.doc",
+ "document/Bug60942b.doc",
+ "document/cn.orthodox.www_divenbog_APRIL_30-APRIL.DOC",
+ "hpsf/TestMickey.doc",
+ "document/52117.doc",
+ "hpsf/TestInvertedClassID.doc",
+ "hpsf/TestBug52117.doc"
+ );
+
+ private static final Set<String> EXPECTED_FAILURES = unmodifiableHashSet(
+ // password protected files without known password
+ "spreadsheet/51832.xls",
+ "document/PasswordProtected.doc",
+
+ // TODO: fails XMLExportTest, is this ok?
+ "spreadsheet/CustomXMLMapping-singleattributenamespace.xlsx",
+ "spreadsheet/55864.xlsx",
+ "spreadsheet/57890.xlsx",
+ "spreadsheet/xxe_in_schema.xlsx",
+
+ // TODO: these fail now with some NPE/file read error because we now try to compute every value via Cell.toString()!
+ "spreadsheet/44958.xls",
+ "spreadsheet/44958_1.xls",
+ "spreadsheet/testArraysAndTables.xls",
+
+ // TODO: good to ignore?
+ "spreadsheet/sample-beta.xlsx",
+ "document/cpansearch.perl.org_src_tobyink_acme-rundoc-0.001_word-lib_hello_world.docm",
+
+ // This is actually a spreadsheet!
+ "hpsf/TestRobert_Flaherty.doc",
+
+ // some files that are broken, eg Word 95, ...
+ "spreadsheet/43493.xls",
+ "spreadsheet/46904.xls",
+ "document/Bug50955.doc",
+ "document/57843.doc",
+ "slideshow/PPT95.ppt",
+ "slideshow/pp40only.ppt",
+ "slideshow/Divino_Revelado.pptx",
+ "openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx",
+ "openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx",
+ "openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_NotPresentFAIL.docx",
+ "openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx",
+ "openxml4j/OPCCompliance_CoreProperties_OnlyOneCorePropertiesPartFAIL.docx",
+ "openxml4j/OPCCompliance_CoreProperties_UnauthorizedXMLLangAttributeFAIL.docx",
+ "openxml4j/OPCCompliance_DerivedPartNameFAIL.docx",
+ "openxml4j/invalid.xlsx",
+ "openxml4j/62592.thmx",
+ "spreadsheet/54764-2.xlsx", // see TestXSSFBugs.bug54764()
+ "spreadsheet/54764.xlsx", // see TestXSSFBugs.bug54764()
+ "poifs/unknown_properties.msg", // POIFS properties corrupted
+ (IGNORE_SCRATCHPAD ? "" : "poifs/only-zero-byte-streams.ole2"), // No actual contents
+ "spreadsheet/poc-xmlbomb.xlsx", // contains xml-entity-expansion
+ "spreadsheet/poc-xmlbomb-empty.xlsx", // contains xml-entity-expansion
+ "spreadsheet/poc-shared-strings.xlsx", // contains shared-string-entity-expansion
+ "document/61612a.docx",
+ "document/word2.doc",
+ "spreadsheet/xlsx-corrupted.xlsx",
+
+ // old Excel files, which we only support simple text extraction of
+ "spreadsheet/testEXCEL_2.xls",
+ "spreadsheet/testEXCEL_3.xls",
+ "spreadsheet/testEXCEL_4.xls",
+ "spreadsheet/testEXCEL_5.xls",
+ "spreadsheet/testEXCEL_95.xls",
+ "spreadsheet/59074.xls",
+ "spreadsheet/60284.xls",
+ "spreadsheet/64130.xls",
+
+ // OOXML Strict is not yet supported, see bug #57699
+ "spreadsheet/SampleSS.strict.xlsx",
+ "spreadsheet/SimpleStrict.xlsx",
+ "spreadsheet/sample.strict.xlsx",
+ "spreadsheet/57914.xlsx",
+
+ // files with XML entities
+ "openxml4j/ContentTypeHasEntities.ooxml",
+
+ // non-TNEF files
+ "ddf/Container.dat",
+ "ddf/47143.dat",
+
+ // sheet cloning errors
+ "spreadsheet/56450.xls",
+ // "spreadsheet/OddStyleRecord.xls",
+
+ // msg files with non-standard encodings
+ "hsmf/ASCII_CP1251_LCID1049.msg",
+ "hsmf/ASCII_UTF-8_CP1252_LCID1031.msg",
+ "hsmf/ASCII_UTF-8_CP1252_LCID1031_HTML.msg",
+ "hsmf/HTMLBodyBinary_CP1251.msg",
+ "hsmf/HTMLBodyBinary_UTF-8.msg"
+ );
+
+ private static final Set<String> IGNORED = unmodifiableHashSet(
+ // OPC handler works / XSSF handler fails
+ "spreadsheet/57181.xlsm",
+ "spreadsheet/61300.xls"//intentionally fuzzed -- used to cause infinite loop
+ );
+
+ @Parameters(name="{index}: {0} using {1}")
+ public static Iterable<Object[]> files() {
+ DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setBasedir(ROOT_DIR);
+ scanner.setExcludes(SCAN_EXCLUDES);
+
+ scanner.scan();
+
+ System.out.println("Handling " + scanner.getIncludedFiles().length + " files");
+
+ List<Object[]> files = new ArrayList<>();
+ for(String file : scanner.getIncludedFiles()) {
+ file = file.replace('\\', '/'); // ... failures/handlers lookup doesn't work on windows otherwise
+ if (IGNORED.contains(file)) {
+ System.out.println("Ignoring " + file);
+ continue;
+ }
+ FileHandler handler = HANDLERS.get(getExtension(file));
+ files.add(new Object[] { file, handler });
+
+ // for some file-types also run OPCFileHandler
+ if(handler instanceof XSSFFileHandler ||
+ handler instanceof XWPFFileHandler ||
+ handler instanceof XSLFFileHandler ||
+ handler instanceof XDGFFileHandler) {
+ files.add(new Object[] { file, new OPCFileHandler() });
+ }
+
+ if (handler instanceof HSSFFileHandler ||
+ handler instanceof HSLFFileHandler ||
+ handler instanceof HWPFFileHandler ||
+ handler instanceof HDGFFileHandler) {
+ files.add(new Object[] { file, new HPSFFileHandler() });
+ }
+ }
+
+ return files;
+ }
+
+ @SuppressWarnings("DefaultAnnotationParam")
+ @Parameter(value=0)
+ public String file;
+
+ @Parameter(value=1)
+ public FileHandler handler;
+
+ @Before
+ public void setPassword() {
+ // this also removes the password for non encrypted files
+ String pass = TestAllFiles.FILE_PASSWORD.get(file);
+ Biff8EncryptionKey.setCurrentUserPassword(pass);
+ }
+
+ @Test
+ public void testAllFiles() throws Exception {
+ if(handler == null) {
+ fail("Did not find a handler for file " + file);
+ }
+
+ System.out.println("Reading " + file + " with " + handler.getClass().getSimpleName());
+ assertNotNull("Unknown file extension for file: " + file + ": " + getExtension(file), handler);
+ File inputFile = new File(ROOT_DIR, file);
+
+ // special cases where docx-handling breaks, but OPCPackage handling works
+ boolean ignoredOPC = (file.endsWith(".docx") || file.endsWith(".xlsx") ||
+ file.endsWith(".xlsb") || file.endsWith(".pptx")) &&
+ handler instanceof OPCFileHandler;
+ boolean ignoreHPSF = (handler instanceof HPSFFileHandler);
+
+ try {
+ try (InputStream stream = new BufferedInputStream(new FileInputStream(inputFile), 64 * 1024)) {
+ handler.handleFile(stream, file);
+ assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!",
+ OLD_FILES_HWPF.contains(file) && !ignoreHPSF);
+ }
+
+ handler.handleExtracting(inputFile);
+
+ assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!",
+ EXPECTED_FAILURES.contains(file) && !ignoredOPC && !ignoreHPSF);
+ } catch (OldFileFormatException e) {
+ // for old word files we should still support extracting text
+ if(OLD_FILES_HWPF.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 (AssumptionViolatedException e) {
+ // file handler ignored this file
+ } 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);
+ }
+ }
+
+ try {
+ // let some file handlers do additional stuff
+ handler.handleAdditional(inputFile);
+ } catch (AssumptionViolatedException e) {
+ // file handler ignored this file
+ } catch (Exception e) {
+ if(!EXPECTED_FAILURES.contains(file) && !AbstractFileHandler.EXPECTED_EXTRACTOR_FAILURES.contains(file)) {
+ System.out.println("Failed: " + file);
+ throw new Exception("While handling " + file, e);
+ }
+ }
+ }
+
+ public static String getExtension(String file) {
+ int pos = file.lastIndexOf('.');
+ if(pos == -1 || pos == file.length()-1) {
+ return file;
+ }
+
+ return file.substring(pos).toLowerCase(Locale.ROOT);
+ }
+
+ public static class NullFileHandler implements FileHandler {
+ public static final FileHandler instance = new NullFileHandler();
+
+ @Override
+ public void handleFile(InputStream stream, String path) {
+ }
+
+ @Override
+ public void handleExtracting(File file) {
+ }
+
+ @Override
+ public void handleAdditional(File file) {
+ }
+ }
+}
import javax.xml.transform.TransformerException;
import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.ooxml.POIXMLException;
+import org.apache.poi.examples.ss.ExcelComparator;
+import org.apache.poi.examples.xssf.eventusermodel.FromHowTo;
+import org.apache.poi.examples.xssf.eventusermodel.XLSX2CSV;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.ss.examples.ExcelComparator;
import org.apache.poi.util.IOUtils;
-import org.apache.poi.xssf.eventusermodel.XLSX2CSV;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
-import org.apache.poi.xssf.eventusermodel.examples.FromHowTo;
import org.apache.poi.xssf.extractor.XSSFExportToXml;
import org.apache.poi.xssf.usermodel.XSSFMap;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
// use the combined handler for HSSF/XSSF
handleWorkbook(wb);
-
+
// TODO: some documents fail currently...
//XSSFFormulaEvaluator evaluator = new XSSFFormulaEvaluator(wb);
//evaluator.evaluateAll();
// also verify general POIFS-stuff
new POIXMLDocumentHandler().handlePOIXMLDocument(wb);
-
+
// and finally ensure that exporting to XML works
exportToXML(wb);
// this allows to trigger a heap-dump at this point to see which memory is still allocated
//HeapDump.dumpHeap("/tmp/poi.hprof", false);
-
+
wb.close();
}
private void checkXSSFReader(OPCPackage p) throws IOException, OpenXML4JException {
XSSFReader reader = new XSSFReader(p);
-
+
// these can be null...
InputStream sharedStringsData = reader.getSharedStringsData();
if(sharedStringsData != null) {
stylesData.close();
}
reader.getStylesTable();
-
+
InputStream themesData = reader.getThemesData();
if(themesData != null) {
themesData.close();
}
assertNotNull(reader.getWorkbookData());
-
+
Iterator<InputStream> sheetsData = reader.getSheetsData();
while(sheetsData.hasNext()) {
InputStream str = sheetsData.next();
str.close();
}
}
-
+
private void exportToXML(XSSFWorkbook wb) throws SAXException,
TransformerException {
for (XSSFMap map : wb.getCustomXMLMappings()) {
public void testAdditional() throws Exception {
handleAdditional(new File("test-data/spreadsheet/poc-xmlbomb.xlsx"));
}
-
- // need to override all methods to omit calls to UTF-handling methods
+
+ // need to override all methods to omit calls to UTF-handling methods
static class NullPrintStream extends PrintStream {
@SuppressWarnings("resource")
NullPrintStream() {
/**
* This holds the common functionality for all POI
* Document classes.
- * Currently, this relates to Document Information Properties
+ * Currently, this relates to Document Information Properties
*/
public abstract class POIDocument implements Closeable {
/** Holds metadata on our document */
/**
* Constructs from the default POIFS
- *
+ *
* @param fs the filesystem the document is read from
*/
protected POIDocument(POIFSFileSystem fs) {
/**
* Fetch the Document Summary Information of the document
- *
- * @return The Document Summary Information or null
+ *
+ * @return The Document Summary Information or null
* if it could not be read for this document.
*/
public DocumentSummaryInformation getDocumentSummaryInformation() {
return dsInf;
}
- /**
+ /**
* Fetch the Summary Information of the document
- *
+ *
* @return The Summary information for the document or null
* if it could not be read for this document.
*/
}
return sInf;
}
-
+
/**
* Will create whichever of SummaryInformation
* and DocumentSummaryInformation (HPSF) properties
* If a given property set is missing or corrupt,
* it will remain null;
*/
- protected void readProperties() {
+ @Internal
+ public void readProperties() {
if (initialized) {
return;
}
}
return null;
}
-
- /**
+
+ /**
* For a given named property entry, either return it or null if
* if it wasn't found
- *
+ *
* @param setName The property to read
* @return The value of the given property or null if it wasn't found.
*
protected PropertySet getPropertySet(String setName) throws IOException {
return getPropertySet(setName, getEncryptionInfo());
}
-
- /**
+
+ /**
* For a given named property entry, either return it or null if
* if it wasn't found
- *
+ *
* @param setName The property to read
* @param encryptionInfo the encryption descriptor in case of cryptoAPI encryption
* @return The value of the given property or null if it wasn't found.
@SuppressWarnings("WeakerAccess")
protected PropertySet getPropertySet(String setName, EncryptionInfo encryptionInfo) throws IOException {
DirectoryNode dirNode = directory;
-
+
POIFSFileSystem encPoifs = null;
String step = "getting";
try {
encPoifs = dec.getSummaryEntries(dirNode, encryptedStream);
dirNode = encPoifs.getRoot();
}
-
+
//directory can be null when creating new documents
if (dirNode == null || !dirNode.hasEntry(setName)) {
return null;
}
-
+
// Find the entry, and get an input stream for it
step = "getting";
try (DocumentInputStream dis = dirNode.createDocumentInputStream(dirNode.getEntry(setName))) {
IOUtils.closeQuietly(encPoifs);
}
}
-
+
/**
* Writes out the updated standard Document Information Properties (HPSF)
* into the currently open POIFSFileSystem
- *
+ *
* @throws IOException if an error when writing to the open
* {@link POIFSFileSystem} occurs
*/
/**
* 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
+ *
+ * @throws IOException if an error when writing to the
* {@link POIFSFileSystem} occurs
*/
- protected void writeProperties(POIFSFileSystem outFS) throws IOException {
+ @Internal
+ public void writeProperties(POIFSFileSystem outFS) throws IOException {
writeProperties(outFS, null);
}
/**
* Writes out the standard Document Information Properties (HPSF)
* @param outFS the {@link POIFSFileSystem} 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
+ *
+ * @throws IOException if an error when writing to the
* {@link POIFSFileSystem} occurs
*/
protected void writeProperties(POIFSFileSystem outFS, List<String> writtenEntries) throws IOException {
writtenEntries.add(name);
}
}
-
+
/**
* Writes out a given PropertySet
*
* @param name the (POIFS Level) name of the property to write
- * @param set the PropertySet to write out
+ * @param set the PropertySet to write out
* @param outFS the {@link POIFSFileSystem} to write the property into
- *
- * @throws IOException if an error when writing to the
+ *
+ * @throws IOException if an error when writing to the
* {@link POIFSFileSystem} occurs
*/
private void writePropertySet(String name, PropertySet set, POIFSFileSystem outFS) throws IOException {
* Called during a {@link #write()} to ensure that the Document (and
* associated {@link POIFSFileSystem}) was opened in a way compatible
* with an in-place write.
- *
+ *
* @throws IllegalStateException if the document was opened suitably
*/
protected void validateInPlaceWritePossible() throws IllegalStateException {
throw new IllegalStateException("Opened read-only or via an InputStream, a Writeable File is required");
}
}
-
+
/**
* Writes the document out to the currently open {@link File}, via the
* writeable {@link POIFSFileSystem} it was opened from.
- *
+ *
* <p>This will fail (with an {@link IllegalStateException} if the
* document was opened read-only, opened from an {@link InputStream}
- * instead of a File, or if this is not the root document. For those cases,
- * you must use {@link #write(OutputStream)} or {@link #write(File)} to
+ * instead of a File, or if this is not the root document. For those cases,
+ * you must use {@link #write(OutputStream)} or {@link #write(File)} to
* write to a brand new document.
- *
+ *
* @since POI 3.15 beta 3
- *
+ *
* @throws IOException thrown on errors writing to the file
* @throws IllegalStateException if this isn't from a writable File
*/
public abstract void write() throws IOException;
/**
- * Writes the document out to the specified new {@link File}. If the file
+ * Writes the document out to the specified new {@link File}. If the file
* exists, it will be replaced, otherwise a new one will be created
*
* @since POI 3.15 beta 3
- *
+ *
* @param newFile The new File to write to.
- *
+ *
* @throws IOException thrown on errors writing to the file
*/
public abstract void write(File newFile) throws IOException;
/**
* Writes the document out to the specified output stream. The
* stream is not closed as part of this operation.
- *
+ *
* Note - if the Document was opened from a {@link File} rather
* than an {@link InputStream}, you <b>must</b> write out using
* {@link #write()} or to a different File. Overwriting the currently
* open file via an OutputStream isn't possible.
- *
+ *
* If {@code stream} is a {@link java.io.FileOutputStream} on a networked drive
* or has a high cost/latency associated with each written byte,
* consider wrapping the OutputStream in a {@link java.io.BufferedOutputStream}
* to improve write performance, or use {@link #write()} / {@link #write(File)}
* if possible.
- *
+ *
* @param out The stream to write to.
- *
+ *
* @throws IOException thrown on errors writing to the stream
*/
public abstract void write(OutputStream out) throws IOException;
public DirectoryNode getDirectory() {
return directory;
}
-
+
/**
* Clear/unlink the attached directory entry
*/
protected void clearDirectory() {
directory = null;
}
-
+
/**
* check if we were created by POIFS otherwise create a new dummy POIFS
* for storing the package data
- *
+ *
* @return {@code true} if dummy directory was created, {@code false} otherwise
*/
@SuppressWarnings("resource")
}
return false;
}
-
+
/**
* Replaces the attached directory, e.g. if this document is written
* to a new POIFSFileSystem
}
}
- /*package*/ InternalWorkbook getWorkbook() {
+ @Internal
+ public InternalWorkbook getWorkbook() {
return workbook;
}
package org.apache.poi.hssf.usermodel;
+import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.usermodel.WorkbookProvider;
import org.apache.poi.util.Internal;
/**
*/
@SuppressWarnings("unused")
@Internal
-public class HSSFWorkbookFactory extends WorkbookFactory {
+public class HSSFWorkbookFactory implements WorkbookProvider {
- static {
- init();
- }
-
- public static void init() {
- WorkbookFactory.createHssfFromScratch = HSSFWorkbookFactory::createWorkbook;
- WorkbookFactory.createHssfByNode = HSSFWorkbookFactory::createWorkbook;
+ @Override
+ public boolean accepts(FileMagic fm) {
+ return FileMagic.OLE2 == fm;
}
/**
*
* @return The created workbook
*/
- public static HSSFWorkbook createWorkbook() {
+ public HSSFWorkbook create() {
return new HSSFWorkbook();
}
* Note that in order to properly release resources the
* Workbook should be closed after use.
*/
- public static HSSFWorkbook createWorkbook(final DirectoryNode root) throws IOException {
- return new HSSFWorkbook(root, true);
+ public HSSFWorkbook create(final DirectoryNode root, String password) throws IOException {
+ boolean passwordSet = false;
+ if (password != null) {
+ Biff8EncryptionKey.setCurrentUserPassword(password);
+ passwordSet = true;
+ }
+ try {
+ return new HSSFWorkbook(root, true);
+ } finally {
+ if (passwordSet) {
+ Biff8EncryptionKey.setCurrentUserPassword(null);
+ }
+ }
+ }
+
+ @Override
+ public Workbook create(InputStream inp) throws IOException {
+ return create(inp, null);
+ }
+
+ @Override
+ public Workbook create(InputStream inp, String password) throws IOException {
+ POIFSFileSystem fs = new POIFSFileSystem(inp);
+ return create(fs.getRoot(), password);
+ }
+
+ @Override
+ public Workbook create(File file, String password, boolean readOnly) throws IOException {
+ boolean passwordSet = false;
+ if (password != null) {
+ Biff8EncryptionKey.setCurrentUserPassword(password);
+ passwordSet = true;
+ }
+ try {
+ return new HSSFWorkbook(new POIFSFileSystem(file, readOnly), true);
+ } finally {
+ if (passwordSet) {
+ Biff8EncryptionKey.setCurrentUserPassword(null);
+ }
+ }
}
}
public enum ChainingMode {
// ecb - only for standard encryption
- ecb("ECB", 1),
- cbc("CBC", 2),
+ ecb("ECB", 1, null),
+ cbc("CBC", 2, "ChainingModeCBC"),
/* Cipher feedback chaining (CFB), with an 8-bit window */
- cfb("CFB8", 3);
+ cfb("CFB8", 3, "ChainingModeCFB");
public final String jceId;
public final int ecmaId;
- ChainingMode(String jceId, int ecmaId) {
+ public final String xmlId;
+
+ ChainingMode(String jceId, int ecmaId, String xmlId) {
this.jceId = jceId;
this.ecmaId = ecmaId;
+ this.xmlId = xmlId;
+ }
+
+ public static ChainingMode fromXmlId(String xmlId) {
+ for (ChainingMode cm : values()) {
+ if (cm.xmlId != null && cm.xmlId.equals(xmlId)) {
+ return cm;
+ }
+ }
+ return null;
}
}
\ No newline at end of file
return flags;
}
- protected void setFlags(int flags) {
+ public void setFlags(int flags) {
this.flags = flags;
}
return sizeExtra;
}
- protected void setSizeExtra(int sizeExtra) {
+ public void setSizeExtra(int sizeExtra) {
this.sizeExtra = sizeExtra;
}
return cipherAlgorithm;
}
- protected void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
+ public void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
this.cipherAlgorithm = cipherAlgorithm;
if (cipherAlgorithm.allowedKeySize.length == 1) {
setKeySize(cipherAlgorithm.defaultKeySize);
return hashAlgorithm;
}
- protected void setHashAlgorithm(HashAlgorithm hashAlgorithm) {
+ public void setHashAlgorithm(HashAlgorithm hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm;
}
*
* @param keyBits
*/
- protected void setKeySize(int keyBits) {
+ public void setKeySize(int keyBits) {
this.keyBits = keyBits;
for (int allowedBits : getCipherAlgorithm().allowedKeySize) {
if (allowedBits == keyBits) {
return blockSize;
}
- protected void setBlockSize(int blockSize) {
+ public void setBlockSize(int blockSize) {
this.blockSize = blockSize;
}
return keySalt;
}
- protected void setKeySalt(byte[] salt) {
+ public void setKeySalt(byte[] salt) {
this.keySalt = (salt == null) ? null : salt.clone();
}
return providerType;
}
- protected void setCipherProvider(CipherProvider providerType) {
+ public void setCipherProvider(CipherProvider providerType) {
this.providerType = providerType;
}
return cspName;
}
- protected void setCspName(String cspName) {
+ public void setCspName(String cspName) {
this.cspName = cspName;
}
* @see #getBuilder(EncryptionMode)
*/
public class EncryptionInfo implements GenericRecord {
+
+ /**
+ * Document entry name for encryption info xml descriptor
+ */
+ public static final String ENCRYPTION_INFO_ENTRY = "EncryptionInfo";
+
/**
* A flag that specifies whether CryptoAPI RC4 or ECMA-376 encryption
* ECMA-376 is used. It MUST be 1 unless flagExternal is 1. If flagExternal is 1, it MUST be 0.
versionMinor = dis.readUShort();
}
- if ( versionMajor == xor.versionMajor
- && versionMinor == xor.versionMinor) {
+ if (versionMajor == xor.versionMajor && versionMinor == xor.versionMinor) {
encryptionMode = xor;
encryptionFlags = -1;
- } else if ( versionMajor == binaryRC4.versionMajor
- && versionMinor == binaryRC4.versionMinor) {
+ } else if (versionMajor == binaryRC4.versionMajor && versionMinor == binaryRC4.versionMinor) {
encryptionMode = binaryRC4;
encryptionFlags = -1;
- } else if (
- 2 <= versionMajor && versionMajor <= 4
- && versionMinor == 2) {
+ } else if (2 <= versionMajor && versionMajor <= 4 && versionMinor == 2) {
encryptionFlags = dis.readInt();
- encryptionMode = (
- preferredEncryptionMode == cryptoAPI
- || !flagAES.isSet(encryptionFlags))
- ? cryptoAPI : standard;
- } else if (
- versionMajor == agile.versionMajor
- && versionMinor == agile.versionMinor){
+ encryptionMode = (preferredEncryptionMode == cryptoAPI || !flagAES.isSet(encryptionFlags)) ? cryptoAPI : standard;
+ } else if (versionMajor == agile.versionMajor && versionMinor == agile.versionMinor){
encryptionMode = agile;
encryptionFlags = dis.readInt();
} else {
return chainingMode;
}
- protected void setSalt(byte[] salt) {
+ public void setSalt(byte[] salt) {
this.salt = (salt == null) ? null : salt.clone();
}
- protected void setEncryptedVerifier(byte[] encryptedVerifier) {
+ public void setEncryptedVerifier(byte[] encryptedVerifier) {
this.encryptedVerifier = (encryptedVerifier == null) ? null : encryptedVerifier.clone();
}
- protected void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
+ public void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
this.encryptedVerifierHash = (encryptedVerifierHash == null) ? null : encryptedVerifierHash.clone();
}
- protected void setEncryptedKey(byte[] encryptedKey) {
+ public void setEncryptedKey(byte[] encryptedKey) {
this.encryptedKey = (encryptedKey == null) ? null : encryptedKey.clone();
}
- protected void setSpinCount(int spinCount) {
+ public void setSpinCount(int spinCount) {
this.spinCount = spinCount;
}
- protected void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
+ public void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
this.cipherAlgorithm = cipherAlgorithm;
}
- protected void setChainingMode(ChainingMode chainingMode) {
+ public void setChainingMode(ChainingMode chainingMode) {
this.chainingMode = chainingMode;
}
- protected void setHashAlgorithm(HashAlgorithm hashAlgorithm) {
+ public void setHashAlgorithm(HashAlgorithm hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm;
}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import static org.apache.poi.poifs.crypt.CryptoFunctions.generateIv;
+import static org.apache.poi.poifs.crypt.CryptoFunctions.generateKey;
+import static org.apache.poi.poifs.crypt.CryptoFunctions.getBlock0;
+import static org.apache.poi.poifs.crypt.CryptoFunctions.getCipher;
+import static org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest;
+import static org.apache.poi.poifs.crypt.CryptoFunctions.hashPassword;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.RC2ParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.ChunkedCipherInputStream;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.CryptoFunctions;
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.poi.poifs.crypt.EncryptionHeader;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+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.util.LittleEndian;
+
+/**
+ * Decryptor implementation for Agile Encryption
+ */
+public class AgileDecryptor extends Decryptor {
+ static final byte[] kVerifierInputBlock = longToBytes(0xfea7d2763b4b9e79L);
+ static final byte[] kHashedVerifierBlock = longToBytes(0xd7aa0f6d3061344eL);
+ static final byte[] kCryptoKeyBlock = longToBytes(0x146e0be7abacd0d6L);
+ static final byte[] kIntegrityKeyBlock = longToBytes(0x5fb2ad010cb9e1f6L);
+ static final byte[] kIntegrityValueBlock = longToBytes(0xa0677f02b22c8433L);
+
+ private long _length = -1;
+
+ protected AgileDecryptor() {
+ }
+
+ protected AgileDecryptor(AgileDecryptor other) {
+ super(other);
+ _length = other._length;
+ }
+
+ private static byte[] longToBytes(long l) {
+ return ByteBuffer.allocate(Long.BYTES).putLong(l).array();
+ }
+
+ /**
+ * set decryption password
+ */
+ @Override
+ public boolean verifyPassword(String password) throws GeneralSecurityException {
+ AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
+
+ int blockSize = header.getBlockSize();
+
+ byte[] pwHash = hashPassword(password, ver.getHashAlgorithm(), ver.getSalt(), ver.getSpinCount());
+
+ /*
+ * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
+ * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
+ * attribute.
+ * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
+ * the binary byte array used to create the saltValue attribute, and a blockKey byte array
+ * consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79.
+ * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
+ * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
+ * integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of
+ * blockSize bytes.
+ * 4. Use base64 to encode the result of step 3.
+ */
+ byte[] verfierInputEnc = hashInput(ver, pwHash, kVerifierInputBlock, ver.getEncryptedVerifier(), Cipher.DECRYPT_MODE);
+ setVerifier(verfierInputEnc);
+ MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm());
+ byte[] verifierHash = hashMD.digest(verfierInputEnc);
+
+ /*
+ * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
+ * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for
+ * encryptedVerifierHashInput.
+ * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
+ * the binary byte array used to create the saltValue attribute, and a blockKey byte array
+ * consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e.
+ * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as
+ * an initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of
+ * blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
+ * 4. Use base64 to encode the result of step 3.
+ */
+ byte[] verifierHashDec = hashInput(ver, pwHash, kHashedVerifierBlock, ver.getEncryptedVerifierHash(), Cipher.DECRYPT_MODE);
+ verifierHashDec = getBlock0(verifierHashDec, ver.getHashAlgorithm().hashSize);
+
+ /*
+ * encryptedKeyValue: This attribute MUST be generated by using the following steps:
+ * 1. Generate a random array of bytes that is the same size as specified by the
+ * Encryptor.KeyData.keyBits attribute of the parent element.
+ * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password,
+ * the binary byte array used to create the saltValue attribute, and a blockKey byte array
+ * consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6.
+ * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
+ * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
+ * integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of
+ * blockSize bytes.
+ * 4. Use base64 to encode the result of step 3.
+ */
+ byte[] keyspec = hashInput(ver, pwHash, kCryptoKeyBlock, ver.getEncryptedKey(), Cipher.DECRYPT_MODE);
+ keyspec = getBlock0(keyspec, header.getKeySize()/8);
+ SecretKeySpec secretKey = new SecretKeySpec(keyspec, header.getCipherAlgorithm().jceId);
+
+ /*
+ * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
+ * contained within the KeyEncryptors sequence. Use this key for encryption operations in the
+ * remaining steps of this section.
+ * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the
+ * KeyData.hashSize attribute.
+ * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the
+ * KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes: 0x5f,
+ * 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an initialization vector as specified in
+ * section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize bytes, pad the
+ * array with 0x00 to the next integral multiple of blockSize bytes.
+ * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3.
+ */
+ byte[] vec = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, blockSize);
+ CipherAlgorithm cipherAlgo = header.getCipherAlgorithm();
+ Cipher cipher = getCipher(secretKey, cipherAlgo, header.getChainingMode(), vec, Cipher.DECRYPT_MODE);
+ byte[] hmacKey = cipher.doFinal(header.getEncryptedHmacKey());
+ hmacKey = getBlock0(hmacKey, header.getHashAlgorithm().hashSize);
+
+ /*
+ * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
+ * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
+ * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
+ * used as the message.
+ * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
+ * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
+ * 7. Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6.
+ */
+ vec = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize);
+ cipher = getCipher(secretKey, cipherAlgo, ver.getChainingMode(), vec, Cipher.DECRYPT_MODE);
+ byte[] hmacValue = cipher.doFinal(header.getEncryptedHmacValue());
+ hmacValue = getBlock0(hmacValue, header.getHashAlgorithm().hashSize);
+
+ if (Arrays.equals(verifierHashDec, verifierHash)) {
+ setSecretKey(secretKey);
+ setIntegrityHmacKey(hmacKey);
+ setIntegrityHmacValue(hmacValue);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected static int getNextBlockSize(int inputLen, int blockSize) {
+ return (int)Math.ceil(inputLen / (double)blockSize) * blockSize;
+ }
+
+ /* package */ static byte[] hashInput(AgileEncryptionVerifier ver, byte[] pwHash, byte[] blockKey, byte[] inputKey, int cipherMode) {
+ CipherAlgorithm cipherAlgo = ver.getCipherAlgorithm();
+ ChainingMode chainMode = ver.getChainingMode();
+ int keySize = ver.getKeySize()/8;
+ int blockSize = ver.getBlockSize();
+ HashAlgorithm hashAlgo = ver.getHashAlgorithm();
+
+ byte[] intermedKey = generateKey(pwHash, hashAlgo, blockKey, keySize);
+ SecretKey skey = new SecretKeySpec(intermedKey, cipherAlgo.jceId);
+ byte[] iv = generateIv(hashAlgo, ver.getSalt(), null, blockSize);
+ Cipher cipher = getCipher(skey, cipherAlgo, chainMode, iv, cipherMode);
+ byte[] hashFinal;
+
+ try {
+ inputKey = getBlock0(inputKey, getNextBlockSize(inputKey.length, blockSize));
+ hashFinal = cipher.doFinal(inputKey);
+ return hashFinal;
+ } catch (GeneralSecurityException e) {
+ throw new EncryptedDocumentException(e);
+ }
+ }
+
+ @Override
+ public InputStream getDataStream(DirectoryNode dir) throws IOException, GeneralSecurityException {
+ DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
+ _length = dis.readLong();
+ return new AgileCipherInputStream(dis, _length);
+ }
+
+ @Override
+ public long getLength(){
+ if(_length == -1) {
+ throw new IllegalStateException("EcmaDecryptor.getDataStream() was not called");
+ }
+ return _length;
+ }
+
+
+ protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode)
+ throws GeneralSecurityException {
+ EncryptionHeader header = encryptionInfo.getHeader();
+ String padding = (lastChunk ? "PKCS5Padding" : "NoPadding");
+ if (existing == null || !existing.getAlgorithm().endsWith(padding)) {
+ existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding);
+ }
+
+ byte[] blockKey = new byte[4];
+ LittleEndian.putInt(blockKey, 0, block);
+ byte[] iv = generateIv(header.getHashAlgorithm(), header.getKeySalt(), blockKey, header.getBlockSize());
+
+ AlgorithmParameterSpec aps;
+ if (header.getCipherAlgorithm() == CipherAlgorithm.rc2) {
+ aps = new RC2ParameterSpec(skey.getEncoded().length*8, iv);
+ } else {
+ aps = new IvParameterSpec(iv);
+ }
+
+ existing.init(encryptionMode, skey, aps);
+
+ return existing;
+ }
+
+ /**
+ * 2.3.4.15 Data Encryption (Agile Encryption)
+ *
+ * The EncryptedPackage stream (1) MUST be encrypted in 4096-byte segments to facilitate nearly
+ * random access while allowing CBC modes to be used in the encryption process.
+ * The initialization vector for the encryption process MUST be obtained by using the zero-based
+ * segment number as a blockKey and the binary form of the KeyData.saltValue as specified in
+ * section 2.3.4.12. The block number MUST be represented as a 32-bit unsigned integer.
+ * Data blocks MUST then be encrypted by using the initialization vector and the intermediate key
+ * obtained by decrypting the encryptedKeyValue from a KeyEncryptor contained within the
+ * KeyEncryptors sequence as specified in section 2.3.4.10. The final data block MUST be padded to
+ * the next integral multiple of the KeyData.blockSize value. Any padding bytes can be used. Note
+ * that the StreamSize field of the EncryptedPackage field specifies the number of bytes of
+ * unencrypted data as specified in section 2.3.4.4.
+ */
+ private class AgileCipherInputStream extends ChunkedCipherInputStream {
+ public AgileCipherInputStream(DocumentInputStream stream, long size)
+ throws GeneralSecurityException {
+ super(stream, size, 4096);
+ }
+
+ // TODO: calculate integrity hmac while reading the stream
+ // for a post-validation of the data
+
+ @Override
+ protected Cipher initCipherForBlock(Cipher cipher, int block)
+ throws GeneralSecurityException {
+ return AgileDecryptor.initCipherForBlock(cipher, block, false, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE);
+ }
+ }
+
+ @Override
+ public AgileDecryptor copy() {
+ return new AgileDecryptor(this);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.EncryptionHeader;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.util.GenericRecordUtil;
+
+public class AgileEncryptionHeader extends EncryptionHeader {
+ private byte[] encryptedHmacKey;
+ private byte[] encryptedHmacValue;
+
+ public AgileEncryptionHeader(String descriptor) {
+ this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
+ }
+
+ public AgileEncryptionHeader(AgileEncryptionHeader other) {
+ super(other);
+ encryptedHmacKey = (other.encryptedHmacKey == null) ? null : other.encryptedHmacKey.clone();
+ encryptedHmacValue = (other.encryptedHmacValue == null) ? null : other.encryptedHmacValue.clone();
+ }
+
+ protected AgileEncryptionHeader(EncryptionDocument ed) {
+ KeyData keyData;
+ try {
+ keyData = ed.getKeyData();
+ if (keyData == null) {
+ throw new NullPointerException("keyData not set");
+ }
+ } catch (Exception e) {
+ throw new EncryptedDocumentException("Unable to parse keyData");
+ }
+
+ int keyBits = keyData.getKeyBits();
+
+ CipherAlgorithm ca = keyData.getCipherAlgorithm();
+ setCipherAlgorithm(ca);
+ setCipherProvider(ca.provider);
+
+ setKeySize(keyBits);
+ setFlags(0);
+ setSizeExtra(0);
+ setCspName(null);
+ setBlockSize(keyData.getBlockSize());
+
+ setChainingMode(keyData.getCipherChaining());
+
+ if (getChainingMode() != ChainingMode.cbc && getChainingMode() != ChainingMode.cfb) {
+ throw new EncryptedDocumentException("Unsupported chaining mode - "+ keyData.getCipherChaining());
+ }
+
+ int hashSize = keyData.getHashSize();
+
+ HashAlgorithm ha = keyData.getHashAlgorithm();
+ setHashAlgorithm(ha);
+
+ if (getHashAlgorithm().hashSize != hashSize) {
+ throw new EncryptedDocumentException("Unsupported hash algorithm: " +
+ keyData.getHashAlgorithm() + " @ " + hashSize + " bytes");
+ }
+
+ int saltLength = keyData.getSaltSize();
+ setKeySalt(keyData.getSaltValue());
+ if (getKeySalt().length != saltLength) {
+ throw new EncryptedDocumentException("Invalid salt length");
+ }
+
+ DataIntegrity di = ed.getDataIntegrity();
+ setEncryptedHmacKey(di.getEncryptedHmacKey());
+ setEncryptedHmacValue(di.getEncryptedHmacValue());
+ }
+
+
+ public AgileEncryptionHeader(CipherAlgorithm algorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
+ setCipherAlgorithm(algorithm);
+ setHashAlgorithm(hashAlgorithm);
+ setKeySize(keyBits);
+ setBlockSize(blockSize);
+ setChainingMode(chainingMode);
+ }
+
+ // make method visible for this package
+ @Override
+ public void setKeySalt(byte[] salt) {
+ if (salt == null || salt.length != getBlockSize()) {
+ throw new EncryptedDocumentException("invalid verifier salt");
+ }
+ super.setKeySalt(salt);
+ }
+
+ public byte[] getEncryptedHmacKey() {
+ return encryptedHmacKey;
+ }
+
+ protected void setEncryptedHmacKey(byte[] encryptedHmacKey) {
+ this.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone();
+ }
+
+ public byte[] getEncryptedHmacValue() {
+ return encryptedHmacValue;
+ }
+
+ protected void setEncryptedHmacValue(byte[] encryptedHmacValue) {
+ this.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone();
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "encryptedHmacKey", this::getEncryptedHmacKey,
+ "encryptedHmacValue", this::getEncryptedHmacValue
+ );
+ }
+
+ @Override
+ public AgileEncryptionHeader copy() {
+ return new AgileEncryptionHeader(this);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.EncryptionInfoBuilder;
+import org.apache.poi.poifs.crypt.EncryptionMode;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.XMLHelper;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder {
+
+ @Override
+ public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException {
+ EncryptionDocument ed = parseDescriptor((InputStream)dis);
+ info.setHeader(new AgileEncryptionHeader(ed));
+ info.setVerifier(new AgileEncryptionVerifier(ed));
+ if (info.getVersionMajor() == EncryptionMode.agile.versionMajor
+ && info.getVersionMinor() == EncryptionMode.agile.versionMinor) {
+ AgileDecryptor dec = new AgileDecryptor();
+ dec.setEncryptionInfo(info);
+ info.setDecryptor(dec);
+ AgileEncryptor enc = new AgileEncryptor();
+ enc.setEncryptionInfo(info);
+ info.setEncryptor(enc);
+ }
+ }
+
+ @Override
+ public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
+ if (cipherAlgorithm == null) {
+ cipherAlgorithm = CipherAlgorithm.aes128;
+ }
+ if (cipherAlgorithm == CipherAlgorithm.rc4) {
+ throw new EncryptedDocumentException("RC4 must not be used with agile encryption.");
+ }
+ if (hashAlgorithm == null) {
+ hashAlgorithm = HashAlgorithm.sha1;
+ }
+ if (chainingMode == null) {
+ chainingMode = ChainingMode.cbc;
+ }
+ if (!(chainingMode == ChainingMode.cbc || chainingMode == ChainingMode.cfb)) {
+ throw new EncryptedDocumentException("Agile encryption only supports CBC/CFB chaining.");
+ }
+ if (keyBits == -1) {
+ keyBits = cipherAlgorithm.defaultKeySize;
+ }
+ if (blockSize == -1) {
+ blockSize = cipherAlgorithm.blockSize;
+ }
+ boolean found = false;
+ for (int ks : cipherAlgorithm.allowedKeySize) {
+ found |= (ks == keyBits);
+ }
+ if (!found) {
+ throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+ cipherAlgorithm);
+ }
+ info.setHeader(new AgileEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+ info.setVerifier(new AgileEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+ AgileDecryptor dec = new AgileDecryptor();
+ dec.setEncryptionInfo(info);
+ info.setDecryptor(dec);
+ AgileEncryptor enc = new AgileEncryptor();
+ enc.setEncryptionInfo(info);
+ info.setEncryptor(enc);
+ }
+
+ protected static EncryptionDocument parseDescriptor(String descriptor) {
+ return parseDescriptor(new InputSource(descriptor));
+ }
+
+ protected static EncryptionDocument parseDescriptor(InputStream descriptor) {
+ return parseDescriptor(new InputSource(descriptor));
+ }
+
+ private static EncryptionDocument parseDescriptor(InputSource descriptor) {
+ try {
+ Document doc = XMLHelper.newDocumentBuilder().parse(descriptor);
+ EncryptionDocument ed = new EncryptionDocument();
+ ed.parse(doc);
+ return ed;
+ } catch (SAXException|IOException e) {
+ throw new EncryptedDocumentException("Unable to parse encryption descriptor", e);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.EncryptionVerifier;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+
+/**
+ * Used when checking if a key is valid for a document
+ */
+public class AgileEncryptionVerifier extends EncryptionVerifier {
+
+ private int keyBits = -1;
+ private int blockSize = -1;
+
+ @SuppressWarnings("unused")
+ public AgileEncryptionVerifier(String descriptor) {
+ this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
+ }
+
+ protected AgileEncryptionVerifier(EncryptionDocument ed) {
+ PasswordKeyEncryptor keyData = null;
+ for (KeyEncryptor ke : ed.getKeyEncryptors()) {
+ keyData = ke.getPasswordKeyEncryptor();
+ if (keyData != null) {
+ break;
+ }
+ }
+
+ if (keyData == null) {
+ throw new NullPointerException("encryptedKey not set");
+ }
+
+ setCipherAlgorithm(keyData.getCipherAlgorithm());
+ setKeySize(keyData.getKeyBits());
+
+ int blockSize = keyData.getBlockSize();
+ setBlockSize(blockSize);
+
+ int hashSize = keyData.getHashSize();
+
+ HashAlgorithm ha = keyData.getHashAlgorithm();
+ setHashAlgorithm(ha);
+
+ if (getHashAlgorithm().hashSize != hashSize) {
+ throw new EncryptedDocumentException("Unsupported hash algorithm: " +
+ keyData.getHashAlgorithm() + " @ " + hashSize + " bytes");
+ }
+
+ setSpinCount(keyData.getSpinCount());
+ setEncryptedVerifier(keyData.getEncryptedVerifierHashInput());
+ setSalt(keyData.getSaltValue());
+ setEncryptedKey(keyData.getEncryptedKeyValue());
+ setEncryptedVerifierHash(keyData.getEncryptedVerifierHashValue());
+
+ int saltSize = keyData.getSaltSize();
+ if (saltSize != getSalt().length) {
+ throw new EncryptedDocumentException("Invalid salt size");
+ }
+
+ setChainingMode(keyData.getCipherChaining());
+ if (keyData.getCipherChaining() != ChainingMode.cbc && keyData.getCipherChaining() != ChainingMode.cfb) {
+ throw new EncryptedDocumentException("Unsupported chaining mode - "+ keyData.getCipherChaining());
+ }
+ }
+
+ public AgileEncryptionVerifier(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
+ setCipherAlgorithm(cipherAlgorithm);
+ setHashAlgorithm(hashAlgorithm);
+ setChainingMode(chainingMode);
+ setKeySize(keyBits);
+ setBlockSize(blockSize);
+ setSpinCount(100000); // TODO: use parameter
+ }
+
+ public AgileEncryptionVerifier(AgileEncryptionVerifier other) {
+ super(other);
+ keyBits = other.keyBits;
+ blockSize = other.blockSize;
+ }
+
+ @Override
+ public void setSalt(byte[] salt) {
+ if (salt == null || salt.length != getCipherAlgorithm().blockSize) {
+ throw new EncryptedDocumentException("invalid verifier salt");
+ }
+ super.setSalt(salt);
+ }
+
+ // make method visible for this package
+ @Override
+ public void setEncryptedVerifier(byte[] encryptedVerifier) {
+ super.setEncryptedVerifier(encryptedVerifier);
+ }
+
+ // make method visible for this package
+ @Override
+ public void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
+ super.setEncryptedVerifierHash(encryptedVerifierHash);
+ }
+
+ // make method visible for this package
+ @Override
+ public void setEncryptedKey(byte[] encryptedKey) {
+ super.setEncryptedKey(encryptedKey);
+ }
+
+ @Override
+ public AgileEncryptionVerifier copy() {
+ return new AgileEncryptionVerifier(this);
+ }
+
+
+ /**
+ * The keysize (in bits) of the verifier data. This usually equals the keysize of the header,
+ * but only on a few exceptions, like files generated by Office for Mac, can be
+ * different.
+ *
+ * @return the keysize (in bits) of the verifier.
+ */
+ public int getKeySize() {
+ return keyBits;
+ }
+
+
+ /**
+ * The blockSize (in bytes) of the verifier data.
+ * This usually equals the blocksize of the header.
+ *
+ * @return the blockSize (in bytes) of the verifier,
+ */
+ public int getBlockSize() {
+ return blockSize;
+ }
+
+ /**
+ * Sets the keysize (in bits) of the verifier
+ *
+ * @param keyBits the keysize (in bits)
+ */
+ public void setKeySize(int keyBits) {
+ this.keyBits = keyBits;
+ for (int allowedBits : getCipherAlgorithm().allowedKeySize) {
+ if (allowedBits == keyBits) {
+ return;
+ }
+ }
+ throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for cipher "+getCipherAlgorithm());
+ }
+
+
+ /**
+ * Sets the blockSize (in bytes) of the verifier
+ *
+ * @param blockSize the blockSize (in bytes)
+ */
+ public void setBlockSize(int blockSize) {
+ this.blockSize = blockSize;
+ }
+
+ @Override
+ public final void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
+ super.setCipherAlgorithm(cipherAlgorithm);
+ if (cipherAlgorithm.allowedKeySize.length == 1) {
+ setKeySize(cipherAlgorithm.defaultKeySize);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import static org.apache.poi.poifs.crypt.CryptoFunctions.getBlock0;
+import static org.apache.poi.poifs.crypt.CryptoFunctions.getCipher;
+import static org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest;
+import static org.apache.poi.poifs.crypt.CryptoFunctions.hashPassword;
+import static org.apache.poi.poifs.crypt.DataSpaceMapUtils.createEncryptionEntry;
+import static org.apache.poi.poifs.crypt.EncryptionInfo.ENCRYPTION_INFO_ENTRY;
+import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.getNextBlockSize;
+import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.hashInput;
+import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kCryptoKeyBlock;
+import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kHashedVerifierBlock;
+import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kIntegrityKeyBlock;
+import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kIntegrityValueBlock;
+import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kVerifierInputBlock;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.Random;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
+import org.apache.poi.poifs.crypt.CryptoFunctions;
+import org.apache.poi.poifs.crypt.DataSpaceMapUtils;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.Encryptor;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.XMLHelper;
+import org.w3c.dom.Document;
+
+public class AgileEncryptor extends Encryptor {
+
+ //arbitrarily selected; may need to increase
+ private static final int MAX_RECORD_LENGTH = 1_000_000;
+
+ private byte[] integritySalt;
+ private byte[] pwHash;
+
+ protected AgileEncryptor() {}
+
+ protected AgileEncryptor(AgileEncryptor other) {
+ super(other);
+ integritySalt = (other.integritySalt == null) ? null : other.integritySalt.clone();
+ pwHash = (other.pwHash == null) ? null : other.pwHash.clone();
+ }
+
+ @Override
+ public void confirmPassword(String password) {
+ // see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier
+ Random r = new SecureRandom();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
+ int blockSize = header.getBlockSize();
+ int keySize = header.getKeySize()/8;
+ int hashSize = header.getHashAlgorithm().hashSize;
+
+ byte[] newVerifierSalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
+ , newVerifier = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
+ , newKeySalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
+ , newKeySpec = IOUtils.safelyAllocate(keySize, MAX_RECORD_LENGTH)
+ , newIntegritySalt = IOUtils.safelyAllocate(hashSize, MAX_RECORD_LENGTH);
+ r.nextBytes(newVerifierSalt); // blocksize
+ r.nextBytes(newVerifier); // blocksize
+ r.nextBytes(newKeySalt); // blocksize
+ r.nextBytes(newKeySpec); // keysize
+ r.nextBytes(newIntegritySalt); // hashsize
+
+ confirmPassword(password, newKeySpec, newKeySalt, newVerifierSalt, newVerifier, newIntegritySalt);
+ }
+
+ @Override
+ public void confirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) {
+ AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
+
+ ver.setSalt(verifierSalt);
+ header.setKeySalt(keySalt);
+
+ int blockSize = header.getBlockSize();
+
+ pwHash = hashPassword(password, ver.getHashAlgorithm(), verifierSalt, ver.getSpinCount());
+
+ /*
+ * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
+ * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
+ * attribute.
+ * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
+ * the binary byte array used to create the saltValue attribute, and a blockKey byte array
+ * consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79.
+ * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
+ * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
+ * integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of
+ * blockSize bytes.
+ * 4. Use base64 to encode the result of step 3.
+ */
+ byte[] encryptedVerifier = hashInput(ver, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
+ ver.setEncryptedVerifier(encryptedVerifier);
+
+
+ /*
+ * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
+ * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for
+ * encryptedVerifierHashInput.
+ * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
+ * the binary byte array used to create the saltValue attribute, and a blockKey byte array
+ * consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e.
+ * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as
+ * an initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of
+ * blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
+ * 4. Use base64 to encode the result of step 3.
+ */
+ MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm());
+ byte[] hashedVerifier = hashMD.digest(verifier);
+ byte[] encryptedVerifierHash = hashInput(ver, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
+ ver.setEncryptedVerifierHash(encryptedVerifierHash);
+
+ /*
+ * encryptedKeyValue: This attribute MUST be generated by using the following steps:
+ * 1. Generate a random array of bytes that is the same size as specified by the
+ * Encryptor.KeyData.keyBits attribute of the parent element.
+ * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password,
+ * the binary byte array used to create the saltValue attribute, and a blockKey byte array
+ * consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6.
+ * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
+ * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
+ * integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of
+ * blockSize bytes.
+ * 4. Use base64 to encode the result of step 3.
+ */
+ byte[] encryptedKey = hashInput(ver, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
+ ver.setEncryptedKey(encryptedKey);
+
+ SecretKey secretKey = new SecretKeySpec(keySpec, header.getCipherAlgorithm().jceId);
+ setSecretKey(secretKey);
+
+ /*
+ * 2.3.4.14 DataIntegrity Generation (Agile Encryption)
+ *
+ * The DataIntegrity element contained within an Encryption element MUST be generated by using
+ * the following steps:
+ * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
+ * contained within the KeyEncryptors sequence. Use this key for encryption operations in the
+ * remaining steps of this section.
+ * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the
+ * KeyData.hashSize attribute.
+ * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the
+ * KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes:
+ * 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an initialization vector as
+ * specified in section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize
+ * bytes, pad the array with 0x00 to the next integral multiple of blockSize bytes.
+ * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3.
+ * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
+ * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
+ * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
+ * used as the message.
+ * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
+ * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
+ * 7. Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6.
+ */
+ this.integritySalt = integritySalt.clone();
+
+ try {
+ byte[] vec = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, header.getBlockSize());
+ Cipher cipher = getCipher(secretKey, header.getCipherAlgorithm(), header.getChainingMode(), vec, Cipher.ENCRYPT_MODE);
+ byte[] hmacKey = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize));
+ byte[] encryptedHmacKey = cipher.doFinal(hmacKey);
+ header.setEncryptedHmacKey(encryptedHmacKey);
+ } catch (GeneralSecurityException e) {
+ throw new EncryptedDocumentException(e);
+ }
+ }
+
+ @Override
+ public OutputStream getDataStream(DirectoryNode dir)
+ throws IOException, GeneralSecurityException {
+ // TODO: initialize headers
+ return new AgileCipherOutputStream(dir);
+ }
+
+ /**
+ * Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
+ * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
+ * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
+ * used as the message.
+ *
+ * Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
+ * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
+ **/
+ protected void updateIntegrityHMAC(File tmpFile, int oleStreamSize) throws GeneralSecurityException, IOException {
+ // as the integrity hmac needs to contain the StreamSize,
+ // it's not possible to calculate it on-the-fly while buffering
+ // TODO: add stream size parameter to getDataStream()
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
+ int blockSize = header.getBlockSize();
+ HashAlgorithm hashAlgo = header.getHashAlgorithm();
+ Mac integrityMD = CryptoFunctions.getMac(hashAlgo);
+ byte[] hmacKey = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize));
+ integrityMD.init(new SecretKeySpec(hmacKey, hashAlgo.jceHmacId));
+
+ byte[] buf = new byte[1024];
+ LittleEndian.putLong(buf, 0, oleStreamSize);
+ integrityMD.update(buf, 0, LittleEndianConsts.LONG_SIZE);
+
+ try (InputStream fis = new FileInputStream(tmpFile)) {
+ int readBytes;
+ while ((readBytes = fis.read(buf)) != -1) {
+ integrityMD.update(buf, 0, readBytes);
+ }
+ }
+
+ byte[] hmacValue = integrityMD.doFinal();
+ byte[] hmacValueFilled = getBlock0(hmacValue, getNextBlockSize(hmacValue.length, blockSize));
+
+ byte[] iv = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize);
+ Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE);
+ byte[] encryptedHmacValue = cipher.doFinal(hmacValueFilled);
+
+ header.setEncryptedHmacValue(encryptedHmacValue);
+ }
+
+ protected EncryptionDocument createEncryptionDocument() {
+ AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
+
+ EncryptionDocument ed = new EncryptionDocument();
+ KeyData keyData = new KeyData();
+ ed.setKeyData(keyData);
+
+ KeyEncryptor keyEnc = new KeyEncryptor();
+ ed.getKeyEncryptors().add(keyEnc);
+
+ PasswordKeyEncryptor keyPass = new PasswordKeyEncryptor();
+ keyEnc.setPasswordKeyEncryptor(keyPass);
+
+ keyPass.setSpinCount(ver.getSpinCount());
+
+ keyData.setSaltSize(header.getBlockSize());
+ keyPass.setSaltSize(ver.getBlockSize());
+
+ keyData.setBlockSize(header.getBlockSize());
+ keyPass.setBlockSize(ver.getBlockSize());
+
+ keyData.setKeyBits(header.getKeySize());
+ keyPass.setKeyBits(ver.getKeySize());
+
+ keyData.setHashSize(header.getHashAlgorithm().hashSize);
+ keyPass.setHashSize(ver.getHashAlgorithm().hashSize);
+
+ // header and verifier have to have the same cipher algorithm
+ if (!header.getCipherAlgorithm().xmlId.equals(ver.getCipherAlgorithm().xmlId)) {
+ throw new EncryptedDocumentException("Cipher algorithm of header and verifier have to match");
+ }
+
+ keyData.setCipherAlgorithm(header.getCipherAlgorithm());
+ keyPass.setCipherAlgorithm(header.getCipherAlgorithm());
+
+ keyData.setCipherChaining(header.getChainingMode());
+ keyPass.setCipherChaining(header.getChainingMode());
+
+ keyData.setHashAlgorithm(header.getHashAlgorithm());
+ keyPass.setHashAlgorithm(ver.getHashAlgorithm());
+
+ keyData.setSaltValue(header.getKeySalt());
+ keyPass.setSaltValue(ver.getSalt());
+ keyPass.setEncryptedVerifierHashInput(ver.getEncryptedVerifier());
+ keyPass.setEncryptedVerifierHashValue(ver.getEncryptedVerifierHash());
+ keyPass.setEncryptedKeyValue(ver.getEncryptedKey());
+
+ DataIntegrity hmacData = new DataIntegrity();
+ ed.setDataIntegrity(hmacData);
+ hmacData.setEncryptedHmacKey(header.getEncryptedHmacKey());
+ hmacData.setEncryptedHmacValue(header.getEncryptedHmacValue());
+
+ return ed;
+ }
+
+ protected void marshallEncryptionDocument(EncryptionDocument ed, LittleEndianByteArrayOutputStream os) {
+ Document doc = XMLHelper.newDocumentBuilder().newDocument();
+ ed.write(doc);
+
+ try {
+ Transformer trans = XMLHelper.newTransformer();
+ trans.setOutputProperty(OutputKeys.METHOD, "xml");
+ trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ trans.setOutputProperty(OutputKeys.INDENT, "no");
+ trans.setOutputProperty(OutputKeys.STANDALONE, "yes");
+ trans.transform(new DOMSource(doc), new StreamResult(os));
+ } catch (TransformerException e) {
+ throw new EncryptedDocumentException("error marshalling encryption info document", e);
+ }
+ }
+
+ /**
+ * 2.3.4.15 Data Encryption (Agile Encryption)
+ *
+ * The EncryptedPackage stream (1) MUST be encrypted in 4096-byte segments to facilitate nearly
+ * random access while allowing CBC modes to be used in the encryption process.
+ * The initialization vector for the encryption process MUST be obtained by using the zero-based
+ * segment number as a blockKey and the binary form of the KeyData.saltValue as specified in
+ * section 2.3.4.12. The block number MUST be represented as a 32-bit unsigned integer.
+ * Data blocks MUST then be encrypted by using the initialization vector and the intermediate key
+ * obtained by decrypting the encryptedKeyValue from a KeyEncryptor contained within the
+ * KeyEncryptors sequence as specified in section 2.3.4.10. The final data block MUST be padded to
+ * the next integral multiple of the KeyData.blockSize value. Any padding bytes can be used. Note
+ * that the StreamSize field of the EncryptedPackage field specifies the number of bytes of
+ * unencrypted data as specified in section 2.3.4.4.
+ */
+ private class AgileCipherOutputStream extends ChunkedCipherOutputStream {
+ public AgileCipherOutputStream(DirectoryNode dir) throws IOException, GeneralSecurityException {
+ super(dir, 4096);
+ }
+
+ @Override
+ protected Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk)
+ throws GeneralSecurityException {
+ return AgileDecryptor.initCipherForBlock(existing, block, lastChunk, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE);
+ }
+
+ @Override
+ protected void calculateChecksum(File fileOut, int oleStreamSize)
+ throws GeneralSecurityException, IOException {
+ // integrityHMAC needs to be updated before the encryption document is created
+ updateIntegrityHMAC(fileOut, oleStreamSize);
+ }
+
+ @Override
+ protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile)
+ throws IOException {
+ DataSpaceMapUtils.addDefaultDataSpace(dir);
+ createEncryptionEntry(dir, ENCRYPTION_INFO_ENTRY, this::marshallEncryptionRecord);
+ }
+
+ private void marshallEncryptionRecord(LittleEndianByteArrayOutputStream bos) {
+ final EncryptionInfo info = getEncryptionInfo();
+
+ // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where
+ // Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004
+ bos.writeShort(info.getVersionMajor());
+ bos.writeShort(info.getVersionMinor());
+ // Reserved (4 bytes): A value that MUST be 0x00000040
+ bos.writeInt(info.getEncryptionFlags());
+
+ EncryptionDocument ed = createEncryptionDocument();
+ marshallEncryptionDocument(ed, bos);
+ }
+ }
+
+ @Override
+ public AgileEncryptor copy() {
+ return new AgileEncryptor(this);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.getBinAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.setBinAttr;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class CertificateKeyEncryptor {
+
+ /**
+ * A base64-encoded value that specifies the encrypted form of the intermediate key,
+ * which is encrypted with the public key contained within the X509Certificate attribute.
+ */
+ private byte[] encryptedKeyValue;
+
+ /**
+ * A base64-encoded value that specifies a DER-encoded X.509 certificate (1) used to encrypt the intermediate key.
+ * The certificate (1) MUST contain only the public portion of the public-private key pair.
+ */
+ private byte[] x509Certificate;
+
+ /**
+ * A base64-encoded value that specifies the HMAC of the binary data obtained by base64-decoding the X509Certificate
+ * attribute. The hashing algorithm used to derive the HMAC MUST be the hashing algorithm specified for the
+ * Encryption.keyData element. The secret key used to derive the HMAC MUST be the intermediate key. If the
+ * intermediate key is reset, any CertificateKeyEncryptor elements are also reset to contain the new intermediate
+ * key, except that the certVerifier attribute MUST match the value calculated using the current intermediate key,
+ * to verify that the CertificateKeyEncryptor element actually encrypted the current intermediate key. If a
+ * CertificateKeyEncryptor element does not have a correct certVerifier attribute, it MUST be discarded.
+ */
+ private byte[] certVerifier;
+
+ public CertificateKeyEncryptor(Element certificateKey) {
+ if (certificateKey == null) {
+ throw new EncryptedDocumentException("Unable to parse encryption descriptor");
+ }
+ encryptedKeyValue = getBinAttr(certificateKey, "encryptedKeyValue");
+ x509Certificate = getBinAttr(certificateKey, "X509Certificate");
+ certVerifier = getBinAttr(certificateKey, "certVerifier");
+ }
+
+ void write(Element encryption) {
+ Document doc = encryption.getOwnerDocument();
+ Element keyEncryptor = (Element) encryption.appendChild(doc.createElement("keyEncryptor"));
+ keyEncryptor.setAttribute("uri", KeyEncryptor.CERT_NS);
+ Element encryptedKey = (Element) keyEncryptor.appendChild(doc.createElement("c:encryptedKey"));
+
+ setBinAttr(encryptedKey, "encryptedKeyValue", encryptedKeyValue);
+ setBinAttr(encryptedKey, "x509Certificate", x509Certificate);
+ setBinAttr(encryptedKey, "certVerifier", certVerifier);
+ }
+
+ public byte[] getEncryptedKeyValue() {
+ return encryptedKeyValue;
+ }
+
+ public void setEncryptedKeyValue(byte[] encryptedKeyValue) {
+ this.encryptedKeyValue = encryptedKeyValue;
+ }
+
+ public byte[] getX509Certificate() {
+ return x509Certificate;
+ }
+
+ public void setX509Certificate(byte[] x509Certificate) {
+ this.x509Certificate = x509Certificate;
+ }
+
+ public byte[] getCertVerifier() {
+ return certVerifier;
+ }
+
+ public void setCertVerifier(byte[] certVerifier) {
+ this.certVerifier = certVerifier;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.ENC_NS;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.getBinAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.getTag;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.setBinAttr;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ * A complex type that specifies data used to verify whether the encrypted data passes an integrity check.
+ * It MUST be generated using the method specified in section 2.3.4.14
+ *
+ * @see <a href="http://msdn.microsoft.com/en-us/library/dd924068(v=office.12).aspx">DataIntegrity Generation</a>
+ */
+public class DataIntegrity {
+ /**
+ * A base64-encoded value that specifies an encrypted key used in calculating the encryptedHmacValue.
+ */
+ private byte[] encryptedHmacKey;
+
+ /**
+ * A base64-encoded value that specifies an HMAC derived from encryptedHmacKey and the encrypted data.
+ */
+ private byte[] encryptedHmacValue;
+
+ public DataIntegrity() {
+
+ }
+
+ public DataIntegrity(Element parent) {
+ Element dataIntegrity = getTag(parent, ENC_NS, "dataIntegrity");
+ if (dataIntegrity == null) {
+ throw new EncryptedDocumentException("Unable to parse encryption descriptor");
+ }
+ encryptedHmacKey = getBinAttr(dataIntegrity, "encryptedHmacKey");
+ encryptedHmacValue = getBinAttr(dataIntegrity, "encryptedHmacValue");
+ }
+
+ void write(Element encryption) {
+ Document doc = encryption.getOwnerDocument();
+ Element dataIntegrity = (Element)encryption.appendChild(doc.createElement("dataIntegrity"));
+ setBinAttr(dataIntegrity, "encryptedHmacKey", encryptedHmacKey);
+ setBinAttr(dataIntegrity, "encryptedHmacValue", encryptedHmacValue);
+ }
+
+ public byte[] getEncryptedHmacKey() {
+ return encryptedHmacKey;
+ }
+
+ public void setEncryptedHmacKey(byte[] encryptedHmacKey) {
+ this.encryptedHmacKey = encryptedHmacKey;
+ }
+
+ public byte[] getEncryptedHmacValue() {
+ return encryptedHmacValue;
+ }
+
+ public void setEncryptedHmacValue(byte[] encryptedHmacValue) {
+ this.encryptedHmacValue = encryptedHmacValue;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.XMLConstants;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.poi.EncryptedDocumentException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class EncryptionDocument {
+ static final String ENC_NS = "http://schemas.microsoft.com/office/2006/encryption";
+
+ private KeyData keyData;
+
+ /**
+ * All ECMA-376 documents [ECMA-376] encrypted by Microsoft Office using agile encryption will have a DataIntegrity
+ * element present. The schema allows for a DataIntegrity element to not be present because the encryption schema
+ * can be used by applications that do not create ECMA-376 documents [ECMA-376].
+ */
+ private DataIntegrity dataIntegrity;
+
+ private final List<KeyEncryptor> keyEncryptors = new ArrayList<>();
+
+ public EncryptionDocument() {
+
+ }
+
+ public void parse(Document doc) {
+ Element encryption = doc.getDocumentElement();
+ if (!ENC_NS.equals(encryption.getNamespaceURI()) || !"encryption".equals(encryption.getLocalName())) {
+ throw new EncryptedDocumentException("Unable to parse encryption descriptor");
+ }
+ keyData = new KeyData(encryption);
+ dataIntegrity = new DataIntegrity(encryption);
+
+ // The KeyEncryptor element, which MUST be used when encrypting password-protected agile encryption documents,
+ // is either a PasswordKeyEncryptor or a CertificateKeyEncryptor. Exactly one PasswordKeyEncryptor MUST be
+ // present. Zero or more CertificateKeyEncryptor elements are contained within the KeyEncryptors element.
+ Element keyEncryptors = getTag(encryption, ENC_NS, "keyEncryptors");
+ if (keyEncryptors == null) {
+ throw new EncryptedDocumentException("Unable to parse encryption descriptor");
+ }
+ NodeList ke = keyEncryptors.getElementsByTagNameNS(ENC_NS, "keyEncryptor");
+ for (int i=0; i<ke.getLength(); i++) {
+ this.keyEncryptors.add(new KeyEncryptor((Element)ke.item(i)));
+ }
+ }
+
+ public void write(Document doc) {
+ doc.setXmlStandalone(true);
+ Element encryption = (Element)doc.appendChild(doc.createElementNS(ENC_NS, "encryption"));
+ if (keyData != null) {
+ keyData.write(encryption);
+ }
+ if (dataIntegrity != null) {
+ dataIntegrity.write(encryption);
+ }
+ Element keyEncryptors = (Element)encryption.appendChild(doc.createElement("keyEncryptors"));
+ boolean hasPass = false;
+ boolean hasCert = false;
+ for (KeyEncryptor ke : this.keyEncryptors) {
+ ke.write(keyEncryptors);
+ hasPass |= ke.getPasswordKeyEncryptor() != null;
+ hasCert |= ke.getCertificateKeyEncryptor() != null;
+ }
+ if (hasPass) {
+ encryption.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:p", KeyEncryptor.PASS_NS);
+ }
+ if (hasCert) {
+ encryption.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:c", KeyEncryptor.CERT_NS);
+ }
+
+ }
+
+
+ public KeyData getKeyData() {
+ return keyData;
+ }
+
+ public void setKeyData(KeyData keyData) {
+ this.keyData = keyData;
+ }
+
+ public DataIntegrity getDataIntegrity() {
+ return dataIntegrity;
+ }
+
+ public void setDataIntegrity(DataIntegrity dataIntegrity) {
+ this.dataIntegrity = dataIntegrity;
+ }
+
+ public List<KeyEncryptor> getKeyEncryptors() {
+ return keyEncryptors;
+ }
+
+ static Element getTag(Element el, String ns, String name) {
+ if (el == null) {
+ return null;
+ }
+ NodeList nl = el.getElementsByTagNameNS(ns, name);
+ return (nl.getLength() > 0) ? (Element)nl.item(0) : null;
+ }
+
+ static Integer getIntAttr(Element el, String name) {
+ String at = el.getAttribute(name);
+ return (at.isEmpty()) ? null : Integer.valueOf(at);
+ }
+
+ static byte[] getBinAttr(Element el, String name) {
+ String at = el.getAttribute(name);
+ return (at.isEmpty()) ? null : Base64.decodeBase64(at);
+ }
+
+ static void setIntAttr(Element el, String name, Integer val) {
+ setAttr(el, name, val == null ? null : val.toString());
+ }
+
+ static void setAttr(Element el, String name, String val) {
+ if (val != null) {
+ el.setAttribute(name, val);
+ }
+ }
+
+ static void setBinAttr(Element el, String name, byte[] val) {
+ if (val != null) {
+ setAttr(el, name, Base64.encodeBase64String(val));
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.ENC_NS;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.getBinAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.getIntAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.getTag;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.setAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.setBinAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.setIntAttr;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * A complex type that specifies the encryption used within this element. The saltValue attribute is a base64-encoded
+ * binary value that is randomly generated. The number of bytes required to decode the saltValue attribute MUST be equal
+ * to the value of the saltSize attribute.
+ */
+public class KeyData {
+ private Integer saltSize;
+ private Integer blockSize;
+ private Integer keyBits;
+ private Integer hashSize;
+ private CipherAlgorithm cipherAlgorithm;
+ private ChainingMode cipherChaining;
+ private HashAlgorithm hashAlgorithm;
+ private byte[] saltValue;
+
+ public KeyData() {
+
+ }
+
+ public KeyData(Element parent) {
+ Element keyData = getTag(parent, ENC_NS, "keyData");
+ if (keyData == null) {
+ throw new EncryptedDocumentException("Unable to parse encryption descriptor");
+ }
+ saltSize = getIntAttr(keyData, "saltSize");
+ blockSize = getIntAttr(keyData, "blockSize");
+ keyBits = getIntAttr(keyData, "keyBits");
+ hashSize = getIntAttr(keyData, "hashSize");
+ cipherAlgorithm = CipherAlgorithm.fromXmlId(keyData.getAttribute("cipherAlgorithm"), keyBits);
+ cipherChaining = ChainingMode.fromXmlId(keyData.getAttribute("cipherChaining"));
+ hashAlgorithm = HashAlgorithm.fromEcmaId(keyData.getAttribute("hashAlgorithm"));
+ if (cipherAlgorithm == null || cipherChaining == null || hashAlgorithm == null) {
+ throw new EncryptedDocumentException("Cipher algorithm, chaining mode or hash algorithm was null");
+ }
+ saltValue = getBinAttr(keyData, "saltValue");
+ }
+
+ void write(Element encryption) {
+ Document doc = encryption.getOwnerDocument();
+ Element keyData = (Element)encryption.appendChild(doc.createElement("keyData"));
+ setIntAttr(keyData, "saltSize", saltSize);
+ setIntAttr(keyData, "blockSize", blockSize);
+ setIntAttr(keyData, "keyBits", keyBits);
+ setIntAttr(keyData, "hashSize", hashSize);
+ setAttr(keyData, "cipherAlgorithm", cipherAlgorithm == null ? null : cipherAlgorithm.xmlId);
+ setAttr(keyData, "cipherChaining", cipherChaining == null ? null : cipherChaining.xmlId);
+ setAttr(keyData, "hashAlgorithm", hashAlgorithm == null ? null : hashAlgorithm.ecmaString);
+ setBinAttr(keyData, "saltValue", saltValue);
+ }
+
+ public Integer getSaltSize() {
+ return saltSize;
+ }
+
+ public void setSaltSize(Integer saltSize) {
+ this.saltSize = saltSize;
+ }
+
+ public Integer getBlockSize() {
+ return blockSize;
+ }
+
+ public void setBlockSize(Integer blockSize) {
+ this.blockSize = blockSize;
+ }
+
+ public Integer getKeyBits() {
+ return keyBits;
+ }
+
+ public void setKeyBits(Integer keyBits) {
+ this.keyBits = keyBits;
+ }
+
+ public Integer getHashSize() {
+ return hashSize;
+ }
+
+ public void setHashSize(Integer hashSize) {
+ this.hashSize = hashSize;
+ }
+
+ public CipherAlgorithm getCipherAlgorithm() {
+ return cipherAlgorithm;
+ }
+
+ public void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
+ this.cipherAlgorithm = cipherAlgorithm;
+ }
+
+ public ChainingMode getCipherChaining() {
+ return cipherChaining;
+ }
+
+ public void setCipherChaining(ChainingMode cipherChaining) {
+ this.cipherChaining = cipherChaining;
+ }
+
+ public HashAlgorithm getHashAlgorithm() {
+ return hashAlgorithm;
+ }
+
+ public void setHashAlgorithm(HashAlgorithm hashAlgorithm) {
+ this.hashAlgorithm = hashAlgorithm;
+ }
+
+ public byte[] getSaltValue() {
+ return saltValue;
+ }
+
+ public void setSaltValue(byte[] saltValue) {
+ this.saltValue = (saltValue == null) ? null : saltValue.clone();
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * A sequence of KeyEncryptor elements. Exactly one KeyEncryptors element MUST be present, and the KeyEncryptors element
+ * MUST contain at least one KeyEncryptor.
+ */
+public class KeyEncryptor {
+ static final String PASS_NS = "http://schemas.microsoft.com/office/2006/keyEncryptor/password";
+ static final String CERT_NS = "http://schemas.microsoft.com/office/2006/keyEncryptor/certificate";
+
+ private PasswordKeyEncryptor passwordKeyEncryptor;
+ private CertificateKeyEncryptor certificateKeyEncryptor;
+
+ public KeyEncryptor() {
+
+ }
+
+ public KeyEncryptor(Element keyEncryptor) {
+ if (keyEncryptor == null) {
+ throw new EncryptedDocumentException("Unable to parse encryption descriptor");
+ }
+ NodeList nl = keyEncryptor.getElementsByTagNameNS("*", "encryptedKey");
+ // usually only one encryptor is set, so iterate and overwrite the encryptor members
+ for (int i=0; i<nl.getLength(); i++) {
+ Element el = (Element)nl.item(i);
+ String nsUri = el.getNamespaceURI();
+ if (PASS_NS.equals(nsUri)) {
+ passwordKeyEncryptor = new PasswordKeyEncryptor(el);
+ } else if (CERT_NS.equals(nsUri)) {
+ certificateKeyEncryptor = new CertificateKeyEncryptor(el);
+ }
+ }
+ }
+
+ void write(Element keyEncryptors) {
+ if (passwordKeyEncryptor != null) {
+ passwordKeyEncryptor.write(keyEncryptors);
+ } else if (certificateKeyEncryptor != null) {
+ certificateKeyEncryptor.write(keyEncryptors);
+ }
+ }
+
+
+
+ public PasswordKeyEncryptor getPasswordKeyEncryptor() {
+ return passwordKeyEncryptor;
+ }
+
+ public void setPasswordKeyEncryptor(PasswordKeyEncryptor passwordKeyEncryptor) {
+ this.passwordKeyEncryptor = passwordKeyEncryptor;
+ }
+
+ public CertificateKeyEncryptor getCertificateKeyEncryptor() {
+ return certificateKeyEncryptor;
+ }
+
+ public void setCertificateKeyEncryptor(CertificateKeyEncryptor certificateKeyEncryptor) {
+ this.certificateKeyEncryptor = certificateKeyEncryptor;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.agile;
+
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.getBinAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.getIntAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.setAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.setBinAttr;
+import static org.apache.poi.poifs.crypt.agile.EncryptionDocument.setIntAttr;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class PasswordKeyEncryptor {
+
+ /**
+ * An unsigned integer that specifies the number of bytes used by a salt. It MUST be at least 1 and no greater than 65,536.
+ */
+ private Integer saltSize;
+
+ /**
+ * An unsigned integer that specifies the number of bytes used to encrypt one block of data.
+ * It MUST be at least 2, no greater than 4096, and a multiple of 2.
+ */
+ private Integer blockSize;
+
+ /**
+ * An unsigned integer that specifies the number of bits used by an encryption algorithm.
+ * It MUST be at least 8 and a multiple of 8.
+ */
+ private Integer keyBits;
+
+ /**
+ * An unsigned integer that specifies the number of bytes used by a hash value.
+ * It MUST be at least 1, no greater than 65,536, and the same number of bytes as the hash algorithm emits.
+ */
+ private Integer hashSize;
+
+ /**
+ * A CipherAlgorithm that specifies the cipher algorithm for a PasswordKeyEncryptor.
+ * The cipher algorithm specified MUST be the same as the cipher algorithm specified for the Encryption.keyData element.
+ */
+ private CipherAlgorithm cipherAlgorithm;
+
+ /**
+ * A CipherChaining that specifies the cipher chaining mode for a PasswordKeyEncryptor.
+ */
+ private ChainingMode cipherChaining;
+
+ /**
+ * A HashAlgorithm that specifies the hashing algorithm for a PasswordKeyEncryptor.
+ * The hashing algorithm specified MUST be the same as the hashing algorithm specified for the Encryption.keyData element.
+ */
+ private HashAlgorithm hashAlgorithm;
+
+ /**
+ * A base64-encoded binary byte array that specifies the salt value for a PasswordKeyEncryptor.
+ * The number of bytes required by the decoded form of this element MUST be saltSize.
+ */
+ private byte[] saltValue;
+
+ /**
+ * A SpinCount that specifies the spin count for a PasswordKeyEncryptor.
+ */
+ private Integer spinCount;
+
+ /**
+ * A base64-encoded value that specifies the encrypted verifier hash input for a
+ * PasswordKeyEncryptor used in password verification.
+ */
+ private byte[] encryptedVerifierHashInput;
+
+ /**
+ * A base64-encoded value that specifies the encrypted verifier hash value for a
+ * PasswordKeyEncryptor used in password verification.
+ */
+ private byte[] encryptedVerifierHashValue;
+
+ /**
+ * A base64-encoded value that specifies the encrypted form of the intermediate key.
+ */
+ private byte[] encryptedKeyValue;
+
+ public PasswordKeyEncryptor() {
+
+ }
+
+ public PasswordKeyEncryptor(Element passwordKey) {
+ if (passwordKey == null) {
+ throw new EncryptedDocumentException("Unable to parse encryption descriptor");
+ }
+ saltSize = getIntAttr(passwordKey, "saltSize");
+ blockSize = getIntAttr(passwordKey, "blockSize");
+ keyBits = getIntAttr(passwordKey, "keyBits");
+ hashSize = getIntAttr(passwordKey, "hashSize");
+ cipherAlgorithm = CipherAlgorithm.fromXmlId(passwordKey.getAttribute("cipherAlgorithm"), keyBits);
+ cipherChaining = ChainingMode.fromXmlId(passwordKey.getAttribute("cipherChaining"));
+ hashAlgorithm = HashAlgorithm.fromEcmaId(passwordKey.getAttribute("hashAlgorithm"));
+ saltValue = getBinAttr(passwordKey, "saltValue");
+ spinCount = getIntAttr(passwordKey, "spinCount");
+ encryptedVerifierHashInput = getBinAttr(passwordKey, "encryptedVerifierHashInput");
+ encryptedVerifierHashValue = getBinAttr(passwordKey, "encryptedVerifierHashValue");
+ encryptedKeyValue = getBinAttr(passwordKey, "encryptedKeyValue");
+ }
+
+ void write(Element encryption) {
+ Document doc = encryption.getOwnerDocument();
+ Element keyEncryptor = (Element) encryption.appendChild(doc.createElement("keyEncryptor"));
+ keyEncryptor.setAttribute("uri", KeyEncryptor.PASS_NS);
+ Element encryptedKey = (Element) keyEncryptor.appendChild(doc.createElement("p:encryptedKey"));
+
+ setIntAttr(encryptedKey, "saltSize", saltSize);
+ setIntAttr(encryptedKey, "blockSize", blockSize);
+ setIntAttr(encryptedKey, "keyBits", keyBits);
+ setIntAttr(encryptedKey, "hashSize", hashSize);
+ setAttr(encryptedKey, "cipherAlgorithm", cipherAlgorithm == null ? null : cipherAlgorithm.xmlId);
+ setAttr(encryptedKey, "cipherChaining", cipherChaining == null ? null : cipherChaining.xmlId);
+ setAttr(encryptedKey, "hashAlgorithm", hashAlgorithm == null ? null : hashAlgorithm.ecmaString);
+ setBinAttr(encryptedKey, "saltValue", saltValue);
+ setIntAttr(encryptedKey, "spinCount", spinCount);
+ setBinAttr(encryptedKey, "encryptedVerifierHashInput", encryptedVerifierHashInput);
+ setBinAttr(encryptedKey, "encryptedVerifierHashValue", encryptedVerifierHashValue);
+ setBinAttr(encryptedKey, "encryptedKeyValue", encryptedKeyValue);
+
+ }
+
+ public Integer getSaltSize() {
+ return saltSize;
+ }
+
+ public void setSaltSize(Integer saltSize) {
+ this.saltSize = saltSize;
+ }
+
+ public Integer getBlockSize() {
+ return blockSize;
+ }
+
+ public void setBlockSize(Integer blockSize) {
+ this.blockSize = blockSize;
+ }
+
+ public Integer getKeyBits() {
+ return keyBits;
+ }
+
+ public void setKeyBits(Integer keyBits) {
+ this.keyBits = keyBits;
+ }
+
+ public Integer getHashSize() {
+ return hashSize;
+ }
+
+ public void setHashSize(Integer hashSize) {
+ this.hashSize = hashSize;
+ }
+
+ public CipherAlgorithm getCipherAlgorithm() {
+ return cipherAlgorithm;
+ }
+
+ public void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
+ this.cipherAlgorithm = cipherAlgorithm;
+ }
+
+ public ChainingMode getCipherChaining() {
+ return cipherChaining;
+ }
+
+ public void setCipherChaining(ChainingMode cipherChaining) {
+ this.cipherChaining = cipherChaining;
+ }
+
+ public HashAlgorithm getHashAlgorithm() {
+ return hashAlgorithm;
+ }
+
+ public void setHashAlgorithm(HashAlgorithm hashAlgorithm) {
+ this.hashAlgorithm = hashAlgorithm;
+ }
+
+ public byte[] getSaltValue() {
+ return saltValue;
+ }
+
+ public void setSaltValue(byte[] saltValue) {
+ this.saltValue = saltValue;
+ }
+
+ public Integer getSpinCount() {
+ return spinCount;
+ }
+
+ public void setSpinCount(Integer spinCount) {
+ this.spinCount = spinCount;
+ }
+
+ public byte[] getEncryptedVerifierHashInput() {
+ return encryptedVerifierHashInput;
+ }
+
+ public void setEncryptedVerifierHashInput(byte[] encryptedVerifierHashInput) {
+ this.encryptedVerifierHashInput = encryptedVerifierHashInput;
+ }
+
+ public byte[] getEncryptedVerifierHashValue() {
+ return encryptedVerifierHashValue;
+ }
+
+ public void setEncryptedVerifierHashValue(byte[] encryptedVerifierHashValue) {
+ this.encryptedVerifierHashValue = encryptedVerifierHashValue;
+ }
+
+ public byte[] getEncryptedKeyValue() {
+ return encryptedKeyValue;
+ }
+
+ public void setEncryptedKeyValue(byte[] encryptedKeyValue) {
+ this.encryptedKeyValue = encryptedKeyValue;
+ }
+}
}
@Override
- protected void setSalt(byte[] salt) {
+ public void setSalt(byte[] salt) {
if (salt == null || salt.length != 16) {
throw new EncryptedDocumentException("invalid verifier salt");
}
}
@Override
- protected void setEncryptedVerifier(byte[] encryptedVerifier) {
+ public void setEncryptedVerifier(byte[] encryptedVerifier) {
super.setEncryptedVerifier(encryptedVerifier);
}
@Override
- protected void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
+ public void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
super.setEncryptedVerifierHash(encryptedVerifierHash);
}
}
@Override
- protected void setSalt(byte[] salt) {
+ public void setSalt(byte[] salt) {
super.setSalt(salt);
}
@Override
- protected void setEncryptedVerifier(byte[] encryptedVerifier) {
+ public void setEncryptedVerifier(byte[] encryptedVerifier) {
super.setEncryptedVerifier(encryptedVerifier);
}
@Override
- protected void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
+ public void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
super.setEncryptedVerifierHash(encryptedVerifierHash);
}
// make method visible for this package
@Override
- protected void setSalt(byte[] salt) {
+ public void setSalt(byte[] salt) {
if (salt == null || salt.length != 16) {
throw new EncryptedDocumentException("invalid verifier salt");
}
// make method visible for this package
@Override
- protected void setEncryptedVerifier(byte[] encryptedVerifier) {
+ public void setEncryptedVerifier(byte[] encryptedVerifier) {
super.setEncryptedVerifier(encryptedVerifier);
}
// make method visible for this package
@Override
- protected void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
+ public void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
super.setEncryptedVerifierHash(encryptedVerifierHash);
}
bos.write(encryptedVerifierHash);
}
- protected int getVerifierHashSize() {
+ public int getVerifierHashSize() {
return verifierHashSize;
}
}
@Override
- protected final void setEncryptedVerifier(byte[] encryptedVerifier) {
+ public final void setEncryptedVerifier(byte[] encryptedVerifier) {
super.setEncryptedVerifier(encryptedVerifier);
}
@Override
- protected final void setEncryptedKey(byte[] encryptedKey) {
+ public final void setEncryptedKey(byte[] encryptedKey) {
super.setEncryptedKey(encryptedKey);
}
}
// handle (b) and (c)
attList.add(new AttributedStringData(TextAttribute.FAMILY, fontMapped.getFontName(Locale.ROOT), beginIndex+partBegin, beginIndex+partEnd));
if (LOG.check(POILogger.DEBUG)) {
- LOG.log(POILogger.DEBUG, "mapped: ",fontMapped.getFontName(Locale.ROOT)," ",(beginIndex+partBegin)," ",(beginIndex+partEnd)," - ",runText.substring(beginIndex+partBegin, beginIndex+partEnd));
+ LOG.log(POILogger.DEBUG, "mapped: ",fontMapped.getFontName(Locale.ROOT)," ",(beginIndex+partBegin)," ",(beginIndex+partEnd)," - ",runText.substring(partBegin, partEnd));
}
}
// handle (a) and (b)
attList.add(new AttributedStringData(TextAttribute.FAMILY, fontFallback.getFontName(Locale.ROOT), beginIndex+partBegin, beginIndex+partEnd));
if (LOG.check(POILogger.DEBUG)) {
- LOG.log(POILogger.DEBUG, "fallback: ",fontFallback.getFontName(Locale.ROOT)," ",(beginIndex+partBegin)," ",(beginIndex+partEnd)," - ",runText.substring(beginIndex+partBegin, beginIndex+partEnd));
+ LOG.log(POILogger.DEBUG, "fallback: ",fontFallback.getFontName(Locale.ROOT)," ",(beginIndex+partBegin)," ",(beginIndex+partEnd)," - ",runText.substring(partBegin, partEnd));
}
}
}
==================================================================== */
package org.apache.poi.ss.usermodel;
+import static org.apache.poi.poifs.crypt.EncryptionInfo.ENCRYPTION_INFO_ENTRY;
+
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
+import org.apache.poi.EmptyFileException;
import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
import org.apache.poi.poifs.filesystem.FileMagic;
-import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.Removal;
/**
* Factory for creating the appropriate kind of Workbook
* (be it {@link HSSFWorkbook} or XSSFWorkbook),
* by auto-detecting from the supplied input.
*/
-public abstract class WorkbookFactory {
-
- protected interface CreateWorkbook0 {
- Workbook apply() throws IOException;
- }
+public final class WorkbookFactory {
- protected interface CreateWorkbook1<T> {
- Workbook apply(T t) throws IOException;
+ private static class Singleton {
+ private static final WorkbookFactory INSTANCE = new WorkbookFactory();
}
- protected interface CreateWorkbook2<T, U> {
- Workbook apply(T t, U u) throws IOException;
+ private interface ProviderMethod {
+ Workbook create(WorkbookProvider prov) throws IOException;
}
- private static final Object hssfLock = new Object();
- private static final Object xssfLock = new Object();
+ private final List<WorkbookProvider> provider = new ArrayList<>();
- protected static CreateWorkbook0 createHssfFromScratch;
- protected static CreateWorkbook1<DirectoryNode> createHssfByNode;
+ private WorkbookFactory() {
+ ServiceLoader.load(WorkbookProvider.class).forEach(provider::add);
+ }
- protected static CreateWorkbook0 createXssfFromScratch;
- protected static CreateWorkbook1<InputStream> createXssfByStream;
- protected static CreateWorkbook1<Object> createXssfByPackage;
- protected static CreateWorkbook2<File,Boolean> createXssfByFile;
/**
* Create a new empty Workbook, either XSSF or HSSF depending
* @throws IOException if an error occurs while creating the objects
*/
public static Workbook create(boolean xssf) throws IOException {
- if(xssf) {
- initXssf();
- return createXssfFromScratch.apply();
- } else {
- initHssf();
- return createHssfFromScratch.apply();
- }
+ return wp(xssf ? FileMagic.OOXML : FileMagic.OLE2, WorkbookProvider::create);
}
/**
public static Workbook create(final DirectoryNode root, String password) throws IOException {
// Encrypted OOXML files go inside OLE2 containers, is this one?
if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
- InputStream stream = null;
- try {
- stream = DocumentFactoryHelper.getDecryptedStream(root, password);
- initXssf();
- return createXssfByStream.apply(stream);
- } finally {
- IOUtils.closeQuietly(stream);
-
- // as we processed the full stream already, we can close the filesystem here
- // otherwise file handles are leaked
- root.getFileSystem().close();
- }
- }
-
- // If we get here, it isn't an encrypted PPTX file
- // So, treat it as a regular HSLF PPT one
- boolean passwordSet = false;
- if (password != null) {
- Biff8EncryptionKey.setCurrentUserPassword(password);
- passwordSet = true;
- }
- try {
- initHssf();
- return createHssfByNode.apply(root);
- } finally {
- if (passwordSet) {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- }
+ return wp(FileMagic.OOXML, w -> w.create(root, password));
+ } else {
+ return wp(FileMagic.OLE2, w -> w.create(root, password));
}
}
- /**
- * Creates a XSSFWorkbook from the given OOXML Package.
- * As the WorkbookFactory is located in the POI module, which doesn't know about the OOXML formats,
- * this can be only achieved by using an Object reference to the OPCPackage.
- *
- * <p>Note that in order to properly release resources the
- * Workbook should be closed after use.</p>
- *
- * @param pkg The org.apache.poi.openxml4j.opc.OPCPackage opened for reading data.
- *
- * @return The created Workbook
- *
- * @throws IOException if an error occurs while reading the data
- *
- * @deprecated use {@link #create(File)}, {@link #create(InputStream)} or
- * XSSFWorkbookFactory.create(OPCPackage) instead.
- */
- @Deprecated
- @Removal(version = "4.2.0")
- public static Workbook create(Object pkg) throws IOException {
- initXssf();
- return createXssfByPackage.apply(pkg);
- }
-
/**
* Creates the appropriate HSSFWorkbook / XSSFWorkbook from
* the given InputStream.
*/
public static Workbook create(InputStream inp, String password) throws IOException, EncryptedDocumentException {
InputStream is = FileMagic.prepareToCheckMagic(inp);
- FileMagic fm = FileMagic.valueOf(is);
-
- switch (fm) {
- case OLE2:
- POIFSFileSystem fs = new POIFSFileSystem(is);
- return create(fs, password);
- case OOXML:
- initXssf();
- return createXssfByStream.apply(is);
- default:
- throw new IOException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
+ byte[] emptyFileCheck = new byte[1];
+ is.mark(emptyFileCheck.length);
+ if (is.read(emptyFileCheck) < emptyFileCheck.length) {
+ throw new EmptyFileException();
+ }
+ is.reset();
+
+ final FileMagic fm = FileMagic.valueOf(is);
+ if (FileMagic.OOXML == fm) {
+ return wp(fm, w -> w.create(is));
+ }
+
+ if (FileMagic.OLE2 != fm) {
+ throw new IOException("Can't open workbook - unsupported file type: "+fm);
}
+
+ POIFSFileSystem poifs = new POIFSFileSystem(is);
+ boolean isOOXML = poifs.getRoot().hasEntry(ENCRYPTION_INFO_ENTRY);
+
+ return wp(isOOXML ? FileMagic.OOXML : fm, w -> w.create(poifs.getRoot(), password));
}
/**
throw new FileNotFoundException(file.toString());
}
- POIFSFileSystem fs = null;
- try {
- fs = new POIFSFileSystem(file, readOnly);
- return create(fs, password);
- } catch(OfficeXmlFileException e) {
- IOUtils.closeQuietly(fs);
- initXssf();
- return createXssfByFile.apply(file, readOnly);
- } catch(RuntimeException e) {
- IOUtils.closeQuietly(fs);
- throw e;
+ if (file.length() == 0) {
+ throw new EmptyFileException();
}
- }
- private static void initXssf() throws IOException {
- if (createXssfFromScratch == null) {
- synchronized (xssfLock) {
- if (createXssfFromScratch == null) {
- String factoryClass = "org.apache.poi.xssf.usermodel.XSSFWorkbookFactory";
- Class<?> cls = initFactory(factoryClass, "poi-ooxml-*.jar");
- try {
- cls.getMethod("init").invoke(null);
- } catch (Exception e) {
- throw new IOException(factoryClass+" failed to init.");
- }
- }
+ FileMagic fm = FileMagic.valueOf(file);
+ if (fm == FileMagic.OOXML) {
+ return wp(fm, w -> w.create(file, password, readOnly));
+ } else if (fm == FileMagic.OLE2) {
+ boolean ooxmlEnc = false;
+ try (POIFSFileSystem fs = new POIFSFileSystem(file, true)) {
+ ooxmlEnc = fs.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY);
}
+ return wp(ooxmlEnc ? FileMagic.OOXML : fm, w -> w.create(file, password, readOnly));
}
- }
- private static void initHssf() throws IOException {
- if (createHssfFromScratch == null) {
- // HSSF is part of the main jar, so this shouldn't fail ...
- synchronized (hssfLock) {
- if (createHssfFromScratch == null) {
- String factoryClass = "org.apache.poi.hssf.usermodel.HSSFWorkbookFactory";
- Class<?> cls = initFactory(factoryClass, "poi-*.jar");
- try {
- cls.getMethod("init").invoke(null);
- } catch (Exception e) {
- throw new IOException(factoryClass+" failed to init.");
- }
- }
- }
- }
+ return null;
}
- private static Class<?> initFactory(String factoryClass, String jar) throws IOException {
- try {
- return Class.forName(factoryClass, true, WorkbookFactory.class.getClassLoader());
- } catch (ClassNotFoundException e) {
- throw new IOException(factoryClass+" not found - check if " + jar + " is on the classpath.");
+
+ private static Workbook wp(FileMagic fm, ProviderMethod fun) throws IOException {
+
+ for (WorkbookProvider prov : Singleton.INSTANCE.provider) {
+ if (prov.accepts(fm)) {
+ return fun.create(prov);
+ }
}
+ throw new IOException("Your InputStream was neither an OLE2 stream, nor an OOXML stream " +
+ "or you haven't provide the poi-ooxml*.jar in the classpath/modulepath - FileMagic: "+fm);
}
}
--- /dev/null
+/* ====================================================================
+ 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.ss.usermodel;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.FileMagic;
+
+public interface WorkbookProvider {
+ boolean accepts(FileMagic fm);
+
+ Workbook create();
+
+ Workbook create(InputStream inp) throws IOException;
+
+ Workbook create(InputStream inp, String password) throws IOException;
+
+ Workbook create(DirectoryNode root, String password) throws IOException;
+
+ Workbook create(File file, String password, boolean readOnly) throws IOException;
+}
package org.apache.poi.util;
+import static org.apache.poi.util.TempFile.JAVA_IO_TMPDIR;
+
import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
-import static org.apache.poi.util.TempFile.JAVA_IO_TMPDIR;
-
/**
* Default implementation of the {@link TempFileCreationStrategy} used by {@link TempFile}:
* Files are collected into one directory and by default are deleted on exit from the VM.
* Files may be manually deleted by user prior to JVM exit.
* Files can be kept by defining the system property {@link #KEEP_FILES}.
- *
+ *
* Each file is registered for deletion with the JVM and the temporary directory is not deleted
* after the JVM exits. Files that are created in the poifiles directory outside
* the control of DefaultTempFileCreationStrategy are not deleted.
* processes or limited temporary storage.
*/
public class DefaultTempFileCreationStrategy implements TempFileCreationStrategy {
- /*package*/ static final String POIFILES = "poifiles";
-
+ public static final String POIFILES = "poifiles";
+
/** To keep files after JVM exit, set the <code>-Dpoi.keep.tmp.files</code> JVM property */
public static final String KEEP_FILES = "poi.keep.tmp.files";
-
+
/** random number generator to generate unique filenames */
private static final SecureRandom random = new SecureRandom();
-
+
/** The directory where the temporary files will be created (<code>null</code> to use the default directory). */
private File dir;
-
+
/**
* Creates the strategy so that it creates the temporary files in the default directory.
- *
+ *
* @see File#createTempFile(String, String)
*/
public DefaultTempFileCreationStrategy() {
this(null);
}
-
+
/**
- * Creates the strategy allowing to set the
+ * Creates the strategy allowing to set the
*
* @param dir The directory where the temporary files will be created (<code>null</code> to use the default directory).
- *
+ *
* @see File#createTempFile(String, String, File)
*/
public DefaultTempFileCreationStrategy(File dir) {
this.dir = dir;
}
-
+
private void createPOIFilesDirectory() throws IOException {
// Identify and create our temp dir, if needed
// The directory is not deleted, even if it was created by this TempFileCreationStrategy
}
dir = new File(tmpDir, POIFILES);
}
-
+
createTempDirectory(dir);
}
-
+
/**
* Attempt to create a directory, including any necessary parent directories.
* Does nothing if directory already exists.
private synchronized void createTempDirectory(File directory) throws IOException {
// create directory if it doesn't exist
final boolean dirExists = (directory.exists() || directory.mkdirs());
-
+
if (!dirExists) {
throw new IOException("Could not create temporary directory '" + directory + "'");
}
throw new IOException("Could not create temporary directory. '" + directory + "' exists but is not a directory.");
}
}
-
+
@Override
public File createTempFile(String prefix, String suffix) throws IOException {
// Identify and create our temp dir, if needed
createPOIFilesDirectory();
-
- // Generate a unique new filename
+
+ // Generate a unique new filename
File newFile = File.createTempFile(prefix, suffix, dir);
// Set the delete on exit flag, unless explicitly disabled
public File createTempDirectory(String prefix) throws IOException {
// Identify and create our temp dir, if needed
createPOIFilesDirectory();
-
+
// Generate a unique new filename
// FIXME: Java 7+: use java.nio.Files#createTempDirectory
final long n = random.nextLong();
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.examples {
+
+ requires transitive org.apache.poi.ooxml;
+ requires transitive org.apache.poi.scratchpad;
+ requires java.xml;
+
+ exports org.apache.poi.examples.crypt;
+ exports org.apache.poi.examples.hpsf;
+ exports org.apache.poi.examples.hslf;
+ exports org.apache.poi.examples.hsmf;
+ exports org.apache.poi.examples.hssf.eventusermodel;
+ exports org.apache.poi.examples.hssf.usermodel;
+ exports org.apache.poi.examples.hwpf;
+ exports org.apache.poi.examples.ss;
+ exports org.apache.poi.examples.ss.formula;
+ exports org.apache.poi.examples.ss.html;
+ exports org.apache.poi.examples.util;
+ exports org.apache.poi.examples.xslf;
+ exports org.apache.poi.examples.xssf.eventusermodel;
+ exports org.apache.poi.examples.xssf.streaming;
+ exports org.apache.poi.examples.xssf.usermodel;
+ exports org.apache.poi.examples.xwpf.usermodel;
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.excelant {
+
+ requires ant;
+ requires org.apache.poi.ooxml;
+ requires org.apache.poi.scratchpad;
+
+ exports org.apache.poi.ss.excelant;
+ exports org.apache.poi.ss.excelant.util;
+
+ opens org.apache.poi.ss.excelant;
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.excelant {
+
+ requires ant;
+ requires org.apache.poi.ooxml;
+ requires org.apache.poi.scratchpad;
+
+ exports org.apache.poi.ss.excelant;
+ exports org.apache.poi.ss.excelant.util;
+
+ opens org.apache.poi.ss.excelant;
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.stress {
+ requires junit;
+ requires net.bytebuddy;
+ requires java.desktop;
+
+ requires org.apache.poi.examples;
+
+ exports org.apache.poi.stress;
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.ooxml_lite {
+ requires java.instrument;
+
+ exports org.apache.poi.ooxml.lite;
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+
+open module org.apache.poi.ooxml.schemas {
+ // this still throws "requires transitive directive for an automatic module" in JDK 14
+ // see https://bugs.openjdk.java.net/browse/JDK-8240847
+ requires transitive org.apache.xmlbeans;
+ requires java.xml;
+
+ exports com.microsoft.schemas.compatibility;
+ exports com.microsoft.schemas.office.excel;
+ exports com.microsoft.schemas.office.office;
+ exports com.microsoft.schemas.office.visio.x2012.main;
+ exports com.microsoft.schemas.office.x2006.digsig;
+ exports com.microsoft.schemas.vml;
+ exports org.apache.poi.schemas.ooxml.system.ooxml;
+ exports org.etsi.uri.x01903.v13;
+ exports org.openxmlformats.schemas.drawingml.x2006.chart;
+ exports org.openxmlformats.schemas.drawingml.x2006.main;
+ exports org.openxmlformats.schemas.drawingml.x2006.picture;
+ exports org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing;
+ exports org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing;
+ exports org.openxmlformats.schemas.officeDocument.x2006.customProperties;
+ exports org.openxmlformats.schemas.officeDocument.x2006.docPropsVTypes;
+ exports org.openxmlformats.schemas.officeDocument.x2006.extendedProperties;
+ exports org.openxmlformats.schemas.officeDocument.x2006.relationships;
+ exports org.openxmlformats.schemas.presentationml.x2006.main;
+ exports org.openxmlformats.schemas.spreadsheetml.x2006.main;
+ exports org.openxmlformats.schemas.wordprocessingml.x2006.main;
+ exports org.openxmlformats.schemas.xpackage.x2006.digitalSignature;
+ exports org.w3.x2000.x09.xmldsig;
+}
\ No newline at end of file
open module org.apache.poi.ooxml.schemas {
- requires transitive xmlbeans;
+ // this still throws "requires transitive directive for an automatic module" in JDK 14
+ // see https://bugs.openjdk.java.net/browse/JDK-8240847
+ requires transitive org.apache.xmlbeans;
requires java.xml;
exports com.microsoft.schemas.compatibility;
exports com.microsoft.schemas.office.excel;
exports org.openxmlformats.schemas.schemaLibrary.x2006.main;
exports org.openxmlformats.schemas.spreadsheetml.x2006.main;
exports org.openxmlformats.schemas.wordprocessingml.x2006.main;
- // opens schemaorg_apache_xmlbeans.system.OoxmlSchemas to xmlbeans;
+
+ exports com.microsoft.schemas.office.x2006.digsig;
+ exports org.etsi.uri.x01903.v13;
+ exports org.etsi.uri.x01903.v14;
+ exports org.openxmlformats.schemas.xpackage.x2006.digitalSignature;
+ exports org.openxmlformats.schemas.xpackage.x2006.relationships;
+ exports org.w3.x2000.x09.xmldsig;
}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.
-==================================================================== */
-
-
-open module org.apache.poi.ooxml.security {
- requires transitive xmlbeans;
- requires java.xml;
- exports com.microsoft.schemas.office.x2006.digsig;
- exports com.microsoft.schemas.office.x2006.encryption;
- exports com.microsoft.schemas.office.x2006.keyEncryptor.certificate;
- exports com.microsoft.schemas.office.x2006.keyEncryptor.password;
- exports org.etsi.uri.x01903.v13;
- exports org.etsi.uri.x01903.v14;
- exports org.openxmlformats.schemas.xpackage.x2006.digitalSignature;
- exports org.openxmlformats.schemas.xpackage.x2006.relationships;
- exports org.w3.x2000.x09.xmldsig;
- // opens schemaorg_apache_xmlbeans.system.OoxmlSecurity to xmlbeans;
-}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.ooxml {
+ requires transitive org.apache.poi.poi;
+ requires transitive org.apache.xmlbeans;
+ requires transitive org.apache.poi.ooxml.schemas;
+ requires org.apache.commons.collections4;
+ requires org.apache.commons.codec;
+ requires commons.math3;
+ requires SparseBitSet;
+ requires commons.logging;
+ requires java.logging;
+ requires java.desktop;
+ requires java.security.jgss;
+
+ provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
+
+ exports org.apache.poi.xwpf.extractor;
+ exports org.apache.poi.xwpf.usermodel;
+ exports org.apache.poi.xwpf.model;
+ exports org.apache.poi.xdgf.extractor;
+ exports org.apache.poi.xdgf.exceptions;
+ exports org.apache.poi.xdgf.usermodel;
+ exports org.apache.poi.xdgf.usermodel.section;
+ exports org.apache.poi.xdgf.usermodel.section.geometry;
+ exports org.apache.poi.xdgf.usermodel.shape;
+ exports org.apache.poi.xdgf.usermodel.shape.exceptions;
+ exports org.apache.poi.xdgf.xml;
+ exports org.apache.poi.xdgf.util;
+ exports org.apache.poi.xdgf.geom;
+ exports org.apache.poi.ooxml;
+ exports org.apache.poi.ooxml.dev;
+ exports org.apache.poi.ooxml.extractor;
+ exports org.apache.poi.ooxml.util;
+ exports org.apache.poi.xddf.usermodel;
+ exports org.apache.poi.xddf.usermodel.text;
+ exports org.apache.poi.xddf.usermodel.chart;
+ exports org.apache.poi.openxml4j.exceptions;
+ exports org.apache.poi.openxml4j.opc;
+ exports org.apache.poi.openxml4j.opc.internal;
+ exports org.apache.poi.openxml4j.opc.internal.marshallers;
+ exports org.apache.poi.openxml4j.opc.internal.unmarshallers;
+ exports org.apache.poi.openxml4j.util;
+ exports org.apache.poi.xssf;
+ exports org.apache.poi.xssf.extractor;
+ exports org.apache.poi.xssf.eventusermodel;
+ exports org.apache.poi.xssf.usermodel;
+ exports org.apache.poi.xssf.usermodel.helpers;
+ exports org.apache.poi.xssf.usermodel.extensions;
+ exports org.apache.poi.xssf.binary;
+ exports org.apache.poi.xssf.model;
+ exports org.apache.poi.xssf.streaming;
+ exports org.apache.poi.xssf.util;
+ exports org.apache.poi.xslf.draw;
+ exports org.apache.poi.xslf.usermodel;
+ exports org.apache.poi.xslf.model;
+ exports org.apache.poi.xslf.util;
+ exports org.apache.poi.poifs.crypt.dsig;
+ exports org.apache.poi.poifs.crypt.dsig.facets;
+ exports org.apache.poi.poifs.crypt.dsig.services;
+ exports org.apache.poi.poifs.crypt.temp;
+
+ opens org.apache.poi.openxml4j.opc to org.apache.poi.poi;
+
+
+ /* optional dependencies for xml signatures - you need to add a require entry your module-info
+ * or add them via the --add-modules JVM argument */
+ requires java.xml.crypto;
+ requires static org.apache.santuario.xmlsec;
+ requires static org.bouncycastle.provider;
+ requires static org.bouncycastle.pkix;
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.ooxml {
+ requires transitive org.apache.poi.poi;
+ requires transitive org.apache.xmlbeans;
+ requires transitive org.apache.poi.ooxml.schemas;
+ requires org.apache.commons.collections4;
+ requires org.apache.commons.codec;
+ requires commons.math3;
+ requires SparseBitSet;
+ requires commons.logging;
+ requires java.logging;
+ requires java.desktop;
+ requires java.security.jgss;
+
+ provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
+
+ exports org.apache.poi.xwpf.extractor;
+ exports org.apache.poi.xwpf.usermodel;
+ exports org.apache.poi.xwpf.model;
+ exports org.apache.poi.xdgf.extractor;
+ exports org.apache.poi.xdgf.exceptions;
+ exports org.apache.poi.xdgf.usermodel;
+ exports org.apache.poi.xdgf.usermodel.section;
+ exports org.apache.poi.xdgf.usermodel.section.geometry;
+ exports org.apache.poi.xdgf.usermodel.shape;
+ exports org.apache.poi.xdgf.usermodel.shape.exceptions;
+ exports org.apache.poi.xdgf.xml;
+ exports org.apache.poi.xdgf.util;
+ exports org.apache.poi.xdgf.geom;
+ exports org.apache.poi.ooxml;
+ exports org.apache.poi.ooxml.dev;
+ exports org.apache.poi.ooxml.extractor;
+ exports org.apache.poi.ooxml.util;
+ exports org.apache.poi.xddf.usermodel;
+ exports org.apache.poi.xddf.usermodel.text;
+ exports org.apache.poi.xddf.usermodel.chart;
+ exports org.apache.poi.openxml4j.exceptions;
+ exports org.apache.poi.openxml4j.opc;
+ exports org.apache.poi.openxml4j.opc.internal;
+ exports org.apache.poi.openxml4j.opc.internal.marshallers;
+ exports org.apache.poi.openxml4j.opc.internal.unmarshallers;
+ exports org.apache.poi.openxml4j.util;
+ exports org.apache.poi.xssf;
+ exports org.apache.poi.xssf.extractor;
+ exports org.apache.poi.xssf.eventusermodel;
+ exports org.apache.poi.xssf.usermodel;
+ exports org.apache.poi.xssf.usermodel.helpers;
+ exports org.apache.poi.xssf.usermodel.extensions;
+ exports org.apache.poi.xssf.binary;
+ exports org.apache.poi.xssf.model;
+ exports org.apache.poi.xssf.streaming;
+ exports org.apache.poi.xssf.util;
+ exports org.apache.poi.xslf.draw;
+ exports org.apache.poi.xslf.usermodel;
+ exports org.apache.poi.xslf.model;
+ exports org.apache.poi.xslf.util;
+ exports org.apache.poi.poifs.crypt.dsig;
+ exports org.apache.poi.poifs.crypt.dsig.facets;
+ exports org.apache.poi.poifs.crypt.dsig.services;
+ exports org.apache.poi.poifs.crypt.temp;
+
+ opens org.apache.poi.openxml4j.opc to org.apache.poi.poi;
+
+
+ /* optional dependencies for xml signatures - you need to add a require entry your module-info
+ * or add them via the --add-modules JVM argument */
+ requires java.xml.crypto;
+ requires org.apache.santuario.xmlsec;
+ requires org.bouncycastle.provider;
+ requires org.bouncycastle.pkix;
+
+
+ // test specific exports
+ requires junit;
+ requires com.google.common;
+
+ exports org.apache.poi.extractor.ooxml to junit;
+ exports org.apache.poi.openxml4j.opc.compliance to junit;
+ exports org.apache.poi.poifs.crypt.tests to junit;
+ exports org.apache.poi.sl.tests to junit;
+ exports org.apache.poi.sl.tests.draw to junit;
+ exports org.apache.poi.ss.tests to junit;
+ exports org.apache.poi.ss.tests.extractor to junit;
+ exports org.apache.poi.ss.tests.format to junit;
+ exports org.apache.poi.ss.tests.formula to junit;
+ exports org.apache.poi.ss.tests.formula.eval to junit;
+ exports org.apache.poi.ss.tests.formula.functions to junit;
+ exports org.apache.poi.ss.tests.usermodel to junit;
+ exports org.apache.poi.ss.tests.util to junit;
+ exports org.apache.poi.util.tests to junit;
+ exports org.apache.poi.xslf to junit;
+ exports org.apache.poi.xslf.extractor to junit;
+ exports org.apache.poi.xssf.io to junit;
+ exports org.apache.poi.xssf.usermodel.charts to junit;
+ exports org.apache.poi.xwpf to junit;
+
+
+}
\ No newline at end of file
requires commons.math3;
requires SparseBitSet;
requires commons.logging;
+ requires java.logging;
+ requires java.desktop;
+ uses org.apache.poi.ss.usermodel.WorkbookProvider;
+ provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.hssf.usermodel.HSSFWorkbookFactory;
+
+ exports org.apache.poi;
+ exports org.apache.poi.common;
+ exports org.apache.poi.common.usermodel;
exports org.apache.poi.common.usermodel.fonts;
exports org.apache.poi.ddf;
exports org.apache.poi.extractor;
exports org.apache.poi.hssf.util;
exports org.apache.poi.poifs.common;
exports org.apache.poi.poifs.crypt;
+ exports org.apache.poi.poifs.crypt.agile;
exports org.apache.poi.poifs.crypt.binaryrc4;
exports org.apache.poi.poifs.crypt.cryptoapi;
exports org.apache.poi.poifs.crypt.standard;
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.poi {
+ requires org.apache.commons.collections4;
+ requires org.apache.commons.codec;
+ requires commons.math3;
+ requires SparseBitSet;
+ requires commons.logging;
+ requires java.logging;
+ requires java.desktop;
+
+ uses org.apache.poi.ss.usermodel.WorkbookProvider;
+
+ provides org.apache.poi.ss.usermodel.WorkbookProvider with org.apache.poi.hssf.usermodel.HSSFWorkbookFactory;
+
+ exports org.apache.poi;
+ exports org.apache.poi.common;
+ exports org.apache.poi.common.usermodel;
+ exports org.apache.poi.common.usermodel.fonts;
+ exports org.apache.poi.ddf;
+ exports org.apache.poi.extractor;
+ exports org.apache.poi.hpsf;
+ exports org.apache.poi.hpsf.extractor;
+ exports org.apache.poi.hpsf.wellknown;
+ exports org.apache.poi.hssf;
+ exports org.apache.poi.hssf.dev;
+ exports org.apache.poi.hssf.eventmodel;
+ exports org.apache.poi.hssf.eventusermodel;
+ exports org.apache.poi.hssf.eventusermodel.dummyrecord;
+ exports org.apache.poi.hssf.extractor;
+ exports org.apache.poi.hssf.model;
+ exports org.apache.poi.hssf.record;
+ exports org.apache.poi.hssf.record.aggregates;
+ exports org.apache.poi.hssf.record.cf;
+ exports org.apache.poi.hssf.record.chart;
+ exports org.apache.poi.hssf.record.common;
+ exports org.apache.poi.hssf.record.cont;
+ exports org.apache.poi.hssf.record.crypto;
+ exports org.apache.poi.hssf.record.pivottable;
+ exports org.apache.poi.hssf.usermodel;
+ exports org.apache.poi.hssf.usermodel.helpers;
+ exports org.apache.poi.hssf.util;
+ exports org.apache.poi.poifs.common;
+ exports org.apache.poi.poifs.crypt;
+ exports org.apache.poi.poifs.crypt.agile;
+ exports org.apache.poi.poifs.crypt.binaryrc4;
+ exports org.apache.poi.poifs.crypt.cryptoapi;
+ exports org.apache.poi.poifs.crypt.standard;
+ exports org.apache.poi.poifs.crypt.xor;
+ exports org.apache.poi.poifs.dev;
+ exports org.apache.poi.poifs.eventfilesystem;
+ exports org.apache.poi.poifs.filesystem;
+ exports org.apache.poi.poifs.macros;
+ exports org.apache.poi.poifs.nio;
+ exports org.apache.poi.poifs.property;
+ exports org.apache.poi.poifs.storage;
+ exports org.apache.poi.sl.draw;
+ exports org.apache.poi.sl.draw.geom;
+ exports org.apache.poi.sl.extractor;
+ exports org.apache.poi.sl.image;
+ exports org.apache.poi.sl.usermodel;
+ exports org.apache.poi.ss;
+ exports org.apache.poi.ss.extractor;
+ exports org.apache.poi.ss.format;
+ exports org.apache.poi.ss.formula;
+ exports org.apache.poi.ss.formula.atp;
+ exports org.apache.poi.ss.formula.constant;
+ exports org.apache.poi.ss.formula.eval;
+ exports org.apache.poi.ss.formula.eval.forked;
+ exports org.apache.poi.ss.formula.function;
+ exports org.apache.poi.ss.formula.functions;
+ exports org.apache.poi.ss.formula.ptg;
+ exports org.apache.poi.ss.formula.udf;
+ exports org.apache.poi.ss.usermodel;
+ exports org.apache.poi.ss.usermodel.helpers;
+ exports org.apache.poi.ss.util;
+ exports org.apache.poi.ss.util.cellwalk;
+ exports org.apache.poi.util;
+ exports org.apache.poi.wp.usermodel;
+
+ // test specific exports
+ requires junit;
+ requires net.bytebuddy;
+ opens org.apache.poi.hpsf.basic to junit;
+ opens org.apache.poi.hssf.record.pivot to junit;
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.scratchpad {
+ requires transitive org.apache.poi.poi;
+ requires java.desktop;
+ requires commons.math3;
+
+ exports org.apache.poi.hmef;
+ exports org.apache.poi.hmef.dev;
+ exports org.apache.poi.hmef.extractor;
+ exports org.apache.poi.hmef.attribute;
+ exports org.apache.poi.hdgf;
+ exports org.apache.poi.hdgf.dev;
+ exports org.apache.poi.hdgf.streams;
+ exports org.apache.poi.hdgf.extractor;
+ exports org.apache.poi.hdgf.pointers;
+ exports org.apache.poi.hdgf.exceptions;
+ exports org.apache.poi.hdgf.chunks;
+ exports org.apache.poi.hwpf;
+ exports org.apache.poi.hwpf.dev;
+ exports org.apache.poi.hwpf.sprm;
+ exports org.apache.poi.hwpf.converter;
+ exports org.apache.poi.hwpf.extractor;
+ exports org.apache.poi.hwpf.usermodel;
+ exports org.apache.poi.hwpf.model;
+ exports org.apache.poi.hwpf.model.io;
+ exports org.apache.poi.hwpf.model.types;
+ // exports org.apache.poi.hwmf;
+ exports org.apache.poi.hwmf.record;
+ exports org.apache.poi.hwmf.draw;
+ exports org.apache.poi.hwmf.usermodel;
+ // exports org.apache.poi.extractor;
+ exports org.apache.poi.extractor.ole2;
+ exports org.apache.poi.hpbf;
+ exports org.apache.poi.hpbf.dev;
+ exports org.apache.poi.hpbf.extractor;
+ exports org.apache.poi.hpbf.model;
+ exports org.apache.poi.hpbf.model.qcbits;
+ // exports org.apache.poi.hslf;
+ exports org.apache.poi.hslf.dev;
+ exports org.apache.poi.hslf.record;
+ exports org.apache.poi.hslf.extractor;
+ exports org.apache.poi.hslf.exceptions;
+ exports org.apache.poi.hslf.usermodel;
+ exports org.apache.poi.hslf.blip;
+ exports org.apache.poi.hslf.model;
+ exports org.apache.poi.hslf.model.textproperties;
+ exports org.apache.poi.hslf.util;
+ // exports org.apache.poi.hssf;
+ exports org.apache.poi.hssf.converter;
+ // exports org.apache.poi.hssf.usermodel;
+ exports org.apache.poi.hsmf;
+ exports org.apache.poi.hsmf.dev;
+ exports org.apache.poi.hsmf.datatypes;
+ exports org.apache.poi.hsmf.extractor;
+ exports org.apache.poi.hsmf.exceptions;
+ exports org.apache.poi.hsmf.parsers;
+ // exports org.apache.poi.hemf;
+ // exports org.apache.poi.hemf.record;
+ exports org.apache.poi.hemf.record.emf;
+ exports org.apache.poi.hemf.record.emfplus;
+ exports org.apache.poi.hemf.draw;
+ exports org.apache.poi.hemf.usermodel;
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+module org.apache.poi.scratchpad {
+ requires transitive org.apache.poi.poi;
+ requires java.desktop;
+ requires commons.math3;
+
+ exports org.apache.poi.hmef;
+ exports org.apache.poi.hmef.dev;
+ exports org.apache.poi.hmef.extractor;
+ exports org.apache.poi.hmef.attribute;
+ exports org.apache.poi.hdgf;
+ exports org.apache.poi.hdgf.dev;
+ exports org.apache.poi.hdgf.streams;
+ exports org.apache.poi.hdgf.extractor;
+ exports org.apache.poi.hdgf.pointers;
+ exports org.apache.poi.hdgf.exceptions;
+ exports org.apache.poi.hdgf.chunks;
+ exports org.apache.poi.hwpf;
+ exports org.apache.poi.hwpf.dev;
+ exports org.apache.poi.hwpf.sprm;
+ exports org.apache.poi.hwpf.converter;
+ exports org.apache.poi.hwpf.extractor;
+ exports org.apache.poi.hwpf.usermodel;
+ exports org.apache.poi.hwpf.model;
+ exports org.apache.poi.hwpf.model.io;
+ exports org.apache.poi.hwpf.model.types;
+ exports org.apache.poi.hwmf.record;
+ exports org.apache.poi.hwmf.draw;
+ exports org.apache.poi.hwmf.usermodel;
+ exports org.apache.poi.extractor.ole2;
+ exports org.apache.poi.hpbf;
+ exports org.apache.poi.hpbf.dev;
+ exports org.apache.poi.hpbf.extractor;
+ exports org.apache.poi.hpbf.model;
+ exports org.apache.poi.hpbf.model.qcbits;
+ exports org.apache.poi.hslf.dev;
+ exports org.apache.poi.hslf.record;
+ exports org.apache.poi.hslf.extractor;
+ exports org.apache.poi.hslf.exceptions;
+ exports org.apache.poi.hslf.usermodel;
+ exports org.apache.poi.hslf.blip;
+ exports org.apache.poi.hslf.model;
+ exports org.apache.poi.hslf.model.textproperties;
+ exports org.apache.poi.hslf.util;
+ exports org.apache.poi.hssf.converter;
+ exports org.apache.poi.hsmf;
+ exports org.apache.poi.hsmf.dev;
+ exports org.apache.poi.hsmf.datatypes;
+ exports org.apache.poi.hsmf.extractor;
+ exports org.apache.poi.hsmf.exceptions;
+ exports org.apache.poi.hsmf.parsers;
+ exports org.apache.poi.hemf.record.emf;
+ exports org.apache.poi.hemf.record.emfplus;
+ exports org.apache.poi.hemf.draw;
+ exports org.apache.poi.hemf.usermodel;
+
+
+ // test specific exports
+ requires junit;
+ requires org.mockito;
+
+ exports org.apache.poi.hemf.hemfplus.extractor to junit;
+ exports org.apache.poi.hslf to junit;
+ exports org.apache.poi.hwmf to junit;
+
+ opens org.apache.poi.hwpf.model to org.mockito;
+ opens org.apache.poi.hwpf.model.types to org.mockito;
+}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt.agile;
-
-import static org.apache.poi.poifs.crypt.CryptoFunctions.generateIv;
-import static org.apache.poi.poifs.crypt.CryptoFunctions.generateKey;
-import static org.apache.poi.poifs.crypt.CryptoFunctions.getBlock0;
-import static org.apache.poi.poifs.crypt.CryptoFunctions.getCipher;
-import static org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest;
-import static org.apache.poi.poifs.crypt.CryptoFunctions.hashPassword;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.security.GeneralSecurityException;
-import java.security.MessageDigest;
-import java.security.spec.AlgorithmParameterSpec;
-import java.util.Arrays;
-
-import javax.crypto.Cipher;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.RC2ParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.poifs.crypt.ChainingMode;
-import org.apache.poi.poifs.crypt.ChunkedCipherInputStream;
-import org.apache.poi.poifs.crypt.CipherAlgorithm;
-import org.apache.poi.poifs.crypt.CryptoFunctions;
-import org.apache.poi.poifs.crypt.Decryptor;
-import org.apache.poi.poifs.crypt.EncryptionHeader;
-import org.apache.poi.poifs.crypt.EncryptionInfo;
-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.util.LittleEndian;
-
-/**
- * Decryptor implementation for Agile Encryption
- */
-public class AgileDecryptor extends Decryptor {
- static final byte[] kVerifierInputBlock = longToBytes(0xfea7d2763b4b9e79L);
- static final byte[] kHashedVerifierBlock = longToBytes(0xd7aa0f6d3061344eL);
- static final byte[] kCryptoKeyBlock = longToBytes(0x146e0be7abacd0d6L);
- static final byte[] kIntegrityKeyBlock = longToBytes(0x5fb2ad010cb9e1f6L);
- static final byte[] kIntegrityValueBlock = longToBytes(0xa0677f02b22c8433L);
-
- private long _length = -1;
-
- protected AgileDecryptor() {
- }
-
- protected AgileDecryptor(AgileDecryptor other) {
- super(other);
- _length = other._length;
- }
-
- private static byte[] longToBytes(long l) {
- return ByteBuffer.allocate(Long.BYTES).putLong(l).array();
- }
-
- /**
- * set decryption password
- */
- @Override
- public boolean verifyPassword(String password) throws GeneralSecurityException {
- AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
- AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
-
- int blockSize = header.getBlockSize();
-
- byte[] pwHash = hashPassword(password, ver.getHashAlgorithm(), ver.getSalt(), ver.getSpinCount());
-
- /*
- * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
- * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
- * attribute.
- * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
- * the binary byte array used to create the saltValue attribute, and a blockKey byte array
- * consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79.
- * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
- * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
- * integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of
- * blockSize bytes.
- * 4. Use base64 to encode the result of step 3.
- */
- byte[] verfierInputEnc = hashInput(ver, pwHash, kVerifierInputBlock, ver.getEncryptedVerifier(), Cipher.DECRYPT_MODE);
- setVerifier(verfierInputEnc);
- MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm());
- byte[] verifierHash = hashMD.digest(verfierInputEnc);
-
- /*
- * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
- * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for
- * encryptedVerifierHashInput.
- * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
- * the binary byte array used to create the saltValue attribute, and a blockKey byte array
- * consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e.
- * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as
- * an initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of
- * blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
- * 4. Use base64 to encode the result of step 3.
- */
- byte[] verifierHashDec = hashInput(ver, pwHash, kHashedVerifierBlock, ver.getEncryptedVerifierHash(), Cipher.DECRYPT_MODE);
- verifierHashDec = getBlock0(verifierHashDec, ver.getHashAlgorithm().hashSize);
-
- /*
- * encryptedKeyValue: This attribute MUST be generated by using the following steps:
- * 1. Generate a random array of bytes that is the same size as specified by the
- * Encryptor.KeyData.keyBits attribute of the parent element.
- * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password,
- * the binary byte array used to create the saltValue attribute, and a blockKey byte array
- * consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6.
- * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
- * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
- * integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of
- * blockSize bytes.
- * 4. Use base64 to encode the result of step 3.
- */
- byte[] keyspec = hashInput(ver, pwHash, kCryptoKeyBlock, ver.getEncryptedKey(), Cipher.DECRYPT_MODE);
- keyspec = getBlock0(keyspec, header.getKeySize()/8);
- SecretKeySpec secretKey = new SecretKeySpec(keyspec, header.getCipherAlgorithm().jceId);
-
- /*
- * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
- * contained within the KeyEncryptors sequence. Use this key for encryption operations in the
- * remaining steps of this section.
- * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the
- * KeyData.hashSize attribute.
- * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the
- * KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes: 0x5f,
- * 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an initialization vector as specified in
- * section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize bytes, pad the
- * array with 0x00 to the next integral multiple of blockSize bytes.
- * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3.
- */
- byte[] vec = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, blockSize);
- CipherAlgorithm cipherAlgo = header.getCipherAlgorithm();
- Cipher cipher = getCipher(secretKey, cipherAlgo, header.getChainingMode(), vec, Cipher.DECRYPT_MODE);
- byte[] hmacKey = cipher.doFinal(header.getEncryptedHmacKey());
- hmacKey = getBlock0(hmacKey, header.getHashAlgorithm().hashSize);
-
- /*
- * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
- * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
- * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
- * used as the message.
- * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
- * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
- * 7. Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6.
- */
- vec = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize);
- cipher = getCipher(secretKey, cipherAlgo, ver.getChainingMode(), vec, Cipher.DECRYPT_MODE);
- byte[] hmacValue = cipher.doFinal(header.getEncryptedHmacValue());
- hmacValue = getBlock0(hmacValue, header.getHashAlgorithm().hashSize);
-
- if (Arrays.equals(verifierHashDec, verifierHash)) {
- setSecretKey(secretKey);
- setIntegrityHmacKey(hmacKey);
- setIntegrityHmacValue(hmacValue);
- return true;
- } else {
- return false;
- }
- }
-
- protected static int getNextBlockSize(int inputLen, int blockSize) {
- return (int)Math.ceil(inputLen / (double)blockSize) * blockSize;
- }
-
- /* package */ static byte[] hashInput(AgileEncryptionVerifier ver, byte[] pwHash, byte[] blockKey, byte[] inputKey, int cipherMode) {
- CipherAlgorithm cipherAlgo = ver.getCipherAlgorithm();
- ChainingMode chainMode = ver.getChainingMode();
- int keySize = ver.getKeySize()/8;
- int blockSize = ver.getBlockSize();
- HashAlgorithm hashAlgo = ver.getHashAlgorithm();
-
- byte[] intermedKey = generateKey(pwHash, hashAlgo, blockKey, keySize);
- SecretKey skey = new SecretKeySpec(intermedKey, cipherAlgo.jceId);
- byte[] iv = generateIv(hashAlgo, ver.getSalt(), null, blockSize);
- Cipher cipher = getCipher(skey, cipherAlgo, chainMode, iv, cipherMode);
- byte[] hashFinal;
-
- try {
- inputKey = getBlock0(inputKey, getNextBlockSize(inputKey.length, blockSize));
- hashFinal = cipher.doFinal(inputKey);
- return hashFinal;
- } catch (GeneralSecurityException e) {
- throw new EncryptedDocumentException(e);
- }
- }
-
- @Override
- public InputStream getDataStream(DirectoryNode dir) throws IOException, GeneralSecurityException {
- DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
- _length = dis.readLong();
- return new AgileCipherInputStream(dis, _length);
- }
-
- @Override
- public long getLength(){
- if(_length == -1) {
- throw new IllegalStateException("EcmaDecryptor.getDataStream() was not called");
- }
- return _length;
- }
-
-
- protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode)
- throws GeneralSecurityException {
- EncryptionHeader header = encryptionInfo.getHeader();
- String padding = (lastChunk ? "PKCS5Padding" : "NoPadding");
- if (existing == null || !existing.getAlgorithm().endsWith(padding)) {
- existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding);
- }
-
- byte[] blockKey = new byte[4];
- LittleEndian.putInt(blockKey, 0, block);
- byte[] iv = generateIv(header.getHashAlgorithm(), header.getKeySalt(), blockKey, header.getBlockSize());
-
- AlgorithmParameterSpec aps;
- if (header.getCipherAlgorithm() == CipherAlgorithm.rc2) {
- aps = new RC2ParameterSpec(skey.getEncoded().length*8, iv);
- } else {
- aps = new IvParameterSpec(iv);
- }
-
- existing.init(encryptionMode, skey, aps);
-
- return existing;
- }
-
- /**
- * 2.3.4.15 Data Encryption (Agile Encryption)
- *
- * The EncryptedPackage stream (1) MUST be encrypted in 4096-byte segments to facilitate nearly
- * random access while allowing CBC modes to be used in the encryption process.
- * The initialization vector for the encryption process MUST be obtained by using the zero-based
- * segment number as a blockKey and the binary form of the KeyData.saltValue as specified in
- * section 2.3.4.12. The block number MUST be represented as a 32-bit unsigned integer.
- * Data blocks MUST then be encrypted by using the initialization vector and the intermediate key
- * obtained by decrypting the encryptedKeyValue from a KeyEncryptor contained within the
- * KeyEncryptors sequence as specified in section 2.3.4.10. The final data block MUST be padded to
- * the next integral multiple of the KeyData.blockSize value. Any padding bytes can be used. Note
- * that the StreamSize field of the EncryptedPackage field specifies the number of bytes of
- * unencrypted data as specified in section 2.3.4.4.
- */
- private class AgileCipherInputStream extends ChunkedCipherInputStream {
- public AgileCipherInputStream(DocumentInputStream stream, long size)
- throws GeneralSecurityException {
- super(stream, size, 4096);
- }
-
- // TODO: calculate integrity hmac while reading the stream
- // for a post-validation of the data
-
- @Override
- protected Cipher initCipherForBlock(Cipher cipher, int block)
- throws GeneralSecurityException {
- return AgileDecryptor.initCipherForBlock(cipher, block, false, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE);
- }
- }
-
- @Override
- public AgileDecryptor copy() {
- return new AgileDecryptor(this);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt.agile;
-
-import java.util.Map;
-import java.util.function.Supplier;
-
-import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
-import com.microsoft.schemas.office.x2006.encryption.CTKeyData;
-import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
-import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.poifs.crypt.ChainingMode;
-import org.apache.poi.poifs.crypt.CipherAlgorithm;
-import org.apache.poi.poifs.crypt.EncryptionHeader;
-import org.apache.poi.poifs.crypt.HashAlgorithm;
-import org.apache.poi.util.GenericRecordUtil;
-
-public class AgileEncryptionHeader extends EncryptionHeader {
- private byte[] encryptedHmacKey;
- private byte[] encryptedHmacValue;
-
- public AgileEncryptionHeader(String descriptor) {
- this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
- }
-
- public AgileEncryptionHeader(AgileEncryptionHeader other) {
- super(other);
- encryptedHmacKey = (other.encryptedHmacKey == null) ? null : other.encryptedHmacKey.clone();
- encryptedHmacValue = (other.encryptedHmacValue == null) ? null : other.encryptedHmacValue.clone();
- }
-
- protected AgileEncryptionHeader(EncryptionDocument ed) {
- CTKeyData keyData;
- try {
- keyData = ed.getEncryption().getKeyData();
- if (keyData == null) {
- throw new NullPointerException("keyData not set");
- }
- } catch (Exception e) {
- throw new EncryptedDocumentException("Unable to parse keyData");
- }
-
- int keyBits = (int)keyData.getKeyBits();
-
- CipherAlgorithm ca = CipherAlgorithm.fromXmlId(keyData.getCipherAlgorithm().toString(), keyBits);
- setCipherAlgorithm(ca);
- setCipherProvider(ca.provider);
-
- setKeySize(keyBits);
- setFlags(0);
- setSizeExtra(0);
- setCspName(null);
- setBlockSize(keyData.getBlockSize());
-
- switch (keyData.getCipherChaining().intValue()) {
- case STCipherChaining.INT_CHAINING_MODE_CBC:
- setChainingMode(ChainingMode.cbc);
- break;
- case STCipherChaining.INT_CHAINING_MODE_CFB:
- setChainingMode(ChainingMode.cfb);
- break;
- default:
- throw new EncryptedDocumentException("Unsupported chaining mode - "+ keyData.getCipherChaining());
- }
-
- int hashSize = keyData.getHashSize();
-
- HashAlgorithm ha = HashAlgorithm.fromEcmaId(keyData.getHashAlgorithm().toString());
- setHashAlgorithm(ha);
-
- if (getHashAlgorithm().hashSize != hashSize) {
- throw new EncryptedDocumentException("Unsupported hash algorithm: " +
- keyData.getHashAlgorithm() + " @ " + hashSize + " bytes");
- }
-
- int saltLength = keyData.getSaltSize();
- setKeySalt(keyData.getSaltValue());
- if (getKeySalt().length != saltLength) {
- throw new EncryptedDocumentException("Invalid salt length");
- }
-
- CTDataIntegrity di = ed.getEncryption().getDataIntegrity();
- setEncryptedHmacKey(di.getEncryptedHmacKey());
- setEncryptedHmacValue(di.getEncryptedHmacValue());
- }
-
-
- public AgileEncryptionHeader(CipherAlgorithm algorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
- setCipherAlgorithm(algorithm);
- setHashAlgorithm(hashAlgorithm);
- setKeySize(keyBits);
- setBlockSize(blockSize);
- setChainingMode(chainingMode);
- }
-
- // make method visible for this package
- @Override
- protected void setKeySalt(byte[] salt) {
- if (salt == null || salt.length != getBlockSize()) {
- throw new EncryptedDocumentException("invalid verifier salt");
- }
- super.setKeySalt(salt);
- }
-
- public byte[] getEncryptedHmacKey() {
- return encryptedHmacKey;
- }
-
- protected void setEncryptedHmacKey(byte[] encryptedHmacKey) {
- this.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone();
- }
-
- public byte[] getEncryptedHmacValue() {
- return encryptedHmacValue;
- }
-
- protected void setEncryptedHmacValue(byte[] encryptedHmacValue) {
- this.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone();
- }
-
- @Override
- public Map<String, Supplier<?>> getGenericProperties() {
- return GenericRecordUtil.getGenericProperties(
- "base", super::getGenericProperties,
- "encryptedHmacKey", this::getEncryptedHmacKey,
- "encryptedHmacValue", this::getEncryptedHmacValue
- );
- }
-
- @Override
- public AgileEncryptionHeader copy() {
- return new AgileEncryptionHeader(this);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt.agile;
-
-import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.poifs.crypt.ChainingMode;
-import org.apache.poi.poifs.crypt.CipherAlgorithm;
-import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.poifs.crypt.EncryptionInfoBuilder;
-import org.apache.poi.poifs.crypt.EncryptionMode;
-import org.apache.poi.poifs.crypt.HashAlgorithm;
-import org.apache.poi.util.LittleEndianInput;
-import org.apache.xmlbeans.XmlException;
-
-import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
-
-public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder {
-
- @Override
- public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException {
- EncryptionDocument ed = parseDescriptor((InputStream)dis);
- info.setHeader(new AgileEncryptionHeader(ed));
- info.setVerifier(new AgileEncryptionVerifier(ed));
- if (info.getVersionMajor() == EncryptionMode.agile.versionMajor
- && info.getVersionMinor() == EncryptionMode.agile.versionMinor) {
- AgileDecryptor dec = new AgileDecryptor();
- dec.setEncryptionInfo(info);
- info.setDecryptor(dec);
- AgileEncryptor enc = new AgileEncryptor();
- enc.setEncryptionInfo(info);
- info.setEncryptor(enc);
- }
- }
-
- @Override
- public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
- if (cipherAlgorithm == null) {
- cipherAlgorithm = CipherAlgorithm.aes128;
- }
- if (cipherAlgorithm == CipherAlgorithm.rc4) {
- throw new EncryptedDocumentException("RC4 must not be used with agile encryption.");
- }
- if (hashAlgorithm == null) {
- hashAlgorithm = HashAlgorithm.sha1;
- }
- if (chainingMode == null) {
- chainingMode = ChainingMode.cbc;
- }
- if (!(chainingMode == ChainingMode.cbc || chainingMode == ChainingMode.cfb)) {
- throw new EncryptedDocumentException("Agile encryption only supports CBC/CFB chaining.");
- }
- if (keyBits == -1) {
- keyBits = cipherAlgorithm.defaultKeySize;
- }
- if (blockSize == -1) {
- blockSize = cipherAlgorithm.blockSize;
- }
- boolean found = false;
- for (int ks : cipherAlgorithm.allowedKeySize) {
- found |= (ks == keyBits);
- }
- if (!found) {
- throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+ cipherAlgorithm);
- }
- info.setHeader(new AgileEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
- info.setVerifier(new AgileEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
- AgileDecryptor dec = new AgileDecryptor();
- dec.setEncryptionInfo(info);
- info.setDecryptor(dec);
- AgileEncryptor enc = new AgileEncryptor();
- enc.setEncryptionInfo(info);
- info.setEncryptor(enc);
- }
-
- protected static EncryptionDocument parseDescriptor(String descriptor) {
- try {
- return EncryptionDocument.Factory.parse(descriptor, DEFAULT_XML_OPTIONS);
- } catch (XmlException e) {
- throw new EncryptedDocumentException("Unable to parse encryption descriptor", e);
- }
- }
-
- protected static EncryptionDocument parseDescriptor(InputStream descriptor) {
- try {
- return EncryptionDocument.Factory.parse(descriptor, DEFAULT_XML_OPTIONS);
- } catch (Exception e) {
- throw new EncryptedDocumentException("Unable to parse encryption descriptor", e);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt.agile;
-
-import java.util.Iterator;
-
-import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptor;
-import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
-import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
-import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor;
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.poifs.crypt.ChainingMode;
-import org.apache.poi.poifs.crypt.CipherAlgorithm;
-import org.apache.poi.poifs.crypt.EncryptionVerifier;
-import org.apache.poi.poifs.crypt.HashAlgorithm;
-
-/**
- * Used when checking if a key is valid for a document
- */
-public class AgileEncryptionVerifier extends EncryptionVerifier {
-
- private int keyBits = -1;
- private int blockSize = -1;
-
- @SuppressWarnings("unused")
- public AgileEncryptionVerifier(String descriptor) {
- this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
- }
-
- protected AgileEncryptionVerifier(EncryptionDocument ed) {
- Iterator<CTKeyEncryptor> encList = ed.getEncryption().getKeyEncryptors().getKeyEncryptorList().iterator();
- CTPasswordKeyEncryptor keyData;
- try {
- keyData = encList.next().getEncryptedPasswordKey();
- if (keyData == null) {
- throw new NullPointerException("encryptedKey not set");
- }
- } catch (Exception e) {
- throw new EncryptedDocumentException("Unable to parse keyData", e);
- }
-
- int kb = (int)keyData.getKeyBits();
- CipherAlgorithm ca = CipherAlgorithm.fromXmlId(keyData.getCipherAlgorithm().toString(), kb);
- setCipherAlgorithm(ca);
-
- setKeySize(kb);
-
- int blockSize = keyData.getBlockSize();
- setBlockSize(blockSize);
-
- int hashSize = keyData.getHashSize();
-
- HashAlgorithm ha = HashAlgorithm.fromEcmaId(keyData.getHashAlgorithm().toString());
- setHashAlgorithm(ha);
-
- if (getHashAlgorithm().hashSize != hashSize) {
- throw new EncryptedDocumentException("Unsupported hash algorithm: " +
- keyData.getHashAlgorithm() + " @ " + hashSize + " bytes");
- }
-
- setSpinCount(keyData.getSpinCount());
- setEncryptedVerifier(keyData.getEncryptedVerifierHashInput());
- setSalt(keyData.getSaltValue());
- setEncryptedKey(keyData.getEncryptedKeyValue());
- setEncryptedVerifierHash(keyData.getEncryptedVerifierHashValue());
-
- int saltSize = keyData.getSaltSize();
- if (saltSize != getSalt().length) {
- throw new EncryptedDocumentException("Invalid salt size");
- }
-
- switch (keyData.getCipherChaining().intValue()) {
- case STCipherChaining.INT_CHAINING_MODE_CBC:
- setChainingMode(ChainingMode.cbc);
- break;
- case STCipherChaining.INT_CHAINING_MODE_CFB:
- setChainingMode(ChainingMode.cfb);
- break;
- default:
- throw new EncryptedDocumentException("Unsupported chaining mode - "+ keyData.getCipherChaining());
- }
- }
-
- public AgileEncryptionVerifier(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
- setCipherAlgorithm(cipherAlgorithm);
- setHashAlgorithm(hashAlgorithm);
- setChainingMode(chainingMode);
- setKeySize(keyBits);
- setBlockSize(blockSize);
- setSpinCount(100000); // TODO: use parameter
- }
-
- public AgileEncryptionVerifier(AgileEncryptionVerifier other) {
- super(other);
- keyBits = other.keyBits;
- blockSize = other.blockSize;
- }
-
- @Override
- protected void setSalt(byte[] salt) {
- if (salt == null || salt.length != getCipherAlgorithm().blockSize) {
- throw new EncryptedDocumentException("invalid verifier salt");
- }
- super.setSalt(salt);
- }
-
- // make method visible for this package
- @Override
- protected void setEncryptedVerifier(byte[] encryptedVerifier) {
- super.setEncryptedVerifier(encryptedVerifier);
- }
-
- // make method visible for this package
- @Override
- protected void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
- super.setEncryptedVerifierHash(encryptedVerifierHash);
- }
-
- // make method visible for this package
- @Override
- protected void setEncryptedKey(byte[] encryptedKey) {
- super.setEncryptedKey(encryptedKey);
- }
-
- @Override
- public AgileEncryptionVerifier copy() {
- return new AgileEncryptionVerifier(this);
- }
-
-
- /**
- * The keysize (in bits) of the verifier data. This usually equals the keysize of the header,
- * but only on a few exceptions, like files generated by Office for Mac, can be
- * different.
- *
- * @return the keysize (in bits) of the verifier.
- */
- public int getKeySize() {
- return keyBits;
- }
-
-
- /**
- * The blockSize (in bytes) of the verifier data.
- * This usually equals the blocksize of the header.
- *
- * @return the blockSize (in bytes) of the verifier,
- */
- public int getBlockSize() {
- return blockSize;
- }
-
- /**
- * Sets the keysize (in bits) of the verifier
- *
- * @param keyBits the keysize (in bits)
- */
- protected void setKeySize(int keyBits) {
- this.keyBits = keyBits;
- for (int allowedBits : getCipherAlgorithm().allowedKeySize) {
- if (allowedBits == keyBits) {
- return;
- }
- }
- throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for cipher "+getCipherAlgorithm());
- }
-
-
- /**
- * Sets the blockSize (in bytes) of the verifier
- *
- * @param blockSize the blockSize (in bytes)
- */
- protected void setBlockSize(int blockSize) {
- this.blockSize = blockSize;
- }
-
- @Override
- protected final void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
- super.setCipherAlgorithm(cipherAlgorithm);
- if (cipherAlgorithm.allowedKeySize.length == 1) {
- setKeySize(cipherAlgorithm.defaultKeySize);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt.agile;
-
-import static org.apache.poi.poifs.crypt.CryptoFunctions.getBlock0;
-import static org.apache.poi.poifs.crypt.CryptoFunctions.getCipher;
-import static org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest;
-import static org.apache.poi.poifs.crypt.CryptoFunctions.hashPassword;
-import static org.apache.poi.poifs.crypt.DataSpaceMapUtils.createEncryptionEntry;
-import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.getNextBlockSize;
-import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.hashInput;
-import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kCryptoKeyBlock;
-import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kHashedVerifierBlock;
-import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kIntegrityKeyBlock;
-import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kIntegrityValueBlock;
-import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kVerifierInputBlock;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-import java.security.GeneralSecurityException;
-import java.security.MessageDigest;
-import java.security.SecureRandom;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
-import com.microsoft.schemas.office.x2006.encryption.CTEncryption;
-import com.microsoft.schemas.office.x2006.encryption.CTKeyData;
-import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptor;
-import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptors;
-import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
-import com.microsoft.schemas.office.x2006.encryption.STCipherAlgorithm;
-import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
-import com.microsoft.schemas.office.x2006.encryption.STHashAlgorithm;
-import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor;
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
-import org.apache.poi.poifs.crypt.CryptoFunctions;
-import org.apache.poi.poifs.crypt.DataSpaceMapUtils;
-import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.poifs.crypt.Encryptor;
-import org.apache.poi.poifs.crypt.HashAlgorithm;
-import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.LittleEndianByteArrayOutputStream;
-import org.apache.poi.util.LittleEndianConsts;
-import org.apache.xmlbeans.XmlOptions;
-
-public class AgileEncryptor extends Encryptor {
-
- //arbitrarily selected; may need to increase
- private static final int MAX_RECORD_LENGTH = 1_000_000;
-
- private byte[] integritySalt;
- private byte[] pwHash;
-
- protected AgileEncryptor() {}
-
- protected AgileEncryptor(AgileEncryptor other) {
- super(other);
- integritySalt = (other.integritySalt == null) ? null : other.integritySalt.clone();
- pwHash = (other.pwHash == null) ? null : other.pwHash.clone();
- }
-
- @Override
- public void confirmPassword(String password) {
- // see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier
- Random r = new SecureRandom();
- AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
- int blockSize = header.getBlockSize();
- int keySize = header.getKeySize()/8;
- int hashSize = header.getHashAlgorithm().hashSize;
-
- byte[] newVerifierSalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
- , newVerifier = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
- , newKeySalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
- , newKeySpec = IOUtils.safelyAllocate(keySize, MAX_RECORD_LENGTH)
- , newIntegritySalt = IOUtils.safelyAllocate(hashSize, MAX_RECORD_LENGTH);
- r.nextBytes(newVerifierSalt); // blocksize
- r.nextBytes(newVerifier); // blocksize
- r.nextBytes(newKeySalt); // blocksize
- r.nextBytes(newKeySpec); // keysize
- r.nextBytes(newIntegritySalt); // hashsize
-
- confirmPassword(password, newKeySpec, newKeySalt, newVerifierSalt, newVerifier, newIntegritySalt);
- }
-
- @Override
- public void confirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) {
- AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
- AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
-
- ver.setSalt(verifierSalt);
- header.setKeySalt(keySalt);
-
- int blockSize = header.getBlockSize();
-
- pwHash = hashPassword(password, ver.getHashAlgorithm(), verifierSalt, ver.getSpinCount());
-
- /*
- * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
- * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
- * attribute.
- * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
- * the binary byte array used to create the saltValue attribute, and a blockKey byte array
- * consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79.
- * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
- * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
- * integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of
- * blockSize bytes.
- * 4. Use base64 to encode the result of step 3.
- */
- byte[] encryptedVerifier = hashInput(ver, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
- ver.setEncryptedVerifier(encryptedVerifier);
-
-
- /*
- * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
- * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for
- * encryptedVerifierHashInput.
- * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
- * the binary byte array used to create the saltValue attribute, and a blockKey byte array
- * consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e.
- * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as
- * an initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of
- * blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
- * 4. Use base64 to encode the result of step 3.
- */
- MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm());
- byte[] hashedVerifier = hashMD.digest(verifier);
- byte[] encryptedVerifierHash = hashInput(ver, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
- ver.setEncryptedVerifierHash(encryptedVerifierHash);
-
- /*
- * encryptedKeyValue: This attribute MUST be generated by using the following steps:
- * 1. Generate a random array of bytes that is the same size as specified by the
- * Encryptor.KeyData.keyBits attribute of the parent element.
- * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password,
- * the binary byte array used to create the saltValue attribute, and a blockKey byte array
- * consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6.
- * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
- * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
- * integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of
- * blockSize bytes.
- * 4. Use base64 to encode the result of step 3.
- */
- byte[] encryptedKey = hashInput(ver, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
- ver.setEncryptedKey(encryptedKey);
-
- SecretKey secretKey = new SecretKeySpec(keySpec, header.getCipherAlgorithm().jceId);
- setSecretKey(secretKey);
-
- /*
- * 2.3.4.14 DataIntegrity Generation (Agile Encryption)
- *
- * The DataIntegrity element contained within an Encryption element MUST be generated by using
- * the following steps:
- * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
- * contained within the KeyEncryptors sequence. Use this key for encryption operations in the
- * remaining steps of this section.
- * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the
- * KeyData.hashSize attribute.
- * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the
- * KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes:
- * 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an initialization vector as
- * specified in section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize
- * bytes, pad the array with 0x00 to the next integral multiple of blockSize bytes.
- * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3.
- * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
- * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
- * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
- * used as the message.
- * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
- * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
- * 7. Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6.
- */
- this.integritySalt = integritySalt.clone();
-
- try {
- byte[] vec = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, header.getBlockSize());
- Cipher cipher = getCipher(secretKey, header.getCipherAlgorithm(), header.getChainingMode(), vec, Cipher.ENCRYPT_MODE);
- byte[] hmacKey = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize));
- byte[] encryptedHmacKey = cipher.doFinal(hmacKey);
- header.setEncryptedHmacKey(encryptedHmacKey);
- } catch (GeneralSecurityException e) {
- throw new EncryptedDocumentException(e);
- }
- }
-
- @Override
- public OutputStream getDataStream(DirectoryNode dir)
- throws IOException, GeneralSecurityException {
- // TODO: initialize headers
- return new AgileCipherOutputStream(dir);
- }
-
- /**
- * Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
- * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
- * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
- * used as the message.
- *
- * Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
- * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
- **/
- protected void updateIntegrityHMAC(File tmpFile, int oleStreamSize) throws GeneralSecurityException, IOException {
- // as the integrity hmac needs to contain the StreamSize,
- // it's not possible to calculate it on-the-fly while buffering
- // TODO: add stream size parameter to getDataStream()
- AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
- int blockSize = header.getBlockSize();
- HashAlgorithm hashAlgo = header.getHashAlgorithm();
- Mac integrityMD = CryptoFunctions.getMac(hashAlgo);
- byte[] hmacKey = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize));
- integrityMD.init(new SecretKeySpec(hmacKey, hashAlgo.jceHmacId));
-
- byte[] buf = new byte[1024];
- LittleEndian.putLong(buf, 0, oleStreamSize);
- integrityMD.update(buf, 0, LittleEndianConsts.LONG_SIZE);
-
- try (InputStream fis = new FileInputStream(tmpFile)) {
- int readBytes;
- while ((readBytes = fis.read(buf)) != -1) {
- integrityMD.update(buf, 0, readBytes);
- }
- }
-
- byte[] hmacValue = integrityMD.doFinal();
- byte[] hmacValueFilled = getBlock0(hmacValue, getNextBlockSize(hmacValue.length, blockSize));
-
- byte[] iv = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize);
- Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE);
- byte[] encryptedHmacValue = cipher.doFinal(hmacValueFilled);
-
- header.setEncryptedHmacValue(encryptedHmacValue);
- }
-
- private final CTKeyEncryptor.Uri.Enum passwordUri =
- CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_PASSWORD;
-
- protected EncryptionDocument createEncryptionDocument() {
- AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
- AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
-
- EncryptionDocument ed = EncryptionDocument.Factory.newInstance();
- CTEncryption edRoot = ed.addNewEncryption();
-
- CTKeyData keyData = edRoot.addNewKeyData();
- CTKeyEncryptors keyEncList = edRoot.addNewKeyEncryptors();
- CTKeyEncryptor keyEnc = keyEncList.addNewKeyEncryptor();
- keyEnc.setUri(passwordUri);
- CTPasswordKeyEncryptor keyPass = keyEnc.addNewEncryptedPasswordKey();
-
- keyPass.setSpinCount(ver.getSpinCount());
-
- keyData.setSaltSize(header.getBlockSize());
- keyPass.setSaltSize(ver.getBlockSize());
-
- keyData.setBlockSize(header.getBlockSize());
- keyPass.setBlockSize(ver.getBlockSize());
-
- keyData.setKeyBits(header.getKeySize());
- keyPass.setKeyBits(ver.getKeySize());
-
- keyData.setHashSize(header.getHashAlgorithm().hashSize);
- keyPass.setHashSize(ver.getHashAlgorithm().hashSize);
-
- // header and verifier have to have the same cipher algorithm
- if (!header.getCipherAlgorithm().xmlId.equals(ver.getCipherAlgorithm().xmlId)) {
- throw new EncryptedDocumentException("Cipher algorithm of header and verifier have to match");
- }
- STCipherAlgorithm.Enum xmlCipherAlgo = STCipherAlgorithm.Enum.forString(header.getCipherAlgorithm().xmlId);
- if (xmlCipherAlgo == null) {
- throw new EncryptedDocumentException("CipherAlgorithm "+header.getCipherAlgorithm()+" not supported.");
- }
- keyData.setCipherAlgorithm(xmlCipherAlgo);
- keyPass.setCipherAlgorithm(xmlCipherAlgo);
-
- switch (header.getChainingMode()) {
- case cbc:
- keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC);
- keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC);
- break;
- case cfb:
- keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CFB);
- keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CFB);
- break;
- default:
- throw new EncryptedDocumentException("ChainingMode "+header.getChainingMode()+" not supported.");
- }
-
- keyData.setHashAlgorithm(mapHashAlgorithm(header.getHashAlgorithm()));
- keyPass.setHashAlgorithm(mapHashAlgorithm(ver.getHashAlgorithm()));
-
- keyData.setSaltValue(header.getKeySalt());
- keyPass.setSaltValue(ver.getSalt());
- keyPass.setEncryptedVerifierHashInput(ver.getEncryptedVerifier());
- keyPass.setEncryptedVerifierHashValue(ver.getEncryptedVerifierHash());
- keyPass.setEncryptedKeyValue(ver.getEncryptedKey());
-
- CTDataIntegrity hmacData = edRoot.addNewDataIntegrity();
- hmacData.setEncryptedHmacKey(header.getEncryptedHmacKey());
- hmacData.setEncryptedHmacValue(header.getEncryptedHmacValue());
-
- return ed;
- }
-
- private static STHashAlgorithm.Enum mapHashAlgorithm(HashAlgorithm hashAlgo) {
- STHashAlgorithm.Enum xmlHashAlgo = STHashAlgorithm.Enum.forString(hashAlgo.ecmaString);
- if (xmlHashAlgo == null) {
- throw new EncryptedDocumentException("HashAlgorithm "+hashAlgo+" not supported.");
- }
- return xmlHashAlgo;
- }
-
- protected void marshallEncryptionDocument(EncryptionDocument ed, LittleEndianByteArrayOutputStream os) {
- XmlOptions xo = new XmlOptions();
- xo.setCharacterEncoding("UTF-8");
- Map<String,String> nsMap = new HashMap<>();
- nsMap.put(passwordUri.toString(),"p");
- xo.setUseDefaultNamespace();
- xo.setSaveSuggestedPrefixes(nsMap);
- xo.setSaveNamespacesFirst();
- xo.setSaveAggressiveNamespaces();
-
- // setting standalone doesn't work with xmlbeans-2.3 & 2.6
- // ed.documentProperties().setStandalone(true);
- xo.setSaveNoXmlDecl();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try {
- bos.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n".getBytes(StandardCharsets.UTF_8));
- ed.save(bos, xo);
- bos.writeTo(os);
- } catch (IOException e) {
- throw new EncryptedDocumentException("error marshalling encryption info document", e);
- }
- }
-
- /**
- * 2.3.4.15 Data Encryption (Agile Encryption)
- *
- * The EncryptedPackage stream (1) MUST be encrypted in 4096-byte segments to facilitate nearly
- * random access while allowing CBC modes to be used in the encryption process.
- * The initialization vector for the encryption process MUST be obtained by using the zero-based
- * segment number as a blockKey and the binary form of the KeyData.saltValue as specified in
- * section 2.3.4.12. The block number MUST be represented as a 32-bit unsigned integer.
- * Data blocks MUST then be encrypted by using the initialization vector and the intermediate key
- * obtained by decrypting the encryptedKeyValue from a KeyEncryptor contained within the
- * KeyEncryptors sequence as specified in section 2.3.4.10. The final data block MUST be padded to
- * the next integral multiple of the KeyData.blockSize value. Any padding bytes can be used. Note
- * that the StreamSize field of the EncryptedPackage field specifies the number of bytes of
- * unencrypted data as specified in section 2.3.4.4.
- */
- private class AgileCipherOutputStream extends ChunkedCipherOutputStream {
- public AgileCipherOutputStream(DirectoryNode dir) throws IOException, GeneralSecurityException {
- super(dir, 4096);
- }
-
- @Override
- protected Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk)
- throws GeneralSecurityException {
- return AgileDecryptor.initCipherForBlock(existing, block, lastChunk, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE);
- }
-
- @Override
- protected void calculateChecksum(File fileOut, int oleStreamSize)
- throws GeneralSecurityException, IOException {
- // integrityHMAC needs to be updated before the encryption document is created
- updateIntegrityHMAC(fileOut, oleStreamSize);
- }
-
- @Override
- protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile)
- throws IOException {
- DataSpaceMapUtils.addDefaultDataSpace(dir);
- createEncryptionEntry(dir, "EncryptionInfo", this::marshallEncryptionRecord);
- }
-
- private void marshallEncryptionRecord(LittleEndianByteArrayOutputStream bos) {
- final EncryptionInfo info = getEncryptionInfo();
-
- // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where
- // Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004
- bos.writeShort(info.getVersionMajor());
- bos.writeShort(info.getVersionMinor());
- // Reserved (4 bytes): A value that MUST be 0x00000040
- bos.writeInt(info.getEncryptionFlags());
-
- EncryptionDocument ed = createEncryptionDocument();
- marshallEncryptionDocument(ed, bos);
- }
- }
-
- @Override
- public AgileEncryptor copy() {
- return new AgileEncryptor(this);
- }
-}
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.openxml4j.opc.ZipPackage;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
+import org.apache.poi.poifs.filesystem.FileMagic;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookProvider;
+import org.apache.poi.util.Internal;
-public class XSSFWorkbookFactory extends WorkbookFactory {
+@Internal
+public class XSSFWorkbookFactory implements WorkbookProvider {
- static {
- init();
- }
-
- public static void init() {
- WorkbookFactory.createXssfFromScratch = XSSFWorkbookFactory::createWorkbook;
- WorkbookFactory.createXssfByStream = XSSFWorkbookFactory::createWorkbook;
- WorkbookFactory.createXssfByPackage = o -> XSSFWorkbookFactory.createWorkbook((OPCPackage)o);
- WorkbookFactory.createXssfByFile = XSSFWorkbookFactory::createWorkbook;
+ @Override
+ public boolean accepts(FileMagic fm) {
+ return fm == FileMagic.OOXML;
}
/**
*
* @return The created workbook
*/
- public static XSSFWorkbook createWorkbook() {
+ @Override
+ public XSSFWorkbook create() {
return new XSSFWorkbook();
}
- /**
- * Creates a XSSFWorkbook from the given OOXML Package.
- * This is a convenience method to go along the create-methods of the super class.
- *
- * <p>Note that in order to properly release resources the
- * Workbook should be closed after use.</p>
- *
- * @param pkg The {@link OPCPackage} opened for reading data.
- *
- * @return The created Workbook
- *
- * @throws IOException if an error occurs while reading the data
- */
- public static XSSFWorkbook create(OPCPackage pkg) throws IOException {
- return createWorkbook(pkg);
+ @Override
+ public XSSFWorkbook create(DirectoryNode root, String password) throws IOException {
+ try (InputStream stream = DocumentFactoryHelper.getDecryptedStream(root, password)) {
+ return create(stream);
+ } finally {
+ // as we processed the full stream already, we can close the filesystem here
+ // otherwise file handles are leaked
+ root.getFileSystem().close();
+ }
+ }
+
+ @Override
+ public Workbook create(InputStream inp, String password) throws IOException {
+ InputStream bufInp = FileMagic.prepareToCheckMagic(inp);
+ FileMagic fm = FileMagic.valueOf(bufInp);
+
+ if (fm == FileMagic.OLE2) {
+ try (POIFSFileSystem poifs = new POIFSFileSystem(bufInp);
+ InputStream stream = DocumentFactoryHelper.getDecryptedStream(poifs.getRoot(), password)) {
+ return create(stream);
+ }
+ }
+
+ if (fm == FileMagic.OOXML) {
+ return create(bufInp);
+ }
+
+ return null;
}
/**
- * Creates a XSSFWorkbook from the given OOXML Package
+ * Creates a XSSFWorkbook from the given InputStream
*
* <p>Note that in order to properly release resources the
- * Workbook should be closed after use.</p>
+ * Workbook should be closed after use.</p>
*
- * @param pkg The {@link ZipPackage} opened for reading data.
+ * @param stream The {@link InputStream} to read data from.
*
- * @return The created Workbook
+ * @return The created Workbook
*
- * @throws IOException if an error occurs while reading the data
+ * @throws IOException if an error occurs while reading the data
*/
- public static XSSFWorkbook createWorkbook(ZipPackage pkg) throws IOException {
- return createWorkbook((OPCPackage)pkg);
+ @SuppressWarnings("resource")
+ @Override
+ public XSSFWorkbook create(InputStream stream) throws IOException {
+ try {
+ OPCPackage pkg = OPCPackage.open(stream);
+ return createWorkbook(pkg);
+ } catch (InvalidFormatException e) {
+ throw new IOException(e);
+ }
}
/**
* @throws EncryptedDocumentException If the wrong password is given for a protected file
*/
@SuppressWarnings("resource")
- public static XSSFWorkbook createWorkbook(File file, boolean readOnly) throws IOException {
- try {
- OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
- return createWorkbook(pkg);
- } catch (InvalidFormatException e) {
- throw new IOException(e);
+ public XSSFWorkbook create(File file, String password, boolean readOnly) throws IOException {
+ FileMagic fm = FileMagic.valueOf(file);
+
+ if (fm == FileMagic.OLE2) {
+ try (POIFSFileSystem poifs = new POIFSFileSystem(file, true);
+ InputStream stream = DocumentFactoryHelper.getDecryptedStream(poifs.getRoot(), password)) {
+ return create(stream);
+ }
}
- }
- /**
- * Creates a XSSFWorkbook from the given InputStream
- *
- * <p>Note that in order to properly release resources the
- * Workbook should be closed after use.</p>
- *
- * @param stream The {@link InputStream} to read data from.
- *
- * @return The created Workbook
- *
- * @throws IOException if an error occurs while reading the data
- */
- @SuppressWarnings("resource")
- public static XSSFWorkbook createWorkbook(InputStream stream) throws IOException {
try {
- OPCPackage pkg = OPCPackage.open(stream);
+ OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
return createWorkbook(pkg);
} catch (InvalidFormatException e) {
throw new IOException(e);
+++ /dev/null
-/* ====================================================================
- 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;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
-import org.apache.poi.poifs.filesystem.FileMagic;
-import org.apache.poi.util.IOUtils;
-import org.junit.Test;
-
-/**
- * Class to test that HXF correctly detects OOXML
- * documents
- */
-@SuppressWarnings("deprecation")
-public class TestDetectAsOOXML {
- @Test
- public void testOpensProperly() throws IOException, InvalidFormatException {
- OPCPackage.open(HSSFTestDataSamples.openSampleFileStream("sample.xlsx")).close();
- }
-
- @Test
- public void testDetectAsPOIFS() throws IOException {
- Object[][] fileAndMagic = {
- {"SampleSS.xlsx", FileMagic.OOXML},
- {"SampleSS.xls", FileMagic.OLE2},
- {"SampleSS.txt", FileMagic.UNKNOWN}
- };
-
- for (Object[] fm : fileAndMagic) {
- InputStream is = HSSFTestDataSamples.openSampleFileStream((String)fm[0]);
- is = FileMagic.prepareToCheckMagic(is);
- FileMagic act = FileMagic.valueOf(is);
-
- assertEquals("OOXML files should be detected, others not",
- act == FileMagic.OOXML, DocumentFactoryHelper.hasOOXMLHeader(is));
-
- assertEquals("file magic failed for "+fm[0], fm[1], act);
- is.close();
- }
- }
-
- @Test
- public void testFileCorruption() throws Exception {
- // create test InputStream
- byte[] testData = { 1, 2, 3 };
- ByteArrayInputStream testInput = new ByteArrayInputStream(testData);
- InputStream is = FileMagic.prepareToCheckMagic(testInput);
-
- // detect header
- assertFalse(DocumentFactoryHelper.hasOOXMLHeader(is));
-
- // check if InputStream is still intact
- byte[] act = IOUtils.toByteArray(is);
- assertArrayEquals(testData, act);
- assertEquals(-1, is.read());
- is.close();
- }
-}
+++ /dev/null
-
-/* ====================================================================
- 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.poi.ooxml.POIXMLDocument;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.xslf.usermodel.XSLFSlideShow;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.junit.Test;
-
-/**
- * Class to test that we handle embeded bits in OOXML files properly
- */
-public class TestEmbedded {
- @Test
- public void testExcel() throws Exception {
- POIXMLDocument doc = new XSSFWorkbook(
- POIDataSamples.getSpreadSheetInstance().openResourceAsStream("ExcelWithAttachments.xlsm")
- );
- test(doc, 4);
- }
-
- @Test
- public void testWord() throws Exception {
- POIXMLDocument doc = new XWPFDocument(
- POIDataSamples.getDocumentInstance().openResourceAsStream("WordWithAttachments.docx")
- );
- test(doc, 5);
- }
-
- @Test
- public void testPowerPoint() throws Exception {
- POIXMLDocument doc = new XSLFSlideShow(OPCPackage.open(
- POIDataSamples.getSlideShowInstance().openResourceAsStream("PPTWithAttachments.pptm"))
- );
- test(doc, 4);
- }
-
- private void test(POIXMLDocument doc, int expectedCount) throws Exception {
- assertNotNull(doc.getAllEmbeddedParts());
- assertEquals(expectedCount, doc.getAllEmbeddedParts().size());
-
- for(int i=0; i<doc.getAllEmbeddedParts().size(); i++) {
- PackagePart pp = doc.getAllEmbeddedParts().get(i);
- assertNotNull(pp);
-
- byte[] b = IOUtils.toByteArray(pp.getInputStream());
- assertTrue(b.length > 0);
- }
-
- doc.close();
- }
-}
+++ /dev/null
-/* ====================================================================
- 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;
-
-import static org.apache.poi.POITestCase.assertContains;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.poi.ooxml.extractor.POIXMLPropertiesTextExtractor;
-import org.apache.poi.ooxml.util.PackageHelper;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.xslf.usermodel.XSLFSlideShow;
-import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.Test;
-
-public final class TestXMLPropertiesTextExtractor {
- private static final POIDataSamples _ssSamples = POIDataSamples.getSpreadSheetInstance();
- private static final POIDataSamples _slSamples = POIDataSamples.getSlideShowInstance();
-
- @Test
- public void testGetFromMainExtractor() throws Exception {
- OPCPackage pkg = PackageHelper.open(_ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm"));
-
- XSSFWorkbook wb = new XSSFWorkbook(pkg);
-
- XSSFExcelExtractor ext = new XSSFExcelExtractor(wb);
- POIXMLPropertiesTextExtractor textExt = ext.getMetadataTextExtractor();
-
- // Check basics
- assertNotNull(textExt);
- assertTrue(textExt.getText().length() > 0);
-
- // Check some of the content
- String text = textExt.getText();
- String cText = textExt.getCorePropertiesText();
-
- assertContains(text, "LastModifiedBy = Yury Batrakov");
- assertContains(cText, "LastModifiedBy = Yury Batrakov");
-
- textExt.close();
- ext.close();
- }
-
- @Test
- public void testCore() throws Exception {
- OPCPackage pkg = PackageHelper.open(
- _ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm")
- );
- XSSFWorkbook wb = new XSSFWorkbook(pkg);
-
- POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb);
- ext.getText();
-
- // Now check
- String text = ext.getText();
- String cText = ext.getCorePropertiesText();
-
- assertContains(text, "LastModifiedBy = Yury Batrakov");
- assertContains(cText, "LastModifiedBy = Yury Batrakov");
-
- ext.close();
- }
-
- @Test
- public void testExtended() throws Exception {
- OPCPackage pkg = OPCPackage.open(
- _ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm")
- );
- XSSFWorkbook wb = new XSSFWorkbook(pkg);
-
- POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb);
- ext.getText();
-
- // Now check
- String text = ext.getText();
- String eText = ext.getExtendedPropertiesText();
-
- assertContains(text, "Application = Microsoft Excel");
- assertContains(text, "Company = Mera");
- assertContains(eText, "Application = Microsoft Excel");
- assertContains(eText, "Company = Mera");
-
- ext.close();
- }
-
- @Test
- public void testCustom() throws Exception {
- OPCPackage pkg = OPCPackage.open(
- _ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm")
- );
- XSSFWorkbook wb = new XSSFWorkbook(pkg);
-
- POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb);
- ext.getText();
-
- // Now check
- String text = ext.getText();
- String cText = ext.getCustomPropertiesText();
-
- assertContains(text, "description = another value");
- assertContains(cText, "description = another value");
-
- ext.close();
- }
-
- /**
- * Bug #49386 - some properties, especially
- * dates can be null
- */
- @Test
- public void testWithSomeNulls() throws Exception {
- OPCPackage pkg = OPCPackage.open(
- _slSamples.openResourceAsStream("49386-null_dates.pptx")
- );
- XSLFSlideShow sl = new XSLFSlideShow(pkg);
-
- POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(sl);
- ext.getText();
-
- String text = ext.getText();
- assertFalse(text.contains("Created =")); // With date is null
- assertContains(text, "CreatedString = "); // Via string is blank
- assertContains(text, "LastModifiedBy = IT Client Services");
-
- ext.close();
- }
-}
--- /dev/null
+/* ====================================================================
+ 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.ooxml;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
+import org.apache.poi.poifs.filesystem.FileMagic;
+import org.apache.poi.util.IOUtils;
+import org.junit.Test;
+
+/**
+ * Class to test that HXF correctly detects OOXML
+ * documents
+ */
+@SuppressWarnings("deprecation")
+public class TestDetectAsOOXML {
+ @Test
+ public void testOpensProperly() throws IOException, InvalidFormatException {
+ OPCPackage.open(HSSFTestDataSamples.openSampleFileStream("sample.xlsx")).close();
+ }
+
+ @Test
+ public void testDetectAsPOIFS() throws IOException {
+ Object[][] fileAndMagic = {
+ {"SampleSS.xlsx", FileMagic.OOXML},
+ {"SampleSS.xls", FileMagic.OLE2},
+ {"SampleSS.txt", FileMagic.UNKNOWN}
+ };
+
+ for (Object[] fm : fileAndMagic) {
+ InputStream is = HSSFTestDataSamples.openSampleFileStream((String)fm[0]);
+ is = FileMagic.prepareToCheckMagic(is);
+ FileMagic act = FileMagic.valueOf(is);
+
+ assertEquals("OOXML files should be detected, others not",
+ act == FileMagic.OOXML, DocumentFactoryHelper.hasOOXMLHeader(is));
+
+ assertEquals("file magic failed for "+fm[0], fm[1], act);
+ is.close();
+ }
+ }
+
+ @Test
+ public void testFileCorruption() throws Exception {
+ // create test InputStream
+ byte[] testData = { 1, 2, 3 };
+ ByteArrayInputStream testInput = new ByteArrayInputStream(testData);
+ InputStream is = FileMagic.prepareToCheckMagic(testInput);
+
+ // detect header
+ assertFalse(DocumentFactoryHelper.hasOOXMLHeader(is));
+
+ // check if InputStream is still intact
+ byte[] act = IOUtils.toByteArray(is);
+ assertArrayEquals(testData, act);
+ assertEquals(-1, is.read());
+ is.close();
+ }
+}
--- /dev/null
+
+/* ====================================================================
+ 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.ooxml;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xslf.usermodel.XSLFSlideShow;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.junit.Test;
+
+/**
+ * Class to test that we handle embeded bits in OOXML files properly
+ */
+public class TestEmbedded {
+ @Test
+ public void testExcel() throws Exception {
+ POIXMLDocument doc = new XSSFWorkbook(
+ POIDataSamples.getSpreadSheetInstance().openResourceAsStream("ExcelWithAttachments.xlsm")
+ );
+ test(doc, 4);
+ }
+
+ @Test
+ public void testWord() throws Exception {
+ POIXMLDocument doc = new XWPFDocument(
+ POIDataSamples.getDocumentInstance().openResourceAsStream("WordWithAttachments.docx")
+ );
+ test(doc, 5);
+ }
+
+ @Test
+ public void testPowerPoint() throws Exception {
+ POIXMLDocument doc = new XSLFSlideShow(OPCPackage.open(
+ POIDataSamples.getSlideShowInstance().openResourceAsStream("PPTWithAttachments.pptm"))
+ );
+ test(doc, 4);
+ }
+
+ private void test(POIXMLDocument doc, int expectedCount) throws Exception {
+ assertNotNull(doc.getAllEmbeddedParts());
+ assertEquals(expectedCount, doc.getAllEmbeddedParts().size());
+
+ for(int i=0; i<doc.getAllEmbeddedParts().size(); i++) {
+ PackagePart pp = doc.getAllEmbeddedParts().get(i);
+ assertNotNull(pp);
+
+ byte[] b = IOUtils.toByteArray(pp.getInputStream());
+ assertTrue(b.length > 0);
+ }
+
+ doc.close();
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ooxml;
+
+import static org.apache.poi.POITestCase.assertContains;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.ooxml.extractor.POIXMLPropertiesTextExtractor;
+import org.apache.poi.ooxml.util.PackageHelper;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.xslf.usermodel.XSLFSlideShow;
+import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+
+public final class TestXMLPropertiesTextExtractor {
+ private static final POIDataSamples _ssSamples = POIDataSamples.getSpreadSheetInstance();
+ private static final POIDataSamples _slSamples = POIDataSamples.getSlideShowInstance();
+
+ @Test
+ public void testGetFromMainExtractor() throws Exception {
+ OPCPackage pkg = PackageHelper.open(_ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm"));
+
+ XSSFWorkbook wb = new XSSFWorkbook(pkg);
+
+ XSSFExcelExtractor ext = new XSSFExcelExtractor(wb);
+ POIXMLPropertiesTextExtractor textExt = ext.getMetadataTextExtractor();
+
+ // Check basics
+ assertNotNull(textExt);
+ assertTrue(textExt.getText().length() > 0);
+
+ // Check some of the content
+ String text = textExt.getText();
+ String cText = textExt.getCorePropertiesText();
+
+ assertContains(text, "LastModifiedBy = Yury Batrakov");
+ assertContains(cText, "LastModifiedBy = Yury Batrakov");
+
+ textExt.close();
+ ext.close();
+ }
+
+ @Test
+ public void testCore() throws Exception {
+ OPCPackage pkg = PackageHelper.open(
+ _ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm")
+ );
+ XSSFWorkbook wb = new XSSFWorkbook(pkg);
+
+ POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb);
+ ext.getText();
+
+ // Now check
+ String text = ext.getText();
+ String cText = ext.getCorePropertiesText();
+
+ assertContains(text, "LastModifiedBy = Yury Batrakov");
+ assertContains(cText, "LastModifiedBy = Yury Batrakov");
+
+ ext.close();
+ }
+
+ @Test
+ public void testExtended() throws Exception {
+ OPCPackage pkg = OPCPackage.open(
+ _ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm")
+ );
+ XSSFWorkbook wb = new XSSFWorkbook(pkg);
+
+ POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb);
+ ext.getText();
+
+ // Now check
+ String text = ext.getText();
+ String eText = ext.getExtendedPropertiesText();
+
+ assertContains(text, "Application = Microsoft Excel");
+ assertContains(text, "Company = Mera");
+ assertContains(eText, "Application = Microsoft Excel");
+ assertContains(eText, "Company = Mera");
+
+ ext.close();
+ }
+
+ @Test
+ public void testCustom() throws Exception {
+ OPCPackage pkg = OPCPackage.open(
+ _ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm")
+ );
+ XSSFWorkbook wb = new XSSFWorkbook(pkg);
+
+ POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb);
+ ext.getText();
+
+ // Now check
+ String text = ext.getText();
+ String cText = ext.getCustomPropertiesText();
+
+ assertContains(text, "description = another value");
+ assertContains(cText, "description = another value");
+
+ ext.close();
+ }
+
+ /**
+ * Bug #49386 - some properties, especially
+ * dates can be null
+ */
+ @Test
+ public void testWithSomeNulls() throws Exception {
+ OPCPackage pkg = OPCPackage.open(
+ _slSamples.openResourceAsStream("49386-null_dates.pptx")
+ );
+ XSLFSlideShow sl = new XSLFSlideShow(pkg);
+
+ POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(sl);
+ ext.getText();
+
+ String text = ext.getText();
+ assertFalse(text.contains("Created =")); // With date is null
+ assertContains(text, "CreatedString = "); // Via string is blank
+ assertContains(text, "LastModifiedBy = IT Client Services");
+
+ ext.close();
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ooxml.lite;
+
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.Instrumentation;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.security.ProtectionDomain;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+/**
+ * OOXMLLiteAgent is the replacement for the former OOXMLLite, because in Java 12
+ * it isn't possible to access the privates :) of the ClassLoader
+ */
+public class OOXMLLiteAgent {
+
+ static class LoggingTransformer implements ClassFileTransformer {
+ final Path path;
+ final Pattern includes;
+ final Set<Integer> fileHashes = new HashSet<>();
+
+ public LoggingTransformer(String agentArgs) {
+ String[] args = (agentArgs == null ? "" : agentArgs).split("\\|", 2);
+ path = Paths.get(args.length >= 1 ? args[0] : "ooxml-lite.out");
+ includes = Pattern.compile(args.length >= 2 ? args[1] : ".*/schemas/.*");
+
+ try {
+ if (Files.exists(path)) {
+ try (Stream<String> stream = Files.lines(path)) {
+ stream.forEach((s) -> fileHashes.add(s.hashCode()));
+ }
+ } else {
+ Files.createFile(path);
+ }
+ } catch (IOException ignored) {
+ }
+ }
+
+ public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) {
+ if (path != null && className != null && !fileHashes.contains(className.hashCode()) && includes.matcher(className).find()) {
+ try {
+ // TODO: check if this is atomic ... as transform() is probably called synchronized, it doesn't matter anyway
+ Files.write(path, (className+"\n").getBytes(StandardCharsets.ISO_8859_1), StandardOpenOption.APPEND);
+ fileHashes.add(className.hashCode());
+ } catch (IOException ignroed) {
+ }
+ }
+ return bytes;
+ }
+ }
+
+ public static void premain(String agentArgs, Instrumentation inst) {
+ inst.addTransformer(new LoggingTransformer(agentArgs));
+ }
+}
+++ /dev/null
-/* ====================================================================
- 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.ooxml.util;
-
-import java.io.IOException;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.Instrumentation;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.security.ProtectionDomain;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-
-/**
- * OOXMLLiteAgent is the replacement for the former OOXMLLite, because in Java 12
- * it isn't possible to access the privates :) of the ClassLoader
- */
-public class OOXMLLiteAgent {
-
- static class LoggingTransformer implements ClassFileTransformer {
- final Path path;
- final Pattern includes;
- final Set<Integer> fileHashes = new HashSet<>();
-
- public LoggingTransformer(String agentArgs) {
- String[] args = (agentArgs == null ? "" : agentArgs).split("\\|", 2);
- path = Paths.get(args.length >= 1 ? args[0] : "ooxml-lite.out");
- includes = Pattern.compile(args.length >= 2 ? args[1] : ".*/schemas/.*");
-
- try {
- if (Files.exists(path)) {
- try (Stream<String> stream = Files.lines(path)) {
- stream.forEach((s) -> fileHashes.add(s.hashCode()));
- }
- } else {
- Files.createFile(path);
- }
- } catch (IOException ignored) {
- }
- }
-
- public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) {
- if (path != null && className != null && !fileHashes.contains(className.hashCode()) && includes.matcher(className).find()) {
- try {
- // TODO: check if this is atomic ... as transform() is probably called synchronized, it doesn't matter anyway
- Files.write(path, (className+"\n").getBytes(StandardCharsets.ISO_8859_1), StandardOpenOption.APPEND);
- fileHashes.add(className.hashCode());
- } catch (IOException ignroed) {
- }
- }
- return bytes;
- }
- }
-
- public static void premain(String agentArgs, Instrumentation inst) {
- inst.addTransformer(new LoggingTransformer(agentArgs));
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-
-/**
- * Tests for org.apache.poi.poifs.crypt
- */
-@RunWith(Suite.class)
-@Suite.SuiteClasses({
- TestEncryptionInfo.class
- , TestDecryptor.class
- , TestEncryptor.class
- , TestAgileEncryptionParameters.class
-})
-public final class AllPOIFSCryptoTests {
-}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.crypto.Cipher;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.util.IOUtils;
-import org.junit.Assume;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TestAgileEncryptionParameters {
-
- static byte[] testData;
-
- @Parameter(value = 0)
- public CipherAlgorithm ca;
- @Parameter(value = 1)
- public HashAlgorithm ha;
- @Parameter(value = 2)
- public ChainingMode cm;
-
- @Parameters(name="{0} {1} {2}")
- public static Collection<Object[]> data() {
- CipherAlgorithm[] caList = {CipherAlgorithm.aes128, CipherAlgorithm.aes192, CipherAlgorithm.aes256, CipherAlgorithm.rc2, CipherAlgorithm.des, CipherAlgorithm.des3};
- HashAlgorithm[] haList = {HashAlgorithm.sha1, HashAlgorithm.sha256, HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.md5};
- ChainingMode[] cmList = {ChainingMode.cbc, ChainingMode.cfb};
-
- List<Object[]> data = new ArrayList<>();
- for (CipherAlgorithm ca : caList) {
- for (HashAlgorithm ha : haList) {
- for (ChainingMode cm : cmList) {
- data.add(new Object[]{ca,ha,cm});
- }
- }
- }
-
- return data;
- }
-
- @BeforeClass
- public static void initTestData() throws Exception {
- InputStream testFile = POIDataSamples.getDocumentInstance().openResourceAsStream("SampleDoc.docx");
- testData = IOUtils.toByteArray(testFile);
- testFile.close();
- }
-
- @Test
- public void testAgileEncryptionModes() throws Exception {
- int maxKeyLen = Cipher.getMaxAllowedKeyLength(ca.jceId);
- Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files", maxKeyLen >= ca.defaultKeySize);
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
- POIFSFileSystem fsEnc = new POIFSFileSystem();
- EncryptionInfo infoEnc = new EncryptionInfo(EncryptionMode.agile, ca, ha, -1, -1, cm);
- Encryptor enc = infoEnc.getEncryptor();
- enc.confirmPassword("foobaa");
- OutputStream os = enc.getDataStream(fsEnc);
- os.write(testData);
- os.close();
- bos.reset();
- fsEnc.writeFilesystem(bos);
- fsEnc.close();
-
- POIFSFileSystem fsDec = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
- EncryptionInfo infoDec = new EncryptionInfo(fsDec);
- Decryptor dec = infoDec.getDecryptor();
- boolean passed = dec.verifyPassword("foobaa");
- assertTrue(passed);
- InputStream is = dec.getDataStream(fsDec);
- byte[] actualData = IOUtils.toByteArray(is);
- is.close();
- fsDec.close();
- assertArrayEquals("Failed roundtrip - "+ca+"-"+ha+"-"+cm, testData, actualData);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.GeneralSecurityException;
-import java.util.stream.IntStream;
-
-import javax.crypto.Cipher;
-
-import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
-import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.util.IOUtils;
-import org.junit.Assume;
-import org.junit.Test;
-
-public class TestDecryptor {
- private static final POIDataSamples samples = POIDataSamples.getPOIFSInstance();
-
- @Test
- public void passwordVerification() throws IOException, GeneralSecurityException {
- try (InputStream is = samples.openResourceAsStream("protect.xlsx");
- POIFSFileSystem fs = new POIFSFileSystem(is)) {
- EncryptionInfo info = new EncryptionInfo(fs);
- Decryptor d = Decryptor.getInstance(info);
- assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
- }
- }
-
- @Test
- public void decrypt() throws IOException, GeneralSecurityException {
- try (InputStream is = samples.openResourceAsStream("protect.xlsx");
- POIFSFileSystem fs = new POIFSFileSystem(is)) {
- EncryptionInfo info = new EncryptionInfo(fs);
- Decryptor d = Decryptor.getInstance(info);
- d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
- zipOk(fs.getRoot(), d);
- }
- }
-
- @Test
- public void agile() throws IOException, GeneralSecurityException {
- try (InputStream is = samples.openResourceAsStream("protected_agile.docx");
- POIFSFileSystem fs = new POIFSFileSystem(is)) {
- EncryptionInfo info = new EncryptionInfo(fs);
- assertTrue(info.getVersionMajor() == 4 && info.getVersionMinor() == 4);
- Decryptor d = Decryptor.getInstance(info);
- assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
- zipOk(fs.getRoot(), d);
- }
- }
-
- private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException {
- try (ZipArchiveInputStream zin = new ZipArchiveInputStream(d.getDataStream(root))) {
-
- while (true) {
- ZipArchiveEntry entry = zin.getNextZipEntry();
- if (entry == null) {
- break;
- }
- // crc32 is checked within zip-stream
- if (entry.isDirectory()) {
- continue;
- }
- assertEquals(entry.getSize() - 1, zin.skip(entry.getSize() - 1));
- byte[] buf = new byte[10];
- int readBytes = zin.read(buf);
- // zin.available() doesn't work for entries
- assertEquals("size failed for " + entry.getName(), 1, readBytes);
- }
- }
- }
-
- @Test
- public void dataLength() throws Exception {
- try (InputStream fsIs = samples.openResourceAsStream("protected_agile.docx");
- POIFSFileSystem fs = new POIFSFileSystem(fsIs)) {
- EncryptionInfo info = new EncryptionInfo(fs);
- Decryptor d = Decryptor.getInstance(info);
- d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
-
- try (InputStream is = d.getDataStream(fs)) {
-
- long len = d.getLength();
- assertEquals(12810, len);
-
- byte[] buf = new byte[(int) len];
- assertEquals(12810, is.read(buf));
-
- ZipArchiveInputStream zin = new ZipArchiveInputStream(new ByteArrayInputStream(buf));
-
- while (true) {
- ZipArchiveEntry entry = zin.getNextZipEntry();
- if (entry==null) {
- break;
- }
-
- IOUtils.toByteArray(zin);
- }
- }
- }
- }
-
- @Test
- public void bug57080() throws Exception {
- // the test file contains a wrong ole entry size, produced by extenxls
- // the fix limits the available size and tries to read all entries
- File f = samples.getFile("extenxls_pwd123.xlsx");
-
- try (POIFSFileSystem fs = new POIFSFileSystem(f, true)) {
- EncryptionInfo info = new EncryptionInfo(fs);
- Decryptor d = Decryptor.getInstance(info);
- d.verifyPassword("pwd123");
-
- final ByteArrayOutputStream bos = new ByteArrayOutputStream(10000);
- try (final ZipArchiveInputStream zis = new ZipArchiveInputStream(d.getDataStream(fs))) {
- IntStream.of(3711, 1155, 445, 9376, 450, 588, 1337, 2593, 304, 7910).forEach(size -> {
- try {
- final ZipArchiveEntry ze = zis.getNextZipEntry();
- assertNotNull(ze);
- IOUtils.copy(zis, bos);
- assertEquals(size, bos.size());
- bos.reset();
- } catch (IOException e) {
- fail(e.getMessage());
- }
- });
- }
- }
- }
-
- @Test
- public void test58616() throws IOException, GeneralSecurityException {
- try (InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("58616.xlsx");
- POIFSFileSystem pfs = new POIFSFileSystem(is)) {
- EncryptionInfo info = new EncryptionInfo(pfs);
- Decryptor dec = Decryptor.getInstance(info);
- dec.getDataStream(pfs).close();
- }
- }
-
- @Test
- public void bug60320() throws IOException, GeneralSecurityException {
- int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
- Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647);
-
- try (InputStream is = samples.openResourceAsStream("60320-protected.xlsx");
- POIFSFileSystem fs = new POIFSFileSystem(is)) {
- EncryptionInfo info = new EncryptionInfo(fs);
- Decryptor d = Decryptor.getInstance(info);
- assertTrue(d.verifyPassword("Test001!!"));
- zipOk(fs.getRoot(), d);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.junit.Test;
-
-public class TestEncryptionInfo {
- @Test
- public void testEncryptionInfo() throws IOException {
- POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx"));
-
- EncryptionInfo info = new EncryptionInfo(fs);
-
- assertEquals(3, info.getVersionMajor());
- assertEquals(2, info.getVersionMinor());
-
- assertEquals(CipherAlgorithm.aes128, info.getHeader().getCipherAlgorithm());
- assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithm());
- assertEquals(128, info.getHeader().getKeySize());
- assertEquals(32, info.getVerifier().getEncryptedVerifierHash().length);
- assertEquals(CipherProvider.aes, info.getHeader().getCipherProvider());
- assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName());
-
- fs.close();
- }
-
- @Test
- public void testEncryptionInfoSHA512() throws Exception {
- POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_sha512.xlsx"));
-
- EncryptionInfo info = new EncryptionInfo(fs);
-
- assertEquals(4, info.getVersionMajor());
- assertEquals(4, info.getVersionMinor());
-
- assertEquals(CipherAlgorithm.aes256, info.getHeader().getCipherAlgorithm());
- assertEquals(HashAlgorithm.sha512, info.getHeader().getHashAlgorithm());
- assertEquals(256, info.getHeader().getKeySize());
- assertEquals(64, info.getVerifier().getEncryptedVerifierHash().length);
- assertEquals(CipherProvider.aes, info.getHeader().getCipherProvider());
-// assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName());
-
- fs.close();
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt;
-
-import static org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.DigestInputStream;
-import java.security.GeneralSecurityException;
-import java.security.MessageDigest;
-import java.util.Iterator;
-import java.util.Random;
-
-import javax.crypto.Cipher;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.openxml4j.opc.ContentTypes;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.poifs.crypt.agile.AgileDecryptor;
-import org.apache.poi.poifs.crypt.agile.AgileEncryptionHeader;
-import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier;
-import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.poifs.filesystem.DocumentEntry;
-import org.apache.poi.poifs.filesystem.DocumentNode;
-import org.apache.poi.poifs.filesystem.Entry;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.poifs.filesystem.TempFilePOIFSFileSystem;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.NullOutputStream;
-import org.apache.poi.util.TempFile;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.junit.Assume;
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class TestEncryptor {
- @Test
- public void binaryRC4Encryption() throws Exception {
- // please contribute a real sample file, which is binary rc4 encrypted
- // ... at least the output can be opened in Excel Viewer
- String password = "pass";
-
- final byte[] payloadExpected;
- try (InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleMultiCell.xlsx")) {
- payloadExpected = IOUtils.toByteArray(is);
- }
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try (POIFSFileSystem fs = new POIFSFileSystem()) {
- EncryptionInfo ei = new EncryptionInfo(EncryptionMode.binaryRC4);
- Encryptor enc = ei.getEncryptor();
- enc.confirmPassword(password);
-
- try (OutputStream os = enc.getDataStream(fs.getRoot())) {
- os.write(payloadExpected);
- }
-
- fs.writeFilesystem(bos);
- }
-
- final byte[] payloadActual;
- try (POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
- EncryptionInfo ei = new EncryptionInfo(fs);
- Decryptor dec = ei.getDecryptor();
- boolean b = dec.verifyPassword(password);
- assertTrue(b);
-
- try (InputStream is = dec.getDataStream(fs.getRoot())) {
- payloadActual = IOUtils.toByteArray(is);
- }
- }
-
- assertArrayEquals(payloadExpected, payloadActual);
- }
-
- @Test
- public void tempFileAgileEncryption() throws Exception {
- String password = "pass";
-
- final byte[] payloadExpected;
- try (InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleMultiCell.xlsx")) {
- payloadExpected = IOUtils.toByteArray(is);
- }
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try (POIFSFileSystem fs = new TempFilePOIFSFileSystem()) {
- EncryptionInfo ei = new EncryptionInfo(EncryptionMode.agile);
- Encryptor enc = ei.getEncryptor();
- enc.confirmPassword(password);
-
- try (OutputStream os = enc.getDataStream(fs.getRoot())) {
- os.write(payloadExpected);
- }
-
- fs.writeFilesystem(bos);
- }
-
- final byte[] payloadActual;
- try (POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
- EncryptionInfo ei = new EncryptionInfo(fs);
- Decryptor dec = ei.getDecryptor();
- boolean b = dec.verifyPassword(password);
- assertTrue(b);
-
- try (InputStream is = dec.getDataStream(fs.getRoot())) {
- payloadActual = IOUtils.toByteArray(is);
- }
- }
-
- assertArrayEquals(payloadExpected, payloadActual);
- }
-
- @Test
- public void agileEncryption() throws Exception {
- int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
- Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647);
-
- File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-pass.docx");
- String pass = "pass";
-
- final byte[] payloadExpected, encPackExpected;
- final long decPackLenExpected;
- final EncryptionInfo infoExpected;
- final Decryptor decExpected;
-
- try (POIFSFileSystem nfs = new POIFSFileSystem(file, true)) {
-
- // Check the encryption details
- infoExpected = new EncryptionInfo(nfs);
- decExpected = Decryptor.getInstance(infoExpected);
- boolean passed = decExpected.verifyPassword(pass);
- assertTrue("Unable to process: document is encrypted", passed);
-
- // extract the payload
- try (InputStream is = decExpected.getDataStream(nfs)) {
- payloadExpected = IOUtils.toByteArray(is);
- }
-
- decPackLenExpected = decExpected.getLength();
- assertEquals(decPackLenExpected, payloadExpected.length);
-
- final DirectoryNode root = nfs.getRoot();
- final DocumentEntry entry = (DocumentEntry)root.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
- try (InputStream is = root.createDocumentInputStream(entry)) {
- // ignore padding block
- encPackExpected = IOUtils.toByteArray(is, entry.getSize()-16);
- }
- }
-
- // check that same verifier/salt lead to same hashes
- final byte[] verifierSaltExpected = infoExpected.getVerifier().getSalt();
- final byte[] verifierExpected = decExpected.getVerifier();
- final byte[] keySalt = infoExpected.getHeader().getKeySalt();
- final byte[] keySpec = decExpected.getSecretKey().getEncoded();
- final byte[] integritySalt = decExpected.getIntegrityHmacKey();
- // the hmacs of the file always differ, as we use PKCS5-padding to pad the bytes
- // whereas office just uses random bytes
- // byte integrityHash[] = d.getIntegrityHmacValue();
-
- final EncryptionInfo infoActual = new EncryptionInfo(
- EncryptionMode.agile
- , infoExpected.getVerifier().getCipherAlgorithm()
- , infoExpected.getVerifier().getHashAlgorithm()
- , infoExpected.getHeader().getKeySize()
- , infoExpected.getHeader().getBlockSize()
- , infoExpected.getVerifier().getChainingMode()
- );
-
- Encryptor e = Encryptor.getInstance(infoActual);
- e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, integritySalt);
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try (POIFSFileSystem fs = new POIFSFileSystem()) {
- try (OutputStream os = e.getDataStream(fs)) {
- os.write(payloadExpected);
- }
- fs.writeFilesystem(bos);
- }
-
- final EncryptionInfo infoActual2;
- final byte[] payloadActual, encPackActual;
- final long decPackLenActual;
- try (POIFSFileSystem nfs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
- infoActual2 = new EncryptionInfo(nfs.getRoot());
- Decryptor decActual = Decryptor.getInstance(infoActual2);
- boolean passed = decActual.verifyPassword(pass);
- assertTrue("Unable to process: document is encrypted", passed);
-
- // extract the payload
- try (InputStream is = decActual.getDataStream(nfs)) {
- payloadActual = IOUtils.toByteArray(is);
- }
-
- decPackLenActual = decActual.getLength();
-
- final DirectoryNode root = nfs.getRoot();
- final DocumentEntry entry = (DocumentEntry)root.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
- try (InputStream is = root.createDocumentInputStream(entry)) {
- // ignore padding block
- encPackActual = IOUtils.toByteArray(is, entry.getSize()-16);
- }
- }
-
- AgileEncryptionHeader aehExpected = (AgileEncryptionHeader)infoExpected.getHeader();
- AgileEncryptionHeader aehActual = (AgileEncryptionHeader)infoActual.getHeader();
- assertArrayEquals(aehExpected.getEncryptedHmacKey(), aehActual.getEncryptedHmacKey());
- assertEquals(decPackLenExpected, decPackLenActual);
- assertArrayEquals(payloadExpected, payloadActual);
- assertArrayEquals(encPackExpected, encPackActual);
- }
-
- @Test
- public void standardEncryption() throws Exception {
- File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-solrcell.docx");
- final String pass = "solrcell";
-
- final byte[] payloadExpected;
- final EncryptionInfo infoExpected;
- final Decryptor d;
- try (POIFSFileSystem nfs = new POIFSFileSystem(file, true)) {
-
- // Check the encryption details
- infoExpected = new EncryptionInfo(nfs);
- d = Decryptor.getInstance(infoExpected);
- boolean passed = d.verifyPassword(pass);
- assertTrue("Unable to process: document is encrypted", passed);
-
- // extract the payload
- try (InputStream is = d.getDataStream(nfs)) {
- payloadExpected = IOUtils.toByteArray(is);
- }
- }
-
- // check that same verifier/salt lead to same hashes
- final byte[] verifierSaltExpected = infoExpected.getVerifier().getSalt();
- final byte[] verifierExpected = d.getVerifier();
- final byte[] keySpec = d.getSecretKey().getEncoded();
- final byte[] keySalt = infoExpected.getHeader().getKeySalt();
-
-
- final EncryptionInfo infoActual = new EncryptionInfo(
- EncryptionMode.standard
- , infoExpected.getVerifier().getCipherAlgorithm()
- , infoExpected.getVerifier().getHashAlgorithm()
- , infoExpected.getHeader().getKeySize()
- , infoExpected.getHeader().getBlockSize()
- , infoExpected.getVerifier().getChainingMode()
- );
-
- final Encryptor e = Encryptor.getInstance(infoActual);
- e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, null);
-
- assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifier(), infoActual.getVerifier().getEncryptedVerifier());
- assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifierHash(), infoActual.getVerifier().getEncryptedVerifierHash());
-
- // now we use a newly generated salt/verifier and check
- // if the file content is still the same
-
- final byte[] encBytes;
- try (POIFSFileSystem fs = new POIFSFileSystem()) {
-
- final EncryptionInfo infoActual2 = new EncryptionInfo(
- EncryptionMode.standard
- , infoExpected.getVerifier().getCipherAlgorithm()
- , infoExpected.getVerifier().getHashAlgorithm()
- , infoExpected.getHeader().getKeySize()
- , infoExpected.getHeader().getBlockSize()
- , infoExpected.getVerifier().getChainingMode()
- );
-
- final Encryptor e2 = Encryptor.getInstance(infoActual2);
- e2.confirmPassword(pass);
-
- try (OutputStream os = e2.getDataStream(fs)) {
- os.write(payloadExpected);
- }
-
- final ByteArrayOutputStream bos = new ByteArrayOutputStream(50000);
- fs.writeFilesystem(bos);
- encBytes = bos.toByteArray();
- }
-
- final byte[] payloadActual;
- try (POIFSFileSystem nfs = new POIFSFileSystem(new ByteArrayInputStream(encBytes))) {
- final EncryptionInfo ei = new EncryptionInfo(nfs);
- Decryptor d2 = Decryptor.getInstance(ei);
- assertTrue("Unable to process: document is encrypted", d2.verifyPassword(pass));
-
- try (InputStream is = d2.getDataStream(nfs)) {
- payloadActual = IOUtils.toByteArray(is);
- }
- }
-
- assertArrayEquals(payloadExpected, payloadActual);
- }
-
- /**
- * Ensure we can encrypt a package that is missing the Core
- * Properties, eg one from dodgy versions of Jasper Reports
- * See https://github.com/nestoru/xlsxenc/ and
- * http://stackoverflow.com/questions/28593223
- */
- @Test
- public void encryptPackageWithoutCoreProperties() throws Exception {
- // Open our file without core properties
- final byte[] encBytes;
- try (InputStream is = POIDataSamples.getOpenXML4JInstance().openResourceAsStream("OPCCompliance_NoCoreProperties.xlsx");
- OPCPackage pkg = OPCPackage.open(is)) {
-
- // It doesn't have any core properties yet
- assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size());
- assertNotNull(pkg.getPackageProperties());
- assertNotNull(pkg.getPackageProperties().getLanguageProperty());
- assertFalse(pkg.getPackageProperties().getLanguageProperty().isPresent());
-
- // Encrypt it
- EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
- Encryptor enc = info.getEncryptor();
- enc.confirmPassword("password");
-
- try (POIFSFileSystem fs = new POIFSFileSystem()) {
-
- try (OutputStream os = enc.getDataStream(fs)) {
- pkg.save(os);
- }
-
- // Save the resulting OLE2 document, and re-open it
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- fs.writeFilesystem(baos);
- encBytes = baos.toByteArray();
- }
- }
-
-
- try (POIFSFileSystem inpFS = new POIFSFileSystem(new ByteArrayInputStream(encBytes))) {
- // Check we can decrypt it
- EncryptionInfo info = new EncryptionInfo(inpFS);
- Decryptor d = Decryptor.getInstance(info);
- assertTrue(d.verifyPassword("password"));
-
- try (OPCPackage inpPkg = OPCPackage.open(d.getDataStream(inpFS))) {
- // Check it now has empty core properties
- assertEquals(1, inpPkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size());
- assertNotNull(inpPkg.getPackageProperties());
- assertNotNull(inpPkg.getPackageProperties().getLanguageProperty());
- assertFalse(inpPkg.getPackageProperties().getLanguageProperty().isPresent());
-
- }
- }
- }
-
- @Test
- @Ignore
- public void inPlaceRewrite() throws Exception {
- File f = TempFile.createTempFile("protected_agile", ".docx");
-
- try (FileOutputStream fos = new FileOutputStream(f);
- InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx")) {
- IOUtils.copy(fis, fos);
- }
-
- try (POIFSFileSystem fs = new POIFSFileSystem(f, false)) {
-
- // decrypt the protected file - in this case it was encrypted with the default password
- EncryptionInfo encInfo = new EncryptionInfo(fs);
- Decryptor d = encInfo.getDecryptor();
- boolean b = d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
- assertTrue(b);
-
- try (InputStream docIS = d.getDataStream(fs);
- XWPFDocument docx = new XWPFDocument(docIS)) {
-
- // do some strange things with it ;)
- XWPFParagraph p = docx.getParagraphArray(0);
- p.insertNewRun(0).setText("POI was here! All your base are belong to us!");
- p.insertNewRun(1).addBreak();
-
- // and encrypt it again
- Encryptor e = encInfo.getEncryptor();
- e.confirmPassword("AYBABTU");
-
- try (OutputStream os = e.getDataStream(fs)) {
- docx.write(os);
- }
- }
- }
- }
-
-
- private void listEntry(DocumentNode de, String ext, String path) throws IOException {
- path += "\\" + de.getName().replaceAll("[\\p{Cntrl}]", "_");
- System.out.println(ext+": "+path+" ("+de.getSize()+" bytes)");
-
- String name = de.getName().replaceAll("[\\p{Cntrl}]", "_");
-
- InputStream is = ((DirectoryNode)de.getParent()).createDocumentInputStream(de);
- FileOutputStream fos = new FileOutputStream("solr."+name+"."+ext);
- IOUtils.copy(is, fos);
- fos.close();
- is.close();
- }
-
- @SuppressWarnings("unused")
- private void listDir(DirectoryNode dn, String ext, String path) throws IOException {
- path += "\\" + dn.getName().replace('\u0006', '_');
- System.out.println(ext+": "+path+" ("+dn.getStorageClsid()+")");
-
- Iterator<Entry> iter = dn.getEntries();
- while (iter.hasNext()) {
- Entry ent = iter.next();
- if (ent instanceof DirectoryNode) {
- listDir((DirectoryNode)ent, ext, path);
- } else {
- listEntry((DocumentNode)ent, ext, path);
- }
- }
- }
-
- /*
- * this test simulates the generation of bugs 60320 sample file
- * as the padding bytes of the EncryptedPackage stream are random or in POIs case PKCS5-padded
- * one would need to mock those bytes to get the same hmacValues - see diff below
- *
- * this use-case is experimental - for the time being the setters of the encryption classes
- * are spreaded between two packages and are protected - so you would need to violate
- * the packages rules and provide a helper class in the *poifs.crypt package-namespace.
- * the default way of defining the encryption settings is via the EncryptionInfo class
- */
- @Test
- public void bug60320CustomEncrypt() throws Exception {
- int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
- Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647);
-
- // --- src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (revision 1766745)
- // +++ src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (working copy)
- // @@ -208,6 +208,13 @@
- // protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException {
- // byte plain[] = (_plainByteFlags.isEmpty()) ? null : _chunk.clone();
- //
- // + if (posInChunk < 4096) {
- // + _cipher.update(_chunk, 0, posInChunk, _chunk);
- // + byte bla[] = { (byte)0x7A,(byte)0x0F,(byte)0x27,(byte)0xF0,(byte)0x17,(byte)0x6E,(byte)0x77,(byte)0x05,(byte)0xB9,(byte)0xDA,(byte)0x49,(byte)0xF9,(byte)0xD7,(byte)0x8E,(byte)0x03,(byte)0x1D };
- // + System.arraycopy(bla, 0, _chunk, posInChunk-2, bla.length);
- // + return posInChunk-2+bla.length;
- // + }
- // +
- // int ciLen = (doFinal)
- // ? _cipher.doFinal(_chunk, 0, posInChunk, _chunk)
- // : _cipher.update(_chunk, 0, posInChunk, _chunk);
- //
- // --- src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (revision 1766745)
- // +++ src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (working copy)
- //
- // @@ -300,7 +297,7 @@
- // protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode)
- // throws GeneralSecurityException {
- // EncryptionHeader header = encryptionInfo.getHeader();
- // - String padding = (lastChunk ? "PKCS5Padding" : "NoPadding");
- // + String padding = "NoPadding"; // (lastChunk ? "PKCS5Padding" : "NoPadding");
- // if (existing == null || !existing.getAlgorithm().endsWith(padding)) {
- // existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding);
- // }
-
- final EncryptionInfo infoOrig;
- final byte[] zipInput, epOrigBytes;
- try (InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx");
- POIFSFileSystem fsOrig = new POIFSFileSystem(is)) {
- infoOrig = new EncryptionInfo(fsOrig);
- Decryptor decOrig = infoOrig.getDecryptor();
- boolean b = decOrig.verifyPassword("Test001!!");
- assertTrue(b);
- try (InputStream decIn = decOrig.getDataStream(fsOrig)) {
- zipInput = IOUtils.toByteArray(decIn);
- }
-
- try (InputStream epOrig = fsOrig.getRoot().createDocumentInputStream("EncryptedPackage")) {
- // ignore the 16 padding bytes
- epOrigBytes = IOUtils.toByteArray(epOrig, 9400);
- }
- }
-
- EncryptionInfo eiNew = new EncryptionInfo(EncryptionMode.agile);
- AgileEncryptionHeader aehHeader = (AgileEncryptionHeader)eiNew.getHeader();
- aehHeader.setCipherAlgorithm(CipherAlgorithm.aes128);
- aehHeader.setHashAlgorithm(HashAlgorithm.sha1);
- AgileEncryptionVerifier aehVerifier = (AgileEncryptionVerifier)eiNew.getVerifier();
-
- // this cast might look strange - if the setters would be public, it will become obsolete
- // see http://stackoverflow.com/questions/5637650/overriding-protected-methods-in-java
- ((EncryptionVerifier)aehVerifier).setCipherAlgorithm(CipherAlgorithm.aes256);
- aehVerifier.setHashAlgorithm(HashAlgorithm.sha512);
-
- Encryptor enc = eiNew.getEncryptor();
- enc.confirmPassword("Test001!!",
- infoOrig.getDecryptor().getSecretKey().getEncoded(),
- infoOrig.getHeader().getKeySalt(),
- infoOrig.getDecryptor().getVerifier(),
- infoOrig.getVerifier().getSalt(),
- infoOrig.getDecryptor().getIntegrityHmacKey()
- );
-
- final byte[] epNewBytes;
- final EncryptionInfo infoReload;
- try (POIFSFileSystem fsNew = new POIFSFileSystem()) {
- try (OutputStream os = enc.getDataStream(fsNew)) {
- os.write(zipInput);
- }
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- fsNew.writeFilesystem(bos);
-
- try (POIFSFileSystem fsReload = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
- infoReload = new EncryptionInfo(fsReload);
- try (InputStream epReload = fsReload.getRoot().createDocumentInputStream("EncryptedPackage")) {
- epNewBytes = IOUtils.toByteArray(epReload, 9400);
- }
- }
- }
-
- assertArrayEquals(epOrigBytes, epNewBytes);
-
- Decryptor decReload = infoReload.getDecryptor();
- assertTrue(decReload.verifyPassword("Test001!!"));
-
- AgileEncryptionHeader aehOrig = (AgileEncryptionHeader)infoOrig.getHeader();
- AgileEncryptionHeader aehReload = (AgileEncryptionHeader)infoReload.getHeader();
- assertEquals(aehOrig.getBlockSize(), aehReload.getBlockSize());
- assertEquals(aehOrig.getChainingMode(), aehReload.getChainingMode());
- assertEquals(aehOrig.getCipherAlgorithm(), aehReload.getCipherAlgorithm());
- assertEquals(aehOrig.getCipherProvider(), aehReload.getCipherProvider());
- assertEquals(aehOrig.getCspName(), aehReload.getCspName());
- assertArrayEquals(aehOrig.getEncryptedHmacKey(), aehReload.getEncryptedHmacKey());
- // this only works, when the paddings are mocked to be the same ...
- // assertArrayEquals(aehOrig.getEncryptedHmacValue(), aehReload.getEncryptedHmacValue());
- assertEquals(aehOrig.getFlags(), aehReload.getFlags());
- assertEquals(aehOrig.getHashAlgorithm(), aehReload.getHashAlgorithm());
- assertArrayEquals(aehOrig.getKeySalt(), aehReload.getKeySalt());
- assertEquals(aehOrig.getKeySize(), aehReload.getKeySize());
-
- AgileEncryptionVerifier aevOrig = (AgileEncryptionVerifier)infoOrig.getVerifier();
- AgileEncryptionVerifier aevReload = (AgileEncryptionVerifier)infoReload.getVerifier();
- assertEquals(aevOrig.getBlockSize(), aevReload.getBlockSize());
- assertEquals(aevOrig.getChainingMode(), aevReload.getChainingMode());
- assertEquals(aevOrig.getCipherAlgorithm(), aevReload.getCipherAlgorithm());
- assertArrayEquals(aevOrig.getEncryptedKey(), aevReload.getEncryptedKey());
- assertArrayEquals(aevOrig.getEncryptedVerifier(), aevReload.getEncryptedVerifier());
- assertArrayEquals(aevOrig.getEncryptedVerifierHash(), aevReload.getEncryptedVerifierHash());
- assertEquals(aevOrig.getHashAlgorithm(), aevReload.getHashAlgorithm());
- assertEquals(aevOrig.getKeySize(), aevReload.getKeySize());
- assertArrayEquals(aevOrig.getSalt(), aevReload.getSalt());
- assertEquals(aevOrig.getSpinCount(), aevReload.getSpinCount());
-
- AgileDecryptor adOrig = (AgileDecryptor)infoOrig.getDecryptor();
- AgileDecryptor adReload = (AgileDecryptor)infoReload.getDecryptor();
-
- assertArrayEquals(adOrig.getIntegrityHmacKey(), adReload.getIntegrityHmacKey());
- // doesn't work without mocking ... see above
- // assertArrayEquals(adOrig.getIntegrityHmacValue(), adReload.getIntegrityHmacValue());
- assertArrayEquals(adOrig.getSecretKey().getEncoded(), adReload.getSecretKey().getEncoded());
- assertArrayEquals(adOrig.getVerifier(), adReload.getVerifier());
- }
-
- @Test
- public void smallFile() throws IOException, GeneralSecurityException {
- // see https://stackoverflow.com/questions/61463301
- final int tinyFileSize = 80_000_000;
- final String pass = "s3cr3t";
-
- File tmpFile = TempFile.createTempFile("tiny", ".bin");
-
- // create/populate empty file
- try (POIFSFileSystem poifs = new POIFSFileSystem();
- FileOutputStream fos = new FileOutputStream(tmpFile)) {
- poifs.writeFilesystem(fos);
- }
-
- EncryptionInfo info1 = new EncryptionInfo(EncryptionMode.agile);
- Encryptor enc = info1.getEncryptor();
- enc.confirmPassword(pass);
-
- final MessageDigest md = getMessageDigest(HashAlgorithm.sha256);
-
- // reopen as mmap-ed file
- try (POIFSFileSystem poifs = new POIFSFileSystem(tmpFile, false)) {
- try (OutputStream os = enc.getDataStream(poifs);
- RandomStream rs = new RandomStream(md)) {
- IOUtils.copy(rs, os, tinyFileSize);
- }
- poifs.writeFilesystem();
- }
-
- final byte[] digest1 = md.digest();
- md.reset();
-
- // reopen and check the digest
- try (POIFSFileSystem poifs = new POIFSFileSystem(tmpFile)) {
- EncryptionInfo info2 = new EncryptionInfo(poifs);
- Decryptor dec = info2.getDecryptor();
- boolean passOk = dec.verifyPassword(pass);
- assertTrue(passOk);
-
- try (InputStream is = dec.getDataStream(poifs);
- DigestInputStream dis = new DigestInputStream(is, md);
- NullOutputStream nos = new NullOutputStream()) {
- IOUtils.copy(dis, nos);
- }
- }
-
- final byte[] digest2 = md.digest();
- assertArrayEquals(digest1, digest2);
-
- boolean isDeleted = tmpFile.delete();
- assertTrue(isDeleted);
- }
-
- private static final class RandomStream extends InputStream {
- private final Random rand = new Random();
- private final byte[] buf = new byte[1024];
- private final MessageDigest md;
-
- private RandomStream(MessageDigest md) {
- this.md = md;
- }
-
- @Override
- public int read() {
- int ret = rand.nextInt(256);
- md.update((byte)ret);
- return ret;
- }
-
- @Override
- public int read(byte[] b, final int off, int len) {
- for (int start = off; start-off < len; start += buf.length) {
- rand.nextBytes(buf);
- int copyLen = Math.min(buf.length, len-(start-off));
- System.arraycopy(buf, 0, b, start, copyLen);
- md.update(buf, 0, copyLen);
- }
- return len;
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt;
-
-import static org.apache.poi.POIDataSamples.getDocumentInstance;
-import static org.apache.poi.POIDataSamples.getSlideShowInstance;
-import static org.apache.poi.POIDataSamples.getSpreadSheetInstance;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.Collection;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.POIDocument;
-import org.apache.poi.extractor.POITextExtractor;
-import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
-import org.apache.poi.ooxml.extractor.ExtractorFactory;
-import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
-import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader;
-import org.apache.poi.poifs.storage.RawDataUtil;
-import org.apache.xmlbeans.XmlException;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TestHxxFEncryption {
- @Parameter(value = 0)
- public POIDataSamples sampleDir;
-
- @Parameter(value = 1)
- public String file;
-
- @Parameter(value = 2)
- public String password;
-
- @Parameter(value = 3)
- public String expected;
-
- @Parameters(name="{1}")
- public static Collection<Object[]> data() throws IOException {
- final String base64 =
- "H4sIAAAAAAAAAF1Uu24bMRDs/RULVwkgCUhSpHaZwkDgpHJH8fZ0G/Nx4ZI6y13yG/mRfIb9R5mlZFlIpdPtcnZmdnjPf57/vvx6+f3h6obuv3"+
- "ylbY5bEiVHe1fEpUp5pOgkrK0iabehm7FyoZi1ks8xcvHiQu8h5bLnorTlnUvkJ/YPOHKsLVInAqCs91KakuaxLq4w3g00SgCo9Xou1UnCmSBe"+
- "MhpRY6qHmXVFteQfQJ5yUaaOw4qXwgPVjPGAqhNH5bBHAfTmwqqoSkLdFT/J3nC0eZBRk7yiu5s7yoU+r+9l3tDtm5A3jgt6AQxNOY2ya+U4sK"+
- "XZ+YczbpfSVVuzFOuunKraqIVD2ND3yVXauT3TNthR/O3IJAM7gzTOGeIcXZvj14ahotW8wSognlMu0Yyp/Fi7O6s+CK6haUUjtPCji7MVcgqH"+
- "jh+42tqeqPDMroJ/lBAE4AZbJbJu6Fu35ej42Tw9mYeTwVXoBKJiPeFV94q2rZJAyNEPo/qOdWYLBpq3B2JX8GDZeJ14mZf3tOQWBmpd9yQ7kI"+
- "DCY/jmkj1oGOicFy62r9vutC5uJsVEMFgmAXXfYcC6BRBKNHCybALFJolnrDcPXNLl+K60Vctt09YZT7YgbeOICGJ/ZgC2JztOnm1JhX3eJXni"+
- "U5Bqhezzlu334vD/Ajr3yDGXw5G9IZ6aLmLfQafY42N3J7cjj1LaXOHihSrcC5ThmuYIB5FX5AU8tKlnNG9Dn1EnsdD4KcnPhsSNPRiXtz461b"+
- "VZw8Pm6vn0afh4fvr0D5P/+cMuBAAA";
- final String x = new String(RawDataUtil.decompress(base64), StandardCharsets.UTF_8);
-
- return Arrays.asList(
- // binary rc4
- new Object[]{ getDocumentInstance(), "password_tika_binaryrc4.doc", "tika", "This is an encrypted Word 2007 File." },
- // cryptoapi
- new Object[]{ getDocumentInstance(), "password_password_cryptoapi.doc", "password", "This is a test" },
- // binary rc4
- new Object[]{ getSpreadSheetInstance(), "password.xls", "password", x },
- // cryptoapi
- new Object[]{ getSpreadSheetInstance(), "35897-type4.xls", "freedom", "Sheet1\nhello there!" },
- // cryptoapi (PPT only supports cryptoapi...)
- new Object[]{ getSlideShowInstance(), "cryptoapi-proc2356.ppt", "crypto", "Dominic Salemno" }
- );
- }
-
- @Test
- public void extract() throws IOException, OpenXML4JException, XmlException {
- File f = sampleDir.getFile(file);
- Biff8EncryptionKey.setCurrentUserPassword(password);
- try (POITextExtractor te = ExtractorFactory.createExtractor(f)) {
- String actual = te.getText().trim();
- assertEquals(expected, actual);
- } finally {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- }
- }
-
- @Test
- public void changePassword() throws IOException, OpenXML4JException, XmlException {
- newPassword("test");
- }
-
- @Test
- public void removePassword() throws IOException, OpenXML4JException, XmlException {
- newPassword(null);
- }
-
- private void newPassword(String newPass) throws IOException, OpenXML4JException, XmlException {
- File f = sampleDir.getFile(file);
- Biff8EncryptionKey.setCurrentUserPassword(password);
- try (POITextExtractor te1 = ExtractorFactory.createExtractor(f)) {
- Biff8EncryptionKey.setCurrentUserPassword(newPass);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try (POIDocument doc = (POIDocument) te1.getDocument()) {
- doc.write(bos);
- }
- ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
- try (POITextExtractor te2 = ExtractorFactory.createExtractor(bis)) {
- String actual = te2.getText().trim();
- assertEquals(expected, actual);
- }
- } finally {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- }
- }
-
- /** changing the encryption mode and key size in poor mans style - see comments below */
- @Test
- public void changeEncryption() throws IOException, OpenXML4JException, XmlException {
- File f = sampleDir.getFile(file);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- Biff8EncryptionKey.setCurrentUserPassword(password);
- try (POITextExtractor te1 = ExtractorFactory.createExtractor(f)) {
- // first remove encryption
- Biff8EncryptionKey.setCurrentUserPassword(null);
- try (POIDocument doc = (POIDocument) te1.getDocument()) {
- doc.write(bos);
- }
- // then use default setting, which is cryptoapi
- String newPass = "newPass";
- try (POITextExtractor te2 = ExtractorFactory.createExtractor(new ByteArrayInputStream(bos.toByteArray()))) {
- Biff8EncryptionKey.setCurrentUserPassword(newPass);
- try (POIDocument doc = (POIDocument) te2.getDocument()) {
- bos.reset();
- doc.write(bos);
- }
- }
- // and finally update cryptoapi setting
- try (POITextExtractor te3 = ExtractorFactory.createExtractor(new ByteArrayInputStream(bos.toByteArray()));
- POIDocument doc = (POIDocument) te3.getDocument()) {
- // need to cache data (i.e. read all data) before changing the key size
- Class<?> clazz = doc.getClass();
- if ("HSLFSlideShowImpl".equals(clazz.getSimpleName())) {
- try {
- clazz.getDeclaredMethod("getPictureData").invoke(doc);
- } catch (ReflectiveOperationException e) {
- fail("either scratchpad jar is included and this should work or the clazz should be != HSLFSlideShowImpl");
- }
- doc.getDocumentSummaryInformation();
- }
- EncryptionInfo ei = doc.getEncryptionInfo();
- assertNotNull(ei);
- assertTrue(ei.getHeader() instanceof CryptoAPIEncryptionHeader);
- assertEquals(0x28, ei.getHeader().getKeySize());
- ei.getHeader().setKeySize(0x78);
- bos.reset();
- doc.write(bos);
- }
- // check the setting
- try (POITextExtractor te4 = ExtractorFactory.createExtractor(new ByteArrayInputStream(bos.toByteArray()));
- POIDocument doc = (POIDocument) te4.getDocument()) {
- EncryptionInfo ei = doc.getEncryptionInfo();
- assertNotNull(ei);
- assertTrue(ei.getHeader() instanceof CryptoAPIEncryptionHeader);
- assertEquals(0x78, ei.getHeader().getKeySize());
- }
- } finally {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.poifs.crypt;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import javax.crypto.Cipher;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.GeneralSecurityException;
-
-import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.util.ZipEntrySource;
-import org.apache.poi.poifs.crypt.temp.AesZipFileZipEntrySource;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.apache.poi.xssf.extractor.XSSFBEventBasedExcelExtractor;
-import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.apache.xmlbeans.XmlException;
-import org.junit.Assume;
-import org.junit.Test;
-
-public class TestSecureTempZip {
-
- /**
- * Test case for #59841 - this is an example on how to use encrypted temp files,
- * which are streamed into POI opposed to having everything in memory
- */
- @Test
- public void protectedTempZip() throws IOException, GeneralSecurityException, XmlException, OpenXML4JException {
- File tikaProt = XSSFTestDataSamples.getSampleFile("protected_passtika.xlsx");
- FileInputStream fis = new FileInputStream(tikaProt);
- POIFSFileSystem poifs = new POIFSFileSystem(fis);
- EncryptionInfo ei = new EncryptionInfo(poifs);
- Decryptor dec = ei.getDecryptor();
- boolean passOk = dec.verifyPassword("tika");
- assertTrue(passOk);
-
- // extract encrypted ooxml file and write to custom encrypted zip file
- InputStream is = dec.getDataStream(poifs);
-
- // provide ZipEntrySource to poi which decrypts on the fly
- ZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(is);
-
- // test the source
- OPCPackage opc = OPCPackage.open(source);
- String expected = "This is an Encrypted Excel spreadsheet.";
-
- XSSFEventBasedExcelExtractor extractor = new XSSFEventBasedExcelExtractor(opc);
- extractor.setIncludeSheetNames(false);
- String txt = extractor.getText();
- assertEquals(expected, txt.trim());
-
- XSSFWorkbook wb = new XSSFWorkbook(opc);
- txt = wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue();
- assertEquals(expected, txt);
-
- extractor.close();
-
- wb.close();
- opc.close();
- source.close();
- poifs.close();
- fis.close();
- }
-
- /**
- * Now try with xlsb.
- */
- @Test
- public void protectedXLSBZip() throws IOException, GeneralSecurityException, XmlException, OpenXML4JException {
- //The test file requires that JCE unlimited be installed.
- //If it isn't installed, skip this test.
- int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
- Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256",
- maxKeyLen == 2147483647);
-
- File tikaProt = XSSFTestDataSamples.getSampleFile("protected_passtika.xlsb");
- FileInputStream fis = new FileInputStream(tikaProt);
- POIFSFileSystem poifs = new POIFSFileSystem(fis);
- EncryptionInfo ei = new EncryptionInfo(poifs);
- Decryptor dec = ei.getDecryptor();
- boolean passOk = dec.verifyPassword("tika");
- assertTrue(passOk);
-
- // extract encrypted ooxml file and write to custom encrypted zip file
- InputStream is = dec.getDataStream(poifs);
-
- // provide ZipEntrySource to poi which decrypts on the fly
- ZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(is);
-
- // test the source
- OPCPackage opc = OPCPackage.open(source);
- String expected = "You can't see me";
-
- XSSFBEventBasedExcelExtractor extractor = new XSSFBEventBasedExcelExtractor(opc);
- extractor.setIncludeSheetNames(false);
- String txt = extractor.getText();
- assertEquals(expected, txt.trim());
-
- extractor.close();
- opc.close();
- poifs.close();
- fis.close();
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.
-==================================================================== */
-
-/* ====================================================================
- This product contains an ASLv2 licensed version of the OOXML signer
- package from the eID Applet project
- http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
- Copyright (C) 2008-2014 FedICT.
- ================================================================= */
-package org.apache.poi.poifs.crypt;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.math.BigInteger;
-import java.net.ConnectException;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.security.Key;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStore;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.cert.CRLException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.RSAKeyGenParameterSpec;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.xml.crypto.MarshalException;
-import javax.xml.crypto.dsig.CanonicalizationMethod;
-import javax.xml.crypto.dsig.XMLSignatureException;
-import javax.xml.crypto.dsig.dom.DOMSignContext;
-
-import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.ooxml.util.DocumentHelper;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
-import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
-import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
-import org.apache.poi.poifs.crypt.dsig.SignaturePart;
-import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet;
-import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
-import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet;
-import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
-import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet;
-import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
-import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;
-import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
-import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;
-import org.apache.poi.poifs.storage.RawDataUtil;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.LocaleUtil;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.apache.xmlbeans.SystemProperties;
-import org.apache.xmlbeans.XmlObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
-import org.bouncycastle.asn1.x509.BasicConstraints;
-import org.bouncycastle.asn1.x509.CRLNumber;
-import org.bouncycastle.asn1.x509.Extension;
-import org.bouncycastle.asn1.x509.Extensions;
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.cert.X509CRLHolder;
-import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.cert.X509ExtensionUtils;
-import org.bouncycastle.cert.X509v2CRLBuilder;
-import org.bouncycastle.cert.X509v3CertificateBuilder;
-import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
-import org.bouncycastle.cert.ocsp.BasicOCSPResp;
-import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
-import org.bouncycastle.cert.ocsp.CertificateID;
-import org.bouncycastle.cert.ocsp.CertificateStatus;
-import org.bouncycastle.cert.ocsp.OCSPReq;
-import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
-import org.bouncycastle.cert.ocsp.OCSPResp;
-import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
-import org.bouncycastle.cert.ocsp.Req;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
-import org.bouncycastle.openssl.PEMParser;
-import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.DigestCalculator;
-import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
-import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
-import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
-import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
-import org.junit.AfterClass;
-import org.junit.Assume;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.w3.x2000.x09.xmldsig.ReferenceType;
-import org.w3.x2000.x09.xmldsig.SignatureDocument;
-import org.w3c.dom.Document;
-
-public class TestSignatureInfo {
- private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class);
- private static final POIDataSamples testdata = POIDataSamples.getXmlDSignInstance();
-
- private static Calendar cal;
- private KeyPair keyPair;
- private X509Certificate x509;
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @AfterClass
- public static void removeUserLocale() {
- LocaleUtil.resetUserLocale();
- }
-
- @BeforeClass
- public static void initBouncy() {
- CryptoFunctions.registerBouncyCastle();
-
- // Set cal to now ... only set to fixed date for debugging ...
- LocaleUtil.resetUserLocale();
- LocaleUtil.resetUserTimeZone();
-
- cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
- assertNotNull(cal);
-
- // don't run this test when we are using older Xerces as it triggers an XML Parser backwards compatibility issue
- // in the xmlsec jar file
- String additionalJar = System.getProperty("additionaljar");
- //System.out.println("Having: " + additionalJar);
- Assume.assumeTrue("Not running TestSignatureInfo because we are testing with additionaljar set to " + additionalJar,
- additionalJar == null || additionalJar.trim().length() == 0);
-
- System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");
-
- // Set line.separator for bug61182
- // System.setProperty("line.separator", "\n");
- }
-
- @Ignore("This test is very sensitive, it breaks with every little change to the produced XML")
- @Test
- public void bug61182() throws Exception {
- final String pfxInput =
- "H4sIAAAAAAAAAFXTfzzTeRwH8P2uGRmG6hKSmJh9a2HsuPy60VnHCEU6v86sieZH2Jr2qFl+s+ZHJ5tfUcfKb4uho/OjiFq1qTv5ceFyp0PqEK"+
- "fH4+66++Pz+Dwer9fj8f7r9cRzEd4QMBTPRWxDIM14ZN47NfAWsJgL34Bx4at4Lvwdngvd9b8KqgbjQpGbMXzzgRGovytVFTBEzIXU47kQCd4U"+
- "ofJPvHl8JwyTjRS55hbKoor3UJLDE1i/PcPKCBAIDATjQlKiK67XjVYdcnkZgD2txroiAUb8W9dtn57DvTsbM+3wIsdocXDEN7TdPKgaSl+tU1"+
- "xq9oqiB5yMaZCPho8uUEbFU9U6u3N7lEMLTJGeA0RfX+5FMRrpXPFrbrlJ8uNUCE2H247P28Ckyfqlsy32yeKg/HTbH5JpqUDNw2B32+SaiRw7"+
- "ofRMePUpaAoK7KYgmd5ZIc0rLLYjJBfOWCb28xlrGhbpJvdToFdqt5PXVjEz5YOJ6g7W0fskuKW9/iZP0yLEVpR9XkkHmb6tfpcE8YwCdWNCan"+
- "LvAsco25JdF1j2/FLAMVU79HdOex07main90dy40511OZtTGZ+TdVd3lKZ7D3clEg9hLESHwSNnZ6239X4yLM4xYSElQ/hqSbwdmiozYG9PhF2"+
- "Zf0XaZnxzTK0Iot+rJ3kYoxWTLE8DR9leV62Ywbtlg4mapYOxb3lT7fQ1x4EQ44flh2oFWSPLR8LMbsc6jzJsV6OZ3TrODjHEdw9W+8OD32vd8"+
- "XQ6iCaIHcrSOn6qS0TKLr786234eeSAhvAQbEsVn7vrvc/487Be/O2e/+5Y5zRq2zAtz6pfcNyraJNDqMW1inNkgJ3t3VESbZ3pNzyl3KHILs0"+
- "51dY6msDYSlWhw40TglXxj9rw95O6gFWIuN012W/vhS50jpKXcao4gc1aLaXtJXxirbRkpZ/0e7a0pD6TDa7+GxEdEEML3VGo9udD5YUKhU3y7"+
- "SzWAgN6WIEIglq7LilvCjqIVLIfg8CvVGL9f5iSsCDf5hef4vMxbyvcjINuy06gZu+iPYOWNxjfrwKGYzoqqotK2aywgYVrPMh0JovfkDuN95n"+
- "MdVlYHbN1Mnn4TxAwuv+u3AkBlDZvRUUCwoDMUGxeMNPhTaAgWl60xhhBgCBaEMgAACReMAav7n3x598IDYJ9GxGXRAwaPOT/kfO/1AgPqLQkp"+
- "MiIVaHthnUS4v2y32e2BjdMPyIImUTBW3cV3R5tjVQm0MOm+D2C5+bBW9vHLjLR4lun4toQiY3Ls/v4bES/OJ4EmpZk5xhL9i5ClofYZNEsxFn"+
- "An/q821Tg+Cq9Er4XYGQe8ogjjLJ2b7dUsJ3auFQFNUJF7Ke7yUL2EeYYxl6vz5l4q5u8704mRbFts1E1eWMp6WIy91GPrsVlRGvtuNERfrjfE"+
- "YtzUI3Flcv65zJUbUBEzUnTS0fEYso2XyToAl8kb251mUY2o2lJzv5dp/1htmcjeeP2MjxC+3S45ljx7jd52Pv9XAat+ryiauFOF7YgztkoWWD"+
- "h62tplPH1bzDV+d0NLdaE5AfVJ09HuUYTFS+iggtvT5Euyk+unj4N2XvzW91n+GNjtgWfKOHmkinUPvYRh70Jv+wlPJrVaT8mL7GxJLqDC9jbv"+
- "Gznoiae6es+wQejnk3XjU366MrK/zXxngBYj9J6NnXc9mMiTFLX8WqQ8iTelTAFs2NJzPoDzrBUz4JFIEOa6Dja6dULc68g1jFDTeEHZyra7RZ"+
- "2ElqGDEqcNRo3SNX6feMy9EF1GOyZK0Sa87KwjKw8aM68dpsIYjfLcTXaZ6atg0BKfMnl6axeUGEaIFSP7rzj9wjzumRbG3jgUVp2lX5AK/tsO"+
- "7R4TQX/9/H6RiN34c9KldmPZZGANXzzTajZS9mR2OSvlJ+F4AgSko4htrMAKFTBu51/5SWNsO1vlRaaG48ZRJ+8PzuHQMdvS36gNpRPi7jhF1S"+
- "H3B2ycI4y0VURv6SrqJNUY/X645ZFJQ+eBO+ptG7o8axf1dcqh2beiQk+GRTeZ37LVeUlaeo9vl1/+8tyBfyT2v5lFC5E19WdKIyCuZe7r99Px"+
- "D/Od4Qj0TA92+DQnbCQTCMy/wwse9O4gsEebkkpPIP5GBV3Q0YBsj75XE0uSFQ1tCZSW8bNa9MUJZ/nPBfExohHlgGAAA=";
-
- // Unix
- final String unixSignExp =
- "QkqTFQZjXagjRAoOWKpAGa8AR0rKqkSfBtfSWqtjBmTgyjarn+t2POHkpySIpheHAbg+90GKSH88ACMtPHbG7q" +
- "FL4gtgAD9Kjew6j16j0IRBwy145UlPrSLFMfF7YF7UlU1k1LBkIlRJ6Fv4MAJl6XspuzZOZIUmHZrWrdxycUQ=";
-
- // Windows
- final String winSignExp =
- "GmAlL7+bT1r3FsMHJOp3pKg8betblYieZTjhMIrPZPRBbSzjO7KsYRGNtr0aOE3qr8xzyYJN6/8QdF5X7pUEUc" +
- "2m8ctrm7s5o2vZTkAqk9ENJGDjBPXX7TnuVOiVeL1cJdtjHC2QpjtRwkFR+B54G6b1OXLOFuQpP3vqR3+/XXE=";
-
- // Mac
- final String macSignExp =
- "NZedY/LNTYU4nAUEUhIOg5+fKdgVtzRXKmdD3v+47E7Mb84oeiUGv9cCEE91DU3StF/JFIhjOJqavOzKnCsNcz" +
- "NJ4j/inggUl1OJUsicqIGQnA7E8vzWnN1kf5lINgJLv+0PyrrX9sQZbItzxUpgqyOFYcD0trid+31nRt4wtaA=";
-
-
-
- Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
- cal.clear();
- cal.setTimeZone(LocaleUtil.TIMEZONE_UTC);
- cal.set(2017, Calendar.JULY, 1);
-
- SignatureConfig signatureConfig = prepareConfig(pfxInput);
- signatureConfig.setExecutionTime(cal.getTime());
-
- SignatureInfo si = new SignatureInfo();
- si.setSignatureConfig(signatureConfig);
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream(100000);
- try (XSSFWorkbook wb1 = new XSSFWorkbook()) {
- wb1.createSheet().createRow(1).createCell(1).setCellValue("Test");
- wb1.write(bos);
- }
-
- try (OPCPackage pkg1 = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()))) {
- si.setOpcPackage(pkg1);
- si.confirmSignature();
- assertTrue(si.verifySignature());
- bos.reset();
- pkg1.save(bos);
- }
-
- try (XSSFWorkbook wb2 = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) {
- assertEquals("Test", wb2.getSheetAt(0).getRow(1).getCell(1).getStringCellValue());
- OPCPackage pkg2 = wb2.getPackage();
- si.setOpcPackage(pkg2);
- assertTrue(si.verifySignature());
-
- // xmlbeans adds line-breaks depending on the system setting, so we get different
- // test results on Unix/Mac/Windows
- // if the xml documents eventually change, this test needs to be run with the
- // separator set to the various system configurations
- String sep = SystemProperties.getProperty("line.separator");
- String signExp;
- assumeTrue("Hashes only known for Windows/Unix/Mac", sep == null || "\n".equals(sep) || "\r\n".equals(sep) || "\r".equals(sep));
- signExp = (sep == null || "\n".equals(sep)) ? unixSignExp : ("\r\n".equals(sep)) ? winSignExp : macSignExp;
-
- String signAct = si.getSignatureParts().iterator().next().
- getSignatureDocument().getSignature().getSignatureValue().getStringValue();
- assertEquals(signExp, signAct);
- }
- }
-
- @Test
- public void office2007prettyPrintedRels() throws Exception {
- try (OPCPackage pkg = OPCPackage.open(testdata.getFile("office2007prettyPrintedRels.docx"), PackageAccess.READ)) {
- SignatureConfig sic = new SignatureConfig();
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(sic);
- boolean isValid = si.verifySignature();
- assertTrue(isValid);
- }
- }
-
- @Test
- public void getSignerUnsigned() throws Exception {
- String[] testFiles = {
- "hello-world-unsigned.docx",
- "hello-world-unsigned.pptx",
- "hello-world-unsigned.xlsx",
- "hello-world-office-2010-technical-preview-unsigned.docx"
- };
-
- for (String testFile : testFiles) {
- List<X509Certificate> result = new ArrayList<>();
- try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
- SignatureConfig sic = new SignatureConfig();
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(sic);
- for (SignaturePart sp : si.getSignatureParts()) {
- if (sp.validate()) {
- result.add(sp.getSigner());
- }
- }
- pkg.revert();
- }
- assertNotNull(result);
- assertTrue(result.isEmpty());
- }
- }
-
- @Test
- public void getSigner() throws Exception {
- String[] testFiles = {
- "hyperlink-example-signed.docx",
- "hello-world-signed.docx",
- "hello-world-signed.pptx",
- "hello-world-signed.xlsx",
- "hello-world-office-2010-technical-preview.docx",
- "ms-office-2010-signed.docx",
- "ms-office-2010-signed.pptx",
- "ms-office-2010-signed.xlsx",
- "Office2010-SP1-XAdES-X-L.docx",
- "signed.docx"
- };
-
- for (String testFile : testFiles) {
- try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
- SignatureConfig sic = new SignatureConfig();
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(sic);
- List<X509Certificate> result = new ArrayList<>();
- for (SignaturePart sp : si.getSignatureParts()) {
- if (sp.validate()) {
- result.add(sp.getSigner());
- }
- }
-
- assertNotNull(result);
- assertEquals("test-file: " + testFile, 1, result.size());
- X509Certificate signer = result.get(0);
- LOG.log(POILogger.DEBUG, "signer: " + signer.getSubjectX500Principal());
-
- boolean b = si.verifySignature();
- assertTrue("test-file: " + testFile, b);
- pkg.revert();
- }
- }
- }
-
- @Test
- public void getMultiSigners() throws Exception {
- String testFile = "hello-world-signed-twice.docx";
- try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
- SignatureConfig sic = new SignatureConfig();
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(sic);
- List<X509Certificate> result = new ArrayList<>();
- for (SignaturePart sp : si.getSignatureParts()) {
- if (sp.validate()) {
- result.add(sp.getSigner());
- }
- }
-
- assertNotNull(result);
- assertEquals("test-file: " + testFile, 2, result.size());
- X509Certificate signer1 = result.get(0);
- X509Certificate signer2 = result.get(1);
- LOG.log(POILogger.DEBUG, "signer 1: " + signer1.getSubjectX500Principal());
- LOG.log(POILogger.DEBUG, "signer 2: " + signer2.getSubjectX500Principal());
-
- boolean b = si.verifySignature();
- assertTrue("test-file: " + testFile, b);
- pkg.revert();
- }
- }
-
- @Test
- public void testSignSpreadsheet() throws Exception {
- String testFile = "hello-world-unsigned.xlsx";
- try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
- sign(pkg);
- }
- }
-
- private static class CommitableWorkbook extends XSSFWorkbook {
- CommitableWorkbook(OPCPackage pkg) throws IOException {
- super(pkg);
- }
- public void commit() throws IOException {
- super.commit();
- }
- }
-
- @Test
- public void testManipulation() throws Exception {
- // sign & validate
- String testFile = "hello-world-unsigned.xlsx";
- try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
- sign(pkg);
-
- // manipulate
- try (CommitableWorkbook wb = new CommitableWorkbook(pkg)) {
- wb.setSheetName(0, "manipulated");
- // ... I don't know, why commit is protected ...
- wb.commit();
-
- // todo: test a manipulation on a package part, which is not signed
- // ... maybe in combination with #56164
-
- // validate
- SignatureConfig sic = new SignatureConfig();
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(sic);
- boolean b = si.verifySignature();
- assertFalse("signature should be broken", b);
- }
- }
- }
-
- @Test
- public void testSignSpreadsheetWithSignatureInfo() throws Exception {
- initKeyPair();
- String testFile = "hello-world-unsigned.xlsx";
- try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
- SignatureConfig sic = new SignatureConfig();
- sic.setKey(keyPair.getPrivate());
- sic.setSigningCertificateChain(Collections.singletonList(x509));
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(sic);
- // hash > sha1 doesn't work in excel viewer ...
- si.confirmSignature();
- List<X509Certificate> result = new ArrayList<>();
- for (SignaturePart sp : si.getSignatureParts()) {
- if (sp.validate()) {
- result.add(sp.getSigner());
- }
- }
- assertEquals(1, result.size());
- }
- }
-
- @Test
- public void testSignEnvelopingDocument() throws Exception {
- String testFile = "hello-world-unsigned.xlsx";
- File sigCopy = testdata.getFile(testFile);
- ByteArrayOutputStream bos = new ByteArrayOutputStream(50000);
-
- final String execTimestr;
-
-
- try (OPCPackage pkg = OPCPackage.open(copy(sigCopy), PackageAccess.READ_WRITE)) {
-
- initKeyPair();
- final X509CRL crl = generateCrl(x509, keyPair.getPrivate());
-
- // setup
- SignatureConfig signatureConfig = new SignatureConfig();
- signatureConfig.setKey(keyPair.getPrivate());
-
- /*
- * We need at least 2 certificates for the XAdES-C complete certificate
- * refs construction.
- */
- List<X509Certificate> certificateChain = new ArrayList<>();
- certificateChain.add(x509);
- certificateChain.add(x509);
- signatureConfig.setSigningCertificateChain(certificateChain);
-
- signatureConfig.addSignatureFacet(new OOXMLSignatureFacet());
- signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet());
- signatureConfig.addSignatureFacet(new KeyInfoSignatureFacet());
- signatureConfig.addSignatureFacet(new XAdESSignatureFacet());
- signatureConfig.addSignatureFacet(new XAdESXLSignatureFacet());
-
- // check for internet, no error means it works
- boolean mockTsp = (getAccessError("http://timestamp.comodoca.com/rfc3161", true, 10000) != null);
-
- // http://timestamping.edelweb.fr/service/tsp
- // http://tsa.belgium.be/connect
- // http://timestamp.comodoca.com/authenticode
- // http://timestamp.comodoca.com/rfc3161
- // http://services.globaltrustfinder.com/adss/tsa
- signatureConfig.setTspUrl("http://timestamp.comodoca.com/rfc3161");
- signatureConfig.setTspRequestPolicy(null); // comodoca request fails, if default policy is set ...
- signatureConfig.setTspOldProtocol(false);
-
- signatureConfig.setXadesDigestAlgo(HashAlgorithm.sha512);
- signatureConfig.setXadesRole("Xades Reviewer");
- signatureConfig.setSignatureDescription("test xades signature");
-
- execTimestr = signatureConfig.formatExecutionTime();
-
- //set proxy info if any
- String proxy = System.getProperty("http_proxy");
- if (proxy != null && proxy.trim().length() > 0) {
- signatureConfig.setProxyUrl(proxy);
- }
-
- if (mockTsp) {
- TimeStampService tspService = (signatureInfo, data, revocationData) -> {
- revocationData.addCRL(crl);
- return "time-stamp-token".getBytes(LocaleUtil.CHARSET_1252);
- };
- signatureConfig.setTspService(tspService);
- } else {
- TimeStampServiceValidator tspValidator = (validateChain, revocationData) -> {
- for (X509Certificate certificate : validateChain) {
- LOG.log(POILogger.DEBUG, "certificate: " + certificate.getSubjectX500Principal());
- LOG.log(POILogger.DEBUG, "validity: " + certificate.getNotBefore() + " - " + certificate.getNotAfter());
- }
- };
- signatureConfig.setTspValidator(tspValidator);
- signatureConfig.setTspOldProtocol(signatureConfig.getTspUrl().contains("edelweb"));
- }
-
- final RevocationData revocationData = new RevocationData();
- revocationData.addCRL(crl);
- OCSPResp ocspResp = createOcspResp(x509, x509, x509, keyPair.getPrivate(), cal.getTimeInMillis());
- revocationData.addOCSP(ocspResp.getEncoded());
-
- RevocationDataService revocationDataService = revocationChain -> revocationData;
- signatureConfig.setRevocationDataService(revocationDataService);
-
- // operate
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(signatureConfig);
- try {
- si.confirmSignature();
- } catch (RuntimeException e) {
- // only allow a ConnectException because of timeout, we see this in Jenkins from time to time...
- if (e.getCause() == null) {
- throw e;
- }
- if ((e.getCause() instanceof ConnectException) || (e.getCause() instanceof SocketTimeoutException)) {
- Assume.assumeFalse("Only allowing ConnectException with 'timed out' as message here, but had: " + e,
- e.getCause().getMessage().contains("timed out"));
- } else if (e.getCause() instanceof IOException) {
- Assume.assumeFalse("Only allowing IOException with 'Error contacting TSP server' as message here, but had: " + e,
- e.getCause().getMessage().contains("Error contacting TSP server"));
- } else if (e.getCause() instanceof RuntimeException) {
- Assume.assumeFalse("Only allowing RuntimeException with 'This site is cur' as message here, but had: " + e,
- e.getCause().getMessage().contains("This site is cur"));
- }
- throw e;
- }
-
- // verify
- Iterator<SignaturePart> spIter = si.getSignatureParts().iterator();
- assertTrue("Had: " + pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN), spIter.hasNext());
- SignaturePart sp = spIter.next();
- boolean valid = sp.validate();
- assertTrue(valid);
-
- SignatureDocument sigDoc = sp.getSignatureDocument();
- String declareNS =
- "declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; "
- + "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; ";
-
- String digestValXQuery = declareNS +
- "$this/ds:Signature/ds:SignedInfo/ds:Reference";
- for (ReferenceType rt : (ReferenceType[]) sigDoc.selectPath(digestValXQuery)) {
- assertNotNull(rt.getDigestValue());
- assertEquals(signatureConfig.getDigestMethodUri(), rt.getDigestMethod().getAlgorithm());
- }
-
- String certDigestXQuery = declareNS +
- "$this//xades:SigningCertificate/xades:Cert/xades:CertDigest";
- XmlObject[] xoList = sigDoc.selectPath(certDigestXQuery);
- assertEquals(xoList.length, 1);
- DigestAlgAndValueType certDigest = (DigestAlgAndValueType) xoList[0];
- assertNotNull(certDigest.getDigestValue());
-
- String qualPropXQuery = declareNS +
- "$this/ds:Signature/ds:Object/xades:QualifyingProperties";
- xoList = sigDoc.selectPath(qualPropXQuery);
- assertEquals(xoList.length, 1);
- QualifyingPropertiesType qualProp = (QualifyingPropertiesType) xoList[0];
- boolean qualPropXsdOk = qualProp.validate();
- assertTrue(qualPropXsdOk);
-
- pkg.save(bos);
- }
-
- try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()))) {
- SignatureConfig signatureConfig = new SignatureConfig();
- signatureConfig.setUpdateConfigOnValidate(true);
-
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(signatureConfig);
-
- assertTrue(si.verifySignature());
-
- assertEquals(HashAlgorithm.sha512, signatureConfig.getXadesDigestAlgo());
- assertEquals("Xades Reviewer", signatureConfig.getXadesRole());
- assertEquals("test xades signature", signatureConfig.getSignatureDescription());
- assertEquals(execTimestr, signatureConfig.formatExecutionTime());
- }
- }
-
- public static String getAccessError(String destinationUrl, boolean fireRequest, int timeout) {
- URL url;
- try {
- url = new URL(destinationUrl);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("Invalid destination URL", e);
- }
-
- HttpURLConnection conn = null;
- try {
- conn = (HttpURLConnection) url.openConnection();
-
- // set specified timeout if non-zero
- if(timeout != 0) {
- conn.setConnectTimeout(timeout);
- conn.setReadTimeout(timeout);
- }
-
- conn.setDoOutput(false);
- conn.setDoInput(true);
-
- /* if connecting is not possible this will throw a connection refused exception */
- conn.connect();
-
- if (fireRequest) {
- conn.getInputStream().close();
- }
- /* if connecting is possible we return true here */
- return null;
-
- } catch (IOException e) {
- /* exception is thrown -> server not available */
- return e.getClass().getName() + ": " + e.getMessage();
- } finally {
- if (conn != null) {
- conn.disconnect();
- }
- }
- }
-
- @Test
- public void testCertChain() throws Exception {
- KeyStore keystore = KeyStore.getInstance("PKCS12");
- String password = "test";
- try (InputStream is = testdata.openResourceAsStream("chaintest.pfx")) {
- keystore.load(is, password.toCharArray());
- }
-
- Key key = keystore.getKey("poitest", password.toCharArray());
- Certificate[] chainList = keystore.getCertificateChain("poitest");
- List<X509Certificate> certChain = new ArrayList<>();
- for (Certificate c : chainList) {
- certChain.add((X509Certificate)c);
- }
- x509 = certChain.get(0);
- keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key);
-
- String testFile = "hello-world-unsigned.xlsx";
- try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
-
- SignatureConfig signatureConfig = new SignatureConfig();
- signatureConfig.setKey(keyPair.getPrivate());
- signatureConfig.setSigningCertificateChain(certChain);
- Calendar oldCal = LocaleUtil.getLocaleCalendar(2007, 7, 1);
- signatureConfig.setExecutionTime(oldCal.getTime());
- signatureConfig.setDigestAlgo(HashAlgorithm.sha1);
-
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(signatureConfig);
-
- si.confirmSignature();
-
- for (SignaturePart sp : si.getSignatureParts()) {
- assertTrue("Could not validate", sp.validate());
- X509Certificate signer = sp.getSigner();
- assertNotNull("signer undefined?!", signer);
- List<X509Certificate> certChainRes = sp.getCertChain();
- assertEquals(3, certChainRes.size());
- }
-
- }
- }
-
- @Test
- public void testNonSha1() throws Exception {
- String testFile = "hello-world-unsigned.xlsx";
- initKeyPair();
-
- SignatureConfig signatureConfig = new SignatureConfig();
- signatureConfig.setKey(keyPair.getPrivate());
- signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
-
- HashAlgorithm[] testAlgo = {HashAlgorithm.sha224, HashAlgorithm.sha256
- , HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.ripemd160};
-
- for (HashAlgorithm ha : testAlgo) {
- signatureConfig.setDigestAlgo(ha);
- try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(signatureConfig);
-
- si.confirmSignature();
- boolean b = si.verifySignature();
- assertTrue("Signature not correctly calculated for " + ha, b);
- } catch (EncryptedDocumentException e) {
- Assume.assumeTrue(e.getMessage().startsWith("Export Restrictions"));
- }
- }
- }
-
- @Test
- public void bug58630() throws Exception {
- // test deletion of sheet 0 and signing
- File tpl = copy(testdata.getFile("bug58630.xlsx"));
- try (SXSSFWorkbook wb1 = new SXSSFWorkbook((XSSFWorkbook)WorkbookFactory.create(tpl), 10)) {
- wb1.setCompressTempFiles(true);
- wb1.removeSheetAt(0);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- wb1.write(os);
-
- try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(os.toByteArray()))) {
- initKeyPair();
- SignatureConfig signatureConfig = new SignatureConfig();
- signatureConfig.setKey(keyPair.getPrivate());
- signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
-
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(signatureConfig);
- si.confirmSignature();
- assertTrue("invalid signature", si.verifySignature());
- }
- }
- }
-
- @Test
- public void testMultiSign() throws Exception {
- cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
- cal.clear();
- cal.setTimeZone(LocaleUtil.TIMEZONE_UTC);
- cal.set(2018, Calendar.DECEMBER, 14);
-
- // test signing with separate opened packages
- File tpl = copy(testdata.getFile("hello-world-unsigned.xlsx"));
- try (OPCPackage pkg = OPCPackage.open(tpl)) {
- signPkg63011(pkg, "bug63011_key1.pem", true);
- }
-
- try (OPCPackage pkg = OPCPackage.open(tpl)) {
- signPkg63011(pkg, "bug63011_key2.pem", true);
- }
-
- verifyPkg63011(tpl, true);
-
- // test signing with single opened package
- tpl = copy(testdata.getFile("hello-world-unsigned.xlsx"));
- try (OPCPackage pkg = OPCPackage.open(tpl)) {
- signPkg63011(pkg, "bug63011_key1.pem", true);
- signPkg63011(pkg, "bug63011_key2.pem", true);
- }
-
- verifyPkg63011(tpl, true);
-
- try (OPCPackage pkg = OPCPackage.open(tpl)) {
- signPkg63011(pkg, "bug63011_key1.pem", true);
- signPkg63011(pkg, "bug63011_key2.pem", false);
- }
-
- verifyPkg63011(tpl, false);
- }
-
- private void verifyPkg63011(File tpl, boolean multi) throws InvalidFormatException, IOException {
- try (OPCPackage pkg = OPCPackage.open(tpl, PackageAccess.READ)) {
- SignatureConfig sic = new SignatureConfig();
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(sic);
- List<X509Certificate> result = new ArrayList<>();
- for (SignaturePart sp : si.getSignatureParts()) {
- if (sp.validate()) {
- result.add(sp.getSigner());
- }
- }
-
- assertNotNull(result);
-
- if (multi) {
- assertEquals(2, result.size());
- assertEquals("CN=Muj Klic", result.get(0).getSubjectDN().toString());
- assertEquals("CN=My Second key", result.get(1).getSubjectDN().toString());
- } else {
- assertEquals(1, result.size());
- assertEquals("CN=My Second key", result.get(0).getSubjectDN().toString());
- }
-
- assertTrue(si.verifySignature());
- pkg.revert();
- }
- }
-
- private void signPkg63011(OPCPackage pkg, String pemFile, boolean multi)
- throws IOException, CertificateException, XMLSignatureException, MarshalException {
- assertNotNull(pkg);
- initKeyFromPEM(testdata.getFile(pemFile));
-
- SignatureConfig config = new SignatureConfig();
- config.setKey(keyPair.getPrivate());
- config.setSigningCertificateChain(Collections.singletonList(x509));
- config.setExecutionTime(cal.getTime());
- config.setAllowMultipleSignatures(multi);
-
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(config);
- si.confirmSignature();
- }
-
- @Test
- public void testRetrieveCertificate() throws InvalidFormatException, IOException {
- SignatureConfig sic = new SignatureConfig();
- final File file = testdata.getFile("PPT2016withComment.pptx");
- try (final OPCPackage pkg = OPCPackage.open(file, PackageAccess.READ)) {
- sic.setUpdateConfigOnValidate(true);
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkg);
- si.setSignatureConfig(sic);
- assertTrue(si.verifySignature());
- }
-
- final List<X509Certificate> certs = sic.getSigningCertificateChain();
- assertEquals(1, certs.size());
- assertEquals("CN=Test", certs.get(0).getSubjectDN().getName());
- assertEquals("SuperDuper-Reviewer", sic.getXadesRole());
- assertEquals("Purpose for signing", sic.getSignatureDescription());
- assertEquals("2018-06-10T09:00:54Z", sic.formatExecutionTime());
- assertEquals(CanonicalizationMethod.INCLUSIVE, sic.getCanonicalizationMethod());
- }
-
- private SignatureConfig prepareConfig(String pfxInput) throws Exception {
- initKeyPair(pfxInput);
-
- SignatureConfig signatureConfig = new SignatureConfig();
- signatureConfig.setKey(keyPair.getPrivate());
- signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
- signatureConfig.setExecutionTime(cal.getTime());
- signatureConfig.setDigestAlgo(HashAlgorithm.sha1);
-
- return signatureConfig;
- }
-
- private void sign(OPCPackage pkgCopy) throws Exception {
- int signerCount = 1;
-
- SignatureConfig signatureConfig = prepareConfig(null);
-
- SignatureInfo si = new SignatureInfo();
- si.setOpcPackage(pkgCopy);
- si.setSignatureConfig(signatureConfig);
-
- final Document document = DocumentHelper.createDocument();
- final DOMSignContext xmlSignContext = si.createXMLSignContext(document);
-
- // operate
- final DOMSignedInfo signedInfo = si.preSign(xmlSignContext);
-
- // verify
- assertNotNull(signedInfo);
- assertEquals("Office OpenXML Document", signatureConfig.getSignatureDescription());
-
- // setup: key material, signature value
- final String signatureValue = si.signDigest(xmlSignContext, signedInfo);
-
- // operate: postSign
- si.postSign(xmlSignContext, signatureValue);
-
- // verify: signature
- si.setOpcPackage(pkgCopy);
- List<X509Certificate> result = new ArrayList<>();
- for (SignaturePart sp : si.getSignatureParts()) {
- if (sp.validate()) {
- result.add(sp.getSigner());
- }
- }
- assertEquals(signerCount, result.size());
- }
-
- private void initKeyPair() throws Exception {
- initKeyPair(null);
- }
-
- private void initKeyPair(String pfxInput) throws Exception {
- final String alias = "Test";
- final char[] password = "test".toCharArray();
- File file = new File("build/test.pfx");
-
- KeyStore keystore = KeyStore.getInstance("PKCS12");
-
- if (pfxInput != null) {
- try (InputStream fis = new ByteArrayInputStream(RawDataUtil.decompress(pfxInput))) {
- keystore.load(fis, password);
- }
- } else if (file.exists()) {
- try (InputStream fis = new FileInputStream(file)) {
- keystore.load(fis, password);
- }
- } else {
- keystore.load(null, password);
- }
-
- if (keystore.isKeyEntry(alias)) {
- Key key = keystore.getKey(alias, password);
- x509 = (X509Certificate)keystore.getCertificate(alias);
- keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key);
- } else {
- keyPair = generateKeyPair();
- Date notBefore = cal.getTime();
- Calendar cal2 = (Calendar)cal.clone();
- cal2.add(Calendar.YEAR, 1);
- Date notAfter = cal2.getTime();
- KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature);
-
- x509 = generateCertificate(keyPair.getPublic(), notBefore, notAfter, keyPair.getPrivate(), keyUsage);
-
- keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509});
-
- if (pfxInput == null) {
- try (FileOutputStream fos = new FileOutputStream(file)) {
- keystore.store(fos, password);
- }
- }
- }
- }
-
- private void initKeyFromPEM(File pemFile) throws IOException, CertificateException {
- // see https://stackoverflow.com/questions/11787571/how-to-read-pem-file-to-get-private-and-public-key
- PrivateKey key = null;
- x509 = null;
-
- try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(pemFile), StandardCharsets.ISO_8859_1))) {
- PEMParser parser = new PEMParser(br);
- for (Object obj; (obj = parser.readObject()) != null; ) {
- if (obj instanceof PrivateKeyInfo) {
- key = new JcaPEMKeyConverter().setProvider("BC").getPrivateKey((PrivateKeyInfo)obj);
- } else if (obj instanceof X509CertificateHolder) {
- x509 = new JcaX509CertificateConverter().setProvider("BC").getCertificate((X509CertificateHolder)obj);
- }
- }
- }
-
- if (key != null && x509 != null) {
- keyPair = new KeyPair(x509.getPublicKey(), key);
- }
- }
-
- private static File copy(File input) throws IOException {
- String extension = input.getName().replaceAll(".*?(\\.[^.]+)?$", "$1");
- if (extension.isEmpty()) {
- extension = ".zip";
- }
-
- // ensure that we create the "build" directory as it might not be existing
- // in the Sonar Maven runs where we are at a different source directory
- File buildDir = new File("build");
- if(!buildDir.exists()) {
- assertTrue("Failed to create " + buildDir.getAbsolutePath(), buildDir.mkdirs());
- }
- File tmpFile = new File(buildDir, "sigtest"+extension);
-
- try (OutputStream fos = new FileOutputStream(tmpFile)) {
- try (InputStream fis = new FileInputStream(input)) {
- IOUtils.copy(fis, fos);
- }
- }
-
- return tmpFile;
- }
-
- private static KeyPair generateKeyPair() throws Exception {
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
- SecureRandom random = new SecureRandom();
- keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024,
- RSAKeyGenParameterSpec.F4), random);
- return keyPairGenerator.generateKeyPair();
- }
-
- private static X509Certificate generateCertificate(PublicKey subjectPublicKey,
- Date notBefore, Date notAfter,
- PrivateKey issuerPrivateKey,
- KeyUsage keyUsage)
- throws IOException, OperatorCreationException, CertificateException {
- final String signatureAlgorithm = "SHA1withRSA";
- final String subjectDn = "CN=Test";
- X500Name issuerName = new X500Name(subjectDn);
-
- RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey;
- RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent());
-
- SubjectPublicKeyInfo subjectPublicKeyInfo =
- SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaSpec);
-
- DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
- .setProvider("BC").build().get(CertificateID.HASH_SHA1);
-
- X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder(
- issuerName
- , new BigInteger(128, new SecureRandom())
- , notBefore
- , notAfter
- , new X500Name(subjectDn)
- , subjectPublicKeyInfo
- );
-
- X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc);
- SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo);
- AuthorityKeyIdentifier autKeyId = exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo);
-
- certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId);
- certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId);
-
- BasicConstraints bc = new BasicConstraints(0);
- certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
-
- if (null != keyUsage) {
- certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage);
- }
-
- JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlgorithm);
- signerBuilder.setProvider("BC");
-
- X509CertificateHolder certHolder =
- certificateGenerator.build(signerBuilder.build(issuerPrivateKey));
-
- /*
- * Next certificate factory trick is needed to make sure that the
- * certificate delivered to the caller is provided by the default
- * security provider instead of BouncyCastle. If we don't do this trick
- * we might run into trouble when trying to use the CertPath validator.
- */
-// CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
-// certificate = (X509Certificate) certificateFactory
-// .generateCertificate(new ByteArrayInputStream(certificate
-// .getEncoded()));
- return new JcaX509CertificateConverter().getCertificate(certHolder);
- }
-
- private static X509CRL generateCrl(X509Certificate issuer, PrivateKey issuerPrivateKey)
- throws CertificateEncodingException, IOException, CRLException, OperatorCreationException {
-
- X509CertificateHolder holder = new X509CertificateHolder(issuer.getEncoded());
- X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(holder.getIssuer(), new Date());
- crlBuilder.setNextUpdate(new Date(new Date().getTime() + 100000));
- JcaContentSignerBuilder contentBuilder = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC");
-
- CRLNumber crlNumber = new CRLNumber(new BigInteger("1234"));
-
- crlBuilder.addExtension(Extension.cRLNumber, false, crlNumber);
- X509CRLHolder x509Crl = crlBuilder.build(contentBuilder.build(issuerPrivateKey));
- return new JcaX509CRLConverter().setProvider("BC").getCRL(x509Crl);
- }
-
- private static OCSPResp createOcspResp(X509Certificate certificate,
- X509Certificate issuerCertificate,
- X509Certificate ocspResponderCertificate,
- PrivateKey ocspResponderPrivateKey,
- long nonceTimeinMillis)
- throws Exception {
- DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
- .setProvider("BC").build().get(CertificateID.HASH_SHA1);
- X509CertificateHolder issuerHolder = new X509CertificateHolder(issuerCertificate.getEncoded());
- CertificateID certId = new CertificateID(digestCalc, issuerHolder, certificate.getSerialNumber());
-
- // request
- //create a nonce to avoid replay attack
- BigInteger nonce = BigInteger.valueOf(nonceTimeinMillis);
- DEROctetString nonceDer = new DEROctetString(nonce.toByteArray());
- Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer);
- Extensions exts = new Extensions(ext);
-
- OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
- ocspReqBuilder.addRequest(certId);
- ocspReqBuilder.setRequestExtensions(exts);
- OCSPReq ocspReq = ocspReqBuilder.build();
-
-
- SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo
- (CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded());
-
- BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc);
- basicOCSPRespBuilder.setResponseExtensions(exts);
-
- // request processing
- Req[] requestList = ocspReq.getRequestList();
- for (Req ocspRequest : requestList) {
- CertificateID certificateID = ocspRequest.getCertID();
- CertificateStatus certificateStatus = CertificateStatus.GOOD;
- basicOCSPRespBuilder.addResponse(certificateID, certificateStatus);
- }
-
- // basic response generation
- X509CertificateHolder[] chain = null;
- if (!ocspResponderCertificate.equals(issuerCertificate)) {
- // TODO: HorribleProxy can't convert array input params yet
- chain = new X509CertificateHolder[] {
- new X509CertificateHolder(ocspResponderCertificate.getEncoded()),
- issuerHolder
- };
- }
-
- ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA")
- .setProvider("BC").build(ocspResponderPrivateKey);
- BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis));
-
-
- OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
-
- return ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp);
- }
-}
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+/* ====================================================================
+ This product contains an ASLv2 licensed version of the OOXML signer
+ package from the eID Applet project
+ http://code.google.com/p/eid-applet/source/browse/trunk/README.txt
+ Copyright (C) 2008-2014 FedICT.
+ ================================================================= */
+package org.apache.poi.poifs.crypt.dsig;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.net.ConnectException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.CRLException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAKeyGenParameterSpec;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.crypto.MarshalException;
+import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.XMLSignatureException;
+import javax.xml.crypto.dsig.dom.DOMSignContext;
+
+import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.ooxml.util.DocumentHelper;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackageAccess;
+import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
+import org.apache.poi.poifs.crypt.CryptoFunctions;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
+import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;
+import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
+import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;
+import org.apache.poi.poifs.storage.RawDataUtil;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.LocaleUtil;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.xmlbeans.SystemProperties;
+import org.apache.xmlbeans.XmlObject;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.CRLNumber;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509CRLHolder;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.X509ExtensionUtils;
+import org.bouncycastle.cert.X509v2CRLBuilder;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.ocsp.BasicOCSPResp;
+import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
+import org.bouncycastle.cert.ocsp.CertificateID;
+import org.bouncycastle.cert.ocsp.CertificateStatus;
+import org.bouncycastle.cert.ocsp.OCSPReq;
+import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
+import org.bouncycastle.cert.ocsp.OCSPResp;
+import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
+import org.bouncycastle.cert.ocsp.Req;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
+import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.w3.x2000.x09.xmldsig.ReferenceType;
+import org.w3.x2000.x09.xmldsig.SignatureDocument;
+import org.w3c.dom.Document;
+
+public class TestSignatureInfo {
+ private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class);
+ private static final POIDataSamples testdata = POIDataSamples.getXmlDSignInstance();
+
+ private static Calendar cal;
+ private KeyPair keyPair;
+ private X509Certificate x509;
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @AfterClass
+ public static void removeUserLocale() {
+ LocaleUtil.resetUserLocale();
+ }
+
+ @BeforeClass
+ public static void initBouncy() {
+ CryptoFunctions.registerBouncyCastle();
+
+ // Set cal to now ... only set to fixed date for debugging ...
+ LocaleUtil.resetUserLocale();
+ LocaleUtil.resetUserTimeZone();
+
+ cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
+ assertNotNull(cal);
+
+ // don't run this test when we are using older Xerces as it triggers an XML Parser backwards compatibility issue
+ // in the xmlsec jar file
+ String additionalJar = System.getProperty("additionaljar");
+ //System.out.println("Having: " + additionalJar);
+ Assume.assumeTrue("Not running TestSignatureInfo because we are testing with additionaljar set to " + additionalJar,
+ additionalJar == null || additionalJar.trim().length() == 0);
+
+ System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");
+
+ // Set line.separator for bug61182
+ // System.setProperty("line.separator", "\n");
+ }
+
+ @Ignore("This test is very sensitive, it breaks with every little change to the produced XML")
+ @Test
+ public void bug61182() throws Exception {
+ final String pfxInput =
+ "H4sIAAAAAAAAAFXTfzzTeRwH8P2uGRmG6hKSmJh9a2HsuPy60VnHCEU6v86sieZH2Jr2qFl+s+ZHJ5tfUcfKb4uho/OjiFq1qTv5ceFyp0PqEK"+
+ "fH4+66++Pz+Dwer9fj8f7r9cRzEd4QMBTPRWxDIM14ZN47NfAWsJgL34Bx4at4Lvwdngvd9b8KqgbjQpGbMXzzgRGovytVFTBEzIXU47kQCd4U"+
+ "ofJPvHl8JwyTjRS55hbKoor3UJLDE1i/PcPKCBAIDATjQlKiK67XjVYdcnkZgD2txroiAUb8W9dtn57DvTsbM+3wIsdocXDEN7TdPKgaSl+tU1"+
+ "xq9oqiB5yMaZCPho8uUEbFU9U6u3N7lEMLTJGeA0RfX+5FMRrpXPFrbrlJ8uNUCE2H247P28Ckyfqlsy32yeKg/HTbH5JpqUDNw2B32+SaiRw7"+
+ "ofRMePUpaAoK7KYgmd5ZIc0rLLYjJBfOWCb28xlrGhbpJvdToFdqt5PXVjEz5YOJ6g7W0fskuKW9/iZP0yLEVpR9XkkHmb6tfpcE8YwCdWNCan"+
+ "LvAsco25JdF1j2/FLAMVU79HdOex07main90dy40511OZtTGZ+TdVd3lKZ7D3clEg9hLESHwSNnZ6239X4yLM4xYSElQ/hqSbwdmiozYG9PhF2"+
+ "Zf0XaZnxzTK0Iot+rJ3kYoxWTLE8DR9leV62Ywbtlg4mapYOxb3lT7fQ1x4EQ44flh2oFWSPLR8LMbsc6jzJsV6OZ3TrODjHEdw9W+8OD32vd8"+
+ "XQ6iCaIHcrSOn6qS0TKLr786234eeSAhvAQbEsVn7vrvc/487Be/O2e/+5Y5zRq2zAtz6pfcNyraJNDqMW1inNkgJ3t3VESbZ3pNzyl3KHILs0"+
+ "51dY6msDYSlWhw40TglXxj9rw95O6gFWIuN012W/vhS50jpKXcao4gc1aLaXtJXxirbRkpZ/0e7a0pD6TDa7+GxEdEEML3VGo9udD5YUKhU3y7"+
+ "SzWAgN6WIEIglq7LilvCjqIVLIfg8CvVGL9f5iSsCDf5hef4vMxbyvcjINuy06gZu+iPYOWNxjfrwKGYzoqqotK2aywgYVrPMh0JovfkDuN95n"+
+ "MdVlYHbN1Mnn4TxAwuv+u3AkBlDZvRUUCwoDMUGxeMNPhTaAgWl60xhhBgCBaEMgAACReMAav7n3x598IDYJ9GxGXRAwaPOT/kfO/1AgPqLQkp"+
+ "MiIVaHthnUS4v2y32e2BjdMPyIImUTBW3cV3R5tjVQm0MOm+D2C5+bBW9vHLjLR4lun4toQiY3Ls/v4bES/OJ4EmpZk5xhL9i5ClofYZNEsxFn"+
+ "An/q821Tg+Cq9Er4XYGQe8ogjjLJ2b7dUsJ3auFQFNUJF7Ke7yUL2EeYYxl6vz5l4q5u8704mRbFts1E1eWMp6WIy91GPrsVlRGvtuNERfrjfE"+
+ "YtzUI3Flcv65zJUbUBEzUnTS0fEYso2XyToAl8kb251mUY2o2lJzv5dp/1htmcjeeP2MjxC+3S45ljx7jd52Pv9XAat+ryiauFOF7YgztkoWWD"+
+ "h62tplPH1bzDV+d0NLdaE5AfVJ09HuUYTFS+iggtvT5Euyk+unj4N2XvzW91n+GNjtgWfKOHmkinUPvYRh70Jv+wlPJrVaT8mL7GxJLqDC9jbv"+
+ "Gznoiae6es+wQejnk3XjU366MrK/zXxngBYj9J6NnXc9mMiTFLX8WqQ8iTelTAFs2NJzPoDzrBUz4JFIEOa6Dja6dULc68g1jFDTeEHZyra7RZ"+
+ "2ElqGDEqcNRo3SNX6feMy9EF1GOyZK0Sa87KwjKw8aM68dpsIYjfLcTXaZ6atg0BKfMnl6axeUGEaIFSP7rzj9wjzumRbG3jgUVp2lX5AK/tsO"+
+ "7R4TQX/9/H6RiN34c9KldmPZZGANXzzTajZS9mR2OSvlJ+F4AgSko4htrMAKFTBu51/5SWNsO1vlRaaG48ZRJ+8PzuHQMdvS36gNpRPi7jhF1S"+
+ "H3B2ycI4y0VURv6SrqJNUY/X645ZFJQ+eBO+ptG7o8axf1dcqh2beiQk+GRTeZ37LVeUlaeo9vl1/+8tyBfyT2v5lFC5E19WdKIyCuZe7r99Px"+
+ "D/Od4Qj0TA92+DQnbCQTCMy/wwse9O4gsEebkkpPIP5GBV3Q0YBsj75XE0uSFQ1tCZSW8bNa9MUJZ/nPBfExohHlgGAAA=";
+
+ // Unix
+ final String unixSignExp =
+ "QkqTFQZjXagjRAoOWKpAGa8AR0rKqkSfBtfSWqtjBmTgyjarn+t2POHkpySIpheHAbg+90GKSH88ACMtPHbG7q" +
+ "FL4gtgAD9Kjew6j16j0IRBwy145UlPrSLFMfF7YF7UlU1k1LBkIlRJ6Fv4MAJl6XspuzZOZIUmHZrWrdxycUQ=";
+
+ // Windows
+ final String winSignExp =
+ "GmAlL7+bT1r3FsMHJOp3pKg8betblYieZTjhMIrPZPRBbSzjO7KsYRGNtr0aOE3qr8xzyYJN6/8QdF5X7pUEUc" +
+ "2m8ctrm7s5o2vZTkAqk9ENJGDjBPXX7TnuVOiVeL1cJdtjHC2QpjtRwkFR+B54G6b1OXLOFuQpP3vqR3+/XXE=";
+
+ // Mac
+ final String macSignExp =
+ "NZedY/LNTYU4nAUEUhIOg5+fKdgVtzRXKmdD3v+47E7Mb84oeiUGv9cCEE91DU3StF/JFIhjOJqavOzKnCsNcz" +
+ "NJ4j/inggUl1OJUsicqIGQnA7E8vzWnN1kf5lINgJLv+0PyrrX9sQZbItzxUpgqyOFYcD0trid+31nRt4wtaA=";
+
+
+
+ Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
+ cal.clear();
+ cal.setTimeZone(LocaleUtil.TIMEZONE_UTC);
+ cal.set(2017, Calendar.JULY, 1);
+
+ SignatureConfig signatureConfig = prepareConfig(pfxInput);
+ signatureConfig.setExecutionTime(cal.getTime());
+
+ SignatureInfo si = new SignatureInfo();
+ si.setSignatureConfig(signatureConfig);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(100000);
+ try (XSSFWorkbook wb1 = new XSSFWorkbook()) {
+ wb1.createSheet().createRow(1).createCell(1).setCellValue("Test");
+ wb1.write(bos);
+ }
+
+ try (OPCPackage pkg1 = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()))) {
+ si.setOpcPackage(pkg1);
+ si.confirmSignature();
+ assertTrue(si.verifySignature());
+ bos.reset();
+ pkg1.save(bos);
+ }
+
+ try (XSSFWorkbook wb2 = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) {
+ assertEquals("Test", wb2.getSheetAt(0).getRow(1).getCell(1).getStringCellValue());
+ OPCPackage pkg2 = wb2.getPackage();
+ si.setOpcPackage(pkg2);
+ assertTrue(si.verifySignature());
+
+ // xmlbeans adds line-breaks depending on the system setting, so we get different
+ // test results on Unix/Mac/Windows
+ // if the xml documents eventually change, this test needs to be run with the
+ // separator set to the various system configurations
+ String sep = SystemProperties.getProperty("line.separator");
+ String signExp;
+ assumeTrue("Hashes only known for Windows/Unix/Mac", sep == null || "\n".equals(sep) || "\r\n".equals(sep) || "\r".equals(sep));
+ signExp = (sep == null || "\n".equals(sep)) ? unixSignExp : ("\r\n".equals(sep)) ? winSignExp : macSignExp;
+
+ String signAct = si.getSignatureParts().iterator().next().
+ getSignatureDocument().getSignature().getSignatureValue().getStringValue();
+ assertEquals(signExp, signAct);
+ }
+ }
+
+ @Test
+ public void office2007prettyPrintedRels() throws Exception {
+ try (OPCPackage pkg = OPCPackage.open(testdata.getFile("office2007prettyPrintedRels.docx"), PackageAccess.READ)) {
+ SignatureConfig sic = new SignatureConfig();
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(sic);
+ boolean isValid = si.verifySignature();
+ assertTrue(isValid);
+ }
+ }
+
+ @Test
+ public void getSignerUnsigned() throws Exception {
+ String[] testFiles = {
+ "hello-world-unsigned.docx",
+ "hello-world-unsigned.pptx",
+ "hello-world-unsigned.xlsx",
+ "hello-world-office-2010-technical-preview-unsigned.docx"
+ };
+
+ for (String testFile : testFiles) {
+ List<X509Certificate> result = new ArrayList<>();
+ try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
+ SignatureConfig sic = new SignatureConfig();
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(sic);
+ for (SignaturePart sp : si.getSignatureParts()) {
+ if (sp.validate()) {
+ result.add(sp.getSigner());
+ }
+ }
+ pkg.revert();
+ }
+ assertNotNull(result);
+ assertTrue(result.isEmpty());
+ }
+ }
+
+ @Test
+ public void getSigner() throws Exception {
+ String[] testFiles = {
+ "hyperlink-example-signed.docx",
+ "hello-world-signed.docx",
+ "hello-world-signed.pptx",
+ "hello-world-signed.xlsx",
+ "hello-world-office-2010-technical-preview.docx",
+ "ms-office-2010-signed.docx",
+ "ms-office-2010-signed.pptx",
+ "ms-office-2010-signed.xlsx",
+ "Office2010-SP1-XAdES-X-L.docx",
+ "signed.docx"
+ };
+
+ for (String testFile : testFiles) {
+ try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
+ SignatureConfig sic = new SignatureConfig();
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(sic);
+ List<X509Certificate> result = new ArrayList<>();
+ for (SignaturePart sp : si.getSignatureParts()) {
+ if (sp.validate()) {
+ result.add(sp.getSigner());
+ }
+ }
+
+ assertNotNull(result);
+ assertEquals("test-file: " + testFile, 1, result.size());
+ X509Certificate signer = result.get(0);
+ LOG.log(POILogger.DEBUG, "signer: " + signer.getSubjectX500Principal());
+
+ boolean b = si.verifySignature();
+ assertTrue("test-file: " + testFile, b);
+ pkg.revert();
+ }
+ }
+ }
+
+ @Test
+ public void getMultiSigners() throws Exception {
+ String testFile = "hello-world-signed-twice.docx";
+ try (OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ)) {
+ SignatureConfig sic = new SignatureConfig();
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(sic);
+ List<X509Certificate> result = new ArrayList<>();
+ for (SignaturePart sp : si.getSignatureParts()) {
+ if (sp.validate()) {
+ result.add(sp.getSigner());
+ }
+ }
+
+ assertNotNull(result);
+ assertEquals("test-file: " + testFile, 2, result.size());
+ X509Certificate signer1 = result.get(0);
+ X509Certificate signer2 = result.get(1);
+ LOG.log(POILogger.DEBUG, "signer 1: " + signer1.getSubjectX500Principal());
+ LOG.log(POILogger.DEBUG, "signer 2: " + signer2.getSubjectX500Principal());
+
+ boolean b = si.verifySignature();
+ assertTrue("test-file: " + testFile, b);
+ pkg.revert();
+ }
+ }
+
+ @Test
+ public void testSignSpreadsheet() throws Exception {
+ String testFile = "hello-world-unsigned.xlsx";
+ try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
+ sign(pkg);
+ }
+ }
+
+ private static class CommitableWorkbook extends XSSFWorkbook {
+ CommitableWorkbook(OPCPackage pkg) throws IOException {
+ super(pkg);
+ }
+ public void commit() throws IOException {
+ super.commit();
+ }
+ }
+
+ @Test
+ public void testManipulation() throws Exception {
+ // sign & validate
+ String testFile = "hello-world-unsigned.xlsx";
+ try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
+ sign(pkg);
+
+ // manipulate
+ try (CommitableWorkbook wb = new CommitableWorkbook(pkg)) {
+ wb.setSheetName(0, "manipulated");
+ // ... I don't know, why commit is protected ...
+ wb.commit();
+
+ // todo: test a manipulation on a package part, which is not signed
+ // ... maybe in combination with #56164
+
+ // validate
+ SignatureConfig sic = new SignatureConfig();
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(sic);
+ boolean b = si.verifySignature();
+ assertFalse("signature should be broken", b);
+ }
+ }
+ }
+
+ @Test
+ public void testSignSpreadsheetWithSignatureInfo() throws Exception {
+ initKeyPair();
+ String testFile = "hello-world-unsigned.xlsx";
+ try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
+ SignatureConfig sic = new SignatureConfig();
+ sic.setKey(keyPair.getPrivate());
+ sic.setSigningCertificateChain(Collections.singletonList(x509));
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(sic);
+ // hash > sha1 doesn't work in excel viewer ...
+ si.confirmSignature();
+ List<X509Certificate> result = new ArrayList<>();
+ for (SignaturePart sp : si.getSignatureParts()) {
+ if (sp.validate()) {
+ result.add(sp.getSigner());
+ }
+ }
+ assertEquals(1, result.size());
+ }
+ }
+
+ @Test
+ public void testSignEnvelopingDocument() throws Exception {
+ String testFile = "hello-world-unsigned.xlsx";
+ File sigCopy = testdata.getFile(testFile);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(50000);
+
+ final String execTimestr;
+
+
+ try (OPCPackage pkg = OPCPackage.open(copy(sigCopy), PackageAccess.READ_WRITE)) {
+
+ initKeyPair();
+ final X509CRL crl = generateCrl(x509, keyPair.getPrivate());
+
+ // setup
+ SignatureConfig signatureConfig = new SignatureConfig();
+ signatureConfig.setKey(keyPair.getPrivate());
+
+ /*
+ * We need at least 2 certificates for the XAdES-C complete certificate
+ * refs construction.
+ */
+ List<X509Certificate> certificateChain = new ArrayList<>();
+ certificateChain.add(x509);
+ certificateChain.add(x509);
+ signatureConfig.setSigningCertificateChain(certificateChain);
+
+ signatureConfig.addSignatureFacet(new OOXMLSignatureFacet());
+ signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet());
+ signatureConfig.addSignatureFacet(new KeyInfoSignatureFacet());
+ signatureConfig.addSignatureFacet(new XAdESSignatureFacet());
+ signatureConfig.addSignatureFacet(new XAdESXLSignatureFacet());
+
+ // check for internet, no error means it works
+ boolean mockTsp = (getAccessError("http://timestamp.comodoca.com/rfc3161", true, 10000) != null);
+
+ // http://timestamping.edelweb.fr/service/tsp
+ // http://tsa.belgium.be/connect
+ // http://timestamp.comodoca.com/authenticode
+ // http://timestamp.comodoca.com/rfc3161
+ // http://services.globaltrustfinder.com/adss/tsa
+ signatureConfig.setTspUrl("http://timestamp.comodoca.com/rfc3161");
+ signatureConfig.setTspRequestPolicy(null); // comodoca request fails, if default policy is set ...
+ signatureConfig.setTspOldProtocol(false);
+
+ signatureConfig.setXadesDigestAlgo(HashAlgorithm.sha512);
+ signatureConfig.setXadesRole("Xades Reviewer");
+ signatureConfig.setSignatureDescription("test xades signature");
+
+ execTimestr = signatureConfig.formatExecutionTime();
+
+ //set proxy info if any
+ String proxy = System.getProperty("http_proxy");
+ if (proxy != null && proxy.trim().length() > 0) {
+ signatureConfig.setProxyUrl(proxy);
+ }
+
+ if (mockTsp) {
+ TimeStampService tspService = (signatureInfo, data, revocationData) -> {
+ revocationData.addCRL(crl);
+ return "time-stamp-token".getBytes(LocaleUtil.CHARSET_1252);
+ };
+ signatureConfig.setTspService(tspService);
+ } else {
+ TimeStampServiceValidator tspValidator = (validateChain, revocationData) -> {
+ for (X509Certificate certificate : validateChain) {
+ LOG.log(POILogger.DEBUG, "certificate: " + certificate.getSubjectX500Principal());
+ LOG.log(POILogger.DEBUG, "validity: " + certificate.getNotBefore() + " - " + certificate.getNotAfter());
+ }
+ };
+ signatureConfig.setTspValidator(tspValidator);
+ signatureConfig.setTspOldProtocol(signatureConfig.getTspUrl().contains("edelweb"));
+ }
+
+ final RevocationData revocationData = new RevocationData();
+ revocationData.addCRL(crl);
+ OCSPResp ocspResp = createOcspResp(x509, x509, x509, keyPair.getPrivate(), cal.getTimeInMillis());
+ revocationData.addOCSP(ocspResp.getEncoded());
+
+ RevocationDataService revocationDataService = revocationChain -> revocationData;
+ signatureConfig.setRevocationDataService(revocationDataService);
+
+ // operate
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(signatureConfig);
+ try {
+ si.confirmSignature();
+ } catch (RuntimeException e) {
+ // only allow a ConnectException because of timeout, we see this in Jenkins from time to time...
+ if (e.getCause() == null) {
+ throw e;
+ }
+ if ((e.getCause() instanceof ConnectException) || (e.getCause() instanceof SocketTimeoutException)) {
+ Assume.assumeFalse("Only allowing ConnectException with 'timed out' as message here, but had: " + e,
+ e.getCause().getMessage().contains("timed out"));
+ } else if (e.getCause() instanceof IOException) {
+ Assume.assumeFalse("Only allowing IOException with 'Error contacting TSP server' as message here, but had: " + e,
+ e.getCause().getMessage().contains("Error contacting TSP server"));
+ } else if (e.getCause() instanceof RuntimeException) {
+ Assume.assumeFalse("Only allowing RuntimeException with 'This site is cur' as message here, but had: " + e,
+ e.getCause().getMessage().contains("This site is cur"));
+ }
+ throw e;
+ }
+
+ // verify
+ Iterator<SignaturePart> spIter = si.getSignatureParts().iterator();
+ assertTrue("Had: " + pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN), spIter.hasNext());
+ SignaturePart sp = spIter.next();
+ boolean valid = sp.validate();
+ assertTrue(valid);
+
+ SignatureDocument sigDoc = sp.getSignatureDocument();
+ String declareNS =
+ "declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; "
+ + "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; ";
+
+ String digestValXQuery = declareNS +
+ "$this/ds:Signature/ds:SignedInfo/ds:Reference";
+ for (ReferenceType rt : (ReferenceType[]) sigDoc.selectPath(digestValXQuery)) {
+ assertNotNull(rt.getDigestValue());
+ assertEquals(signatureConfig.getDigestMethodUri(), rt.getDigestMethod().getAlgorithm());
+ }
+
+ String certDigestXQuery = declareNS +
+ "$this//xades:SigningCertificate/xades:Cert/xades:CertDigest";
+ XmlObject[] xoList = sigDoc.selectPath(certDigestXQuery);
+ assertEquals(xoList.length, 1);
+ DigestAlgAndValueType certDigest = (DigestAlgAndValueType) xoList[0];
+ assertNotNull(certDigest.getDigestValue());
+
+ String qualPropXQuery = declareNS +
+ "$this/ds:Signature/ds:Object/xades:QualifyingProperties";
+ xoList = sigDoc.selectPath(qualPropXQuery);
+ assertEquals(xoList.length, 1);
+ QualifyingPropertiesType qualProp = (QualifyingPropertiesType) xoList[0];
+ boolean qualPropXsdOk = qualProp.validate();
+ assertTrue(qualPropXsdOk);
+
+ pkg.save(bos);
+ }
+
+ try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(bos.toByteArray()))) {
+ SignatureConfig signatureConfig = new SignatureConfig();
+ signatureConfig.setUpdateConfigOnValidate(true);
+
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(signatureConfig);
+
+ assertTrue(si.verifySignature());
+
+ assertEquals(HashAlgorithm.sha512, signatureConfig.getXadesDigestAlgo());
+ assertEquals("Xades Reviewer", signatureConfig.getXadesRole());
+ assertEquals("test xades signature", signatureConfig.getSignatureDescription());
+ assertEquals(execTimestr, signatureConfig.formatExecutionTime());
+ }
+ }
+
+ public static String getAccessError(String destinationUrl, boolean fireRequest, int timeout) {
+ URL url;
+ try {
+ url = new URL(destinationUrl);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException("Invalid destination URL", e);
+ }
+
+ HttpURLConnection conn = null;
+ try {
+ conn = (HttpURLConnection) url.openConnection();
+
+ // set specified timeout if non-zero
+ if(timeout != 0) {
+ conn.setConnectTimeout(timeout);
+ conn.setReadTimeout(timeout);
+ }
+
+ conn.setDoOutput(false);
+ conn.setDoInput(true);
+
+ /* if connecting is not possible this will throw a connection refused exception */
+ conn.connect();
+
+ if (fireRequest) {
+ conn.getInputStream().close();
+ }
+ /* if connecting is possible we return true here */
+ return null;
+
+ } catch (IOException e) {
+ /* exception is thrown -> server not available */
+ return e.getClass().getName() + ": " + e.getMessage();
+ } finally {
+ if (conn != null) {
+ conn.disconnect();
+ }
+ }
+ }
+
+ @Test
+ public void testCertChain() throws Exception {
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+ String password = "test";
+ try (InputStream is = testdata.openResourceAsStream("chaintest.pfx")) {
+ keystore.load(is, password.toCharArray());
+ }
+
+ Key key = keystore.getKey("poitest", password.toCharArray());
+ Certificate[] chainList = keystore.getCertificateChain("poitest");
+ List<X509Certificate> certChain = new ArrayList<>();
+ for (Certificate c : chainList) {
+ certChain.add((X509Certificate)c);
+ }
+ x509 = certChain.get(0);
+ keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key);
+
+ String testFile = "hello-world-unsigned.xlsx";
+ try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
+
+ SignatureConfig signatureConfig = new SignatureConfig();
+ signatureConfig.setKey(keyPair.getPrivate());
+ signatureConfig.setSigningCertificateChain(certChain);
+ Calendar oldCal = LocaleUtil.getLocaleCalendar(2007, 7, 1);
+ signatureConfig.setExecutionTime(oldCal.getTime());
+ signatureConfig.setDigestAlgo(HashAlgorithm.sha1);
+
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(signatureConfig);
+
+ si.confirmSignature();
+
+ for (SignaturePart sp : si.getSignatureParts()) {
+ assertTrue("Could not validate", sp.validate());
+ X509Certificate signer = sp.getSigner();
+ assertNotNull("signer undefined?!", signer);
+ List<X509Certificate> certChainRes = sp.getCertChain();
+ assertEquals(3, certChainRes.size());
+ }
+
+ }
+ }
+
+ @Test
+ public void testNonSha1() throws Exception {
+ String testFile = "hello-world-unsigned.xlsx";
+ initKeyPair();
+
+ SignatureConfig signatureConfig = new SignatureConfig();
+ signatureConfig.setKey(keyPair.getPrivate());
+ signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
+
+ HashAlgorithm[] testAlgo = {HashAlgorithm.sha224, HashAlgorithm.sha256
+ , HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.ripemd160};
+
+ for (HashAlgorithm ha : testAlgo) {
+ signatureConfig.setDigestAlgo(ha);
+ try (OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE)) {
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(signatureConfig);
+
+ si.confirmSignature();
+ boolean b = si.verifySignature();
+ assertTrue("Signature not correctly calculated for " + ha, b);
+ } catch (EncryptedDocumentException e) {
+ Assume.assumeTrue(e.getMessage().startsWith("Export Restrictions"));
+ }
+ }
+ }
+
+ @Test
+ public void bug58630() throws Exception {
+ // test deletion of sheet 0 and signing
+ File tpl = copy(testdata.getFile("bug58630.xlsx"));
+ try (SXSSFWorkbook wb1 = new SXSSFWorkbook((XSSFWorkbook)WorkbookFactory.create(tpl), 10)) {
+ wb1.setCompressTempFiles(true);
+ wb1.removeSheetAt(0);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ wb1.write(os);
+
+ try (OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(os.toByteArray()))) {
+ initKeyPair();
+ SignatureConfig signatureConfig = new SignatureConfig();
+ signatureConfig.setKey(keyPair.getPrivate());
+ signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
+
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(signatureConfig);
+ si.confirmSignature();
+ assertTrue("invalid signature", si.verifySignature());
+ }
+ }
+ }
+
+ @Test
+ public void testMultiSign() throws Exception {
+ cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
+ cal.clear();
+ cal.setTimeZone(LocaleUtil.TIMEZONE_UTC);
+ cal.set(2018, Calendar.DECEMBER, 14);
+
+ // test signing with separate opened packages
+ File tpl = copy(testdata.getFile("hello-world-unsigned.xlsx"));
+ try (OPCPackage pkg = OPCPackage.open(tpl)) {
+ signPkg63011(pkg, "bug63011_key1.pem", true);
+ }
+
+ try (OPCPackage pkg = OPCPackage.open(tpl)) {
+ signPkg63011(pkg, "bug63011_key2.pem", true);
+ }
+
+ verifyPkg63011(tpl, true);
+
+ // test signing with single opened package
+ tpl = copy(testdata.getFile("hello-world-unsigned.xlsx"));
+ try (OPCPackage pkg = OPCPackage.open(tpl)) {
+ signPkg63011(pkg, "bug63011_key1.pem", true);
+ signPkg63011(pkg, "bug63011_key2.pem", true);
+ }
+
+ verifyPkg63011(tpl, true);
+
+ try (OPCPackage pkg = OPCPackage.open(tpl)) {
+ signPkg63011(pkg, "bug63011_key1.pem", true);
+ signPkg63011(pkg, "bug63011_key2.pem", false);
+ }
+
+ verifyPkg63011(tpl, false);
+ }
+
+ private void verifyPkg63011(File tpl, boolean multi) throws InvalidFormatException, IOException {
+ try (OPCPackage pkg = OPCPackage.open(tpl, PackageAccess.READ)) {
+ SignatureConfig sic = new SignatureConfig();
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(sic);
+ List<X509Certificate> result = new ArrayList<>();
+ for (SignaturePart sp : si.getSignatureParts()) {
+ if (sp.validate()) {
+ result.add(sp.getSigner());
+ }
+ }
+
+ assertNotNull(result);
+
+ if (multi) {
+ assertEquals(2, result.size());
+ assertEquals("CN=Muj Klic", result.get(0).getSubjectDN().toString());
+ assertEquals("CN=My Second key", result.get(1).getSubjectDN().toString());
+ } else {
+ assertEquals(1, result.size());
+ assertEquals("CN=My Second key", result.get(0).getSubjectDN().toString());
+ }
+
+ assertTrue(si.verifySignature());
+ pkg.revert();
+ }
+ }
+
+ private void signPkg63011(OPCPackage pkg, String pemFile, boolean multi)
+ throws IOException, CertificateException, XMLSignatureException, MarshalException {
+ assertNotNull(pkg);
+ initKeyFromPEM(testdata.getFile(pemFile));
+
+ SignatureConfig config = new SignatureConfig();
+ config.setKey(keyPair.getPrivate());
+ config.setSigningCertificateChain(Collections.singletonList(x509));
+ config.setExecutionTime(cal.getTime());
+ config.setAllowMultipleSignatures(multi);
+
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(config);
+ si.confirmSignature();
+ }
+
+ @Test
+ public void testRetrieveCertificate() throws InvalidFormatException, IOException {
+ SignatureConfig sic = new SignatureConfig();
+ final File file = testdata.getFile("PPT2016withComment.pptx");
+ try (final OPCPackage pkg = OPCPackage.open(file, PackageAccess.READ)) {
+ sic.setUpdateConfigOnValidate(true);
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkg);
+ si.setSignatureConfig(sic);
+ assertTrue(si.verifySignature());
+ }
+
+ final List<X509Certificate> certs = sic.getSigningCertificateChain();
+ assertEquals(1, certs.size());
+ assertEquals("CN=Test", certs.get(0).getSubjectDN().getName());
+ assertEquals("SuperDuper-Reviewer", sic.getXadesRole());
+ assertEquals("Purpose for signing", sic.getSignatureDescription());
+ assertEquals("2018-06-10T09:00:54Z", sic.formatExecutionTime());
+ assertEquals(CanonicalizationMethod.INCLUSIVE, sic.getCanonicalizationMethod());
+ }
+
+ private SignatureConfig prepareConfig(String pfxInput) throws Exception {
+ initKeyPair(pfxInput);
+
+ SignatureConfig signatureConfig = new SignatureConfig();
+ signatureConfig.setKey(keyPair.getPrivate());
+ signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
+ signatureConfig.setExecutionTime(cal.getTime());
+ signatureConfig.setDigestAlgo(HashAlgorithm.sha1);
+
+ return signatureConfig;
+ }
+
+ private void sign(OPCPackage pkgCopy) throws Exception {
+ int signerCount = 1;
+
+ SignatureConfig signatureConfig = prepareConfig(null);
+
+ SignatureInfo si = new SignatureInfo();
+ si.setOpcPackage(pkgCopy);
+ si.setSignatureConfig(signatureConfig);
+
+ final Document document = DocumentHelper.createDocument();
+ final DOMSignContext xmlSignContext = si.createXMLSignContext(document);
+
+ // operate
+ final DOMSignedInfo signedInfo = si.preSign(xmlSignContext);
+
+ // verify
+ assertNotNull(signedInfo);
+ assertEquals("Office OpenXML Document", signatureConfig.getSignatureDescription());
+
+ // setup: key material, signature value
+ final String signatureValue = si.signDigest(xmlSignContext, signedInfo);
+
+ // operate: postSign
+ si.postSign(xmlSignContext, signatureValue);
+
+ // verify: signature
+ si.setOpcPackage(pkgCopy);
+ List<X509Certificate> result = new ArrayList<>();
+ for (SignaturePart sp : si.getSignatureParts()) {
+ if (sp.validate()) {
+ result.add(sp.getSigner());
+ }
+ }
+ assertEquals(signerCount, result.size());
+ }
+
+ private void initKeyPair() throws Exception {
+ initKeyPair(null);
+ }
+
+ private void initKeyPair(String pfxInput) throws Exception {
+ final String alias = "Test";
+ final char[] password = "test".toCharArray();
+ File file = new File("build/test.pfx");
+
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+
+ if (pfxInput != null) {
+ try (InputStream fis = new ByteArrayInputStream(RawDataUtil.decompress(pfxInput))) {
+ keystore.load(fis, password);
+ }
+ } else if (file.exists()) {
+ try (InputStream fis = new FileInputStream(file)) {
+ keystore.load(fis, password);
+ }
+ } else {
+ keystore.load(null, password);
+ }
+
+ if (keystore.isKeyEntry(alias)) {
+ Key key = keystore.getKey(alias, password);
+ x509 = (X509Certificate)keystore.getCertificate(alias);
+ keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key);
+ } else {
+ keyPair = generateKeyPair();
+ Date notBefore = cal.getTime();
+ Calendar cal2 = (Calendar)cal.clone();
+ cal2.add(Calendar.YEAR, 1);
+ Date notAfter = cal2.getTime();
+ KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature);
+
+ x509 = generateCertificate(keyPair.getPublic(), notBefore, notAfter, keyPair.getPrivate(), keyUsage);
+
+ keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509});
+
+ if (pfxInput == null) {
+ try (FileOutputStream fos = new FileOutputStream(file)) {
+ keystore.store(fos, password);
+ }
+ }
+ }
+ }
+
+ private void initKeyFromPEM(File pemFile) throws IOException, CertificateException {
+ // see https://stackoverflow.com/questions/11787571/how-to-read-pem-file-to-get-private-and-public-key
+ PrivateKey key = null;
+ x509 = null;
+
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(pemFile), StandardCharsets.ISO_8859_1))) {
+ PEMParser parser = new PEMParser(br);
+ for (Object obj; (obj = parser.readObject()) != null; ) {
+ if (obj instanceof PrivateKeyInfo) {
+ key = new JcaPEMKeyConverter().setProvider("BC").getPrivateKey((PrivateKeyInfo)obj);
+ } else if (obj instanceof X509CertificateHolder) {
+ x509 = new JcaX509CertificateConverter().setProvider("BC").getCertificate((X509CertificateHolder)obj);
+ }
+ }
+ }
+
+ if (key != null && x509 != null) {
+ keyPair = new KeyPair(x509.getPublicKey(), key);
+ }
+ }
+
+ private static File copy(File input) throws IOException {
+ String extension = input.getName().replaceAll(".*?(\\.[^.]+)?$", "$1");
+ if (extension.isEmpty()) {
+ extension = ".zip";
+ }
+
+ // ensure that we create the "build" directory as it might not be existing
+ // in the Sonar Maven runs where we are at a different source directory
+ File buildDir = new File("build");
+ if(!buildDir.exists()) {
+ assertTrue("Failed to create " + buildDir.getAbsolutePath(), buildDir.mkdirs());
+ }
+ File tmpFile = new File(buildDir, "sigtest"+extension);
+
+ try (OutputStream fos = new FileOutputStream(tmpFile)) {
+ try (InputStream fis = new FileInputStream(input)) {
+ IOUtils.copy(fis, fos);
+ }
+ }
+
+ return tmpFile;
+ }
+
+ private static KeyPair generateKeyPair() throws Exception {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ SecureRandom random = new SecureRandom();
+ keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024,
+ RSAKeyGenParameterSpec.F4), random);
+ return keyPairGenerator.generateKeyPair();
+ }
+
+ private static X509Certificate generateCertificate(PublicKey subjectPublicKey,
+ Date notBefore, Date notAfter,
+ PrivateKey issuerPrivateKey,
+ KeyUsage keyUsage)
+ throws IOException, OperatorCreationException, CertificateException {
+ final String signatureAlgorithm = "SHA1withRSA";
+ final String subjectDn = "CN=Test";
+ X500Name issuerName = new X500Name(subjectDn);
+
+ RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey;
+ RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent());
+
+ SubjectPublicKeyInfo subjectPublicKeyInfo =
+ SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaSpec);
+
+ DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
+ .setProvider("BC").build().get(CertificateID.HASH_SHA1);
+
+ X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder(
+ issuerName
+ , new BigInteger(128, new SecureRandom())
+ , notBefore
+ , notAfter
+ , new X500Name(subjectDn)
+ , subjectPublicKeyInfo
+ );
+
+ X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc);
+ SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo);
+ AuthorityKeyIdentifier autKeyId = exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo);
+
+ certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId);
+ certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId);
+
+ BasicConstraints bc = new BasicConstraints(0);
+ certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
+
+ if (null != keyUsage) {
+ certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage);
+ }
+
+ JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlgorithm);
+ signerBuilder.setProvider("BC");
+
+ X509CertificateHolder certHolder =
+ certificateGenerator.build(signerBuilder.build(issuerPrivateKey));
+
+ /*
+ * Next certificate factory trick is needed to make sure that the
+ * certificate delivered to the caller is provided by the default
+ * security provider instead of BouncyCastle. If we don't do this trick
+ * we might run into trouble when trying to use the CertPath validator.
+ */
+// CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+// certificate = (X509Certificate) certificateFactory
+// .generateCertificate(new ByteArrayInputStream(certificate
+// .getEncoded()));
+ return new JcaX509CertificateConverter().getCertificate(certHolder);
+ }
+
+ private static X509CRL generateCrl(X509Certificate issuer, PrivateKey issuerPrivateKey)
+ throws CertificateEncodingException, IOException, CRLException, OperatorCreationException {
+
+ X509CertificateHolder holder = new X509CertificateHolder(issuer.getEncoded());
+ X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(holder.getIssuer(), new Date());
+ crlBuilder.setNextUpdate(new Date(new Date().getTime() + 100000));
+ JcaContentSignerBuilder contentBuilder = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC");
+
+ CRLNumber crlNumber = new CRLNumber(new BigInteger("1234"));
+
+ crlBuilder.addExtension(Extension.cRLNumber, false, crlNumber);
+ X509CRLHolder x509Crl = crlBuilder.build(contentBuilder.build(issuerPrivateKey));
+ return new JcaX509CRLConverter().setProvider("BC").getCRL(x509Crl);
+ }
+
+ private static OCSPResp createOcspResp(X509Certificate certificate,
+ X509Certificate issuerCertificate,
+ X509Certificate ocspResponderCertificate,
+ PrivateKey ocspResponderPrivateKey,
+ long nonceTimeinMillis)
+ throws Exception {
+ DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
+ .setProvider("BC").build().get(CertificateID.HASH_SHA1);
+ X509CertificateHolder issuerHolder = new X509CertificateHolder(issuerCertificate.getEncoded());
+ CertificateID certId = new CertificateID(digestCalc, issuerHolder, certificate.getSerialNumber());
+
+ // request
+ //create a nonce to avoid replay attack
+ BigInteger nonce = BigInteger.valueOf(nonceTimeinMillis);
+ DEROctetString nonceDer = new DEROctetString(nonce.toByteArray());
+ Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer);
+ Extensions exts = new Extensions(ext);
+
+ OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
+ ocspReqBuilder.addRequest(certId);
+ ocspReqBuilder.setRequestExtensions(exts);
+ OCSPReq ocspReq = ocspReqBuilder.build();
+
+
+ SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo
+ (CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded());
+
+ BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc);
+ basicOCSPRespBuilder.setResponseExtensions(exts);
+
+ // request processing
+ Req[] requestList = ocspReq.getRequestList();
+ for (Req ocspRequest : requestList) {
+ CertificateID certificateID = ocspRequest.getCertID();
+ CertificateStatus certificateStatus = CertificateStatus.GOOD;
+ basicOCSPRespBuilder.addResponse(certificateID, certificateStatus);
+ }
+
+ // basic response generation
+ X509CertificateHolder[] chain = null;
+ if (!ocspResponderCertificate.equals(issuerCertificate)) {
+ // TODO: HorribleProxy can't convert array input params yet
+ chain = new X509CertificateHolder[] {
+ new X509CertificateHolder(ocspResponderCertificate.getEncoded()),
+ issuerHolder
+ };
+ }
+
+ ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA")
+ .setProvider("BC").build(ocspResponderPrivateKey);
+ BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis));
+
+
+ OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
+
+ return ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.tests;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+
+/**
+ * Tests for org.apache.poi.poifs.crypt
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ TestEncryptionInfo.class
+ , TestDecryptor.class
+ , TestEncryptor.class
+ , TestAgileEncryptionParameters.class
+})
+public final class AllPOIFSCryptoTests {
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.tests;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.crypto.Cipher;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.EncryptionMode;
+import org.apache.poi.poifs.crypt.Encryptor;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.IOUtils;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class TestAgileEncryptionParameters {
+
+ static byte[] testData;
+
+ @Parameter(value = 0)
+ public CipherAlgorithm ca;
+ @Parameter(value = 1)
+ public HashAlgorithm ha;
+ @Parameter(value = 2)
+ public ChainingMode cm;
+
+ @Parameters(name="{0} {1} {2}")
+ public static Collection<Object[]> data() {
+ CipherAlgorithm[] caList = {CipherAlgorithm.aes128, CipherAlgorithm.aes192, CipherAlgorithm.aes256, CipherAlgorithm.rc2, CipherAlgorithm.des, CipherAlgorithm.des3};
+ HashAlgorithm[] haList = {HashAlgorithm.sha1, HashAlgorithm.sha256, HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.md5};
+ ChainingMode[] cmList = {ChainingMode.cbc, ChainingMode.cfb};
+
+ List<Object[]> data = new ArrayList<>();
+ for (CipherAlgorithm ca : caList) {
+ for (HashAlgorithm ha : haList) {
+ for (ChainingMode cm : cmList) {
+ data.add(new Object[]{ca,ha,cm});
+ }
+ }
+ }
+
+ return data;
+ }
+
+ @BeforeClass
+ public static void initTestData() throws Exception {
+ InputStream testFile = POIDataSamples.getDocumentInstance().openResourceAsStream("SampleDoc.docx");
+ testData = IOUtils.toByteArray(testFile);
+ testFile.close();
+ }
+
+ @Test
+ public void testAgileEncryptionModes() throws Exception {
+ int maxKeyLen = Cipher.getMaxAllowedKeyLength(ca.jceId);
+ Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files", maxKeyLen >= ca.defaultKeySize);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ POIFSFileSystem fsEnc = new POIFSFileSystem();
+ EncryptionInfo infoEnc = new EncryptionInfo(EncryptionMode.agile, ca, ha, -1, -1, cm);
+ Encryptor enc = infoEnc.getEncryptor();
+ enc.confirmPassword("foobaa");
+ OutputStream os = enc.getDataStream(fsEnc);
+ os.write(testData);
+ os.close();
+ bos.reset();
+ fsEnc.writeFilesystem(bos);
+ fsEnc.close();
+
+ POIFSFileSystem fsDec = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
+ EncryptionInfo infoDec = new EncryptionInfo(fsDec);
+ Decryptor dec = infoDec.getDecryptor();
+ boolean passed = dec.verifyPassword("foobaa");
+ assertTrue(passed);
+ InputStream is = dec.getDataStream(fsDec);
+ byte[] actualData = IOUtils.toByteArray(is);
+ is.close();
+ fsDec.close();
+ assertArrayEquals("Failed roundtrip - "+ca+"-"+ha+"-"+cm, testData, actualData);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.util.stream.IntStream;
+
+import javax.crypto.Cipher;
+
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.IOUtils;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class TestDecryptor {
+ private static final POIDataSamples samples = POIDataSamples.getPOIFSInstance();
+
+ @Test
+ public void passwordVerification() throws IOException, GeneralSecurityException {
+ try (InputStream is = samples.openResourceAsStream("protect.xlsx");
+ POIFSFileSystem fs = new POIFSFileSystem(is)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ Decryptor d = Decryptor.getInstance(info);
+ assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
+ }
+ }
+
+ @Test
+ public void decrypt() throws IOException, GeneralSecurityException {
+ try (InputStream is = samples.openResourceAsStream("protect.xlsx");
+ POIFSFileSystem fs = new POIFSFileSystem(is)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ Decryptor d = Decryptor.getInstance(info);
+ d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
+ zipOk(fs.getRoot(), d);
+ }
+ }
+
+ @Test
+ public void agile() throws IOException, GeneralSecurityException {
+ try (InputStream is = samples.openResourceAsStream("protected_agile.docx");
+ POIFSFileSystem fs = new POIFSFileSystem(is)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ assertTrue(info.getVersionMajor() == 4 && info.getVersionMinor() == 4);
+ Decryptor d = Decryptor.getInstance(info);
+ assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
+ zipOk(fs.getRoot(), d);
+ }
+ }
+
+ private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException {
+ try (ZipArchiveInputStream zin = new ZipArchiveInputStream(d.getDataStream(root))) {
+
+ while (true) {
+ ZipArchiveEntry entry = zin.getNextZipEntry();
+ if (entry == null) {
+ break;
+ }
+ // crc32 is checked within zip-stream
+ if (entry.isDirectory()) {
+ continue;
+ }
+ assertEquals(entry.getSize() - 1, zin.skip(entry.getSize() - 1));
+ byte[] buf = new byte[10];
+ int readBytes = zin.read(buf);
+ // zin.available() doesn't work for entries
+ assertEquals("size failed for " + entry.getName(), 1, readBytes);
+ }
+ }
+ }
+
+ @Test
+ public void dataLength() throws Exception {
+ try (InputStream fsIs = samples.openResourceAsStream("protected_agile.docx");
+ POIFSFileSystem fs = new POIFSFileSystem(fsIs)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ Decryptor d = Decryptor.getInstance(info);
+ d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
+
+ try (InputStream is = d.getDataStream(fs)) {
+
+ long len = d.getLength();
+ assertEquals(12810, len);
+
+ byte[] buf = new byte[(int) len];
+ assertEquals(12810, is.read(buf));
+
+ ZipArchiveInputStream zin = new ZipArchiveInputStream(new ByteArrayInputStream(buf));
+
+ while (true) {
+ ZipArchiveEntry entry = zin.getNextZipEntry();
+ if (entry==null) {
+ break;
+ }
+
+ IOUtils.toByteArray(zin);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void bug57080() throws Exception {
+ // the test file contains a wrong ole entry size, produced by extenxls
+ // the fix limits the available size and tries to read all entries
+ File f = samples.getFile("extenxls_pwd123.xlsx");
+
+ try (POIFSFileSystem fs = new POIFSFileSystem(f, true)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ Decryptor d = Decryptor.getInstance(info);
+ d.verifyPassword("pwd123");
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream(10000);
+ try (final ZipArchiveInputStream zis = new ZipArchiveInputStream(d.getDataStream(fs))) {
+ IntStream.of(3711, 1155, 445, 9376, 450, 588, 1337, 2593, 304, 7910).forEach(size -> {
+ try {
+ final ZipArchiveEntry ze = zis.getNextZipEntry();
+ assertNotNull(ze);
+ IOUtils.copy(zis, bos);
+ assertEquals(size, bos.size());
+ bos.reset();
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ });
+ }
+ }
+ }
+
+ @Test
+ public void test58616() throws IOException, GeneralSecurityException {
+ try (InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("58616.xlsx");
+ POIFSFileSystem pfs = new POIFSFileSystem(is)) {
+ EncryptionInfo info = new EncryptionInfo(pfs);
+ Decryptor dec = Decryptor.getInstance(info);
+ dec.getDataStream(pfs).close();
+ }
+ }
+
+ @Test
+ public void bug60320() throws IOException, GeneralSecurityException {
+ int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
+ Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647);
+
+ try (InputStream is = samples.openResourceAsStream("60320-protected.xlsx");
+ POIFSFileSystem fs = new POIFSFileSystem(is)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ Decryptor d = Decryptor.getInstance(info);
+ assertTrue(d.verifyPassword("Test001!!"));
+ zipOk(fs.getRoot(), d);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.CipherProvider;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestEncryptionInfo {
+ @Test
+ public void testEncryptionInfo() throws IOException {
+ POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx"));
+
+ EncryptionInfo info = new EncryptionInfo(fs);
+
+ assertEquals(3, info.getVersionMajor());
+ assertEquals(2, info.getVersionMinor());
+
+ Assert.assertEquals(CipherAlgorithm.aes128, info.getHeader().getCipherAlgorithm());
+ Assert.assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithm());
+ assertEquals(128, info.getHeader().getKeySize());
+ assertEquals(32, info.getVerifier().getEncryptedVerifierHash().length);
+ Assert.assertEquals(CipherProvider.aes, info.getHeader().getCipherProvider());
+ assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName());
+
+ fs.close();
+ }
+
+ @Test
+ public void testEncryptionInfoSHA512() throws Exception {
+ POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_sha512.xlsx"));
+
+ EncryptionInfo info = new EncryptionInfo(fs);
+
+ assertEquals(4, info.getVersionMajor());
+ assertEquals(4, info.getVersionMinor());
+
+ assertEquals(CipherAlgorithm.aes256, info.getHeader().getCipherAlgorithm());
+ assertEquals(HashAlgorithm.sha512, info.getHeader().getHashAlgorithm());
+ assertEquals(256, info.getHeader().getKeySize());
+ assertEquals(64, info.getVerifier().getEncryptedVerifierHash().length);
+ assertEquals(CipherProvider.aes, info.getHeader().getCipherProvider());
+// assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName());
+
+ fs.close();
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.tests;
+
+import static org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.DigestInputStream;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.util.Iterator;
+import java.util.Random;
+
+import javax.crypto.Cipher;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.openxml4j.opc.ContentTypes;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.EncryptionMode;
+import org.apache.poi.poifs.crypt.EncryptionVerifier;
+import org.apache.poi.poifs.crypt.Encryptor;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.crypt.agile.AgileDecryptor;
+import org.apache.poi.poifs.crypt.agile.AgileEncryptionHeader;
+import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.DocumentEntry;
+import org.apache.poi.poifs.filesystem.DocumentNode;
+import org.apache.poi.poifs.filesystem.Entry;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.poifs.filesystem.TempFilePOIFSFileSystem;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.NullOutputStream;
+import org.apache.poi.util.TempFile;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.junit.Assume;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class TestEncryptor {
+ @Test
+ public void binaryRC4Encryption() throws Exception {
+ // please contribute a real sample file, which is binary rc4 encrypted
+ // ... at least the output can be opened in Excel Viewer
+ String password = "pass";
+
+ final byte[] payloadExpected;
+ try (InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleMultiCell.xlsx")) {
+ payloadExpected = IOUtils.toByteArray(is);
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (POIFSFileSystem fs = new POIFSFileSystem()) {
+ EncryptionInfo ei = new EncryptionInfo(EncryptionMode.binaryRC4);
+ Encryptor enc = ei.getEncryptor();
+ enc.confirmPassword(password);
+
+ try (OutputStream os = enc.getDataStream(fs.getRoot())) {
+ os.write(payloadExpected);
+ }
+
+ fs.writeFilesystem(bos);
+ }
+
+ final byte[] payloadActual;
+ try (POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
+ EncryptionInfo ei = new EncryptionInfo(fs);
+ Decryptor dec = ei.getDecryptor();
+ boolean b = dec.verifyPassword(password);
+ assertTrue(b);
+
+ try (InputStream is = dec.getDataStream(fs.getRoot())) {
+ payloadActual = IOUtils.toByteArray(is);
+ }
+ }
+
+ assertArrayEquals(payloadExpected, payloadActual);
+ }
+
+ @Test
+ public void tempFileAgileEncryption() throws Exception {
+ String password = "pass";
+
+ final byte[] payloadExpected;
+ try (InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleMultiCell.xlsx")) {
+ payloadExpected = IOUtils.toByteArray(is);
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (POIFSFileSystem fs = new TempFilePOIFSFileSystem()) {
+ EncryptionInfo ei = new EncryptionInfo(EncryptionMode.agile);
+ Encryptor enc = ei.getEncryptor();
+ enc.confirmPassword(password);
+
+ try (OutputStream os = enc.getDataStream(fs.getRoot())) {
+ os.write(payloadExpected);
+ }
+
+ fs.writeFilesystem(bos);
+ }
+
+ final byte[] payloadActual;
+ try (POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
+ EncryptionInfo ei = new EncryptionInfo(fs);
+ Decryptor dec = ei.getDecryptor();
+ boolean b = dec.verifyPassword(password);
+ assertTrue(b);
+
+ try (InputStream is = dec.getDataStream(fs.getRoot())) {
+ payloadActual = IOUtils.toByteArray(is);
+ }
+ }
+
+ assertArrayEquals(payloadExpected, payloadActual);
+ }
+
+ @Test
+ public void agileEncryption() throws Exception {
+ int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
+ Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647);
+
+ File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-pass.docx");
+ String pass = "pass";
+
+ final byte[] payloadExpected, encPackExpected;
+ final long decPackLenExpected;
+ final EncryptionInfo infoExpected;
+ final Decryptor decExpected;
+
+ try (POIFSFileSystem nfs = new POIFSFileSystem(file, true)) {
+
+ // Check the encryption details
+ infoExpected = new EncryptionInfo(nfs);
+ decExpected = Decryptor.getInstance(infoExpected);
+ boolean passed = decExpected.verifyPassword(pass);
+ assertTrue("Unable to process: document is encrypted", passed);
+
+ // extract the payload
+ try (InputStream is = decExpected.getDataStream(nfs)) {
+ payloadExpected = IOUtils.toByteArray(is);
+ }
+
+ decPackLenExpected = decExpected.getLength();
+ assertEquals(decPackLenExpected, payloadExpected.length);
+
+ final DirectoryNode root = nfs.getRoot();
+ final DocumentEntry entry = (DocumentEntry)root.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
+ try (InputStream is = root.createDocumentInputStream(entry)) {
+ // ignore padding block
+ encPackExpected = IOUtils.toByteArray(is, entry.getSize()-16);
+ }
+ }
+
+ // check that same verifier/salt lead to same hashes
+ final byte[] verifierSaltExpected = infoExpected.getVerifier().getSalt();
+ final byte[] verifierExpected = decExpected.getVerifier();
+ final byte[] keySalt = infoExpected.getHeader().getKeySalt();
+ final byte[] keySpec = decExpected.getSecretKey().getEncoded();
+ final byte[] integritySalt = decExpected.getIntegrityHmacKey();
+ // the hmacs of the file always differ, as we use PKCS5-padding to pad the bytes
+ // whereas office just uses random bytes
+ // byte integrityHash[] = d.getIntegrityHmacValue();
+
+ final EncryptionInfo infoActual = new EncryptionInfo(
+ EncryptionMode.agile
+ , infoExpected.getVerifier().getCipherAlgorithm()
+ , infoExpected.getVerifier().getHashAlgorithm()
+ , infoExpected.getHeader().getKeySize()
+ , infoExpected.getHeader().getBlockSize()
+ , infoExpected.getVerifier().getChainingMode()
+ );
+
+ Encryptor e = Encryptor.getInstance(infoActual);
+ e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, integritySalt);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (POIFSFileSystem fs = new POIFSFileSystem()) {
+ try (OutputStream os = e.getDataStream(fs)) {
+ os.write(payloadExpected);
+ }
+ fs.writeFilesystem(bos);
+ }
+
+ final EncryptionInfo infoActual2;
+ final byte[] payloadActual, encPackActual;
+ final long decPackLenActual;
+ try (POIFSFileSystem nfs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
+ infoActual2 = new EncryptionInfo(nfs.getRoot());
+ Decryptor decActual = Decryptor.getInstance(infoActual2);
+ boolean passed = decActual.verifyPassword(pass);
+ assertTrue("Unable to process: document is encrypted", passed);
+
+ // extract the payload
+ try (InputStream is = decActual.getDataStream(nfs)) {
+ payloadActual = IOUtils.toByteArray(is);
+ }
+
+ decPackLenActual = decActual.getLength();
+
+ final DirectoryNode root = nfs.getRoot();
+ final DocumentEntry entry = (DocumentEntry)root.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
+ try (InputStream is = root.createDocumentInputStream(entry)) {
+ // ignore padding block
+ encPackActual = IOUtils.toByteArray(is, entry.getSize()-16);
+ }
+ }
+
+ AgileEncryptionHeader aehExpected = (AgileEncryptionHeader)infoExpected.getHeader();
+ AgileEncryptionHeader aehActual = (AgileEncryptionHeader)infoActual.getHeader();
+ assertArrayEquals(aehExpected.getEncryptedHmacKey(), aehActual.getEncryptedHmacKey());
+ assertEquals(decPackLenExpected, decPackLenActual);
+ assertArrayEquals(payloadExpected, payloadActual);
+ assertArrayEquals(encPackExpected, encPackActual);
+ }
+
+ @Test
+ public void standardEncryption() throws Exception {
+ File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-solrcell.docx");
+ final String pass = "solrcell";
+
+ final byte[] payloadExpected;
+ final EncryptionInfo infoExpected;
+ final Decryptor d;
+ try (POIFSFileSystem nfs = new POIFSFileSystem(file, true)) {
+
+ // Check the encryption details
+ infoExpected = new EncryptionInfo(nfs);
+ d = Decryptor.getInstance(infoExpected);
+ boolean passed = d.verifyPassword(pass);
+ assertTrue("Unable to process: document is encrypted", passed);
+
+ // extract the payload
+ try (InputStream is = d.getDataStream(nfs)) {
+ payloadExpected = IOUtils.toByteArray(is);
+ }
+ }
+
+ // check that same verifier/salt lead to same hashes
+ final byte[] verifierSaltExpected = infoExpected.getVerifier().getSalt();
+ final byte[] verifierExpected = d.getVerifier();
+ final byte[] keySpec = d.getSecretKey().getEncoded();
+ final byte[] keySalt = infoExpected.getHeader().getKeySalt();
+
+
+ final EncryptionInfo infoActual = new EncryptionInfo(
+ EncryptionMode.standard
+ , infoExpected.getVerifier().getCipherAlgorithm()
+ , infoExpected.getVerifier().getHashAlgorithm()
+ , infoExpected.getHeader().getKeySize()
+ , infoExpected.getHeader().getBlockSize()
+ , infoExpected.getVerifier().getChainingMode()
+ );
+
+ final Encryptor e = Encryptor.getInstance(infoActual);
+ e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, null);
+
+ assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifier(), infoActual.getVerifier().getEncryptedVerifier());
+ assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifierHash(), infoActual.getVerifier().getEncryptedVerifierHash());
+
+ // now we use a newly generated salt/verifier and check
+ // if the file content is still the same
+
+ final byte[] encBytes;
+ try (POIFSFileSystem fs = new POIFSFileSystem()) {
+
+ final EncryptionInfo infoActual2 = new EncryptionInfo(
+ EncryptionMode.standard
+ , infoExpected.getVerifier().getCipherAlgorithm()
+ , infoExpected.getVerifier().getHashAlgorithm()
+ , infoExpected.getHeader().getKeySize()
+ , infoExpected.getHeader().getBlockSize()
+ , infoExpected.getVerifier().getChainingMode()
+ );
+
+ final Encryptor e2 = Encryptor.getInstance(infoActual2);
+ e2.confirmPassword(pass);
+
+ try (OutputStream os = e2.getDataStream(fs)) {
+ os.write(payloadExpected);
+ }
+
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream(50000);
+ fs.writeFilesystem(bos);
+ encBytes = bos.toByteArray();
+ }
+
+ final byte[] payloadActual;
+ try (POIFSFileSystem nfs = new POIFSFileSystem(new ByteArrayInputStream(encBytes))) {
+ final EncryptionInfo ei = new EncryptionInfo(nfs);
+ Decryptor d2 = Decryptor.getInstance(ei);
+ assertTrue("Unable to process: document is encrypted", d2.verifyPassword(pass));
+
+ try (InputStream is = d2.getDataStream(nfs)) {
+ payloadActual = IOUtils.toByteArray(is);
+ }
+ }
+
+ assertArrayEquals(payloadExpected, payloadActual);
+ }
+
+ /**
+ * Ensure we can encrypt a package that is missing the Core
+ * Properties, eg one from dodgy versions of Jasper Reports
+ * See https://github.com/nestoru/xlsxenc/ and
+ * http://stackoverflow.com/questions/28593223
+ */
+ @Test
+ public void encryptPackageWithoutCoreProperties() throws Exception {
+ // Open our file without core properties
+ final byte[] encBytes;
+ try (InputStream is = POIDataSamples.getOpenXML4JInstance().openResourceAsStream("OPCCompliance_NoCoreProperties.xlsx");
+ OPCPackage pkg = OPCPackage.open(is)) {
+
+ // It doesn't have any core properties yet
+ assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size());
+ assertNotNull(pkg.getPackageProperties());
+ assertNotNull(pkg.getPackageProperties().getLanguageProperty());
+ assertFalse(pkg.getPackageProperties().getLanguageProperty().isPresent());
+
+ // Encrypt it
+ EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
+ Encryptor enc = info.getEncryptor();
+ enc.confirmPassword("password");
+
+ try (POIFSFileSystem fs = new POIFSFileSystem()) {
+
+ try (OutputStream os = enc.getDataStream(fs)) {
+ pkg.save(os);
+ }
+
+ // Save the resulting OLE2 document, and re-open it
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ fs.writeFilesystem(baos);
+ encBytes = baos.toByteArray();
+ }
+ }
+
+
+ try (POIFSFileSystem inpFS = new POIFSFileSystem(new ByteArrayInputStream(encBytes))) {
+ // Check we can decrypt it
+ EncryptionInfo info = new EncryptionInfo(inpFS);
+ Decryptor d = Decryptor.getInstance(info);
+ assertTrue(d.verifyPassword("password"));
+
+ try (OPCPackage inpPkg = OPCPackage.open(d.getDataStream(inpFS))) {
+ // Check it now has empty core properties
+ assertEquals(1, inpPkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size());
+ assertNotNull(inpPkg.getPackageProperties());
+ assertNotNull(inpPkg.getPackageProperties().getLanguageProperty());
+ assertFalse(inpPkg.getPackageProperties().getLanguageProperty().isPresent());
+
+ }
+ }
+ }
+
+ @Test
+ @Ignore
+ public void inPlaceRewrite() throws Exception {
+ File f = TempFile.createTempFile("protected_agile", ".docx");
+
+ try (FileOutputStream fos = new FileOutputStream(f);
+ InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx")) {
+ IOUtils.copy(fis, fos);
+ }
+
+ try (POIFSFileSystem fs = new POIFSFileSystem(f, false)) {
+
+ // decrypt the protected file - in this case it was encrypted with the default password
+ EncryptionInfo encInfo = new EncryptionInfo(fs);
+ Decryptor d = encInfo.getDecryptor();
+ boolean b = d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
+ assertTrue(b);
+
+ try (InputStream docIS = d.getDataStream(fs);
+ XWPFDocument docx = new XWPFDocument(docIS)) {
+
+ // do some strange things with it ;)
+ XWPFParagraph p = docx.getParagraphArray(0);
+ p.insertNewRun(0).setText("POI was here! All your base are belong to us!");
+ p.insertNewRun(1).addBreak();
+
+ // and encrypt it again
+ Encryptor e = encInfo.getEncryptor();
+ e.confirmPassword("AYBABTU");
+
+ try (OutputStream os = e.getDataStream(fs)) {
+ docx.write(os);
+ }
+ }
+ }
+ }
+
+
+ private void listEntry(DocumentNode de, String ext, String path) throws IOException {
+ path += "\\" + de.getName().replaceAll("[\\p{Cntrl}]", "_");
+ System.out.println(ext+": "+path+" ("+de.getSize()+" bytes)");
+
+ String name = de.getName().replaceAll("[\\p{Cntrl}]", "_");
+
+ InputStream is = ((DirectoryNode)de.getParent()).createDocumentInputStream(de);
+ FileOutputStream fos = new FileOutputStream("solr."+name+"."+ext);
+ IOUtils.copy(is, fos);
+ fos.close();
+ is.close();
+ }
+
+ @SuppressWarnings("unused")
+ private void listDir(DirectoryNode dn, String ext, String path) throws IOException {
+ path += "\\" + dn.getName().replace('\u0006', '_');
+ System.out.println(ext+": "+path+" ("+dn.getStorageClsid()+")");
+
+ Iterator<Entry> iter = dn.getEntries();
+ while (iter.hasNext()) {
+ Entry ent = iter.next();
+ if (ent instanceof DirectoryNode) {
+ listDir((DirectoryNode)ent, ext, path);
+ } else {
+ listEntry((DocumentNode)ent, ext, path);
+ }
+ }
+ }
+
+ /*
+ * this test simulates the generation of bugs 60320 sample file
+ * as the padding bytes of the EncryptedPackage stream are random or in POIs case PKCS5-padded
+ * one would need to mock those bytes to get the same hmacValues - see diff below
+ *
+ * this use-case is experimental - for the time being the setters of the encryption classes
+ * are spreaded between two packages and are protected - so you would need to violate
+ * the packages rules and provide a helper class in the *poifs.crypt package-namespace.
+ * the default way of defining the encryption settings is via the EncryptionInfo class
+ */
+ @Test
+ public void bug60320CustomEncrypt() throws Exception {
+ int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
+ Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647);
+
+ // --- src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (revision 1766745)
+ // +++ src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (working copy)
+ // @@ -208,6 +208,13 @@
+ // protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException {
+ // byte plain[] = (_plainByteFlags.isEmpty()) ? null : _chunk.clone();
+ //
+ // + if (posInChunk < 4096) {
+ // + _cipher.update(_chunk, 0, posInChunk, _chunk);
+ // + byte bla[] = { (byte)0x7A,(byte)0x0F,(byte)0x27,(byte)0xF0,(byte)0x17,(byte)0x6E,(byte)0x77,(byte)0x05,(byte)0xB9,(byte)0xDA,(byte)0x49,(byte)0xF9,(byte)0xD7,(byte)0x8E,(byte)0x03,(byte)0x1D };
+ // + System.arraycopy(bla, 0, _chunk, posInChunk-2, bla.length);
+ // + return posInChunk-2+bla.length;
+ // + }
+ // +
+ // int ciLen = (doFinal)
+ // ? _cipher.doFinal(_chunk, 0, posInChunk, _chunk)
+ // : _cipher.update(_chunk, 0, posInChunk, _chunk);
+ //
+ // --- src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (revision 1766745)
+ // +++ src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (working copy)
+ //
+ // @@ -300,7 +297,7 @@
+ // protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode)
+ // throws GeneralSecurityException {
+ // EncryptionHeader header = encryptionInfo.getHeader();
+ // - String padding = (lastChunk ? "PKCS5Padding" : "NoPadding");
+ // + String padding = "NoPadding"; // (lastChunk ? "PKCS5Padding" : "NoPadding");
+ // if (existing == null || !existing.getAlgorithm().endsWith(padding)) {
+ // existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding);
+ // }
+
+ final EncryptionInfo infoOrig;
+ final byte[] zipInput, epOrigBytes;
+ try (InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx");
+ POIFSFileSystem fsOrig = new POIFSFileSystem(is)) {
+ infoOrig = new EncryptionInfo(fsOrig);
+ Decryptor decOrig = infoOrig.getDecryptor();
+ boolean b = decOrig.verifyPassword("Test001!!");
+ assertTrue(b);
+ try (InputStream decIn = decOrig.getDataStream(fsOrig)) {
+ zipInput = IOUtils.toByteArray(decIn);
+ }
+
+ try (InputStream epOrig = fsOrig.getRoot().createDocumentInputStream("EncryptedPackage")) {
+ // ignore the 16 padding bytes
+ epOrigBytes = IOUtils.toByteArray(epOrig, 9400);
+ }
+ }
+
+ EncryptionInfo eiNew = new EncryptionInfo(EncryptionMode.agile);
+ AgileEncryptionHeader aehHeader = (AgileEncryptionHeader)eiNew.getHeader();
+ aehHeader.setCipherAlgorithm(CipherAlgorithm.aes128);
+ aehHeader.setHashAlgorithm(HashAlgorithm.sha1);
+ AgileEncryptionVerifier aehVerifier = (AgileEncryptionVerifier)eiNew.getVerifier();
+
+ // this cast might look strange - if the setters would be public, it will become obsolete
+ // see http://stackoverflow.com/questions/5637650/overriding-protected-methods-in-java
+ ((EncryptionVerifier)aehVerifier).setCipherAlgorithm(CipherAlgorithm.aes256);
+ aehVerifier.setHashAlgorithm(HashAlgorithm.sha512);
+
+ Encryptor enc = eiNew.getEncryptor();
+ enc.confirmPassword("Test001!!",
+ infoOrig.getDecryptor().getSecretKey().getEncoded(),
+ infoOrig.getHeader().getKeySalt(),
+ infoOrig.getDecryptor().getVerifier(),
+ infoOrig.getVerifier().getSalt(),
+ infoOrig.getDecryptor().getIntegrityHmacKey()
+ );
+
+ final byte[] epNewBytes;
+ final EncryptionInfo infoReload;
+ try (POIFSFileSystem fsNew = new POIFSFileSystem()) {
+ try (OutputStream os = enc.getDataStream(fsNew)) {
+ os.write(zipInput);
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ fsNew.writeFilesystem(bos);
+
+ try (POIFSFileSystem fsReload = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
+ infoReload = new EncryptionInfo(fsReload);
+ try (InputStream epReload = fsReload.getRoot().createDocumentInputStream("EncryptedPackage")) {
+ epNewBytes = IOUtils.toByteArray(epReload, 9400);
+ }
+ }
+ }
+
+ assertArrayEquals(epOrigBytes, epNewBytes);
+
+ Decryptor decReload = infoReload.getDecryptor();
+ assertTrue(decReload.verifyPassword("Test001!!"));
+
+ AgileEncryptionHeader aehOrig = (AgileEncryptionHeader)infoOrig.getHeader();
+ AgileEncryptionHeader aehReload = (AgileEncryptionHeader)infoReload.getHeader();
+ assertEquals(aehOrig.getBlockSize(), aehReload.getBlockSize());
+ assertEquals(aehOrig.getChainingMode(), aehReload.getChainingMode());
+ assertEquals(aehOrig.getCipherAlgorithm(), aehReload.getCipherAlgorithm());
+ assertEquals(aehOrig.getCipherProvider(), aehReload.getCipherProvider());
+ assertEquals(aehOrig.getCspName(), aehReload.getCspName());
+ assertArrayEquals(aehOrig.getEncryptedHmacKey(), aehReload.getEncryptedHmacKey());
+ // this only works, when the paddings are mocked to be the same ...
+ // assertArrayEquals(aehOrig.getEncryptedHmacValue(), aehReload.getEncryptedHmacValue());
+ assertEquals(aehOrig.getFlags(), aehReload.getFlags());
+ assertEquals(aehOrig.getHashAlgorithm(), aehReload.getHashAlgorithm());
+ assertArrayEquals(aehOrig.getKeySalt(), aehReload.getKeySalt());
+ assertEquals(aehOrig.getKeySize(), aehReload.getKeySize());
+
+ AgileEncryptionVerifier aevOrig = (AgileEncryptionVerifier)infoOrig.getVerifier();
+ AgileEncryptionVerifier aevReload = (AgileEncryptionVerifier)infoReload.getVerifier();
+ assertEquals(aevOrig.getBlockSize(), aevReload.getBlockSize());
+ assertEquals(aevOrig.getChainingMode(), aevReload.getChainingMode());
+ assertEquals(aevOrig.getCipherAlgorithm(), aevReload.getCipherAlgorithm());
+ assertArrayEquals(aevOrig.getEncryptedKey(), aevReload.getEncryptedKey());
+ assertArrayEquals(aevOrig.getEncryptedVerifier(), aevReload.getEncryptedVerifier());
+ assertArrayEquals(aevOrig.getEncryptedVerifierHash(), aevReload.getEncryptedVerifierHash());
+ assertEquals(aevOrig.getHashAlgorithm(), aevReload.getHashAlgorithm());
+ assertEquals(aevOrig.getKeySize(), aevReload.getKeySize());
+ assertArrayEquals(aevOrig.getSalt(), aevReload.getSalt());
+ assertEquals(aevOrig.getSpinCount(), aevReload.getSpinCount());
+
+ AgileDecryptor adOrig = (AgileDecryptor)infoOrig.getDecryptor();
+ AgileDecryptor adReload = (AgileDecryptor)infoReload.getDecryptor();
+
+ assertArrayEquals(adOrig.getIntegrityHmacKey(), adReload.getIntegrityHmacKey());
+ // doesn't work without mocking ... see above
+ // assertArrayEquals(adOrig.getIntegrityHmacValue(), adReload.getIntegrityHmacValue());
+ assertArrayEquals(adOrig.getSecretKey().getEncoded(), adReload.getSecretKey().getEncoded());
+ assertArrayEquals(adOrig.getVerifier(), adReload.getVerifier());
+ }
+
+ @Test
+ public void smallFile() throws IOException, GeneralSecurityException {
+ // see https://stackoverflow.com/questions/61463301
+ final int tinyFileSize = 80_000_000;
+ final String pass = "s3cr3t";
+
+ File tmpFile = TempFile.createTempFile("tiny", ".bin");
+
+ // create/populate empty file
+ try (POIFSFileSystem poifs = new POIFSFileSystem();
+ FileOutputStream fos = new FileOutputStream(tmpFile)) {
+ poifs.writeFilesystem(fos);
+ }
+
+ EncryptionInfo info1 = new EncryptionInfo(EncryptionMode.agile);
+ Encryptor enc = info1.getEncryptor();
+ enc.confirmPassword(pass);
+
+ final MessageDigest md = getMessageDigest(HashAlgorithm.sha256);
+
+ // reopen as mmap-ed file
+ try (POIFSFileSystem poifs = new POIFSFileSystem(tmpFile, false)) {
+ try (OutputStream os = enc.getDataStream(poifs);
+ RandomStream rs = new RandomStream(md)) {
+ IOUtils.copy(rs, os, tinyFileSize);
+ }
+ poifs.writeFilesystem();
+ }
+
+ final byte[] digest1 = md.digest();
+ md.reset();
+
+ // reopen and check the digest
+ try (POIFSFileSystem poifs = new POIFSFileSystem(tmpFile)) {
+ EncryptionInfo info2 = new EncryptionInfo(poifs);
+ Decryptor dec = info2.getDecryptor();
+ boolean passOk = dec.verifyPassword(pass);
+ assertTrue(passOk);
+
+ try (InputStream is = dec.getDataStream(poifs);
+ DigestInputStream dis = new DigestInputStream(is, md);
+ NullOutputStream nos = new NullOutputStream()) {
+ IOUtils.copy(dis, nos);
+ }
+ }
+
+ final byte[] digest2 = md.digest();
+ assertArrayEquals(digest1, digest2);
+
+ boolean isDeleted = tmpFile.delete();
+ assertTrue(isDeleted);
+ }
+
+ private static final class RandomStream extends InputStream {
+ private final Random rand = new Random();
+ private final byte[] buf = new byte[1024];
+ private final MessageDigest md;
+
+ private RandomStream(MessageDigest md) {
+ this.md = md;
+ }
+
+ @Override
+ public int read() {
+ int ret = rand.nextInt(256);
+ md.update((byte)ret);
+ return ret;
+ }
+
+ @Override
+ public int read(byte[] b, final int off, int len) {
+ for (int start = off; start-off < len; start += buf.length) {
+ rand.nextBytes(buf);
+ int copyLen = Math.min(buf.length, len-(start-off));
+ System.arraycopy(buf, 0, b, start, copyLen);
+ md.update(buf, 0, copyLen);
+ }
+ return len;
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.tests;
+
+import static org.apache.poi.POIDataSamples.getDocumentInstance;
+import static org.apache.poi.POIDataSamples.getSlideShowInstance;
+import static org.apache.poi.POIDataSamples.getSpreadSheetInstance;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.POIDocument;
+import org.apache.poi.extractor.POITextExtractor;
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.ooxml.extractor.ExtractorFactory;
+import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader;
+import org.apache.poi.poifs.storage.RawDataUtil;
+import org.apache.xmlbeans.XmlException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class TestHxxFEncryption {
+ @Parameter(value = 0)
+ public POIDataSamples sampleDir;
+
+ @Parameter(value = 1)
+ public String file;
+
+ @Parameter(value = 2)
+ public String password;
+
+ @Parameter(value = 3)
+ public String expected;
+
+ @Parameters(name="{1}")
+ public static Collection<Object[]> data() throws IOException {
+ final String base64 =
+ "H4sIAAAAAAAAAF1Uu24bMRDs/RULVwkgCUhSpHaZwkDgpHJH8fZ0G/Nx4ZI6y13yG/mRfIb9R5mlZFlIpdPtcnZmdnjPf57/vvx6+f3h6obuv3"+
+ "ylbY5bEiVHe1fEpUp5pOgkrK0iabehm7FyoZi1ks8xcvHiQu8h5bLnorTlnUvkJ/YPOHKsLVInAqCs91KakuaxLq4w3g00SgCo9Xou1UnCmSBe"+
+ "MhpRY6qHmXVFteQfQJ5yUaaOw4qXwgPVjPGAqhNH5bBHAfTmwqqoSkLdFT/J3nC0eZBRk7yiu5s7yoU+r+9l3tDtm5A3jgt6AQxNOY2ya+U4sK"+
+ "XZ+YczbpfSVVuzFOuunKraqIVD2ND3yVXauT3TNthR/O3IJAM7gzTOGeIcXZvj14ahotW8wSognlMu0Yyp/Fi7O6s+CK6haUUjtPCji7MVcgqH"+
+ "jh+42tqeqPDMroJ/lBAE4AZbJbJu6Fu35ej42Tw9mYeTwVXoBKJiPeFV94q2rZJAyNEPo/qOdWYLBpq3B2JX8GDZeJ14mZf3tOQWBmpd9yQ7kI"+
+ "DCY/jmkj1oGOicFy62r9vutC5uJsVEMFgmAXXfYcC6BRBKNHCybALFJolnrDcPXNLl+K60Vctt09YZT7YgbeOICGJ/ZgC2JztOnm1JhX3eJXni"+
+ "U5Bqhezzlu334vD/Ajr3yDGXw5G9IZ6aLmLfQafY42N3J7cjj1LaXOHihSrcC5ThmuYIB5FX5AU8tKlnNG9Dn1EnsdD4KcnPhsSNPRiXtz461b"+
+ "VZw8Pm6vn0afh4fvr0D5P/+cMuBAAA";
+ final String x = new String(RawDataUtil.decompress(base64), StandardCharsets.UTF_8);
+
+ return Arrays.asList(
+ // binary rc4
+ new Object[]{ getDocumentInstance(), "password_tika_binaryrc4.doc", "tika", "This is an encrypted Word 2007 File." },
+ // cryptoapi
+ new Object[]{ getDocumentInstance(), "password_password_cryptoapi.doc", "password", "This is a test" },
+ // binary rc4
+ new Object[]{ getSpreadSheetInstance(), "password.xls", "password", x },
+ // cryptoapi
+ new Object[]{ getSpreadSheetInstance(), "35897-type4.xls", "freedom", "Sheet1\nhello there!" },
+ // cryptoapi (PPT only supports cryptoapi...)
+ new Object[]{ getSlideShowInstance(), "cryptoapi-proc2356.ppt", "crypto", "Dominic Salemno" }
+ );
+ }
+
+ @Test
+ public void extract() throws IOException, OpenXML4JException, XmlException {
+ File f = sampleDir.getFile(file);
+ Biff8EncryptionKey.setCurrentUserPassword(password);
+ try (POITextExtractor te = ExtractorFactory.createExtractor(f)) {
+ String actual = te.getText().trim();
+ assertEquals(expected, actual);
+ } finally {
+ Biff8EncryptionKey.setCurrentUserPassword(null);
+ }
+ }
+
+ @Test
+ public void changePassword() throws IOException, OpenXML4JException, XmlException {
+ newPassword("test");
+ }
+
+ @Test
+ public void removePassword() throws IOException, OpenXML4JException, XmlException {
+ newPassword(null);
+ }
+
+ private void newPassword(String newPass) throws IOException, OpenXML4JException, XmlException {
+ File f = sampleDir.getFile(file);
+ Biff8EncryptionKey.setCurrentUserPassword(password);
+ try (POITextExtractor te1 = ExtractorFactory.createExtractor(f)) {
+ Biff8EncryptionKey.setCurrentUserPassword(newPass);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (POIDocument doc = (POIDocument) te1.getDocument()) {
+ doc.write(bos);
+ }
+ ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+ try (POITextExtractor te2 = ExtractorFactory.createExtractor(bis)) {
+ String actual = te2.getText().trim();
+ assertEquals(expected, actual);
+ }
+ } finally {
+ Biff8EncryptionKey.setCurrentUserPassword(null);
+ }
+ }
+
+ /** changing the encryption mode and key size in poor mans style - see comments below */
+ @Test
+ public void changeEncryption() throws IOException, OpenXML4JException, XmlException {
+ File f = sampleDir.getFile(file);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ Biff8EncryptionKey.setCurrentUserPassword(password);
+ try (POITextExtractor te1 = ExtractorFactory.createExtractor(f)) {
+ // first remove encryption
+ Biff8EncryptionKey.setCurrentUserPassword(null);
+ try (POIDocument doc = (POIDocument) te1.getDocument()) {
+ doc.write(bos);
+ }
+ // then use default setting, which is cryptoapi
+ String newPass = "newPass";
+ try (POITextExtractor te2 = ExtractorFactory.createExtractor(new ByteArrayInputStream(bos.toByteArray()))) {
+ Biff8EncryptionKey.setCurrentUserPassword(newPass);
+ try (POIDocument doc = (POIDocument) te2.getDocument()) {
+ bos.reset();
+ doc.write(bos);
+ }
+ }
+ // and finally update cryptoapi setting
+ try (POITextExtractor te3 = ExtractorFactory.createExtractor(new ByteArrayInputStream(bos.toByteArray()));
+ POIDocument doc = (POIDocument) te3.getDocument()) {
+ // need to cache data (i.e. read all data) before changing the key size
+ Class<?> clazz = doc.getClass();
+ if ("HSLFSlideShowImpl".equals(clazz.getSimpleName())) {
+ try {
+ clazz.getDeclaredMethod("getPictureData").invoke(doc);
+ } catch (ReflectiveOperationException e) {
+ fail("either scratchpad jar is included and this should work or the clazz should be != HSLFSlideShowImpl");
+ }
+ doc.getDocumentSummaryInformation();
+ }
+ EncryptionInfo ei = doc.getEncryptionInfo();
+ assertNotNull(ei);
+ assertTrue(ei.getHeader() instanceof CryptoAPIEncryptionHeader);
+ assertEquals(0x28, ei.getHeader().getKeySize());
+ ei.getHeader().setKeySize(0x78);
+ bos.reset();
+ doc.write(bos);
+ }
+ // check the setting
+ try (POITextExtractor te4 = ExtractorFactory.createExtractor(new ByteArrayInputStream(bos.toByteArray()));
+ POIDocument doc = (POIDocument) te4.getDocument()) {
+ EncryptionInfo ei = doc.getEncryptionInfo();
+ assertNotNull(ei);
+ assertTrue(ei.getHeader() instanceof CryptoAPIEncryptionHeader);
+ assertEquals(0x78, ei.getHeader().getKeySize());
+ }
+ } finally {
+ Biff8EncryptionKey.setCurrentUserPassword(null);
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.poifs.crypt.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+
+import javax.crypto.Cipher;
+
+import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.util.ZipEntrySource;
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.temp.AesZipFileZipEntrySource;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.extractor.XSSFBEventBasedExcelExtractor;
+import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.xmlbeans.XmlException;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class TestSecureTempZip {
+
+ /**
+ * Test case for #59841 - this is an example on how to use encrypted temp files,
+ * which are streamed into POI opposed to having everything in memory
+ */
+ @Test
+ public void protectedTempZip() throws IOException, GeneralSecurityException, XmlException, OpenXML4JException {
+ File tikaProt = XSSFTestDataSamples.getSampleFile("protected_passtika.xlsx");
+ FileInputStream fis = new FileInputStream(tikaProt);
+ POIFSFileSystem poifs = new POIFSFileSystem(fis);
+ EncryptionInfo ei = new EncryptionInfo(poifs);
+ Decryptor dec = ei.getDecryptor();
+ boolean passOk = dec.verifyPassword("tika");
+ assertTrue(passOk);
+
+ // extract encrypted ooxml file and write to custom encrypted zip file
+ InputStream is = dec.getDataStream(poifs);
+
+ // provide ZipEntrySource to poi which decrypts on the fly
+ ZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(is);
+
+ // test the source
+ OPCPackage opc = OPCPackage.open(source);
+ String expected = "This is an Encrypted Excel spreadsheet.";
+
+ XSSFEventBasedExcelExtractor extractor = new XSSFEventBasedExcelExtractor(opc);
+ extractor.setIncludeSheetNames(false);
+ String txt = extractor.getText();
+ assertEquals(expected, txt.trim());
+
+ XSSFWorkbook wb = new XSSFWorkbook(opc);
+ txt = wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue();
+ assertEquals(expected, txt);
+
+ extractor.close();
+
+ wb.close();
+ opc.close();
+ source.close();
+ poifs.close();
+ fis.close();
+ }
+
+ /**
+ * Now try with xlsb.
+ */
+ @Test
+ public void protectedXLSBZip() throws IOException, GeneralSecurityException, XmlException, OpenXML4JException {
+ //The test file requires that JCE unlimited be installed.
+ //If it isn't installed, skip this test.
+ int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
+ Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256",
+ maxKeyLen == 2147483647);
+
+ File tikaProt = XSSFTestDataSamples.getSampleFile("protected_passtika.xlsb");
+ FileInputStream fis = new FileInputStream(tikaProt);
+ POIFSFileSystem poifs = new POIFSFileSystem(fis);
+ EncryptionInfo ei = new EncryptionInfo(poifs);
+ Decryptor dec = ei.getDecryptor();
+ boolean passOk = dec.verifyPassword("tika");
+ assertTrue(passOk);
+
+ // extract encrypted ooxml file and write to custom encrypted zip file
+ InputStream is = dec.getDataStream(poifs);
+
+ // provide ZipEntrySource to poi which decrypts on the fly
+ ZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(is);
+
+ // test the source
+ OPCPackage opc = OPCPackage.open(source);
+ String expected = "You can't see me";
+
+ XSSFBEventBasedExcelExtractor extractor = new XSSFBEventBasedExcelExtractor(opc);
+ extractor.setIncludeSheetNames(false);
+ String txt = extractor.getText();
+ assertEquals(expected, txt.trim());
+
+ extractor.close();
+ opc.close();
+ poifs.close();
+ fis.close();
+ }
+
+}
+++ /dev/null
-/*
- * ====================================================================
- * 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.sl;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.sl.usermodel.SlideShowFactory;
-
-public class SLCommonUtils {
- private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
-
- /** a generic way to open a sample slideshow document **/
- public static SlideShow<?,?> openSampleSlideshow(String sampleName) throws IOException {
- try (InputStream is = _slTests.openResourceAsStream(sampleName)) {
- return SlideShowFactory.create(is);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Tests, if the scratchpad classes are on the classpath
- *
- * @return true, if only xslf is on the classpath, and false, if both classpaths
- * (XSLF and HSLF) can be used/referenced
- */
- public static boolean xslfOnly() {
- try {
- Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow");
- return false;
- } catch (Exception e) {
- return true;
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.sl;
-
-import static org.apache.poi.sl.SLCommonUtils.xslfOnly;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.FontFormatException;
-import java.awt.Graphics2D;
-import java.awt.GraphicsEnvironment;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.common.usermodel.fonts.FontGroup;
-import org.apache.poi.sl.draw.Drawable;
-import org.apache.poi.sl.usermodel.Slide;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
-import org.apache.poi.sl.usermodel.TextBox;
-import org.apache.poi.sl.usermodel.TextParagraph;
-import org.apache.poi.sl.usermodel.TextRun;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-
-/**
- * Test rendering - specific to font handling
- */
-public class TestFonts {
- private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
-
- private static final String JPTEXT =
- "\u3061\u3087\u3063\u3068\u65E9\u3044\u3051\u3069T\u30B7\u30E3\u30C4\u304C\u7740\u305F\u304F\u306A" +
- "\u308B\u5B63\u7BC0\u2661\u304A\u6BCD\u3055\u3093\u306E\u5F71\u97FF\u304B\u3001\u975E\u5E38\u306B" +
- "\u6050\u7ADC\u304C\u5927\u597D\u304D\u3067\u3059\u3002\u3082\u3046\u98FC\u3044\u305F\u3044\u304F" +
- "\u3089\u3044\u5927\u597D\u304D\u3067\u3059\u3002#\u30B8\u30E5\u30E9\u30B7\u30C3\u30AF\u30EF\u30FC" +
- "\u30EB\u30C9 \u306E\u30E9\u30D7\u30C8\u30EB4\u59C9\u59B9\u3068\u304B\u6FC0\u7684\u306B\u53EF\u611B" +
- "\u304F\u3066\u53EF\u611B\u304F\u3066\u53EF\u611B\u304F\u3066\u53EF\u611B\u3044\u3067\u3059\u3002" +
- "\u3081\u308D\u3081\u308D\u3001\u5927\u597D\u304D\u2661\u304A\u6BCD\u3055\u3093\u3082\u6050\u7ADC" +
- "\u304C\u597D\u304D\u3067\u3001\u5C0F\u3055\u3044\u9803\u3001\u53E4\u4EE3\u751F\u7269\u306E\u56F3" +
- "\u9451\u3092\u4E00\u7DD2\u306B\u898B\u3066\u305F\u306E\u601D\u3044\u51FA\u3059\u301C\u3068\u3044";
-
- private static final String[] INIT_FONTS = {"mona.ttf"};
-
- @BeforeClass
- public static void initGE() throws FontFormatException, IOException {
- GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
- for (String s : INIT_FONTS) {
- Font font = Font.createFont(Font.TRUETYPE_FONT, _slTests.getFile(s));
- ge.registerFont(font);
- }
- }
-
- @Test
- public void resizeToFitTextHSLF() throws IOException, ReflectiveOperationException {
- assumeFalse(xslfOnly());
- SlideShow<?,?> ppt = (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
- resizeToFitText(ppt);
- ppt.close();
- }
-
- @Test
- public void resizeToFitTextXSLF() throws IOException {
- SlideShow<?,?> ppt = new XMLSlideShow();
- resizeToFitText(ppt);
- ppt.close();
- }
-
- private void resizeToFitText(SlideShow<?,?> slideshow) throws IOException {
- Slide<?,?> sld = slideshow.createSlide();
- TextBox<?,?> tb = sld.createTextBox();
- tb.setAnchor(new Rectangle(50, 50, 200, 50));
- tb.setStrokeStyle(Color.black, LineDash.SOLID, 3);
- tb.setText(JPTEXT);
-
- setFont(tb, "NoSuchFont", FontGroup.LATIN);
-
- Dimension pgsize = slideshow.getPageSize();
- int width = (int)pgsize.getWidth();
- int height = (int)pgsize.getHeight();
-
- BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
- Graphics2D graphics = img.createGraphics();
-
- Map<String,String> fallbackMap = new HashMap<>();
- fallbackMap.put("NoSuchFont", "Mona");
- // in XSLF the fonts default to the theme fonts (Calibri), if the font group is not overridden
- // see XSLFTextRun.XSLFTextInfo.getCTTextFont
- fallbackMap.put("Calibri", "Mona");
- graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap);
- graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
-
- tb.resizeToFitText(graphics);
- graphics.dispose();
-
- Rectangle2D anc = tb.getAnchor();
- // ignore font metrics differences on windows / linux (... hopefully ...)
- int tbHeight = (int)anc.getHeight();
- assertTrue(tbHeight > 100);
- }
-
- private void setFont(TextBox<?,?> tb, String fontFamily, FontGroup fontGroup) {
- // TODO: set east asian font family - MS Office uses "MS Mincho" or "MS Gothic" as a fallback
- // see https://stackoverflow.com/questions/26063828 for good explanation about the font metrics
- // differences on different environments
- for (TextParagraph<?,?,? extends TextRun> p : tb.getTextParagraphs()) {
- for (TextRun r : p.getTextRuns()) {
- r.setFontFamily(fontFamily, fontGroup);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.sl;
-
-import static org.apache.poi.sl.SLCommonUtils.openSampleSlideshow;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.poi.sl.usermodel.Shape;
-import org.apache.poi.sl.usermodel.Slide;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.sl.usermodel.TextParagraph;
-import org.apache.poi.sl.usermodel.TextShape;
-import org.junit.Test;
-
-public class TestHeadersFooters {
- @Test
- public void bug58144c() throws IOException {
- SlideShow<?,?> ppt = openSampleSlideshow("bug58144-headers-footers-2007.pptx");
- testSlideShow(ppt);
- ppt.close();
- }
-
- private void testSlideShow(SlideShow<?,?> ppt) {
- Slide<?,?> sl = ppt.getSlides().get(0);
-
- List<? extends Shape<?,?>> shapes = sl.getShapes();
- TextShape<?,?> ts0 = (TextShape<?,?>)shapes.get(0);
- assertEquals("Test file", ts0.getText());
- TextShape<?,?> ts1 = (TextShape<?,?>)shapes.get(1);
- assertEquals("Has some text in the headers and footers", ts1.getText());
- TextShape<?,?> ts2 = (TextShape<?,?>)shapes.get(2);
- assertEquals("Slide footer", ts2.getText());
- List<? extends TextParagraph<?,?,?>> ltp = ts2.getTextParagraphs();
- assertTrue(ltp.get(0).isHeaderOrFooter());
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.sl;
-
-import static org.apache.poi.sl.SLCommonUtils.xslfOnly;
-import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.EXCEL_V12;
-import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.EXCEL_V8;
-import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.PDF;
-import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.WORD_V12;
-import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.WORD_V8;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeFalse;
-
-import java.awt.geom.Rectangle2D;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Collection;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.POIDocument;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.poifs.storage.RawDataUtil;
-import org.apache.poi.sl.usermodel.ObjectMetaData;
-import org.apache.poi.sl.usermodel.ObjectShape;
-import org.apache.poi.sl.usermodel.PictureData;
-import org.apache.poi.sl.usermodel.PictureData.PictureType;
-import org.apache.poi.sl.usermodel.Slide;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.sl.usermodel.SlideShowFactory;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TestOleShape {
- private static final String PDF_SAMPLE =
- "H4sIAAAAAAAAAJWUezRUWxzHe+o2FXncVtxLpxi3FPOeKYspjMdM5J1S4TTOaDIzxzpzJo9CUrnrSiUxIeT" +
- "9jB7yqInihrhepTwqt1AT5VZCC7XcY0LWcv+5Z521zz6fvX+/vb/7t9cX78CyMiQZ0XD4W4OFEzgKQATgg4" +
- "dxJiYAwRYS+aCHACqGnHAAABCs+AIUQrCvAEQhFsSFvSEck4kTowgECnEBl6E4OxGesfLkl2Bc0g5V/MCHt" +
- "duqroTFC27YIKGAp+OL5Ou1SsmebA1XvciLk+Ucg84aLclQZhRZmh0amrG9Ina4t7Lh+ZCAHyezsg/NXsZg" +
- "vuPw8NIedsrI2sZlz2vfhLkZfIgfMr4zFvTrmfbRgMmPw1UTvWk+r4MCZfLtj2WPPStVJ0P2PiKkxo+YnJ5" +
- "Ua7v5UnefkB9ev0vSR37a8NrsC2lApaLp7086wS3Lzi2LqB3TMW2POrdRRUYMFYWs8vBo/kSQ6dYXpR6rxM" +
- "UXM0vqu4arpe5dha7XS5MYS5P1arVG653sb8pXqReVw/TfjK8R3q4Z7X7Uk9dZ2Bcl8Wpmsl80Xf1QTOxe3" +
- "Nutwus0kYge1LoHvgKLbc/f6WvdcsBfS9ctU3vSaneHNm0w/uhrm0Zett5O83s2xh2Gm8WZfWJ+/CNWruZ2" +
- "cap8tR2/U9bAfRBbYt3PL9jvb3+0usqSF6vfrFuEq8Hf6jgrx/fERpZJEjKbHtJ11jCdUwI7Oc8QrmZf2pr" +
- "L43WJn1mlT1ydV+QbrndcdN3qSEnicVhmoJyfWyprUEsIZlPyvi0tiEy7FzkOnqlE/qC6xFSpyg0E8tODa7" +
- "qiKX61hMxRkZt73ITLWIHwtZtj71NbS4/BgKHnssOMcXOp1aacX4A//V+VFN4TWl6QryxdkcAp79BZcipmP" +
- "OWOWkS6KhqUWlG+yCCxVMMtfW+9e56++gKHYEs9PNJztTI6KtyfOCDPOBppt3udRs3NpGrKfrs3i3Nivtrs" +
- "VTl5LFerXZlTbf5XumbeYsOfwnve5ksEjKy6s1Z78rpbeJq7biTdzWwU3vhZ1GqkYb9D+t6mYvWLhXn6FWi" +
- "c60VWpbBtVYHLQkmbh6Txwm6Ul3LbNW/Hs5FtLnlNX3fsAX2jPdlOI5W3HDIcm2MyNiR39rdyHlpwusjoOj" +
- "I3IKfgPMILSzHZInmQaWyUFXEi0bHsCLX8pm9Gzl2vou7E3rrkPYdt1EwW3R5Qcg8rwzk88c1p13l8v+WkY" +
- "75FHeS7XrvRsHgLy+wfr2EBRfNJ/4UVhUrihRqDktXciPGxWv1eXs396/0lqWG3YtU/A+D90hrT46cumSUN" +
- "rBdG0G2Knn3T9Kw0X96vbhxMyr92uqUNOa4aEnGqP8us6GULm7mIyFKuxnOW2MZEEuKXmOpxnnqlwiMn+ju" +
- "Xu+inC5mpG9oesxKkhcJq9bra5vR3H7l10hGbAxqu6t0LvHzaDnPIp/zeu0iXj1NNtVc+cMyUsH18u7TGXJ" +
- "XiL4W3tqaL2mq6zkgXWB6kOTB3RxW8PHAOvzfaufDptdg7qmZlEcrUzbd5jKtVb85Sr9jaMT8a3y2Q30+3/" +
- "FrsfGZDblh/mYnHhCg3ekm2q1JIYEVCd9rv42PNb9RFpuSsa4MNE0GfdSYDv6lsudikg4NE3tNugfWmfIY6" +
- "7TeYvZCItG0zmDxrQwrjsQxArZ1RzHSA72CKgURgyqQszAASQOCCWItZETaAtdg7nYc2x85cAv0ggOAA+kC" +
- "KnA4gAolQLGzG3ewgbz5oDgcA+zBEBEhUkhGDQiZvpc3tHlBMtYBFKBYsBiiz0dYILPGbs73vqynoDHLGKA" +
- "KKxH5TK3MDZzAbQBEJNPNngc1iQUf4XMjJ2nxazxR3gsSwBOFCYoCsWPOHRtJ/ahQronbyvcWYnqljcJrdu" +
- "2RK9pwE9DkJLLDioDACbOSCfAQGSEYkqhGJCGw8hKJ+xgSCgvogoN8hPldsBCM+mzZ9P0wE9pZwof8V92MD" +
- "jHkKLEAUFMA+04XC1EzX6UdMAALxcERgK444+wB0Go1CA3jANCNRGdj1UoyIZhlpPsMobf48GmkeI1Pp8xi" +
- "Nsm0eo9O3/mAoAvIFEKIQ58wPgrAtK+oJwyjAmL0+bBEPBugzGsUoiKAKhSQGmYjD4y3trXD/AmBc9IeqBwAA";
-
- enum Api { HSLF, XSLF }
-
-
- @Parameter(value = 0)
- public Api api;
- @Parameter(value = 1)
- public ObjectMetaData.Application app;
-
-
- private static File pictureFile;
-
- @BeforeClass
- public static void initPicture() {
- pictureFile = POIDataSamples.getSlideShowInstance().getFile("wrench.emf");
- }
-
-
- @Parameters(name="{0} {1}")
- public static Collection<Object[]> data() {
- return Arrays.asList(new Object[][] {
- { Api.HSLF, EXCEL_V8 },
- { Api.HSLF, WORD_V8 },
- { Api.HSLF, PDF },
- { Api.XSLF, EXCEL_V12 },
- { Api.XSLF, WORD_V12 },
- { Api.XSLF, PDF },
- });
- }
-
- @Test
- public void embedData() throws IOException, InvalidFormatException, ReflectiveOperationException {
- final ByteArrayInputStream pptBytes;
- try (SlideShow<?,?> ppt = createSlideShow()) {
- final PictureData picData = ppt.addPicture(pictureFile, PictureType.EMF);
- final Slide<?,?> slide = ppt.createSlide();
- final ObjectShape<?,?> oleShape = slide.createOleShape(picData);
- oleShape.setAnchor(new Rectangle2D.Double(100,100,100,100));
- try (OutputStream os = oleShape.updateObjectData(app, null)) {
- fillOleData(os);
- }
- final ByteArrayOutputStream bos = new ByteArrayOutputStream(50000);
- ppt.write(bos);
- pptBytes = new ByteArrayInputStream(bos.toByteArray());
- }
- try (SlideShow<?,?> ppt = SlideShowFactory.create(pptBytes)) {
- final ObjectShape<?,?> oleShape = (ObjectShape<?,?>)ppt.getSlides().get(0).getShapes().get(0);
- try (InputStream bis = oleShape.readObjectData()) {
- validateOleData(bis);
- }
- }
- }
-
- private SlideShow<?,?> createSlideShow() throws ReflectiveOperationException {
- if (api == Api.XSLF) {
- return new XMLSlideShow();
- } else {
- assumeFalse(xslfOnly());
- return (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
- }
- }
-
-
- private void fillOleData(final OutputStream out) throws IOException {
- switch (app) {
- case EXCEL_V8:
- case EXCEL_V12:
- try (Workbook wb = (app == EXCEL_V12) ? new XSSFWorkbook() : new HSSFWorkbook()) {
- wb.createSheet().createRow(0).createCell(0).setCellValue("test me");
- wb.write(out);
- }
- break;
- case WORD_V8:
- try (InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream("simple.doc")) {
- IOUtils.copy(is, out);
- }
- break;
- case WORD_V12:
- try (XWPFDocument doc = new XWPFDocument()) {
- doc.createParagraph().createRun().setText("Test me");
- doc.write(out);
- }
- break;
- case PDF:
- out.write(RawDataUtil.decompress(PDF_SAMPLE));
- break;
- default:
- case CUSTOM:
- fail("not implemented");
- break;
- }
- }
-
- private void validateOleData(final InputStream in) throws IOException, InvalidFormatException, ReflectiveOperationException {
- switch (app) {
- case EXCEL_V8:
- case EXCEL_V12:
- try (Workbook wb = WorkbookFactory.create(in)) {
- assertEquals("test me", wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
- }
- break;
- case WORD_V8:
- Class<? extends POIDocument> clazz = (Class<? extends POIDocument>)Class.forName("org.apache.poi.hwpf.HWPFDocument");
- Constructor<? extends POIDocument> con = clazz.getDeclaredConstructor(InputStream.class);
- Method m = clazz.getMethod("getDocumentText");
- try (POIDocument doc = con.newInstance(in)) {
- assertEquals("This is a simple file created with Word 97-SR2.\r", m.invoke(doc));
- }
- break;
- case WORD_V12:
- try (XWPFDocument doc = new XWPFDocument(in)) {
- assertEquals("Test me", doc.getParagraphs().get(0).getText());
- }
- break;
- case PDF:
- final byte[] expected = RawDataUtil.decompress(PDF_SAMPLE);
- final byte[] actual = IOUtils.toByteArray(in);
- assertArrayEquals(expected, actual);
- break;
- default:
- case CUSTOM:
- fail("not implemented");
- break;
- }
-
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.sl;
-
-import static org.apache.poi.sl.SLCommonUtils.xslfOnly;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.sl.usermodel.SlideShowFactory;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.junit.Test;
-
-public class TestSlide {
-
- @Test
- public void hideHSLF() throws IOException, ReflectiveOperationException {
- assumeFalse(xslfOnly());
- SlideShow<?,?> ppt1 = (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
- hideSlide(ppt1);
- ppt1.close();
- }
-
- @Test
- public void hideXSLF() throws IOException {
- SlideShow<?,?> ppt1 = new XMLSlideShow();
- hideSlide(ppt1);
- ppt1.close();
- }
-
- private void hideSlide(SlideShow<?,?> ppt1) throws IOException {
- ppt1.createSlide().setHidden(true);
- ppt1.createSlide();
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ppt1.write(bos);
- ppt1.close();
-
- InputStream is = new ByteArrayInputStream(bos.toByteArray());
- SlideShow<?,?> ppt2 = SlideShowFactory.create(is);
-
- Boolean[] hiddenState = ppt2.getSlides().stream().map(e -> e.isHidden()).toArray(Boolean[]::new);
-
- assertTrue(hiddenState[0]);
- assertFalse(hiddenState[1]);
-
- ppt2.close();
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * ====================================================================
- * 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.sl;
-
-import static org.apache.poi.sl.SLCommonUtils.openSampleSlideshow;
-import static org.apache.poi.sl.SLCommonUtils.xslfOnly;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-
-import java.awt.geom.Rectangle2D;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.sl.usermodel.Slide;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.sl.usermodel.SlideShowFactory;
-import org.apache.poi.sl.usermodel.TableCell;
-import org.apache.poi.sl.usermodel.TableShape;
-import org.apache.poi.sl.usermodel.TextShape.TextDirection;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.junit.Test;
-
-public class TestTable {
-
- @Test
- public void colWidthRowHeight() throws IOException {
- assumeFalse(xslfOnly());
-
- // Test of table dimensions of same slideshow saved as ppt/x
- // to check if both return similar (points) value
- SlideShow<?,?> ppt = openSampleSlideshow("table_test.ppt");
- TableShape<?,?> ts = (TableShape<?,?>)ppt.getSlides().get(0).getShapes().get(0);
-
- SlideShow<?,?> pptx = openSampleSlideshow("table_test.pptx");
- TableShape<?,?> tsx = (TableShape<?,?>)pptx.getSlides().get(0).getShapes().get(0);
-
- // assume table shape should be equal to itself
- confirmTableShapeEqual(ts, ts);
- confirmTableShapeEqual(tsx, tsx);
-
- // assert ppt and pptx versions of the same table have the same shape
- confirmTableShapeEqual(ts, tsx);
-
- // change row height and validate again
- tsx.setRowHeight(1, 50);
- ts.setRowHeight(1, 50);
- confirmTableShapeEqual(ts, tsx);
-
- pptx.close();
- ppt.close();
- }
-
- private void confirmTableShapeEqual(TableShape<?,?> tableA, TableShape<?,?> tableB) {
- int cols = tableA.getNumberOfColumns();
- int rows = tableA.getNumberOfRows();
-
- int colsx = tableB.getNumberOfColumns();
- int rowsx = tableB.getNumberOfRows();
-
- assertEquals("tables should have same number of columns", cols, colsx);
- assertEquals("tables should have same number of rows", rows, rowsx);
-
- for (int i=0; i<cols; i++) {
- assertEquals("Width of column " + i + " should be equal",
- tableA.getColumnWidth(i), tableB.getColumnWidth(i), 0.2);
- }
-
- for (int i=0; i<rows; i++) {
- assertEquals("Height of row " + i + " should be equal",
- tableA.getRowHeight(i), tableB.getRowHeight(i), 0.3);
- }
- }
-
- @Test
- public void directionHSLF() throws IOException, ReflectiveOperationException {
- assumeFalse(xslfOnly());
- SlideShow<?,?> ppt1 = (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
- testTextDirection(ppt1);
- ppt1.close();
- }
-
- @Test
- public void directionXSLF() throws IOException {
- SlideShow<?,?> ppt1 = new XMLSlideShow();
- testTextDirection(ppt1);
- ppt1.close();
- }
-
- private void testTextDirection(SlideShow<?,?> ppt1) throws IOException {
-
- TextDirection[] tds = {
- TextDirection.HORIZONTAL,
- TextDirection.VERTICAL,
- TextDirection.VERTICAL_270,
- // TextDirection.STACKED is not supported on HSLF
- };
-
- TableShape<?,?> tbl1 = ppt1.createSlide().createTable(1, 3);
- tbl1.setAnchor(new Rectangle2D.Double(50, 50, 200, 200));
-
- int col = 0;
- for (TextDirection td : tds) {
- TableCell<?,?> c = tbl1.getCell(0, col++);
- if (c != null) {
- c.setTextDirection(td);
- c.setText("bla");
- }
- }
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ppt1.write(bos);
- ppt1.close();
-
- InputStream is = new ByteArrayInputStream(bos.toByteArray());
- SlideShow<?,?> ppt2 = SlideShowFactory.create(is);
- TableShape<?,?> tbl2 = (TableShape<?,?>)ppt2.getSlides().get(0).getShapes().get(0);
-
- col = 0;
- for (TextDirection td : tds) {
- TableCell<?,?> c = tbl2.getCell(0, col++);
- assertEquals(td, c.getTextDirection());
- }
- ppt2.close();
- }
-
- @Test
- public void tableSpan() throws IOException {
- String[] files = (xslfOnly()) ? new String[]{"bug60993.pptx"} : new String[]{"bug60993.pptx", "bug60993.ppt"};
- for (String f : files) {
- SlideShow<?,?> ppt = openSampleSlideshow(f);
- Slide<?,?> slide = ppt.getSlides().get(0);
- TableShape<?,?> ts = (TableShape<?,?>)slide.getShapes().get(0);
- int cols = ts.getNumberOfColumns();
- int rows = ts.getNumberOfRows();
- for (int r=0; r<rows; r++) {
- for (int c=0; c<cols; c++) {
- TableCell<?,?> tc = ts.getCell(r, c);
- int rc = r*10+c;
- String msg = f+" (r"+r+",c"+c+")";
- switch (rc) {
- case 22:
- case 51:
- if (f.endsWith("ppt")) {
- assertNull(msg, tc);
- } else {
- assertNotNull(msg, tc);
- assertTrue(msg, tc.isMerged());
- }
- break;
- case 21:
- assertNotNull(msg, tc);
- assertEquals(msg, 1, tc.getRowSpan());
- assertEquals(msg, 2, tc.getGridSpan());
- assertFalse(msg, tc.isMerged());
- break;
- case 41:
- assertNotNull(msg, tc);
- assertEquals(msg, 2, tc.getRowSpan());
- assertEquals(msg, 1, tc.getGridSpan());
- assertFalse(msg, tc.isMerged());
- break;
- default:
- assertNotNull(msg, tc);
- assertEquals(msg, 1, tc.getRowSpan());
- assertEquals(msg, 1, tc.getGridSpan());
- assertFalse(msg, tc.isMerged());
- break;
- }
- }
- }
- ppt.close();
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * ====================================================================
- * 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.sl.draw;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assume.assumeFalse;
-
-import java.awt.Dimension;
-import java.awt.geom.Rectangle2D;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.sl.usermodel.PictureData;
-import org.apache.poi.sl.usermodel.PictureShape;
-import org.apache.poi.sl.usermodel.RectAlign;
-import org.apache.poi.sl.usermodel.Shape;
-import org.apache.poi.sl.usermodel.Slide;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.sl.usermodel.SlideShowFactory;
-import org.apache.poi.util.Units;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class TestDrawPictureShape {
- final static POIDataSamples ssSamples = POIDataSamples.getSlideShowInstance();
-
- private static boolean xslfOnly;
-
- @BeforeClass
- public static void checkHslf() {
- try {
- Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow");
- } catch (Exception e) {
- xslfOnly = true;
- }
- }
-
- /** a generic way to open a sample slideshow document **/
- public static SlideShow<?,?> openSampleDocument(String sampleName) throws IOException {
- try (InputStream is = ssSamples.openResourceAsStream(sampleName)) {
- return SlideShowFactory.create(is);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- @Test
- public void testResizeHSLF() throws IOException {
- assumeFalse(xslfOnly);
- testResize("pictures.ppt");
- }
-
- @Test
- public void testResizeXSLF() throws IOException {
- testResize("shapes.pptx");
- }
-
-
- public void testResize(String file) throws IOException {
- SlideShow<?,?> ss = openSampleDocument(file);
-
- Slide<?,?> slide = ss.getSlides().get(0);
- PictureShape<?,?> picShape = null;
- for (Shape<?,?> shape : slide.getShapes()) {
- if (shape instanceof PictureShape) {
- picShape = (PictureShape<?,?>)shape;
- break;
- }
- }
- assertNotNull(picShape);
- PictureData pd = picShape.getPictureData();
- Dimension dimPd = pd.getImageDimension();
- new DrawPictureShape(picShape).resize();
- Dimension dimShape = new Dimension(
- (int)picShape.getAnchor().getWidth(),
- (int)picShape.getAnchor().getHeight()
- );
- assertEquals(dimPd, dimShape);
-
- double newWidth = (dimPd.getWidth()*(100d/dimPd.getHeight()));
- // ... -1 is a rounding error
- Rectangle2D expRect = new Rectangle2D.Double(rbf(50+300-newWidth, picShape), 50, rbf(newWidth, picShape), 100);
- Rectangle2D target = new Rectangle2D.Double(50,50,300,100);
- new DrawPictureShape(picShape).resize(target, RectAlign.BOTTOM_RIGHT);
- Rectangle2D actRect = picShape.getAnchor();
- assertEquals(expRect.getX(), actRect.getX(), .0001);
- assertEquals(expRect.getY(), actRect.getY(), .0001);
- assertEquals(expRect.getWidth(), actRect.getWidth(), .0001);
- assertEquals(expRect.getHeight(), actRect.getHeight(), .0001);
- ss.close();
- }
-
- // round back and forth - points -> master -> points
- static double rbf(double val, PictureShape<?,?> picShape) {
- if (picShape.getClass().getName().contains("HSLF")) {
- return Units.masterToPoints(Units.pointsToMaster(val));
- } else {
- return val;
- }
- }
-}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.sl.tests;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
+
+public class SLCommonUtils {
+ private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
+
+ /** a generic way to open a sample slideshow document **/
+ public static SlideShow<?,?> openSampleSlideshow(String sampleName) throws IOException {
+ try (InputStream is = _slTests.openResourceAsStream(sampleName)) {
+ return SlideShowFactory.create(is);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tests, if the scratchpad classes are on the classpath
+ *
+ * @return true, if only xslf is on the classpath, and false, if both classpaths
+ * (XSLF and HSLF) can be used/referenced
+ */
+ public static boolean xslfOnly() {
+ try {
+ Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow");
+ return false;
+ } catch (Exception e) {
+ return true;
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.sl.tests;
+
+import static org.apache.poi.sl.tests.SLCommonUtils.xslfOnly;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontFormatException;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.common.usermodel.fonts.FontGroup;
+import org.apache.poi.sl.draw.Drawable;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
+import org.apache.poi.sl.usermodel.TextBox;
+import org.apache.poi.sl.usermodel.TextParagraph;
+import org.apache.poi.sl.usermodel.TextRun;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Test rendering - specific to font handling
+ */
+public class TestFonts {
+ private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
+
+ private static final String JPTEXT =
+ "\u3061\u3087\u3063\u3068\u65E9\u3044\u3051\u3069T\u30B7\u30E3\u30C4\u304C\u7740\u305F\u304F\u306A" +
+ "\u308B\u5B63\u7BC0\u2661\u304A\u6BCD\u3055\u3093\u306E\u5F71\u97FF\u304B\u3001\u975E\u5E38\u306B" +
+ "\u6050\u7ADC\u304C\u5927\u597D\u304D\u3067\u3059\u3002\u3082\u3046\u98FC\u3044\u305F\u3044\u304F" +
+ "\u3089\u3044\u5927\u597D\u304D\u3067\u3059\u3002#\u30B8\u30E5\u30E9\u30B7\u30C3\u30AF\u30EF\u30FC" +
+ "\u30EB\u30C9 \u306E\u30E9\u30D7\u30C8\u30EB4\u59C9\u59B9\u3068\u304B\u6FC0\u7684\u306B\u53EF\u611B" +
+ "\u304F\u3066\u53EF\u611B\u304F\u3066\u53EF\u611B\u304F\u3066\u53EF\u611B\u3044\u3067\u3059\u3002" +
+ "\u3081\u308D\u3081\u308D\u3001\u5927\u597D\u304D\u2661\u304A\u6BCD\u3055\u3093\u3082\u6050\u7ADC" +
+ "\u304C\u597D\u304D\u3067\u3001\u5C0F\u3055\u3044\u9803\u3001\u53E4\u4EE3\u751F\u7269\u306E\u56F3" +
+ "\u9451\u3092\u4E00\u7DD2\u306B\u898B\u3066\u305F\u306E\u601D\u3044\u51FA\u3059\u301C\u3068\u3044";
+
+ private static final String[] INIT_FONTS = {"mona.ttf"};
+
+ @BeforeClass
+ public static void initGE() throws FontFormatException, IOException {
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ for (String s : INIT_FONTS) {
+ Font font = Font.createFont(Font.TRUETYPE_FONT, _slTests.getFile(s));
+ ge.registerFont(font);
+ }
+ }
+
+ @Test
+ public void resizeToFitTextHSLF() throws IOException, ReflectiveOperationException {
+ assumeFalse(xslfOnly());
+ SlideShow<?,?> ppt = (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
+ resizeToFitText(ppt);
+ ppt.close();
+ }
+
+ @Test
+ public void resizeToFitTextXSLF() throws IOException {
+ SlideShow<?,?> ppt = new XMLSlideShow();
+ resizeToFitText(ppt);
+ ppt.close();
+ }
+
+ private void resizeToFitText(SlideShow<?,?> slideshow) throws IOException {
+ Slide<?,?> sld = slideshow.createSlide();
+ TextBox<?,?> tb = sld.createTextBox();
+ tb.setAnchor(new Rectangle(50, 50, 200, 50));
+ tb.setStrokeStyle(Color.black, LineDash.SOLID, 3);
+ tb.setText(JPTEXT);
+
+ setFont(tb, "NoSuchFont", FontGroup.LATIN);
+
+ Dimension pgsize = slideshow.getPageSize();
+ int width = (int)pgsize.getWidth();
+ int height = (int)pgsize.getHeight();
+
+ BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D graphics = img.createGraphics();
+
+ Map<String,String> fallbackMap = new HashMap<>();
+ fallbackMap.put("NoSuchFont", "Mona");
+ // in XSLF the fonts default to the theme fonts (Calibri), if the font group is not overridden
+ // see XSLFTextRun.XSLFTextInfo.getCTTextFont
+ fallbackMap.put("Calibri", "Mona");
+ graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap);
+ graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+
+ tb.resizeToFitText(graphics);
+ graphics.dispose();
+
+ Rectangle2D anc = tb.getAnchor();
+ // ignore font metrics differences on windows / linux (... hopefully ...)
+ int tbHeight = (int)anc.getHeight();
+ assertTrue(tbHeight > 100);
+ }
+
+ private void setFont(TextBox<?,?> tb, String fontFamily, FontGroup fontGroup) {
+ // TODO: set east asian font family - MS Office uses "MS Mincho" or "MS Gothic" as a fallback
+ // see https://stackoverflow.com/questions/26063828 for good explanation about the font metrics
+ // differences on different environments
+ for (TextParagraph<?,?,? extends TextRun> p : tb.getTextParagraphs()) {
+ for (TextRun r : p.getTextRuns()) {
+ r.setFontFamily(fontFamily, fontGroup);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.sl.tests;
+
+import static org.apache.poi.sl.tests.SLCommonUtils.openSampleSlideshow;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.poi.sl.usermodel.Shape;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.TextParagraph;
+import org.apache.poi.sl.usermodel.TextShape;
+import org.junit.Test;
+
+public class TestHeadersFooters {
+ @Test
+ public void bug58144c() throws IOException {
+ SlideShow<?,?> ppt = openSampleSlideshow("bug58144-headers-footers-2007.pptx");
+ testSlideShow(ppt);
+ ppt.close();
+ }
+
+ private void testSlideShow(SlideShow<?,?> ppt) {
+ Slide<?,?> sl = ppt.getSlides().get(0);
+
+ List<? extends Shape<?,?>> shapes = sl.getShapes();
+ TextShape<?,?> ts0 = (TextShape<?,?>)shapes.get(0);
+ assertEquals("Test file", ts0.getText());
+ TextShape<?,?> ts1 = (TextShape<?,?>)shapes.get(1);
+ assertEquals("Has some text in the headers and footers", ts1.getText());
+ TextShape<?,?> ts2 = (TextShape<?,?>)shapes.get(2);
+ assertEquals("Slide footer", ts2.getText());
+ List<? extends TextParagraph<?,?,?>> ltp = ts2.getTextParagraphs();
+ assertTrue(ltp.get(0).isHeaderOrFooter());
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.sl.tests;
+
+import static org.apache.poi.sl.tests.SLCommonUtils.xslfOnly;
+import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.EXCEL_V12;
+import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.EXCEL_V8;
+import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.PDF;
+import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.WORD_V12;
+import static org.apache.poi.sl.usermodel.ObjectMetaData.Application.WORD_V8;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+
+import java.awt.geom.Rectangle2D;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.POIDocument;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.poifs.storage.RawDataUtil;
+import org.apache.poi.sl.usermodel.ObjectMetaData;
+import org.apache.poi.sl.usermodel.ObjectShape;
+import org.apache.poi.sl.usermodel.PictureData;
+import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class TestOleShape {
+ private static final String PDF_SAMPLE =
+ "H4sIAAAAAAAAAJWUezRUWxzHe+o2FXncVtxLpxi3FPOeKYspjMdM5J1S4TTOaDIzxzpzJo9CUrnrSiUxIeT" +
+ "9jB7yqInihrhepTwqt1AT5VZCC7XcY0LWcv+5Z521zz6fvX+/vb/7t9cX78CyMiQZ0XD4W4OFEzgKQATgg4" +
+ "dxJiYAwRYS+aCHACqGnHAAABCs+AIUQrCvAEQhFsSFvSEck4kTowgECnEBl6E4OxGesfLkl2Bc0g5V/MCHt" +
+ "duqroTFC27YIKGAp+OL5Ou1SsmebA1XvciLk+Ucg84aLclQZhRZmh0amrG9Ina4t7Lh+ZCAHyezsg/NXsZg" +
+ "vuPw8NIedsrI2sZlz2vfhLkZfIgfMr4zFvTrmfbRgMmPw1UTvWk+r4MCZfLtj2WPPStVJ0P2PiKkxo+YnJ5" +
+ "Ua7v5UnefkB9ev0vSR37a8NrsC2lApaLp7086wS3Lzi2LqB3TMW2POrdRRUYMFYWs8vBo/kSQ6dYXpR6rxM" +
+ "UXM0vqu4arpe5dha7XS5MYS5P1arVG653sb8pXqReVw/TfjK8R3q4Z7X7Uk9dZ2Bcl8Wpmsl80Xf1QTOxe3" +
+ "Nutwus0kYge1LoHvgKLbc/f6WvdcsBfS9ctU3vSaneHNm0w/uhrm0Zett5O83s2xh2Gm8WZfWJ+/CNWruZ2" +
+ "cap8tR2/U9bAfRBbYt3PL9jvb3+0usqSF6vfrFuEq8Hf6jgrx/fERpZJEjKbHtJ11jCdUwI7Oc8QrmZf2pr" +
+ "L43WJn1mlT1ydV+QbrndcdN3qSEnicVhmoJyfWyprUEsIZlPyvi0tiEy7FzkOnqlE/qC6xFSpyg0E8tODa7" +
+ "qiKX61hMxRkZt73ITLWIHwtZtj71NbS4/BgKHnssOMcXOp1aacX4A//V+VFN4TWl6QryxdkcAp79BZcipmP" +
+ "OWOWkS6KhqUWlG+yCCxVMMtfW+9e56++gKHYEs9PNJztTI6KtyfOCDPOBppt3udRs3NpGrKfrs3i3Nivtrs" +
+ "VTl5LFerXZlTbf5XumbeYsOfwnve5ksEjKy6s1Z78rpbeJq7biTdzWwU3vhZ1GqkYb9D+t6mYvWLhXn6FWi" +
+ "c60VWpbBtVYHLQkmbh6Txwm6Ul3LbNW/Hs5FtLnlNX3fsAX2jPdlOI5W3HDIcm2MyNiR39rdyHlpwusjoOj" +
+ "I3IKfgPMILSzHZInmQaWyUFXEi0bHsCLX8pm9Gzl2vou7E3rrkPYdt1EwW3R5Qcg8rwzk88c1p13l8v+WkY" +
+ "75FHeS7XrvRsHgLy+wfr2EBRfNJ/4UVhUrihRqDktXciPGxWv1eXs396/0lqWG3YtU/A+D90hrT46cumSUN" +
+ "rBdG0G2Knn3T9Kw0X96vbhxMyr92uqUNOa4aEnGqP8us6GULm7mIyFKuxnOW2MZEEuKXmOpxnnqlwiMn+ju" +
+ "Xu+inC5mpG9oesxKkhcJq9bra5vR3H7l10hGbAxqu6t0LvHzaDnPIp/zeu0iXj1NNtVc+cMyUsH18u7TGXJ" +
+ "XiL4W3tqaL2mq6zkgXWB6kOTB3RxW8PHAOvzfaufDptdg7qmZlEcrUzbd5jKtVb85Sr9jaMT8a3y2Q30+3/" +
+ "FrsfGZDblh/mYnHhCg3ekm2q1JIYEVCd9rv42PNb9RFpuSsa4MNE0GfdSYDv6lsudikg4NE3tNugfWmfIY6" +
+ "7TeYvZCItG0zmDxrQwrjsQxArZ1RzHSA72CKgURgyqQszAASQOCCWItZETaAtdg7nYc2x85cAv0ggOAA+kC" +
+ "KnA4gAolQLGzG3ewgbz5oDgcA+zBEBEhUkhGDQiZvpc3tHlBMtYBFKBYsBiiz0dYILPGbs73vqynoDHLGKA" +
+ "KKxH5TK3MDZzAbQBEJNPNngc1iQUf4XMjJ2nxazxR3gsSwBOFCYoCsWPOHRtJ/ahQronbyvcWYnqljcJrdu" +
+ "2RK9pwE9DkJLLDioDACbOSCfAQGSEYkqhGJCGw8hKJ+xgSCgvogoN8hPldsBCM+mzZ9P0wE9pZwof8V92MD" +
+ "jHkKLEAUFMA+04XC1EzX6UdMAALxcERgK444+wB0Go1CA3jANCNRGdj1UoyIZhlpPsMobf48GmkeI1Pp8xi" +
+ "Nsm0eo9O3/mAoAvIFEKIQ58wPgrAtK+oJwyjAmL0+bBEPBugzGsUoiKAKhSQGmYjD4y3trXD/AmBc9IeqBwAA";
+
+ enum Api { HSLF, XSLF }
+
+
+ @Parameter(value = 0)
+ public Api api;
+ @Parameter(value = 1)
+ public ObjectMetaData.Application app;
+
+
+ private static File pictureFile;
+
+ @BeforeClass
+ public static void initPicture() {
+ pictureFile = POIDataSamples.getSlideShowInstance().getFile("wrench.emf");
+ }
+
+
+ @Parameters(name="{0} {1}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] {
+ { Api.HSLF, EXCEL_V8 },
+ { Api.HSLF, WORD_V8 },
+ { Api.HSLF, PDF },
+ { Api.XSLF, EXCEL_V12 },
+ { Api.XSLF, WORD_V12 },
+ { Api.XSLF, PDF },
+ });
+ }
+
+ @Test
+ public void embedData() throws IOException, InvalidFormatException, ReflectiveOperationException {
+ final ByteArrayInputStream pptBytes;
+ try (SlideShow<?,?> ppt = createSlideShow()) {
+ final PictureData picData = ppt.addPicture(pictureFile, PictureType.EMF);
+ final Slide<?,?> slide = ppt.createSlide();
+ final ObjectShape<?,?> oleShape = slide.createOleShape(picData);
+ oleShape.setAnchor(new Rectangle2D.Double(100,100,100,100));
+ try (OutputStream os = oleShape.updateObjectData(app, null)) {
+ fillOleData(os);
+ }
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream(50000);
+ ppt.write(bos);
+ pptBytes = new ByteArrayInputStream(bos.toByteArray());
+ }
+ try (SlideShow<?,?> ppt = SlideShowFactory.create(pptBytes)) {
+ final ObjectShape<?,?> oleShape = (ObjectShape<?,?>)ppt.getSlides().get(0).getShapes().get(0);
+ try (InputStream bis = oleShape.readObjectData()) {
+ validateOleData(bis);
+ }
+ }
+ }
+
+ private SlideShow<?,?> createSlideShow() throws ReflectiveOperationException {
+ if (api == Api.XSLF) {
+ return new XMLSlideShow();
+ } else {
+ assumeFalse(xslfOnly());
+ return (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
+ }
+ }
+
+
+ private void fillOleData(final OutputStream out) throws IOException {
+ switch (app) {
+ case EXCEL_V8:
+ case EXCEL_V12:
+ try (Workbook wb = (app == EXCEL_V12) ? new XSSFWorkbook() : new HSSFWorkbook()) {
+ wb.createSheet().createRow(0).createCell(0).setCellValue("test me");
+ wb.write(out);
+ }
+ break;
+ case WORD_V8:
+ try (InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream("simple.doc")) {
+ IOUtils.copy(is, out);
+ }
+ break;
+ case WORD_V12:
+ try (XWPFDocument doc = new XWPFDocument()) {
+ doc.createParagraph().createRun().setText("Test me");
+ doc.write(out);
+ }
+ break;
+ case PDF:
+ out.write(RawDataUtil.decompress(PDF_SAMPLE));
+ break;
+ default:
+ case CUSTOM:
+ fail("not implemented");
+ break;
+ }
+ }
+
+ private void validateOleData(final InputStream in) throws IOException, InvalidFormatException, ReflectiveOperationException {
+ switch (app) {
+ case EXCEL_V8:
+ case EXCEL_V12:
+ try (Workbook wb = WorkbookFactory.create(in)) {
+ assertEquals("test me", wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
+ }
+ break;
+ case WORD_V8:
+ Class<? extends POIDocument> clazz = (Class<? extends POIDocument>)Class.forName("org.apache.poi.hwpf.HWPFDocument");
+ Constructor<? extends POIDocument> con = clazz.getDeclaredConstructor(InputStream.class);
+ Method m = clazz.getMethod("getDocumentText");
+ try (POIDocument doc = con.newInstance(in)) {
+ assertEquals("This is a simple file created with Word 97-SR2.\r", m.invoke(doc));
+ }
+ break;
+ case WORD_V12:
+ try (XWPFDocument doc = new XWPFDocument(in)) {
+ assertEquals("Test me", doc.getParagraphs().get(0).getText());
+ }
+ break;
+ case PDF:
+ final byte[] expected = RawDataUtil.decompress(PDF_SAMPLE);
+ final byte[] actual = IOUtils.toByteArray(in);
+ assertArrayEquals(expected, actual);
+ break;
+ default:
+ case CUSTOM:
+ fail("not implemented");
+ break;
+ }
+
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.sl.tests;
+
+import static org.apache.poi.sl.tests.SLCommonUtils.xslfOnly;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.junit.Test;
+
+public class TestSlide {
+
+ @Test
+ public void hideHSLF() throws IOException, ReflectiveOperationException {
+ assumeFalse(xslfOnly());
+ SlideShow<?,?> ppt1 = (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
+ hideSlide(ppt1);
+ ppt1.close();
+ }
+
+ @Test
+ public void hideXSLF() throws IOException {
+ SlideShow<?,?> ppt1 = new XMLSlideShow();
+ hideSlide(ppt1);
+ ppt1.close();
+ }
+
+ private void hideSlide(SlideShow<?,?> ppt1) throws IOException {
+ ppt1.createSlide().setHidden(true);
+ ppt1.createSlide();
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ppt1.write(bos);
+ ppt1.close();
+
+ InputStream is = new ByteArrayInputStream(bos.toByteArray());
+ SlideShow<?,?> ppt2 = SlideShowFactory.create(is);
+
+ Boolean[] hiddenState = ppt2.getSlides().stream().map(e -> e.isHidden()).toArray(Boolean[]::new);
+
+ assertTrue(hiddenState[0]);
+ assertFalse(hiddenState[1]);
+
+ ppt2.close();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * ====================================================================
+ * 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.sl.tests;
+
+import static org.apache.poi.sl.tests.SLCommonUtils.openSampleSlideshow;
+import static org.apache.poi.sl.tests.SLCommonUtils.xslfOnly;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
+import java.awt.geom.Rectangle2D;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
+import org.apache.poi.sl.usermodel.TableCell;
+import org.apache.poi.sl.usermodel.TableShape;
+import org.apache.poi.sl.usermodel.TextShape.TextDirection;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.junit.Test;
+
+public class TestTable {
+
+ @Test
+ public void colWidthRowHeight() throws IOException {
+ assumeFalse(xslfOnly());
+
+ // Test of table dimensions of same slideshow saved as ppt/x
+ // to check if both return similar (points) value
+ SlideShow<?,?> ppt = openSampleSlideshow("table_test.ppt");
+ TableShape<?,?> ts = (TableShape<?,?>)ppt.getSlides().get(0).getShapes().get(0);
+
+ SlideShow<?,?> pptx = openSampleSlideshow("table_test.pptx");
+ TableShape<?,?> tsx = (TableShape<?,?>)pptx.getSlides().get(0).getShapes().get(0);
+
+ // assume table shape should be equal to itself
+ confirmTableShapeEqual(ts, ts);
+ confirmTableShapeEqual(tsx, tsx);
+
+ // assert ppt and pptx versions of the same table have the same shape
+ confirmTableShapeEqual(ts, tsx);
+
+ // change row height and validate again
+ tsx.setRowHeight(1, 50);
+ ts.setRowHeight(1, 50);
+ confirmTableShapeEqual(ts, tsx);
+
+ pptx.close();
+ ppt.close();
+ }
+
+ private void confirmTableShapeEqual(TableShape<?,?> tableA, TableShape<?,?> tableB) {
+ int cols = tableA.getNumberOfColumns();
+ int rows = tableA.getNumberOfRows();
+
+ int colsx = tableB.getNumberOfColumns();
+ int rowsx = tableB.getNumberOfRows();
+
+ assertEquals("tables should have same number of columns", cols, colsx);
+ assertEquals("tables should have same number of rows", rows, rowsx);
+
+ for (int i=0; i<cols; i++) {
+ assertEquals("Width of column " + i + " should be equal",
+ tableA.getColumnWidth(i), tableB.getColumnWidth(i), 0.2);
+ }
+
+ for (int i=0; i<rows; i++) {
+ assertEquals("Height of row " + i + " should be equal",
+ tableA.getRowHeight(i), tableB.getRowHeight(i), 0.3);
+ }
+ }
+
+ @Test
+ public void directionHSLF() throws IOException, ReflectiveOperationException {
+ assumeFalse(xslfOnly());
+ SlideShow<?,?> ppt1 = (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
+ testTextDirection(ppt1);
+ ppt1.close();
+ }
+
+ @Test
+ public void directionXSLF() throws IOException {
+ SlideShow<?,?> ppt1 = new XMLSlideShow();
+ testTextDirection(ppt1);
+ ppt1.close();
+ }
+
+ private void testTextDirection(SlideShow<?,?> ppt1) throws IOException {
+
+ TextDirection[] tds = {
+ TextDirection.HORIZONTAL,
+ TextDirection.VERTICAL,
+ TextDirection.VERTICAL_270,
+ // TextDirection.STACKED is not supported on HSLF
+ };
+
+ TableShape<?,?> tbl1 = ppt1.createSlide().createTable(1, 3);
+ tbl1.setAnchor(new Rectangle2D.Double(50, 50, 200, 200));
+
+ int col = 0;
+ for (TextDirection td : tds) {
+ TableCell<?,?> c = tbl1.getCell(0, col++);
+ if (c != null) {
+ c.setTextDirection(td);
+ c.setText("bla");
+ }
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ppt1.write(bos);
+ ppt1.close();
+
+ InputStream is = new ByteArrayInputStream(bos.toByteArray());
+ SlideShow<?,?> ppt2 = SlideShowFactory.create(is);
+ TableShape<?,?> tbl2 = (TableShape<?,?>)ppt2.getSlides().get(0).getShapes().get(0);
+
+ col = 0;
+ for (TextDirection td : tds) {
+ TableCell<?,?> c = tbl2.getCell(0, col++);
+ assertEquals(td, c.getTextDirection());
+ }
+ ppt2.close();
+ }
+
+ @Test
+ public void tableSpan() throws IOException {
+ String[] files = (xslfOnly()) ? new String[]{"bug60993.pptx"} : new String[]{"bug60993.pptx", "bug60993.ppt"};
+ for (String f : files) {
+ SlideShow<?,?> ppt = openSampleSlideshow(f);
+ Slide<?,?> slide = ppt.getSlides().get(0);
+ TableShape<?,?> ts = (TableShape<?,?>)slide.getShapes().get(0);
+ int cols = ts.getNumberOfColumns();
+ int rows = ts.getNumberOfRows();
+ for (int r=0; r<rows; r++) {
+ for (int c=0; c<cols; c++) {
+ TableCell<?,?> tc = ts.getCell(r, c);
+ int rc = r*10+c;
+ String msg = f+" (r"+r+",c"+c+")";
+ switch (rc) {
+ case 22:
+ case 51:
+ if (f.endsWith("ppt")) {
+ assertNull(msg, tc);
+ } else {
+ assertNotNull(msg, tc);
+ assertTrue(msg, tc.isMerged());
+ }
+ break;
+ case 21:
+ assertNotNull(msg, tc);
+ assertEquals(msg, 1, tc.getRowSpan());
+ assertEquals(msg, 2, tc.getGridSpan());
+ assertFalse(msg, tc.isMerged());
+ break;
+ case 41:
+ assertNotNull(msg, tc);
+ assertEquals(msg, 2, tc.getRowSpan());
+ assertEquals(msg, 1, tc.getGridSpan());
+ assertFalse(msg, tc.isMerged());
+ break;
+ default:
+ assertNotNull(msg, tc);
+ assertEquals(msg, 1, tc.getRowSpan());
+ assertEquals(msg, 1, tc.getGridSpan());
+ assertFalse(msg, tc.isMerged());
+ break;
+ }
+ }
+ }
+ ppt.close();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * ====================================================================
+ * 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.sl.tests.draw;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeFalse;
+
+import java.awt.Dimension;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.sl.draw.DrawPictureShape;
+import org.apache.poi.sl.usermodel.PictureData;
+import org.apache.poi.sl.usermodel.PictureShape;
+import org.apache.poi.sl.usermodel.RectAlign;
+import org.apache.poi.sl.usermodel.Shape;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
+import org.apache.poi.util.Units;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestDrawPictureShape {
+ final static POIDataSamples ssSamples = POIDataSamples.getSlideShowInstance();
+
+ private static boolean xslfOnly;
+
+ @BeforeClass
+ public static void checkHslf() {
+ try {
+ Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow");
+ } catch (Exception e) {
+ xslfOnly = true;
+ }
+ }
+
+ /** a generic way to open a sample slideshow document **/
+ public static SlideShow<?,?> openSampleDocument(String sampleName) throws IOException {
+ try (InputStream is = ssSamples.openResourceAsStream(sampleName)) {
+ return SlideShowFactory.create(is);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testResizeHSLF() throws IOException {
+ assumeFalse(xslfOnly);
+ testResize("pictures.ppt");
+ }
+
+ @Test
+ public void testResizeXSLF() throws IOException {
+ testResize("shapes.pptx");
+ }
+
+
+ public void testResize(String file) throws IOException {
+ SlideShow<?,?> ss = openSampleDocument(file);
+
+ Slide<?,?> slide = ss.getSlides().get(0);
+ PictureShape<?,?> picShape = null;
+ for (Shape<?,?> shape : slide.getShapes()) {
+ if (shape instanceof PictureShape) {
+ picShape = (PictureShape<?,?>)shape;
+ break;
+ }
+ }
+ assertNotNull(picShape);
+ PictureData pd = picShape.getPictureData();
+ Dimension dimPd = pd.getImageDimension();
+ new DrawPictureShape(picShape).resize();
+ Dimension dimShape = new Dimension(
+ (int)picShape.getAnchor().getWidth(),
+ (int)picShape.getAnchor().getHeight()
+ );
+ assertEquals(dimPd, dimShape);
+
+ double newWidth = (dimPd.getWidth()*(100d/dimPd.getHeight()));
+ // ... -1 is a rounding error
+ Rectangle2D expRect = new Rectangle2D.Double(rbf(50+300-newWidth, picShape), 50, rbf(newWidth, picShape), 100);
+ Rectangle2D target = new Rectangle2D.Double(50,50,300,100);
+ new DrawPictureShape(picShape).resize(target, RectAlign.BOTTOM_RIGHT);
+ Rectangle2D actRect = picShape.getAnchor();
+ assertEquals(expRect.getX(), actRect.getX(), .0001);
+ assertEquals(expRect.getY(), actRect.getY(), .0001);
+ assertEquals(expRect.getWidth(), actRect.getWidth(), .0001);
+ assertEquals(expRect.getHeight(), actRect.getHeight(), .0001);
+ ss.close();
+ }
+
+ // round back and forth - points -> master -> points
+ static double rbf(double val, PictureShape<?,?> picShape) {
+ if (picShape.getClass().getName().contains("HSLF")) {
+ return Units.masterToPoints(Units.pointsToMaster(val));
+ } else {
+ return val;
+ }
+ }
+}
+++ /dev/null
-/* ====================================================================
- 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.ss;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.apache.poi.EmptyFileException;
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-import org.apache.poi.util.SuppressForbidden;
-import org.apache.poi.util.TempFile;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
-import org.junit.Test;
-
-public final class TestWorkbookFactory {
- private static final String xls = "SampleSS.xls";
- private static final String xlsx = "SampleSS.xlsx";
- private static final String[] xls_protected = new String[] {"password.xls", "password"};
- private static final String[] xlsx_protected = new String[]{"protected_passtika.xlsx", "tika"};
- private static final String txt = "SampleSS.txt";
-
- private static final POILogger LOGGER = POILogFactory.getLogger(TestWorkbookFactory.class);
-
- /**
- * Closes the sample workbook read in from filename.
- * Throws an exception if closing the workbook results in the file on disk getting modified.
- *
- * @param filename the sample workbook to read in
- * @param wb the workbook to close
- */
- private static void assertCloseDoesNotModifyFile(String filename, Workbook wb) throws IOException {
- final byte[] before = HSSFTestDataSamples.getTestDataFileContent(filename);
- // FIXME: replace with wb.close() when bug 58779 is resolved
- closeOrRevert(wb);
- final byte[] after = HSSFTestDataSamples.getTestDataFileContent(filename);
- assertArrayEquals(filename + " sample file was modified as a result of closing the workbook",
- before, after);
- }
-
- /**
- * bug 58779: Closing an XSSFWorkbook that was created with WorkbookFactory modifies the file
- * FIXME: replace this method with wb.close() when bug 58779 is resolved.
- *
- * @param wb the workbook to close or revert
- */
- private static void closeOrRevert(Workbook wb) throws IOException {
- if (wb instanceof HSSFWorkbook) {
- wb.close();
- }
- else if (wb instanceof XSSFWorkbook) {
- final XSSFWorkbook xwb = (XSSFWorkbook) wb;
- if (PackageAccess.READ == xwb.getPackage().getPackageAccess()) {
- xwb.close();
- }
- else {
- // TODO: close() re-writes the sample-file?! Resort to revert() for now to close file handle...
- LOGGER.log(POILogger.WARN,
- "reverting XSSFWorkbook rather than closing it to avoid close() modifying the file on disk. " +
- "Refer to bug 58779.");
- xwb.getPackage().revert();
- }
- } else {
- throw new RuntimeException("Unsupported workbook type");
- }
- }
-
- @Test
- public void testCreateNative() throws Exception {
- Workbook wb;
-
- // POIFS -> hssf
- wb = WorkbookFactory.create(
- new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls))
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- wb = WorkbookFactory.create(
- new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls)).getRoot()
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- // Package -> xssf
- wb = XSSFWorkbookFactory.create(
- OPCPackage.open(
- HSSFTestDataSamples.openSampleFileStream(xlsx))
- );
- assertNotNull(wb);
- //noinspection ConstantConditions
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx, wb);
- }
-
- @Test
- public void testCreateReadOnly() throws Exception {
- Workbook wb;
-
- // POIFS -> hssf
- wb = WorkbookFactory.create(HSSFTestDataSamples.getSampleFile(xls), null, true);
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- // Package -> xssf
- wb = WorkbookFactory.create(HSSFTestDataSamples.getSampleFile(xlsx), null, true);
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx, wb);
- }
-
- /**
- * Creates the appropriate kind of Workbook, but
- * checking the mime magic at the start of the
- * InputStream, then creating what's required.
- */
- @Test
- public void testCreateGeneric() throws Exception {
- Workbook wb;
-
- // InputStream -> either
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xls)
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xlsx)
- );
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx, wb);
-
- // File -> either
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xls)
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xlsx)
- );
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx, wb);
-
- // Invalid type -> exception
- final byte[] before = HSSFTestDataSamples.getTestDataFileContent(txt);
- try {
- try (InputStream stream = HSSFTestDataSamples.openSampleFileStream(txt)) {
- wb = WorkbookFactory.create(stream);
- assertNotNull(wb);
- }
- fail();
- } catch(IOException e) {
- // Good
- }
- final byte[] after = HSSFTestDataSamples.getTestDataFileContent(txt);
- assertArrayEquals("Invalid type file was modified after trying to open the file as a spreadsheet",
- before, after);
- }
-
- /**
- * Check that the overloaded stream methods which take passwords work properly
- */
- @Test
- public void testCreateWithPasswordFromStream() throws Exception {
- Workbook wb;
-
- // Unprotected, no password given, opens normally
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xls), null
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xlsx), null
- );
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx, wb);
-
-
- // Unprotected, wrong password, opens normally
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xls), "wrong"
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xlsx), "wrong"
- );
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx, wb);
-
-
- // Protected, correct password, opens fine
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xls_protected[0]), xls_protected[1]
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls_protected[0], wb);
-
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xlsx_protected[0]), xlsx_protected[1]
- );
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
-
-
- // Protected, wrong password, throws Exception
- try {
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xls_protected[0]), "wrong"
- );
- assertCloseDoesNotModifyFile(xls_protected[0], wb);
- fail("Shouldn't be able to open with the wrong password");
- } catch (EncryptedDocumentException e) {
- // expected here
- }
-
- try {
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.openSampleFileStream(xlsx_protected[0]), "wrong"
- );
- assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
- fail("Shouldn't be able to open with the wrong password");
- } catch (EncryptedDocumentException e) {
- // expected here
- }
- }
-
- /**
- * Check that the overloaded file methods which take passwords work properly
- */
- @Test
- public void testCreateWithPasswordFromFile() throws Exception {
- Workbook wb;
-
- // Unprotected, no password given, opens normally
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xls), null
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xlsx), null
- );
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx, wb);
-
- // Unprotected, wrong password, opens normally
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xls), "wrong"
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
-
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xlsx), "wrong"
- );
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertCloseDoesNotModifyFile(xlsx, wb);
-
- // Protected, correct password, opens fine
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xls_protected[0]), xls_protected[1]
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls_protected[0], wb);
-
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xlsx_protected[0]), xlsx_protected[1]
- );
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- assertTrue(wb.getNumberOfSheets() > 0);
- assertNotNull(wb.getSheetAt(0));
- assertNotNull(wb.getSheetAt(0).getRow(0));
- assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
-
- // Protected, wrong password, throws Exception
- try {
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xls_protected[0]), "wrong"
- );
- assertCloseDoesNotModifyFile(xls_protected[0], wb);
- fail("Shouldn't be able to open with the wrong password");
- } catch (EncryptedDocumentException e) {
- // expected here
- }
-
- try {
- wb = WorkbookFactory.create(
- HSSFTestDataSamples.getSampleFile(xlsx_protected[0]), "wrong"
- );
- assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
- fail("Shouldn't be able to open with the wrong password");
- } catch (EncryptedDocumentException e) {
- // expected here
- }
- }
-
- /**
- * Check that a helpful exception is given on an empty input stream
- */
- @Test(expected = EmptyFileException.class)
- public void testEmptyInputStream() throws Exception {
- InputStream emptyStream = new ByteArrayInputStream(new byte[0]);
- WorkbookFactory.create(emptyStream);
- }
-
- /**
- * Check that a helpful exception is given on an empty file
- */
- @Test(expected = EmptyFileException.class)
- public void testEmptyFile() throws Exception {
- File emptyFile = TempFile.createTempFile("empty", ".poi");
- try {
- WorkbookFactory.create(emptyFile);
- fail("Shouldn't be able to create for an empty file");
- } finally {
- assertTrue(emptyFile.delete());
- }
- }
-
- /**
- * Check that a helpful exception is raised on a non-existing file
- */
- @Test(expected = FileNotFoundException.class)
- public void testNonExistingFile() throws Exception {
- File nonExistingFile = new File("notExistingFile");
- assertFalse(nonExistingFile.exists());
- WorkbookFactory.create(nonExistingFile, "password", true);
- }
-
- /**
- * See Bugzilla bug #62831 - #WorkbookFactory.create(File) needs
- * to work for sub-classes of File too, eg JFileChooser
- */
- @Test(expected = ClassCastException.class)
- public void testFileSubclass() throws Exception {
- File normalXLS = HSSFTestDataSamples.getSampleFile(xls);
- File normalXLSX = HSSFTestDataSamples.getSampleFile(xlsx);
- File altXLS = new TestFile(normalXLS.getAbsolutePath());
- File altXLSX = new TestFile(normalXLSX.getAbsolutePath());
- assertTrue(altXLS.exists());
- assertTrue(altXLSX.exists());
-
- Workbook wb = WorkbookFactory.create(altXLS);
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- closeOrRevert(wb);
-
- wb = WorkbookFactory.create(altXLSX);
- assertNotNull(wb);
- assertTrue(wb instanceof XSSFWorkbook);
- closeOrRevert(wb);
-
- // check what happens if the file is passed as "Object"
-
- //noinspection deprecation
- WorkbookFactory.create((Object)altXLSX);
- // expected a ClassCastException here because create() in this case expects an object of type "OPCPackage"
- }
-
- private static class TestFile extends File {
- public TestFile(String file) {
- super(file);
- }
- }
-
- /**
- * Check that the overloaded file methods which take passwords work properly
- */
- @Test
- public void testCreateEmpty() throws Exception {
- Workbook wb = WorkbookFactory.create(false);
- assertTrue(wb instanceof HSSFWorkbook);
- closeOrRevert(wb);
-
- wb = WorkbookFactory.create(true);
- assertTrue(wb instanceof XSSFWorkbook);
- closeOrRevert(wb);
- }
-
- @Test
- @SuppressForbidden("test code")
- public void testOpenManyHSSF() throws Exception {
- final int size = 1000;
- ExecutorService executorService = Executors.newFixedThreadPool(10);
- ArrayList<Future<Boolean>> futures = new ArrayList(size);
- for (int i = 0; i < size; i++) {
- futures.add(executorService.submit(() -> openHSSFFile()));
- }
- for (Future<Boolean> future: futures) {
- assertTrue(future.get());
- }
- }
-
- @Test(expected = IOException.class)
- public void testInvalidFormatException() throws IOException {
- String filename = "OPCCompliance_DerivedPartNameFAIL.docx";
- WorkbookFactory.create(POIDataSamples.getOpenXML4JInstance().openResourceAsStream(filename));
- }
-
- private boolean openHSSFFile() {
- try {
- // POIFS -> hssf
- Workbook wb = WorkbookFactory.create(
- new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls))
- );
- assertNotNull(wb);
- assertTrue(wb instanceof HSSFWorkbook);
- assertCloseDoesNotModifyFile(xls, wb);
- return true;
- } catch (Exception e) {
- return false;
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.extractor;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.List;
-
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.junit.Test;
-
-public class TestEmbeddedExtractor {
- private static final POIDataSamples samples = POIDataSamples.getSpreadSheetInstance();
-
- @Test
- public void extractPDFfromEMF() throws Exception {
- InputStream fis = samples.openResourceAsStream("Basic_Expense_Template_2011.xls");
- Workbook wb = WorkbookFactory.create(fis);
- fis.close();
-
- EmbeddedExtractor ee = new EmbeddedExtractor();
- List<EmbeddedData> edList = new ArrayList<>();
- for (Sheet s : wb) {
- edList.addAll(ee.extractAll(s));
- }
- wb.close();
-
- assertEquals(2, edList.size());
-
- String filename1 = "Sample.pdf";
- EmbeddedData ed0 = edList.get(0);
- assertEquals(filename1, ed0.getFilename());
- assertEquals(filename1, ed0.getShape().getShapeName().trim());
- assertEquals("uNplB1QpYug+LWappiTh0w==", md5hash(ed0.getEmbeddedData()));
-
- String filename2 = "kalastuslupa_jiyjhnj_yuiyuiyuio_uyte_sldfsdfsdf_sfsdfsdf_sfsssfsf_sdfsdfsdfsdf_sdfsdfsdf.pdf";
- EmbeddedData ed1 = edList.get(1);
- assertEquals(filename2, ed1.getFilename());
- assertEquals(filename2, ed1.getShape().getShapeName().trim());
- assertEquals("QjLuAZ+cd7KbhVz4sj+QdA==", md5hash(ed1.getEmbeddedData()));
- }
-
- @Test
- public void extractFromXSSF() throws IOException, EncryptedDocumentException, InvalidFormatException {
- InputStream fis = samples.openResourceAsStream("58325_db.xlsx");
- Workbook wb = WorkbookFactory.create(fis);
- fis.close();
-
- EmbeddedExtractor ee = new EmbeddedExtractor();
- List<EmbeddedData> edList = new ArrayList<>();
- for (Sheet s : wb) {
- edList.addAll(ee.extractAll(s));
- }
- wb.close();
-
- assertEquals(4, edList.size());
- EmbeddedData ed0 = edList.get(0);
- assertEquals("Object 1.pdf", ed0.getFilename());
- assertEquals("Object 1", ed0.getShape().getShapeName().trim());
- assertEquals("Oyys6UtQU1gbHYBYqA4NFA==", md5hash(ed0.getEmbeddedData()));
-
- EmbeddedData ed1 = edList.get(1);
- assertEquals("Object 2.pdf", ed1.getFilename());
- assertEquals("Object 2", ed1.getShape().getShapeName().trim());
- assertEquals("xLScPUS0XH+5CTZ2A3neNw==", md5hash(ed1.getEmbeddedData()));
-
- EmbeddedData ed2 = edList.get(2);
- assertEquals("Object 3.pdf", ed2.getFilename());
- assertEquals("Object 3", ed2.getShape().getShapeName().trim());
- assertEquals("rX4klZqJAeM5npb54Gi2+Q==", md5hash(ed2.getEmbeddedData()));
-
- EmbeddedData ed3 = edList.get(3);
- assertEquals("Microsoft_Excel_Worksheet1.xlsx", ed3.getFilename());
- assertEquals("Object 1", ed3.getShape().getShapeName().trim());
- assertEquals("4m4N8ji2tjpEGPQuw2YwGA==", md5hash(ed3.getEmbeddedData()));
- }
-
- public static String md5hash(byte[] input) {
- try {
- MessageDigest md = MessageDigest.getInstance("MD5");
- byte[] hash = md.digest(input);
- return Base64.getEncoder().encodeToString(hash);
- } catch (NoSuchAlgorithmException e) {
- // doesn't happen
- throw new RuntimeException(e);
- }
- }
-
-
- @Test
- public void testNPE() throws IOException {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("angelo.edu_content_files_19555-nsse-2011-multiyear-benchmark.xls");
- EmbeddedExtractor ee = new EmbeddedExtractor();
-
- for (Sheet s : wb) {
- for (EmbeddedData ed : ee.extractAll(s)) {
- assertNotNull(ed.getFilename());
- assertNotNull(ed.getEmbeddedData());
- assertNotNull(ed.getShape());
- }
- }
-
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.format;
-
-import static java.awt.Color.ORANGE;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.awt.Color;
-import java.io.IOException;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-
-import javax.swing.JLabel;
-
-import org.apache.poi.hssf.util.HSSFColor;
-import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.util.LocaleUtil;
-import org.apache.poi.xssf.XSSFITestDataProvider;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * Class for spreadsheet-based tests, such as are used for cell formatting.
- * This reads tests from the spreadsheet, as well as reading
- * flags that can be used to paramterize these tests.
- * <p>
- * Each test has four parts: The expected result (column A), the format string
- * (column B), the value to format (column C), and a comma-separated list of
- * categores that this test falls in. Normally all tests are run, but if the
- * flag "Categories" is not empty, only tests that have at least one category
- * listed in "Categories" are run.
- */
-public class TestCellFormatPart {
- private static final Pattern NUMBER_EXTRACT_FMT = Pattern.compile(
- "([-+]?[0-9]+)(\\.[0-9]+)?.*(?:(e).*?([+-]?[0-9]+))",
- Pattern.CASE_INSENSITIVE);
- private static final Color TEST_COLOR = ORANGE.darker();
- private static Locale userLocale;
-
-
-
- @BeforeClass
- public static void setLocale() {
- userLocale = LocaleUtil.getUserLocale();
- LocaleUtil.setUserLocale(Locale.UK);
- }
-
- @AfterClass
- public static void unsetLocale() {
- LocaleUtil.setUserLocale(userLocale);
- }
-
- private final ITestDataProvider _testDataProvider = XSSFITestDataProvider.instance;
-
- private interface CellValue {
- Object getValue(Cell cell);
-
- default void equivalent(String expected, String actual, CellFormatPart format) {
- assertEquals("format \"" + format + "\"", '"' + expected + '"',
- '"' + actual + '"');
- }
- }
-
- @Test
- public void testGeneralFormat() throws IOException {
- runFormatTests("GeneralFormatTests.xlsx", cell -> {
- assertNotNull(cell);
- switch (CellFormat.ultimateType(cell)) {
- case BOOLEAN:
- return cell.getBooleanCellValue();
- case NUMERIC:
- return cell.getNumericCellValue();
- default:
- return cell.getStringCellValue();
- }
- });
- }
-
- @Test
- public void testNumberFormat() throws IOException {
- runFormatTests("NumberFormatTests.xlsx", Cell::getNumericCellValue);
- }
-
- @Test
- public void testNumberApproxFormat() throws IOException {
- runFormatTests("NumberFormatApproxTests.xlsx", new CellValue() {
- @Override
- public Object getValue(Cell cell) {
- return cell.getNumericCellValue();
- }
-
- @Override
- public void equivalent(String expected, String actual,
- CellFormatPart format) {
- double expectedVal = extractNumber(expected);
- double actualVal = extractNumber(actual);
- // equal within 1%
- double delta = expectedVal / 100;
- assertEquals("format \"" + format + "\"," + expected + " ~= " +
- actual, expectedVal, actualVal, delta);
- }
- });
- }
-
- @Test
- public void testDateFormat() throws IOException {
- TimeZone tz = LocaleUtil.getUserTimeZone();
- LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
- try {
- runFormatTests("DateFormatTests.xlsx", Cell::getDateCellValue);
- } finally {
- LocaleUtil.setUserTimeZone(tz);
- }
- }
-
- @Test
- public void testElapsedFormat() throws IOException {
- runFormatTests("ElapsedFormatTests.xlsx", Cell::getNumericCellValue);
- }
-
- @Test
- public void testTextFormat() throws IOException {
- runFormatTests("TextFormatTests.xlsx", cell ->
- (CellFormat.ultimateType(cell) == CellType.BOOLEAN) ? cell.getBooleanCellValue() : cell.getStringCellValue()
- );
- }
-
- @Test
- public void testConditions() throws IOException {
- runFormatTests("FormatConditionTests.xlsx", Cell::getNumericCellValue);
- }
-
- @Test
- public void testNamedColors() {
- assertTrue(CellFormatPart.NAMED_COLORS.size() >= HSSFColor.HSSFColorPredefined.values().length);
- Stream.of("GREEN","Green","RED","Red","BLUE","Blue","YELLOW","Yellow")
- .map(CellFormatPart.NAMED_COLORS::get)
- .forEach(Assert::assertNotNull);
- }
-
- private double extractNumber(String str) {
- Matcher m = NUMBER_EXTRACT_FMT.matcher(str);
- if (!m.find()) {
- throw new IllegalArgumentException("Cannot find number in \"" + str + "\"");
- }
-
- StringBuilder sb = new StringBuilder();
- // The groups in the pattern are the parts of the number
- for (int i = 1; i <= m.groupCount(); i++) {
- String part = m.group(i);
- if (part != null)
- sb.append(part);
- }
- return Double.parseDouble(sb.toString());
- }
-
-
- protected void runFormatTests(String workbookName, CellValue valueGetter) throws IOException {
- try (Workbook workbook = _testDataProvider.openSampleWorkbook(workbookName)) {
- workbook.setMissingCellPolicy(Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
-
- Sheet sheet = workbook.getSheet("Tests");
- boolean isHeader = true;
- for (Row row : sheet) {
- // Skip the header row
- if (isHeader || row == null) {
- isHeader = false;
- continue;
- }
- String expectedText = row.getCell(0).getStringCellValue();
- String format = row.getCell(1).getStringCellValue();
- Cell value = row.getCell(2);
-
- if (expectedText.isEmpty() && format.isEmpty()) {
- continue;
- }
-
- Object objVal = valueGetter.getValue(value);
- JLabel label = new JLabel();
- label.setForeground(TEST_COLOR);
- label.setText("xyzzy");
-
- Color origColor = label.getForeground();
- CellFormatPart cellFormatPart = new CellFormatPart(format);
- // If this doesn't apply, no color change is expected
- Color expectedColor = cellFormatPart.apply(label, objVal).applies ? TEST_COLOR : origColor;
-
- String actualText = label.getText();
- Color actualColor = label.getForeground();
- valueGetter.equivalent(expectedText, actualText, cellFormatPart);
- assertEquals("no color", expectedColor, actualColor);
- }
- }
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.formula;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.formula.ptg.AbstractFunctionPtg;
-import org.apache.poi.ss.formula.ptg.NameXPxg;
-import org.apache.poi.ss.formula.ptg.Ptg;
-import org.apache.poi.ss.formula.ptg.Ref3DPxg;
-import org.apache.poi.ss.formula.ptg.StringPtg;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.Test;
-
-/**
- * Test {@link FormulaParser}'s handling of row numbers at the edge of the
- * HSSF/XSSF ranges.
- *
- * @author David North
- */
-public class TestFormulaParser {
-
- @Test
- public void testHSSFFailsForOver65536() {
- FormulaParsingWorkbook workbook = HSSFEvaluationWorkbook.create(new HSSFWorkbook());
- try {
- FormulaParser.parse("Sheet1!1:65537", workbook, FormulaType.CELL, 0);
- fail("Expected exception");
- }
- catch (FormulaParseException expected) {
- // expected here
- }
- }
-
- private static void checkHSSFFormula(String formula) {
- HSSFWorkbook wb = new HSSFWorkbook();
- FormulaParsingWorkbook workbook = HSSFEvaluationWorkbook.create(wb);
- FormulaParser.parse(formula, workbook, FormulaType.CELL, 0);
- IOUtils.closeQuietly(wb);
- }
- private static void checkXSSFFormula(String formula) {
- XSSFWorkbook wb = new XSSFWorkbook();
- FormulaParsingWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
- FormulaParser.parse(formula, workbook, FormulaType.CELL, 0);
- IOUtils.closeQuietly(wb);
- }
- private static void checkFormula(String formula) {
- checkHSSFFormula(formula);
- checkXSSFFormula(formula);
- }
-
- @Test
- public void testHSSFPassCase() {
- checkHSSFFormula("Sheet1!1:65536");
- }
-
- @Test
- public void testXSSFWorksForOver65536() {
- checkXSSFFormula("Sheet1!1:65537");
- }
-
- @Test
- public void testXSSFFailCase() {
- FormulaParsingWorkbook workbook = XSSFEvaluationWorkbook.create(new XSSFWorkbook());
- try {
- FormulaParser.parse("Sheet1!1:1048577", workbook, FormulaType.CELL, 0); // one more than max rows.
- fail("Expected exception");
- }
- catch (FormulaParseException expected) {
- // expected here
- }
- }
-
- // copied from org.apache.poi.hssf.model.TestFormulaParser
- @Test
- public void testMacroFunction() throws Exception {
- // testNames.xlsm contains a VB function called 'myFunc'
- final String testFile = "testNames.xlsm";
- try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(testFile)) {
- XSSFEvaluationWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
-
- //Expected ptg stack: [NamePtg(myFunc), StringPtg(arg), (additional operands would go here...), FunctionPtg(myFunc)]
- Ptg[] ptg = FormulaParser.parse("myFunc(\"arg\")", workbook, FormulaType.CELL, -1);
- assertEquals(3, ptg.length);
-
- // the name gets encoded as the first operand on the stack
- NameXPxg tname = (NameXPxg) ptg[0];
- assertEquals("myFunc", tname.toFormulaString());
-
- // the function's arguments are pushed onto the stack from left-to-right as OperandPtgs
- StringPtg arg = (StringPtg) ptg[1];
- assertEquals("arg", arg.getValue());
-
- // The external FunctionPtg is the last Ptg added to the stack
- // During formula evaluation, this Ptg pops off the the appropriate number of
- // arguments (getNumberOfOperands()) and pushes the result on the stack
- AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[2];
- assertTrue(tfunc.isExternalFunction());
-
- // confirm formula parsing is case-insensitive
- FormulaParser.parse("mYfUnC(\"arg\")", workbook, FormulaType.CELL, -1);
-
- // confirm formula parsing doesn't care about argument count or type
- // this should only throw an error when evaluating the formula.
- FormulaParser.parse("myFunc()", workbook, FormulaType.CELL, -1);
- FormulaParser.parse("myFunc(\"arg\", 0, TRUE)", workbook, FormulaType.CELL, -1);
-
- // A completely unknown formula name (not saved in workbook) should still be parseable and renderable
- // but will throw an NotImplementedFunctionException or return a #NAME? error value if evaluated.
- FormulaParser.parse("yourFunc(\"arg\")", workbook, FormulaType.CELL, -1);
-
- // Make sure workbook can be written and read
- XSSFTestDataSamples.writeOutAndReadBack(wb).close();
-
- // Manually check to make sure file isn't corrupted
- // TODO: develop a process for occasionally manually reviewing workbooks
- // to verify workbooks are not corrupted
- /*
- final File fileIn = XSSFTestDataSamples.getSampleFile(testFile);
- final File reSavedFile = new File(fileIn.getParentFile(), fileIn.getName().replace(".xlsm", "-saved.xlsm"));
- final FileOutputStream fos = new FileOutputStream(reSavedFile);
- wb.write(fos);
- fos.close();
- */
- }
- }
-
- @Test
- public void testParserErrors() throws Exception {
- try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("testNames.xlsm")) {
- XSSFEvaluationWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
-
- parseExpectedException("(");
- parseExpectedException(")");
- parseExpectedException("+");
- parseExpectedException("42+");
- parseExpectedException("IF()");
- parseExpectedException("IF("); //no closing paren
- parseExpectedException("myFunc(", workbook); //no closing paren
- }
- }
-
- private static void parseExpectedException(String formula) {
- parseExpectedException(formula, null);
- }
-
- /** confirm formula has invalid syntax and parsing the formula results in FormulaParseException
- */
- private static void parseExpectedException(String formula, FormulaParsingWorkbook wb) {
- try {
- FormulaParser.parse(formula, wb, FormulaType.CELL, -1);
- fail("Expected FormulaParseException: " + formula);
- } catch (final FormulaParseException e) {
- // expected during successful test
- assertNotNull(e.getMessage());
- }
- }
-
- // trivial case for bug 60219: FormulaParser can't parse external references when sheet name is quoted
- @Test
- public void testParseExternalReferencesWithUnquotedSheetName() throws Exception {
- XSSFWorkbook wb = new XSSFWorkbook();
- XSSFEvaluationWorkbook fpwb = XSSFEvaluationWorkbook.create(wb);
- Ptg[] ptgs = FormulaParser.parse("[1]Sheet1!A1", fpwb, FormulaType.CELL, -1);
- // org.apache.poi.ss.formula.ptg.Ref3DPxg [ [workbook=1] sheet=Sheet 1 ! A1]
- assertEquals("Ptgs length", 1, ptgs.length);
- assertTrue("Ptg class", ptgs[0] instanceof Ref3DPxg);
- Ref3DPxg pxg = (Ref3DPxg) ptgs[0];
- assertEquals("External workbook number", 1, pxg.getExternalWorkbookNumber());
- assertEquals("Sheet name", "Sheet1", pxg.getSheetName());
- assertEquals("Row", 0, pxg.getRow());
- assertEquals("Column", 0, pxg.getColumn());
- wb.close();
- }
-
- // bug 60219: FormulaParser can't parse external references when sheet name is quoted
- @Test
- public void testParseExternalReferencesWithQuotedSheetName() throws Exception {
- XSSFWorkbook wb = new XSSFWorkbook();
- XSSFEvaluationWorkbook fpwb = XSSFEvaluationWorkbook.create(wb);
- Ptg[] ptgs = FormulaParser.parse("'[1]Sheet 1'!A1", fpwb, FormulaType.CELL, -1);
- // org.apache.poi.ss.formula.ptg.Ref3DPxg [ [workbook=1] sheet=Sheet 1 ! A1]
- assertEquals("Ptgs length", 1, ptgs.length);
- assertTrue("Ptg class", ptgs[0] instanceof Ref3DPxg);
- Ref3DPxg pxg = (Ref3DPxg) ptgs[0];
- assertEquals("External workbook number", 1, pxg.getExternalWorkbookNumber());
- assertEquals("Sheet name", "Sheet 1", pxg.getSheetName());
- assertEquals("Row", 0, pxg.getRow());
- assertEquals("Column", 0, pxg.getColumn());
- wb.close();
- }
-
- // bug 60260
- @Test
- public void testUnicodeSheetName() {
- checkFormula("'Sheet\u30FB1'!A1:A6");
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.formula;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import org.apache.poi.ss.SpreadsheetVersion;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Table;
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFTable;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.Test;
-
-/**
- * Tests Excel Table expressions (structured references)
- * @see <a href="https://support.office.com/en-us/article/Using-structured-references-with-Excel-tables-F5ED2452-2337-4F71-BED3-C8AE6D2B276E">
- * Excel Structured Reference Syntax
- * </a>
- */
-public class TestStructuredReferences {
-
- /**
- * Test the regular expression used in INDIRECT() evaluation to recognize structured references
- */
- @Test
- public void testTableExpressionSyntax() {
- assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("abc[col1]").matches());
- assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("_abc[col1]").matches());
- assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("_[col1]").matches());
- assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("\\[col1]").matches());
- assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("\\[col1]").matches());
- assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("\\[#This Row]").matches());
- assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("\\[ [col1], [col2] ]").matches());
-
- // can't have a space between the table name and open bracket
- assertFalse("Invalid structured reference syntax didn't fail expression", Table.isStructuredReference.matcher("\\abc [ [col1], [col2] ]").matches());
- }
-
- @Test
- public void testTableFormulas() throws Exception {
- try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("StructuredReferences.xlsx")) {
-
- final FormulaEvaluator eval = new XSSFFormulaEvaluator(wb);
- final XSSFSheet tableSheet = wb.getSheet("Table");
- final XSSFSheet formulaSheet = wb.getSheet("Formulas");
-
- confirm(eval, tableSheet.getRow(5).getCell(0), 49);
- confirm(eval, formulaSheet.getRow(0).getCell(0), 209);
- confirm(eval, formulaSheet.getRow(1).getCell(0), "one");
-
- // test changing a table value, to see if the caches are properly cleared
- // Issue 59814
-
- // this test passes before the fix for 59814
- tableSheet.getRow(1).getCell(1).setCellValue("ONEA");
- confirm(eval, formulaSheet.getRow(1).getCell(0), "ONEA");
-
- // test adding a row to a table, issue 59814
- Row newRow = tableSheet.getRow(7);
- if (newRow == null) newRow = tableSheet.createRow(7);
- newRow.createCell(0, CellType.FORMULA).setCellFormula("\\_Prime.1[[#This Row],[@Number]]*\\_Prime.1[[#This Row],[@Number]]");
- newRow.createCell(1, CellType.STRING).setCellValue("thirteen");
- newRow.createCell(2, CellType.NUMERIC).setCellValue(13);
-
- // update Table
- final XSSFTable table = wb.getTable("\\_Prime.1");
- final AreaReference newArea = wb.getCreationHelper().createAreaReference(
- table.getStartCellReference(),
- new CellReference(table.getEndRowIndex() + 1, table.getEndColIndex()));
- String newAreaStr = newArea.formatAsString();
- table.getCTTable().setRef(newAreaStr);
- table.getCTTable().getAutoFilter().setRef(newAreaStr);
- table.updateHeaders();
- table.updateReferences();
-
- // these fail before the fix for 59814
- confirm(eval, tableSheet.getRow(7).getCell(0), 13 * 13);
- confirm(eval, formulaSheet.getRow(0).getCell(0), 209 + 13 * 13);
-
- }
- }
-
- private static void confirm(FormulaEvaluator fe, Cell cell, double expectedResult) {
- fe.clearAllCachedResultValues();
- CellValue cv = fe.evaluate(cell);
- if (cv.getCellType() != CellType.NUMERIC) {
- fail("expected numeric cell type but got " + cv.formatAsString());
- }
- assertEquals(expectedResult, cv.getNumberValue(), 0.0);
- }
-
- private static void confirm(FormulaEvaluator fe, Cell cell, String expectedResult) {
- fe.clearAllCachedResultValues();
- CellValue cv = fe.evaluate(cell);
- if (cv.getCellType() != CellType.STRING) {
- fail("expected String cell type but got " + cv.formatAsString());
- }
- assertEquals(expectedResult, cv.getStringValue());
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.formula.eval;
-
-import org.apache.poi.xssf.XSSFITestDataProvider;
-
-/**
- * Tests XSSFFormulaEvaluator for its handling of cell formula circular references.
- *
- * @author Josh Micich
- */
-public final class TestXSSFCircularReferences extends BaseTestCircularReferences {
- public TestXSSFCircularReferences() {
- super(XSSFITestDataProvider.instance);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.formula.functions;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.SheetUtil;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Test the COUNTIFS() function
- */
-public class CountifsTests {
-
- private Workbook workbook;
-
- /**
- * initialize a workbook
- */
- @Before
- public void before() {
- // not sure why we allow this, COUNTIFS() is only available
- // in OOXML, it was introduced with Office 2007
- workbook = new HSSFWorkbook();
- }
-
- /**
- * Close the workbook if needed
- */
- @After
- public void after() {
- IOUtils.closeQuietly(workbook);
- }
-
- /**
- * Basic call
- */
- @Test
- public void testCallFunction() {
- Sheet sheet = workbook.createSheet("test");
- Row row1 = sheet.createRow(0);
- Cell cellA1 = row1.createCell(0, CellType.FORMULA);
- Cell cellB1 = row1.createCell(1, CellType.NUMERIC);
- Cell cellC1 = row1.createCell(2, CellType.NUMERIC);
- Cell cellD1 = row1.createCell(3, CellType.NUMERIC);
- Cell cellE1 = row1.createCell(4, CellType.NUMERIC);
- cellB1.setCellValue(1);
- cellC1.setCellValue(1);
- cellD1.setCellValue(2);
- cellE1.setCellValue(4);
-
- cellA1.setCellFormula("COUNTIFS(B1:C1,1, D1:E1,2)");
- FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
- CellValue evaluate = evaluator.evaluate(cellA1);
- assertEquals(1.0d, evaluate.getNumberValue(), 0.000000000000001);
- }
-
- /**
- * Test argument count check
- */
- @Test
- public void testCallFunction_invalidArgs() {
- Sheet sheet = workbook.createSheet("test");
- Row row1 = sheet.createRow(0);
- Cell cellA1 = row1.createCell(0, CellType.FORMULA);
- cellA1.setCellFormula("COUNTIFS()");
- FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
- CellValue evaluate = evaluator.evaluate(cellA1);
- assertEquals(15, evaluate.getErrorValue());
- cellA1.setCellFormula("COUNTIFS(A1:C1)");
- evaluator = workbook.getCreationHelper().createFormulaEvaluator();
- evaluate = evaluator.evaluate(cellA1);
- assertEquals(15, evaluate.getErrorValue());
- cellA1.setCellFormula("COUNTIFS(A1:C1,2,2)");
- evaluator = workbook.getCreationHelper().createFormulaEvaluator();
- evaluate = evaluator.evaluate(cellA1);
- assertEquals(15, evaluate.getErrorValue());
- }
-
- /**
- * the bug returned the wrong count, this verifies the fix
- * @throws Exception if the file can't be read
- */
- @Test
- public void testBug56822() throws Exception {
- workbook = XSSFTestDataSamples.openSampleWorkbook("56822-Countifs.xlsx");
- FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
- Cell cell = SheetUtil.getCell(workbook.getSheetAt(0), 0, 3);
- assertNotNull("Test workbook missing cell D1", cell);
- CellValue evaluate = evaluator.evaluate(cell);
- assertEquals(2.0d, evaluate.getNumberValue(), 0.00000000000001);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.formula.functions;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.formula.eval.StringEval;
-import org.apache.poi.ss.formula.eval.ValueEval;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.Test;
-
-public final class TestProper {
- private Cell cell11;
- private FormulaEvaluator evaluator;
-
- @Test
- public void testValidHSSF() {
- HSSFWorkbook wb = new HSSFWorkbook();
- evaluator = new HSSFFormulaEvaluator(wb);
-
- confirm(wb);
- }
-
- @Test
- public void testValidXSSF() {
- XSSFWorkbook wb = new XSSFWorkbook();
- evaluator = new XSSFFormulaEvaluator(wb);
-
- confirm(wb);
- }
-
- private void confirm(Workbook wb) {
- Sheet sheet = wb.createSheet("new sheet");
- cell11 = sheet.createRow(0).createCell(0);
-
- confirm("PROPER(\"hi there\")", "Hi There"); //simple case
- confirm("PROPER(\"what's up\")", "What'S Up"); //apostrophes are treated as word breaks
- confirm("PROPER(\"I DON'T TH!NK SO!\")", "I Don'T Th!Nk So!"); //capitalization is ignored, special punctuation is treated as a word break
- confirm("PROPER(\"dr\u00dcb\u00f6'\u00e4 \u00e9lo\u015f|\u00eb\u00e8 \")", "Dr\u00fcb\u00f6'\u00c4 \u00c9lo\u015f|\u00cb\u00e8 ");
- confirm("PROPER(\"hi123 the123re\")", "Hi123 The123Re"); //numbers are treated as word breaks
- confirm("PROPER(\"-\")", "-"); //nothing happens with ascii punctuation that is not upper or lower case
- confirm("PROPER(\"!\u00a7$\")", "!\u00a7$"); //nothing happens with unicode punctuation (section sign) that is not upper or lower case
- confirm("PROPER(\"/&%\")", "/&%"); //nothing happens with ascii punctuation that is not upper or lower case
- confirm("PROPER(\"Apache POI\")", "Apache Poi"); //acronyms are not special
- confirm("PROPER(\" hello world\")", " Hello World"); //leading whitespace is ignored
-
- final String scharfes = "\u00df"; //German lowercase eszett, scharfes s, sharp s
- confirm("PROPER(\"stra"+scharfes+"e\")", "Stra"+scharfes+"e");
- assertTrue(Character.isLetter(scharfes.charAt(0)));
-
- // CURRENTLY FAILS: result: "SSUnd"+scharfes
- // LibreOffice 5.0.3.2 behavior: "Sund"+scharfes
- // Excel 2013 behavior: ???
- confirm("PROPER(\""+scharfes+"und"+scharfes+"\")", "SSund"+scharfes);
-
- // also test longer string
- StringBuilder builder = new StringBuilder("A");
- StringBuilder expected = new StringBuilder("A");
- for(int i = 1;i < 254;i++) {
- builder.append((char)(65 + (i % 26)));
- expected.append((char)(97 + (i % 26)));
- }
- confirm("PROPER(\"" + builder + "\")", expected.toString());
- }
-
- private void confirm(String formulaText, String expectedResult) {
- cell11.setCellFormula(formulaText);
- evaluator.clearAllCachedResultValues();
- CellValue cv = evaluator.evaluate(cell11);
- assertEquals("Wrong result type", CellType.STRING, cv.getCellType());
- String actualValue = cv.getStringValue();
- assertEquals(expectedResult, actualValue);
- }
-
- @Test
- public void test() {
- checkProper("", "");
- checkProper("a", "A");
- checkProper("abc", "Abc");
- checkProper("abc abc", "Abc Abc");
- checkProper("abc/abc", "Abc/Abc");
- checkProper("ABC/ABC", "Abc/Abc");
- checkProper("aBc/ABC", "Abc/Abc");
- checkProper("aBc@#$%^&*()_+=-ABC", "Abc@#$%^&*()_+=-Abc");
- checkProper("aBc25aerg/ABC", "Abc25Aerg/Abc");
- checkProper("aBc/\u00C4\u00F6\u00DF\u00FC/ABC", "Abc/\u00C4\u00F6\u00DF\u00FC/Abc"); // Some German umlauts with uppercase first letter is not changed
- checkProper("\u00FC", "\u00DC");
- checkProper("\u00DC", "\u00DC");
- checkProper("\u00DF", "SS"); // German "scharfes s" is uppercased to "SS"
- checkProper("\u00DFomesing", "SSomesing"); // German "scharfes s" is uppercased to "SS"
- checkProper("aBc/\u00FC\u00C4\u00F6\u00DF\u00FC/ABC", "Abc/\u00DC\u00E4\u00F6\u00DF\u00FC/Abc"); // Some German umlauts with lowercase first letter is changed to uppercase
- }
-
- @Test
- public void testMicroBenchmark() {
- ValueEval strArg = new StringEval("some longer text that needs a number of replacements to check for runtime of different implementations");
- long start = System.currentTimeMillis();
- for(int i = 0;i < 300000;i++) {
- final ValueEval ret = TextFunction.PROPER.evaluate(new ValueEval[]{strArg}, 0, 0);
- assertEquals("Some Longer Text That Needs A Number Of Replacements To Check For Runtime Of Different Implementations", ((StringEval)ret).getStringValue());
- }
- // Took approx. 600ms on a decent Laptop in July 2016
- //System.out.println("Took: " + (System.currentTimeMillis() - start) + "ms");
- }
-
- private void checkProper(String input, String expected) {
- ValueEval strArg = new StringEval(input);
- final ValueEval ret = TextFunction.PROPER.evaluate(new ValueEval[]{strArg}, 0, 0);
- assertEquals(expected, ((StringEval)ret).getStringValue());
- }
-}
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.formula.functions;
-
-import static org.junit.Assert.assertEquals;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.junit.Test;
-
-import java.io.IOException;
-
-/**
- *
- */
-public class TestSumifsXSSF {
-
- /**
- * handle null cell predicate
- */
- @Test
- public void testBug60858() throws IOException {
- try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("bug60858.xlsx")) {
- FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator();
-
- Sheet sheet = wb.getSheetAt(0);
- Cell cell = sheet.getRow(1).getCell(5);
- fe.evaluate(cell);
- assertEquals(0.0, cell.getNumericCellValue(), 0.0000000000000001);
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.formula.functions;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.Test;
-
-import java.io.IOException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-/**
- * Test the VLOOKUP function
- */
-public class TestVlookup {
-
- @Test
- public void testFullColumnAreaRef61841() throws IOException {
- try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("VLookupFullColumn.xlsx")) {
- FormulaEvaluator feval = wb.getCreationHelper().createFormulaEvaluator();
- feval.evaluateAll();
- assertEquals("Wrong lookup value", "Value1",
- feval.evaluate(wb.getSheetAt(0).getRow(3).getCell(1)).getStringValue());
- assertEquals("Lookup should return #N/A",
- CellType.ERROR, feval.evaluate(wb.getSheetAt(0).getRow(4).getCell(1)).getCellType());
- }
- }
-
- @Test
- public void bug62275_true() throws IOException {
- try (Workbook wb = new XSSFWorkbook()) {
- Sheet sheet = wb.createSheet();
- Row row = sheet.createRow(0);
-
- Cell cell = row.createCell(0);
- cell.setCellFormula("vlookup(A2,B1:B5,2,true)");
-
- CreationHelper createHelper = wb.getCreationHelper();
- FormulaEvaluator eval = createHelper.createFormulaEvaluator();
- CellValue value = eval.evaluate(cell);
-
- assertFalse(value.getBooleanValue());
- }
- }
-
- @Test
- public void bug62275_false() throws IOException {
- try (Workbook wb = new XSSFWorkbook()) {
- Sheet sheet = wb.createSheet();
- Row row = sheet.createRow(0);
-
- Cell cell = row.createCell(0);
- cell.setCellFormula("vlookup(A2,B1:B5,2,false)");
-
- CreationHelper crateHelper = wb.getCreationHelper();
- FormulaEvaluator eval = crateHelper.createFormulaEvaluator();
- CellValue value = eval.evaluate(cell);
-
- assertFalse(value.getBooleanValue());
- }
- }
-
- @Test
- public void bug62275_empty_3args() throws IOException {
- try (Workbook wb = new XSSFWorkbook()) {
- Sheet sheet = wb.createSheet();
- Row row = sheet.createRow(0);
-
- Cell cell = row.createCell(0);
- cell.setCellFormula("vlookup(A2,B1:B5,2,)");
-
- CreationHelper crateHelper = wb.getCreationHelper();
- FormulaEvaluator eval = crateHelper.createFormulaEvaluator();
- CellValue value = eval.evaluate(cell);
-
- assertFalse(value.getBooleanValue());
- }
- }
-
- @Test
- public void bug62275_empty_2args() throws IOException {
- try (Workbook wb = new XSSFWorkbook()) {
- Sheet sheet = wb.createSheet();
- Row row = sheet.createRow(0);
-
- Cell cell = row.createCell(0);
- cell.setCellFormula("vlookup(A2,B1:B5,,)");
-
- CreationHelper crateHelper = wb.getCreationHelper();
- FormulaEvaluator eval = crateHelper.createFormulaEvaluator();
- CellValue value = eval.evaluate(cell);
-
- assertFalse(value.getBooleanValue());
- }
- }
-
- @Test
- public void bug62275_empty_1arg() throws IOException {
- try (Workbook wb = new XSSFWorkbook()) {
- Sheet sheet = wb.createSheet();
- Row row = sheet.createRow(0);
-
- Cell cell = row.createCell(0);
- cell.setCellFormula("vlookup(A2,,,)");
-
- CreationHelper crateHelper = wb.getCreationHelper();
- FormulaEvaluator eval = crateHelper.createFormulaEvaluator();
- CellValue value = eval.evaluate(cell);
-
- assertFalse(value.getBooleanValue());
- }
- }
-}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.poi.EmptyFileException;
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackageAccess;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.SuppressForbidden;
+import org.apache.poi.util.TempFile;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
+import org.junit.Test;
+
+public final class TestWorkbookFactory {
+ private static final String xls = "SampleSS.xls";
+ private static final String xlsx = "SampleSS.xlsx";
+ private static final String[] xls_protected = new String[] {"password.xls", "password"};
+ private static final String[] xlsx_protected = new String[]{"protected_passtika.xlsx", "tika"};
+ private static final String txt = "SampleSS.txt";
+
+ private static final POILogger LOGGER = POILogFactory.getLogger(TestWorkbookFactory.class);
+
+ /**
+ * Closes the sample workbook read in from filename.
+ * Throws an exception if closing the workbook results in the file on disk getting modified.
+ *
+ * @param filename the sample workbook to read in
+ * @param wb the workbook to close
+ */
+ private static void assertCloseDoesNotModifyFile(String filename, Workbook wb) throws IOException {
+ final byte[] before = HSSFTestDataSamples.getTestDataFileContent(filename);
+ // FIXME: replace with wb.close() when bug 58779 is resolved
+ closeOrRevert(wb);
+ final byte[] after = HSSFTestDataSamples.getTestDataFileContent(filename);
+ assertArrayEquals(filename + " sample file was modified as a result of closing the workbook",
+ before, after);
+ }
+
+ /**
+ * bug 58779: Closing an XSSFWorkbook that was created with WorkbookFactory modifies the file
+ * FIXME: replace this method with wb.close() when bug 58779 is resolved.
+ *
+ * @param wb the workbook to close or revert
+ */
+ private static void closeOrRevert(Workbook wb) throws IOException {
+ if (wb instanceof HSSFWorkbook) {
+ wb.close();
+ }
+ else if (wb instanceof XSSFWorkbook) {
+ final XSSFWorkbook xwb = (XSSFWorkbook) wb;
+ if (PackageAccess.READ == xwb.getPackage().getPackageAccess()) {
+ xwb.close();
+ }
+ else {
+ // TODO: close() re-writes the sample-file?! Resort to revert() for now to close file handle...
+ LOGGER.log(POILogger.WARN,
+ "reverting XSSFWorkbook rather than closing it to avoid close() modifying the file on disk. " +
+ "Refer to bug 58779.");
+ xwb.getPackage().revert();
+ }
+ } else {
+ throw new RuntimeException("Unsupported workbook type");
+ }
+ }
+
+ @Test
+ public void testCreateNative() throws Exception {
+ Workbook wb;
+
+ // POIFS -> hssf
+ wb = WorkbookFactory.create(
+ new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls))
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ wb = WorkbookFactory.create(
+ new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls)).getRoot()
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ // Package -> xssf
+ wb = XSSFWorkbookFactory.createWorkbook(
+ OPCPackage.open(
+ HSSFTestDataSamples.openSampleFileStream(xlsx))
+ );
+ assertNotNull(wb);
+ //noinspection ConstantConditions
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx, wb);
+ }
+
+ @Test
+ public void testCreateReadOnly() throws Exception {
+ Workbook wb;
+
+ // POIFS -> hssf
+ wb = WorkbookFactory.create(HSSFTestDataSamples.getSampleFile(xls), null, true);
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ // Package -> xssf
+ wb = WorkbookFactory.create(HSSFTestDataSamples.getSampleFile(xlsx), null, true);
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx, wb);
+ }
+
+ /**
+ * Creates the appropriate kind of Workbook, but
+ * checking the mime magic at the start of the
+ * InputStream, then creating what's required.
+ */
+ @Test
+ public void testCreateGeneric() throws Exception {
+ Workbook wb;
+
+ // InputStream -> either
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xls)
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xlsx)
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx, wb);
+
+ // File -> either
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xls)
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xlsx)
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx, wb);
+
+ // Invalid type -> exception
+ final byte[] before = HSSFTestDataSamples.getTestDataFileContent(txt);
+ try {
+ try (InputStream stream = HSSFTestDataSamples.openSampleFileStream(txt)) {
+ wb = WorkbookFactory.create(stream);
+ assertNotNull(wb);
+ }
+ fail();
+ } catch(IOException e) {
+ // Good
+ }
+ final byte[] after = HSSFTestDataSamples.getTestDataFileContent(txt);
+ assertArrayEquals("Invalid type file was modified after trying to open the file as a spreadsheet",
+ before, after);
+ }
+
+ /**
+ * Check that the overloaded stream methods which take passwords work properly
+ */
+ @Test
+ public void testCreateWithPasswordFromStream() throws Exception {
+ Workbook wb;
+
+ // Unprotected, no password given, opens normally
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xls), null
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xlsx), null
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx, wb);
+
+
+ // Unprotected, wrong password, opens normally
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xls), "wrong"
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xlsx), "wrong"
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx, wb);
+
+
+ // Protected, correct password, opens fine
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xls_protected[0]), xls_protected[1]
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls_protected[0], wb);
+
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xlsx_protected[0]), xlsx_protected[1]
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
+
+
+ // Protected, wrong password, throws Exception
+ try {
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xls_protected[0]), "wrong"
+ );
+ assertCloseDoesNotModifyFile(xls_protected[0], wb);
+ fail("Shouldn't be able to open with the wrong password");
+ } catch (EncryptedDocumentException e) {
+ // expected here
+ }
+
+ try {
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.openSampleFileStream(xlsx_protected[0]), "wrong"
+ );
+ assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
+ fail("Shouldn't be able to open with the wrong password");
+ } catch (EncryptedDocumentException e) {
+ // expected here
+ }
+ }
+
+ /**
+ * Check that the overloaded file methods which take passwords work properly
+ */
+ @Test
+ public void testCreateWithPasswordFromFile() throws Exception {
+ Workbook wb;
+
+ // Unprotected, no password given, opens normally
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xls), null
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xlsx), null
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx, wb);
+
+ // Unprotected, wrong password, opens normally
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xls), "wrong"
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xlsx), "wrong"
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertCloseDoesNotModifyFile(xlsx, wb);
+
+ // Protected, correct password, opens fine
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xls_protected[0]), xls_protected[1]
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls_protected[0], wb);
+
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xlsx_protected[0]), xlsx_protected[1]
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ assertTrue(wb.getNumberOfSheets() > 0);
+ assertNotNull(wb.getSheetAt(0));
+ assertNotNull(wb.getSheetAt(0).getRow(0));
+ assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
+
+ // Protected, wrong password, throws Exception
+ try {
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xls_protected[0]), "wrong"
+ );
+ assertCloseDoesNotModifyFile(xls_protected[0], wb);
+ fail("Shouldn't be able to open with the wrong password");
+ } catch (EncryptedDocumentException e) {
+ // expected here
+ }
+
+ try {
+ wb = WorkbookFactory.create(
+ HSSFTestDataSamples.getSampleFile(xlsx_protected[0]), "wrong"
+ );
+ assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
+ fail("Shouldn't be able to open with the wrong password");
+ } catch (EncryptedDocumentException e) {
+ // expected here
+ }
+ }
+
+ /**
+ * Check that a helpful exception is given on an empty input stream
+ */
+ @Test(expected = EmptyFileException.class)
+ public void testEmptyInputStream() throws Exception {
+ InputStream emptyStream = new ByteArrayInputStream(new byte[0]);
+ WorkbookFactory.create(emptyStream);
+ }
+
+ /**
+ * Check that a helpful exception is given on an empty file
+ */
+ @Test(expected = EmptyFileException.class)
+ public void testEmptyFile() throws Exception {
+ File emptyFile = TempFile.createTempFile("empty", ".poi");
+ try {
+ WorkbookFactory.create(emptyFile);
+ fail("Shouldn't be able to create for an empty file");
+ } finally {
+ assertTrue(emptyFile.delete());
+ }
+ }
+
+ /**
+ * Check that a helpful exception is raised on a non-existing file
+ */
+ @Test(expected = FileNotFoundException.class)
+ public void testNonExistingFile() throws Exception {
+ File nonExistingFile = new File("notExistingFile");
+ assertFalse(nonExistingFile.exists());
+ WorkbookFactory.create(nonExistingFile, "password", true);
+ }
+
+ /**
+ * See Bugzilla bug #62831 - #WorkbookFactory.create(File) needs
+ * to work for sub-classes of File too, eg JFileChooser
+ */
+ @Test
+ public void testFileSubclass() throws Exception {
+ File normalXLS = HSSFTestDataSamples.getSampleFile(xls);
+ File normalXLSX = HSSFTestDataSamples.getSampleFile(xlsx);
+ File altXLS = new TestFile(normalXLS.getAbsolutePath());
+ File altXLSX = new TestFile(normalXLSX.getAbsolutePath());
+ assertTrue(altXLS.exists());
+ assertTrue(altXLSX.exists());
+
+ try (Workbook wb = WorkbookFactory.create(altXLS)) {
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ closeOrRevert(wb);
+ }
+
+ try (Workbook wb = WorkbookFactory.create(altXLSX)) {
+ assertNotNull(wb);
+ assertTrue(wb instanceof XSSFWorkbook);
+ closeOrRevert(wb);
+ }
+ }
+
+ private static class TestFile extends File {
+ public TestFile(String file) {
+ super(file);
+ }
+ }
+
+ /**
+ * Check that the overloaded file methods which take passwords work properly
+ */
+ @Test
+ public void testCreateEmpty() throws Exception {
+ Workbook wb = WorkbookFactory.create(false);
+ assertTrue(wb instanceof HSSFWorkbook);
+ closeOrRevert(wb);
+
+ wb = WorkbookFactory.create(true);
+ assertTrue(wb instanceof XSSFWorkbook);
+ closeOrRevert(wb);
+ }
+
+ @Test
+ @SuppressForbidden("test code")
+ public void testOpenManyHSSF() throws Exception {
+ final int size = 1000;
+ ExecutorService executorService = Executors.newFixedThreadPool(10);
+ ArrayList<Future<Boolean>> futures = new ArrayList(size);
+ for (int i = 0; i < size; i++) {
+ futures.add(executorService.submit(() -> openHSSFFile()));
+ }
+ for (Future<Boolean> future: futures) {
+ assertTrue(future.get());
+ }
+ }
+
+ @Test(expected = IOException.class)
+ public void testInvalidFormatException() throws IOException {
+ String filename = "OPCCompliance_DerivedPartNameFAIL.docx";
+ WorkbookFactory.create(POIDataSamples.getOpenXML4JInstance().openResourceAsStream(filename));
+ }
+
+ private boolean openHSSFFile() {
+ try {
+ // POIFS -> hssf
+ Workbook wb = WorkbookFactory.create(
+ new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls))
+ );
+ assertNotNull(wb);
+ assertTrue(wb instanceof HSSFWorkbook);
+ assertCloseDoesNotModifyFile(xls, wb);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.extractor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.extractor.EmbeddedData;
+import org.apache.poi.ss.extractor.EmbeddedExtractor;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.junit.Test;
+
+public class TestEmbeddedExtractor {
+ private static final POIDataSamples samples = POIDataSamples.getSpreadSheetInstance();
+
+ @Test
+ public void extractPDFfromEMF() throws Exception {
+ InputStream fis = samples.openResourceAsStream("Basic_Expense_Template_2011.xls");
+ Workbook wb = WorkbookFactory.create(fis);
+ fis.close();
+
+ EmbeddedExtractor ee = new EmbeddedExtractor();
+ List<EmbeddedData> edList = new ArrayList<>();
+ for (Sheet s : wb) {
+ edList.addAll(ee.extractAll(s));
+ }
+ wb.close();
+
+ assertEquals(2, edList.size());
+
+ String filename1 = "Sample.pdf";
+ EmbeddedData ed0 = edList.get(0);
+ assertEquals(filename1, ed0.getFilename());
+ assertEquals(filename1, ed0.getShape().getShapeName().trim());
+ assertEquals("uNplB1QpYug+LWappiTh0w==", md5hash(ed0.getEmbeddedData()));
+
+ String filename2 = "kalastuslupa_jiyjhnj_yuiyuiyuio_uyte_sldfsdfsdf_sfsdfsdf_sfsssfsf_sdfsdfsdfsdf_sdfsdfsdf.pdf";
+ EmbeddedData ed1 = edList.get(1);
+ assertEquals(filename2, ed1.getFilename());
+ assertEquals(filename2, ed1.getShape().getShapeName().trim());
+ assertEquals("QjLuAZ+cd7KbhVz4sj+QdA==", md5hash(ed1.getEmbeddedData()));
+ }
+
+ @Test
+ public void extractFromXSSF() throws IOException, EncryptedDocumentException, InvalidFormatException {
+ InputStream fis = samples.openResourceAsStream("58325_db.xlsx");
+ Workbook wb = WorkbookFactory.create(fis);
+ fis.close();
+
+ EmbeddedExtractor ee = new EmbeddedExtractor();
+ List<EmbeddedData> edList = new ArrayList<>();
+ for (Sheet s : wb) {
+ edList.addAll(ee.extractAll(s));
+ }
+ wb.close();
+
+ assertEquals(4, edList.size());
+ EmbeddedData ed0 = edList.get(0);
+ assertEquals("Object 1.pdf", ed0.getFilename());
+ assertEquals("Object 1", ed0.getShape().getShapeName().trim());
+ assertEquals("Oyys6UtQU1gbHYBYqA4NFA==", md5hash(ed0.getEmbeddedData()));
+
+ EmbeddedData ed1 = edList.get(1);
+ assertEquals("Object 2.pdf", ed1.getFilename());
+ assertEquals("Object 2", ed1.getShape().getShapeName().trim());
+ assertEquals("xLScPUS0XH+5CTZ2A3neNw==", md5hash(ed1.getEmbeddedData()));
+
+ EmbeddedData ed2 = edList.get(2);
+ assertEquals("Object 3.pdf", ed2.getFilename());
+ assertEquals("Object 3", ed2.getShape().getShapeName().trim());
+ assertEquals("rX4klZqJAeM5npb54Gi2+Q==", md5hash(ed2.getEmbeddedData()));
+
+ EmbeddedData ed3 = edList.get(3);
+ assertEquals("Microsoft_Excel_Worksheet1.xlsx", ed3.getFilename());
+ assertEquals("Object 1", ed3.getShape().getShapeName().trim());
+ assertEquals("4m4N8ji2tjpEGPQuw2YwGA==", md5hash(ed3.getEmbeddedData()));
+ }
+
+ public static String md5hash(byte[] input) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] hash = md.digest(input);
+ return Base64.getEncoder().encodeToString(hash);
+ } catch (NoSuchAlgorithmException e) {
+ // doesn't happen
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ @Test
+ public void testNPE() throws IOException {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("angelo.edu_content_files_19555-nsse-2011-multiyear-benchmark.xls");
+ EmbeddedExtractor ee = new EmbeddedExtractor();
+
+ for (Sheet s : wb) {
+ for (EmbeddedData ed : ee.extractAll(s)) {
+ assertNotNull(ed.getFilename());
+ assertNotNull(ed.getEmbeddedData());
+ assertNotNull(ed.getShape());
+ }
+ }
+
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.format;
+
+import static java.awt.Color.ORANGE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.swing.JLabel;
+
+import org.apache.poi.ss.ITestDataProvider;
+import org.apache.poi.ss.format.CellFormat;
+import org.apache.poi.ss.format.CellFormatPart;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.util.LocaleUtil;
+import org.apache.poi.xssf.XSSFITestDataProvider;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Class for spreadsheet-based tests, such as are used for cell formatting.
+ * This reads tests from the spreadsheet, as well as reading
+ * flags that can be used to paramterize these tests.
+ * <p>
+ * Each test has four parts: The expected result (column A), the format string
+ * (column B), the value to format (column C), and a comma-separated list of
+ * categores that this test falls in. Normally all tests are run, but if the
+ * flag "Categories" is not empty, only tests that have at least one category
+ * listed in "Categories" are run.
+ */
+public class TestCellFormatPart {
+ private static final Pattern NUMBER_EXTRACT_FMT = Pattern.compile(
+ "([-+]?[0-9]+)(\\.[0-9]+)?.*(?:(e).*?([+-]?[0-9]+))",
+ Pattern.CASE_INSENSITIVE);
+ private static final Color TEST_COLOR = ORANGE.darker();
+ private static Locale userLocale;
+
+
+
+ @BeforeClass
+ public static void setLocale() {
+ userLocale = LocaleUtil.getUserLocale();
+ LocaleUtil.setUserLocale(Locale.UK);
+ }
+
+ @AfterClass
+ public static void unsetLocale() {
+ LocaleUtil.setUserLocale(userLocale);
+ }
+
+ private final ITestDataProvider _testDataProvider = XSSFITestDataProvider.instance;
+
+ private interface CellValue {
+ Object getValue(Cell cell);
+
+ default void equivalent(String expected, String actual, CellFormatPart format) {
+ assertEquals("format \"" + format + "\"", '"' + expected + '"',
+ '"' + actual + '"');
+ }
+ }
+
+ @Test
+ public void testGeneralFormat() throws IOException {
+ runFormatTests("GeneralFormatTests.xlsx", cell -> {
+ assertNotNull(cell);
+ switch (CellFormat.ultimateType(cell)) {
+ case BOOLEAN:
+ return cell.getBooleanCellValue();
+ case NUMERIC:
+ return cell.getNumericCellValue();
+ default:
+ return cell.getStringCellValue();
+ }
+ });
+ }
+
+ @Test
+ public void testNumberFormat() throws IOException {
+ runFormatTests("NumberFormatTests.xlsx", Cell::getNumericCellValue);
+ }
+
+ @Test
+ public void testNumberApproxFormat() throws IOException {
+ runFormatTests("NumberFormatApproxTests.xlsx", new CellValue() {
+ @Override
+ public Object getValue(Cell cell) {
+ return cell.getNumericCellValue();
+ }
+
+ @Override
+ public void equivalent(String expected, String actual,
+ CellFormatPart format) {
+ double expectedVal = extractNumber(expected);
+ double actualVal = extractNumber(actual);
+ // equal within 1%
+ double delta = expectedVal / 100;
+ assertEquals("format \"" + format + "\"," + expected + " ~= " +
+ actual, expectedVal, actualVal, delta);
+ }
+ });
+ }
+
+ @Test
+ public void testDateFormat() throws IOException {
+ TimeZone tz = LocaleUtil.getUserTimeZone();
+ LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
+ try {
+ runFormatTests("DateFormatTests.xlsx", Cell::getDateCellValue);
+ } finally {
+ LocaleUtil.setUserTimeZone(tz);
+ }
+ }
+
+ @Test
+ public void testElapsedFormat() throws IOException {
+ runFormatTests("ElapsedFormatTests.xlsx", Cell::getNumericCellValue);
+ }
+
+ @Test
+ public void testTextFormat() throws IOException {
+ runFormatTests("TextFormatTests.xlsx", cell ->
+ (CellFormat.ultimateType(cell) == CellType.BOOLEAN) ? cell.getBooleanCellValue() : cell.getStringCellValue()
+ );
+ }
+
+ @Test
+ public void testConditions() throws IOException {
+ runFormatTests("FormatConditionTests.xlsx", Cell::getNumericCellValue);
+ }
+
+ private double extractNumber(String str) {
+ Matcher m = NUMBER_EXTRACT_FMT.matcher(str);
+ if (!m.find()) {
+ throw new IllegalArgumentException("Cannot find number in \"" + str + "\"");
+ }
+
+ StringBuilder sb = new StringBuilder();
+ // The groups in the pattern are the parts of the number
+ for (int i = 1; i <= m.groupCount(); i++) {
+ String part = m.group(i);
+ if (part != null)
+ sb.append(part);
+ }
+ return Double.parseDouble(sb.toString());
+ }
+
+
+ protected void runFormatTests(String workbookName, CellValue valueGetter) throws IOException {
+ try (Workbook workbook = _testDataProvider.openSampleWorkbook(workbookName)) {
+ workbook.setMissingCellPolicy(Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
+
+ Sheet sheet = workbook.getSheet("Tests");
+ boolean isHeader = true;
+ for (Row row : sheet) {
+ // Skip the header row
+ if (isHeader || row == null) {
+ isHeader = false;
+ continue;
+ }
+ String expectedText = row.getCell(0).getStringCellValue();
+ String format = row.getCell(1).getStringCellValue();
+ Cell value = row.getCell(2);
+
+ if (expectedText.isEmpty() && format.isEmpty()) {
+ continue;
+ }
+
+ Object objVal = valueGetter.getValue(value);
+ JLabel label = new JLabel();
+ label.setForeground(TEST_COLOR);
+ label.setText("xyzzy");
+
+ Color origColor = label.getForeground();
+ CellFormatPart cellFormatPart = new CellFormatPart(format);
+ // If this doesn't apply, no color change is expected
+ Color expectedColor = cellFormatPart.apply(label, objVal).applies ? TEST_COLOR : origColor;
+
+ String actualText = label.getText();
+ Color actualColor = label.getForeground();
+ valueGetter.equivalent(expectedText, actualText, cellFormatPart);
+ assertEquals("no color", expectedColor, actualColor);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.ss.tests.formula;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.formula.FormulaParseException;
+import org.apache.poi.ss.formula.FormulaParser;
+import org.apache.poi.ss.formula.FormulaParsingWorkbook;
+import org.apache.poi.ss.formula.FormulaType;
+import org.apache.poi.ss.formula.ptg.AbstractFunctionPtg;
+import org.apache.poi.ss.formula.ptg.NameXPxg;
+import org.apache.poi.ss.formula.ptg.Ptg;
+import org.apache.poi.ss.formula.ptg.Ref3DPxg;
+import org.apache.poi.ss.formula.ptg.StringPtg;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+
+/**
+ * Test {@link FormulaParser}'s handling of row numbers at the edge of the
+ * HSSF/XSSF ranges.
+ *
+ * @author David North
+ */
+public class TestFormulaParser {
+
+ @Test
+ public void testHSSFFailsForOver65536() {
+ FormulaParsingWorkbook workbook = HSSFEvaluationWorkbook.create(new HSSFWorkbook());
+ try {
+ FormulaParser.parse("Sheet1!1:65537", workbook, FormulaType.CELL, 0);
+ fail("Expected exception");
+ }
+ catch (FormulaParseException expected) {
+ // expected here
+ }
+ }
+
+ private static void checkHSSFFormula(String formula) {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ FormulaParsingWorkbook workbook = HSSFEvaluationWorkbook.create(wb);
+ FormulaParser.parse(formula, workbook, FormulaType.CELL, 0);
+ IOUtils.closeQuietly(wb);
+ }
+ private static void checkXSSFFormula(String formula) {
+ XSSFWorkbook wb = new XSSFWorkbook();
+ FormulaParsingWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
+ FormulaParser.parse(formula, workbook, FormulaType.CELL, 0);
+ IOUtils.closeQuietly(wb);
+ }
+ private static void checkFormula(String formula) {
+ checkHSSFFormula(formula);
+ checkXSSFFormula(formula);
+ }
+
+ @Test
+ public void testHSSFPassCase() {
+ checkHSSFFormula("Sheet1!1:65536");
+ }
+
+ @Test
+ public void testXSSFWorksForOver65536() {
+ checkXSSFFormula("Sheet1!1:65537");
+ }
+
+ @Test
+ public void testXSSFFailCase() {
+ FormulaParsingWorkbook workbook = XSSFEvaluationWorkbook.create(new XSSFWorkbook());
+ try {
+ FormulaParser.parse("Sheet1!1:1048577", workbook, FormulaType.CELL, 0); // one more than max rows.
+ fail("Expected exception");
+ }
+ catch (FormulaParseException expected) {
+ // expected here
+ }
+ }
+
+ // copied from org.apache.poi.hssf.model.TestFormulaParser
+ @Test
+ public void testMacroFunction() throws Exception {
+ // testNames.xlsm contains a VB function called 'myFunc'
+ final String testFile = "testNames.xlsm";
+ try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(testFile)) {
+ XSSFEvaluationWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
+
+ //Expected ptg stack: [NamePtg(myFunc), StringPtg(arg), (additional operands would go here...), FunctionPtg(myFunc)]
+ Ptg[] ptg = FormulaParser.parse("myFunc(\"arg\")", workbook, FormulaType.CELL, -1);
+ assertEquals(3, ptg.length);
+
+ // the name gets encoded as the first operand on the stack
+ NameXPxg tname = (NameXPxg) ptg[0];
+ assertEquals("myFunc", tname.toFormulaString());
+
+ // the function's arguments are pushed onto the stack from left-to-right as OperandPtgs
+ StringPtg arg = (StringPtg) ptg[1];
+ assertEquals("arg", arg.getValue());
+
+ // The external FunctionPtg is the last Ptg added to the stack
+ // During formula evaluation, this Ptg pops off the the appropriate number of
+ // arguments (getNumberOfOperands()) and pushes the result on the stack
+ AbstractFunctionPtg tfunc = (AbstractFunctionPtg) ptg[2];
+ assertTrue(tfunc.isExternalFunction());
+
+ // confirm formula parsing is case-insensitive
+ FormulaParser.parse("mYfUnC(\"arg\")", workbook, FormulaType.CELL, -1);
+
+ // confirm formula parsing doesn't care about argument count or type
+ // this should only throw an error when evaluating the formula.
+ FormulaParser.parse("myFunc()", workbook, FormulaType.CELL, -1);
+ FormulaParser.parse("myFunc(\"arg\", 0, TRUE)", workbook, FormulaType.CELL, -1);
+
+ // A completely unknown formula name (not saved in workbook) should still be parseable and renderable
+ // but will throw an NotImplementedFunctionException or return a #NAME? error value if evaluated.
+ FormulaParser.parse("yourFunc(\"arg\")", workbook, FormulaType.CELL, -1);
+
+ // Make sure workbook can be written and read
+ XSSFTestDataSamples.writeOutAndReadBack(wb).close();
+
+ // Manually check to make sure file isn't corrupted
+ // TODO: develop a process for occasionally manually reviewing workbooks
+ // to verify workbooks are not corrupted
+ /*
+ final File fileIn = XSSFTestDataSamples.getSampleFile(testFile);
+ final File reSavedFile = new File(fileIn.getParentFile(), fileIn.getName().replace(".xlsm", "-saved.xlsm"));
+ final FileOutputStream fos = new FileOutputStream(reSavedFile);
+ wb.write(fos);
+ fos.close();
+ */
+ }
+ }
+
+ @Test
+ public void testParserErrors() throws Exception {
+ try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("testNames.xlsm")) {
+ XSSFEvaluationWorkbook workbook = XSSFEvaluationWorkbook.create(wb);
+
+ parseExpectedException("(");
+ parseExpectedException(")");
+ parseExpectedException("+");
+ parseExpectedException("42+");
+ parseExpectedException("IF()");
+ parseExpectedException("IF("); //no closing paren
+ parseExpectedException("myFunc(", workbook); //no closing paren
+ }
+ }
+
+ private static void parseExpectedException(String formula) {
+ parseExpectedException(formula, null);
+ }
+
+ /** confirm formula has invalid syntax and parsing the formula results in FormulaParseException
+ */
+ private static void parseExpectedException(String formula, FormulaParsingWorkbook wb) {
+ try {
+ FormulaParser.parse(formula, wb, FormulaType.CELL, -1);
+ fail("Expected FormulaParseException: " + formula);
+ } catch (final FormulaParseException e) {
+ // expected during successful test
+ assertNotNull(e.getMessage());
+ }
+ }
+
+ // trivial case for bug 60219: FormulaParser can't parse external references when sheet name is quoted
+ @Test
+ public void testParseExternalReferencesWithUnquotedSheetName() throws Exception {
+ XSSFWorkbook wb = new XSSFWorkbook();
+ XSSFEvaluationWorkbook fpwb = XSSFEvaluationWorkbook.create(wb);
+ Ptg[] ptgs = FormulaParser.parse("[1]Sheet1!A1", fpwb, FormulaType.CELL, -1);
+ // org.apache.poi.ss.formula.ptg.Ref3DPxg [ [workbook=1] sheet=Sheet 1 ! A1]
+ assertEquals("Ptgs length", 1, ptgs.length);
+ assertTrue("Ptg class", ptgs[0] instanceof Ref3DPxg);
+ Ref3DPxg pxg = (Ref3DPxg) ptgs[0];
+ assertEquals("External workbook number", 1, pxg.getExternalWorkbookNumber());
+ assertEquals("Sheet name", "Sheet1", pxg.getSheetName());
+ assertEquals("Row", 0, pxg.getRow());
+ assertEquals("Column", 0, pxg.getColumn());
+ wb.close();
+ }
+
+ // bug 60219: FormulaParser can't parse external references when sheet name is quoted
+ @Test
+ public void testParseExternalReferencesWithQuotedSheetName() throws Exception {
+ XSSFWorkbook wb = new XSSFWorkbook();
+ XSSFEvaluationWorkbook fpwb = XSSFEvaluationWorkbook.create(wb);
+ Ptg[] ptgs = FormulaParser.parse("'[1]Sheet 1'!A1", fpwb, FormulaType.CELL, -1);
+ // org.apache.poi.ss.formula.ptg.Ref3DPxg [ [workbook=1] sheet=Sheet 1 ! A1]
+ assertEquals("Ptgs length", 1, ptgs.length);
+ assertTrue("Ptg class", ptgs[0] instanceof Ref3DPxg);
+ Ref3DPxg pxg = (Ref3DPxg) ptgs[0];
+ assertEquals("External workbook number", 1, pxg.getExternalWorkbookNumber());
+ assertEquals("Sheet name", "Sheet 1", pxg.getSheetName());
+ assertEquals("Row", 0, pxg.getRow());
+ assertEquals("Column", 0, pxg.getColumn());
+ wb.close();
+ }
+
+ // bug 60260
+ @Test
+ public void testUnicodeSheetName() {
+ checkFormula("'Sheet\u30FB1'!A1:A6");
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.formula;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Table;
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFTable;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+
+/**
+ * Tests Excel Table expressions (structured references)
+ * @see <a href="https://support.office.com/en-us/article/Using-structured-references-with-Excel-tables-F5ED2452-2337-4F71-BED3-C8AE6D2B276E">
+ * Excel Structured Reference Syntax
+ * </a>
+ */
+public class TestStructuredReferences {
+
+ /**
+ * Test the regular expression used in INDIRECT() evaluation to recognize structured references
+ */
+ @Test
+ public void testTableExpressionSyntax() {
+ assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("abc[col1]").matches());
+ assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("_abc[col1]").matches());
+ assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("_[col1]").matches());
+ assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("\\[col1]").matches());
+ assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("\\[col1]").matches());
+ assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("\\[#This Row]").matches());
+ assertTrue("Valid structured reference syntax didn't match expression", Table.isStructuredReference.matcher("\\[ [col1], [col2] ]").matches());
+
+ // can't have a space between the table name and open bracket
+ assertFalse("Invalid structured reference syntax didn't fail expression", Table.isStructuredReference.matcher("\\abc [ [col1], [col2] ]").matches());
+ }
+
+ @Test
+ public void testTableFormulas() throws Exception {
+ try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("StructuredReferences.xlsx")) {
+
+ final FormulaEvaluator eval = new XSSFFormulaEvaluator(wb);
+ final XSSFSheet tableSheet = wb.getSheet("Table");
+ final XSSFSheet formulaSheet = wb.getSheet("Formulas");
+
+ confirm(eval, tableSheet.getRow(5).getCell(0), 49);
+ confirm(eval, formulaSheet.getRow(0).getCell(0), 209);
+ confirm(eval, formulaSheet.getRow(1).getCell(0), "one");
+
+ // test changing a table value, to see if the caches are properly cleared
+ // Issue 59814
+
+ // this test passes before the fix for 59814
+ tableSheet.getRow(1).getCell(1).setCellValue("ONEA");
+ confirm(eval, formulaSheet.getRow(1).getCell(0), "ONEA");
+
+ // test adding a row to a table, issue 59814
+ Row newRow = tableSheet.getRow(7);
+ if (newRow == null) newRow = tableSheet.createRow(7);
+ newRow.createCell(0, CellType.FORMULA).setCellFormula("\\_Prime.1[[#This Row],[@Number]]*\\_Prime.1[[#This Row],[@Number]]");
+ newRow.createCell(1, CellType.STRING).setCellValue("thirteen");
+ newRow.createCell(2, CellType.NUMERIC).setCellValue(13);
+
+ // update Table
+ final XSSFTable table = wb.getTable("\\_Prime.1");
+ final AreaReference newArea = wb.getCreationHelper().createAreaReference(
+ table.getStartCellReference(),
+ new CellReference(table.getEndRowIndex() + 1, table.getEndColIndex()));
+ String newAreaStr = newArea.formatAsString();
+ table.getCTTable().setRef(newAreaStr);
+ table.getCTTable().getAutoFilter().setRef(newAreaStr);
+ table.updateHeaders();
+ table.updateReferences();
+
+ // these fail before the fix for 59814
+ confirm(eval, tableSheet.getRow(7).getCell(0), 13 * 13);
+ confirm(eval, formulaSheet.getRow(0).getCell(0), 209 + 13 * 13);
+
+ }
+ }
+
+ private static void confirm(FormulaEvaluator fe, Cell cell, double expectedResult) {
+ fe.clearAllCachedResultValues();
+ CellValue cv = fe.evaluate(cell);
+ if (cv.getCellType() != CellType.NUMERIC) {
+ fail("expected numeric cell type but got " + cv.formatAsString());
+ }
+ assertEquals(expectedResult, cv.getNumberValue(), 0.0);
+ }
+
+ private static void confirm(FormulaEvaluator fe, Cell cell, String expectedResult) {
+ fe.clearAllCachedResultValues();
+ CellValue cv = fe.evaluate(cell);
+ if (cv.getCellType() != CellType.STRING) {
+ fail("expected String cell type but got " + cv.formatAsString());
+ }
+ assertEquals(expectedResult, cv.getStringValue());
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.formula.eval;
+
+import org.apache.poi.ss.formula.eval.BaseTestCircularReferences;
+import org.apache.poi.xssf.XSSFITestDataProvider;
+
+/**
+ * Tests XSSFFormulaEvaluator for its handling of cell formula circular references.
+ *
+ * @author Josh Micich
+ */
+public final class TestXSSFCircularReferences extends BaseTestCircularReferences {
+ public TestXSSFCircularReferences() {
+ super(XSSFITestDataProvider.instance);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.formula.functions;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.SheetUtil;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test the COUNTIFS() function
+ */
+public class CountifsTests {
+
+ private Workbook workbook;
+
+ /**
+ * initialize a workbook
+ */
+ @Before
+ public void before() {
+ // not sure why we allow this, COUNTIFS() is only available
+ // in OOXML, it was introduced with Office 2007
+ workbook = new HSSFWorkbook();
+ }
+
+ /**
+ * Close the workbook if needed
+ */
+ @After
+ public void after() {
+ IOUtils.closeQuietly(workbook);
+ }
+
+ /**
+ * Basic call
+ */
+ @Test
+ public void testCallFunction() {
+ Sheet sheet = workbook.createSheet("test");
+ Row row1 = sheet.createRow(0);
+ Cell cellA1 = row1.createCell(0, CellType.FORMULA);
+ Cell cellB1 = row1.createCell(1, CellType.NUMERIC);
+ Cell cellC1 = row1.createCell(2, CellType.NUMERIC);
+ Cell cellD1 = row1.createCell(3, CellType.NUMERIC);
+ Cell cellE1 = row1.createCell(4, CellType.NUMERIC);
+ cellB1.setCellValue(1);
+ cellC1.setCellValue(1);
+ cellD1.setCellValue(2);
+ cellE1.setCellValue(4);
+
+ cellA1.setCellFormula("COUNTIFS(B1:C1,1, D1:E1,2)");
+ FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+ CellValue evaluate = evaluator.evaluate(cellA1);
+ assertEquals(1.0d, evaluate.getNumberValue(), 0.000000000000001);
+ }
+
+ /**
+ * Test argument count check
+ */
+ @Test
+ public void testCallFunction_invalidArgs() {
+ Sheet sheet = workbook.createSheet("test");
+ Row row1 = sheet.createRow(0);
+ Cell cellA1 = row1.createCell(0, CellType.FORMULA);
+ cellA1.setCellFormula("COUNTIFS()");
+ FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+ CellValue evaluate = evaluator.evaluate(cellA1);
+ assertEquals(15, evaluate.getErrorValue());
+ cellA1.setCellFormula("COUNTIFS(A1:C1)");
+ evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+ evaluate = evaluator.evaluate(cellA1);
+ assertEquals(15, evaluate.getErrorValue());
+ cellA1.setCellFormula("COUNTIFS(A1:C1,2,2)");
+ evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+ evaluate = evaluator.evaluate(cellA1);
+ assertEquals(15, evaluate.getErrorValue());
+ }
+
+ /**
+ * the bug returned the wrong count, this verifies the fix
+ * @throws Exception if the file can't be read
+ */
+ @Test
+ public void testBug56822() throws Exception {
+ workbook = XSSFTestDataSamples.openSampleWorkbook("56822-Countifs.xlsx");
+ FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+ Cell cell = SheetUtil.getCell(workbook.getSheetAt(0), 0, 3);
+ assertNotNull("Test workbook missing cell D1", cell);
+ CellValue evaluate = evaluator.evaluate(cell);
+ assertEquals(2.0d, evaluate.getNumberValue(), 0.00000000000001);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.formula.functions;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.TextFunction;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+
+public final class TestProper {
+ private Cell cell11;
+ private FormulaEvaluator evaluator;
+
+ @Test
+ public void testValidHSSF() {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ evaluator = new HSSFFormulaEvaluator(wb);
+
+ confirm(wb);
+ }
+
+ @Test
+ public void testValidXSSF() {
+ XSSFWorkbook wb = new XSSFWorkbook();
+ evaluator = new XSSFFormulaEvaluator(wb);
+
+ confirm(wb);
+ }
+
+ private void confirm(Workbook wb) {
+ Sheet sheet = wb.createSheet("new sheet");
+ cell11 = sheet.createRow(0).createCell(0);
+
+ confirm("PROPER(\"hi there\")", "Hi There"); //simple case
+ confirm("PROPER(\"what's up\")", "What'S Up"); //apostrophes are treated as word breaks
+ confirm("PROPER(\"I DON'T TH!NK SO!\")", "I Don'T Th!Nk So!"); //capitalization is ignored, special punctuation is treated as a word break
+ confirm("PROPER(\"dr\u00dcb\u00f6'\u00e4 \u00e9lo\u015f|\u00eb\u00e8 \")", "Dr\u00fcb\u00f6'\u00c4 \u00c9lo\u015f|\u00cb\u00e8 ");
+ confirm("PROPER(\"hi123 the123re\")", "Hi123 The123Re"); //numbers are treated as word breaks
+ confirm("PROPER(\"-\")", "-"); //nothing happens with ascii punctuation that is not upper or lower case
+ confirm("PROPER(\"!\u00a7$\")", "!\u00a7$"); //nothing happens with unicode punctuation (section sign) that is not upper or lower case
+ confirm("PROPER(\"/&%\")", "/&%"); //nothing happens with ascii punctuation that is not upper or lower case
+ confirm("PROPER(\"Apache POI\")", "Apache Poi"); //acronyms are not special
+ confirm("PROPER(\" hello world\")", " Hello World"); //leading whitespace is ignored
+
+ final String scharfes = "\u00df"; //German lowercase eszett, scharfes s, sharp s
+ confirm("PROPER(\"stra"+scharfes+"e\")", "Stra"+scharfes+"e");
+ assertTrue(Character.isLetter(scharfes.charAt(0)));
+
+ // CURRENTLY FAILS: result: "SSUnd"+scharfes
+ // LibreOffice 5.0.3.2 behavior: "Sund"+scharfes
+ // Excel 2013 behavior: ???
+ confirm("PROPER(\""+scharfes+"und"+scharfes+"\")", "SSund"+scharfes);
+
+ // also test longer string
+ StringBuilder builder = new StringBuilder("A");
+ StringBuilder expected = new StringBuilder("A");
+ for(int i = 1;i < 254;i++) {
+ builder.append((char)(65 + (i % 26)));
+ expected.append((char)(97 + (i % 26)));
+ }
+ confirm("PROPER(\"" + builder + "\")", expected.toString());
+ }
+
+ private void confirm(String formulaText, String expectedResult) {
+ cell11.setCellFormula(formulaText);
+ evaluator.clearAllCachedResultValues();
+ CellValue cv = evaluator.evaluate(cell11);
+ assertEquals("Wrong result type", CellType.STRING, cv.getCellType());
+ String actualValue = cv.getStringValue();
+ assertEquals(expectedResult, actualValue);
+ }
+
+ @Test
+ public void test() {
+ checkProper("", "");
+ checkProper("a", "A");
+ checkProper("abc", "Abc");
+ checkProper("abc abc", "Abc Abc");
+ checkProper("abc/abc", "Abc/Abc");
+ checkProper("ABC/ABC", "Abc/Abc");
+ checkProper("aBc/ABC", "Abc/Abc");
+ checkProper("aBc@#$%^&*()_+=-ABC", "Abc@#$%^&*()_+=-Abc");
+ checkProper("aBc25aerg/ABC", "Abc25Aerg/Abc");
+ checkProper("aBc/\u00C4\u00F6\u00DF\u00FC/ABC", "Abc/\u00C4\u00F6\u00DF\u00FC/Abc"); // Some German umlauts with uppercase first letter is not changed
+ checkProper("\u00FC", "\u00DC");
+ checkProper("\u00DC", "\u00DC");
+ checkProper("\u00DF", "SS"); // German "scharfes s" is uppercased to "SS"
+ checkProper("\u00DFomesing", "SSomesing"); // German "scharfes s" is uppercased to "SS"
+ checkProper("aBc/\u00FC\u00C4\u00F6\u00DF\u00FC/ABC", "Abc/\u00DC\u00E4\u00F6\u00DF\u00FC/Abc"); // Some German umlauts with lowercase first letter is changed to uppercase
+ }
+
+ @Test
+ public void testMicroBenchmark() {
+ ValueEval strArg = new StringEval("some longer text that needs a number of replacements to check for runtime of different implementations");
+ long start = System.currentTimeMillis();
+ for(int i = 0;i < 300000;i++) {
+ final ValueEval ret = TextFunction.PROPER.evaluate(new ValueEval[]{strArg}, 0, 0);
+ assertEquals("Some Longer Text That Needs A Number Of Replacements To Check For Runtime Of Different Implementations", ((StringEval)ret).getStringValue());
+ }
+ // Took approx. 600ms on a decent Laptop in July 2016
+ //System.out.println("Took: " + (System.currentTimeMillis() - start) + "ms");
+ }
+
+ private void checkProper(String input, String expected) {
+ ValueEval strArg = new StringEval(input);
+ final ValueEval ret = TextFunction.PROPER.evaluate(new ValueEval[]{strArg}, 0, 0);
+ assertEquals(expected, ((StringEval)ret).getStringValue());
+ }
+}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.ss.tests.formula.functions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class TestSumifsXSSF {
+
+ /**
+ * handle null cell predicate
+ */
+ @Test
+ public void testBug60858() throws IOException {
+ try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("bug60858.xlsx")) {
+ FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator();
+
+ Sheet sheet = wb.getSheetAt(0);
+ Cell cell = sheet.getRow(1).getCell(5);
+ fe.evaluate(cell);
+ assertEquals(0.0, cell.getNumericCellValue(), 0.0000000000000001);
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.formula.functions;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.CreationHelper;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+
+/**
+ * Test the VLOOKUP function
+ */
+public class TestVlookup {
+
+ @Test
+ public void testFullColumnAreaRef61841() throws IOException {
+ try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("VLookupFullColumn.xlsx")) {
+ FormulaEvaluator feval = wb.getCreationHelper().createFormulaEvaluator();
+ feval.evaluateAll();
+ assertEquals("Wrong lookup value", "Value1",
+ feval.evaluate(wb.getSheetAt(0).getRow(3).getCell(1)).getStringValue());
+ assertEquals("Lookup should return #N/A",
+ CellType.ERROR, feval.evaluate(wb.getSheetAt(0).getRow(4).getCell(1)).getCellType());
+ }
+ }
+
+ @Test
+ public void bug62275_true() throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) {
+ Sheet sheet = wb.createSheet();
+ Row row = sheet.createRow(0);
+
+ Cell cell = row.createCell(0);
+ cell.setCellFormula("vlookup(A2,B1:B5,2,true)");
+
+ CreationHelper createHelper = wb.getCreationHelper();
+ FormulaEvaluator eval = createHelper.createFormulaEvaluator();
+ CellValue value = eval.evaluate(cell);
+
+ assertFalse(value.getBooleanValue());
+ }
+ }
+
+ @Test
+ public void bug62275_false() throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) {
+ Sheet sheet = wb.createSheet();
+ Row row = sheet.createRow(0);
+
+ Cell cell = row.createCell(0);
+ cell.setCellFormula("vlookup(A2,B1:B5,2,false)");
+
+ CreationHelper crateHelper = wb.getCreationHelper();
+ FormulaEvaluator eval = crateHelper.createFormulaEvaluator();
+ CellValue value = eval.evaluate(cell);
+
+ assertFalse(value.getBooleanValue());
+ }
+ }
+
+ @Test
+ public void bug62275_empty_3args() throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) {
+ Sheet sheet = wb.createSheet();
+ Row row = sheet.createRow(0);
+
+ Cell cell = row.createCell(0);
+ cell.setCellFormula("vlookup(A2,B1:B5,2,)");
+
+ CreationHelper crateHelper = wb.getCreationHelper();
+ FormulaEvaluator eval = crateHelper.createFormulaEvaluator();
+ CellValue value = eval.evaluate(cell);
+
+ assertFalse(value.getBooleanValue());
+ }
+ }
+
+ @Test
+ public void bug62275_empty_2args() throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) {
+ Sheet sheet = wb.createSheet();
+ Row row = sheet.createRow(0);
+
+ Cell cell = row.createCell(0);
+ cell.setCellFormula("vlookup(A2,B1:B5,,)");
+
+ CreationHelper crateHelper = wb.getCreationHelper();
+ FormulaEvaluator eval = crateHelper.createFormulaEvaluator();
+ CellValue value = eval.evaluate(cell);
+
+ assertFalse(value.getBooleanValue());
+ }
+ }
+
+ @Test
+ public void bug62275_empty_1arg() throws IOException {
+ try (Workbook wb = new XSSFWorkbook()) {
+ Sheet sheet = wb.createSheet();
+ Row row = sheet.createRow(0);
+
+ Cell cell = row.createCell(0);
+ cell.setCellFormula("vlookup(A2,,,)");
+
+ CreationHelper crateHelper = wb.getCreationHelper();
+ FormulaEvaluator eval = crateHelper.createFormulaEvaluator();
+ CellValue value = eval.evaluate(cell);
+
+ assertFalse(value.getBooleanValue());
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.usermodel;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.ss.ITestDataProvider;
+import org.apache.poi.ss.usermodel.BaseTestCell;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.streaming.SXSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.junit.Test;
+
+/**
+ * Class for combined testing of XML-specific functionality of
+ * {@link XSSFCell} and {@link SXSSFCell}.
+ *
+ * Any test that is applicable for {@link HSSFCell} as well should go into
+ * the common base class {@link BaseTestCell}.
+ */
+public abstract class BaseTestXCell extends BaseTestCell {
+ protected BaseTestXCell(ITestDataProvider testDataProvider) {
+ super(testDataProvider);
+ }
+
+ @Test
+ public void testXmlEncoding() throws IOException {
+ Workbook wb1 = _testDataProvider.createWorkbook();
+ Sheet sh = wb1.createSheet();
+ Row row = sh.createRow(0);
+ Cell cell = row.createCell(0);
+ String sval = "\u0000\u0002\u0012<>\t\n\u00a0 &\"POI'\u2122";
+ cell.setCellValue(sval);
+
+ Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
+ wb1.close();
+
+ // invalid characters are replaced with question marks
+ assertEquals("???<>\t\n\u00a0 &\"POI'\u2122", wb2.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
+ wb2.close();
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.usermodel;
+
+import java.io.IOException;
+
+import org.apache.poi.ss.ITestDataProvider;
+import org.apache.poi.ss.usermodel.BaseTestRow;
+import org.apache.poi.xssf.streaming.SXSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.junit.Test;
+
+/**
+ * Class for combined testing of XML-specific functionality of
+ * {@link XSSFRow} and {@link SXSSFRow}.
+ *
+ * Any test that is applicable for {@link org.apache.poi.hssf.usermodel.HSSFRow} as well should go into
+ * the common base class {@link BaseTestRow}.
+ */
+public abstract class BaseTestXRow extends BaseTestRow {
+ protected BaseTestXRow(ITestDataProvider testDataProvider) {
+ super(testDataProvider);
+ }
+
+ @Test
+ public void testRowBounds() throws IOException {
+ baseTestRowBounds(_testDataProvider.getSpreadsheetVersion().getLastRowIndex());
+ }
+
+ @Test
+ public void testCellBounds() throws IOException {
+ baseTestCellBounds(_testDataProvider.getSpreadsheetVersion().getLastColumnIndex());
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.usermodel;
+
+import org.apache.poi.ss.ITestDataProvider;
+import org.apache.poi.ss.usermodel.BaseTestSheet;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+
+/**
+ * Class for combined testing of XML-specific functionality of
+ * {@link XSSFSheet} and {@link SXSSFSheet}.
+ *
+ * Any test that is applicable for {@link org.apache.poi.hssf.usermodel.HSSFSheet} as well should go into
+ * the common base class {@link BaseTestSheet}.
+ */
+public abstract class BaseTestXSheet extends BaseTestSheet {
+ protected BaseTestXSheet(ITestDataProvider testDataProvider) {
+ super(testDataProvider);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.usermodel;
+
+import org.apache.poi.ss.ITestDataProvider;
+import org.apache.poi.ss.usermodel.BaseTestWorkbook;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * Class for combined testing of XML-specific functionality of
+ * {@link XSSFWorkbook} and {@link SXSSFWorkbook}.
+ *
+ * Any test that is applicable for {@link org.apache.poi.hssf.usermodel.HSSFWorkbook} as well should go into
+ * the common base class {@link BaseTestWorkbook}.
+ */
+public abstract class BaseTestXWorkbook extends BaseTestWorkbook {
+ protected BaseTestXWorkbook(ITestDataProvider testDataProvider) {
+ super(testDataProvider);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.usermodel;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.poi.ss.formula.ConditionalFormattingEvaluator;
+import org.apache.poi.ss.formula.EvaluationConditionalFormatRule;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Color;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConditionalFormattingEvalTest {
+
+ private XSSFWorkbook wb;
+ private Sheet sheet;
+ private XSSFFormulaEvaluator formulaEval;
+ private ConditionalFormattingEvaluator cfe;
+ private CellReference ref;
+ private List<EvaluationConditionalFormatRule> rules;
+
+ @Before
+ public void openWB() {
+ wb = XSSFTestDataSamples.openSampleWorkbook("ConditionalFormattingSamples.xlsx");
+ formulaEval = new XSSFFormulaEvaluator(wb);
+ cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
+ }
+
+ @After
+ public void closeWB() {
+ formulaEval = null;
+ cfe = null;
+ ref = null;
+ rules = null;
+ try {
+ if (wb != null) wb.close();
+ } catch (IOException e) {
+ // keep going, this shouldn't cancel things
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testFormattingEvaluation() {
+ sheet = wb.getSheet("Products1");
+
+ getRulesFor(12, 1);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+ assertEquals("wrong bg color for " + ref, "FFFFEB9C", getColor(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()));
+ assertFalse("should not be italic " + ref, rules.get(0).getRule().getFontFormatting().isItalic());
+
+ getRulesFor(16, 3);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+ assertEquals("wrong bg color for " + ref, 0.7999816888943144d, getTint(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()), 0.000000000000001);
+
+ getRulesFor(12, 3);
+ assertEquals("wrong # of rules for " + ref, 0, rules.size());
+
+ sheet = wb.getSheet("Products2");
+
+ getRulesFor(15,1);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+ assertEquals("wrong bg color for " + ref, "FFFFEB9C", getColor(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()));
+
+ getRulesFor(20,3);
+ assertEquals("wrong # of rules for " + ref, 0, rules.size());
+
+ // now change a cell value that's an input for the rules
+ Cell cell = sheet.getRow(1).getCell(6);
+ cell.setCellValue("Dairy");
+ formulaEval.notifyUpdateCell(cell);
+ cell = sheet.getRow(4).getCell(6);
+ cell.setCellValue(500);
+ formulaEval.notifyUpdateCell(cell);
+ // need to throw away all evaluations, since we don't know how value changes may have affected format formulas
+ cfe.clearAllCachedValues();
+
+ // test that the conditional validation evaluations changed
+ getRulesFor(15,1);
+ assertEquals("wrong # of rules for " + ref, 0, rules.size());
+
+ getRulesFor(20,3);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+ assertEquals("wrong bg color for " + ref, 0.7999816888943144d, getTint(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()), 0.000000000000001);
+
+ getRulesFor(20,1);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+ assertEquals("wrong bg color for " + ref, "FFFFEB9C", getColor(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()));
+
+ sheet = wb.getSheet("Book tour");
+
+ getRulesFor(8,2);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+
+ sheet = wb.getSheet("Compare to totals");
+ getRulesFor(3, 2);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+ assertEquals("wrong fg color for " + ref, "FFFF0000", getColor(rules.get(0).getRule().getFontFormatting().getFontColor()));
+ getRulesFor(3, 3);
+ assertEquals("wrong # of rules for " + ref, 0, rules.size());
+ getRulesFor(15, 4);
+ assertEquals("wrong # of rules for " + ref, 0, rules.size());
+ getRulesFor(16, 1);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+ assertEquals("wrong fg color for " + ref, "FFFF0000", getColor(rules.get(0).getRule().getFontFormatting().getFontColor()));
+
+ sheet = wb.getSheet("Products3");
+ sheet.getRow(8).getCell(0).setCellValue(new Date());
+ getRulesFor(8, 0);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+ getRulesFor(8, 3);
+ assertEquals("wrong # of rules for " + ref, 1, rules.size());
+
+ sheet = wb.getSheet("Customers2");
+ getRulesFor(3, 0);
+ assertEquals("wrong # of rules for " + ref, 0, rules.size());
+ }
+
+ @Test
+ public void testFormattingOnUndefinedCell() throws Exception {
+ wb = XSSFTestDataSamples.openSampleWorkbook("conditional_formatting_with_formula_on_second_sheet.xlsx");
+ formulaEval = new XSSFFormulaEvaluator(wb);
+ cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
+
+ sheet = wb.getSheet("Sales Plan");
+ getRulesFor(9,2);
+ assertNotEquals("No rules for " + ref, 0, rules.size());
+ assertEquals("wrong bg color for " + ref, "FFFFFF00", getColor(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()));
+ }
+
+ @Test
+ public void testRepeatedEval() throws Exception {
+ wb = XSSFTestDataSamples.openSampleWorkbook("test_conditional_formatting.xlsx");
+ formulaEval = new XSSFFormulaEvaluator(wb);
+ cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
+
+ sheet = wb.getSheetAt(0);
+ assertEquals("no rules should apply", 0, getRulesFor(2, 1).size());
+
+ assertEquals("no rules should apply", 0, getRulesFor(2, 1).size());
+
+ }
+
+ @Test
+ public void testCellValueIsWrongType() throws Exception {
+ wb = XSSFTestDataSamples.openSampleWorkbook("conditional_formatting_cell_is.xlsx");
+ formulaEval = new XSSFFormulaEvaluator(wb);
+ cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
+
+ sheet = wb.getSheetAt(1);
+
+ assertEquals("wrong # of matching rules", 1, getRulesFor(3, 1).size());
+ }
+
+ @Test
+ public void testRangeCondition() throws Exception {
+ wb = XSSFTestDataSamples.openSampleWorkbook("conditional_formatting_multiple_ranges.xlsx");
+ formulaEval = new XSSFFormulaEvaluator(wb);
+ cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
+
+ sheet = wb.getSheetAt(0);
+
+ assertEquals("wrong # of matching rules", 0, getRulesFor(0, 0).size());
+ assertEquals("wrong # of matching rules", 0, getRulesFor(1, 0).size());
+ assertEquals("wrong # of matching rules", 0, getRulesFor(2, 0).size());
+ assertEquals("wrong # of matching rules", 1, getRulesFor(3, 0).size());
+ assertEquals("wrong # of matching rules", 0, getRulesFor(0, 1).size());
+ assertEquals("wrong # of matching rules", 0, getRulesFor(1, 1).size());
+ assertEquals("wrong # of matching rules", 1, getRulesFor(2, 1).size());
+ assertEquals("wrong # of matching rules", 1, getRulesFor(3, 1).size());
+ assertEquals("wrong # of matching rules", 1, getRulesFor(0, 3).size());
+ assertEquals("wrong # of matching rules", 0, getRulesFor(1, 3).size());
+ assertEquals("wrong # of matching rules", 1, getRulesFor(2, 3).size());
+ assertEquals("wrong # of matching rules", 0, getRulesFor(0, 6).size());
+ assertEquals("wrong # of matching rules", 0, getRulesFor(3, 6).size());
+ assertEquals("wrong # of matching rules", 0, getRulesFor(2, 6).size());
+ }
+
+ private List<EvaluationConditionalFormatRule> getRulesFor(int row, int col) {
+ ref = new CellReference(sheet.getSheetName(), row, col, false, false);
+ return rules = cfe.getConditionalFormattingForCell(ref);
+ }
+
+ private String getColor(Color color) {
+ final XSSFColor c = XSSFColor.toXSSFColor(color);
+ return c.getARGBHex();
+ }
+
+ private double getTint(Color color) {
+ final XSSFColor c = XSSFColor.toXSSFColor(color);
+ return c.getTint();
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.usermodel;
+
+import static org.apache.poi.sl.tests.SLCommonUtils.xslfOnly;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hpsf.ClassIDPredefined;
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.poifs.crypt.CryptoFunctions;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.EntryUtils;
+import org.apache.poi.poifs.filesystem.Ole10Native;
+import org.apache.poi.poifs.filesystem.Ole10NativeException;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.sl.usermodel.AutoShape;
+import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.ss.extractor.EmbeddedData;
+import org.apache.poi.ss.extractor.EmbeddedExtractor;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.ObjectData;
+import org.apache.poi.ss.usermodel.Shape;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.usermodel.XSSFObjectData;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestEmbedOLEPackage {
+ private static byte[] samplePPT, samplePPTX, samplePNG;
+
+ private static final POIDataSamples ssamples = POIDataSamples.getSpreadSheetInstance();
+
+ @BeforeClass
+ public static void init() throws IOException, ReflectiveOperationException {
+ samplePPT = getSamplePPT(false);
+ samplePPTX = getSamplePPT(true);
+ samplePNG = ssamples.readFile("logoKarmokar4.png");
+ }
+
+ @Test
+ public void embedPDF() throws IOException {
+ try (InputStream is = ssamples.openResourceAsStream("bug64512_embed.xlsx");
+ XSSFWorkbook wb = new XSSFWorkbook(is)) {
+ List<XSSFObjectData> oleShapes = new ArrayList<>();
+ List<Ole10Native> ole10s = new ArrayList<>();
+ List<String> digests = new ArrayList<>();
+
+ final boolean digestMatch =
+ wb.getSheetAt(0).getDrawingPatriarch().getShapes().stream()
+ .map(s -> (XSSFObjectData)s)
+ .filter(oleShapes::add)
+ .map(TestEmbedOLEPackage::extractOle10Native)
+ .filter(ole10s::add)
+ .map(TestEmbedOLEPackage::digest)
+ .allMatch("FUJBVHTAZ0ly/TNDNmEj1gQ4a2TbZwDMVF4WUkDQLaM="::equals);
+
+ assertEquals(2, oleShapes.size());
+ assertEquals("Package", oleShapes.get(0).getOLE2ClassName());
+ assertEquals("Package2", oleShapes.get(1).getOLE2ClassName());
+ assertTrue(digestMatch);
+
+ final String expLabel = "Apache_POI_project_logo_(2018).pdf";
+ final String expFilenName = "C:\\Dell\\Apache_POI_project_logo_(2018).pdf";
+ final String expCmd1 = "C:\\Users\\KIWIWI~1\\AppData\\Local\\Temp\\{84287F34-B79C-4F3A-9A92-6BB664586F48}\\Apache_POI_project_logo_(2018).pdf";
+ final String expCmd2 = "C:\\Users\\KIWIWI~1\\AppData\\Local\\Temp\\{84287F34-B79C-4F3A-9A92-6BB664586F48}\\Apache_POI_project_logo_(2).pdf";
+
+ assertTrue(ole10s.stream().map(Ole10Native::getLabel).allMatch(expLabel::equals));
+ assertTrue(ole10s.stream().map(Ole10Native::getFileName).allMatch(expFilenName::equals));
+ assertEquals(expCmd1, ole10s.get(0).getCommand());
+ assertEquals(expCmd2, ole10s.get(1).getCommand());
+
+ for (Ole10Native o : ole10s) {
+ assertEquals(o.getLabel(), o.getLabel2());
+ assertEquals(o.getCommand(), o.getCommand2());
+ assertEquals(o.getFileName(), o.getFileName2());
+ }
+
+ Ole10Native scratch = new Ole10Native(expLabel, expFilenName, expCmd1, ole10s.get(0).getDataBuffer());
+ scratch.setLabel2(expLabel);
+ scratch.setFileName2(expFilenName);
+ scratch.setCommand2(expCmd1);
+
+ try (POIFSFileSystem scratchFS = new POIFSFileSystem();
+ POIFSFileSystem ole1FS = new POIFSFileSystem(new ByteArrayInputStream(oleShapes.get(0).getObjectData()))) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ scratch.writeOut(bos);
+ scratchFS.createDocument(new ByteArrayInputStream(bos.toByteArray()), Ole10Native.OLE10_NATIVE);
+ scratchFS.getRoot().setStorageClsid(ClassIDPredefined.OLE_V1_PACKAGE.getClassID());
+ assertTrue(EntryUtils.areDirectoriesIdentical(ole1FS.getRoot(), scratchFS.getRoot()));
+ }
+ }
+ }
+
+ private static Ole10Native extractOle10Native(XSSFObjectData objectData) {
+ try (InputStream is = objectData.getObjectPart().getInputStream();
+ POIFSFileSystem poifs = new POIFSFileSystem(is)) {
+ return Ole10Native.createFromEmbeddedOleObject(poifs);
+ } catch (IOException | Ole10NativeException e) {
+ throw new AssertionError(e.getMessage(), e);
+ }
+ }
+
+ private static String digest(Ole10Native ole10) {
+ MessageDigest sha = CryptoFunctions.getMessageDigest(HashAlgorithm.sha256);
+ byte[] digest = sha.digest(ole10.getDataBuffer());
+ return Base64.encodeBase64String(digest);
+ }
+
+ @Test
+ public void embedXSSF() throws IOException {
+ Workbook wb1 = new XSSFWorkbook();
+ addEmbeddedObjects(wb1);
+
+ Workbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1);
+ validateEmbeddedObjects(wb2);
+
+ wb2.close();
+ wb1.close();
+ }
+
+ @Test
+ public void embedHSSF() throws IOException {
+ assumeFalse(xslfOnly());
+
+ HSSFWorkbook wb1 = new HSSFWorkbook();
+ addEmbeddedObjects(wb1);
+ Workbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
+ validateEmbeddedObjects(wb2);
+
+ wb2.close();
+ wb1.close();
+ }
+
+ static void validateEmbeddedObjects(Workbook wb) throws IOException {
+ boolean ooxml = wb.getClass().getName().toLowerCase(Locale.ROOT).contains("xssf");
+ byte[] data = (ooxml) ? samplePPTX : samplePPT;
+ Iterator<Integer> shapeIds = Arrays.asList(1025,1026,2049).iterator();
+ EmbeddedExtractor ee = new EmbeddedExtractor();
+ for (Sheet sheet : wb) {
+ Drawing<? extends Shape> pat = sheet.getDrawingPatriarch();
+ for (Shape shape : pat) {
+ assertTrue(shape instanceof ObjectData);
+ ObjectData od = (ObjectData)shape;
+ EmbeddedData ed = ee.extractOne((DirectoryNode)od.getDirectory());
+ assertArrayEquals(data, ed.getEmbeddedData());
+ assertArrayEquals(samplePNG, od.getPictureData().getData());
+ assertEquals((int)shapeIds.next(), od.getShapeId());
+ }
+ }
+ }
+
+ static void addEmbeddedObjects(Workbook wb) throws IOException {
+ boolean ooxml = wb.getClass().getName().toLowerCase(Locale.ROOT).contains("xssf");
+ int picIdx = wb.addPicture(samplePNG, Workbook.PICTURE_TYPE_PNG);
+ byte[] data = (ooxml) ? samplePPTX : samplePPT;
+ String ext = (ooxml) ? ".pptx" : ".ppt";
+
+ int oleIdx1a = wb.addOlePackage(data, "dummy1a"+ext, "dummy1a"+ext, "dummy1a"+ext);
+ int oleIdx1b = wb.addOlePackage(data, "dummy1b"+ext, "dummy1b"+ext, "dummy1b"+ext);
+ int oleIdx2 = wb.addOlePackage(data, "dummy2"+ext, "dummy2"+ext, "dummy2"+ext);
+
+ Sheet sh1 = wb.createSheet();
+ Drawing<?> pat1 = sh1.createDrawingPatriarch();
+ ClientAnchor anchor1a = pat1.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
+ pat1.createObjectData(anchor1a, oleIdx1a, picIdx);
+ ClientAnchor anchor1b = pat1.createAnchor(0, 0, 0, 0, 1, 1+7, 3, 6+7);
+ pat1.createObjectData(anchor1b, oleIdx1b, picIdx);
+
+ Sheet sh2 = wb.createSheet();
+ Drawing<?> pat2 = sh2.createDrawingPatriarch();
+ ClientAnchor anchor2 = pat2.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
+ pat2.createObjectData(anchor2, oleIdx2, picIdx);
+ }
+
+ static byte[] getSamplePPT(boolean ooxml) throws IOException, ReflectiveOperationException {
+ SlideShow<?,?> ppt = (ooxml) ? new XMLSlideShow()
+ : (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
+ Slide<?,?> slide = ppt.createSlide();
+
+ AutoShape<?,?> sh1 = slide.createAutoShape();
+ sh1.setShapeType(ShapeType.STAR_32);
+ sh1.setAnchor(new java.awt.Rectangle(50, 50, 100, 200));
+ sh1.setFillColor(java.awt.Color.red);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ppt.write(bos);
+ ppt.close();
+
+ return bos.toByteArray();
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.usermodel;
+
+import org.apache.poi.ss.usermodel.BaseTestBorderStyle;
+import org.apache.poi.xssf.XSSFITestDataProvider;
+
+/**
+ * @author Yegor Kozlov
+ */
+public final class TestXSSFBorderStyle extends BaseTestBorderStyle {
+
+ public TestXSSFBorderStyle() {
+ super(XSSFITestDataProvider.instance);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * ====================================================================
+ * 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.ss.tests.usermodel;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.BaseTestRangeCopier;
+import org.apache.poi.ss.usermodel.CellCopyPolicy;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.xssf.XSSFITestDataProvider;
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.apache.poi.xssf.usermodel.XSSFRangeCopier;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestXSSFRangeCopier extends BaseTestRangeCopier {
+ public TestXSSFRangeCopier() {
+ super();
+ workbook = new XSSFWorkbook();
+ testDataProvider = XSSFITestDataProvider.instance;
+ }
+
+ @Before
+ public void init() {
+ workbook = XSSFTestDataSamples.openSampleWorkbook("tile-range-test.xlsx");
+ initSheets();
+ rangeCopier = new XSSFRangeCopier(sheet1, sheet1);
+ transSheetRangeCopier = new XSSFRangeCopier(sheet1, sheet2);
+ }
+
+ @After
+ public void shutdown() throws IOException {
+ workbook.close();
+ }
+
+ @Test // XSSF only. HSSF version wouldn't be so simple. And also this test is contained in following, more complex tests, so it's not really important.
+ public void copyRow() {
+ Row existingRow = sheet1.getRow(4);
+ XSSFRow newRow = (XSSFRow)sheet1.getRow(5);
+ CellCopyPolicy policy = new CellCopyPolicy();
+ newRow.copyRowFrom(existingRow, policy);
+ assertEquals("$C2+B$2", newRow.getCell(1).getCellFormula());
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.util;
+
+import org.apache.poi.ss.util.BaseTestCellUtil;
+import org.apache.poi.xssf.SXSSFITestDataProvider;
+
+public class TestSXSSFCellUtil extends BaseTestCellUtil {
+ public TestSXSSFCellUtil() {
+ super(SXSSFITestDataProvider.instance);
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.util;
+
+import org.apache.poi.ss.util.BaseTestCellUtil;
+import org.apache.poi.xssf.XSSFITestDataProvider;
+
+public class TestXSSFCellUtil extends BaseTestCellUtil {
+ public TestXSSFCellUtil() {
+ super(XSSFITestDataProvider.instance);
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.ss.tests.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.BorderExtent;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.PropertyTemplate;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+
+public class TestXSSFPropertyTemplate {
+
+ @Test
+ public void applyBorders() throws IOException {
+ CellRangeAddress a1c3 = new CellRangeAddress(0, 2, 0, 2);
+ CellRangeAddress b2 = new CellRangeAddress(1, 1, 1, 1);
+ PropertyTemplate pt = new PropertyTemplate();
+ Workbook wb = new XSSFWorkbook();
+ Sheet sheet = wb.createSheet();
+
+ pt.drawBorders(a1c3, BorderStyle.THIN, IndexedColors.RED.getIndex(), BorderExtent.ALL);
+ pt.applyBorders(sheet);
+
+ for (Row row: sheet) {
+ for (Cell cell: row) {
+ CellStyle cs = cell.getCellStyle();
+ assertEquals(BorderStyle.THIN, cs.getBorderTop());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getTopBorderColor());
+ assertEquals(BorderStyle.THIN, cs.getBorderBottom());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getBottomBorderColor());
+ assertEquals(BorderStyle.THIN, cs.getBorderLeft());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getLeftBorderColor());
+ assertEquals(BorderStyle.THIN, cs.getBorderRight());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getRightBorderColor());
+ }
+ }
+
+ pt.drawBorders(b2, BorderStyle.NONE, BorderExtent.ALL);
+ pt.applyBorders(sheet);
+
+ for (Row row: sheet) {
+ for (Cell cell: row) {
+ CellStyle cs = cell.getCellStyle();
+ if (cell.getColumnIndex() != 1 || row.getRowNum() == 0) {
+ assertEquals(BorderStyle.THIN, cs.getBorderTop());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getTopBorderColor());
+ } else {
+ assertEquals(BorderStyle.NONE, cs.getBorderTop());
+ }
+ if (cell.getColumnIndex() != 1 || row.getRowNum() == 2) {
+ assertEquals(BorderStyle.THIN, cs.getBorderBottom());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getBottomBorderColor());
+ } else {
+ assertEquals(BorderStyle.NONE, cs.getBorderBottom());
+ }
+ if (cell.getColumnIndex() == 0 || row.getRowNum() != 1) {
+ assertEquals(BorderStyle.THIN, cs.getBorderLeft());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getLeftBorderColor());
+ } else {
+ assertEquals(BorderStyle.NONE, cs.getBorderLeft());
+ }
+ if (cell.getColumnIndex() == 2 || row.getRowNum() != 1) {
+ assertEquals(BorderStyle.THIN, cs.getBorderRight());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getRightBorderColor());
+ } else {
+ assertEquals(BorderStyle.NONE, cs.getBorderRight());
+ }
+ }
+ }
+
+ wb.close();
+ }
+
+ @Test
+ public void clonePropertyTemplate() throws IOException {
+ CellRangeAddress a1c3 = new CellRangeAddress(0, 2, 0, 2);
+ PropertyTemplate pt = new PropertyTemplate();
+ pt.drawBorders(a1c3, BorderStyle.MEDIUM, IndexedColors.RED.getIndex(), BorderExtent.ALL);
+ PropertyTemplate pt2 = new PropertyTemplate(pt);
+ assertNotSame(pt2, pt);
+ for (int i = 0; i <= 2; i++) {
+ for (int j = 0; j <= 2; j++) {
+ assertEquals(4, pt2.getNumBorderColors(i, j));
+ assertEquals(4, pt2.getNumBorderColors(i, j));
+ }
+ }
+
+ CellRangeAddress b2 = new CellRangeAddress(1,1,1,1);
+ pt2.drawBorders(b2, BorderStyle.THIN, BorderExtent.ALL);
+
+ Workbook wb = new XSSFWorkbook();
+ Sheet sheet = wb.createSheet();
+ pt.applyBorders(sheet);
+
+ for (Row row : sheet) {
+ for (Cell cell : row) {
+ CellStyle cs = cell.getCellStyle();
+ assertEquals(BorderStyle.MEDIUM, cs.getBorderTop());
+ assertEquals(BorderStyle.MEDIUM, cs.getBorderBottom());
+ assertEquals(BorderStyle.MEDIUM, cs.getBorderLeft());
+ assertEquals(BorderStyle.MEDIUM, cs.getBorderRight());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getTopBorderColor());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getBottomBorderColor());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getLeftBorderColor());
+ assertEquals(IndexedColors.RED.getIndex(), cs.getRightBorderColor());
+ }
+ }
+
+ wb.close();
+ }
+}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.ss.usermodel;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.xssf.streaming.SXSSFCell;
-import org.apache.poi.xssf.usermodel.XSSFCell;
-import org.junit.Test;
-
-/**
- * Class for combined testing of XML-specific functionality of
- * {@link XSSFCell} and {@link SXSSFCell}.
- *
- * Any test that is applicable for {@link HSSFCell} as well should go into
- * the common base class {@link BaseTestCell}.
- */
-public abstract class BaseTestXCell extends BaseTestCell {
- protected BaseTestXCell(ITestDataProvider testDataProvider) {
- super(testDataProvider);
- }
-
- @Test
- public void testXmlEncoding() throws IOException {
- Workbook wb1 = _testDataProvider.createWorkbook();
- Sheet sh = wb1.createSheet();
- Row row = sh.createRow(0);
- Cell cell = row.createCell(0);
- String sval = "\u0000\u0002\u0012<>\t\n\u00a0 &\"POI'\u2122";
- cell.setCellValue(sval);
-
- Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
- wb1.close();
-
- // invalid characters are replaced with question marks
- assertEquals("???<>\t\n\u00a0 &\"POI'\u2122", wb2.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
- wb2.close();
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.usermodel;
-
-import java.io.IOException;
-
-import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.xssf.streaming.SXSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.junit.Test;
-
-/**
- * Class for combined testing of XML-specific functionality of
- * {@link XSSFRow} and {@link SXSSFRow}.
- *
- * Any test that is applicable for {@link org.apache.poi.hssf.usermodel.HSSFRow} as well should go into
- * the common base class {@link BaseTestRow}.
- */
-public abstract class BaseTestXRow extends BaseTestRow {
- protected BaseTestXRow(ITestDataProvider testDataProvider) {
- super(testDataProvider);
- }
-
- @Test
- public void testRowBounds() throws IOException {
- baseTestRowBounds(_testDataProvider.getSpreadsheetVersion().getLastRowIndex());
- }
-
- @Test
- public void testCellBounds() throws IOException {
- baseTestCellBounds(_testDataProvider.getSpreadsheetVersion().getLastColumnIndex());
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.usermodel;
-
-import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.xssf.streaming.SXSSFSheet;
-import org.apache.poi.xssf.usermodel.XSSFSheet;
-
-/**
- * Class for combined testing of XML-specific functionality of
- * {@link XSSFSheet} and {@link SXSSFSheet}.
- *
- * Any test that is applicable for {@link org.apache.poi.hssf.usermodel.HSSFSheet} as well should go into
- * the common base class {@link BaseTestSheet}.
- */
-public abstract class BaseTestXSheet extends BaseTestSheet {
- protected BaseTestXSheet(ITestDataProvider testDataProvider) {
- super(testDataProvider);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.usermodel;
-
-import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-
-/**
- * Class for combined testing of XML-specific functionality of
- * {@link XSSFWorkbook} and {@link SXSSFWorkbook}.
- *
- * Any test that is applicable for {@link org.apache.poi.hssf.usermodel.HSSFWorkbook} as well should go into
- * the common base class {@link BaseTestWorkbook}.
- */
-public abstract class BaseTestXWorkbook extends BaseTestWorkbook {
- protected BaseTestXWorkbook(ITestDataProvider testDataProvider) {
- super(testDataProvider);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.usermodel;
-
-
-import java.io.IOException;
-import java.util.Date;
-import java.util.List;
-
-import org.apache.poi.ss.formula.ConditionalFormattingEvaluator;
-import org.apache.poi.ss.formula.EvaluationConditionalFormatRule;
-import org.apache.poi.ss.formula.eval.NotImplementedException;
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.apache.poi.xssf.usermodel.XSSFColor;
-import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class ConditionalFormattingEvalTest {
-
- private XSSFWorkbook wb;
- private Sheet sheet;
- private XSSFFormulaEvaluator formulaEval;
- private ConditionalFormattingEvaluator cfe;
- private CellReference ref;
- private List<EvaluationConditionalFormatRule> rules;
-
- @Before
- public void openWB() {
- wb = XSSFTestDataSamples.openSampleWorkbook("ConditionalFormattingSamples.xlsx");
- formulaEval = new XSSFFormulaEvaluator(wb);
- cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
- }
-
- @After
- public void closeWB() {
- formulaEval = null;
- cfe = null;
- ref = null;
- rules = null;
- try {
- if (wb != null) wb.close();
- } catch (IOException e) {
- // keep going, this shouldn't cancel things
- e.printStackTrace();
- }
- }
-
- @Test
- public void testFormattingEvaluation() {
- sheet = wb.getSheet("Products1");
-
- getRulesFor(12, 1);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
- assertEquals("wrong bg color for " + ref, "FFFFEB9C", getColor(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()));
- assertFalse("should not be italic " + ref, rules.get(0).getRule().getFontFormatting().isItalic());
-
- getRulesFor(16, 3);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
- assertEquals("wrong bg color for " + ref, 0.7999816888943144d, getTint(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()), 0.000000000000001);
-
- getRulesFor(12, 3);
- assertEquals("wrong # of rules for " + ref, 0, rules.size());
-
- sheet = wb.getSheet("Products2");
-
- getRulesFor(15,1);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
- assertEquals("wrong bg color for " + ref, "FFFFEB9C", getColor(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()));
-
- getRulesFor(20,3);
- assertEquals("wrong # of rules for " + ref, 0, rules.size());
-
- // now change a cell value that's an input for the rules
- Cell cell = sheet.getRow(1).getCell(6);
- cell.setCellValue("Dairy");
- formulaEval.notifyUpdateCell(cell);
- cell = sheet.getRow(4).getCell(6);
- cell.setCellValue(500);
- formulaEval.notifyUpdateCell(cell);
- // need to throw away all evaluations, since we don't know how value changes may have affected format formulas
- cfe.clearAllCachedValues();
-
- // test that the conditional validation evaluations changed
- getRulesFor(15,1);
- assertEquals("wrong # of rules for " + ref, 0, rules.size());
-
- getRulesFor(20,3);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
- assertEquals("wrong bg color for " + ref, 0.7999816888943144d, getTint(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()), 0.000000000000001);
-
- getRulesFor(20,1);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
- assertEquals("wrong bg color for " + ref, "FFFFEB9C", getColor(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()));
-
- sheet = wb.getSheet("Book tour");
-
- getRulesFor(8,2);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
-
- sheet = wb.getSheet("Compare to totals");
- getRulesFor(3, 2);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
- assertEquals("wrong fg color for " + ref, "FFFF0000", getColor(rules.get(0).getRule().getFontFormatting().getFontColor()));
- getRulesFor(3, 3);
- assertEquals("wrong # of rules for " + ref, 0, rules.size());
- getRulesFor(15, 4);
- assertEquals("wrong # of rules for " + ref, 0, rules.size());
- getRulesFor(16, 1);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
- assertEquals("wrong fg color for " + ref, "FFFF0000", getColor(rules.get(0).getRule().getFontFormatting().getFontColor()));
-
- sheet = wb.getSheet("Products3");
- sheet.getRow(8).getCell(0).setCellValue(new Date());
- getRulesFor(8, 0);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
- getRulesFor(8, 3);
- assertEquals("wrong # of rules for " + ref, 1, rules.size());
-
- sheet = wb.getSheet("Customers2");
- getRulesFor(3, 0);
- assertEquals("wrong # of rules for " + ref, 0, rules.size());
- }
-
- @Test
- public void testFormattingOnUndefinedCell() throws Exception {
- wb = XSSFTestDataSamples.openSampleWorkbook("conditional_formatting_with_formula_on_second_sheet.xlsx");
- formulaEval = new XSSFFormulaEvaluator(wb);
- cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
-
- sheet = wb.getSheet("Sales Plan");
- getRulesFor(9,2);
- assertNotEquals("No rules for " + ref, 0, rules.size());
- assertEquals("wrong bg color for " + ref, "FFFFFF00", getColor(rules.get(0).getRule().getPatternFormatting().getFillBackgroundColorColor()));
- }
-
- @Test
- public void testRepeatedEval() throws Exception {
- wb = XSSFTestDataSamples.openSampleWorkbook("test_conditional_formatting.xlsx");
- formulaEval = new XSSFFormulaEvaluator(wb);
- cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
-
- sheet = wb.getSheetAt(0);
- assertEquals("no rules should apply", 0, getRulesFor(2, 1).size());
-
- assertEquals("no rules should apply", 0, getRulesFor(2, 1).size());
-
- }
-
- @Test
- public void testCellValueIsWrongType() throws Exception {
- wb = XSSFTestDataSamples.openSampleWorkbook("conditional_formatting_cell_is.xlsx");
- formulaEval = new XSSFFormulaEvaluator(wb);
- cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
-
- sheet = wb.getSheetAt(1);
-
- assertEquals("wrong # of matching rules", 1, getRulesFor(3, 1).size());
- }
-
- @Test
- public void testRangeCondition() throws Exception {
- wb = XSSFTestDataSamples.openSampleWorkbook("conditional_formatting_multiple_ranges.xlsx");
- formulaEval = new XSSFFormulaEvaluator(wb);
- cfe = new ConditionalFormattingEvaluator(wb, formulaEval);
-
- sheet = wb.getSheetAt(0);
-
- assertEquals("wrong # of matching rules", 0, getRulesFor(0, 0).size());
- assertEquals("wrong # of matching rules", 0, getRulesFor(1, 0).size());
- assertEquals("wrong # of matching rules", 0, getRulesFor(2, 0).size());
- assertEquals("wrong # of matching rules", 1, getRulesFor(3, 0).size());
- assertEquals("wrong # of matching rules", 0, getRulesFor(0, 1).size());
- assertEquals("wrong # of matching rules", 0, getRulesFor(1, 1).size());
- assertEquals("wrong # of matching rules", 1, getRulesFor(2, 1).size());
- assertEquals("wrong # of matching rules", 1, getRulesFor(3, 1).size());
- assertEquals("wrong # of matching rules", 1, getRulesFor(0, 3).size());
- assertEquals("wrong # of matching rules", 0, getRulesFor(1, 3).size());
- assertEquals("wrong # of matching rules", 1, getRulesFor(2, 3).size());
- assertEquals("wrong # of matching rules", 0, getRulesFor(0, 6).size());
- assertEquals("wrong # of matching rules", 0, getRulesFor(3, 6).size());
- assertEquals("wrong # of matching rules", 0, getRulesFor(2, 6).size());
- }
-
- private List<EvaluationConditionalFormatRule> getRulesFor(int row, int col) {
- ref = new CellReference(sheet.getSheetName(), row, col, false, false);
- return rules = cfe.getConditionalFormattingForCell(ref);
- }
-
- private String getColor(Color color) {
- final XSSFColor c = XSSFColor.toXSSFColor(color);
- return c.getARGBHex();
- }
-
- private double getTint(Color color) {
- final XSSFColor c = XSSFColor.toXSSFColor(color);
- return c.getTint();
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.usermodel;
-
-import static org.apache.poi.sl.SLCommonUtils.xslfOnly;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.hpsf.ClassIDPredefined;
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.poifs.crypt.CryptoFunctions;
-import org.apache.poi.poifs.crypt.HashAlgorithm;
-import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.poifs.filesystem.EntryUtils;
-import org.apache.poi.poifs.filesystem.Ole10Native;
-import org.apache.poi.poifs.filesystem.Ole10NativeException;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.sl.usermodel.AutoShape;
-import org.apache.poi.sl.usermodel.ShapeType;
-import org.apache.poi.sl.usermodel.Slide;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.ss.extractor.EmbeddedData;
-import org.apache.poi.ss.extractor.EmbeddedExtractor;
-import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.apache.poi.xssf.usermodel.XSSFObjectData;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class TestEmbedOLEPackage {
- private static byte[] samplePPT, samplePPTX, samplePNG;
-
- private static final POIDataSamples ssamples = POIDataSamples.getSpreadSheetInstance();
-
- @BeforeClass
- public static void init() throws IOException, ReflectiveOperationException {
- samplePPT = getSamplePPT(false);
- samplePPTX = getSamplePPT(true);
- samplePNG = ssamples.readFile("logoKarmokar4.png");
- }
-
- @Test
- public void embedPDF() throws IOException {
- try (InputStream is = ssamples.openResourceAsStream("bug64512_embed.xlsx");
- XSSFWorkbook wb = new XSSFWorkbook(is)) {
- List<XSSFObjectData> oleShapes = new ArrayList<>();
- List<Ole10Native> ole10s = new ArrayList<>();
- List<String> digests = new ArrayList<>();
-
- final boolean digestMatch =
- wb.getSheetAt(0).getDrawingPatriarch().getShapes().stream()
- .map(s -> (XSSFObjectData)s)
- .filter(oleShapes::add)
- .map(TestEmbedOLEPackage::extractOle10Native)
- .filter(ole10s::add)
- .map(TestEmbedOLEPackage::digest)
- .allMatch("FUJBVHTAZ0ly/TNDNmEj1gQ4a2TbZwDMVF4WUkDQLaM="::equals);
-
- assertEquals(2, oleShapes.size());
- assertEquals("Package", oleShapes.get(0).getOLE2ClassName());
- assertEquals("Package2", oleShapes.get(1).getOLE2ClassName());
- assertTrue(digestMatch);
-
- final String expLabel = "Apache_POI_project_logo_(2018).pdf";
- final String expFilenName = "C:\\Dell\\Apache_POI_project_logo_(2018).pdf";
- final String expCmd1 = "C:\\Users\\KIWIWI~1\\AppData\\Local\\Temp\\{84287F34-B79C-4F3A-9A92-6BB664586F48}\\Apache_POI_project_logo_(2018).pdf";
- final String expCmd2 = "C:\\Users\\KIWIWI~1\\AppData\\Local\\Temp\\{84287F34-B79C-4F3A-9A92-6BB664586F48}\\Apache_POI_project_logo_(2).pdf";
-
- assertTrue(ole10s.stream().map(Ole10Native::getLabel).allMatch(expLabel::equals));
- assertTrue(ole10s.stream().map(Ole10Native::getFileName).allMatch(expFilenName::equals));
- assertEquals(expCmd1, ole10s.get(0).getCommand());
- assertEquals(expCmd2, ole10s.get(1).getCommand());
-
- for (Ole10Native o : ole10s) {
- assertEquals(o.getLabel(), o.getLabel2());
- assertEquals(o.getCommand(), o.getCommand2());
- assertEquals(o.getFileName(), o.getFileName2());
- }
-
- Ole10Native scratch = new Ole10Native(expLabel, expFilenName, expCmd1, ole10s.get(0).getDataBuffer());
- scratch.setLabel2(expLabel);
- scratch.setFileName2(expFilenName);
- scratch.setCommand2(expCmd1);
-
- try (POIFSFileSystem scratchFS = new POIFSFileSystem();
- POIFSFileSystem ole1FS = new POIFSFileSystem(new ByteArrayInputStream(oleShapes.get(0).getObjectData()))) {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- scratch.writeOut(bos);
- scratchFS.createDocument(new ByteArrayInputStream(bos.toByteArray()), Ole10Native.OLE10_NATIVE);
- scratchFS.getRoot().setStorageClsid(ClassIDPredefined.OLE_V1_PACKAGE.getClassID());
- assertTrue(EntryUtils.areDirectoriesIdentical(ole1FS.getRoot(), scratchFS.getRoot()));
- }
- }
- }
-
- private static Ole10Native extractOle10Native(XSSFObjectData objectData) {
- try (InputStream is = objectData.getObjectPart().getInputStream();
- POIFSFileSystem poifs = new POIFSFileSystem(is)) {
- return Ole10Native.createFromEmbeddedOleObject(poifs);
- } catch (IOException | Ole10NativeException e) {
- throw new AssertionError(e.getMessage(), e);
- }
- }
-
- private static String digest(Ole10Native ole10) {
- MessageDigest sha = CryptoFunctions.getMessageDigest(HashAlgorithm.sha256);
- byte[] digest = sha.digest(ole10.getDataBuffer());
- return Base64.encodeBase64String(digest);
- }
-
- @Test
- public void embedXSSF() throws IOException {
- Workbook wb1 = new XSSFWorkbook();
- addEmbeddedObjects(wb1);
-
- Workbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1);
- validateEmbeddedObjects(wb2);
-
- wb2.close();
- wb1.close();
- }
-
- @Test
- public void embedHSSF() throws IOException {
- assumeFalse(xslfOnly());
-
- HSSFWorkbook wb1 = new HSSFWorkbook();
- addEmbeddedObjects(wb1);
- Workbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
- validateEmbeddedObjects(wb2);
-
- wb2.close();
- wb1.close();
- }
-
- static void validateEmbeddedObjects(Workbook wb) throws IOException {
- boolean ooxml = wb.getClass().getName().toLowerCase(Locale.ROOT).contains("xssf");
- byte[] data = (ooxml) ? samplePPTX : samplePPT;
- Iterator<Integer> shapeIds = Arrays.asList(1025,1026,2049).iterator();
- EmbeddedExtractor ee = new EmbeddedExtractor();
- for (Sheet sheet : wb) {
- Drawing<? extends Shape> pat = sheet.getDrawingPatriarch();
- for (Shape shape : pat) {
- assertTrue(shape instanceof ObjectData);
- ObjectData od = (ObjectData)shape;
- EmbeddedData ed = ee.extractOne((DirectoryNode)od.getDirectory());
- assertArrayEquals(data, ed.getEmbeddedData());
- assertArrayEquals(samplePNG, od.getPictureData().getData());
- assertEquals((int)shapeIds.next(), od.getShapeId());
- }
- }
- }
-
- static void addEmbeddedObjects(Workbook wb) throws IOException {
- boolean ooxml = wb.getClass().getName().toLowerCase(Locale.ROOT).contains("xssf");
- int picIdx = wb.addPicture(samplePNG, Workbook.PICTURE_TYPE_PNG);
- byte[] data = (ooxml) ? samplePPTX : samplePPT;
- String ext = (ooxml) ? ".pptx" : ".ppt";
-
- int oleIdx1a = wb.addOlePackage(data, "dummy1a"+ext, "dummy1a"+ext, "dummy1a"+ext);
- int oleIdx1b = wb.addOlePackage(data, "dummy1b"+ext, "dummy1b"+ext, "dummy1b"+ext);
- int oleIdx2 = wb.addOlePackage(data, "dummy2"+ext, "dummy2"+ext, "dummy2"+ext);
-
- Sheet sh1 = wb.createSheet();
- Drawing<?> pat1 = sh1.createDrawingPatriarch();
- ClientAnchor anchor1a = pat1.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
- pat1.createObjectData(anchor1a, oleIdx1a, picIdx);
- ClientAnchor anchor1b = pat1.createAnchor(0, 0, 0, 0, 1, 1+7, 3, 6+7);
- pat1.createObjectData(anchor1b, oleIdx1b, picIdx);
-
- Sheet sh2 = wb.createSheet();
- Drawing<?> pat2 = sh2.createDrawingPatriarch();
- ClientAnchor anchor2 = pat2.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
- pat2.createObjectData(anchor2, oleIdx2, picIdx);
- }
-
- static byte[] getSamplePPT(boolean ooxml) throws IOException, ReflectiveOperationException {
- SlideShow<?,?> ppt = (ooxml) ? new XMLSlideShow()
- : (SlideShow<?,?>)Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow").newInstance();
- Slide<?,?> slide = ppt.createSlide();
-
- AutoShape<?,?> sh1 = slide.createAutoShape();
- sh1.setShapeType(ShapeType.STAR_32);
- sh1.setAnchor(new java.awt.Rectangle(50, 50, 100, 200));
- sh1.setFillColor(java.awt.Color.red);
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ppt.write(bos);
- ppt.close();
-
- return bos.toByteArray();
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.usermodel;
-
-import org.apache.poi.xssf.XSSFITestDataProvider;
-
-/**
- * @author Yegor Kozlov
- */
-public final class TestXSSFBorderStyle extends BaseTestBorderStyle {
-
- public TestXSSFBorderStyle() {
- super(XSSFITestDataProvider.instance);
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.usermodel;
-
-import static org.junit.Assert.assertEquals;
-
-import org.apache.poi.xssf.XSSFITestDataProvider;
-import org.apache.poi.xssf.XSSFTestDataSamples;
-import org.apache.poi.xssf.usermodel.XSSFRangeCopier;
-import org.apache.poi.xssf.usermodel.XSSFRow;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.IOException;
-
-public class TestXSSFRangeCopier extends TestRangeCopier {
- public TestXSSFRangeCopier() {
- super();
- workbook = new XSSFWorkbook();
- testDataProvider = XSSFITestDataProvider.instance;
- }
-
- @Before
- public void init() {
- workbook = XSSFTestDataSamples.openSampleWorkbook("tile-range-test.xlsx");
- initSheets();
- rangeCopier = new XSSFRangeCopier(sheet1, sheet1);
- transSheetRangeCopier = new XSSFRangeCopier(sheet1, sheet2);
- }
-
- @After
- public void shutdown() throws IOException {
- workbook.close();
- }
-
- @Test // XSSF only. HSSF version wouldn't be so simple. And also this test is contained in following, more complex tests, so it's not really important.
- public void copyRow() {
- Row existingRow = sheet1.getRow(4);
- XSSFRow newRow = (XSSFRow)sheet1.getRow(5);
- CellCopyPolicy policy = new CellCopyPolicy();
- newRow.copyRowFrom(existingRow, policy);
- assertEquals("$C2+B$2", newRow.getCell(1).getCellFormula());
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.ss.util;
-
-import org.apache.poi.xssf.SXSSFITestDataProvider;
-
-public class TestSXSSFCellUtil extends BaseTestCellUtil {
- public TestSXSSFCellUtil() {
- super(SXSSFITestDataProvider.instance);
- }
-}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.ss.util;
-
-import org.apache.poi.xssf.XSSFITestDataProvider;
-
-public class TestXSSFCellUtil extends BaseTestCellUtil {
- public TestXSSFCellUtil() {
- super(XSSFITestDataProvider.instance);
- }
-}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.ss.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
-
-import java.io.IOException;
-
-import org.apache.poi.ss.usermodel.BorderExtent;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.junit.Test;
-
-public class TestXSSFPropertyTemplate {
-
- @Test
- public void applyBorders() throws IOException {
- CellRangeAddress a1c3 = new CellRangeAddress(0, 2, 0, 2);
- CellRangeAddress b2 = new CellRangeAddress(1, 1, 1, 1);
- PropertyTemplate pt = new PropertyTemplate();
- Workbook wb = new XSSFWorkbook();
- Sheet sheet = wb.createSheet();
-
- pt.drawBorders(a1c3, BorderStyle.THIN, IndexedColors.RED.getIndex(), BorderExtent.ALL);
- pt.applyBorders(sheet);
-
- for (Row row: sheet) {
- for (Cell cell: row) {
- CellStyle cs = cell.getCellStyle();
- assertEquals(BorderStyle.THIN, cs.getBorderTop());
- assertEquals(IndexedColors.RED.getIndex(), cs.getTopBorderColor());
- assertEquals(BorderStyle.THIN, cs.getBorderBottom());
- assertEquals(IndexedColors.RED.getIndex(), cs.getBottomBorderColor());
- assertEquals(BorderStyle.THIN, cs.getBorderLeft());
- assertEquals(IndexedColors.RED.getIndex(), cs.getLeftBorderColor());
- assertEquals(BorderStyle.THIN, cs.getBorderRight());
- assertEquals(IndexedColors.RED.getIndex(), cs.getRightBorderColor());
- }
- }
-
- pt.drawBorders(b2, BorderStyle.NONE, BorderExtent.ALL);
- pt.applyBorders(sheet);
-
- for (Row row: sheet) {
- for (Cell cell: row) {
- CellStyle cs = cell.getCellStyle();
- if (cell.getColumnIndex() != 1 || row.getRowNum() == 0) {
- assertEquals(BorderStyle.THIN, cs.getBorderTop());
- assertEquals(IndexedColors.RED.getIndex(), cs.getTopBorderColor());
- } else {
- assertEquals(BorderStyle.NONE, cs.getBorderTop());
- }
- if (cell.getColumnIndex() != 1 || row.getRowNum() == 2) {
- assertEquals(BorderStyle.THIN, cs.getBorderBottom());
- assertEquals(IndexedColors.RED.getIndex(), cs.getBottomBorderColor());
- } else {
- assertEquals(BorderStyle.NONE, cs.getBorderBottom());
- }
- if (cell.getColumnIndex() == 0 || row.getRowNum() != 1) {
- assertEquals(BorderStyle.THIN, cs.getBorderLeft());
- assertEquals(IndexedColors.RED.getIndex(), cs.getLeftBorderColor());
- } else {
- assertEquals(BorderStyle.NONE, cs.getBorderLeft());
- }
- if (cell.getColumnIndex() == 2 || row.getRowNum() != 1) {
- assertEquals(BorderStyle.THIN, cs.getBorderRight());
- assertEquals(IndexedColors.RED.getIndex(), cs.getRightBorderColor());
- } else {
- assertEquals(BorderStyle.NONE, cs.getBorderRight());
- }
- }
- }
-
- wb.close();
- }
-
- @Test
- public void clonePropertyTemplate() throws IOException {
- CellRangeAddress a1c3 = new CellRangeAddress(0, 2, 0, 2);
- PropertyTemplate pt = new PropertyTemplate();
- pt.drawBorders(a1c3, BorderStyle.MEDIUM, IndexedColors.RED.getIndex(), BorderExtent.ALL);
- PropertyTemplate pt2 = new PropertyTemplate(pt);
- assertNotSame(pt2, pt);
- for (int i = 0; i <= 2; i++) {
- for (int j = 0; j <= 2; j++) {
- assertEquals(4, pt2.getNumBorderColors(i, j));
- assertEquals(4, pt2.getNumBorderColors(i, j));
- }
- }
-
- CellRangeAddress b2 = new CellRangeAddress(1,1,1,1);
- pt2.drawBorders(b2, BorderStyle.THIN, BorderExtent.ALL);
-
- Workbook wb = new XSSFWorkbook();
- Sheet sheet = wb.createSheet();
- pt.applyBorders(sheet);
-
- for (Row row : sheet) {
- for (Cell cell : row) {
- CellStyle cs = cell.getCellStyle();
- assertEquals(BorderStyle.MEDIUM, cs.getBorderTop());
- assertEquals(BorderStyle.MEDIUM, cs.getBorderBottom());
- assertEquals(BorderStyle.MEDIUM, cs.getBorderLeft());
- assertEquals(BorderStyle.MEDIUM, cs.getBorderRight());
- assertEquals(IndexedColors.RED.getIndex(), cs.getTopBorderColor());
- assertEquals(IndexedColors.RED.getIndex(), cs.getBottomBorderColor());
- assertEquals(IndexedColors.RED.getIndex(), cs.getLeftBorderColor());
- assertEquals(IndexedColors.RED.getIndex(), cs.getRightBorderColor());
- }
- }
-
- wb.close();
- }
-}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import org.apache.poi.ooxml.util.IdentifierManager;
-import org.junit.Test;
-
-public class TestIdentifierManager {
- @Test
- public void testBasic()
- {
- IdentifierManager manager = new IdentifierManager(0L,100L);
- assertEquals(101L,manager.getRemainingIdentifiers());
- assertEquals(0L,manager.reserveNew());
- assertEquals(100L,manager.getRemainingIdentifiers());
- assertEquals(1L,manager.reserve(0L));
- assertEquals(99L,manager.getRemainingIdentifiers());
- }
-
- @Test
- public void testLongLimits() {
- long min = IdentifierManager.MIN_ID;
- long max = IdentifierManager.MAX_ID;
- IdentifierManager manager = new IdentifierManager(min,max);
- assertTrue("Limits lead to a long variable overflow", max - min + 1 > 0);
- assertTrue("Limits lead to a long variable overflow", manager.getRemainingIdentifiers() > 0);
- assertEquals(min,manager.reserveNew());
- assertEquals(max,manager.reserve(max));
- assertEquals(max - min -1, manager.getRemainingIdentifiers());
- manager.release(max);
- manager.release(min);
- }
-
- @Test
- public void testReserve() {
- IdentifierManager manager = new IdentifierManager(10L,30L);
- assertEquals(12L,manager.reserve(12L));
- long reserve = manager.reserve(12L);
- assertNotEquals("Same id must be reserved twice!", 12L, reserve);
- assertTrue(manager.release(12L));
- assertTrue(manager.release(reserve));
- assertFalse(manager.release(12L));
- assertFalse(manager.release(reserve));
-
- manager = new IdentifierManager(0L,2L);
- assertEquals(0L,manager.reserve(0L));
- assertEquals(1L,manager.reserve(1L));
- assertEquals(2L,manager.reserve(2L));
- try {
- manager.reserve(0L);
- fail("Exception expected");
- } catch(IllegalStateException e) {
- // expected
- }
- try {
- manager.reserve(1L);
- fail("Exception expected");
- } catch(IllegalStateException e) {
- // expected
- }
- try {
- manager.reserve(2L);
- fail("Exception expected");
- } catch(IllegalStateException e) {
- // expected
- }
- }
-
- @Test
- public void testReserveNew() {
- IdentifierManager manager = new IdentifierManager(10L,12L);
- assertSame(10L,manager.reserveNew());
- assertSame(11L,manager.reserveNew());
- assertSame(12L,manager.reserveNew());
- try {
- manager.reserveNew();
- fail("IllegalStateException expected");
- } catch (IllegalStateException e) {
- // expected
- }
- }
-
- @Test
- public void testRelease() {
- IdentifierManager manager = new IdentifierManager(10L,20L);
- assertEquals(10L,manager.reserve(10L));
- assertEquals(11L,manager.reserve(11L));
- assertEquals(12L,manager.reserve(12L));
- assertEquals(13L,manager.reserve(13L));
- assertEquals(14L,manager.reserve(14L));
-
- assertTrue(manager.release(10L));
- assertEquals(10L,manager.reserve(10L));
- assertTrue(manager.release(10L));
-
- assertTrue(manager.release(11L));
- assertEquals(11L,manager.reserve(11L));
- assertTrue(manager.release(11L));
- assertFalse(manager.release(11L));
- assertFalse(manager.release(10L));
-
- assertEquals(10L,manager.reserve(10L));
- assertEquals(11L,manager.reserve(11L));
- assertTrue(manager.release(12L));
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.util;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.xssf.streaming.SXSSFSheet;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import static org.apache.poi.util.DefaultTempFileCreationStrategy.POIFILES;
-import static org.apache.poi.util.TempFile.JAVA_IO_TMPDIR;
-import static org.junit.Assert.assertEquals;
-
-public class TestTempFileThreaded {
- private static final int NUMBER_OF_THREADS = 10;
- private static final int NUMBER_OF_TESTS = 200;
-
- private volatile Throwable exception;
- private int[] executions;
-
- // the actual thread-safe temp-file strategy
- private static TempFileCreationStrategy createTempFileCreationStrategy(File poiTempFileDirectory) {
- return new TempFileCreationStrategy() {
- @Override
- public File createTempFile(String prefix, String suffix) throws IOException {
- long threadId = Thread.currentThread().getId();
- File threadDir = new File(poiTempFileDirectory, Long.toString(threadId));
- if (!threadDir.exists()) {
- if (!threadDir.mkdirs()) {
- throw new IOException("mkdir of " + threadDir + " failed");
- }
- }
-
- File file = File.createTempFile(prefix, suffix, threadDir);
- file.deleteOnExit();
- return file;
- }
-
- @Override
- public File createTempDirectory(String prefix) {
- throw new UnsupportedOperationException("createTempDirectory");
- }
- };
- }
-
- @BeforeClass
- public static void setUpClass() throws IOException {
- String tmpDir = System.getProperty(JAVA_IO_TMPDIR);
- if (tmpDir == null) {
- throw new IOException("Systems temporary directory not defined - set the -D" + JAVA_IO_TMPDIR + " jvm property!");
- }
-
- TempFile.setTempFileCreationStrategy(createTempFileCreationStrategy(new File(new File(tmpDir, POIFILES), "TestTempFileThreaded")));
- }
-
- @Before
- public void setUp() {
- // Initialize array to allow to summarize afterwards
- executions = new int[NUMBER_OF_THREADS];
- }
-
- @Test
- public void runTest() throws Throwable {
- List<Thread> threads = new LinkedList<>();
-
- // start all threads
- for (int i = 0; i < NUMBER_OF_THREADS; i++) {
- Thread t = startThread(i, new TestRunnable());
- threads.add(t);
- }
-
- // wait for all threads
- for (int i = 0; i < NUMBER_OF_THREADS; i++) {
- threads.get(i).join();
- }
-
- // report exceptions if there were any
- if (exception != null) {
- throw exception;
- }
-
- // make sure the resulting number of executions is correct
- for (int i = 0; i < NUMBER_OF_THREADS; i++) {
- // check if enough items were performed
- assertEquals("Thread " + i
- + " did not execute all iterations", NUMBER_OF_TESTS,
- executions[i]);
- }
- }
-
- private static class TestRunnable {
- Map<Integer, List<File>> files = new HashMap<>();
-
- public TestRunnable() {
- for (int i = 0; i < NUMBER_OF_THREADS; i++) {
- files.put(i, new ArrayList<>());
- }
- }
-
- public void doEnd(int threadNum) {
- for (File file : files.get(threadNum)) {
- if (!file.exists()) {
- throw new IllegalStateException("File " + file + " does not exist");
- }
- if (!file.delete()) {
- throw new IllegalStateException("Deletion of " + file + " failed");
- }
- }
- }
-
- public void run(int threadNum, int iter) throws Exception {
- try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
- SXSSFSheet sheet = wb.createSheet("test");
-
- for (int i = 0; i < 100; i++) {
- Row row = sheet.createRow(i);
- for (int j = 0; j < 10; j++) {
- Cell cell = row.createCell(j);
- cell.setCellValue("123");
- }
- }
-
- File file = TempFile.createTempFile("TestTempFile-" + threadNum + "-" + iter + "-", ".xlsx");
- try (OutputStream outputStream = new FileOutputStream(file)) {
- wb.write(outputStream);
- }
-
- files.get(threadNum).add(file);
-
- if (iter % 30 == 0) {
- System.out.println("thread: " + threadNum + ", iter: " + iter + ": " + file);
- }
- }
- }
- }
-
- private Thread startThread(final int threadNum, final TestRunnable run) {
- Thread t1 = new Thread(() -> {
- try {
- for (int iter = 0; iter < NUMBER_OF_TESTS && exception == null; iter++) {
- // call the actual test-code
- run.run(threadNum, iter);
-
- executions[threadNum]++;
- }
-
- // do end-work here, we don't do this in a finally as we log
- // Exception
- // then anyway
- run.doEnd(threadNum);
- } catch (Throwable e) {
- exception = e;
- }
-
- }, "ThreadTestHelper-Thread " + threadNum + ": " + run.getClass().getName());
-
- t1.start();
-
- return t1;
- }
-}
--- /dev/null
+/* ====================================================================
+ 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.util.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.poi.ooxml.util.IdentifierManager;
+import org.junit.Test;
+
+public class TestIdentifierManager {
+ @Test
+ public void testBasic()
+ {
+ IdentifierManager manager = new IdentifierManager(0L,100L);
+ assertEquals(101L,manager.getRemainingIdentifiers());
+ assertEquals(0L,manager.reserveNew());
+ assertEquals(100L,manager.getRemainingIdentifiers());
+ assertEquals(1L,manager.reserve(0L));
+ assertEquals(99L,manager.getRemainingIdentifiers());
+ }
+
+ @Test
+ public void testLongLimits() {
+ long min = IdentifierManager.MIN_ID;
+ long max = IdentifierManager.MAX_ID;
+ IdentifierManager manager = new IdentifierManager(min,max);
+ assertTrue("Limits lead to a long variable overflow", max - min + 1 > 0);
+ assertTrue("Limits lead to a long variable overflow", manager.getRemainingIdentifiers() > 0);
+ assertEquals(min,manager.reserveNew());
+ assertEquals(max,manager.reserve(max));
+ assertEquals(max - min -1, manager.getRemainingIdentifiers());
+ manager.release(max);
+ manager.release(min);
+ }
+
+ @Test
+ public void testReserve() {
+ IdentifierManager manager = new IdentifierManager(10L,30L);
+ assertEquals(12L,manager.reserve(12L));
+ long reserve = manager.reserve(12L);
+ assertNotEquals("Same id must be reserved twice!", 12L, reserve);
+ assertTrue(manager.release(12L));
+ assertTrue(manager.release(reserve));
+ assertFalse(manager.release(12L));
+ assertFalse(manager.release(reserve));
+
+ manager = new IdentifierManager(0L,2L);
+ assertEquals(0L,manager.reserve(0L));
+ assertEquals(1L,manager.reserve(1L));
+ assertEquals(2L,manager.reserve(2L));
+ try {
+ manager.reserve(0L);
+ fail("Exception expected");
+ } catch(IllegalStateException e) {
+ // expected
+ }
+ try {
+ manager.reserve(1L);
+ fail("Exception expected");
+ } catch(IllegalStateException e) {
+ // expected
+ }
+ try {
+ manager.reserve(2L);
+ fail("Exception expected");
+ } catch(IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testReserveNew() {
+ IdentifierManager manager = new IdentifierManager(10L,12L);
+ assertSame(10L,manager.reserveNew());
+ assertSame(11L,manager.reserveNew());
+ assertSame(12L,manager.reserveNew());
+ try {
+ manager.reserveNew();
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testRelease() {
+ IdentifierManager manager = new IdentifierManager(10L,20L);
+ assertEquals(10L,manager.reserve(10L));
+ assertEquals(11L,manager.reserve(11L));
+ assertEquals(12L,manager.reserve(12L));
+ assertEquals(13L,manager.reserve(13L));
+ assertEquals(14L,manager.reserve(14L));
+
+ assertTrue(manager.release(10L));
+ assertEquals(10L,manager.reserve(10L));
+ assertTrue(manager.release(10L));
+
+ assertTrue(manager.release(11L));
+ assertEquals(11L,manager.reserve(11L));
+ assertTrue(manager.release(11L));
+ assertFalse(manager.release(11L));
+ assertFalse(manager.release(10L));
+
+ assertEquals(10L,manager.reserve(10L));
+ assertEquals(11L,manager.reserve(11L));
+ assertTrue(manager.release(12L));
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.util.tests;
+
+import static org.apache.poi.util.DefaultTempFileCreationStrategy.POIFILES;
+import static org.apache.poi.util.TempFile.JAVA_IO_TMPDIR;
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.util.TempFile;
+import org.apache.poi.util.TempFileCreationStrategy;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestTempFileThreaded {
+ private static final int NUMBER_OF_THREADS = 10;
+ private static final int NUMBER_OF_TESTS = 200;
+
+ private volatile Throwable exception;
+ private int[] executions;
+
+ // the actual thread-safe temp-file strategy
+ private static TempFileCreationStrategy createTempFileCreationStrategy(File poiTempFileDirectory) {
+ return new TempFileCreationStrategy() {
+ @Override
+ public File createTempFile(String prefix, String suffix) throws IOException {
+ long threadId = Thread.currentThread().getId();
+ File threadDir = new File(poiTempFileDirectory, Long.toString(threadId));
+ if (!threadDir.exists()) {
+ if (!threadDir.mkdirs()) {
+ throw new IOException("mkdir of " + threadDir + " failed");
+ }
+ }
+
+ File file = File.createTempFile(prefix, suffix, threadDir);
+ file.deleteOnExit();
+ return file;
+ }
+
+ @Override
+ public File createTempDirectory(String prefix) {
+ throw new UnsupportedOperationException("createTempDirectory");
+ }
+ };
+ }
+
+ @BeforeClass
+ public static void setUpClass() throws IOException {
+ String tmpDir = System.getProperty(JAVA_IO_TMPDIR);
+ if (tmpDir == null) {
+ throw new IOException("Systems temporary directory not defined - set the -D" + JAVA_IO_TMPDIR + " jvm property!");
+ }
+
+ TempFile.setTempFileCreationStrategy(createTempFileCreationStrategy(new File(new File(tmpDir, POIFILES), "TestTempFileThreaded")));
+ }
+
+ @Before
+ public void setUp() {
+ // Initialize array to allow to summarize afterwards
+ executions = new int[NUMBER_OF_THREADS];
+ }
+
+ @Test
+ public void runTest() throws Throwable {
+ List<Thread> threads = new LinkedList<>();
+
+ // start all threads
+ for (int i = 0; i < NUMBER_OF_THREADS; i++) {
+ Thread t = startThread(i, new TestRunnable());
+ threads.add(t);
+ }
+
+ // wait for all threads
+ for (int i = 0; i < NUMBER_OF_THREADS; i++) {
+ threads.get(i).join();
+ }
+
+ // report exceptions if there were any
+ if (exception != null) {
+ throw exception;
+ }
+
+ // make sure the resulting number of executions is correct
+ for (int i = 0; i < NUMBER_OF_THREADS; i++) {
+ // check if enough items were performed
+ assertEquals("Thread " + i
+ + " did not execute all iterations", NUMBER_OF_TESTS,
+ executions[i]);
+ }
+ }
+
+ private static class TestRunnable {
+ Map<Integer, List<File>> files = new HashMap<>();
+
+ public TestRunnable() {
+ for (int i = 0; i < NUMBER_OF_THREADS; i++) {
+ files.put(i, new ArrayList<>());
+ }
+ }
+
+ public void doEnd(int threadNum) {
+ for (File file : files.get(threadNum)) {
+ if (!file.exists()) {
+ throw new IllegalStateException("File " + file + " does not exist");
+ }
+ if (!file.delete()) {
+ throw new IllegalStateException("Deletion of " + file + " failed");
+ }
+ }
+ }
+
+ public void run(int threadNum, int iter) throws Exception {
+ try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
+ SXSSFSheet sheet = wb.createSheet("test");
+
+ for (int i = 0; i < 100; i++) {
+ Row row = sheet.createRow(i);
+ for (int j = 0; j < 10; j++) {
+ Cell cell = row.createCell(j);
+ cell.setCellValue("123");
+ }
+ }
+
+ File file = TempFile.createTempFile("TestTempFile-" + threadNum + "-" + iter + "-", ".xlsx");
+ try (OutputStream outputStream = new FileOutputStream(file)) {
+ wb.write(outputStream);
+ }
+
+ files.get(threadNum).add(file);
+
+ if (iter % 30 == 0) {
+ System.out.println("thread: " + threadNum + ", iter: " + iter + ": " + file);
+ }
+ }
+ }
+ }
+
+ private Thread startThread(final int threadNum, final TestRunnable run) {
+ Thread t1 = new Thread(() -> {
+ try {
+ for (int iter = 0; iter < NUMBER_OF_TESTS && exception == null; iter++) {
+ // call the actual test-code
+ run.run(threadNum, iter);
+
+ executions[threadNum]++;
+ }
+
+ // do end-work here, we don't do this in a finally as we log
+ // Exception
+ // then anyway
+ run.doEnd(threadNum);
+ } catch (Throwable e) {
+ exception = e;
+ }
+
+ }, "ThreadTestHelper-Thread " + threadNum + ": " + run.getClass().getName());
+
+ t1.start();
+
+ return t1;
+ }
+}
+++ /dev/null
-/*
- * ====================================================================
- * 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.xslf.geom;
-
-import static org.junit.Assert.assertEquals;
-
-import org.apache.poi.sl.draw.geom.Context;
-import org.apache.poi.sl.draw.geom.CustomGeometry;
-import org.apache.poi.sl.draw.geom.Formula;
-import org.apache.poi.sl.draw.geom.Guide;
-import org.junit.Test;
-
-/**
- * Date: 10/24/11
- *
- * @author Yegor Kozlov
- */
-public class TestFormulaParser {
- @Test
- public void testParse(){
-
- Formula[] ops = {
- newGuide("adj1", "val 100"),
- newGuide("adj2", "val 200"),
- newGuide("adj3", "val -1"),
- newGuide("a1", "*/ adj1 2 adj2"), // a1 = 100*2 / 200
- newGuide("a2", "+- adj2 a1 adj1"), // a2 = 200 + a1 - 100
- newGuide("a3", "+/ adj1 adj2 adj2"), // a3 = (100 + 200) / 200
- newGuide("a4", "?: adj3 adj1 adj2"), // a4 = adj3 > 0 ? adj1 : adj2
- newGuide("a5", "abs -2"),
- };
-
- CustomGeometry geom = new CustomGeometry();
- Context ctx = new Context(geom, null, null);
- for(Formula fmla : ops) {
- ctx.evaluate(fmla);
- }
-
- assertEquals(100.0, ctx.getValue("adj1"), 0.0);
- assertEquals(200.0, ctx.getValue("adj2"), 0.0);
- assertEquals(1.0, ctx.getValue("a1"), 0.0);
- assertEquals(101.0, ctx.getValue("a2"), 0.0);
- assertEquals(1.5, ctx.getValue("a3"), 0.0);
- assertEquals(200.0, ctx.getValue("a4"), 0.0);
- assertEquals(2.0, ctx.getValue("a5"), 0.0);
- }
-
- private static Guide newGuide(String name, String fmla) {
- Guide gd = new Guide();
- gd.setName(name);
- gd.setFmla(fmla);
- return gd;
- }
-}
==================================================================== */
package org.apache.poi.xslf.usermodel;
-import static org.apache.poi.sl.TestCommonSL.getColor;
+import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
==================================================================== */
package org.apache.poi.xslf.usermodel;
-import static org.apache.poi.sl.TestCommonSL.getColor;
+import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
*/
package org.apache.poi.xslf.usermodel;
-import static org.apache.poi.sl.TestCommonSL.getColor;
+import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import java.io.InputStream;
import org.apache.poi.POIDataSamples;
-import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.sl.draw.DrawTextParagraph;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
==================================================================== */
package org.apache.poi.xslf.usermodel;
-import static org.apache.poi.sl.TestCommonSL.getColor;
+import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.apache.poi.xslf.usermodel.TestXSLFSimpleShape.getSpPr;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
==================================================================== */
package org.apache.poi.xslf.usermodel;
-import static org.apache.poi.sl.TestCommonSL.getColor;
+import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
package org.apache.poi.xssf;
-import org.apache.poi.ss.format.TestCellFormatPart;
+import org.apache.poi.ss.tests.format.TestCellFormatPart;
import org.apache.poi.xssf.extractor.TestXSSFExcelExtractor;
import org.apache.poi.xssf.io.TestLoadSaveXSSF;
import org.apache.poi.xssf.model.TestCommentsTable;
//TestStylesTable.class, //converted to junit4
//TestCellReference.class, //converted to junit4
TestCTColComparator.class,
- TestNumericRanges.class,
+ TestNumericRanges.class,
TestCellFormatPart.class,
TestXSSFCloneSheet.class
})
package org.apache.poi.xssf.streaming;
-import org.apache.poi.ss.usermodel.BaseTestXWorkbook;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import org.apache.poi.ss.tests.usermodel.BaseTestXWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.junit.Ignore;
import org.junit.Test;
-import java.io.IOException;
-
-import static org.junit.Assert.*;
-
public final class TestDeferredSXSSFWorkbook extends BaseTestXWorkbook {
-
+
public TestDeferredSXSSFWorkbook() {
super(DeferredSXSSFITestDataProvider.instance);
}
-
+
@After
public void tearDown() {
((DeferredSXSSFITestDataProvider) _testDataProvider).cleanup();
}
-
+
/**
* cloning of sheets is not supported in SXSSF
*/
assertEquals("Not Implemented", e.getMessage());
}
}
-
+
/**
* cloning of sheets is not supported in SXSSF
*/
assertEquals("Not Implemented", e.getMessage());
}
}
-
+
/**
* Skip this test, as SXSSF doesn't update formulas on sheet name changes.
*/
DeferredSXSSFWorkbook wb1 = new DeferredSXSSFWorkbook(xssfWb1);
XSSFWorkbook xssfWb2 = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb1);
assertTrue(wb1.dispose());
-
+
DeferredSXSSFWorkbook wb2 = new DeferredSXSSFWorkbook(xssfWb2);
assertEquals(1, wb2.getNumberOfSheets());
Sheet sheet = wb2.getStreamingSheetAt(0);
assertTrue(wb2.dispose());
xssfWb2.close();
xssfWb1.close();
-
+
wb2.close();
wb1.close();
}
XSSFWorkbook xssfWb2 = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb1);
assertTrue(wb1.dispose());
xssfWb1.close();
-
+
DeferredSXSSFWorkbook wb2 = new DeferredSXSSFWorkbook(xssfWb2);
// Add a row to the existing empty sheet
DeferredSXSSFSheet ssheet1 = wb2.getStreamingSheetAt(0);
Cell cell1_1_1 = row1_1.createCell(1);
cell1_1_1.setCellValue("value 1_1_1");
});
-
+
// Add a row to the existing non-empty sheet
DeferredSXSSFSheet ssheet2 = wb2.getStreamingSheetAt(1);
ssheet2.setRowGenerator((ssxSheet) -> {
Cell cell3_1_1 = row3_1.createCell(1);
cell3_1_1.setCellValue("value 3_1_1");
});
-
+
XSSFWorkbook xssfWb3 = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb2);
wb2.close();
-
+
assertEquals(3, xssfWb3.getNumberOfSheets());
// Verify sheet 1
XSSFSheet sheet1 = xssfWb3.getSheetAt(0);
XSSFCell cell3_1_1 = row3_1.getCell(1);
assertNotNull(cell3_1_1);
assertEquals("value 3_1_1", cell3_1_1.getStringCellValue());
-
+
xssfWb2.close();
xssfWb3.close();
wb1.close();
}
-
+
@Test
public void sheetdataWriter() throws IOException {
DeferredSXSSFWorkbook wb = new DeferredSXSSFWorkbook();
}
}
}
-
+
@Test
public void gzipSheetdataWriter() throws IOException {
DeferredSXSSFWorkbook wb = new DeferredSXSSFWorkbook();
final int rowNum = 1000;
final int sheetNum = 5;
populateData(wb, 1000, 5);
-
+
XSSFWorkbook xwb = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb);
for (int i = 0; i < sheetNum; i++) {
Sheet sh = xwb.getSheetAt(i);
assertNotNull("row[" + j + "]", row);
Cell cell1 = row.getCell(0);
assertEquals(new CellReference(cell1).formatAsString(), cell1.getStringCellValue());
-
+
Cell cell2 = row.getCell(1);
assertEquals(i, (int) cell2.getNumericCellValue());
-
+
Cell cell3 = row.getCell(2);
assertEquals(j, (int) cell3.getNumericCellValue());
}
}
-
+
assertTrue(wb.dispose());
xwb.close();
wb.close();
assertWorkbookDispose(wb2);
wb2.close();
}
-
+
private static void assertWorkbookDispose(DeferredSXSSFWorkbook wb) {
populateData(wb, 1000, 5);
-
+
for (Sheet sheet : wb) {
DeferredSXSSFSheet sxSheet = (DeferredSXSSFSheet) sheet;
assertNull(sxSheet.getSheetDataWriter());
}
-
+
assertTrue(wb.dispose());
-
+
for (Sheet sheet : wb) {
DeferredSXSSFSheet sxSheet = (DeferredSXSSFSheet) sheet;
assertNull(sxSheet.getSheetDataWriter());
}
}
-
+
private static void populateData(DeferredSXSSFWorkbook wb, final int rowNum, final int sheetNum) {
for (int i = 0; i < sheetNum; i++) {
DeferredSXSSFSheet sheet = wb.createSheet("sheet" + i);
Row row = sh.createRow(j);
Cell cell1 = row.createCell(0);
cell1.setCellValue(new CellReference(cell1).formatAsString());
-
+
Cell cell2 = row.createCell(1);
cell2.setCellValue(index);
-
+
Cell cell3 = row.createCell(2);
cell3.setCellValue(j);
}
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.spy;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.xml.namespace.QName;
import org.apache.poi.ss.SpreadsheetVersion;
-import org.apache.poi.ss.usermodel.BaseTestXCell;
+import org.apache.poi.ss.tests.usermodel.BaseTestXCell;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.RichTextString;
import org.junit.Test;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
/**
* Tests various functionality having to do with {@link SXSSFCell}. For instance support for
* particular datatypes, etc.
package org.apache.poi.xssf.streaming;
-import org.apache.poi.ss.usermodel.BaseTestXRow;
+import org.apache.poi.ss.tests.usermodel.BaseTestXRow;
import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.junit.After;
import org.junit.Ignore;
@Override
@Ignore ("see <https://bz.apache.org/bugzilla/show_bug.cgi?id=62030#c1>") @Test
public void testCellShiftingLeft(){
- // Remove when SXSSFRow.shiftCellsLeft() is implemented.
+ // Remove when SXSSFRow.shiftCellsLeft() is implemented.
}
-
+
}
import java.io.IOException;
-import org.apache.poi.ss.usermodel.BaseTestXSheet;
+import org.apache.poi.ss.tests.usermodel.BaseTestXSheet;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.SXSSFITestDataProvider;
public void tearDown(){
SXSSFITestDataProvider.instance.cleanup();
}
-
+
@Override
protected void trackColumnsForAutoSizingIfSXSSF(Sheet sheet) {
SXSSFSheet sxSheet = (SXSSFSheet) sheet;
thrown.expectMessage("Not Implemented");
super.cloneSheetMultipleTimes();
}
-
+
/**
* shifting rows is not supported in SXSSF
*/
@Override
@Test
public void getCellComment() throws IOException {
- // TODO: reading cell comments via Sheet does not work currently as it tries
+ // TODO: reading cell comments via Sheet does not work currently as it tries
// to access the underlying sheet for this, but comments are stored as
// properties on Cells...
}
-
+
@Override
@Test
public void defaultColumnStyle() {
Workbook wb = new SXSSFWorkbook(template);
try {
Sheet sheet = wb.getSheetAt(0);
-
+
try {
sheet.createRow(1);
fail("expected exception");
SXSSFRow row0 = sheet.createRow(0);
SXSSFRow row1 = sheet.createRow(1);
sheet.changeRowNum(row0, 2);
-
+
assertEquals("Row 1 knows its row number", 1, row1.getRowNum());
assertEquals("Row 2 knows its row number", 2, row0.getRowNum());
assertEquals("Sheet knows Row 1's row number", 1, sheet.getRowNum(row1));
assertEquals("Sheet knows Row 2's row number", 2, sheet.getRowNum(row0));
assertEquals("Sheet row iteratation order should be ascending", row1, sheet.iterator().next());
-
+
wb.close();
}
}
package org.apache.poi.xssf.streaming;
-import static org.apache.poi.POITestCase.assertStartsWith;
import static org.apache.poi.POITestCase.assertEndsWith;
+import static org.apache.poi.POITestCase.assertStartsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import java.util.Arrays;
import org.apache.poi.POIDataSamples;
-import org.apache.poi.POITestCase;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.ss.usermodel.BaseTestXWorkbook;
+import org.apache.poi.ss.tests.usermodel.BaseTestXWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
assertTrue(wb2.dispose());
xssfWb2.close();
xssfWb1.close();
-
+
wb2.close();
wb1.close();
}
public void useSharedStringsTable() throws Exception {
SXSSFWorkbook wb = new SXSSFWorkbook(null, 10, false, true);
- SharedStringsTable sss = POITestCase.getFieldValue(SXSSFWorkbook.class, wb, SharedStringsTable.class, "_sharedStringSource");
-
+ SharedStringsTable sss = wb.getSharedStringSource();
+
assertNotNull(sss);
Row row = wb.createSheet("S1").createRow(0);
row.createCell(2).setCellValue("A");
XSSFWorkbook xssfWorkbook = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb);
- sss = POITestCase.getFieldValue(SXSSFWorkbook.class, wb, SharedStringsTable.class, "_sharedStringSource");
+ sss = wb.getSharedStringSource();
assertEquals(2, sss.getUniqueCount());
assertTrue(wb.dispose());
XSSFWorkbook xssfWb3 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb2);
wb2.close();
-
+
assertEquals(3, xssfWb3.getNumberOfSheets());
// Verify sheet 1
sheet1 = xssfWb3.getSheetAt(0);
cell3_1_1 = row3_1.getCell(1);
assertNotNull(cell3_1_1);
assertEquals("value 3_1_1", cell3_1_1.getStringCellValue());
-
+
xssfWb2.close();
xssfWb3.close();
wb1.close();
// Some tests commented out because close() modifies the file
// See bug 58779
-
+
// String
//wb = new SXSSFWorkbook(new XSSFWorkbook(file.getPath()));
//assertCloseDoesNotModifyFile(filename, wb);
-
+
// File
//wb = new SXSSFWorkbook(new XSSFWorkbook(file));
//assertCloseDoesNotModifyFile(filename, wb);
-
+
// InputStream
try (FileInputStream fis = new FileInputStream(file);
SXSSFWorkbook wb = new SXSSFWorkbook(xwb)) {
assertCloseDoesNotModifyFile(filename, wb);
}
-
+
// OPCPackage
//wb = new SXSSFWorkbook(new XSSFWorkbook(OPCPackage.open(file)));
//assertCloseDoesNotModifyFile(filename, wb);
}
-
+
/**
* Bug #59743
- *
+ *
* this is only triggered on other files apart of sheet[1,2,...].xml
* as those are either copied uncompressed or with the use of GZIPInputStream
* so we use shared strings
SXSSFSheet s = swb.createSheet();
char[] useless = new char[32767];
Arrays.fill(useless, ' ');
-
+
for (int row=0; row<1; row++) {
Row r = s.createRow(row);
for (int col=0; col<10; col++) {
r.createCell(col, CellType.STRING).setCellValue(ul);
}
}
-
+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
swb.write(bos);
swb.dispose();
swb.close();
}
-
+
/**
* To avoid accident changes to the template, you should be able
* to create a SXSSFWorkbook from a read-only XSSF one, then
package org.apache.poi.xssf.usermodel;
-import org.apache.poi.ss.formula.eval.forked.TestForkedEvaluator;
+import org.apache.poi.ss.formula.eval.forked.BaseTestForkedEvaluator;
import org.apache.poi.xssf.usermodel.extensions.TestXSSFBorder;
import org.apache.poi.xssf.usermodel.extensions.TestXSSFCellFill;
import org.apache.poi.xssf.usermodel.helpers.TestColumnHelper;
TestColumnHelper.class,
TestHeaderFooterHelper.class,
//TestXSSFPivotTable.class, //converted to junit4
- TestForkedEvaluator.class
+ BaseTestForkedEvaluator.class
})
public final class AllXSSFUsermodelTests {
}
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.formula.eval.TestFormulasFromSpreadsheet;
-import org.apache.poi.ss.formula.functions.TestMathX;
+import org.apache.poi.ss.formula.functions.BaseTestNumeric;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
* except for a XSSF spreadsheet, not a HSSF one.
* This allows us to check that all our Formula Evaluation code
* is able to work for XSSF, as well as for HSSF.
- *
+ *
* Periodically, you should open FormulaEvalTestData.xls in
* Excel 2007, and re-save it as FormulaEvalTestData_Copy.xlsx
- *
+ *
*/
@RunWith(Parameterized.class)
public final class TestFormulaEvaluatorOnXSSF {
private static Sheet sheet;
private static FormulaEvaluator evaluator;
private static Locale userLocale;
-
- /**
+
+ /**
* This class defines constants for navigating around the test data spreadsheet used for these tests.
*/
private static interface SS {
-
+
/**
* Name of the test spreadsheet (found in the standard test data folder)
*/
LocaleUtil.setUserLocale(userLocale);
workbook.close();
}
-
+
@Parameters(name="{0}")
public static Collection<Object[]> data() throws Exception {
// Function "Text" uses custom-formats which are locale specific
workbook = new XSSFWorkbook( OPCPackage.open(HSSFTestDataSamples.getSampleFile(SS.FILENAME), PackageAccess.READ) );
sheet = workbook.getSheetAt( 0 );
evaluator = new XSSFFormulaEvaluator(workbook);
-
+
List<Object[]> data = new ArrayList<>();
-
+
processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
return data;
}
-
+
/**
- * @param startRowIndex row index in the spreadsheet where the first function/operator is found
- * @param testFocusFunctionName name of a single function/operator to test alone.
+ * @param startRowIndex row index in the spreadsheet where the first function/operator is found
+ * @param testFocusFunctionName name of a single function/operator to test alone.
* Typically pass <code>null</code> to test all functions
*/
private static void processFunctionGroup(List<Object[]> data, int startRowIndex, String testFocusFunctionName) {
// only evaluate non empty row
if(r == null) continue;
-
+
String targetFunctionName = getTargetFunctionName(r);
assertNotNull("Test spreadsheet cell empty on row ("
+ (rowIndex+1) + "). Expected function name or '"
break;
}
if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
-
+
// expected results are on the row below
Row expectedValuesRow = sheet.getRow(rowIndex + 1);
// +1 for 1-based, +1 for next row
- assertNotNull("Missing expected values row for function '"
+ assertNotNull("Missing expected values row for function '"
+ targetFunctionName + " (row " + rowIndex + 2 + ")"
, expectedValuesRow);
-
+
data.add(new Object[]{targetFunctionName, rowIndex, rowIndex + 1});
}
}
public void processFunctionRow() {
Row formulasRow = sheet.getRow(formulasRowIdx);
Row expectedValuesRow = sheet.getRow(expectedValuesRowIdx);
-
+
short endcolnum = formulasRow.getLastCellNum();
// iterate across the row for all the evaluation cases
String msg = String.format(Locale.ROOT, "Function '%s': Formula: %s @ %d:%d"
, targetFunctionName, c.getCellFormula(), formulasRow.getRowNum(), colnum);
-
+
assertNotNull(msg + " - Bad setup data expected value is null", expValue);
assertNotNull(msg + " - actual value was null", actValue);
-
+
final CellType expectedCellType = expValue.getCellType();
switch (expectedCellType) {
case BLANK:
fail("Cannot expect formula as result of formula evaluation: " + msg);
case NUMERIC:
assertEquals(msg, CellType.NUMERIC, actValue.getCellType());
- TestMathX.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
+ BaseTestNumeric.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), BaseTestNumeric.POS_ZERO, BaseTestNumeric.DIFF_TOLERANCE_FACTOR);
// double delta = Math.abs(expValue.getNumericCellValue()-actValue.getNumberValue());
// double pctExpValue = Math.abs(0.00001*expValue.getNumericCellValue());
// assertTrue(msg, delta <= pctExpValue);
}
/*
- * TODO - these are all formulas which currently (Apr-2008) break on ooxml
+ * TODO - these are all formulas which currently (Apr-2008) break on ooxml
*/
private static void ignoredFormulaTestCase(String cellFormula) {
// full row ranges are not parsed properly yet.
- // These cases currently work in svn trunk because of another bug which causes the
- // formula to get rendered as COLUMN($A$1:$IV$2) or ROW($A$2:$IV$3)
+ // These cases currently work in svn trunk because of another bug which causes the
+ // formula to get rendered as COLUMN($A$1:$IV$2) or ROW($A$2:$IV$3)
assumeFalse("COLUMN(1:2)".equals(cellFormula));
assumeFalse("ROW(2:3)".equals(cellFormula));
- // currently throws NPE because unknown function "currentcell" causes name lookup
+ // currently throws NPE because unknown function "currentcell" causes name lookup
// Name lookup requires some equivalent object of the Workbook within xSSFWorkbook.
assumeFalse("ISREF(currentcell())".equals(cellFormula));
}
if(cell.getCellType() == CellType.STRING) {
return cell.getRichStringCellValue().getString();
}
-
+
fail("Bad cell type for 'function name' column: ("+cell.getColumnIndex()+") row ("+(r.getRowNum()+1)+")");
return null;
}
import java.util.Locale;
import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.ss.formula.functions.TestMathX;
+import org.apache.poi.ss.formula.functions.BaseTestNumeric;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
fail("Cannot expect formula as result of formula evaluation: " + msg);
case NUMERIC:
assertEquals(msg, CellType.NUMERIC, actValue.getCellType());
- TestMathX.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
+ BaseTestNumeric.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), BaseTestNumeric.POS_ZERO, BaseTestNumeric.DIFF_TOLERANCE_FACTOR);
break;
case STRING:
assertEquals(msg, CellType.STRING, actValue.getCellType());
package org.apache.poi.xssf.usermodel;
+import static org.junit.Assert.assertNotNull;
+
import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.ss.formula.TestMissingWorkbook;
+import org.apache.poi.ss.formula.BaseTestMissingWorkbook;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.junit.Before;
-import static org.junit.Assert.assertNotNull;
-
/**
* XSSF Specific version of the Missing Workbooks test
*/
-public final class TestMissingWorkbookOnXSSF extends TestMissingWorkbook {
+public final class TestMissingWorkbookOnXSSF extends BaseTestMissingWorkbook {
public TestMissingWorkbookOnXSSF() {
super("52575_main.xlsx", "source_dummy.xlsx", "52575_source.xls");
}
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.ss.formula.eval.TestFormulasFromSpreadsheet;
-import org.apache.poi.ss.formula.functions.TestMathX;
+import org.apache.poi.ss.formula.functions.BaseTestNumeric;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
*/
@RunWith(Parameterized.class)
public final class TestMultiSheetFormulaEvaluatorOnXSSF {
- private static final POILogger logger = POILogFactory.getLogger(TestFormulasFromSpreadsheet.class);
+ private static final POILogger logger = POILogFactory.getLogger(TestMultiSheetFormulaEvaluatorOnXSSF.class);
private static XSSFWorkbook workbook;
private static Sheet sheet;
fail("Cannot expect formula as result of formula evaluation: " + msg);
case NUMERIC:
assertEquals(msg, CellType.NUMERIC, actValue.getCellType());
- TestMathX.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
+ BaseTestNumeric.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), BaseTestNumeric.POS_ZERO, BaseTestNumeric.DIFF_TOLERANCE_FACTOR);
// double delta = Math.abs(expected.getNumericCellValue()-actual.getNumberValue());
// double pctExpected = Math.abs(0.00001*expected.getNumericCellValue());
// assertTrue(msg, delta <= pctExpected);
// Workbook Factory gives helpful error on package
try {
- XSSFWorkbookFactory.create(pkg).close();
+ XSSFWorkbookFactory.createWorkbook(pkg).close();
fail(".xlsb files not supported");
} catch (XLSBUnsupportedException e) {
// Good, detected and warned
package org.apache.poi.xssf.usermodel;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.io.IOException;
import java.util.List;
import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaParseException;
-import org.apache.poi.ss.usermodel.BaseTestXCell;
+import org.apache.poi.ss.tests.usermodel.BaseTestXCell;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
-import static org.junit.Assert.*;
-
public final class TestXSSFCell extends BaseTestXCell {
public TestXSSFCell() {
package org.apache.poi.xssf.usermodel;
-import org.apache.poi.ss.formula.eval.forked.TestForkedEvaluator;
+import org.apache.poi.ss.formula.eval.forked.BaseTestForkedEvaluator;
import org.apache.poi.ss.usermodel.Workbook;
-public class TestXSSFForkedEvaluator extends TestForkedEvaluator {
-
+public class TestXSSFForkedEvaluator extends BaseTestForkedEvaluator {
+
@Override
protected Workbook newWorkbook() {
return new XSSFWorkbook();
import java.io.IOException;
-import org.apache.poi.ss.usermodel.BaseTestXRow;
+import org.apache.poi.ss.tests.usermodel.BaseTestXRow;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.CellType;
public TestXSSFRow() {
super(XSSFITestDataProvider.instance);
}
-
+
@Test
public void testCopyRowFrom() throws IOException {
final XSSFWorkbook workbook = new XSSFWorkbook();
final XSSFRow srcRow = sheet.createRow(0);
srcRow.createCell(0).setCellValue("Hello");
final XSSFRow destRow = sheet.createRow(1);
-
+
destRow.copyRowFrom(srcRow, new CellCopyPolicy());
assertNotNull(destRow.getCell(0));
assertEquals("Hello", destRow.getCell(0).getStringCellValue());
-
+
workbook.close();
}
-
+
@Test
public void testCopyRowFromExternalSheet() throws IOException {
final XSSFWorkbook workbook = new XSSFWorkbook();
final Sheet srcSheet = workbook.createSheet("src");
final XSSFSheet destSheet = workbook.createSheet("dest");
workbook.createSheet("other");
-
+
final Row srcRow = srcSheet.createRow(0);
int col = 0;
//Test 2D and 3D Ref Ptgs (Pxg for OOXML Workbooks)
srcRow.createCell(col++).setCellFormula("src!B5");
srcRow.createCell(col++).setCellFormula("dest!B5");
srcRow.createCell(col++).setCellFormula("other!B5");
-
+
//Test 2D and 3D Ref Ptgs with absolute row
srcRow.createCell(col++).setCellFormula("B$5");
srcRow.createCell(col++).setCellFormula("src!B$5");
srcRow.createCell(col++).setCellFormula("dest!B$5");
srcRow.createCell(col++).setCellFormula("other!B$5");
-
+
//Test 2D and 3D Area Ptgs (Pxg for OOXML Workbooks)
srcRow.createCell(col++).setCellFormula("SUM(B5:D$5)");
srcRow.createCell(col++).setCellFormula("SUM(src!B5:D$5)");
final XSSFRow destRow = destSheet.createRow(1);
destRow.copyRowFrom(srcRow, new CellCopyPolicy());
-
+
//////////////////
-
+
//Test 2D and 3D Ref Ptgs (Pxg for OOXML Workbooks)
col = 0;
Cell cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("RefPtg", "B6", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("Ref3DPtg", "src!B6", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("Ref3DPtg", "dest!B6", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("Ref3DPtg", "other!B6", cell.getCellFormula());
-
+
/////////////////////////////////////////////
-
+
//Test 2D and 3D Ref Ptgs with absolute row (Ptg row number shouldn't change)
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("RefPtg", "B$5", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("Ref3DPtg", "src!B$5", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("Ref3DPtg", "dest!B$5", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("Ref3DPtg", "other!B$5", cell.getCellFormula());
-
+
//////////////////////////////////////////
-
+
//Test 2D and 3D Area Ptgs (Pxg for OOXML Workbooks)
// Note: absolute row changes from last cell to first cell in order
// to maintain topLeft:bottomRight order
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("Area2DPtg", "SUM(B$5:D6)", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(cell);
assertEquals("Area3DPtg", "SUM(src!B$5:D6)", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(destRow.getCell(6));
assertEquals("Area3DPtg", "SUM(dest!B$5:D6)", cell.getCellFormula());
-
+
cell = destRow.getCell(col++);
assertNotNull(destRow.getCell(7));
assertEquals("Area3DPtg", "SUM(other!B$5:D6)", cell.getCellFormula());
-
+
workbook.close();
}
-
+
@Test
public void testCopyRowOverwritesExistingRow() throws IOException {
final XSSFWorkbook workbook = new XSSFWorkbook();
final XSSFSheet sheet1 = workbook.createSheet("Sheet1");
final Sheet sheet2 = workbook.createSheet("Sheet2");
-
+
final Row srcRow = sheet1.createRow(0);
final XSSFRow destRow = sheet1.createRow(1);
final Row observerRow = sheet1.createRow(2);
final Row externObserverRow = sheet2.createRow(0);
-
+
srcRow.createCell(0).setCellValue("hello");
srcRow.createCell(1).setCellValue("world");
destRow.createCell(0).setCellValue(5.0); //A2 -> 5.0
observerRow.createCell(0).setCellFormula("A2"); // A3 -> A2 -> 5.0
observerRow.createCell(1).setCellFormula("B2"); // B3 -> B2 -> A1 -> "hello"
externObserverRow.createCell(0).setCellFormula("Sheet1!A2"); //Sheet2!A1 -> Sheet1!A2 -> 5.0
-
+
// overwrite existing destRow with row-copy of srcRow
destRow.copyRowFrom(srcRow, new CellCopyPolicy());
-
+
// copyRowFrom should update existing destRow, rather than creating a new row and reassigning the destRow pointer
// to the new row (and allow the old row to be garbage collected)
// this is mostly so existing references to rows that are overwritten are updated
assertSame("existing references to destRow are still valid", destRow, sheet1.getRow(1));
assertSame("existing references to observerRow are still valid", observerRow, sheet1.getRow(2));
assertSame("existing references to externObserverRow are still valid", externObserverRow, sheet2.getRow(0));
-
+
// Make sure copyRowFrom actually copied row (this is tested elsewhere)
assertEquals(CellType.STRING, destRow.getCell(0).getCellType());
assertEquals("hello", destRow.getCell(0).getStringCellValue());
-
+
// We don't want #REF! errors if we copy a row that contains cells that are referred to by other cells outside of copied region
assertEquals("references to overwritten cells are unmodified", "A2", observerRow.getCell(0).getCellFormula());
assertEquals("references to overwritten cells are unmodified", "B2", observerRow.getCell(1).getCellFormula());
assertEquals("references to overwritten cells are unmodified", "Sheet1!A2", externObserverRow.getCell(0).getCellFormula());
-
+
workbook.close();
}
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
-import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Map;
import java.util.Set;
-import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.ss.tests.usermodel.BaseTestXSheet;
import org.apache.poi.ss.usermodel.AutoFilter;
-import org.apache.poi.ss.usermodel.BaseTestXSheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.apache.poi.ss.util.*;
+import org.apache.poi.ss.util.CellAddress;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.util.CellUtil;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.openxml4j.opc.internal.FileHelper;
import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
-import org.apache.poi.ss.usermodel.BaseTestXWorkbook;
+import org.apache.poi.ss.tests.usermodel.BaseTestXWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
-public final class TestXSSFWorkbook extends BaseTestXWorkbook {
+public final class TestXSSFWorkbook extends BaseTestXWorkbook {
public TestXSSFWorkbook() {
super(XSSFITestDataProvider.instance);
assertTrue(file.exists());
// read-only mode works!
- Workbook workbook = WorkbookFactory.create(OPCPackage.open(file, PackageAccess.READ));
+ Workbook workbook = XSSFWorkbookFactory.createWorkbook(OPCPackage.open(file, PackageAccess.READ));
Date dateAct = workbook.getSheetAt(0).getRow(0).getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getDateCellValue();
assertEquals(dateExp, dateAct);
workbook.close();
workbook = null;
- workbook = WorkbookFactory.create(OPCPackage.open(file, PackageAccess.READ));
+ workbook = XSSFWorkbookFactory.createWorkbook(OPCPackage.open(file, PackageAccess.READ));
dateAct = workbook.getSheetAt(0).getRow(0).getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getDateCellValue();
assertEquals(dateExp, dateAct);
workbook.close();
workbook = null;
// now check read/write mode
- workbook = WorkbookFactory.create(OPCPackage.open(file, PackageAccess.READ_WRITE));
+ workbook = XSSFWorkbookFactory.createWorkbook(OPCPackage.open(file, PackageAccess.READ_WRITE));
dateAct = workbook.getSheetAt(0).getRow(0).getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getDateCellValue();
assertEquals(dateExp, dateAct);
workbook.close();
workbook = null;
- workbook = WorkbookFactory.create(OPCPackage.open(file, PackageAccess.READ_WRITE));
+ workbook = XSSFWorkbookFactory.createWorkbook(OPCPackage.open(file, PackageAccess.READ_WRITE));
dateAct = workbook.getSheetAt(0).getRow(0).getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getDateCellValue();
assertEquals(dateExp, dateAct);
workbook.close();
--- /dev/null
+# ====================================================================
+# 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.
+# ====================================================================
+
+org.apache.poi.hssf.usermodel.HSSFWorkbookFactory
\ No newline at end of file
--- /dev/null
+# ====================================================================
+# 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.
+# ====================================================================
+
+org.apache.poi.xssf.usermodel.XSSFWorkbookFactory
\ No newline at end of file
+++ /dev/null
-/* ====================================================================
- 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;
-
-import org.junit.Test;
-
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.font.TextLayout;
-import java.awt.image.BufferedImage;
-import java.text.AttributedString;
-
-/**
- * Minimal Test-Class found when running the Apache POI regression tests.
- *
- * This reproduces a crash introduced in JDK 12-ea+28 and JDK 13-ea+4
- *
- * This works in recent JDK 8, JDK 11 and at least up to JDK 12-ea+20
- *
- * https://bugs.openjdk.java.net/browse/JDK-8217768
- *
- * Should be fixed in JDK 12-ea+29 and JDK 13-ea+5
- */
-public class TestJDK12 {
- @Test
- public void test() throws Exception {
- BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
- Graphics2D graphics = img.createGraphics();
- graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- graphics.scale(200, 1);
-
- new TextLayout(new AttributedString("agriculture").getIterator(), graphics.getFontRenderContext());
-
- graphics.dispose();
- img.flush();
- }
-
-}
+++ /dev/null
-
-/* ====================================================================
- 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;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.apache.poi.hpsf.DocumentSummaryInformation;
-import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument;
-import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
-import org.apache.poi.hwpf.HWPFTestDataSamples;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Tests that POIDocument correctly loads and saves the common
- * (hspf) Document Properties
- *
- * This is part 2 of 2 of the tests - it only does the POIDocuments
- * which are part of the scratchpad (not main)
- */
-public final class TestPOIDocumentScratchpad {
- // The POI Documents to work on
- private POIDocument doc;
- private POIDocument doc2;
-
- /**
- * Set things up, using a PowerPoint document and
- * a Word Document for our testing
- */
- @Before
- public void setUp() throws IOException {
- doc = new HSLFSlideShowImpl(POIDataSamples.getSlideShowInstance().openResourceAsStream("basic_test_ppt_file.ppt"));
- doc2 = HWPFTestDataSamples.openSampleFile("test2.doc");
- }
-
- @Test
- public void testReadProperties() {
- testReadPropertiesHelper(doc);
- }
-
- private void testReadPropertiesHelper(POIDocument docPH) {
- // We should have both sets
- assertNotNull(docPH.getDocumentSummaryInformation());
- assertNotNull(docPH.getSummaryInformation());
-
- // Check they are as expected for the test doc
- assertEquals("Hogwarts", docPH.getSummaryInformation().getAuthor());
- assertEquals(10598, docPH.getDocumentSummaryInformation().getByteCount());
- }
-
- @Test
- public void testReadProperties2() {
- // Check again on the word one
- assertNotNull(doc2.getDocumentSummaryInformation());
- assertNotNull(doc2.getSummaryInformation());
-
- assertEquals("Hogwarts", doc2.getSummaryInformation().getAuthor());
- assertEquals("", doc2.getSummaryInformation().getKeywords());
- assertEquals(0, doc2.getDocumentSummaryInformation().getByteCount());
- }
-
- @Test
- public void testWriteProperties() throws IOException {
- // Just check we can write them back out into a filesystem
- POIFSFileSystem outFS = new POIFSFileSystem();
- doc.writeProperties(outFS);
-
- // Should now hold them
- assertNotNull(outFS.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME));
- assertNotNull(outFS.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME));
- outFS.close();
- }
-
- @Test
- public void testWriteReadProperties() throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- // Write them out
- POIFSFileSystem outFS = new POIFSFileSystem();
- doc.writeProperties(outFS);
- outFS.writeFilesystem(baos);
-
- // Create a new version
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- POIFSFileSystem inFS = new POIFSFileSystem(bais);
-
- // Check they're still there
- POIDocument ppt = new HPSFPropertiesOnlyDocument(inFS);
- ppt.readProperties();
-
- // Delegate test
- testReadPropertiesHelper(ppt);
-
- ppt.close();
- inFS.close();
- }
-}
--- /dev/null
+
+/* ====================================================================
+ 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.hslf;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.POIDocument;
+import org.apache.poi.hpsf.DocumentSummaryInformation;
+import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument;
+import org.apache.poi.hpsf.SummaryInformation;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
+import org.apache.poi.hwpf.HWPFTestDataSamples;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests that POIDocument correctly loads and saves the common
+ * (hspf) Document Properties
+ *
+ * This is part 2 of 2 of the tests - it only does the POIDocuments
+ * which are part of the scratchpad (not main)
+ */
+public final class TestPOIDocumentScratchpad {
+ // The POI Documents to work on
+ private POIDocument doc;
+ private POIDocument doc2;
+
+ /**
+ * Set things up, using a PowerPoint document and
+ * a Word Document for our testing
+ */
+ @Before
+ public void setUp() throws IOException {
+ doc = new HSLFSlideShowImpl(POIDataSamples.getSlideShowInstance().openResourceAsStream("basic_test_ppt_file.ppt"));
+ doc2 = HWPFTestDataSamples.openSampleFile("test2.doc");
+ }
+
+ @Test
+ public void testReadProperties() {
+ testReadPropertiesHelper(doc);
+ }
+
+ private void testReadPropertiesHelper(POIDocument docPH) {
+ // We should have both sets
+ assertNotNull(docPH.getDocumentSummaryInformation());
+ assertNotNull(docPH.getSummaryInformation());
+
+ // Check they are as expected for the test doc
+ assertEquals("Hogwarts", docPH.getSummaryInformation().getAuthor());
+ assertEquals(10598, docPH.getDocumentSummaryInformation().getByteCount());
+ }
+
+ @Test
+ public void testReadProperties2() {
+ // Check again on the word one
+ assertNotNull(doc2.getDocumentSummaryInformation());
+ assertNotNull(doc2.getSummaryInformation());
+
+ assertEquals("Hogwarts", doc2.getSummaryInformation().getAuthor());
+ assertEquals("", doc2.getSummaryInformation().getKeywords());
+ assertEquals(0, doc2.getDocumentSummaryInformation().getByteCount());
+ }
+
+ @Test
+ public void testWriteProperties() throws IOException {
+ // Just check we can write them back out into a filesystem
+ POIFSFileSystem outFS = new POIFSFileSystem();
+ doc.writeProperties(outFS);
+
+ // Should now hold them
+ assertNotNull(outFS.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME));
+ assertNotNull(outFS.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME));
+ outFS.close();
+ }
+
+ @Test
+ public void testWriteReadProperties() throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // Write them out
+ POIFSFileSystem outFS = new POIFSFileSystem();
+ doc.writeProperties(outFS);
+ outFS.writeFilesystem(baos);
+
+ // Create a new version
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ POIFSFileSystem inFS = new POIFSFileSystem(bais);
+
+ // Check they're still there
+ POIDocument ppt = new HPSFPropertiesOnlyDocument(inFS);
+ ppt.readProperties();
+
+ // Delegate test
+ testReadPropertiesHelper(ppt);
+
+ ppt.close();
+ inFS.close();
+ }
+}
package org.apache.poi.hslf.model;
-import static org.apache.poi.sl.TestCommonSL.getColor;
+import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
package org.apache.poi.hslf.record;
-import static org.apache.poi.ss.formula.functions.AbstractNumericTestCase.assertEquals;
+import static org.apache.poi.ss.formula.functions.BaseTestNumeric.assertEquals;
import static org.junit.Assert.assertArrayEquals;
import java.io.ByteArrayOutputStream;
package org.apache.poi.hslf.usermodel;
-import static org.apache.poi.sl.TestCommonSL.getColor;
+import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+++ /dev/null
-/* ====================================================================
- 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.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-
-import java.io.IOException;
-
-import org.apache.poi.hssf.HSSFITestDataProvider;
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.record.chart.SeriesRecord;
-import org.apache.poi.hssf.usermodel.HSSFChart.HSSFSeries;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellRangeAddressBase;
-import org.junit.Test;
-
-/**
- * Tests for {@link HSSFChart}
- */
-public final class TestHSSFChart {
-
- @Test
- public void testSingleChart() {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithChart.xls");
-
- HSSFSheet s1 = wb.getSheetAt(0);
- HSSFSheet s2 = wb.getSheetAt(1);
- HSSFSheet s3 = wb.getSheetAt(2);
-
- assertEquals(0, HSSFChart.getSheetCharts(s1).length);
- assertEquals(1, HSSFChart.getSheetCharts(s2).length);
- assertEquals(0, HSSFChart.getSheetCharts(s3).length);
-
- HSSFChart[] charts;
-
- // Check the chart on the 2nd sheet
- charts = HSSFChart.getSheetCharts(s2);
- assertEquals(1, charts.length);
-
- assertEquals(2, charts[0].getSeries().length);
- assertEquals("1st Column", charts[0].getSeries()[0].getSeriesTitle());
- assertEquals("2nd Column", charts[0].getSeries()[1].getSeriesTitle());
- assertNull(charts[0].getChartTitle());
-
- // Check x, y, width, height
- assertEquals(0, charts[0].getChartX());
- assertEquals(0, charts[0].getChartY());
- assertEquals(26492928, charts[0].getChartWidth());
- assertEquals(15040512, charts[0].getChartHeight());
- }
-
- @Test
- public void testTwoCharts() {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithTwoCharts.xls");
-
- HSSFSheet s1 = wb.getSheetAt(0);
- HSSFSheet s2 = wb.getSheetAt(1);
- HSSFSheet s3 = wb.getSheetAt(2);
-
- assertEquals(0, HSSFChart.getSheetCharts(s1).length);
- assertEquals(1, HSSFChart.getSheetCharts(s2).length);
- assertEquals(1, HSSFChart.getSheetCharts(s3).length);
-
- HSSFChart[] charts;
-
- // Check the chart on the 2nd sheet
- charts = HSSFChart.getSheetCharts(s2);
- assertEquals(1, charts.length);
-
- assertEquals(2, charts[0].getSeries().length);
- assertEquals("1st Column", charts[0].getSeries()[0].getSeriesTitle());
- assertEquals("2nd Column", charts[0].getSeries()[1].getSeriesTitle());
- assertNull(charts[0].getChartTitle());
-
- // And the third sheet
- charts = HSSFChart.getSheetCharts(s3);
- assertEquals(1, charts.length);
-
- assertEquals(2, charts[0].getSeries().length);
- assertEquals("Squares", charts[0].getSeries()[0].getSeriesTitle());
- assertEquals("Base Numbers", charts[0].getSeries()[1].getSeriesTitle());
- assertNull(charts[0].getChartTitle());
- }
-
- @Test
- public void testThreeCharts() {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithThreeCharts.xls");
-
- HSSFSheet s1 = wb.getSheetAt(0);
- HSSFSheet s2 = wb.getSheetAt(1);
- HSSFSheet s3 = wb.getSheetAt(2);
-
- assertEquals(0, HSSFChart.getSheetCharts(s1).length);
- assertEquals(2, HSSFChart.getSheetCharts(s2).length);
- assertEquals(1, HSSFChart.getSheetCharts(s3).length);
-
- HSSFChart[] charts;
-
- // Check the charts on the 2nd sheet
- charts = HSSFChart.getSheetCharts(s2);
- assertEquals(2, charts.length);
-
- assertEquals(2, charts[0].getSeries().length);
- assertEquals("1st Column", charts[0].getSeries()[0].getSeriesTitle());
- assertEquals("2nd Column", charts[0].getSeries()[1].getSeriesTitle());
- assertEquals(6, charts[0].getSeries()[0].getNumValues());
- assertEquals(6, charts[0].getSeries()[1].getNumValues());
- assertEquals(SeriesRecord.CATEGORY_DATA_TYPE_NUMERIC, charts[0].getSeries()[0].getValueType());
- assertEquals(SeriesRecord.CATEGORY_DATA_TYPE_NUMERIC, charts[0].getSeries()[1].getValueType());
- assertNull(charts[0].getChartTitle());
-
- assertEquals(1, charts[1].getSeries().length);
- assertNull(charts[1].getSeries()[0].getSeriesTitle());
- assertEquals("Pie Chart Title Thingy", charts[1].getChartTitle());
-
- // And the third sheet
- charts = HSSFChart.getSheetCharts(s3);
- assertEquals(1, charts.length);
-
- assertEquals(2, charts[0].getSeries().length);
- assertEquals("Squares", charts[0].getSeries()[0].getSeriesTitle());
- assertEquals("Base Numbers", charts[0].getSeries()[1].getSeriesTitle());
- assertEquals("Sheet 3 Chart with Title", charts[0].getChartTitle());
- }
-
- @Test
- public void testExistingSheet3() throws Exception {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls");
-
- HSSFSheet sheet = wb.getSheetAt( 2 ) ;
- HSSFChart[] charts = HSSFChart.getSheetCharts( sheet ) ;
- assertEquals(1, charts.length);
-
- for ( HSSFChart chart : charts ) {
- for ( HSSFSeries series : chart.getSeries() ) {
- chart.removeSeries( series ) ;
- }
- }
-
- // Save and re-check
- wb = HSSFITestDataProvider.instance.writeOutAndReadBack(wb);
- sheet = wb.getSheetAt( 2 ) ;
- assertEquals(1, HSSFChart.getSheetCharts(sheet).length);
-
- HSSFChart c = HSSFChart.getSheetCharts(sheet)[0];
- assertEquals(0, c.getSeries().length);
- }
-
- @Test
- public void testExistingSheet2() throws Exception {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls");
- HSSFSheet sheet = wb.getSheetAt( 1 ) ;
- HSSFChart[] charts = HSSFChart.getSheetCharts( sheet ) ;
-
- assertEquals(1, charts.length);
- for ( HSSFChart chart : charts ) {
- HSSFSeries series ;
-
- // Starts with one
- assertEquals(1, chart.getSeries().length);
-
- // Add two more
- series = chart.createSeries() ;
- series.setCategoryLabelsCellRange( new CellRangeAddress( 3, 4, 0, 0 ) ) ;
- series.setValuesCellRange( new CellRangeAddress( 3, 4, 1, 1 ) ) ;
-
- series = chart.createSeries() ;
- series.setCategoryLabelsCellRange( new CellRangeAddress( 6, 7, 0, 0 ) ) ;
- series.setValuesCellRange( new CellRangeAddress( 6, 7, 1, 1 ) ) ;
- }
-
- // Save and re-check
- wb = HSSFITestDataProvider.instance.writeOutAndReadBack(wb);
- sheet = wb.getSheetAt( 1 ) ;
- assertEquals(1, HSSFChart.getSheetCharts(sheet).length);
-
- HSSFChart c = HSSFChart.getSheetCharts(sheet)[0];
- assertEquals(3, c.getSeries().length);
- }
-
- @Test
- public void testExistingSheet1() throws Exception {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls");
- HSSFSheet sheet = wb.getSheetAt( 0 ) ;
- HSSFChart[] charts = HSSFChart.getSheetCharts( sheet ) ;
-
- for ( HSSFChart chart : charts ) {
- //System.out.println( chart.getType() ) ;
- HSSFSeries[] seriesArray = chart.getSeries() ;
- //System.out.println( "seriesArray.length=" + seriesArray.length ) ;
- for ( HSSFSeries series : seriesArray )
- {
- //System.out.println( "serie.getNumValues()=" + series.getNumValues() ) ;
- CellRangeAddressBase range ;
-
- range = series.getValuesCellRange() ;
- //System.out.println( range.toString() ) ;
- range.setLastRow( range.getLastRow() + 1 ) ;
- series.setValuesCellRange( range ) ;
-
- range = series.getCategoryLabelsCellRange() ;
- //System.out.println( range.toString() ) ;
- range.setLastRow( range.getLastRow() + 1 ) ;
- series.setCategoryLabelsCellRange( range ) ;
- }
-
- for ( int id = 0 ; id < 2 ; id++ )
- {
- HSSFSeries newSeries = chart.createSeries() ;
- newSeries.setValuesCellRange( new CellRangeAddress( 1 + id, 4, 3, 3 ) ) ;
- String oldSeriesTitle = newSeries.getSeriesTitle() ;
- if ( oldSeriesTitle != null )
- {
- //System.out.println( "old series title: " + oldSeriesTitle ) ;
- newSeries.setSeriesTitle( "new series" ) ;
- }
- }
- }
-
- HSSFChart chart = charts[ 2 ] ;
- chart.removeSeries( chart.getSeries()[ 0 ] ) ;
- }
-
- /**
- * Bug 26862: HSSFWorkbook.cloneSheet copies charts
- */
- @Test
- public void test26862() throws IOException, Exception {
- HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SimpleChart.xls");
- HSSFSheet srcSheet = wb.getSheetAt(0);
- HSSFChart[] srcCharts = HSSFChart.getSheetCharts(srcSheet);
- assertEquals(1, srcCharts.length);
- HSSFChart srcChart = srcCharts[0];
-
- // Clone the sheet
- HSSFSheet clonedSheet = wb.cloneSheet(0);
-
- // Verify the chart was copied
- HSSFChart[] clonedCharts = HSSFChart.getSheetCharts(clonedSheet);
- assertEquals(1, clonedCharts.length);
- HSSFChart clonedChart = clonedCharts[0];
- assertNotSame(srcChart, clonedChart); //refer to different objects
- assertEquals(srcChart.getType(), clonedChart.getType());
- assertEquals(srcChart.getChartTitle(), clonedChart.getChartTitle());
- assertEquals(srcChart.getChartWidth(), clonedChart.getChartWidth());
- assertEquals(srcChart.getChartHeight(), clonedChart.getChartHeight());
- assertEquals(srcChart.getChartX(), clonedChart.getChartX());
- assertEquals(srcChart.getChartY(), clonedChart.getChartY());
-
- // Check if chart was shallow copied or deep copied
- clonedChart.setChartWidth(clonedChart.getChartWidth()+10);
- assertEquals(srcChart.getChartWidth()+10, clonedChart.getChartWidth());
-
- wb.close();
- }
-}
--- /dev/null
+/* ====================================================================
+ 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;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.font.TextLayout;
+import java.awt.image.BufferedImage;
+import java.text.AttributedString;
+
+import org.junit.Test;
+
+/**
+ * Minimal Test-Class found when running the Apache POI regression tests.
+ *
+ * This reproduces a crash introduced in JDK 12-ea+28 and JDK 13-ea+4
+ *
+ * This works in recent JDK 8, JDK 11 and at least up to JDK 12-ea+20
+ *
+ * https://bugs.openjdk.java.net/browse/JDK-8217768
+ *
+ * Should be fixed in JDK 12-ea+29 and JDK 13-ea+5
+ */
+public class TestJDK12 {
+ @Test
+ public void test() throws Exception {
+ BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D graphics = img.createGraphics();
+ graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ graphics.scale(200, 1);
+
+ new TextLayout(new AttributedString("agriculture").getIterator(), graphics.getFontRenderContext());
+
+ graphics.dispose();
+ img.flush();
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.dev;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.util.NullOutputStream;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Base class for integration-style tests which iterate over all test-files
+ * and execute the same action to find out if any change breaks these applications.
+ *
+ * This test uses {@link Parameterized} to run the test for each file separatedely.
+ */
+@RunWith(Parameterized.class)
+public abstract class BaseTestIteratingXLS {
+ protected static final OutputStream NULL_OUTPUT_STREAM = new NullOutputStream();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ protected static final Map<String,Class<? extends Throwable>> EXCLUDED =
+ new HashMap<>();
+
+ @Parameters(name="{index}: {0}")
+ public static Iterable<Object[]> files() {
+ String dataDirName = System.getProperty(POIDataSamples.TEST_PROPERTY);
+ if(dataDirName == null) {
+ dataDirName = "test-data";
+ }
+
+ List<Object[]> files = new ArrayList<>();
+ findFile(files, dataDirName + "/spreadsheet");
+ findFile(files, dataDirName + "/hpsf");
+
+ return files;
+ }
+
+ private static void findFile(List<Object[]> list, String dir) {
+ String[] files = new File(dir).list((arg0, arg1) -> arg1.toLowerCase(Locale.ROOT).endsWith(".xls"));
+
+ assertNotNull("Did not find any xls files in directory " + dir, files);
+
+ for(String file : files) {
+ list.add(new Object[] { new File(dir, file) });
+ }
+ }
+
+ @Parameter
+ public File file;
+
+ @Test
+ public void testMain() throws Exception {
+ String fileName = file.getName();
+ if (EXCLUDED.containsKey(fileName)) {
+ thrown.expect(EXCLUDED.get(fileName));
+ }
+
+ try {
+ runOneFile(file);
+ } catch (Exception e) {
+ // try to read it in HSSFWorkbook to quickly fail if we cannot read the file there at all and thus probably should use EXCLUDED instead
+ try (FileInputStream stream = new FileInputStream(file); HSSFWorkbook wb = new HSSFWorkbook(stream)) {
+ assertNotNull(wb);
+ }
+
+ throw e;
+ }
+ }
+
+ abstract void runOneFile(File pFile) throws Exception;
+}
+++ /dev/null
-/* ====================================================================
- 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.dev;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.util.NullOutputStream;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * Base class for integration-style tests which iterate over all test-files
- * and execute the same action to find out if any change breaks these applications.
- *
- * This test uses {@link Parameterized} to run the test for each file separatedely.
- */
-@RunWith(Parameterized.class)
-public abstract class BaseXLSIteratingTest {
- protected static final OutputStream NULL_OUTPUT_STREAM = new NullOutputStream();
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- protected static final Map<String,Class<? extends Throwable>> EXCLUDED =
- new HashMap<>();
-
- @Parameters(name="{index}: {0}")
- public static Iterable<Object[]> files() {
- String dataDirName = System.getProperty(POIDataSamples.TEST_PROPERTY);
- if(dataDirName == null) {
- dataDirName = "test-data";
- }
-
- List<Object[]> files = new ArrayList<>();
- findFile(files, dataDirName + "/spreadsheet");
- findFile(files, dataDirName + "/hpsf");
-
- return files;
- }
-
- private static void findFile(List<Object[]> list, String dir) {
- String[] files = new File(dir).list((arg0, arg1) -> arg1.toLowerCase(Locale.ROOT).endsWith(".xls"));
-
- assertNotNull("Did not find any xls files in directory " + dir, files);
-
- for(String file : files) {
- list.add(new Object[] { new File(dir, file) });
- }
- }
-
- @Parameter
- public File file;
-
- @Test
- public void testMain() throws Exception {
- String fileName = file.getName();
- if (EXCLUDED.containsKey(fileName)) {
- thrown.expect(EXCLUDED.get(fileName));
- }
-
- try {
- runOneFile(file);
- } catch (Exception e) {
- // try to read it in HSSFWorkbook to quickly fail if we cannot read the file there at all and thus probably should use EXCLUDED instead
- try (FileInputStream stream = new FileInputStream(file); HSSFWorkbook wb = new HSSFWorkbook(stream)) {
- assertNotNull(wb);
- }
-
- throw e;
- }
- }
-
- abstract void runOneFile(File pFile) throws Exception;
-}
import org.apache.poi.util.RecordFormatException;
import org.junit.BeforeClass;
-public class TestBiffDrawingToXml extends BaseXLSIteratingTest {
+public class TestBiffDrawingToXml extends BaseTestIteratingXLS {
@BeforeClass
public static void setup() {
EXCLUDED.clear();
import org.junit.Ignore;
import org.junit.Test;
-public class TestBiffViewer extends BaseXLSIteratingTest {
+public class TestBiffViewer extends BaseTestIteratingXLS {
@BeforeClass
public static void setup() {
EXCLUDED.clear();
import org.apache.poi.util.RecordFormatException;
import org.junit.BeforeClass;
-public class TestEFBiffViewer extends BaseXLSIteratingTest {
+public class TestEFBiffViewer extends BaseTestIteratingXLS {
@BeforeClass
public static void setup() {
EXCLUDED.clear();
import org.apache.poi.util.RecordFormatException;
import org.junit.BeforeClass;
-public class TestFormulaViewer extends BaseXLSIteratingTest {
+public class TestFormulaViewer extends BaseTestIteratingXLS {
@BeforeClass
public static void setup() {
EXCLUDED.clear();
import org.junit.Ignore;
import org.junit.Test;
-public class TestReSave extends BaseXLSIteratingTest {
+public class TestReSave extends BaseTestIteratingXLS {
@BeforeClass
public static void setup() {
EXCLUDED.clear();
import org.apache.poi.util.RecordFormatException;
import org.junit.BeforeClass;
-public class TestRecordLister extends BaseXLSIteratingTest {
+public class TestRecordLister extends BaseTestIteratingXLS {
@BeforeClass
public static void setup() {
EXCLUDED.clear();
EXCLUDED.put("61300.xls", RecordFormatException.class);
EXCLUDED.put("64130.xls", OldExcelFormatException.class); //Biff 5
}
-
+
@Override
void runOneFile(File fileIn) throws IOException {
PrintStream save = System.out;
--- /dev/null
+/* ====================================================================
+ 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.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+
+import org.apache.poi.hssf.HSSFITestDataProvider;
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.record.chart.SeriesRecord;
+import org.apache.poi.hssf.usermodel.HSSFChart.HSSFSeries;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellRangeAddressBase;
+import org.junit.Test;
+
+/**
+ * Tests for {@link HSSFChart}
+ */
+public final class TestHSSFChart {
+
+ @Test
+ public void testSingleChart() {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithChart.xls");
+
+ HSSFSheet s1 = wb.getSheetAt(0);
+ HSSFSheet s2 = wb.getSheetAt(1);
+ HSSFSheet s3 = wb.getSheetAt(2);
+
+ assertEquals(0, HSSFChart.getSheetCharts(s1).length);
+ assertEquals(1, HSSFChart.getSheetCharts(s2).length);
+ assertEquals(0, HSSFChart.getSheetCharts(s3).length);
+
+ HSSFChart[] charts;
+
+ // Check the chart on the 2nd sheet
+ charts = HSSFChart.getSheetCharts(s2);
+ assertEquals(1, charts.length);
+
+ assertEquals(2, charts[0].getSeries().length);
+ assertEquals("1st Column", charts[0].getSeries()[0].getSeriesTitle());
+ assertEquals("2nd Column", charts[0].getSeries()[1].getSeriesTitle());
+ assertNull(charts[0].getChartTitle());
+
+ // Check x, y, width, height
+ assertEquals(0, charts[0].getChartX());
+ assertEquals(0, charts[0].getChartY());
+ assertEquals(26492928, charts[0].getChartWidth());
+ assertEquals(15040512, charts[0].getChartHeight());
+ }
+
+ @Test
+ public void testTwoCharts() {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithTwoCharts.xls");
+
+ HSSFSheet s1 = wb.getSheetAt(0);
+ HSSFSheet s2 = wb.getSheetAt(1);
+ HSSFSheet s3 = wb.getSheetAt(2);
+
+ assertEquals(0, HSSFChart.getSheetCharts(s1).length);
+ assertEquals(1, HSSFChart.getSheetCharts(s2).length);
+ assertEquals(1, HSSFChart.getSheetCharts(s3).length);
+
+ HSSFChart[] charts;
+
+ // Check the chart on the 2nd sheet
+ charts = HSSFChart.getSheetCharts(s2);
+ assertEquals(1, charts.length);
+
+ assertEquals(2, charts[0].getSeries().length);
+ assertEquals("1st Column", charts[0].getSeries()[0].getSeriesTitle());
+ assertEquals("2nd Column", charts[0].getSeries()[1].getSeriesTitle());
+ assertNull(charts[0].getChartTitle());
+
+ // And the third sheet
+ charts = HSSFChart.getSheetCharts(s3);
+ assertEquals(1, charts.length);
+
+ assertEquals(2, charts[0].getSeries().length);
+ assertEquals("Squares", charts[0].getSeries()[0].getSeriesTitle());
+ assertEquals("Base Numbers", charts[0].getSeries()[1].getSeriesTitle());
+ assertNull(charts[0].getChartTitle());
+ }
+
+ @Test
+ public void testThreeCharts() {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithThreeCharts.xls");
+
+ HSSFSheet s1 = wb.getSheetAt(0);
+ HSSFSheet s2 = wb.getSheetAt(1);
+ HSSFSheet s3 = wb.getSheetAt(2);
+
+ assertEquals(0, HSSFChart.getSheetCharts(s1).length);
+ assertEquals(2, HSSFChart.getSheetCharts(s2).length);
+ assertEquals(1, HSSFChart.getSheetCharts(s3).length);
+
+ HSSFChart[] charts;
+
+ // Check the charts on the 2nd sheet
+ charts = HSSFChart.getSheetCharts(s2);
+ assertEquals(2, charts.length);
+
+ assertEquals(2, charts[0].getSeries().length);
+ assertEquals("1st Column", charts[0].getSeries()[0].getSeriesTitle());
+ assertEquals("2nd Column", charts[0].getSeries()[1].getSeriesTitle());
+ assertEquals(6, charts[0].getSeries()[0].getNumValues());
+ assertEquals(6, charts[0].getSeries()[1].getNumValues());
+ assertEquals(SeriesRecord.CATEGORY_DATA_TYPE_NUMERIC, charts[0].getSeries()[0].getValueType());
+ assertEquals(SeriesRecord.CATEGORY_DATA_TYPE_NUMERIC, charts[0].getSeries()[1].getValueType());
+ assertNull(charts[0].getChartTitle());
+
+ assertEquals(1, charts[1].getSeries().length);
+ assertNull(charts[1].getSeries()[0].getSeriesTitle());
+ assertEquals("Pie Chart Title Thingy", charts[1].getChartTitle());
+
+ // And the third sheet
+ charts = HSSFChart.getSheetCharts(s3);
+ assertEquals(1, charts.length);
+
+ assertEquals(2, charts[0].getSeries().length);
+ assertEquals("Squares", charts[0].getSeries()[0].getSeriesTitle());
+ assertEquals("Base Numbers", charts[0].getSeries()[1].getSeriesTitle());
+ assertEquals("Sheet 3 Chart with Title", charts[0].getChartTitle());
+ }
+
+ @Test
+ public void testExistingSheet3() throws Exception {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls");
+
+ HSSFSheet sheet = wb.getSheetAt( 2 ) ;
+ HSSFChart[] charts = HSSFChart.getSheetCharts( sheet ) ;
+ assertEquals(1, charts.length);
+
+ for ( HSSFChart chart : charts ) {
+ for ( HSSFSeries series : chart.getSeries() ) {
+ chart.removeSeries( series ) ;
+ }
+ }
+
+ // Save and re-check
+ wb = HSSFITestDataProvider.instance.writeOutAndReadBack(wb);
+ sheet = wb.getSheetAt( 2 ) ;
+ assertEquals(1, HSSFChart.getSheetCharts(sheet).length);
+
+ HSSFChart c = HSSFChart.getSheetCharts(sheet)[0];
+ assertEquals(0, c.getSeries().length);
+ }
+
+ @Test
+ public void testExistingSheet2() throws Exception {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls");
+ HSSFSheet sheet = wb.getSheetAt( 1 ) ;
+ HSSFChart[] charts = HSSFChart.getSheetCharts( sheet ) ;
+
+ assertEquals(1, charts.length);
+ for ( HSSFChart chart : charts ) {
+ HSSFSeries series ;
+
+ // Starts with one
+ assertEquals(1, chart.getSeries().length);
+
+ // Add two more
+ series = chart.createSeries() ;
+ series.setCategoryLabelsCellRange( new CellRangeAddress( 3, 4, 0, 0 ) ) ;
+ series.setValuesCellRange( new CellRangeAddress( 3, 4, 1, 1 ) ) ;
+
+ series = chart.createSeries() ;
+ series.setCategoryLabelsCellRange( new CellRangeAddress( 6, 7, 0, 0 ) ) ;
+ series.setValuesCellRange( new CellRangeAddress( 6, 7, 1, 1 ) ) ;
+ }
+
+ // Save and re-check
+ wb = HSSFITestDataProvider.instance.writeOutAndReadBack(wb);
+ sheet = wb.getSheetAt( 1 ) ;
+ assertEquals(1, HSSFChart.getSheetCharts(sheet).length);
+
+ HSSFChart c = HSSFChart.getSheetCharts(sheet)[0];
+ assertEquals(3, c.getSeries().length);
+ }
+
+ @Test
+ public void testExistingSheet1() throws Exception {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls");
+ HSSFSheet sheet = wb.getSheetAt( 0 ) ;
+ HSSFChart[] charts = HSSFChart.getSheetCharts( sheet ) ;
+
+ for ( HSSFChart chart : charts ) {
+ //System.out.println( chart.getType() ) ;
+ HSSFSeries[] seriesArray = chart.getSeries() ;
+ //System.out.println( "seriesArray.length=" + seriesArray.length ) ;
+ for ( HSSFSeries series : seriesArray )
+ {
+ //System.out.println( "serie.getNumValues()=" + series.getNumValues() ) ;
+ CellRangeAddressBase range ;
+
+ range = series.getValuesCellRange() ;
+ //System.out.println( range.toString() ) ;
+ range.setLastRow( range.getLastRow() + 1 ) ;
+ series.setValuesCellRange( range ) ;
+
+ range = series.getCategoryLabelsCellRange() ;
+ //System.out.println( range.toString() ) ;
+ range.setLastRow( range.getLastRow() + 1 ) ;
+ series.setCategoryLabelsCellRange( range ) ;
+ }
+
+ for ( int id = 0 ; id < 2 ; id++ )
+ {
+ HSSFSeries newSeries = chart.createSeries() ;
+ newSeries.setValuesCellRange( new CellRangeAddress( 1 + id, 4, 3, 3 ) ) ;
+ String oldSeriesTitle = newSeries.getSeriesTitle() ;
+ if ( oldSeriesTitle != null )
+ {
+ //System.out.println( "old series title: " + oldSeriesTitle ) ;
+ newSeries.setSeriesTitle( "new series" ) ;
+ }
+ }
+ }
+
+ HSSFChart chart = charts[ 2 ] ;
+ chart.removeSeries( chart.getSeries()[ 0 ] ) ;
+ }
+
+ /**
+ * Bug 26862: HSSFWorkbook.cloneSheet copies charts
+ */
+ @Test
+ public void test26862() throws IOException, Exception {
+ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SimpleChart.xls");
+ HSSFSheet srcSheet = wb.getSheetAt(0);
+ HSSFChart[] srcCharts = HSSFChart.getSheetCharts(srcSheet);
+ assertEquals(1, srcCharts.length);
+ HSSFChart srcChart = srcCharts[0];
+
+ // Clone the sheet
+ HSSFSheet clonedSheet = wb.cloneSheet(0);
+
+ // Verify the chart was copied
+ HSSFChart[] clonedCharts = HSSFChart.getSheetCharts(clonedSheet);
+ assertEquals(1, clonedCharts.length);
+ HSSFChart clonedChart = clonedCharts[0];
+ assertNotSame(srcChart, clonedChart); //refer to different objects
+ assertEquals(srcChart.getType(), clonedChart.getType());
+ assertEquals(srcChart.getChartTitle(), clonedChart.getChartTitle());
+ assertEquals(srcChart.getChartWidth(), clonedChart.getChartWidth());
+ assertEquals(srcChart.getChartHeight(), clonedChart.getChartHeight());
+ assertEquals(srcChart.getChartX(), clonedChart.getChartX());
+ assertEquals(srcChart.getChartY(), clonedChart.getChartY());
+
+ // Check if chart was shallow copied or deep copied
+ clonedChart.setChartWidth(clonedChart.getChartWidth()+10);
+ assertEquals(srcChart.getChartWidth()+10, clonedChart.getChartWidth());
+
+ wb.close();
+ }
+}
import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.ss.usermodel.TestRangeCopier;
+import org.apache.poi.ss.usermodel.BaseTestRangeCopier;
import org.junit.Before;
-public class TestHSSFRangeCopier extends TestRangeCopier {
+public class TestHSSFRangeCopier extends BaseTestRangeCopier {
public TestHSSFRangeCopier() {
super();
+++ /dev/null
-/* ====================================================================
- 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.sl;
-
-import java.awt.Color;
-
-import org.apache.poi.sl.draw.DrawPaint;
-import org.apache.poi.sl.usermodel.PaintStyle;
-import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
-import org.junit.Ignore;
-
-/**
- * Currently only contains helper methods
- */
-@Ignore
-public class TestCommonSL {
-
- public static Color getColor(PaintStyle paintActual) {
- return (paintActual instanceof SolidPaint)
- ? DrawPaint.applyColorTransform(((SolidPaint)paintActual).getSolidColor())
- : null;
- }
-
-}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.sl.draw.geom;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+/**
+ * Date: 10/24/11
+ *
+ * @author Yegor Kozlov
+ */
+public class TestFormulaParser {
+ @Test
+ public void testParse(){
+
+ Formula[] ops = {
+ newGuide("adj1", "val 100"),
+ newGuide("adj2", "val 200"),
+ newGuide("adj3", "val -1"),
+ newGuide("a1", "*/ adj1 2 adj2"), // a1 = 100*2 / 200
+ newGuide("a2", "+- adj2 a1 adj1"), // a2 = 200 + a1 - 100
+ newGuide("a3", "+/ adj1 adj2 adj2"), // a3 = (100 + 200) / 200
+ newGuide("a4", "?: adj3 adj1 adj2"), // a4 = adj3 > 0 ? adj1 : adj2
+ newGuide("a5", "abs -2"),
+ };
+
+ CustomGeometry geom = new CustomGeometry();
+ Context ctx = new Context(geom, null, null);
+ for(Formula fmla : ops) {
+ ctx.evaluate(fmla);
+ }
+
+ assertEquals(100.0, ctx.getValue("adj1"), 0.0);
+ assertEquals(200.0, ctx.getValue("adj2"), 0.0);
+ assertEquals(1.0, ctx.getValue("a1"), 0.0);
+ assertEquals(101.0, ctx.getValue("a2"), 0.0);
+ assertEquals(1.5, ctx.getValue("a3"), 0.0);
+ assertEquals(200.0, ctx.getValue("a4"), 0.0);
+ assertEquals(2.0, ctx.getValue("a5"), 0.0);
+ }
+
+ private static Guide newGuide(String name, String fmla) {
+ Guide gd = new Guide();
+ gd.setName(name);
+ gd.setFmla(fmla);
+ return gd;
+ }
+}
import org.apache.poi.POIDataSamples;
import org.apache.poi.common.usermodel.fonts.FontInfo;
+import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.sl.usermodel.TabStop.TabStopType;
import org.junit.Test;
P extends TextParagraph<S,P,? extends TextRun>
> {
protected static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
-
+
public abstract SlideShow<S,P> createSlideShow();
public abstract SlideShow<S,P> reopen(SlideShow<S,P> show);
-
+
@Test
public void addPicture_File() throws IOException {
SlideShow<S,P> show = createSlideShow();
File f = slTests.getFile("clock.jpg");
-
+
assertEquals(0, show.getPictureData().size());
PictureData picture = show.addPicture(f, PictureType.JPEG);
assertEquals(1, show.getPictureData().size());
assertSame(picture, show.getPictureData().get(0));
-
+
show.close();
}
-
+
@Test
public void addPicture_Stream() throws IOException {
try (SlideShow<S,P> show = createSlideShow();
assertSame(picture, show.getPictureData().get(0));
}
}
-
+
@Test
public void addPicture_ByteArray() throws IOException {
SlideShow<S,P> show = createSlideShow();
byte[] data = slTests.readFile("clock.jpg");
-
+
assertEquals(0, show.getPictureData().size());
PictureData picture = show.addPicture(data, PictureType.JPEG);
assertEquals(1, show.getPictureData().size());
assertSame(picture, show.getPictureData().get(0));
-
+
show.close();
}
-
+
@Test
public void findPicture() throws IOException {
SlideShow<S,P> show = createSlideShow();
byte[] data = slTests.readFile("clock.jpg");
-
+
assertNull(show.findPictureData(data));
PictureData picture = show.addPicture(data, PictureType.JPEG);
PictureData found = show.findPictureData(data);
assertNotNull(found);
assertEquals(picture, found);
-
+
show.close();
}
-
+
@Test
public void addTabStops() throws IOException {
try (final SlideShow<S,P> show1 = createSlideShow()) {
master1_tp.addTabStops(10+i1*10, tst);
i1++;
}
-
+
// then set it on a normal slide
final Slide<S,P> slide1 = show1.createSlide();
final AutoShape<S,P> slide1_as = slide1.createAutoShape();
slide1_tp.addTabStops(15+i2*5, tst);
i2++;
}
-
+
try (final SlideShow<S,P> show2 = reopen(show1)) {
final MasterSheet<S,P> master2 = show2.getSlideMasters().get(0);
final AutoShape<S,P> master2_as = (AutoShape<S,P>)master2.getPlaceholder(Placeholder.BODY);
assertEquals(tst, ts.getType());
i3++;
}
-
-
+
+
final Slide<S,P> slide2 = show2.getSlides().get(0);
@SuppressWarnings("unchecked")
final AutoShape<S,P> slide2_as = (AutoShape<S,P>)slide2.getShapes().get(0);
i4++;
}
}
- }
+ }
}
@Test
}
}
}
+
+ public static Color getColor(PaintStyle paintActual) {
+ return (paintActual instanceof PaintStyle.SolidPaint)
+ ? DrawPaint.applyColorTransform(((PaintStyle.SolidPaint)paintActual).getSolidColor())
+ : null;
+ }
+
}
==================================================================== */
package org.apache.poi.ss.format;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
+import java.util.stream.Stream;
import javax.swing.JLabel;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
+import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
CellFormat cf = CellFormat.getInstance("\"ca. \"0");
assertEquals("ca. 5", cf.apply((double) 5).text);
}
+
+ @Test
+ public void testNamedColors() {
+ assertTrue(CellFormatPart.NAMED_COLORS.size() >= HSSFColor.HSSFColorPredefined.values().length);
+ Stream.of("GREEN", "Green", "RED", "Red", "BLUE", "Blue", "YELLOW", "Yellow")
+ .map(CellFormatPart.NAMED_COLORS::get)
+ .forEach(Assert::assertNotNull);
+ }
}
package org.apache.poi.ss.formula;
-import org.apache.poi.ss.formula.eval.forked.TestForkedEvaluator;
+import org.apache.poi.ss.formula.eval.forked.BaseTestForkedEvaluator;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
TestCellCacheEntry.class,
TestEvaluationCache.class,
TestWorkbookEvaluator.class,
- TestForkedEvaluator.class
+ BaseTestForkedEvaluator.class
})
public class AllSSFormulaTests {
}
--- /dev/null
+/*
+ * ====================================================================
+ * 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.ss.formula;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class BaseTestMissingWorkbook {
+ protected Workbook mainWorkbook;
+ protected Workbook sourceWorkbook;
+
+ protected final String MAIN_WORKBOOK_FILENAME;
+ protected final String SOURCE_DUMMY_WORKBOOK_FILENAME;
+ protected final String SOURCE_WORKBOOK_FILENAME;
+
+ public BaseTestMissingWorkbook() {
+ this("52575_main.xls", "source_dummy.xls", "52575_source.xls");
+ }
+
+ protected BaseTestMissingWorkbook(String MAIN_WORKBOOK_FILENAME,
+ String SOURCE_DUMMY_WORKBOOK_FILENAME, String SOURCE_WORKBOOK_FILENAME) {
+ this.MAIN_WORKBOOK_FILENAME = MAIN_WORKBOOK_FILENAME;
+ this.SOURCE_DUMMY_WORKBOOK_FILENAME = SOURCE_DUMMY_WORKBOOK_FILENAME;
+ this.SOURCE_WORKBOOK_FILENAME = SOURCE_WORKBOOK_FILENAME;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mainWorkbook = HSSFTestDataSamples.openSampleWorkbook(MAIN_WORKBOOK_FILENAME);
+ sourceWorkbook = HSSFTestDataSamples.openSampleWorkbook(SOURCE_WORKBOOK_FILENAME);
+
+ assertNotNull(mainWorkbook);
+ assertNotNull(sourceWorkbook);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if(mainWorkbook != null) {
+ mainWorkbook.close();
+ }
+
+ if(sourceWorkbook != null) {
+ sourceWorkbook.close();
+ }
+ }
+
+ @Test
+ public void testMissingWorkbookMissing() {
+ FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator();
+
+ Sheet lSheet = mainWorkbook.getSheetAt(0);
+ Row lARow = lSheet.getRow(0);
+ Cell lA1Cell = lARow.getCell(0);
+
+ assertEquals(CellType.FORMULA, lA1Cell.getCellType());
+ try {
+ evaluator.evaluateFormulaCell(lA1Cell);
+ fail("Missing external workbook reference exception expected!");
+ } catch(RuntimeException re) {
+ assertTrue("Unexpected exception: " + re, re.getMessage().contains(SOURCE_DUMMY_WORKBOOK_FILENAME));
+ }
+ }
+
+ @Test
+ public void testMissingWorkbookMissingOverride() {
+ Sheet lSheet = mainWorkbook.getSheetAt(0);
+ Cell lA1Cell = lSheet.getRow(0).getCell(0);
+ Cell lB1Cell = lSheet.getRow(1).getCell(0);
+ Cell lC1Cell = lSheet.getRow(2).getCell(0);
+
+ assertEquals(CellType.FORMULA, lA1Cell.getCellType());
+ assertEquals(CellType.FORMULA, lB1Cell.getCellType());
+ assertEquals(CellType.FORMULA, lC1Cell.getCellType());
+
+ // Check cached values
+ assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d);
+ assertEquals("POI rocks!", lB1Cell.getStringCellValue());
+ assertTrue(lC1Cell.getBooleanCellValue());
+
+ // Evaluate
+ FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator();
+ evaluator.setIgnoreMissingWorkbooks(true);
+
+ assertEquals(CellType.NUMERIC, evaluator.evaluateFormulaCell(lA1Cell));
+ assertEquals(CellType.STRING, evaluator.evaluateFormulaCell(lB1Cell));
+ assertEquals(CellType.BOOLEAN, evaluator.evaluateFormulaCell(lC1Cell));
+
+ assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d);
+ assertEquals("POI rocks!", lB1Cell.getStringCellValue());
+ assertTrue(lC1Cell.getBooleanCellValue());
+ }
+
+ @Test
+ public void testExistingWorkbook() {
+ Sheet lSheet = mainWorkbook.getSheetAt(0);
+ Cell lA1Cell = lSheet.getRow(0).getCell(0);
+ Cell lB1Cell = lSheet.getRow(1).getCell(0);
+ Cell lC1Cell = lSheet.getRow(2).getCell(0);
+
+ assertEquals(CellType.FORMULA, lA1Cell.getCellType());
+ assertEquals(CellType.FORMULA, lB1Cell.getCellType());
+ assertEquals(CellType.FORMULA, lC1Cell.getCellType());
+
+ FormulaEvaluator lMainWorkbookEvaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator();
+ FormulaEvaluator lSourceEvaluator = sourceWorkbook.getCreationHelper().createFormulaEvaluator();
+ Map<String,FormulaEvaluator> workbooks = new HashMap<>();
+ workbooks.put(MAIN_WORKBOOK_FILENAME, lMainWorkbookEvaluator);
+ workbooks.put(SOURCE_DUMMY_WORKBOOK_FILENAME, lSourceEvaluator);
+ lMainWorkbookEvaluator.setupReferencedWorkbooks(workbooks);
+
+ assertEquals(CellType.NUMERIC, lMainWorkbookEvaluator.evaluateFormulaCell(lA1Cell));
+ assertEquals(CellType.STRING, lMainWorkbookEvaluator.evaluateFormulaCell(lB1Cell));
+ assertEquals(CellType.BOOLEAN, lMainWorkbookEvaluator.evaluateFormulaCell(lC1Cell));
+
+ assertEquals(20.0d, lA1Cell.getNumericCellValue(), 0.00001d);
+ assertEquals("Apache rocks!", lB1Cell.getStringCellValue());
+ assertFalse(lC1Cell.getBooleanCellValue());
+ }
+}
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.formula;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class TestMissingWorkbook {
- protected Workbook mainWorkbook;
- protected Workbook sourceWorkbook;
-
- protected final String MAIN_WORKBOOK_FILENAME;
- protected final String SOURCE_DUMMY_WORKBOOK_FILENAME;
- protected final String SOURCE_WORKBOOK_FILENAME;
-
- public TestMissingWorkbook() {
- this("52575_main.xls", "source_dummy.xls", "52575_source.xls");
- }
-
- protected TestMissingWorkbook(String MAIN_WORKBOOK_FILENAME,
- String SOURCE_DUMMY_WORKBOOK_FILENAME, String SOURCE_WORKBOOK_FILENAME) {
- this.MAIN_WORKBOOK_FILENAME = MAIN_WORKBOOK_FILENAME;
- this.SOURCE_DUMMY_WORKBOOK_FILENAME = SOURCE_DUMMY_WORKBOOK_FILENAME;
- this.SOURCE_WORKBOOK_FILENAME = SOURCE_WORKBOOK_FILENAME;
- }
-
- @Before
- public void setUp() throws Exception {
- mainWorkbook = HSSFTestDataSamples.openSampleWorkbook(MAIN_WORKBOOK_FILENAME);
- sourceWorkbook = HSSFTestDataSamples.openSampleWorkbook(SOURCE_WORKBOOK_FILENAME);
-
- assertNotNull(mainWorkbook);
- assertNotNull(sourceWorkbook);
- }
-
- @After
- public void tearDown() throws Exception {
- if(mainWorkbook != null) {
- mainWorkbook.close();
- }
-
- if(sourceWorkbook != null) {
- sourceWorkbook.close();
- }
- }
-
- @Test
- public void testMissingWorkbookMissing() {
- FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator();
-
- Sheet lSheet = mainWorkbook.getSheetAt(0);
- Row lARow = lSheet.getRow(0);
- Cell lA1Cell = lARow.getCell(0);
-
- assertEquals(CellType.FORMULA, lA1Cell.getCellType());
- try {
- evaluator.evaluateFormulaCell(lA1Cell);
- fail("Missing external workbook reference exception expected!");
- } catch(RuntimeException re) {
- assertTrue("Unexpected exception: " + re, re.getMessage().contains(SOURCE_DUMMY_WORKBOOK_FILENAME));
- }
- }
-
- @Test
- public void testMissingWorkbookMissingOverride() {
- Sheet lSheet = mainWorkbook.getSheetAt(0);
- Cell lA1Cell = lSheet.getRow(0).getCell(0);
- Cell lB1Cell = lSheet.getRow(1).getCell(0);
- Cell lC1Cell = lSheet.getRow(2).getCell(0);
-
- assertEquals(CellType.FORMULA, lA1Cell.getCellType());
- assertEquals(CellType.FORMULA, lB1Cell.getCellType());
- assertEquals(CellType.FORMULA, lC1Cell.getCellType());
-
- // Check cached values
- assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d);
- assertEquals("POI rocks!", lB1Cell.getStringCellValue());
- assertTrue(lC1Cell.getBooleanCellValue());
-
- // Evaluate
- FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator();
- evaluator.setIgnoreMissingWorkbooks(true);
-
- assertEquals(CellType.NUMERIC, evaluator.evaluateFormulaCell(lA1Cell));
- assertEquals(CellType.STRING, evaluator.evaluateFormulaCell(lB1Cell));
- assertEquals(CellType.BOOLEAN, evaluator.evaluateFormulaCell(lC1Cell));
-
- assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d);
- assertEquals("POI rocks!", lB1Cell.getStringCellValue());
- assertTrue(lC1Cell.getBooleanCellValue());
- }
-
- @Test
- public void testExistingWorkbook() {
- Sheet lSheet = mainWorkbook.getSheetAt(0);
- Cell lA1Cell = lSheet.getRow(0).getCell(0);
- Cell lB1Cell = lSheet.getRow(1).getCell(0);
- Cell lC1Cell = lSheet.getRow(2).getCell(0);
-
- assertEquals(CellType.FORMULA, lA1Cell.getCellType());
- assertEquals(CellType.FORMULA, lB1Cell.getCellType());
- assertEquals(CellType.FORMULA, lC1Cell.getCellType());
-
- FormulaEvaluator lMainWorkbookEvaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator();
- FormulaEvaluator lSourceEvaluator = sourceWorkbook.getCreationHelper().createFormulaEvaluator();
- Map<String,FormulaEvaluator> workbooks = new HashMap<>();
- workbooks.put(MAIN_WORKBOOK_FILENAME, lMainWorkbookEvaluator);
- workbooks.put(SOURCE_DUMMY_WORKBOOK_FILENAME, lSourceEvaluator);
- lMainWorkbookEvaluator.setupReferencedWorkbooks(workbooks);
-
- assertEquals(CellType.NUMERIC, lMainWorkbookEvaluator.evaluateFormulaCell(lA1Cell));
- assertEquals(CellType.STRING, lMainWorkbookEvaluator.evaluateFormulaCell(lB1Cell));
- assertEquals(CellType.BOOLEAN, lMainWorkbookEvaluator.evaluateFormulaCell(lC1Cell));
-
- assertEquals(20.0d, lA1Cell.getNumericCellValue(), 0.00001d);
- assertEquals("Apache rocks!", lB1Cell.getStringCellValue());
- assertFalse(lC1Cell.getBooleanCellValue());
- }
-}
--- /dev/null
+/* ====================================================================
+ 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.ss.formula.eval.forked;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.formula.IStabilityClassifier;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class BaseTestForkedEvaluator {
+
+ @Rule
+ public ExpectedException expectedEx = ExpectedException.none();
+
+ protected Workbook newWorkbook() {
+ return new HSSFWorkbook();
+ }
+
+ /**
+ * set up a calculation workbook with input cells nicely segregated on a
+ * sheet called "Inputs"
+ */
+ protected Workbook createWorkbook() {
+ Workbook wb = newWorkbook();
+ Sheet sheet1 = wb.createSheet("Inputs");
+ Sheet sheet2 = wb.createSheet("Calculations");
+ Row row;
+ row = sheet2.createRow(0);
+ row.createCell(0).setCellFormula("B1*Inputs!A1-Inputs!B1");
+ row.createCell(1).setCellValue(5.0); // Calculations!B1
+
+ // some default input values
+ row = sheet1.createRow(0);
+ row.createCell(0).setCellValue(2.0); // Inputs!A1
+ row.createCell(1).setCellValue(3.0); // Inputs!B1
+ return wb;
+ }
+
+ /**
+ * Shows a basic use-case for {@link ForkedEvaluator}
+ */
+ @Test
+ public void testBasic() throws IOException {
+ Workbook wb = createWorkbook();
+
+ // The stability classifier is useful to reduce memory consumption of caching logic
+ IStabilityClassifier stabilityClassifier = (sheetIndex, rowIndex, columnIndex) -> sheetIndex == 1;
+
+ ForkedEvaluator fe1 = ForkedEvaluator.create(wb, stabilityClassifier, null);
+ ForkedEvaluator fe2 = ForkedEvaluator.create(wb, stabilityClassifier, null);
+
+ // fe1 and fe2 can be used concurrently on separate threads
+
+ fe1.updateCell("Inputs", 0, 0, new NumberEval(4.0));
+ fe1.updateCell("Inputs", 0, 1, new NumberEval(1.1));
+
+ fe2.updateCell("Inputs", 0, 0, new NumberEval(1.2));
+ fe2.updateCell("Inputs", 0, 1, new NumberEval(2.0));
+
+ NumberEval eval1 = (NumberEval) fe1.evaluate("Calculations", 0, 0);
+ assertNotNull(eval1);
+ assertEquals(18.9, eval1.getNumberValue(), 0.0);
+ NumberEval eval2 = (NumberEval) fe2.evaluate("Calculations", 0, 0);
+ assertNotNull(eval2);
+ assertEquals(4.0, eval2.getNumberValue(), 0.0);
+ fe1.updateCell("Inputs", 0, 0, new NumberEval(3.0));
+ eval1 = (NumberEval) fe1.evaluate("Calculations", 0, 0);
+ assertNotNull(eval1);
+ assertEquals(13.9, eval1.getNumberValue(), 0.0);
+
+ wb.close();
+ }
+
+ /**
+ * As of Sep 2009, the Forked evaluator can update values from existing cells (this is because
+ * the underlying 'master' cell is used as a key into the calculation cache. Prior to the fix
+ * for this bug, an attempt to update a missing cell would result in NPE. This junit tests for
+ * a more meaningful error message.<br>
+ *
+ * An alternate solution might involve allowing empty cells to be created as necessary. That
+ * was considered less desirable because so far, the underlying 'master' workbook is strictly
+ * <i>read-only</i> with respect to the ForkedEvaluator.
+ */
+ @Test
+ public void testMissingInputCellH() throws IOException {
+ expectedEx.expect(UnsupportedOperationException.class);
+ expectedEx.expectMessage("Underlying cell 'A2' is missing in master sheet.");
+
+ try (Workbook wb = createWorkbook()) {
+ ForkedEvaluator fe = ForkedEvaluator.create(wb, null, null);
+ // attempt update input at cell A2 (which is missing)
+ fe.updateCell("Inputs", 1, 0, new NumberEval(4.0));
+ }
+ }
+}
+++ /dev/null
-/* ====================================================================
- 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.ss.formula.eval.forked;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.IOException;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.ss.formula.IStabilityClassifier;
-import org.apache.poi.ss.formula.eval.NumberEval;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class TestForkedEvaluator {
-
- @Rule
- public ExpectedException expectedEx = ExpectedException.none();
-
- protected Workbook newWorkbook() {
- return new HSSFWorkbook();
- }
-
- /**
- * set up a calculation workbook with input cells nicely segregated on a
- * sheet called "Inputs"
- */
- protected Workbook createWorkbook() {
- Workbook wb = newWorkbook();
- Sheet sheet1 = wb.createSheet("Inputs");
- Sheet sheet2 = wb.createSheet("Calculations");
- Row row;
- row = sheet2.createRow(0);
- row.createCell(0).setCellFormula("B1*Inputs!A1-Inputs!B1");
- row.createCell(1).setCellValue(5.0); // Calculations!B1
-
- // some default input values
- row = sheet1.createRow(0);
- row.createCell(0).setCellValue(2.0); // Inputs!A1
- row.createCell(1).setCellValue(3.0); // Inputs!B1
- return wb;
- }
-
- /**
- * Shows a basic use-case for {@link ForkedEvaluator}
- */
- @Test
- public void testBasic() throws IOException {
- Workbook wb = createWorkbook();
-
- // The stability classifier is useful to reduce memory consumption of caching logic
- IStabilityClassifier stabilityClassifier = (sheetIndex, rowIndex, columnIndex) -> sheetIndex == 1;
-
- ForkedEvaluator fe1 = ForkedEvaluator.create(wb, stabilityClassifier, null);
- ForkedEvaluator fe2 = ForkedEvaluator.create(wb, stabilityClassifier, null);
-
- // fe1 and fe2 can be used concurrently on separate threads
-
- fe1.updateCell("Inputs", 0, 0, new NumberEval(4.0));
- fe1.updateCell("Inputs", 0, 1, new NumberEval(1.1));
-
- fe2.updateCell("Inputs", 0, 0, new NumberEval(1.2));
- fe2.updateCell("Inputs", 0, 1, new NumberEval(2.0));
-
- NumberEval eval1 = (NumberEval) fe1.evaluate("Calculations", 0, 0);
- assertNotNull(eval1);
- assertEquals(18.9, eval1.getNumberValue(), 0.0);
- NumberEval eval2 = (NumberEval) fe2.evaluate("Calculations", 0, 0);
- assertNotNull(eval2);
- assertEquals(4.0, eval2.getNumberValue(), 0.0);
- fe1.updateCell("Inputs", 0, 0, new NumberEval(3.0));
- eval1 = (NumberEval) fe1.evaluate("Calculations", 0, 0);
- assertNotNull(eval1);
- assertEquals(13.9, eval1.getNumberValue(), 0.0);
-
- wb.close();
- }
-
- /**
- * As of Sep 2009, the Forked evaluator can update values from existing cells (this is because
- * the underlying 'master' cell is used as a key into the calculation cache. Prior to the fix
- * for this bug, an attempt to update a missing cell would result in NPE. This junit tests for
- * a more meaningful error message.<br>
- *
- * An alternate solution might involve allowing empty cells to be created as necessary. That
- * was considered less desirable because so far, the underlying 'master' workbook is strictly
- * <i>read-only</i> with respect to the ForkedEvaluator.
- */
- @Test
- public void testMissingInputCellH() throws IOException {
- expectedEx.expect(UnsupportedOperationException.class);
- expectedEx.expectMessage("Underlying cell 'A2' is missing in master sheet.");
-
- try (Workbook wb = createWorkbook()) {
- ForkedEvaluator fe = ForkedEvaluator.create(wb, null, null);
- // attempt update input at cell A2 (which is missing)
- fe.updateCell("Inputs", 1, 0, new NumberEval(4.0));
- }
- }
-}
+++ /dev/null
-/*
-* 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.
-*/
-/*
- * Created on May 29, 2005
- *
- */
-package org.apache.poi.ss.formula.functions;
-
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public abstract class AbstractNumericTestCase {
-
- public static final double POS_ZERO = 1E-4;
- public static final double DIFF_TOLERANCE_FACTOR = 1E-8;
-
- /**
- * Why doesnt JUnit have a method like this for doubles?
- * The current impl (3.8.1) of Junit has a retar*** method
- * for comparing doubles. DO NOT use that.
- * TODO: This class should really be in an abstract super class
- * to avoid code duplication across this project.
- * @param message
- * @param baseval
- * @param checkval
- */
- public static void assertEquals(String message, double baseval, double checkval, double almostZero, double diffToleranceFactor) {
- double posZero = Math.abs(almostZero);
- double negZero = -1 * posZero;
- if (Double.isNaN(baseval)) {
- assertTrue(message+": Expected " + baseval + " but was " + checkval
- , Double.isNaN(baseval));
- }
- else if (Double.isInfinite(baseval)) {
- assertTrue(message+": Expected " + baseval + " but was " + checkval
- , Double.isInfinite(baseval) && ((baseval<0) == (checkval<0)));
- }
- else {
- assertTrue(message+": Expected " + baseval + " but was " + checkval
- ,baseval != 0
- ? Math.abs(baseval - checkval) <= Math.abs(diffToleranceFactor * baseval)
- : checkval < posZero && checkval > negZero);
- }
- }
-
- public static void assertEquals(String msg, double baseval, double checkval) {
- assertEquals(msg, baseval, checkval, POS_ZERO, DIFF_TOLERANCE_FACTOR);
- }
-
-
- public static void assertEquals(double baseval, double checkval) {
- assertEquals("", baseval, checkval, POS_ZERO, DIFF_TOLERANCE_FACTOR);
- }
-}
--- /dev/null
+/*
+* 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.
+*/
+/*
+ * Created on May 29, 2005
+ *
+ */
+package org.apache.poi.ss.formula.functions;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
+ *
+ */
+public abstract class BaseTestNumeric {
+
+ public static final double POS_ZERO = 1E-4;
+ public static final double DIFF_TOLERANCE_FACTOR = 1E-8;
+
+ /**
+ * Why doesnt JUnit have a method like this for doubles?
+ * The current impl (3.8.1) of Junit has a retar*** method
+ * for comparing doubles. DO NOT use that.
+ * TODO: This class should really be in an abstract super class
+ * to avoid code duplication across this project.
+ * @param message
+ * @param baseval
+ * @param checkval
+ */
+ public static void assertEquals(String message, double baseval, double checkval, double almostZero, double diffToleranceFactor) {
+ double posZero = Math.abs(almostZero);
+ double negZero = -1 * posZero;
+ if (Double.isNaN(baseval)) {
+ assertTrue(message+": Expected " + baseval + " but was " + checkval
+ , Double.isNaN(baseval));
+ }
+ else if (Double.isInfinite(baseval)) {
+ assertTrue(message+": Expected " + baseval + " but was " + checkval
+ , Double.isInfinite(baseval) && ((baseval<0) == (checkval<0)));
+ }
+ else {
+ assertTrue(message+": Expected " + baseval + " but was " + checkval
+ ,baseval != 0
+ ? Math.abs(baseval - checkval) <= Math.abs(diffToleranceFactor * baseval)
+ : checkval < posZero && checkval > negZero);
+ }
+ }
+
+ public static void assertEquals(String msg, double baseval, double checkval) {
+ assertEquals(msg, baseval, checkval, POS_ZERO, DIFF_TOLERANCE_FACTOR);
+ }
+
+
+ public static void assertEquals(double baseval, double checkval) {
+ assertEquals("", baseval, checkval, POS_ZERO, DIFF_TOLERANCE_FACTOR);
+ }
+}
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
*
*/
-public class TestFinanceLib extends AbstractNumericTestCase {
+public class TestFinanceLib extends BaseTestNumeric {
@Test
public void testFv() {
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
*
*/
-public class TestMathX extends AbstractNumericTestCase {
+public class TestMathX extends BaseTestNumeric {
@Test
public void testAcosh() {
import org.junit.Test;
-public class TestStatsLib extends AbstractNumericTestCase {
+public class TestStatsLib extends BaseTestNumeric {
@Test
public void testDevsq() {
*
* @author Stephen Wolke (smwolke at geistig.com)
*/
-public final class TestTrunc extends AbstractNumericTestCase {
+public final class TestTrunc extends BaseTestNumeric {
private static final NumericFunction F = null;
@Test
+++ /dev/null
-/* ====================================================================
- 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.ss.formula.ptg;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-
-/**
- * Convenient abstract class to reduce the amount of boilerplate code needed
- * in ptg-related unit tests.
- */
-public abstract class AbstractPtgTestCase {
-
- /**
- * Loads a workbook from the given filename in the test data dir.
- *
- * @param sampleFileName the filename.
- * @return the loaded workbook.
- */
- protected static HSSFWorkbook loadWorkbook(String sampleFileName) {
- return HSSFTestDataSamples.openSampleWorkbook(sampleFileName);
- }
-
- /**
- * Creates a new Workbook and adds one sheet with the specified name
- */
- protected static HSSFWorkbook createWorkbookWithSheet(String sheetName) {
- HSSFWorkbook book = new HSSFWorkbook();
- book.createSheet(sheetName);
- return book;
- }
-}
--- /dev/null
+/* ====================================================================
+ 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.ss.formula.ptg;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+/**
+ * Convenient abstract class to reduce the amount of boilerplate code needed
+ * in ptg-related unit tests.
+ */
+public abstract class BaseTestPtg {
+
+ /**
+ * Loads a workbook from the given filename in the test data dir.
+ *
+ * @param sampleFileName the filename.
+ * @return the loaded workbook.
+ */
+ protected static HSSFWorkbook loadWorkbook(String sampleFileName) {
+ return HSSFTestDataSamples.openSampleWorkbook(sampleFileName);
+ }
+
+ /**
+ * Creates a new Workbook and adds one sheet with the specified name
+ */
+ protected static HSSFWorkbook createWorkbookWithSheet(String sheetName) {
+ HSSFWorkbook book = new HSSFWorkbook();
+ book.createSheet(sheetName);
+ return book;
+ }
+}
/**
* Tests for Area3DPtg
*/
-public final class TestArea3DPtg extends AbstractPtgTestCase {
+public final class TestArea3DPtg extends BaseTestPtg {
/**
* confirms that sheet names get properly escaped
/**
* Tests for {@link AreaErrPtg}.
*/
-public final class TestAreaErrPtg extends AbstractPtgTestCase {
+public final class TestAreaErrPtg extends BaseTestPtg {
/**
* Tests reading a file containing this ptg.
*/
/**
* Tests for {@link AttrPtg}.
*/
-public final class TestAttrPtg extends AbstractPtgTestCase {
+public final class TestAttrPtg extends BaseTestPtg {
/**
* Fix for bug visible around svn r706772.
/**
* Tests for {@link ErrPtg}.
*/
-public final class TestErrPtg extends AbstractPtgTestCase {
+public final class TestErrPtg extends BaseTestPtg {
/**
* Tests reading a file containing this ptg.
*/
/**
* Tests for {@link IntersectionPtg}.
*/
-public final class TestIntersectionPtg extends AbstractPtgTestCase {
+public final class TestIntersectionPtg extends BaseTestPtg {
/**
* Tests reading a file containing this ptg.
*/
/**
* Tests for {@link PercentPtg}.
*/
-public final class TestPercentPtg extends AbstractPtgTestCase {
+public final class TestPercentPtg extends BaseTestPtg {
/**
* Tests reading a file containing this ptg.
*/
/**
* Tests for {@link RangePtg}.
*/
-public final class TestRangePtg extends AbstractPtgTestCase {
+public final class TestRangePtg extends BaseTestPtg {
/**
* Tests reading a file containing this ptg.
*/
/**
* Tests for Ref3DPtg
*/
-public final class TestRef3DPtg extends AbstractPtgTestCase {
+public final class TestRef3DPtg extends BaseTestPtg {
@Test
public void testToFormulaString() throws IOException {
/**
* Tests for {@link UnionPtg}.
*/
-public final class TestUnionPtg extends AbstractPtgTestCase {
+public final class TestUnionPtg extends BaseTestPtg {
/**
* Tests reading a file containing this ptg.
*/
--- /dev/null
+/*
+ * ====================================================================
+ * 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.ss.usermodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.poi.ss.ITestDataProvider;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore
+public abstract class BaseTestRangeCopier {
+ protected Sheet sheet1;
+ protected Sheet sheet2;
+ protected Workbook workbook;
+ protected RangeCopier rangeCopier;
+ protected RangeCopier transSheetRangeCopier;
+ protected ITestDataProvider testDataProvider;
+
+ protected void initSheets() {
+ sheet1 = workbook.getSheet("sheet1");
+ sheet2 = workbook.getSheet("sheet2");
+ }
+
+ @Test
+ public void copySheetRangeWithoutFormulas() {
+ CellRangeAddress rangeToCopy = CellRangeAddress.valueOf("B1:C2"); //2x2
+ CellRangeAddress destRange = CellRangeAddress.valueOf("C2:D3"); //2x2
+ rangeCopier.copyRange(rangeToCopy, destRange);
+ assertEquals("1.1", sheet1.getRow(2).getCell(2).toString());
+ assertEquals("2.1", sheet1.getRow(2).getCell(3).toString());
+ }
+
+ @Test
+ public void tileTheRangeAway() {
+ CellRangeAddress tileRange = CellRangeAddress.valueOf("C4:D5");
+ CellRangeAddress destRange = CellRangeAddress.valueOf("F4:K5");
+ rangeCopier.copyRange(tileRange, destRange);
+ assertEquals("1.3", getCellContent(sheet1, "H4"));
+ assertEquals("1.3", getCellContent(sheet1, "J4"));
+ assertEquals("$C1+G$2", getCellContent(sheet1, "G5"));
+ assertEquals("SUM(G3:I3)", getCellContent(sheet1, "H5"));
+ assertEquals("$C1+I$2", getCellContent(sheet1, "I5"));
+ assertEquals("", getCellContent(sheet1, "L5")); //out of borders
+ assertEquals("", getCellContent(sheet1, "G7")); //out of borders
+ }
+
+ @Test
+ public void tileTheRangeOver() {
+ CellRangeAddress tileRange = CellRangeAddress.valueOf("C4:D5");
+ CellRangeAddress destRange = CellRangeAddress.valueOf("A4:C5");
+ rangeCopier.copyRange(tileRange, destRange);
+ assertEquals("1.3", getCellContent(sheet1, "A4"));
+ assertEquals("$C1+B$2", getCellContent(sheet1, "B5"));
+ assertEquals("SUM(B3:D3)", getCellContent(sheet1, "C5"));
+ }
+
+ @Test
+ public void copyRangeToOtherSheet() {
+ Sheet destSheet = sheet2;
+ CellRangeAddress tileRange = CellRangeAddress.valueOf("C4:D5"); // on sheet1
+ CellRangeAddress destRange = CellRangeAddress.valueOf("F4:J6"); // on sheet2
+ transSheetRangeCopier.copyRange(tileRange, destRange);
+ assertEquals("1.3", getCellContent(destSheet, "H4"));
+ assertEquals("1.3", getCellContent(destSheet, "J4"));
+ assertEquals("$C1+G$2", getCellContent(destSheet, "G5"));
+ assertEquals("SUM(G3:I3)", getCellContent(destSheet, "H5"));
+ assertEquals("$C1+I$2", getCellContent(destSheet, "I5"));
+ }
+
+ @Test
+ public void testEmptyRow() {
+ // leave some rows empty in-between
+ Row row = sheet1.createRow(23);
+ row.createCell(0).setCellValue(1.2);
+
+ Sheet destSheet = sheet2;
+ CellRangeAddress tileRange = CellRangeAddress.valueOf("A1:A100"); // on sheet1
+ CellRangeAddress destRange = CellRangeAddress.valueOf("G1:G100"); // on sheet2
+ transSheetRangeCopier.copyRange(tileRange, destRange);
+
+ assertEquals("1.2", getCellContent(destSheet, "G24"));
+ }
+
+ @Test
+ public void testSameSheet() {
+ // leave some rows empty in-between
+ Row row = sheet1.createRow(23);
+ row.createCell(0).setCellValue(1.2);
+
+ CellRangeAddress tileRange = CellRangeAddress.valueOf("A1:A100"); // on sheet1
+ CellRangeAddress destRange = CellRangeAddress.valueOf("G1:G100"); // on sheet2
+
+ // use the a RangeCopier with the same Sheet for source and dest
+ rangeCopier.copyRange(tileRange, destRange);
+
+ assertEquals("1.2", getCellContent(sheet1, "G24"));
+ }
+
+ @Test
+ public void testCopyStyles() {
+ String cellContent = "D6 aligned to the right";
+ HorizontalAlignment toTheRight = HorizontalAlignment.RIGHT;
+ // create cell with content aligned to the right
+ CellStyle style = workbook.createCellStyle();
+ style.setAlignment(toTheRight);
+ Cell cell = sheet1.createRow(5).createCell(3);
+ cell.setCellValue(cellContent);
+ cell.setCellStyle(style);
+
+ Sheet destSheet = sheet2;
+ CellRangeAddress tileRange = CellRangeAddress.valueOf("D6:D6"); // on sheet1
+ CellRangeAddress destRange = CellRangeAddress.valueOf("J6:J6"); // on sheet2
+ transSheetRangeCopier.copyRange(tileRange, destRange, true, false);
+ assertEquals(cellContent, getCellContent(destSheet, "J6"));
+ assertEquals(toTheRight, getCell(destSheet, "J6").getCellStyle().getAlignment());
+ }
+
+ @Test
+ public void testMergedRanges() {
+ String cellContent = "D6 merged to E7";
+
+ // create cell merged from D6 to E7
+ CellRangeAddress mergedRangeAddress = new CellRangeAddress(5,6,3,4);
+ Cell cell = sheet1.createRow(5).createCell(3);
+ cell.setCellValue(cellContent);
+ sheet1.addMergedRegion(mergedRangeAddress);
+
+ Sheet destSheet = sheet2;
+ CellRangeAddress tileRange = CellRangeAddress.valueOf("D6:E7"); // on sheet1
+ transSheetRangeCopier.copyRange(tileRange, tileRange, false, true);
+ assertEquals(cellContent, getCellContent(destSheet, "D6"));
+ assertFalse(destSheet.getMergedRegions().isEmpty());
+ destSheet.getMergedRegions().forEach((mergedRegion) -> {
+ assertTrue(mergedRegion.equals(mergedRangeAddress));
+ });
+ }
+
+ protected static String getCellContent(Sheet sheet, String coordinates) {
+ Cell cell = getCell(sheet, coordinates);
+ return cell == null ? "" : cell.toString();
+ }
+
+ protected static Cell getCell(Sheet sheet, String coordinates) {
+ try {
+ CellReference p = new CellReference(coordinates);
+ return sheet.getRow(p.getRow()).getCell(p.getCol());
+ }
+ catch (NullPointerException e) { // row or cell does not exist
+ return null;
+ }
+ }
+}
+++ /dev/null
-/*
- * ====================================================================
- * 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.ss.usermodel;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellReference;
-
-import static org.junit.Assert.*;
-
-@Ignore
-public abstract class TestRangeCopier {
- protected Sheet sheet1;
- protected Sheet sheet2;
- protected Workbook workbook;
- protected RangeCopier rangeCopier;
- protected RangeCopier transSheetRangeCopier;
- protected ITestDataProvider testDataProvider;
-
- protected void initSheets() {
- sheet1 = workbook.getSheet("sheet1");
- sheet2 = workbook.getSheet("sheet2");
- }
-
- @Test
- public void copySheetRangeWithoutFormulas() {
- CellRangeAddress rangeToCopy = CellRangeAddress.valueOf("B1:C2"); //2x2
- CellRangeAddress destRange = CellRangeAddress.valueOf("C2:D3"); //2x2
- rangeCopier.copyRange(rangeToCopy, destRange);
- assertEquals("1.1", sheet1.getRow(2).getCell(2).toString());
- assertEquals("2.1", sheet1.getRow(2).getCell(3).toString());
- }
-
- @Test
- public void tileTheRangeAway() {
- CellRangeAddress tileRange = CellRangeAddress.valueOf("C4:D5");
- CellRangeAddress destRange = CellRangeAddress.valueOf("F4:K5");
- rangeCopier.copyRange(tileRange, destRange);
- assertEquals("1.3", getCellContent(sheet1, "H4"));
- assertEquals("1.3", getCellContent(sheet1, "J4"));
- assertEquals("$C1+G$2", getCellContent(sheet1, "G5"));
- assertEquals("SUM(G3:I3)", getCellContent(sheet1, "H5"));
- assertEquals("$C1+I$2", getCellContent(sheet1, "I5"));
- assertEquals("", getCellContent(sheet1, "L5")); //out of borders
- assertEquals("", getCellContent(sheet1, "G7")); //out of borders
- }
-
- @Test
- public void tileTheRangeOver() {
- CellRangeAddress tileRange = CellRangeAddress.valueOf("C4:D5");
- CellRangeAddress destRange = CellRangeAddress.valueOf("A4:C5");
- rangeCopier.copyRange(tileRange, destRange);
- assertEquals("1.3", getCellContent(sheet1, "A4"));
- assertEquals("$C1+B$2", getCellContent(sheet1, "B5"));
- assertEquals("SUM(B3:D3)", getCellContent(sheet1, "C5"));
- }
-
- @Test
- public void copyRangeToOtherSheet() {
- Sheet destSheet = sheet2;
- CellRangeAddress tileRange = CellRangeAddress.valueOf("C4:D5"); // on sheet1
- CellRangeAddress destRange = CellRangeAddress.valueOf("F4:J6"); // on sheet2
- transSheetRangeCopier.copyRange(tileRange, destRange);
- assertEquals("1.3", getCellContent(destSheet, "H4"));
- assertEquals("1.3", getCellContent(destSheet, "J4"));
- assertEquals("$C1+G$2", getCellContent(destSheet, "G5"));
- assertEquals("SUM(G3:I3)", getCellContent(destSheet, "H5"));
- assertEquals("$C1+I$2", getCellContent(destSheet, "I5"));
- }
-
- @Test
- public void testEmptyRow() {
- // leave some rows empty in-between
- Row row = sheet1.createRow(23);
- row.createCell(0).setCellValue(1.2);
-
- Sheet destSheet = sheet2;
- CellRangeAddress tileRange = CellRangeAddress.valueOf("A1:A100"); // on sheet1
- CellRangeAddress destRange = CellRangeAddress.valueOf("G1:G100"); // on sheet2
- transSheetRangeCopier.copyRange(tileRange, destRange);
-
- assertEquals("1.2", getCellContent(destSheet, "G24"));
- }
-
- @Test
- public void testSameSheet() {
- // leave some rows empty in-between
- Row row = sheet1.createRow(23);
- row.createCell(0).setCellValue(1.2);
-
- CellRangeAddress tileRange = CellRangeAddress.valueOf("A1:A100"); // on sheet1
- CellRangeAddress destRange = CellRangeAddress.valueOf("G1:G100"); // on sheet2
-
- // use the a RangeCopier with the same Sheet for source and dest
- rangeCopier.copyRange(tileRange, destRange);
-
- assertEquals("1.2", getCellContent(sheet1, "G24"));
- }
-
- @Test
- public void testCopyStyles() {
- String cellContent = "D6 aligned to the right";
- HorizontalAlignment toTheRight = HorizontalAlignment.RIGHT;
- // create cell with content aligned to the right
- CellStyle style = workbook.createCellStyle();
- style.setAlignment(toTheRight);
- Cell cell = sheet1.createRow(5).createCell(3);
- cell.setCellValue(cellContent);
- cell.setCellStyle(style);
-
- Sheet destSheet = sheet2;
- CellRangeAddress tileRange = CellRangeAddress.valueOf("D6:D6"); // on sheet1
- CellRangeAddress destRange = CellRangeAddress.valueOf("J6:J6"); // on sheet2
- transSheetRangeCopier.copyRange(tileRange, destRange, true, false);
- assertEquals(cellContent, getCellContent(destSheet, "J6"));
- assertEquals(toTheRight, getCell(destSheet, "J6").getCellStyle().getAlignment());
- }
-
- @Test
- public void testMergedRanges() {
- String cellContent = "D6 merged to E7";
-
- // create cell merged from D6 to E7
- CellRangeAddress mergedRangeAddress = new CellRangeAddress(5,6,3,4);
- Cell cell = sheet1.createRow(5).createCell(3);
- cell.setCellValue(cellContent);
- sheet1.addMergedRegion(mergedRangeAddress);
-
- Sheet destSheet = sheet2;
- CellRangeAddress tileRange = CellRangeAddress.valueOf("D6:E7"); // on sheet1
- transSheetRangeCopier.copyRange(tileRange, tileRange, false, true);
- assertEquals(cellContent, getCellContent(destSheet, "D6"));
- assertFalse(destSheet.getMergedRegions().isEmpty());
- destSheet.getMergedRegions().forEach((mergedRegion) -> {
- assertTrue(mergedRegion.equals(mergedRangeAddress));
- });
- }
-
- protected static String getCellContent(Sheet sheet, String coordinates) {
- Cell cell = getCell(sheet, coordinates);
- return cell == null ? "" : cell.toString();
- }
-
- protected static Cell getCell(Sheet sheet, String coordinates) {
- try {
- CellReference p = new CellReference(coordinates);
- return sheet.getRow(p.getRow()).getCell(p.getCol());
- }
- catch (NullPointerException e) { // row or cell does not exist
- return null;
- }
- }
-}