merge trunk

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/hemf@1843032 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2018-10-06 19:33:27 +00:00
commit 1f93a366f5
82 changed files with 2163 additions and 856 deletions

View File

@ -28,8 +28,8 @@
<classpathentry kind="lib" path="lib/jmh-generator-annprocess-1.19.jar"/> <classpathentry kind="lib" path="lib/jmh-generator-annprocess-1.19.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry exported="true" kind="lib" path="compile-lib/slf4j-api-1.7.25.jar"/> <classpathentry exported="true" kind="lib" path="compile-lib/slf4j-api-1.7.25.jar"/>
<classpathentry kind="lib" path="compile-lib/bcpkix-jdk15on-1.59.jar"/> <classpathentry kind="lib" path="compile-lib/bcpkix-jdk15on-1.60.jar"/>
<classpathentry kind="lib" path="compile-lib/bcprov-ext-jdk15on-1.59.jar"/> <classpathentry kind="lib" path="compile-lib/bcprov-ext-jdk15on-1.60.jar"/>
<classpathentry exported="true" kind="lib" path="compile-lib/xmlsec-2.1.0.jar"/> <classpathentry exported="true" kind="lib" path="compile-lib/xmlsec-2.1.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-codec-1.11.jar"/> <classpathentry exported="true" kind="lib" path="lib/commons-codec-1.11.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-logging-1.2.jar"/> <classpathentry exported="true" kind="lib" path="lib/commons-logging-1.2.jar"/>

View File

