merged TRUNK changes r608809 into REL_3_0_2_BETA2

git-svn-id: https://svn.apache.org/repos/asf/poi/tags/REL_3_0_2_BETA2@608846 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2008-01-04 14:19:14 +00:00
parent 6b10a34fd8
commit 86aca7ed1c
81 changed files with 4408 additions and 199 deletions

160
build.xml
View File

@ -70,6 +70,7 @@ under the License.
<property name="main.output.dir" location="build/classes"/> <property name="main.output.dir" location="build/classes"/>
<property name="main.output.test.dir" location="build/test-classes"/> <property name="main.output.test.dir" location="build/test-classes"/>
<property name="main.lib" location="lib"/> <property name="main.lib" location="lib"/>
<property name="ooxml.lib" location="ooxml-lib"/>
<property name="main.reports.test" location="build/test-results"/> <property name="main.reports.test" location="build/test-results"/>
<property name="main.jar1.dir" location="${main.lib}/commons-logging-1.1.jar"/> <property name="main.jar1.dir" location="${main.lib}/commons-logging-1.1.jar"/>
<property name="main.jar1.url" value="${repository}/commons-logging/jars/commons-logging-1.1.jar"/> <property name="main.jar1.url" value="${repository}/commons-logging/jars/commons-logging-1.1.jar"/>
@ -77,6 +78,9 @@ under the License.
<property name="main.jar2.url" value="${repository}/log4j/jars/log4j-1.2.13.jar"/> <property name="main.jar2.url" value="${repository}/log4j/jars/log4j-1.2.13.jar"/>
<property name="main.testokfile" location="build/main-testokfile.txt"/> <property name="main.testokfile" location="build/main-testokfile.txt"/>
<property name="junit.jar1.dir" location="${main.lib}/junit-3.8.1.jar"/>
<property name="junit.jar1.url" value="${repository}/junit/jars/junit-3.8.1.jar"/>
<!-- Scratchpad: --> <!-- Scratchpad: -->
<property name="scratchpad.src" location="src/scratchpad/src"/> <property name="scratchpad.src" location="src/scratchpad/src"/>
<property name="scratchpad.src.test" location="src/scratchpad/testcases"/> <property name="scratchpad.src.test" location="src/scratchpad/testcases"/>
@ -116,8 +120,33 @@ under the License.
<property name="examples.jar3.url" value="${repository}/commons-lang/jars/commons-lang-2.1.jar"/> <property name="examples.jar3.url" value="${repository}/commons-lang/jars/commons-lang-2.1.jar"/>
<property name="examples.testokfile" location="build/examples-testokfile.txt"/> <property name="examples.testokfile" location="build/examples-testokfile.txt"/>
<property name="junit.jar1.dir" location="${main.lib}/junit-3.8.1.jar"/> <!-- Experimental OOXML support: -->
<property name="junit.jar1.url" value="${repository}/junit/jars/junit-3.8.1.jar"/> <property name="ooxml.src" location="src/scratchpad/ooxml-src"/>
<property name="ooxml.src.test" location="src/scratchpad/ooxml-testcases"/>
<property name="ooxml.reports.test" location="build/ooxml-test-results"/>
<property name="ooxml.output.dir" location="build/ooxml-classes"/>
<property name="ooxml.output.test.dir" location="build/ooxml-test-classes"/>
<property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/>
<property name="ooxml.jar1.dir" location="${ooxml.lib}/dom4j-1.6.1.jar"/>
<property name="ooxml.jar1.url" value="${repository}/dom4j/jars/dom4j-1.6.1.jar"/>
<property name="ooxml.jar2.dir" location="${ooxml.lib}/jaxen-1.1.jar"/>
<property name="ooxml.jar2.url" value="${repository}/jaxen/jars/jaxen-1.1.jar"/>
<property name="ooxml.jar3.dir" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/>
<property name="ooxml.jar3.url" value="${repository}/org.apache.xmlbeans/jars/xmlbeans-2.3.0.jar"/>
<property name="ooxml.jar4.dir" location="${ooxml.lib}/jsr173_1.0_api.jar"/>
<property name="ooxml.jar4.url" value="${repository}/xmlbeans/jars/jsr173_1.0_api.jar"/>
<!-- No official release of openxml4j yet -->
<property name="ooxml.jar5.dir" location="${ooxml.lib}/openxml4j-bin-prealpha-071224.jar"/>
<property name="ooxml.jar5.url" value="http://people.apache.org/~nick/openxml4j-bin-prealpha-071224.jar"/>
<!-- See http://www.ecma-international.org/publications/standards/Ecma-376.htm -->
<!-- "Copy these file(s), free of charge" -->
<property name="ooxml.xsds.ozip" location="${ooxml.lib}/OfficeOpenXML-Part4.zip"/>
<property name="ooxml.xsds.izip" location="${ooxml.lib}/OfficeOpenXML-XMLSchema.zip"/>
<property name="ooxml.xsds.url" value="http://www.ecma-international.org/publications/files/ECMA-ST/Office%20Open%20XML%20Part%204%20(DOCX).zip" />
<property name="ooxml.xsds.jar" location="${ooxml.lib}/ooxml-schemas.jar"/>
<property name="build.site" location="build/tmp/site/build/site"/> <property name="build.site" location="build/tmp/site/build/site"/>
<property name="build.site.src" location="build/tmp/site"/> <property name="build.site.src" location="build/tmp/site"/>
<property name="junit.report.dir" location="${build.site}/junit"/> <property name="junit.report.dir" location="${build.site}/junit"/>
@ -130,7 +159,7 @@ under the License.
<property name="mavendist.poi.dir" location="build/maven-dist/poi"/> <property name="mavendist.poi.dir" location="build/maven-dist/poi"/>
<property name="mavendist.oap.dir" location="build/maven-dist/org.apache.poi"/> <property name="mavendist.oap.dir" location="build/maven-dist/org.apache.poi"/>
<property name="jar.name" value="poi"/> <property name="jar.name" value="poi"/>
<property name="version.id" value="3.0.2-beta1"/> <property name="version.id" value="3.0.2-beta2"/>
<property name="halt.on.test.failure" value="true"/> <property name="halt.on.test.failure" value="true"/>
<property name="jdk.version.source" value="1.3" <property name="jdk.version.source" value="1.3"
description="JDK version of source code"/> description="JDK version of source code"/>
@ -162,6 +191,15 @@ under the License.
<pathelement location="${contrib.output.test.dir}"/> <pathelement location="${contrib.output.test.dir}"/>
</path> </path>
<path id="ooxml.classpath">
<path refid="main.classpath"/>
<path refid="scratchpad.classpath"/>
<fileset dir="${ooxml.lib}">
<include name="*.jar" />
</fileset>
</path>
<path id="examples.classpath"> <path id="examples.classpath">
<path refid="main.classpath"/> <path refid="main.classpath"/>
<pathelement location="${main.output.dir}"/> <pathelement location="${main.output.dir}"/>
@ -225,12 +263,15 @@ under the License.
<mkdir dir="${scratchpad.output.dir}"/> <mkdir dir="${scratchpad.output.dir}"/>
<mkdir dir="${contrib.output.dir}"/> <mkdir dir="${contrib.output.dir}"/>
<mkdir dir="${examples.output.dir}"/> <mkdir dir="${examples.output.dir}"/>
<mkdir dir="${ooxml.output.dir}"/>
<mkdir dir="${main.output.test.dir}"/> <mkdir dir="${main.output.test.dir}"/>
<mkdir dir="${contrib.output.test.dir}"/> <mkdir dir="${contrib.output.test.dir}"/>
<mkdir dir="${scratchpad.output.test.dir}"/> <mkdir dir="${scratchpad.output.test.dir}"/>
<mkdir dir="${ooxml.output.test.dir}"/>
<mkdir dir="${main.reports.test}"/> <mkdir dir="${main.reports.test}"/>
<mkdir dir="${scratchpad.reports.test}"/> <mkdir dir="${scratchpad.reports.test}"/>
<mkdir dir="${contrib.reports.test}"/> <mkdir dir="${contrib.reports.test}"/>
<mkdir dir="${ooxml.reports.test}"/>
<mkdir dir="${junit.report.dir}"/> <mkdir dir="${junit.report.dir}"/>
<mkdir dir="${jdepend.report.dir}"/> <mkdir dir="${jdepend.report.dir}"/>
<mkdir dir="${jdepend.report.out.dir}"/> <mkdir dir="${jdepend.report.out.dir}"/>
@ -281,6 +322,57 @@ under the License.
<get src="${junit.jar1.url}" dest="${junit.jar1.dir}"/> <get src="${junit.jar1.url}" dest="${junit.jar1.dir}"/>
</target> </target>
<target name="check-ooxml-xsds">
<condition property="ooxml-xsds.present">
<or>
<and>
<available file="${ooxml.xsds.izip}"/>
</and>
<isset property="disconnected"/>
</or>
</condition>
</target>
<target name="fetch-ooxml-xsds" unless="ooxml-xsds.present"
description="Fetches needed OOXML xsd files from the Internet">
<get src="${ooxml.xsds.url}" dest="${ooxml.xsds.ozip}"/>
<unzip src="${ooxml.xsds.ozip}" dest="${ooxml.lib}">
<patternset>
<include name="OfficeOpenXML-XMLSchema.zip" />
</patternset>
</unzip>
</target>
<target name="check-compiled-ooxml-xsds">
<condition property="ooxml-compiled-xsds.present">
<or>
<and>
<available file="${ooxml.xsds.jar}"/>
</and>
<isset property="disconnected"/>
</or>
</condition>
</target>
<target name="compile-ooxml-xsds" unless="ooxml-compiled-xsds.present"
depends="check-jars,fetch-jars,check-ooxml-xsds,fetch-ooxml-xsds,check-compiled-ooxml-xsds"
description="Unpacks the OOXML xsd files, and compiles them into XmlBeans">
<taskdef name="xmlbean"
classname="org.apache.xmlbeans.impl.tool.XMLBean"
classpath="${ooxml.jar3.dir}:${ooxml.jar4.dir}" />
<unzip src="${ooxml.xsds.izip}" dest="build/ooxml-xsds/" />
<!--
schema="build/ooxml-xsds/"
schema="build/ooxml-xsds/sml-workbook.xsd"
-->
<xmlbean
schema="build/ooxml-xsds/"
destfile="${ooxml.xsds.jar}"
javasource="1.4"
failonerror="false"
>
<classpath refid="ooxml.classpath"/>
</xmlbean>
</target>
<target name="compile" depends="init, compile-main, compile-scratchpad, <target name="compile" depends="init, compile-main, compile-scratchpad,
compile-contrib, compile-examples" compile-contrib, compile-examples"
description="Compiles the POI main classes, scratchpad, contrib, and examples"/> description="Compiles the POI main classes, scratchpad, contrib, and examples"/>
@ -305,7 +397,7 @@ under the License.
</javac> </javac>
</target> </target>
<target name="compile-scratchpad" depends="init"> <target name="compile-scratchpad" depends="init,compile-main">
<javac target="${jdk.version.class}" source="${jdk.version.source}" <javac target="${jdk.version.class}" source="${jdk.version.source}"
failonerror="true" destdir="${scratchpad.output.dir}" debug="on" failonerror="true" destdir="${scratchpad.output.dir}" debug="on"
fork="yes" srcdir="${scratchpad.src}"> fork="yes" srcdir="${scratchpad.src}">
@ -363,6 +455,14 @@ under the License.
</javac> </javac>
</target> </target>
<target name="compile-ooxml" depends="init, check-ooxml-xsds, fetch-ooxml-xsds, compile-ooxml-xsds, compile-main">
<!-- openxml4j requires java 1.5, so so must we, for now -->
<javac target="1.5" source="1.5"
destdir="${ooxml.output.dir}" debug="on" srcdir="${ooxml.src}">
<classpath refid="ooxml.classpath"/>
</javac>
</target>
<target name="test" depends="test-main,test-scratchpad,test-contrib" <target name="test" depends="test-main,test-scratchpad,test-contrib"
description="Tests main, contrib and scratchpad"/> description="Tests main, contrib and scratchpad"/>
@ -590,6 +690,43 @@ under the License.
<echo file="${contrib.testokfile}" append="false" message="testok"/> <echo file="${contrib.testokfile}" append="false" message="testok"/>
</target> </target>
<target name="-test-ooxml-check">
<uptodate property="ooxml.test.notRequired" targetfile="${ooxml.testokfile}">
<srcfiles dir="${ooxml.src}"/>
<srcfiles dir="${ooxml.src.test}"/>
</uptodate>
</target>
<target name="test-ooxml" depends="compile-main,compile-ooxml,-test-ooxml-check" unless="ooxml.test.notRequired">
<junit printsummary="yes" fork="no" haltonfailure="${halt.on.test.failure}" failureproperty="ooxml.test.failed">
<classpath>
<path refid="ooxml.classpath"/>
<pathelement location="${main.output.dir}"/>
<pathelement location="${ooxml.output.dir}"/>
<pathelement location="${ooxml.output.test.dir}"/>
<pathelement location="${junit.jar1.dir}"/>
</classpath>
<sysproperty key="HSSF.testdata.path" file="${main.src.test}/org/apache/poi/hssf/data"/>
<sysproperty key="HWPF.testdata.path" file="${scratchpad.src.test}/org/apache/poi/hwpf/data"/>
<sysproperty key="HSLF.testdata.path" file="${scratchpad.src.test}/org/apache/poi/hslf/data"/>
<sysproperty key="java.awt.headless" value="true"/>
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${ooxml.reports.test}">
<fileset dir="${ooxml.src.test}">
<include name="**/Test*.java"/>
<exclude name="**/AllTests.java"/>
</fileset>
</batchtest>
</junit>
<delete file="${ooxml.testokfile}"/>
<antcall target="-test-ooxml-write-testfile"/>
</target>
<target name="-test-ooxml-write-testfile" unless="ooxml.test.failed">
<echo file="${ooxml.testokfile}" append="false" message="testok"/>
</target>
<target name="-check-docs"> <target name="-check-docs">
<uptodate property="main.docs.notRequired" targetfile="${build.site}/index.html"> <uptodate property="main.docs.notRequired" targetfile="${build.site}/index.html">
<srcfiles dir="${build.site.src}"/> <srcfiles dir="${build.site.src}"/>
@ -976,6 +1113,21 @@ FORREST_HOME environment variable!</echo>
</manifest> </manifest>
</jar> </jar>
</target> </target>
<target name="jar-ooxml" depends="compile-ooxml" description="Creates the ooxml jar files for distribution">
<jar destfile="${dist.dir}/${jar.name}-ooxml-${version.id}-${DSTAMP}.jar">
<fileset dir="${ooxml.output.dir}" />
<fileset dir="legal/" />
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Specification-Title" value="Apache POI"/>
<attribute name="Specification-Version" value="${version.id}-${DSTAMP}"/>
<attribute name="Specification-Vendor" value="Apache"/>
<attribute name="Implementation-Title" value="Apache POI"/>
<attribute name="Implementation-Version" value="${version.id}-${DSTAMP}"/>
<attribute name="Implementation-Vendor" value="Apache"/>
</manifest>
</jar>
</target>
<target name="dist" depends="clean, fail-unless-tools-are-available, compile, site, jar" <target name="dist" depends="clean, fail-unless-tools-are-available, compile, site, jar"
description="Creates the entire distribution into build/dist, from scratch"> description="Creates the entire distribution into build/dist, from scratch">

View File

@ -77,8 +77,8 @@ under the License.
</license> </license>
</licenses> </licenses>
<scm> <scm>
<url>http://svn.apache.org/viewvc/jakarta/poi/trunk</url> <url>http://svn.apache.org/viewvc/poi/trunk</url>
<connection>scm:svn:http://svn.apache.org/repos/asf/jakarta/poi/trunk</connection> <connection>scm:svn:http://svn.apache.org/repos/asf/poi/trunk</connection>
</scm> </scm>
<issueManagement> <issueManagement>
<system>bugzilla</system> <system>bugzilla</system>

View File

@ -57,6 +57,7 @@
<menu-item label="History and Future" href="historyandfuture.html"/> <menu-item label="History and Future" href="historyandfuture.html"/>
<menu-item label="Who We Are" href="who.html"/> <menu-item label="Who We Are" href="who.html"/>
<menu-item label="Resolutions" href="resolutions/index.html"/> <menu-item label="Resolutions" href="resolutions/index.html"/>
<menu-item label="Sponsors" href="http://www.apache.org/foundation/thanks.html" />
</menu> </menu>
<menu label="Docs"> <menu label="Docs">

View File

@ -35,7 +35,18 @@
</devs> </devs>
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.0.2-FINAL" date="2007-??-??"> <release version="3.0.2-FINAL" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">Support for tables in HSLF</action>
<action dev="POI-DEVELOPERS" type="fix">43781 - Fix for extracting text from TextBoxes HSLF in</action>
<action dev="POI-DEVELOPERS" type="fix">Improve JavaDocs relating to hssf font and fill colourings</action>
<action dev="POI-DEVELOPERS" type="add">44095, 44097, 44099 - [PATCH] Support for Mid, Replace and Substitute excel functions</action>
<action dev="POI-DEVELOPERS" type="add">44055 - [PATCH] Support for getting the from field from HSMF messages</action>
<action dev="POI-DEVELOPERS" type="add">43551 - [PATCH] Support for 1904 date windowing in HSSF (previously only supported 1900 date windowing)</action>
<action dev="POI-DEVELOPERS" type="add">41064 - [PATCH] Support for String continue records</action>
<action dev="POI-DEVELOPERS" type="add">27511 - [PATCH] Support for data validation, via DVRecord and DVALRecord</action>
</release>
<release version="3.0.2-BETA1" date="2007-12-04">
<action dev="POI-DEVELOPERS" type="fix">43877 and 39512 - Fix for handling mixed OBJ and CONTINUE records.</action> <action dev="POI-DEVELOPERS" type="fix">43877 and 39512 - Fix for handling mixed OBJ and CONTINUE records.</action>
<action dev="POI-DEVELOPERS" type="fix">43807 - Throw an IllegalArgumentException if asked to create a merged region with invalid columns or rows, rather than writing out a corrupt file</action> <action dev="POI-DEVELOPERS" type="fix">43807 - Throw an IllegalArgumentException if asked to create a merged region with invalid columns or rows, rather than writing out a corrupt file</action>
<action dev="POI-DEVELOPERS" type="fix">43837 - [PATCH] Support for unicode NameRecords</action> <action dev="POI-DEVELOPERS" type="fix">43837 - [PATCH] Support for unicode NameRecords</action>

View File

@ -39,6 +39,7 @@
<li><link href="#Fill">How to work with slide/shape background</link></li> <li><link href="#Fill">How to work with slide/shape background</link></li>
<li><link href="#Bullets">How to create bulleted lists</link></li> <li><link href="#Bullets">How to create bulleted lists</link></li>
<li><link href="#Hyperlinks">Hyperlinks</link></li> <li><link href="#Hyperlinks">Hyperlinks</link></li>
<li><link href="#Tables">Tables</link></li>
</ul> </ul>
</section> </section>
<section><title>Features</title> <section><title>Features</title>
@ -387,6 +388,57 @@
} }
</source> </source>
</section> </section>
<anchor id="Tables"/>
<section><title>How to create tables</title>
<source>
//table data
String[][] data = {
{"INPUT FILE", "NUMBER OF RECORDS"},
{"Item File", "11,559"},
{"Vendor File", "300"},
{"Purchase History File", "10,000"},
{"Total # of requisitions", "10,200,038"}
};
SlideShow ppt = new SlideShow();
Slide slide = ppt.createSlide();
//create a table of 5 rows and 2 columns
Table table = new Table(5, 2);
for (int i = 0; i &lt; data.length; i++) {
for (int j = 0; j &lt; data[i].length; j++) {
TableCell cell = table.getCell(i, j);
cell.setText(data[i][j]);
RichTextRun rt = cell.getTextRun().getRichTextRuns()[0];
rt.setFontName("Arial");
rt.setFontSize(10);
cell.setVerticalAlignment(TextBox.AnchorMiddle);
cell.setHorizontalAlignment(TextBox.AlignCenter);
}
}
//set table borders
Line border = table.createBorder();
border.setLineColor(Color.black);
border.setLineWidth(1.0);
table.setAllBorders(border);
//set width of the 1st column
table.setColumnWidth(0, 300);
//set width of the 2nd column
table.setColumnWidth(1, 150);
slide.addShape(table);
table.moveTo(100, 100);
FileOutputStream out = new FileOutputStream("hslf-table.ppt");
ppt.write(out);
out.close();
</source>
</section>
</section> </section>
</section> </section>

View File

