mirror of https://github.com/apache/poi.git
merge trunk
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/hemf@1845617 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
commit
0e68ef5f84
|
@ -18,7 +18,7 @@
|
|||
<classpathentry kind="lib" path="lib/ant-1.10.1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/ant-launcher-1.10.1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="ooxml-lib/xmlbeans-3.0.1.jar" sourcepath="ooxml-lib/xmlbeans-3.0.1.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="ooxml-lib/xmlbeans-3.0.2.jar" sourcepath="ooxml-lib/xmlbeans-3.0.2.jar"/>
|
||||
<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/junit-4.12.jar"/>
|
||||
<classpathentry kind="lib" path="ooxml-lib/curvesapi-1.05.jar"/>
|
||||
|
@ -30,13 +30,16 @@
|
|||
<classpathentry exported="true" kind="lib" path="compile-lib/slf4j-api-1.7.25.jar"/>
|
||||
<classpathentry kind="lib" path="compile-lib/bcpkix-jdk15on-1.60.jar"/>
|
||||
<classpathentry kind="lib" path="compile-lib/bcprov-ext-jdk15on-1.60.jar"/>
|
||||
<classpathentry kind="lib" path="ooxml-testlib/reflections.jar"/>
|
||||
<classpathentry kind="lib" path="ooxml-testlib/guava.jar"/>
|
||||
<classpathentry kind="lib" path="ooxml-testlib/javassist.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="compile-lib/xmlsec-2.1.0.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/commons-codec-1.11.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/commons-logging-1.2.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/commons-collections4-4.2.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-math3-3.6.1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/xmlunit-core-2.5.1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/mockito-core-2.13.0.jar"/>
|
||||
<classpathentry kind="lib" path="lib/mockito-core-2.21.0.jar"/>
|
||||
<classpathentry kind="lib" path="lib/byte-buddy-1.7.9.jar"/>
|
||||
<classpathentry kind="lib" path="lib/byte-buddy-agent-1.7.9.jar"/>
|
||||
<classpathentry kind="lib" path="lib/objenesis-2.6.jar"/>
|
||||
|
|
|
@ -11,6 +11,7 @@ log*.*
|
|||
forrest.properties
|
||||
compile-lib/
|
||||
ooxml-lib/
|
||||
ooxml-testlib/
|
||||
|
||||
# Eclipse
|
||||
/bin
|
||||
|
|
|
@ -225,7 +225,7 @@ project('ooxml') {
|
|||
compileJava.dependsOn 'ant-compile-ooxml-xsds'
|
||||
|
||||
dependencies {
|
||||
compile 'org.apache.xmlbeans:xmlbeans:3.0.1'
|
||||
compile 'org.apache.xmlbeans:xmlbeans:3.0.2'
|
||||
compile 'org.apache.commons:commons-collections4:4.2'
|
||||
compile 'org.apache.commons:commons-math3:3.6.1'
|
||||
compile 'org.apache.commons:commons-compress:1.18'
|
||||
|
|
20
build.xml
20
build.xml
|
@ -213,9 +213,9 @@ under the License.
|
|||
<property name="ooxml.curvesapi.jar" location="${ooxml.lib}/curvesapi-1.05.jar"/>
|
||||
<property name="ooxml.curvesapi.url"
|
||||
value="${repository.m2}/maven2/com/github/virtuald/curvesapi/1.05/curvesapi-1.05.jar"/>
|
||||
<property name="ooxml.xmlbeans.jar" location="${ooxml.lib}/xmlbeans-3.0.1.jar"/>
|
||||
<property name="ooxml.xmlbeans.jar" location="${ooxml.lib}/xmlbeans-3.0.2.jar"/>
|
||||
<property name="ooxml.xmlbeans.url"
|
||||
value="https://repository.apache.org/content/repositories/releases/org/apache/xmlbeans/xmlbeans/3.0.1/xmlbeans-3.0.1.jar"/>
|
||||
value="https://repository.apache.org/content/repositories/releases/org/apache/xmlbeans/xmlbeans/3.0.2/xmlbeans-3.0.2.jar"/>
|
||||
<property name="ooxml.commons-compress.jar" location="${main.lib}/commons-compress-1.18.jar"/>
|
||||
<property name="ooxml.commons-compress.url"
|
||||
value="${repository.m2}/maven2/org/apache/commons/commons-compress/1.18/commons-compress-1.18.jar"/>
|
||||
|
@ -289,7 +289,7 @@ under the License.
|
|||
<!-- build and distro settings -->
|
||||
<property name="jar.name" value="poi"/>
|
||||
<property name="build.site" location="build/site"/>
|
||||
<property name="javadocs.report.dir" location="${build.site}/apidocs"/>
|
||||
<property name="javadocs.report.dir" location="${build.site}/apidocs/dev"/>
|
||||
<property name="dist.dir" location="build/dist"/>
|
||||
<property name="halt.on.test.failure" value="true"/>
|
||||
|
||||
|
@ -671,6 +671,7 @@ under the License.
|
|||
<include name="curvesapi-1.04.jar"/>
|
||||
<include name="xmlbeans-2.*.jar"/>
|
||||
<include name="xmlbeans-3.0.0.jar"/>
|
||||
<include name="xmlbeans-3.0.1.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${compile.lib}">
|
||||
<include name="xercesImpl-*.jar"/>
|
||||
|
@ -1798,9 +1799,11 @@ under the License.
|
|||
<fail message="Apache Forrest is not installed."/>
|
||||
</target>
|
||||
|
||||
<target name="docs" depends="init, -check-forrest-installed, -check-docs, javadocs"
|
||||
unless="main.docs.notRequired" description="Builds the POI website">
|
||||
|
||||
<target name="docs" depends="init, -check-forrest-installed, -check-docs, javadocs, -forrest-docs"
|
||||
unless="main.docs.notRequired"
|
||||
description="Builds the POI website" />
|
||||
<target name="-forrest-docs" depends="-check-forrest-installed, -check-docs"
|
||||
unless="main.docs.notRequired" description="Builds the HTML pages of the POI website">
|
||||
<exec executable="${env.FORREST_HOME}/bin/forrest" osfamily="unix"/>
|
||||
<exec executable="cmd" osfamily="windows">
|
||||
<arg value="/c"/>
|
||||
|
@ -1817,9 +1820,10 @@ under the License.
|
|||
</touch>
|
||||
</target>
|
||||
|
||||
<!-- Generates the API documentation. -->
|
||||
<!-- Generates the latest/development API documentation. -->
|
||||
<target name="javadocs"
|
||||
description="Generates the API documentation">
|
||||
<echo message="Generating latest Javadocs in ${javadocs.report.dir}"/>
|
||||
<javadoc verbose="false" author="true" destdir="${javadocs.report.dir}"
|
||||
windowtitle="POI API Documentation" use="true" version="true"
|
||||
maxmemory="384M" additionalparam="-notimestamp" locale="en_US"
|
||||
|
@ -2035,7 +2039,7 @@ under the License.
|
|||
<packageset dir="@{src}" defaultexcludes="yes">
|
||||
<include name="org/apache/poi/**"/>
|
||||
</packageset>
|
||||
<link offline="true" href="https://poi.apache.org/apidocs" packagelistLoc="${javadocs.report.dir}"/>
|
||||
<link offline="true" href="https://poi.apache.org/apidocs/dev" packagelistLoc="${javadocs.report.dir}"/>
|
||||
</javadoc>
|
||||
<jar destfile="${dist.dir}/maven/@{dest}/@{dest}-${version.id}-javadoc.jar"
|
||||
manifest="build/poi-manifest.mf">
|
||||
|
|
|
@ -610,7 +610,24 @@ dashboardView("P/POI-new") {
|
|||
//lastSuccessDescription()
|
||||
jacoco()
|
||||
}
|
||||
description("Jobs related to building/testing Apache POI")
|
||||
description("<table>\n" +
|
||||
" <tr>\n" +
|
||||
" <td><img src=\"https://poi.apache.org/images/project-header.png\" /></td>\n" +
|
||||
" <td> \n" +
|
||||
" <p>Apache POI - the Java API for Microsoft Documents</p>\n" +
|
||||
" <p><b>Most of the POI Jobs are automatically generated by Jenkins Job DSL\n" +
|
||||
" at <a href=\"https://svn.apache.org/repos/asf/poi/trunk/jenkins\">https://svn.apache.org/repos/asf/poi/trunk/jenkins</a>,<br/>\n" +
|
||||
" see <a href=\"https://github.com/jenkinsci/job-dsl-plugin/wiki\">https://github.com/jenkinsci/job-dsl-plugin/wiki</a>\n" +
|
||||
" for more details about the DSL.</b>\n" +
|
||||
" </p>\n" +
|
||||
" <p>\n" +
|
||||
" <b><a href=\"job/POI-DSL-1.8/lastSuccessfulBuild/findbugsResult/\" target=\"_blank\">Findbugs report of latest build</a></b> -\n" +
|
||||
" <b><a href=\"https://builds.apache.org/analysis/dashboard?id=org.apache.poi%3Apoi-parent&did=1\" target=\"_blank\">Sonar reports</a></b> -\n" +
|
||||
" <b><a href=\"job/POI-DSL-1.8/lastSuccessfulBuild/artifact/build/coverage/index.html\" target=\"_blank\">Coverage of latest build</a></b>\n" +
|
||||
" </p>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
"</table>")
|
||||
filterBuildQueue(false)
|
||||
filterExecutors(false)
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.xmlbeans</groupId>
|
||||
<artifactId>xmlbeans</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
<sonar.scm.disabled>true</sonar.scm.disabled>
|
||||
|
||||
<!-- define some of the third-party or plugin-versions globally to use the same in all modules -->
|
||||
<xmlbeans.version>3.0.1</xmlbeans.version>
|
||||
<xmlbeans.version>3.0.2</xmlbeans.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<xmlunit.version>2.5.1</xmlunit.version>
|
||||
<mockito.version>2.13.0</mockito.version>
|
||||
|
|
|
@ -142,13 +142,13 @@ import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
|
|||
public class AddDimensionedImage {
|
||||
|
||||
// Four constants that determine how - and indeed whether - the rows
|
||||
// and columns an image may overlie should be expanded to accomodate that
|
||||
// and columns an image may overlie should be expanded to accommodate that
|
||||
// image.
|
||||
// Passing EXPAND_ROW will result in the height of a row being increased
|
||||
// to accomodate the image if it is not already larger. The image will
|
||||
// to accommodate the image if it is not already larger. The image will
|
||||
// be layed across one or more columns.
|
||||
// Passing EXPAND_COLUMN will result in the width of the column being
|
||||
// increased to accomodate the image if it is not already larger. The image
|
||||
// increased to accommodate the image if it is not already larger. The image
|
||||
// will be layed across one or many rows.
|
||||
// Passing EXPAND_ROW_AND_COLUMN will result in the height of the row
|
||||
// bing increased along with the width of the column to accomdate the
|
||||
|
@ -266,7 +266,7 @@ public class AddDimensionedImage {
|
|||
}
|
||||
|
||||
// Call methods to calculate how the image and sheet should be
|
||||
// manipulated to accomodate the image; columns and then rows.
|
||||
// manipulated to accommodate the image; columns and then rows.
|
||||
colClientAnchorDetail = this.fitImageToColumns(sheet, colNumber,
|
||||
reqImageWidthMM, resizeBehaviour);
|
||||
rowClientAnchorDetail = this.fitImageToRows(sheet, rowNumber,
|
||||
|
@ -312,7 +312,7 @@ public class AddDimensionedImage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether the sheets columns should be re-sized to accomodate
|
||||
* Determines whether the sheets columns should be re-sized to accommodate
|
||||
* the image, adjusts the columns width if necessary and creates then
|
||||
* returns a ClientAnchorDetail object that facilitates construction of
|
||||
* an HSSFClientAnchor that will fix the image on the sheet and establish
|
||||
|
@ -348,7 +348,7 @@ public class AddDimensionedImage {
|
|||
colWidthMM = ConvertImageUnits.widthUnits2Millimetres(
|
||||
(short)sheet.getColumnWidth(colNumber));
|
||||
|
||||
// Check that the column's width will accomodate the image at the
|
||||
// Check that the column's width will accommodate the image at the
|
||||
// required dimension. If the width of the column is LESS than the
|
||||
// required width of the image, decide how the application should
|
||||
// respond - resize the column or overlay the image across one or more
|
||||
|
@ -396,7 +396,7 @@ public class AddDimensionedImage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether the sheet's row should be re-sized to accomodate
|
||||
* Determines whether the sheet's row should be re-sized to accommodate
|
||||
* the image, adjusts the rows height if necessary and creates then
|
||||
* returns a ClientAnchorDetail object that facilitates construction of
|
||||
* an HSSFClientAnchor that will fix the image on the sheet and establish
|
||||
|
@ -436,7 +436,7 @@ public class AddDimensionedImage {
|
|||
// Get the row's height in millimetres
|
||||
double rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE;
|
||||
|
||||
// Check that the row's height will accomodate the image at the required
|
||||
// Check that the row's height will accommodate the image at the required
|
||||
// dimensions. If the height of the row is LESS than the required height
|
||||
// of the image, decide how the application should respond - resize the
|
||||
// row or overlay the image across a series of rows.
|
||||
|
|
|
@ -17,19 +17,23 @@
|
|||
|
||||
package org.apache.poi.hssf.usermodel.examples;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFComment;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.RichTextString;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
|
||||
import org.apache.poi.hssf.usermodel.HSSFComment;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFont;
|
||||
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
|
||||
|
||||
/**
|
||||
* Demonstrates how to work with excel cell comments.<p>
|
||||
*
|
||||
|
@ -39,46 +43,64 @@ import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
|
|||
public class CellComments {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
try (HSSFWorkbook wb = new HSSFWorkbook()) {
|
||||
HSSFSheet sheet = wb.createSheet("Cell comments in POI HSSF");
|
||||
createWorkbook(false, ".xls");
|
||||
createWorkbook(true, ".xlsx");
|
||||
}
|
||||
|
||||
private static void createWorkbook(boolean xssf, String extension) throws IOException {
|
||||
try (Workbook wb = WorkbookFactory.create(xssf)) {
|
||||
Sheet sheet = wb.createSheet("Cell comments in POI " + extension);
|
||||
CreationHelper creationHelper = wb.getCreationHelper();
|
||||
|
||||
// Create the drawing patriarch. This is the top level container for all shapes including cell comments.
|
||||
HSSFPatriarch patr = sheet.createDrawingPatriarch();
|
||||
Drawing<?> patr = sheet.createDrawingPatriarch();
|
||||
|
||||
//create a cell in row 3
|
||||
HSSFCell cell1 = sheet.createRow(3).createCell(1);
|
||||
cell1.setCellValue(new HSSFRichTextString("Hello, World"));
|
||||
Cell cell1 = sheet.createRow(3).createCell(1);
|
||||
cell1.setCellValue(creationHelper.createRichTextString("Hello, World"));
|
||||
|
||||
//anchor defines size and position of the comment in worksheet
|
||||
HSSFComment comment1 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5));
|
||||
ClientAnchor clientAnchor = creationHelper.createClientAnchor();
|
||||
clientAnchor.setCol1(4);
|
||||
clientAnchor.setRow1(2);
|
||||
clientAnchor.setCol2(6);
|
||||
clientAnchor.setRow2(5);
|
||||
Comment comment1 = patr.createCellComment(clientAnchor);
|
||||
|
||||
// set text in the comment
|
||||
comment1.setString(new HSSFRichTextString("We can set comments in POI"));
|
||||
comment1.setString(creationHelper.createRichTextString("We can set comments in POI"));
|
||||
|
||||
//set comment author.
|
||||
//you can see it in the status bar when moving mouse over the commented cell
|
||||
comment1.setAuthor("Apache Software Foundation");
|
||||
|
||||
// The first way to assign comment to a cell is via HSSFCell.setCellComment method
|
||||
// The first way to assign comment to a cell is via Cell.setCellComment method
|
||||
cell1.setCellComment(comment1);
|
||||
|
||||
//create another cell in row 6
|
||||
HSSFCell cell2 = sheet.createRow(6).createCell(1);
|
||||
Cell cell2 = sheet.createRow(6).createCell(1);
|
||||
cell2.setCellValue(36.6);
|
||||
|
||||
|
||||
HSSFComment comment2 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 8, (short) 6, 11));
|
||||
//modify background color of the comment
|
||||
comment2.setFillColor(204, 236, 255);
|
||||
clientAnchor = creationHelper.createClientAnchor();
|
||||
clientAnchor.setCol1(4);
|
||||
clientAnchor.setRow1(8);
|
||||
clientAnchor.setCol2(6);
|
||||
clientAnchor.setRow2(11);
|
||||
Comment comment2 = patr.createCellComment(clientAnchor);
|
||||
//modify background color of the comment, only available in HSSF currently
|
||||
if (wb instanceof HSSFWorkbook) {
|
||||
((HSSFComment) comment2).setFillColor(204, 236, 255);
|
||||
}
|
||||
|
||||
HSSFRichTextString string = new HSSFRichTextString("Normal body temperature");
|
||||
RichTextString string = creationHelper.createRichTextString("Normal body temperature");
|
||||
|
||||
//apply custom font to the text in the comment
|
||||
HSSFFont font = wb.createFont();
|
||||
Font font = wb.createFont();
|
||||
font.setFontName("Arial");
|
||||
font.setFontHeightInPoints((short) 10);
|
||||
font.setBold(true);
|
||||
font.setColor(HSSFColorPredefined.RED.getIndex());
|
||||
font.setColor(IndexedColors.RED.getIndex());
|
||||
string.applyFont(font);
|
||||
|
||||
comment2.setString(string);
|
||||
|
@ -94,7 +116,7 @@ public class CellComments {
|
|||
comment2.setRow(6);
|
||||
comment2.setColumn(1);
|
||||
|
||||
try (FileOutputStream out = new FileOutputStream("poi_comment.xls")) {
|
||||
try (FileOutputStream out = new FileOutputStream("poi_comment" + extension)) {
|
||||
wb.write(out);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,13 +202,13 @@ import org.apache.poi.util.IOUtils;
|
|||
public class AddDimensionedImage {
|
||||
|
||||
// Four constants that determine how - and indeed whether - the rows
|
||||
// and columns an image may overlie should be expanded to accomodate that
|
||||
// and columns an image may overlie should be expanded to accommodate that
|
||||
// image.
|
||||
// Passing EXPAND_ROW will result in the height of a row being increased
|
||||
// to accomodate the image if it is not already larger. The image will
|
||||
// to accommodate the image if it is not already larger. The image will
|
||||
// be layed across one or more columns.
|
||||
// Passing EXPAND_COLUMN will result in the width of the column being
|
||||
// increased to accomodate the image if it is not already larger. The image
|
||||
// increased to accommodate the image if it is not already larger. The image
|
||||
// will be layed across one or many rows.
|
||||
// Passing EXPAND_ROW_AND_COLUMN will result in the height of the row
|
||||
// bing increased along with the width of the column to accomdate the
|
||||
|
@ -348,7 +348,7 @@ public class AddDimensionedImage {
|
|||
}
|
||||
|
||||
// Call methods to calculate how the image and sheet should be
|
||||
// manipulated to accomodate the image; columns and then rows.
|
||||
// manipulated to accommodate the image; columns and then rows.
|
||||
colClientAnchorDetail = this.fitImageToColumns(sheet, colNumber,
|
||||
reqImageWidthMM, resizeBehaviour);
|
||||
rowClientAnchorDetail = this.fitImageToRows(sheet, rowNumber,
|
||||
|
@ -440,7 +440,7 @@ public class AddDimensionedImage {
|
|||
colWidthMM = ConvertImageUnits.widthUnits2Millimetres(
|
||||
(short)sheet.getColumnWidth(colNumber));
|
||||
|
||||
// Check that the column's width will accomodate the image at the
|
||||
// Check that the column's width will accommodate the image at the
|
||||
// required dimension. If the width of the column is LESS than the
|
||||
// required width of the image, decide how the application should
|
||||
// respond - resize the column or overlay the image across one or more
|
||||
|
@ -500,7 +500,7 @@ public class AddDimensionedImage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether the sheets row should be re-sized to accomodate
|
||||
* Determines whether the sheets row should be re-sized to accommodate
|
||||
* the image, adjusts the rows height if necessary and creates then
|
||||
* returns a ClientAnchorDetail object that facilitates construction of
|
||||
* a ClientAnchor that will fix the image on the sheet and establish
|
||||
|
@ -542,7 +542,7 @@ public class AddDimensionedImage {
|
|||
// Get the row's height in millimetres
|
||||
rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE;
|
||||
|
||||
// Check that the row's height will accomodate the image at the required
|
||||
// Check that the row's height will accommodate the image at the required
|
||||
// dimensions. If the height of the row is LESS than the required height
|
||||
// of the image, decide how the application should respond - resize the
|
||||
// row or overlay the image across a series of rows.
|
||||
|
|
|
@ -44,8 +44,8 @@ public class NewLinesInCells {
|
|||
cs.setWrapText(true);
|
||||
cell.setCellStyle(cs);
|
||||
|
||||
//increase row height to accomodate two lines of text
|
||||
row.setHeightInPoints((2 * sheet.getDefaultRowHeightInPoints()));
|
||||
//increase row height to accommodate two lines of text
|
||||
row.setHeightInPoints(2 * sheet.getDefaultRowHeightInPoints());
|
||||
|
||||
//adjust column width to fit the content
|
||||
sheet.autoSizeColumn(2);
|
||||
|
@ -55,5 +55,4 @@ public class NewLinesInCells {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.poi.hpsf.DocumentSummaryInformation;
|
|||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
||||
import org.apache.poi.poifs.crypt.Encryptor;
|
||||
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
|
||||
|
@ -176,6 +177,8 @@ public abstract class POIDocument implements Closeable {
|
|||
*
|
||||
* @param setName The property to read
|
||||
* @return The value of the given property or null if it wasn't found.
|
||||
*
|
||||
* @throws IOException If retrieving properties fails
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected PropertySet getPropertySet(String setName) throws IOException {
|
||||
|
@ -189,6 +192,8 @@ public abstract class POIDocument implements Closeable {
|
|||
* @param setName The property to read
|
||||
* @param encryptionInfo the encryption descriptor in case of cryptoAPI encryption
|
||||
* @return The value of the given property or null if it wasn't found.
|
||||
*
|
||||
* @throws IOException If retrieving properties fails
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected PropertySet getPropertySet(String setName, EncryptionInfo encryptionInfo) throws IOException {
|
||||
|
@ -305,7 +310,8 @@ public abstract class POIDocument implements Closeable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Writes out a given ProperySet
|
||||
* Writes out a given PropertySet
|
||||
*
|
||||
* @param name the (POIFS Level) name of the property to write
|
||||
* @param set the PropertySet to write out
|
||||
* @param outFS the NPOIFSFileSystem to write the property into
|
||||
|
@ -326,7 +332,7 @@ public abstract class POIDocument implements Closeable {
|
|||
outFS.createOrUpdateDocument(bIn, name);
|
||||
|
||||
logger.log(POILogger.INFO, "Wrote property set " + name + " of size " + data.length);
|
||||
} catch(org.apache.poi.hpsf.WritingNotSupportedException wnse) {
|
||||
} catch(WritingNotSupportedException ignored) {
|
||||
logger.log( POILogger.ERROR, "Couldn't write property set with name " + name + " as not supported by HPSF yet");
|
||||
}
|
||||
}
|
||||
|
@ -468,6 +474,8 @@ public abstract class POIDocument implements Closeable {
|
|||
|
||||
/**
|
||||
* @return the encryption info if the document is encrypted, otherwise {@code null}
|
||||
*
|
||||
* @throws IOException If retrieving the encryption information fails
|
||||
*/
|
||||
public EncryptionInfo getEncryptionInfo() throws IOException {
|
||||
return null;
|
||||
|
|
|
@ -68,13 +68,15 @@ public enum FontFamily {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get FontFamily from combined native id
|
||||
*
|
||||
* @param pitchAndFamily The PitchFamily to decode.
|
||||
*
|
||||
* @return The resulting FontFamily
|
||||
*/
|
||||
public static FontFamily valueOfPitchFamily(byte pitchAndFamily) {
|
||||
return valueOf(pitchAndFamily >>> 4);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,11 @@ public enum FontPitch {
|
|||
* Combine pitch and family to native id
|
||||
*
|
||||
* @see <a href="https://msdn.microsoft.com/en-us/library/dd145037.aspx">LOGFONT structure</a>
|
||||
*
|
||||
* @param pitch The pitch-value, cannot be null
|
||||
* @param family The family-value, cannot be null
|
||||
*
|
||||
* @return The resulting combined byte-value with pitch and family encoded into one byte
|
||||
*/
|
||||
public static byte getNativeId(FontPitch pitch, FontFamily family) {
|
||||
return (byte)(pitch.getNativeId() | (family.getFlag() << 4));
|
||||
|
@ -66,9 +71,12 @@ public enum FontPitch {
|
|||
|
||||
/**
|
||||
* Get FontPitch from native id
|
||||
*
|
||||
* @param pitchAndFamily The combined byte value for pitch and family
|
||||
*
|
||||
* @return The resulting FontPitch enumeration value
|
||||
*/
|
||||
public static FontPitch valueOfPitchFamily(byte pitchAndFamily) {
|
||||
return valueOf(pitchAndFamily & 0x3);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ public final class OLE2ExtractorFactory {
|
|||
* Should this thread prefer event based over usermodel based extractors?
|
||||
* (usermodel extractors tend to be more accurate, but use more memory)
|
||||
* Default is false.
|
||||
*
|
||||
* @return true if event extractors should be preferred in the current thread, fals otherwise.
|
||||
*/
|
||||
public static boolean getThreadPrefersEventExtractors() {
|
||||
return threadPreferEventExtractors.get();
|
||||
|
@ -74,6 +76,8 @@ public final class OLE2ExtractorFactory {
|
|||
* Should all threads prefer event based over usermodel based extractors?
|
||||
* (usermodel extractors tend to be more accurate, but use more memory)
|
||||
* Default is to use the thread level setting, which defaults to false.
|
||||
*
|
||||
* @return true if event extractors should be preferred in all threads, fals otherwise.
|
||||
*/
|
||||
public static Boolean getAllThreadsPreferEventExtractors() {
|
||||
return allPreferEventExtractors;
|
||||
|
@ -82,6 +86,8 @@ public final class OLE2ExtractorFactory {
|
|||
/**
|
||||
* Should this thread prefer event based over usermodel based extractors?
|
||||
* Will only be used if the All Threads setting is null.
|
||||
*
|
||||
* @param preferEventExtractors If this threads should prefer event based extractors.
|
||||
*/
|
||||
public static void setThreadPrefersEventExtractors(boolean preferEventExtractors) {
|
||||
threadPreferEventExtractors.set(preferEventExtractors);
|
||||
|
@ -90,6 +96,8 @@ public final class OLE2ExtractorFactory {
|
|||
/**
|
||||
* Should all threads prefer event based over usermodel based extractors?
|
||||
* If set, will take preference over the Thread level setting.
|
||||
*
|
||||
* @param preferEventExtractors If all threads should prefer event based extractors.
|
||||
*/
|
||||
public static void setAllThreadsPreferEventExtractors(Boolean preferEventExtractors) {
|
||||
allPreferEventExtractors = preferEventExtractors;
|
||||
|
@ -98,6 +106,8 @@ public final class OLE2ExtractorFactory {
|
|||
/**
|
||||
* Should this thread use event based extractors is available?
|
||||
* Checks the all-threads one first, then thread specific.
|
||||
*
|
||||
* @return If the current thread should use event based extractors.
|
||||
*/
|
||||
public static boolean getPreferEventExtractor() {
|
||||
if(allPreferEventExtractors != null) {
|
||||
|
@ -155,6 +165,16 @@ public final class OLE2ExtractorFactory {
|
|||
* Create the Extractor, if possible. Generally needs the Scratchpad jar.
|
||||
* Note that this won't check for embedded OOXML resources either, use
|
||||
* {@link org.apache.poi.ooxml.extractor.ExtractorFactory} for that.
|
||||
*
|
||||
* @param poifsDir The {@link DirectoryNode} pointing to a document.
|
||||
*
|
||||
* @return The resulting {@link POITextExtractor}, an exception is thrown if
|
||||
* no TextExtractor can be created for some reason.
|
||||
*
|
||||
* @throws IOException If converting the {@link DirectoryNode} into a HSSFWorkbook fails
|
||||
* @throws OldFileFormatException If the {@link DirectoryNode} points to a format of
|
||||
* an unsupported version of Excel.
|
||||
* @throws IllegalArgumentException If creating the Extractor fails
|
||||
*/
|
||||
public static POITextExtractor createExtractor(DirectoryNode poifsDir) throws IOException {
|
||||
// Look for certain entries in the stream, to figure it
|
||||
|
@ -193,11 +213,17 @@ public final class OLE2ExtractorFactory {
|
|||
* If there are no embedded documents, you'll get back an
|
||||
* empty array. Otherwise, you'll get one open
|
||||
* {@link POITextExtractor} for each embedded file.
|
||||
*
|
||||
* @param ext The extractor to look at for embedded documents
|
||||
*
|
||||
* @return An array of resulting extractors. Empty if no embedded documents are found.
|
||||
*
|
||||
* @throws IOException If converting the {@link DirectoryNode} into a HSSFWorkbook fails
|
||||
* @throws OldFileFormatException If the {@link DirectoryNode} points to a format of
|
||||
* an unsupported version of Excel.
|
||||
* @throws IllegalArgumentException If creating the Extractor fails
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static POITextExtractor[] getEmbededDocsTextExtractors(POIOLE2TextExtractor ext)
|
||||
throws IOException
|
||||
{
|
||||
public static POITextExtractor[] getEmbededDocsTextExtractors(POIOLE2TextExtractor ext) throws IOException {
|
||||
// All the embedded directories we spotted
|
||||
List<Entry> dirs = new ArrayList<>();
|
||||
// For anything else not directly held in as a POIFS directory
|
||||
|
@ -237,13 +263,12 @@ public final class OLE2ExtractorFactory {
|
|||
|
||||
ArrayList<POITextExtractor> e = new ArrayList<>();
|
||||
for (Entry dir : dirs) {
|
||||
e.add(createExtractor(
|
||||
(DirectoryNode) dir
|
||||
e.add(createExtractor((DirectoryNode) dir
|
||||
));
|
||||
}
|
||||
for (InputStream nonPOIF : nonPOIFS) {
|
||||
for (InputStream stream : nonPOIFS) {
|
||||
try {
|
||||
e.add(createExtractor(nonPOIF));
|
||||
e.add(createExtractor(stream));
|
||||
} catch (Exception xe) {
|
||||
// Ignore, invalid format
|
||||
LOGGER.log(POILogger.WARN, xe);
|
||||
|
|
|
@ -248,12 +248,14 @@ public class Property {
|
|||
/**
|
||||
* Returns the property's size in bytes. This is always a multiple of 4.
|
||||
*
|
||||
* @param property The integer property to check
|
||||
*
|
||||
* @return the property's size in bytes
|
||||
*
|
||||
* @exception WritingNotSupportedException if HPSF does not yet support the
|
||||
* property's variant type.
|
||||
*/
|
||||
protected int getSize(int codepage) throws WritingNotSupportedException
|
||||
protected int getSize(int property) throws WritingNotSupportedException
|
||||
{
|
||||
int length = Variant.getVariantLength(type);
|
||||
if (length >= 0 || type == Variant.VT_EMPTY) {
|
||||
|
@ -269,16 +271,16 @@ public class Property {
|
|||
if (type == Variant.VT_LPSTR || type == Variant.VT_LPWSTR) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try {
|
||||
length = write(bos, codepage) - 2*LittleEndianConsts.INT_SIZE;
|
||||
length = write(bos, property) - 2*LittleEndianConsts.INT_SIZE;
|
||||
/* Pad to multiples of 4. */
|
||||
length += (4 - (length & 0x3)) & 0x3;
|
||||
return length;
|
||||
} catch (IOException e) {
|
||||
throw new WritingNotSupportedException(type, value);
|
||||
throw new WritingNotSupportedException(type, this.value);
|
||||
}
|
||||
}
|
||||
|
||||
throw new WritingNotSupportedException(type, value);
|
||||
throw new WritingNotSupportedException(type, this.value);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,15 @@ import org.apache.poi.util.Internal;
|
|||
@SuppressWarnings("unused")
|
||||
@Internal
|
||||
public class HSSFWorkbookFactory extends WorkbookFactory {
|
||||
/**
|
||||
* Create a new empty Workbook
|
||||
*
|
||||
* @return The created workbook
|
||||
*/
|
||||
public static HSSFWorkbook createWorkbook() {
|
||||
return new HSSFWorkbook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HSSFWorkbook from the given NPOIFSFileSystem<p>
|
||||
* Note that in order to properly release resources the
|
||||
|
|
|
@ -20,9 +20,19 @@ package org.apache.poi.poifs.macros;
|
|||
import static org.apache.poi.util.StringUtil.endsWithIgnoreCase;
|
||||
import static org.apache.poi.util.StringUtil.startsWithIgnoreCase;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
@ -39,6 +49,8 @@ import org.apache.poi.util.CodePageUtil;
|
|||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.util.RLEDecompressingInputStream;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
|
@ -56,6 +68,10 @@ import org.apache.poi.util.StringUtil;
|
|||
* @since 3.15-beta2
|
||||
*/
|
||||
public class VBAMacroReader implements Closeable {
|
||||
private static final POILogger LOGGER = POILogFactory.getLogger(VBAMacroReader.class);
|
||||
|
||||
//arbitrary limit on size of strings to read, etc.
|
||||
private static final int MAX_STRING_LENGTH = 20000;
|
||||
protected static final String VBA_PROJECT_OOXML = "vbaProject.bin";
|
||||
protected static final String VBA_PROJECT_POIFS = "VBA";
|
||||
|
||||
|
@ -111,8 +127,13 @@ public class VBAMacroReader implements Closeable {
|
|||
|
||||
public Map<String, Module> readMacroModules() throws IOException {
|
||||
final ModuleMap modules = new ModuleMap();
|
||||
//ascii -> unicode mapping for module names
|
||||
//preserve insertion order
|
||||
final Map<String, String> moduleNameMap = new LinkedHashMap<>();
|
||||
|
||||
findMacros(fs.getRoot(), modules);
|
||||
findProjectProperties(fs.getRoot(), modules);
|
||||
findModuleNameMap(fs.getRoot(), moduleNameMap, modules);
|
||||
findProjectProperties(fs.getRoot(), moduleNameMap, modules);
|
||||
|
||||
Map<String, Module> moduleSources = new HashMap<>();
|
||||
for (Map.Entry<String, ModuleImpl> entry : modules.entrySet()) {
|
||||
|
@ -327,19 +348,30 @@ public class VBAMacroReader implements Closeable {
|
|||
}
|
||||
}
|
||||
|
||||
protected void findProjectProperties(DirectoryNode node, ModuleMap modules) throws IOException {
|
||||
protected void findProjectProperties(DirectoryNode node, Map<String, String> moduleNameMap, ModuleMap modules) throws IOException {
|
||||
for (Entry entry : node) {
|
||||
if ("project".equalsIgnoreCase(entry.getName())) {
|
||||
DocumentNode document = (DocumentNode)entry;
|
||||
DocumentInputStream dis = new DocumentInputStream(document);
|
||||
readProjectProperties(dis, modules);
|
||||
} else {
|
||||
for (Entry child : node) {
|
||||
if (child instanceof DirectoryNode) {
|
||||
findProjectProperties((DirectoryNode)child, modules);
|
||||
}
|
||||
try(DocumentInputStream dis = new DocumentInputStream(document)) {
|
||||
readProjectProperties(dis, moduleNameMap, modules);
|
||||
return;
|
||||
}
|
||||
} else if (entry instanceof DirectoryNode) {
|
||||
findProjectProperties((DirectoryNode)entry, moduleNameMap, modules);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void findModuleNameMap(DirectoryNode node, Map<String, String> moduleNameMap, ModuleMap modules) throws IOException {
|
||||
for (Entry entry : node) {
|
||||
if ("projectwm".equalsIgnoreCase(entry.getName())) {
|
||||
DocumentNode document = (DocumentNode)entry;
|
||||
try(DocumentInputStream dis = new DocumentInputStream(document)) {
|
||||
readNameMapRecords(dis, moduleNameMap, modules.charset);
|
||||
return;
|
||||
}
|
||||
} else if (entry.isDirectoryEntry()) {
|
||||
findModuleNameMap((DirectoryNode)entry, moduleNameMap, modules);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -426,10 +458,18 @@ public class VBAMacroReader implements Closeable {
|
|||
private static class ASCIIUnicodeStringPair {
|
||||
private final String ascii;
|
||||
private final String unicode;
|
||||
private final int pushbackRecordId;
|
||||
|
||||
ASCIIUnicodeStringPair(String ascii, int pushbackRecordId) {
|
||||
this.ascii = ascii;
|
||||
this.unicode = "";
|
||||
this.pushbackRecordId = pushbackRecordId;
|
||||
}
|
||||
|
||||
ASCIIUnicodeStringPair(String ascii, String unicode) {
|
||||
this.ascii = ascii;
|
||||
this.unicode = unicode;
|
||||
pushbackRecordId = -1;
|
||||
}
|
||||
|
||||
private String getAscii() {
|
||||
|
@ -439,6 +479,10 @@ public class VBAMacroReader implements Closeable {
|
|||
private String getUnicode() {
|
||||
return unicode;
|
||||
}
|
||||
|
||||
private int getPushbackRecordId() {
|
||||
return pushbackRecordId;
|
||||
}
|
||||
}
|
||||
|
||||
private void processDirStream(Entry dir, ModuleMap modules) throws IOException {
|
||||
|
@ -447,7 +491,7 @@ public class VBAMacroReader implements Closeable {
|
|||
try (DocumentInputStream dis = new DocumentInputStream(dirDocumentNode)) {
|
||||
String streamName = null;
|
||||
int recordId = 0;
|
||||
boolean inReferenceTwiddled = false;
|
||||
|
||||
try (RLEDecompressingInputStream in = new RLEDecompressingInputStream(dis)) {
|
||||
while (true) {
|
||||
recordId = in.readShort();
|
||||
|
@ -485,7 +529,27 @@ public class VBAMacroReader implements Closeable {
|
|||
if (dirState.equals(DIR_STATE.INFORMATION_RECORD)) {
|
||||
dirState = DIR_STATE.REFERENCES_RECORD;
|
||||
}
|
||||
readStringPair(in, modules.charset, REFERENCE_NAME_RESERVED);
|
||||
ASCIIUnicodeStringPair stringPair = readStringPair(in,
|
||||
modules.charset, REFERENCE_NAME_RESERVED, false);
|
||||
if (stringPair.getPushbackRecordId() == -1) {
|
||||
break;
|
||||
}
|
||||
//Special handling for when there's only an ascii string and a REFERENCED_REGISTERED
|
||||
//record that follows.
|
||||
//See https://github.com/decalage2/oletools/blob/master/oletools/olevba.py#L1516
|
||||
//and https://github.com/decalage2/oletools/pull/135 from (@c1fe)
|
||||
if (stringPair.getPushbackRecordId() != RecordType.REFERENCE_REGISTERED.id) {
|
||||
throw new IllegalArgumentException("Unexpected reserved character. "+
|
||||
"Expected "+Integer.toHexString(REFERENCE_NAME_RESERVED)
|
||||
+ " or "+Integer.toHexString(RecordType.REFERENCE_REGISTERED.id)+
|
||||
" not: "+Integer.toHexString(stringPair.getPushbackRecordId()));
|
||||
}
|
||||
//fall through!
|
||||
case REFERENCE_REGISTERED:
|
||||
//REFERENCE_REGISTERED must come immediately after
|
||||
//REFERENCE_NAME to allow for fall through in special case of bug 62625
|
||||
int recLength = in.readInt();
|
||||
trySkip(in, recLength);
|
||||
break;
|
||||
case MODULE_DOC_STRING:
|
||||
int modDocStringLength = in.readInt();
|
||||
|
@ -546,19 +610,105 @@ public class VBAMacroReader implements Closeable {
|
|||
}
|
||||
}
|
||||
|
||||
private ASCIIUnicodeStringPair readStringPair(RLEDecompressingInputStream in, Charset charset, int reservedByte) throws IOException {
|
||||
|
||||
|
||||
private ASCIIUnicodeStringPair readStringPair(RLEDecompressingInputStream in,
|
||||
Charset charset, int reservedByte) throws IOException {
|
||||
return readStringPair(in, charset, reservedByte, true);
|
||||
}
|
||||
|
||||
private ASCIIUnicodeStringPair readStringPair(RLEDecompressingInputStream in,
|
||||
Charset charset, int reservedByte,
|
||||
boolean throwOnUnexpectedReservedByte) throws IOException {
|
||||
int nameLength = in.readInt();
|
||||
String ascii = readString(in, nameLength, charset);
|
||||
int reserved = in.readShort();
|
||||
|
||||
if (reserved != reservedByte) {
|
||||
throw new IOException("Expected "+Integer.toHexString(reservedByte)+ "after name before Unicode name, but found: " +
|
||||
Integer.toHexString(reserved));
|
||||
if (throwOnUnexpectedReservedByte) {
|
||||
throw new IOException("Expected " + Integer.toHexString(reservedByte) +
|
||||
"after name before Unicode name, but found: " +
|
||||
Integer.toHexString(reserved));
|
||||
} else {
|
||||
return new ASCIIUnicodeStringPair(ascii, reserved);
|
||||
}
|
||||
}
|
||||
int unicodeNameRecordLength = in.readInt();
|
||||
String unicode = readUnicodeString(in, unicodeNameRecordLength);
|
||||
return new ASCIIUnicodeStringPair(ascii, unicode);
|
||||
}
|
||||
|
||||
protected void readNameMapRecords(InputStream is,
|
||||
Map<String, String> moduleNames, Charset charset) throws IOException {
|
||||
//see 2.3.3 PROJECTwm Stream: Module Name Information
|
||||
//multibytecharstring
|
||||
String mbcs = null;
|
||||
String unicode = null;
|
||||
//arbitrary sanity threshold
|
||||
final int maxNameRecords = 10000;
|
||||
int records = 0;
|
||||
while (++records < maxNameRecords) {
|
||||
try {
|
||||
int b = IOUtils.readByte(is);
|
||||
//check for two 0x00 that mark end of record
|
||||
if (b == 0) {
|
||||
b = IOUtils.readByte(is);
|
||||
if (b == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mbcs = readMBCS(b, is, charset, MAX_STRING_LENGTH);
|
||||
} catch (EOFException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
unicode = readUnicode(is, MAX_STRING_LENGTH);
|
||||
} catch (EOFException e) {
|
||||
return;
|
||||
}
|
||||
if (mbcs.trim().length() > 0 && unicode.trim().length() > 0) {
|
||||
moduleNames.put(mbcs, unicode);
|
||||
}
|
||||
|
||||
}
|
||||
if (records >= maxNameRecords) {
|
||||
LOGGER.log(POILogger.WARN, "Hit max name records to read ("+maxNameRecords+"). Stopped early.");
|
||||
}
|
||||
}
|
||||
|
||||
private static String readUnicode(InputStream is, int maxLength) throws IOException {
|
||||
//reads null-terminated unicode string
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
int b0 = IOUtils.readByte(is);
|
||||
int b1 = IOUtils.readByte(is);
|
||||
|
||||
int read = 2;
|
||||
while ((b0 + b1) != 0 && read < maxLength) {
|
||||
|
||||
bos.write(b0);
|
||||
bos.write(b1);
|
||||
b0 = IOUtils.readByte(is);
|
||||
b1 = IOUtils.readByte(is);
|
||||
read += 2;
|
||||
}
|
||||
if (read >= maxLength) {
|
||||
LOGGER.log(POILogger.WARN, "stopped reading unicode name after "+read+" bytes");
|
||||
}
|
||||
return new String (bos.toByteArray(), StandardCharsets.UTF_16LE);
|
||||
}
|
||||
|
||||
private static String readMBCS(int firstByte, InputStream is, Charset charset, int maxLength) throws IOException {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
int len = 0;
|
||||
int b = firstByte;
|
||||
while (b > 0 && len < maxLength) {
|
||||
++len;
|
||||
bos.write(b);
|
||||
b = IOUtils.readByte(is);
|
||||
}
|
||||
return new String(bos.toByteArray(), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read <tt>length</tt> bytes of MBCS (multi-byte character set) characters from the stream
|
||||
|
@ -570,7 +720,7 @@ public class VBAMacroReader implements Closeable {
|
|||
* @throws IOException If reading from the stream fails
|
||||
*/
|
||||
private static String readString(InputStream stream, int length, Charset charset) throws IOException {
|
||||
byte[] buffer = IOUtils.safelyAllocate(length, 20000);
|
||||
byte[] buffer = IOUtils.safelyAllocate(length, MAX_STRING_LENGTH);
|
||||
int bytesRead = IOUtils.readFully(stream, buffer);
|
||||
if (bytesRead != length) {
|
||||
throw new IOException("Tried to read: "+length +
|
||||
|
@ -579,7 +729,8 @@ public class VBAMacroReader implements Closeable {
|
|||
return new String(buffer, 0, length, charset);
|
||||
}
|
||||
|
||||
protected void readProjectProperties(DocumentInputStream dis, ModuleMap modules) throws IOException {
|
||||
protected void readProjectProperties(DocumentInputStream dis,
|
||||
Map<String, String> moduleNameMap, ModuleMap modules) throws IOException {
|
||||
InputStreamReader reader = new InputStreamReader(dis, modules.charset);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
char[] buffer = new char[512];
|
||||
|
@ -588,6 +739,9 @@ public class VBAMacroReader implements Closeable {
|
|||
builder.append(buffer, 0, read);
|
||||
}
|
||||
String properties = builder.toString();
|
||||
//the module name map names should be in exactly the same order
|
||||
//as the module names here. See 2.3.3 PROJECTwm Stream.
|
||||
//At some point, we might want to enforce that.
|
||||
for (String line : properties.split("\r\n|\n\r")) {
|
||||
if (!line.startsWith("[")) {
|
||||
String[] tokens = line.split("=");
|
||||
|
@ -595,28 +749,46 @@ public class VBAMacroReader implements Closeable {
|
|||
&& tokens[1].startsWith("\"") && tokens[1].endsWith("\"")) {
|
||||
// Remove any double quotes
|
||||
tokens[1] = tokens[1].substring(1, tokens[1].length() - 1);
|
||||
|
||||
}
|
||||
if ("Document".equals(tokens[0])) {
|
||||
if ("Document".equals(tokens[0]) && tokens.length > 1) {
|
||||
String mn = tokens[1].substring(0, tokens[1].indexOf("/&H"));
|
||||
ModuleImpl module = modules.get(mn);
|
||||
module.moduleType = ModuleType.Document;
|
||||
} else if ("Module".equals(tokens[0])) {
|
||||
ModuleImpl module = modules.get(tokens[1]);
|
||||
module.moduleType = ModuleType.Module;
|
||||
} else if ("Class".equals(tokens[0])) {
|
||||
ModuleImpl module = modules.get(tokens[1]);
|
||||
module.moduleType = ModuleType.Class;
|
||||
ModuleImpl module = getModule(mn, moduleNameMap, modules);
|
||||
if (module != null) {
|
||||
module.moduleType = ModuleType.Document;
|
||||
} else {
|
||||
LOGGER.log(POILogger.WARN, "couldn't find module with name: "+mn);
|
||||
}
|
||||
} else if ("Module".equals(tokens[0]) && tokens.length > 1) {
|
||||
ModuleImpl module = getModule(tokens[1], moduleNameMap, modules);
|
||||
if (module != null) {
|
||||
module.moduleType = ModuleType.Module;
|
||||
} else {
|
||||
LOGGER.log(POILogger.WARN, "couldn't find module with name: "+tokens[1]);
|
||||
}
|
||||
} else if ("Class".equals(tokens[0]) && tokens.length > 1) {
|
||||
ModuleImpl module = getModule(tokens[1], moduleNameMap, modules);
|
||||
if (module != null) {
|
||||
module.moduleType = ModuleType.Class;
|
||||
} else {
|
||||
LOGGER.log(POILogger.WARN, "couldn't find module with name: "+tokens[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//can return null!
|
||||
private ModuleImpl getModule(String moduleName, Map<String, String> moduleNameMap, ModuleMap moduleMap) {
|
||||
if (moduleNameMap.containsKey(moduleName)) {
|
||||
return moduleMap.get(moduleNameMap.get(moduleName));
|
||||
}
|
||||
return moduleMap.get(moduleName);
|
||||
}
|
||||
|
||||
private String readUnicodeString(RLEDecompressingInputStream in, int unicodeNameRecordLength) throws IOException {
|
||||
byte[] buffer = IOUtils.safelyAllocate(unicodeNameRecordLength, 20000);
|
||||
byte[] buffer = IOUtils.safelyAllocate(unicodeNameRecordLength, MAX_STRING_LENGTH);
|
||||
int bytesRead = IOUtils.readFully(in, buffer);
|
||||
if (bytesRead != unicodeNameRecordLength) {
|
||||
|
||||
throw new EOFException();
|
||||
}
|
||||
return new String(buffer, StringUtil.UTF16LE);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ public class CellDateFormatter extends CellFormatter {
|
|||
private int hStart = -1;
|
||||
private int hLen;
|
||||
|
||||
@Override
|
||||
public String handlePart(Matcher m, String part, CellFormatType type,
|
||||
StringBuffer desc) {
|
||||
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
==================================================================== */
|
||||
package org.apache.poi.ss.format;
|
||||
|
||||
import org.apache.poi.ss.format.CellFormatPart.PartHandler;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* This class implements printing out text.
|
||||
|
@ -38,15 +35,12 @@ public class CellTextFormatter extends CellFormatter {
|
|||
final int[] numPlaces = new int[1];
|
||||
|
||||
desc = CellFormatPart.parseFormat(format, CellFormatType.TEXT,
|
||||
new PartHandler() {
|
||||
public String handlePart(Matcher m, String part,
|
||||
CellFormatType type, StringBuffer desc) {
|
||||
if (part.equals("@")) {
|
||||
numPlaces[0]++;
|
||||
return "\u0000";
|
||||
}
|
||||
return null;
|
||||
(m, part, type, desc) -> {
|
||||
if (part.equals("@")) {
|
||||
numPlaces[0]++;
|
||||
return "\u0000";
|
||||
}
|
||||
return null;
|
||||
}).toString();
|
||||
|
||||
// Remember the "@" positions in last-to-first order (to make insertion easier)
|
||||
|
@ -66,8 +60,8 @@ public class CellTextFormatter extends CellFormatter {
|
|||
text = text.toUpperCase(Locale.ROOT);
|
||||
}
|
||||
toAppendTo.append(desc);
|
||||
for (int i = 0; i < textPos.length; i++) {
|
||||
int pos = start + textPos[i];
|
||||
for (int textPo : textPos) {
|
||||
int pos = start + textPo;
|
||||
toAppendTo.replace(pos, pos + 1, text);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,14 @@ public abstract class BaseFormulaEvaluator implements FormulaEvaluator, Workbook
|
|||
return _bookEvaluator;
|
||||
}
|
||||
|
||||
/**
|
||||
* internal use
|
||||
* @return evaluation workbook
|
||||
*/
|
||||
protected EvaluationWorkbook getEvaluationWorkbook() {
|
||||
return _bookEvaluator.getWorkbook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called whenever there are major changes (e.g. moving sheets) to input cells
|
||||
* in the evaluated workbook. If performance is not critical, a single call to this method
|
||||
|
@ -208,14 +216,19 @@ public abstract class BaseFormulaEvaluator implements FormulaEvaluator, Workbook
|
|||
return evaluateFormulaCell(cell);
|
||||
}
|
||||
|
||||
protected static void setCellType(Cell cell, CellValue cv) {
|
||||
/**
|
||||
* set the cell type
|
||||
* @param cell
|
||||
* @param cv
|
||||
*/
|
||||
protected void setCellType(Cell cell, CellValue cv) {
|
||||
CellType cellType = cv.getCellType();
|
||||
switch (cellType) {
|
||||
case BOOLEAN:
|
||||
case ERROR:
|
||||
case NUMERIC:
|
||||
case STRING:
|
||||
cell.setCellType(cellType);
|
||||
setCellType(cell, cellType);
|
||||
return;
|
||||
case BLANK:
|
||||
// never happens - blanks eventually get translated to zero
|
||||
|
@ -227,6 +240,15 @@ public abstract class BaseFormulaEvaluator implements FormulaEvaluator, Workbook
|
|||
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if a different variation is needed, e.g. passing the evaluator to the cell method
|
||||
* @param cell
|
||||
* @param cellType
|
||||
*/
|
||||
protected void setCellType(Cell cell, CellType cellType) {
|
||||
cell.setCellType(cellType);
|
||||
}
|
||||
|
||||
protected abstract RichTextString createRichTextString(String str);
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ public final class FunctionEval {
|
|||
// 47: DVAR
|
||||
retval[48] = TextFunction.TEXT;
|
||||
// 49: LINEST
|
||||
// 50: TREND
|
||||
retval[50] = new Trend();
|
||||
// 51: LOGEST
|
||||
// 52: GROWTH
|
||||
|
||||
|
@ -243,7 +243,8 @@ public final class FunctionEval {
|
|||
|
||||
// 247: DB
|
||||
// 252: FEQUENCY
|
||||
|
||||
retval[252] = Frequency.instance;
|
||||
|
||||
retval[FunctionID.EXTERNAL_FUNC] = null; // ExternalFunction is a FreeRefFunction, nominally 255
|
||||
|
||||
retval[261] = new Errortype();
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.ss.formula.CacheAreaEval;
|
||||
import org.apache.poi.ss.formula.eval.EvaluationException;
|
||||
import org.apache.poi.ss.formula.eval.NumberEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Implementation of Excel 'Analysis ToolPak' function FREQUENCY()<br>
|
||||
* Returns a frequency distribution as a vertical array<p>
|
||||
* <p>
|
||||
* <b>Syntax</b><br>
|
||||
* <b>FREQUENCY</b>(<b>data_array</b>, <b>bins_array</b>)<p>
|
||||
* <p>
|
||||
* <b>data_array</b> Required. An array of or reference to a set of values for which you want to count frequencies.
|
||||
* If data_array contains no values, FREQUENCY returns an array of zeros.<br>
|
||||
* <b>bins_array</b> Required. An array of or reference to intervals into which you want to group the values in data_array.
|
||||
* If bins_array contains no values, FREQUENCY returns the number of elements in data_array.<br>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class Frequency extends Fixed2ArgFunction {
|
||||
public static final Function instance = new Frequency();
|
||||
|
||||
private Frequency() {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
|
||||
MatrixFunction.MutableValueCollector collector = new MatrixFunction.MutableValueCollector(false, false);
|
||||
|
||||
double[] values;
|
||||
double[] bins;
|
||||
try {
|
||||
values = collector.collectValues(arg0);
|
||||
bins = collector.collectValues(arg1);
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
|
||||
// can bins be not sorted?
|
||||
//bins = Arrays.stream(bins).sorted().distinct().toArray();
|
||||
|
||||
int[] histogram = histogram(values, bins);
|
||||
NumberEval[] result = Arrays.stream(histogram).boxed().map(NumberEval::new).toArray(NumberEval[]::new);
|
||||
return new CacheAreaEval(srcRowIndex, srcColumnIndex,
|
||||
srcRowIndex + result.length - 1, srcColumnIndex, result);
|
||||
}
|
||||
|
||||
static int findBin(double value, double[] bins) {
|
||||
int idx = Arrays.binarySearch(bins, value);
|
||||
return idx >= 0 ? idx + 1 : -idx;
|
||||
}
|
||||
|
||||
static int[] histogram(double[] values, double[] bins) {
|
||||
int[] histogram = new int[bins.length + 1];
|
||||
for (double val : values) {
|
||||
histogram[findBin(val, bins) - 1]++;
|
||||
}
|
||||
return histogram;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
/*
|
||||
* Notes:
|
||||
* Duplicate x values don't work most of the time because of the way the
|
||||
* math library handles multiple regression.
|
||||
* The math library currently fails when the number of x variables is >=
|
||||
* the sample size (see https://github.com/Hipparchus-Math/hipparchus/issues/13).
|
||||
*/
|
||||
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.ss.formula.CacheAreaEval;
|
||||
import org.apache.poi.ss.formula.eval.AreaEval;
|
||||
import org.apache.poi.ss.formula.eval.BoolEval;
|
||||
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||
import org.apache.poi.ss.formula.eval.EvaluationException;
|
||||
import org.apache.poi.ss.formula.eval.MissingArgEval;
|
||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||
import org.apache.poi.ss.formula.eval.NumberEval;
|
||||
import org.apache.poi.ss.formula.eval.NumericValueEval;
|
||||
import org.apache.poi.ss.formula.eval.RefEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
import org.apache.commons.math3.linear.SingularMatrixException;
|
||||
import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation for the Excel function TREND<p>
|
||||
*
|
||||
* Syntax:<br>
|
||||
* TREND(known_y's, known_x's, new_x's, constant)
|
||||
* <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions">
|
||||
* <tr><th>known_y's, known_x's, new_x's</th><td>typically area references, possibly cell references or scalar values</td></tr>
|
||||
* <tr><th>constant</th><td><b>TRUE</b> or <b>FALSE</b>:
|
||||
* determines whether the regression line should include an intercept term</td></tr>
|
||||
* </table><br>
|
||||
* If <b>known_x's</b> is not given, it is assumed to be the default array {1, 2, 3, ...}
|
||||
* of the same size as <b>known_y's</b>.<br>
|
||||
* If <b>new_x's</b> is not given, it is assumed to be the same as <b>known_x's</b><br>
|
||||
* If <b>constant</b> is omitted, it is assumed to be <b>TRUE</b>
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public final class Trend implements Function {
|
||||
MatrixFunction.MutableValueCollector collector = new MatrixFunction.MutableValueCollector(false, false);
|
||||
private static final class TrendResults {
|
||||
public double[] vals;
|
||||
public int resultWidth;
|
||||
public int resultHeight;
|
||||
|
||||
public TrendResults(double[] vals, int resultWidth, int resultHeight) {
|
||||
this.vals = vals;
|
||||
this.resultWidth = resultWidth;
|
||||
this.resultHeight = resultHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
|
||||
if (args.length < 1 || args.length > 4) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
try {
|
||||
TrendResults tr = getNewY(args);
|
||||
ValueEval[] vals = new ValueEval[tr.vals.length];
|
||||
for (int i = 0; i < tr.vals.length; i++) {
|
||||
vals[i] = new NumberEval(tr.vals[i]);
|
||||
}
|
||||
if (tr.vals.length == 1) {
|
||||
return vals[0];
|
||||
}
|
||||
return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + tr.resultHeight - 1, srcColumnIndex + tr.resultWidth - 1, vals);
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
}
|
||||
|
||||
private static double[][] evalToArray(ValueEval arg) throws EvaluationException {
|
||||
double[][] ar;
|
||||
ValueEval eval;
|
||||
if (arg instanceof MissingArgEval) {
|
||||
return new double[0][0];
|
||||
}
|
||||
if (arg instanceof RefEval) {
|
||||
RefEval re = (RefEval) arg;
|
||||
if (re.getNumberOfSheets() > 1) {
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
eval = re.getInnerValueEval(re.getFirstSheetIndex());
|
||||
} else {
|
||||
eval = arg;
|
||||
}
|
||||
if (eval == null) {
|
||||
throw new RuntimeException("Parameter may not be null.");
|
||||
}
|
||||
|
||||
if (eval instanceof AreaEval) {
|
||||
AreaEval ae = (AreaEval) eval;
|
||||
int w = ae.getWidth();
|
||||
int h = ae.getHeight();
|
||||
ar = new double[h][w];
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
ValueEval ve = ae.getRelativeValue(i, j);
|
||||
if (!(ve instanceof NumericValueEval)) {
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
ar[i][j] = ((NumericValueEval)ve).getNumberValue();
|
||||
}
|
||||
}
|
||||
} else if (eval instanceof NumericValueEval) {
|
||||
ar = new double[1][1];
|
||||
ar[0][0] = ((NumericValueEval)eval).getNumberValue();
|
||||
} else {
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
private static double[][] getDefaultArrayOneD(int w) {
|
||||
double[][] array = new double[w][1];
|
||||
for (int i = 0; i < w; i++) {
|
||||
array[i][0] = i + 1;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private static double[] flattenArray(double[][] twoD) {
|
||||
if (twoD.length < 1) {
|
||||
return new double[0];
|
||||
}
|
||||
double[] oneD = new double[twoD.length * twoD[0].length];
|
||||
for (int i = 0; i < twoD.length; i++) {
|
||||
for (int j = 0; j < twoD[0].length; j++) {
|
||||
oneD[i * twoD[0].length + j] = twoD[i][j];
|
||||
}
|
||||
}
|
||||
return oneD;
|
||||
}
|
||||
|
||||
private static double[][] flattenArrayToRow(double[][] twoD) {
|
||||
if (twoD.length < 1) {
|
||||
return new double[0][0];
|
||||
}
|
||||
double[][] oneD = new double[twoD.length * twoD[0].length][1];
|
||||
for (int i = 0; i < twoD.length; i++) {
|
||||
for (int j = 0; j < twoD[0].length; j++) {
|
||||
oneD[i * twoD[0].length + j][0] = twoD[i][j];
|
||||
}
|
||||
}
|
||||
return oneD;
|
||||
}
|
||||
|
||||
private static double[][] switchRowsColumns(double[][] array) {
|
||||
double[][] newArray = new double[array[0].length][array.length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
for (int j = 0; j < array[0].length; j++) {
|
||||
newArray[j][i] = array[i][j];
|
||||
}
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all columns in a matrix contain the same values.
|
||||
* Return true if the number of distinct values in each column is 1.
|
||||
*
|
||||
* @param matrix column-oriented matrix. A Row matrix should be transposed to column .
|
||||
* @return true if all columns contain the same value
|
||||
*/
|
||||
private static boolean isAllColumnsSame(double[][] matrix){
|
||||
if(matrix.length == 0) return false;
|
||||
|
||||
boolean[] cols = new boolean[matrix[0].length];
|
||||
for (int j = 0; j < matrix[0].length; j++) {
|
||||
double prev = Double.NaN;
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
double v = matrix[i][j];
|
||||
if(i > 0 && v != prev) {
|
||||
cols[j] = true;
|
||||
break;
|
||||
}
|
||||
prev = v;
|
||||
}
|
||||
}
|
||||
boolean allEquals = true;
|
||||
for (boolean x : cols) {
|
||||
if(x) {
|
||||
allEquals = false;
|
||||
break;
|
||||
}
|
||||
};
|
||||
return allEquals;
|
||||
|
||||
}
|
||||
|
||||
private static TrendResults getNewY(ValueEval[] args) throws EvaluationException {
|
||||
double[][] xOrig;
|
||||
double[][] x;
|
||||
double[][] yOrig;
|
||||
double[] y;
|
||||
double[][] newXOrig;
|
||||
double[][] newX;
|
||||
double[][] resultSize;
|
||||
boolean passThroughOrigin = false;
|
||||
switch (args.length) {
|
||||
case 1:
|
||||
yOrig = evalToArray(args[0]);
|
||||
xOrig = new double[0][0];
|
||||
newXOrig = new double[0][0];
|
||||
break;
|
||||
case 2:
|
||||
yOrig = evalToArray(args[0]);
|
||||
xOrig = evalToArray(args[1]);
|
||||
newXOrig = new double[0][0];
|
||||
break;
|
||||
case 3:
|
||||
yOrig = evalToArray(args[0]);
|
||||
xOrig = evalToArray(args[1]);
|
||||
newXOrig = evalToArray(args[2]);
|
||||
break;
|
||||
case 4:
|
||||
yOrig = evalToArray(args[0]);
|
||||
xOrig = evalToArray(args[1]);
|
||||
newXOrig = evalToArray(args[2]);
|
||||
if (!(args[3] instanceof BoolEval)) {
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
// The argument in Excel is false when it *should* pass through the origin.
|
||||
passThroughOrigin = !((BoolEval)args[3]).getBooleanValue();
|
||||
break;
|
||||
default:
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
|
||||
if (yOrig.length < 1) {
|
||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
y = flattenArray(yOrig);
|
||||
newX = newXOrig;
|
||||
|
||||
if (newXOrig.length > 0) {
|
||||
resultSize = newXOrig;
|
||||
} else {
|
||||
resultSize = new double[1][1];
|
||||
}
|
||||
|
||||
if (y.length == 1) {
|
||||
/* See comment at top of file
|
||||
if (xOrig.length > 0 && !(xOrig.length == 1 || xOrig[0].length == 1)) {
|
||||
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||
} else if (xOrig.length < 1) {
|
||||
x = new double[1][1];
|
||||
x[0][0] = 1;
|
||||
} else {
|
||||
x = new double[1][];
|
||||
x[0] = flattenArray(xOrig);
|
||||
if (newXOrig.length < 1) {
|
||||
resultSize = xOrig;
|
||||
}
|
||||
}*/
|
||||
throw new NotImplementedException("Sample size too small");
|
||||
} else if (yOrig.length == 1 || yOrig[0].length == 1) {
|
||||
if (xOrig.length < 1) {
|
||||
x = getDefaultArrayOneD(y.length);
|
||||
if (newXOrig.length < 1) {
|
||||
resultSize = yOrig;
|
||||
}
|
||||
} else {
|
||||
x = xOrig;
|
||||
if (xOrig[0].length > 1 && yOrig.length == 1) {
|
||||
x = switchRowsColumns(x);
|
||||
}
|
||||
if (newXOrig.length < 1) {
|
||||
resultSize = xOrig;
|
||||
}
|
||||
}
|
||||
if (newXOrig.length > 0 && (x.length == 1 || x[0].length == 1)) {
|
||||
newX = flattenArrayToRow(newXOrig);
|
||||
}
|
||||
} else {
|
||||
if (xOrig.length < 1) {
|
||||
x = getDefaultArrayOneD(y.length);
|
||||
if (newXOrig.length < 1) {
|
||||
resultSize = yOrig;
|
||||
}
|
||||
} else {
|
||||
x = flattenArrayToRow(xOrig);
|
||||
if (newXOrig.length < 1) {
|
||||
resultSize = xOrig;
|
||||
}
|
||||
}
|
||||
if (newXOrig.length > 0) {
|
||||
newX = flattenArrayToRow(newXOrig);
|
||||
}
|
||||
if (y.length != x.length || yOrig.length != xOrig.length) {
|
||||
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
if (newXOrig.length < 1) {
|
||||
newX = x;
|
||||
} else if (newXOrig.length == 1 && newXOrig[0].length > 1 && xOrig.length > 1 && xOrig[0].length == 1) {
|
||||
newX = switchRowsColumns(newXOrig);
|
||||
}
|
||||
|
||||
if (newX[0].length != x[0].length) {
|
||||
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||
}
|
||||
|
||||
if (x[0].length >= x.length) {
|
||||
/* See comment at top of file */
|
||||
throw new NotImplementedException("Sample size too small");
|
||||
}
|
||||
|
||||
int resultHeight = resultSize.length;
|
||||
int resultWidth = resultSize[0].length;
|
||||
|
||||
if(isAllColumnsSame(x)){
|
||||
double[] result = new double[newX.length];
|
||||
double avg = Arrays.stream(y).average().orElse(0);
|
||||
for(int i = 0; i < result.length; i++) result[i] = avg;
|
||||
return new TrendResults(result, resultWidth, resultHeight);
|
||||
}
|
||||
|
||||
OLSMultipleLinearRegression reg = new OLSMultipleLinearRegression();
|
||||
if (passThroughOrigin) {
|
||||
reg.setNoIntercept(true);
|
||||
}
|
||||
|
||||
try {
|
||||
reg.newSampleData(y, x);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||
}
|
||||
double[] par;
|
||||
try {
|
||||
par = reg.estimateRegressionParameters();
|
||||
} catch (SingularMatrixException e) {
|
||||
throw new NotImplementedException("Singular matrix in input");
|
||||
}
|
||||
|
||||
double[] result = new double[newX.length];
|
||||
for (int i = 0; i < newX.length; i++) {
|
||||
result[i] = 0;
|
||||
if (passThroughOrigin) {
|
||||
for (int j = 0; j < par.length; j++) {
|
||||
result[i] += par[j] * newX[i][j];
|
||||
}
|
||||
} else {
|
||||
result[i] = par[0];
|
||||
for (int j = 1; j < par.length; j++) {
|
||||
result[i] += par[j] * newX[i][j - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return new TrendResults(result, resultWidth, resultHeight);
|
||||
}
|
||||
}
|
|
@ -43,7 +43,7 @@ public abstract class RefPtgBase extends OperandPtg {
|
|||
|
||||
/**
|
||||
* YK: subclasses of RefPtgBase are used by the FormulaParser and FormulaEvaluator accross HSSF and XSSF.
|
||||
* The bit mask should accomodate the maximum number of avaiable columns, i.e. 0x3FFF.
|
||||
* The bit mask should accommodate the maximum number of avaiable columns, i.e. 0x3FFF.
|
||||
*
|
||||
* @see org.apache.poi.ss.SpreadsheetVersion
|
||||
*/
|
||||
|
|
|
@ -1006,7 +1006,10 @@ public interface Sheet extends Iterable<Row> {
|
|||
|
||||
/**
|
||||
* Sets array formula to specified region for result.
|
||||
*
|
||||
* <p>
|
||||
* Note if there are shared formulas this will invalidate any
|
||||
* {@link FormulaEvaluator} instances based on this workbook
|
||||
*</p>
|
||||
* @param formula text representation of the formula
|
||||
* @param range Region of array formula for result.
|
||||
* @return the {@link CellRange} of cells affected by this change
|
||||
|
|
|
@ -43,6 +43,24 @@ import org.apache.poi.util.Removal;
|
|||
* by auto-detecting from the supplied input.
|
||||
*/
|
||||
public class WorkbookFactory {
|
||||
/**
|
||||
* Create a new empty Workbook, either XSSF or HSSF depending
|
||||
* on the parameter
|
||||
*
|
||||
* @param xssf If an XSSFWorkbook or a HSSFWorkbook should be created
|
||||
*
|
||||
* @return The created workbook
|
||||
*
|
||||
* @throws IOException if an error occurs while reading the data
|
||||
*/
|
||||
public static Workbook create(boolean xssf) throws IOException {
|
||||
if(xssf) {
|
||||
return createXSSFWorkbook();
|
||||
} else {
|
||||
return createHSSFWorkbook();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HSSFWorkbook from the given NPOIFSFileSystem<p>
|
||||
*
|
||||
|
@ -296,6 +314,11 @@ public class WorkbookFactory {
|
|||
return createWorkbook("org.apache.poi.xssf.usermodel.XSSFWorkbookFactory", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the actual call to HSSF or XSSF to do the creation.
|
||||
* Uses reflection, so that this class can be in the Core non-OOXML
|
||||
* POI jar without errors / broken references to the OOXML / XSSF code.
|
||||
*/
|
||||
private static Workbook createWorkbook(String factoryClass, Object args[]) throws IOException, EncryptedDocumentException {
|
||||
try {
|
||||
Class<?> clazz = WorkbookFactory.class.getClassLoader().loadClass(factoryClass);
|
||||
|
@ -307,6 +330,8 @@ public class WorkbookFactory {
|
|||
c = boolean.class;
|
||||
} else if (InputStream.class.isAssignableFrom(c)) {
|
||||
c = InputStream.class;
|
||||
} else if (File.class.isAssignableFrom(c)) {
|
||||
c = File.class;
|
||||
}
|
||||
argsClz[i++] = c;
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ public class CellReference {
|
|||
if (rowRef.length() == 0) {
|
||||
_rowIndex = -1;
|
||||
} else {
|
||||
// throws NumberFormatException if rowRef is not convertable to an int
|
||||
// throws NumberFormatException if rowRef is not convertible to an int
|
||||
_rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
|
||||
}
|
||||
}
|
||||
|
@ -336,10 +336,10 @@ public class CellReference {
|
|||
if(colStr.toUpperCase(Locale.ROOT).compareTo(lastCol) > 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
} /*else {
|
||||
// apparent column name has less chars than max
|
||||
// no need to check range
|
||||
}
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -426,7 +426,7 @@ public class CellReference {
|
|||
// AreaReference.separateAreaRefs()
|
||||
// SheetNameFormatter.format() (inverse)
|
||||
|
||||
StringBuffer sb = new StringBuffer(indexOfSheetNameDelimiter);
|
||||
StringBuilder sb = new StringBuilder(indexOfSheetNameDelimiter);
|
||||
|
||||
for(int i=1; i<lastQuotePos; i++) { // Note boundaries - skip outer quotes
|
||||
char ch = reference.charAt(i);
|
||||
|
@ -495,11 +495,7 @@ public class CellReference {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
return getClass().getName() + " [" + formatAsString() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -420,7 +420,7 @@ public final class CellUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the named short value form the given map.
|
||||
* Utility method that returns the named short value from the given map.
|
||||
*
|
||||
* @param properties map of named properties (String -> Object)
|
||||
* @param name property name
|
||||
|
@ -436,7 +436,7 @@ public final class CellUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the named int value form the given map.
|
||||
* Utility method that returns the named int value from the given map.
|
||||
*
|
||||
* @param properties map of named properties (String -> Object)
|
||||
* @param name property name
|
||||
|
@ -452,7 +452,7 @@ public final class CellUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the named BorderStyle value form the given map.
|
||||
* Utility method that returns the named BorderStyle value from the given map.
|
||||
*
|
||||
* @param properties map of named properties (String -> Object)
|
||||
* @param name property name
|
||||
|
@ -483,7 +483,7 @@ public final class CellUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the named FillPatternType value form the given map.
|
||||
* Utility method that returns the named FillPatternType value from the given map.
|
||||
*
|
||||
* @param properties map of named properties (String -> Object)
|
||||
* @param name property name
|
||||
|
@ -515,7 +515,7 @@ public final class CellUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the named HorizontalAlignment value form the given map.
|
||||
* Utility method that returns the named HorizontalAlignment value from the given map.
|
||||
*
|
||||
* @param properties map of named properties (String -> Object)
|
||||
* @param name property name
|
||||
|
@ -547,7 +547,7 @@ public final class CellUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the named VerticalAlignment value form the given map.
|
||||
* Utility method that returns the named VerticalAlignment value from the given map.
|
||||
*
|
||||
* @param properties map of named properties (String -> Object)
|
||||
* @param name property name
|
||||
|
@ -579,7 +579,7 @@ public final class CellUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns the named boolean value form the given map.
|
||||
* Utility method that returns the named boolean value from the given map.
|
||||
*
|
||||
* @param properties map of properties (String -> Object)
|
||||
* @param name property name
|
||||
|
@ -594,7 +594,7 @@ public final class CellUtil {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility method that puts the given value to the given map.
|
||||
*
|
||||
|
|
|
@ -571,6 +571,22 @@ public final class IOUtils {
|
|||
return new byte[(int)length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple utility function to check that you haven't hit EOF
|
||||
* when reading a byte.
|
||||
*
|
||||
* @param is inputstream to read
|
||||
* @return byte read, unless
|
||||
* @throws IOException on IOException or EOF if -1 is read
|
||||
*/
|
||||
public static int readByte(InputStream is) throws IOException {
|
||||
int b = is.read();
|
||||
if (b == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private static void throwRFE(long length, int maxLength) {
|
||||
throw new RecordFormatException("Tried to allocate an array of length "+length +
|
||||
", but "+ maxLength+" is the maximum for this record type.\n" +
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.apache.poi.util.POILogger;
|
|||
import org.apache.poi.xddf.usermodel.chart.XDDFChart;
|
||||
import org.apache.poi.xssf.usermodel.XSSFRelation;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.xwpf.usermodel.XWPFRelation;
|
||||
|
||||
/**
|
||||
* Represents an entry of a OOXML package.
|
||||
|
@ -613,6 +614,14 @@ public class POIXMLDocumentPart {
|
|||
*/
|
||||
protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException {
|
||||
PackagePart pp = getPackagePart();
|
||||
|
||||
if (pp.getContentType().equals(XWPFRelation.TEMPLATE.getContentType())) {
|
||||
logger.log(POILogger.WARN,
|
||||
"POI does not currently support template.main+xml (glossary) parts. " +
|
||||
"Skipping this part for now.");
|
||||
return;
|
||||
}
|
||||
|
||||
// add mapping a second time, in case of initial caller hasn't done so
|
||||
POIXMLDocumentPart otherChild = context.put(pp, this);
|
||||
if (otherChild != null && otherChild != this) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
package org.apache.poi.openxml4j.exceptions;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public final class InvalidFormatException extends OpenXML4JException{
|
||||
public final class InvalidFormatException extends OpenXML4JException {
|
||||
|
||||
public InvalidFormatException(String message){
|
||||
super(message);
|
||||
|
|
|
@ -291,6 +291,8 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
|
|||
* @param in
|
||||
* The InputStream to read the package from
|
||||
* @return A PackageBase object
|
||||
*
|
||||
* @throws InvalidFormatException
|
||||
*/
|
||||
public static OPCPackage open(InputStream in) throws InvalidFormatException,
|
||||
IOException {
|
||||
|
|
|
@ -63,7 +63,7 @@ import org.w3c.dom.events.EventListener;
|
|||
* This class bundles the configuration options used for the existing
|
||||
* signature facets.
|
||||
* Apart of the thread local members (e.g. opc-package) most values will probably be constant, so
|
||||
* it might be configured centrally (e.g. by spring)
|
||||
* it might be configured centrally (e.g. by spring)
|
||||
*/
|
||||
@SuppressWarnings({"unused","WeakerAccess"})
|
||||
public class SignatureConfig {
|
||||
|
@ -76,14 +76,14 @@ public class SignatureConfig {
|
|||
|
||||
|
||||
public interface SignatureConfigurable {
|
||||
void setSignatureConfig(SignatureConfig signatureConfig);
|
||||
void setSignatureConfig(SignatureConfig signatureConfig);
|
||||
}
|
||||
|
||||
private ThreadLocal<OPCPackage> opcPackage = new ThreadLocal<>();
|
||||
private ThreadLocal<XMLSignatureFactory> signatureFactory = new ThreadLocal<>();
|
||||
private ThreadLocal<KeyInfoFactory> keyInfoFactory = new ThreadLocal<>();
|
||||
private ThreadLocal<Provider> provider = new ThreadLocal<>();
|
||||
|
||||
|
||||
private List<SignatureFacet> signatureFacets = new ArrayList<>();
|
||||
private HashAlgorithm digestAlgo = HashAlgorithm.sha256;
|
||||
private Date executionTime = new Date();
|
||||
|
@ -96,11 +96,11 @@ public class SignatureConfig {
|
|||
private SignaturePolicyService signaturePolicyService;
|
||||
private URIDereferencer uriDereferencer;
|
||||
private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE;
|
||||
|
||||
|
||||
private boolean includeEntireCertificateChain = true;
|
||||
private boolean includeIssuerSerial;
|
||||
private boolean includeKeyValue;
|
||||
|
||||
|
||||
/**
|
||||
* the time-stamp service used for XAdES-T and XAdES-X.
|
||||
*/
|
||||
|
@ -123,7 +123,7 @@ public class SignatureConfig {
|
|||
private String tspRequestPolicy = "1.3.6.1.4.1.13762.3";
|
||||
private String userAgent = "POI XmlSign Service TSP Client";
|
||||
private String proxyUrl;
|
||||
|
||||
|
||||
/**
|
||||
* the optional revocation data service used for XAdES-C and XAdES-X-L.
|
||||
* When <code>null</code> the signature will be limited to XAdES-T only.
|
||||
|
@ -148,16 +148,16 @@ public class SignatureConfig {
|
|||
* <code>null</code> value will trigger an automatically generated signature Id.
|
||||
*/
|
||||
private String packageSignatureId = "idPackageSignature";
|
||||
|
||||
|
||||
/**
|
||||
* Gives back the human-readable description of what the citizen will be
|
||||
* signing. The default value is "Office OpenXML Document".
|
||||
*/
|
||||
private String signatureDescription = "Office OpenXML Document";
|
||||
|
||||
|
||||
/**
|
||||
* The process of signing includes the marshalling of xml structures.
|
||||
* This also includes the canonicalization. Currently this leads to problems
|
||||
* This also includes the canonicalization. Currently this leads to problems
|
||||
* with certain namespaces, so this EventListener is used to interfere
|
||||
* with the marshalling process.
|
||||
*/
|
||||
|
@ -177,7 +177,7 @@ public class SignatureConfig {
|
|||
|
||||
/**
|
||||
* Inits and checks the config object.
|
||||
* If not set previously, complex configuration properties also get
|
||||
* If not set previously, complex configuration properties also get
|
||||
* created/initialized via this initialization call.
|
||||
*
|
||||
* @param onlyValidation if true, only a subset of the properties
|
||||
|
@ -202,7 +202,7 @@ public class SignatureConfig {
|
|||
namespacePrefixes.put(OO_DIGSIG_NS, "mdssi");
|
||||
namespacePrefixes.put(XADES_132_NS, "xd");
|
||||
}
|
||||
|
||||
|
||||
if (onlyValidation) {
|
||||
return;
|
||||
}
|
||||
|
@ -210,15 +210,15 @@ public class SignatureConfig {
|
|||
if (signatureMarshalListener == null) {
|
||||
signatureMarshalListener = new SignatureMarshalListener();
|
||||
}
|
||||
|
||||
|
||||
if (signatureMarshalListener instanceof SignatureConfigurable) {
|
||||
((SignatureConfigurable)signatureMarshalListener).setSignatureConfig(this);
|
||||
}
|
||||
|
||||
|
||||
if (tspService != null) {
|
||||
tspService.setSignatureConfig(this);
|
||||
}
|
||||
|
||||
|
||||
if (signatureFacets.isEmpty()) {
|
||||
addSignatureFacet(new OOXMLSignatureFacet());
|
||||
addSignatureFacet(new KeyInfoSignatureFacet());
|
||||
|
@ -230,14 +230,14 @@ public class SignatureConfig {
|
|||
sf.setSignatureConfig(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param signatureFacet the signature facet is appended to facet list
|
||||
* @param signatureFacet the signature facet is appended to facet list
|
||||
*/
|
||||
public void addSignatureFacet(SignatureFacet signatureFacet) {
|
||||
signatureFacets.add(signatureFacet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the list of facets, may be empty when the config object is not initialized
|
||||
*/
|
||||
|
@ -265,14 +265,14 @@ public class SignatureConfig {
|
|||
public void setDigestAlgo(HashAlgorithm digestAlgo) {
|
||||
this.digestAlgo = digestAlgo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the opc package to be used by this thread, stored as thread-local
|
||||
*/
|
||||
public OPCPackage getOpcPackage() {
|
||||
return opcPackage.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param opcPackage the opc package to be handled by this thread, stored as thread-local
|
||||
*/
|
||||
|
@ -398,14 +398,14 @@ public class SignatureConfig {
|
|||
public void setSignatureDescription(String signatureDescription) {
|
||||
this.signatureDescription = signatureDescription;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the default canonicalization method, defaults to INCLUSIVE
|
||||
*/
|
||||
public String getCanonicalizationMethod() {
|
||||
return canonicalizationMethod;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param canonicalizationMethod the default canonicalization method
|
||||
*/
|
||||
|
@ -459,15 +459,15 @@ public class SignatureConfig {
|
|||
public void setTspUrl(String tspUrl) {
|
||||
this.tspUrl = tspUrl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return if true, uses timestamp-request/response mimetype,
|
||||
* if false, timestamp-query/reply mimetype
|
||||
* if false, timestamp-query/reply mimetype
|
||||
*/
|
||||
public boolean isTspOldProtocol() {
|
||||
return tspOldProtocol;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param tspOldProtocol defines the timestamp-protocol mimetype
|
||||
* @see #isTspOldProtocol
|
||||
|
@ -475,7 +475,7 @@ public class SignatureConfig {
|
|||
public void setTspOldProtocol(boolean tspOldProtocol) {
|
||||
this.tspOldProtocol = tspOldProtocol;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the hash algorithm to be used for the timestamp entry.
|
||||
* Defaults to the hash algorithm of the main entry
|
||||
|
@ -483,7 +483,7 @@ public class SignatureConfig {
|
|||
public HashAlgorithm getTspDigestAlgo() {
|
||||
return nvl(tspDigestAlgo,digestAlgo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param tspDigestAlgo the algorithm to be used for the timestamp entry.
|
||||
* if <code>null</code>, the hash algorithm of the main entry
|
||||
|
@ -499,7 +499,7 @@ public class SignatureConfig {
|
|||
public String getProxyUrl() {
|
||||
return proxyUrl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param proxyUrl the proxy url to be used for all communications.
|
||||
* Currently this affects the timestamp service
|
||||
|
@ -507,56 +507,56 @@ public class SignatureConfig {
|
|||
public void setProxyUrl(String proxyUrl) {
|
||||
this.proxyUrl = proxyUrl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the timestamp service. Defaults to {@link TSPTimeStampService}
|
||||
*/
|
||||
public TimeStampService getTspService() {
|
||||
return tspService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param tspService the timestamp service
|
||||
*/
|
||||
public void setTspService(TimeStampService tspService) {
|
||||
this.tspService = tspService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the user id for the timestamp service - currently only basic authorization is supported
|
||||
*/
|
||||
public String getTspUser() {
|
||||
return tspUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param tspUser the user id for the timestamp service - currently only basic authorization is supported
|
||||
*/
|
||||
public void setTspUser(String tspUser) {
|
||||
this.tspUser = tspUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the password for the timestamp service
|
||||
*/
|
||||
public String getTspPass() {
|
||||
return tspPass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param tspPass the password for the timestamp service
|
||||
*/
|
||||
public void setTspPass(String tspPass) {
|
||||
this.tspPass = tspPass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the validator for the timestamp service (certificate)
|
||||
*/
|
||||
public TimeStampServiceValidator getTspValidator() {
|
||||
return tspValidator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param tspValidator the validator for the timestamp service (certificate)
|
||||
*/
|
||||
|
@ -586,7 +586,7 @@ public class SignatureConfig {
|
|||
public HashAlgorithm getXadesDigestAlgo() {
|
||||
return nvl(xadesDigestAlgo,digestAlgo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param xadesDigestAlgo hash algorithm used for XAdES.
|
||||
* When <code>null</code>, defaults to {@link #getDigestAlgo()}
|
||||
|
@ -611,7 +611,7 @@ public class SignatureConfig {
|
|||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param userAgent the user agent used for http communication (e.g. to the TSP)
|
||||
*/
|
||||
|
@ -626,7 +626,7 @@ public class SignatureConfig {
|
|||
public String getTspRequestPolicy() {
|
||||
return tspRequestPolicy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param tspRequestPolicy the asn.1 object id for the tsp request policy.
|
||||
*/
|
||||
|
@ -636,7 +636,7 @@ public class SignatureConfig {
|
|||
|
||||
/**
|
||||
* @return true, if the whole certificate chain is included in the signature.
|
||||
* When false, only the signer cert will be included
|
||||
* When false, only the signer cert will be included
|
||||
*/
|
||||
public boolean isIncludeEntireCertificateChain() {
|
||||
return includeEntireCertificateChain;
|
||||
|
@ -728,7 +728,7 @@ public class SignatureConfig {
|
|||
* Make sure the DN is encoded using the same order as present
|
||||
* within the certificate. This is an Office2010 work-around.
|
||||
* Should be reverted back.
|
||||
*
|
||||
*
|
||||
* XXX: not correct according to RFC 4514.
|
||||
*
|
||||
* @return when true, the issuer DN is used instead of the issuer X500 principal
|
||||
|
@ -744,7 +744,7 @@ public class SignatureConfig {
|
|||
this.xadesIssuerNameNoReverseOrder = xadesIssuerNameNoReverseOrder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return the event listener which is active while xml structure for
|
||||
* the signature is created.
|
||||
|
@ -813,8 +813,8 @@ public class SignatureConfig {
|
|||
|
||||
/**
|
||||
* Converts the digest algorithm - currently only sha* and ripemd160 is supported.
|
||||
* MS Office only supports sha1, sha256, sha384, sha512.
|
||||
*
|
||||
* MS Office only supports sha1, sha256, sha384, sha512.
|
||||
*
|
||||
* @param digestAlgo the digest algorithm
|
||||
* @return the uri for the given digest
|
||||
*/
|
||||
|
@ -835,7 +835,7 @@ public class SignatureConfig {
|
|||
* Converts the digest algorithm ur - currently only sha* and ripemd160 is supported.
|
||||
* MS Office only supports sha1, sha256, sha384, sha512.
|
||||
*
|
||||
* @param digestAlgo the digest algorithm uri
|
||||
* @param digestMethodUri the digest algorithm uri
|
||||
* @return the hash algorithm for the given digest
|
||||
*/
|
||||
private static HashAlgorithm getDigestMethodAlgo(String digestMethodUri) {
|
||||
|
@ -895,7 +895,7 @@ public class SignatureConfig {
|
|||
public void setSignatureFactory(XMLSignatureFactory signatureFactory) {
|
||||
this.signatureFactory.set(signatureFactory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the xml signature factory (thread-local)
|
||||
*/
|
||||
|
@ -914,7 +914,7 @@ public class SignatureConfig {
|
|||
public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) {
|
||||
this.keyInfoFactory.set(keyInfoFactory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the key factory (thread-local)
|
||||
*/
|
||||
|
@ -934,10 +934,10 @@ public class SignatureConfig {
|
|||
* <li>the Santuario xmlsec provider</li>
|
||||
* <li>the JDK xmlsec provider</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* For signing the classes are linked against the Santuario xmlsec, so this might
|
||||
* only work for validation (not tested).
|
||||
*
|
||||
*
|
||||
* @return the xml dsig provider
|
||||
*/
|
||||
public Provider getProvider() {
|
||||
|
@ -948,7 +948,7 @@ public class SignatureConfig {
|
|||
// Santuario xmlsec
|
||||
"org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI",
|
||||
// JDK xmlsec
|
||||
"org.jcp.xml.dsig.internal.dom.XMLDSigRI"
|
||||
"org.jcp.xml.dsig.internal.dom.XMLDSigRI"
|
||||
};
|
||||
for (String pn : dsigProviderNames) {
|
||||
if (pn == null) {
|
||||
|
@ -966,7 +966,7 @@ public class SignatureConfig {
|
|||
if (prov == null) {
|
||||
throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!");
|
||||
}
|
||||
|
||||
|
||||
return prov;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,13 +116,15 @@ public class XDGFShape extends XDGFSheet {
|
|||
_parentPage = parentPage;
|
||||
|
||||
TextType text = shapeSheet.getText();
|
||||
if (text != null)
|
||||
if (text != null) {
|
||||
_text = new XDGFText(text, this);
|
||||
}
|
||||
|
||||
if (shapeSheet.isSetShapes()) {
|
||||
_shapes = new ArrayList<>();
|
||||
for (ShapeSheetType shape : shapeSheet.getShapes().getShapeArray())
|
||||
for (ShapeSheetType shape : shapeSheet.getShapes().getShapeArray()) {
|
||||
_shapes.add(new XDGFShape(this, shape, parentPage, document));
|
||||
}
|
||||
}
|
||||
|
||||
readProperties();
|
||||
|
@ -130,10 +132,11 @@ public class XDGFShape extends XDGFSheet {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (_parentPage instanceof XDGFMasterContents)
|
||||
if (_parentPage instanceof XDGFMasterContents) {
|
||||
return _parentPage + ": <Shape ID=\"" + getID() + "\">";
|
||||
else
|
||||
} else {
|
||||
return "<Shape ID=\"" + getID() + "\">";
|
||||
}
|
||||
}
|
||||
|
||||
protected void readProperties() {
|
||||
|
@ -181,9 +184,10 @@ public class XDGFShape extends XDGFSheet {
|
|||
|
||||
if (obj.isSetMaster()) {
|
||||
_master = pageContents.getMasterById(obj.getMaster());
|
||||
if (_master == null)
|
||||
if (_master == null) {
|
||||
throw XDGFException.error("refers to non-existant master "
|
||||
+ obj.getMaster(), this);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a master has one top-level shape, a shape that inherits from
|
||||
|
@ -209,11 +213,12 @@ public class XDGFShape extends XDGFSheet {
|
|||
}
|
||||
|
||||
} else if (obj.isSetMasterShape()) {
|
||||
_masterShape = master.getShapeById(obj.getMasterShape());
|
||||
if (_masterShape == null)
|
||||
_masterShape = (master == null) ? null : master.getShapeById(obj.getMasterShape());
|
||||
if (_masterShape == null) {
|
||||
throw XDGFException.error(
|
||||
"refers to non-existant master shape "
|
||||
+ obj.getMasterShape(), this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -229,21 +234,24 @@ public class XDGFShape extends XDGFSheet {
|
|||
|
||||
protected void setupSectionMasters() {
|
||||
|
||||
if (_masterShape == null)
|
||||
if (_masterShape == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
for (Entry<String, XDGFSection> section : _sections.entrySet()) {
|
||||
XDGFSection master = _masterShape.getSection(section.getKey());
|
||||
if (master != null)
|
||||
if (master != null) {
|
||||
section.getValue().setupMaster(master);
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<Long, GeometrySection> section : _geometry.entrySet()) {
|
||||
GeometrySection master = _masterShape.getGeometryByIdx(section
|
||||
.getKey());
|
||||
if (master != null)
|
||||
if (master != null) {
|
||||
section.getValue().setupMaster(master);
|
||||
}
|
||||
}
|
||||
} catch (POIXMLException e) {
|
||||
throw XDGFException.wrap(this.toString(), e);
|
||||
|
@ -266,8 +274,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
|
||||
public String getTextAsString() {
|
||||
XDGFText text = getText();
|
||||
if (text == null)
|
||||
if (text == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return text.getTextContent();
|
||||
}
|
||||
|
@ -294,7 +303,7 @@ public class XDGFShape extends XDGFSheet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Only available if this shape is a shape group, may be null
|
||||
* Only available if this shape is a shape group, may be null
|
||||
*/
|
||||
// -> May be null
|
||||
public List<XDGFShape> getShapes() {
|
||||
|
@ -304,28 +313,32 @@ public class XDGFShape extends XDGFSheet {
|
|||
// unique to this shape on the page?
|
||||
public String getName() {
|
||||
String name = getXmlObject().getName();
|
||||
if (name == null)
|
||||
if (name == null) {
|
||||
return "";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// unique to this shape on the page?
|
||||
public String getShapeType() {
|
||||
String type = getXmlObject().getType();
|
||||
if (type == null)
|
||||
if (type == null) {
|
||||
return "";
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// name of the symbol that this was derived from
|
||||
public String getSymbolName() {
|
||||
|
||||
if (_master == null)
|
||||
if (_master == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String name = _master.getName();
|
||||
if (name == null)
|
||||
if (name == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
@ -345,8 +358,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
XDGFShape top = null;
|
||||
if (_parent != null) {
|
||||
top = _parent.getTopmostParentShape();
|
||||
if (top == null)
|
||||
if (top == null) {
|
||||
top = _parent;
|
||||
}
|
||||
}
|
||||
|
||||
return top;
|
||||
|
@ -381,190 +395,223 @@ public class XDGFShape extends XDGFSheet {
|
|||
}
|
||||
|
||||
public XDGFText getText() {
|
||||
if (_text == null && _masterShape != null)
|
||||
if (_text == null && _masterShape != null) {
|
||||
return _masterShape.getText();
|
||||
}
|
||||
|
||||
return _text;
|
||||
}
|
||||
|
||||
public Double getPinX() {
|
||||
if (_pinX == null && _masterShape != null)
|
||||
if (_pinX == null && _masterShape != null) {
|
||||
return _masterShape.getPinX();
|
||||
}
|
||||
|
||||
if (_pinX == null)
|
||||
if (_pinX == null) {
|
||||
throw XDGFException.error("PinX not set!", this);
|
||||
}
|
||||
|
||||
return _pinX;
|
||||
}
|
||||
|
||||
public Double getPinY() {
|
||||
if (_pinY == null && _masterShape != null)
|
||||
if (_pinY == null && _masterShape != null) {
|
||||
return _masterShape.getPinY();
|
||||
}
|
||||
|
||||
if (_pinY == null)
|
||||
if (_pinY == null) {
|
||||
throw XDGFException.error("PinY not specified!", this);
|
||||
}
|
||||
|
||||
return _pinY;
|
||||
}
|
||||
|
||||
public Double getWidth() {
|
||||
if (_width == null && _masterShape != null)
|
||||
if (_width == null && _masterShape != null) {
|
||||
return _masterShape.getWidth();
|
||||
}
|
||||
|
||||
if (_width == null)
|
||||
if (_width == null) {
|
||||
throw XDGFException.error("Width not specified!", this);
|
||||
}
|
||||
|
||||
return _width;
|
||||
}
|
||||
|
||||
public Double getHeight() {
|
||||
if (_height == null && _masterShape != null)
|
||||
if (_height == null && _masterShape != null) {
|
||||
return _masterShape.getHeight();
|
||||
}
|
||||
|
||||
if (_height == null)
|
||||
if (_height == null) {
|
||||
throw XDGFException.error("Height not specified!", this);
|
||||
}
|
||||
|
||||
return _height;
|
||||
}
|
||||
|
||||
public Double getLocPinX() {
|
||||
if (_locPinX == null && _masterShape != null)
|
||||
if (_locPinX == null && _masterShape != null) {
|
||||
return _masterShape.getLocPinX();
|
||||
}
|
||||
|
||||
if (_locPinX == null)
|
||||
if (_locPinX == null) {
|
||||
throw XDGFException.error("LocPinX not specified!", this);
|
||||
}
|
||||
|
||||
return _locPinX;
|
||||
}
|
||||
|
||||
public Double getLocPinY() {
|
||||
if (_locPinY == null && _masterShape != null)
|
||||
if (_locPinY == null && _masterShape != null) {
|
||||
return _masterShape.getLocPinY();
|
||||
}
|
||||
|
||||
if (_locPinY == null)
|
||||
if (_locPinY == null) {
|
||||
throw XDGFException.error("LocPinY not specified!", this);
|
||||
}
|
||||
|
||||
return _locPinY;
|
||||
}
|
||||
|
||||
public Double getBeginX() {
|
||||
if (_beginX == null && _masterShape != null)
|
||||
if (_beginX == null && _masterShape != null) {
|
||||
return _masterShape.getBeginX();
|
||||
}
|
||||
|
||||
return _beginX;
|
||||
}
|
||||
|
||||
public Double getBeginY() {
|
||||
if (_beginY == null && _masterShape != null)
|
||||
if (_beginY == null && _masterShape != null) {
|
||||
return _masterShape.getBeginY();
|
||||
}
|
||||
|
||||
return _beginY;
|
||||
}
|
||||
|
||||
public Double getEndX() {
|
||||
if (_endX == null && _masterShape != null)
|
||||
if (_endX == null && _masterShape != null) {
|
||||
return _masterShape.getEndX();
|
||||
}
|
||||
|
||||
return _endX;
|
||||
}
|
||||
|
||||
public Double getEndY() {
|
||||
if (_endY == null && _masterShape != null)
|
||||
if (_endY == null && _masterShape != null) {
|
||||
return _masterShape.getEndY();
|
||||
}
|
||||
|
||||
return _endY;
|
||||
}
|
||||
|
||||
public Double getAngle() {
|
||||
if (_angle == null && _masterShape != null)
|
||||
if (_angle == null && _masterShape != null) {
|
||||
return _masterShape.getAngle();
|
||||
}
|
||||
|
||||
return _angle;
|
||||
}
|
||||
|
||||
public Boolean getFlipX() {
|
||||
if (_flipX == null && _masterShape != null)
|
||||
if (_flipX == null && _masterShape != null) {
|
||||
return _masterShape.getFlipX();
|
||||
}
|
||||
|
||||
return _flipX;
|
||||
}
|
||||
|
||||
public Boolean getFlipY() {
|
||||
if (_flipY == null && _masterShape != null)
|
||||
if (_flipY == null && _masterShape != null) {
|
||||
return _masterShape.getFlipY();
|
||||
}
|
||||
|
||||
return _flipY;
|
||||
}
|
||||
|
||||
public Double getTxtPinX() {
|
||||
if (_txtPinX == null && _masterShape != null
|
||||
&& _masterShape._txtPinX != null)
|
||||
&& _masterShape._txtPinX != null) {
|
||||
return _masterShape._txtPinX;
|
||||
}
|
||||
|
||||
if (_txtPinX == null)
|
||||
if (_txtPinX == null) {
|
||||
return getWidth() * 0.5;
|
||||
}
|
||||
|
||||
return _txtPinX;
|
||||
}
|
||||
|
||||
public Double getTxtPinY() {
|
||||
if (_txtLocPinY == null && _masterShape != null
|
||||
&& _masterShape._txtLocPinY != null)
|
||||
&& _masterShape._txtLocPinY != null) {
|
||||
return _masterShape._txtLocPinY;
|
||||
}
|
||||
|
||||
if (_txtPinY == null)
|
||||
if (_txtPinY == null) {
|
||||
return getHeight() * 0.5;
|
||||
}
|
||||
|
||||
return _txtPinY;
|
||||
}
|
||||
|
||||
public Double getTxtLocPinX() {
|
||||
if (_txtLocPinX == null && _masterShape != null
|
||||
&& _masterShape._txtLocPinX != null)
|
||||
&& _masterShape._txtLocPinX != null) {
|
||||
return _masterShape._txtLocPinX;
|
||||
}
|
||||
|
||||
if (_txtLocPinX == null)
|
||||
if (_txtLocPinX == null) {
|
||||
return getTxtWidth() * 0.5;
|
||||
}
|
||||
|
||||
return _txtLocPinX;
|
||||
}
|
||||
|
||||
public Double getTxtLocPinY() {
|
||||
if (_txtLocPinY == null && _masterShape != null
|
||||
&& _masterShape._txtLocPinY != null)
|
||||
&& _masterShape._txtLocPinY != null) {
|
||||
return _masterShape._txtLocPinY;
|
||||
}
|
||||
|
||||
if (_txtLocPinY == null)
|
||||
if (_txtLocPinY == null) {
|
||||
return getTxtHeight() * 0.5;
|
||||
}
|
||||
|
||||
return _txtLocPinY;
|
||||
}
|
||||
|
||||
public Double getTxtAngle() {
|
||||
if (_txtAngle == null && _masterShape != null)
|
||||
if (_txtAngle == null && _masterShape != null) {
|
||||
return _masterShape.getTxtAngle();
|
||||
}
|
||||
|
||||
return _txtAngle;
|
||||
}
|
||||
|
||||
public Double getTxtWidth() {
|
||||
if (_txtWidth == null && _masterShape != null
|
||||
&& _masterShape._txtWidth != null)
|
||||
&& _masterShape._txtWidth != null) {
|
||||
return _masterShape._txtWidth;
|
||||
}
|
||||
|
||||
if (_txtWidth == null)
|
||||
if (_txtWidth == null) {
|
||||
return getWidth();
|
||||
}
|
||||
|
||||
return _txtWidth;
|
||||
}
|
||||
|
||||
public Double getTxtHeight() {
|
||||
if (_txtHeight == null && _masterShape != null
|
||||
&& _masterShape._txtHeight != null)
|
||||
&& _masterShape._txtHeight != null) {
|
||||
return _masterShape._txtHeight;
|
||||
}
|
||||
|
||||
if (_txtHeight == null)
|
||||
if (_txtHeight == null) {
|
||||
return getHeight();
|
||||
}
|
||||
|
||||
return _txtHeight;
|
||||
}
|
||||
|
@ -573,8 +620,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
public Integer getLineCap() {
|
||||
|
||||
Integer lineCap = super.getLineCap();
|
||||
if (lineCap != null)
|
||||
if (lineCap != null) {
|
||||
return lineCap;
|
||||
}
|
||||
|
||||
// get from master
|
||||
if (_masterShape != null) {
|
||||
|
@ -589,8 +637,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
public Color getLineColor() {
|
||||
|
||||
Color lineColor = super.getLineColor();
|
||||
if (lineColor != null)
|
||||
if (lineColor != null) {
|
||||
return lineColor;
|
||||
}
|
||||
|
||||
// get from master
|
||||
if (_masterShape != null) {
|
||||
|
@ -605,8 +654,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
public Integer getLinePattern() {
|
||||
|
||||
Integer linePattern = super.getLinePattern();
|
||||
if (linePattern != null)
|
||||
if (linePattern != null) {
|
||||
return linePattern;
|
||||
}
|
||||
|
||||
// get from master
|
||||
if (_masterShape != null) {
|
||||
|
@ -621,8 +671,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
public Double getLineWeight() {
|
||||
|
||||
Double lineWeight = super.getLineWeight();
|
||||
if (lineWeight != null)
|
||||
if (lineWeight != null) {
|
||||
return lineWeight;
|
||||
}
|
||||
|
||||
// get from master
|
||||
if (_masterShape != null) {
|
||||
|
@ -637,8 +688,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
public Color getFontColor() {
|
||||
|
||||
Color fontColor = super.getFontColor();
|
||||
if (fontColor != null)
|
||||
if (fontColor != null) {
|
||||
return fontColor;
|
||||
}
|
||||
|
||||
// get from master
|
||||
if (_masterShape != null) {
|
||||
|
@ -653,8 +705,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
public Double getFontSize() {
|
||||
|
||||
Double fontSize = super.getFontSize();
|
||||
if (fontSize != null)
|
||||
if (fontSize != null) {
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
// get from master
|
||||
if (_masterShape != null) {
|
||||
|
@ -791,11 +844,11 @@ public class XDGFShape extends XDGFSheet {
|
|||
public Rectangle2D.Double getBounds() {
|
||||
return new Rectangle2D.Double(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return returns bounds as a path in local coordinates, which is
|
||||
* userful if you need to transform to global coordinates
|
||||
*
|
||||
*
|
||||
* Warning: Don't use this for 1d objects, and will fail for
|
||||
* infinite line objects
|
||||
*/
|
||||
|
@ -819,8 +872,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
*/
|
||||
public Path2D.Double getPath() {
|
||||
for (GeometrySection geoSection : getGeometrySections()) {
|
||||
if (geoSection.getNoShow())
|
||||
if (geoSection.getNoShow()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return geoSection.getPath(this);
|
||||
}
|
||||
|
@ -833,8 +887,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
*/
|
||||
public boolean hasGeometry() {
|
||||
for (GeometrySection geoSection : getGeometrySections()) {
|
||||
if (!geoSection.getNoShow())
|
||||
if (!geoSection.getNoShow()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -889,8 +944,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
tr.concatenate(getParentTransform());
|
||||
|
||||
try {
|
||||
if (visitor.accept(this))
|
||||
if (visitor.accept(this)) {
|
||||
visitor.visit(this, tr, level);
|
||||
}
|
||||
|
||||
if (_shapes != null) {
|
||||
for (XDGFShape shape : _shapes) {
|
||||
|
@ -914,8 +970,9 @@ public class XDGFShape extends XDGFSheet {
|
|||
public void visitShapes(ShapeVisitor visitor, int level) {
|
||||
|
||||
try {
|
||||
if (visitor.accept(this))
|
||||
if (visitor.accept(this)) {
|
||||
visitor.visit(this, null, level);
|
||||
}
|
||||
|
||||
if (_shapes != null) {
|
||||
for (XDGFShape shape : _shapes) {
|
||||
|
|
|
@ -52,7 +52,7 @@ public class XDGFText {
|
|||
// is a mixed type)
|
||||
return ((TextTypeImpl) _text).getStringValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* These are in the shape coordinate system
|
||||
*
|
||||
|
@ -82,8 +82,8 @@ public class XDGFText {
|
|||
public Path2D.Double getBoundsAsPath() {
|
||||
|
||||
Rectangle2D.Double rect = getTextBounds();
|
||||
Double w = rect.getWidth();
|
||||
Double h = rect.getHeight();
|
||||
double w = rect.getWidth();
|
||||
double h = rect.getHeight();
|
||||
|
||||
Path2D.Double bounds = new Path2D.Double();
|
||||
bounds.moveTo(0, 0);
|
||||
|
@ -94,7 +94,7 @@ public class XDGFText {
|
|||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Center of text in local coordinates
|
||||
*/
|
||||
|
@ -110,8 +110,9 @@ public class XDGFText {
|
|||
public void draw(Graphics2D graphics) {
|
||||
|
||||
String textContent = getTextContent();
|
||||
if (textContent.length() == 0)
|
||||
if (textContent.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rectangle2D.Double bounds = getTextBounds();
|
||||
|
||||
|
@ -140,22 +141,25 @@ public class XDGFText {
|
|||
}
|
||||
|
||||
Double txtAngle = _parent.getTxtAngle();
|
||||
if (txtAngle != null && Math.abs(txtAngle) > 0.01)
|
||||
if (txtAngle != null && Math.abs(txtAngle) > 0.01) {
|
||||
graphics.rotate(txtAngle);
|
||||
}
|
||||
|
||||
float nextY = 0;
|
||||
for (String line : lines) {
|
||||
|
||||
if (line.length() == 0)
|
||||
if (line.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TextLayout layout = new TextLayout(line, font, frc);
|
||||
|
||||
if (layout.isLeftToRight())
|
||||
if (layout.isLeftToRight()) {
|
||||
layout.draw(graphics, 0, nextY);
|
||||
else
|
||||
} else {
|
||||
layout.draw(graphics,
|
||||
(float) (bounds.width - layout.getAdvance()), nextY);
|
||||
}
|
||||
|
||||
nextY += layout.getAscent() + layout.getDescent()
|
||||
+ layout.getLeading();
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -38,17 +39,17 @@ import org.apache.poi.xdgf.usermodel.shape.ShapeVisitor;
|
|||
public class HierarchyPrinter {
|
||||
|
||||
public static void printHierarchy(XDGFPage page, File outDir)
|
||||
throws FileNotFoundException, UnsupportedEncodingException {
|
||||
throws FileNotFoundException, UnsupportedEncodingException, IOException {
|
||||
|
||||
File pageFile = new File(outDir, "page" + page.getPageNumber() + "-"
|
||||
+ Util.sanitizeFilename(page.getName()) + ".txt");
|
||||
|
||||
OutputStream os = new FileOutputStream(pageFile);
|
||||
PrintStream pos = new PrintStream(os, false, "utf-8");
|
||||
|
||||
printHierarchy(page, pos);
|
||||
|
||||
pos.close();
|
||||
try (
|
||||
OutputStream os = new FileOutputStream(pageFile);
|
||||
PrintStream pos = new PrintStream(os, false, "utf-8")
|
||||
) {
|
||||
printHierarchy(page, pos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void printHierarchy(XDGFPage page, final PrintStream os) {
|
||||
|
@ -71,7 +72,7 @@ public class HierarchyPrinter {
|
|||
}
|
||||
|
||||
public static void printHierarchy(XmlVisioDocument document,
|
||||
String outDirname) throws FileNotFoundException, UnsupportedEncodingException {
|
||||
String outDirname) throws FileNotFoundException, UnsupportedEncodingException, IOException {
|
||||
|
||||
File outDir = new File(outDirname);
|
||||
|
||||
|
@ -89,8 +90,9 @@ public class HierarchyPrinter {
|
|||
String inFilename = args[0];
|
||||
String outDir = args[1];
|
||||
|
||||
XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(
|
||||
inFilename));
|
||||
printHierarchy(doc, outDir);
|
||||
try (FileInputStream is = new FileInputStream(inFilename)) {
|
||||
XmlVisioDocument doc = new XmlVisioDocument(is);
|
||||
printHierarchy(doc, outDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,10 @@ import java.awt.Color;
|
|||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
|
@ -33,7 +36,7 @@ import org.apache.poi.xdgf.usermodel.shape.ShapeRenderer;
|
|||
|
||||
/**
|
||||
* Converts a Visio diagram to a PNG file.
|
||||
*
|
||||
*
|
||||
* As more elements and styles are added/supported the output will get
|
||||
* better, but it's very rough right now.
|
||||
*/
|
||||
|
@ -91,11 +94,8 @@ public class VsdxToPng {
|
|||
|
||||
graphics.dispose();
|
||||
|
||||
OutputStream out = new FileOutputStream(outFile);
|
||||
try {
|
||||
try (FileOutputStream out = new FileOutputStream(outFile)) {
|
||||
ImageIO.write(img, "png", out);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,8 +127,9 @@ public class VsdxToPng {
|
|||
renderer = new ShapeDebuggerRenderer();
|
||||
}
|
||||
|
||||
XmlVisioDocument doc = new XmlVisioDocument(new FileInputStream(
|
||||
inFilename));
|
||||
renderToPng(doc, pngDir, 2000 / 11.0, renderer);
|
||||
try (FileInputStream is = new FileInputStream(inFilename)) {
|
||||
XmlVisioDocument doc = new XmlVisioDocument(is);
|
||||
renderToPng(doc, pngDir, 2000 / 11.0, renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.poi.ooxml.POIXMLDocument;
|
|||
import org.apache.poi.ooxml.POIXMLDocumentPart;
|
||||
import org.apache.poi.ooxml.POIXMLException;
|
||||
import org.apache.poi.ooxml.extractor.POIXMLPropertiesTextExtractor;
|
||||
import org.apache.poi.ooxml.util.PackageHelper;
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
|
@ -50,7 +51,6 @@ import org.apache.poi.util.LittleEndian;
|
|||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.ooxml.util.PackageHelper;
|
||||
import org.apache.poi.util.Units;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
|
@ -362,7 +362,7 @@ public class XMLSlideShow extends POIXMLDocument
|
|||
CTNotesMasterIdListEntry notesMasterId = notesMasterIdList.addNewNotesMasterId();
|
||||
notesMasterId.setId(rp.getRelationship().getId());
|
||||
|
||||
Integer themeIndex = 1;
|
||||
int themeIndex = 1;
|
||||
// TODO: check if that list can be replaced by idx = Math.max(idx,themeIdx)
|
||||
List<Integer> themeIndexList = new ArrayList<>();
|
||||
for (POIXMLDocumentPart p : getRelations()) {
|
||||
|
@ -626,7 +626,7 @@ public class XMLSlideShow extends POIXMLDocument
|
|||
// TODO: implement!
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public POIXMLPropertiesTextExtractor getMetadataTextExtractor() {
|
||||
return new POIXMLPropertiesTextExtractor(this);
|
||||
|
|
|
@ -48,7 +48,7 @@ import org.w3c.dom.Node;
|
|||
@Internal
|
||||
public class XSLFColor {
|
||||
private final static POILogger LOGGER = POILogFactory.getLogger(XSLFColor.class);
|
||||
|
||||
|
||||
private XmlObject _xmlObject;
|
||||
private Color _color;
|
||||
private CTSchemeColor _phClr;
|
||||
|
@ -128,7 +128,7 @@ public class XSLFColor {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private Color toColor(XmlObject obj, XSLFTheme theme) {
|
||||
Color color = null;
|
||||
for (XmlObject ch : obj.selectPath("*")) {
|
||||
|
@ -207,19 +207,19 @@ public class XSLFColor {
|
|||
if (fill.isSetScrgbClr()) {
|
||||
fill.unsetScrgbClr();
|
||||
}
|
||||
|
||||
|
||||
if (fill.isSetHslClr()) {
|
||||
fill.unsetHslClr();
|
||||
}
|
||||
|
||||
|
||||
if (fill.isSetPrstClr()) {
|
||||
fill.unsetPrstClr();
|
||||
}
|
||||
|
||||
|
||||
if (fill.isSetSchemeClr()) {
|
||||
fill.unsetSchemeClr();
|
||||
}
|
||||
|
||||
|
||||
if (fill.isSetSysClr()) {
|
||||
fill.unsetSysClr();
|
||||
}
|
||||
|
@ -227,12 +227,12 @@ public class XSLFColor {
|
|||
float[] rgbaf = color.getRGBComponents(null);
|
||||
boolean addAlpha = (rgbaf.length == 4 && rgbaf[3] < 1f);
|
||||
CTPositiveFixedPercentage alphaPct;
|
||||
|
||||
|
||||
// see office open xml part 4 - 5.1.2.2.30 and 5.1.2.2.32
|
||||
if (isInt(rgbaf[0]) && isInt(rgbaf[1]) && isInt(rgbaf[2])) {
|
||||
// sRGB has a gamma of 2.2
|
||||
CTSRgbColor rgb = fill.addNewSrgbClr();
|
||||
|
||||
|
||||
byte rgbBytes[] = { (byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue() };
|
||||
rgb.setVal(rgbBytes);
|
||||
alphaPct = (addAlpha) ? rgb.addNewAlpha() : null;
|
||||
|
@ -249,14 +249,14 @@ public class XSLFColor {
|
|||
alphaPct.setVal((int)(100000 * rgbaf[3]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true, if this is an integer color value
|
||||
*/
|
||||
private static boolean isInt(float f) {
|
||||
return Math.abs((f*255f) - Math.rint(f*255f)) < 0.00001f;
|
||||
return Math.abs((f*255d) - Math.rint(f*255d)) < 0.00001;
|
||||
}
|
||||
|
||||
|
||||
private int getRawValue(String elem) {
|
||||
String query = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem;
|
||||
|
||||
|
@ -281,9 +281,9 @@ public class XSLFColor {
|
|||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read a perecentage value from the supplied xml bean.
|
||||
* Example:
|
||||
|
@ -305,7 +305,7 @@ public class XSLFColor {
|
|||
* or -1 if the value is not set
|
||||
*/
|
||||
int getAlpha(){
|
||||
return getPercentageValue("alpha");
|
||||
return getPercentageValue("alpha");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -413,7 +413,7 @@ public class XSLFColor {
|
|||
/**
|
||||
* specifies the input color with the specific red component, but with the blue and green color
|
||||
* components unchanged
|
||||
*
|
||||
*
|
||||
* @return the value of the red component specified as a
|
||||
* percentage with 0% indicating minimal blue and 100% indicating maximum
|
||||
* or -1 if the value is not set
|
||||
|
@ -479,7 +479,7 @@ public class XSLFColor {
|
|||
/**
|
||||
* specifies a darker version of its input color.
|
||||
* A 10% shade is 10% of the input color combined with 90% black.
|
||||
*
|
||||
*
|
||||
* @return the value of the shade specified as a
|
||||
* percentage with 0% indicating minimal shade and 100% indicating maximum
|
||||
* or -1 if the value is not set
|
||||
|
|
|
@ -49,9 +49,7 @@ implements Notes<XSLFShape,XSLFTextParagraph> {
|
|||
*
|
||||
* @param part the package part holding the notes data,
|
||||
* the content type must be <code>application/vnd.openxmlformats-officedocument.notes+xml</code>
|
||||
* @param rel the package relationship holding this notes,
|
||||
* the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/notes
|
||||
*
|
||||
*
|
||||
* @since POI 3.14-Beta1
|
||||
*/
|
||||
XSLFNotes(PackagePart part) throws IOException, XmlException {
|
||||
|
@ -77,7 +75,7 @@ implements Notes<XSLFShape,XSLFTextParagraph> {
|
|||
|
||||
@Override
|
||||
protected String getRootElementName(){
|
||||
return "notes";
|
||||
return "notes";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -70,7 +70,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
|||
@Beta
|
||||
public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
||||
static final String PML_NS = "http://schemas.openxmlformats.org/presentationml/2006/main";
|
||||
|
||||
|
||||
private final XmlObject _shape;
|
||||
private final XSLFSheet _sheet;
|
||||
private XSLFShapeContainer _parent;
|
||||
|
@ -82,7 +82,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
_shape = shape;
|
||||
_sheet = sheet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the xml bean holding this shape's data
|
||||
*/
|
||||
|
@ -91,11 +91,12 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
// the (not existing) xmlbeans hierarchy and subclasses shouldn't narrow it's return value
|
||||
return _shape;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public XSLFSheet getSheet() {
|
||||
return _sheet;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getShapeName(){
|
||||
return getCNvPr().getName();
|
||||
|
@ -124,22 +125,24 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
PlaceableShape<?,?> ps = (PlaceableShape<?,?>)this;
|
||||
ps.setAnchor(sh.getAnchor());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void setParent(XSLFShapeContainer parent) {
|
||||
this._parent = parent;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public XSLFShapeContainer getParent() {
|
||||
return this._parent;
|
||||
}
|
||||
|
||||
|
||||
protected PaintStyle getFillPaint() {
|
||||
final XSLFTheme theme = getSheet().getTheme();
|
||||
final boolean hasPlaceholder = getPlaceholder() != null;
|
||||
PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
|
||||
@Override
|
||||
public boolean fetch(XSLFShape shape) {
|
||||
XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(shape.getShapeProperties());
|
||||
if (fp == null) {
|
||||
|
@ -150,7 +153,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
setValue(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PackagePart pp = shape.getSheet().getPackagePart();
|
||||
PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder);
|
||||
if (paint != null) {
|
||||
|
@ -167,8 +170,8 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
setValue(paint);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
@ -181,16 +184,16 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
protected CTBackgroundProperties getBgPr() {
|
||||
return getChild(CTBackgroundProperties.class, PML_NS, "bgPr");
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected CTStyleMatrixReference getBgRef() {
|
||||
return getChild(CTStyleMatrixReference.class, PML_NS, "bgRef");
|
||||
}
|
||||
|
||||
|
||||
protected CTGroupShapeProperties getGrpSpPr() {
|
||||
return getChild(CTGroupShapeProperties.class, PML_NS, "grpSpPr");
|
||||
}
|
||||
|
||||
|
||||
protected CTNonVisualDrawingProps getCNvPr() {
|
||||
if (_nvPr == null) {
|
||||
String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr";
|
||||
|
@ -239,7 +242,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
public Placeholder getPlaceholder() {
|
||||
return getPlaceholderDetails().getPlaceholder();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see PlaceholderDetails#setPlaceholder(Placeholder)
|
||||
*/
|
||||
|
@ -268,7 +271,9 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
@SuppressWarnings({"unchecked", "WeakerAccess"})
|
||||
protected <T extends XmlObject> T selectProperty(Class<T> resultClass, String xquery) {
|
||||
XmlObject[] rs = getXmlObject().selectPath(xquery);
|
||||
if (rs.length == 0) return null;
|
||||
if (rs.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return (resultClass.isInstance(rs[0])) ? (T)rs[0] : null;
|
||||
}
|
||||
|
||||
|
@ -281,7 +286,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
* <li>slideLayout
|
||||
* <li>slideMaster
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* Currently themes and their defaults aren't correctly handled
|
||||
*
|
||||
* @param visitor the object that collects the desired property
|
||||
|
@ -299,7 +304,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
return false;
|
||||
}
|
||||
MasterSheet<XSLFShape,XSLFTextParagraph> sm = getSheet().getMasterSheet();
|
||||
|
||||
|
||||
// try slide layout
|
||||
if (sm instanceof XSLFSlideLayout) {
|
||||
XSLFSlideLayout slideLayout = (XSLFSlideLayout)sm;
|
||||
|
@ -309,7 +314,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
}
|
||||
sm = slideLayout.getMasterSheet();
|
||||
}
|
||||
|
||||
|
||||
// try slide master
|
||||
if (sm instanceof XSLFSlideMaster) {
|
||||
XSLFSlideMaster master = (XSLFSlideMaster)sm;
|
||||
|
@ -317,15 +322,15 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
XSLFSimpleShape masterShape = master.getPlaceholderByType(textType);
|
||||
return masterShape != null && visitor.fetch(masterShape);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static int getPlaceholderType(CTPlaceholder ph) {
|
||||
if ( !ph.isSetType()) {
|
||||
return STPlaceholderType.INT_BODY;
|
||||
}
|
||||
|
||||
|
||||
switch (ph.getType().intValue()) {
|
||||
case STPlaceholderType.INT_TITLE:
|
||||
case STPlaceholderType.INT_CTR_TITLE:
|
||||
|
@ -397,7 +402,8 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InputStream getImageData() {
|
||||
try {
|
||||
return getPart().getInputStream();
|
||||
|
@ -406,17 +412,19 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
/* TOOD: map content-type */
|
||||
return getPart().getContentType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlpha() {
|
||||
return (blip.sizeOfAlphaModFixArray() > 0)
|
||||
? blip.getAlphaModFixArray(0).getAmt()
|
||||
: 100000;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
|
@ -426,14 +434,14 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
|
||||
|
||||
Arrays.sort(gs, (o1, o2) -> {
|
||||
Integer pos1 = o1.getPos();
|
||||
Integer pos2 = o2.getPos();
|
||||
return pos1.compareTo(pos2);
|
||||
int pos1 = o1.getPos();
|
||||
int pos2 = o2.getPos();
|
||||
return Integer.compare(pos1, pos2);
|
||||
});
|
||||
|
||||
final ColorStyle cs[] = new ColorStyle[gs.length];
|
||||
final float fractions[] = new float[gs.length];
|
||||
|
||||
|
||||
int i=0;
|
||||
for (CTGradientStop cgs : gs) {
|
||||
CTSchemeColor phClrCgs = phClr;
|
||||
|
@ -444,32 +452,37 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
fractions[i] = cgs.getPos() / 100000.f;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
return new GradientPaint() {
|
||||
|
||||
@Override
|
||||
public double getGradientAngle() {
|
||||
return (gradFill.isSetLin())
|
||||
? gradFill.getLin().getAng() / 60000.d
|
||||
: 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorStyle[] getGradientColors() {
|
||||
return cs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getGradientFractions() {
|
||||
return fractions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRotatedWithShape() {
|
||||
return gradFill.getRotWithShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GradientType getGradientType() {
|
||||
if (gradFill.isSetLin()) {
|
||||
return GradientType.linear;
|
||||
}
|
||||
|
||||
|
||||
if (gradFill.isSetPath()) {
|
||||
/* TODO: handle rect path */
|
||||
STPathShadeType.Enum ps = gradFill.getPath().getPath();
|
||||
|
@ -479,16 +492,18 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
return GradientType.shape;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return GradientType.linear;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) {
|
||||
if (fillRef == null) return null;
|
||||
|
||||
if (fillRef == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// The idx attribute refers to the index of a fill style or
|
||||
// background fill style within the presentation's style matrix, defined by the fmtScheme element.
|
||||
// value of 0 or 1000 indicates no background,
|
||||
|
@ -513,7 +528,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
fp = XSLFPropertiesDelegate.getFillDelegate(cur.getObject());
|
||||
}
|
||||
cur.dispose();
|
||||
|
||||
|
||||
CTSchemeColor phClr = fillRef.getSchemeClr();
|
||||
PaintStyle res = selectPaint(fp, phClr, theme.getPackagePart(), theme, hasPlaceholder);
|
||||
// check for empty placeholder value
|
||||
|
@ -524,12 +539,12 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||
XSLFColor col = new XSLFColor(fillRef, theme, phClr);
|
||||
return DrawPaint.createSolidPaint(col.getColorStyle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D graphics, Rectangle2D bounds) {
|
||||
DrawFactory.getInstance(graphics).drawShape(graphics, this, bounds);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the shape specific (visual) properties
|
||||
*
|
||||
|
|
|
@ -74,13 +74,13 @@ public class PPTX2PNG {
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i].startsWith("-")) {
|
||||
if ("-scale".equals(args[i])) {
|
||||
scale = Float.parseFloat(args[++i]);
|
||||
scale = Float.parseFloat(args[++i]); // lgtm[java/index-out-of-bounds]
|
||||
} else if ("-slide".equals(args[i])) {
|
||||
slidenumStr = args[++i];
|
||||
slidenumStr = args[++i]; // lgtm[java/index-out-of-bounds]
|
||||
} else if ("-format".equals(args[i])) {
|
||||
format = args[++i];
|
||||
format = args[++i]; // lgtm[java/index-out-of-bounds]
|
||||
} else if ("-outdir".equals(args[i])) {
|
||||
outdir = new File(args[++i]);
|
||||
outdir = new File(args[++i]); // lgtm[java/index-out-of-bounds]
|
||||
} else if ("-quiet".equals(args[i])) {
|
||||
quiet = true;
|
||||
}
|
||||
|
@ -98,11 +98,11 @@ public class PPTX2PNG {
|
|||
usage("Invalid format given");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (outdir == null) {
|
||||
outdir = file.getParentFile();
|
||||
}
|
||||
|
||||
|
||||
if (!"null".equals(format) && (outdir == null || !outdir.exists() || !outdir.isDirectory())) {
|
||||
usage("Output directory doesn't exist");
|
||||
return;
|
||||
|
@ -112,7 +112,7 @@ public class PPTX2PNG {
|
|||
usage("Invalid scale given");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!quiet) {
|
||||
System.out.println("Processing " + file);
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ public class PPTX2PNG {
|
|||
System.out.println("Done");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Set<Integer> slideIndexes(final int slideCount, String range) {
|
||||
Set<Integer> slideIdx = new TreeSet<>();
|
||||
if ("-1".equals(range)) {
|
||||
|
|
|
@ -302,9 +302,8 @@ public class XSSFBSheetHandler extends XSSFBParser {
|
|||
}
|
||||
|
||||
private double rkNumber(byte[] data, int offset) {
|
||||
//see 2.5.122 for this abomination
|
||||
//see 2.5.122
|
||||
byte b0 = data[offset];
|
||||
String s = Integer.toString(b0, 2);
|
||||
boolean numDivBy100 = ((b0 & 1) == 1); // else as is
|
||||
boolean floatingPoint = ((b0 >> 1 & 1) == 0); // else signed integer
|
||||
|
||||
|
@ -320,7 +319,8 @@ public class XSSFBSheetHandler extends XSSFBParser {
|
|||
if (floatingPoint) {
|
||||
d = LittleEndian.getDouble(rkBuffer);
|
||||
} else {
|
||||
d = LittleEndian.getInt(rkBuffer);
|
||||
int rawInt = LittleEndian.getInt(rkBuffer, 4);
|
||||
d = rawInt >> 2;//divide by 4/shift bits coz 30 bit int, not 32
|
||||
}
|
||||
d = (numDivBy100) ? d/100 : d;
|
||||
return d;
|
||||
|
|
|
@ -51,7 +51,7 @@ public class XSSFBUtils {
|
|||
int numBytes = 2*(int)numChars;
|
||||
offset += 4;
|
||||
if (offset+numBytes > data.length) {
|
||||
throw new XSSFBParseException("trying to read beyond data length:" +
|
||||
throw new XSSFBParseException("trying to read beyond data length: " +
|
||||
"offset="+offset+", numBytes="+numBytes+", data.length="+data.length);
|
||||
}
|
||||
sb.append(new String(data, offset, numBytes, StandardCharsets.UTF_16LE));
|
||||
|
|
|
@ -39,22 +39,22 @@ import org.apache.poi.util.NotImplemented;
|
|||
public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
||||
{
|
||||
private static final Boolean UNDEFINED = null;
|
||||
|
||||
|
||||
private final SXSSFSheet _sheet; // parent sheet
|
||||
private final SortedMap<Integer, SXSSFCell> _cells = new TreeMap<>();
|
||||
private short _style = -1; // index of cell style in style table
|
||||
private short _height = -1; // row height in twips (1/20 point)
|
||||
private boolean _zHeight; // row zero-height (this is somehow different than being hidden)
|
||||
private int _outlineLevel; // Outlining level of the row, when outlining is on
|
||||
// use Boolean to have a tri-state for on/off/undefined
|
||||
// use Boolean to have a tri-state for on/off/undefined
|
||||
private Boolean _hidden = UNDEFINED;
|
||||
private Boolean _collapsed = UNDEFINED;
|
||||
|
||||
|
||||
public SXSSFRow(SXSSFSheet sheet)
|
||||
{
|
||||
_sheet=sheet;
|
||||
}
|
||||
|
||||
|
||||
public Iterator<Cell> allCellsIterator()
|
||||
{
|
||||
return new CellIterator();
|
||||
|
@ -71,7 +71,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
void setOutlineLevel(int level){
|
||||
_outlineLevel = level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get row hidden state: Hidden (true), Unhidden (false), Undefined (null)
|
||||
*
|
||||
|
@ -235,7 +235,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
public SXSSFCell getCell(int cellnum, MissingCellPolicy policy)
|
||||
{
|
||||
checkBounds(cellnum);
|
||||
|
||||
|
||||
final SXSSFCell cell = _cells.get(cellnum);
|
||||
switch (policy) {
|
||||
case RETURN_NULL_AND_BLANK:
|
||||
|
@ -345,10 +345,11 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
@Override
|
||||
public void setHeightInPoints(float height)
|
||||
{
|
||||
if(height==-1)
|
||||
if(height==-1) {
|
||||
_height=-1;
|
||||
else
|
||||
} else {
|
||||
_height=(short)(height*20);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -375,7 +376,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
{
|
||||
return (float)(_height==-1?getSheet().getDefaultRowHeightInPoints():_height/20.0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is this row formatted? Most aren't, but some rows
|
||||
* do have whole-row styles. For those that do, you
|
||||
|
@ -392,16 +393,18 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
*/
|
||||
@Override
|
||||
public CellStyle getRowStyle() {
|
||||
if(!isFormatted()) return null;
|
||||
|
||||
if(!isFormatted()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getSheet().getWorkbook().getCellStyleAt(_style);
|
||||
}
|
||||
|
||||
|
||||
@Internal
|
||||
/*package*/ int getRowStyleIndex() {
|
||||
return _style;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies a whole-row cell styling to the row.
|
||||
* The row style can be cleared by passing in <code>null</code>.
|
||||
|
@ -440,7 +443,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
/**
|
||||
* Create an iterator over the cells from [0, getLastCellNum()).
|
||||
* Includes blank cells, excludes empty cells
|
||||
*
|
||||
*
|
||||
* Returns an iterator over all filled cells (created via Row.createCell())
|
||||
* Throws ConcurrentModificationException if cells are added, moved, or
|
||||
* removed after the iterator is created.
|
||||
|
@ -485,10 +488,11 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
@Override
|
||||
public Cell next() throws NoSuchElementException
|
||||
{
|
||||
if (hasNext())
|
||||
if (hasNext()) {
|
||||
return _cells.get(pos++);
|
||||
else
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void remove()
|
||||
|
@ -496,7 +500,7 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two <code>SXSSFRow</code> objects. Two rows are equal if they belong to the same worksheet and
|
||||
* their row indexes are equal.
|
||||
|
@ -524,9 +528,9 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
|
|||
throw new IllegalArgumentException("The compared rows must belong to the same sheet");
|
||||
}
|
||||
|
||||
Integer thisRow = this.getRowNum();
|
||||
Integer otherRow = other.getRowNum();
|
||||
return thisRow.compareTo(otherRow);
|
||||
int thisRow = this.getRowNum();
|
||||
int otherRow = other.getRowNum();
|
||||
return Integer.compare(thisRow, otherRow);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel;
|
|||
|
||||
import org.apache.poi.ss.formula.BaseFormulaEvaluator;
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||
import org.apache.poi.ss.formula.eval.BoolEval;
|
||||
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||
|
@ -26,6 +27,7 @@ import org.apache.poi.ss.formula.eval.NumberEval;
|
|||
import org.apache.poi.ss.formula.eval.StringEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
import org.apache.poi.ss.usermodel.RichTextString;
|
||||
|
||||
|
@ -69,4 +71,16 @@ public abstract class BaseXSSFFormulaEvaluator extends BaseFormulaEvaluator {
|
|||
}
|
||||
throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")");
|
||||
}
|
||||
|
||||
protected void setCellType(Cell cell, CellType cellType) {
|
||||
if (cell instanceof XSSFCell) {
|
||||
EvaluationWorkbook evaluationWorkbook = getEvaluationWorkbook();
|
||||
BaseXSSFEvaluationWorkbook xewb = BaseXSSFEvaluationWorkbook.class.isAssignableFrom(evaluationWorkbook.getClass()) ? (BaseXSSFEvaluationWorkbook) evaluationWorkbook : null;
|
||||
|
||||
((XSSFCell) cell).setCellType(cellType, xewb);
|
||||
} else {
|
||||
// could be an SXSSFCell
|
||||
cell.setCellType(cellType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.poi.ss.usermodel.Comment;
|
|||
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.FormulaError;
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
import org.apache.poi.ss.usermodel.RichTextString;
|
||||
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
|
||||
|
@ -477,7 +478,7 @@ public final class XSSFCell implements Cell {
|
|||
* @return a formula for the cell
|
||||
* @throws IllegalStateException if the cell type returned by {@link #getCellType()} is not {@link CellType#FORMULA}
|
||||
*/
|
||||
protected String getCellFormula(XSSFEvaluationWorkbook fpb) {
|
||||
protected String getCellFormula(BaseXSSFEvaluationWorkbook fpb) {
|
||||
CellType cellType = getCellType();
|
||||
if(cellType != CellType.FORMULA) {
|
||||
throw typeMismatch(CellType.FORMULA, cellType, false);
|
||||
|
@ -506,7 +507,7 @@ public final class XSSFCell implements Cell {
|
|||
* @param si Shared Group Index
|
||||
* @return non shared formula created for the given shared formula and this cell
|
||||
*/
|
||||
private String convertSharedFormula(int si, XSSFEvaluationWorkbook fpb){
|
||||
private String convertSharedFormula(int si, BaseXSSFEvaluationWorkbook fpb){
|
||||
XSSFSheet sheet = getSheet();
|
||||
|
||||
CTCellFormula f = sheet.getSharedFormula(si);
|
||||
|
@ -536,6 +537,10 @@ public final class XSSFCell implements Cell {
|
|||
* Note, this method only sets the formula string and does not calculate the formula value.
|
||||
* To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)}
|
||||
* </p>
|
||||
* <p>
|
||||
* Note, if there are any shared formulas, his will invalidate any
|
||||
* {@link FormulaEvaluator} instances based on this workbook.
|
||||
* </p>
|
||||
*
|
||||
* @param formula the formula to set, e.g. <code>"SUM(C4:E4)"</code>.
|
||||
* If the argument is <code>null</code> then the current formula is removed.
|
||||
|
@ -563,7 +568,7 @@ public final class XSSFCell implements Cell {
|
|||
if (formula == null) {
|
||||
wb.onDeleteFormula(this);
|
||||
if (_cell.isSetF()) {
|
||||
_row.getSheet().onDeleteFormula(this);
|
||||
_row.getSheet().onDeleteFormula(this, null);
|
||||
_cell.unsetF();
|
||||
}
|
||||
return;
|
||||
|
@ -962,6 +967,16 @@ public final class XSSFCell implements Cell {
|
|||
*/
|
||||
@Override
|
||||
public void setCellType(CellType cellType) {
|
||||
setCellType(cellType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed by bug #62834, which points out getCellFormula() expects an evaluation context or creates a new one,
|
||||
* so if there is one in use, it needs to be carried on through.
|
||||
* @param cellType
|
||||
* @param evalWb BaseXSSFEvaluationWorkbook already in use, or null if a new implicit one should be used
|
||||
*/
|
||||
protected void setCellType(CellType cellType, BaseXSSFEvaluationWorkbook evalWb) {
|
||||
CellType prevType = getCellType();
|
||||
|
||||
if(isPartOfArrayFormulaGroup()){
|
||||
|
@ -969,7 +984,7 @@ public final class XSSFCell implements Cell {
|
|||
}
|
||||
if(prevType == CellType.FORMULA && cellType != CellType.FORMULA) {
|
||||
if (_cell.isSetF()) {
|
||||
_row.getSheet().onDeleteFormula(this);
|
||||
_row.getSheet().onDeleteFormula(this, evalWb);
|
||||
}
|
||||
getSheet().getWorkbook().onDeleteFormula(this);
|
||||
}
|
||||
|
|
|
@ -446,7 +446,7 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSS
|
|||
XSSFSheet sheet = getSheet();
|
||||
XSSFWorkbook wb = sheet.getWorkbook();
|
||||
int sheetIndex = wb.getSheetIndex(sheet);
|
||||
long shapeId = (sheetIndex + 1) * 1024 + newShapeId();
|
||||
long shapeId = (sheetIndex + 1L) * 1024 + newShapeId();
|
||||
|
||||
// add reference to OLE part
|
||||
PackagePartName olePN;
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.util.Iterator;
|
|||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.poi.ss.formula.FormulaShifter;
|
||||
import org.apache.poi.ss.SpreadsheetVersion;
|
||||
import org.apache.poi.ss.formula.FormulaShifter;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellCopyPolicy;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
|
@ -77,7 +77,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
_cells.put(colI, cell);
|
||||
sheet.onReadCell(cell);
|
||||
}
|
||||
|
||||
|
||||
if (! row.isSetR()) {
|
||||
// Certain file format writers skip the row number
|
||||
// Assume no gaps, and give this the next row number
|
||||
|
@ -158,9 +158,9 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
throw new IllegalArgumentException("The compared rows must belong to the same sheet");
|
||||
}
|
||||
|
||||
Integer thisRow = this.getRowNum();
|
||||
Integer otherRow = other.getRowNum();
|
||||
return thisRow.compareTo(otherRow);
|
||||
int thisRow = this.getRowNum();
|
||||
int otherRow = other.getRowNum();
|
||||
return Integer.compare(thisRow, otherRow);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -245,7 +245,9 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
*/
|
||||
@Override
|
||||
public XSSFCell getCell(int cellnum, MissingCellPolicy policy) {
|
||||
if(cellnum < 0) throw new IllegalArgumentException("Cell index must be >= 0");
|
||||
if(cellnum < 0) {
|
||||
throw new IllegalArgumentException("Cell index must be >= 0");
|
||||
}
|
||||
|
||||
// Performance optimization for bug 57840: explicit boxing is slightly faster than auto-unboxing, though may use more memory
|
||||
final Integer colI = Integer.valueOf(cellnum); // NOSONAR
|
||||
|
@ -332,8 +334,12 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
@Override
|
||||
public void setHeight(short height) {
|
||||
if (height == -1) {
|
||||
if (_row.isSetHt()) _row.unsetHt();
|
||||
if (_row.isSetCustomHeight()) _row.unsetCustomHeight();
|
||||
if (_row.isSetHt()) {
|
||||
_row.unsetHt();
|
||||
}
|
||||
if (_row.isSetCustomHeight()) {
|
||||
_row.unsetCustomHeight();
|
||||
}
|
||||
} else {
|
||||
_row.setHt((double) height / 20);
|
||||
_row.setCustomHeight(true);
|
||||
|
@ -425,8 +431,10 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
*/
|
||||
@Override
|
||||
public XSSFCellStyle getRowStyle() {
|
||||
if(!isFormatted()) return null;
|
||||
|
||||
if(!isFormatted()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StylesTable stylesSource = getSheet().getWorkbook().getStylesSource();
|
||||
if(stylesSource.getNumCellStyles() > 0) {
|
||||
return stylesSource.getStyleAt((int)_row.getS());
|
||||
|
@ -434,7 +442,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies a whole-row cell styling to the row.
|
||||
* If the value is null then the style information is removed,
|
||||
|
@ -449,7 +457,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
}
|
||||
} else {
|
||||
StylesTable styleSource = getSheet().getWorkbook().getStylesSource();
|
||||
|
||||
|
||||
XSSFCellStyle xStyle = (XSSFCellStyle)style;
|
||||
xStyle.verifyBelongsToStylesSource(styleSource);
|
||||
|
||||
|
@ -458,7 +466,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
_row.setCustomFormat(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the Cell from this row.
|
||||
*
|
||||
|
@ -502,8 +510,8 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
int i = 0;
|
||||
for (XSSFCell xssfCell : _cells.values()) {
|
||||
cArray[i] = (CTCell) xssfCell.getCTCell().copy();
|
||||
|
||||
// we have to copy and re-create the XSSFCell here because the
|
||||
|
||||
// we have to copy and re-create the XSSFCell here because the
|
||||
// elements as otherwise setCArray below invalidates all the columns!
|
||||
// see Bug 56170, XMLBeans seems to always release previous objects
|
||||
// in the CArray, so we need to provide completely new ones here!
|
||||
|
@ -537,7 +545,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
}
|
||||
setRowNum(rownum);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the cells from srcRow to this row
|
||||
* If this row is not a blank row, this will merge the two rows, overwriting
|
||||
|
@ -589,7 +597,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
final int srcRowNum = srcRow.getRowNum();
|
||||
final int destRowNum = getRowNum();
|
||||
final int rowDifference = destRowNum - srcRowNum;
|
||||
|
||||
|
||||
final FormulaShifter formulaShifter = FormulaShifter.createForRowCopy(sheetIndex, sheetName, srcRowNum, srcRowNum, rowDifference, SpreadsheetVersion.EXCEL2007);
|
||||
final XSSFRowShifter rowShifter = new XSSFRowShifter(_sheet);
|
||||
rowShifter.updateRowFormulas(this, formulaShifter);
|
||||
|
@ -617,7 +625,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
public int getOutlineLevel() {
|
||||
return _row.getOutlineLevel();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shifts column range [firstShiftColumnIndex-lastShiftColumnIndex] step places to the right.
|
||||
* @param firstShiftColumnIndex the column to start shifting
|
||||
|
@ -626,20 +634,23 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
*/
|
||||
@Override
|
||||
public void shiftCellsRight(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) {
|
||||
if(step < 0)
|
||||
if(step < 0) {
|
||||
throw new IllegalArgumentException("Shifting step may not be negative ");
|
||||
if(firstShiftColumnIndex > lastShiftColumnIndex)
|
||||
}
|
||||
if(firstShiftColumnIndex > lastShiftColumnIndex) {
|
||||
throw new IllegalArgumentException(String.format(LocaleUtil.getUserLocale(),
|
||||
"Incorrect shifting range : %d-%d", firstShiftColumnIndex, lastShiftColumnIndex));
|
||||
for (int columnIndex = lastShiftColumnIndex; columnIndex >= firstShiftColumnIndex; columnIndex--){ // process cells backwards, because of shifting
|
||||
}
|
||||
for (int columnIndex = lastShiftColumnIndex; columnIndex >= firstShiftColumnIndex; columnIndex--){ // process cells backwards, because of shifting
|
||||
shiftCell(columnIndex, step);
|
||||
}
|
||||
for (int columnIndex = firstShiftColumnIndex; columnIndex <= firstShiftColumnIndex+step-1; columnIndex++)
|
||||
{
|
||||
_cells.remove(columnIndex);
|
||||
XSSFCell targetCell = getCell(columnIndex);
|
||||
if(targetCell != null)
|
||||
if(targetCell != null) {
|
||||
targetCell.getCTCell().set(CTCell.Factory.newInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -650,27 +661,32 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
*/
|
||||
@Override
|
||||
public void shiftCellsLeft(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) {
|
||||
if(step < 0)
|
||||
if(step < 0) {
|
||||
throw new IllegalArgumentException("Shifting step may not be negative ");
|
||||
if(firstShiftColumnIndex > lastShiftColumnIndex)
|
||||
}
|
||||
if(firstShiftColumnIndex > lastShiftColumnIndex) {
|
||||
throw new IllegalArgumentException(String.format(LocaleUtil.getUserLocale(),
|
||||
"Incorrect shifting range : %d-%d", firstShiftColumnIndex, lastShiftColumnIndex));
|
||||
if(firstShiftColumnIndex - step < 0)
|
||||
}
|
||||
if(firstShiftColumnIndex - step < 0) {
|
||||
throw new IllegalStateException("Column index less than zero : " + (Integer.valueOf(firstShiftColumnIndex + step)).toString());
|
||||
for (int columnIndex = firstShiftColumnIndex; columnIndex <= lastShiftColumnIndex; columnIndex++){
|
||||
}
|
||||
for (int columnIndex = firstShiftColumnIndex; columnIndex <= lastShiftColumnIndex; columnIndex++){
|
||||
shiftCell(columnIndex, -step);
|
||||
}
|
||||
for (int columnIndex = lastShiftColumnIndex-step+1; columnIndex <= lastShiftColumnIndex; columnIndex++){
|
||||
_cells.remove(columnIndex);
|
||||
XSSFCell targetCell = getCell(columnIndex);
|
||||
if(targetCell != null)
|
||||
if(targetCell != null) {
|
||||
targetCell.getCTCell().set(CTCell.Factory.newInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
private void shiftCell(int columnIndex, int step/*pass negative value for left shift*/){
|
||||
if(columnIndex + step < 0) // only for shifting left
|
||||
if(columnIndex + step < 0) {
|
||||
throw new IllegalStateException("Column index less than zero : " + (Integer.valueOf(columnIndex + step)).toString());
|
||||
|
||||
}
|
||||
|
||||
XSSFCell currentCell = getCell(columnIndex);
|
||||
if(currentCell != null){
|
||||
currentCell.setCellNum(columnIndex+step);
|
||||
|
@ -679,8 +695,9 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||
else {
|
||||
_cells.remove(columnIndex+step);
|
||||
XSSFCell targetCell = getCell(columnIndex+step);
|
||||
if(targetCell != null)
|
||||
if(targetCell != null) {
|
||||
targetCell.getCTCell().set(CTCell.Factory.newInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
|
|||
* contain text, numbers, dates, and formulas. Cells can also be formatted.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
||||
private static final POILogger logger = POILogFactory.getLogger(XSSFSheet.class);
|
||||
|
||||
|
@ -472,7 +473,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
/**
|
||||
* Verify that candidate region does not intersect with an existing merged region in this sheet
|
||||
*
|
||||
* @param candidateRegion
|
||||
* @param candidateRegion the range of cells to verify
|
||||
* @throws IllegalStateException if candidate region intersects an existing merged region in this sheet (or candidateRegion is already merged in this sheet)
|
||||
*/
|
||||
private void validateMergedRegions(CellRangeAddress candidateRegion) {
|
||||
|
@ -855,8 +856,8 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
/**
|
||||
* Get a Hyperlink in this sheet anchored at row, column
|
||||
*
|
||||
* @param row
|
||||
* @param column
|
||||
* @param row The row where the hyperlink is anchored
|
||||
* @param column The column where the hyperlinkn is anchored
|
||||
* @return hyperlink if there is a hyperlink anchored at row, column; otherwise returns null
|
||||
*/
|
||||
@Override
|
||||
|
@ -1480,8 +1481,9 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
*
|
||||
* @param startRowNum the first row number in this sheet to return
|
||||
* @param endRowNum the last row number in this sheet to return
|
||||
* @param createRowIfMissing
|
||||
* @return All rows between startRow and endRow, inclusive
|
||||
* @param createRowIfMissing If missing rows should be created.
|
||||
* @return All rows between startRow and endRow, inclusive. If createRowIfMissing is false,
|
||||
* only previously existing rows are returned, otherwise empty rows are added as necessary
|
||||
* @throws IllegalArgumentException if startRowNum and endRowNum are not in ascending order
|
||||
*/
|
||||
private List<XSSFRow> getRows(int startRowNum, int endRowNum, boolean createRowIfMissing) {
|
||||
|
@ -2472,7 +2474,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
* 'Collapsed' state is stored in a single column col info record
|
||||
* immediately after the outline group
|
||||
*
|
||||
* @param idx
|
||||
* @param idx The column-index to check
|
||||
* @return a boolean represented if the column is collapsed
|
||||
*/
|
||||
private boolean isColumnGroupCollapsed(int idx) {
|
||||
|
@ -3052,7 +3054,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
rebuildRows();
|
||||
}
|
||||
|
||||
private final void rebuildRows() {
|
||||
private void rebuildRows() {
|
||||
//rebuild the _rows map
|
||||
List<XSSFRow> rowList = new ArrayList<>(_rows.values());
|
||||
_rows.clear();
|
||||
|
@ -3114,25 +3116,22 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
// then do the actual moving and also adjust comments/rowHeight
|
||||
// we need to sort it in a way so the shifting does not mess up the structures,
|
||||
// i.e. when shifting down, start from down and go up, when shifting up, vice-versa
|
||||
SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>(new Comparator<XSSFComment>() {
|
||||
@Override
|
||||
public int compare(XSSFComment o1, XSSFComment o2) {
|
||||
int row1 = o1.getRow();
|
||||
int row2 = o2.getRow();
|
||||
SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>((o1, o2) -> {
|
||||
int row1 = o1.getRow();
|
||||
int row2 = o2.getRow();
|
||||
|
||||
if (row1 == row2) {
|
||||
// ordering is not important when row is equal, but don't return zero to still
|
||||
// get multiple comments per row into the map
|
||||
return o1.hashCode() - o2.hashCode();
|
||||
}
|
||||
if (row1 == row2) {
|
||||
// ordering is not important when row is equal, but don't return zero to still
|
||||
// get multiple comments per row into the map
|
||||
return o1.hashCode() - o2.hashCode();
|
||||
}
|
||||
|
||||
// when shifting down, sort higher row-values first
|
||||
if (n > 0) {
|
||||
return row1 < row2 ? 1 : -1;
|
||||
} else {
|
||||
// sort lower-row values first when shifting up
|
||||
return row1 > row2 ? 1 : -1;
|
||||
}
|
||||
// when shifting down, sort higher row-values first
|
||||
if (n > 0) {
|
||||
return row1 < row2 ? 1 : -1;
|
||||
} else {
|
||||
// sort lower-row values first when shifting up
|
||||
return row1 > row2 ? 1 : -1;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3211,25 +3210,22 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
// then do the actual moving and also adjust comments/rowHeight
|
||||
// we need to sort it in a way so the shifting does not mess up the structures,
|
||||
// i.e. when shifting down, start from down and go up, when shifting up, vice-versa
|
||||
SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>(new Comparator<XSSFComment>() {
|
||||
@Override
|
||||
public int compare(XSSFComment o1, XSSFComment o2) {
|
||||
int column1 = o1.getColumn();
|
||||
int column2 = o2.getColumn();
|
||||
SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>((o1, o2) -> {
|
||||
int column1 = o1.getColumn();
|
||||
int column2 = o2.getColumn();
|
||||
|
||||
if (column1 == column2) {
|
||||
// ordering is not important when row is equal, but don't return zero to still
|
||||
// get multiple comments per row into the map
|
||||
return o1.hashCode() - o2.hashCode();
|
||||
}
|
||||
if (column1 == column2) {
|
||||
// ordering is not important when row is equal, but don't return zero to still
|
||||
// get multiple comments per row into the map
|
||||
return o1.hashCode() - o2.hashCode();
|
||||
}
|
||||
|
||||
// when shifting down, sort higher row-values first
|
||||
if (n > 0) {
|
||||
return column1 < column2 ? 1 : -1;
|
||||
} else {
|
||||
// sort lower-row values first when shifting up
|
||||
return column1 > column2 ? 1 : -1;
|
||||
}
|
||||
// when shifting down, sort higher row-values first
|
||||
if (n > 0) {
|
||||
return column1 < column2 ? 1 : -1;
|
||||
} else {
|
||||
// sort lower-row values first when shifting up
|
||||
return column1 > column2 ? 1 : -1;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -4096,7 +4092,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
* Creates a new Table, and associates it with this Sheet.
|
||||
*
|
||||
* @param tableArea
|
||||
* the area that the table should cover, should not be {@null}
|
||||
* the area that the table should cover, should not be null
|
||||
* @return the created table
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
@ -4421,18 +4417,15 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
+ "defined source sheet " + sourceSheet.getSheetName() + ".");
|
||||
}
|
||||
|
||||
return createPivotTable(position, sourceSheet, new PivotTableReferenceConfigurator() {
|
||||
@Override
|
||||
public void configureReference(CTWorksheetSource wsSource) {
|
||||
final String[] firstCell = source.getFirstCell().getCellRefParts();
|
||||
final String firstRow = firstCell[1];
|
||||
final String firstCol = firstCell[2];
|
||||
final String[] lastCell = source.getLastCell().getCellRefParts();
|
||||
final String lastRow = lastCell[1];
|
||||
final String lastCol = lastCell[2];
|
||||
final String ref = firstCol+firstRow+':'+lastCol+lastRow; //or just source.formatAsString()
|
||||
wsSource.setRef(ref);
|
||||
}
|
||||
return createPivotTable(position, sourceSheet, wsSource -> {
|
||||
final String[] firstCell = source.getFirstCell().getCellRefParts();
|
||||
final String firstRow = firstCell[1];
|
||||
final String firstCol = firstCell[2];
|
||||
final String[] lastCell = source.getLastCell().getCellRefParts();
|
||||
final String lastRow = lastCell[1];
|
||||
final String lastCol = lastCell[2];
|
||||
final String ref = firstCol+firstRow+':'+lastCol+lastRow; //or just source.formatAsString()
|
||||
wsSource.setRef(ref);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4494,12 +4487,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
+ "defined source sheet " + sourceSheet.getSheetName() + ".");
|
||||
}
|
||||
|
||||
return createPivotTable(position, sourceSheet, new PivotTableReferenceConfigurator() {
|
||||
@Override
|
||||
public void configureReference(CTWorksheetSource wsSource) {
|
||||
wsSource.setName(source.getNameName());
|
||||
}
|
||||
});
|
||||
return createPivotTable(position, sourceSheet, wsSource -> wsSource.setName(source.getNameName()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4523,12 +4511,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
*/
|
||||
@Beta
|
||||
public XSSFPivotTable createPivotTable(final Table source, CellReference position) {
|
||||
return createPivotTable(position, getWorkbook().getSheet(source.getSheetName()), new PivotTableReferenceConfigurator() {
|
||||
@Override
|
||||
public void configureReference(CTWorksheetSource wsSource) {
|
||||
wsSource.setName(source.getName());
|
||||
}
|
||||
});
|
||||
return createPivotTable(position, getWorkbook().getSheet(source.getSheetName()), wsSource -> wsSource.setName(source.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4621,8 +4604,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
|
||||
/**
|
||||
* when a cell with a 'master' shared formula is removed, the next cell in the range becomes the master
|
||||
* @param cell The cell that is removed
|
||||
* @param evalWb BaseXSSFEvaluationWorkbook in use, if one exists
|
||||
*/
|
||||
protected void onDeleteFormula(XSSFCell cell){
|
||||
protected void onDeleteFormula(XSSFCell cell, BaseXSSFEvaluationWorkbook evalWb){
|
||||
|
||||
CTCellFormula f = cell.getCTCell().getF();
|
||||
if (f != null && f.getT() == STCellFormulaType.SHARED && f.isSetRef() && f.getStringValue() != null) {
|
||||
|
@ -4634,9 +4619,9 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||
XSSFRow row = getRow(i);
|
||||
if(row != null) for(int j = cell.getColumnIndex(); j <= ref.getLastColumn(); j++){
|
||||
XSSFCell nextCell = row.getCell(j);
|
||||
if(nextCell != null && nextCell != cell){
|
||||
if(nextCell != null && nextCell != cell && nextCell.getCellType() == CellType.FORMULA){
|
||||
CTCellFormula nextF = nextCell.getCTCell().getF();
|
||||
nextF.setStringValue(nextCell.getCellFormula());
|
||||
nextF.setStringValue(nextCell.getCellFormula(evalWb));
|
||||
CellRangeAddress nextRef = new CellRangeAddress(
|
||||
nextCell.getRowIndex(), ref.getLastRow(),
|
||||
nextCell.getColumnIndex(), ref.getLastColumn());
|
||||
|
|
|
@ -29,6 +29,14 @@ import org.apache.poi.openxml4j.opc.ZipPackage;
|
|||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
|
||||
public class XSSFWorkbookFactory extends WorkbookFactory {
|
||||
/**
|
||||
* Create a new empty Workbook
|
||||
*
|
||||
* @return The created workbook
|
||||
*/
|
||||
public static XSSFWorkbook createWorkbook() {
|
||||
return new XSSFWorkbook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a XSSFWorkbook from the given OOXML Package.
|
||||
|
@ -42,7 +50,6 @@ public class XSSFWorkbookFactory extends WorkbookFactory {
|
|||
* @return The created Workbook
|
||||
*
|
||||
* @throws IOException if an error occurs while reading the data
|
||||
* @throws InvalidFormatException
|
||||
*/
|
||||
public static XSSFWorkbook create(OPCPackage pkg) throws IOException {
|
||||
return createWorkbook(pkg);
|
||||
|
@ -59,7 +66,6 @@ public class XSSFWorkbookFactory extends WorkbookFactory {
|
|||
* @return The created Workbook
|
||||
*
|
||||
* @throws IOException if an error occurs while reading the data
|
||||
* @throws InvalidFormatException
|
||||
*/
|
||||
public static XSSFWorkbook createWorkbook(ZipPackage pkg) throws IOException {
|
||||
return createWorkbook((OPCPackage)pkg);
|
||||
|
@ -76,7 +82,6 @@ public class XSSFWorkbookFactory extends WorkbookFactory {
|
|||
* @return The created Workbook
|
||||
*
|
||||
* @throws IOException if an error occurs while reading the data
|
||||
* @throws InvalidFormatException
|
||||
*/
|
||||
public static XSSFWorkbook createWorkbook(OPCPackage pkg) throws IOException {
|
||||
try {
|
||||
|
@ -122,13 +127,11 @@ public class XSSFWorkbookFactory extends WorkbookFactory {
|
|||
* @return The created Workbook
|
||||
*
|
||||
* @throws IOException if an error occurs while reading the data
|
||||
* @throws InvalidFormatException
|
||||
* @throws InvalidFormatException if the package is not valid.
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public static XSSFWorkbook createWorkbook(InputStream stream) throws IOException, InvalidFormatException {
|
||||
OPCPackage pkg = OPCPackage.open(stream);
|
||||
return createWorkbook(pkg);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class ColumnHelper {
|
|||
TreeSet<CTCol> trackedCols = new TreeSet<>(CTColComparator.BY_MIN_MAX);
|
||||
CTCols newCols = CTCols.Factory.newInstance();
|
||||
CTCols[] colsArray = worksheet.getColsArray();
|
||||
int i = 0;
|
||||
int i;
|
||||
for (i = 0; i < colsArray.length; i++) {
|
||||
CTCols cols = colsArray[i];
|
||||
for (CTCol col : cols.getColList()) {
|
||||
|
@ -61,7 +61,7 @@ public class ColumnHelper {
|
|||
worksheet.removeCols(y);
|
||||
}
|
||||
|
||||
newCols.setColArray(trackedCols.toArray(new CTCol[trackedCols.size()]));
|
||||
newCols.setColArray(trackedCols.toArray(new CTCol[0]));
|
||||
worksheet.addNewCols();
|
||||
worksheet.setColsArray(0, newCols);
|
||||
}
|
||||
|
|
|
@ -40,21 +40,27 @@ public class XWPFSDTContent implements ISDTContent {
|
|||
|
||||
// private final IBody part;
|
||||
// private final XWPFDocument document;
|
||||
private List<XWPFParagraph> paragraphs = new ArrayList<>();
|
||||
private List<XWPFTable> tables = new ArrayList<>();
|
||||
private List<XWPFRun> runs = new ArrayList<>();
|
||||
private List<XWPFSDT> contentControls = new ArrayList<>();
|
||||
// private List<XWPFParagraph> paragraphs = new ArrayList<>();
|
||||
// private List<XWPFTable> tables = new ArrayList<>();
|
||||
// private List<XWPFRun> runs = new ArrayList<>();
|
||||
// private List<XWPFSDT> contentControls = new ArrayList<>();
|
||||
private List<ISDTContents> bodyElements = new ArrayList<>();
|
||||
|
||||
public XWPFSDTContent(CTSdtContentRun sdtRun, IBody part, IRunBody parent) {
|
||||
if (sdtRun == null) {
|
||||
return;
|
||||
}
|
||||
for (CTR ctr : sdtRun.getRArray()) {
|
||||
XWPFRun run = new XWPFRun(ctr, parent);
|
||||
runs.add(run);
|
||||
// runs.add(run);
|
||||
bodyElements.add(run);
|
||||
}
|
||||
}
|
||||
|
||||
public XWPFSDTContent(CTSdtContentBlock block, IBody part, IRunBody parent) {
|
||||
if (block == null) {
|
||||
return;
|
||||
}
|
||||
XmlCursor cursor = block.newCursor();
|
||||
cursor.selectPath("./*");
|
||||
while (cursor.toNextSelection()) {
|
||||
|
@ -62,24 +68,25 @@ public class XWPFSDTContent implements ISDTContent {
|
|||
if (o instanceof CTP) {
|
||||
XWPFParagraph p = new XWPFParagraph((CTP) o, part);
|
||||
bodyElements.add(p);
|
||||
paragraphs.add(p);
|
||||
// paragraphs.add(p);
|
||||
} else if (o instanceof CTTbl) {
|
||||
XWPFTable t = new XWPFTable((CTTbl) o, part);
|
||||
bodyElements.add(t);
|
||||
tables.add(t);
|
||||
// tables.add(t);
|
||||
} else if (o instanceof CTSdtBlock) {
|
||||
XWPFSDT c = new XWPFSDT(((CTSdtBlock) o), part);
|
||||
bodyElements.add(c);
|
||||
contentControls.add(c);
|
||||
// contentControls.add(c);
|
||||
} else if (o instanceof CTR) {
|
||||
XWPFRun run = new XWPFRun((CTR) o, parent);
|
||||
runs.add(run);
|
||||
// runs.add(run);
|
||||
bodyElements.add(run);
|
||||
}
|
||||
}
|
||||
cursor.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
StringBuilder text = new StringBuilder();
|
||||
boolean addNewLine = false;
|
||||
|
@ -130,6 +137,7 @@ public class XWPFSDTContent implements ISDTContent {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getText();
|
||||
}
|
||||
|
|
|
@ -161,8 +161,9 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
this.ctTbl = table;
|
||||
|
||||
// is an empty table: I add one row and one column as default
|
||||
if (table.sizeOfTrArray() == 0)
|
||||
if (table.sizeOfTrArray() == 0) {
|
||||
createEmptyTable(table);
|
||||
}
|
||||
|
||||
for (CTRow row : table.getTrList()) {
|
||||
StringBuilder rowText = new StringBuilder();
|
||||
|
@ -233,7 +234,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
return text.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This method has existed since 2008 without an implementation.
|
||||
* It will be removed unless an implementation is provided.
|
||||
|
@ -288,7 +289,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
/**
|
||||
* Get the width value as an integer.
|
||||
* <p>If the width type is AUTO, DXA, or NIL, the value is 20ths of a point. If
|
||||
* the width type is PCT, the value is the percentage times 50 (e.g., 2500 for 50%).</p>
|
||||
* the width type is PCT, the value is the percentage times 50 (e.g., 2500 for 50%).</p>
|
||||
* @return width value as an integer
|
||||
*/
|
||||
public int getWidth() {
|
||||
|
@ -322,7 +323,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns CTTblPr object for table. If force parameter is true, will
|
||||
* Returns CTTblPr object for table. If force parameter is true, will
|
||||
* create the element if necessary. If force parameter is false, returns
|
||||
* null when CTTblPr element is missing.
|
||||
*
|
||||
|
@ -343,7 +344,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
private CTTblBorders getTblBorders(boolean force) {
|
||||
CTTblPr tblPr = getTblPr(force);
|
||||
return tblPr == null ? null
|
||||
: tblPr.isSetTblBorders() ? tblPr.getTblBorders()
|
||||
: tblPr.isSetTblBorders() ? tblPr.getTblBorders()
|
||||
: force ? tblPr.addNewTblBorders()
|
||||
: null;
|
||||
}
|
||||
|
@ -413,18 +414,18 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
: tPr.isSetJc() ? TableRowAlign.valueOf(tPr.getJc().getVal().intValue())
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set table alignment to specified {@link TableRowAlign}
|
||||
*
|
||||
* @param ha {@link TableRowAlign} to set
|
||||
* @param tra {@link TableRowAlign} to set
|
||||
*/
|
||||
public void setTableAlignment(TableRowAlign tra) {
|
||||
CTTblPr tPr = getTblPr(true);
|
||||
CTJc jc = tPr.isSetJc() ? tPr.getJc() : tPr.addNewJc();
|
||||
jc.setVal(STJc.Enum.forInt(tra.getValue()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the table alignment attribute from a table
|
||||
*/
|
||||
|
@ -434,7 +435,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
tPr.unsetJc();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void addColumn(XWPFTableRow tabRow, int sizeCol) {
|
||||
if (sizeCol > 0) {
|
||||
for (int i = 0; i < sizeCol; i++) {
|
||||
|
@ -486,7 +487,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get inside horizontal border size
|
||||
*
|
||||
*
|
||||
* @return The width of the Inside Horizontal borders in 1/8th points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -496,7 +497,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get inside horizontal border spacing
|
||||
*
|
||||
*
|
||||
* @return The offset to the Inside Horizontal borders in points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -506,7 +507,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get inside horizontal border color
|
||||
*
|
||||
*
|
||||
* @return The color of the Inside Horizontal borders, null if missing.
|
||||
*/
|
||||
public String getInsideHBorderColor() {
|
||||
|
@ -524,7 +525,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get inside vertical border size
|
||||
*
|
||||
*
|
||||
* @return The width of the Inside vertical borders in 1/8th points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -534,7 +535,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get inside vertical border spacing
|
||||
*
|
||||
*
|
||||
* @return The offset to the Inside vertical borders in points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -544,7 +545,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get inside vertical border color
|
||||
*
|
||||
*
|
||||
* @return The color of the Inside vertical borders, null if missing.
|
||||
*/
|
||||
public String getInsideVBorderColor() {
|
||||
|
@ -562,7 +563,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get top border size
|
||||
*
|
||||
*
|
||||
* @return The width of the top borders in 1/8th points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -572,7 +573,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get top border spacing
|
||||
*
|
||||
*
|
||||
* @return The offset to the top borders in points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -582,7 +583,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get top border color
|
||||
*
|
||||
*
|
||||
* @return The color of the top borders, null if missing.
|
||||
*/
|
||||
public String getTopBorderColor() {
|
||||
|
@ -600,7 +601,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get bottom border size
|
||||
*
|
||||
*
|
||||
* @return The width of the bottom borders in 1/8th points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -610,7 +611,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get bottom border spacing
|
||||
*
|
||||
*
|
||||
* @return The offset to the bottom borders in points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -620,7 +621,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get bottom border color
|
||||
*
|
||||
*
|
||||
* @return The color of the bottom borders, null if missing.
|
||||
*/
|
||||
public String getBottomBorderColor() {
|
||||
|
@ -638,7 +639,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get Left border size
|
||||
*
|
||||
*
|
||||
* @return The width of the Left borders in 1/8th points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -648,7 +649,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get Left border spacing
|
||||
*
|
||||
*
|
||||
* @return The offset to the Left borders in points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -658,7 +659,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get Left border color
|
||||
*
|
||||
*
|
||||
* @return The color of the Left borders, null if missing.
|
||||
*/
|
||||
public String getLeftBorderColor() {
|
||||
|
@ -676,7 +677,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get Right border size
|
||||
*
|
||||
*
|
||||
* @return The width of the Right borders in 1/8th points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -686,7 +687,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get Right border spacing
|
||||
*
|
||||
*
|
||||
* @return The offset to the Right borders in points,
|
||||
* -1 if missing.
|
||||
*/
|
||||
|
@ -696,7 +697,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
|
||||
/**
|
||||
* Get Right border color
|
||||
*
|
||||
*
|
||||
* @return The color of the Right borders, null if missing.
|
||||
*/
|
||||
public String getRightBorderColor() {
|
||||
|
@ -770,7 +771,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
* of a point) and a maximum value of 96 (twelve points). Any values outside this
|
||||
* range may be reassigned to a more appropriate value.
|
||||
* @param space - Specifies the spacing offset that shall be used to place this border on the table
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* or auto to allow a consumer to automatically determine the border color as appropriate.
|
||||
*/
|
||||
public void setInsideHBorder(XWPFBorderType type, int size, int space, String rgbColor) {
|
||||
|
@ -786,7 +787,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
* of a point) and a maximum value of 96 (twelve points). Any values outside this
|
||||
* range may be reassigned to a more appropriate value.
|
||||
* @param space - Specifies the spacing offset that shall be used to place this border on the table
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* or auto to allow a consumer to automatically determine the border color as appropriate.
|
||||
*/
|
||||
public void setInsideVBorder(XWPFBorderType type, int size, int space, String rgbColor) {
|
||||
|
@ -802,7 +803,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
* of a point) and a maximum value of 96 (twelve points). Any values outside this
|
||||
* range may be reassigned to a more appropriate value.
|
||||
* @param space - Specifies the spacing offset that shall be used to place this border on the table
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* or auto to allow a consumer to automatically determine the border color as appropriate.
|
||||
*/
|
||||
public void setTopBorder(XWPFBorderType type, int size, int space, String rgbColor) {
|
||||
|
@ -818,7 +819,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
* of a point) and a maximum value of 96 (twelve points). Any values outside this
|
||||
* range may be reassigned to a more appropriate value.
|
||||
* @param space - Specifies the spacing offset that shall be used to place this border on the table
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* or auto to allow a consumer to automatically determine the border color as appropriate.
|
||||
*/
|
||||
public void setBottomBorder(XWPFBorderType type, int size, int space, String rgbColor) {
|
||||
|
@ -834,7 +835,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
* of a point) and a maximum value of 96 (twelve points). Any values outside this
|
||||
* range may be reassigned to a more appropriate value.
|
||||
* @param space - Specifies the spacing offset that shall be used to place this border on the table
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* or auto to allow a consumer to automatically determine the border color as appropriate.
|
||||
*/
|
||||
public void setLeftBorder(XWPFBorderType type, int size, int space, String rgbColor) {
|
||||
|
@ -850,7 +851,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
* of a point) and a maximum value of 96 (twelve points). Any values outside this
|
||||
* range may be reassigned to a more appropriate value.
|
||||
* @param space - Specifies the spacing offset that shall be used to place this border on the table
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* @param rgbColor - This color may either be presented as a hex value (in RRGGBB format),
|
||||
* or auto to allow a consumer to automatically determine the border color as appropriate.
|
||||
*/
|
||||
public void setRightBorder(XWPFBorderType type, int size, int space, String rgbColor) {
|
||||
|
@ -872,14 +873,14 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
public void removeInsideHBorder() {
|
||||
removeBorder(Border.INSIDE_H);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove inside vertical borders for table
|
||||
*/
|
||||
public void removeInsideVBorder() {
|
||||
removeBorder(Border.INSIDE_V);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove top borders for table
|
||||
*/
|
||||
|
@ -893,21 +894,21 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
public void removeBottomBorder() {
|
||||
removeBorder(Border.BOTTOM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove left borders for table
|
||||
*/
|
||||
public void removeLeftBorder() {
|
||||
removeBorder(Border.LEFT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove right borders for table
|
||||
*/
|
||||
public void removeRightBorder() {
|
||||
removeBorder(Border.RIGHT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove all borders from table
|
||||
*/
|
||||
|
@ -959,7 +960,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
}
|
||||
|
||||
/**
|
||||
* removes the Borders node from Table properties if there are
|
||||
* removes the Borders node from Table properties if there are
|
||||
* no border elements
|
||||
*/
|
||||
private void cleanupTblBorders() {
|
||||
|
@ -976,7 +977,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getCellMarginTop() {
|
||||
return getCellMargin(CTTblCellMar::getTop);
|
||||
}
|
||||
|
@ -1095,10 +1096,12 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
*
|
||||
* @see org.apache.poi.xwpf.usermodel.IBodyElement#getElementType()
|
||||
*/
|
||||
@Override
|
||||
public BodyElementType getElementType() {
|
||||
return BodyElementType.TABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBody getBody() {
|
||||
return part;
|
||||
}
|
||||
|
@ -1108,6 +1111,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
*
|
||||
* @see org.apache.poi.xwpf.usermodel.IBody#getPart()
|
||||
*/
|
||||
@Override
|
||||
public POIXMLDocumentPart getPart() {
|
||||
if (part != null) {
|
||||
return part.getPart();
|
||||
|
@ -1120,6 +1124,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
*
|
||||
* @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
|
||||
*/
|
||||
@Override
|
||||
public BodyType getPartType() {
|
||||
return part.getPartType();
|
||||
}
|
||||
|
@ -1130,11 +1135,13 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
*/
|
||||
public XWPFTableRow getRow(CTRow row) {
|
||||
for (int i = 0; i < getRows().size(); i++) {
|
||||
if (getRows().get(i).getCtRow() == row) return getRow(i);
|
||||
if (getRows().get(i).getCtRow() == row) {
|
||||
return getRow(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the table width as a decimal value.
|
||||
* <p>If the width type is DXA or AUTO, then the value will always have
|
||||
|
@ -1159,14 +1166,14 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
protected static double getWidthDecimal(CTTblWidth ctWidth) {
|
||||
double result = 0.0;
|
||||
STTblWidth.Enum typeValue = ctWidth.getType();
|
||||
if (typeValue == STTblWidth.DXA
|
||||
|| typeValue == STTblWidth.AUTO
|
||||
if (typeValue == STTblWidth.DXA
|
||||
|| typeValue == STTblWidth.AUTO
|
||||
|| typeValue == STTblWidth.NIL) {
|
||||
result = 0.0 + ctWidth.getW().intValue();
|
||||
} else if (typeValue == STTblWidth.PCT) {
|
||||
// Percentage values are stored as integers that are 50 times
|
||||
// percentage.
|
||||
result = ctWidth.getW().intValue() / 50.0;
|
||||
result = ctWidth.getW().intValue() / 50.0;
|
||||
} else {
|
||||
// Should never get here
|
||||
}
|
||||
|
@ -1230,7 +1237,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
protected static void setWidthValue(String widthValue, CTTblWidth ctWidth) {
|
||||
if (!widthValue.matches(REGEX_WIDTH_VALUE)) {
|
||||
throw new RuntimeException("Table width value \"" + widthValue + "\" "
|
||||
+ "must match regular expression \"" + REGEX_WIDTH_VALUE + "\".");
|
||||
+ "must match regular expression \"" + REGEX_WIDTH_VALUE + "\".");
|
||||
}
|
||||
if (widthValue.matches("auto")) {
|
||||
ctWidth.setType(STTblWidth.AUTO);
|
||||
|
@ -1240,13 +1247,13 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
} else {
|
||||
// Must be an integer
|
||||
ctWidth.setW(new BigInteger(widthValue));
|
||||
ctWidth.setType(STTblWidth.DXA);
|
||||
ctWidth.setType(STTblWidth.DXA);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the underlying table width value to a percentage value.
|
||||
* @param ctWidth The CTTblWidth to set the value on
|
||||
* @param ctWidth The CTTblWidth to set the value on
|
||||
* @param widthValue String width value in form "33.3%" or an integer that is 50 times desired percentage value (e.g,
|
||||
* 2500 for 50%)
|
||||
* @since 4.0.0
|
||||
|
@ -1257,7 +1264,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
String numberPart = widthValue.substring(0, widthValue.length() - 1);
|
||||
double percentage = Double.parseDouble(numberPart) * 50;
|
||||
long intValue = Math.round(percentage);
|
||||
ctWidth.setW(BigInteger.valueOf(intValue));
|
||||
ctWidth.setW(BigInteger.valueOf(intValue));
|
||||
} else if (widthValue.matches("[0-9]+")) {
|
||||
ctWidth.setW(new BigInteger(widthValue));
|
||||
} else {
|
||||
|
@ -1275,7 +1282,7 @@ public class XWPFTable implements IBodyElement, ISDTContents {
|
|||
* @since 4.0.0
|
||||
*/
|
||||
public void setWidthType(TableWidthType widthType) {
|
||||
setWidthType(widthType, getTblPr().getTblW());
|
||||
setWidthType(widthType, getTblPr().getTblW());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,25 @@
|
|||
|
||||
package org.apache.poi.ooxml.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
import org.apache.poi.util.SuppressForbidden;
|
||||
|
@ -29,19 +47,7 @@ import org.junit.runner.JUnitCore;
|
|||
import org.junit.runner.Result;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.regex.Pattern;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Build a 'lite' version of the ooxml-schemas.jar
|
||||
|
@ -74,12 +80,12 @@ public final class OOXMLLite {
|
|||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("Free memory (bytes): " +
|
||||
System.out.println("Free memory (bytes): " +
|
||||
Runtime.getRuntime().freeMemory());
|
||||
long maxMemory = Runtime.getRuntime().maxMemory();
|
||||
System.out.println("Maximum memory (bytes): " +
|
||||
System.out.println("Maximum memory (bytes): " +
|
||||
(maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));
|
||||
System.out.println("Total memory (bytes): " +
|
||||
System.out.println("Total memory (bytes): " +
|
||||
Runtime.getRuntime().totalMemory());
|
||||
|
||||
String dest = null, test = null, ooxml = null;
|
||||
|
@ -87,13 +93,13 @@ public final class OOXMLLite {
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
switch (args[i]) {
|
||||
case "-dest":
|
||||
dest = args[++i];
|
||||
dest = args[++i]; // lgtm[java/index-out-of-bounds]
|
||||
break;
|
||||
case "-test":
|
||||
test = args[++i];
|
||||
test = args[++i]; // lgtm[java/index-out-of-bounds]
|
||||
break;
|
||||
case "-ooxml":
|
||||
ooxml = args[++i];
|
||||
ooxml = args[++i]; // lgtm[java/index-out-of-bounds]
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +254,7 @@ public final class OOXMLLite {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// also check super classes
|
||||
if(testclass.getSuperclass() != null) {
|
||||
for (Method m : testclass.getSuperclass().getDeclaredMethods()) {
|
||||
|
@ -257,7 +263,7 @@ public final class OOXMLLite {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
System.out.println("Class " + testclass.getName() + " does not derive from TestCase and does not have a @Test annotation");
|
||||
|
||||
// Should we also look at superclasses to find cases
|
||||
|
@ -286,8 +292,12 @@ public final class OOXMLLite {
|
|||
String path = arg.getAbsolutePath();
|
||||
String prefix = root.getAbsolutePath();
|
||||
String cls = path.substring(prefix.length() + 1).replace(File.separator, ".");
|
||||
if(!cls.matches(ptrn)) return;
|
||||
if (cls.matches(exclude)) return;
|
||||
if(!cls.matches(ptrn)) {
|
||||
return;
|
||||
}
|
||||
if (cls.matches(exclude)) {
|
||||
return;
|
||||
}
|
||||
//ignore inner classes defined in tests
|
||||
if (cls.indexOf('$') != -1) {
|
||||
System.out.println("Inner class " + cls + " not included");
|
||||
|
@ -315,10 +325,11 @@ public final class OOXMLLite {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Set<Class<?>> getLoadedClasses(String ptrn) {
|
||||
// make the field accessible, we defer this from static initialization to here to
|
||||
// make the field accessible, we defer this from static initialization to here to
|
||||
// allow JDKs which do not have this field (e.g. IBM JDK) to at least load the class
|
||||
// without failing, see https://issues.apache.org/bugzilla/show_bug.cgi?id=56550
|
||||
final Field _classes = AccessController.doPrivileged(new PrivilegedAction<Field>() {
|
||||
@Override
|
||||
@SuppressForbidden("TODO: Reflection works until Java 8 on Oracle/Sun JDKs, but breaks afterwards (different classloader types, access checks)")
|
||||
public Field run() {
|
||||
try {
|
||||
|
@ -339,11 +350,17 @@ public final class OOXMLLite {
|
|||
for (Class<?> cls : classes) {
|
||||
// e.g. proxy-classes, ...
|
||||
ProtectionDomain pd = cls.getProtectionDomain();
|
||||
if (pd == null) continue;
|
||||
if (pd == null) {
|
||||
continue;
|
||||
}
|
||||
CodeSource cs = pd.getCodeSource();
|
||||
if (cs == null) continue;
|
||||
if (cs == null) {
|
||||
continue;
|
||||
}
|
||||
URL loc = cs.getLocation();
|
||||
if (loc == null) continue;
|
||||
if (loc == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String jar = loc.toString();
|
||||
if (jar.contains(ptrn)) {
|
||||
|
|
|
@ -30,7 +30,6 @@ import java.io.IOException;
|
|||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
|
@ -44,125 +43,130 @@ import org.xmlunit.diff.Diff;
|
|||
import org.xmlunit.diff.DifferenceEvaluator;
|
||||
import org.xmlunit.diff.ElementSelectors;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
/**
|
||||
* Compare the contents of 2 zip files.
|
||||
*/
|
||||
public final class ZipFileAssert {
|
||||
private ZipFileAssert() {
|
||||
}
|
||||
private ZipFileAssert() {
|
||||
}
|
||||
|
||||
private static void equals(
|
||||
TreeMap<String, ByteArrayOutputStream> file1,
|
||||
TreeMap<String, ByteArrayOutputStream> file2) {
|
||||
Set<String> listFile1 = file1.keySet();
|
||||
Assert.assertEquals("not the same number of files in zip:", listFile1.size(), file2.keySet().size());
|
||||
|
||||
for (String fileName : listFile1) {
|
||||
// extract the contents for both
|
||||
ByteArrayOutputStream contain1 = file1.get(fileName);
|
||||
ByteArrayOutputStream contain2 = file2.get(fileName);
|
||||
private static void equals(
|
||||
TreeMap<String, ByteArrayOutputStream> file1,
|
||||
TreeMap<String, ByteArrayOutputStream> file2) {
|
||||
Set<String> listFile1 = file1.keySet();
|
||||
Assert.assertEquals("not the same number of files in zip:", listFile1.size(), file2.keySet().size());
|
||||
|
||||
assertNotNull(fileName + " not found in 2nd zip", contain2);
|
||||
// no need to check for contain1. The key come from it
|
||||
for (String fileName : listFile1) {
|
||||
// extract the contents for both
|
||||
ByteArrayOutputStream contain1 = file1.get(fileName);
|
||||
ByteArrayOutputStream contain2 = file2.get(fileName);
|
||||
|
||||
if (fileName.matches(".*\\.(xml|rels)$")) {
|
||||
// we have a xml file
|
||||
final Diff diff = DiffBuilder.
|
||||
compare(Input.fromByteArray(contain1.toByteArray())).
|
||||
withTest(Input.fromByteArray(contain2.toByteArray())).
|
||||
ignoreWhitespace().
|
||||
checkForSimilar().
|
||||
withDifferenceEvaluator(new IgnoreXMLDeclEvaluator()).
|
||||
withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes, ElementSelectors.byNameAndText)).
|
||||
build();
|
||||
assertFalse(fileName+": "+diff.toString(), diff.hasDifferences());
|
||||
assertNotNull(fileName + " not found in 2nd zip", contain2);
|
||||
// no need to check for contain1. The key come from it
|
||||
|
||||
if (fileName.matches(".*\\.(xml|rels)$")) {
|
||||
// we have a xml file
|
||||
final Diff diff = DiffBuilder.
|
||||
compare(Input.fromByteArray(contain1.toByteArray())).
|
||||
withTest(Input.fromByteArray(contain2.toByteArray())).
|
||||
ignoreWhitespace().
|
||||
checkForSimilar().
|
||||
withDifferenceEvaluator(new IgnoreXMLDeclEvaluator()).
|
||||
withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes, ElementSelectors.byNameAndText)).
|
||||
build();
|
||||
assertFalse(fileName+": "+diff.toString(), diff.hasDifferences());
|
||||
} else {
|
||||
// not xml, may be an image or other binary format
|
||||
// not xml, may be an image or other binary format
|
||||
Assert.assertEquals(fileName + " does not have the same size in both zip:", contain1.size(), contain2.size());
|
||||
assertArrayEquals("contents differ", contain1.toByteArray(), contain2.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
assertArrayEquals("contents differ", contain1.toByteArray(), contain2.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TreeMap<String, ByteArrayOutputStream> decompress(
|
||||
File filename) throws IOException {
|
||||
// store the zip content in memory
|
||||
// let s assume it is not Go ;-)
|
||||
TreeMap<String, ByteArrayOutputStream> zipContent = new TreeMap<>();
|
||||
private static TreeMap<String, ByteArrayOutputStream> decompress(
|
||||
File filename) throws IOException {
|
||||
// store the zip content in memory
|
||||
// let s assume it is not Go ;-)
|
||||
TreeMap<String, ByteArrayOutputStream> zipContent = new TreeMap<>();
|
||||
|
||||
/* Open file to decompress */
|
||||
FileInputStream file_decompress = new FileInputStream(filename);
|
||||
try (
|
||||
/* Open file to decompress */
|
||||
FileInputStream file_decompress = new FileInputStream(filename);
|
||||
|
||||
/* Create a buffer for the decompressed files */
|
||||
BufferedInputStream buffi = new BufferedInputStream(file_decompress);
|
||||
/* Create a buffer for the decompressed files */
|
||||
BufferedInputStream buffi = new BufferedInputStream(file_decompress);
|
||||
|
||||
/* Open the file with the buffer */
|
||||
ZipArchiveInputStream zis = new ZipArchiveInputStream(buffi);
|
||||
/* Open the file with the buffer */
|
||||
ZipArchiveInputStream zis = new ZipArchiveInputStream(buffi);
|
||||
) {
|
||||
|
||||
/* Processing entries of the zip file */
|
||||
ArchiveEntry entree;
|
||||
while ((entree = zis.getNextEntry()) != null) {
|
||||
/* Processing entries of the zip file */
|
||||
ArchiveEntry entree;
|
||||
while ((entree = zis.getNextEntry()) != null) {
|
||||
|
||||
/* Create a array for the current entry */
|
||||
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
|
||||
IOUtils.copy(zis, byteArray);
|
||||
zipContent.put(entree.getName(), byteArray);
|
||||
}
|
||||
/* Create a array for the current entry */
|
||||
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
|
||||
IOUtils.copy(zis, byteArray);
|
||||
zipContent.put(entree.getName(), byteArray);
|
||||
}
|
||||
|
||||
zis.close();
|
||||
}
|
||||
|
||||
return zipContent;
|
||||
}
|
||||
return zipContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two files are equal. Throws an <tt>AssertionFailedError</tt>
|
||||
* if they are not.
|
||||
* <p>
|
||||
*
|
||||
*/
|
||||
public static void assertEquals(File expected, File actual) {
|
||||
assertNotNull(expected);
|
||||
assertNotNull(actual);
|
||||
/**
|
||||
* Asserts that two files are equal. Throws an <tt>AssertionFailedError</tt>
|
||||
* if they are not.
|
||||
* <p>
|
||||
*
|
||||
*/
|
||||
public static void assertEquals(File expected, File actual) {
|
||||
assertNotNull(expected);
|
||||
assertNotNull(actual);
|
||||
|
||||
assertTrue("File does not exist [" + expected.getAbsolutePath()
|
||||
+ "]", expected.exists());
|
||||
assertTrue("File does not exist [" + actual.getAbsolutePath()
|
||||
+ "]", actual.exists());
|
||||
assertTrue("File does not exist [" + expected.getAbsolutePath()
|
||||
+ "]", expected.exists());
|
||||
assertTrue("File does not exist [" + actual.getAbsolutePath()
|
||||
+ "]", actual.exists());
|
||||
|
||||
assertTrue("Expected file not readable", expected.canRead());
|
||||
assertTrue("Actual file not readable", actual.canRead());
|
||||
assertTrue("Expected file not readable", expected.canRead());
|
||||
assertTrue("Actual file not readable", actual.canRead());
|
||||
|
||||
try {
|
||||
TreeMap<String, ByteArrayOutputStream> file1 = decompress(expected);
|
||||
TreeMap<String, ByteArrayOutputStream> file2 = decompress(actual);
|
||||
equals(file1, file2);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionFailedError(e.toString());
|
||||
}
|
||||
}
|
||||
try {
|
||||
TreeMap<String, ByteArrayOutputStream> file1 = decompress(expected);
|
||||
TreeMap<String, ByteArrayOutputStream> file2 = decompress(actual);
|
||||
equals(file1, file2);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionFailedError(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static class IgnoreXMLDeclEvaluator implements DifferenceEvaluator {
|
||||
public ComparisonResult evaluate(final Comparison comparison, final ComparisonResult outcome) {
|
||||
if (outcome != ComparisonResult.EQUAL) {
|
||||
// only evaluate differences
|
||||
switch (comparison.getType()) {
|
||||
case CHILD_NODELIST_SEQUENCE:
|
||||
case XML_STANDALONE:
|
||||
case NAMESPACE_PREFIX:
|
||||
return ComparisonResult.SIMILAR;
|
||||
case TEXT_VALUE:
|
||||
switch (comparison.getControlDetails().getTarget().getParentNode().getNodeName()) {
|
||||
case "dcterms:created":
|
||||
case "dc:creator":
|
||||
return ComparisonResult.SIMILAR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private static class IgnoreXMLDeclEvaluator implements DifferenceEvaluator {
|
||||
@Override
|
||||
public ComparisonResult evaluate(final Comparison comparison, final ComparisonResult outcome) {
|
||||
if (outcome != ComparisonResult.EQUAL) {
|
||||
// only evaluate differences
|
||||
switch (comparison.getType()) {
|
||||
case CHILD_NODELIST_SEQUENCE:
|
||||
case XML_STANDALONE:
|
||||
case NAMESPACE_PREFIX:
|
||||
return ComparisonResult.SIMILAR;
|
||||
case TEXT_VALUE:
|
||||
switch (comparison.getControlDetails().getTarget().getParentNode().getNodeName()) {
|
||||
case "dcterms:created":
|
||||
case "dc:creator":
|
||||
return ComparisonResult.SIMILAR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
}
|
||||
return outcome;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,9 +83,7 @@ public final class TestOPCComplianceCoreProperties {
|
|||
try {
|
||||
InputStream is = OpenXML4JTestDataSamples.openComplianceSampleStream("OPCCompliance_CoreProperties_OnlyOneCorePropertiesPart.docx");
|
||||
pkg = OPCPackage.open(is);
|
||||
} catch (InvalidFormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
} catch (InvalidFormatException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
pkg.revert();
|
||||
|
@ -151,9 +149,7 @@ public final class TestOPCComplianceCoreProperties {
|
|||
OPCPackage pkg;
|
||||
try {
|
||||
pkg = OPCPackage.open(is);
|
||||
} catch (InvalidFormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
} catch (InvalidFormatException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
URI partUri = createURI("/docProps/core2.xml");
|
||||
|
|
|
@ -74,7 +74,7 @@ public class TestFonts {
|
|||
// currently linux and mac return quite different values
|
||||
private static final int[] expected_sizes = {
|
||||
304, // windows 10, 1080p, MS Office 2016, system text scaling 100% instead of default 125%
|
||||
306, // Windows 10, 15.6" 3840x2160
|
||||
306, 308,// Windows 10, 15.6" 3840x2160
|
||||
311, 312, 313, 318,
|
||||
348, // Windows 10, 15.6" 3840x2160
|
||||
362, // Windows 10, 13.3" 1080p high-dpi
|
||||
|
|
|
@ -17,18 +17,25 @@
|
|||
|
||||
package org.apache.poi.ss;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import org.apache.poi.EmptyFileException;
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackageAccess;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
|
@ -36,16 +43,14 @@ import org.apache.poi.util.POILogFactory;
|
|||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.util.TempFile;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackageAccess;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbookFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
public final class TestWorkbookFactory {
|
||||
private static final String xls = "SampleSS.xls";
|
||||
private static final String xlsx = "SampleSS.xlsx";
|
||||
private static final String[] xls_prot = new String[] {"password.xls", "password"};
|
||||
private static final String[] xlsx_prot = new String[]{"protected_passtika.xlsx", "tika"};
|
||||
private static final String[] xls_protected = new String[] {"password.xls", "password"};
|
||||
private static final String[] xlsx_protected = new String[]{"protected_passtika.xlsx", "tika"};
|
||||
private static final String txt = "SampleSS.txt";
|
||||
|
||||
private static final POILogger LOGGER = POILogFactory.getLogger(TestWorkbookFactory.class);
|
||||
|
@ -105,6 +110,13 @@ public final class TestWorkbookFactory {
|
|||
assertTrue(wb instanceof HSSFWorkbook);
|
||||
assertCloseDoesNotModifyFile(xls, wb);
|
||||
|
||||
wb = WorkbookFactory.create(
|
||||
new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls)).getRoot()
|
||||
);
|
||||
assertNotNull(wb);
|
||||
assertTrue(wb instanceof HSSFWorkbook);
|
||||
assertCloseDoesNotModifyFile(xls, wb);
|
||||
|
||||
// Package -> xssf
|
||||
wb = XSSFWorkbookFactory.create(
|
||||
OPCPackage.open(
|
||||
|
@ -195,7 +207,6 @@ public final class TestWorkbookFactory {
|
|||
public void testCreateWithPasswordFromStream() throws Exception {
|
||||
Workbook wb;
|
||||
|
||||
|
||||
// Unprotected, no password given, opens normally
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.openSampleFileStream(xls), null
|
||||
|
@ -230,26 +241,26 @@ public final class TestWorkbookFactory {
|
|||
|
||||
// Protected, correct password, opens fine
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.openSampleFileStream(xls_prot[0]), xls_prot[1]
|
||||
HSSFTestDataSamples.openSampleFileStream(xls_protected[0]), xls_protected[1]
|
||||
);
|
||||
assertNotNull(wb);
|
||||
assertTrue(wb instanceof HSSFWorkbook);
|
||||
assertCloseDoesNotModifyFile(xls_prot[0], wb);
|
||||
assertCloseDoesNotModifyFile(xls_protected[0], wb);
|
||||
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.openSampleFileStream(xlsx_prot[0]), xlsx_prot[1]
|
||||
HSSFTestDataSamples.openSampleFileStream(xlsx_protected[0]), xlsx_protected[1]
|
||||
);
|
||||
assertNotNull(wb);
|
||||
assertTrue(wb instanceof XSSFWorkbook);
|
||||
assertCloseDoesNotModifyFile(xlsx_prot[0], wb);
|
||||
assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
|
||||
|
||||
|
||||
// Protected, wrong password, throws Exception
|
||||
try {
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.openSampleFileStream(xls_prot[0]), "wrong"
|
||||
HSSFTestDataSamples.openSampleFileStream(xls_protected[0]), "wrong"
|
||||
);
|
||||
assertCloseDoesNotModifyFile(xls_prot[0], wb);
|
||||
assertCloseDoesNotModifyFile(xls_protected[0], wb);
|
||||
fail("Shouldn't be able to open with the wrong password");
|
||||
} catch (EncryptedDocumentException e) {
|
||||
// expected here
|
||||
|
@ -257,9 +268,9 @@ public final class TestWorkbookFactory {
|
|||
|
||||
try {
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.openSampleFileStream(xlsx_prot[0]), "wrong"
|
||||
HSSFTestDataSamples.openSampleFileStream(xlsx_protected[0]), "wrong"
|
||||
);
|
||||
assertCloseDoesNotModifyFile(xlsx_prot[0], wb);
|
||||
assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
|
||||
fail("Shouldn't be able to open with the wrong password");
|
||||
} catch (EncryptedDocumentException e) {
|
||||
// expected here
|
||||
|
@ -305,28 +316,28 @@ public final class TestWorkbookFactory {
|
|||
|
||||
// Protected, correct password, opens fine
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.getSampleFile(xls_prot[0]), xls_prot[1]
|
||||
HSSFTestDataSamples.getSampleFile(xls_protected[0]), xls_protected[1]
|
||||
);
|
||||
assertNotNull(wb);
|
||||
assertTrue(wb instanceof HSSFWorkbook);
|
||||
assertCloseDoesNotModifyFile(xls_prot[0], wb);
|
||||
assertCloseDoesNotModifyFile(xls_protected[0], wb);
|
||||
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.getSampleFile(xlsx_prot[0]), xlsx_prot[1]
|
||||
HSSFTestDataSamples.getSampleFile(xlsx_protected[0]), xlsx_protected[1]
|
||||
);
|
||||
assertNotNull(wb);
|
||||
assertTrue(wb instanceof XSSFWorkbook);
|
||||
assertTrue(wb.getNumberOfSheets() > 0);
|
||||
assertNotNull(wb.getSheetAt(0));
|
||||
assertNotNull(wb.getSheetAt(0).getRow(0));
|
||||
assertCloseDoesNotModifyFile(xlsx_prot[0], wb);
|
||||
assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
|
||||
|
||||
// Protected, wrong password, throws Exception
|
||||
try {
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.getSampleFile(xls_prot[0]), "wrong"
|
||||
HSSFTestDataSamples.getSampleFile(xls_protected[0]), "wrong"
|
||||
);
|
||||
assertCloseDoesNotModifyFile(xls_prot[0], wb);
|
||||
assertCloseDoesNotModifyFile(xls_protected[0], wb);
|
||||
fail("Shouldn't be able to open with the wrong password");
|
||||
} catch (EncryptedDocumentException e) {
|
||||
// expected here
|
||||
|
@ -334,9 +345,9 @@ public final class TestWorkbookFactory {
|
|||
|
||||
try {
|
||||
wb = WorkbookFactory.create(
|
||||
HSSFTestDataSamples.getSampleFile(xlsx_prot[0]), "wrong"
|
||||
HSSFTestDataSamples.getSampleFile(xlsx_protected[0]), "wrong"
|
||||
);
|
||||
assertCloseDoesNotModifyFile(xlsx_prot[0], wb);
|
||||
assertCloseDoesNotModifyFile(xlsx_protected[0], wb);
|
||||
fail("Shouldn't be able to open with the wrong password");
|
||||
} catch (EncryptedDocumentException e) {
|
||||
// expected here
|
||||
|
@ -387,4 +398,59 @@ public final class TestWorkbookFactory {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See Bugzilla bug #62831 - #WorkbookFactory.create(File) needs
|
||||
* to work for sub-classes of File too, eg JFileChooser
|
||||
*/
|
||||
@Test
|
||||
public void testFileSubclass() throws Exception {
|
||||
File normalXLS = HSSFTestDataSamples.getSampleFile(xls);
|
||||
File normalXLSX = HSSFTestDataSamples.getSampleFile(xlsx);
|
||||
File altXLS = new TestFile(normalXLS.getAbsolutePath());
|
||||
File altXLSX = new TestFile(normalXLSX.getAbsolutePath());
|
||||
assertTrue(altXLS.exists());
|
||||
assertTrue(altXLSX.exists());
|
||||
|
||||
Workbook wb = WorkbookFactory.create(altXLS);
|
||||
assertNotNull(wb);
|
||||
assertTrue(wb instanceof HSSFWorkbook);
|
||||
closeOrRevert(wb);
|
||||
|
||||
wb = WorkbookFactory.create(altXLSX);
|
||||
assertNotNull(wb);
|
||||
assertTrue(wb instanceof XSSFWorkbook);
|
||||
closeOrRevert(wb);
|
||||
}
|
||||
|
||||
private static class TestFile extends File {
|
||||
public TestFile(String file) {
|
||||
super(file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the overloaded file methods which take passwords work properly
|
||||
*/
|
||||
@Test
|
||||
public void testCreateEmpty() throws Exception {
|
||||
Workbook wb = WorkbookFactory.create(false);
|
||||
assertTrue(wb instanceof HSSFWorkbook);
|
||||
closeOrRevert(wb);
|
||||
|
||||
wb = WorkbookFactory.create(true);
|
||||
assertTrue(wb instanceof XSSFWorkbook);
|
||||
closeOrRevert(wb);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidFormatException() {
|
||||
String filename = "OPCCompliance_DerivedPartNameFAIL.docx";
|
||||
try {
|
||||
WorkbookFactory.create(POIDataSamples.getOpenXML4JInstance().openResourceAsStream(filename));
|
||||
fail("Expecting an Exception for this document");
|
||||
} catch (IOException e) {
|
||||
// expected here
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,22 +47,22 @@ public class TestXSLFTextParagraph {
|
|||
DrawTextParagraphProxy(XSLFTextParagraph p) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void breakText(Graphics2D graphics) {
|
||||
super.breakText(graphics);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getWrappingWidth(boolean firstLine, Graphics2D graphics) {
|
||||
return super.getWrappingWidth(firstLine, graphics);
|
||||
}
|
||||
|
||||
|
||||
public List<DrawTextFragment> getLines() {
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testWrappingWidth() throws IOException {
|
||||
XMLSlideShow ppt = new XMLSlideShow();
|
||||
|
@ -78,11 +78,11 @@ public class TestXSLFTextParagraph {
|
|||
|
||||
Rectangle2D anchor = new Rectangle2D.Double(50, 50, 300, 200);
|
||||
sh.setAnchor(anchor);
|
||||
|
||||
|
||||
DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p);
|
||||
|
||||
Double leftInset = sh.getLeftInset();
|
||||
Double rightInset = sh.getRightInset();
|
||||
double leftInset = sh.getLeftInset();
|
||||
double rightInset = sh.getRightInset();
|
||||
assertEquals(7.2, leftInset, 0);
|
||||
assertEquals(7.2, rightInset, 0);
|
||||
|
||||
|
@ -142,13 +142,13 @@ public class TestXSLFTextParagraph {
|
|||
indent = p.getIndent();
|
||||
assertEquals(-72.0, indent, 0);
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset;
|
||||
assertEquals(280.0, expectedWidth, 0); // 300 - 10 - 10
|
||||
assertEquals(280.0, expectedWidth, 0); // 300 - 10 - 10
|
||||
assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is NOT indented
|
||||
// other lines are indented by leftMargin (the value of indent is not used)
|
||||
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
|
||||
assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36
|
||||
assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36
|
||||
assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0);
|
||||
|
||||
|
||||
ppt.close();
|
||||
}
|
||||
|
||||
|
@ -294,13 +294,13 @@ public class TestXSLFTextParagraph {
|
|||
assertEquals(-20.0, p.getBulletFontSize(), 0);
|
||||
|
||||
assertEquals(72.0, p.getDefaultTabSize(), 0);
|
||||
|
||||
|
||||
assertNull(p.getIndent());
|
||||
p.setIndent(72.0);
|
||||
assertEquals(72.0, p.getIndent(), 0);
|
||||
p.setIndent(-1d); // the value of -1.0 resets to the defaults (not any more ...)
|
||||
assertEquals(-1d, p.getIndent(), 0);
|
||||
p.setIndent(null);
|
||||
p.setIndent(null);
|
||||
assertNull(p.getIndent());
|
||||
|
||||
assertEquals(0.0, p.getLeftMargin(), 0);
|
||||
|
|
|
@ -28,13 +28,12 @@ import java.io.InputStream;
|
|||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.TempFile;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
/**
|
||||
* Centralises logic for finding/opening sample files in the test-data/spreadsheet folder.
|
||||
*
|
||||
* Centralises logic for finding/opening sample files in the test-data/spreadsheet folder.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class XSSFTestDataSamples {
|
||||
|
@ -63,7 +62,7 @@ public class XSSFTestDataSamples {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write out workbook <code>wb</code> to {@link #TEST_OUTPUT_DIR}/testName.xlsx
|
||||
* (or create a temporary file if <code>TEST_OUTPUT_DIR</code> is not defined).
|
||||
|
@ -78,11 +77,13 @@ public class XSSFTestDataSamples {
|
|||
writeOut(wb, file);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
private static <R extends Workbook> void writeOut(R wb, File file) throws IOException {
|
||||
IOUtils.write(wb, new FileOutputStream(file));
|
||||
try (FileOutputStream out = new FileOutputStream(file)) {
|
||||
wb.write(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Anticipates the location of where a workbook will be written to
|
||||
// Note that if TEST_OUTPUT_DIR is not set, this will create temporary files
|
||||
// with unique names. Subsequent calls with the same argument may return a different file.
|
||||
|
@ -107,7 +108,7 @@ public class XSSFTestDataSamples {
|
|||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write out workbook <code>wb</code> to a memory buffer
|
||||
*
|
||||
|
@ -120,18 +121,18 @@ public class XSSFTestDataSamples {
|
|||
wb.write(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write out the workbook then closes the workbook.
|
||||
* Write out the workbook then closes the workbook.
|
||||
* This should be used when there is insufficient memory to have
|
||||
* both workbooks open.
|
||||
*
|
||||
*
|
||||
* Make sure there are no references to any objects in the workbook
|
||||
* so that garbage collection may free the workbook.
|
||||
*
|
||||
*
|
||||
* After calling this method, null the reference to <code>wb</code>,
|
||||
* then call {@link #readBack(File)} or {@link #readBackAndDelete(File)} to re-read the file.
|
||||
*
|
||||
*
|
||||
* Alternatively, use {@link #writeOutAndClose(Workbook)} to use a ByteArrayOutputStream/ByteArrayInputStream
|
||||
* to avoid creating a temporary file. However, this may complicate the calling
|
||||
* code to avoid having the workbook, BAOS, and BAIS open at the same time.
|
||||
|
@ -152,8 +153,8 @@ public class XSSFTestDataSamples {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Write out workbook <code>wb</code> to a memory buffer,
|
||||
* then close the workbook
|
||||
|
@ -173,7 +174,7 @@ public class XSSFTestDataSamples {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read back a workbook that was written out to a file with
|
||||
* {@link #writeOut(Workbook, String))} or {@link #writeOutAndClose(Workbook, String)}.
|
||||
|
@ -186,11 +187,11 @@ public class XSSFTestDataSamples {
|
|||
*/
|
||||
public static XSSFWorkbook readBackAndDelete(File file) throws IOException {
|
||||
XSSFWorkbook wb = readBack(file);
|
||||
// do not delete the file if there's an error--might be helpful for debugging
|
||||
// do not delete the file if there's an error--might be helpful for debugging
|
||||
file.delete();
|
||||
return wb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read back a workbook that was written out to a file with
|
||||
* {@link #writeOut(Workbook, String)} or {@link #writeOutAndClose(Workbook, String)}.
|
||||
|
@ -208,12 +209,12 @@ public class XSSFTestDataSamples {
|
|||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read back a workbook that was written out to a memory buffer with
|
||||
* {@link #writeOut(Workbook)} or {@link #writeOutAndClose(Workbook)}.
|
||||
*
|
||||
* @param file the workbook file to read
|
||||
* @param out the output stream to read back from
|
||||
* @return the read back workbook
|
||||
* @throws IOException
|
||||
*/
|
||||
|
@ -227,15 +228,15 @@ public class XSSFTestDataSamples {
|
|||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write out and read back using a memory buffer to avoid disk I/O.
|
||||
* If there is not enough memory to have two workbooks open at the same time,
|
||||
* consider using:
|
||||
*
|
||||
*
|
||||
* Workbook wb = new XSSFWorkbook();
|
||||
* String testName = "example";
|
||||
*
|
||||
*
|
||||
* <code>
|
||||
* File file = writeOutAndClose(wb, testName);
|
||||
* // clear all references that would prevent the workbook from getting garbage collected
|
||||
|
@ -257,7 +258,7 @@ public class XSSFTestDataSamples {
|
|||
R r = (R) result;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write out, close, and read back the workbook using a memory buffer to avoid disk I/O.
|
||||
*
|
||||
|
@ -274,18 +275,18 @@ public class XSSFTestDataSamples {
|
|||
@SuppressWarnings("unchecked")
|
||||
R r = (R) result;
|
||||
return r;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes the Workbook either into a file or into a byte array, depending on presence of
|
||||
* Writes the Workbook either into a file or into a byte array, depending on presence of
|
||||
* the system property {@value #TEST_OUTPUT_DIR}, and reads it in a new instance of the Workbook back.
|
||||
* If TEST_OUTPUT_DIR is set, the file will NOT be deleted at the end of this function.
|
||||
* @param wb workbook to write
|
||||
* @param testName file name to be used if writing into a file. The old file with the same name will be overridden.
|
||||
* @return new instance read from the stream written by the wb parameter.
|
||||
*/
|
||||
|
||||
|
||||
public static <R extends Workbook> R writeOutAndReadBack(R wb, String testName) {
|
||||
if (System.getProperty(TEST_OUTPUT_DIR) == null) {
|
||||
return writeOutAndReadBack(wb);
|
||||
|
|
|
@ -26,6 +26,10 @@ import static org.junit.Assert.assertTrue;
|
|||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Tests for {@link XSSFBEventBasedExcelExtractor}
|
||||
*/
|
||||
|
@ -110,4 +114,23 @@ public class TestXSSFBEventBasedExcelExtractor {
|
|||
"This is an example spreadsheet created with Microsoft Excel 2007 Beta 2.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test62815() throws Exception {
|
||||
//test file based on http://oss.sheetjs.com/test_files/RkNumber.xlsb
|
||||
XSSFEventBasedExcelExtractor extractor = getExtractor("62815.xlsb");
|
||||
extractor.setIncludeCellComments(true);
|
||||
String[] rows = extractor.getText().split("[\r\n]+");
|
||||
assertEquals(283, rows.length);
|
||||
BufferedReader reader = Files.newBufferedReader(XSSFTestDataSamples.getSampleFile("62815.xlsb.txt").toPath(),
|
||||
StandardCharsets.UTF_8);
|
||||
String line = reader.readLine();
|
||||
for (int i = 0; i < rows.length; i++) {
|
||||
assertEquals(line, rows[i]);
|
||||
line = reader.readLine();
|
||||
while (line != null && line.startsWith("#")) {
|
||||
line = reader.readLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ import java.util.Arrays;
|
|||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.POITestCase;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackageAccess;
|
||||
import org.apache.poi.ss.usermodel.BaseTestXWorkbook;
|
||||
|
@ -55,7 +54,6 @@ import org.apache.poi.xssf.XSSFTestDataSamples;
|
|||
import org.apache.poi.xssf.model.SharedStringsTable;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.After;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -103,9 +101,9 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook {
|
|||
* changes.
|
||||
*/
|
||||
@Override
|
||||
@Ignore("SXSSF doesn't update formulas on sheet name changes, as most cells probably aren't in memory at the time")
|
||||
@Test
|
||||
public void setSheetName() {
|
||||
Assume.assumeTrue("SXSSF doesn't update formulas on sheet name changes, as most cells probably aren't in memory at the time", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -374,7 +372,7 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook {
|
|||
@Test
|
||||
public void bug53515a() throws Exception {
|
||||
File out = new File("Test.xlsx");
|
||||
out.delete();
|
||||
assertTrue(!out.exists() || out.delete());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
final SXSSFWorkbook wb;
|
||||
if (out.exists()) {
|
||||
|
@ -402,7 +400,8 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook {
|
|||
}
|
||||
wb.close();
|
||||
}
|
||||
out.delete();
|
||||
assertTrue(out.exists());
|
||||
assertTrue(out.delete());
|
||||
}
|
||||
|
||||
private static void populateWorkbook(Workbook wb) {
|
||||
|
@ -500,33 +499,37 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook {
|
|||
@Test
|
||||
@Ignore
|
||||
public void createFromReadOnlyWorkbook() throws Exception {
|
||||
File input = XSSFTestDataSamples.getSampleFile("sample.xlsx");
|
||||
OPCPackage pkg = OPCPackage.open(input, PackageAccess.READ);
|
||||
XSSFWorkbook xssf = new XSSFWorkbook(pkg);
|
||||
SXSSFWorkbook wb = new SXSSFWorkbook(xssf, 2);
|
||||
|
||||
String sheetName = "Test SXSSF";
|
||||
Sheet s = wb.createSheet(sheetName);
|
||||
for (int i=0; i<10; i++) {
|
||||
Row r = s.createRow(i);
|
||||
r.createCell(0).setCellValue(true);
|
||||
r.createCell(1).setCellValue(2.4);
|
||||
r.createCell(2).setCellValue("Test Row " + i);
|
||||
File input = XSSFTestDataSamples.getSampleFile("sample.xlsx");
|
||||
|
||||
try (OPCPackage pkg = OPCPackage.open(input, PackageAccess.READ)) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try (XSSFWorkbook xssf = new XSSFWorkbook(pkg)) {
|
||||
try (SXSSFWorkbook wb = new SXSSFWorkbook(xssf, 2)) {
|
||||
Sheet s = wb.createSheet(sheetName);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Row r = s.createRow(i);
|
||||
r.createCell(0).setCellValue(true);
|
||||
r.createCell(1).setCellValue(2.4);
|
||||
r.createCell(2).setCellValue("Test Row " + i);
|
||||
}
|
||||
assertEquals(10, s.getLastRowNum());
|
||||
|
||||
wb.write(bos);
|
||||
wb.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
try (XSSFWorkbook xssf = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||
Sheet s = xssf.getSheet(sheetName);
|
||||
assertEquals(10, s.getLastRowNum());
|
||||
assertTrue(s.getRow(0).getCell(0).getBooleanCellValue());
|
||||
assertEquals("Test Row 9", s.getRow(9).getCell(2).getStringCellValue());
|
||||
}
|
||||
}
|
||||
assertEquals(10, s.getLastRowNum());
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
wb.write(bos);
|
||||
wb.dispose();
|
||||
wb.close();
|
||||
|
||||
xssf = new XSSFWorkbook(new ByteArrayInputStream(bos.toByteArray()));
|
||||
s = xssf.getSheet(sheetName);
|
||||
assertEquals(10, s.getLastRowNum());
|
||||
assertTrue(s.getRow(0).getCell(0).getBooleanCellValue());
|
||||
assertEquals("Test Row 9", s.getRow(9).getCell(2).getStringCellValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test56557() throws IOException {
|
||||
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56557.xlsx");
|
||||
|
|
|
@ -47,15 +47,15 @@ import java.util.TreeMap;
|
|||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.ooxml.POIXMLDocumentPart;
|
||||
import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart;
|
||||
import org.apache.poi.ooxml.POIXMLException;
|
||||
import org.apache.poi.ooxml.POIXMLProperties;
|
||||
import org.apache.poi.common.usermodel.HyperlinkType;
|
||||
import org.apache.poi.hssf.HSSFITestDataProvider;
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ooxml.POIXMLDocumentPart;
|
||||
import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart;
|
||||
import org.apache.poi.ooxml.POIXMLException;
|
||||
import org.apache.poi.ooxml.POIXMLProperties;
|
||||
import org.apache.poi.ooxml.util.DocumentHelper;
|
||||
import org.apache.poi.ooxml.util.SAXHelper;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
|
@ -82,7 +82,31 @@ import org.apache.poi.ss.formula.eval.ErrorEval;
|
|||
import org.apache.poi.ss.formula.eval.NumberEval;
|
||||
import org.apache.poi.ss.formula.functions.Function;
|
||||
import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||
import org.apache.poi.ss.usermodel.DataFormat;
|
||||
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.FormulaError;
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.Name;
|
||||
import org.apache.poi.ss.usermodel.PrintSetup;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.apache.poi.ss.util.AreaReference;
|
||||
import org.apache.poi.ss.util.CellAddress;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
|
@ -2261,7 +2285,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
* problems when deleting columns, conditionally to stop recursion
|
||||
*/
|
||||
private static final String FORMULA1 =
|
||||
"IF( INDIRECT( ADDRESS( ROW(), COLUMN()-1 ) ) = 0, 0,"
|
||||
"IF( INDIRECT( ADDRESS( ROW(), COLUMN()-1 ) ) = 0, 0, "
|
||||
+ "INDIRECT( ADDRESS( ROW(), COLUMN()-1 ) ) ) + 2";
|
||||
|
||||
/**
|
||||
|
@ -2269,7 +2293,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
* problems when deleting rows, conditionally to stop recursion
|
||||
*/
|
||||
private static final String FORMULA2 =
|
||||
"IF( INDIRECT( ADDRESS( ROW()-1, COLUMN() ) ) = 0, 0,"
|
||||
"IF( INDIRECT( ADDRESS( ROW()-1, COLUMN() ) ) = 0, 0, "
|
||||
+ "INDIRECT( ADDRESS( ROW()-1, COLUMN() ) ) ) + 2";
|
||||
|
||||
/**
|
||||
|
@ -2847,7 +2871,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
@Test
|
||||
public void test57236() throws IOException {
|
||||
// Having very small numbers leads to different formatting, Excel uses the scientific notation, but POI leads to "0"
|
||||
|
||||
|
||||
/*
|
||||
DecimalFormat format = new DecimalFormat("#.##########", new DecimalFormatSymbols(Locale.getDefault()));
|
||||
double d = 3.0E-104;
|
||||
|
@ -2969,13 +2993,21 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
cell.setCellStyle(style);
|
||||
|
||||
// Everything is fine at this point, cell is red
|
||||
XSSFColor actual = cell.getCellStyle().getFillBackgroundColorColor();
|
||||
assertNull(actual);
|
||||
actual = cell.getCellStyle().getFillForegroundColorColor();
|
||||
assertNotNull(actual);
|
||||
assertEquals(color.getARGBHex(), actual.getARGBHex());
|
||||
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(CellUtil.BORDER_BOTTOM, BorderStyle.THIN);
|
||||
CellUtil.setCellStyleProperties(cell, properties);
|
||||
|
||||
// Now the cell is all black
|
||||
XSSFColor actual = cell.getCellStyle().getFillBackgroundColorColor();
|
||||
actual = cell.getCellStyle().getFillBackgroundColorColor();
|
||||
assertNotNull(actual);
|
||||
assertNull(actual.getARGBHex());
|
||||
actual = cell.getCellStyle().getFillForegroundColorColor();
|
||||
assertNotNull(actual);
|
||||
assertEquals(color.getARGBHex(), actual.getARGBHex());
|
||||
|
||||
|
@ -3290,7 +3322,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Auto column sizing failed when there were loads of fonts with
|
||||
* errors like ArrayIndexOutOfBoundsException: -32765
|
||||
|
@ -3300,7 +3332,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
XSSFSheet sheet = wb.createSheet();
|
||||
XSSFRow row = sheet.createRow(0);
|
||||
|
||||
|
||||
// Create lots of fonts
|
||||
XSSFDataFormat formats = wb.createDataFormat();
|
||||
XSSFFont[] fonts = new XSSFFont[50000];
|
||||
|
@ -3309,23 +3341,23 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
font.setFontHeight(i);
|
||||
fonts[i] = font;
|
||||
}
|
||||
|
||||
|
||||
// Create a moderate number of columns, which use
|
||||
// fonts from the start and end of the font list
|
||||
final int numCols = 125;
|
||||
for (int i=0; i<numCols; i++) {
|
||||
XSSFCellStyle cs = wb.createCellStyle();
|
||||
cs.setDataFormat(formats.getFormat("'Test "+i+"' #,###"));
|
||||
|
||||
|
||||
XSSFFont font = fonts[i];
|
||||
if (i%2==1) { font = fonts[fonts.length-i]; }
|
||||
cs.setFont(font);
|
||||
|
||||
|
||||
XSSFCell c = row.createCell(i);
|
||||
c.setCellValue(i);
|
||||
c.setCellStyle(cs);
|
||||
}
|
||||
|
||||
|
||||
// Do the auto-size
|
||||
for (int i=0; i<numCols; i++) {
|
||||
sheet.autoSizeColumn(i);
|
||||
|
|
|
@ -33,20 +33,20 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
|
|||
* Test asserts the POI produces <cols> element that could be read and properly interpreted by the MS Excel.
|
||||
* For specification of the "cols" element see the chapter 3.3.1.16 of the "Office Open XML Part 4 - Markup Language Reference.pdf".
|
||||
* The specification can be downloaded at http://www.ecma-international.org/publications/files/ECMA-ST/Office%20Open%20XML%201st%20edition%20Part%204%20(PDF).zip.
|
||||
*
|
||||
*
|
||||
* <p><em>
|
||||
* The test saves xlsx file on a disk if the system property is set:
|
||||
* -Dpoi.test.xssf.output.dir=${workspace_loc}/poi/build/xssf-output
|
||||
* </em>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TestXSSFColGrouping {
|
||||
|
||||
|
||||
private static final POILogger logger = POILogFactory.getLogger(TestXSSFColGrouping.class);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tests that POI doesn't produce "col" elements without "width" attribute.
|
||||
* Tests that POI doesn't produce "col" elements without "width" attribute.
|
||||
* POI-52186
|
||||
*/
|
||||
@Test
|
||||
|
@ -56,25 +56,25 @@ public class TestXSSFColGrouping {
|
|||
|
||||
sheet.setColumnWidth(4, 5000);
|
||||
sheet.setColumnWidth(5, 5000);
|
||||
|
||||
|
||||
sheet.groupColumn((short) 4, (short) 7);
|
||||
sheet.groupColumn((short) 9, (short) 12);
|
||||
|
||||
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testNoColsWithoutWidthWhenGrouping");
|
||||
sheet = wb2.getSheet("test");
|
||||
|
||||
|
||||
CTCols cols = sheet.getCTWorksheet().getColsArray(0);
|
||||
logger.log(POILogger.DEBUG, "test52186/cols:" + cols);
|
||||
for (CTCol col : cols.getColArray()) {
|
||||
assertTrue("Col width attribute is unset: " + col, col.isSetWidth());
|
||||
}
|
||||
|
||||
|
||||
wb2.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that POI doesn't produce "col" elements without "width" attribute.
|
||||
* Tests that POI doesn't produce "col" elements without "width" attribute.
|
||||
* POI-52186
|
||||
*/
|
||||
@Test
|
||||
|
@ -84,17 +84,17 @@ public class TestXSSFColGrouping {
|
|||
|
||||
sheet.setColumnWidth(4, 5000);
|
||||
sheet.setColumnWidth(5, 5000);
|
||||
|
||||
|
||||
sheet.groupColumn((short) 4, (short) 5);
|
||||
|
||||
|
||||
sheet.setColumnGroupCollapsed(4, true);
|
||||
|
||||
|
||||
CTCols cols = sheet.getCTWorksheet().getColsArray(0);
|
||||
logger.log(POILogger.DEBUG, "test52186_2/cols:" + cols);
|
||||
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testNoColsWithoutWidthWhenGroupingAndCollapsing");
|
||||
sheet = wb2.getSheet("test");
|
||||
|
||||
|
||||
for (int i = 4; i <= 5; i++) {
|
||||
assertEquals("Unexpected width of column "+ i, 5000, sheet.getColumnWidth(i));
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ public class TestXSSFColGrouping {
|
|||
wb2.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test the cols element is correct in case of NumericRanges.OVERLAPS_2_WRAPS
|
||||
*/
|
||||
|
@ -122,10 +122,10 @@ public class TestXSSFColGrouping {
|
|||
col.setCustomWidth(true);
|
||||
|
||||
sheet.groupColumn((short) 2, (short) 3);
|
||||
|
||||
|
||||
sheet.getCTWorksheet().getColsArray(0);
|
||||
logger.log(POILogger.DEBUG, "testMergingOverlappingCols_OVERLAPS_2_WRAPS/cols:" + cols);
|
||||
|
||||
|
||||
assertEquals(0, cols.getColArray(0).getOutlineLevel());
|
||||
assertEquals(2, cols.getColArray(0).getMin()); // 1 based
|
||||
assertEquals(2, cols.getColArray(0).getMax()); // 1 based
|
||||
|
@ -133,23 +133,23 @@ public class TestXSSFColGrouping {
|
|||
|
||||
assertEquals(1, cols.getColArray(1).getOutlineLevel());
|
||||
assertEquals(3, cols.getColArray(1).getMin()); // 1 based
|
||||
assertEquals(4, cols.getColArray(1).getMax()); // 1 based
|
||||
assertEquals(4, cols.getColArray(1).getMax()); // 1 based
|
||||
assertEquals(true, cols.getColArray(1).getCustomWidth());
|
||||
|
||||
assertEquals(0, cols.getColArray(2).getOutlineLevel());
|
||||
assertEquals(5, cols.getColArray(2).getMin()); // 1 based
|
||||
assertEquals(5, cols.getColArray(2).getMax()); // 1 based
|
||||
assertEquals(true, cols.getColArray(2).getCustomWidth());
|
||||
|
||||
|
||||
assertEquals(3, cols.sizeOfColArray());
|
||||
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testMergingOverlappingCols_OVERLAPS_2_WRAPS");
|
||||
sheet = wb2.getSheet("test");
|
||||
|
||||
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
assertEquals("Unexpected width of column "+ i, 20 * 256, sheet.getColumnWidth(i));
|
||||
}
|
||||
|
||||
|
||||
wb2.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
@ -170,10 +170,10 @@ public class TestXSSFColGrouping {
|
|||
col.setCustomWidth(true);
|
||||
|
||||
sheet.groupColumn((short) 1, (short) 5);
|
||||
|
||||
|
||||
cols = sheet.getCTWorksheet().getColsArray(0);
|
||||
logger.log(POILogger.DEBUG, "testMergingOverlappingCols_OVERLAPS_1_WRAPS/cols:" + cols);
|
||||
|
||||
|
||||
assertEquals(1, cols.getColArray(0).getOutlineLevel());
|
||||
assertEquals(2, cols.getColArray(0).getMin()); // 1 based
|
||||
assertEquals(2, cols.getColArray(0).getMax()); // 1 based
|
||||
|
@ -181,23 +181,23 @@ public class TestXSSFColGrouping {
|
|||
|
||||
assertEquals(1, cols.getColArray(1).getOutlineLevel());
|
||||
assertEquals(3, cols.getColArray(1).getMin()); // 1 based
|
||||
assertEquals(5, cols.getColArray(1).getMax()); // 1 based
|
||||
assertEquals(5, cols.getColArray(1).getMax()); // 1 based
|
||||
assertEquals(true, cols.getColArray(1).getCustomWidth());
|
||||
|
||||
assertEquals(1, cols.getColArray(2).getOutlineLevel());
|
||||
assertEquals(6, cols.getColArray(2).getMin()); // 1 based
|
||||
assertEquals(6, cols.getColArray(2).getMax()); // 1 based
|
||||
assertEquals(false, cols.getColArray(2).getCustomWidth());
|
||||
|
||||
|
||||
assertEquals(3, cols.sizeOfColArray());
|
||||
|
||||
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testMergingOverlappingCols_OVERLAPS_1_WRAPS");
|
||||
sheet = wb2.getSheet("test");
|
||||
|
||||
|
||||
for (int i = 2; i <= 4; i++) {
|
||||
assertEquals("Unexpected width of column "+ i, 20 * 256, sheet.getColumnWidth(i));
|
||||
}
|
||||
|
||||
|
||||
wb2.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ public class TestXSSFColGrouping {
|
|||
col.setCustomWidth(true);
|
||||
|
||||
sheet.groupColumn((short) 3, (short) 5);
|
||||
|
||||
|
||||
cols = sheet.getCTWorksheet().getColsArray(0);
|
||||
logger.log(POILogger.DEBUG, "testMergingOverlappingCols_OVERLAPS_1_MINOR/cols:" + cols);
|
||||
|
||||
|
@ -229,24 +229,24 @@ public class TestXSSFColGrouping {
|
|||
|
||||
assertEquals(1, cols.getColArray(1).getOutlineLevel());
|
||||
assertEquals(4, cols.getColArray(1).getMin()); // 1 based
|
||||
assertEquals(5, cols.getColArray(1).getMax()); // 1 based
|
||||
assertEquals(5, cols.getColArray(1).getMax()); // 1 based
|
||||
assertEquals(true, cols.getColArray(1).getCustomWidth());
|
||||
|
||||
assertEquals(1, cols.getColArray(2).getOutlineLevel());
|
||||
assertEquals(6, cols.getColArray(2).getMin()); // 1 based
|
||||
assertEquals(6, cols.getColArray(2).getMax()); // 1 based
|
||||
assertEquals(false, cols.getColArray(2).getCustomWidth());
|
||||
|
||||
|
||||
assertEquals(3, cols.sizeOfColArray());
|
||||
|
||||
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testMergingOverlappingCols_OVERLAPS_1_MINOR");
|
||||
sheet = wb2.getSheet("test");
|
||||
|
||||
|
||||
for (int i = 2; i <= 4; i++) {
|
||||
assertEquals("Unexpected width of column "+ i, 20 * 256, sheet.getColumnWidth(i));
|
||||
assertEquals("Unexpected width of column "+ i, 20 * 256L, sheet.getColumnWidth(i));
|
||||
}
|
||||
assertEquals("Unexpected width of column "+ 5, sheet.getDefaultColumnWidth() * 256, sheet.getColumnWidth(5));
|
||||
|
||||
assertEquals("Unexpected width of column "+ 5, sheet.getDefaultColumnWidth() * 256L, sheet.getColumnWidth(5));
|
||||
|
||||
wb2.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ public class TestXSSFColGrouping {
|
|||
col.setCustomWidth(true);
|
||||
|
||||
sheet.groupColumn((short) 1, (short) 3);
|
||||
|
||||
|
||||
cols = sheet.getCTWorksheet().getColsArray(0);
|
||||
logger.log(POILogger.DEBUG, "testMergingOverlappingCols_OVERLAPS_2_MINOR/cols:" + cols);
|
||||
|
||||
|
@ -278,24 +278,24 @@ public class TestXSSFColGrouping {
|
|||
|
||||
assertEquals(1, cols.getColArray(1).getOutlineLevel());
|
||||
assertEquals(3, cols.getColArray(1).getMin()); // 1 based
|
||||
assertEquals(4, cols.getColArray(1).getMax()); // 1 based
|
||||
assertEquals(4, cols.getColArray(1).getMax()); // 1 based
|
||||
assertEquals(true, cols.getColArray(1).getCustomWidth());
|
||||
|
||||
assertEquals(0, cols.getColArray(2).getOutlineLevel());
|
||||
assertEquals(5, cols.getColArray(2).getMin()); // 1 based
|
||||
assertEquals(5, cols.getColArray(2).getMax()); // 1 based
|
||||
assertEquals(true, cols.getColArray(2).getCustomWidth());
|
||||
|
||||
|
||||
assertEquals(3, cols.sizeOfColArray());
|
||||
|
||||
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1, "testMergingOverlappingCols_OVERLAPS_2_MINOR");
|
||||
sheet = wb2.getSheet("test");
|
||||
|
||||
|
||||
for (int i = 2; i <= 4; i++) {
|
||||
assertEquals("Unexpected width of column "+ i, 20 * 256, sheet.getColumnWidth(i));
|
||||
assertEquals("Unexpected width of column "+ i, 20 * 256L, sheet.getColumnWidth(i));
|
||||
}
|
||||
assertEquals("Unexpected width of column "+ 1, sheet.getDefaultColumnWidth() * 256, sheet.getColumnWidth(1));
|
||||
|
||||
assertEquals("Unexpected width of column "+ 1, sheet.getDefaultColumnWidth() * 256L, sheet.getColumnWidth(1));
|
||||
|
||||
wb2.close();
|
||||
wb1.close();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.math.BigDecimal;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.poi.ss.formula.DataValidationEvaluator;
|
||||
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
import org.apache.poi.ss.usermodel.BaseTestDataValidation;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
|
@ -57,16 +56,16 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
/**
|
||||
* For each validation type, there are two cells with the same validation. This tests
|
||||
* application of a single validation definition to multiple cells.
|
||||
*
|
||||
*
|
||||
* For list ( 3 validations for explicit and 3 for formula )
|
||||
* - one validation that allows blank.
|
||||
* - one validation that allows blank.
|
||||
* - one that does not allow blank.
|
||||
* - one that does not show the drop down arrow.
|
||||
* = 2
|
||||
*
|
||||
*
|
||||
* For number validations ( integer/decimal and text length ) with 8 different types of operators.
|
||||
* = 50
|
||||
*
|
||||
* = 50
|
||||
*
|
||||
* = 52 ( Total )
|
||||
*/
|
||||
assertEquals(52,dataValidations.size());
|
||||
|
@ -140,7 +139,7 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
cell_10.setCellValue(XSSFDataValidation.operatorTypeMappings.get(operatorType).toString());
|
||||
Cell cell_11 = row1.createCell(1);
|
||||
Cell cell_21 = row1.createCell(2);
|
||||
Cell cell_22 = i==0 && j < 2 ? row2.createCell(2) : null;
|
||||
Cell cell_22 = i==0 && j < 2 ? (row2 == null ? null : row2.createCell(2)) : null;
|
||||
|
||||
Cell cell_13 = row1.createCell(3);
|
||||
|
||||
|
@ -170,7 +169,9 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
assertEquals(++lastKnownNumValidations, ((XSSFSheet) sheet).getDataValidations().size());
|
||||
|
||||
cellRangeAddressList = new CellRangeAddressList();
|
||||
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex()));
|
||||
if (cell_22 != null) {
|
||||
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex()));
|
||||
}
|
||||
validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
|
||||
setOtherValidationParameters( validation);
|
||||
sheet.addValidationData(validation);
|
||||
|
@ -178,7 +179,9 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
} else if(i==0 && j==1 ){
|
||||
cellRangeAddressList = new CellRangeAddressList();
|
||||
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_21.getRowIndex(), cell_21.getRowIndex(), cell_21.getColumnIndex(), cell_21.getColumnIndex()));
|
||||
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex()));
|
||||
if (cell_22 != null) {
|
||||
cellRangeAddressList.addCellRangeAddress(new CellRangeAddress(cell_22.getRowIndex(), cell_22.getRowIndex(), cell_22.getColumnIndex(), cell_22.getColumnIndex()));
|
||||
}
|
||||
validation = dataValidationHelper.createValidation(constraint, cellRangeAddressList);
|
||||
setOtherValidationParameters( validation);
|
||||
sheet.addValidationData(validation);
|
||||
|
@ -262,16 +265,16 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
XSSFSheet sheet = wb.createSheet();
|
||||
List<XSSFDataValidation> lst = sheet.getDataValidations(); //<-- works
|
||||
assertEquals(0, lst.size());
|
||||
|
||||
|
||||
//create the cell that will have the validation applied
|
||||
sheet.createRow(0).createCell(0);
|
||||
|
||||
|
||||
DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
|
||||
DataValidationConstraint constraint = dataValidationHelper.createCustomConstraint("SUM($A$1:$A$1) <= 3500");
|
||||
CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
|
||||
DataValidation validation = dataValidationHelper.createValidation(constraint, addressList);
|
||||
sheet.addValidationData(validation);
|
||||
|
||||
|
||||
// this line caused XmlValueOutOfRangeException , see Bugzilla 3965
|
||||
lst = sheet.getDataValidations();
|
||||
assertEquals(1, lst.size());
|
||||
|
@ -282,10 +285,10 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
public void testDefaultErrorStyle() throws IOException {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
XSSFSheet sheet = wb.createSheet();
|
||||
|
||||
|
||||
final XSSFDataValidation validation = createValidation(sheet);
|
||||
sheet.addValidationData(validation);
|
||||
|
||||
|
||||
final List<XSSFDataValidation> dataValidations = sheet.getDataValidations();
|
||||
assertEquals(DataValidation.ErrorStyle.STOP, dataValidations.get(0).getErrorStyle());
|
||||
}
|
||||
|
@ -295,22 +298,22 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
public void testSetErrorStyles() throws IOException {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
XSSFSheet sheet = wb.createSheet();
|
||||
|
||||
|
||||
XSSFDataValidation validation = createValidation(sheet);
|
||||
sheet.addValidationData(validation);
|
||||
|
||||
|
||||
// extract generated validation from sheet
|
||||
List<XSSFDataValidation> dataValidations = sheet.getDataValidations();
|
||||
validation = dataValidations.get(0);
|
||||
|
||||
|
||||
// test INFO
|
||||
validation.setErrorStyle(DataValidation.ErrorStyle.INFO);
|
||||
assertEquals(DataValidation.ErrorStyle.INFO, dataValidations.get(0).getErrorStyle());
|
||||
|
||||
|
||||
// test WARNING
|
||||
validation.setErrorStyle(DataValidation.ErrorStyle.WARNING);
|
||||
assertEquals(DataValidation.ErrorStyle.WARNING, dataValidations.get(0).getErrorStyle());
|
||||
|
||||
|
||||
// test STOP
|
||||
validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
|
||||
assertEquals(DataValidation.ErrorStyle.STOP, dataValidations.get(0).getErrorStyle());
|
||||
|
@ -321,10 +324,10 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
public void testDefaultAllowBlank() throws IOException {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
XSSFSheet sheet = wb.createSheet();
|
||||
|
||||
|
||||
final XSSFDataValidation validation = createValidation(sheet);
|
||||
sheet.addValidationData(validation);
|
||||
|
||||
|
||||
final List<XSSFDataValidation> dataValidations = sheet.getDataValidations();
|
||||
assertEquals(true, dataValidations.get(0).getCtDdataValidation().getAllowBlank());
|
||||
}
|
||||
|
@ -334,12 +337,12 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
public void testSetAllowBlankToFalse() throws IOException {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
XSSFSheet sheet = wb.createSheet();
|
||||
|
||||
|
||||
final XSSFDataValidation validation = createValidation(sheet);
|
||||
validation.getCtDdataValidation().setAllowBlank(false);
|
||||
|
||||
|
||||
sheet.addValidationData(validation);
|
||||
|
||||
|
||||
final List<XSSFDataValidation> dataValidations = sheet.getDataValidations();
|
||||
assertEquals(false, dataValidations.get(0).getCtDdataValidation().getAllowBlank());
|
||||
}
|
||||
|
@ -349,12 +352,12 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
public void testSetAllowBlankToTrue() throws IOException {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
XSSFSheet sheet = wb.createSheet();
|
||||
|
||||
|
||||
final XSSFDataValidation validation = createValidation(sheet);
|
||||
validation.getCtDdataValidation().setAllowBlank(true);
|
||||
|
||||
|
||||
sheet.addValidationData(validation);
|
||||
|
||||
|
||||
final List<XSSFDataValidation> dataValidations = sheet.getDataValidations();
|
||||
assertEquals(true, dataValidations.get(0).getCtDdataValidation().getAllowBlank());
|
||||
}
|
||||
|
@ -370,7 +373,7 @@ public class TestXSSFDataValidation extends BaseTestDataValidation {
|
|||
DataValidationConstraint constraint = dataValidationHelper.createCustomConstraint("true");
|
||||
return (XSSFDataValidation) dataValidationHelper.createValidation(constraint, new CellRangeAddressList(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTableBasedValidationList() throws IOException {
|
||||
try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("dataValidationTableRange.xlsx")) {
|
||||
|
|
|
@ -17,14 +17,24 @@
|
|||
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.usermodel.BaseTestFormulaEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.XSSFITestDataProvider;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
|
@ -437,6 +447,10 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator {
|
|||
assertEquals("D 0,068", evaluator.evaluate(wb.getSheetAt(0).getRow(1).getCell(1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* see bug 62275
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testBug62275() throws IOException {
|
||||
try (Workbook wb = new XSSFWorkbook()) {
|
||||
|
@ -451,4 +465,29 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator {
|
|||
eval.evaluate(cell);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* see bug 62834, handle when a shared formula range doesn't contain only formula cells
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testBug62834() throws IOException {
|
||||
try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("62834.xlsx")) {
|
||||
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
|
||||
|
||||
Cell a2 = wb.getSheetAt(0).getRow(1).getCell(0);
|
||||
Cell value = evaluator.evaluateInCell(a2);
|
||||
assertEquals("wrong value A2", "a value", value.getStringCellValue());
|
||||
|
||||
// evaluator.clearAllCachedResultValues();
|
||||
|
||||
Cell a3 = wb.getSheetAt(0).getRow(2).getCell(0);
|
||||
value = evaluator.evaluateInCell(a3);
|
||||
assertEquals("wrong value A3", "a value", value.getStringCellValue());
|
||||
|
||||
Cell a5 = wb.getSheetAt(0).getRow(4).getCell(0);
|
||||
value = evaluator.evaluateInCell(a5);
|
||||
assertEquals("wrong value A5", "another value", value.getStringCellValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.poi.ooxml.POIXMLException;
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.ooxml.POIXMLException;
|
||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.ss.usermodel.AutoFilter;
|
||||
|
@ -158,7 +158,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals("", ftr.getLeft());
|
||||
assertEquals("", ftr.getCenter());
|
||||
assertEquals("", ftr.getRight());
|
||||
|
||||
|
||||
wb2.close();
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
// Defaults are odd
|
||||
assertEquals("odd footer left", sheet.getFooter().getLeft());
|
||||
assertEquals("odd header center", sheet.getHeader().getCenter());
|
||||
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
sheet.createSplitPane(4, 8, 12, 12, 1);
|
||||
assertEquals(8.0, ctWorksheet.getSheetViews().getSheetViewArray(0).getPane().getYSplit(), 0.0);
|
||||
assertEquals(STPane.BOTTOM_RIGHT, ctWorksheet.getSheetViews().getSheetViewArray(0).getPane().getActivePane());
|
||||
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
|
@ -374,7 +374,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
colArray = cols.getColArray();
|
||||
assertEquals(4, colArray.length);
|
||||
assertEquals(2, sheet.getCTWorksheet().getSheetFormatPr().getOutlineLevelCol());
|
||||
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
|
@ -411,7 +411,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals(3, sheet.getPhysicalNumberOfRows());
|
||||
|
||||
assertEquals(1, sheet.getCTWorksheet().getSheetFormatPr().getOutlineLevelRow());
|
||||
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
|
@ -553,10 +553,10 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
checkColumnGroup(cols.getColArray(3), 10, 11); // false, true
|
||||
checkColumnGroup(cols.getColArray(4), 12, 12, false, false);
|
||||
checkColumnGroup(cols.getColArray(5), 13, 13, false, false);
|
||||
|
||||
|
||||
wb2.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verify that column groups were created correctly after Sheet.groupColumn
|
||||
*
|
||||
|
@ -575,7 +575,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals("isSetHidden", isSetHidden, col.isSetHidden());
|
||||
assertEquals("isSetCollapsed", isSetCollapsed, col.isSetCollapsed()); //not necessarily set
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verify that column groups were created correctly after Sheet.groupColumn
|
||||
*
|
||||
|
@ -708,7 +708,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertFalse(sheet1.getRow(16).getCTRow().isSetHidden());
|
||||
assertFalse(sheet1.getRow(18).getCTRow().isSetCollapsed());
|
||||
assertFalse(sheet1.getRow(18).getCTRow().isSetHidden());
|
||||
|
||||
|
||||
wb2.close();
|
||||
}
|
||||
|
||||
|
@ -755,7 +755,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals(4, col.getMax());
|
||||
assertEquals(33.0, col.getWidth(), 0.0);
|
||||
assertTrue(col.getCustomWidth());
|
||||
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
|
@ -801,7 +801,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
//now the span is splitted into 5 individual columns
|
||||
assertEquals(5, cols.sizeOfColArray());
|
||||
for (int i = 0; i < 5; i++) {
|
||||
assertEquals(cw[i]*256, sheet.getColumnWidth(i));
|
||||
assertEquals(cw[i]*256L, sheet.getColumnWidth(i));
|
||||
assertEquals(cw[i], cols.getColArray(i).getWidth(), 0.0);
|
||||
}
|
||||
|
||||
|
@ -812,10 +812,10 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
cols = sheet.getCTWorksheet().getColsArray(0);
|
||||
assertEquals(5, cols.sizeOfColArray());
|
||||
for (int i = 0; i < 5; i++) {
|
||||
assertEquals(cw[i]*256, sheet.getColumnWidth(i));
|
||||
assertEquals(cw[i]*256L, sheet.getColumnWidth(i));
|
||||
assertEquals(cw[i], cols.getColArray(i).getWidth(), 0.0);
|
||||
}
|
||||
|
||||
|
||||
wb2.close();
|
||||
}
|
||||
|
||||
|
@ -889,7 +889,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertFalse(sheet.isColumnHidden(3));
|
||||
assertFalse(sheet.isColumnHidden(4));
|
||||
assertFalse(sheet.isColumnHidden(5));
|
||||
|
||||
|
||||
wb2.close();
|
||||
}
|
||||
|
||||
|
@ -920,7 +920,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
//comment1 and comment2 are different objects
|
||||
assertNotSame(comment1, comment2);
|
||||
wb1.close();
|
||||
|
||||
|
||||
//now test against a workbook containing cell comments
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.openSampleWorkbook("WithMoreVariousData.xlsx");
|
||||
sheet1 = wb2.getSheetAt(0);
|
||||
|
@ -928,7 +928,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertNotNull(comment1);
|
||||
assertEquals("/xl/comments1.xml", comment1.getPackagePart().getPartName().getName());
|
||||
assertSame(comment1, sheet1.getCommentsTable(true));
|
||||
|
||||
|
||||
wb2.close();
|
||||
}
|
||||
|
||||
|
@ -1034,7 +1034,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertTrue(nm.getCTName().getHidden());
|
||||
assertEquals("_xlnm._FilterDatabase", nm.getCTName().getName());
|
||||
assertEquals("'new sheet'!$A$1:$D$100", nm.getCTName().getStringValue());
|
||||
|
||||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
@ -1057,7 +1057,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
|
||||
sheet.protectSheet(null);
|
||||
assertNull("protectSheet(null) should unset CTSheetProtection", sheet.getCTWorksheet().getSheetProtection());
|
||||
|
||||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
@ -1095,12 +1095,12 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
wb1.close();
|
||||
assertTrue(wb2.getSheetAt(0).validateSheetPassword(password));
|
||||
wb2.close();
|
||||
|
||||
|
||||
XSSFWorkbook wb3 = openSampleWorkbook("workbookProtection-sheet_password-2013.xlsx");
|
||||
assertTrue(wb3.getSheetAt(0).validateSheetPassword("pwd"));
|
||||
wb3.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void bug49966() throws IOException {
|
||||
|
@ -1161,7 +1161,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
XSSFSheet sheet = wb1.createSheet("Sheet 1");
|
||||
|
||||
assertFalse(sheet.getForceFormulaRecalculation());
|
||||
|
||||
|
||||
// Set
|
||||
sheet.setForceFormulaRecalculation(true);
|
||||
assertTrue(sheet.getForceFormulaRecalculation());
|
||||
|
@ -1221,7 +1221,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
}
|
||||
swb.close();
|
||||
}
|
||||
|
||||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
@ -1246,7 +1246,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
}
|
||||
swb.close();
|
||||
}
|
||||
|
||||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
@ -1295,7 +1295,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
name = wb.getBuiltInName(XSSFName.BUILTIN_FILTER_DB, 0);
|
||||
assertNotNull(name);
|
||||
assertEquals("Sheet0!$B:$C", name.getRefersToFormula());
|
||||
|
||||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
@ -1389,7 +1389,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
XSSFPivotTable pivotTable = sheet2.createPivotTable
|
||||
(wb.getCreationHelper().createAreaReference("A1:B2"), new CellReference("H5"), sheet1);
|
||||
assertEquals(0, pivotTable.getRowLabelColumns().size());
|
||||
|
||||
|
||||
assertEquals(1, wb.getPivotTables().size());
|
||||
assertEquals(0, sheet1.getPivotTables().size());
|
||||
assertEquals(1, sheet2.getPivotTables().size());
|
||||
|
@ -1421,12 +1421,12 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
sheet2);
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=POIXMLException.class)
|
||||
public void testReadFails() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
XSSFSheet sheet = wb.createSheet();
|
||||
|
||||
|
||||
// Throws exception because we cannot read here
|
||||
try {
|
||||
sheet.onDocumentRead();
|
||||
|
@ -1434,8 +1434,8 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* This would be better off as a testable example rather than a simple unit test
|
||||
* since Sheet.createComment() was deprecated and removed.
|
||||
* https://poi.apache.org/spreadsheet/quick-guide.html#CellComments
|
||||
|
@ -1450,7 +1450,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertNotNull(comment);
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
||||
protected void testCopyOneRow(String copyRowsTestWorkbook) throws IOException {
|
||||
final double FLOAT_PRECISION = 1e-9;
|
||||
final XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(copyRowsTestWorkbook);
|
||||
|
@ -1496,24 +1496,24 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
cell = CellUtil.getCell(destRow, col++);
|
||||
assertEquals("[String] G7 cell type", CellType.STRING, cell.getCellType());
|
||||
assertEquals("[String] G7 cell value", "Hello", cell.getStringCellValue());
|
||||
|
||||
|
||||
// Int
|
||||
cell = CellUtil.getCell(destRow, col++);
|
||||
assertEquals("[Int] H7 cell type", CellType.NUMERIC, cell.getCellType());
|
||||
assertEquals("[Int] H7 cell value", 15, (int) cell.getNumericCellValue());
|
||||
|
||||
|
||||
// Float
|
||||
cell = CellUtil.getCell(destRow, col++);
|
||||
assertEquals("[Float] I7 cell type", CellType.NUMERIC, cell.getCellType());
|
||||
assertEquals("[Float] I7 cell value", 12.5, cell.getNumericCellValue(), FLOAT_PRECISION);
|
||||
|
||||
|
||||
// Cell Formula
|
||||
cell = CellUtil.getCell(destRow, col++);
|
||||
assertEquals("J7", new CellReference(cell).formatAsString());
|
||||
assertEquals("[Cell Formula] J7 cell type", CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula] J7 cell formula", "5+2", cell.getCellFormula());
|
||||
//System.out.println("Cell formula evaluation currently unsupported");
|
||||
|
||||
|
||||
// Cell Formula with Reference
|
||||
// Formula row references should be adjusted by destRowNum-srcRowNum
|
||||
cell = CellUtil.getCell(destRow, col++);
|
||||
|
@ -1522,21 +1522,21 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Reference] K7 cell formula",
|
||||
"J7+H$2", cell.getCellFormula());
|
||||
|
||||
|
||||
// Cell Formula with Reference spanning multiple rows
|
||||
cell = CellUtil.getCell(destRow, col++);
|
||||
assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell type",
|
||||
CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell formula",
|
||||
"G7&\" \"&G8", cell.getCellFormula());
|
||||
|
||||
|
||||
// Cell Formula with Reference spanning multiple rows
|
||||
cell = CellUtil.getCell(destRow, col++);
|
||||
assertEquals("[Cell Formula with Area Reference] M7 cell type",
|
||||
CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Area Reference] M7 cell formula",
|
||||
"SUM(H7:I8)", cell.getCellFormula());
|
||||
|
||||
|
||||
// Array Formula
|
||||
cell = CellUtil.getCell(destRow, col++);
|
||||
//System.out.println("Array formulas currently unsupported");
|
||||
|
@ -1545,7 +1545,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals("[Array Formula] N7 cell type", CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Array Formula] N7 cell formula", "{SUM(H7:J7*{1,2,3})}", cell.getCellFormula());
|
||||
*/
|
||||
|
||||
|
||||
// Data Format
|
||||
cell = CellUtil.getCell(destRow, col++);
|
||||
assertEquals("[Data Format] O7 cell type;", CellType.NUMERIC, cell.getCellType());
|
||||
|
@ -1553,14 +1553,14 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
//FIXME: currently fails
|
||||
final String moneyFormat = "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)";
|
||||
assertEquals("[Data Format] O7 data format", moneyFormat, cell.getCellStyle().getDataFormatString());
|
||||
|
||||
|
||||
// Merged
|
||||
cell = CellUtil.getCell(destRow, col);
|
||||
assertEquals("[Merged] P7:Q7 cell value",
|
||||
"Merged cells", cell.getStringCellValue());
|
||||
assertTrue("[Merged] P7:Q7 merged region",
|
||||
sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P7:Q7")));
|
||||
|
||||
|
||||
// Merged across multiple rows
|
||||
// Microsoft Excel 2013 does not copy a merged region unless all rows of
|
||||
// the source merged region are selected
|
||||
|
@ -1571,23 +1571,23 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
// which will not overwrite a cell in destination row if merged region extends beyond the copied row.
|
||||
// The Excel way would require:
|
||||
//assertEquals("[Merged across multiple rows] R7:S8 merged region", "Should NOT be overwritten", cell.getStringCellValue());
|
||||
//assertFalse("[Merged across multiple rows] R7:S8 merged region",
|
||||
//assertFalse("[Merged across multiple rows] R7:S8 merged region",
|
||||
// sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S8")));
|
||||
// As currently implemented, cell value is copied but merged region is not copied
|
||||
assertEquals("[Merged across multiple rows] R7:S8 cell value",
|
||||
"Merged cells across multiple rows", cell.getStringCellValue());
|
||||
assertFalse("[Merged across multiple rows] R7:S7 merged region (one row)",
|
||||
assertFalse("[Merged across multiple rows] R7:S7 merged region (one row)",
|
||||
sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S7"))); //shouldn't do 1-row merge
|
||||
assertFalse("[Merged across multiple rows] R7:S8 merged region",
|
||||
assertFalse("[Merged across multiple rows] R7:S8 merged region",
|
||||
sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S8"))); //shouldn't do 2-row merge
|
||||
|
||||
|
||||
// Make sure other rows are blank (off-by-one errors)
|
||||
assertNull(sheet.getRow(5));
|
||||
assertNull(sheet.getRow(7));
|
||||
|
||||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
||||
protected void testCopyMultipleRows(String copyRowsTestWorkbook) throws IOException {
|
||||
final double FLOAT_PRECISION = 1e-9;
|
||||
final XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(copyRowsTestWorkbook);
|
||||
|
@ -1595,8 +1595,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
final CellCopyPolicy defaultCopyPolicy = new CellCopyPolicy();
|
||||
sheet.copyRows(0, 3, 8, defaultCopyPolicy);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
final Row srcHeaderRow = sheet.getRow(0);
|
||||
sheet.getRow(0);
|
||||
final Row srcRow1 = sheet.getRow(1);
|
||||
final Row srcRow2 = sheet.getRow(2);
|
||||
final Row srcRow3 = sheet.getRow(3);
|
||||
|
@ -1606,102 +1605,102 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
final Row destRow3 = sheet.getRow(11);
|
||||
int col = 0;
|
||||
Cell cell;
|
||||
|
||||
|
||||
// Header row should be copied
|
||||
assertNotNull(destHeaderRow);
|
||||
|
||||
|
||||
// Data rows
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("Source row ->", cell.getStringCellValue());
|
||||
|
||||
|
||||
// Style
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Style] B10 cell value", "Red", cell.getStringCellValue());
|
||||
assertEquals("[Style] B10 cell style", CellUtil.getCell(srcRow1, 1).getCellStyle(), cell.getCellStyle());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Style] B11 cell value", "Blue", cell.getStringCellValue());
|
||||
assertEquals("[Style] B11 cell style", CellUtil.getCell(srcRow2, 1).getCellStyle(), cell.getCellStyle());
|
||||
|
||||
|
||||
// Blank
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Blank] C10 cell type", CellType.BLANK, cell.getCellType());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Blank] C11 cell type", CellType.BLANK, cell.getCellType());
|
||||
|
||||
|
||||
// Error
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Error] D10 cell type", CellType.ERROR, cell.getCellType());
|
||||
FormulaError error = FormulaError.forInt(cell.getErrorCellValue());
|
||||
assertEquals("[Error] D10 cell value", FormulaError.NA, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Error] D11 cell type", CellType.ERROR, cell.getCellType());
|
||||
error = FormulaError.forInt(cell.getErrorCellValue());
|
||||
assertEquals("[Error] D11 cell value", FormulaError.NAME, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here
|
||||
|
||||
|
||||
// Date
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Date] E10 cell type", CellType.NUMERIC, cell.getCellType());
|
||||
Date date = LocaleUtil.getLocaleCalendar(2000, Calendar.JANUARY, 1).getTime();
|
||||
assertEquals("[Date] E10 cell value", date, cell.getDateCellValue());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Date] E11 cell type", CellType.NUMERIC, cell.getCellType());
|
||||
date = LocaleUtil.getLocaleCalendar(2000, Calendar.JANUARY, 2).getTime();
|
||||
assertEquals("[Date] E11 cell value", date, cell.getDateCellValue());
|
||||
|
||||
|
||||
// Boolean
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Boolean] F10 cell type", CellType.BOOLEAN, cell.getCellType());
|
||||
assertEquals("[Boolean] F10 cell value", true, cell.getBooleanCellValue());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Boolean] F11 cell type", CellType.BOOLEAN, cell.getCellType());
|
||||
assertEquals("[Boolean] F11 cell value", false, cell.getBooleanCellValue());
|
||||
|
||||
|
||||
// String
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[String] G10 cell type", CellType.STRING, cell.getCellType());
|
||||
assertEquals("[String] G10 cell value", "Hello", cell.getStringCellValue());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[String] G11 cell type", CellType.STRING, cell.getCellType());
|
||||
assertEquals("[String] G11 cell value", "World", cell.getStringCellValue());
|
||||
|
||||
|
||||
// Int
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Int] H10 cell type", CellType.NUMERIC, cell.getCellType());
|
||||
assertEquals("[Int] H10 cell value", 15, (int) cell.getNumericCellValue());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Int] H11 cell type", CellType.NUMERIC, cell.getCellType());
|
||||
assertEquals("[Int] H11 cell value", 42, (int) cell.getNumericCellValue());
|
||||
|
||||
|
||||
// Float
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Float] I10 cell type", CellType.NUMERIC, cell.getCellType());
|
||||
assertEquals("[Float] I10 cell value", 12.5, cell.getNumericCellValue(), FLOAT_PRECISION);
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Float] I11 cell type", CellType.NUMERIC, cell.getCellType());
|
||||
assertEquals("[Float] I11 cell value", 5.5, cell.getNumericCellValue(), FLOAT_PRECISION);
|
||||
|
||||
|
||||
// Cell Formula
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Cell Formula] J10 cell type", CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula] J10 cell formula", "5+2", cell.getCellFormula());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Cell Formula] J11 cell type", CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula] J11 cell formula", "6+18", cell.getCellFormula());
|
||||
|
@ -1714,11 +1713,11 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Reference] K10 cell formula",
|
||||
"J10+H$2", cell.getCellFormula());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Cell Formula with Reference] K11 cell type", CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Reference] K11 cell formula", "J11+H$2", cell.getCellFormula());
|
||||
|
||||
|
||||
// Cell Formula with Reference spanning multiple rows
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
|
@ -1726,13 +1725,13 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Reference spanning multiple rows] L10 cell formula",
|
||||
"G10&\" \"&G11", cell.getCellFormula());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell type",
|
||||
CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell formula",
|
||||
"G11&\" \"&G12", cell.getCellFormula());
|
||||
|
||||
|
||||
// Cell Formula with Area Reference
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
|
@ -1740,13 +1739,13 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Area Reference] M10 cell formula",
|
||||
"SUM(H10:I11)", cell.getCellFormula());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Cell Formula with Area Reference] M11 cell type",
|
||||
CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Cell Formula with Area Reference] M11 cell formula",
|
||||
"SUM($H$3:I10)", cell.getCellFormula()); //Also acceptable: SUM($H10:I$3), but this AreaReference isn't in ascending order
|
||||
|
||||
|
||||
// Array Formula
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
|
@ -1755,13 +1754,13 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
// FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula()
|
||||
assertEquals("[Array Formula] N10 cell type", CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Array Formula] N10 cell formula", "{SUM(H10:J10*{1,2,3})}", cell.getCellFormula());
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
// FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula()
|
||||
// FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula()
|
||||
assertEquals("[Array Formula] N11 cell type", CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("[Array Formula] N11 cell formula", "{SUM(H11:J11*{1,2,3})}", cell.getCellFormula());
|
||||
*/
|
||||
|
||||
|
||||
// Data Format
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
|
@ -1769,7 +1768,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals("[Data Format] O10 cell value", 100.20, cell.getNumericCellValue(), FLOAT_PRECISION);
|
||||
final String moneyFormat = "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)";
|
||||
assertEquals("[Data Format] O10 cell data format", moneyFormat, cell.getCellStyle().getDataFormatString());
|
||||
|
||||
|
||||
// Merged
|
||||
col++;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
|
@ -1777,42 +1776,42 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
"Merged cells", cell.getStringCellValue());
|
||||
assertTrue("[Merged] P10:Q10 merged region",
|
||||
sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P10:Q10")));
|
||||
|
||||
|
||||
cell = CellUtil.getCell(destRow2, col);
|
||||
assertEquals("[Merged] P11:Q11 cell value", "Merged cells", cell.getStringCellValue());
|
||||
assertTrue("[Merged] P11:Q11 merged region",
|
||||
sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P11:Q11")));
|
||||
|
||||
|
||||
// Should Q10/Q11 be checked?
|
||||
|
||||
|
||||
// Merged across multiple rows
|
||||
// Microsoft Excel 2013 does not copy a merged region unless all rows of
|
||||
// the source merged region are selected
|
||||
// POI's behavior should match this behavior
|
||||
col += 2;
|
||||
cell = CellUtil.getCell(destRow1, col);
|
||||
assertEquals("[Merged across multiple rows] R10:S11 cell value",
|
||||
assertEquals("[Merged across multiple rows] R10:S11 cell value",
|
||||
"Merged cells across multiple rows", cell.getStringCellValue());
|
||||
assertTrue("[Merged across multiple rows] R10:S11 merged region",
|
||||
assertTrue("[Merged across multiple rows] R10:S11 merged region",
|
||||
sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R10:S11")));
|
||||
|
||||
|
||||
// Row 3 (zero-based) was empty, so Row 11 (zero-based) should be empty too.
|
||||
if (srcRow3 == null) {
|
||||
assertNull("Row 3 was empty, so Row 11 should be empty", destRow3);
|
||||
}
|
||||
|
||||
|
||||
// Make sure other rows are blank (off-by-one errors)
|
||||
assertNull("Off-by-one lower edge case", sheet.getRow(7)); //one row above destHeaderRow
|
||||
assertNull("Off-by-one upper edge case", sheet.getRow(12)); //one row below destRow3
|
||||
|
||||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCopyOneRow() throws IOException {
|
||||
testCopyOneRow("XSSFSheet.copyRows.xlsx");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCopyMultipleRows() throws IOException {
|
||||
testCopyMultipleRows("XSSFSheet.copyRows.xlsx");
|
||||
|
@ -1828,12 +1827,12 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals(1, ignoredError.getSqref().size());
|
||||
assertEquals("B2:D4", ignoredError.getSqref().get(0));
|
||||
assertTrue(ignoredError.getNumberStoredAsText());
|
||||
|
||||
|
||||
Map<IgnoredErrorType, Set<CellRangeAddress>> ignoredErrors = sheet.getIgnoredErrors();
|
||||
assertEquals(1, ignoredErrors.size());
|
||||
assertEquals(1, ignoredErrors.get(IgnoredErrorType.NUMBER_STORED_AS_TEXT).size());
|
||||
assertEquals("B2:D4", ignoredErrors.get(IgnoredErrorType.NUMBER_STORED_AS_TEXT).iterator().next().formatAsString());
|
||||
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
|
@ -1849,7 +1848,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertFalse(ignoredError.getNumberStoredAsText());
|
||||
assertTrue(ignoredError.getFormula());
|
||||
assertTrue(ignoredError.getEvalError());
|
||||
|
||||
|
||||
Map<IgnoredErrorType, Set<CellRangeAddress>> ignoredErrors = sheet.getIgnoredErrors();
|
||||
assertEquals(2, ignoredErrors.size());
|
||||
assertEquals(1, ignoredErrors.get(IgnoredErrorType.FORMULA).size());
|
||||
|
@ -1867,19 +1866,19 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
// Two calls means two elements, no clever collapsing just yet.
|
||||
sheet.addIgnoredErrors(region, IgnoredErrorType.EVALUATION_ERROR);
|
||||
sheet.addIgnoredErrors(region, IgnoredErrorType.FORMULA);
|
||||
|
||||
|
||||
CTIgnoredError ignoredError = sheet.getCTWorksheet().getIgnoredErrors().getIgnoredErrorArray(0);
|
||||
assertEquals(1, ignoredError.getSqref().size());
|
||||
assertEquals("B2:D4", ignoredError.getSqref().get(0));
|
||||
assertFalse(ignoredError.getFormula());
|
||||
assertTrue(ignoredError.getEvalError());
|
||||
|
||||
|
||||
ignoredError = sheet.getCTWorksheet().getIgnoredErrors().getIgnoredErrorArray(1);
|
||||
assertEquals(1, ignoredError.getSqref().size());
|
||||
assertEquals("B2:D4", ignoredError.getSqref().get(0));
|
||||
assertTrue(ignoredError.getFormula());
|
||||
assertFalse(ignoredError.getEvalError());
|
||||
|
||||
|
||||
Map<IgnoredErrorType, Set<CellRangeAddress>> ignoredErrors = sheet.getIgnoredErrors();
|
||||
assertEquals(2, ignoredErrors.size());
|
||||
assertEquals(1, ignoredErrors.get(IgnoredErrorType.FORMULA).size());
|
||||
|
@ -1888,7 +1887,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals("B2:D4", ignoredErrors.get(IgnoredErrorType.EVALUATION_ERROR).iterator().next().formatAsString());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void setTabColor() throws IOException {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
|
@ -1900,7 +1899,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
sh.getCTWorksheet().getSheetPr().getTabColor().getIndexed());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getTabColor() throws IOException {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
|
@ -1912,7 +1911,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals(expected, sh.getTabColor());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Test using an existing workbook saved by Excel
|
||||
@Test
|
||||
public void tabColor() throws IOException {
|
||||
|
@ -1930,7 +1929,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
assertEquals(expected, wb.getSheet("customOrange").getTabColor());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See bug #52425
|
||||
*/
|
||||
|
@ -1947,7 +1946,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
// Adding Comment to cloned Sheet 3
|
||||
addComments(helper, sheet3);
|
||||
}
|
||||
|
||||
|
||||
private void addComments(CreationHelper helper, Sheet sheet) {
|
||||
Drawing<?> drawing = sheet.createDrawingPatriarch();
|
||||
|
||||
|
@ -1974,7 +1973,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// bug 59687: XSSFSheet.RemoveRow doesn't handle row gaps properly when removing row comments
|
||||
@Test
|
||||
public void testRemoveRowWithCommentAndGapAbove() throws IOException {
|
||||
|
@ -1984,22 +1983,22 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
// comment exists
|
||||
CellAddress commentCellAddress = new CellAddress("A4");
|
||||
assertNotNull(sheet.getCellComment(commentCellAddress));
|
||||
|
||||
|
||||
assertEquals("Wrong starting # of comments", 1, sheet.getCellComments().size());
|
||||
|
||||
|
||||
sheet.removeRow(sheet.getRow(commentCellAddress.getRow()));
|
||||
|
||||
|
||||
assertEquals("There should not be any comments left!", 0, sheet.getCellComments().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetHeaderFooterProperties() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
XSSFSheet sh = wb.createSheet();
|
||||
|
||||
|
||||
XSSFHeaderFooterProperties hfProp = sh.getHeaderFooterProperties();
|
||||
assertNotNull(hfProp);
|
||||
|
||||
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1044,8 +1044,10 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
|
|||
//assertCloseDoesNotModifyFile(filename, wb);
|
||||
|
||||
// InputStream
|
||||
wb = new XSSFWorkbook(new FileInputStream(file));
|
||||
assertCloseDoesNotModifyFile(filename, wb);
|
||||
try (FileInputStream is = new FileInputStream(file)) {
|
||||
wb = new XSSFWorkbook(is);
|
||||
assertCloseDoesNotModifyFile(filename, wb);
|
||||
}
|
||||
|
||||
// OPCPackage
|
||||
//wb = new XSSFWorkbook(OPCPackage.open(file));
|
||||
|
|
|
@ -65,7 +65,7 @@ public class TestXSSFChartTitle {
|
|||
row = sheet.createRow((short) rowIndex);
|
||||
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
|
||||
cell = row.createCell((short) colIndex);
|
||||
cell.setCellValue(colIndex * (rowIndex + 1));
|
||||
cell.setCellValue(colIndex * (rowIndex + 1L));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.xssf.model.StylesTable;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
|
@ -192,14 +195,14 @@ public final class TestColumnHelper {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddCleanColIntoColsExactOverlap() throws Exception {
|
||||
public void testAddCleanColIntoColsExactOverlap() {
|
||||
CTCols cols = createHiddenAndBestFitColsWithHelper(1, 1, 1, 1);
|
||||
assertEquals(1, cols.sizeOfColArray());
|
||||
assertMinMaxHiddenBestFit(cols, 0, 1, 1, true, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddCleanColIntoColsOverlapsOverhangingBothSides() throws Exception {
|
||||
public void testAddCleanColIntoColsOverlapsOverhangingBothSides() {
|
||||
CTCols cols = createHiddenAndBestFitColsWithHelper(2, 2, 1, 3);
|
||||
assertEquals(3, cols.sizeOfColArray());
|
||||
assertMinMaxHiddenBestFit(cols, 0, 1, 1, false, true);
|
||||
|
@ -208,7 +211,7 @@ public final class TestColumnHelper {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddCleanColIntoColsOverlapsCompletelyNested() throws Exception {
|
||||
public void testAddCleanColIntoColsOverlapsCompletelyNested() {
|
||||
CTCols cols = createHiddenAndBestFitColsWithHelper(1, 3, 2, 2);
|
||||
assertEquals(3, cols.sizeOfColArray());
|
||||
assertMinMaxHiddenBestFit(cols, 0, 1, 1, true, false);
|
||||
|
@ -217,7 +220,7 @@ public final class TestColumnHelper {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddCleanColIntoColsNewOverlapsOverhangingLeftNotRightExactRight() throws Exception {
|
||||
public void testAddCleanColIntoColsNewOverlapsOverhangingLeftNotRightExactRight() {
|
||||
CTCols cols = createHiddenAndBestFitColsWithHelper(2, 3, 1, 3);
|
||||
assertEquals(2, cols.sizeOfColArray());
|
||||
assertMinMaxHiddenBestFit(cols, 0, 1, 1, false, true);
|
||||
|
@ -225,7 +228,7 @@ public final class TestColumnHelper {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddCleanColIntoColsNewOverlapsOverhangingRightNotLeftExactLeft() throws Exception {
|
||||
public void testAddCleanColIntoColsNewOverlapsOverhangingRightNotLeftExactLeft() {
|
||||
CTCols cols = createHiddenAndBestFitColsWithHelper(1, 2, 1, 3);
|
||||
assertEquals(2, cols.sizeOfColArray());
|
||||
assertMinMaxHiddenBestFit(cols, 0, 1, 2, true, true);
|
||||
|
@ -233,7 +236,7 @@ public final class TestColumnHelper {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddCleanColIntoColsNewOverlapsOverhangingLeftNotRight() throws Exception {
|
||||
public void testAddCleanColIntoColsNewOverlapsOverhangingLeftNotRight() {
|
||||
CTCols cols = createHiddenAndBestFitColsWithHelper(2, 3, 1, 2);
|
||||
assertEquals(3, cols.sizeOfColArray());
|
||||
assertMinMaxHiddenBestFit(cols, 0, 1, 1, false, true);
|
||||
|
@ -242,7 +245,7 @@ public final class TestColumnHelper {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddCleanColIntoColsNewOverlapsOverhangingRightNotLeft() throws Exception {
|
||||
public void testAddCleanColIntoColsNewOverlapsOverhangingRightNotLeft() {
|
||||
CTCols cols = createHiddenAndBestFitColsWithHelper(1, 2, 2, 3);
|
||||
assertEquals(3, cols.sizeOfColArray());
|
||||
assertMinMaxHiddenBestFit(cols, 0, 1, 1, true, false);
|
||||
|
@ -402,4 +405,36 @@ public final class TestColumnHelper {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testColumnsCollapsed() {
|
||||
Workbook wb = new XSSFWorkbook();
|
||||
Sheet sheet = wb.createSheet("test");
|
||||
Row row = sheet.createRow(0);
|
||||
row.createCell(0);
|
||||
row.createCell(1);
|
||||
row.createCell(2);
|
||||
|
||||
sheet.setColumnWidth(0, 10);
|
||||
sheet.setColumnWidth(1, 10);
|
||||
sheet.setColumnWidth(2, 10);
|
||||
|
||||
sheet.groupColumn(0, 1);
|
||||
sheet.setColumnGroupCollapsed(0, true);
|
||||
|
||||
CTCols ctCols = ((XSSFSheet) sheet).getCTWorksheet().getColsArray()[0];
|
||||
assertEquals(3, ctCols.sizeOfColArray());
|
||||
assertTrue(ctCols.getColArray(0).isSetCollapsed());
|
||||
assertTrue(ctCols.getColArray(1).isSetCollapsed());
|
||||
assertTrue(ctCols.getColArray(2).isSetCollapsed());
|
||||
|
||||
ColumnHelper helper = new ColumnHelper(CTWorksheet.Factory.newInstance());
|
||||
helper.setColumnAttributes(ctCols.getColArray(1), ctCols.getColArray(2));
|
||||
|
||||
ctCols = ((XSSFSheet) sheet).getCTWorksheet().getColsArray()[0];
|
||||
assertTrue(ctCols.getColArray(0).isSetCollapsed());
|
||||
assertTrue(ctCols.getColArray(1).isSetCollapsed());
|
||||
assertTrue(ctCols.getColArray(2).isSetCollapsed());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,18 +17,23 @@
|
|||
|
||||
package org.apache.poi.xssf.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Mixed utilities for testing memory usage in XSSF
|
||||
|
@ -37,7 +42,7 @@ import java.util.ArrayList;
|
|||
*/
|
||||
public class MemoryUsage extends TestCase {
|
||||
private static final int NUM_COLUMNS = 255;
|
||||
|
||||
|
||||
private static void printMemoryUsage(String msg) {
|
||||
System.out.println(" Memory (" + msg + "): " + Runtime.getRuntime().totalMemory()/(1024*1024) + "MB");
|
||||
}
|
||||
|
@ -62,8 +67,11 @@ public class MemoryUsage extends TestCase {
|
|||
Row row = sh.createRow(i);
|
||||
for(int j=0; j < numCols; j++){
|
||||
Cell cell = row.createCell(j);
|
||||
if(j % 2 == 0) cell.setCellValue(j);
|
||||
else cell.setCellValue(new CellReference(j, i).formatAsString());
|
||||
if(j % 2 == 0) {
|
||||
cell.setCellValue(j);
|
||||
} else {
|
||||
cell.setCellValue(new CellReference(j, i).formatAsString());
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +86,7 @@ public class MemoryUsage extends TestCase {
|
|||
|
||||
/**
|
||||
* Generate a spreadsheet who's all cell values are numbers.
|
||||
* The data is generated until OutOfMemoryError.
|
||||
* The data is generated until OutOfMemoryError.
|
||||
* <p>
|
||||
* as compared to {@link #mixedSpreadsheet(org.apache.poi.ss.usermodel.Workbook, int)},
|
||||
* this method does not set string values and, hence, does not involve the Shared Strings Table.
|
||||
|
@ -161,7 +169,7 @@ public class MemoryUsage extends TestCase {
|
|||
rows.add(r);
|
||||
}
|
||||
} catch (OutOfMemoryError er) {
|
||||
System.out.println("Failed at row=" + i);
|
||||
System.out.println("Failed at row=" + i + " from " + rows.size() + " kept.");
|
||||
} catch (final Exception e) {
|
||||
System.out.println("Unable to reach an OutOfMemoryError");
|
||||
System.out.println(e.getClass().getName() + ": " + e.getMessage());
|
||||
|
@ -190,7 +198,7 @@ public class MemoryUsage extends TestCase {
|
|||
rows.add(r);
|
||||
}
|
||||
} catch (OutOfMemoryError er) {
|
||||
System.out.println("Failed at row=" + i);
|
||||
System.out.println("Failed at row=" + i + " from " + rows.size() + " kept.");
|
||||
} catch (final Exception e) {
|
||||
System.out.println("Unable to reach an OutOfMemoryError");
|
||||
System.out.println(e.getClass().getName() + ": " + e.getMessage());
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.apache.poi.xwpf.XWPFTestDataSamples;
|
|||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||
import static org.apache.poi.POITestCase.assertContains;
|
||||
import static org.apache.poi.POITestCase.assertEndsWith;
|
||||
import static org.apache.poi.POITestCase.assertNotContained;
|
||||
import static org.apache.poi.POITestCase.assertStartsWith;
|
||||
|
||||
/**
|
||||
|
@ -441,4 +442,14 @@ public class TestXWPFWordExtractor extends TestCase {
|
|||
assertContains(txt, "Sequencing data");
|
||||
extractor.close();
|
||||
}
|
||||
|
||||
public void testGlossary() throws IOException {
|
||||
XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("60316.dotx");
|
||||
XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
|
||||
String txt = extractor.getText();
|
||||
assertContains(txt, "Getting the perfect");
|
||||
//this content appears only in the glossary document
|
||||
//once we add processing for this, we can change this to contains
|
||||
assertNotContained(txt, "table rows");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,6 +148,19 @@ public final class TestXWPFSDT {
|
|||
assertEquals("", sdts.get(0).getTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test62859() throws IOException {
|
||||
//this doesn't test the exact code path for this issue, but
|
||||
//it does test for a related issue, and the fix fixes both.
|
||||
//We should try to add the actual triggering document
|
||||
//to our test suite.
|
||||
XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug62859.docx");
|
||||
List<XWPFAbstractSDT> sdts = extractAllSDTs(doc);
|
||||
assertEquals(1, sdts.size());
|
||||
assertEquals("", sdts.get(0).getTag());
|
||||
assertEquals("", sdts.get(0).getTitle());
|
||||
}
|
||||
|
||||
private List<XWPFAbstractSDT> extractAllSDTs(XWPFDocument doc) {
|
||||
|
||||
List<XWPFAbstractSDT> sdts = new ArrayList<>();
|
||||
|
|
|
@ -75,33 +75,25 @@ import org.apache.poi.util.LittleEndian;
|
|||
* @author Sergey Vladimirov (vlsergey at gmail dot com)
|
||||
*/
|
||||
@Beta
|
||||
public final class HWPFLister
|
||||
{
|
||||
private static HWPFDocumentCore loadDoc( File docFile ) throws IOException
|
||||
{
|
||||
public final class HWPFLister {
|
||||
private static HWPFDocumentCore loadDoc( File docFile ) throws IOException {
|
||||
try (final FileInputStream istream = new FileInputStream( docFile )) {
|
||||
return loadDoc( istream );
|
||||
}
|
||||
}
|
||||
|
||||
private static HWPFDocumentCore loadDoc( InputStream inputStream )
|
||||
throws IOException
|
||||
{
|
||||
final POIFSFileSystem poifsFileSystem = HWPFDocumentCore.verifyAndBuildPOIFS( inputStream );
|
||||
try
|
||||
{
|
||||
throws IOException {
|
||||
final POIFSFileSystem poifsFileSystem = HWPFDocumentCore.verifyAndBuildPOIFS( inputStream ); // NOSONAR
|
||||
try {
|
||||
return new HWPFDocument( poifsFileSystem );
|
||||
}
|
||||
catch ( OldWordFileFormatException exc )
|
||||
{
|
||||
} catch ( OldWordFileFormatException exc ) {
|
||||
return new HWPFOldDocument( poifsFileSystem );
|
||||
}
|
||||
}
|
||||
|
||||
public static void main( String[] args ) throws Exception
|
||||
{
|
||||
if ( args.length == 0 )
|
||||
{
|
||||
public static void main( String[] args ) throws Exception {
|
||||
if ( args.length == 0 ) {
|
||||
System.err.println( "Use:" );
|
||||
System.err.println( "\tHWPFLister <filename>\n" + "\t\t[--dop]\n"
|
||||
+ "\t\t[--textPieces] [--textPiecesText]\n"
|
||||
|
@ -140,8 +132,7 @@ public final class HWPFLister
|
|||
|
||||
boolean writereadback = false;
|
||||
|
||||
for ( String arg : Arrays.asList( args ).subList( 1, args.length ) )
|
||||
{
|
||||
for ( String arg : Arrays.asList( args ).subList( 1, args.length ) ) {
|
||||
if ( "--dop".equals( arg ) )
|
||||
outputDop = true;
|
||||
|
||||
|
@ -190,17 +181,14 @@ public final class HWPFLister
|
|||
if ( writereadback )
|
||||
doc = writeOutAndReadBack( doc );
|
||||
|
||||
HWPFDocumentCore original;
|
||||
{
|
||||
System.setProperty( "org.apache.poi.hwpf.preserveBinTables",
|
||||
Boolean.TRUE.toString() );
|
||||
System.setProperty( "org.apache.poi.hwpf.preserveTextTable",
|
||||
Boolean.TRUE.toString() );
|
||||
System.setProperty( "org.apache.poi.hwpf.preserveBinTables",
|
||||
Boolean.TRUE.toString() );
|
||||
System.setProperty( "org.apache.poi.hwpf.preserveTextTable",
|
||||
Boolean.TRUE.toString() );
|
||||
|
||||
original = loadDoc( new File( args[0] ) );
|
||||
if ( writereadback )
|
||||
original = writeOutAndReadBack( original );
|
||||
}
|
||||
HWPFDocumentCore original = loadDoc( new File( args[0] ) );
|
||||
if ( writereadback )
|
||||
original = writeOutAndReadBack( original );
|
||||
|
||||
HWPFLister listerOriginal = new HWPFLister( original );
|
||||
HWPFLister listerRebuilded = new HWPFLister( doc );
|
||||
|
@ -211,20 +199,17 @@ public final class HWPFLister
|
|||
System.out.println( "== FIB (original) ==" );
|
||||
listerOriginal.dumpFIB();
|
||||
|
||||
if ( outputDop )
|
||||
{
|
||||
if ( outputDop ) {
|
||||
System.out.println( "== Document properties ==" );
|
||||
listerOriginal.dumpDop();
|
||||
}
|
||||
|
||||
if ( outputTextPieces )
|
||||
{
|
||||
if ( outputTextPieces ) {
|
||||
System.out.println( "== Text pieces (original) ==" );
|
||||
listerOriginal.dumpTextPieces( outputTextPiecesText );
|
||||
}
|
||||
|
||||
if ( outputChpx )
|
||||
{
|
||||
if ( outputChpx ) {
|
||||
System.out.println( "== CHPX (original) ==" );
|
||||
listerOriginal.dumpChpx( outputChpxProperties, outputChpxSprms );
|
||||
|
||||
|
@ -232,8 +217,7 @@ public final class HWPFLister
|
|||
listerRebuilded.dumpChpx( outputChpxProperties, outputChpxSprms );
|
||||
}
|
||||
|
||||
if ( outputPapx )
|
||||
{
|
||||
if ( outputPapx ) {
|
||||
System.out.println( "== PAPX (original) ==" );
|
||||
listerOriginal.dumpPapx( outputPapxProperties, outputPapxSprms );
|
||||
|
||||
|
@ -241,8 +225,7 @@ public final class HWPFLister
|
|||
listerRebuilded.dumpPapx( outputPapxProperties, outputPapxSprms );
|
||||
}
|
||||
|
||||
if ( outputParagraphs )
|
||||
{
|
||||
if ( outputParagraphs ) {
|
||||
System.out.println( "== Text paragraphs (original) ==" );
|
||||
listerRebuilded.dumpParagraphs( true );
|
||||
|
||||
|
@ -250,56 +233,47 @@ public final class HWPFLister
|
|||
listerRebuilded.dumpParagraphsDom( outputParagraphsText );
|
||||
}
|
||||
|
||||
if ( outputBookmarks )
|
||||
{
|
||||
if ( outputBookmarks ) {
|
||||
System.out.println( "== BOOKMARKS (rebuilded) ==" );
|
||||
listerRebuilded.dumpBookmarks();
|
||||
}
|
||||
|
||||
if ( outputEscher )
|
||||
{
|
||||
if ( outputEscher ) {
|
||||
System.out.println( "== ESCHER PROPERTIES (rebuilded) ==" );
|
||||
listerRebuilded.dumpEscher();
|
||||
}
|
||||
|
||||
if ( outputFields )
|
||||
{
|
||||
if ( outputFields ) {
|
||||
System.out.println( "== FIELDS (rebuilded) ==" );
|
||||
listerRebuilded.dumpFields();
|
||||
}
|
||||
|
||||
if ( outputOfficeDrawings )
|
||||
{
|
||||
if ( outputOfficeDrawings ) {
|
||||
System.out.println( "== OFFICE DRAWINGS (rebuilded) ==" );
|
||||
listerRebuilded.dumpOfficeDrawings();
|
||||
}
|
||||
|
||||
if ( outputPictures )
|
||||
{
|
||||
if ( outputPictures ) {
|
||||
System.out.println( "== PICTURES (rebuilded) ==" );
|
||||
listerRebuilded.dumpPictures();
|
||||
}
|
||||
|
||||
if ( outputStyles )
|
||||
{
|
||||
if ( outputStyles ) {
|
||||
System.out.println( "== STYLES (rebuilded) ==" );
|
||||
listerRebuilded.dumpStyles();
|
||||
}
|
||||
}
|
||||
|
||||
private static HWPFDocumentCore writeOutAndReadBack(
|
||||
HWPFDocumentCore original )
|
||||
{
|
||||
try
|
||||
{
|
||||
HWPFDocumentCore original ) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream( 4096 );
|
||||
original.write( baos );
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(
|
||||
baos.toByteArray() );
|
||||
return loadDoc( bais );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
catch ( IOException e ) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
}
|
||||
|
@ -308,82 +282,67 @@ public final class HWPFLister
|
|||
|
||||
private LinkedHashMap<Integer, String> paragraphs;
|
||||
|
||||
public HWPFLister( HWPFDocumentCore doc )
|
||||
{
|
||||
public HWPFLister( HWPFDocumentCore doc ) {
|
||||
_doc = doc;
|
||||
|
||||
buildParagraphs();
|
||||
}
|
||||
|
||||
private void buildParagraphs()
|
||||
{
|
||||
private void buildParagraphs() {
|
||||
paragraphs = new LinkedHashMap<>();
|
||||
|
||||
StringBuilder part = new StringBuilder();
|
||||
String text = _doc.getDocumentText();
|
||||
for ( int charIndex = 0; charIndex < text.length(); charIndex++ )
|
||||
{
|
||||
for ( int charIndex = 0; charIndex < text.length(); charIndex++ ) {
|
||||
char c = text.charAt( charIndex );
|
||||
part.append( c );
|
||||
if ( c == 13 || c == 7 || c == 12 )
|
||||
{
|
||||
if ( c == 13 || c == 7 || c == 12 ) {
|
||||
paragraphs.put( Integer.valueOf( charIndex ), part.toString() );
|
||||
part.setLength( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpBookmarks()
|
||||
{
|
||||
if ( !( _doc instanceof HWPFDocument ) )
|
||||
{
|
||||
private void dumpBookmarks() {
|
||||
if ( !( _doc instanceof HWPFDocument ) ) {
|
||||
System.out.println( "Word 95 not supported so far" );
|
||||
return;
|
||||
}
|
||||
|
||||
HWPFDocument document = (HWPFDocument) _doc;
|
||||
Bookmarks bookmarks = document.getBookmarks();
|
||||
for ( int b = 0; b < bookmarks.getBookmarksCount(); b++ )
|
||||
{
|
||||
for ( int b = 0; b < bookmarks.getBookmarksCount(); b++ ) {
|
||||
Bookmark bookmark = bookmarks.getBookmark( b );
|
||||
System.out.println( "[" + bookmark.getStart() + "; "
|
||||
+ bookmark.getEnd() + "): " + bookmark.getName() );
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpChpx( boolean withProperties, boolean withSprms )
|
||||
{
|
||||
for ( CHPX chpx : _doc.getCharacterTable().getTextRuns() )
|
||||
{
|
||||
public void dumpChpx( boolean withProperties, boolean withSprms ) {
|
||||
for ( CHPX chpx : _doc.getCharacterTable().getTextRuns() ) {
|
||||
System.out.println( chpx );
|
||||
|
||||
if ( withProperties )
|
||||
{
|
||||
if ( withProperties ) {
|
||||
System.out.println( chpx.getCharacterProperties(
|
||||
_doc.getStyleSheet(), (short) StyleSheet.NIL_STYLE ) );
|
||||
}
|
||||
|
||||
if ( withSprms )
|
||||
{
|
||||
if ( withSprms ) {
|
||||
SprmIterator sprmIt = new SprmIterator( chpx.getGrpprl(), 0 );
|
||||
while ( sprmIt.hasNext() )
|
||||
{
|
||||
while ( sprmIt.hasNext() ) {
|
||||
SprmOperation sprm = sprmIt.next();
|
||||
System.out.println( "\t" + sprm);
|
||||
}
|
||||
}
|
||||
|
||||
String text = new Range( chpx.getStart(), chpx.getEnd(),
|
||||
_doc.getOverallRange() )
|
||||
{
|
||||
public String toString()
|
||||
{
|
||||
_doc.getOverallRange() ) {
|
||||
public String toString() {
|
||||
return "CHPX range (" + super.toString() + ")";
|
||||
}
|
||||
}.text();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for ( char c : text.toCharArray() )
|
||||
{
|
||||
for ( char c : text.toCharArray() ) {
|
||||
if ( c < 30 )
|
||||
stringBuilder.append("\\0x").append(Integer.toHexString(c));
|
||||
else
|
||||
|
@ -393,10 +352,8 @@ public final class HWPFLister
|
|||
}
|
||||
}
|
||||
|
||||
private void dumpDop()
|
||||
{
|
||||
if ( !( _doc instanceof HWPFDocument ) )
|
||||
{
|
||||
private void dumpDop() {
|
||||
if ( !( _doc instanceof HWPFDocument ) ) {
|
||||
System.out.println( "Word 95 not supported so far" );
|
||||
return;
|
||||
}
|
||||
|
@ -404,10 +361,8 @@ public final class HWPFLister
|
|||
System.out.println( ( (HWPFDocument) _doc ).getDocProperties() );
|
||||
}
|
||||
|
||||
private void dumpEscher()
|
||||
{
|
||||
if ( _doc instanceof HWPFOldDocument )
|
||||
{
|
||||
private void dumpEscher() {
|
||||
if ( _doc instanceof HWPFOldDocument ) {
|
||||
System.out.println( "Word 95 not supported so far" );
|
||||
return;
|
||||
}
|
||||
|
@ -415,46 +370,38 @@ public final class HWPFLister
|
|||
System.out.println( ( (HWPFDocument) _doc ).getEscherRecordHolder() );
|
||||
}
|
||||
|
||||
public void dumpFIB()
|
||||
{
|
||||
public void dumpFIB() {
|
||||
FileInformationBlock fib = _doc.getFileInformationBlock();
|
||||
System.out.println( fib );
|
||||
|
||||
}
|
||||
|
||||
private void dumpFields()
|
||||
{
|
||||
if ( !( _doc instanceof HWPFDocument ) )
|
||||
{
|
||||
private void dumpFields() {
|
||||
if ( !( _doc instanceof HWPFDocument ) ) {
|
||||
System.out.println( "Word 95 not supported so far" );
|
||||
return;
|
||||
}
|
||||
|
||||
HWPFDocument document = (HWPFDocument) _doc;
|
||||
|
||||
for ( FieldsDocumentPart part : FieldsDocumentPart.values() )
|
||||
{
|
||||
for ( FieldsDocumentPart part : FieldsDocumentPart.values() ) {
|
||||
System.out.println( "=== Document part: " + part + " ===" );
|
||||
for ( Field field : document.getFields().getFields( part ) )
|
||||
{
|
||||
for ( Field field : document.getFields().getFields( part ) ) {
|
||||
System.out.println( field );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpFileSystem() throws Exception
|
||||
{
|
||||
public void dumpFileSystem() throws Exception {
|
||||
System.out.println( dumpFileSystem( _doc.getDirectory() ) );
|
||||
}
|
||||
|
||||
private String dumpFileSystem( DirectoryEntry directory )
|
||||
{
|
||||
private String dumpFileSystem( DirectoryEntry directory ) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append( "+ " );
|
||||
result.append( directory.getName() );
|
||||
for ( Iterator<Entry> iterator = directory.getEntries(); iterator
|
||||
.hasNext(); )
|
||||
{
|
||||
.hasNext(); ) {
|
||||
Entry entry = iterator.next();
|
||||
String entryToString = "\n" + dumpFileSystem( entry );
|
||||
entryToString = entryToString.replaceAll( "\n", "\n+---" );
|
||||
|
@ -464,50 +411,41 @@ public final class HWPFLister
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
private String dumpFileSystem( Entry entry )
|
||||
{
|
||||
private String dumpFileSystem( Entry entry ) {
|
||||
if ( entry instanceof DirectoryEntry )
|
||||
return dumpFileSystem( (DirectoryEntry) entry );
|
||||
|
||||
return entry.getName();
|
||||
}
|
||||
|
||||
private void dumpOfficeDrawings()
|
||||
{
|
||||
if ( !( _doc instanceof HWPFDocument ) )
|
||||
{
|
||||
private void dumpOfficeDrawings() {
|
||||
if ( !( _doc instanceof HWPFDocument ) ) {
|
||||
System.out.println( "Word 95 not supported so far" );
|
||||
return;
|
||||
}
|
||||
|
||||
HWPFDocument document = (HWPFDocument) _doc;
|
||||
|
||||
if ( document.getOfficeDrawingsHeaders() != null )
|
||||
{
|
||||
if ( document.getOfficeDrawingsHeaders() != null ) {
|
||||
System.out.println( "=== Document part: HEADER ===" );
|
||||
for ( OfficeDrawing officeDrawing : document
|
||||
.getOfficeDrawingsHeaders().getOfficeDrawings() )
|
||||
{
|
||||
.getOfficeDrawingsHeaders().getOfficeDrawings() ) {
|
||||
System.out.println( officeDrawing );
|
||||
}
|
||||
}
|
||||
|
||||
if ( document.getOfficeDrawingsHeaders() != null )
|
||||
{
|
||||
if ( document.getOfficeDrawingsHeaders() != null ) {
|
||||
System.out.println( "=== Document part: MAIN ===" );
|
||||
for ( OfficeDrawing officeDrawing : document
|
||||
.getOfficeDrawingsMain().getOfficeDrawings() )
|
||||
{
|
||||
.getOfficeDrawingsMain().getOfficeDrawings() ) {
|
||||
System.out.println( officeDrawing );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpPapx( boolean withProperties, boolean withSprms )
|
||||
throws Exception
|
||||
{
|
||||
if ( _doc instanceof HWPFDocument )
|
||||
{
|
||||
throws Exception {
|
||||
if ( _doc instanceof HWPFDocument ) {
|
||||
System.out.println( "binary PAP pages " );
|
||||
|
||||
HWPFDocument doc = (HWPFDocument) _doc;
|
||||
|
@ -521,8 +459,7 @@ public final class HWPFLister
|
|||
List<PAPX> papxs = new ArrayList<>();
|
||||
|
||||
int length = binTable.length();
|
||||
for ( int x = 0; x < length; x++ )
|
||||
{
|
||||
for ( int x = 0; x < length; x++ ) {
|
||||
GenericPropertyNode node = binTable.getProperty( x );
|
||||
|
||||
int pageNum = LittleEndian.getInt( node.getBytes() );
|
||||
|
@ -535,12 +472,10 @@ public final class HWPFLister
|
|||
|
||||
System.out.println( "* PFKP: " + pfkp );
|
||||
|
||||
for ( PAPX papx : pfkp.getPAPXs() )
|
||||
{
|
||||
for ( PAPX papx : pfkp.getPAPXs() ) {
|
||||
System.out.println( "** " + papx );
|
||||
papxs.add( papx );
|
||||
if ( papx != null && withSprms )
|
||||
{
|
||||
if ( papx != null && withSprms ) {
|
||||
SprmIterator sprmIt = new SprmIterator(
|
||||
papx.getGrpprl(), 2 );
|
||||
dumpSprms( sprmIt, "*** " );
|
||||
|
@ -551,11 +486,9 @@ public final class HWPFLister
|
|||
|
||||
Collections.sort( papxs );
|
||||
System.out.println( "* Sorted by END" );
|
||||
for ( PAPX papx : papxs )
|
||||
{
|
||||
for ( PAPX papx : papxs ) {
|
||||
System.out.println( "** " + papx );
|
||||
if ( papx != null && withSprms )
|
||||
{
|
||||
if ( papx != null && withSprms ) {
|
||||
SprmIterator sprmIt = new SprmIterator( papx.getGrpprl(), 2 );
|
||||
dumpSprms( sprmIt, "*** " );
|
||||
}
|
||||
|
@ -563,12 +496,10 @@ public final class HWPFLister
|
|||
}
|
||||
|
||||
|
||||
for ( PAPX papx : _doc.getParagraphTable().getParagraphs() )
|
||||
{
|
||||
for ( PAPX papx : _doc.getParagraphTable().getParagraphs() ) {
|
||||
System.out.println( papx );
|
||||
|
||||
if ( withProperties )
|
||||
{
|
||||
if ( withProperties ) {
|
||||
Paragraph paragraph = Paragraph.newParagraph( _doc.getOverallRange(), papx );
|
||||
System.out.println( paragraph.getProps() );
|
||||
}
|
||||
|
@ -578,23 +509,18 @@ public final class HWPFLister
|
|||
}
|
||||
}
|
||||
|
||||
public void dumpParagraphs( boolean dumpAssotiatedPapx )
|
||||
{
|
||||
for ( Map.Entry<Integer, String> entry : paragraphs.entrySet() )
|
||||
{
|
||||
public void dumpParagraphs( boolean dumpAssotiatedPapx ) {
|
||||
for ( Map.Entry<Integer, String> entry : paragraphs.entrySet() ) {
|
||||
Integer endOfParagraphCharOffset = entry.getKey();
|
||||
System.out.println( "[...; " + ( endOfParagraphCharOffset + 1 )
|
||||
+ "): " + entry.getValue() );
|
||||
|
||||
if ( dumpAssotiatedPapx )
|
||||
{
|
||||
if ( dumpAssotiatedPapx ) {
|
||||
boolean hasAssotiatedPapx = false;
|
||||
for ( PAPX papx : _doc.getParagraphTable().getParagraphs() )
|
||||
{
|
||||
for ( PAPX papx : _doc.getParagraphTable().getParagraphs() ) {
|
||||
if ( papx.getStart() <= endOfParagraphCharOffset.intValue()
|
||||
&& endOfParagraphCharOffset.intValue() < papx
|
||||
.getEnd() )
|
||||
{
|
||||
.getEnd() ) {
|
||||
hasAssotiatedPapx = true;
|
||||
System.out.println( "* " + papx );
|
||||
|
||||
|
@ -603,8 +529,7 @@ public final class HWPFLister
|
|||
dumpSprms( sprmIt, "** " );
|
||||
}
|
||||
}
|
||||
if ( !hasAssotiatedPapx )
|
||||
{
|
||||
if ( !hasAssotiatedPapx ) {
|
||||
System.out.println( "* "
|
||||
+ "NO PAPX ASSOTIATED WITH PARAGRAPH!" );
|
||||
}
|
||||
|
@ -612,20 +537,16 @@ public final class HWPFLister
|
|||
}
|
||||
}
|
||||
|
||||
protected void dumpSprms( SprmIterator sprmIt, String linePrefix )
|
||||
{
|
||||
while ( sprmIt.hasNext() )
|
||||
{
|
||||
protected void dumpSprms( SprmIterator sprmIt, String linePrefix ) {
|
||||
while ( sprmIt.hasNext() ) {
|
||||
SprmOperation sprm = sprmIt.next();
|
||||
System.out.println( linePrefix + sprm);
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpParagraphsDom( boolean withText )
|
||||
{
|
||||
public void dumpParagraphsDom( boolean withText ) {
|
||||
Range range = _doc.getOverallRange();
|
||||
for ( int p = 0; p < range.numParagraphs(); p++ )
|
||||
{
|
||||
for ( int p = 0; p < range.numParagraphs(); p++ ) {
|
||||
Paragraph paragraph = range.getParagraph( p );
|
||||
System.out.println( p + ":\t" + paragraph);
|
||||
|
||||
|
@ -634,33 +555,27 @@ public final class HWPFLister
|
|||
}
|
||||
}
|
||||
|
||||
private void dumpPictures()
|
||||
{
|
||||
if ( _doc instanceof HWPFOldDocument )
|
||||
{
|
||||
private void dumpPictures() {
|
||||
if ( _doc instanceof HWPFOldDocument ) {
|
||||
System.out.println( "Word 95 not supported so far" );
|
||||
return;
|
||||
}
|
||||
|
||||
List<Picture> allPictures = ( (HWPFDocument) _doc ).getPicturesTable()
|
||||
.getAllPictures();
|
||||
for ( Picture picture : allPictures )
|
||||
{
|
||||
for ( Picture picture : allPictures ) {
|
||||
System.out.println(picture);
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpStyles()
|
||||
{
|
||||
if ( _doc instanceof HWPFOldDocument )
|
||||
{
|
||||
private void dumpStyles() {
|
||||
if ( _doc instanceof HWPFOldDocument ) {
|
||||
System.out.println( "Word 95 not supported so far" );
|
||||
return;
|
||||
}
|
||||
HWPFDocument hwpfDocument = (HWPFDocument) _doc;
|
||||
|
||||
for ( int s = 0; s < hwpfDocument.getStyleSheet().numStyles(); s++ )
|
||||
{
|
||||
for ( int s = 0; s < hwpfDocument.getStyleSheet().numStyles(); s++ ) {
|
||||
StyleDescription styleDescription = hwpfDocument.getStyleSheet()
|
||||
.getStyleDescription( s );
|
||||
if ( styleDescription == null )
|
||||
|
@ -681,32 +596,27 @@ public final class HWPFLister
|
|||
}
|
||||
|
||||
protected void dumpParagraphLevels( ListTables listTables,
|
||||
ParagraphProperties paragraph )
|
||||
{
|
||||
if ( paragraph.getIlfo() != 0 )
|
||||
{
|
||||
ParagraphProperties paragraph ) {
|
||||
if ( paragraph.getIlfo() != 0 ) {
|
||||
final LFO lfo = listTables.getLfo( paragraph.getIlfo() );
|
||||
System.out.println( "PAP's LFO: " + lfo );
|
||||
|
||||
final LFOData lfoData = listTables.getLfoData( paragraph.getIlfo() );
|
||||
System.out.println( "PAP's LFOData: " + lfoData );
|
||||
|
||||
if ( lfo != null )
|
||||
{
|
||||
if ( lfo != null ) {
|
||||
final ListLevel listLevel = listTables.getLevel( lfo.getLsid(),
|
||||
paragraph.getIlvl() );
|
||||
|
||||
System.out.println( "PAP's ListLevel: " + listLevel );
|
||||
if ( listLevel.getGrpprlPapx() != null )
|
||||
{
|
||||
if ( listLevel.getGrpprlPapx() != null ) {
|
||||
System.out.println( "PAP's ListLevel PAPX:" );
|
||||
dumpSprms(
|
||||
new SprmIterator( listLevel.getGrpprlPapx(), 0 ),
|
||||
"* " );
|
||||
}
|
||||
|
||||
if ( listLevel.getGrpprlPapx() != null )
|
||||
{
|
||||
if ( listLevel.getGrpprlPapx() != null ) {
|
||||
System.out.println( "PAP's ListLevel CHPX:" );
|
||||
dumpSprms(
|
||||
new SprmIterator( listLevel.getGrpprlChpx(), 0 ),
|
||||
|
@ -716,14 +626,11 @@ public final class HWPFLister
|
|||
}
|
||||
}
|
||||
|
||||
public void dumpTextPieces( boolean withText )
|
||||
{
|
||||
for ( TextPiece textPiece : _doc.getTextTable().getTextPieces() )
|
||||
{
|
||||
public void dumpTextPieces( boolean withText ) {
|
||||
for ( TextPiece textPiece : _doc.getTextTable().getTextPieces() ) {
|
||||
System.out.println( textPiece );
|
||||
|
||||
if ( withText )
|
||||
{
|
||||
if ( withText ) {
|
||||
System.out.println( "\t" + textPiece.getStringBuilder() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,22 +31,18 @@ import org.apache.poi.util.Internal;
|
|||
* v20110608 Word (.doc) Binary File Format
|
||||
*/
|
||||
@Internal
|
||||
public class FibBase extends FibBaseAbstractType
|
||||
{
|
||||
public class FibBase extends FibBaseAbstractType {
|
||||
|
||||
public FibBase()
|
||||
{
|
||||
public FibBase() {
|
||||
}
|
||||
|
||||
public FibBase( byte[] std, int offset )
|
||||
{
|
||||
public FibBase( byte[] std, int offset ) {
|
||||
fillFields( std, offset );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( "deprecation" )
|
||||
public boolean equals( Object obj )
|
||||
{
|
||||
public boolean equals( Object obj ) {
|
||||
if ( this == obj )
|
||||
return true;
|
||||
if ( obj == null )
|
||||
|
@ -87,8 +83,7 @@ public class FibBase extends FibBaseAbstractType
|
|||
|
||||
@Override
|
||||
@SuppressWarnings( "deprecation" )
|
||||
public int hashCode()
|
||||
{
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + field_10_flags2;
|
||||
|
@ -107,5 +102,4 @@ public class FibBase extends FibBaseAbstractType
|
|||
result = prime * result + field_9_envr;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -286,4 +286,35 @@ public class TestVBAMacroReader {
|
|||
assertContains(content, "Attribute VB_Customizable = True");
|
||||
r.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bug62624() throws IOException {
|
||||
//macro comes from Common Crawl: HRLOXHGMGLFIJQQU27RIWXOARRHAAAAS
|
||||
File f = POIDataSamples.getSpreadSheetInstance().getFile("62624.bin");
|
||||
VBAMacroReader r = new VBAMacroReader(f);
|
||||
|
||||
Map<String, Module> macros = r.readMacroModules();
|
||||
assertEquals(13, macros.size());
|
||||
assertNotNull(macros.get("M\u00F3dulo1"));
|
||||
assertContains(macros.get("M\u00F3dulo1").getContent(), "Calcula_tributos");
|
||||
assertEquals(Module.ModuleType.Module, macros.get("M\u00F3dulo1").geModuleType());
|
||||
r.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bug62625() throws IOException {
|
||||
//macro comes from Common Crawl: 4BZ22N5QG5R2SUU2MNN47PO7VBQLNYIQ
|
||||
//A REFERENCE_NAME can sometimes only have an ascii string without
|
||||
//a reserved byte followed by the unicode string.
|
||||
//See https://github.com/decalage2/oletools/blob/master/oletools/olevba.py#L1516
|
||||
//and https://github.com/decalage2/oletools/pull/135 from (@c1fe)
|
||||
|
||||
|
||||
File f = POIDataSamples.getSpreadSheetInstance().getFile("62625.bin");
|
||||
VBAMacroReader r = new VBAMacroReader(f);
|
||||
|
||||
Map<String, Module> macros = r.readMacroModules();
|
||||
assertEquals(20, macros.size());
|
||||
r.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.junit.runners.Suite;
|
|||
TestQuotientFunctionsFromSpreadsheet.class,
|
||||
TestReptFunctionsFromSpreadsheet.class,
|
||||
TestRomanFunctionsFromSpreadsheet.class,
|
||||
TestTrendFunctionsFromSpreadsheet.class,
|
||||
TestWeekNumFunctionsFromSpreadsheet.class,
|
||||
TestWeekNumFunctionsFromSpreadsheet2013.class
|
||||
})
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.apache.poi.ss.formula.functions.Frequency.histogram;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Testcase for the function FREQUENCY(data, bins)
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestFrequency {
|
||||
|
||||
@Test
|
||||
public void testHistogram() {
|
||||
assertArrayEquals(new int[]{3, 2, 2, 0, 1, 1},
|
||||
histogram(
|
||||
new double[]{11, 12, 13, 21, 29, 36, 40, 58, 69},
|
||||
new double[]{20, 30, 40, 50, 60})
|
||||
);
|
||||
|
||||
assertArrayEquals(new int[]{1, 1, 1, 1, 1, 0},
|
||||
histogram(
|
||||
new double[]{20, 30, 40, 50, 60},
|
||||
new double[]{20, 30, 40, 50, 60})
|
||||
|
||||
);
|
||||
|
||||
assertArrayEquals(new int[]{2, 3},
|
||||
histogram(
|
||||
new double[]{20, 30, 40, 50, 60},
|
||||
new double[]{30})
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEvaluate() {
|
||||
Workbook wb = new HSSFWorkbook();
|
||||
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
|
||||
|
||||
int[] data = {1, 1, 2, 3, 4, 4, 5, 7, 8, 9, 9, 11, 3, 5, 8};
|
||||
int[] bins = {3, 6, 9};
|
||||
Sheet sheet = wb.createSheet();
|
||||
Row dataRow = sheet.createRow(0); // A1:O1
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
dataRow.createCell(i).setCellValue(data[i]);
|
||||
}
|
||||
Row binsRow = sheet.createRow(1);
|
||||
for (int i = 0; i < bins.length; i++) { // A2:C2
|
||||
binsRow.createCell(i).setCellValue(bins[i]);
|
||||
}
|
||||
Row fmlaRow = sheet.createRow(2);
|
||||
CellRange<? extends Cell> arrayFmla = sheet.setArrayFormula("FREQUENCY(A1:O1,A2:C2)", CellRangeAddress.valueOf("A3:A6"));
|
||||
Cell b3 = fmlaRow.createCell(1); // B3
|
||||
b3.setCellFormula("COUNT(FREQUENCY(A1:O1,A2:C2))"); // frequency returns a vertical array of bins+1
|
||||
|
||||
Cell c3 = fmlaRow.createCell(2);
|
||||
c3.setCellFormula("SUM(FREQUENCY(A1:O1,A2:C2))"); // sum of the frequency bins should add up to the number of data values
|
||||
|
||||
assertEquals(5, (int) evaluator.evaluate(arrayFmla.getFlattenedCells()[0]).getNumberValue());
|
||||
assertEquals(4, (int) evaluator.evaluate(arrayFmla.getFlattenedCells()[1]).getNumberValue());
|
||||
assertEquals(5, (int) evaluator.evaluate(arrayFmla.getFlattenedCells()[2]).getNumberValue());
|
||||
assertEquals(1, (int) evaluator.evaluate(arrayFmla.getFlattenedCells()[3]).getNumberValue());
|
||||
|
||||
assertEquals(4, (int) evaluator.evaluate(b3).getNumberValue());
|
||||
assertEquals(15, (int) evaluator.evaluate(c3).getNumberValue());
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Tests TREND() as loaded from a test data spreadsheet.
|
||||
*/
|
||||
public class TestTrendFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
|
||||
@Parameters(name="{0}")
|
||||
public static Collection<Object[]> data() throws Exception {
|
||||
return data(TestTrendFunctionsFromSpreadsheet.class, "Trend.xls");
|
||||
}
|
||||
}
|
|
@ -99,15 +99,6 @@ public final class TestDateFormatConverter {
|
|||
row.createCell(5).setCellValue(javaDateFormatPattern);
|
||||
row.createCell(6).setCellValue(excelFormatPattern);
|
||||
} catch (Exception e) {
|
||||
// this can be removed after https://bugs.openjdk.java.net/browse/JDK-8209047 is available
|
||||
// in JDK 11 ea > 26
|
||||
if(locale.toString().startsWith("my") &&
|
||||
e.getMessage().contains("Illegal pattern character 'B'") &&
|
||||
System.getProperty("java.version").startsWith("11")) {
|
||||
System.out.println("DateFormat.getDateTimeInstance() fails for Malaysian Locale on JDK 11, submitted bug report to Oracle");
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new RuntimeException(
|
||||
"Failed for locale: " + locale + " and style " + style + "\n" +
|
||||
"Having locales: " + Arrays.toString(DateFormat.getAvailableLocales()), e);
|
||||
|
@ -153,7 +144,6 @@ public final class TestDateFormatConverter {
|
|||
DateFormatConverter.getPrefixForLocale(new Locale(""));
|
||||
}
|
||||
|
||||
@Ignore("Fails on JDK 11, submitted as ID : 9056763")
|
||||
@Test
|
||||
public void testJDK11MyLocale() {
|
||||
DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.forLanguageTag("my"));
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,284 @@
|
|||
RkNumber
|
||||
10000000
|
||||
1200455
|
||||
0.01
|
||||
12004.55
|
||||
-10000000
|
||||
-1200455
|
||||
-0.01
|
||||
-12004.55
|
||||
10268609
|
||||
1071427521
|
||||
-1071427521
|
||||
273214017855
|
||||
69942788570880
|
||||
17905353874145300
|
||||
17835411085574400
|
||||
273214017855
|
||||
273214017856
|
||||
273214017857
|
||||
273214017858
|
||||
273214017859
|
||||
273214017860
|
||||
273214017861
|
||||
273214017862
|
||||
273214017863
|
||||
273214017864
|
||||
273214017865
|
||||
273214017866
|
||||
273214017867
|
||||
273214017868
|
||||
273214017869
|
||||
273214017870
|
||||
273214017871
|
||||
273214017872
|
||||
273214017873
|
||||
273214017874
|
||||
273214017875
|
||||
273214017876
|
||||
273214017877
|
||||
273214017878
|
||||
273214017879
|
||||
273214017880
|
||||
273214017881
|
||||
273214017882
|
||||
273214017883
|
||||
273214017884
|
||||
273214017885
|
||||
273214017886
|
||||
273214017887
|
||||
273214017888
|
||||
273214017889
|
||||
273214017890
|
||||
273214017891
|
||||
273214017892
|
||||
273214017893
|
||||
273214017894
|
||||
273214017895
|
||||
273214017896
|
||||
273214017897
|
||||
273214017898
|
||||
273214017899
|
||||
273214017900
|
||||
273214017901
|
||||
273214017902
|
||||
273214017903
|
||||
273214017904
|
||||
273214017905
|
||||
273214017906
|
||||
273214017907
|
||||
273214017908
|
||||
273214017909
|
||||
273214017910
|
||||
273214017911
|
||||
273214017912
|
||||
273214017913
|
||||
273214017914
|
||||
273214017915
|
||||
273214017916
|
||||
273214017917
|
||||
273214017918
|
||||
273214017919
|
||||
273214017920
|
||||
273214017921
|
||||
273214017922
|
||||
273214017923
|
||||
273214017924
|
||||
273214017925
|
||||
273214017926
|
||||
273214017927
|
||||
273214017928
|
||||
273214017929
|
||||
273214017930
|
||||
273214017931
|
||||
273214017932
|
||||
273214017933
|
||||
273214017934
|
||||
273214017935
|
||||
273214017936
|
||||
273214017937
|
||||
273214017938
|
||||
273214017939
|
||||
273214017940
|
||||
273214017941
|
||||
273214017942
|
||||
273214017943
|
||||
273214017944
|
||||
273214017945
|
||||
273214017946
|
||||
273214017947
|
||||
273214017948
|
||||
273214017949
|
||||
273214017950
|
||||
273214017951
|
||||
273214017952
|
||||
273214017953
|
||||
273214017954
|
||||
273214017955
|
||||
273214017956
|
||||
273214017957
|
||||
273214017958
|
||||
273214017959
|
||||
273214017960
|
||||
273214017961
|
||||
273214017962
|
||||
273214017963
|
||||
273214017964
|
||||
273214017965
|
||||
273214017966
|
||||
273214017967
|
||||
273214017968
|
||||
273214017969
|
||||
273214017970
|
||||
273214017971
|
||||
273214017972
|
||||
273214017973
|
||||
273214017974
|
||||
273214017975
|
||||
273214017976
|
||||
273214017977
|
||||
273214017978
|
||||
273214017979
|
||||
273214017980
|
||||
273214017981
|
||||
273214017982
|
||||
273214017983
|
||||
273214017984
|
||||
273214017985
|
||||
273214017986
|
||||
273214017987
|
||||
273214017988
|
||||
273214017989
|
||||
273214017990
|
||||
273214017991
|
||||
273214017992
|
||||
273214017993
|
||||
273214017994
|
||||
273214017995
|
||||
273214017996
|
||||
273214017997
|
||||
273214017998
|
||||
273214017999
|
||||
273214018000
|
||||
273214018001
|
||||
273214018002
|
||||
273214018003
|
||||
273214018004
|
||||
273214018005
|
||||
273214018006
|
||||
273214018007
|
||||
273214018008
|
||||
273214018009
|
||||
273214018010
|
||||
273214018011
|
||||
273214018012
|
||||
273214018013
|
||||
273214018014
|
||||
273214018015
|
||||
273214018016
|
||||
273214018017
|
||||
273214018018
|
||||
273214018019
|
||||
273214018020
|
||||
273214018021
|
||||
273214018022
|
||||
273214018023
|
||||
273214018024
|
||||
273214018025
|
||||
273214018026
|
||||
273214018027
|
||||
273214018028
|
||||
273214018029
|
||||
273214018030
|
||||
273214018031
|
||||
273214018032
|
||||
273214018033
|
||||
273214018034
|
||||
273214018035
|
||||
273214018036
|
||||
273214018037
|
||||
273214018038
|
||||
273214018039
|
||||
273214018040
|
||||
273214018041
|
||||
273214018042
|
||||
273214018043
|
||||
273214018044
|
||||
273214018045
|
||||
273214018046
|
||||
273214018047
|
||||
273214018048
|
||||
273214018049
|
||||
273214018050
|
||||
273214018051
|
||||
273214018052
|
||||
273214018053
|
||||
273214018054
|
||||
273214018055
|
||||
273214018056
|
||||
273214018057
|
||||
273214018058
|
||||
273214018059
|
||||
273214018060
|
||||
273214018061
|
||||
273214018062
|
||||
273214018063
|
||||
273214018064
|
||||
273214018065
|
||||
273214018066
|
||||
273214018067
|
||||
273214018068
|
||||
273214018069
|
||||
273214018070
|
||||
273214018071
|
||||
273214018072
|
||||
273214018073
|
||||
273214018074
|
||||
273214018075
|
||||
273214018076
|
||||
273214018077
|
||||
273214018078
|
||||
273214018079
|
||||
273214018080
|
||||
273214018081
|
||||
273214018082
|
||||
273214018083
|
||||
273214018084
|
||||
273214018085
|
||||
273214018086
|
||||
273214018087
|
||||
273214018088
|
||||
273214018089
|
||||
273214018090
|
||||
273214018091
|
||||
273214018092
|
||||
273214018093
|
||||
273214018094
|
||||
273214018095
|
||||
273214018096
|
||||
273214018097
|
||||
273214018098
|
||||
273214018099
|
||||
273214018100
|
||||
273214018101
|
||||
273214018102
|
||||
273214018103
|
||||
273214018104
|
||||
273214018105
|
||||
273214018106
|
||||
273214018107
|
||||
273214018108
|
||||
273214018109
|
||||
273214018110
|
||||
273214018111
|
||||
273214018112
|
||||
273214018113
|
||||
273214018114
|
||||
273214018115
|
||||
910713.3937166670
|
||||
3.03571131238889
|
||||
0.000010119037707963000
|
||||
3.37E-11
|
||||
1.12E-16
|
||||
#excel doesn't display ...863, this was manually altered to get the test to work
|
||||
3.7477917436899863E-22
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue