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="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 kind="lib" path="compile-lib/bcpkix-jdk15on-1.59.jar"/>
<classpathentry kind="lib" path="compile-lib/bcprov-ext-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.60.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-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) {
to = jar.archivePath
onlyModified = true
@ -187,6 +185,7 @@ project('main') {
compile 'javax.activation:activation:1.1.1'
testCompile 'junit:junit:4.12'
testCompile 'org.reflections:reflections:0.9.11'
}
jar {
@ -231,7 +230,7 @@ project('ooxml') {
compile 'org.apache.commons:commons-math3:3.6.1'
compile 'org.apache.commons:commons-compress:1.18'
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'
// for ooxml-lite, should we move this somewhere else?
@ -245,6 +244,7 @@ project('ooxml') {
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:2.21.0'
testCompile 'org.xmlunit:xmlunit-core:2.5.1'
testCompile 'org.reflections:reflections:0.9.11'
testCompile project(path: ':main', configuration: 'tests')
testCompile 'org.openjdk.jmh:jmh-core: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="ooxml.lib" location="ooxml-lib"/>
<property name="ooxml.test.lib" location="ooxml-testlib"/>
<property name="compile.lib" location="compile-lib"/>
<!-- compiler options options -->
@ -201,14 +202,14 @@ under the License.
<!-- xml signature libs -->
<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.bouncycastle-prov.jar" location="${compile.lib}/bcprov-ext-jdk15on-1.59.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-pkix.jar" location="${compile.lib}/bcpkix-jdk15on-1.59.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-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.60/bcprov-ext-jdk15on-1.60.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.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.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.url"
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"
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 -->
<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"/>
@ -232,8 +244,8 @@ under the License.
<!-- license and api checks -->
<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="forbidden.jar" location="${main.lib}/forbiddenapis-2.5.jar"/>
<property name="forbidden.url" value="${repository.m2}/maven2/de/thetaphi/forbiddenapis/2.5/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.6/forbiddenapis-2.6.jar"/>
<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"/>
<!-- 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.url" value="${repository.m2}/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.59/bcprov-ext-jdk15on-1.59.jar"/>
<property name="dist.bouncycastle-bcpg.jar" location="${compile.lib}/bcpg-jdk15on-1.59.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-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.60/bcprov-ext-jdk15on-1.60.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.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.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"/>
@ -416,10 +428,17 @@ under the License.
<pathelement location="${additionaljar}"/>
</path>
<path id="test.ooxml.reflections.classpath">
<pathelement location="${ooxml.test.reflections.jar}"/>
<pathelement location="${ooxml.test.guava.jar}"/>
<pathelement location="${ooxml.test.javassist.jar}"/>
</path>
<path id="test.ooxml.classpath">
<path refid="ooxml.classpath"/>
<path refid="ooxml.xmlsec.classpath"/>
<path refid="test.jar.classpath"/>
<path refid="test.ooxml.reflections.classpath"/>
<pathelement location="${ooxml.output.dir}"/>
<pathelement location="${ooxml.output.test.dir}"/>
<pathelement location="${main.output.test.dir}"/>
@ -484,6 +503,7 @@ under the License.
<path refid="scratchpad.classpath"/>
<path refid="ooxml.classpath"/>
<path refid="ooxml.xmlsec.classpath"/>
<path refid="test.ooxml.reflections.classpath"/>
<path refid="excelant.classpath"/>
<path refid="examples.classpath"/>
<pathelement location="${examples.output.dir}"/>
@ -582,6 +602,7 @@ under the License.
<mkdir dir="${main.lib}"/>
<mkdir dir="${compile.lib}"/>
<mkdir dir="${ooxml.lib}"/>
<mkdir dir="${ooxml.test.lib}"/>
<delete verbose="true">
<fileset dir="${main.lib}">
<include name="ant-1.8*"/>
@ -631,6 +652,7 @@ under the License.
<include name="forbiddenapis-2.0.jar"/>
<include name="forbiddenapis-2.1.jar"/>
<include name="forbiddenapis-2.3.jar"/>
<include name="forbiddenapis-2.5.jar"/>
<include name="apache-rat-0.11.jar"/>
<include name="mockito-core-2.13.0.jar"/>
</fileset>
@ -655,10 +677,7 @@ under the License.
<include name="xmlsec-2.0.1.jar"/>
<include name="xmlsec-2.0.5.jar"/>
<include name="xmlsec-2.0.6.jar"/>
<include name="bc*jdk15on-1.51.jar"/>
<include name="bc*jdk15on-1.53.jar"/>
<include name="bc*jdk15on-1.54.jar"/>
<include name="bc*jdk15on-1.58.jar"/>
<include name="bc*jdk15on-1.5*.jar"/>
<include name="slf4j-api-1.7.7.jar"/>
<include name="slf4j-api-1.7.12.jar"/>
</fileset>
@ -753,6 +772,9 @@ under the License.
<available file="${ooxml.curvesapi.jar}"/>
<available file="${ooxml.xmlbeans.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>
<isset property="disconnected"/>
</or>
@ -760,9 +782,13 @@ under the License.
</target>
<target name="fetch-ooxml-jars" depends="check-ooxml-jars" unless="ooxml.jars.present">
<mkdir dir="${ooxml.lib}"/>
<mkdir dir="${ooxml.test.lib}"/>
<downloadfile src="${ooxml.curvesapi.url}" dest="${ooxml.curvesapi.jar}"/>
<downloadfile src="${ooxml.xmlbeans.url}" dest="${ooxml.xmlbeans.jar}"/>
<downloadfile src="${ooxml.commons-compress.url}" dest="${ooxml.commons-compress.jar}"/>
<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 name="check-svn-jars">
<condition property="svn.jars.present">
@ -2045,6 +2071,7 @@ under the License.
<include name="commons-codec-*.jar"/>
<include name="commons-logging-*.jar"/>
<include name="commons-collections4-*.jar"/>
<include name="commons-compress*.jar"/>
<include name="commons-math3-*.jar"/>
<include name="jaxb-api-*.jar"/>
<include name="jaxb-impl-*.jar"/>
@ -2753,13 +2780,20 @@ under the License.
project.setProperty(attributes.get("property"), mega);
</scriptdef>
<macrodef name="loadFilesize">
<attribute name="url"/>
<attribute name="property"/>
<macrodef name="download-line">
<attribute name="prop"/>
<attribute name="dist"/>
<attribute name="pack"/>
<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"/>
<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"/>
<local name="fileSize"/>
<loadfile property="fileSize" srcFile="build/loadFilesize.txt">
@ -2770,7 +2804,16 @@ under the License.
</tokenfilter>
</filterchain>
</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>
</macrodef>
@ -2795,23 +2838,17 @@ under the License.
<format property="rel_date" pattern="dd MMMM yyyy" locale="US"/>
<format property="file_date" pattern="yyyyMMdd" locale="US"/>
</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"/>
<loadChecksum property="bin-tar-sha512" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.tar.gz.sha512"/>
<loadChecksum property="bin-zip-sha256" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.zip.sha256"/>
<loadChecksum property="bin-zip-sha512" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.zip.sha512"/>
<loadChecksum property="src-tar-sha256" url="${baseurl}/src/poi-src-${version.id}-${file_date}.tar.gz.sha256"/>
<loadChecksum property="src-tar-sha512" url="${baseurl}/src/poi-src-${version.id}-${file_date}.tar.gz.sha512"/>
<loadChecksum property="src-zip-sha256" url="${baseurl}/src/poi-src-${version.id}-${file_date}.zip.sha256"/>
<loadChecksum property="src-zip-sha512" url="${baseurl}/src/poi-src-${version.id}-${file_date}.zip.sha512"/>
<local name="li1"/>
<local name="li2"/>
<local name="li3"/>
<local name="li4"/>
<download-line prop="li1" dist="bin" pack="tar.gz"/>
<download-line prop="li2" dist="bin" pack="zip"/>
<download-line prop="li3" dist="src" pack="tar.gz"/>
<download-line prop="li4" dist="src" pack="zip"/>
<loadFilesize property="bin-tar-size" url="${baseurl}/bin/poi-bin-${version.id}-${file_date}.tar.gz"/>
<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[
<echo file="download-snipplet.xml"><![CDATA[
<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}.
Featured are a handful of new areas of functionality and numerous bug fixes.</p>
@ -2828,46 +2865,14 @@ under the License.
</p>
<section id="POI-${version.id}-bin"><title>Binary Distribution</title>
<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>
(${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>)
<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>
${li1}
${li2}
</ul>
</section>
<section id="POI-${version.id}-src"><title>Source Distribution</title>
<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>
(${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>)
<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>
${li3}
${li4}
</ul>
</section>
</section>

View File

@ -25,19 +25,6 @@ def poijobs = [
// the JDK is missing on some slaves so builds are unstable
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,
properties: ['-Djava9addmods=--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 xmlbeansSvnBase = 'https://svn.apache.org/repos/asf/xmlbeans/trunk'
def defaultJdk = '1.8'
def defaultTrigger = 'H/15 * * * *' // check SCM every 60/15 = 4 minutes
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 jdkMapping = [
'1.6': 'JDK 1.6 (latest)',
'1.8': 'JDK 1.8 (latest)',
'1.9': 'JDK 1.9 (latest)',
'1.10': 'JDK 10 (latest)',
'1.11': 'JDK 11 (latest)',
'1.12': 'JDK 12 (latest)',
@ -141,7 +135,7 @@ static def shellEx(def context, String cmd, def poijob) {
}
def defaultDesc = '''
<img src="https://poi.apache.org/resources/images/project-logo.jpg" />
<img src="https://poi.apache.org/images/project-header.png" />
<p>
Apache POI - the Java API for Microsoft Documents
</p>
@ -233,7 +227,7 @@ poijobs.each { poijob ->
label(slaves)
environmentVariables {
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
// 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')
@ -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
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!
'IBM 1.8 64-bit (on Ubuntu only)',
'JDK 1.9 (latest)',
'JDK 10 (latest)',
'JDK 10 b46 (Windows Only)',
'OpenJDK 10.0.2 (on Ubuntu only)',

View File

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

View File

@ -76,7 +76,17 @@
<dependency>
<groupId>commons-codec</groupId>
<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>
@ -91,11 +101,6 @@
<scope>test</scope>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.2</version>
</dependency>
</dependencies>
</project>

View File

@ -12,64 +12,64 @@
<packaging>jar</packaging>
<name>Apache POI OOXML package</name>
<build>
<plugins>
<!-- copy sources, resources and tests in place as otherwise Sonar does not pick them up correctly! -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.plugin.resources.version}</version>
<executions>
<execution>
<id>copy-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<resources>
<resource>
<directory>../../src/ooxml/java</directory>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/resources</outputDirectory>
<resources>
<resource>
<directory>../../src/resources/ooxml</directory>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-tests</id>
<phase>generate-test-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/test/java</outputDirectory>
<resources>
<resource>
<directory>../../src/ooxml/testcases</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- clean copied sources afterwards -->
<plugin>
<build>
<plugins>
<!-- copy sources, resources and tests in place as otherwise Sonar does not pick them up correctly! -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.plugin.resources.version}</version>
<executions>
<execution>
<id>copy-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<resources>
<resource>
<directory>../../src/ooxml/java</directory>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/resources</outputDirectory>
<resources>
<resource>
<directory>../../src/resources/ooxml</directory>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-tests</id>
<phase>generate-test-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/test/java</outputDirectory>
<resources>
<resource>
<directory>../../src/ooxml/testcases</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- clean copied sources afterwards -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven.plugin.clean.version}</version>
<configuration>
@ -96,88 +96,94 @@
<argLine>@{argLine} -Duser.language=en -Duser.country=US -Xmx1024m -Djava.io.tmpdir=target/tmp -XX:-OmitStackTraceInFastThrow</argLine>
</configuration>
</plugin>
</plugins>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<groupId>${project.groupId}</groupId>
<artifactId>poi-ooxml-schema</artifactId>
<version>${project.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>poi-ooxml-schema-encryption</artifactId>
<version>${project.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<groupId>${project.groupId}</groupId>
<artifactId>poi-ooxml-schema-security</artifactId>
<version>${project.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>poi-main</artifactId>
<version>${project.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>poi-main</artifactId>
<version>${project.version}</version>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>poi-main</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>${xmlbeans.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>com.github.virtuald</groupId>
<artifactId>curvesapi</artifactId>
<version>1.05</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>${xmlbeans.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.60</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
<dependency>
<groupId>org.apache.santuario</groupId>
<artifactId>xmlsec</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>com.github.virtuald</groupId>
<artifactId>curvesapi</artifactId>
<version>1.05</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.19</version>
<scope>test</scope>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.19</version>
<scope>test</scope>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

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

View File

@ -53,7 +53,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
* Excel Conditional Formatting -- Examples
*
* <p>
* Partly based on the code snippets from
* Partly based on the code snippets from
* http://www.contextures.com/xlcondformat03.html
* </p>
*/
@ -89,7 +89,7 @@ public class ConditionalFormats {
// print overlapping rule results
evaluateRules(wb, "Overlapping");
// Write the output to a file
String file = "cf-poi.xls";
if(wb instanceof XSSFWorkbook) {
@ -178,11 +178,11 @@ public class ConditionalFormats {
sheet.getRow(2).createCell(4).setCellValue("<== Condition 1: Formula Is =$B2>75 (Blue Fill)");
}
/**
* Multiple conditional formatting rules can apply to
* one cell, some combining, some beating others.
* Done in order of the rules added to the
* Done in order of the rules added to the
* SheetConditionalFormatting object
*/
static void overlapping(Sheet sheet) {
@ -210,39 +210,39 @@ public class ConditionalFormats {
}
sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);
sheet.getRow(1).createCell(3).setCellValue("Even rows are blue");
sheet.getRow(2).createCell(3).setCellValue("Multiples of 3 have a grey background");
sheet.getRow(4).createCell(3).setCellValue("Multiples of 5 are bold");
sheet.getRow(9).createCell(3).setCellValue("Multiples of 10 are red (beats even)");
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
// Condition 1: Row divides by 10, red (will beat #1)
ConditionalFormattingRule rule1 =
ConditionalFormattingRule rule1 =
sheetCF.createConditionalFormattingRule("MOD(ROW(),10)=0");
FontFormatting font1 = rule1.createFontFormatting();
font1.setFontColorIndex(IndexedColors.RED.index);
// Condition 2: Row is even, blue
ConditionalFormattingRule rule2 =
ConditionalFormattingRule rule2 =
sheetCF.createConditionalFormattingRule("MOD(ROW(),2)=0");
FontFormatting font2 = rule2.createFontFormatting();
font2.setFontColorIndex(IndexedColors.BLUE.index);
// Condition 3: Row divides by 5, bold
ConditionalFormattingRule rule3 =
ConditionalFormattingRule rule3 =
sheetCF.createConditionalFormattingRule("MOD(ROW(),5)=0");
FontFormatting font3 = rule3.createFontFormatting();
font3.setFontStyle(false, true);
// Condition 4: Row divides by 3, grey background
ConditionalFormattingRule rule4 =
ConditionalFormattingRule rule4 =
sheetCF.createConditionalFormattingRule("MOD(ROW(),3)=0");
PatternFormatting fill4 = rule4.createPatternFormatting();
fill4.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index);
fill4.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
// Apply
CellRangeAddress[] regions = {
CellRangeAddress.valueOf("A1:F41")
@ -441,7 +441,7 @@ public class ConditionalFormats {
}
/**
* You can use Excel conditional formatting to shade bands of rows on the worksheet.
* You can use Excel conditional formatting to shade bands of rows on the worksheet.
* In this example, 3 rows are shaded light grey, and 3 are left with no shading.
* In the MOD function, the total number of rows in the set of banded rows (6) is entered.
*/
@ -462,7 +462,7 @@ public class ConditionalFormats {
sheet.createRow(0).createCell(1).setCellValue("Shade Bands of Rows");
sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),6)<2 (Light Grey Fill)");
}
/**
* Icon Sets / Multi-States allow you to have icons shown which vary
* based on the values, eg Red traffic light / Yellow traffic light /
@ -487,7 +487,7 @@ public class ConditionalFormats {
r.createCell(3).setCellValue(10);
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
CellRangeAddress[] regions = { CellRangeAddress.valueOf("B1:B4") };
ConditionalFormattingRule rule1 =
sheetCF.createConditionalFormattingRule(IconSet.GYR_3_TRAFFIC_LIGHTS);
@ -497,7 +497,7 @@ public class ConditionalFormats {
im1.getThresholds()[1].setValue(33d);
im1.getThresholds()[2].setRangeType(RangeType.MAX);
sheetCF.addConditionalFormatting(regions, rule1);
regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C1:C4") };
ConditionalFormattingRule rule2 =
sheetCF.createConditionalFormattingRule(IconSet.GYR_3_FLAGS);
@ -509,7 +509,7 @@ public class ConditionalFormats {
im2.getThresholds()[2].setRangeType(RangeType.PERCENT);
im2.getThresholds()[2].setValue(67d);
sheetCF.addConditionalFormatting(regions, rule2);
regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D1:D4") };
ConditionalFormattingRule rule3 =
sheetCF.createConditionalFormattingRule(IconSet.GYR_3_SYMBOLS_CIRCLE);
@ -522,7 +522,7 @@ public class ConditionalFormats {
im3.getThresholds()[2].setValue(7d);
sheetCF.addConditionalFormatting(regions, rule3);
}
/**
* Color Scales / Colour Scales / Colour Gradients allow you shade the
* background colour of the cell based on the values, eg from Red to
@ -533,12 +533,12 @@ public class ConditionalFormats {
Row r = sheet.createRow(1);
r.createCell(0).setCellValue("Red-Yellow-Green");
for (int i=1; i<=7; i++) {
r.createCell(i).setCellValue((i-1)*5);
r.createCell(i).setCellValue((i-1)*5.0);
}
r = sheet.createRow(2);
r.createCell(0).setCellValue("Red-White-Blue");
for (int i=1; i<=9; i++) {
r.createCell(i).setCellValue((i-1)*5);
r.createCell(i).setCellValue((i-1)*5.0);
}
r = sheet.createRow(3);
r.createCell(0).setCellValue("Blue-Green");
@ -546,9 +546,9 @@ public class ConditionalFormats {
r.createCell(i).setCellValue((i-1));
}
sheet.setColumnWidth(0, 5000);
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:H2") };
ConditionalFormattingRule rule1 =
sheetCF.createConditionalFormattingColorScaleRule();
@ -561,7 +561,7 @@ public class ConditionalFormats {
((ExtendedColor)cs1.getColors()[1]).setARGBHex("FFFFEB84");
((ExtendedColor)cs1.getColors()[2]).setARGBHex("FF63BE7B");
sheetCF.addConditionalFormatting(regions, rule1);
regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B3:J3") };
ConditionalFormattingRule rule2 =
sheetCF.createConditionalFormattingColorScaleRule();
@ -574,7 +574,7 @@ public class ConditionalFormats {
((ExtendedColor)cs2.getColors()[1]).setARGBHex("FFFCFCFF");
((ExtendedColor)cs2.getColors()[2]).setARGBHex("FF5A8AC6");
sheetCF.addConditionalFormatting(regions, rule2);
regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B4:Q4") };
ConditionalFormattingRule rule3=
sheetCF.createConditionalFormattingColorScaleRule();
@ -586,7 +586,7 @@ public class ConditionalFormats {
((ExtendedColor)cs3.getColors()[1]).setARGBHex("FF63BE7B");
sheetCF.addConditionalFormatting(regions, rule3);
}
/**
* DataBars / Data-Bars allow you to have bars shown vary
* based on the values, from full to empty
@ -623,7 +623,7 @@ public class ConditionalFormats {
sheet.setColumnWidth(3, 5000);
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
ExtendedColor color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
color.setARGBHex("FF63BE7B");
CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:B7") };
@ -632,7 +632,7 @@ public class ConditionalFormats {
db1.getMinThreshold().setRangeType(RangeType.MIN);
db1.getMaxThreshold().setRangeType(RangeType.MAX);
sheetCF.addConditionalFormatting(regions, rule1);
color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
color.setARGBHex("FF5A8AC6");
regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C2:C7") };
@ -641,7 +641,7 @@ public class ConditionalFormats {
db2.getMinThreshold().setRangeType(RangeType.MIN);
db2.getMaxThreshold().setRangeType(RangeType.MAX);
sheetCF.addConditionalFormatting(regions, rule2);
color = sheet.getWorkbook().getCreationHelper().createExtendedColor();
color.setARGBHex("FFF8696B");
regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D2:D7") };
@ -651,7 +651,7 @@ public class ConditionalFormats {
db3.getMaxThreshold().setRangeType(RangeType.MAX);
sheetCF.addConditionalFormatting(regions, rule3);
}
/**
* Print out a summary of the conditional formatting rules applied to cells on the given sheet.
* Only cells with a matching rule are printed, and for those, all matching rules are sumarized.
@ -661,15 +661,19 @@ public class ConditionalFormats {
final ConditionalFormattingEvaluator cfEval = new ConditionalFormattingEvaluator(wb, wbEvalProv);
// if cell values have changed, clear cached format results
cfEval.clearAllCachedValues();
final Sheet sheet = wb.getSheet(sheetName);
for (Row r : sheet) {
for (Cell c : r) {
final List<EvaluationConditionalFormatRule> rules = cfEval.getConditionalFormattingForCell(c);
// check rules list for null, although current implementation will return an empty list, not null, then do what you want with results
if (rules == null || rules.isEmpty()) continue;
if (rules == null || rules.isEmpty()) {
continue;
}
final CellReference ref = ConditionalFormattingEvaluator.getRef(c);
if (rules.isEmpty()) continue;
if (rules.isEmpty()) {
continue;
}
System.out.println("\n"
+ ref.formatAsString()
@ -682,7 +686,7 @@ public class ConditionalFormats {
b.append("\tRule ")
.append(rule.getFormattingIndex())
.append(": ");
// check for color scale
if (cf.getColorScaleFormatting() != null) {
b.append("\n\t\tcolor scale (caller must calculate bucket)");
@ -709,13 +713,19 @@ public class ConditionalFormats {
b.append("\n\t\tfont format ")
.append("color index ")
.append(ff.getFontColorIndex());
if (ff.isBold()) b.append(" bold");
if (ff.isItalic()) b.append(" italic");
if (ff.isStruckout()) b.append(" strikeout");
if (ff.isBold()) {
b.append(" bold");
}
if (ff.isItalic()) {
b.append(" italic");
}
if (ff.isStruckout()) {
b.append(" strikeout");
}
b.append(" underline index ")
.append(ff.getUnderlineType());
}
System.out.println(b);
}
}

View File

@ -33,7 +33,6 @@ import java.util.Set;
import java.util.TreeMap;
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.CellFormatResult;
import org.apache.poi.ss.usermodel.BorderStyle;
@ -96,10 +95,10 @@ public class ToHtml {
BorderStyle.SLANTED_DASH_DOT, "dashed 2pt",
BorderStyle.THICK, "solid 3pt",
BorderStyle.THIN, "dashed 1pt");
private static final int IDX_TABLE_WIDTH = -2;
private static final int IDX_HEADER_COL_WIDTH = -1;
@SuppressWarnings({"unchecked"})
private static <K, V> Map<K, V> mapFor(Object... mapping) {
@ -189,9 +188,14 @@ public class ToHtml {
return;
}
ToHtml toHtml = create(args[0], new PrintWriter(new FileWriter(args[1])));
toHtml.setCompleteHTML(true);
toHtml.printPage();
try (
FileWriter fw = new FileWriter(args[1]);
PrintWriter pw = new PrintWriter(fw)
) {
ToHtml toHtml = create(args[0], pw);
toHtml.setCompleteHTML(true);
toHtml.printPage();
}
}
public void setCompleteHTML(boolean completeHTML) {
@ -350,32 +354,32 @@ public class ToHtml {
public void printSheet(Sheet sheet) {
ensureOut();
Map<Integer, Integer> widths = computeWidths(sheet);
int tableWidth = widths.get(IDX_TABLE_WIDTH);
int tableWidth = widths.get(IDX_TABLE_WIDTH);
out.format("<table class=%s style=\"width:%dpx;\">%n", DEFAULTS_CLASS, tableWidth);
printCols(widths);
printSheetContent(sheet);
out.format("</table>%n");
}
/**
* computes the column widths, defined by the sheet.
*
* computes the column widths, defined by the sheet.
*
* @param sheet The sheet for which to compute widths
* @return Map with key: column index; value: column width in pixels
* <br>special keys:
* <br>special keys:
* <br>{@link #IDX_HEADER_COL_WIDTH} - width of the header column
* <br>{@link #IDX_TABLE_WIDTH} - width of the entire table
* <br>{@link #IDX_TABLE_WIDTH} - width of the entire table
*/
private Map<Integer, Integer> computeWidths(Sheet sheet) {
Map<Integer, Integer> ret = new TreeMap<>();
int tableWidth = 0;
ensureColumnBounds(sheet);
// compute width of the header column
int lastRowNum = sheet.getLastRowNum();
int headerCharCount = String.valueOf(lastRowNum).length();
int headerColWidth = widthToPixels((headerCharCount + 1) * 256);
int headerColWidth = widthToPixels((headerCharCount + 1) * 256.0);
ret.put(IDX_HEADER_COL_WIDTH, headerColWidth);
tableWidth += headerColWidth;
@ -384,11 +388,11 @@ public class ToHtml {
ret.put(i, colWidth);
tableWidth += colWidth;
}
ret.put(IDX_TABLE_WIDTH, tableWidth);
return ret ;
}
/**
* Probably platform-specific, but appears to be a close approximation on some systems
* @param widthUnits POI's native width unit (twips)

View File

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

View File

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

View File

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

@ -58,18 +58,18 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
* <p>
* If you really want to use this approach, which is also the one that SXSSF
* does for you, it works as follows:
*
*
* 1. create a template workbook, create sheets and global objects such as cell styles, number formats, etc.
* 2. create an application that streams data in a text file
* 3. Substitute the sheet in the template with the generated data
*
* <p>
* Since 3.8 POI provides a low-memory footprint SXSSF API, which implements
* Since 3.8 POI provides a low-memory footprint SXSSF API, which implements
* ths "BigGridDemo" strategy. SXSSF is an API-compatible streaming extension
* of XSSF to be used when very large spreadsheets have to be produced, and
* heap space is limited. SXSSF achieves its low memory footprint by limiting
* access to the rows that are within a sliding window, while XSSF gives access
* to all rows in the document. Older rows that are no longer in the window
* of XSSF to be used when very large spreadsheets have to be produced, and
* heap space is limited. SXSSF achieves its low memory footprint by limiting
* access to the rows that are within a sliding window, while XSSF gives access
* to all rows in the document. Older rows that are no longer in the window
* become inaccessible, as they are written to the disk.
* </p>
* See <a "http://poi.apache.org/spreadsheet/how-to.html#sxssf">
@ -79,7 +79,7 @@ public final class BigGridDemo {
private static final String XML_ENCODING = "UTF-8";
private BigGridDemo() {}
public static void main(String[] args) throws Exception {
// Step 1. Create a template file. Setup sheets and workbook-level objects such as
@ -99,7 +99,10 @@ public final class BigGridDemo {
//Step 2. Generate XML file.
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);
}
@ -265,7 +268,9 @@ public final class BigGridDemo {
public void createCell(int columnIndex, String value, int styleIndex) throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\""+ref+"\" t=\"inlineStr\"");
if(styleIndex != -1) _out.write(" s=\""+styleIndex+"\"");
if(styleIndex != -1) {
_out.write(" s=\""+styleIndex+"\"");
}
_out.write(">");
_out.write("<is><t>"+value+"</t></is>");
_out.write("</c>");
@ -278,7 +283,9 @@ public final class BigGridDemo {
public void createCell(int columnIndex, double value, int styleIndex) throws IOException {
String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("<c r=\""+ref+"\" t=\"n\"");
if(styleIndex != -1) _out.write(" s=\""+styleIndex+"\"");
if(styleIndex != -1) {
_out.write(" s=\""+styleIndex+"\"");
}
_out.write(">");
_out.write("<v>"+value+"</v>");
_out.write("</c>");

View File

@ -33,14 +33,18 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
* Demonstrates how to create a simple table using Apache POI.
*/
public class CreateTable {
public static void main(String[] args) throws IOException {
try (Workbook wb = new XSSFWorkbook()) {
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
XSSFTable table = sheet.createTable();
XSSFTable table = sheet.createTable(reference);
table.setName("Test");
table.setDisplayName("Test_Table");
@ -70,7 +74,7 @@ public class CreateTable {
if (i == 0) {
cell.setCellValue("Column" + (j + 1));
} 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 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
try (FileOutputStream fileOut = new FileOutputStream("ooxml-table.xlsx")) {
wb.write(fileOut);

View File

@ -32,7 +32,10 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class IterateCells {
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++) {
Sheet sheet = wb.getSheetAt(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.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.PresetColor;
import org.apache.poi.xddf.usermodel.XDDFColor;
import org.apache.poi.xddf.usermodel.XDDFLineProperties;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
import org.apache.poi.xddf.usermodel.chart.AxisPosition;
import org.apache.poi.xddf.usermodel.chart.ChartTypes;
import org.apache.poi.xddf.usermodel.chart.LegendPosition;
import org.apache.poi.xddf.usermodel.chart.MarkerStyle;
import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFLineChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
import org.apache.poi.xssf.usermodel.XSSFChart;
@ -57,35 +64,64 @@ public class LineChart {
row = sheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex);
cell.setCellValue(colIndex * (rowIndex + 1));
cell.setCellValue(colIndex * (rowIndex + 1.0));
}
}
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
XDDFChartData data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
data.addSeries(xs, ys1);
data.addSeries(xs, ys2);
XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1);
series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
series1.setSmooth(false); // https://stackoverflow.com/questions/29014848
series1.setMarkerStyle(MarkerStyle.STAR); // https://stackoverflow.com/questions/39636138
XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2);
series2.setTitle("3x", null);
series2.setSmooth(true);
series2.setMarkerSize((short) 6);
series2.setMarkerStyle(MarkerStyle.TRIANGLE); // https://stackoverflow.com/questions/39636138
chart.plot(data);
// if your series have missing values like https://stackoverflow.com/questions/29014848
// chart.displayBlanksAs(DisplayBlanks.GAP);
// https://stackoverflow.com/questions/24676460
solidLineSeries(data, 0, PresetColor.CHARTREUSE);
solidLineSeries(data, 1, PresetColor.TURQUOISE);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) {
wb.write(fileOut);
}
}
}
private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFLineProperties line = new XDDFLineProperties();
line.setFillProperties(fill);
XDDFChartData.Series series = data.getSeries().get(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setLineProperties(line);
series.setShapeProperties(properties);
}
}

View File

@ -25,6 +25,11 @@ import java.io.IOException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.PresetColor;
import org.apache.poi.xddf.usermodel.XDDFColor;
import org.apache.poi.xddf.usermodel.XDDFLineProperties;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
import org.apache.poi.xddf.usermodel.chart.AxisPosition;
import org.apache.poi.xddf.usermodel.chart.ChartTypes;
@ -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.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFScatterChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
@ -59,36 +65,56 @@ public class ScatterChart {
row = sheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex);
cell.setCellValue(colIndex * (rowIndex + 1));
cell.setCellValue(colIndex * (rowIndex + 1.0));
}
}
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
XDDFChartData data = chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
data.addSeries(xs, ys1);
data.addSeries(xs, ys2);
XDDFScatterChartData data = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) data.addSeries(xs, ys1);
series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
series1.setSmooth(false); // https://stackoverflow.com/questions/39636138
XDDFScatterChartData.Series series2 = (XDDFScatterChartData.Series) data.addSeries(xs, ys2);
series2.setTitle("3x", null);
chart.plot(data);
solidLineSeries(data, 0, PresetColor.CHARTREUSE);
solidLineSeries(data, 1, PresetColor.TURQUOISE);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-scatter-chart.xlsx")) {
wb.write(fileOut);
}
}
}
private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFLineProperties line = new XDDFLineProperties();
line.setFillProperties(fill);
XDDFChartData.Series series = data.getSeries().get(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setLineProperties(line);
series.setShapeProperties(properties);
}
}

View File

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

View File

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

View File

@ -43,18 +43,29 @@ public class SimpleImages {
for (String imgFile : args) {
int format;
if (imgFile.endsWith(".emf")) format = XWPFDocument.PICTURE_TYPE_EMF;
else if (imgFile.endsWith(".wmf")) format = XWPFDocument.PICTURE_TYPE_WMF;
else if (imgFile.endsWith(".pict")) format = XWPFDocument.PICTURE_TYPE_PICT;
else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) format = XWPFDocument.PICTURE_TYPE_JPEG;
else if (imgFile.endsWith(".png")) format = XWPFDocument.PICTURE_TYPE_PNG;
else if (imgFile.endsWith(".dib")) 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 {
if (imgFile.endsWith(".emf")) {
format = XWPFDocument.PICTURE_TYPE_EMF;
} else if (imgFile.endsWith(".wmf")) {
format = XWPFDocument.PICTURE_TYPE_WMF;
} else if (imgFile.endsWith(".pict")) {
format = XWPFDocument.PICTURE_TYPE_PICT;
} else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) {
format = XWPFDocument.PICTURE_TYPE_JPEG;
} else if (imgFile.endsWith(".png")) {
format = XWPFDocument.PICTURE_TYPE_PNG;
} else if (imgFile.endsWith(".dib")) {
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 +
". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
continue;
@ -62,7 +73,9 @@ public class SimpleImages {
r.setText(imgFile);
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);
}

View File

@ -1,4 +1,12 @@
My Bar or Column Chart
First 1.0
Second 3.0
Third 4.0
10 languages with most speakers as first language
countries,speakers,language
58,315,العربية
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]);
boolean hasValue = 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];
if (value == null) {
// ignore null values
@ -384,7 +384,7 @@ public abstract class EscherRecord implements Cloneable {
if (attrList != null && attrList.length > 0) {
String childTab = " ";
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];
if (value == null) {
// ignore null values

View File

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

View File

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

View File

@ -77,7 +77,7 @@ final class RandBetween implements FreeRefFunction{
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
*/
public static XMLInputFactory newXMLInputFactory() {
XMLInputFactory factory = XMLInputFactory.newFactory();
XMLInputFactory factory = XMLInputFactory.newInstance();
trySetProperty(factory, XMLInputFactory.IS_NAMESPACE_AWARE, true);
trySetProperty(factory, XMLInputFactory.IS_VALIDATING, false);
trySetProperty(factory, XMLInputFactory.SUPPORT_DTD, false);
@ -46,7 +46,7 @@ public final class StaxHelper {
* Creates a new StAX XMLOutputFactory, with sensible defaults
*/
public static XMLOutputFactory newXMLOutputFactory() {
XMLOutputFactory factory = XMLOutputFactory.newFactory();
XMLOutputFactory factory = XMLOutputFactory.newInstance();
trySetProperty(factory, XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
return factory;
}
@ -55,7 +55,8 @@ public final class StaxHelper {
* Creates a new StAX XMLEventFactory, with sensible defaults
*/
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) {

View File

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

View File

@ -28,7 +28,6 @@ import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher;
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()}
* when finished with the package.
*
* This method is not thread-safe.
*
* @throws IOException
* If an IO exception occur during the saving process.
*/
@ -434,27 +435,20 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
return;
}
// Save the content
ReentrantReadWriteLock l = new ReentrantReadWriteLock();
try {
l.writeLock().lock();
if (this.originalPackagePath != null
&& !this.originalPackagePath.trim().isEmpty()) {
File targetFile = new File(this.originalPackagePath);
if (!targetFile.exists()
|| !(this.originalPackagePath
.equalsIgnoreCase(targetFile.getAbsolutePath()))) {
// Case of a package created from scratch
save(targetFile);
} else {
closeImpl();
}
} else if (this.output != null) {
save(this.output);
output.close();
if (this.originalPackagePath != null
&& !this.originalPackagePath.trim().isEmpty()) {
File targetFile = new File(this.originalPackagePath);
if (!targetFile.exists()
|| !(this.originalPackagePath
.equalsIgnoreCase(targetFile.getAbsolutePath()))) {
// Case of a package created from scratch
save(targetFile);
} else {
closeImpl();
}
} finally {
l.writeLock().unlock();
} else if (this.output != null) {
save(this.output);
output.close();
}
// Clear

View File

@ -21,8 +21,6 @@ import java.io.OutputStream;
import java.util.Optional;
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.opc.PackagePart;
@ -36,105 +34,109 @@ import org.w3c.dom.Element;
* Package properties marshaller.
*/
public class PackagePropertiesMarshaller implements PartMarshaller {
private final static Namespace namespaceDC, namespaceCoreProperties, namespaceDcTerms, namespaceXSI;
static {
final XMLEventFactory f = XMLEventFactory.newInstance();
namespaceDC = f.createNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI);
namespaceCoreProperties = f.createNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI);
namespaceDcTerms = f.createNamespace("dcterms", PackagePropertiesPart.NAMESPACE_DCTERMS_URI);
namespaceXSI = f.createNamespace("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
}
private final static NamespaceImpl namespaceDC =
new NamespaceImpl("dc", PackagePropertiesPart.NAMESPACE_DC_URI);
private final static NamespaceImpl namespaceCoreProperties =
new NamespaceImpl("cp", PackagePropertiesPart.NAMESPACE_CP_URI);;
private final static NamespaceImpl namespaceDcTerms =
new NamespaceImpl("dcterms", PackagePropertiesPart.NAMESPACE_DCTERMS_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";
protected static final String KEYWORD_CONTENT_STATUS = "contentStatus";
protected static final String KEYWORD_CONTENT_STATUS = "contentStatus";
protected static final String KEYWORD_CONTENT_TYPE = "contentType";
protected static final String KEYWORD_CONTENT_TYPE = "contentType";
protected static final String KEYWORD_CREATED = "created";
protected static final String KEYWORD_CREATED = "created";
protected static final String KEYWORD_CREATOR = "creator";
protected static final String KEYWORD_CREATOR = "creator";
protected static final String KEYWORD_DESCRIPTION = "description";
protected static final String KEYWORD_DESCRIPTION = "description";
protected static final String KEYWORD_IDENTIFIER = "identifier";
protected static final String KEYWORD_IDENTIFIER = "identifier";
protected static final String KEYWORD_KEYWORDS = "keywords";
protected static final String KEYWORD_KEYWORDS = "keywords";
protected static final String KEYWORD_LANGUAGE = "language";
protected static final String KEYWORD_LANGUAGE = "language";
protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy";
protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy";
protected static final String KEYWORD_LAST_PRINTED = "lastPrinted";
protected static final String KEYWORD_LAST_PRINTED = "lastPrinted";
protected static final String KEYWORD_MODIFIED = "modified";
protected static final String KEYWORD_MODIFIED = "modified";
protected static final String KEYWORD_REVISION = "revision";
protected static final String KEYWORD_REVISION = "revision";
protected static final String KEYWORD_SUBJECT = "subject";
protected static final String KEYWORD_SUBJECT = "subject";
protected static final String KEYWORD_TITLE = "title";
protected static final String KEYWORD_TITLE = "title";
protected static final String KEYWORD_VERSION = "version";
protected static final String KEYWORD_VERSION = "version";
PackagePropertiesPart propsPart;
PackagePropertiesPart propsPart;
// The document
Document xmlDoc;
// The document
Document xmlDoc;
/**
* Marshall package core properties to an XML document. Always return
* <code>true</code>.
*/
@Override
public boolean marshall(PackagePart part, OutputStream out)
throws OpenXML4JException {
if (!(part instanceof PackagePropertiesPart))
throw new IllegalArgumentException(
"'part' must be a PackagePropertiesPart instance.");
propsPart = (PackagePropertiesPart) part;
/**
* Marshall package core properties to an XML document. Always return
* <code>true</code>.
*/
@Override
public boolean marshall(PackagePart part, OutputStream out)
throws OpenXML4JException {
if (!(part instanceof PackagePropertiesPart))
throw new IllegalArgumentException(
"'part' must be a PackagePropertiesPart instance.");
propsPart = (PackagePropertiesPart) part;
// Configure the document
xmlDoc = DocumentHelper.createDocument();
// Configure the document
xmlDoc = DocumentHelper.createDocument();
Element rootElem = xmlDoc.createElementNS(namespaceCoreProperties.getNamespaceURI(),
getQName("coreProperties", namespaceCoreProperties));
DocumentHelper.addNamespaceDeclaration(rootElem, namespaceCoreProperties);
DocumentHelper.addNamespaceDeclaration(rootElem, namespaceDC);
DocumentHelper.addNamespaceDeclaration(rootElem, namespaceDcTerms);
DocumentHelper.addNamespaceDeclaration(rootElem, namespaceXSI);
DocumentHelper.addNamespaceDeclaration(rootElem,
namespaceCoreProperties.getPrefix(), namespaceCoreProperties.getNamespaceURI());
DocumentHelper.addNamespaceDeclaration(rootElem,
namespaceDC.getPrefix(), namespaceDC.getNamespaceURI());
DocumentHelper.addNamespaceDeclaration(rootElem,
namespaceDcTerms.getPrefix(), namespaceDcTerms.getNamespaceURI());
DocumentHelper.addNamespaceDeclaration(rootElem,
namespaceXSI.getPrefix(), namespaceXSI.getNamespaceURI());
xmlDoc.appendChild(rootElem);
addCategory();
addContentStatus();
addContentType();
addCreated();
addCreator();
addDescription();
addIdentifier();
addKeywords();
addLanguage();
addLastModifiedBy();
addLastPrinted();
addModified();
addRevision();
addSubject();
addTitle();
addVersion();
return true;
}
addCategory();
addContentStatus();
addContentType();
addCreated();
addCreator();
addDescription();
addIdentifier();
addKeywords();
addLanguage();
addLastModifiedBy();
addLastPrinted();
addModified();
addRevision();
addSubject();
addTitle();
addVersion();
return true;
}
/**
* 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));
}
private String getQName(String localName, Namespace namespace) {
private String getQName(String localName, NamespaceImpl namespace) {
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())
return null;
@ -149,7 +151,7 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
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);
if (element != null) {
element.setAttributeNS(namespaceXSI.getNamespaceURI(), getQName("type", namespaceXSI), xsiType);
@ -159,114 +161,129 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
/**
* Add category property element if needed.
*/
private void addCategory() {
* Add category property element if needed.
*/
private void addCategory() {
setElementTextContent(KEYWORD_CATEGORY, namespaceCoreProperties, propsPart.getCategoryProperty());
}
/**
* Add content status property element if needed.
*/
private void addContentStatus() {
setElementTextContent(KEYWORD_CONTENT_STATUS, namespaceCoreProperties, propsPart.getContentStatusProperty());
}
/**
* Add content type property element if needed.
*/
private void addContentType() {
setElementTextContent(KEYWORD_CONTENT_TYPE, namespaceCoreProperties, propsPart.getContentTypeProperty());
}
/**
* Add created property element if needed.
*/
private void addCreated() {
setElementTextContent(KEYWORD_CREATED, namespaceDcTerms, propsPart.getCreatedProperty(),
propsPart.getCreatedPropertyString(), "dcterms:W3CDTF");
}
/**
* Add creator property element if needed.
*/
private void addCreator() {
setElementTextContent(KEYWORD_CREATOR, namespaceDC, propsPart.getCreatorProperty());
}
/**
* Add description property element if needed.
*/
private void addDescription() {
setElementTextContent(KEYWORD_DESCRIPTION, namespaceDC, propsPart.getDescriptionProperty());
}
/**
* Add identifier property element if needed.
*/
private void addIdentifier() {
setElementTextContent(KEYWORD_IDENTIFIER, namespaceDC, propsPart.getIdentifierProperty());
}
}
/**
* Add keywords property element if needed.
*/
private void addKeywords() {
* Add content status property element if needed.
*/
private void addContentStatus() {
setElementTextContent(KEYWORD_CONTENT_STATUS, namespaceCoreProperties, propsPart.getContentStatusProperty());
}
/**
* Add content type property element if needed.
*/
private void addContentType() {
setElementTextContent(KEYWORD_CONTENT_TYPE, namespaceCoreProperties, propsPart.getContentTypeProperty());
}
/**
* Add created property element if needed.
*/
private void addCreated() {
setElementTextContent(KEYWORD_CREATED, namespaceDcTerms, propsPart.getCreatedProperty(),
propsPart.getCreatedPropertyString(), "dcterms:W3CDTF");
}
/**
* Add creator property element if needed.
*/
private void addCreator() {
setElementTextContent(KEYWORD_CREATOR, namespaceDC, propsPart.getCreatorProperty());
}
/**
* Add description property element if needed.
*/
private void addDescription() {
setElementTextContent(KEYWORD_DESCRIPTION, namespaceDC, propsPart.getDescriptionProperty());
}
/**
* Add identifier property element if needed.
*/
private void addIdentifier() {
setElementTextContent(KEYWORD_IDENTIFIER, namespaceDC, propsPart.getIdentifierProperty());
}
/**
* Add keywords property element if needed.
*/
private void addKeywords() {
setElementTextContent(KEYWORD_KEYWORDS, namespaceCoreProperties, propsPart.getKeywordsProperty());
}
}
/**
* Add language property element if needed.
*/
private void addLanguage() {
/**
* Add language property element if needed.
*/
private void addLanguage() {
setElementTextContent(KEYWORD_LANGUAGE, namespaceDC, propsPart.getLanguageProperty());
}
}
/**
* Add 'last modified by' property if needed.
*/
private void addLastModifiedBy() {
/**
* Add 'last modified by' property if needed.
*/
private void addLastModifiedBy() {
setElementTextContent(KEYWORD_LAST_MODIFIED_BY, namespaceCoreProperties, propsPart.getLastModifiedByProperty());
}
}
/**
* Add 'last printed' property if needed.
*
*/
private void addLastPrinted() {
/**
* Add 'last printed' property if needed.
*/
private void addLastPrinted() {
setElementTextContent(KEYWORD_LAST_PRINTED, namespaceCoreProperties, propsPart.getLastPrintedProperty(), propsPart.getLastPrintedPropertyString());
}
}
/**
* Add modified property element if needed.
*/
private void addModified() {
/**
* Add modified property element if needed.
*/
private void addModified() {
setElementTextContent(KEYWORD_MODIFIED, namespaceDcTerms, propsPart.getModifiedProperty(),
propsPart.getModifiedPropertyString(), "dcterms:W3CDTF");
}
/**
* Add revision property if needed.
*/
private void addRevision() {
/**
* Add revision property if needed.
*/
private void addRevision() {
setElementTextContent(KEYWORD_REVISION, namespaceCoreProperties, propsPart.getRevisionProperty());
}
}
/**
* Add subject property if needed.
*/
private void addSubject() {
/**
* Add subject property if needed.
*/
private void addSubject() {
setElementTextContent(KEYWORD_SUBJECT, namespaceDC, propsPart.getSubjectProperty());
}
}
/**
* Add title property if needed.
*/
private void addTitle() {
/**
* Add title property if needed.
*/
private void addTitle() {
setElementTextContent(KEYWORD_TITLE, namespaceDC, propsPart.getTitleProperty());
}
}
private void addVersion() {
private void addVersion() {
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;
import org.apache.poi.util.Removal;
/**
* An immutable object that could be defined as null.
*
* @author Julien Chable
* @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> {
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
* in the classpath:</p>
* <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>and slf4j-api (tested against 1.7.25)</li>
* </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,
Map<Long, XDDFValueAxis> values) {
this.chart = chart;
if (chart.getBarDir() == null) {
chart.addNewBarDir().setVal(BarDirection.BAR.underlying);
}
for (CTBarSer series : chart.getSerList()) {
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);
}
@ -94,6 +109,7 @@ public class XDDFBarChartData extends XDDFChartData {
XDDFNumericalDataSource<? extends Number> values) {
final int index = this.series.size();
final CTBarSer ctSer = this.chart.addNewSer();
ctSer.addNewTx();
ctSer.addNewCat();
ctSer.addNewVal();
ctSer.addNewIdx().setVal(index);
@ -119,7 +135,11 @@ public class XDDFBarChartData extends XDDFChartData {
@Override
protected CTSerTx getSeriesText() {
return series.getTx();
if (series.isSetTx()) {
return series.getTx();
} else {
return series.addNewTx();
}
}
@Override

View File

@ -79,6 +79,19 @@ public class XDDFCategoryAxis extends XDDFChartAxis {
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
public boolean isSetMinorUnit() {
return false;

View File

@ -23,4 +23,23 @@ import org.apache.poi.util.Beta;
@Beta
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.CTSurface;
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.ChartSpaceDocument;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
@ -214,6 +213,72 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
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
* formula.
@ -225,15 +290,7 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
if (!chart.isSetTitle()) {
return null;
}
CTTitle title = chart.getTitle();
if (!title.isSetTx()) {
return null;
}
CTTx tx = title.getTx();
if (!tx.isSetRich()) {
return null;
}
return new XDDFTextBody(this, tx.getRich());
return new XDDFTitle(this, chart.getTitle()).getBody();
}
@Override
@ -327,7 +384,7 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
private Map<Long, XDDFChartAxis> getCategoryAxes() {
CTPlotArea plotArea = getCTPlotArea();
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++) {
CTCatAx category = plotArea.getCatAxArray(i);
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
* title of sheet
* @param column
* column index
* @return return cell reference
* @since POI 4.0.0
*/
public CellReference setSheetTitle(String title) {
public CellReference setSheetTitle(String title, int column) {
XSSFSheet sheet = getSheet();
XSSFRow row = this.getRow(sheet, 0);
XSSFCell cell = this.getCell(row, 1);
XSSFCell cell = this.getCell(row, column);
cell.setCellValue(title);
this.updateSheetTable(sheet.getTables().get(0).getCTTable(), title, 1);
return new CellReference(sheet.getSheetName(), 0, 1, true, true);
this.updateSheetTable(sheet.getTables().get(0).getCTTable(), title, column);
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) {
CTTableColumns tableColumnList = ctTable.getTableColumns();
CTTableColumn column = null;
if (tableColumnList.getCount() >= index) {
column = tableColumnList.getTableColumnArray(index);
} else {
for( int i = 0; tableColumnList.getCount() < index; i++) {
column = tableColumnList.addNewTableColumn();
column.setId(index);
column.setId(i);
}
column = tableColumnList.getTableColumnArray(index);
column.setName(title);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -82,6 +82,19 @@ public class XDDFDateAxis extends XDDFChartAxis {
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
public boolean isSetMinorUnit() {
return ctDateAx.isSetMinorUnit();

View File

@ -38,6 +38,18 @@ public class XDDFLineChartData extends XDDFChartData {
for (CTLineSer series : chart.getSerList()) {
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);
}
@ -88,7 +100,11 @@ public class XDDFLineChartData extends XDDFChartData {
@Override
protected CTSerTx getSeriesText() {
return series.getTx();
if (series.isSetTx()) {
return series.getTx();
} else {
return series.addNewTx();
}
}
@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) {
if (size < 2 || 72 < size) {
throw new IllegalArgumentException("Minimum inclusive: 2; Maximum inclusive: 72");
}
CTMarker marker = getMarker();
if (marker.isSetSize()) {
marker.getSize().setVal(size);

View File

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

View File

@ -38,6 +38,18 @@ public class XDDFRadarChartData extends XDDFChartData {
for (CTRadarSer series : chart.getSerList()) {
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);
}
@ -92,7 +104,11 @@ public class XDDFRadarChartData extends XDDFChartData {
@Override
protected CTSerTx getSeriesText() {
return series.getTx();
if (series.isSetTx()) {
return series.getTx();
} else {
return series.addNewTx();
}
}
@Override

View File

@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.poi.util.Beta;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
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.CTScatterChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterSer;
@ -38,6 +39,18 @@ public class XDDFScatterChartData extends XDDFChartData {
for (CTScatterSer series : chart.getSerList()) {
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);
}
@ -96,7 +109,78 @@ public class XDDFScatterChartData extends XDDFChartData {
@Override
protected CTSerTx getSeriesText() {
return series.getTx();
if (series.isSetTx()) {
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

View File

@ -79,6 +79,19 @@ public class XDDFSeriesAxis extends XDDFChartAxis {
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
public boolean isSetMinorUnit() {
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);
}
/**
* @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
public boolean 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() {
if (props.isSetDefRPr()) {
return new XDDFRunProperties(props.getDefRPr());

View File

@ -70,6 +70,19 @@ public class XDDFTextBody {
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() {
return new XDDFTextParagraph(_body.addNewP(), this);
}

View File

@ -69,6 +69,24 @@ public class XDDFTextParagraph {
_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() {
@ -662,6 +680,13 @@ public class XDDFTextParagraph {
}
}
/**
* @since 4.0.1
*/
public XDDFRunProperties addDefaultRunProperties() {
return getOrCreateProperties().addDefaultRunProperties();
}
public XDDFRunProperties getDefaultRunProperties() {
if (_p.isSetPPr()) {
return getProperties().getDefaultRunProperties();

View File

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

View File

@ -77,7 +77,20 @@ public class XSLFBackground extends XSLFSimpleShape
public void setFillColor(Color color) {
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 (bgPr.isSetSolidFill()) {
bgPr.unsetSolidFill();

View File

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

View File

@ -153,7 +153,7 @@ public class XSLFColor {
colorRef = _phClr.getVal().toString();
}
// 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) {
color = toColor(ctColor, null);
}

View File

@ -692,10 +692,24 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
/**
* 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) {
removeRelation(pictureShape.getBlipId());
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());
}
}

View File

@ -98,7 +98,7 @@ public class StylesTable extends POIXMLDocumentPart implements Styles {
if (num < 0) {
throw new IllegalArgumentException("Maximum Number of Data Formats must be greater than or equal to 0");
} 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.");
}
}
@ -316,7 +316,7 @@ public class StylesTable extends POIXMLDocumentPart implements Styles {
short nextKey = (short) (numberFormats.lastKey() + 1);
if (nextKey < 0) {
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.");
}
formatIndex = (short) Math.max(nextKey, FIRST_USER_DEFINED_NUMBER_FORMAT_ID);

View File

@ -18,7 +18,9 @@
package org.apache.poi.xssf.usermodel;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.EnumMap;
import java.util.Map;
@ -33,11 +35,13 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
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.
* The actual styling is defined in presetTableStyles.xml
*/
public enum XSSFBuiltinTableStyle {
@ -329,16 +333,16 @@ public enum XSSFBuiltinTableStyle {
PivotStyleDark27,
/***/
PivotStyleDark28,
;
;
/**
* Interestingly, this is initialized after the enum instances, so using an {@link EnumMap} works.
*/
private static final Map<XSSFBuiltinTableStyle, TableStyle> styleMap = new EnumMap<>(XSSFBuiltinTableStyle.class);
private XSSFBuiltinTableStyle() {
}
/**
* @return built-in {@link TableStyle} definition
*/
@ -346,9 +350,10 @@ public enum XSSFBuiltinTableStyle {
init();
return styleMap.get(this);
}
/**
* NOTE: only checks by name, not definition.
*
* @param 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;
}
}
/**
* Only init once - thus the synchronized. Lazy, after creating instances,
* and only when a style is actually needed, to avoid overhead for uses
@ -370,8 +376,8 @@ public enum XSSFBuiltinTableStyle {
* during evaluation if desired.
*/
public static synchronized void init() {
if (! styleMap.isEmpty()) return;
if (!styleMap.isEmpty()) return;
/*
* initialize map. Every built-in has this format:
* <styleName>
@ -388,18 +394,18 @@ public enum XSSFBuiltinTableStyle {
final InputStream is = XSSFBuiltinTableStyle.class.getResourceAsStream("presetTableStyles.xml");
try {
final Document doc = DocumentHelper.readDocument(is);
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);
if (node.getNodeType() != Node.ELEMENT_NODE) continue; // only care about elements
final Element tag = (Element) node;
String styleName = tag.getTagName();
XSSFBuiltinTableStyle builtIn = XSSFBuiltinTableStyle.valueOf(styleName);
Node dxfsNode = tag.getElementsByTagName("dxfs").item(0);
Node tableStyleNode = tag.getElementsByTagName("tableStyles").item(0);
// hack because I can't figure out how to get XMLBeans to parse a sub-element in a standalone manner
// - build a fake styles.xml file with just this built-in
StylesTable styles = new StylesTable();
@ -413,28 +419,35 @@ public enum XSSFBuiltinTableStyle {
throw new RuntimeException(e);
}
}
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.
// add a dummy node to adjust properly.
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();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n")
.append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" "
+ "xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" "
+ "xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" "
+ "xmlns:x16r2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main\" "
+ "mc:Ignorable=\"x14ac x16r2\">\n");
sb.append(lsSerializer.writeToString(dxfsNode));
sb.append(lsSerializer.writeToString(tableStyleNode));
sb.append("</styleSheet>");
return sb.toString();
.append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" ")
.append("xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" ")
.append("xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" ")
.append("xmlns:x16r2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main\" ")
.append("mc:Ignorable=\"x14ac x16r2\">\n");
sb.append(writeToString(dxfsNode));
sb.append(writeToString(tableStyleNode));
sb.append("</styleSheet>");
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
*/
@ -451,7 +464,7 @@ public enum XSSFBuiltinTableStyle {
this.builtIn = builtIn;
this.style = style;
}
public String getName() {
return style.getName();
}
@ -463,10 +476,10 @@ public enum XSSFBuiltinTableStyle {
public boolean isBuiltin() {
return true;
}
public DifferentialStyleProvider getStyle(TableStyleType type) {
return style.getStyle(type);
}
}
}

View File

@ -491,10 +491,13 @@ public final class XSSFCell implements Cell {
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);
} else {
return f.getStringValue();
}
return f.getStringValue();
}
/**

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.CTTx;
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.NodeList;
import org.w3c.dom.Text;
@ -260,19 +256,6 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
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
* 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());
}
/**
* 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
*

View File

@ -18,7 +18,6 @@
package org.apache.poi.xssf.usermodel;
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.Units;
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());
}
/**
*
* @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) {
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
// 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());
CTClientData clientData = vmlShape.getClientDataArray(0);
clientData.setRowArray(0, new BigInteger(String.valueOf(ref.getRow())));
@ -70,7 +70,7 @@ public class XSSFComment implements Comment {
*/
@Override
public String getAuthor() {
return _comments.getAuthor((int) _comment.getAuthorId());
return _comments.getAuthor(_comment.getAuthorId());
}
/**
@ -80,9 +80,7 @@ public class XSSFComment implements Comment {
*/
@Override
public void setAuthor(String author) {
_comment.setAuthorId(
_comments.findAuthor(author)
);
_comment.setAuthorId(_comments.findAuthor(author));
}
/**

View File

@ -2262,8 +2262,8 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
}
}
private void unsetCollapsed(boolean collapsed, CTCol ci) {
if (collapsed) {
private void unsetCollapsed(Boolean collapsed, CTCol ci) {
if (collapsed != null && collapsed.booleanValue()) {
ci.setCollapsed(collapsed);
} else {
ci.unsetCollapsed();
@ -2410,7 +2410,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
boolean endHidden = false;
int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup(idx);
CTCol[] colArray = cols.getColArray();
if (endOfOutlineGroupIdx < colArray.length) {
if (endOfOutlineGroupIdx < (colArray.length - 1)) {
CTCol nextInfo = colArray[endOfOutlineGroupIdx + 1];
if (isAdjacentBefore(colArray[endOfOutlineGroupIdx], nextInfo)) {
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() + ".");
// FIXME: assumes row objects belong to non-null sheets and sheets belong to non-null workbooks.
} 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() + "). " +
"Got srcRows[" + index + "] from different workbook (" + curRow.getSheet().getWorkbook() + ").");
} 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
long nextColumnId = 1;
long nextColumnId = 0;
for (XSSFTableColumn tableColumn : getColumns()) {
if (columnName != null && columnName.equalsIgnoreCase(tableColumn.getName())) {
throw new IllegalArgumentException("Column '" + columnName
@ -291,6 +291,8 @@ public class XSSFTable extends POIXMLDocumentPart implements Table {
}
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
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
* 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"
* @since 3.17 beta 1
*/
@Deprecated
@Removal(version="4.2.0")
public void setCellReferences(AreaReference 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
* the right side of the table but will not modify any cell values.
*
* @param refs
* @param tableArea
* the new area of the table
* @throws IllegalArgumentException
* if the area is {@code null} or not

View File

@ -19,6 +19,10 @@
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.FormulaRenderer;
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.Sheet;
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.XSSFName;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
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
@ -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)}
* <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);
}
String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs);
if (!formula.equals(updatedFormula)) f.setStringValue(updatedFormula);
if (!formula.equals(updatedFormula)) {
f.setStringValue(updatedFormula);
}
}
}
}
@ -119,10 +143,12 @@ public final class XSSFFormulaUtils {
updatePtg(ptg, oldName, newName);
}
String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs);
if (!formula.equals(updatedFormula)) name.setRefersToFormula(updatedFormula);
if (!formula.equals(updatedFormula)) {
name.setRefersToFormula(updatedFormula);
}
}
}
private void updatePtg(Ptg ptg, String oldName, String newName) {
if (ptg instanceof Pxg) {
Pxg pxg = (Pxg)ptg;
@ -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;
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.IOException;
import java.lang.reflect.Field;
@ -26,29 +38,11 @@ import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.ArrayList;
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.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
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
*
@ -193,20 +187,37 @@ public final class OOXMLLite {
//see what classes from the ooxml-schemas.jar are loaded
System.out.println("Copying classes to " + _destDest);
Map<String, Class<?>> classes = getLoadedClasses(_ooxmlJar.getName());
for (Class<?> cls : classes.values()) {
String className = cls.getName();
String classRef = className.replace('.', '/') + ".class";
File destFile = new File(_destDest, classRef);
IOUtils.copy(cls.getResourceAsStream('/' + classRef), destFile);
Set<Class<?>> classes = getLoadedClasses(_ooxmlJar.getName());
Set<String> packages = new HashSet<>();
for (Class<?> cls : classes) {
copyFile(cls);
packages.add(cls.getPackage().getName());
if(cls.isInterface()){
if (cls.isInterface()) {
/// Copy classes and interfaces declared as members of this class
for(Class<?> fc : cls.getDeclaredClasses()){
className = fc.getName();
classRef = className.replace('.', '/') + ".class";
destFile = new File(_destDest, classRef);
IOUtils.copy(fc.getResourceAsStream('/' + classRef), destFile);
for (Class<?> fc : cls.getDeclaredClasses()) {
copyFile(fc);
}
}
}
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) {
for (Method m : testclass.getDeclaredMethods()) {
if(m.isAnnotationPresent(Test.class)) {
@ -293,10 +311,10 @@ public final class OOXMLLite {
/**
*
* @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")
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
// 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
@ -317,7 +335,7 @@ public final class OOXMLLite {
ClassLoader appLoader = ClassLoader.getSystemClassLoader();
try {
Vector<Class<?>> classes = (Vector<Class<?>>) _classes.get(appLoader);
Map<String, Class<?>> map = new HashMap<>();
Set<Class<?>> set = new HashSet<>();
for (Class<?> cls : classes) {
// e.g. proxy-classes, ...
ProtectionDomain pd = cls.getProtectionDomain();
@ -326,13 +344,13 @@ public final class OOXMLLite {
if (cs == null) continue;
URL loc = cs.getLocation();
if (loc == null) continue;
String jar = loc.toString();
if (jar.contains(ptrn)) {
map.put(cls.getName(), cls);
set.add(cls);
}
}
return map;
return set;
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}

View File

@ -37,8 +37,12 @@ public class TestDocumentHelper {
@Test
public void testDocumentBuilderFactory() throws Exception {
assertTrue(DocumentHelper.documentBuilderFactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
try {
assertTrue(DocumentHelper.documentBuilderFactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
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.xml.sax.InputSource;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.XMLReader;
public class TestSAXHelper {
@ -31,14 +32,18 @@ public class TestSAXHelper {
public void testXMLReader() throws Exception {
XMLReader reader = SAXHelper.newXMLReader();
assertNotSame(reader, SAXHelper.newXMLReader());
assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
assertEquals(SAXHelper.IGNORING_ENTITY_RESOLVER, reader.getEntityResolver());
assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
assertEquals("1", reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_SECURITY_MANAGER));
try {
assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
assertEquals(SAXHelper.IGNORING_ENTITY_RESOLVER, reader.getEntityResolver());
assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
assertEquals("1", reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
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"))));
}
}

View File

@ -907,7 +907,7 @@ public final class TestPackage {
getZipStatsAndConsume((max_size, min_ratio) -> {
// check max entry size ouf of bounds
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) {
continue;
}
// add zip entry header ~ 30 bytes
long size = ze.getSize()+30;
// add zip entry header ~ 128 bytes
long size = ze.getSize()+128;
double ratio = ze.getCompressedSize() / (double)size;
min_ratio = Math.min(min_ratio, ratio);
max_size = Math.max(max_size, size);

View File

@ -93,6 +93,87 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
public class TestXSLFBugs {
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
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);
series.replaceData(categoryData, valuesData);
final String title = "Apache POI";
series.setTitle(title, chart.setSheetTitle(title));
series.setTitle(title, chart.setSheetTitle(title, 0));
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.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@ -395,15 +396,21 @@ public final class TestXSSFTable {
assertEquals(2, table.getRowCount());
// add columns
table.createColumn("Column B");
table.createColumn("Column D");
table.createColumn("Column C", 2); // add between B and D
XSSFTableColumn c1 = table.getColumns().get(0);
XSSFTableColumn cB = table.createColumn("Column B");
XSSFTableColumn cD = table.createColumn("Column D");
XSSFTableColumn cC = table.createColumn("Column C", 2); // add between B and D
table.updateReferences();
table.updateHeaders();
assertEquals(4, table.getColumnCount());
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 B", table.getColumns().get(1).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 org.apache.poi.POIDataSamples;
import org.apache.poi.ooxml.POIXMLProperties;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ooxml.POIXMLProperties;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.ContentTypes;
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.LocaleUtil;
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.XSSFTestDataSamples;
import org.apache.poi.xssf.model.StylesTable;
@ -553,7 +555,9 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
Sheet sheet = wb.getSheetAt(0);
sheet.shiftRows(2, sheet.getLastRowNum(), 1, true, false);
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");
wb.cloneSheet(0);
@ -667,8 +671,8 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
XSSFWorkbook wb3 = XSSFTestDataSamples.writeOutAndReadBack(wb2);
assertNotNull(wb3);
sheet = wb3.getSheetAt(0);
row = sheet.getRow(2);
row = sheet.getRow(2);
assertEquals("test1", row.getCell(3).getStringCellValue());
assertEquals("test2", row.getCell(4).getStringCellValue());
wb3.close();
@ -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 boolean isEmpty(CharSequence cs) {
@ -1009,22 +1031,22 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
final String filename = "SampleSS.xlsx";
final File file = POIDataSamples.getSpreadSheetInstance().getFile(filename);
Workbook wb;
// Some tests commented out because close() modifies the file
// See bug 58779
// String
//wb = new XSSFWorkbook(file.getPath());
//assertCloseDoesNotModifyFile(filename, wb);
// File
//wb = new XSSFWorkbook(file);
//assertCloseDoesNotModifyFile(filename, wb);
// InputStream
wb = new XSSFWorkbook(new FileInputStream(file));
assertCloseDoesNotModifyFile(filename, wb);
// OPCPackage
//wb = new XSSFWorkbook(OPCPackage.open(file));
//assertCloseDoesNotModifyFile(filename, wb);
@ -1070,7 +1092,7 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
XSSFTable table2 = wb.getSheet("Foglio2").createTable();
table2.setName("Table2");
assertSame("Did not find Table2", table2, wb.getTable("Table2"));
// If table name is modified after getTable is called, the table can only be found by its new name
// This test makes sure that if any caching is done that getTable never uses a stale cache
table1.setName("Table1");

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
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
java.lang.String#toString()

View File

@ -187,7 +187,7 @@ public class TextSpecInfoRun {
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];
Object valO = flds[i+1];
if (!fld.isSet(mask)) continue;
@ -210,7 +210,8 @@ public class TextSpecInfoRun {
valid = false;
}
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);
}
@Override
protected void tearDown() throws Exception {
// TODO Auto-generated method stub
super.tearDown();
}
/**
* Check where values are the same
*/
@ -74,6 +68,17 @@ public class TestRandBetween extends TestCase {
assertEquals(-1, formulaCell.getNumericCellValue(), 0);
}
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

Binary file not shown.

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

Binary file not shown.