@ -63,6 +63,8 @@ HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
CellReference cellReference = new CellReference("B3"); CellReference cellReference = new CellReference("B3");
HSSFRow row = sheet.getRow(cellReference.getRow()); HSSFRow row = sheet.getRow(cellReference.getRow());
HSSFCell cell = row.getCell(cellReference.getCol()); HSSFCell cell = row.getCell(cellReference.getCol());
evaluator.setCurrentRow(row);
HSSFFormulaEvaluator.CellValue cellValue = evaluator.evaluate(cell); HSSFFormulaEvaluator.CellValue cellValue = evaluator.evaluate(cell);
switch (cellValue.getCellType()) { switch (cellValue.getCellType()) {
@ -106,7 +108,7 @@ HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
CellReference cellReference = new CellReference("B3"); CellReference cellReference = new CellReference("B3");
HSSFRow row = sheet.getRow(cellReference.getRow()); HSSFRow row = sheet.getRow(cellReference.getRow());
HSSFCell cell = row.getCell(cellReference.getCol()); HSSFCell cell = row.getCell(cellReference.getCol());
evaluator.setCurrentRow(row);
if (cell!=null) { if (cell!=null) {
switch (<strong>evaluator.evaluateInCell</strong>(cell).getCellType()) { switch (<strong>evaluator.evaluateInCell</strong>(cell).getCellType()) {

View File

@ -41,6 +41,7 @@
<li><link href="#CreateCells">How to create cells</link></li> <li><link href="#CreateCells">How to create cells</link></li>
<li><link href="#CreateDateCells">How to create date cells</link></li> <li><link href="#CreateDateCells">How to create date cells</link></li>
<li><link href="#CellTypes">Working with different types of cells</link></li> <li><link href="#CellTypes">Working with different types of cells</link></li>
<li><link href="#Iterator">Iterate over rows and cells</link></li>
<li><link href="#TextExtraction">Text Extraction</link></li> <li><link href="#TextExtraction">Text Extraction</link></li>
<li><link href="#Alignment">Aligning cells</link></li> <li><link href="#Alignment">Aligning cells</link></li>
<li><link href="#Borders">Working with borders</link></li> <li><link href="#Borders">Working with borders</link></li>
@ -234,6 +235,26 @@
fileOut.close(); fileOut.close();
</source> </source>
</section> </section>
<anchor id="Iterator"/>
<section><title>Iterate over rows and cells (including Java 5 foreach loops)</title>
<p>Sometimes, you'd like to just iterate over all the rows in
a sheet, or all the cells in a row. If you are using Java
5 or later, then this is especially handy, as it'll allow the
new foreach loop support to work.</p>
<p>Luckily, this is very easy. HSSFRow defines a
<em>CellIterator</em> inner class to handle iterating over
the cells (get one with a call to <em>row.cellIterator()</em>),
and HSSFSheet provides a <em>rowIterator()</em> method to
give an iterator over all the rows.</p>
<source>
HSSFSheet sheet = wb.getSheetAt(0);
for (HSSFRow row : sheet.rowIterator()) {
for (HSSFCell cell : row.cellIterator()) {
// Do something here
}
}
</source>
</section>
<anchor id="TextExtraction"/> <anchor id="TextExtraction"/>
<section><title>Text Extraction</title> <section><title>Text Extraction</title>
<p>For most text extraction requirements, the standard <p>For most text extraction requirements, the standard

View File

@ -31,6 +31,18 @@
</header> </header>
<body> <body>
<section><title>POI 3.0.2 BETA1 Release</title>
<p>The latest release of Apache POI is 3.0.2 BETA1 which was promoted to "Beta" on 04 December 2007. It contains a mixture of
new features and bug fixes, compared to 3.0.1. A full list of changes
is available in
<link href="./changes.html">the changelog</link>, and
<link href="http://www.apache.org/dyn/closer.cgi/poi/release/">download</link>
the source and binaries from your
<link href="http://www.apache.org/dyn/closer.cgi/poi/release/">local mirror</link>.
The release is also available from the central Maven repository under Group ID "org.apache.poi".
</p>
</section>
<section><title>POI 3.0.1 Release</title> <section><title>POI 3.0.1 Release</title>
<p>The latest release of Apache POI (formerly Apache Jakarta POI), <p>The latest release of Apache POI (formerly Apache Jakarta POI),
version 3.0.1, has now been released. It contains a mixture of version 3.0.1, has now been released. It contains a mixture of

View File

@ -32,7 +32,17 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.0.2-FINAL" date="2007-??-??"> <release version="3.0.2-FINAL" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">Support for tables in HSLF</action>
<action dev="POI-DEVELOPERS" type="fix">43781 - Fix for extracting text from TextBoxes HSLF in</action>
<action dev="POI-DEVELOPERS" type="fix">Improve JavaDocs relating to hssf font and fill colourings</action>
<action dev="POI-DEVELOPERS" type="add">44095, 44097, 44099 - [PATCH] Support for Mid, Replace and Substitute excel functions</action>
<action dev="POI-DEVELOPERS" type="add">44055 - [PATCH] Support for getting the from field from HSMF messages</action>
<action dev="POI-DEVELOPERS" type="add">43551 - [PATCH] Support for 1904 date windowing in HSSF (previously only supported 1900 date windowing)</action>
<action dev="POI-DEVELOPERS" type="add">41064 - [PATCH] Support for String continue records</action>
<action dev="POI-DEVELOPERS" type="add">27511 - [PATCH] Support for data validation, via DVRecord and DVALRecord</action>
</release>
<release version="3.0.2-BETA1" date="2007-12-04">
<action dev="POI-DEVELOPERS" type="fix">43877 - Fix for handling mixed OBJ and CONTINUE records</action> <action dev="POI-DEVELOPERS" type="fix">43877 - Fix for handling mixed OBJ and CONTINUE records</action>
<action dev="POI-DEVELOPERS" type="fix">39512 - Fix for handling mixed OBJ and CONTINUE records</action> <action dev="POI-DEVELOPERS" type="fix">39512 - Fix for handling mixed OBJ and CONTINUE records</action>
<action dev="POI-DEVELOPERS" type="fix">43837 - [PATCH] Support for unicode NameRecords</action> <action dev="POI-DEVELOPERS" type="fix">43837 - [PATCH] Support for unicode NameRecords</action>

View File

@ -0,0 +1,157 @@
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
/**
* Title: DVAL Record<P>
* Description: used in data validation ;
* This record is the list header of all data validation records in the current sheet.
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
* @version 2.0-pre
*/
public class DVALRecord extends Record
{
public final static short sid = 0x01B2;
//unknown field ; it's size should be 10
private short field_unknown = 0x0000;
//Object ID of the drop down arrow object for list boxes ;
//in our case this will be always FFFF , until
//MSODrawingGroup and MSODrawing records are implemented
private int field_cbo_id = 0xFFFFFFFF;
//Number of following DV records
//Default value is 1
private int field_3_dv_no = 0x00000000;
public DVALRecord()
{
}
/**
* Constructs a DVAL record and sets its fields appropriately.
*
* @param in the RecordInputstream to read the record from
*/
public DVALRecord(RecordInputStream in)
{
super(in);
}
protected void validateSid(short id)
{
if (id != sid)
{
throw new RecordFormatException("NOT A valid DVAL RECORD");
}
}
protected void fillFields(RecordInputStream in)
{
for ( int i=0; i<5; i++)
{
this.field_unknown = in.readShort();
}
this.field_cbo_id = in.readInt();
this.field_3_dv_no = in.readInt();
}
/**
* set the object ID of the drop down arrow object for list boxes
* @param cboID - Object ID
*/
public void setObjectID(int cboID)
{
this.field_cbo_id = cboID;
}
/**
* Set the number of following DV records
* @param dvNo - the DV records number
*/
public void setDVRecNo(int dvNo)
{
this.field_3_dv_no = dvNo;
}
/**
* get Object ID of the drop down arrow object for list boxes
*/
public int getObjectID( )
{
return this.field_cbo_id;
}
/**
* Get number of following DV records
*/
public int getDVRecNo( )
{
return this.field_3_dv_no;
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("[DVAL]\n");
buffer.append(" .comboObjectID = ").append(Integer.toHexString(this.getObjectID())).append("\n");
buffer.append(" .DVRecordsNumber = ").append(Integer.toHexString(this.getDVRecNo())).append("\n");
buffer.append("[/DVAL]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, 0 + offset, this.sid);
LittleEndian.putShort(data, 2 + offset, ( short)(this.getRecordSize()-4));
for ( int i=0; i<5; i++)
{
LittleEndian.putShort(data, 4 + i*2 + offset, (short)this.field_unknown);
}
LittleEndian.putInt(data, 14 + offset, this.getObjectID());
LittleEndian.putInt(data, 18 + offset, this.getDVRecNo());
return getRecordSize();
}
//with 4 bytes header
public int getRecordSize()
{
return 22;
}
public short getSid()
{
return this.sid;
}
public Object clone()
{
DVALRecord rec = new DVALRecord();
rec.field_unknown = this.field_unknown;
rec.field_cbo_id = this.field_cbo_id;
rec.field_3_dv_no = this.field_3_dv_no;
return rec;
}
}

View File

@ -0,0 +1,590 @@
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import org.apache.poi.util.BitField;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
import org.apache.poi.hssf.util.HSSFCellRangeAddress;
import org.apache.poi.hssf.record.formula.Ptg;
import java.io.IOException;
import java.util.Stack;
import java.util.Hashtable;
import java.util.Enumeration;
/**
* Title: DV Record<P>
* Description: This record stores data validation settings and a list of cell ranges
* which contain these settings. The data validation settings of a sheet
* are stored in a sequential list of DV records. This list is followed by
* DVAL record(s)
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
* @version 2.0-pre
*/
public class DVRecord extends Record
{
public final static short sid = 0x01BE;
/**
* Option flags
*/
private int field_option_flags;
/**
* Title of the prompt box
*/
private String field_title_prompt;
/**
* Title of the error box
*/
private String field_title_error;
/**
* Text of the prompt box
*/
private String field_text_prompt;
/**
* Text of the error box
*/
private String field_text_error;
/**
* Size of the formula data for first condition
*/
private short field_size_first_formula;
/**
* Not used
*/
private short field_not_used_1 = 0x3FE0;
/**
* Formula data for first condition (RPN token array without size field)
*/
private Stack field_rpn_token_1 ;
/**
* Size of the formula data for second condition
*/
private short field_size_sec_formula;
/**
* Not used
*/
private short field_not_used_2 = 0x0000;
/**
* Formula data for second condition (RPN token array without size field)
*/
private Stack field_rpn_token_2 ;
/**
* Cell range address list with all affected ranges
*/
private HSSFCellRangeAddress field_regions;
public static final Integer STRING_PROMPT_TITLE = new Integer(0);
public static final Integer STRING_ERROR_TITLE = new Integer(1);
public static final Integer STRING_PROMPT_TEXT = new Integer(2);
public static final Integer STRING_ERROR_TEXT = new Integer(3);
private Hashtable _hash_strings ;
/**
* Option flags field
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
private BitField opt_data_type = new BitField(0x0000000F);
private BitField opt_error_style = new BitField(0x00000070);
private BitField opt_string_list_formula = new BitField(0x00000080);
private BitField opt_empty_cell_allowed = new BitField(0x00000100);
private BitField opt_surppres_dropdown_arrow = new BitField(0x00000200);
private BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000);
private BitField opt_show_error_on_invalid_value = new BitField(0x00080000);
private BitField opt_condition_operator = new BitField(0x00F00000);
public DVRecord()
{
}
/**
* Constructs a DV record and sets its fields appropriately.
*
* @param in the RecordInputstream to read the record from
*/
public DVRecord(RecordInputStream in)
{
super(in);
}
protected void validateSid(short id)
{
if (id != sid)
{
throw new RecordFormatException("NOT a valid DV RECORD");
}
}
protected void fillFields(RecordInputStream in)
{
field_rpn_token_1 = new Stack();
field_rpn_token_2 = new Stack();
this.field_option_flags = in.readInt();
this._hash_strings = new Hashtable(4);
StringHandler strHandler_prompt_title = new StringHandler( in );
this.field_title_prompt = strHandler_prompt_title.getStringData();
this._hash_strings.put(DVRecord.STRING_PROMPT_TITLE, strHandler_prompt_title);
StringHandler strHandler_error_title = new StringHandler( in );
this.field_title_error = strHandler_error_title.getStringData();
this._hash_strings.put(DVRecord.STRING_ERROR_TITLE, strHandler_error_title);
StringHandler strHandler_prompt_text = new StringHandler( in );
this.field_text_prompt = strHandler_prompt_text.getStringData();
this._hash_strings.put(DVRecord.STRING_PROMPT_TEXT, strHandler_prompt_text);
StringHandler strHandler_error_text = new StringHandler( in );
this.field_text_error = strHandler_error_text.getStringData();
this._hash_strings.put(DVRecord.STRING_ERROR_TEXT, strHandler_error_text);
this.field_size_first_formula = in.readShort();
this.field_not_used_1 = in.readShort();
//read first formula data condition
// Not sure if this was needed or not...
// try {
// in.skip(this.field_size_first_formula);
// } catch(IOException e) { throw new IllegalStateException(e); }
int token_pos = 0;
while (token_pos < this.field_size_first_formula)
{
Ptg ptg = Ptg.createPtg(in);
token_pos += ptg.getSize();
field_rpn_token_1.push(ptg);
}
this.field_size_sec_formula = in.readShort();
this.field_not_used_2 = in.readShort();
//read sec formula data condition
// Not sure if this was needed or not...
try {
in.skip(this.field_size_sec_formula);
} catch(IOException e) { throw new IllegalStateException(e); }
token_pos = 0;
while (token_pos < this.field_size_sec_formula)
{
Ptg ptg = Ptg.createPtg(in);
token_pos += ptg.getSize();
field_rpn_token_2.push(ptg);
}
//read cell range address list with all affected ranges
this.field_regions = new HSSFCellRangeAddress(in);
}
// --> start option flags
/**
* set the condition data type
* @param type - condition data type
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public void setDataType(int type)
{
this.field_option_flags = this.opt_data_type.setValue(this.field_option_flags, type);
}
/**
* get the condition data type
* @return the condition data type
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public int getDataType()
{
return this.opt_data_type.getValue(this.field_option_flags);
}
/**
* set the condition error style
* @param type - condition error style
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public void setErrorStyle(int style)
{
this.field_option_flags = this.opt_error_style.setValue(this.field_option_flags, style);
}
/**
* get the condition error style
* @return the condition error style
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public int getErrorStyle()
{
return this.opt_error_style.getValue(this.field_option_flags);
}
/**
* set if in list validations the string list is explicitly given in the formula
* @param type - true if in list validations the string list is explicitly given in the formula; false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public void setListExplicitFormula(boolean explicit)
{
this.field_option_flags = this.opt_string_list_formula.setBoolean(this.field_option_flags, explicit);
}
/**
* return true if in list validations the string list is explicitly given in the formula, false otherwise
* @return true if in list validations the string list is explicitly given in the formula, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public boolean getListExplicitFormula()
{
return (this.opt_string_list_formula.isSet(this.field_option_flags));
}
/**
* set if empty values are allowed in cells
* @param type - true if empty values are allowed in cells, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public void setEmptyCellAllowed(boolean allowed)
{
this.field_option_flags = this.opt_empty_cell_allowed.setBoolean(this.field_option_flags, allowed);
}
/**
* return true if empty values are allowed in cells, false otherwise
* @return if empty values are allowed in cells, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public boolean getEmptyCellAllowed()
{
return (this.opt_empty_cell_allowed.isSet(this.field_option_flags));
}
/**
* set if drop down arrow should be surppressed when list validation is used
* @param type - true if drop down arrow should be surppressed when list validation is used, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public void setSurppresDropdownArrow(boolean surppress)
{
this.field_option_flags = this.opt_surppres_dropdown_arrow.setBoolean(this.field_option_flags, surppress);
}
/**
* return true if drop down arrow should be surppressed when list validation is used, false otherwise
* @return if drop down arrow should be surppressed when list validation is used, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public boolean getSurppresDropdownArrow()
{
return (this.opt_surppres_dropdown_arrow.isSet(this.field_option_flags));
}
/**
* set if a prompt window should appear when cell is selected
* @param type - true if a prompt window should appear when cell is selected, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public void setShowPromptOnCellSelected(boolean show)
{
this.field_option_flags = this.opt_show_prompt_on_cell_selected.setBoolean(this.field_option_flags, show);
}
/**
* return true if a prompt window should appear when cell is selected, false otherwise
* @return if a prompt window should appear when cell is selected, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public boolean getShowPromptOnCellSelected()
{
return (this.opt_show_prompt_on_cell_selected.isSet(this.field_option_flags));
}
/**
* set if an error window should appear when an invalid value is entered in the cell
* @param type - true if an error window should appear when an invalid value is entered in the cell, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public void setShowErrorOnInvalidValue(boolean show)
{
this.field_option_flags = this.opt_show_error_on_invalid_value.setBoolean(this.field_option_flags, show);
}
/**
* return true if an error window should appear when an invalid value is entered in the cell, false otherwise
* @return if an error window should appear when an invalid value is entered in the cell, false otherwise
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public boolean getShowErrorOnInvalidValue()
{
return (this.opt_show_error_on_invalid_value.isSet(this.field_option_flags));
}
/**
* set the condition operator
* @param type - condition operator
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public void setConditionOperator(int operator)
{
this.field_option_flags = this.opt_condition_operator.setValue(this.field_option_flags, operator);
}
/**
* get the condition operator
* @return the condition operator
* @see org.apache.poi.hssf.util.HSSFDataValidation utility class
*/
public int getConditionOperator()
{
return this.opt_condition_operator.getValue(this.field_option_flags);
}
// <-- end option flags
public void setFirstFormulaRPN( Stack rpn )
{
this.field_rpn_token_1 = rpn;
}
public void setFirstFormulaSize( short size )
{
this.field_size_first_formula = size;
}
public void setSecFormulaRPN( Stack rpn )
{
this.field_rpn_token_2 = rpn;
}
public void setSecFormulaSize( short size )
{
this.field_size_sec_formula = size;
}
public void setStringField( Integer type, String str_data )
{
if ( this._hash_strings == null )
{
this._hash_strings = new Hashtable();
}
StringHandler strHandler = new StringHandler();
if ( str_data == null )
{
str_data = "";
}
else
{
strHandler.setStringLength(str_data.length());
}
strHandler.setStringData(str_data);
strHandler.setUnicodeFlag((byte)0x00);
this._hash_strings.put( type, strHandler);
}
public String getStringField( Integer type )
{
return ((StringHandler)this._hash_strings.get(type)).getStringData();
}
public void setCellRangeAddress( HSSFCellRangeAddress range )
{
this.field_regions = range;
}
public HSSFCellRangeAddress getCellRangeAddress( )
{
return this.field_regions;
}
/**
* gets the option flags field.
* @return options - the option flags field
*/
public int getOptionFlags()
{
return this.field_option_flags;
}
public String toString()
{
/** @todo DVRecord string representation */
StringBuffer buffer = new StringBuffer();
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
int size = this.getRecordSize();
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, ( short ) (size-4));
int pos = 4;
LittleEndian.putInt(data, pos + offset, this.getOptionFlags());
pos += 4;
pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_PROMPT_TITLE )).serialize(pos+offset, data);
pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_ERROR_TITLE )).serialize(pos+offset, data);
pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_PROMPT_TEXT )).serialize(pos+offset, data);
pos += ((StringHandler)this._hash_strings.get( DVRecord.STRING_ERROR_TEXT )).serialize(pos+offset, data);
LittleEndian.putShort(data, offset+pos, this.field_size_first_formula);
pos += 2;
LittleEndian.putShort(data, offset+pos, this.field_not_used_1);
pos += 2;
for (int k = 0; k < this.field_rpn_token_1.size(); k++)
{
Ptg ptg = ( Ptg ) this.field_rpn_token_1.get(k);
ptg.writeBytes(data, pos+offset);
pos += ptg.getSize();
}
LittleEndian.putShort(data, offset+pos, this.field_size_sec_formula);
pos += 2;
LittleEndian.putShort(data, offset+pos, this.field_not_used_2);
pos += 2;
if ( this.field_size_sec_formula > 0 )
{
for (int k = 0; k < this.field_rpn_token_2.size(); k++)
{
Ptg ptg = ( Ptg ) this.field_rpn_token_2.get(k);
ptg.writeBytes(data, pos+offset);
pos += ptg.getSize();
}
}
this.field_regions.serialize(pos+offset, data);
return size;
}
public int getRecordSize()
{
int size = 4+4+2+2+2+2;//header+options_field+first_formula_size+first_unused+sec_formula_size+sec+unused;
if ( this._hash_strings != null )
{
Enumeration enum_keys = this._hash_strings.keys();
while ( enum_keys.hasMoreElements() )
{
size += ((StringHandler)this._hash_strings.get( (Integer)enum_keys.nextElement() )).getSize();
}
}
size += this.field_size_first_formula+ this.field_size_sec_formula;
size += this.field_regions.getSize();
return size;
}
public short getSid()
{
return this.sid;
}
/**@todo DVRecord = Serializare */
private class StringHandler
{
private int _string_length = 0x0001;
private byte _string_unicode_flag = 0x00;
private String _string_data = "0x00";
private int _start_offset;
private int _end_offset;
StringHandler()
{
}
StringHandler(RecordInputStream in)
{
this.fillFields(in);
}
protected void fillFields(RecordInputStream in)
{
this._string_length = in.readUShort();
this._string_unicode_flag = in.readByte();
if (this._string_unicode_flag == 1)
{
this._string_data = in.readUnicodeLEString(this._string_length);
}
else
{
this._string_data = in.readCompressedUnicode(this._string_length);
}
}
private void setStringData( String string_data )
{
this._string_data = string_data;
}
private String getStringData()
{
return this._string_data;
}
private int getEndOffset()
{
return this._end_offset;
}
public int serialize( int offset, byte[] data )
{
LittleEndian.putUShort(data, offset, this._string_length );
data[2 + offset] = this._string_unicode_flag;
if (this._string_unicode_flag == 1)
{
StringUtil.putUnicodeLE(this._string_data, data, 3 + offset);
}
else
{
StringUtil.putCompressedUnicode(this._string_data, data, 3 + offset);
}
return getSize();
}
private void setUnicodeFlag( byte flag )
{
this._string_unicode_flag = flag;
}
private void setStringLength( int len )
{
this._string_length = len;
}
private int getStringByteLength()
{
return (this._string_unicode_flag == 1) ? this._string_length * 2 : this._string_length;
}
public int getSize()
{
return 2 + 1 + getStringByteLength();
}
}
}