@ -159,8 +159,6 @@ subprojects {
} }
} }
// japicmp will fail with "Could not load" because we moved some classes out of the root-package
// for Java 9 compatibility in 4.0.0
task(japicmp, type: me.champeau.gradle.ArtifactJapicmpTask, dependsOn: jar) { task(japicmp, type: me.champeau.gradle.ArtifactJapicmpTask, dependsOn: jar) {
to = jar.archivePath to = jar.archivePath
onlyModified = true onlyModified = true
@ -187,6 +185,7 @@ project('main') {
compile 'javax.activation:activation:1.1.1' compile 'javax.activation:activation:1.1.1'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
testCompile 'org.reflections:reflections:0.9.11'
} }
jar { jar {
@ -231,7 +230,7 @@ project('ooxml') {
compile 'org.apache.commons:commons-math3:3.6.1' compile 'org.apache.commons:commons-math3:3.6.1'
compile 'org.apache.commons:commons-compress:1.18' compile 'org.apache.commons:commons-compress:1.18'
compile 'org.apache.santuario:xmlsec:2.1.0' compile 'org.apache.santuario:xmlsec:2.1.0'
compile 'org.bouncycastle:bcpkix-jdk15on:1.59' compile 'org.bouncycastle:bcpkix-jdk15on:1.60'
compile 'com.github.virtuald:curvesapi:1.05' compile 'com.github.virtuald:curvesapi:1.05'
// for ooxml-lite, should we move this somewhere else? // for ooxml-lite, should we move this somewhere else?
@ -245,6 +244,7 @@ project('ooxml') {
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:2.21.0' testCompile 'org.mockito:mockito-core:2.21.0'
testCompile 'org.xmlunit:xmlunit-core:2.5.1' testCompile 'org.xmlunit:xmlunit-core:2.5.1'
testCompile 'org.reflections:reflections:0.9.11'
testCompile project(path: ':main', configuration: 'tests') testCompile project(path: ':main', configuration: 'tests')
testCompile 'org.openjdk.jmh:jmh-core:1.19' testCompile 'org.openjdk.jmh:jmh-core:1.19'
testCompile 'org.openjdk.jmh:jmh-generator-annprocess:1.19' testCompile 'org.openjdk.jmh:jmh-generator-annprocess:1.19'

147
build.xml
View File

@ -52,6 +52,7 @@ under the License.
<property name="main.lib" location="lib"/> <property name="main.lib" location="lib"/>
<property name="ooxml.lib" location="ooxml-lib"/> <property name="ooxml.lib" location="ooxml-lib"/>
<property name="ooxml.test.lib" location="ooxml-testlib"/>
<property name="compile.lib" location="compile-lib"/> <property name="compile.lib" location="compile-lib"/>
<!-- compiler options options --> <!-- compiler options options -->
@ -201,14 +202,14 @@ under the License.
<!-- xml signature libs --> <!-- xml signature libs -->
<property name="dsig.xmlsec.jar" location="${compile.lib}/xmlsec-2.1.0.jar"/> <property name="dsig.xmlsec.jar" location="${compile.lib}/xmlsec-2.1.0.jar"/>
<property name="dsig.xmlsec.url" value="${repository.m2}/maven2/org/apache/santuario/xmlsec/2.1.0/xmlsec-2.1.0.jar"/> <property name="dsig.xmlsec.url" value="${repository.m2}/maven2/org/apache/santuario/xmlsec/2.1.0/xmlsec-2.1.0.jar"/>
<property name="dsig.bouncycastle-prov.jar" location="${compile.lib}/bcprov-ext-jdk15on-1.59.jar"/> <property name="dsig.bouncycastle-prov.jar" location="${compile.lib}/bcprov-ext-jdk15on-1.60.jar"/>
<property name="dsig.bouncycastle-prov.url" value="${repository.m2}/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.59/bcprov-ext-jdk15on-1.59.jar"/> <property name="dsig.bouncycastle-prov.url" value="${repository.m2}/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.60/bcprov-ext-jdk15on-1.60.jar"/>
<property name="dsig.bouncycastle-pkix.jar" location="${compile.lib}/bcpkix-jdk15on-1.59.jar"/> <property name="dsig.bouncycastle-pkix.jar" location="${compile.lib}/bcpkix-jdk15on-1.60.jar"/>
<property name="dsig.bouncycastle-pkix.url" value="${repository.m2}/maven2/org/bouncycastle/bcpkix-jdk15on/1.59/bcpkix-jdk15on-1.59.jar"/> <property name="dsig.bouncycastle-pkix.url" value="${repository.m2}/maven2/org/bouncycastle/bcpkix-jdk15on/1.60/bcpkix-jdk15on-1.60.jar"/>
<property name="dsig.sl4j-api.jar" location="${compile.lib}/slf4j-api-1.7.25.jar"/> <property name="dsig.sl4j-api.jar" location="${compile.lib}/slf4j-api-1.7.25.jar"/>
<property name="dsig.sl4j-api.url" value="${repository.m2}/maven2/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar"/> <property name="dsig.sl4j-api.url" value="${repository.m2}/maven2/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar"/>
<!-- jars in the lib-ooxml directory, see the fetch-ooxml-jars target--> <!-- jars in the ooxml-lib directory, see the fetch-ooxml-jars target-->
<property name="ooxml.curvesapi.jar" location="${ooxml.lib}/curvesapi-1.05.jar"/> <property name="ooxml.curvesapi.jar" location="${ooxml.lib}/curvesapi-1.05.jar"/>
<property name="ooxml.curvesapi.url" <property name="ooxml.curvesapi.url"
value="${repository.m2}/maven2/com/github/virtuald/curvesapi/1.05/curvesapi-1.05.jar"/> value="${repository.m2}/maven2/com/github/virtuald/curvesapi/1.05/curvesapi-1.05.jar"/>
@ -219,6 +220,17 @@ under the License.
<property name="ooxml.commons-compress.url" <property name="ooxml.commons-compress.url"
value="${repository.m2}/maven2/org/apache/commons/commons-compress/1.18/commons-compress-1.18.jar"/> value="${repository.m2}/maven2/org/apache/commons/commons-compress/1.18/commons-compress-1.18.jar"/>
<!-- jars in the ooxml-test-lib directory, see the fetch-ooxml-jars target-->
<property name="ooxml.test.reflections.jar" location="${ooxml.test.lib}/reflections.jar"/>
<property name="ooxml.test.reflections.url"
value="${repository.m2}/maven2/org/reflections/reflections/0.9.11/reflections-0.9.11.jar"/>
<property name="ooxml.test.guava.jar" location="${ooxml.test.lib}/guava.jar"/>
<property name="ooxml.test.guava.url"
value="${repository.m2}/maven2/com/google/guava/guava/20.0/guava-20.0.jar"/>
<property name="ooxml.test.javassist.jar" location="${ooxml.test.lib}/javassist.jar"/>
<property name="ooxml.test.javassist.url"
value="${repository.m2}/maven2/org/javassist/javassist/3.21.0-GA/javassist-3.21.0-GA.jar"/>
<!-- coverage libs --> <!-- coverage libs -->
<property name="jacoco.zip" location="${main.lib}/jacoco-0.8.2.zip"/> <property name="jacoco.zip" location="${main.lib}/jacoco-0.8.2.zip"/>
<property name="jacoco.url" value="${repository.m2}/maven2/org/jacoco/jacoco/0.8.2/jacoco-0.8.2.zip"/> <property name="jacoco.url" value="${repository.m2}/maven2/org/jacoco/jacoco/0.8.2/jacoco-0.8.2.zip"/>
@ -232,8 +244,8 @@ under the License.
<!-- license and api checks --> <!-- license and api checks -->
<property name="rat.jar" location="${main.lib}/apache-rat-0.12.jar"/> <property name="rat.jar" location="${main.lib}/apache-rat-0.12.jar"/>
<property name="rat.url" value="${repository.m2}/maven2/org/apache/rat/apache-rat/0.12/apache-rat-0.12.jar"/> <property name="rat.url" value="${repository.m2}/maven2/org/apache/rat/apache-rat/0.12/apache-rat-0.12.jar"/>
<property name="forbidden.jar" location="${main.lib}/forbiddenapis-2.5.jar"/> <property name="forbidden.jar" location="${main.lib}/forbiddenapis-2.6.jar"/>
<property name="forbidden.url" value="${repository.m2}/maven2/de/thetaphi/forbiddenapis/2.5/forbiddenapis-2.5.jar"/> <property name="forbidden.url" value="${repository.m2}/maven2/de/thetaphi/forbiddenapis/2.6/forbiddenapis-2.6.jar"/>
<property name="maven.ooxml.xsds.version.id" value="1.4"/> <property name="maven.ooxml.xsds.version.id" value="1.4"/>
@ -282,10 +294,10 @@ under the License.
<property name="halt.on.test.failure" value="true"/> <property name="halt.on.test.failure" value="true"/>
<!-- helper jars for pgp signing, building and nexus staging --> <!-- helper jars for pgp signing, building and nexus staging -->
<property name="dist.bouncycastle-prov.jar" location="${compile.lib}/bcprov-ext-jdk15on-1.59.jar"/> <property name="dist.bouncycastle-prov.jar" location="${compile.lib}/bcprov-ext-jdk15on-1.60.jar"/>
<property name="dist.bouncycastle-prov.url" value="${repository.m2}/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.59/bcprov-ext-jdk15on-1.59.jar"/> <property name="dist.bouncycastle-prov.url" value="${repository.m2}/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.60/bcprov-ext-jdk15on-1.60.jar"/>
<property name="dist.bouncycastle-bcpg.jar" location="${compile.lib}/bcpg-jdk15on-1.59.jar"/> <property name="dist.bouncycastle-bcpg.jar" location="${compile.lib}/bcpg-jdk15on-1.60.jar"/>
<property name="dist.bouncycastle-bcpg.url" value="${repository.m2}/maven2/org/bouncycastle/bcpg-jdk15on/1.59/bcpg-jdk15on-1.59.jar"/> <property name="dist.bouncycastle-bcpg.url" value="${repository.m2}/maven2/org/bouncycastle/bcpg-jdk15on/1.60/bcpg-jdk15on-1.60.jar"/>
<property name="dist.commons-openpgp.jar" location="${compile.lib}/commons-openpgp-1.0-SNAPSHOT.jar"/> <property name="dist.commons-openpgp.jar" location="${compile.lib}/commons-openpgp-1.0-SNAPSHOT.jar"/>
<property name="dist.commons-openpgp.url" value="https://repository.apache.org/snapshots/org/apache/commons/commons-openpgp/1.0-SNAPSHOT/commons-openpgp-1.0-20140717.171036-11.jar"/> <property name="dist.commons-openpgp.url" value="https://repository.apache.org/snapshots/org/apache/commons/commons-openpgp/1.0-SNAPSHOT/commons-openpgp-1.0-20140717.171036-11.jar"/>
<property name="dist.nexus-staging.jar" location="${compile.lib}/nexus-staging-ant-tasks-1.6.3-uber.jar"/> <property name="dist.nexus-staging.jar" location="${compile.lib}/nexus-staging-ant-tasks-1.6.3-uber.jar"/>
@ -416,10 +428,17 @@ under the License.
<pathelement location="${additionaljar}"/> <pathelement location="${additionaljar}"/>
</path> </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 id="test.ooxml.classpath">
<path refid="ooxml.classpath"/> <path refid="ooxml.classpath"/>
<path refid="ooxml.xmlsec.classpath"/> <path refid="ooxml.xmlsec.classpath"/>
<path refid="test.jar.classpath"/> <path refid="test.jar.classpath"/>
<path refid="test.ooxml.reflections.classpath"/>
<pathelement location="${ooxml.output.dir}"/> <pathelement location="${ooxml.output.dir}"/>
<pathelement location="${ooxml.output.test.dir}"/> <pathelement location="${ooxml.output.test.dir}"/>
<pathelement location="${main.output.test.dir}"/> <pathelement location="${main.output.test.dir}"/>
@ -484,6 +503,7 @@ under the License.
<path refid="scratchpad.classpath"/> <path refid="scratchpad.classpath"/>
<path refid="ooxml.classpath"/> <path refid="ooxml.classpath"/>
<path refid="ooxml.xmlsec.classpath"/> <path refid="ooxml.xmlsec.classpath"/>
<path refid="test.ooxml.reflections.classpath"/>
<path refid="excelant.classpath"/> <path refid="excelant.classpath"/>
<path refid="examples.classpath"/> <path refid="examples.classpath"/>
<pathelement location="${examples.output.dir}"/> <pathelement location="${examples.output.dir}"/>
@ -582,6 +602,7 @@ under the License.
<mkdir dir="${main.lib}"/> <mkdir dir="${main.lib}"/>
<mkdir dir="${compile.lib}"/> <mkdir dir="${compile.lib}"/>
<mkdir dir="${ooxml.lib}"/> <mkdir dir="${ooxml.lib}"/>
<mkdir dir="${ooxml.test.lib}"/>
<delete verbose="true"> <delete verbose="true">
<fileset dir="${main.lib}"> <fileset dir="${main.lib}">
<include name="ant-1.8*"/> <include name="ant-1.8*"/>
@ -631,6 +652,7 @@ under the License.
<include name="forbiddenapis-2.0.jar"/> <include name="forbiddenapis-2.0.jar"/>
<include name="forbiddenapis-2.1.jar"/> <include name="forbiddenapis-2.1.jar"/>
<include name="forbiddenapis-2.3.jar"/> <include name="forbiddenapis-2.3.jar"/>
<include name="forbiddenapis-2.5.jar"/>
<include name="apache-rat-0.11.jar"/> <include name="apache-rat-0.11.jar"/>
<include name="mockito-core-2.13.0.jar"/> <include name="mockito-core-2.13.0.jar"/>
</fileset> </fileset>
@ -655,10 +677,7 @@ under the License.
<include name="xmlsec-2.0.1.jar"/> <include name="xmlsec-2.0.1.jar"/>
<include name="xmlsec-2.0.5.jar"/> <include name="xmlsec-2.0.5.jar"/>
<include name="xmlsec-2.0.6.jar"/> <include name="xmlsec-2.0.6.jar"/>
<include name="bc*jdk15on-1.51.jar"/> <include name="bc*jdk15on-1.5*.jar"/>
<include name="bc*jdk15on-1.53.jar"/>
<include name="bc*jdk15on-1.54.jar"/>
<include name="bc*jdk15on-1.58.jar"/>
<include name="slf4j-api-1.7.7.jar"/> <include name="slf4j-api-1.7.7.jar"/>
<include name="slf4j-api-1.7.12.jar"/> <include name="slf4j-api-1.7.12.jar"/>
</fileset> </fileset>
@ -753,6 +772,9 @@ under the License.
<available file="${ooxml.curvesapi.jar}"/> <available file="${ooxml.curvesapi.jar}"/>
<available file="${ooxml.xmlbeans.jar}"/> <available file="${ooxml.xmlbeans.jar}"/>
<available file="${ooxml.commons-compress.jar}"/> <available file="${ooxml.commons-compress.jar}"/>
<available file="${ooxml.test.reflections.jar}"/>
<available file="${ooxml.test.guava.jar}"/>
<available file="${ooxml.test.javassist.jar}"/>
</and> </and>
<isset property="disconnected"/> <isset property="disconnected"/>
</or> </or>
@ -760,9 +782,13 @@ under the License.
</target> </target>
<target name="fetch-ooxml-jars" depends="check-ooxml-jars" unless="ooxml.jars.present"> <target name="fetch-ooxml-jars" depends="check-ooxml-jars" unless="ooxml.jars.present">
<mkdir dir="${ooxml.lib}"/> <mkdir dir="${ooxml.lib}"/>
<mkdir dir="${ooxml.test.lib}"/>
<downloadfile src="${ooxml.curvesapi.url}" dest="${ooxml.curvesapi.jar}"/> <downloadfile src="${ooxml.curvesapi.url}" dest="${ooxml.curvesapi.jar}"/>
<downloadfile src="${ooxml.xmlbeans.url}" dest="${ooxml.xmlbeans.jar}"/> <downloadfile src="${ooxml.xmlbeans.url}" dest="${ooxml.xmlbeans.jar}"/>
<downloadfile src="${ooxml.commons-compress.url}" dest="${ooxml.commons-compress.jar}"/> <downloadfile src="${ooxml.commons-compress.url}" dest="${ooxml.commons-compress.jar}"/>
<downloadfile src="${ooxml.test.reflections.url}" dest="${ooxml.test.reflections.jar}"/>
<downloadfile src="${ooxml.test.guava.url}" dest="${ooxml.test.guava.jar}"/>
<downloadfile src="${ooxml.test.javassist.url}" dest="${ooxml.test.javassist.jar}"/>
</target> </target>
<target name="check-svn-jars"> <target name="check-svn-jars">
<condition property="svn.jars.present"> <condition property="svn.jars.present">
@ -2045,6 +2071,7 @@ under the License.
<include name="commons-codec-*.jar"/> <include name="commons-codec-*.jar"/>
<include name="commons-logging-*.jar"/> <include name="commons-logging-*.jar"/>
<include name="commons-collections4-*.jar"/> <include name="commons-collections4-*.jar"/>
<include name="commons-compress*.jar"/>
<include name="commons-math3-*.jar"/> <include name="commons-math3-*.jar"/>
<include name="jaxb-api-*.jar"/> <include name="jaxb-api-*.jar"/>
<include name="jaxb-impl-*.jar"/> <include name="jaxb-impl-*.jar"/>
@ -2753,13 +2780,20 @@ under the License.
project.setProperty(attributes.get("property"), mega); project.setProperty(attributes.get("property"), mega);
</scriptdef> </scriptdef>
<macrodef name="loadFilesize"> <macrodef name="download-line">
<attribute name="url"/> <attribute name="prop"/>
<attribute name="property"/> <attribute name="dist"/>
<attribute name="pack"/>
<sequential> <sequential>
<local name="baseurl"/>
<property name="baseurl" value="https://www.apache.org/dist/poi/release"/>
<local name="basedyn"/>
<property name="basedyn" value="https://www.apache.org/dyn/closer.lua/poi/release"/>
<delete file="build/loadFilesize.txt"/> <delete file="build/loadFilesize.txt"/>
<record name="build/loadFilesize.txt" action="start" loglevel="verbose" append="false"/> <record name="build/loadFilesize.txt" action="start" loglevel="verbose" append="false"/>
<http url="@{url}" method="HEAD" expected="200" printrequestheaders="false" printresponseheaders="false"/> <http url="${baseurl}/@{dist}/poi-@{dist}-${version.id}-${file_date}.@{pack}" method="HEAD" expected="200" printrequestheaders="false" printresponseheaders="false"/>
<record name="build/loadFilesize.txt" action="stop"/> <record name="build/loadFilesize.txt" action="stop"/>
<local name="fileSize"/> <local name="fileSize"/>
<loadfile property="fileSize" srcFile="build/loadFilesize.txt"> <loadfile property="fileSize" srcFile="build/loadFilesize.txt">
@ -2770,7 +2804,16 @@ under the License.
</tokenfilter> </tokenfilter>
</filterchain> </filterchain>
</loadfile> </loadfile>
<bytes2mega property="@{property}" bytes="${fileSize}"/>
<local name="fileSizeMb"/>
<bytes2mega property="fileSizeMb" bytes="${fileSize}"/>
<property name="@{prop}"><![CDATA[<li>
<a href="${basedyn}/@{dist}/poi-@{dist}-${version.id}-${file_date}.@{pack}">poi-@{dist}-${version.id}-${file_date}.@{pack}</a>
(${fileSizeMb} MB, <a href="${baseurl}/@{dist}/poi-@{dist}-${version.id}-${file_date}.@{pack}.asc">signature (.asc)</a>,
checksum: <a href="${baseurl}/@{dist}/poi-@{dist}-${version.id}-${file_date}.@{pack}.sha256">SHA-256</a>,
<a href="${baseurl}/@{dist}/poi-@{dist}-${version.id}-${file_date}.@{pack}.sha512">SHA-512</a>)
</li>]]></property>
</sequential> </sequential>
</macrodef> </macrodef>
@ -2795,23 +2838,17 @@ under the License.
<format property="rel_date" pattern="dd MMMM yyyy" locale="US"/> <format property="rel_date" pattern="dd MMMM yyyy" locale="US"/>
<format property="file_date" pattern="yyyyMMdd" locale="US"/> <format property="file_date" pattern="yyyyMMdd" locale="US"/>
</tstamp> </tstamp>
<property name="baseurl" value="https://www.apache.org/dist/poi/release"/>
<loadChecksum property="bin-tar-sha256" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.tar.gz.sha256"/> <local name="li1"/>
<loadChecksum property="bin-tar-sha512" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.tar.gz.sha512"/> <local name="li2"/>
<loadChecksum property="bin-zip-sha256" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.zip.sha256"/> <local name="li3"/>
<loadChecksum property="bin-zip-sha512" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.zip.sha512"/> <local name="li4"/>
<loadChecksum property="src-tar-sha256" url="${baseurl}/src/poi-src-${version.id}-${file_date}.tar.gz.sha256"/> <download-line prop="li1" dist="bin" pack="tar.gz"/>
<loadChecksum property="src-tar-sha512" url="${baseurl}/src/poi-src-${version.id}-${file_date}.tar.gz.sha512"/> <download-line prop="li2" dist="bin" pack="zip"/>
<loadChecksum property="src-zip-sha256" url="${baseurl}/src/poi-src-${version.id}-${file_date}.zip.sha256"/> <download-line prop="li3" dist="src" pack="tar.gz"/>
<loadChecksum property="src-zip-sha512" url="${baseurl}/src/poi-src-${version.id}-${file_date}.zip.sha512"/> <download-line prop="li4" dist="src" pack="zip"/>
<loadFilesize property="bin-tar-size" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.tar.gz"/> <echo file="download-snipplet.xml"><![CDATA[
<loadFilesize property="bin-zip-size" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.zip"/>
<loadFilesize property="src-tar-size" url="${baseurl}/src/poi-src-${version.id}-${file_date}.tar.gz"/>
<loadFilesize property="src-zip-size" url="${baseurl}/src/poi-src-${version.id}-${file_date}.zip"/>
<echo file="download-snipplet.xml"><![CDATA[
<section id="POI-${version.id}"><title>${rel_date} - POI ${version.id} available</title> <section id="POI-${version.id}"><title>${rel_date} - POI ${version.id} available</title>
<p>The Apache POI team is pleased to announce the release of ${version.id}. <p>The Apache POI team is pleased to announce the release of ${version.id}.
Featured are a handful of new areas of functionality and numerous bug fixes.</p> Featured are a handful of new areas of functionality and numerous bug fixes.</p>
@ -2828,46 +2865,14 @@ under the License.
</p> </p>
<section id="POI-${version.id}-bin"><title>Binary Distribution</title> <section id="POI-${version.id}-bin"><title>Binary Distribution</title>
<ul> <ul>
<li><a href="https://www.apache.org/dyn/closer.lua/poi/release/bin/poi-bin-${version.id}-${file_date}.tar.gz">poi-bin-${version.id}-${file_date}.tar.gz</a> ${li1}
(${bin-tar-size} MB, <a href="https://www.apache.org/dist/poi/release/bin/poi-bin-${version.id}-${file_date}.tar.gz.asc">signature (.asc)</a>) ${li2}
<br/>
SHA256 checksum: <a href="https://www.apache.org/dist/poi/release/bin/poi-bin-${version.id}-${file_date}.tar.gz.sha256">
${bin-tar-sha256}</a>
<br/>
SHA512 checksum: <a href="https://www.apache.org/dist/poi/release/bin/poi-bin-${version.id}-${file_date}.tar.gz.sha512">
${bin-tar-sha512}</a>
</li>
<li><a href="https://www.apache.org/dyn/closer.lua/poi/release/bin/poi-bin-${version.id}-${file_date}.zip">poi-bin-${version.id}-${file_date}.zip</a>
(${bin-zip-size} MB, <a href="https://www.apache.org/dist/poi/release/bin/poi-bin-${version.id}-${file_date}.zip.asc">signature (.asc)</a>)
<br/>
SHA256 checksum: <a href="https://www.apache.org/dist/poi/release/bin/poi-bin-${version.id}-${file_date}.zip.sha256">
${bin-zip-sha256}</a>
<br/>
SHA512 checksum: <a href="https://www.apache.org/dist/poi/release/bin/poi-bin-${version.id}-${file_date}.zip.sha512">
${bin-zip-sha512}</a>
</li>
</ul> </ul>
</section> </section>
<section id="POI-${version.id}-src"><title>Source Distribution</title> <section id="POI-${version.id}-src"><title>Source Distribution</title>
<ul> <ul>
<li><a href="https://www.apache.org/dyn/closer.lua/poi/release/src/poi-src-${version.id}-${file_date}.tar.gz">poi-src-${version.id}-${file_date}.tar.gz</a> ${li3}
(${src-tar-size} MB, <a href="https://www.apache.org/dist/poi/release/src/poi-src-${version.id}-${file_date}.tar.gz.asc">signature (.asc)</a>) ${li4}
<br/>
SHA256 checksum: <a href="https://www.apache.org/dist/poi/release/src/poi-src-${version.id}-${file_date}.tar.gz.sha256">
${src-tar-sha256}</a>
<br/>
SHA512 checksum: <a href="https://www.apache.org/dist/poi/release/src/poi-src-${version.id}-${file_date}.tar.gz.sha512">
${src-tar-sha512}</a>
</li>
<li><a href="https://www.apache.org/dyn/closer.lua/poi/release/src/poi-src-${version.id}-${file_date}.zip">poi-src-${version.id}-${file_date}.zip</a>
(${src-zip-size} MB, <a href="https://www.apache.org/dist/poi/release/src/poi-src-${version.id}-${file_date}.zip.asc">signature (.asc)</a>)
<br/>
SHA256 checksum: <a href="https://www.apache.org/dist/poi/release/src/poi-src-${version.id}-${file_date}.zip.sha256">
${src-zip-sha256}</a>
<br/>
SHA512 checksum: <a href="https://www.apache.org/dist/poi/release/src/poi-src-${version.id}-${file_date}.zip.sha512">
${src-zip-sha512}</a>
</li>
</ul> </ul>
</section> </section>
</section> </section>

View File

@ -25,19 +25,6 @@ def poijobs = [
// the JDK is missing on some slaves so builds are unstable // the JDK is missing on some slaves so builds are unstable
skipcigame: true skipcigame: true
], ],
[ name: 'POI-DSL-1.9', jdk: '1.9', trigger: triggerSundays,
properties: ['-Djava9addmods=--add-modules=java.xml.bind',
'-Djavadoc9addmods=--add-modules=java.xml.bind',
'-Djava9addmodsvalue=-Dsun.reflect.debugModuleAccessChecks=true',
'-Djava9addopens1=--add-opens=java.xml/com.sun.org.apache.xerces.internal.util=ALL-UNNAMED',
'-Djava9addopens2=--add-opens=java.base/java.io=ALL-UNNAMED',
'-Djava9addopens3=--add-opens=java.base/java.nio=ALL-UNNAMED',
'-Djava9addopens4=--add-opens=java.base/java.lang=ALL-UNNAMED',
'-Djava9addopens5=--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED',
'-Djava9addopens6=--add-opens=java.base/java.lang=java.xml.bind',
'-Djava.locale.providers=JRE,CLDR'],
skipcigame: true
],
[ name: 'POI-DSL-1.10', jdk: '1.10', trigger: triggerSundays, [ name: 'POI-DSL-1.10', jdk: '1.10', trigger: triggerSundays,
properties: ['-Djava9addmods=--add-modules=java.xml.bind', properties: ['-Djava9addmods=--add-modules=java.xml.bind',
'-Djavadoc9addmods=--add-modules=java.xml.bind', '-Djavadoc9addmods=--add-modules=java.xml.bind',
@ -114,7 +101,14 @@ def poijobs = [
], ],
] ]
def xmlbeansjobs = [
[ name: 'POI-XMLBeans-DSL-1.6', jdk: '1.6', trigger: 'H */12 * * *', skipcigame: true
]
]
def svnBase = 'https://svn.apache.org/repos/asf/poi/trunk' def svnBase = 'https://svn.apache.org/repos/asf/poi/trunk'
def xmlbeansSvnBase = 'https://svn.apache.org/repos/asf/xmlbeans/trunk'
def defaultJdk = '1.8' def defaultJdk = '1.8'
def defaultTrigger = 'H/15 * * * *' // check SCM every 60/15 = 4 minutes def defaultTrigger = 'H/15 * * * *' // check SCM every 60/15 = 4 minutes
def defaultEmail = 'dev@poi.apache.org' def defaultEmail = 'dev@poi.apache.org'
@ -123,8 +117,8 @@ def defaultAnt = 'Ant 1.9.9'
def defaultSlaves = '(ubuntu||beam)&&!cloud-slave&&!H15&&!H17&&!H18&&!H24&&!ubuntu-4&&!H21' def defaultSlaves = '(ubuntu||beam)&&!cloud-slave&&!H15&&!H17&&!H18&&!H24&&!ubuntu-4&&!H21'
def jdkMapping = [ def jdkMapping = [
'1.6': 'JDK 1.6 (latest)',
'1.8': 'JDK 1.8 (latest)', '1.8': 'JDK 1.8 (latest)',
'1.9': 'JDK 1.9 (latest)',
'1.10': 'JDK 10 (latest)', '1.10': 'JDK 10 (latest)',
'1.11': 'JDK 11 (latest)', '1.11': 'JDK 11 (latest)',
'1.12': 'JDK 12 (latest)', '1.12': 'JDK 12 (latest)',
@ -141,7 +135,7 @@ static def shellEx(def context, String cmd, def poijob) {
} }
def defaultDesc = ''' def defaultDesc = '''
<img src="https://poi.apache.org/resources/images/project-logo.jpg" /> <img src="https://poi.apache.org/images/project-header.png" />
<p> <p>
Apache POI - the Java API for Microsoft Documents Apache POI - the Java API for Microsoft Documents
</p> </p>
@ -233,7 +227,7 @@ poijobs.each { poijob ->
label(slaves) label(slaves)
environmentVariables { environmentVariables {
env('LANG', 'en_US.UTF-8') env('LANG', 'en_US.UTF-8')
if(jdkKey == '1.9' || jdkKey == '1.10') { if(jdkKey == '1.10') {
// when using JDK 9/10 for running Ant, we need to provide more modules for the forbidden-api-checks task // when using JDK 9/10 for running Ant, we need to provide more modules for the forbidden-api-checks task
// on JDK 11 and newer there is no such module any more, so do not add it here // on JDK 11 and newer there is no such module any more, so do not add it here
env('ANT_OPTS', '--add-modules=java.xml.bind --add-opens=java.xml/com.sun.org.apache.xerces.internal.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED') env('ANT_OPTS', '--add-modules=java.xml.bind --add-opens=java.xml/com.sun.org.apache.xerces.internal.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED')
@ -442,6 +436,92 @@ poijobs.each { poijob ->
} }
} }
xmlbeansjobs.each { xjob ->
def jdkKey = xjob.jdk ?: defaultJdk
def trigger = xjob.trigger ?: defaultTrigger
def email = xjob.email ?: defaultEmail
def slaves = xjob.slaves ?: defaultSlaves + (xjob.slaveAdd ?: '')
def antRT = defaultAnt + (xjob.windows ? ' (Windows)' : '')
job(xjob.name) {
if (xjob.disabled) {
disabled()
}
description( defaultDesc + (xjob.apicheck ? apicheckDesc : sonarDesc) )
logRotator {
numToKeep(5)
artifactNumToKeep(1)
}
label(slaves)
environmentVariables {
env('LANG', 'en_US.UTF-8')
if(jdkKey == '1.10') {
// when using JDK 9/10 for running Ant, we need to provide more modules for the forbidden-api-checks task
// on JDK 11 and newer there is no such module any more, so do not add it here
env('ANT_OPTS', '--add-modules=java.xml.bind --add-opens=java.xml/com.sun.org.apache.xerces.internal.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED')
}
env('FORREST_HOME', xjob.windows ? 'f:\\jenkins\\tools\\forrest\\latest' : '/home/jenkins/tools/forrest/latest')
}
wrappers {
timeout {
absolute(180)
abortBuild()
writeDescription('Build was aborted due to timeout')
}
}
jdk(jdkMapping.get(jdkKey))
scm {
svn(xmlbeansSvnBase) { svnNode ->
svnNode / browser(class: 'hudson.scm.browsers.ViewSVN') /
url << 'http://svn.apache.org/viewcvs.cgi/?root=Apache-SVN'
}
}
checkoutRetryCount(3)
triggers {
scm(trigger)
}
def shellcmds = (xjob.windows ? shellCmdsWin : shellCmdsUnix).replace('POIJOBSHELL', xjob.shell ?: '')
// Create steps and publishers depending on the type of Job that is selected
steps {
shellEx(delegate, shellcmds, xjob)
if(xjob.addShell) {
shellEx(delegate, xjob.addShell, xjob)
}
ant {
targets(['clean'])
antInstallation(antRT)
}
ant {
targets(['checkintest'])
antInstallation(antRT)
}
ant {
targets(['dist'])
antInstallation(antRT)
}
}
publishers {
archiveArtifacts('build/private/**')
//archiveJunit('build/test/reports/*.xml') {
// testDataPublishers {
// publishTestStabilityData()
// }
//}
if (!xjob.skipcigame) {
configure { project ->
project / publishers << 'hudson.plugins.cigame.GamePublisher' {}
}
}
mailer(email, false, false)
}
}
}
/* /*
Add a special job which spans a two-dimensional matrix of all JDKs that we want to use and Add a special job which spans a two-dimensional matrix of all JDKs that we want to use and
all slaves that we would like to use and test if the java and ant binaries are available all slaves that we would like to use and test if the java and ant binaries are available
@ -471,8 +551,6 @@ Unfortunately we often see builds break because of changes/new machines...'''
'OpenJDK 8 (on Ubuntu only) ', // blank is required here until the name in the Jenkins instance is fixed! 'OpenJDK 8 (on Ubuntu only) ', // blank is required here until the name in the Jenkins instance is fixed!
'IBM 1.8 64-bit (on Ubuntu only)', 'IBM 1.8 64-bit (on Ubuntu only)',
'JDK 1.9 (latest)',
'JDK 10 (latest)', 'JDK 10 (latest)',
'JDK 10 b46 (Windows Only)', 'JDK 10 b46 (Windows Only)',
'OpenJDK 10.0.2 (on Ubuntu only)', 'OpenJDK 10.0.2 (on Ubuntu only)',

View File

@ -77,7 +77,7 @@
<dependency> <dependency>
<groupId>com.github.virtuald</groupId> <groupId>com.github.virtuald</groupId>
<artifactId>curvesapi</artifactId> <artifactId>curvesapi</artifactId>
<version>1.04</version> <version>1.05</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -76,7 +76,17 @@
<dependency> <dependency>
<groupId>commons-codec</groupId> <groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<version>1.10</version> <version>1.11</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency> </dependency>
<dependency> <dependency>
@ -91,11 +101,6 @@
<scope>test</scope> <scope>test</scope>
<version>4.12</version> <version>4.12</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.2</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -137,12 +137,12 @@
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId> <artifactId>bcpkix-jdk15on</artifactId>
<version>1.59</version> <version>1.60</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId> <artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version> <version>1.60</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.santuario</groupId> <groupId>org.apache.santuario</groupId>
@ -166,6 +166,12 @@
<version>${junit.version}</version> <version>${junit.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.openjdk.jmh</groupId> <groupId>org.openjdk.jmh</groupId>

View File

@ -348,11 +348,13 @@ public void paintBorder(Component c, Graphics g, int x, int y, int width,
// if there are borders on the west or east then // if there are borders on the west or east then
// the second line shouldn't cross them // the second line shouldn't cross them
if (westBorder) if (westBorder) {
leftx = x+3; leftx = x + 3;
}
if (eastBorder) if (eastBorder) {
rightx = width-3; rightx = width - 3;
}
g.drawLine(x,y,width,y); g.drawLine(x,y,width,y);
g.drawLine(leftx,y+2,rightx,y+2); g.drawLine(leftx,y+2,rightx,y+2);
@ -370,11 +372,13 @@ public void paintBorder(Component c, Graphics g, int x, int y, int width,
int topy=y; int topy=y;
int bottomy=height; int bottomy=height;
if (northBorder) if (northBorder) {
topy=y+3; topy = y + 3;
}
if (southBorder) if (southBorder) {
bottomy=height-3; bottomy = height - 3;
}
g.drawLine(width-1,y,width-1,height); g.drawLine(width-1,y,width-1,height);
g.drawLine(width-3,topy,width-3,bottomy); g.drawLine(width-3,topy,width-3,bottomy);

View File

@ -533,12 +533,12 @@ public class ConditionalFormats {
Row r = sheet.createRow(1); Row r = sheet.createRow(1);
r.createCell(0).setCellValue("Red-Yellow-Green"); r.createCell(0).setCellValue("Red-Yellow-Green");
for (int i=1; i<=7; i++) { for (int i=1; i<=7; i++) {
r.createCell(i).setCellValue((i-1)*5); r.createCell(i).setCellValue((i-1)*5.0);
} }
r = sheet.createRow(2); r = sheet.createRow(2);
r.createCell(0).setCellValue("Red-White-Blue"); r.createCell(0).setCellValue("Red-White-Blue");
for (int i=1; i<=9; i++) { for (int i=1; i<=9; i++) {
r.createCell(i).setCellValue((i-1)*5); r.createCell(i).setCellValue((i-1)*5.0);
} }
r = sheet.createRow(3); r = sheet.createRow(3);
r.createCell(0).setCellValue("Blue-Green"); r.createCell(0).setCellValue("Blue-Green");
@ -667,9 +667,13 @@ public class ConditionalFormats {
for (Cell c : r) { for (Cell c : r) {
final List<EvaluationConditionalFormatRule> rules = cfEval.getConditionalFormattingForCell(c); 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 // 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; if (rules == null || rules.isEmpty()) {
continue;
}
final CellReference ref = ConditionalFormattingEvaluator.getRef(c); final CellReference ref = ConditionalFormattingEvaluator.getRef(c);
if (rules.isEmpty()) continue; if (rules.isEmpty()) {
continue;
}
System.out.println("\n" System.out.println("\n"
+ ref.formatAsString() + ref.formatAsString()
@ -709,9 +713,15 @@ public class ConditionalFormats {
b.append("\n\t\tfont format ") b.append("\n\t\tfont format ")
.append("color index ") .append("color index ")
.append(ff.getFontColorIndex()); .append(ff.getFontColorIndex());
if (ff.isBold()) b.append(" bold"); if (ff.isBold()) {
if (ff.isItalic()) b.append(" italic"); b.append(" bold");
if (ff.isStruckout()) b.append(" strikeout"); }
if (ff.isItalic()) {
b.append(" italic");
}
if (ff.isStruckout()) {
b.append(" strikeout");
}
b.append(" underline index ") b.append(" underline index ")
.append(ff.getUnderlineType()); .append(ff.getUnderlineType());
} }

View File

@ -33,7 +33,6 @@ import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.format.CellFormat; import org.apache.poi.ss.format.CellFormat;
import org.apache.poi.ss.format.CellFormatResult; import org.apache.poi.ss.format.CellFormatResult;
import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.BorderStyle;
@ -189,10 +188,15 @@ public class ToHtml {
return; return;
} }
ToHtml toHtml = create(args[0], new PrintWriter(new FileWriter(args[1]))); try (
FileWriter fw = new FileWriter(args[1]);
PrintWriter pw = new PrintWriter(fw)
) {
ToHtml toHtml = create(args[0], pw);
toHtml.setCompleteHTML(true); toHtml.setCompleteHTML(true);
toHtml.printPage(); toHtml.printPage();
} }
}
public void setCompleteHTML(boolean completeHTML) { public void setCompleteHTML(boolean completeHTML) {
this.completeHTML = completeHTML; this.completeHTML = completeHTML;
@ -375,7 +379,7 @@ public class ToHtml {
// compute width of the header column // compute width of the header column
int lastRowNum = sheet.getLastRowNum(); int lastRowNum = sheet.getLastRowNum();
int headerCharCount = String.valueOf(lastRowNum).length(); int headerCharCount = String.valueOf(lastRowNum).length();
int headerColWidth = widthToPixels((headerCharCount + 1) * 256); int headerColWidth = widthToPixels((headerCharCount + 1) * 256.0);
ret.put(IDX_HEADER_COL_WIDTH, headerColWidth); ret.put(IDX_HEADER_COL_WIDTH, headerColWidth);
tableWidth += headerColWidth; tableWidth += headerColWidth;

View File

@ -59,26 +59,30 @@ public class BarChartDemo {
BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) { BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
String chartTitle = modelReader.readLine(); // first line is chart title String chartTitle = modelReader.readLine(); // first line is chart title
String[] series = modelReader.readLine().split(",");
// Category Axis Data // Category Axis Data
List<String> listCategories = new ArrayList<String>(3); List<String> listLanguages = new ArrayList<>(10);
// Values // Values
List<Double> listValues = new ArrayList<Double>(3); List<Double> listCountries = new ArrayList<>(10);
List<Double> listSpeakers = new ArrayList<>(10);
// set model // set model
String ln; String ln;
while((ln = modelReader.readLine()) != null){ while((ln = modelReader.readLine()) != null) {
String[] vals = ln.split("\\s+"); String[] vals = ln.split(",");
listCategories.add(vals[0]); listCountries.add(Double.valueOf(vals[0]));
listValues.add(Double.valueOf(vals[1])); listSpeakers.add(Double.valueOf(vals[1]));
listLanguages.add(vals[2]);
} }
String[] categories = listCategories.toArray(new String[listCategories.size()]); String[] categories = listLanguages.toArray(new String[listLanguages.size()]);
Double[] values = listValues.toArray(new Double[listValues.size()]); Double[] values1 = listCountries.toArray(new Double[listCountries.size()]);
Double[] values2 = listSpeakers.toArray(new Double[listSpeakers.size()]);
try (XMLSlideShow pptx = new XMLSlideShow(argIS)) { try (XMLSlideShow pptx = new XMLSlideShow(argIS)) {
XSLFSlide slide = pptx.getSlides().get(0); XSLFSlide slide = pptx.getSlides().get(0);
setBarData(findChart(slide), chartTitle, categories, values); setBarData(findChart(slide), chartTitle, series, categories, values1, values2);
XSLFChart chart = findChart(pptx.createSlide().importContent(slide)); XSLFChart chart = findChart(pptx.createSlide().importContent(slide));
setColumnData(chart, "Column variant"); setColumnData(chart, "Column variant");
@ -91,30 +95,41 @@ public class BarChartDemo {
} }
} }
private static void setBarData(XSLFChart chart, String chartTitle, String[] categories, Double[] values) { private static void setBarData(XSLFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
final List<XDDFChartData> series = chart.getChartSeries(); final List<XDDFChartData> data = chart.getChartSeries();
final XDDFBarChartData bar = (XDDFBarChartData) series.get(0); final XDDFBarChartData bar = (XDDFBarChartData) data.get(0);
final int numOfPoints = categories.length; final int numOfPoints = categories.length;
final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0)); final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1)); final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange); final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange); 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().get(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));
bar.getSeries().get(0).replaceData(categoriesData, valuesData);
bar.getSeries().get(0).setTitle(chartTitle, chart.setSheetTitle(chartTitle));
chart.plot(bar); chart.plot(bar);
chart.setTitleText(chartTitle); // https://stackoverflow.com/questions/30532612
// chart.setTitleOverlay(overlay);
} }
private static void setColumnData(XSLFChart chart, String chartTitle) { private static void setColumnData(XSLFChart chart, String chartTitle) {
// Series Text // Series Text
List<XDDFChartData> series = chart.getChartSeries(); List<XDDFChartData> series = chart.getChartSeries();
XDDFBarChartData bar = (XDDFBarChartData) series.get(0); XDDFBarChartData bar = (XDDFBarChartData) series.get(0);
bar.getSeries().get(0).setTitle(chartTitle, chart.setSheetTitle(chartTitle));
// in order to transform a bar chart into a column chart, you just need to change the bar direction // in order to transform a bar chart into a column chart, you just need to change the bar direction
bar.setBarDirection(BarDirection.COL); bar.setBarDirection(BarDirection.COL);
// looking for "Stacked Bar Chart"? uncomment the following line
// bar.setBarGrouping(BarGrouping.STACKED);
// additionally, you can adjust the axes // additionally, you can adjust the axes
bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN); bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN);
bar.getValueAxes().get(0).setPosition(AxisPosition.TOP); bar.getValueAxes().get(0).setPosition(AxisPosition.TOP);

View File

@ -77,10 +77,10 @@ public class PieChartDemo {
XDDFPieChartData pie = (XDDFPieChartData) series.get(0); XDDFPieChartData pie = (XDDFPieChartData) series.get(0);
// Category Axis Data // Category Axis Data
List<String> listCategories = new ArrayList<String>(3); List<String> listCategories = new ArrayList<>(3);
// Values // Values
List<Double> listValues = new ArrayList<Double>(3); List<Double> listValues = new ArrayList<>(3);
// set model // set model
String ln; String ln;
@ -100,7 +100,7 @@ public class PieChartDemo {
XDDFPieChartData.Series firstSeries = (XDDFPieChartData.Series) pie.getSeries().get(0); XDDFPieChartData.Series firstSeries = (XDDFPieChartData.Series) pie.getSeries().get(0);
firstSeries.replaceData(categoriesData, valuesData); firstSeries.replaceData(categoriesData, valuesData);
firstSeries.setTitle(chartTitle, chart.setSheetTitle(chartTitle)); firstSeries.setTitle(chartTitle, chart.setSheetTitle(chartTitle, 0));
firstSeries.setExplosion(25); firstSeries.setExplosion(25);
chart.plot(pie); chart.plot(pie);

View File

@ -1,4 +1,12 @@
My Bar or Column Chart 10 languages with most speakers as first language
First 1.0 countries,speakers,language
Second 3.0 58,315,العربية
Third 4.0 4,243,বাংলা
38,1299,中文
118,378,English
4,260,हिन्दी
2,128,日本語
15,223,português
6,119,ਪੰਜਾਬੀ
18,154,Русский язык
31,442,español

View File

@ -0,0 +1,200 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF 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.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.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.XDDFBarChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
import org.apache.poi.xddf.usermodel.chart.XDDFCategoryDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
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 class BarAndLineChart {
private static final int NUM_OF_ROWS = 7;
private static final Random RNG = new Random();
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(solidLine(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, lineCategories, rightValues);
XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(xs, ys1);
series1.setTitle("Bars", new CellReference("Sheet1!$B$1"));
bar.setVaryColors(true);
bar.setBarDirection(BarDirection.COL);
chart.plot(bar);
// the line chart
XDDFLineChartData lines = (XDDFLineChartData) chart.createData(ChartTypes.LINE, lineCategories,
rightValues);
XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) lines.addSeries(xs, ys2);
series2.setTitle("Lines", new CellReference("Sheet1!$C$1"));
lines.setVaryColors(true);
chart.plot(lines);
// some colors
solidFillSeries(bar, 0, PresetColor.CHARTREUSE);
solidLineSeries(lines, 0, PresetColor.TURQUOISE);
// 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);
}
}
}
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);
}
private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
XDDFLineProperties line = solidLine(color);
XDDFChartData.Series series = data.getSeries().get(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setLineProperties(line);
series.setShapeProperties(properties);
}
private static XDDFLineProperties solidLine(PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFLineProperties line = new XDDFLineProperties();
line.setFillProperties(fill);
return line;
}
}

View File

@ -28,8 +28,10 @@ import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties; import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.chart.AxisCrosses; import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
import org.apache.poi.xddf.usermodel.chart.AxisPosition; 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.ChartTypes;
import org.apache.poi.xddf.usermodel.chart.LegendPosition; 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.XDDFCategoryAxis;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData; import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend; import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
@ -61,7 +63,7 @@ public class BarChart {
row = sheet.createRow((short) rowIndex); row = sheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) { for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex); cell = row.createCell((short) colIndex);
cell.setCellValue(colIndex * (rowIndex + 1)); cell.setCellValue(colIndex * (rowIndex + 1.0));
} }
} }
@ -69,12 +71,16 @@ public class BarChart {
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15); XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor); XSSFChart chart = drawing.createChart(anchor);
chart.setTitleText("x = 2x and x = 3x");
chart.setTitleOverlay(false);
XDDFChartLegend legend = chart.getOrAddLegend(); XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT); legend.setPosition(LegendPosition.TOP_RIGHT);
// Use a category axis for the bottom axis. // Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1)); XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
@ -82,18 +88,20 @@ public class BarChart {
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 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 data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
data.addSeries(xs, ys1); XDDFChartData.Series series1 = data.addSeries(xs, ys1);
data.addSeries(xs, ys2); series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
XDDFChartData.Series series2 = data.addSeries(xs, ys2);
series2.setTitle("3x", null);
chart.plot(data); chart.plot(data);
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHARTREUSE)); // in order to transform a bar chart into a column chart, you just need to change the bar direction
XDDFChartData.Series firstSeries = data.getSeries().get(0); XDDFBarChartData bar = (XDDFBarChartData) data;
XDDFShapeProperties properties = firstSeries.getShapeProperties(); bar.setBarDirection(BarDirection.COL);
if (properties == null) { // looking for "Stacked Bar Chart"? uncomment the following line
properties = new XDDFShapeProperties(); // bar.setBarGrouping(BarGrouping.STACKED);
}
properties.setFillProperties(fill); solidFillSeries(data, 0, PresetColor.CHARTREUSE);
firstSeries.setShapeProperties(properties); solidFillSeries(data, 1, PresetColor.TURQUOISE);
// Write the output to a file // Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-bar-chart.xlsx")) { try (FileOutputStream fileOut = new FileOutputStream("ooxml-bar-chart.xlsx")) {
@ -101,4 +109,15 @@ public class BarChart {
} }
} }
} }
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);
}
} }

View File

@ -99,7 +99,10 @@ public final class BigGridDemo {
//Step 2. Generate XML file. //Step 2. Generate XML file.
File tmp = File.createTempFile("sheet", ".xml"); File tmp = File.createTempFile("sheet", ".xml");
try (Writer fw = new OutputStreamWriter(new FileOutputStream(tmp), XML_ENCODING)) { try (
FileOutputStream stream = new FileOutputStream(tmp);
Writer fw = new OutputStreamWriter(stream, XML_ENCODING)
) {
generate(fw, styles); generate(fw, styles);
} }
@ -265,7 +268,9 @@ public final class BigGridDemo {
public void createCell(int columnIndex, String value, int styleIndex) throws IOException { public void createCell(int columnIndex, String value, int styleIndex) throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString(); String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\""+ref+"\" t=\"inlineStr\""); _out.write("<c r=\""+ref+"\" t=\"inlineStr\"");
if(styleIndex != -1) _out.write(" s=\""+styleIndex+"\""); if(styleIndex != -1) {
_out.write(" s=\""+styleIndex+"\"");
}
_out.write(">"); _out.write(">");
_out.write("<is><t>"+value+"</t></is>"); _out.write("<is><t>"+value+"</t></is>");
_out.write("</c>"); _out.write("</c>");
@ -278,7 +283,9 @@ public final class BigGridDemo {
public void createCell(int columnIndex, double value, int styleIndex) throws IOException { public void createCell(int columnIndex, double value, int styleIndex) throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString(); String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\""+ref+"\" t=\"n\""); _out.write("<c r=\""+ref+"\" t=\"n\"");
if(styleIndex != -1) _out.write(" s=\""+styleIndex+"\""); if(styleIndex != -1) {
_out.write(" s=\""+styleIndex+"\"");
}
_out.write(">"); _out.write(">");
_out.write("<v>"+value+"</v>"); _out.write("<v>"+value+"</v>");
_out.write("</c>"); _out.write("</c>");

View File

@ -39,8 +39,12 @@ public class CreateTable {
try (Workbook wb = new XSSFWorkbook()) { try (Workbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = (XSSFSheet) wb.createSheet(); XSSFSheet sheet = (XSSFSheet) 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 // Create
XSSFTable table = sheet.createTable(); XSSFTable table = sheet.createTable(reference);
table.setName("Test"); table.setName("Test");
table.setDisplayName("Test_Table"); table.setDisplayName("Test_Table");
@ -70,7 +74,7 @@ public class CreateTable {
if (i == 0) { if (i == 0) {
cell.setCellValue("Column" + (j + 1)); cell.setCellValue("Column" + (j + 1));
} else { } else {
cell.setCellValue((i + 1) * (j + 1)); cell.setCellValue((i + 1.0) * (j + 1.0));
} }
} }
} }
@ -79,11 +83,6 @@ public class CreateTable {
table.createColumn("Column 2"); table.createColumn("Column 2");
table.createColumn("Column 3"); table.createColumn("Column 3");
// Set which area the table should be placed in
AreaReference reference = wb.getCreationHelper().createAreaReference(
new CellReference(0, 0), new CellReference(2, 2));
table.setCellReferences(reference);
// Save // Save
try (FileOutputStream fileOut = new FileOutputStream("ooxml-table.xlsx")) { try (FileOutputStream fileOut = new FileOutputStream("ooxml-table.xlsx")) {
wb.write(fileOut); wb.write(fileOut);

View File

@ -32,7 +32,10 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class IterateCells { public class IterateCells {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
try (Workbook wb = new XSSFWorkbook(new FileInputStream(args[0]))) { try (
FileInputStream is = new FileInputStream(args[0]);
Workbook wb = new XSSFWorkbook(is)
) {
for (int i = 0; i < wb.getNumberOfSheets(); i++) { for (int i = 0; i < wb.getNumberOfSheets(); i++) {
Sheet sheet = wb.getSheetAt(i); Sheet sheet = wb.getSheetAt(i);
System.out.println(wb.getSheetName(i)); System.out.println(wb.getSheetName(i));

View File

@ -22,15 +22,22 @@ import java.io.IOException;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress; 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.AxisCrosses;
import org.apache.poi.xddf.usermodel.chart.AxisPosition; import org.apache.poi.xddf.usermodel.chart.AxisPosition;
import org.apache.poi.xddf.usermodel.chart.ChartTypes; import org.apache.poi.xddf.usermodel.chart.ChartTypes;
import org.apache.poi.xddf.usermodel.chart.LegendPosition; 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.XDDFCategoryAxis;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData; import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend; import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSource; import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory; 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.XDDFNumericalDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis; import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
import org.apache.poi.xssf.usermodel.XSSFChart; import org.apache.poi.xssf.usermodel.XSSFChart;
@ -57,7 +64,7 @@ public class LineChart {
row = sheet.createRow((short) rowIndex); row = sheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) { for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex); cell = row.createCell((short) colIndex);
cell.setCellValue(colIndex * (rowIndex + 1)); cell.setCellValue(colIndex * (rowIndex + 1.0));
} }
} }
@ -70,22 +77,51 @@ public class LineChart {
// Use a category axis for the bottom axis. // Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1)); 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> 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)); XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
XDDFChartData data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis); XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
data.addSeries(xs, ys1); XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1);
data.addSeries(xs, ys2); 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); 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 // Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) { try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) {
wb.write(fileOut); 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);
}
} }

View File

@ -25,6 +25,11 @@ import java.io.IOException;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress; 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.AxisCrosses;
import org.apache.poi.xddf.usermodel.chart.AxisPosition; import org.apache.poi.xddf.usermodel.chart.AxisPosition;
import org.apache.poi.xddf.usermodel.chart.ChartTypes; import org.apache.poi.xddf.usermodel.chart.ChartTypes;
@ -34,6 +39,7 @@ import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSource; import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory; import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource; 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.chart.XDDFValueAxis;
import org.apache.poi.xssf.usermodel.XSSFChart; import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
@ -59,7 +65,7 @@ public class ScatterChart {
row = sheet.createRow((short) rowIndex); row = sheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) { for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex); cell = row.createCell((short) colIndex);
cell.setCellValue(colIndex * (rowIndex + 1)); cell.setCellValue(colIndex * (rowIndex + 1.0));
} }
} }
@ -71,7 +77,9 @@ public class ScatterChart {
legend.setPosition(LegendPosition.TOP_RIGHT); legend.setPosition(LegendPosition.TOP_RIGHT);
XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM); XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1)); XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
@ -79,16 +87,34 @@ public class ScatterChart {
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 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.SCATTER, bottomAxis, leftAxis); XDDFScatterChartData data = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) data.addSeries(xs, ys1);
data.addSeries(xs, ys1); series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
data.addSeries(xs, ys2); series1.setSmooth(false); // https://stackoverflow.com/questions/39636138
XDDFScatterChartData.Series series2 = (XDDFScatterChartData.Series) data.addSeries(xs, ys2);
series2.setTitle("3x", null);
chart.plot(data); chart.plot(data);
solidLineSeries(data, 0, PresetColor.CHARTREUSE);
solidLineSeries(data, 1, PresetColor.TURQUOISE);
// Write the output to a file // Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-scatter-chart.xlsx")) { try (FileOutputStream fileOut = new FileOutputStream("ooxml-scatter-chart.xlsx")) {
wb.write(fileOut); 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);
}
} }

View File

@ -43,9 +43,9 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument;
/** /**
* Build a bar chart from a template docx * Build a bar chart from a template docx
*/ */
public class BarChartExampleDOCX { public class BarChartExample {
private static void usage(){ private static void usage(){
System.out.println("Usage: BarChartDemo <bar-chart-template.docx> <bar-chart-data.txt>"); 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-template.docx template with a bar chart");
System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " + System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
"then go pairs {axis-label value}"); "then go pairs {axis-label value}");
@ -61,26 +61,30 @@ public class BarChartExampleDOCX {
BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) { BufferedReader modelReader = new BufferedReader(new FileReader(args[1]))) {
String chartTitle = modelReader.readLine(); // first line is chart title String chartTitle = modelReader.readLine(); // first line is chart title
String[] series = modelReader.readLine().split(",");
// Category Axis Data // Category Axis Data
List<String> listCategories = new ArrayList<String>(3); List<String> listLanguages = new ArrayList<>(10);
// Values // Values
List<Double> listValues = new ArrayList<Double>(3); List<Double> listCountries = new ArrayList<>(10);
List<Double> listSpeakers = new ArrayList<>(10);
// set model // set model
String ln; String ln;
while((ln = modelReader.readLine()) != null) { while((ln = modelReader.readLine()) != null) {
String[] vals = ln.split("\\s+"); String[] vals = ln.split(",");
listCategories.add(vals[0]); listCountries.add(Double.valueOf(vals[0]));
listValues.add(Double.valueOf(vals[1])); listSpeakers.add(Double.valueOf(vals[1]));
listLanguages.add(vals[2]);
} }
String[] categories = listCategories.toArray(new String[listCategories.size()]); String[] categories = listLanguages.toArray(new String[listLanguages.size()]);
Double[] values = listValues.toArray(new Double[listValues.size()]); Double[] values1 = listCountries.toArray(new Double[listCountries.size()]);
Double[] values2 = listSpeakers.toArray(new Double[listSpeakers.size()]);
try (XWPFDocument doc = new XWPFDocument(argIS)) { try (XWPFDocument doc = new XWPFDocument(argIS)) {
XWPFChart chart = doc.getCharts().get(0); XWPFChart chart = doc.getCharts().get(0);
setBarData(chart, chartTitle, categories, values); setBarData(chart, chartTitle, series, categories, values1, values2);
chart = doc.getCharts().get(1); chart = doc.getCharts().get(1);
setColumnData(chart, "Column variant"); setColumnData(chart, "Column variant");
@ -93,33 +97,41 @@ public class BarChartExampleDOCX {
System.out.println("Done"); System.out.println("Done");
} }
private static void setBarData(XWPFChart chart, String chartTitle, String[] categories, Double[] values) { private static void setBarData(XWPFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
final List<XDDFChartData> series = chart.getChartSeries(); final List<XDDFChartData> data = chart.getChartSeries();
final XDDFBarChartData bar = (XDDFBarChartData) series.get(0); final XDDFBarChartData bar = (XDDFBarChartData) data.get(0);
final int numOfPoints = categories.length; final int numOfPoints = categories.length;
final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0)); final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1)); final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2)); final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0); final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange, 1); final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1);
values[2] = 10.0; values1[6] = 16.0; // if you ever want to change the underlying data
final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values, valuesDataRange2, 2); final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);
bar.getSeries().get(0).replaceData(categoriesData, valuesData);
bar.addSeries(categoriesData, valuesData2); XDDFChartData.Series series1 = bar.getSeries().get(0);
bar.getSeries().get(0).setTitle(chartTitle, chart.setSheetTitle(chartTitle)); 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.plot(bar);
chart.setTitleText(chartTitle); // https://stackoverflow.com/questions/30532612
chart.setTitleOverlay(false);
} }
private static void setColumnData(XWPFChart chart, String chartTitle) { private static void setColumnData(XWPFChart chart, String chartTitle) {
// Series Text // Series Text
List<XDDFChartData> series = chart.getChartSeries(); List<XDDFChartData> series = chart.getChartSeries();
XDDFBarChartData bar = (XDDFBarChartData) series.get(0); XDDFBarChartData bar = (XDDFBarChartData) series.get(0);
bar.getSeries().get(0).setTitle(chartTitle, chart.setSheetTitle(chartTitle));
// in order to transform a bar chart into a column chart, you just need to change the bar direction // in order to transform a bar chart into a column chart, you just need to change the bar direction
bar.setBarDirection(BarDirection.COL); bar.setBarDirection(BarDirection.COL);
// looking for "Stacked Bar Chart"? uncomment the following line
// bar.setBarGrouping(BarGrouping.STACKED);
// additionally, you can adjust the axes // additionally, you can adjust the axes
bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN); bar.getCategoryAxis().setOrientation(AxisOrientation.MAX_MIN);
bar.getValueAxes().get(0).setPosition(AxisPosition.TOP); bar.getValueAxes().get(0).setPosition(AxisPosition.TOP);

View File

@ -111,16 +111,16 @@ public class SimpleDocument {
r5.setTextPosition(-10); r5.setTextPosition(-10);
r5.setText("For in that sleep of death what dreams may come"); r5.setText("For in that sleep of death what dreams may come");
r5.addCarriageReturn(); r5.addCarriageReturn();
r5.setText("When we have shuffled off this mortal coil," r5.setText("When we have shuffled off this mortal coil, "
+ "Must give us pause: there's the respect" + "Must give us pause: there's the respect "
+ "That makes calamity of so long life;"); + "That makes calamity of so long life;");
r5.addBreak(); r5.addBreak();
r5.setText("For who would bear the whips and scorns of time," r5.setText("For who would bear the whips and scorns of time, "
+ "The oppressor's wrong, the proud man's contumely,"); + "The oppressor's wrong, the proud man's contumely,");
r5.addBreak(BreakClear.ALL); r5.addBreak(BreakClear.ALL);
r5.setText("The pangs of despised love, the law's delay," r5.setText("The pangs of despised love, the law's delay, "
+ "The insolence of office and the spurns" + "......."); + "The insolence of office and the spurns " + ".......");
try (FileOutputStream out = new FileOutputStream("simple.docx")) { try (FileOutputStream out = new FileOutputStream("simple.docx")) {
doc.write(out); doc.write(out);

View File

@ -43,18 +43,29 @@ public class SimpleImages {
for (String imgFile : args) { for (String imgFile : args) {
int format; int format;
if (imgFile.endsWith(".emf")) format = XWPFDocument.PICTURE_TYPE_EMF; if (imgFile.endsWith(".emf")) {
else if (imgFile.endsWith(".wmf")) format = XWPFDocument.PICTURE_TYPE_WMF; format = XWPFDocument.PICTURE_TYPE_EMF;
else if (imgFile.endsWith(".pict")) format = XWPFDocument.PICTURE_TYPE_PICT; } else if (imgFile.endsWith(".wmf")) {
else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) format = XWPFDocument.PICTURE_TYPE_JPEG; format = XWPFDocument.PICTURE_TYPE_WMF;
else if (imgFile.endsWith(".png")) format = XWPFDocument.PICTURE_TYPE_PNG; } else if (imgFile.endsWith(".pict")) {
else if (imgFile.endsWith(".dib")) format = XWPFDocument.PICTURE_TYPE_DIB; format = XWPFDocument.PICTURE_TYPE_PICT;
else if (imgFile.endsWith(".gif")) format = XWPFDocument.PICTURE_TYPE_GIF; } else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) {
else if (imgFile.endsWith(".tiff")) format = XWPFDocument.PICTURE_TYPE_TIFF; format = XWPFDocument.PICTURE_TYPE_JPEG;
else if (imgFile.endsWith(".eps")) format = XWPFDocument.PICTURE_TYPE_EPS; } else if (imgFile.endsWith(".png")) {
else if (imgFile.endsWith(".bmp")) format = XWPFDocument.PICTURE_TYPE_BMP; format = XWPFDocument.PICTURE_TYPE_PNG;
else if (imgFile.endsWith(".wpg")) format = XWPFDocument.PICTURE_TYPE_WPG; } else if (imgFile.endsWith(".dib")) {
else { format = XWPFDocument.PICTURE_TYPE_DIB;
} else if (imgFile.endsWith(".gif")) {
format = XWPFDocument.PICTURE_TYPE_GIF;
} else if (imgFile.endsWith(".tiff")) {
format = XWPFDocument.PICTURE_TYPE_TIFF;
} else if (imgFile.endsWith(".eps")) {
format = XWPFDocument.PICTURE_TYPE_EPS;
} else if (imgFile.endsWith(".bmp")) {
format = XWPFDocument.PICTURE_TYPE_BMP;
} else if (imgFile.endsWith(".wpg")) {
format = XWPFDocument.PICTURE_TYPE_WPG;
} else {
System.err.println("Unsupported picture: " + imgFile + System.err.println("Unsupported picture: " + imgFile +
". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg"); ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
continue; continue;
@ -62,7 +73,9 @@ public class SimpleImages {
r.setText(imgFile); r.setText(imgFile);
r.addBreak(); r.addBreak();
r.addPicture(new FileInputStream(imgFile), format, imgFile, Units.toEMU(200), Units.toEMU(200)); // 200x200 pixels try (FileInputStream is = new FileInputStream(imgFile)) {
r.addPicture(is, format, imgFile, Units.toEMU(200), Units.toEMU(200)); // 200x200 pixels
}
r.addBreak(BreakType.PAGE); r.addBreak(BreakType.PAGE);
} }

View File

@ -1,4 +1,12 @@
My Bar or Column Chart 10 languages with most speakers as first language
First 1.0 countries,speakers,language
Second 3.0 58,315,العربية
Third 4.0 4,243,বাংলা
38,1299,中文
118,378,English
4,260,हिन्दी
2,128,日本語
15,223,português
6,119,ਪੰਜਾਬੀ
18,154,Русский язык
31,442,español

View File

@ -336,7 +336,7 @@ public abstract class EscherRecord implements Cloneable {
String tagName = capitalizeAndTrim((String)attrs[0]); String tagName = capitalizeAndTrim((String)attrs[0]);
boolean hasValue = false; boolean hasValue = false;
boolean lastChildComplex = false; boolean lastChildComplex = false;
for (int i=0; i<attrs.length; i+=2) { for (int i=0; i<attrs.length-1; i+=2) {
Object value = attrs[i+1]; Object value = attrs[i+1];
if (value == null) { if (value == null) {
// ignore null values // ignore null values
@ -384,7 +384,7 @@ public abstract class EscherRecord implements Cloneable {
if (attrList != null && attrList.length > 0) { if (attrList != null && attrList.length > 0) {
String childTab = " "; String childTab = " ";
for (Object[] attrs : attrList) { for (Object[] attrs : attrList) {
for (int i=0; i<attrs.length; i+=2) { for (int i=0; i<attrs.length-1; i+=2) {
Object value = attrs[i+1]; Object value = attrs[i+1];
if (value == null) { if (value == null) {
// ignore null values // ignore null values

View File

@ -21,15 +21,7 @@ import java.text.CollationKey;
import java.text.Collator; import java.text.Collator;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.poi.ss.formula.eval.BlankEval; import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.BoolEval; import org.apache.poi.ss.formula.eval.BoolEval;
@ -900,9 +892,9 @@ public class EvaluationConditionalFormatRule implements Comparable<EvaluationCon
return false; return false;
} }
ValueAndFormat o = (ValueAndFormat) obj; ValueAndFormat o = (ValueAndFormat) obj;
return ( value == o.value || value.equals(o.value)) return (Objects.equals(value, o.value)
&& ( format == o.format || format.equals(o.format)) && Objects.equals(format, o.format)
&& (string == o.string || string.equals(o.string)); && Objects.equals(string, o.string));
} }
/** /**

View File

@ -382,9 +382,6 @@ public final class FormulaParser {
if (token instanceof OperandPtg) { if (token instanceof OperandPtg) {
return false; return false;
} }
if (token instanceof OperationPtg) {
return true;
}
return false; return false;
} }

View File

@ -77,7 +77,7 @@ final class RandBetween implements FreeRefFunction{
top = bottom; top = bottom;
} }
return new NumberEval((bottom + (int)(Math.random() * ((top - bottom) + 1)))); return new NumberEval((bottom + (long)(Math.random() * ((top - bottom) + 1))));
} }

View File

@ -34,7 +34,7 @@ public final class StaxHelper {
* Creates a new StAX XMLInputFactory, with sensible defaults * Creates a new StAX XMLInputFactory, with sensible defaults
*/ */
public static XMLInputFactory newXMLInputFactory() { public static XMLInputFactory newXMLInputFactory() {
XMLInputFactory factory = XMLInputFactory.newFactory(); XMLInputFactory factory = XMLInputFactory.newInstance();
trySetProperty(factory, XMLInputFactory.IS_NAMESPACE_AWARE, true); trySetProperty(factory, XMLInputFactory.IS_NAMESPACE_AWARE, true);
trySetProperty(factory, XMLInputFactory.IS_VALIDATING, false); trySetProperty(factory, XMLInputFactory.IS_VALIDATING, false);
trySetProperty(factory, XMLInputFactory.SUPPORT_DTD, false); trySetProperty(factory, XMLInputFactory.SUPPORT_DTD, false);
@ -46,7 +46,7 @@ public final class StaxHelper {
* Creates a new StAX XMLOutputFactory, with sensible defaults * Creates a new StAX XMLOutputFactory, with sensible defaults
*/ */
public static XMLOutputFactory newXMLOutputFactory() { public static XMLOutputFactory newXMLOutputFactory() {
XMLOutputFactory factory = XMLOutputFactory.newFactory(); XMLOutputFactory factory = XMLOutputFactory.newInstance();
trySetProperty(factory, XMLOutputFactory.IS_REPAIRING_NAMESPACES, true); trySetProperty(factory, XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
return factory; return factory;
} }
@ -55,7 +55,8 @@ public final class StaxHelper {
* Creates a new StAX XMLEventFactory, with sensible defaults * Creates a new StAX XMLEventFactory, with sensible defaults
*/ */
public static XMLEventFactory newXMLEventFactory() { public static XMLEventFactory newXMLEventFactory() {
return XMLEventFactory.newFactory(); // this method seems safer on Android than getFactory()
return XMLEventFactory.newInstance();
} }
private static void trySetProperty(XMLInputFactory factory, String feature, boolean flag) { private static void trySetProperty(XMLInputFactory factory, String feature, boolean flag) {

View File

@ -223,7 +223,7 @@ public class POIXMLProperties {
throw new POIXMLException(e); throw new POIXMLException(e);
} }
} }
if(extPart != null){ if(extPart != null && ext != null && ext.props != null){
try (OutputStream out = extPart.getOutputStream()) { try (OutputStream out = extPart.getOutputStream()) {
if (extPart.getSize() > 0) { if (extPart.getSize() > 0) {
extPart.clear(); extPart.clear();
@ -231,7 +231,7 @@ public class POIXMLProperties {
ext.props.save(out, DEFAULT_XML_OPTIONS); ext.props.save(out, DEFAULT_XML_OPTIONS);
} }
} }
if(custPart != null){ if(custPart != null && cust != null && cust.props != null){
try (OutputStream out = custPart.getOutputStream()) { try (OutputStream out = custPart.getOutputStream()) {
cust.props.save(out, DEFAULT_XML_OPTIONS); cust.props.save(out, DEFAULT_XML_OPTIONS);
} }

View File

@ -28,7 +28,6 @@ import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.*; import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -416,6 +415,8 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
* If your package is open read only, then you should call {@link #revert()} * If your package is open read only, then you should call {@link #revert()}
* when finished with the package. * when finished with the package.
* *
* This method is not thread-safe.
*
* @throws IOException * @throws IOException
* If an IO exception occur during the saving process. * If an IO exception occur during the saving process.
*/ */
@ -434,10 +435,6 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
return; return;
} }
// Save the content
ReentrantReadWriteLock l = new ReentrantReadWriteLock();
try {
l.writeLock().lock();
if (this.originalPackagePath != null if (this.originalPackagePath != null
&& !this.originalPackagePath.trim().isEmpty()) { && !this.originalPackagePath.trim().isEmpty()) {
File targetFile = new File(this.originalPackagePath); File targetFile = new File(this.originalPackagePath);
@ -453,9 +450,6 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
save(this.output); save(this.output);
output.close(); output.close();
} }
} finally {
l.writeLock().unlock();
}
// Clear // Clear
this.contentTypeManager.clearAll(); this.contentTypeManager.clearAll();

View File

@ -21,8 +21,6 @@ import java.io.OutputStream;
import java.util.Optional; import java.util.Optional;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.events.Namespace;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
@ -36,14 +34,14 @@ import org.w3c.dom.Element;
* Package properties marshaller. * Package properties marshaller.
*/ */
public class PackagePropertiesMarshaller implements PartMarshaller { public class PackagePropertiesMarshaller implements PartMarshaller {
private final static Namespace namespaceDC, namespaceCoreProperties, namespaceDcTerms, namespaceXSI; private final static NamespaceImpl namespaceDC =
static { new NamespaceImpl("dc", PackagePropertiesPart.NAMESPACE_DC_URI);
final XMLEventFactory f = XMLEventFactory.newInstance(); private final static NamespaceImpl namespaceCoreProperties =
namespaceDC = f.createNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI); new NamespaceImpl("cp", PackagePropertiesPart.NAMESPACE_CP_URI);;
namespaceCoreProperties = f.createNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI); private final static NamespaceImpl namespaceDcTerms =
namespaceDcTerms = f.createNamespace("dcterms", PackagePropertiesPart.NAMESPACE_DCTERMS_URI); new NamespaceImpl("dcterms", PackagePropertiesPart.NAMESPACE_DCTERMS_URI);
namespaceXSI = f.createNamespace("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); private final static NamespaceImpl namespaceXSI =
} new NamespaceImpl("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);;
protected static final String KEYWORD_CATEGORY = "category"; protected static final String KEYWORD_CATEGORY = "category";
@ -98,10 +96,14 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
xmlDoc = DocumentHelper.createDocument(); xmlDoc = DocumentHelper.createDocument();
Element rootElem = xmlDoc.createElementNS(namespaceCoreProperties.getNamespaceURI(), Element rootElem = xmlDoc.createElementNS(namespaceCoreProperties.getNamespaceURI(),
getQName("coreProperties", namespaceCoreProperties)); getQName("coreProperties", namespaceCoreProperties));
DocumentHelper.addNamespaceDeclaration(rootElem, namespaceCoreProperties); DocumentHelper.addNamespaceDeclaration(rootElem,
DocumentHelper.addNamespaceDeclaration(rootElem, namespaceDC); namespaceCoreProperties.getPrefix(), namespaceCoreProperties.getNamespaceURI());
DocumentHelper.addNamespaceDeclaration(rootElem, namespaceDcTerms); DocumentHelper.addNamespaceDeclaration(rootElem,
DocumentHelper.addNamespaceDeclaration(rootElem, namespaceXSI); namespaceDC.getPrefix(), namespaceDC.getNamespaceURI());
DocumentHelper.addNamespaceDeclaration(rootElem,
namespaceDcTerms.getPrefix(), namespaceDcTerms.getNamespaceURI());
DocumentHelper.addNamespaceDeclaration(rootElem,
namespaceXSI.getPrefix(), namespaceXSI.getNamespaceURI());
xmlDoc.appendChild(rootElem); xmlDoc.appendChild(rootElem);
addCategory(); addCategory();
@ -126,15 +128,15 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
/** /**
* Sets the given element's text content, creating it if necessary. * Sets the given element's text content, creating it if necessary.
*/ */
private Element setElementTextContent(String localName, Namespace namespace, Optional<String> property) { private Element setElementTextContent(String localName, NamespaceImpl namespace, Optional<String> property) {
return setElementTextContent(localName, namespace, property, property.orElse(null)); return setElementTextContent(localName, namespace, property, property.orElse(null));
} }
private String getQName(String localName, Namespace namespace) { private String getQName(String localName, NamespaceImpl namespace) {
return namespace.getPrefix().isEmpty() ? localName : namespace.getPrefix() + ':' + localName; return namespace.getPrefix().isEmpty() ? localName : namespace.getPrefix() + ':' + localName;
} }
private Element setElementTextContent(String localName, Namespace namespace, Optional<?> property, String propertyValue) { private Element setElementTextContent(String localName, NamespaceImpl namespace, Optional<?> property, String propertyValue) {
if (!property.isPresent()) if (!property.isPresent())
return null; return null;
@ -149,7 +151,7 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
return elem; return elem;
} }
private Element setElementTextContent(String localName, Namespace namespace, Optional<?> property, String propertyValue, String xsiType) { private Element setElementTextContent(String localName, NamespaceImpl namespace, Optional<?> property, String propertyValue, String xsiType) {
Element element = setElementTextContent(localName, namespace, property, propertyValue); Element element = setElementTextContent(localName, namespace, property, propertyValue);
if (element != null) { if (element != null) {
element.setAttributeNS(namespaceXSI.getNamespaceURI(), getQName("type", namespaceXSI), xsiType); element.setAttributeNS(namespaceXSI.getNamespaceURI(), getQName("type", namespaceXSI), xsiType);
@ -231,7 +233,6 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
/** /**
* Add 'last printed' property if needed. * Add 'last printed' property if needed.
*
*/ */
private void addLastPrinted() { private void addLastPrinted() {
setElementTextContent(KEYWORD_LAST_PRINTED, namespaceCoreProperties, propsPart.getLastPrintedProperty(), propsPart.getLastPrintedPropertyString()); setElementTextContent(KEYWORD_LAST_PRINTED, namespaceCoreProperties, propsPart.getLastPrintedProperty(), propsPart.getLastPrintedPropertyString());
@ -269,4 +270,20 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
private void addVersion() { private void addVersion() {
setElementTextContent(KEYWORD_VERSION, namespaceCoreProperties, propsPart.getVersionProperty()); setElementTextContent(KEYWORD_VERSION, namespaceCoreProperties, propsPart.getVersionProperty());
} }
private static class NamespaceImpl {
private final String prefix;
private final String namespaceURI;
NamespaceImpl(String prefix, String namespaceURI) {
this.prefix = prefix;
this.namespaceURI = namespaceURI;
}
public String getPrefix() { return prefix; }
public String getNamespaceURI() {
return namespaceURI;
}
}
} }

View File

@ -17,12 +17,17 @@
package org.apache.poi.openxml4j.util; package org.apache.poi.openxml4j.util;
import org.apache.poi.util.Removal;
/** /**
* An immutable object that could be defined as null. * An immutable object that could be defined as null.
* *
* @author Julien Chable * @author Julien Chable
* @version 0.9 * @version 0.9
* @deprecated No longer used in POI code base, use {@link java.util.Optional} instead
*/ */
@Removal(version = "4.2")
@Deprecated
public final class Nullable<E> { public final class Nullable<E> {
private E value; private E value;

View File

@ -150,7 +150,7 @@ import org.w3c.dom.events.EventTarget;
* <p>To use SignatureInfo and its sibling classes, you'll need to have the following libs * <p>To use SignatureInfo and its sibling classes, you'll need to have the following libs
* in the classpath:</p> * in the classpath:</p>
* <ul> * <ul>
* <li>BouncyCastle bcpkix and bcprov (tested against 1.59)</li> * <li>BouncyCastle bcpkix and bcprov (tested against 1.60)</li>
* <li>Apache Santuario "xmlsec" (tested against 2.1.0)</li> * <li>Apache Santuario "xmlsec" (tested against 2.1.0)</li>
* <li>and slf4j-api (tested against 1.7.25)</li> * <li>and slf4j-api (tested against 1.7.25)</li>
* </ul> * </ul>

View File

@ -0,0 +1,45 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xddf.usermodel.chart;
import java.util.HashMap;
import org.openxmlformats.schemas.drawingml.x2006.chart.STDispBlanksAs;
public enum DisplayBlanks {
GAP(STDispBlanksAs.GAP),
SPAN(STDispBlanksAs.SPAN),
ZERO(STDispBlanksAs.ZERO);
final STDispBlanksAs.Enum underlying;
DisplayBlanks(STDispBlanksAs.Enum mode) {
this.underlying = mode;
}
private final static HashMap<STDispBlanksAs.Enum, DisplayBlanks> reverse = new HashMap<>();
static {
for (DisplayBlanks value : values()) {
reverse.put(value.underlying, value);
}
}
static DisplayBlanks valueOf(STDispBlanksAs.Enum mode) {
return reverse.get(mode);
}
}

View File

@ -34,9 +34,24 @@ public class XDDFBarChartData extends XDDFChartData {
public XDDFBarChartData(CTBarChart chart, Map<Long, XDDFChartAxis> categories, public XDDFBarChartData(CTBarChart chart, Map<Long, XDDFChartAxis> categories,
Map<Long, XDDFValueAxis> values) { Map<Long, XDDFValueAxis> values) {
this.chart = chart; this.chart = chart;
if (chart.getBarDir() == null) {
chart.addNewBarDir().setVal(BarDirection.BAR.underlying);
}
for (CTBarSer series : chart.getSerList()) { for (CTBarSer series : chart.getSerList()) {
this.series.add(new Series(series, series.getCat(), series.getVal())); this.series.add(new Series(series, series.getCat(), series.getVal()));
} }
defineAxes(categories, values);
}
private void defineAxes(Map<Long, XDDFChartAxis> categories, Map<Long, XDDFValueAxis> values) {
if (chart.sizeOfAxIdArray() == 0) {
for (Long id : categories.keySet()) {
chart.addNewAxId().setVal(id);
}
for (Long id : values.keySet()) {
chart.addNewAxId().setVal(id);
}
}
defineAxes(chart.getAxIdArray(), categories, values); defineAxes(chart.getAxIdArray(), categories, values);
} }
@ -94,6 +109,7 @@ public class XDDFBarChartData extends XDDFChartData {
XDDFNumericalDataSource<? extends Number> values) { XDDFNumericalDataSource<? extends Number> values) {
final int index = this.series.size(); final int index = this.series.size();
final CTBarSer ctSer = this.chart.addNewSer(); final CTBarSer ctSer = this.chart.addNewSer();
ctSer.addNewTx();
ctSer.addNewCat(); ctSer.addNewCat();
ctSer.addNewVal(); ctSer.addNewVal();
ctSer.addNewIdx().setVal(index); ctSer.addNewIdx().setVal(index);
@ -119,7 +135,11 @@ public class XDDFBarChartData extends XDDFChartData {
@Override @Override
protected CTSerTx getSeriesText() { protected CTSerTx getSeriesText() {
if (series.isSetTx()) {
return series.getTx(); return series.getTx();
} else {
return series.addNewTx();
}
} }
@Override @Override

View File

@ -79,6 +79,19 @@ public class XDDFCategoryAxis extends XDDFChartAxis {
return new XDDFShapeProperties(properties); return new XDDFShapeProperties(properties);
} }
/**
* @since 4.0.1
*/
@Override
public void setTitle(String text) {
if (!ctCatAx.isSetTitle()) {
ctCatAx.addNewTitle();
}
XDDFTitle title = new XDDFTitle(null, ctCatAx.getTitle());
title.setOverlay(false);
title.setText(text);
}
@Override @Override
public boolean isSetMinorUnit() { public boolean isSetMinorUnit() {
return false; return false;

View File

@ -23,4 +23,23 @@ import org.apache.poi.util.Beta;
@Beta @Beta
public interface XDDFCategoryDataSource extends XDDFDataSource<String> { public interface XDDFCategoryDataSource extends XDDFDataSource<String> {
@Override
default int getColIndex() {
return 0;
}
@Override
default boolean isNumeric() {
return false;
}
@Override
default boolean isReference() {
return true;
}
@Override
default String getDataRangeReference() {
return getFormula();
}
} }

View File

@ -70,7 +70,6 @@ import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerAx; import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerAx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSurface; import org.openxmlformats.schemas.drawingml.x2006.chart.CTSurface;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTTitle; import org.openxmlformats.schemas.drawingml.x2006.chart.CTTitle;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx; import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx;
import org.openxmlformats.schemas.drawingml.x2006.chart.ChartSpaceDocument; import org.openxmlformats.schemas.drawingml.x2006.chart.ChartSpaceDocument;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
@ -214,6 +213,72 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
chart.getAutoTitleDeleted().setVal(deleted); chart.getAutoTitleDeleted().setVal(deleted);
} }
/**
* @since 4.0.1
*
*/
public void displayBlanksAs(DisplayBlanks as) {
if (as == null){
if (chart.isSetDispBlanksAs()) {
chart.unsetDispBlanksAs();
}
} else {
if (chart.isSetDispBlanksAs()) {
chart.getDispBlanksAs().setVal(as.underlying);
} else {
chart.addNewDispBlanksAs().setVal(as.underlying);
}
}
}
/**
* @since 4.0.1
*/
public Boolean getTitleOverlay() {
if (chart.isSetTitle()) {
CTTitle title = chart.getTitle();
if (title.isSetOverlay()) {
return title.getOverlay().getVal();
}
}
return null;
}
/**
* @since 4.0.1
*/
public void setTitleOverlay(boolean overlay) {
if (!chart.isSetTitle()) {
chart.addNewTitle();
}
new XDDFTitle(this, chart.getTitle()).setOverlay(overlay);
}
/**
* Sets the title text as a static string.
*
* @param text
* to use as new title
* @since 4.0.1
*/
public void setTitleText(String text) {
if (!chart.isSetTitle()) {
chart.addNewTitle();
}
new XDDFTitle(this, chart.getTitle()).setText(text);
}
/**
* @since 4.0.1
*/
public XDDFTitle getTitle() {
if (chart.isSetTitle()) {
return new XDDFTitle(this, chart.getTitle());
} else {
return null;
}
}
/** /**
* Get the chart title body if there is one, i.e. title is set and is not a * Get the chart title body if there is one, i.e. title is set and is not a
* formula. * formula.
@ -225,15 +290,7 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
if (!chart.isSetTitle()) { if (!chart.isSetTitle()) {
return null; return null;
} }
CTTitle title = chart.getTitle(); return new XDDFTitle(this, chart.getTitle()).getBody();
if (!title.isSetTx()) {
return null;
}
CTTx tx = title.getTx();
if (!tx.isSetRich()) {
return null;
}
return new XDDFTextBody(this, tx.getRich());
} }
@Override @Override
@ -327,7 +384,7 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
private Map<Long, XDDFChartAxis> getCategoryAxes() { private Map<Long, XDDFChartAxis> getCategoryAxes() {
CTPlotArea plotArea = getCTPlotArea(); CTPlotArea plotArea = getCTPlotArea();
int sizeOfArray = plotArea.sizeOfCatAxArray(); int sizeOfArray = plotArea.sizeOfCatAxArray();
Map<Long, XDDFChartAxis> axes = new HashMap<Long, XDDFChartAxis>(sizeOfArray); Map<Long, XDDFChartAxis> axes = new HashMap<>(sizeOfArray);
for (int i = 0; i < sizeOfArray; i++) { for (int i = 0; i < sizeOfArray; i++) {
CTCatAx category = plotArea.getCatAxArray(i); CTCatAx category = plotArea.getCatAxArray(i);
axes.put(category.getAxId().getVal(), new XDDFCategoryAxis(category)); axes.put(category.getAxId().getVal(), new XDDFCategoryAxis(category));
@ -641,20 +698,22 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
} }
/** /**
* set sheet time in excel file * set sheet title in excel file
* *
* @param title * @param title
* title of sheet * title of sheet
* @param column
* column index
* @return return cell reference * @return return cell reference
* @since POI 4.0.0 * @since POI 4.0.0
*/ */
public CellReference setSheetTitle(String title) { public CellReference setSheetTitle(String title, int column) {
XSSFSheet sheet = getSheet(); XSSFSheet sheet = getSheet();
XSSFRow row = this.getRow(sheet, 0); XSSFRow row = this.getRow(sheet, 0);
XSSFCell cell = this.getCell(row, 1); XSSFCell cell = this.getCell(row, column);
cell.setCellValue(title); cell.setCellValue(title);
this.updateSheetTable(sheet.getTables().get(0).getCTTable(), title, 1); this.updateSheetTable(sheet.getTables().get(0).getCTTable(), title, column);
return new CellReference(sheet.getSheetName(), 0, 1, true, true); return new CellReference(sheet.getSheetName(), 0, column, true, true);
} }
/** /**
@ -670,12 +729,11 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
private void updateSheetTable(CTTable ctTable, String title, int index) { private void updateSheetTable(CTTable ctTable, String title, int index) {
CTTableColumns tableColumnList = ctTable.getTableColumns(); CTTableColumns tableColumnList = ctTable.getTableColumns();
CTTableColumn column = null; CTTableColumn column = null;
if (tableColumnList.getCount() >= index) { for( int i = 0; tableColumnList.getCount() < index; i++) {
column = tableColumnList.getTableColumnArray(index);
} else {
column = tableColumnList.addNewTableColumn(); column = tableColumnList.addNewTableColumn();
column.setId(index); column.setId(i);
} }
column = tableColumnList.getTableColumnArray(index);
column.setName(title); column.setName(title);
} }

View File

@ -56,6 +56,11 @@ public abstract class XDDFChartAxis implements HasShapeProperties {
public abstract XDDFShapeProperties getOrAddMinorGridProperties(); public abstract XDDFShapeProperties getOrAddMinorGridProperties();
/**
* @since 4.0.1
*/
public abstract void setTitle(String text);
/** /**
* @return true if minor unit value is defined, false otherwise * @return true if minor unit value is defined, false otherwise
*/ */

View File

@ -130,6 +130,10 @@ public abstract class XDDFChartData {
} else { } else {
cache = ref.addNewStrCache(); cache = ref.addNewStrCache();
} }
if (cache.sizeOfPtArray() < 1) {
cache.addNewPtCount().setVal(1);
cache.addNewPt().setIdx(0);;
}
cache.getPtArray(0).setV(title); cache.getPtArray(0).setV(title);
ref.setF(titleRef.formatAsString()); ref.setF(titleRef.formatAsString());
} }

View File

@ -34,4 +34,6 @@ public interface XDDFDataSource<T> {
int getColIndex(); int getColIndex();
String getDataRangeReference(); String getDataRangeReference();
String getFormula();
} }

View File

@ -41,17 +41,18 @@ public class XDDFDataSourcesFactory {
} }
public static XDDFCategoryDataSource fromDataSource(final CTAxDataSource categoryDS) { public static XDDFCategoryDataSource fromDataSource(final CTAxDataSource categoryDS) {
if (categoryDS.getStrRef() == null) {
return new XDDFCategoryDataSource() { return new XDDFCategoryDataSource() {
private CTStrData category = (CTStrData) categoryDS.getStrRef().getStrCache().copy(); private CTNumData category = (CTNumData) categoryDS.getNumRef().getNumCache().copy();
@Override @Override
public boolean isNumeric() { public boolean isNumeric() {
return false; return true;
} }
@Override @Override
public boolean isReference() { public String getFormula() {
return true; return categoryDS.getNumRef().getF();
} }
@Override @Override
@ -63,24 +64,39 @@ public class XDDFDataSourcesFactory {
public String getPointAt(int index) { public String getPointAt(int index) {
return category.getPtArray(index).getV(); return category.getPtArray(index).getV();
} }
};
} else {
return new XDDFCategoryDataSource() {
private CTStrData category = (CTStrData) categoryDS.getStrRef().getStrCache().copy();
@Override @Override
public String getDataRangeReference() { public String getFormula() {
return categoryDS.getStrRef().getF(); return categoryDS.getStrRef().getF();
} }
@Override @Override
public int getColIndex() { public int getPointCount() {
return 0; return (int) category.getPtCount().getVal();
}
@Override
public String getPointAt(int index) {
return category.getPtArray(index).getV();
} }
}; };
} }
}
public static XDDFNumericalDataSource<Double> fromDataSource(final CTNumDataSource valuesDS) { public static XDDFNumericalDataSource<Double> fromDataSource(final CTNumDataSource valuesDS) {
return new XDDFNumericalDataSource<Double>() { return new XDDFNumericalDataSource<Double>() {
private CTNumData values = (CTNumData) valuesDS.getNumRef().getNumCache().copy(); private CTNumData values = (CTNumData) valuesDS.getNumRef().getNumCache().copy();
private String formatCode = values.isSetFormatCode() ? values.getFormatCode() : null; private String formatCode = values.isSetFormatCode() ? values.getFormatCode() : null;
@Override
public String getFormula() {
return valuesDS.getNumRef().getF();
}
@Override @Override
public String getFormatCode() { public String getFormatCode() {
return formatCode; return formatCode;
@ -124,7 +140,7 @@ public class XDDFDataSourcesFactory {
} }
public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange) { public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange) {
return new NumericalArrayDataSource<T>(elements, dataRange); return new NumericalArrayDataSource<>(elements, dataRange);
} }
public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange) { public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange) {
@ -132,7 +148,7 @@ public class XDDFDataSourcesFactory {
} }
public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange, int col) { public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange, int col) {
return new NumericalArrayDataSource<T>(elements, dataRange, col); return new NumericalArrayDataSource<>(elements, dataRange, col);
} }
public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange, int col) { public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange, int col) {
@ -212,6 +228,11 @@ public class XDDFDataSourcesFactory {
super(elements, dataRange, col); super(elements, dataRange, col);
} }
@Override
public String getFormula() {
return getDataRangeReference();
}
@Override @Override
public String getFormatCode() { public String getFormatCode() {
return formatCode; return formatCode;
@ -232,6 +253,11 @@ public class XDDFDataSourcesFactory {
public StringArrayDataSource(String[] elements, String dataRange, int col) { public StringArrayDataSource(String[] elements, String dataRange, int col) {
super(elements, dataRange, col); super(elements, dataRange, col);
} }
@Override
public String getFormula() {
return getDataRangeReference();
}
} }
private abstract static class AbstractCellRangeDataSource<T> implements XDDFDataSource<T> { private abstract static class AbstractCellRangeDataSource<T> implements XDDFDataSource<T> {
@ -290,6 +316,11 @@ public class XDDFDataSourcesFactory {
super(sheet, cellRangeAddress); super(sheet, cellRangeAddress);
} }
@Override
public String getFormula() {
return getDataRangeReference();
}
private String formatCode; private String formatCode;
@Override @Override
@ -324,6 +355,11 @@ public class XDDFDataSourcesFactory {
super(sheet, cellRangeAddress); super(sheet, cellRangeAddress);
} }
@Override
public String getFormula() {
return getDataRangeReference();
}
@Override @Override
public String getPointAt(int index) { public String getPointAt(int index) {
CellValue cellValue = getCellValueAt(index); CellValue cellValue = getCellValueAt(index);

View File

@ -82,6 +82,19 @@ public class XDDFDateAxis extends XDDFChartAxis {
return new XDDFShapeProperties(properties); return new XDDFShapeProperties(properties);
} }
/**
* @since 4.0.1
*/
@Override
public void setTitle(String text) {
if (!ctDateAx.isSetTitle()) {
ctDateAx.addNewTitle();
}
XDDFTitle title = new XDDFTitle(null, ctDateAx.getTitle());
title.setOverlay(false);
title.setText(text);
}
@Override @Override
public boolean isSetMinorUnit() { public boolean isSetMinorUnit() {
return ctDateAx.isSetMinorUnit(); return ctDateAx.isSetMinorUnit();

View File

@ -38,6 +38,18 @@ public class XDDFLineChartData extends XDDFChartData {
for (CTLineSer series : chart.getSerList()) { for (CTLineSer series : chart.getSerList()) {
this.series.add(new Series(series, series.getCat(), series.getVal())); this.series.add(new Series(series, series.getCat(), series.getVal()));
} }
defineAxes(categories, values);
}
private void defineAxes(Map<Long, XDDFChartAxis> categories, Map<Long, XDDFValueAxis> values) {
if (chart.sizeOfAxIdArray() == 0) {
for (Long id : categories.keySet()) {
chart.addNewAxId().setVal(id);
}
for (Long id : values.keySet()) {
chart.addNewAxId().setVal(id);
}
}
defineAxes(chart.getAxIdArray(), categories, values); defineAxes(chart.getAxIdArray(), categories, values);
} }
@ -88,7 +100,11 @@ public class XDDFLineChartData extends XDDFChartData {
@Override @Override
protected CTSerTx getSeriesText() { protected CTSerTx getSeriesText() {
if (series.isSetTx()) {
return series.getTx(); return series.getTx();
} else {
return series.addNewTx();
}
} }
@Override @Override
@ -127,7 +143,44 @@ public class XDDFLineChartData extends XDDFChartData {
} }
} }
/**
* @since 4.0.1
*/
public Boolean getSmooth() {
if (series.isSetSmooth()) {
return series.getSmooth().getVal();
} else {
return null;
}
}
/**
* @param smooth
* whether or not to smooth lines, if <code>null</code> then reverts to default.
* @since 4.0.1
*/
public void setSmooth(Boolean smooth) {
if (smooth == null) {
if (series.isSetSmooth()) {
series.unsetSmooth();
}
} else {
if (series.isSetSmooth()) {
series.getSmooth().setVal(smooth);
} else {
series.addNewSmooth().setVal(smooth);
}
}
}
/**
* @param size
* <dl><dt>Minimum inclusive:</dt><dd>2</dd><dt>Maximum inclusive:</dt><dd>72</dd></dl>
*/
public void setMarkerSize(short size) { public void setMarkerSize(short size) {
if (size < 2 || 72 < size) {
throw new IllegalArgumentException("Minimum inclusive: 2; Maximum inclusive: 72");
}
CTMarker marker = getMarker(); CTMarker marker = getMarker();
if (marker.isSetSize()) { if (marker.isSetSize()) {
marker.getSize().setVal(size); marker.getSize().setVal(size);

View File

@ -75,7 +75,11 @@ public class XDDFPieChartData extends XDDFChartData {
@Override @Override
protected CTSerTx getSeriesText() { protected CTSerTx getSeriesText() {
if (series.isSetTx()) {
return series.getTx(); return series.getTx();
} else {
return series.addNewTx();
}
} }
@Override @Override

View File

@ -38,6 +38,18 @@ public class XDDFRadarChartData extends XDDFChartData {
for (CTRadarSer series : chart.getSerList()) { for (CTRadarSer series : chart.getSerList()) {
this.series.add(new Series(series, series.getCat(), series.getVal())); this.series.add(new Series(series, series.getCat(), series.getVal()));
} }
defineAxes(categories, values);
}
private void defineAxes(Map<Long, XDDFChartAxis> categories, Map<Long, XDDFValueAxis> values) {
if (chart.sizeOfAxIdArray() == 0) {
for (Long id : categories.keySet()) {
chart.addNewAxId().setVal(id);
}
for (Long id : values.keySet()) {
chart.addNewAxId().setVal(id);
}
}
defineAxes(chart.getAxIdArray(), categories, values); defineAxes(chart.getAxIdArray(), categories, values);
} }
@ -92,7 +104,11 @@ public class XDDFRadarChartData extends XDDFChartData {
@Override @Override
protected CTSerTx getSeriesText() { protected CTSerTx getSeriesText() {
if (series.isSetTx()) {
return series.getTx(); return series.getTx();
} else {
return series.addNewTx();
}
} }
@Override @Override

View File

@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties; import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource; import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTMarker;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource; import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterChart; import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterSer; import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterSer;
@ -38,6 +39,18 @@ public class XDDFScatterChartData extends XDDFChartData {
for (CTScatterSer series : chart.getSerList()) { for (CTScatterSer series : chart.getSerList()) {
this.series.add(new Series(series, series.getXVal(), series.getYVal())); this.series.add(new Series(series, series.getXVal(), series.getYVal()));
} }
defineAxes(categories, values);
}
private void defineAxes(Map<Long, XDDFChartAxis> categories, Map<Long, XDDFValueAxis> values) {
if (chart.sizeOfAxIdArray() == 0) {
for (Long id : categories.keySet()) {
chart.addNewAxId().setVal(id);
}
for (Long id : values.keySet()) {
chart.addNewAxId().setVal(id);
}
}
defineAxes(chart.getAxIdArray(), categories, values); defineAxes(chart.getAxIdArray(), categories, values);
} }
@ -96,7 +109,78 @@ public class XDDFScatterChartData extends XDDFChartData {
@Override @Override
protected CTSerTx getSeriesText() { protected CTSerTx getSeriesText() {
if (series.isSetTx()) {
return series.getTx(); return series.getTx();
} else {
return series.addNewTx();
}
}
/**
* @since 4.0.1
*/
public Boolean getSmooth() {
if (series.isSetSmooth()) {
return series.getSmooth().getVal();
} else {
return null;
}
}
/**
* @param smooth
* whether or not to smooth lines, if <code>null</code> then reverts to default.
* @since 4.0.1
*/
public void setSmooth(Boolean smooth) {
if (smooth == null) {
if (series.isSetSmooth()) {
series.unsetSmooth();
}
} else {
if (series.isSetSmooth()) {
series.getSmooth().setVal(smooth);
} else {
series.addNewSmooth().setVal(smooth);
}
}
}
/**
* @param size
* <dl><dt>Minimum inclusive:</dt><dd>2</dd><dt>Maximum inclusive:</dt><dd>72</dd></dl>
* @since 4.0.1
*/
public void setMarkerSize(short size) {
if (size < 2 || 72 < size) {
throw new IllegalArgumentException("Minimum inclusive: 2; Maximum inclusive: 72");
}
CTMarker marker = getMarker();
if (marker.isSetSize()) {
marker.getSize().setVal(size);
} else {
marker.addNewSize().setVal(size);
}
}
/**
* @since 4.0.1
*/
public void setMarkerStyle(MarkerStyle style) {
CTMarker marker = getMarker();
if (marker.isSetSymbol()) {
marker.getSymbol().setVal(style.underlying);
} else {
marker.addNewSymbol().setVal(style.underlying);
}
}
private CTMarker getMarker() {
if (series.isSetMarker()) {
return series.getMarker();
} else {
return series.addNewMarker();
}
} }
@Override @Override

View File

@ -79,6 +79,19 @@ public class XDDFSeriesAxis extends XDDFChartAxis {
return new XDDFShapeProperties(properties); return new XDDFShapeProperties(properties);
} }
/**
* @since 4.0.1
*/
@Override
public void setTitle(String text) {
if (!ctSerAx.isSetTitle()) {
ctSerAx.addNewTitle();
}
XDDFTitle title = new XDDFTitle(null, ctSerAx.getTitle());
title.setOverlay(false);
title.setText(text);
}
@Override @Override
public boolean isSetMinorUnit() { public boolean isSetMinorUnit() {
return false; return false;

View File

@ -0,0 +1,76 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.apache.poi.xddf.usermodel.chart;
import org.apache.poi.util.Beta;
import org.apache.poi.xddf.usermodel.text.TextContainer;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTTitle;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTTx;
/**
* @since 4.0.1
*/
@Beta
public class XDDFTitle {
private final CTTitle title;
private final TextContainer parent;
public XDDFTitle(TextContainer parent, CTTitle title) {
this.parent = parent;
this.title = title;
}
public XDDFTextBody getBody() {
if (!title.isSetTx()) {
title.addNewTx();
}
CTTx tx = title.getTx();
if (tx.isSetStrRef()) {
tx.unsetStrRef();
}
if (!tx.isSetRich()) {
tx.addNewRich();
}
return new XDDFTextBody(parent, tx.getRich());
}
public void setText(String text) {
if (!title.isSetLayout()) {
title.addNewLayout();
}
getBody().setText(text);
}
public void setOverlay(Boolean overlay) {
if (overlay == null) {
if (title.isSetOverlay()) {
title.unsetOverlay();
}
} else {
if (title.isSetOverlay()) {
title.getOverlay().setVal(overlay);
} else {
title.addNewOverlay().setVal(overlay);
}
}
}
}

View File

@ -78,6 +78,19 @@ public class XDDFValueAxis extends XDDFChartAxis {
return new XDDFShapeProperties(properties); return new XDDFShapeProperties(properties);
} }
/**
* @since 4.0.1
*/
@Override
public void setTitle(String text) {
if (!ctValAx.isSetTitle()) {
ctValAx.addNewTitle();
}
XDDFTitle title = new XDDFTitle(null, ctValAx.getTitle());
title.setOverlay(false);
title.setText(text);
}
@Override @Override
public boolean isSetMinorUnit() { public boolean isSetMinorUnit() {
return ctValAx.isSetMinorUnit(); return ctValAx.isSetMinorUnit();

View File

@ -67,6 +67,16 @@ public class XDDFParagraphProperties {
} }
} }
/**
* @since 4.0.1
*/
public XDDFRunProperties addDefaultRunProperties() {
if (!props.isSetDefRPr()) {
props.addNewDefRPr();
}
return getDefaultRunProperties();
}
public XDDFRunProperties getDefaultRunProperties() { public XDDFRunProperties getDefaultRunProperties() {
if (props.isSetDefRPr()) { if (props.isSetDefRPr()) {
return new XDDFRunProperties(props.getDefRPr()); return new XDDFRunProperties(props.getDefRPr());

View File

@ -70,6 +70,19 @@ public class XDDFTextBody {
return p; return p;
} }
public void setText(String text) {
if (_body.sizeOfPArray() > 0) {
// remove all but first paragraph
for (int i = _body.sizeOfPArray() - 1; i > 0; i--) {
_body.removeP(i);
}
getParagraph(0).setText(text);
} else {
// as there were no paragraphs yet, initialize the text body
initialize().setText(text);
}
}
public XDDFTextParagraph addNewParagraph() { public XDDFTextParagraph addNewParagraph() {
return new XDDFTextParagraph(_body.addNewP(), this); return new XDDFTextParagraph(_body.addNewP(), this);
} }

View File

@ -69,6 +69,24 @@ public class XDDFTextParagraph {
_runs.add(new XDDFTextRun((CTRegularTextRun) xo, this)); _runs.add(new XDDFTextRun((CTRegularTextRun) xo, this));
} }
} }
addDefaultRunProperties();
addAfterLastRunProperties();
}
public void setText(String text) {
// remove all runs
for (int i = _p.sizeOfBrArray() - 1; i >= 0; i--) {
_p.removeBr(i);
}
for (int i = _p.sizeOfFldArray() - 1; i >= 0; i--) {
_p.removeFld(i);
}
for (int i = _p.sizeOfRArray() - 1; i >= 0; i--) {
_p.removeR(i);
}
_runs.clear();
appendRegularRun(text);
} }
public String getText() { public String getText() {
@ -662,6 +680,13 @@ public class XDDFTextParagraph {
} }
} }
/**
* @since 4.0.1
*/
public XDDFRunProperties addDefaultRunProperties() {
return getOrCreateProperties().addDefaultRunProperties();
}
public XDDFRunProperties getDefaultRunProperties() { public XDDFRunProperties getDefaultRunProperties() {
if (_p.isSetPPr()) { if (_p.isSetPPr()) {
return getProperties().getDefaultRunProperties(); return getProperties().getDefaultRunProperties();

View File

@ -372,8 +372,8 @@ public class XMLSlideShow extends POIXMLDocument
} }
if (!themeIndexList.isEmpty()) { if (!themeIndexList.isEmpty()) {
Boolean found = false; boolean found = false;
for (Integer i = 1; i <= themeIndexList.size(); i++) { for (int i = 1; i <= themeIndexList.size(); i++) {
if (!themeIndexList.contains(i)) { if (!themeIndexList.contains(i)) {
found = true; found = true;
themeIndex = i; themeIndex = i;

View File

@ -78,6 +78,19 @@ public class XSLFBackground extends XSLFSimpleShape
public void setFillColor(Color color) { public void setFillColor(Color color) {
CTBackgroundProperties bgPr = getBgPr(true); CTBackgroundProperties bgPr = getBgPr(true);
if (bgPr.isSetBlipFill()) {
bgPr.unsetBlipFill();
}
if (bgPr.isSetGradFill()) {
bgPr.unsetGradFill();
}
if (bgPr.isSetGrpFill()) {
bgPr.unsetGrpFill();
}
if (bgPr.isSetPattFill()) {
bgPr.unsetPattFill();
}
if (color == null) { if (color == null) {
if (bgPr.isSetSolidFill()) { if (bgPr.isSetSolidFill()) {
bgPr.unsetSolidFill(); bgPr.unsetSolidFill();

View File

@ -69,7 +69,7 @@ public final class XSLFChart extends XDDFChart {
return XSLFFactory.getInstance(); return XSLFFactory.getInstance();
} }
public XSLFTextShape getTitle() { public XSLFTextShape getTitleShape() {
if (!chart.isSetTitle()) { if (!chart.isSetTitle()) {
chart.addNewTitle(); chart.addNewTitle();
} }

View File

@ -153,7 +153,7 @@ public class XSLFColor {
colorRef = _phClr.getVal().toString(); colorRef = _phClr.getVal().toString();
} }
// find referenced CTColor in the theme and convert it to java.awt.Color via a recursive call // find referenced CTColor in the theme and convert it to java.awt.Color via a recursive call
CTColor ctColor = theme.getCTColor(colorRef); CTColor ctColor = theme == null ? null : theme.getCTColor(colorRef);
if(ctColor != null) { if(ctColor != null) {
color = toColor(ctColor, null); color = toColor(ctColor, null);
} }

View File

@ -692,11 +692,25 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
/** /**
* Helper method for sheet and group shapes * Helper method for sheet and group shapes
* *
* @param pictureShape the picture shapes whose relation is to be removed * @param pictureShape the picture shapes whose relation is to be removed,
* only if there are no more relations on its sheet to that picture
*/ */
void removePictureRelation(XSLFPictureShape pictureShape) { void removePictureRelation(XSLFPictureShape pictureShape) {
int numberOfRelations = 0;
String targetBlipId = pictureShape.getBlipId();
for (XSLFShape shape : pictureShape.getSheet().getShapes()) {
if (shape instanceof XSLFPictureShape) {
XSLFPictureShape currentPictureShape = ((XSLFPictureShape) shape);
String currentBlipId = currentPictureShape.getBlipId();
if (currentBlipId != null && currentBlipId.equals(targetBlipId)) {
numberOfRelations++;
}
}
}
if (numberOfRelations <= 1) {
removeRelation(pictureShape.getBlipId()); removeRelation(pictureShape.getBlipId());
} }
}
@Override @Override

View File

@ -98,7 +98,7 @@ public class StylesTable extends POIXMLDocumentPart implements Styles {
if (num < 0) { if (num < 0) {
throw new IllegalArgumentException("Maximum Number of Data Formats must be greater than or equal to 0"); throw new IllegalArgumentException("Maximum Number of Data Formats must be greater than or equal to 0");
} else { } else {
throw new IllegalStateException("Cannot set the maximum number of data formats less than the current quantity." + throw new IllegalStateException("Cannot set the maximum number of data formats less than the current quantity. " +
"Data formats must be explicitly removed (via StylesTable.removeNumberFormat) before the limit can be decreased."); "Data formats must be explicitly removed (via StylesTable.removeNumberFormat) before the limit can be decreased.");
} }
} }
@ -316,7 +316,7 @@ public class StylesTable extends POIXMLDocumentPart implements Styles {
short nextKey = (short) (numberFormats.lastKey() + 1); short nextKey = (short) (numberFormats.lastKey() + 1);
if (nextKey < 0) { if (nextKey < 0) {
throw new IllegalStateException( throw new IllegalStateException(
"Cowardly avoiding creating a number format with a negative id." + "Cowardly avoiding creating a number format with a negative id. " +
"This is probably due to arithmetic overflow."); "This is probably due to arithmetic overflow.");
} }
formatIndex = (short) Math.max(nextKey, FIRST_USER_DEFINED_NUMBER_FORMAT_ID); formatIndex = (short) Math.max(nextKey, FIRST_USER_DEFINED_NUMBER_FORMAT_ID);

View File

@ -18,7 +18,9 @@
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
@ -33,8 +35,10 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer; import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/** /**
* Table style names defined in the OOXML spec. * Table style names defined in the OOXML spec.
@ -349,6 +353,7 @@ public enum XSSFBuiltinTableStyle {
/** /**
* NOTE: only checks by name, not definition. * NOTE: only checks by name, not definition.
*
* @param style * @param style
* @return true if the style represents a built-in style, false if it is null or a custom style * @return true if the style represents a built-in style, false if it is null or a custom style
*/ */
@ -361,6 +366,7 @@ public enum XSSFBuiltinTableStyle {
return false; return false;
} }
} }
/** /**
* Only init once - thus the synchronized. Lazy, after creating instances, * Only init once - thus the synchronized. Lazy, after creating instances,
* and only when a style is actually needed, to avoid overhead for uses * and only when a style is actually needed, to avoid overhead for uses
@ -370,7 +376,7 @@ public enum XSSFBuiltinTableStyle {
* during evaluation if desired. * during evaluation if desired.
*/ */
public static synchronized void init() { public static synchronized void init() {
if (! styleMap.isEmpty()) return; if (!styleMap.isEmpty()) return;
/* /*
* initialize map. Every built-in has this format: * initialize map. Every built-in has this format:
@ -390,7 +396,7 @@ public enum XSSFBuiltinTableStyle {
final Document doc = DocumentHelper.readDocument(is); final Document doc = DocumentHelper.readDocument(is);
final NodeList styleNodes = doc.getDocumentElement().getChildNodes(); final NodeList styleNodes = doc.getDocumentElement().getChildNodes();
for (int i=0; i < styleNodes.getLength(); i++) { for (int i = 0; i < styleNodes.getLength(); i++) {
final Node node = styleNodes.item(i); final Node node = styleNodes.item(i);
if (node.getNodeType() != Node.ELEMENT_NODE) continue; // only care about elements if (node.getNodeType() != Node.ELEMENT_NODE) continue; // only care about elements
final Element tag = (Element) node; final Element tag = (Element) node;
@ -414,27 +420,34 @@ public enum XSSFBuiltinTableStyle {
} }
} }
private static String styleXML(Node dxfsNode, Node tableStyleNode) { private static String styleXML(Node dxfsNode, Node tableStyleNode) throws IOException, TransformerException {
// built-ins doc uses 1-based dxf indexing, Excel uses 0 based. // built-ins doc uses 1-based dxf indexing, Excel uses 0 based.
// add a dummy node to adjust properly. // add a dummy node to adjust properly.
dxfsNode.insertBefore(dxfsNode.getOwnerDocument().createElement("dxf"), dxfsNode.getFirstChild()); dxfsNode.insertBefore(dxfsNode.getOwnerDocument().createElement("dxf"), dxfsNode.getFirstChild());
DOMImplementationLS lsImpl = (DOMImplementationLS)dxfsNode.getOwnerDocument().getImplementation().getFeature("LS", "3.0");
LSSerializer lsSerializer = lsImpl.createLSSerializer();
lsSerializer.getDomConfig().setParameter("xml-declaration", false);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n") sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n")
.append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" " .append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" ")
+ "xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" " .append("xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" ")
+ "xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" " .append("xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" ")
+ "xmlns:x16r2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main\" " .append("xmlns:x16r2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main\" ")
+ "mc:Ignorable=\"x14ac x16r2\">\n"); .append("mc:Ignorable=\"x14ac x16r2\">\n");
sb.append(lsSerializer.writeToString(dxfsNode)); sb.append(writeToString(dxfsNode));
sb.append(lsSerializer.writeToString(tableStyleNode)); sb.append(writeToString(tableStyleNode));
sb.append("</styleSheet>"); sb.append("</styleSheet>");
return sb.toString(); return sb.toString();
} }
private static String writeToString(Node node) throws IOException, TransformerException {
TransformerFactory tf = TransformerFactory.newInstance();
try (StringWriter sw = new StringWriter()){
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(node), new StreamResult(sw));
return sw.toString();
}
}
/** /**
* implementation for built-in styles * implementation for built-in styles
*/ */

View File

@ -491,11 +491,14 @@ public final class XSSFCell implements Cell {
return cell.getCellFormula(fpb); return cell.getCellFormula(fpb);
} }
} }
if (f.getT() == STCellFormulaType.SHARED) { if (f == null) {
return null;
} else if (f.getT() == STCellFormulaType.SHARED) {
return convertSharedFormula((int)f.getSi(), fpb == null ? XSSFEvaluationWorkbook.create(getSheet().getWorkbook()) : fpb); return convertSharedFormula((int)f.getSi(), fpb == null ? XSSFEvaluationWorkbook.create(getSheet().getWorkbook()) : fpb);
} } else {
return f.getStringValue(); return f.getStringValue();
} }
}
/** /**
* Creates a non shared formula from the shared formula counterpart * Creates a non shared formula from the shared formula counterpart

View File

@ -55,10 +55,6 @@ import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrRef;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTTitle; import org.openxmlformats.schemas.drawingml.x2006.chart.CTTitle;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTTx; import org.openxmlformats.schemas.drawingml.x2006.chart.CTTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx; import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.w3c.dom.Text; import org.w3c.dom.Text;
@ -260,19 +256,6 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
return new XSSFManualLayout(this); return new XSSFManualLayout(this);
} }
/**
* Returns the title static text, or null if none is set. Note that a title
* formula may be set instead.
*
* @return static title text, if set
* @deprecated POI 3.16, use {@link #getTitleText()} instead.
*/
@Deprecated
@Removal(version = "4.0")
public XSSFRichTextString getTitle() {
return getTitleText();
}
/** /**
* Returns the title static text, or null if none is set. Note that a title * Returns the title static text, or null if none is set. Note that a title
* formula may be set instead. Empty text result is for backward * formula may be set instead. Empty text result is for backward
@ -307,59 +290,6 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
return new XSSFRichTextString(text.toString()); return new XSSFRichTextString(text.toString());
} }
/**
* Sets the title text as a static string.
*
* @param newTitle
* to use
*/
public void setTitleText(String newTitle) {
CTTitle ctTitle;
if (chart.isSetTitle()) {
ctTitle = chart.getTitle();
} else {
ctTitle = chart.addNewTitle();
}
CTTx tx;
if (ctTitle.isSetTx()) {
tx = ctTitle.getTx();
} else {
tx = ctTitle.addNewTx();
}
if (tx.isSetStrRef()) {
tx.unsetStrRef();
}
CTTextBody rich;
if (tx.isSetRich()) {
rich = tx.getRich();
} else {
rich = tx.addNewRich();
rich.addNewBodyPr(); // body properties must exist (but can be
// empty)
}
CTTextParagraph para;
if (rich.sizeOfPArray() > 0) {
para = rich.getPArray(0);
} else {
para = rich.addNewP();
}
if (para.sizeOfRArray() > 0) {
CTRegularTextRun run = para.getRArray(0);
run.setT(newTitle);
} else if (para.sizeOfFldArray() > 0) {
CTTextField fld = para.getFldArray(0);
fld.setT(newTitle);
} else {
CTRegularTextRun run = para.addNewR();
run.setT(newTitle);
}
}
/** /**
* Get the chart title formula expression if there is one * Get the chart title formula expression if there is one
* *

View File

@ -18,7 +18,6 @@
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
@ -154,12 +153,6 @@ public class XSSFClientAnchor extends XSSFAnchor implements ClientAnchor {
// this.cell2 = calcCell(sheet, cell1, size.getCx(), size.getCy()); // this.cell2 = calcCell(sheet, cell1, size.getCx(), size.getCy());
} }
/**
*
* @param sheet
* @param cell starting point and offsets (may be zeros)
* @param size dimensions to calculate relative to starting point
*/
private CTMarker calcCell(CTMarker cell, long w, long h) { private CTMarker calcCell(CTMarker cell, long w, long h) {
CTMarker c2 = CTMarker.Factory.newInstance(); CTMarker c2 = CTMarker.Factory.newInstance();

View File

@ -54,7 +54,7 @@ public class XSSFComment implements Comment {
// we potentially need to adjust the column/row information in the shape // we potentially need to adjust the column/row information in the shape
// the same way as we do in setRow()/setColumn() // the same way as we do in setRow()/setColumn()
if(vmlShape != null && vmlShape.sizeOfClientDataArray() > 0) { if(comment != null && vmlShape != null && vmlShape.sizeOfClientDataArray() > 0) {
CellReference ref = new CellReference(comment.getRef()); CellReference ref = new CellReference(comment.getRef());
CTClientData clientData = vmlShape.getClientDataArray(0); CTClientData clientData = vmlShape.getClientDataArray(0);
clientData.setRowArray(0, new BigInteger(String.valueOf(ref.getRow()))); clientData.setRowArray(0, new BigInteger(String.valueOf(ref.getRow())));
@ -70,7 +70,7 @@ public class XSSFComment implements Comment {
*/ */
@Override @Override
public String getAuthor() { public String getAuthor() {
return _comments.getAuthor((int) _comment.getAuthorId()); return _comments.getAuthor(_comment.getAuthorId());
} }
/** /**
@ -80,9 +80,7 @@ public class XSSFComment implements Comment {
*/ */
@Override @Override
public void setAuthor(String author) { public void setAuthor(String author) {
_comment.setAuthorId( _comment.setAuthorId(_comments.findAuthor(author));
_comments.findAuthor(author)
);
} }
/** /**

View File

@ -2262,8 +2262,8 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
} }
} }
private void unsetCollapsed(boolean collapsed, CTCol ci) { private void unsetCollapsed(Boolean collapsed, CTCol ci) {
if (collapsed) { if (collapsed != null && collapsed.booleanValue()) {
ci.setCollapsed(collapsed); ci.setCollapsed(collapsed);
} else { } else {
ci.unsetCollapsed(); ci.unsetCollapsed();
@ -2410,7 +2410,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
boolean endHidden = false; boolean endHidden = false;
int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup(idx); int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup(idx);
CTCol[] colArray = cols.getColArray(); CTCol[] colArray = cols.getColArray();
if (endOfOutlineGroupIdx < colArray.length) { if (endOfOutlineGroupIdx < (colArray.length - 1)) {
CTCol nextInfo = colArray[endOfOutlineGroupIdx + 1]; CTCol nextInfo = colArray[endOfOutlineGroupIdx + 1];
if (isAdjacentBefore(colArray[endOfOutlineGroupIdx], nextInfo)) { if (isAdjacentBefore(colArray[endOfOutlineGroupIdx], nextInfo)) {
endLevel = nextInfo.getOutlineLevel(); endLevel = nextInfo.getOutlineLevel();
@ -2900,7 +2900,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
// "Got srcRows[" + (index-1) + "]=Row " + prevRow.getRowNum() + ", srcRows[" + index + "]=Row " + curRow.getRowNum() + "."); // "Got srcRows[" + (index-1) + "]=Row " + prevRow.getRowNum() + ", srcRows[" + index + "]=Row " + curRow.getRowNum() + ".");
// FIXME: assumes row objects belong to non-null sheets and sheets belong to non-null workbooks. // FIXME: assumes row objects belong to non-null sheets and sheets belong to non-null workbooks.
} else if (srcStartRow.getSheet().getWorkbook() != curRow.getSheet().getWorkbook()) { } else if (srcStartRow.getSheet().getWorkbook() != curRow.getSheet().getWorkbook()) {
throw new IllegalArgumentException("All rows in srcRows must belong to the same sheet in the same workbook." + throw new IllegalArgumentException("All rows in srcRows must belong to the same sheet in the same workbook. " +
"Expected all rows from same workbook (" + srcStartRow.getSheet().getWorkbook() + "). " + "Expected all rows from same workbook (" + srcStartRow.getSheet().getWorkbook() + "). " +
"Got srcRows[" + index + "] from different workbook (" + curRow.getSheet().getWorkbook() + ")."); "Got srcRows[" + index + "] from different workbook (" + curRow.getSheet().getWorkbook() + ").");
} else if (srcStartRow.getSheet() != curRow.getSheet()) { } else if (srcStartRow.getSheet() != curRow.getSheet()) {

View File

@ -283,7 +283,7 @@ public class XSSFTable extends POIXMLDocumentPart implements Table {
} }
// check if name is unique and calculate unique column id // check if name is unique and calculate unique column id
long nextColumnId = 1; long nextColumnId = 0;
for (XSSFTableColumn tableColumn : getColumns()) { for (XSSFTableColumn tableColumn : getColumns()) {
if (columnName != null && columnName.equalsIgnoreCase(tableColumn.getName())) { if (columnName != null && columnName.equalsIgnoreCase(tableColumn.getName())) {
throw new IllegalArgumentException("Column '" + columnName throw new IllegalArgumentException("Column '" + columnName
@ -291,6 +291,8 @@ public class XSSFTable extends POIXMLDocumentPart implements Table {
} }
nextColumnId = Math.max(nextColumnId, tableColumn.getId()); nextColumnId = Math.max(nextColumnId, tableColumn.getId());
} }
// Bug #62740, the logic was just re-using the existing max ID, not incrementing beyond it.
nextColumnId++;
// Add the new Column // Add the new Column
CTTableColumn column = columns.insertNewTableColumn(columnIndex); CTTableColumn column = columns.insertNewTableColumn(columnIndex);
@ -474,14 +476,9 @@ public class XSSFTable extends POIXMLDocumentPart implements Table {
* this method does not create or remove any columns and does not change any * this method does not create or remove any columns and does not change any
* cell values. * cell values.
* *
* @deprecated Use {@link #setTableArea} instead, which will ensure that the
* the amount of columns always matches table area always width.
*
* @see "Open Office XML Part 4: chapter 3.5.1.2, attribute ref" * @see "Open Office XML Part 4: chapter 3.5.1.2, attribute ref"
* @since 3.17 beta 1 * @since 3.17 beta 1
*/ */
@Deprecated
@Removal(version="4.2.0")
public void setCellReferences(AreaReference refs) { public void setCellReferences(AreaReference refs) {
setCellRef(refs); setCellRef(refs);
} }
@ -525,7 +522,7 @@ public class XSSFTable extends POIXMLDocumentPart implements Table {
* Updating the area with this method will create new column as necessary to * Updating the area with this method will create new column as necessary to
* the right side of the table but will not modify any cell values. * the right side of the table but will not modify any cell values.
* *
* @param refs * @param tableArea
* the new area of the table * the new area of the table
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the area is {@code null} or not * if the area is {@code null} or not

View File

@ -19,6 +19,10 @@
package org.apache.poi.xssf.usermodel.helpers; package org.apache.poi.xssf.usermodel.helpers;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaParser;
import org.apache.poi.ss.formula.FormulaRenderer; import org.apache.poi.ss.formula.FormulaRenderer;
import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.FormulaType;
@ -30,10 +34,14 @@ import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook; import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
import org.apache.poi.xssf.usermodel.XSSFName; import org.apache.poi.xssf.usermodel.XSSFName;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/** /**
* Utility to update formulas and named ranges when a sheet name was changed * Utility to update formulas and named ranges when a sheet name was changed
@ -50,7 +58,7 @@ public final class XSSFFormulaUtils {
} }
/** /**
* Update sheet name in all formulas and named ranges. * Update sheet name in all charts, formulas and named ranges.
* Called from {@link XSSFWorkbook#setSheetName(int, String)} * Called from {@link XSSFWorkbook#setSheetName(int, String)}
* <p> * <p>
* <p> * <p>
@ -81,6 +89,20 @@ public final class XSSFFormulaUtils {
} }
} }
} }
// update charts
List<POIXMLDocumentPart> rels = _wb.getSheetAt(sheetIndex).getRelations();
for (POIXMLDocumentPart r : rels) {
if (r instanceof XSSFDrawing) {
XSSFDrawing dg = (XSSFDrawing) r;
Iterator<XSSFChart> it = dg.getCharts().iterator();
while (it.hasNext()) {
XSSFChart chart = it.next();
Node dom = chart.getCTChartSpace().getDomNode();
updateDomSheetReference(dom, oldName, newName);
}
}
}
} }
/** /**
@ -99,7 +121,9 @@ public final class XSSFFormulaUtils {
updatePtg(ptg, oldName, newName); updatePtg(ptg, oldName, newName);
} }
String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs); String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs);
if (!formula.equals(updatedFormula)) f.setStringValue(updatedFormula); if (!formula.equals(updatedFormula)) {
f.setStringValue(updatedFormula);
}
} }
} }
} }
@ -119,7 +143,9 @@ public final class XSSFFormulaUtils {
updatePtg(ptg, oldName, newName); updatePtg(ptg, oldName, newName);
} }
String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs); String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs);
if (!formula.equals(updatedFormula)) name.setRefersToFormula(updatedFormula); if (!formula.equals(updatedFormula)) {
name.setRefersToFormula(updatedFormula);
}
} }
} }
@ -141,4 +167,32 @@ public final class XSSFFormulaUtils {
} }
} }
} }
/**
* Parse the DOM tree recursively searching for text containing reference to the old sheet name and replacing it.
*
* @param dom the XML node in which to perform the replacement.
*
* Code extracted from: <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=54470">Bug 54470</a>
*/
private void updateDomSheetReference(Node dom, final String oldName, final String newName) {
String value = dom.getNodeValue();
if (value != null) {
// make sure the value contains the old sheet and not a similar sheet
// (ex: Valid: 'Sheet1'! or Sheet1! ; NotValid: 'Sheet1Test'! or Sheet1Test!)
if (value.contains(oldName+"!") || value.contains(oldName+"'!")) {
XSSFName temporary = _wb.createName();
temporary.setRefersToFormula(value);
updateName(temporary, oldName, newName);
dom.setNodeValue(temporary.getRefersToFormula());
_wb.removeName(temporary);
}
}
NodeList nl = dom.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
updateDomSheetReference(nl.item(i), oldName, newName);
}
}
} }

View File

@ -17,6 +17,18 @@
package org.apache.poi.ooxml.util; package org.apache.poi.ooxml.util;
import junit.framework.TestCase;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.StringUtil;
import org.apache.poi.util.SuppressForbidden;
import org.apache.xmlbeans.StringEnumAbstractBase;
import org.junit.Test;
import org.junit.internal.TextListener;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.reflections.Reflections;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -26,29 +38,11 @@ import java.security.AccessController;
import java.security.CodeSource; import java.security.CodeSource;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.util.ArrayList; import java.util.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import junit.framework.TestCase;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.StringUtil;
import org.apache.poi.util.SuppressForbidden;
import org.junit.Test;
import org.junit.internal.TextListener;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
/** /**
* Build a 'lite' version of the ooxml-schemas.jar * Build a 'lite' version of the ooxml-schemas.jar
* *
@ -193,20 +187,37 @@ public final class OOXMLLite {
//see what classes from the ooxml-schemas.jar are loaded //see what classes from the ooxml-schemas.jar are loaded
System.out.println("Copying classes to " + _destDest); System.out.println("Copying classes to " + _destDest);
Map<String, Class<?>> classes = getLoadedClasses(_ooxmlJar.getName()); Set<Class<?>> classes = getLoadedClasses(_ooxmlJar.getName());
for (Class<?> cls : classes.values()) { Set<String> packages = new HashSet<>();
String className = cls.getName(); for (Class<?> cls : classes) {
String classRef = className.replace('.', '/') + ".class"; copyFile(cls);
File destFile = new File(_destDest, classRef); packages.add(cls.getPackage().getName());
IOUtils.copy(cls.getResourceAsStream('/' + classRef), destFile);
if(cls.isInterface()){ if (cls.isInterface()) {
/// Copy classes and interfaces declared as members of this class /// Copy classes and interfaces declared as members of this class
for(Class<?> fc : cls.getDeclaredClasses()){ for (Class<?> fc : cls.getDeclaredClasses()) {
className = fc.getName(); copyFile(fc);
classRef = className.replace('.', '/') + ".class"; }
destFile = new File(_destDest, classRef); }
IOUtils.copy(fc.getResourceAsStream('/' + classRef), destFile); }
for (String pkg : packages) {
Reflections reflections = new Reflections(pkg);
Set<Class<? extends List>> listClasses = reflections.getSubTypesOf(List.class);
listClasses.removeAll(classes);
for (Class listClass : listClasses) {
for (Class<?> compare : classes) {
if (listClass.getName().startsWith(compare.getName())) {
copyFile(listClass);
}
}
}
Set<Class<? extends StringEnumAbstractBase>> enumClasses = reflections.getSubTypesOf(StringEnumAbstractBase.class);
listClasses.removeAll(classes);
for (Class enumClass : enumClasses) {
for (Class<?> compare : classes) {
if (enumClass.getName().startsWith(compare.getName())) {
copyFile(enumClass);
}
} }
} }
} }
@ -224,6 +235,13 @@ public final class OOXMLLite {
} }
} }
private void copyFile(Class<?> cls) throws IOException {
String className = cls.getName();
String classRef = className.replace('.', '/') + ".class";
File destFile = new File(_destDest, classRef);
IOUtils.copy(cls.getResourceAsStream('/' + classRef), destFile);
}
private static boolean checkForTestAnnotation(Class<?> testclass) { private static boolean checkForTestAnnotation(Class<?> testclass) {
for (Method m : testclass.getDeclaredMethods()) { for (Method m : testclass.getDeclaredMethods()) {
if(m.isAnnotationPresent(Test.class)) { if(m.isAnnotationPresent(Test.class)) {
@ -293,10 +311,10 @@ public final class OOXMLLite {
/** /**
* *
* @param ptrn the pattern to filter output * @param ptrn the pattern to filter output
* @return the classes loaded by the system class loader keyed by class name * @return the classes loaded by the system class loader
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static Map<String, Class<?>> getLoadedClasses(String ptrn) { private static Set<Class<?>> getLoadedClasses(String ptrn) {
// make the field accessible, we defer this from static initialization to here to // make the field accessible, we defer this from static initialization to here to
// allow JDKs which do not have this field (e.g. IBM JDK) to at least load the class // allow JDKs which do not have this field (e.g. IBM JDK) to at least load the class
// without failing, see https://issues.apache.org/bugzilla/show_bug.cgi?id=56550 // without failing, see https://issues.apache.org/bugzilla/show_bug.cgi?id=56550
@ -317,7 +335,7 @@ public final class OOXMLLite {
ClassLoader appLoader = ClassLoader.getSystemClassLoader(); ClassLoader appLoader = ClassLoader.getSystemClassLoader();
try { try {
Vector<Class<?>> classes = (Vector<Class<?>>) _classes.get(appLoader); Vector<Class<?>> classes = (Vector<Class<?>>) _classes.get(appLoader);
Map<String, Class<?>> map = new HashMap<>(); Set<Class<?>> set = new HashSet<>();
for (Class<?> cls : classes) { for (Class<?> cls : classes) {
// e.g. proxy-classes, ... // e.g. proxy-classes, ...
ProtectionDomain pd = cls.getProtectionDomain(); ProtectionDomain pd = cls.getProtectionDomain();
@ -329,10 +347,10 @@ public final class OOXMLLite {
String jar = loc.toString(); String jar = loc.toString();
if (jar.contains(ptrn)) { if (jar.contains(ptrn)) {
map.put(cls.getName(), cls); set.add(cls);
} }
} }
return map; return set;
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@ -37,8 +37,12 @@ public class TestDocumentHelper {
@Test @Test
public void testDocumentBuilderFactory() throws Exception { public void testDocumentBuilderFactory() throws Exception {
try {
assertTrue(DocumentHelper.documentBuilderFactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); assertTrue(DocumentHelper.documentBuilderFactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR)); assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD)); assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
} catch(AbstractMethodError e) {
// ignore exceptions from old parsers that don't support this API (https://bz.apache.org/bugzilla/show_bug.cgi?id=62692)
}
} }
} }

View File

@ -24,6 +24,7 @@ import javax.xml.XMLConstants;
import org.junit.Test; import org.junit.Test;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.XMLReader; import org.xml.sax.XMLReader;
public class TestSAXHelper { public class TestSAXHelper {
@ -31,6 +32,7 @@ public class TestSAXHelper {
public void testXMLReader() throws Exception { public void testXMLReader() throws Exception {
XMLReader reader = SAXHelper.newXMLReader(); XMLReader reader = SAXHelper.newXMLReader();
assertNotSame(reader, SAXHelper.newXMLReader()); assertNotSame(reader, SAXHelper.newXMLReader());
try {
assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR)); assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD)); assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
@ -38,7 +40,10 @@ public class TestSAXHelper {
assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT)); assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
assertEquals("1", reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT)); assertEquals("1", reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_SECURITY_MANAGER)); assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_SECURITY_MANAGER));
} catch(SAXNotRecognizedException e) {
// ignore exceptions from old parsers that don't support these features
// (https://bz.apache.org/bugzilla/show_bug.cgi?id=62692)
}
reader.parse(new InputSource(new ByteArrayInputStream("<xml></xml>".getBytes("UTF-8")))); reader.parse(new InputSource(new ByteArrayInputStream("<xml></xml>".getBytes("UTF-8"))));
} }
} }

View File

@ -907,7 +907,7 @@ public final class TestPackage {
getZipStatsAndConsume((max_size, min_ratio) -> { getZipStatsAndConsume((max_size, min_ratio) -> {
// check max entry size ouf of bounds // check max entry size ouf of bounds
ZipSecureFile.setMinInflateRatio(min_ratio-0.002); ZipSecureFile.setMinInflateRatio(min_ratio-0.002);
ZipSecureFile.setMaxEntrySize(max_size-100); ZipSecureFile.setMaxEntrySize(max_size-200);
}); });
} }
@ -925,8 +925,8 @@ public final class TestPackage {
if (ze.getSize() == 0) { if (ze.getSize() == 0) {
continue; continue;
} }
// add zip entry header ~ 30 bytes // add zip entry header ~ 128 bytes
long size = ze.getSize()+30; long size = ze.getSize()+128;
double ratio = ze.getCompressedSize() / (double)size; double ratio = ze.getCompressedSize() / (double)size;
min_ratio = Math.min(min_ratio, ratio); min_ratio = Math.min(min_ratio, ratio);
max_size = Math.max(max_size, size); max_size = Math.max(max_size, size);

View File

@ -93,6 +93,87 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
public class TestXSLFBugs { public class TestXSLFBugs {
private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
@Test
public void bug62736() throws Exception {
XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("bug62736.pptx");
assertEquals(1, ss1.getSlides().size());
XSLFSlide slide0 = ss1.getSlides().get(0);
assertEquals(slide0.getShapes().size(), 4);
assertRelation(slide0, "/ppt/slides/slide1.xml", null);
assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
assertRelation(slide0, "/ppt/media/image1.png", "rId2");
assertEquals(slide0.getRelations().size(), 2);
List<XSLFPictureShape> pictures = new ArrayList<>();
for (XSLFShape shape : slide0.getShapes()) {
if (shape instanceof XSLFPictureShape) {
pictures.add((XSLFPictureShape) shape);
}
}
assertEquals(pictures.size(), 2);
assertEquals(pictures.get(0).getPictureData().getFileName(), "image1.png");
assertEquals(pictures.get(1).getPictureData().getFileName(), "image1.png");
// blipId is rId2 of both pictures
// remove just the first picture
slide0.removeShape(pictures.get(0));
assertEquals(slide0.getShapes().size(), 3);
assertRelation(slide0, "/ppt/slides/slide1.xml", null);
assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
// the bug is that the following relation is gone
assertRelation(slide0, "/ppt/media/image1.png", "rId2");
assertEquals(slide0.getRelations().size(), 2);
// Save and re-load
XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss1);
ss1.close();
assertEquals(1, ss2.getSlides().size());
slide0 = ss2.getSlides().get(0);
assertRelation(slide0, "/ppt/slides/slide1.xml", null);
assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
assertRelation(slide0, "/ppt/media/image1.png", "rId2");
assertEquals(slide0.getRelations().size(), 2);
pictures.clear();
for (XSLFShape shape : slide0.getShapes()) {
if (shape instanceof XSLFPictureShape) {
pictures.add((XSLFPictureShape) shape);
}
}
assertEquals(pictures.size(), 1);
assertEquals(pictures.get(0).getPictureData().getFileName(), "image1.png");
slide0.removeShape(pictures.get(0));
assertEquals(slide0.getShapes().size(), 2);
assertRelation(slide0, "/ppt/slides/slide1.xml", null);
assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
assertNull(slide0.getRelationById("rId2"));
assertEquals(slide0.getRelations().size(), 1);
// Save and re-load
XMLSlideShow ss3 = XSLFTestDataSamples.writeOutAndReadBack(ss2);
ss2.close();
assertEquals(1, ss3.getSlides().size());
slide0 = ss3.getSlides().get(0);
assertRelation(slide0, "/ppt/slides/slide1.xml", null);
assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
assertEquals(slide0.getShapes().size(), 2);
ss3.close();
}
@Test @Test
public void bug61589() throws IOException { public void bug61589() throws IOException {

View File

@ -0,0 +1,158 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF 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.poi.xslf.XSLFTestDataSamples;
import org.junit.Test;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties;
import org.openxmlformats.schemas.presentationml.x2006.main.impl.CTBackgroundImpl;
import java.awt.*;
import java.io.IOException;
import static org.junit.Assert.*;
public class TestXSLFBackground {
@Test
public void testNoFillBackground() throws IOException {
XMLSlideShow pptx = new XMLSlideShow();
XSLFSlide slide = pptx.createSlide();
slide.getBackground().setFillColor(null);
CTBackgroundImpl bg = (CTBackgroundImpl) slide.getBackground().getXmlObject();
CTBackgroundProperties bgPr = bg.getBgPr();
assertFalse(bgPr.isSetBlipFill());
assertFalse(bgPr.isSetGradFill());
assertFalse(bgPr.isSetGrpFill());
assertFalse(bgPr.isSetPattFill());
assertFalse(bgPr.isSetSolidFill());
assertTrue(bgPr.isSetNoFill());
pptx.close();
}
@Test
public void testSolidFillBackground() throws IOException {
XMLSlideShow pptx = new XMLSlideShow();
XSLFSlide slide = pptx.createSlide();
Color color = Color.RED;
slide.getBackground().setFillColor(color);
CTBackgroundImpl bg = (CTBackgroundImpl) slide.getBackground().getXmlObject();
CTBackgroundProperties bgPr = bg.getBgPr();
assertFalse(bgPr.isSetBlipFill());
assertFalse(bgPr.isSetGradFill());
assertFalse(bgPr.isSetGrpFill());
assertFalse(bgPr.isSetPattFill());
assertTrue(bgPr.isSetSolidFill());
assertFalse(bgPr.isSetNoFill());
assertEquals(slide.getBackground().getFillColor(), color);
pptx.close();
}
@Test
public void testBlipFillBackground() throws IOException {
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("pptx2svg.pptx");
XSLFSlide slide = pptx.getSlides().get(0);
Color color = Color.WHITE;
CTBackgroundImpl bg = (CTBackgroundImpl) slide.getBackground().getXmlObject();
CTBackgroundProperties bgPr = bg.getBgPr();
assertTrue(bgPr.isSetBlipFill());
assertFalse(bgPr.isSetGradFill());
assertFalse(bgPr.isSetGrpFill());
assertFalse(bgPr.isSetPattFill());
assertFalse(bgPr.isSetSolidFill());
assertFalse(bgPr.isSetNoFill());
slide.getBackground().setFillColor(color);
assertFalse(bgPr.isSetBlipFill());
assertFalse(bgPr.isSetGradFill());
assertFalse(bgPr.isSetGrpFill());
assertFalse(bgPr.isSetPattFill());
assertTrue(bgPr.isSetSolidFill());
assertFalse(bgPr.isSetNoFill());
assertEquals(slide.getBackground().getFillColor(), color);
slide.getBackground().setFillColor(null);
assertFalse(bgPr.isSetBlipFill());
assertFalse(bgPr.isSetGradFill());
assertFalse(bgPr.isSetGrpFill());
assertFalse(bgPr.isSetPattFill());
assertFalse(bgPr.isSetSolidFill());
assertTrue(bgPr.isSetNoFill());
assertNull(slide.getBackground().getFillColor());
pptx.close();
}
@Test
public void testGradFillBackground() throws IOException {
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("themes.pptx");
XSLFSlide slide = pptx.getSlides().get(9);
Color color = Color.GREEN;
CTBackgroundImpl bg = (CTBackgroundImpl) slide.getBackground().getXmlObject();
CTBackgroundProperties bgPr = bg.getBgPr();
assertFalse(bgPr.isSetBlipFill());
assertTrue(bgPr.isSetGradFill());
assertFalse(bgPr.isSetGrpFill());
assertFalse(bgPr.isSetPattFill());
assertFalse(bgPr.isSetSolidFill());
assertFalse(bgPr.isSetNoFill());
slide.getBackground().setFillColor(color);
assertFalse(bgPr.isSetBlipFill());
assertFalse(bgPr.isSetGradFill());
assertFalse(bgPr.isSetGrpFill());
assertFalse(bgPr.isSetPattFill());
assertTrue(bgPr.isSetSolidFill());
assertFalse(bgPr.isSetNoFill());
assertEquals(slide.getBackground().getFillColor(), color);
slide.getBackground().setFillColor(null);
assertFalse(bgPr.isSetBlipFill());
assertFalse(bgPr.isSetGradFill());
assertFalse(bgPr.isSetGrpFill());
assertFalse(bgPr.isSetPattFill());
assertFalse(bgPr.isSetSolidFill());
assertTrue(bgPr.isSetNoFill());
assertNull(slide.getBackground().getFillColor());
pptx.close();
}
}

View File

@ -158,7 +158,7 @@ public class TestXSLFChart {
final XDDFNumericalDataSource<Integer> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange); final XDDFNumericalDataSource<Integer> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange);
series.replaceData(categoryData, valuesData); series.replaceData(categoryData, valuesData);
final String title = "Apache POI"; final String title = "Apache POI";
series.setTitle(title, chart.setSheetTitle(title)); series.setTitle(title, chart.setSheetTitle(title, 0));
chart.plot(data); chart.plot(data);
} }

View File

@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -395,15 +396,21 @@ public final class TestXSSFTable {
assertEquals(2, table.getRowCount()); assertEquals(2, table.getRowCount());
// add columns // add columns
table.createColumn("Column B"); XSSFTableColumn c1 = table.getColumns().get(0);
table.createColumn("Column D"); XSSFTableColumn cB = table.createColumn("Column B");
table.createColumn("Column C", 2); // add between B and D XSSFTableColumn cD = table.createColumn("Column D");
XSSFTableColumn cC = table.createColumn("Column C", 2); // add between B and D
table.updateReferences(); table.updateReferences();
table.updateHeaders(); table.updateHeaders();
assertEquals(4, table.getColumnCount()); assertEquals(4, table.getColumnCount());
assertEquals(2, table.getRowCount()); assertEquals(2, table.getRowCount());
// column IDs start at 1, and increase in the order columns are added (see bug #62740)
assertEquals("Column c ID", 1, c1.getId());
assertTrue("Column B ID", c1.getId() < cB.getId());
assertTrue("Column D ID", cB.getId() < cD.getId());
assertTrue("Column C ID", cD.getId() < cC.getId());
assertEquals("Column 1", table.getColumns().get(0).getName()); // generated name assertEquals("Column 1", table.getColumns().get(0).getName()); // generated name
assertEquals("Column B", table.getColumns().get(1).getName()); assertEquals("Column B", table.getColumns().get(1).getName());
assertEquals("Column C", table.getColumns().get(2).getName()); assertEquals("Column C", table.getColumns().get(2).getName());

View File

@ -39,8 +39,8 @@ import java.util.List;
import java.util.zip.CRC32; import java.util.zip.CRC32;
import org.apache.poi.POIDataSamples; import org.apache.poi.POIDataSamples;
import org.apache.poi.ooxml.POIXMLProperties;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ooxml.POIXMLProperties;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.ContentTypes; import org.apache.poi.openxml4j.opc.ContentTypes;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
@ -67,6 +67,8 @@ import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.TempFile; import org.apache.poi.util.TempFile;
import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.model.StylesTable;
@ -553,7 +555,9 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
Sheet sheet = wb.getSheetAt(0); Sheet sheet = wb.getSheetAt(0);
sheet.shiftRows(2, sheet.getLastRowNum(), 1, true, false); sheet.shiftRows(2, sheet.getLastRowNum(), 1, true, false);
Row newRow = sheet.getRow(2); Row newRow = sheet.getRow(2);
if (newRow == null) newRow = sheet.createRow(2); if (newRow == null) {
newRow = sheet.createRow(2);
}
newRow.createCell(0).setCellValue(" Another Header"); newRow.createCell(0).setCellValue(" Another Header");
wb.cloneSheet(0); wb.cloneSheet(0);
@ -700,6 +704,24 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
} }
} }
@Test
public void bug60509() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("60509.xlsx");
assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3");
int sheetIndex = wb.getSheetIndex("Sheet1");
wb.setSheetName(sheetIndex, "Sheet1-Renamed");
Workbook read = XSSFTestDataSamples.writeOutAndReadBack(wb);
assertNotNull(read);
assertSheetOrder(read, "Sheet1-Renamed", "Sheet2", "Sheet3");
XSSFSheet sheet = (XSSFSheet) read.getSheet("Sheet1-Renamed");
XDDFChartData.Series series = sheet.getDrawingPatriarch().getCharts().get(0).getChartSeries().get(0).getSeries().get(0);
assertTrue("should be a bar chart data series", series instanceof XDDFBarChartData.Series);
String formula = ((XDDFBarChartData.Series) series).getCategoryData().getFormula();
assertTrue("should contain new sheet name", formula.startsWith("'Sheet1-Renamed'!"));
read.close();
wb.close();
}
private static final int INDEX_NOT_FOUND = -1; private static final int INDEX_NOT_FOUND = -1;
private static boolean isEmpty(CharSequence cs) { private static boolean isEmpty(CharSequence cs) {

View File

@ -123,6 +123,11 @@ java.util.concurrent.Future#cancel(boolean)
@defaultMessage Don't use ...InputStream.available() as it gives wrong result for certain streams - use IOUtils.toByteArray to read the stream fully and then count the available bytes @defaultMessage Don't use ...InputStream.available() as it gives wrong result for certain streams - use IOUtils.toByteArray to read the stream fully and then count the available bytes
java.io.InputStream#available() java.io.InputStream#available()
@defaultMessage Use newInstance, as newFactory does not seem to work on Android - https://github.com/centic9/poi-on-android/issues/44#issuecomment-426517981
javax.xml.stream.XMLEventFactory#newFactory()
javax.xml.stream.XMLInputFactory#newFactory()
javax.xml.stream.XMLOutputFactory#newFactory()
@defaultMessage Unnecessary, inefficient, and confusing conversion of String.toString @defaultMessage Unnecessary, inefficient, and confusing conversion of String.toString
java.lang.String#toString() java.lang.String#toString()

View File

@ -187,7 +187,7 @@ public class TextSpecInfoRun {
smartTagFld, smartTagsBytes, "smart tags" smartTagFld, smartTagsBytes, "smart tags"
}; };
for (int i=0; i<flds.length; i+=3) { for (int i=0; i<flds.length-1; i+=3) {
BitField fld = (BitField)flds[i+0]; BitField fld = (BitField)flds[i+0];
Object valO = flds[i+1]; Object valO = flds[i+1];
if (!fld.isSet(mask)) continue; if (!fld.isSet(mask)) continue;
@ -210,7 +210,8 @@ public class TextSpecInfoRun {
valid = false; valid = false;
} }
if (!valid) { if (!valid) {
throw new IOException(flds[i+2]+" is activated, but its value is invalid"); Object fval = (i + 2) < flds.length ? flds[i + 2] : null;
throw new IOException(fval + " is activated, but its value is invalid");
} }
} }
} }

View File

@ -53,12 +53,6 @@ public class TestRandBetween extends TestCase {
formulaCell = row.createCell(2, CellType.FORMULA); formulaCell = row.createCell(2, CellType.FORMULA);
} }
@Override
protected void tearDown() throws Exception {
// TODO Auto-generated method stub
super.tearDown();
}
/** /**
* Check where values are the same * Check where values are the same
*/ */
@ -75,6 +69,17 @@ public class TestRandBetween extends TestCase {
} }
public void testRandBetweenLargeLongs() {
for (int i = 0; i < 100; i++) {
evaluator.clearAllCachedResultValues();
formulaCell.setCellFormula("RANDBETWEEN(0,9999999999)");
evaluator.evaluateFormulaCell(formulaCell);
double value = formulaCell.getNumericCellValue();
assertTrue("rand is greater than or equal to lowerbound", value >= 0.0);
assertTrue("rand is less than or equal to upperbound", value <= 9999999999.0);
}
}
/** /**
* Check special case where rounded up bottom value is greater than * Check special case where rounded up bottom value is greater than
* top value. * top value.

Binary file not shown.

BIN
test-data/spreadsheet/60509.xlsx Executable file

Binary file not shown.