View File

@ -75,7 +75,8 @@ public class RecordFactory
HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class, HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class,
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class, WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class, NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class,
FileSharingRecord.class, ChartTitleFormatRecord.class FileSharingRecord.class, ChartTitleFormatRecord.class,
DVRecord.class, DVALRecord.class
}; };
} }
private static Map recordsMap = recordsToMap(records); private static Map recordsMap = recordsToMap(records);
@ -146,6 +147,9 @@ public class RecordFactory
} else if (record.getSid() == ContinueRecord.sid && } else if (record.getSid() == ContinueRecord.sid &&
(lastRecord instanceof DrawingGroupRecord)) { (lastRecord instanceof DrawingGroupRecord)) {
((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData()); ((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
} else if (record.getSid() == ContinueRecord.sid &&
(lastRecord instanceof StringRecord)) {
((StringRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
} else if (record.getSid() == ContinueRecord.sid) { } else if (record.getSid() == ContinueRecord.sid) {
if (lastRecord instanceof UnknownRecord) { if (lastRecord instanceof UnknownRecord) {
//Gracefully handle records that we dont know about, //Gracefully handle records that we dont know about,

View File

@ -84,6 +84,14 @@ public class StringRecord
} }
} }
public void processContinueRecord(byte[] data) {
if(isUnCompressedUnicode()) {
field_3_string += StringUtil.getFromUnicodeLE(data, 0, field_1_string_length - field_3_string.length());
} else {
field_3_string += StringUtil.getFromCompressedUnicode(data, 0, field_1_string_length - field_3_string.length());
}
}
public boolean isInValueSection() public boolean isInValueSection()
{ {
return true; return true;

View File

@ -521,7 +521,7 @@ public class HSSFCell
*/ */
public void setCellValue(Date value) public void setCellValue(Date value)
{ {
setCellValue(HSSFDateUtil.getExcelDate(value)); setCellValue(HSSFDateUtil.getExcelDate(value, this.book.isUsing1904DateWindowing()));
} }
/** /**

View File

@ -294,11 +294,25 @@ public class HSSFCellStyle
format.setFontIndex(fontindex); format.setFontIndex(fontindex);
} }
/**
* gets the index of the font for this style
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getFontAt(short)
*/
public short getFontIndex() public short getFontIndex()
{ {
return format.getFontIndex(); return format.getFontIndex();
} }
/**
* gets the font for this style
* @param parentWorkbook The HSSFWorkbook that this style belongs to
* @see org.apache.poi.hssf.usermodel.HSSFCellStyle#getFontIndex()
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getFontAt(short)
*/
public HSSFFont getFont(HSSFWorkbook parentWorkbook) {
return parentWorkbook.getFontAt(getFontIndex());
}
/** /**
* set the cell's using this style to be hidden * set the cell's using this style to be hidden
* @param hidden - whether the cell using this style should be hidden * @param hidden - whether the cell using this style should be hidden
@ -689,7 +703,6 @@ public class HSSFCellStyle
* @see #BORDER_MEDIUM_DASH_DOT_DOT * @see #BORDER_MEDIUM_DASH_DOT_DOT
* @see #BORDER_SLANTED_DASH_DOT * @see #BORDER_SLANTED_DASH_DOT
*/ */
public short getBorderBottom() public short getBorderBottom()
{ {
return format.getBorderBottom(); return format.getBorderBottom();
@ -697,9 +710,8 @@ public class HSSFCellStyle
/** /**
* set the color to use for the left border * set the color to use for the left border
* @param color * @param color The index of the color definition
*/ */
public void setLeftBorderColor(short color) public void setLeftBorderColor(short color)
{ {
format.setLeftBorderPaletteIdx(color); format.setLeftBorderPaletteIdx(color);
@ -707,9 +719,9 @@ public class HSSFCellStyle
/** /**
* get the color to use for the left border * get the color to use for the left border
* @return color * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/ */
public short getLeftBorderColor() public short getLeftBorderColor()
{ {
return format.getLeftBorderPaletteIdx(); return format.getLeftBorderPaletteIdx();
@ -717,9 +729,8 @@ public class HSSFCellStyle
/** /**
* set the color to use for the right border * set the color to use for the right border
* @param color * @param color The index of the color definition
*/ */
public void setRightBorderColor(short color) public void setRightBorderColor(short color)
{ {
format.setRightBorderPaletteIdx(color); format.setRightBorderPaletteIdx(color);
@ -727,9 +738,9 @@ public class HSSFCellStyle
/** /**
* get the color to use for the left border * get the color to use for the left border
* @return color * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/ */
public short getRightBorderColor() public short getRightBorderColor()
{ {
return format.getRightBorderPaletteIdx(); return format.getRightBorderPaletteIdx();
@ -737,9 +748,8 @@ public class HSSFCellStyle
/** /**
* set the color to use for the top border * set the color to use for the top border
* @param color * @param color The index of the color definition
*/ */
public void setTopBorderColor(short color) public void setTopBorderColor(short color)
{ {
format.setTopBorderPaletteIdx(color); format.setTopBorderPaletteIdx(color);
@ -747,9 +757,9 @@ public class HSSFCellStyle
/** /**
* get the color to use for the top border * get the color to use for the top border
* @return color * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/ */
public short getTopBorderColor() public short getTopBorderColor()
{ {
return format.getTopBorderPaletteIdx(); return format.getTopBorderPaletteIdx();
@ -757,9 +767,8 @@ public class HSSFCellStyle
/** /**
* set the color to use for the bottom border * set the color to use for the bottom border
* @param color * @param color The index of the color definition
*/ */
public void setBottomBorderColor(short color) public void setBottomBorderColor(short color)
{ {
format.setBottomBorderPaletteIdx(color); format.setBottomBorderPaletteIdx(color);
@ -767,9 +776,9 @@ public class HSSFCellStyle
/** /**
* get the color to use for the left border * get the color to use for the left border
* @return color * @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @param color The index of the color definition
*/ */
public short getBottomBorderColor() public short getBottomBorderColor()
{ {
return format.getBottomBorderPaletteIdx(); return format.getBottomBorderPaletteIdx();
@ -871,9 +880,9 @@ public class HSSFCellStyle
/** /**
* get the background fill color * get the background fill color
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @return fill color * @return fill color
*/ */
public short getFillBackgroundColor() public short getFillBackgroundColor()
{ {
short result = format.getFillBackground(); short result = format.getFillBackground();
@ -889,7 +898,6 @@ public class HSSFCellStyle
* <i>Note: Ensure Foreground color is set prior to background color.</i> * <i>Note: Ensure Foreground color is set prior to background color.</i>
* @param bg color * @param bg color
*/ */
public void setFillForegroundColor(short bg) public void setFillForegroundColor(short bg)
{ {
format.setFillForeground(bg); format.setFillForeground(bg);
@ -898,12 +906,11 @@ public class HSSFCellStyle
/** /**
* get the foreground fill color * get the foreground fill color
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
* @return fill color * @return fill color
*/ */
public short getFillForegroundColor() public short getFillForegroundColor()
{ {
return format.getFillForeground(); return format.getFillForeground();
} }
} }

View File

@ -82,8 +82,8 @@ public class HSSFClientAnchor
*/ */
public float getAnchorHeightInPoints(HSSFSheet sheet ) public float getAnchorHeightInPoints(HSSFSheet sheet )
{ {
int y1 = Math.min( getDy1(), getDy2() ); int y1 = getDy1();
int y2 = Math.max( getDy1(), getDy2() ); int y2 = getDy2();
int row1 = Math.min( getRow1(), getRow2() ); int row1 = Math.min( getRow1(), getRow2() );
int row2 = Math.max( getRow1(), getRow2() ); int row2 = Math.max( getRow1(), getRow2() );

View File

@ -35,6 +35,8 @@ import java.util.GregorianCalendar;
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
* @author Dan Sherman (dsherman at isisph.com) * @author Dan Sherman (dsherman at isisph.com)
* @author Hack Kampbjorn (hak at 2mba.dk) * @author Hack Kampbjorn (hak at 2mba.dk)
* @author Alex Jacoby (ajacoby at gmail.com)
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
*/ */
public class HSSFDateUtil public class HSSFDateUtil
@ -54,19 +56,26 @@ public class HSSFDateUtil
* @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1) * @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1)
* @param date the Date * @param date the Date
*/ */
public static double getExcelDate(Date date) {
public static double getExcelDate(Date date) return getExcelDate(date, false);
{ }
/**
* Given a Date, converts it into a double representing its internal Excel representation,
* which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
*
* @return Excel representation of Date (-1 if error - test for error by checking for less than 0.1)
* @param date the Date
* @param use1904windowing Should 1900 or 1904 date windowing be used?
*/
public static double getExcelDate(Date date, boolean use1904windowing) {
Calendar calStart = new GregorianCalendar(); Calendar calStart = new GregorianCalendar();
calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0
calStart.setTime( if ((!use1904windowing && calStart.get(Calendar.YEAR) < 1900) ||
date); // If date includes hours, minutes, and seconds, set them to 0 (use1904windowing && calStart.get(Calendar.YEAR) < 1904))
if (calStart.get(Calendar.YEAR) < 1900)
{ {
return BAD_DATE; return BAD_DATE;
} } else {
else
{
// Because of daylight time saving we cannot use // Because of daylight time saving we cannot use
// date.getTime() - calStart.getTimeInMillis() // date.getTime() - calStart.getTimeInMillis()
// as the difference in milliseconds between 00:00 and 04:00 // as the difference in milliseconds between 00:00 and 04:00
@ -81,10 +90,12 @@ public class HSSFDateUtil
) / ( double ) DAY_MILLISECONDS; ) / ( double ) DAY_MILLISECONDS;
calStart = dayStart(calStart); calStart = dayStart(calStart);
double value = fraction + absoluteDay(calStart); double value = fraction + absoluteDay(calStart, use1904windowing);
if (value >= 60) { if (!use1904windowing && value >= 60) {
value += 1; value++;
} else if (use1904windowing) {
value--;
} }
return value; return value;
@ -92,20 +103,25 @@ public class HSSFDateUtil
} }
/** /**
* Given a excel date, converts it into a Date. * Given an Excel date with using 1900 date windowing, and
* Assumes 1900 date windowing. * converts it to a java.util.Date.
* *
* @param date the Excel Date * NOTE: If the default <code>TimeZone</code> in Java uses Daylight
* Saving Time then the conversion back to an Excel date may not give
* the same value, that is the comparison
* <CODE>excelDate == getExcelDate(getJavaDate(excelDate,false))</CODE>
* is not always true. For example if default timezone is
* <code>Europe/Copenhagen</code>, on 2004-03-28 the minute after
* 01:59 CET is 03:00 CEST, if the excel date represents a time between
* 02:00 and 03:00 then it is converted to past 03:00 summer time
* *
* @return Java representation of a date (null if error) * @param date The Excel date.
* @see #getJavaDate(double,boolean) * @return Java representation of the date, or null if date is not a valid Excel date
* @see java.util.TimeZone
*/ */
public static Date getJavaDate(double date) {
public static Date getJavaDate(double date)
{
return getJavaDate(date, false); return getJavaDate(date, false);
} }
/** /**
* Given an Excel date with either 1900 or 1904 date windowing, * Given an Excel date with either 1900 or 1904 date windowing,
* converts it to a java.util.Date. * converts it to a java.util.Date.
@ -142,7 +158,7 @@ public class HSSFDateUtil
GregorianCalendar calendar = new GregorianCalendar(startYear,0, GregorianCalendar calendar = new GregorianCalendar(startYear,0,
wholeDays + dayAdjust); wholeDays + dayAdjust);
int millisecondsInDay = (int)((date - Math.floor(date)) * int millisecondsInDay = (int)((date - Math.floor(date)) *
(double) DAY_MILLISECONDS + 0.5); DAY_MILLISECONDS + 0.5);
calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay); calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
return calendar.getTime(); return calendar.getTime();
} }
@ -238,7 +254,7 @@ public class HSSFDateUtil
* Check if a cell contains a date * Check if a cell contains a date
* Since dates are stored internally in Excel as double values * Since dates are stored internally in Excel as double values
* we infer it is a date if it is formatted as such. * we infer it is a date if it is formatted as such.
* @see #isADateFormat(int,string) * @see #isADateFormat(int, String)
* @see #isInternalDateFormat(int) * @see #isInternalDateFormat(int)
*/ */
public static boolean isCellDateFormatted(HSSFCell cell) { public static boolean isCellDateFormatted(HSSFCell cell) {
@ -259,7 +275,7 @@ public class HSSFDateUtil
* excel date formats. * excel date formats.
* As Excel stores a great many of its dates in "non-internal" * As Excel stores a great many of its dates in "non-internal"
* date formats, you will not normally want to use this method. * date formats, you will not normally want to use this method.
* @see #isADateFormat(int,string) * @see #isADateFormat(int,String)
* @see #isInternalDateFormat(int) * @see #isInternalDateFormat(int)
*/ */
public static boolean isCellInternalDateFormatted(HSSFCell cell) { public static boolean isCellInternalDateFormatted(HSSFCell cell) {
@ -296,10 +312,10 @@ public class HSSFDateUtil
* @exception IllegalArgumentException if date is invalid * @exception IllegalArgumentException if date is invalid
*/ */
private static int absoluteDay(Calendar cal) static int absoluteDay(Calendar cal, boolean use1904windowing)
{ {
return cal.get(Calendar.DAY_OF_YEAR) return cal.get(Calendar.DAY_OF_YEAR)
+ daysInPriorYears(cal.get(Calendar.YEAR)); + daysInPriorYears(cal.get(Calendar.YEAR), use1904windowing);
} }
/** /**
@ -307,14 +323,14 @@ public class HSSFDateUtil
* *
* @return days number of days in years prior to yr. * @return days number of days in years prior to yr.
* @param yr a year (1900 < yr < 4000) * @param yr a year (1900 < yr < 4000)
* @param use1904windowing
* @exception IllegalArgumentException if year is outside of range. * @exception IllegalArgumentException if year is outside of range.
*/ */
private static int daysInPriorYears(int yr) private static int daysInPriorYears(int yr, boolean use1904windowing)
{ {
if (yr < 1900) { if ((!use1904windowing && yr < 1900) || (use1904windowing && yr < 1900)) {
throw new IllegalArgumentException( throw new IllegalArgumentException("'year' must be 1900 or greater");
"'year' must be 1900 or greater");
} }
int yr1 = yr - 1; int yr1 = yr - 1;
@ -323,7 +339,7 @@ public class HSSFDateUtil
+ yr1 / 400 // plus years divisible by 400 + yr1 / 400 // plus years divisible by 400
- 460; // leap days in previous 1900 years - 460; // leap days in previous 1900 years
return 365 * (yr - 1900) + leapDays; return 365 * (yr - (use1904windowing ? 1904 : 1900)) + leapDays;
} }
// set HH:MM:SS fields of cal to 00:00:00:000 // set HH:MM:SS fields of cal to 00:00:00:000

View File

@ -281,8 +281,8 @@ public class HSSFFont
* @return color to use * @return color to use
* @see #COLOR_NORMAL * @see #COLOR_NORMAL
* @see #COLOR_RED * @see #COLOR_RED
* @see org.apache.poi.hssf.usermodel.HSSFPalette#getColor(short)
*/ */
public short getColor() public short getColor()
{ {
return font.getColorPaletteIndex(); return font.getColorPaletteIndex();

View File

@ -23,9 +23,13 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.util.HSSFCellRangeAddress;
import org.apache.poi.hssf.util.HSSFDataValidation;
import org.apache.poi.hssf.util.Region; import org.apache.poi.hssf.util.Region;
import org.apache.poi.hssf.util.PaneInformation; import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
@ -35,6 +39,7 @@ import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Stack;
import java.util.TreeMap; import java.util.TreeMap;
import java.text.AttributedString; import java.text.AttributedString;
import java.text.NumberFormat; import java.text.NumberFormat;
@ -354,6 +359,94 @@ public class HSSFSheet
return lastrow; return lastrow;
} }
/**
* Creates a data validation object
* @param obj_validation The Data validation object settings
*/
public void addValidationData(HSSFDataValidation obj_validation)
{
if ( obj_validation == null )
{
return;
}
DVALRecord dvalRec = (DVALRecord)sheet.findFirstRecordBySid( DVALRecord.sid );
int eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid );
if ( dvalRec == null )
{
dvalRec = new DVALRecord();
sheet.getRecords().add( eofLoc, dvalRec );
}
int curr_dvRecNo = dvalRec.getDVRecNo();
dvalRec.setDVRecNo(curr_dvRecNo+1);
//create dv record
DVRecord dvRecord = new DVRecord();
//dv record's option flags
dvRecord.setDataType( obj_validation.getDataValidationType() );
dvRecord.setErrorStyle(obj_validation.getErrorStyle());
dvRecord.setEmptyCellAllowed(obj_validation.getEmptyCellAllowed());
dvRecord.setSurppresDropdownArrow(obj_validation.getSurppressDropDownArrow());
dvRecord.setShowPromptOnCellSelected(obj_validation.getShowPromptBox());
dvRecord.setShowErrorOnInvalidValue(obj_validation.getShowErrorBox());
dvRecord.setConditionOperator(obj_validation.getOperator());
//string fields
dvRecord.setStringField( DVRecord.STRING_PROMPT_TITLE,obj_validation.getPromptBoxTitle());
dvRecord.setStringField( DVRecord.STRING_PROMPT_TEXT, obj_validation.getPromptBoxText());
dvRecord.setStringField( DVRecord.STRING_ERROR_TITLE, obj_validation.getErrorBoxTitle());
dvRecord.setStringField( DVRecord.STRING_ERROR_TEXT, obj_validation.getErrorBoxText());
//formula fields ( size and data )
String str_formula = obj_validation.getFirstFormula();
FormulaParser fp = new FormulaParser(str_formula+";",book);
fp.parse();
Stack ptg_arr = new Stack();
Ptg[] ptg = fp.getRPNPtg();
int size = 0;
for (int k = 0; k < ptg.length; k++)
{
if ( ptg[k] instanceof org.apache.poi.hssf.record.formula.AreaPtg )
{
//we should set ptgClass to Ptg.CLASS_REF and explicit formula string to false
ptg[k].setClass(Ptg.CLASS_REF);
obj_validation.setExplicitListFormula(false);
}
size += ptg[k].getSize();
ptg_arr.push(ptg[k]);
}
dvRecord.setFirstFormulaRPN(ptg_arr);
dvRecord.setFirstFormulaSize((short)size);
dvRecord.setListExplicitFormula(obj_validation.getExplicitListFormula());
if ( obj_validation.getSecondFormula() != null )
{
str_formula = obj_validation.getSecondFormula();
fp = new FormulaParser(str_formula+";",book);
fp.parse();
ptg_arr = new Stack();
ptg = fp.getRPNPtg();
size = 0;
for (int k = 0; k < ptg.length; k++)
{
size += ptg[k].getSize();
ptg_arr.push(ptg[k]);
}
dvRecord.setSecFormulaRPN(ptg_arr);
dvRecord.setSecFormulaSize((short)size);
}
//dv records cell range field
HSSFCellRangeAddress cell_range = new HSSFCellRangeAddress();
cell_range.addADDRStructure(obj_validation.getFirstRow(), obj_validation.getFirstColumn(), obj_validation.getLastRow(), obj_validation.getLastColumn());
dvRecord.setCellRangeAddress(cell_range);
//add dv record
eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid );
sheet.getRecords().add( eofLoc, dvRecord );
}
/** /**
* Get the visibility state for a given column. * Get the visibility state for a given column.
* @param column - the column to get (0-based) * @param column - the column to get (0-based)

View File

@ -0,0 +1,253 @@
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.util;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.util.LittleEndian;
import java.util.ArrayList;
/**
* <p>Title: HSSFCellRangeAddress</p>
* <p>Description:
* Implementation of the cell range address lists,like is described in
* OpenOffice.org's Excel Documentation .
* In BIFF8 there is a common way to store absolute cell range address
* lists in several records (not formulas). A cell range address list
* consists of a field with the number of ranges and the list of the range
* addresses. Each cell range address (called an ADDR structure) contains
* 4 16-bit-values.</p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: </p>
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
* @version 2.0-pre
*/
public class HSSFCellRangeAddress
{
/**
* Number of following ADDR structures
*/
private short field_addr_number;
/**
* List of ADDR structures. Each structure represents a cell range
*/
private ArrayList field_regions_list;
public HSSFCellRangeAddress()
{
}
/**
* Construct a new HSSFCellRangeAddress object and sets its fields appropriately .
* Even this isn't an Excel record , I kept the same behavior for reading/writing
* the object's data as for a regular record .
*
* @param in the RecordInputstream to read the record from
*/
public HSSFCellRangeAddress(RecordInputStream in)
{
this.fillFields(in);
}
public void fillFields(RecordInputStream in)
{
this.field_addr_number = in.readShort();
this.field_regions_list = new ArrayList(this.field_addr_number);
for (int k = 0; k < this.field_addr_number; k++)
{
short first_row = in.readShort();
short first_col = in.readShort();
short last_row = in.readShort();
short last_col = in.readShort();
AddrStructure region = new AddrStructure(first_row, first_col, last_row, last_col);
this.field_regions_list.add(region);
}
}
/**
* Get the number of following ADDR structures.
* The number of this structures is automatically set when reading an Excel file
* and/or increased when you manually add a new ADDR structure .
* This is the reason there isn't a set method for this field .
* @return number of ADDR structures
*/
public short getADDRStructureNumber()
{
return this.field_addr_number;
}
/**
* Add an ADDR structure .
* @param first_row - the upper left hand corner's row
* @param first_col - the upper left hand corner's col
* @param last_row - the lower right hand corner's row
* @param last_col - the lower right hand corner's col
* @return the index of this ADDR structure
*/
public int addADDRStructure(short first_row, short first_col, short last_row, short last_col)
{
if (this.field_regions_list == null)
{
//just to be sure :-)
this.field_addr_number= 0;
this.field_regions_list = new ArrayList(10);
}
AddrStructure region = new AddrStructure(first_row, last_row, first_col, last_col);
this.field_regions_list.add(region);
this.field_addr_number++;
return this.field_addr_number;
}
/**
* Remove the ADDR structure stored at the passed in index
* @param index The ADDR structure's index
*/
public void removeADDRStructureAt(int index)
{
this.field_regions_list.remove(index);
this.field_addr_number--;
}
/**
* return the ADDR structure at the given index.
* @return AddrStructure representing
*/
public AddrStructure getADDRStructureAt(int index)
{
return ( AddrStructure ) this.field_regions_list.get(index);
}
public int serialize(int offset, byte [] data)
{
int pos = 2;
LittleEndian.putShort(data, offset, this.getADDRStructureNumber());
for (int k = 0; k < this.getADDRStructureNumber(); k++)
{
AddrStructure region = this.getADDRStructureAt(k);
LittleEndian.putShort(data, offset + pos, region.getFirstRow());
pos += 2;
LittleEndian.putShort(data, offset + pos, region.getLastRow());
pos += 2;
LittleEndian.putShort(data, offset + pos, region.getFirstColumn());
pos += 2;
LittleEndian.putShort(data, offset + pos, region.getLastColumn());
pos += 2;
}
return this.getSize();
}
public int getSize()
{
return 2 + this.field_addr_number*8;
}
public class AddrStructure
{
private short _first_row;
private short _first_col;
private short _last_row;
private short _last_col;
public AddrStructure(short first_row, short last_row, short first_col, short last_col)
{
this._first_row = first_row;
this._last_row = last_row;
this._first_col = first_col;
this._last_col = last_col;
}
/**
* get the upper left hand corner column number
* @return column number for the upper left hand corner
*/
public short getFirstColumn()
{
return this._first_col;
}
/**
* get the upper left hand corner row number
* @return row number for the upper left hand corner
*/
public short getFirstRow()
{
return this._first_row;
}
/**
* get the lower right hand corner column number
* @return column number for the lower right hand corner
*/
public short getLastColumn()
{
return this._last_col;
}
/**
* get the lower right hand corner row number
* @return row number for the lower right hand corner
*/
public short getLastRow()
{
return this._last_row;
}
/**
* set the upper left hand corner column number
* @param this._first_col column number for the upper left hand corner
*/
public void setFirstColumn(short first_col)
{
this._first_col = first_col;
}
/**
* set the upper left hand corner row number
* @param rowFrom row number for the upper left hand corner
*/
public void setFirstRow(short first_row)
{
this._first_row = first_row;
}
/**
* set the lower right hand corner column number
* @param colTo column number for the lower right hand corner
*/
public void setLastColumn(short last_col)
{
this._last_col = last_col;
}
/**
* get the lower right hand corner row number
* @param rowTo row number for the lower right hand corner
*/
public void setLastRow(short last_row)
{
this._last_row = last_row;
}
}
}

View File

@ -0,0 +1,471 @@
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.util;
/**
* <p>Title: HSSFDataValidation</p>
* <p>Description: Utilty class for creating data validation cells</p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: </p>
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
* @version 2.0-pre
*/
public class HSSFDataValidation
{
/**
* Validation data type constants
*/
/**
* Any type
*/
public static final int DATA_TYPE_ANY = 0x00;
/**
* Integer type
*/
public static final int DATA_TYPE_INTEGER = 0x01;
/**
* Decimal type
*/
public static final int DATA_TYPE_DECIMAL = 0x02;
/**
* List type ( combo box type )
*/
public static final int DATA_TYPE_LIST = 0x03;
/**
* Date type
*/
public static final int DATA_TYPE_DATE = 0x04;
/**
* Time type
*/
public static final int DATA_TYPE_TIME = 0x05;
/**
* String length type
*/
public static final int DATA_TYPE_TEXT_LENGTH = 0x06;
/**
* Formula ( custom ) type
*/
public static final int DATA_TYPE_FORMULA = 0x07;
/**
* Error style constants for error box
*/
/**
* STOP style like
*/
public static final int ERROR_STYLE_STOP = 0x00;
/**
* WARNING style like
*/
public static final int ERROR_STYLE_WARNING = 0x01;
/**
* INFO style like
*/
public static final int ERROR_STYLE_INFO = 0x02;
/**
* Condition operator
*/
public static final int OPERATOR_BETWEEN = 0x00;
public static final int OPERATOR_NOT_BETWEEN = 0x01;
public static final int OPERATOR_EQUAL = 0x02;
public static final int OPERATOR_NOT_EQUAL = 0x03;
public static final int OPERATOR_GREATER_THAN = 0x04;
public static final int OPERATOR_LESS_THAN = 0x05;
public static final int OPERATOR_GREATER_OR_EQUAL = 0x06;
public static final int OPERATOR_LESS_OR_EQUAL = 0x07;
private short _first_row = 0;
private short _first_col = 0;
private short _last_row = 0;
private short _last_col = 0;
private String _prompt_title = null;
private String _prompt_text = null;
private String _error_title = null;
private String _error_text = null;
private String _string_first_formula = null;
private String _string_sec_formula = null;
private int _data_type = HSSFDataValidation.DATA_TYPE_ANY;
private int _error_style = HSSFDataValidation.ERROR_STYLE_STOP;
private boolean _list_explicit_formula = true;
private boolean _empty_cell_allowed = true;
private boolean _surpress_dropdown_arrow = false;
private boolean _show_prompt_box = true;
private boolean _show_error_box = true;
private int _operator = HSSFDataValidation.OPERATOR_BETWEEN;
/**
* Empty constructor
*/
public HSSFDataValidation( )
{
}
/**
* Constructor wich initializes the cell range on wich this object will be applied
* @param first_row First row
* @param first_col First column
* @param last_row Last row
* @param last_col Last column
*/
public HSSFDataValidation( short first_row, short first_col, short last_row, short last_col )
{
this._first_row = first_row;
this._first_col = first_col;
this._last_row = last_row;
this._last_col = last_col;
}
/**
* Set the type of this object
* @param data_type The type
* @see DATA_TYPE_ANY, DATA_TYPE_INTEGER, DATA_TYPE_DECIMNAL, DATA_TYPE_LIST, DATA_TYPE_DATE,
* DATA_TYPE_TIME, DATA_TYPE_TEXT_LENTGH, DATA_TYPE_FORMULA
*/
public void setDataValidationType( int data_type )
{
this._data_type = data_type;
}
/**
* The data type of this object
* @return The type
* @see DATA_TYPE_ANY, DATA_TYPE_INTEGER, DATA_TYPE_DECIMNAL, DATA_TYPE_LIST, DATA_TYPE_DATE,
* DATA_TYPE_TIME, DATA_TYPE_TEXT_LENTGH, DATA_TYPE_FORMULA
*/
public int getDataValidationType()
{
return this._data_type;
}
/**
* Sets the error style for error box
* @param error_style Error style constant
* @see ERROR_STYLE_STOP, ERROR_STYLE_WARNING, ERROR_STYLE_INFO
*/
public void setErrorStyle( int error_style )
{
this._error_style = error_style;
}
/**
* returns the error style of errror box
* @return the style constant
* @see ERROR_STYLE_STOP, ERROR_STYLE_WARNING, ERROR_STYLE_INFO
*/
public int getErrorStyle( )
{
return this._error_style;
}
/**
* If this object has an explicit formula . This is useful only for list data validation object
* @param explicit True if use an explicit formula
*/
public void setExplicitListFormula( boolean explicit )
{
this._list_explicit_formula = explicit;
}
/**
* Returns the settings for explicit formula . This is useful only for list data validation objects.
* This method always returns false if the object isn't a list validation object
* @see setDataValidationType( int data_type )
* @return
*/
public boolean getExplicitListFormula( )
{
if ( this._data_type != HSSFDataValidation.DATA_TYPE_LIST )
{
return false;
}
return this._list_explicit_formula ;
}
/**
* Sets if this object allows empty as a valid value
* @param allowed True if this object should treats empty as valid value , false otherwise
*/
public void setEmptyCellAllowed( boolean allowed )
{
this._empty_cell_allowed = allowed;
}
/**
* Retrieve the settings for empty cells allowed
* @return True if this object should treats empty as valid value , false otherwise
*/
public boolean getEmptyCellAllowed( )
{
return this._empty_cell_allowed ;
}
/**
* Useful for list validation objects .
* @param surppres True if a list should display the values into a drop down list , false otherwise .
* In other words , if a list should display the arrow sign on its right side
*/
public void setSurppressDropDownArrow( boolean surppres )
{
this._surpress_dropdown_arrow = surppres;
}
/**
* Useful only list validation objects .
* This method always returns false if the object isn't a list validation object
* @return True if a list should display the values into a drop down list , false otherwise .
* @see setDataValidationType( int data_type )
*/
public boolean getSurppressDropDownArrow( )
{
if ( this._data_type != HSSFDataValidation.DATA_TYPE_LIST )
{
return false;
}
return this._surpress_dropdown_arrow ;
}
/**
* Sets the behaviour when a cell which belongs to this object is selected
* @param show True if an prompt box should be displayed , false otherwise
*/
public void setShowPromptBox( boolean show )
{
this._show_prompt_box = show;
}
/**
* @param show True if an prompt box should be displayed , false otherwise
*/
public boolean getShowPromptBox( )
{
if ( (this.getPromptBoxText() == null) && (this.getPromptBoxTitle() == null) )
{
return false;
}
return this._show_prompt_box ;
}
/**
* Sets the behaviour when an invalid value is entered
* @param show True if an error box should be displayed , false otherwise
*/
public void setShowErrorBox( boolean show )
{
this._show_error_box = show;
}
/**
* @return True if an error box should be displayed , false otherwise
*/
public boolean getShowErrorBox( )
{
if ( (this.getErrorBoxText() == null) && (this.getErrorBoxTitle() == null) )
{
return false;
}
return this._show_error_box ;
}
/**
* Sets the operator involved in the formula whic governs this object
* Example : if you wants that a cell to accept only values between 1 and 5 , which
* mathematically means 1 <= value <= 5 , then the operator should be OPERATOR_BETWEEN
* @param operator A constant for operator
* @see OPERATOR_BETWEEN, OPERATOR_NOT_BETWEEN, OPERATOR_EQUAL, OPERATOR_NOT_EQUAL
* OPERATOR_GREATER_THAN, OPERATOR_LESS_THAN, OPERATOR_GREATER_OR_EQUAL,
* OPERATOR_LESS_OR_EQUAL
*/
public void setOperator( int operator )
{
this._operator = operator;
}
/**
* Retrieves the operator used for this object's formula
* @return
* @see OPERATOR_BETWEEN, OPERATOR_NOT_BETWEEN, OPERATOR_EQUAL, OPERATOR_NOT_EQUAL
* OPERATOR_GREATER_THAN, OPERATOR_LESS_THAN, OPERATOR_GREATER_OR_EQUAL,
* OPERATOR_LESS_OR_EQUAL
*/
public int getOperator()
{
return this._operator;
}
/**
* Sets the title and text for the prompt box . Prompt box is displayed when the user
* selects a cell which belongs to this validation object . In order for a prompt box
* to be displayed you should also use method setShowPromptBox( boolean show )
* @param title The prompt box's title
* @param text The prompt box's text
* @see setShowPromptBox( boolean show )
*/
public void createPromptBox( String title, String text )
{
this._prompt_title = title;
this._prompt_text = text;
this.setShowPromptBox(true);
}
/**
* Returns the prompt box's title
* @return Prompt box's title or null
*/
public String getPromptBoxTitle( )
{
return this._prompt_title;
}
/**
* Returns the prompt box's text
* @return Prompt box's text or null
*/
public String getPromptBoxText( )
{
return this._prompt_text;
}
/**
* Sets the title and text for the error box . Error box is displayed when the user
* enters an invalid value int o a cell which belongs to this validation object .
* In order for an error box to be displayed you should also use method
* setShowErrorBox( boolean show )
* @param title The error box's title
* @param text The error box's text
* @see setShowErrorBox( boolean show )
*/
public void createErrorBox( String title, String text )
{
this._error_title = title;
this._error_text = text;
this.setShowErrorBox(true);
}
/**
* Returns the error box's title
* @return Error box's title or null
*/
public String getErrorBoxTitle( )
{
return this._error_title;
}
/**
* Returns the error box's text
* @return Error box's text or null
*/
public String getErrorBoxText( )
{
return this._error_text;
}
/**
* Sets the first formula for this object .
* A formula is divided into three parts : first formula , operator and second formula .
* In other words , a formula contains a left oprand , an operator and a right operand.
* This is the general rule . An example is 1<= value <= 5 . In this case ,
* the left operand ( or the first formula ) is the number 1 . The operator is
* OPERATOR_BETWEEN and the right operand ( or the second formula ) is 5 .
* @param formula
*/
public void setFirstFormula( String formula )
{
this._string_first_formula = formula;
}
/**
* Returns the first formula
* @return
*/
public String getFirstFormula( )
{
return this._string_first_formula;
}
/**
* Sets the first formula for this object .
* A formula is divided into three parts : first formula , operator and second formula .
* In other words , a formula contains a left oprand , an operator and a right operand.
* This is the general rule . An example is 1<= value <=5 . In this case ,
* the left operand ( or the first formula ) is the number 1 . The operator is
* OPERATOR_BETWEEN and the right operand ( or the second formula ) is 5 .
* But there are cases when a second formula isn't needed :
* You want somethink like : all values less than 5 . In this case , there's only a first
* formula ( in our case 5 ) and the operator OPERATOR_LESS_THAN
* @param formula
*/
public void setSecondFormula( String formula )
{
this._string_sec_formula = formula;
}
/**
* Returns the second formula
* @return
*/
public String getSecondFormula( )
{
return this._string_sec_formula;
}
public void setFirstRow( short first_row )
{
this._first_row = first_row;
}
public void setFirstColumn( short first_column )
{
this._first_col = first_column;
}
public void setLastRow( short last_row )
{
this._last_row = last_row;
}
public void setLastColumn( short last_column )
{
this._last_col = last_column;
}
public short getFirstRow()
{
return this._first_row;
}
public short getFirstColumn()
{
return this._first_col;
}
public short getLastRow()
{
return this._last_row;
}
public short getLastColumn()
{
return this._last_col;
}
}

View File

@ -19,6 +19,7 @@
package org.apache.poi.poifs.storage; package org.apache.poi.poifs.storage;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.filesystem.BATManaged; import org.apache.poi.poifs.filesystem.BATManaged;
import org.apache.poi.poifs.filesystem.POIFSDocument; import org.apache.poi.poifs.filesystem.POIFSDocument;
import org.apache.poi.poifs.property.RootProperty; import org.apache.poi.poifs.property.RootProperty;
@ -69,6 +70,8 @@ public class SmallBlockTableWriter
{ {
_small_blocks.add(blocks[ j ]); _small_blocks.add(blocks[ j ]);
} }
} else {
doc.setStartBlock(POIFSConstants.END_OF_CHAIN);
} }
} }
_sbat.simpleCreateBlocks(); _sbat.simpleCreateBlocks();

View File

@ -19,6 +19,7 @@
package org.apache.poi.util; package org.apache.poi.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -28,6 +29,25 @@ public class IOUtils
{ {
} }
/**
* Reads all the data from the input stream, and returns
* the bytes read.
*/
public static byte[] toByteArray(InputStream stream) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int read = 0;
while(read != -1) {
read = stream.read(buffer);
if(read > 0) {
baos.write(buffer, 0, read);
}
}
return baos.toByteArray();
}
/** /**
* Helper method, just calls <tt>readFully(in, b, 0, b.length)</tt> * Helper method, just calls <tt>readFully(in, b, 0, b.length)</tt>
*/ */

View File

@ -161,7 +161,8 @@ public class StringUtil {
final int offset, final int offset,
final int len) { final int len) {
try { try {
return new String(string, offset, len, "ISO-8859-1"); int len_to_use = Math.min(len, string.length - offset);
return new String(string, offset, len_to_use, "ISO-8859-1");
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new InternalError(); /* unreachable */ throw new InternalError(); /* unreachable */
} }

View File

@ -0,0 +1,127 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hslf.examples;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.hslf.usermodel.RichTextRun;
import org.apache.poi.hslf.model.*;
import java.awt.*;
import java.io.FileOutputStream;
/**
* Demonstrates how to create tables
*
* @author Yegor Kozlov
*/
public class TableDemo {
public static void main(String[] args) throws Exception {
//test data for the first taable
String[][] txt1 = {
{"INPUT FILE", "NUMBER OF RECORDS"},
{"Item File", "11,559"},
{"Vendor File", "502"},
{"Purchase History File - # of PO\u2019s\r(12/01/04 - 05/31/06)", "12,852"},
{"Purchase History File - # of PO Lines\r(12/01/04 - 05/31/06)", "53,523" },
{"Total PO History Spend", "$10,172,038"}
};
SlideShow ppt = new SlideShow();
Slide slide = ppt.createSlide();
//six rows, two columns
Table table1 = new Table(6, 2);
for (int i = 0; i < txt1.length; i++) {
for (int j = 0; j < txt1[i].length; j++) {
TableCell cell = table1.getCell(i, j);
cell.setText(txt1[i][j]);
RichTextRun rt = cell.getTextRun().getRichTextRuns()[0];
rt.setFontName("Arial");
rt.setFontSize(10);
if(i == 0){
cell.getFill().setForegroundColor(new Color(227, 227, 227));
} else {
rt.setBold(true);
}
cell.setVerticalAlignment(TextBox.AnchorMiddle);
cell.setHorizontalAlignment(TextBox.AlignCenter);
}
}
Line border1 = table1.createBorder();
border1.setLineColor(Color.black);
border1.setLineWidth(1.0);
table1.setAllBorders(border1);
table1.setColumnWidth(0, 300);
table1.setColumnWidth(1, 150);
slide.addShape(table1);
int pgWidth = ppt.getPageSize().width;
table1.moveTo((pgWidth - table1.getAnchor().width)/2, 100);
//test data for the second taable
String[][] txt2 = {
{"Data Source"},
{"CAS Internal Metrics - Item Master Summary\r" +
"CAS Internal Metrics - Vendor Summary\r" +
"CAS Internal Metrics - PO History Summary"}
};
//two rows, one column
Table table2 = new Table(2, 1);
for (int i = 0; i < txt2.length; i++) {
for (int j = 0; j < txt2[i].length; j++) {
TableCell cell = table2.getCell(i, j);
cell.setText(txt2[i][j]);
RichTextRun rt = cell.getTextRun().getRichTextRuns()[0];
rt.setFontSize(10);
rt.setFontName("Arial");
if(i == 0){
cell.getFill().setForegroundColor(new Color(0, 51, 102));
rt.setFontColor(Color.white);
rt.setBold(true);
rt.setFontSize(14);
cell.setHorizontalAlignment(TextBox.AlignCenter);
} else {
rt.setBullet(true);
rt.setFontSize(12);
cell.setHorizontalAlignment(TextBox.AlignLeft);
}
cell.setVerticalAlignment(TextBox.AnchorMiddle);
}
}
table2.setColumnWidth(0, 300);
table2.setRowHeight(0, 30);
table2.setRowHeight(1, 70);
Line border2 = table2.createBorder();
table2.setOutsideBorders(border2);
slide.addShape(table2);
table2.moveTo(200, 400);
FileOutputStream out = new FileOutputStream("hslf-table.ppt");
ppt.write(out);
out.close();
}
}

View File

@ -283,7 +283,7 @@ public class XLS2CSVmra implements HSSFListener {
format = format.replaceAll("\\\\-","-"); format = format.replaceAll("\\\\-","-");
// Format as a date // Format as a date
Date d = HSSFDateUtil.getJavaDate(value); Date d = HSSFDateUtil.getJavaDate(value, false);
DateFormat df = new SimpleDateFormat(format); DateFormat df = new SimpleDateFormat(format);
return df.format(d); return df.format(d);
} else { } else {

View File

@ -150,10 +150,12 @@ public class Fill {
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID); EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
if (color == null) { if (color == null) {
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, -1); Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, -1);
Shape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150010);
} }
else { else {
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb); Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb);
Shape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150011);
} }
} }

View File

@ -153,7 +153,7 @@ public abstract class Sheet {
*/ */
protected static void findTextRuns(Record[] records, Vector found) { protected static void findTextRuns(Record[] records, Vector found) {
// Look for a TextHeaderAtom // Look for a TextHeaderAtom
for (int i = 0; i < (records.length - 1); i++) { for (int i = 0, slwtIndex=0; i < (records.length - 1); i++) {
if (records[i] instanceof TextHeaderAtom) { if (records[i] instanceof TextHeaderAtom) {
TextRun trun = null; TextRun trun = null;
TextHeaderAtom tha = (TextHeaderAtom) records[i]; TextHeaderAtom tha = (TextHeaderAtom) records[i];
@ -179,7 +179,6 @@ public abstract class Sheet {
// TextSpecInfoAtom - Safe to ignore // TextSpecInfoAtom - Safe to ignore
} else { } else {
System.err.println("Found a TextHeaderAtom not followed by a TextBytesAtom or TextCharsAtom: Followed by " + records[i + 1].getRecordType()); System.err.println("Found a TextHeaderAtom not followed by a TextBytesAtom or TextCharsAtom: Followed by " + records[i + 1].getRecordType());
continue;
} }
if (trun != null) { if (trun != null) {
@ -191,12 +190,14 @@ public abstract class Sheet {
Record[] recs = new Record[lst.size()]; Record[] recs = new Record[lst.size()];
lst.toArray(recs); lst.toArray(recs);
trun._records = recs; trun._records = recs;
trun.setIndex(slwtIndex);
found.add(trun); found.add(trun);
i++; i++;
} else { } else {
// Not a valid one, so skip on to next and look again // Not a valid one, so skip on to next and look again
} }
slwtIndex++;
} }
} }
} }

View File

@ -124,9 +124,11 @@ public class SimpleShape extends Shape {
int rgb = p1.getPropertyValue(); int rgb = p1.getPropertyValue();
if (rgb >= 0x8000000) { if (rgb >= 0x8000000) {
int idx = rgb % 0x8000000; int idx = rgb % 0x8000000;
if(getSheet() != null) {
ColorSchemeAtom ca = getSheet().getColorScheme(); ColorSchemeAtom ca = getSheet().getColorScheme();
if(idx >= 0 && idx <= 7) rgb = ca.getColor(idx); if(idx >= 0 && idx <= 7) rgb = ca.getColor(idx);
} }
}
Color tmp = new Color(rgb, true); Color tmp = new Color(rgb, true);
clr = new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); clr = new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());
} }
@ -192,9 +194,11 @@ public class SimpleShape extends Shape {
int rgb = p1.getPropertyValue(); int rgb = p1.getPropertyValue();
if (rgb >= 0x8000000) { if (rgb >= 0x8000000) {
int idx = rgb % 0x8000000; int idx = rgb % 0x8000000;
if(getSheet() != null) {
ColorSchemeAtom ca = getSheet().getColorScheme(); ColorSchemeAtom ca = getSheet().getColorScheme();
rgb = ca.getColor(idx); rgb = ca.getColor(idx);
} }
}
Color tmp = new Color(rgb, true); Color tmp = new Color(rgb, true);
clr = new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); clr = new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());
} }

View File

@ -0,0 +1,291 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.util.LittleEndian;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.awt.*;
/**
* Represents a table in a PowerPoint presentation
*
* @author Yegor Kozlov
*/
public class Table extends ShapeGroup {
protected static final int BORDER_TOP = 1;
protected static final int BORDER_RIGHT = 2;
protected static final int BORDER_BOTTOM = 3;
protected static final int BORDER_LEFT = 4;
protected static final int BORDERS_ALL = 5;
protected static final int BORDERS_OUTSIDE = 6;
protected static final int BORDERS_INSIDE = 7;
protected static final int BORDERS_NONE = 8;
protected TableCell[][] cells;
/**
* Create a new Table of the given number of rows and columns
*
* @param numrows the number of rows
* @param numcols the number of columns
*/
public Table(int numrows, int numcols) {
super();
int x=0, y=0, tblWidth=0, tblHeight=0;
cells = new TableCell[numrows][numcols];
for (int i = 0; i < cells.length; i++) {
x = 0;
for (int j = 0; j < cells[i].length; j++) {
cells[i][j] = new TableCell(this);
Rectangle anchor = new Rectangle(x, y, TableCell.DEFAULT_WIDTH, TableCell.DEFAULT_HEIGHT);
cells[i][j].setAnchor(anchor);
x += TableCell.DEFAULT_WIDTH;
}
y += TableCell.DEFAULT_HEIGHT;
}
tblWidth = x;
tblHeight = y;
setAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
List lst = spCont.getChildRecords();
EscherOptRecord opt = new EscherOptRecord();
opt.setRecordId((short)0xF122);
opt.addEscherProperty(new EscherSimpleProperty((short)0x39F, 1));
EscherArrayProperty p = new EscherArrayProperty((short)0x43A0, false, null);
p.setSizeOfElements(0x0004);
p.setNumberOfElementsInArray(numrows);
p.setNumberOfElementsInMemory(numrows);
opt.addEscherProperty(p);
lst.add(lst.size()-1, opt);
}
/**
* Create a Table object and initilize it from the supplied Record container.
*
* @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
* @param parent the parent of the shape
*/
protected Table(EscherContainerRecord escherRecord, Shape parent) {
super(escherRecord, parent);
}
/**
* Gets a cell
*
* @param row the row index (0-based)
* @param col the column index (0-based)
* @return the cell
*/
public TableCell getCell(int row, int col) {
return cells[row][col];
}
public int getNumberOfColumns() {
return cells[0].length;
}
public int getNumberOfRows() {
return cells.length;
}
protected void afterInsert(Sheet sh){
EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
List lst = spCont.getChildRecords();
EscherOptRecord opt = (EscherOptRecord)lst.get(lst.size()-2);
EscherArrayProperty p = (EscherArrayProperty)opt.getEscherProperty(1);
for (int i = 0; i < cells.length; i++) {
TableCell cell = cells[i][0];
int rowHeight = cell.getAnchor().height*MASTER_DPI/POINT_DPI;
byte[] val = new byte[4];
LittleEndian.putInt(val, rowHeight);
p.setElement(i, val);
for (int j = 0; j < cells[i].length; j++) {
TableCell c = cells[i][j];
addShape(c);
Line bt = c.getBorderTop();
if(bt != null) addShape(bt);
Line br = c.getBorderRight();
if(br != null) addShape(br);
Line bb = c.getBorderBottom();
if(bb != null) addShape(bb);
Line bl = c.getBorderLeft();
if(bl != null) addShape(bl);
}
}
}
/**
* Sets the row height.
*
* @param row the row index (0-based)
* @param height the height to set (in pixels)
*/
public void setRowHeight(int row, int height){
int currentHeight = cells[row][0].getAnchor().height;
int dy = height - currentHeight;
for (int i = row; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
Rectangle anchor = cells[i][j].getAnchor();
if(i == row) anchor.height = height;
else anchor.y += dy;
cells[i][j].setAnchor(anchor);
}
}
Rectangle tblanchor = getAnchor();
tblanchor.height += dy;
setAnchor(tblanchor);
}
/**
* Sets the column width.
*
* @param col the column index (0-based)
* @param width the width to set (in pixels)
*/
public void setColumnWidth(int col, int width){
int currentWidth = cells[0][col].getAnchor().width;
int dx = width - currentWidth;
for (int i = 0; i < cells.length; i++) {
Rectangle anchor = cells[i][col].getAnchor();
anchor.width = width;
cells[i][col].setAnchor(anchor);
if(col < cells[i].length - 1) for (int j = col+1; j < cells[i].length; j++) {
anchor = cells[i][j].getAnchor();
anchor.x += dx;
cells[i][j].setAnchor(anchor);
}
}
Rectangle tblanchor = getAnchor();
tblanchor.width += dx;
setAnchor(tblanchor);
}
/**
* Format the table and apply the specified Line to all cell boundaries,
* both outside and inside
*
* @param line the border line
*/
public void setAllBorders(Line line){
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
TableCell cell = cells[i][j];
cell.setBorderTop(cloneBorder(line));
cell.setBorderLeft(cloneBorder(line));
if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
}
}
}
/**
* Format the outside border using the specified Line object
*
* @param line the border line
*/
public void setOutsideBorders(Line line){
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
TableCell cell = cells[i][j];
if(j == 0) cell.setBorderLeft(cloneBorder(line));
if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
else {
cell.setBorderLeft(null);
cell.setBorderLeft(null);
}
if(i == 0) cell.setBorderTop(cloneBorder(line));
else if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
else {
cell.setBorderTop(null);
cell.setBorderBottom(null);
}
}
}
}
/**
* Format the inside border using the specified Line object
*
* @param line the border line
*/
public void setInsideBorders(Line line){
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
TableCell cell = cells[i][j];
if(j != cells[i].length - 1)
cell.setBorderRight(cloneBorder(line));
else {
cell.setBorderLeft(null);
cell.setBorderLeft(null);
}
if(i != cells.length - 1) cell.setBorderBottom(cloneBorder(line));
else {
cell.setBorderTop(null);
cell.setBorderBottom(null);
}
}
}
}
private Line cloneBorder(Line line){
Line border = createBorder();
border.setLineWidth(line.getLineWidth());
border.setLineStyle(line.getLineStyle());
border.setLineDashing(line.getLineDashing());
border.setLineColor(line.getLineColor());
return border;
}
/**
* Create a border to format this table
*
* @return the created border
*/
public Line createBorder(){
Line line = new Line(this);
EscherOptRecord opt = (EscherOptRecord)getEscherChild(line.getSpContainer(), EscherOptRecord.RECORD_ID);
setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
return line;
}
}

View File

@ -0,0 +1,155 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.usermodel.RichTextRun;
import java.awt.*;
/**
* Represents a cell in a ppt table
*
* @author Yegor Kozlov
*/
public class TableCell extends TextBox {
protected static final int DEFAULT_WIDTH = 100;
protected static final int DEFAULT_HEIGHT = 40;
private Line borderLeft;
private Line borderRight;
private Line borderTop;
private Line borderBottom;
/**
* Create a TableCell object and initialize it from the supplied Record container.
*
* @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
* @param parent the parent of the shape
*/
protected TableCell(EscherContainerRecord escherRecord, Shape parent){
super(escherRecord, parent);
}
/**
* Create a new TableCell. This constructor is used when a new shape is created.
*
* @param parent the parent of this Shape. For example, if this text box is a cell
* in a table then the parent is Table.
*/
public TableCell(Shape parent){
super(parent);
setShapeType(ShapeTypes.Rectangle);
_txtrun.setRunType(TextHeaderAtom.HALF_BODY_TYPE);
_txtrun.getRichTextRuns()[0].setFlag(false, 0, false);
}
protected EscherContainerRecord createSpContainer(boolean isChild){
EscherContainerRecord spContainer = super.createSpContainer(isChild);
EscherOptRecord opt = (EscherOptRecord)getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
setEscherProperty(opt, EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20000);
setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150001);
setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
return spContainer;
}
protected void anchorBorder(int type, Line line){
Rectangle cellAnchor = getAnchor();
Rectangle lineAnchor = new Rectangle();
switch(type){
case Table.BORDER_TOP:
lineAnchor.x = cellAnchor.x;
lineAnchor.y = cellAnchor.y;
lineAnchor.width = cellAnchor.width;
lineAnchor.height = 0;
break;
case Table.BORDER_RIGHT:
lineAnchor.x = cellAnchor.x + cellAnchor.width;
lineAnchor.y = cellAnchor.y;
lineAnchor.width = 0;
lineAnchor.height = cellAnchor.height;
break;
case Table.BORDER_BOTTOM:
lineAnchor.x = cellAnchor.x;
lineAnchor.y = cellAnchor.y + cellAnchor.height;
lineAnchor.width = cellAnchor.width;
lineAnchor.height = 0;
break;
case Table.BORDER_LEFT:
lineAnchor.x = cellAnchor.x;
lineAnchor.y = cellAnchor.y;
lineAnchor.width = 0;
lineAnchor.height = cellAnchor.height;
break;
default:
throw new IllegalArgumentException("Unknown border type: " + type);
}
line.setAnchor(lineAnchor);
}
public Line getBorderLeft() {
return borderLeft;
}
public void setBorderLeft(Line line) {
if(line != null) anchorBorder(Table.BORDER_LEFT, line);
this.borderLeft = line;
}
public Line getBorderRight() {
return borderRight;
}
public void setBorderRight(Line line) {
if(line != null) anchorBorder(Table.BORDER_RIGHT, line);
this.borderRight = line;
}
public Line getBorderTop() {
return borderTop;
}
public void setBorderTop(Line line) {
if(line != null) anchorBorder(Table.BORDER_TOP, line);
this.borderTop = line;
}
public Line getBorderBottom() {
return borderBottom;
}
public void setBorderBottom(Line line) {
if(line != null) anchorBorder(Table.BORDER_BOTTOM, line);
this.borderBottom = line;
}
public void setAnchor(Rectangle anchor){
super.setAnchor(anchor);
if(borderTop != null) anchorBorder(Table.BORDER_TOP, borderTop);
if(borderRight != null) anchorBorder(Table.BORDER_RIGHT, borderRight);
if(borderBottom != null) anchorBorder(Table.BORDER_BOTTOM, borderBottom);
if(borderLeft != null) anchorBorder(Table.BORDER_LEFT, borderLeft);
}
}

View File

@ -196,7 +196,7 @@ public class TextBox extends SimpleShape {
} catch (IOException e){ } catch (IOException e){
throw new HSLFException(e); throw new HSLFException(e);
} }
if(getAnchor().equals(new java.awt.Rectangle())) resizeToFitText(); if(getAnchor().equals(new java.awt.Rectangle()) && !"".equals(getText())) resizeToFitText();
} }
/** /**
@ -264,6 +264,14 @@ public class TextBox extends SimpleShape {
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
setEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT, align); setEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT, align);
} }
public void setHorizontalAlignment(int align){
_txtrun.getRichTextRuns()[0].setAlignment(align);
}
public int getHorizontalAlignment(){
return _txtrun.getRichTextRuns()[0].getAlignment();
}
/** /**
* Returns the distance (in points) between the bottom of the text frame * Returns the distance (in points) between the bottom of the text frame
* and the bottom of the inscribed rectangle of the shape that contains the text. * and the bottom of the inscribed rectangle of the shape that contains the text.
@ -466,7 +474,11 @@ public class TextBox extends SimpleShape {
TextRun[] runs = sheet.getTextRuns(); TextRun[] runs = sheet.getTextRuns();
if (ota != null) { if (ota != null) {
int idx = ota.getTextIndex(); int idx = ota.getTextIndex();
if(idx < runs.length) _txtrun = runs[idx]; for (int i = 0; i < runs.length; i++) {
if(runs[i].getIndex() == idx){
_txtrun = runs[i];
}
}
if(_txtrun == null) { if(_txtrun == null) {
logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
} }
@ -478,9 +490,6 @@ public class TextBox extends SimpleShape {
break; break;
} }
} }
if(_txtrun == null) {
logger.log(POILogger.WARN, "text run not found for shapeId=" + shapeId);
}
} }
} }

View File

@ -50,6 +50,7 @@ public class TextRun
private SlideShow slideShow; private SlideShow slideShow;
private Sheet sheet; private Sheet sheet;
private int shapeId; private int shapeId;
private int slwtIndex; //position in the owning SlideListWithText
/** /**
* all text run records that follow TextHeaderAtom. * all text run records that follow TextHeaderAtom.
* (there can be misc InteractiveInfo, TxInteractiveInfo and other records) * (there can be misc InteractiveInfo, TxInteractiveInfo and other records)
@ -537,6 +538,20 @@ public class TextRun
shapeId = id; shapeId = id;
} }
/**
* @return 0-based index of the text run in the SLWT container
*/
protected int getIndex(){
return slwtIndex;
}
/**
* @param id 0-based index of the text run in the SLWT container
*/
protected void setIndex(int id){
slwtIndex = id;
}
/** /**
* Returns the array of all hyperlinks in this text run * Returns the array of all hyperlinks in this text run
* *

View File

@ -198,7 +198,7 @@ public class RichTextRun
setFlag(true, index, value); setFlag(true, index, value);
} }
private void setFlag(boolean isCharacter, int index, boolean value) { public void setFlag(boolean isCharacter, int index, boolean value) {
TextPropCollection props; TextPropCollection props;
String propname; String propname;
if (isCharacter){ if (isCharacter){
@ -282,7 +282,7 @@ public class RichTextRun
* @param propName The name of the Character TextProp * @param propName The name of the Character TextProp
* @param val The value to set for the TextProp * @param val The value to set for the TextProp
*/ */
private void setParaTextPropVal(String propName, int val) { public void setParaTextPropVal(String propName, int val) {
// Ensure we have the StyleTextProp atom we're going to need // Ensure we have the StyleTextProp atom we're going to need
if(paragraphStyle == null) { if(paragraphStyle == null) {
parentRun.ensureStyleAtomPresent(); parentRun.ensureStyleAtomPresent();
@ -297,7 +297,7 @@ public class RichTextRun
* @param propName The name of the Paragraph TextProp * @param propName The name of the Paragraph TextProp
* @param val The value to set for the TextProp * @param val The value to set for the TextProp
*/ */
private void setCharTextPropVal(String propName, int val) { public void setCharTextPropVal(String propName, int val) {
// Ensure we have the StyleTextProp atom we're going to need // Ensure we have the StyleTextProp atom we're going to need
if(characterStyle == null) { if(characterStyle == null) {
parentRun.ensureStyleAtomPresent(); parentRun.ensureStyleAtomPresent();

View File

@ -48,16 +48,25 @@ public class MAPIMessage {
/** /**
* Constructor for reading MSG Files. * Constructor for reading MSG Files from the file system.
* @param filename * @param filename
* @throws IOException * @throws IOException
*/ */
public MAPIMessage(String filename) throws IOException { public MAPIMessage(String filename) throws IOException {
InputStream in = new FileInputStream(new File(filename)); this(new FileInputStream(new File(filename)));
}
/**
* Constructor for reading MSG Files from an input stream.
* @param in
* @throws IOException
*/
public MAPIMessage(InputStream in) throws IOException {
this.fs = new POIFSFileSystem(in); this.fs = new POIFSFileSystem(in);
chunkParser = new POIFSChunkParser(this.fs); chunkParser = new POIFSChunkParser(this.fs);
} }
/** /**
* Gets a string value based on the passed chunk. * Gets a string value based on the passed chunk.
* @param chunk * @param chunk
@ -101,6 +110,16 @@ public class MAPIMessage {
return getStringFromChunk(Chunks.getInstance().displayToChunk); return getStringFromChunk(Chunks.getInstance().displayToChunk);
} }
/**
* Gets the display value of the "FROM" line of the outlook message
* This is not the actual address that was sent from but the formated display of the user name.
* @return
* @throws ChunkNotFoundException
*/
public String getDisplayFrom() throws ChunkNotFoundException {
return getStringFromChunk(Chunks.getInstance().displayFromChunk);
}
/** /**
* Gets the display value of the "TO" line of the outlook message * Gets the display value of the "TO" line of the outlook message
* This is not the actual list of addresses/values that will be sent to if you click Reply in the email. * This is not the actual list of addresses/values that will be sent to if you click Reply in the email.

View File

@ -29,6 +29,7 @@ public class Chunks {
public StringChunk textBodyChunk = new StringChunk(0x1000); //BODY Chunk, for plain/text messages public StringChunk textBodyChunk = new StringChunk(0x1000); //BODY Chunk, for plain/text messages
public StringChunk subjectChunk = new StringChunk(0x0037); //Subject link chunk, in plain/text public StringChunk subjectChunk = new StringChunk(0x0037); //Subject link chunk, in plain/text
public StringChunk displayToChunk = new StringChunk(0x0E04); //Value that is in the TO field (not actually the addresses as they are stored in recip directory nodes public StringChunk displayToChunk = new StringChunk(0x0E04); //Value that is in the TO field (not actually the addresses as they are stored in recip directory nodes
public StringChunk displayFromChunk = new StringChunk(0x0C1A); //Value that is in the FROM field
public StringChunk displayCCChunk = new StringChunk(0x0E03); //value that shows in the CC field public StringChunk displayCCChunk = new StringChunk(0x0E03); //value that shows in the CC field
public StringChunk displayBCCChunk = new StringChunk(0x0E02); //Value that shows in the BCC field public StringChunk displayBCCChunk = new StringChunk(0x0E02); //Value that shows in the BCC field
public StringChunk conversationTopic = new StringChunk(0x0070); //Sort of like the subject line, but without the RE: and FWD: parts. public StringChunk conversationTopic = new StringChunk(0x0070); //Sort of like the subject line, but without the RE: and FWD: parts.

View File

@ -70,7 +70,7 @@ public class Date extends NumericFunction {
c.set(year, month, day, 0, 0, 0); c.set(year, month, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0); c.set(Calendar.MILLISECOND, 0);
return new NumberEval(HSSFDateUtil.getExcelDate(c.getTime())); return new NumberEval(HSSFDateUtil.getExcelDate(c.getTime(), false)); // XXX fix 1900/1904 problem
} }
} }

View File

@ -46,7 +46,7 @@ srcCellRow, srcCellCol);
if (ve instanceof NumericValueEval) { if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve; NumericValueEval ne = (NumericValueEval) ve;
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) { if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue()); java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
java.util.Calendar c = java.util.Calendar.getInstance(); java.util.Calendar c = java.util.Calendar.getInstance();
c.setTime(d); c.setTime(d);
retval = new NumberEval(c.get(java.util.Calendar.DAY_OF_MONTH)); retval = new NumberEval(c.get(java.util.Calendar.DAY_OF_MONTH));

View File

@ -20,6 +20,80 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
public class Mid extends NotImplementedFunction { import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* An implementation of the MID function:
* Returns a specific number of characters from a text string,
* starting at the position you specify, based on the number
* of characters you specify.
* @author Manda Wilson &lt; wilson at c bio dot msk cc dot org &gt;
*/
public class Mid extends TextFunction {
/**
* Returns a specific number of characters from a text string,
* starting at the position you specify, based on the number
* of characters you specify.
*
* @see org.apache.poi.hssf.record.formula.eval.Eval
*/
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
Eval retval = null;
String str = null;
int startNum = 0;
int numChars = 0;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
case 3:
// first operand is text string containing characters to extract
// second operand is position of first character to extract
// third operand is the number of characters to return
ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
if (firstveval instanceof StringValueEval
&& secondveval instanceof NumericValueEval
&& thirdveval instanceof NumericValueEval) {
StringValueEval strEval = (StringValueEval) firstveval;
str = strEval.getStringValue();
NumericValueEval startNumEval = (NumericValueEval) secondveval;
// NOTE: it is safe to cast to int here
// because in Excel =MID("test", 1, 1.7) returns t
// so 1.7 must be truncated to 1
// and =MID("test", 1.9, 2) returns te
// so 1.9 must be truncated to 1
startNum = (int) startNumEval.getNumberValue();
NumericValueEval numCharsEval = (NumericValueEval) thirdveval;
numChars = (int) numCharsEval.getNumberValue();
} else {
retval = ErrorEval.VALUE_INVALID;
}
}
if (retval == null) {
if (startNum < 1 || numChars < 0) {
retval = ErrorEval.VALUE_INVALID;
} else if (startNum > str.length() || numChars == 0) {
retval = BlankEval.INSTANCE;
} else if (startNum + numChars > str.length()) {
retval = new StringEval(str.substring(startNum - 1));
} else {
retval = new StringEval(str.substring(startNum - 1, numChars));
}
}
return retval;
}
} }

View File

@ -50,7 +50,7 @@ public class Month extends NumericFunction {
if (ve instanceof NumericValueEval) { if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve; NumericValueEval ne = (NumericValueEval) ve;
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) { if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue()); java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
retval = new NumberEval(d.getMonth()+1); retval = new NumberEval(d.getMonth()+1);
} else { } else {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;

View File

@ -20,6 +20,93 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
public class Replace extends NotImplementedFunction { import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* An implementation of the REPLACE function:
* Replaces part of a text string based on the number of characters
* you specify, with another text string.
* @author Manda Wilson &lt; wilson at c bio dot msk cc dot org &gt;
*/
public class Replace extends TextFunction {
/**
* Replaces part of a text string based on the number of characters
* you specify, with another text string.
*
* @see org.apache.poi.hssf.record.formula.eval.Eval
*/
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
Eval retval = null;
String oldStr = null;
String newStr = null;
int startNum = 0;
int numChars = 0;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
case 4:
// first operand is text string containing characters to replace
// second operand is position of first character to replace
// third operand is the number of characters in the old string
// you want to replace with new string
// fourth operand is the new string
ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
ValueEval fourthveval = singleOperandEvaluate(operands[3], srcCellRow, srcCellCol);
if (firstveval instanceof StringValueEval
&& secondveval instanceof NumericValueEval
&& thirdveval instanceof NumericValueEval
&& fourthveval instanceof StringValueEval) {
StringValueEval oldStrEval = (StringValueEval) firstveval;
oldStr = oldStrEval.getStringValue();
NumericValueEval startNumEval = (NumericValueEval) secondveval;
// NOTE: it is safe to cast to int here
// because in Excel =REPLACE("task", 2.7, 3, "est")
// returns test
// so 2.7 must be truncated to 2
// and =REPLACE("task", 1, 1.9, "") returns ask
// so 1.9 must be truncated to 1
startNum = (int) startNumEval.getNumberValue();
NumericValueEval numCharsEval = (NumericValueEval) thirdveval;
numChars = (int) numCharsEval.getNumberValue();
StringValueEval newStrEval = (StringValueEval) fourthveval;
newStr = newStrEval.getStringValue();
} else {
retval = ErrorEval.VALUE_INVALID;
}
}
if (retval == null) {
if (startNum < 1 || numChars < 0) {
retval = ErrorEval.VALUE_INVALID;
} else {
StringBuffer strBuff = new StringBuffer(oldStr);
// remove any characters that should be replaced
if (startNum <= oldStr.length() && numChars != 0) {
strBuff.delete(startNum - 1, startNum - 1 + numChars);
}
// now insert (or append) newStr
if (startNum > strBuff.length()) {
strBuff.append(newStr);
} else {
strBuff.insert(startNum - 1, newStr);
}
retval = new StringEval(strBuff.toString());
}
}
return retval;
}
} }

View File

@ -20,6 +20,98 @@
*/ */
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
public class Substitute extends NotImplementedFunction { import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* An implementation of the SUBSTITUTE function:
* Substitutes text in a text string with new text, some number of times.
* @author Manda Wilson &lt; wilson at c bio dot msk cc dot org &gt;
*/
public class Substitute extends TextFunction {
private static final int REPLACE_ALL = -1;
/**
*Substitutes text in a text string with new text, some number of times.
*
* @see org.apache.poi.hssf.record.formula.eval.Eval
*/
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
Eval retval = null;
String oldStr = null;
String searchStr = null;
String newStr = null;
int numToReplace = REPLACE_ALL;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
case 4:
ValueEval fourthveval = singleOperandEvaluate(operands[3], srcCellRow, srcCellCol);
if (fourthveval instanceof NumericValueEval) {
NumericValueEval numToReplaceEval = (NumericValueEval) fourthveval;
// NOTE: it is safe to cast to int here
// because in Excel =SUBSTITUTE("teststr","t","T",1.9)
// returns Teststr
// so 1.9 must be truncated to 1
numToReplace = (int) numToReplaceEval.getNumberValue();
} else {
retval = ErrorEval.VALUE_INVALID;
}
case 3:
// first operand is text string containing characters to replace
// second operand is text to find
// third operand is replacement text
ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
if (firstveval instanceof StringValueEval
&& secondveval instanceof StringValueEval
&& thirdveval instanceof StringValueEval) {
StringValueEval oldStrEval = (StringValueEval) firstveval;
oldStr = oldStrEval.getStringValue();
StringValueEval searchStrEval = (StringValueEval) secondveval;
searchStr = searchStrEval.getStringValue();
StringValueEval newStrEval = (StringValueEval) thirdveval;
newStr = newStrEval.getStringValue();
} else {
retval = ErrorEval.VALUE_INVALID;
}
}
if (retval == null) {
if (numToReplace != REPLACE_ALL && numToReplace < 1) {
retval = ErrorEval.VALUE_INVALID;
} else if (searchStr.length() == 0) {
retval = new StringEval(oldStr);
} else {
StringBuffer strBuff = new StringBuffer();
int startIndex = 0;
int nextMatch = -1;
for (int leftToReplace = numToReplace;
(leftToReplace > 0 || numToReplace == REPLACE_ALL)
&& (nextMatch = oldStr.indexOf(searchStr, startIndex)) != -1;
leftToReplace--) {
// store everything from end of last match to start of this match
strBuff.append(oldStr.substring(startIndex, nextMatch));
strBuff.append(newStr);
startIndex = nextMatch + searchStr.length();
}
// store everything from end of last match to end of string
if (startIndex < oldStr.length()) {
strBuff.append(oldStr.substring(startIndex));
}
retval = new StringEval(strBuff.toString());
}
}
return retval;
}
} }

View File

@ -14,12 +14,62 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/*
* Created on May 15, 2005
*
*/
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
public class Trim extends NotImplementedFunction { import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.StringValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* An implementation of the TRIM function:
* Removes leading and trailing spaces from value if evaluated operand
* value is string.
* @author Manda Wilson &lt; wilson at c bio dot msk cc dot org &gt;
*/
public class Trim extends TextFunction {
/**
* Removes leading and trailing spaces from value if evaluated
* operand value is string.
* Returns StringEval only if evaluated operand is of type string
* (and is not blank or null) or number. If evaluated operand is
* of type string and is blank or null, or if evaluated operand is
* of type blank, returns BlankEval. Otherwise returns ErrorEval.
*
* @see org.apache.poi.hssf.record.formula.eval.Eval
*/
public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
Eval retval = ErrorEval.VALUE_INVALID;
String str = null;
switch (operands.length) {
default:
break;
case 1:
ValueEval veval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
if (veval instanceof StringValueEval) {
StringValueEval sve = (StringValueEval) veval;
str = sve.getStringValue();
if (str == null || str.trim().equals("")) {
return BlankEval.INSTANCE;
}
}
else if (veval instanceof NumberEval) {
NumberEval neval = (NumberEval) veval;
str = neval.getStringValue();
}
else if (veval instanceof BlankEval) {
return BlankEval.INSTANCE;
}
}
if (str != null) {
retval = new StringEval(str.trim());
}
return retval;
}
} }

View File

@ -51,7 +51,7 @@ public class Year extends NumericFunction {
if (ve instanceof NumericValueEval) { if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve; NumericValueEval ne = (NumericValueEval) ve;
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) { if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue()); java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
retval = new NumberEval(d.getYear()+1900); retval = new NumberEval(d.getYear()+1900);
} else { } else {
retval = ErrorEval.NUM_ERROR; retval = ErrorEval.NUM_ERROR;

View File

@ -19,6 +19,8 @@
package org.apache.poi.hwpf.model; package org.apache.poi.hwpf.model;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.hwpf.model.io.*; import org.apache.poi.hwpf.model.io.*;
@ -37,6 +39,7 @@ public class ListTables
{ {
private static final int LIST_DATA_SIZE = 28; private static final int LIST_DATA_SIZE = 28;
private static final int LIST_FORMAT_OVERRIDE_SIZE = 16; private static final int LIST_FORMAT_OVERRIDE_SIZE = 16;
private static POILogger log = POILogFactory.getLogger(ListTables.class);
HashMap _listMap = new HashMap(); HashMap _listMap = new HashMap();
ArrayList _overrideList = new ArrayList(); ArrayList _overrideList = new ArrayList();
@ -189,8 +192,13 @@ public class ListTables
public ListLevel getLevel(int listID, int level) public ListLevel getLevel(int listID, int level)
{ {
ListData lst = (ListData)_listMap.get(new Integer(listID)); ListData lst = (ListData)_listMap.get(new Integer(listID));
if(level < lst.numLevels()) {
ListLevel lvl = lst.getLevels()[level]; ListLevel lvl = lst.getLevels()[level];
return lvl; return lvl;
} else {
log.log(POILogger.WARN, "Requested level " + level + " which was greater than the maximum defined (" + lst.numLevels() + ")");
return null;
}
} }
public ListData getListData(int listID) public ListData getListData(int listID)

View File

@ -148,7 +148,9 @@ public class TableSprmUncompressor
for (int x = 0; x < itcMac; x++) for (int x = 0; x < itcMac; x++)
{ {
if(hasTCs) rgtc[x] = TableCellDescriptor.convertBytesToTC(grpprl, // Sometimes, the grpprl does not contain data at every offset. I have no idea why this happens.
if(hasTCs && offset + (1 + ( (itcMac + 1) * 2) + (x * 20)) < grpprl.length)
rgtc[x] = TableCellDescriptor.convertBytesToTC(grpprl,
offset + (1 + ( (itcMac + 1) * 2) + (x * 20))); offset + (1 + ( (itcMac + 1) * 2) + (x * 20)));
else else
rgtc[x] = new TableCellDescriptor(); rgtc[x] = new TableCellDescriptor();

View File

@ -23,21 +23,28 @@ import org.apache.poi.hwpf.model.ListFormatOverrideLevel;
import org.apache.poi.hwpf.model.ListLevel; import org.apache.poi.hwpf.model.ListLevel;
import org.apache.poi.hwpf.model.ListTables; import org.apache.poi.hwpf.model.ListTables;
import org.apache.poi.hwpf.model.PAPX; import org.apache.poi.hwpf.model.PAPX;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.hwpf.sprm.SprmBuffer; import org.apache.poi.util.POILogger;
public class ListEntry public class ListEntry
extends Paragraph extends Paragraph
{ {
private static POILogger log = POILogFactory.getLogger(ListEntry.class);
ListLevel _level; ListLevel _level;
ListFormatOverrideLevel _overrideLevel; ListFormatOverrideLevel _overrideLevel;
ListEntry(PAPX papx, Range parent, ListTables tables) ListEntry(PAPX papx, Range parent, ListTables tables)
{ {
super(papx, parent); super(papx, parent);
if(tables != null) {
ListFormatOverride override = tables.getOverride(_props.getIlfo()); ListFormatOverride override = tables.getOverride(_props.getIlfo());
_overrideLevel = override.getOverrideLevel(_props.getIlvl()); _overrideLevel = override.getOverrideLevel(_props.getIlvl());
_level = tables.getLevel(override.getLsid(), _props.getIlvl()); _level = tables.getLevel(override.getLsid(), _props.getIlvl());
} else {
log.log(POILogger.WARN, "No ListTables found for ListEntry - document probably partly corrupt, and you may experience problems");
}
} }
public int type() public int type()

Binary file not shown.

View File

@ -25,6 +25,7 @@ import org.apache.poi.hslf.model.Shape;
import java.io.*; import java.io.*;
import java.util.HashSet; import java.util.HashSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.ArrayList;
import java.awt.*; import java.awt.*;
/** /**
@ -298,4 +299,35 @@ public class TestBugs extends TestCase {
} }
/**
* Bug 38256: RuntimeException: Couldn't instantiate the class for type with id 0.
* ( also fixed followup: getTextRuns() returns no text )
*/
public void test43781 () throws Exception {
FileInputStream is = new FileInputStream(new File(cwd, "43781.ppt"));
SlideShow ppt = new SlideShow(is);
is.close();
assertTrue("No Exceptions while reading file", true);
Slide slide = ppt.getSlides()[0];
TextRun[] tr1 = slide.getTextRuns();
ArrayList lst = new ArrayList();
Shape[] shape = slide.getShapes();
for (int i = 0; i < shape.length; i++) {
if( shape[i] instanceof TextBox){
TextRun textRun = ((TextBox)shape[i]).getTextRun();
if(textRun != null) lst.add(textRun);
}
}
TextRun[] tr2 = new TextRun[lst.size()];
lst.toArray(tr2);
assertEquals(tr1.length, tr2.length);
for (int i = 0; i < tr1.length; i++) {
assertEquals(tr1[i].getText(), tr2[i].getText());
}
}
} }

View File

@ -83,6 +83,21 @@ public class TestBlankFileRead extends TestCase {
TestCase.assertEquals(obtained, expected); TestCase.assertEquals(obtained, expected);
} }
/**
* Test to see if we can read the FROM Chunk.
* @throws ChunkNotFoundException
*
*/
public void testReadDisplayFrom() throws ChunkNotFoundException {
try {
mapiMessage.getDisplayFrom();
} catch(ChunkNotFoundException exp) {
return;
}
TestCase.fail("Should have thrown a ChunkNotFoundException but didn't");
}
/** /**
* Test to see if we can read the CC Chunk. * Test to see if we can read the CC Chunk.
* @throws ChunkNotFoundException * @throws ChunkNotFoundException

View File

@ -66,6 +66,18 @@ private MAPIMessage mapiMessage;
TestCase.assertEquals(obtained, expected); TestCase.assertEquals(obtained, expected);
} }
/**
* Test to see if we can read the From Chunk.
* @throws ChunkNotFoundException
*
*/
public void testReadDisplayFrom() throws ChunkNotFoundException {
String obtained = mapiMessage.getDisplayFrom();
String expected = "Travis Ferguson";
TestCase.assertEquals(obtained, expected);
}
/** /**
* Test to see if we can read the CC Chunk. * Test to see if we can read the CC Chunk.
* @throws ChunkNotFoundException * @throws ChunkNotFoundException

View File

@ -23,27 +23,37 @@ package org.apache.poi.hssf.record.formula.eval;
import junit.framework.TestSuite; import junit.framework.TestSuite;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * This is a test of all the Eval functions we have implemented.
* Add newly implemented Eval functions in here to have them
* tested.
* For newly implemented functions,
* @see org.apache.poi.hssf.record.formula.functions.TestEverything
* *
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*/ */
public class TestEverything extends TestSuite { public class TestEverything extends TestSuite {
public static TestSuite suite() throws Exception { public static TestSuite suite() throws Exception {
TestSuite suite = new TestSuite("Tests for OperationEval concrete implementation classes."); TestSuite suite = new TestSuite("Tests for OperationEval concrete implementation classes.");
suite.addTest(new GenericFormulaTestCase("D23")); suite.addTest(new GenericFormulaTestCase("D23")); // Add
suite.addTest(new GenericFormulaTestCase("D27")); suite.addTest(new GenericFormulaTestCase("D27")); // ConcatEval
suite.addTest(new GenericFormulaTestCase("D31")); suite.addTest(new GenericFormulaTestCase("D31")); // DivideEval
suite.addTest(new GenericFormulaTestCase("D35")); suite.addTest(new GenericFormulaTestCase("D35")); // EqualEval
suite.addTest(new GenericFormulaTestCase("D39")); suite.addTest(new GenericFormulaTestCase("D39")); // GreaterEqualEval
suite.addTest(new GenericFormulaTestCase("D43")); suite.addTest(new GenericFormulaTestCase("D43")); // GreaterThanEval
suite.addTest(new GenericFormulaTestCase("D47")); suite.addTest(new GenericFormulaTestCase("D47")); // LessEqualEval
suite.addTest(new GenericFormulaTestCase("D51")); suite.addTest(new GenericFormulaTestCase("D51")); // LessThanEval
suite.addTest(new GenericFormulaTestCase("D55")); suite.addTest(new GenericFormulaTestCase("D55")); // MultiplyEval
suite.addTest(new GenericFormulaTestCase("D59")); suite.addTest(new GenericFormulaTestCase("D59")); // NotEqualEval
suite.addTest(new GenericFormulaTestCase("D63")); suite.addTest(new GenericFormulaTestCase("D63")); // PowerEval
suite.addTest(new GenericFormulaTestCase("D67")); suite.addTest(new GenericFormulaTestCase("D67")); // SubtractEval
suite.addTest(new GenericFormulaTestCase("D71")); suite.addTest(new GenericFormulaTestCase("D71")); // UnaryMinusEval
suite.addTest(new GenericFormulaTestCase("D75")); suite.addTest(new GenericFormulaTestCase("D75")); // UnaryPlusEval
// Add newly implemented Eval functions here
// (Formula functions go in
// @see org.apache.poi.hssf.record.formula.functions.TestEverything )
return suite; return suite;
} }
} }

View File

@ -25,11 +25,16 @@ import org.apache.poi.hssf.record.formula.eval.GenericFormulaTestCase;
import junit.framework.TestSuite; import junit.framework.TestSuite;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * This is a test of all the normal formula functions we have implemented.
* It should pick up newly implemented functions which are correctly added
* to the test formula excel file, but tweak the rows below if you
* add any past the end of what's currently checked.
* For newly implemented eval functions,
* @see org.apache.poi.hssf.record.formula.eval.TestEverything
* *
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*/ */
public class TestEverything extends TestSuite { public class TestEverything extends TestSuite {
public static TestSuite suite() throws Exception { public static TestSuite suite() throws Exception {
TestSuite suite = new TestSuite("Tests for individual function classes"); TestSuite suite = new TestSuite("Tests for individual function classes");
String s; String s;

View File

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.poi.hwpf.usermodel;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.StyleSheet;
import org.apache.poi.hwpf.model.TextPiece;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.util.LittleEndian;
import junit.framework.TestCase;
/**
* Test various problem documents
*
* @author Nick Burch (nick at torchbox dot com)
*/
public class TestProblems extends TestCase {
private String dirname = System.getProperty("HWPF.testdata.path");
protected void setUp() throws Exception {
}
/**
* ListEntry passed no ListTable
*/
public void testListEntryNoListTable() throws Exception {
HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/ListEntryNoListTable.doc"));
Range r = doc.getRange();
StyleSheet styleSheet = doc.getStyleSheet();
for (int x = 0; x < r.numSections(); x++) {
Section s = r.getSection(x);
for (int y = 0; y < s.numParagraphs(); y++) {
Paragraph paragraph = s.getParagraph(y);
//System.out.println(paragraph.getCharacterRun(0).text());
}
}
}
/**
* AIOOB for TableSprmUncompressor.unCompressTAPOperation
*/
public void testSprmAIOOB() throws Exception {
HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/AIOOB-Tap.doc"));
Range r = doc.getRange();
StyleSheet styleSheet = doc.getStyleSheet();
for (int x = 0; x < r.numSections(); x++) {
Section s = r.getSection(x);
for (int y = 0; y < s.numParagraphs(); y++) {
Paragraph paragraph = s.getParagraph(y);
//System.out.println(paragraph.getCharacterRun(0).text());
}
}
}
}

Binary file not shown.

Binary file not shown.

View File

@ -68,6 +68,19 @@ public class TestExcelExtractor extends TestCase {
); );
} }
public void testwithContinueRecords() throws Exception {
String path = System.getProperty("HSSF.testdata.path");
FileInputStream fin = new FileInputStream(path + File.separator + "StringContinueRecords.xls");
ExcelExtractor extractor = new ExcelExtractor(new POIFSFileSystem(fin));
extractor.getText();
// Has masses of text
// Until we fixed bug #41064, this would've
// failed by now
assertTrue(extractor.getText().length() > 40960);
}
public void testStringConcat() throws Exception { public void testStringConcat() throws Exception {
String path = System.getProperty("HSSF.testdata.path"); String path = System.getProperty("HSSF.testdata.path");

View File

@ -0,0 +1,910 @@
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.hssf.util.*;
import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;
/**
* <p>Title: TestDataValidation</p>
* <p>Description: Class for testing Excel's data validation mechanism
* Second test :
* -
* </p>
* @author Dragos Buleandra ( dragos.buleandra@trade2b.ro )
*/
public class TestDataValidation extends TestCase
{
public TestDataValidation(String name)
{
super(name);
}
protected void setUp()
{
String filename = System.getProperty("HSSF.testdata.path");
if (filename == null)
{
System.setProperty("HSSF.testdata.path", "src/testcases/org/apache/poi/hssf/data");
}
}
public void testDataValidation() throws Exception
{
System.out.println("\nTest no. 2 - Test Excel's Data validation mechanism");
String resultFile = System.getProperty("HSSF.testdata.path")+"/TestDataValidation.xls";
HSSFWorkbook wb = new HSSFWorkbook();
HSSFCellStyle style_1 = this.createStyle( wb, HSSFCellStyle.ALIGN_LEFT );
HSSFCellStyle style_2 = this.createStyle( wb, HSSFCellStyle.ALIGN_CENTER );
HSSFCellStyle style_3 = this.createStyle( wb, HSSFCellStyle.ALIGN_CENTER, HSSFColor.GREY_25_PERCENT.index, true );
HSSFCellStyle style_4 = this.createHeaderStyle(wb);
HSSFDataValidation data_validation = null;
//data validation's number types
System.out.print(" Create sheet for Data Validation's number types ... ");
HSSFSheet fSheet = wb.createSheet("Number types");
//"Whole number" validation type
this.createDVTypeRow( wb, 0, style_3, "Whole number");
this.createHeaderRow( wb, 0, style_4 );
short start_row = (short)fSheet.getPhysicalNumberOfRows();
data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_INTEGER);
data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
data_validation.setFirstFormula("2");
data_validation.setSecondFormula("6");
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)(start_row+1));
data_validation.setLastRow((short)(start_row+1));
data_validation.setEmptyCellAllowed(false);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
data_validation.setFirstRow((short)(start_row+2));
data_validation.setLastRow((short)(start_row+2));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
data_validation.setFirstRow((short)(start_row+3));
data_validation.setLastRow((short)(start_row+3));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+4));
data_validation.setLastRow((short)(start_row+4));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+5));
data_validation.setLastRow((short)(start_row+5));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+6));
data_validation.setLastRow((short)(start_row+6));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
data_validation.setShowErrorBox(true);
data_validation.setFirstFormula("4");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)(start_row+7));
data_validation.setLastRow((short)(start_row+7));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("4");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false );
this.writeOtherSettings( fSheet, style_1, "-" );
//"Decimal" validation type
this.createDVTypeRow( wb, 0, style_3, "Decimal");
this.createHeaderRow( wb, 0, style_4 );
start_row += (short)(8+4);
data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_DECIMAL);
data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
data_validation.setFirstFormula("2");
data_validation.setSecondFormula("6");
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)(start_row+1));
data_validation.setLastRow((short)(start_row+1));
data_validation.setEmptyCellAllowed(false);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
data_validation.setFirstRow((short)(start_row+2));
data_validation.setLastRow((short)(start_row+2));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
data_validation.setFirstRow((short)(start_row+3));
data_validation.setLastRow((short)(start_row+3));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+4));
data_validation.setLastRow((short)(start_row+4));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+5));
data_validation.setLastRow((short)(start_row+5));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+6));
data_validation.setLastRow((short)(start_row+6));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
data_validation.setShowErrorBox(true);
data_validation.setFirstFormula("4");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)(start_row+7));
data_validation.setLastRow((short)(start_row+7));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("4");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false );
this.writeOtherSettings( fSheet, style_1, "-" );
System.out.println("done !");
//"List" Data Validation type
/** @todo List*/
System.out.print(" Create sheet for 'List' Data Validation type ... ");
fSheet = wb.createSheet("Lists");
this.createDVTypeRow( wb, 1, style_3, "Explicit lists - list items are explicitly provided");
this.createDVDeescriptionRow( wb, 1, style_3, "Disadvantage - sum of item's length should be less than 255 characters");
this.createHeaderRow( wb, 1, style_4 );
start_row = (short)fSheet.getPhysicalNumberOfRows();
data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
data_validation.setFirstFormula("1+2+3");
data_validation.setSecondFormula(null);
data_validation.setSurppressDropDownArrow(false);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", true, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" );
data_validation = new HSSFDataValidation((short)(start_row+1),(short)0,(short)(start_row+1),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
data_validation.setFirstFormula("4+5+6+7");
data_validation.setSecondFormula(null);
data_validation.setSurppressDropDownArrow(false);
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", false, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" );
data_validation = new HSSFDataValidation((short)(start_row+2),(short)0,(short)(start_row+2),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
data_validation.setFirstFormula("7+21");
data_validation.setSecondFormula(null);
data_validation.setSurppressDropDownArrow(true);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", true, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" );
data_validation = new HSSFDataValidation((short)(start_row+3),(short)0,(short)(start_row+3),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
data_validation.setFirstFormula("8/2");
data_validation.setSecondFormula(null);
data_validation.setSurppressDropDownArrow(true);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "POIFS,HSSF,HWPF,HPSF", false, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" );
this.createDVTypeRow( wb, 1, style_3, "Reference lists - list items are taken from others cells");
this.createDVDeescriptionRow( wb, 1, style_3, "Advantage - no restriction regarding the sum of item's length");
this.createHeaderRow( wb, 1, style_4 );
start_row += (short)(4+5);
String cellStrValue = "a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+
"a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+
"a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 "+
"a b c d e f g h i j k l m n o p r s t u v x y z w 0 1 2 3 4 ";
String strFormula = "$A$100:$A$120";
data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
data_validation.setFirstFormula(strFormula);
data_validation.setSecondFormula(null);
data_validation.setSurppressDropDownArrow(false);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, true, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" );
data_validation = new HSSFDataValidation((short)(start_row+1),(short)0,(short)(start_row+1),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
data_validation.setFirstFormula(strFormula);
data_validation.setSecondFormula(null);
data_validation.setSurppressDropDownArrow(false);
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, false, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=yes" );
data_validation = new HSSFDataValidation((short)(start_row+2),(short)0,(short)(start_row+2),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
data_validation.setFirstFormula(strFormula);
data_validation.setSecondFormula(null);
data_validation.setSurppressDropDownArrow(true);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, true, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" );
data_validation = new HSSFDataValidation((short)(start_row+3),(short)0,(short)(start_row+3),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_LIST);
data_validation.setFirstFormula(strFormula);
data_validation.setSecondFormula(null);
data_validation.setSurppressDropDownArrow(true);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, strFormula, false, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type=STOP ; In-cell dropdown=no" );
for (int i=100; i<=120; i++)
{
HSSFRow currRow = fSheet.createRow(i);
currRow.createCell((short)0).setCellValue(cellStrValue);
// currRow.hide( true );
}
System.out.println("done !");
//Date/Time Validation type
System.out.print(" Create sheet for 'Date' and 'Time' Data Validation types ... ");
fSheet = wb.createSheet("Date_Time");
SimpleDateFormat df = new SimpleDateFormat("m/d/yyyy");
HSSFDataFormat dataFormat = wb.createDataFormat();
short fmtDate = dataFormat.getFormat("m/d/yyyy");
short fmtTime = dataFormat.getFormat("h:mm");
HSSFCellStyle cellStyle_data = wb.createCellStyle();
cellStyle_data.setDataFormat(fmtDate);
HSSFCellStyle cellStyle_time = wb.createCellStyle();
cellStyle_time.setDataFormat(fmtTime);
this.createDVTypeRow( wb, 2, style_3, "Date ( cells are already formated as date - m/d/yyyy)");
this.createHeaderRow( wb, 2, style_4 );
start_row = (short)fSheet.getPhysicalNumberOfRows();
data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_DATE);
data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
data_validation.setFirstFormula( String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("1/2/2004"))) );
data_validation.setSecondFormula( String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("1/6/2004"))) );
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 1/2/2004 and 1/6/2004 ", true, true, true );
this.setCellFormat( fSheet, cellStyle_data );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)(start_row+1));
data_validation.setLastRow((short)(start_row+1));
data_validation.setEmptyCellAllowed(false);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 1/2/2004 and 1/6/2004 ", false, true, true );
this.setCellFormat( fSheet, cellStyle_data );
this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
data_validation.setFirstRow((short)(start_row+2));
data_validation.setLastRow((short)(start_row+2));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3/2/2004", false, false, true );
this.setCellFormat( fSheet, cellStyle_data );
this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
data_validation.setFirstRow((short)(start_row+3));
data_validation.setLastRow((short)(start_row+3));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3/2/2004", false, false, false );
this.setCellFormat( fSheet, cellStyle_data );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+4));
data_validation.setLastRow((short)(start_row+4));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3/2/2004", true, false, false );
this.setCellFormat( fSheet, cellStyle_data );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+5));
data_validation.setLastRow((short)(start_row+5));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3/2/2004", true, true, false );
this.setCellFormat( fSheet, cellStyle_data );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+6));
data_validation.setLastRow((short)(start_row+6));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
data_validation.setShowErrorBox(true);
data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/2/2004"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 3/2/2004", true, false, true );
this.setCellFormat( fSheet, cellStyle_data );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)(start_row+7));
data_validation.setLastRow((short)(start_row+7));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("3/4/2004"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 3/4/2004", false, true, false );
this.setCellFormat( fSheet, cellStyle_data );
this.writeOtherSettings( fSheet, style_1, "-" );
//"Time" validation type
this.createDVTypeRow( wb, 2, style_3, "Time ( cells are already formated as time - h:mm)");
this.createHeaderRow( wb, 2, style_4 );
df = new SimpleDateFormat("hh:mm");
start_row += (short)(8+4);
data_validation = new HSSFDataValidation((short)(start_row),(short)0,(short)(start_row),(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_TIME);
data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00"))));
data_validation.setSecondFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("16:00"))));
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 12:00 and 16:00 ", true, true, true );
this.setCellFormat( fSheet, cellStyle_time );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)(start_row+1));
data_validation.setLastRow((short)(start_row+1));
data_validation.setEmptyCellAllowed(false);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 12:00 and 16:00 ", false, true, true );
this.setCellFormat( fSheet, cellStyle_time );
this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
data_validation.setFirstRow((short)(start_row+2));
data_validation.setLastRow((short)(start_row+2));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setFirstFormula(String.valueOf((int)HSSFDateUtil.getExcelDate(df.parse("13:35"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 13:35", false, false, true );
this.setCellFormat( fSheet, cellStyle_time );
this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
data_validation.setFirstRow((short)(start_row+3));
data_validation.setLastRow((short)(start_row+3));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("13:35"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 13:35", false, false, false );
this.setCellFormat( fSheet, cellStyle_time );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+4));
data_validation.setLastRow((short)(start_row+4));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 12:00", true, false, false );
this.setCellFormat( fSheet, cellStyle_time );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+5));
data_validation.setLastRow((short)(start_row+5));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("12:00"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 12:00", true, true, false );
this.setCellFormat( fSheet, cellStyle_time );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)(start_row+6));
data_validation.setLastRow((short)(start_row+6));
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
data_validation.setShowErrorBox(true);
data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("14:00"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 14:00", true, false, true );
this.setCellFormat( fSheet, cellStyle_time );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)(start_row+7));
data_validation.setLastRow((short)(start_row+7));
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula(String.valueOf(HSSFDateUtil.getExcelDate(df.parse("14:00"))));
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 14:00", false, true, false );
this.setCellFormat( fSheet, cellStyle_time );
this.writeOtherSettings( fSheet, style_1, "-" );
System.out.println("done !");
//"Text length" validation type
System.out.print(" Create sheet for 'Text length' Data Validation type... ");
fSheet = wb.createSheet("Text length");
this.createHeaderRow( wb, 3, style_4 );
data_validation = new HSSFDataValidation((short)1,(short)0,(short)1,(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_TEXT_LENGTH);
data_validation.setOperator(HSSFDataValidation.OPERATOR_BETWEEN);
data_validation.setFirstFormula("2");
data_validation.setSecondFormula("6");
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Between 2 and 6 ", true, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)2);
data_validation.setLastRow((short)2);
data_validation.setEmptyCellAllowed(false);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_BETWEEN);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_INFO);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not between 2 and 6 ", false, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = INFO" );
data_validation.setFirstRow((short)3);
data_validation.setLastRow((short)3);
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_EQUAL);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Equal to 3", false, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
data_validation.setFirstRow((short)4);
data_validation.setLastRow((short)4);
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_NOT_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Not equal to 3", false, false, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)5);
data_validation.setLastRow((short)5);
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than 3", true, false, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)6);
data_validation.setLastRow((short)6);
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("3");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_THAN);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than 3", true, true, false );
this.writeOtherSettings( fSheet, style_1, "-" );
data_validation.setFirstRow((short)7);
data_validation.setLastRow((short)7);
data_validation.setEmptyCellAllowed(true);
data_validation.setShowPromptBox(false);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_STOP);
data_validation.setShowErrorBox(true);
data_validation.setFirstFormula("4");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_GREATER_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Greater than or equal to 4", true, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation.setFirstRow((short)8);
data_validation.setLastRow((short)8);
data_validation.setEmptyCellAllowed(false);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(false);
data_validation.setFirstFormula("4");
data_validation.setSecondFormula(null);
data_validation.setOperator(HSSFDataValidation.OPERATOR_LESS_OR_EQUAL);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "Less than or equal to 4", false, true, false );
this.writeOtherSettings( fSheet, style_1, "-" );
System.out.println("done !");
//Custom Validation type
System.out.print(" Create sheet for 'Custom' Data Validation type ... ");
fSheet = wb.createSheet("Custom");
this.createHeaderRow( wb, 4, style_4 );
data_validation = new HSSFDataValidation((short)1,(short)0,(short)1,(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_FORMULA);
data_validation.setFirstFormula("ISNUMBER($A2)");
data_validation.setSecondFormula(null);
data_validation.setShowPromptBox(true);
data_validation.setShowErrorBox(true);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.createPromptBox("Hi , dear user !", "So , you just selected me ! Thanks !");
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "ISNUMBER(A2)", true, true, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = STOP" );
data_validation = new HSSFDataValidation((short)2,(short)0,(short)2,(short)0);
data_validation.setDataValidationType(HSSFDataValidation.DATA_TYPE_FORMULA);
data_validation.setFirstFormula("IF(SUM(A2:A3)=5,TRUE,FALSE)");
data_validation.setSecondFormula(null);
data_validation.setShowPromptBox(false);
data_validation.setShowErrorBox(true);
data_validation.setErrorStyle(HSSFDataValidation.ERROR_STYLE_WARNING);
data_validation.createErrorBox("Invalid input !", "Something is wrong ; check condition !");
data_validation.setEmptyCellAllowed(false);
fSheet.addValidationData(data_validation);
this.writeDataValidationSettings( fSheet, style_1, style_2, "IF(SUM(A2:A3)=5,TRUE,FALSE)", false, false, true );
this.writeOtherSettings( fSheet, style_1, "Error box type = WARNING" );
System.out.println("done !");
//so , everything it's ok for now ; it remains for you to open the file
System.out.println("\n Everything it's ok since we've got so far -:) !\n"+
" In order to complete the test , it remains for you to open the file \n"+
" and see if there are four sheets , as described !");
System.out.println(" File was saved in \""+resultFile+"\"");
FileOutputStream fileOut = new FileOutputStream(resultFile);
wb.write(fileOut);
fileOut.close();
}
private void createDVTypeRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle, String strTypeDescription)
{
HSSFSheet sheet = wb.getSheetAt(sheetNo);
HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
row = sheet.createRow(sheet.getPhysicalNumberOfRows());
sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5));
HSSFCell cell = row.createCell((short)0);
cell.setCellValue(strTypeDescription);
cell.setCellStyle(cellStyle);
row = sheet.createRow(sheet.getPhysicalNumberOfRows());
}
private void createDVDeescriptionRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle, String strTypeDescription )
{
HSSFSheet sheet = wb.getSheetAt(sheetNo);
HSSFRow row = sheet.getRow(sheet.getPhysicalNumberOfRows()-1);
sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5));
HSSFCell cell = row.createCell((short)0);
cell.setCellValue(strTypeDescription);
cell.setCellStyle(cellStyle);
row = sheet.createRow(sheet.getPhysicalNumberOfRows());
}
private void createHeaderRow( HSSFWorkbook wb, int sheetNo , HSSFCellStyle cellStyle )
{
HSSFSheet sheet = wb.getSheetAt(sheetNo);
HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
row.setHeight((short)400);
for ( int i=0; i<6; i++ )
{
row.createCell((short)i).setCellStyle( cellStyle );
if ( i==2 || i==3 || i==4 )
{
sheet.setColumnWidth( (short) i, (short) 3500);
}
else if ( i== 5)
{
sheet.setColumnWidth( (short) i, (short) 10000);
}
else
{
sheet.setColumnWidth( (short) i, (short) 8000);
}
}
HSSFCell cell = row.getCell((short)0);
cell.setCellValue("Data validation cells");
cell = row.getCell((short)1);
cell.setCellValue("Condition");
cell = row.getCell((short)2);
cell.setCellValue("Allow blank");
cell = row.getCell((short)3);
cell.setCellValue("Prompt box");
cell = row.getCell((short)4);
cell.setCellValue("Error box");
cell = row.getCell((short)5);
cell.setCellValue("Other settings");
}
private HSSFCellStyle createHeaderStyle(HSSFWorkbook wb)
{
HSSFFont font = wb.createFont();
font.setColor( HSSFColor.WHITE.index );
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setFillForegroundColor(HSSFColor.BLUE_GREY.index);
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
cellStyle.setLeftBorderColor(HSSFColor.WHITE.index);
cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
cellStyle.setTopBorderColor(HSSFColor.WHITE.index);
cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
cellStyle.setRightBorderColor(HSSFColor.WHITE.index);
cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
cellStyle.setBottomBorderColor(HSSFColor.WHITE.index);
cellStyle.setFont(font);
return cellStyle;
}
private HSSFCellStyle createStyle( HSSFWorkbook wb, short h_align, short color, boolean bold )
{
HSSFFont font = wb.createFont();
if ( bold )
{
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
}
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setFont(font);
cellStyle.setFillForegroundColor(color);
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
cellStyle.setAlignment(h_align);
cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
return cellStyle;
}
private HSSFCellStyle createStyle( HSSFWorkbook wb, short h_align )
{
return this.createStyle(wb, h_align, HSSFColor.WHITE.index, false);
}
private void writeDataValidationSettings( HSSFSheet sheet, HSSFCellStyle style_1, HSSFCellStyle style_2, String strCondition, boolean allowEmpty, boolean inputBox, boolean errorBox )
{
HSSFRow row = sheet.createRow( sheet.getPhysicalNumberOfRows() );
//condition's string
HSSFCell cell = row.createCell((short)1);
cell.setCellStyle(style_1);
cell.setCellValue(strCondition);
//allow empty cells
cell = row.createCell((short)2);
cell.setCellStyle(style_2);
cell.setCellValue( ((allowEmpty) ? "yes" : "no") );
//show input box
cell = row.createCell((short)3);
cell.setCellStyle(style_2);
cell.setCellValue( ((inputBox) ? "yes" : "no") );
//show error box
cell = row.createCell((short)4);
cell.setCellStyle(style_2);
cell.setCellValue( ((errorBox) ? "yes" : "no") );
}
private void setCellFormat( HSSFSheet sheet, HSSFCellStyle cell_style )
{
HSSFRow row = sheet.getRow( sheet.getPhysicalNumberOfRows() -1 );
HSSFCell cell = row.createCell((short)0);
cell.setCellStyle(cell_style);
}
private void writeOtherSettings( HSSFSheet sheet, HSSFCellStyle style, String strStettings )
{
HSSFRow row = sheet.getRow( sheet.getPhysicalNumberOfRows() -1 );
HSSFCell cell = row.createCell((short)5);
cell.setCellStyle(style);
cell.setCellValue(strStettings);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(TestDataValidation.class);
}
}

View File

@ -44,6 +44,7 @@ import java.util.GregorianCalendar;
* paticular datatypes, etc. * paticular datatypes, etc.
* @author Andrew C. Oliver (andy at superlinksoftware dot com) * @author Andrew C. Oliver (andy at superlinksoftware dot com)
* @author Dan Sherman (dsherman at isisph.com) * @author Dan Sherman (dsherman at isisph.com)
* @author Alex Jacoby (ajacoby at gmail.com)
*/ */
public class TestHSSFCell public class TestHSSFCell
@ -111,7 +112,7 @@ extends TestCase {
* is working properly. Conversion of the date is also an issue, * is working properly. Conversion of the date is also an issue,
* but there's a separate unit test for that. * but there's a separate unit test for that.
*/ */
public void testDateWindowing() throws Exception { public void testDateWindowingRead() throws Exception {
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000 GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000
Date date = cal.getTime(); Date date = cal.getTime();
String path = System.getProperty("HSSF.testdata.path"); String path = System.getProperty("HSSF.testdata.path");
@ -143,6 +144,70 @@ extends TestCase {
stream.close(); stream.close();
} }
/**
* Checks that dates are properly written to both types of files:
* those with 1900 and 1904 date windowing. Note that if the
* previous test ({@link #testDateWindowingRead}) fails, the
* results of this test are meaningless.
*/
public void testDateWindowingWrite() throws Exception {
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000
Date date = cal.getTime();
String path = System.getProperty("HSSF.testdata.path");
// first check a file with 1900 Date Windowing
String filename = path + "/1900DateWindowing.xls";
writeCell(filename, 0, (short) 1, date);
assertEquals("Date from file using 1900 Date Windowing",
date.getTime(),
readCell(filename, 0, (short) 1).getTime());
// now check a file with 1904 Date Windowing
filename = path + "/1904DateWindowing.xls";
writeCell(filename, 0, (short) 1, date);
assertEquals("Date from file using 1900 Date Windowing",
date.getTime(),
readCell(filename, 0, (short) 1).getTime());
}
/**
* Sets cell value and writes file.
*/
private void writeCell(String filename,
int rowIdx, short colIdx, Date date) throws Exception {
FileInputStream stream = new FileInputStream(filename);
POIFSFileSystem fs = new POIFSFileSystem(stream);
HSSFWorkbook workbook = new HSSFWorkbook(fs);
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.getRow(rowIdx);
HSSFCell cell = row.getCell(colIdx);
if (cell == null) {
cell = row.createCell(colIdx);
}
cell.setCellValue(date);
// Write the file
stream.close();
FileOutputStream oStream = new FileOutputStream(filename);
workbook.write(oStream);
oStream.close();
}
/**
* Reads cell value from file.
*/
private Date readCell(String filename,
int rowIdx, short colIdx) throws Exception {
FileInputStream stream = new FileInputStream(filename);
POIFSFileSystem fs = new POIFSFileSystem(stream);
HSSFWorkbook workbook = new HSSFWorkbook(fs);
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.getRow(rowIdx);
HSSFCell cell = row.getCell(colIdx);
return cell.getDateCellValue();
}
/** /**
* Tests that the active cell can be correctly read and set * Tests that the active cell can be correctly read and set
*/ */

View File

@ -85,4 +85,23 @@ public class TestHSSFClientAnchor extends TestCase
assertEquals(anchor[i].getRow2(), record.getRow2()); assertEquals(anchor[i].getRow2(), record.getRow2());
} }
} }
public void testAnchorHeightInPoints(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFClientAnchor[] anchor = {
new HSSFClientAnchor( 0 , 0, 0 , 0 ,(short)0, 1,(short)1, 3),
new HSSFClientAnchor( 0 , 254 , 0 , 126 ,(short)0, 1,(short)1, 3),
new HSSFClientAnchor( 0 , 128 , 0 , 128 ,(short)0, 1,(short)1, 3),
new HSSFClientAnchor( 0 , 0 , 0 , 128 ,(short)0, 1,(short)1, 3),
};
float[] ref = {24.0f, 18.0f, 24.0f, 30.0f};
for (int i = 0; i < anchor.length; i++) {
float height = anchor[i].getAnchorHeightInPoints(sheet);
assertEquals(ref[i], height, 0);
}
}
} }

View File

@ -36,6 +36,8 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
* *
* @author Dan Sherman (dsherman at isisph.com) * @author Dan Sherman (dsherman at isisph.com)
* @author Hack Kampbjorn (hak at 2mba.dk) * @author Hack Kampbjorn (hak at 2mba.dk)
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
* @author Alex Jacoby (ajacoby at gmail.com)
* @version %I%, %G% * @version %I%, %G%
*/ */
@ -47,6 +49,8 @@ public class TestHSSFDateUtil
public static final int CALENDAR_FEBRUARY = 1; public static final int CALENDAR_FEBRUARY = 1;
public static final int CALENDAR_MARCH = 2; public static final int CALENDAR_MARCH = 2;
public static final int CALENDAR_APRIL = 3; public static final int CALENDAR_APRIL = 3;
public static final int CALENDAR_JULY = 6;
public static final int CALENDAR_OCTOBER = 9;
public TestHSSFDateUtil(String s) public TestHSSFDateUtil(String s)
{ {
@ -67,10 +71,10 @@ public class TestHSSFDateUtil
GregorianCalendar date = new GregorianCalendar(2002, 0, 1, GregorianCalendar date = new GregorianCalendar(2002, 0, 1,
hour, 1, 1); hour, 1, 1);
double excelDate = double excelDate =
HSSFDateUtil.getExcelDate(date.getTime()); HSSFDateUtil.getExcelDate(date.getTime(), false);
assertEquals("Checking hour = " + hour, date.getTime().getTime(), assertEquals("Checking hour = " + hour, date.getTime().getTime(),
HSSFDateUtil.getJavaDate(excelDate).getTime()); HSSFDateUtil.getJavaDate(excelDate, false).getTime());
} }
// check 1900 and 1904 date windowing conversions // check 1900 and 1904 date windowing conversions
@ -99,7 +103,7 @@ public class TestHSSFDateUtil
public void testExcelConversionOnDSTStart() { public void testExcelConversionOnDSTStart() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen"); TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone.setDefault(cet); TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, Calendar.MARCH, 28); Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
for (int hour = 0; hour < 24; hour++) { for (int hour = 0; hour < 24; hour++) {
// Skip 02:00 CET as that is the Daylight change time // Skip 02:00 CET as that is the Daylight change time
@ -110,7 +114,7 @@ public class TestHSSFDateUtil
cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.HOUR_OF_DAY, hour);
Date javaDate = cal.getTime(); Date javaDate = cal.getTime();
double excelDate = HSSFDateUtil.getExcelDate(javaDate); double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
double difference = excelDate - Math.floor(excelDate); double difference = excelDate - Math.floor(excelDate);
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60; int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date", assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
@ -118,7 +122,7 @@ public class TestHSSFDateUtil
differenceInHours); differenceInHours);
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date", assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
javaDate.getTime(), javaDate.getTime(),
HSSFDateUtil.getJavaDate(excelDate).getTime()); HSSFDateUtil.getJavaDate(excelDate, false).getTime());
} }
} }
@ -129,8 +133,8 @@ public class TestHSSFDateUtil
public void testJavaConversionOnDSTStart() { public void testJavaConversionOnDSTStart() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen"); TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone.setDefault(cet); TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, Calendar.MARCH, 28); Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime()); double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
double oneHour = 1.0 / 24; double oneHour = 1.0 / 24;
double oneMinute = oneHour / 60; double oneMinute = oneHour / 60;
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) { for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
@ -142,10 +146,10 @@ public class TestHSSFDateUtil
} }
cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.HOUR_OF_DAY, hour);
Date javaDate = HSSFDateUtil.getJavaDate(excelDate); Date javaDate = HSSFDateUtil.getJavaDate(excelDate, false);
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date", assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
excelDate, excelDate,
HSSFDateUtil.getExcelDate(javaDate), oneMinute); HSSFDateUtil.getExcelDate(javaDate, false), oneMinute);
} }
} }
@ -156,11 +160,11 @@ public class TestHSSFDateUtil
public void testExcelConversionOnDSTEnd() { public void testExcelConversionOnDSTEnd() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen"); TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone.setDefault(cet); TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, Calendar.OCTOBER, 31); Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
for (int hour = 0; hour < 24; hour++) { for (int hour = 0; hour < 24; hour++) {
cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.HOUR_OF_DAY, hour);
Date javaDate = cal.getTime(); Date javaDate = cal.getTime();
double excelDate = HSSFDateUtil.getExcelDate(javaDate); double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
double difference = excelDate - Math.floor(excelDate); double difference = excelDate - Math.floor(excelDate);
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60; int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
assertEquals("Checking " + hour + " hour on Daylight Saving Time end date", assertEquals("Checking " + hour + " hour on Daylight Saving Time end date",
@ -168,7 +172,7 @@ public class TestHSSFDateUtil
differenceInHours); differenceInHours);
assertEquals("Checking " + hour + " hour on Daylight Saving Time start date", assertEquals("Checking " + hour + " hour on Daylight Saving Time start date",
javaDate.getTime(), javaDate.getTime(),
HSSFDateUtil.getJavaDate(excelDate).getTime()); HSSFDateUtil.getJavaDate(excelDate, false).getTime());
} }
} }
@ -179,16 +183,16 @@ public class TestHSSFDateUtil
public void testJavaConversionOnDSTEnd() { public void testJavaConversionOnDSTEnd() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen"); TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone.setDefault(cet); TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, Calendar.OCTOBER, 31); Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime()); double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
double oneHour = 1.0 / 24; double oneHour = 1.0 / 24;
double oneMinute = oneHour / 60; double oneMinute = oneHour / 60;
for (int hour = 0; hour < 24; hour++, excelDate += oneHour) { for (int hour = 0; hour < 24; hour++, excelDate += oneHour) {
cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.HOUR_OF_DAY, hour);
Date javaDate = HSSFDateUtil.getJavaDate(excelDate); Date javaDate = HSSFDateUtil.getJavaDate(excelDate, false);
assertEquals("Checking " + hour + " hours on Daylight Saving Time start date", assertEquals("Checking " + hour + " hours on Daylight Saving Time start date",
excelDate, excelDate,
HSSFDateUtil.getExcelDate(javaDate), oneMinute); HSSFDateUtil.getExcelDate(javaDate, false), oneMinute);
} }
} }
@ -315,23 +319,36 @@ public class TestHSSFDateUtil
} }
public void testDateBug_2Excel() { public void testDateBug_2Excel() {
assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_FEBRUARY, 28)), 0.00001); assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_FEBRUARY, 28), false), 0.00001);
assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_MARCH, 1)), 0.00001); assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_MARCH, 1), false), 0.00001);
assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_FEBRUARY, 28)), 0.00001); assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_FEBRUARY, 28), false), 0.00001);
assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_MARCH, 1)), 0.00001); assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_MARCH, 1), false), 0.00001);
assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_JANUARY, 1)), 0.00001); assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_JANUARY, 1), false), 0.00001);
assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, CALENDAR_MARCH, 28)), 0.00001); assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, CALENDAR_MARCH, 28), false), 0.00001);
} }
public void testDateBug_2Java() { public void testDateBug_2Java() {
assertEquals(createDate(1900, Calendar.FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0)); assertEquals(createDate(1900, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0, false));
assertEquals(createDate(1900, Calendar.MARCH, 1), HSSFDateUtil.getJavaDate(61.0)); assertEquals(createDate(1900, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(61.0, false));
assertEquals(createDate(2002, Calendar.FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00)); assertEquals(createDate(2002, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00, false));
assertEquals(createDate(2002, Calendar.MARCH, 1), HSSFDateUtil.getJavaDate(37316.00)); assertEquals(createDate(2002, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(37316.00, false));
assertEquals(createDate(2002, Calendar.JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00)); assertEquals(createDate(2002, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00, false));
assertEquals(createDate(2004, Calendar.MARCH, 28), HSSFDateUtil.getJavaDate(38074.00)); assertEquals(createDate(2004, CALENDAR_MARCH, 28), HSSFDateUtil.getJavaDate(38074.00, false));
}
public void testDate1904() {
assertEquals(createDate(1904, CALENDAR_JANUARY, 2), HSSFDateUtil.getJavaDate(1.0, true));
assertEquals(createDate(1904, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(0.0, true));
assertEquals(0.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 1), true), 0.00001);
assertEquals(1.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 2), true), 0.00001);
assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(35981, false));
assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(34519, true));
assertEquals(35981.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), false), 0.00001);
assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), true), 0.00001);
} }
private Date createDate(int year, int month, int day) { private Date createDate(int year, int month, int day) {
@ -341,10 +358,21 @@ public class TestHSSFDateUtil
return c.getTime(); return c.getTime();
} }
/**
* Check if HSSFDateUtil.getAbsoluteDay works as advertised.
*/
public void testAbsoluteDay() {
// 1 Jan 1900 is 1 day after 31 Dec 1899
GregorianCalendar calendar = new GregorianCalendar(1900, 0, 1);
assertEquals("Checking absolute day (1 Jan 1900)", 1, HSSFDateUtil.absoluteDay(calendar, false));
// 1 Jan 1901 is 366 days after 31 Dec 1899
calendar = new GregorianCalendar(1901, 0, 1);
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false));
}
public static void main(String [] args) { public static void main(String [] args) {
System.out System.out
.println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil"); .println("Testing org.apache.poi.hssf.usermodel.TestHSSFDateUtil");
junit.textui.TestRunner.run(TestHSSFDateUtil.class); junit.textui.TestRunner.run(TestHSSFDateUtil.class);
} }
} }

View File

@ -95,6 +95,71 @@ public class TestHSSFPalette extends TestCase
assertEquals(msg, (short) 100, actualRGB[2]); assertEquals(msg, (short) 100, actualRGB[2]);
} }
/**
* Uses the palette from cell stylings
*/
public void testPaletteFromCellColours() throws Exception {
String dir = System.getProperty("HSSF.testdata.path");
File sample = new File(dir + "/SimpleWithColours.xls");
assertTrue("SimpleWithColours.xls exists and is readable", sample.canRead());
FileInputStream fis = new FileInputStream(sample);
HSSFWorkbook book = new HSSFWorkbook(fis);
fis.close();
HSSFPalette p = book.getCustomPalette();
HSSFCell cellA = book.getSheetAt(0).getRow(0).getCell((short)0);
HSSFCell cellB = book.getSheetAt(0).getRow(1).getCell((short)0);
HSSFCell cellC = book.getSheetAt(0).getRow(2).getCell((short)0);
HSSFCell cellD = book.getSheetAt(0).getRow(3).getCell((short)0);
HSSFCell cellE = book.getSheetAt(0).getRow(4).getCell((short)0);
// Plain
assertEquals("I'm plain", cellA.getStringCellValue());
assertEquals(64, cellA.getCellStyle().getFillForegroundColor());
assertEquals(64, cellA.getCellStyle().getFillBackgroundColor());
assertEquals(HSSFFont.COLOR_NORMAL, cellA.getCellStyle().getFont(book).getColor());
assertEquals(0, cellA.getCellStyle().getFillPattern());
assertEquals("0:0:0", p.getColor((short)64).getHexString());
assertEquals(null, p.getColor((short)32767));
// Red
assertEquals("I'm red", cellB.getStringCellValue());
assertEquals(64, cellB.getCellStyle().getFillForegroundColor());
assertEquals(64, cellB.getCellStyle().getFillBackgroundColor());
assertEquals(10, cellB.getCellStyle().getFont(book).getColor());
assertEquals(0, cellB.getCellStyle().getFillPattern());
assertEquals("0:0:0", p.getColor((short)64).getHexString());
assertEquals("FFFF:0:0", p.getColor((short)10).getHexString());
// Red + green bg
assertEquals("I'm red with a green bg", cellC.getStringCellValue());
assertEquals(11, cellC.getCellStyle().getFillForegroundColor());
assertEquals(64, cellC.getCellStyle().getFillBackgroundColor());
assertEquals(10, cellC.getCellStyle().getFont(book).getColor());
assertEquals(1, cellC.getCellStyle().getFillPattern());
assertEquals("0:FFFF:0", p.getColor((short)11).getHexString());
assertEquals("FFFF:0:0", p.getColor((short)10).getHexString());
// Pink with yellow
assertEquals("I'm pink with a yellow pattern (none)", cellD.getStringCellValue());
assertEquals(13, cellD.getCellStyle().getFillForegroundColor());
assertEquals(64, cellD.getCellStyle().getFillBackgroundColor());
assertEquals(14, cellD.getCellStyle().getFont(book).getColor());
assertEquals(0, cellD.getCellStyle().getFillPattern());
assertEquals("FFFF:FFFF:0", p.getColor((short)13).getHexString());
assertEquals("FFFF:0:FFFF", p.getColor((short)14).getHexString());
// Pink with yellow - full
assertEquals("I'm pink with a yellow pattern (full)", cellE.getStringCellValue());
assertEquals(13, cellE.getCellStyle().getFillForegroundColor());
assertEquals(64, cellE.getCellStyle().getFillBackgroundColor());
assertEquals(14, cellE.getCellStyle().getFont(book).getColor());
assertEquals(0, cellE.getCellStyle().getFillPattern());
assertEquals("FFFF:FFFF:0", p.getColor((short)13).getHexString());
assertEquals("FFFF:0:FFFF", p.getColor((short)14).getHexString());
}
/** /**
* Verifies that the generated gnumeric-format string values match the * Verifies that the generated gnumeric-format string values match the
* hardcoded values in the HSSFColor default color palette * hardcoded values in the HSSFColor default color palette

View File

@ -63,7 +63,7 @@ public class TestReadWriteChart
//System.out.println("first assertion for date"); //System.out.println("first assertion for date");
assertEquals(new GregorianCalendar(2000, 0, 1, 10, 51, 2).getTime(), assertEquals(new GregorianCalendar(2000, 0, 1, 10, 51, 2).getTime(),
HSSFDateUtil HSSFDateUtil
.getJavaDate(firstCell.getNumericCellValue())); .getJavaDate(firstCell.getNumericCellValue(), false));
HSSFRow row = sheet.createRow(( short ) 15); HSSFRow row = sheet.createRow(( short ) 15);
HSSFCell cell = row.createCell(( short ) 1); HSSFCell cell = row.createCell(( short ) 1);

View File

@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.poi.hssf.usermodel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import junit.framework.TestCase;
/**
* Tests for how HSSFWorkbook behaves with XLS files
* with a WORKBOOK directory entry (instead of the more
* usual, Workbook)
*/
public class TestSheetHiding extends TestCase {
private String dirPath;
private String xlsHidden = "TwoSheetsOneHidden.xls";
private String xlsShown = "TwoSheetsNoneHidden.xls";
protected void setUp() throws Exception {
super.setUp();
dirPath = System.getProperty("HSSF.testdata.path");
}
/**
* Test that we get the right number of sheets,
* with the right text on them, no matter what
* the hidden flags are
*/
public void testTextSheets() throws Exception {
FileInputStream isH = new FileInputStream(dirPath + "/" + xlsHidden);
POIFSFileSystem fsH = new POIFSFileSystem(isH);
FileInputStream isU = new FileInputStream(dirPath + "/" + xlsShown);
POIFSFileSystem fsU = new POIFSFileSystem(isU);
HSSFWorkbook wbH = new HSSFWorkbook(fsH);
HSSFWorkbook wbU = new HSSFWorkbook(fsU);
// Both should have two sheets
assertEquals(2, wbH.sheets.size());
assertEquals(2, wbU.sheets.size());
// All sheets should have one row
assertEquals(0, wbH.getSheetAt(0).getLastRowNum());
assertEquals(0, wbH.getSheetAt(1).getLastRowNum());
assertEquals(0, wbU.getSheetAt(0).getLastRowNum());
assertEquals(0, wbU.getSheetAt(1).getLastRowNum());
// All rows should have one column
assertEquals(1, wbH.getSheetAt(0).getRow(0).getLastCellNum());
assertEquals(1, wbH.getSheetAt(1).getRow(0).getLastCellNum());
assertEquals(1, wbU.getSheetAt(0).getRow(0).getLastCellNum());
assertEquals(1, wbU.getSheetAt(1).getRow(0).getLastCellNum());
// Text should be sheet based
assertEquals("Sheet1A1", wbH.getSheetAt(0).getRow(0).getCell((short)0).getStringCellValue());
assertEquals("Sheet2A1", wbH.getSheetAt(1).getRow(0).getCell((short)0).getStringCellValue());
assertEquals("Sheet1A1", wbU.getSheetAt(0).getRow(0).getCell((short)0).getStringCellValue());
assertEquals("Sheet2A1", wbU.getSheetAt(1).getRow(0).getCell((short)0).getStringCellValue());
}
/**
* Check that we can get and set the hidden flags
* as expected
*/
public void testHideUnHideFlags() throws Exception {
// TODO
}
/**
* Turn the sheet with none hidden into the one with
* one hidden
*/
public void testHide() throws Exception {
// TODO
}
/**
* Turn the sheet with one hidden into the one with
* none hidden
*/
public void testUnHide() throws Exception {
// TODO
}
}

View File

@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.util.IOUtils;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSWriterEvent; import org.apache.poi.poifs.filesystem.POIFSWriterEvent;
import org.apache.poi.poifs.filesystem.POIFSWriterListener; import org.apache.poi.poifs.filesystem.POIFSWriterListener;
@ -140,4 +141,28 @@ public class TestEmptyDocument extends TestCase {
fs.writeFilesystem(out); fs.writeFilesystem(out);
new POIFSFileSystem(new ByteArrayInputStream(out.toByteArray())); new POIFSFileSystem(new ByteArrayInputStream(out.toByteArray()));
} }
public void testEmptyDocumentBug11744() throws Exception {
byte[] testData = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
POIFSFileSystem fs = new POIFSFileSystem();
fs.createDocument(new ByteArrayInputStream(new byte[0]), "Empty");
fs.createDocument(new ByteArrayInputStream(testData), "NotEmpty");
ByteArrayOutputStream out = new ByteArrayOutputStream();
fs.writeFilesystem(out);
out.toByteArray();
// This line caused the error.
fs = new POIFSFileSystem(new ByteArrayInputStream(out.toByteArray()));
DocumentEntry entry = (DocumentEntry) fs.getRoot().getEntry("Empty");
assertEquals("Expected zero size", 0, entry.getSize());
assertEquals("Expected zero read from stream", 0,
IOUtils.toByteArray(new DocumentInputStream(entry)).length);
entry = (DocumentEntry) fs.getRoot().getEntry("NotEmpty");
assertEquals("Expected size was wrong", testData.length, entry.getSize());
assertEquals("Expected different data read from stream", testData,
IOUtils.toByteArray(new DocumentInputStream(entry)));
}
} }