mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
2456 lines
105 KiB
XML
2456 lines
105 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!--
|
||
====================================================================
|
||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||
contributor license agreements. See the NOTICE file distributed with
|
||
this work for additional information regarding copyright ownership.
|
||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||
(the "License"); you may not use this file except in compliance with
|
||
the License. You may obtain a copy of the License at
|
||
|
||
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
||
Unless required by applicable law or agreed to in writing, software
|
||
distributed under the License is distributed on an "AS IS" BASIS,
|
||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
====================================================================
|
||
-->
|
||
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "document-v20.dtd">
|
||
|
||
<document>
|
||
<header>
|
||
<title>Busy Developers' Guide to HSSF and XSSF Features</title>
|
||
</header>
|
||
<body>
|
||
<section><title>Busy Developers' Guide to Features</title>
|
||
<p>
|
||
Want to use HSSF and XSSF read and write spreadsheets in a hurry? This
|
||
guide is for you. If you're after more in-depth coverage of the HSSF and
|
||
XSSF user-APIs, please consult the <a href="how-to.html">HOWTO</a>
|
||
guide as it contains actual descriptions of how to use this stuff.
|
||
</p>
|
||
<section><title>Index of Features</title>
|
||
<ul>
|
||
<li><a href="#NewWorkbook">How to create a new workbook</a></li>
|
||
<li><a href="#NewSheet">How to create a sheet</a></li>
|
||
<li><a href="#CreateCells">How to create cells</a></li>
|
||
<li><a href="#CreateDateCells">How to create date cells</a></li>
|
||
<li><a href="#CellTypes">Working with different types of cells</a></li>
|
||
<li><a href="#Iterator">Iterate over rows and cells</a></li>
|
||
<li><a href="#CellContents">Getting the cell contents</a></li>
|
||
<li><a href="#TextExtraction">Text Extraction</a></li>
|
||
<li><a href="#FileInputStream">Files vs InputStreams</a></li>
|
||
<li><a href="#Alignment">Aligning cells</a></li>
|
||
<li><a href="#Borders">Working with borders</a></li>
|
||
<li><a href="#FillsAndFrills">Fills and color</a></li>
|
||
<li><a href="#MergedCells">Merging cells</a></li>
|
||
<li><a href="#WorkingWithFonts">Working with fonts</a></li>
|
||
<li><a href="#CustomColors">Custom colors</a></li>
|
||
<li><a href="#ReadWriteWorkbook">Reading and writing</a></li>
|
||
<li><a href="#NewLinesInCells">Use newlines in cells.</a></li>
|
||
<li><a href="#DataFormats">Create user defined data formats</a></li>
|
||
<li><a href="#FitTo">Fit Sheet to One Page</a></li>
|
||
<li><a href="#PrintArea2">Set print area for a sheet</a></li>
|
||
<li><a href="#FooterPageNumbers">Set page numbers on the footer of a sheet</a></li>
|
||
<li><a href="#ShiftRows">Shift rows</a></li>
|
||
<li><a href="#SelectSheet">Set a sheet as selected</a></li>
|
||
<li><a href="#Zoom">Set the zoom magnification for a sheet</a></li>
|
||
<li><a href="#Splits">Create split and freeze panes</a></li>
|
||
<li><a href="#Repeating">Repeating rows and columns</a></li>
|
||
<li><a href="#HeaderFooter">Headers and Footers</a></li>
|
||
<li><a href="#XSSFHeaderFooter">XSSF enhancement for Headers and Footers</a></li>
|
||
<li><a href="#DrawingShapes">Drawing Shapes</a></li>
|
||
<li><a href="#StylingShapes">Styling Shapes</a></li>
|
||
<li><a href="#Graphics2d">Shapes and Graphics2d</a></li>
|
||
<li><a href="#Outlining">Outlining</a></li>
|
||
<li><a href="#Images">Images</a></li>
|
||
<li><a href="#NamedRanges">Named Ranges and Named Cells</a></li>
|
||
<li><a href="#CellComments">How to set cell comments</a></li>
|
||
<li><a href="#Autofit">How to adjust column width to fit the contents</a></li>
|
||
<li><a href="#Hyperlinks">Hyperlinks</a></li>
|
||
<li><a href="#Validation">Data Validations</a></li>
|
||
<li><a href="#Embedded">Embedded Objects</a></li>
|
||
<li><a href="#Autofilter">Autofilters</a></li>
|
||
<li><a href="#ConditionalFormatting">Conditional Formatting</a></li>
|
||
<li><a href="#Hiding">Hiding and Un-Hiding Rows</a></li>
|
||
<li><a href="#CellProperties">Setting Cell Properties</a></li>
|
||
<li><a href="#DrawingBorders">Drawing Borders</a></li>
|
||
<li><a href="#PivotTable">Create a Pivot Table</a></li>
|
||
<li><a href="#RichText">Cells with multiple styles</a></li>
|
||
</ul>
|
||
</section>
|
||
<section><title>Features</title>
|
||
<anchor id="NewWorkbook"/>
|
||
<section><title>New Workbook</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
...
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
Workbook wb = new XSSFWorkbook();
|
||
...
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xlsx")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="NewSheet"/>
|
||
<section><title>New Sheet</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook(); // or new XSSFWorkbook();
|
||
Sheet sheet1 = wb.createSheet("new sheet");
|
||
Sheet sheet2 = wb.createSheet("second sheet");
|
||
|
||
// Note that sheet name is Excel must not exceed 31 characters
|
||
// and must not contain any of the any of the following characters:
|
||
// 0x0000
|
||
// 0x0003
|
||
// colon (:)
|
||
// backslash (\)
|
||
// asterisk (*)
|
||
// question mark (?)
|
||
// forward slash (/)
|
||
// opening square bracket ([)
|
||
// closing square bracket (])
|
||
|
||
// You can use org.apache.poi.ss.util.WorkbookUtil#createSafeSheetName(String nameProposal)}
|
||
// for a safe way to create valid names, this utility replaces invalid characters with a space (' ')
|
||
String safeName = WorkbookUtil.createSafeSheetName("[O'Brien's sales*?]"); // returns " O'Brien's sales "
|
||
Sheet sheet3 = wb.createSheet(safeName);
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="CreateCells"/>
|
||
<section><title>Creating Cells</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
//Workbook wb = new XSSFWorkbook();
|
||
CreationHelper createHelper = wb.getCreationHelper();
|
||
Sheet sheet = wb.createSheet("new sheet");
|
||
|
||
// Create a row and put some cells in it. Rows are 0 based.
|
||
Row row = sheet.createRow(0);
|
||
// Create a cell and put a value in it.
|
||
Cell cell = row.createCell(0);
|
||
cell.setCellValue(1);
|
||
|
||
// Or do it on one line.
|
||
row.createCell(1).setCellValue(1.2);
|
||
row.createCell(2).setCellValue(
|
||
createHelper.createRichTextString("This is a string"));
|
||
row.createCell(3).setCellValue(true);
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="CreateDateCells"/>
|
||
<section><title>Creating Date Cells</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
//Workbook wb = new XSSFWorkbook();
|
||
CreationHelper createHelper = wb.getCreationHelper();
|
||
Sheet sheet = wb.createSheet("new sheet");
|
||
|
||
// Create a row and put some cells in it. Rows are 0 based.
|
||
Row row = sheet.createRow(0);
|
||
|
||
// Create a cell and put a date value in it. The first cell is not styled
|
||
// as a date.
|
||
Cell cell = row.createCell(0);
|
||
cell.setCellValue(new Date());
|
||
|
||
// we style the second cell as a date (and time). It is important to
|
||
// create a new cell style from the workbook otherwise you can end up
|
||
// modifying the built in style and effecting not only this cell but other cells.
|
||
CellStyle cellStyle = wb.createCellStyle();
|
||
cellStyle.setDataFormat(
|
||
createHelper.createDataFormat().getFormat("m/d/yy h:mm"));
|
||
cell = row.createCell(1);
|
||
cell.setCellValue(new Date());
|
||
cell.setCellStyle(cellStyle);
|
||
|
||
//you can also set date as java.util.Calendar
|
||
cell = row.createCell(2);
|
||
cell.setCellValue(Calendar.getInstance());
|
||
cell.setCellStyle(cellStyle);
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="CellTypes"/>
|
||
<section><title>Working with different types of cells</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("new sheet");
|
||
Row row = sheet.createRow(2);
|
||
row.createCell(0).setCellValue(1.1);
|
||
row.createCell(1).setCellValue(new Date());
|
||
row.createCell(2).setCellValue(Calendar.getInstance());
|
||
row.createCell(3).setCellValue("a string");
|
||
row.createCell(4).setCellValue(true);
|
||
row.createCell(5).setCellType(CellType.ERROR);
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="FileInputStream"/>
|
||
<section><title>Files vs InputStreams</title>
|
||
<p>When opening a workbook, either a .xls HSSFWorkbook, or a .xlsx
|
||
XSSFWorkbook, the Workbook can be loaded from either a <em>File</em>
|
||
or an <em>InputStream</em>. Using a <em>File</em> object allows for
|
||
lower memory consumption, while an <em>InputStream</em> requires more
|
||
memory as it has to buffer the whole file.</p>
|
||
<p>If using <em>WorkbookFactory</em>, it's very easy to use one or
|
||
the other:</p>
|
||
<source>
|
||
// Use a file
|
||
Workbook wb = WorkbookFactory.create(new File("MyExcel.xls"));
|
||
|
||
// Use an InputStream, needs more memory
|
||
Workbook wb = WorkbookFactory.create(new FileInputStream("MyExcel.xlsx"));
|
||
</source>
|
||
<p>If using <em>HSSFWorkbook</em> or <em>XSSFWorkbook</em> directly,
|
||
you should generally go through <em>POIFSFileSystem</em> or
|
||
<em>OPCPackage</em>, to have full control of the lifecycle (including
|
||
closing the file when done):</p>
|
||
<source>
|
||
// HSSFWorkbook, File
|
||
POIFSFileSystem fs = new POIFSFileSystem(new File("file.xls"));
|
||
HSSFWorkbook wb = new HSSFWorkbook(fs.getRoot(), true);
|
||
....
|
||
fs.close();
|
||
|
||
// HSSFWorkbook, InputStream, needs more memory
|
||
POIFSFileSystem fs = new POIFSFileSystem(myInputStream);
|
||
HSSFWorkbook wb = new HSSFWorkbook(fs.getRoot(), true);
|
||
|
||
// XSSFWorkbook, File
|
||
OPCPackage pkg = OPCPackage.open(new File("file.xlsx"));
|
||
XSSFWorkbook wb = new XSSFWorkbook(pkg);
|
||
....
|
||
pkg.close();
|
||
|
||
// XSSFWorkbook, InputStream, needs more memory
|
||
OPCPackage pkg = OPCPackage.open(myInputStream);
|
||
XSSFWorkbook wb = new XSSFWorkbook(pkg);
|
||
....
|
||
pkg.close();
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="Alignment"/>
|
||
<section><title>Demonstrates various alignment options</title>
|
||
<source>
|
||
public static void main(String[] args) throws Exception {
|
||
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
|
||
|
||
Sheet sheet = wb.createSheet();
|
||
Row row = sheet.createRow(2);
|
||
row.setHeightInPoints(30);
|
||
|
||
createCell(wb, row, 0, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
|
||
createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.BOTTOM);
|
||
createCell(wb, row, 2, HorizontalAlignment.FILL, VerticalAlignment.CENTER);
|
||
createCell(wb, row, 3, HorizontalAlignment.GENERAL, VerticalAlignment.CENTER);
|
||
createCell(wb, row, 4, HorizontalAlignment.JUSTIFY, VerticalAlignment.JUSTIFY);
|
||
createCell(wb, row, 5, HorizontalAlignment.LEFT, VerticalAlignment.TOP);
|
||
createCell(wb, row, 6, HorizontalAlignment.RIGHT, VerticalAlignment.TOP);
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("xssf-align.xlsx")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
}
|
||
|
||
/**
|
||
* Creates a cell and aligns it a certain way.
|
||
*
|
||
* @param wb the workbook
|
||
* @param row the row to create the cell in
|
||
* @param column the column number to create the cell in
|
||
* @param halign the horizontal alignment for the cell.
|
||
* @param valign the vertical alignment for the cell.
|
||
*/
|
||
private static void createCell(Workbook wb, Row row, int column, HorizontalAlignment halign, VerticalAlignment valign) {
|
||
Cell cell = row.createCell(column);
|
||
cell.setCellValue("Align It");
|
||
CellStyle cellStyle = wb.createCellStyle();
|
||
cellStyle.setAlignment(halign);
|
||
cellStyle.setVerticalAlignment(valign);
|
||
cell.setCellStyle(cellStyle);
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="Borders"/>
|
||
<section><title>Working with borders</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("new sheet");
|
||
|
||
// Create a row and put some cells in it. Rows are 0 based.
|
||
Row row = sheet.createRow(1);
|
||
|
||
// Create a cell and put a value in it.
|
||
Cell cell = row.createCell(1);
|
||
cell.setCellValue(4);
|
||
|
||
// Style the cell with borders all around.
|
||
CellStyle style = wb.createCellStyle();
|
||
style.setBorderBottom(BorderStyle.THIN);
|
||
style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
|
||
style.setBorderLeft(BorderStyle.THIN);
|
||
style.setLeftBorderColor(IndexedColors.GREEN.getIndex());
|
||
style.setBorderRight(BorderStyle.THIN);
|
||
style.setRightBorderColor(IndexedColors.BLUE.getIndex());
|
||
style.setBorderTop(BorderStyle.MEDIUM_DASHED);
|
||
style.setTopBorderColor(IndexedColors.BLACK.getIndex());
|
||
cell.setCellStyle(style);
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
<anchor id="Iterator"/>
|
||
<section><title>Iterate over rows and cells</title>
|
||
<p>Sometimes, you'd like to just iterate over all the sheets in
|
||
a workbook, all the rows in a sheet, or all the cells in a row.
|
||
This is possible with a simple for loop.</p>
|
||
<p>These iterators are available by calling <em>workbook.sheetIterator()</em>,
|
||
<em>sheet.rowIterator()</em>, and <em>row.cellIterator()</em>, or
|
||
implicitly using a for-each loop.
|
||
Note that a rowIterator and cellIterator iterate over rows or
|
||
cells that have been created, skipping empty rows and cells.</p>
|
||
|
||
<source>
|
||
for (Sheet sheet : wb ) {
|
||
for (Row row : sheet) {
|
||
for (Cell cell : row) {
|
||
// Do something here
|
||
}
|
||
}
|
||
}
|
||
</source>
|
||
</section>
|
||
<section><title>Iterate over cells, with control of missing / blank cells</title>
|
||
<p>In some cases, when iterating, you need full control over how
|
||
missing or blank rows and cells are treated, and you need to ensure
|
||
you visit every cell and not just those defined in the file. (The
|
||
CellIterator will only return the cells defined in the file, which
|
||
is largely those with values or stylings, but it depends on Excel).</p>
|
||
<p>In cases such as these, you should fetch the first and last column
|
||
information for a row, then call <em>getCell(int, MissingCellPolicy)</em>
|
||
to fetch the cell. Use a
|
||
<a href="../../apidocs/dev/org/apache/poi/ss/usermodel/Row.MissingCellPolicy.html">MissingCellPolicy</a>
|
||
to control how blank or null cells are handled.</p>
|
||
<source>
|
||
// Decide which rows to process
|
||
int rowStart = Math.min(15, sheet.getFirstRowNum());
|
||
int rowEnd = Math.max(1400, sheet.getLastRowNum());
|
||
|
||
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
|
||
Row r = sheet.getRow(rowNum);
|
||
if (r == null) {
|
||
// This whole row is empty
|
||
// Handle it as needed
|
||
continue;
|
||
}
|
||
|
||
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
|
||
|
||
for (int cn = 0; cn < lastColumn; cn++) {
|
||
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
|
||
if (c == null) {
|
||
// The spreadsheet is empty in this cell
|
||
} else {
|
||
// Do something useful with the cell's contents
|
||
}
|
||
}
|
||
}
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="CellContents"/>
|
||
<section><title>Getting the cell contents</title>
|
||
<p>To get the contents of a cell, you first need to
|
||
know what kind of cell it is (asking a string cell
|
||
for its numeric contents will get you a
|
||
NumberFormatException for example). So, you will
|
||
want to switch on the cell's type, and then call
|
||
the appropriate getter for that cell.</p>
|
||
<p>In the code below, we loop over every cell
|
||
in one sheet, print out the cell's reference
|
||
(eg A3), and then the cell's contents.</p>
|
||
<source>
|
||
// import org.apache.poi.ss.usermodel.*;
|
||
|
||
DataFormatter formatter = new DataFormatter();
|
||
Sheet sheet1 = wb.getSheetAt(0);
|
||
for (Row row : sheet1) {
|
||
for (Cell cell : row) {
|
||
CellReference cellRef = new CellReference(row.getRowNum(), cell.getColumnIndex());
|
||
System.out.print(cellRef.formatAsString());
|
||
System.out.print(" - ");
|
||
|
||
// get the text that appears in the cell by getting the cell value and applying any data formats (Date, 0.00, 1.23e9, $1.23, etc)
|
||
String text = formatter.formatCellValue(cell);
|
||
System.out.println(text);
|
||
|
||
// Alternatively, get the value and format it yourself
|
||
switch (cell.getCellType()) {
|
||
case CellType.STRING:
|
||
System.out.println(cell.getRichStringCellValue().getString());
|
||
break;
|
||
case CellType.NUMERIC:
|
||
if (DateUtil.isCellDateFormatted(cell)) {
|
||
System.out.println(cell.getDateCellValue());
|
||
} else {
|
||
System.out.println(cell.getNumericCellValue());
|
||
}
|
||
break;
|
||
case CellType.BOOLEAN:
|
||
System.out.println(cell.getBooleanCellValue());
|
||
break;
|
||
case CellType.FORMULA:
|
||
System.out.println(cell.getCellFormula());
|
||
break;
|
||
case CellType.BLANK:
|
||
System.out.println();
|
||
break;
|
||
default:
|
||
System.out.println();
|
||
}
|
||
}
|
||
}
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="TextExtraction"/>
|
||
<section><title>Text Extraction</title>
|
||
<p>For most text extraction requirements, the standard
|
||
ExcelExtractor class should provide all you need.</p>
|
||
<source>
|
||
try (InputStream inp = new FileInputStream("workbook.xls")) {
|
||
HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(inp));
|
||
ExcelExtractor extractor = new ExcelExtractor(wb);
|
||
|
||
extractor.setFormulasNotResults(true);
|
||
extractor.setIncludeSheetNames(false);
|
||
String text = extractor.getText();
|
||
wb.close();
|
||
}
|
||
</source>
|
||
<p>For very fancy text extraction, XLS to CSV etc,
|
||
take a look at
|
||
<em>/poi-examples/src/main/java/org/apache/poi/examples/hssf/eventusermodel/XLS2CSVmra.java</em>
|
||
</p>
|
||
</section>
|
||
<anchor id="FillsAndFrills"/>
|
||
<section><title>Fills and colors</title>
|
||
<source>
|
||
Workbook wb = new XSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("new sheet");
|
||
|
||
// Create a row and put some cells in it. Rows are 0 based.
|
||
Row row = sheet.createRow(1);
|
||
|
||
// Aqua background
|
||
CellStyle style = wb.createCellStyle();
|
||
style.setFillBackgroundColor(IndexedColors.AQUA.getIndex());
|
||
style.setFillPattern(FillPatternType.BIG_SPOTS);
|
||
Cell cell = row.createCell(1);
|
||
cell.setCellValue("X");
|
||
cell.setCellStyle(style);
|
||
|
||
// Orange "foreground", foreground being the fill foreground not the font color.
|
||
style = wb.createCellStyle();
|
||
style.setFillForegroundColor(IndexedColors.ORANGE.getIndex());
|
||
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||
cell = row.createCell(2);
|
||
cell.setCellValue("X");
|
||
cell.setCellStyle(style);
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
<anchor id="MergedCells"/>
|
||
<section><title>Merging cells</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("new sheet");
|
||
|
||
Row row = sheet.createRow(1);
|
||
Cell cell = row.createCell(1);
|
||
cell.setCellValue("This is a test of merging");
|
||
|
||
sheet.addMergedRegion(new CellRangeAddress(
|
||
1, //first row (0-based)
|
||
1, //last row (0-based)
|
||
1, //first column (0-based)
|
||
2 //last column (0-based)
|
||
));
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
<anchor id="WorkingWithFonts"/>
|
||
<section><title>Working with fonts</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("new sheet");
|
||
|
||
// Create a row and put some cells in it. Rows are 0 based.
|
||
Row row = sheet.createRow(1);
|
||
|
||
// Create a new font and alter it.
|
||
Font font = wb.createFont();
|
||
font.setFontHeightInPoints((short)24);
|
||
font.setFontName("Courier New");
|
||
font.setItalic(true);
|
||
font.setStrikeout(true);
|
||
|
||
// Fonts are set into a style so create a new one to use.
|
||
CellStyle style = wb.createCellStyle();
|
||
style.setFont(font);
|
||
|
||
// Create a cell and put a value in it.
|
||
Cell cell = row.createCell(1);
|
||
cell.setCellValue("This is a test of fonts");
|
||
cell.setCellStyle(style);
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
<p>
|
||
Note, the maximum number of unique fonts in a workbook is limited to 32767. You should re-use fonts in your applications instead of
|
||
creating a font for each cell.
|
||
Examples:
|
||
</p>
|
||
<p><strong>Wrong:</strong></p>
|
||
<source>
|
||
for (int i = 0; i < 10000; i++) {
|
||
Row row = sheet.createRow(i);
|
||
Cell cell = row.createCell(0);
|
||
|
||
CellStyle style = workbook.createCellStyle();
|
||
Font font = workbook.createFont();
|
||
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
|
||
style.setFont(font);
|
||
cell.setCellStyle(style);
|
||
}
|
||
</source>
|
||
<p><strong>Correct:</strong></p>
|
||
<source>
|
||
CellStyle style = workbook.createCellStyle();
|
||
Font font = workbook.createFont();
|
||
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
|
||
style.setFont(font);
|
||
for (int i = 0; i < 10000; i++) {
|
||
Row row = sheet.createRow(i);
|
||
Cell cell = row.createCell(0);
|
||
cell.setCellStyle(style);
|
||
}
|
||
</source>
|
||
|
||
</section>
|
||
<anchor id="CustomColors"/>
|
||
<section><title>Custom colors</title>
|
||
<p><strong>HSSF:</strong></p>
|
||
<source>
|
||
HSSFWorkbook wb = new HSSFWorkbook();
|
||
HSSFSheet sheet = wb.createSheet();
|
||
HSSFRow row = sheet.createRow(0);
|
||
HSSFCell cell = row.createCell(0);
|
||
cell.setCellValue("Default Palette");
|
||
|
||
//apply some colors from the standard palette,
|
||
// as in the previous examples.
|
||
//we'll use red text on a lime background
|
||
|
||
HSSFCellStyle style = wb.createCellStyle();
|
||
style.setFillForegroundColor(HSSFColor.LIME.index);
|
||
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||
|
||
HSSFFont font = wb.createFont();
|
||
font.setColor(HSSFColor.RED.index);
|
||
style.setFont(font);
|
||
|
||
cell.setCellStyle(style);
|
||
|
||
//save with the default palette
|
||
try (OutputStream out = new FileOutputStream("default_palette.xls")) {
|
||
wb.write(out);
|
||
}
|
||
|
||
//now, let's replace RED and LIME in the palette
|
||
// with a more attractive combination
|
||
// (lovingly borrowed from freebsd.org)
|
||
|
||
cell.setCellValue("Modified Palette");
|
||
|
||
//creating a custom palette for the workbook
|
||
HSSFPalette palette = wb.getCustomPalette();
|
||
|
||
//replacing the standard red with freebsd.org red
|
||
palette.setColorAtIndex(HSSFColor.RED.index,
|
||
(byte) 153, //RGB red (0-255)
|
||
(byte) 0, //RGB green
|
||
(byte) 0 //RGB blue
|
||
);
|
||
//replacing lime with freebsd.org gold
|
||
palette.setColorAtIndex(HSSFColor.LIME.index, (byte) 255, (byte) 204, (byte) 102);
|
||
|
||
//save with the modified palette
|
||
// note that wherever we have previously used RED or LIME, the
|
||
// new colors magically appear
|
||
try (out = new FileOutputStream("modified_palette.xls")) {
|
||
wb.write(out);
|
||
}
|
||
</source>
|
||
<p><strong>XSSF:</strong></p>
|
||
<source>
|
||
XSSFWorkbook wb = new XSSFWorkbook();
|
||
XSSFSheet sheet = wb.createSheet();
|
||
XSSFRow row = sheet.createRow(0);
|
||
XSSFCell cell = row.createCell( 0);
|
||
cell.setCellValue("custom XSSF colors");
|
||
|
||
XSSFCellStyle style1 = wb.createCellStyle();
|
||
style1.setFillForegroundColor(new XSSFColor(new java.awt.Color(128, 0, 128), new DefaultIndexedColorMap()));
|
||
style1.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||
</source>
|
||
</section>
|
||
<anchor id="ReadWriteWorkbook"/>
|
||
<section><title>Reading and Rewriting Workbooks</title>
|
||
<source>
|
||
try (InputStream inp = new FileInputStream("workbook.xls")) {
|
||
//InputStream inp = new FileInputStream("workbook.xlsx");
|
||
|
||
Workbook wb = WorkbookFactory.create(inp);
|
||
Sheet sheet = wb.getSheetAt(0);
|
||
Row row = sheet.getRow(2);
|
||
Cell cell = row.getCell(3);
|
||
if (cell == null)
|
||
cell = row.createCell(3);
|
||
cell.setCellType(CellType.STRING);
|
||
cell.setCellValue("a test");
|
||
|
||
// Write the output to a file
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="NewLinesInCells"/>
|
||
<section><title>Using newlines in cells</title>
|
||
<source>
|
||
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet();
|
||
|
||
Row row = sheet.createRow(2);
|
||
Cell cell = row.createCell(2);
|
||
cell.setCellValue("Use \n with word wrap on to create a new line");
|
||
|
||
//to enable newlines you need set a cell styles with wrap=true
|
||
CellStyle cs = wb.createCellStyle();
|
||
cs.setWrapText(true);
|
||
cell.setCellStyle(cs);
|
||
|
||
//increase row height to accommodate two lines of text
|
||
row.setHeightInPoints((2*sheet.getDefaultRowHeightInPoints()));
|
||
|
||
//adjust column width to fit the content
|
||
sheet.autoSizeColumn(2);
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("ooxml-newlines.xlsx")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
<anchor id="DataFormats"/>
|
||
<section><title>Data Formats</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("format sheet");
|
||
CellStyle style;
|
||
DataFormat format = wb.createDataFormat();
|
||
Row row;
|
||
Cell cell;
|
||
int rowNum = 0;
|
||
int colNum = 0;
|
||
|
||
row = sheet.createRow(rowNum++);
|
||
cell = row.createCell(colNum);
|
||
cell.setCellValue(11111.25);
|
||
style = wb.createCellStyle();
|
||
style.setDataFormat(format.getFormat("0.0"));
|
||
cell.setCellStyle(style);
|
||
|
||
row = sheet.createRow(rowNum++);
|
||
cell = row.createCell(colNum);
|
||
cell.setCellValue(11111.25);
|
||
style = wb.createCellStyle();
|
||
style.setDataFormat(format.getFormat("#,##0.0000"));
|
||
cell.setCellStyle(style);
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
<anchor id="FitTo"/>
|
||
<section><title>Fit Sheet to One Page</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("format sheet");
|
||
PrintSetup ps = sheet.getPrintSetup();
|
||
|
||
sheet.setAutobreaks(true);
|
||
|
||
ps.setFitHeight((short)1);
|
||
ps.setFitWidth((short)1);
|
||
|
||
|
||
// Create various cells and rows for spreadsheet.
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
<anchor id="PrintArea2"/>
|
||
<section><title>Set Print Area</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("Sheet1");
|
||
//sets the print area for the first sheet
|
||
wb.setPrintArea(0, "$A$1:$C$2");
|
||
|
||
//Alternatively:
|
||
wb.setPrintArea(
|
||
0, //sheet index
|
||
0, //start column
|
||
1, //end column
|
||
0, //start row
|
||
0 //end row
|
||
);
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="FooterPageNumbers"/>
|
||
<section><title>Set Page Numbers on Footer</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook(); // or new XSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("format sheet");
|
||
Footer footer = sheet.getFooter();
|
||
|
||
footer.setRight( "Page " + HeaderFooter.page() + " of " + HeaderFooter.numPages() );
|
||
|
||
|
||
|
||
// Create various cells and rows for spreadsheet.
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="ConvenienceFunctions"/>
|
||
<section><title>Using the Convenience Functions</title>
|
||
<p>
|
||
The convenience functions provide
|
||
utility features such as setting borders around merged
|
||
regions and changing style attributes without explicitly
|
||
creating new styles.
|
||
</p>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook(); // or new XSSFWorkbook()
|
||
Sheet sheet1 = wb.createSheet( "new sheet" );
|
||
|
||
// Create a merged region
|
||
Row row = sheet1.createRow( 1 );
|
||
Row row2 = sheet1.createRow( 2 );
|
||
Cell cell = row.createCell( 1 );
|
||
cell.setCellValue( "This is a test of merging" );
|
||
CellRangeAddress region = CellRangeAddress.valueOf("B2:E5");
|
||
sheet1.addMergedRegion( region );
|
||
|
||
// Set the border and border colors.
|
||
RegionUtil.setBorderBottom( BorderStyle.MEDIUM_DASHED, region, sheet1, wb );
|
||
RegionUtil.setBorderTop( BorderStyle.MEDIUM_DASHED, region, sheet1, wb );
|
||
RegionUtil.setBorderLeft( BorderStyle.MEDIUM_DASHED, region, sheet1, wb );
|
||
RegionUtil.setBorderRight( BorderStyle.MEDIUM_DASHED, region, sheet1, wb );
|
||
RegionUtil.setBottomBorderColor(IndexedColors.AQUA.getIndex(), region, sheet1, wb);
|
||
RegionUtil.setTopBorderColor( IndexedColors.AQUA.getIndex(), region, sheet1, wb);
|
||
RegionUtil.setLeftBorderColor( IndexedColors.AQUA.getIndex(), region, sheet1, wb);
|
||
RegionUtil.setRightBorderColor( IndexedColors.AQUA.getIndex(), region, sheet1, wb);
|
||
|
||
// Shows some usages of HSSFCellUtil
|
||
CellStyle style = wb.createCellStyle();
|
||
style.setIndention((short)4);
|
||
CellUtil.createCell(row, 8, "This is the value of the cell", style);
|
||
Cell cell2 = CellUtil.createCell( row2, 8, "This is the value of the cell");
|
||
CellUtil.setAlignment(cell2, HorizontalAlignment.CENTER);
|
||
|
||
// Write out the workbook
|
||
try (OutputStream fileOut = new FileOutputStream( "workbook.xls" )) {
|
||
wb.write( fileOut );
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="ShiftRows"/>
|
||
<section><title>Shift rows up or down on a sheet</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("row sheet");
|
||
|
||
// Create various cells and rows for spreadsheet.
|
||
|
||
// Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5)
|
||
sheet.shiftRows(5, 10, -5);
|
||
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="SelectSheet"/>
|
||
<section><title>Set a sheet as selected</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("row sheet");
|
||
sheet.setSelected(true);
|
||
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="Zoom"/>
|
||
<section><title>Set the zoom magnification</title>
|
||
<p>
|
||
The zoom is expressed as a fraction. For example to
|
||
express a zoom of 75% use 3 for the numerator and
|
||
4 for the denominator.
|
||
</p>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet1 = wb.createSheet("new sheet");
|
||
sheet1.setZoom(75); // 75 percent magnification
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="Splits"/>
|
||
<section><title>Splits and freeze panes</title>
|
||
<p>
|
||
There are two types of panes you can create; freeze panes and split panes.
|
||
</p>
|
||
<p>
|
||
A freeze pane is split by columns and rows. You create
|
||
a freeze pane using the following mechanism:
|
||
</p>
|
||
<p>
|
||
sheet1.createFreezePane( 3, 2, 3, 2 );
|
||
</p>
|
||
<p>
|
||
The first two parameters are the columns and rows you
|
||
wish to split by. The second two parameters indicate
|
||
the cells that are visible in the bottom right quadrant.
|
||
</p>
|
||
<p>
|
||
|
||
Split panes appear differently. The split area is
|
||
divided into four separate work area's. The split
|
||
occurs at the pixel level and the user is able to
|
||
adjust the split by dragging it to a new position.
|
||
</p>
|
||
<p>
|
||
|
||
Split panes are created with the following call:
|
||
</p>
|
||
<p>
|
||
sheet2.createSplitPane( 2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT );
|
||
</p>
|
||
<p>
|
||
|
||
The first parameter is the x position of the split.
|
||
This is in 1/20th of a point. A point in this case
|
||
seems to equate to a pixel. The second parameter is
|
||
the y position of the split. Again in 1/20th of a point.
|
||
</p>
|
||
<p>
|
||
The last parameter indicates which pane currently has
|
||
the focus. This will be one of Sheet.PANE_LOWER_LEFT,
|
||
PANE_LOWER_RIGHT, PANE_UPPER_RIGHT or PANE_UPPER_LEFT.
|
||
</p>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet1 = wb.createSheet("new sheet");
|
||
Sheet sheet2 = wb.createSheet("second sheet");
|
||
Sheet sheet3 = wb.createSheet("third sheet");
|
||
Sheet sheet4 = wb.createSheet("fourth sheet");
|
||
|
||
// Freeze just one row
|
||
sheet1.createFreezePane( 0, 1, 0, 1 );
|
||
// Freeze just one column
|
||
sheet2.createFreezePane( 1, 0, 1, 0 );
|
||
// Freeze the columns and rows (forget about scrolling position of the lower right quadrant).
|
||
sheet3.createFreezePane( 2, 2 );
|
||
// Create a split with the lower left side being the active quadrant
|
||
sheet4.createSplitPane( 2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT );
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="Repeating"/>
|
||
<section><title>Repeating rows and columns</title>
|
||
<p>
|
||
It's possible to set up repeating rows and columns in
|
||
your printouts by using the setRepeatingRows() and
|
||
setRepeatingColumns() methods in the Sheet class.
|
||
</p>
|
||
<p>
|
||
These methods expect a CellRangeAddress parameter
|
||
which specifies the range for the rows or columns to
|
||
repeat.
|
||
For setRepeatingRows(), it should specify a range of
|
||
rows to repeat, with the column part spanning all
|
||
columns.
|
||
For setRepeatingColumns(), it should specify a range of
|
||
columns to repeat, with the row part spanning all
|
||
rows.
|
||
If the parameter is null, the repeating rows or columns
|
||
will be removed.
|
||
</p>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook(); // or new XSSFWorkbook();
|
||
Sheet sheet1 = wb.createSheet("Sheet1");
|
||
Sheet sheet2 = wb.createSheet("Sheet2");
|
||
|
||
// Set the rows to repeat from row 4 to 5 on the first sheet.
|
||
sheet1.setRepeatingRows(CellRangeAddress.valueOf("4:5"));
|
||
// Set the columns to repeat from column A to C on the second sheet
|
||
sheet2.setRepeatingColumns(CellRangeAddress.valueOf("A:C"));
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="HeaderFooter"/>
|
||
<section><title>Headers and Footers</title>
|
||
<p>
|
||
Example is for headers but applies directly to footers.
|
||
</p>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet("new sheet");
|
||
|
||
Header header = sheet.getHeader();
|
||
header.setCenter("Center Header");
|
||
header.setLeft("Left Header");
|
||
header.setRight(HSSFHeader.font("Stencil-Normal", "Italic") +
|
||
HSSFHeader.fontSize((short) 16) + "Right w/ Stencil-Normal Italic font and size 16");
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="XSSFHeaderFooter"/>
|
||
<section><title>XSSF Enhancement for Headers and Footers</title>
|
||
<p>
|
||
Example is for headers but applies directly to footers. Note, the above example for
|
||
basic headers and footers applies to XSSF Workbooks as well as HSSF Workbooks. The HSSFHeader
|
||
stuff does not work for XSSF Workbooks.
|
||
</p>
|
||
<p>
|
||
XSSF has the ability to handle First page headers and footers, as well as Even/Odd
|
||
headers and footers. All Header/Footer Property flags can be handled in XSSF as well.
|
||
The odd header and footer is the default header and footer. It is displayed on all
|
||
pages that do not display either a first page header or an even page header. That is,
|
||
if the Even header/footer does not exist, then the odd header/footer is displayed on
|
||
even pages. If the first page header/footer does not exist, then the odd header/footer
|
||
is displayed on the first page. If the even/odd property is not set, that is the same as
|
||
the even header/footer not existing. If the first page property does not exist, that is
|
||
the same as the first page header/footer not existing.
|
||
</p>
|
||
<source>
|
||
Workbook wb = new XSSFWorkbook();
|
||
XSSFSheet sheet = (XSSFSheet) wb.createSheet("new sheet");
|
||
|
||
// Create a first page header
|
||
Header header = sheet.getFirstHeader();
|
||
header.setCenter("Center First Page Header");
|
||
header.setLeft("Left First Page Header");
|
||
header.setRight("Right First Page Header");
|
||
|
||
// Create an even page header
|
||
Header header2 = sheet.getEvenHeader();
|
||
header2.setCenter("Center Even Page Header");
|
||
header2.setLeft("Left Even Page Header");
|
||
header2.setRight("Right Even Page Header");
|
||
|
||
// Create an odd page header
|
||
Header header3 = sheet.getOddHeader();
|
||
header3.setCenter("Center Odd Page Header");
|
||
header3.setLeft("Left Odd Page Header");
|
||
header3.setRight("Right Odd Page Header");
|
||
|
||
// Set/Remove Header properties
|
||
XSSFHeaderProperties prop = sheet.getHeaderFooterProperties();
|
||
prop.setAlignWithMargins();
|
||
prop.scaleWithDoc();
|
||
prop.removeDifferentFirstPage(); // This does not remove first page headers or footers
|
||
prop.removeDifferentEvenOdd(); // This does not remove even headers or footers
|
||
|
||
try (OutputStream fileOut = new FileOutputStream("workbook.xlsx")) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="DrawingShapes"/>
|
||
<section><title>Drawing Shapes</title>
|
||
<p>
|
||
POI supports drawing shapes using the Microsoft Office
|
||
drawing tools. Shapes on a sheet are organized in a
|
||
hierarchy of groups and and shapes. The top-most shape
|
||
is the patriarch. This is not visible on the sheet
|
||
at all. To start drawing you need to call <code>createPatriarch</code>
|
||
on the <code>HSSFSheet</code> class. This has the
|
||
effect erasing any other shape information stored
|
||
in that sheet. By default POI will leave shape
|
||
records alone in the sheet unless you make a call to
|
||
this method.
|
||
</p>
|
||
<p>
|
||
To create a shape you have to go through the following
|
||
steps:
|
||
</p>
|
||
<ol>
|
||
<li>Create the patriarch.</li>
|
||
<li>Create an anchor to position the shape on the sheet.</li>
|
||
<li>Ask the patriarch to create the shape.</li>
|
||
<li>Set the shape type (line, oval, rectangle etc...)</li>
|
||
<li>Set any other style details concerning the shape. (eg:
|
||
line thickness, etc...)</li>
|
||
</ol>
|
||
<source>
|
||
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
|
||
a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 1, 0, (short) 1, 0 );
|
||
HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1);
|
||
shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
|
||
</source>
|
||
<p>
|
||
Text boxes are created using a different call:
|
||
</p>
|
||
<source>
|
||
HSSFTextbox textbox1 = patriarch.createTextbox(
|
||
new HSSFClientAnchor(0,0,0,0,(short)1,1,(short)2,2));
|
||
textbox1.setString(new HSSFRichTextString("This is a test") );
|
||
</source>
|
||
<p>
|
||
It's possible to use different fonts to style parts of
|
||
the text in the textbox. Here's how:
|
||
</p>
|
||
<source>
|
||
HSSFFont font = wb.createFont();
|
||
font.setItalic(true);
|
||
font.setUnderline(HSSFFont.U_DOUBLE);
|
||
HSSFRichTextString string = new HSSFRichTextString("Woo!!!");
|
||
string.applyFont(2,5,font);
|
||
textbox.setString(string );
|
||
</source>
|
||
<p>
|
||
Just as can be done manually using Excel, it is possible
|
||
to group shapes together. This is done by calling
|
||
<code>createGroup()</code> and then creating the shapes
|
||
using those groups.
|
||
</p>
|
||
<p>
|
||
It's also possible to create groups within groups.
|
||
</p>
|
||
<warning>Any group you create should contain at least two
|
||
other shapes or subgroups.</warning>
|
||
<p>
|
||
Here's how to create a shape group:
|
||
</p>
|
||
<source>
|
||
// Create a shape group.
|
||
HSSFShapeGroup group = patriarch.createGroup(
|
||
new HSSFClientAnchor(0,0,900,200,(short)2,2,(short)2,2));
|
||
|
||
// Create a couple of lines in the group.
|
||
HSSFSimpleShape shape1 = group.createShape(new HSSFChildAnchor(3,3,500,500));
|
||
shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
|
||
( (HSSFChildAnchor) shape1.getAnchor() ).setAnchor(3,3,500,500);
|
||
HSSFSimpleShape shape2 = group.createShape(new HSSFChildAnchor(1,200,400,600));
|
||
shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
|
||
</source>
|
||
<p>
|
||
If you're being observant you'll noticed that the shapes
|
||
that are added to the group use a new type of anchor:
|
||
the <code>HSSFChildAnchor</code>. What happens is that
|
||
the created group has its own coordinate space for
|
||
shapes that are placed into it. POI defaults this to
|
||
(0,0,1023,255) but you are able to change it as desired.
|
||
Here's how:
|
||
</p>
|
||
<source>
|
||
myGroup.setCoordinates(10,10,20,20); // top-left, bottom-right
|
||
</source>
|
||
<p>
|
||
If you create a group within a group it's also going
|
||
to have its own coordinate space.
|
||
</p>
|
||
</section>
|
||
|
||
<anchor id="StylingShapes"/>
|
||
<section><title>Styling Shapes</title>
|
||
<p>
|
||
By default shapes can look a little plain. It's possible
|
||
to apply different styles to the shapes however. The
|
||
sorts of things that can currently be done are:
|
||
</p>
|
||
<ul>
|
||
<li>Change the fill color.</li>
|
||
<li>Make a shape with no fill color.</li>
|
||
<li>Change the thickness of the lines.</li>
|
||
<li>Change the style of the lines. Eg: dashed, dotted.</li>
|
||
<li>Change the line color.</li>
|
||
</ul>
|
||
<p>
|
||
Here's an examples of how this is done:
|
||
</p>
|
||
<source>
|
||
HSSFSimpleShape s = patriarch.createSimpleShape(a);
|
||
s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_OVAL);
|
||
s.setLineStyleColor(10,10,10);
|
||
s.setFillColor(90,10,200);
|
||
s.setLineWidth(HSSFShape.LINEWIDTH_ONE_PT * 3);
|
||
s.setLineStyle(HSSFShape.LINESTYLE_DOTSYS);
|
||
</source>
|
||
</section>
|
||
<anchor id="Graphics2d"/>
|
||
<section><title>Shapes and Graphics2d</title>
|
||
<p>
|
||
While the native POI shape drawing commands are the
|
||
recommended way to draw shapes in a shape it's sometimes
|
||
desirable to use a standard API for compatibility with
|
||
external libraries. With this in mind we created some
|
||
wrappers for <code>Graphics</code> and <code>Graphics2d</code>.
|
||
</p>
|
||
<warning>
|
||
It's important to not however before continuing that
|
||
<code>Graphics2d</code> is a poor match to the capabilities
|
||
of the Microsoft Office drawing commands. The older
|
||
<code>Graphics</code> class offers a closer match but is
|
||
still a square peg in a round hole.
|
||
</warning>
|
||
<p>
|
||
All Graphics commands are issued into an <code>HSSFShapeGroup</code>.
|
||
Here's how it's done:
|
||
</p>
|
||
<source>
|
||
a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 1, 0, (short) 1, 0 );
|
||
group = patriarch.createGroup( a );
|
||
group.setCoordinates( 0, 0, 80 * 4 , 12 * 23 );
|
||
float verticalPointsPerPixel = a.getAnchorHeightInPoints(sheet) / (float)Math.abs(group.getY2() - group.getY1());
|
||
g = new EscherGraphics( group, wb, Color.black, verticalPointsPerPixel );
|
||
g2d = new EscherGraphics2d( g );
|
||
drawChemicalStructure( g2d );
|
||
</source>
|
||
<p>
|
||
The first thing we do is create the group and set its coordinates
|
||
to match what we plan to draw. Next we calculate a reasonable
|
||
fontSizeMultiplier then create the EscherGraphics object.
|
||
Since what we really want is a <code>Graphics2d</code>
|
||
object we create an EscherGraphics2d object and pass in
|
||
the graphics object we created. Finally we call a routine
|
||
that draws into the EscherGraphics2d object.
|
||
</p>
|
||
<p>
|
||
The vertical points per pixel deserves some more explanation.
|
||
One of the difficulties in converting Graphics calls
|
||
into escher drawing calls is that Excel does not have
|
||
the concept of absolute pixel positions. It measures
|
||
its cell widths in 'characters' and the cell heights in points.
|
||
Unfortunately it's not defined exactly what type of character it's
|
||
measuring. Presumably this is due to the fact that the Excel will be
|
||
using different fonts on different platforms or even within the same
|
||
platform.
|
||
</p>
|
||
<p>
|
||
Because of this constraint we've had to implement the concept of a
|
||
verticalPointsPerPixel. This the amount the font should be scaled by when
|
||
you issue commands such as drawString(). To calculate this value
|
||
use the follow formula:
|
||
</p>
|
||
<source>
|
||
multipler = groupHeightInPoints / heightOfGroup
|
||
</source>
|
||
<p>
|
||
The height of the group is calculated fairly simply by calculating the
|
||
difference between the y coordinates of the bounding box of the shape. The
|
||
height of the group can be calculated by using a convenience called
|
||
<code>HSSFClientAnchor.getAnchorHeightInPoints()</code>.
|
||
</p>
|
||
<p>
|
||
Many of the functions supported by the graphics classes
|
||
are not complete. Here's some of the functions that are known
|
||
to work.
|
||
</p>
|
||
<ul>
|
||
<li>fillRect()</li>
|
||
<li>fillOval()</li>
|
||
<li>drawString()</li>
|
||
<li>drawOval()</li>
|
||
<li>drawLine()</li>
|
||
<li>clearRect()</li>
|
||
</ul>
|
||
<p>
|
||
Functions that are not supported will return and log a message
|
||
using the POI logging infrastructure (disabled by default).
|
||
</p>
|
||
</section>
|
||
<anchor id="Outlining"/>
|
||
<section>
|
||
<title>Outlining</title>
|
||
<p>
|
||
Outlines are great for grouping sections of information
|
||
together and can be added easily to columns and rows
|
||
using the POI API. Here's how:
|
||
</p>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet1 = wb.createSheet("new sheet");
|
||
|
||
sheet1.groupRow( 5, 14 );
|
||
sheet1.groupRow( 7, 14 );
|
||
sheet1.groupRow( 16, 19 );
|
||
|
||
sheet1.groupColumn( 4, 7 );
|
||
sheet1.groupColumn( 9, 12 );
|
||
sheet1.groupColumn( 10, 11 );
|
||
|
||
try (OutputStream fileOut = new FileOutputStream(filename)) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
<p>
|
||
To collapse (or expand) an outline use the following calls:
|
||
</p>
|
||
<source>
|
||
sheet1.setRowGroupCollapsed( 7, true );
|
||
sheet1.setColumnGroupCollapsed( 4, true );
|
||
</source>
|
||
<p>
|
||
The row/column you choose should contain an already
|
||
created group. It can be anywhere within the group.
|
||
</p>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
<anchor id="Images"/>
|
||
<section>
|
||
<title>Images</title>
|
||
<p>
|
||
Images are part of the drawing support. To add an image just
|
||
call <code>createPicture()</code> on the drawing patriarch.
|
||
At the time of writing the following types are supported:
|
||
</p>
|
||
<ul>
|
||
<li>PNG</li>
|
||
<li>JPG</li>
|
||
<li>DIB</li>
|
||
</ul>
|
||
<p>
|
||
It should be noted that any existing drawings may be erased
|
||
once you add an image to a sheet.
|
||
</p>
|
||
<source>
|
||
//create a new workbook
|
||
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
|
||
|
||
//add picture data to this workbook.
|
||
InputStream is = new FileInputStream("image1.jpeg");
|
||
byte[] bytes = IOUtils.toByteArray(is);
|
||
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
|
||
is.close();
|
||
|
||
CreationHelper helper = wb.getCreationHelper();
|
||
|
||
//create sheet
|
||
Sheet sheet = wb.createSheet();
|
||
|
||
// Create the drawing patriarch. This is the top level container for all shapes.
|
||
Drawing drawing = sheet.createDrawingPatriarch();
|
||
|
||
//add a picture shape
|
||
ClientAnchor anchor = helper.createClientAnchor();
|
||
//set top-left corner of the picture,
|
||
//subsequent call of Picture#resize() will operate relative to it
|
||
anchor.setCol1(3);
|
||
anchor.setRow1(2);
|
||
Picture pict = drawing.createPicture(anchor, pictureIdx);
|
||
|
||
//auto-size picture relative to its top-left corner
|
||
pict.resize();
|
||
|
||
//save workbook
|
||
String file = "picture.xls";
|
||
if(wb instanceof XSSFWorkbook) file += "x";
|
||
try (OutputStream fileOut = new FileOutputStream(file)) {
|
||
wb.write(fileOut);
|
||
}
|
||
</source>
|
||
<warning>
|
||
Picture.resize() works only for JPEG and PNG. Other formats are not yet supported.
|
||
</warning>
|
||
<p>Reading images from a workbook:</p>
|
||
<source>
|
||
|
||
List lst = workbook.getAllPictures();
|
||
for (Iterator it = lst.iterator(); it.hasNext(); ) {
|
||
PictureData pict = (PictureData)it.next();
|
||
String ext = pict.suggestFileExtension();
|
||
byte[] data = pict.getData();
|
||
if (ext.equals("jpeg")){
|
||
try (OutputStream out = new FileOutputStream("pict.jpg")) {
|
||
out.write(data);
|
||
}
|
||
}
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="NamedRanges"/>
|
||
<section>
|
||
<title>Named Ranges and Named Cells</title>
|
||
<p>
|
||
Named Range is a way to refer to a group of cells by a name. Named Cell is a
|
||
degenerate case of Named Range in that the 'group of cells' contains exactly one
|
||
cell. You can create as well as refer to cells in a workbook by their named range.
|
||
When working with Named Ranges, the classes <code>org.apache.poi.ss.util.CellReference</code>
|
||
and <code>org.apache.poi.ss.util.AreaReference</code> are used.
|
||
</p>
|
||
<p>
|
||
Note: Using relative values like 'A1:B1' can lead to unexpected moving of
|
||
the cell that the name points to when working with the workbook in Microsoft Excel,
|
||
usually using absolute references like '$A$1:$B$1' avoids this, see also
|
||
<a href="https://superuser.com/a/1031047/126954">this discussion</a>.
|
||
</p>
|
||
<p>
|
||
Creating Named Range / Named Cell
|
||
</p>
|
||
<source>
|
||
// setup code
|
||
String sname = "TestSheet", cname = "TestName", cvalue = "TestVal";
|
||
Workbook wb = new HSSFWorkbook();
|
||
Sheet sheet = wb.createSheet(sname);
|
||
sheet.createRow(0).createCell(0).setCellValue(cvalue);
|
||
|
||
// 1. create named range for a single cell using areareference
|
||
Name namedCell = wb.createName();
|
||
namedCell.setNameName(cname + "1");
|
||
String reference = sname+"!$A$1:$A$1"; // area reference
|
||
namedCell.setRefersToFormula(reference);
|
||
|
||
// 2. create named range for a single cell using cellreference
|
||
Name namedCel2 = wb.createName();
|
||
namedCel2.setNameName(cname + "2");
|
||
reference = sname+"!$A$1"; // cell reference
|
||
namedCel2.setRefersToFormula(reference);
|
||
|
||
// 3. create named range for an area using AreaReference
|
||
Name namedCel3 = wb.createName();
|
||
namedCel3.setNameName(cname + "3");
|
||
reference = sname+"!$A$1:$C$5"; // area reference
|
||
namedCel3.setRefersToFormula(reference);
|
||
|
||
// 4. create named formula
|
||
Name namedCel4 = wb.createName();
|
||
namedCel4.setNameName("my_sum");
|
||
namedCel4.setRefersToFormula("SUM(" + sname + "!$I$2:$I$6)");
|
||
</source>
|
||
<p>
|
||
Reading from Named Range / Named Cell
|
||
</p>
|
||
<source>
|
||
// setup code
|
||
String cname = "TestName";
|
||
Workbook wb = getMyWorkbook(); // retrieve workbook
|
||
|
||
// retrieve the named range
|
||
int namedCellIdx = wb.getNameIndex(cellName);
|
||
Name aNamedCell = wb.getNameAt(namedCellIdx);
|
||
|
||
// retrieve the cell at the named range and test its contents
|
||
AreaReference aref = new AreaReference(aNamedCell.getRefersToFormula());
|
||
CellReference[] crefs = aref.getAllReferencedCells();
|
||
for (int i=0; i<crefs.length; i++) {
|
||
Sheet s = wb.getSheet(crefs[i].getSheetName());
|
||
Row r = sheet.getRow(crefs[i].getRow());
|
||
Cell c = r.getCell(crefs[i].getCol());
|
||
// extract the cell contents based on cell type etc.
|
||
}
|
||
</source>
|
||
<p>
|
||
Reading from non-contiguous Named Ranges
|
||
</p>
|
||
<source>
|
||
// Setup code
|
||
String cname = "TestName";
|
||
Workbook wb = getMyWorkbook(); // retrieve workbook
|
||
|
||
// Retrieve the named range
|
||
// Will be something like "$C$10,$D$12:$D$14";
|
||
int namedCellIdx = wb.getNameIndex(cellName);
|
||
Name aNamedCell = wb.getNameAt(namedCellIdx);
|
||
|
||
// Retrieve the cell at the named range and test its contents
|
||
// Will get back one AreaReference for C10, and
|
||
// another for D12 to D14
|
||
AreaReference[] arefs = AreaReference.generateContiguous(aNamedCell.getRefersToFormula());
|
||
for (int i=0; i<arefs.length; i++) {
|
||
// Only get the corners of the Area
|
||
// (use arefs[i].getAllReferencedCells() to get all cells)
|
||
CellReference[] crefs = arefs[i].getCells();
|
||
for (int j=0; j<crefs.length; j++) {
|
||
// Check it turns into real stuff
|
||
Sheet s = wb.getSheet(crefs[j].getSheetName());
|
||
Row r = s.getRow(crefs[j].getRow());
|
||
Cell c = r.getCell(crefs[j].getCol());
|
||
// Do something with this corner cell
|
||
}
|
||
}
|
||
</source>
|
||
<p>
|
||
Note, when a cell is deleted, Excel does not delete the
|
||
attached named range. As result, workbook can contain
|
||
named ranges that point to cells that no longer exist.
|
||
You should check the validity of a reference before
|
||
constructing AreaReference
|
||
</p>
|
||
<source>
|
||
if(name.isDeleted()){
|
||
//named range points to a deleted cell.
|
||
} else {
|
||
AreaReference ref = new AreaReference(name.getRefersToFormula());
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="CellComments"/>
|
||
<section><title>Cell Comments - HSSF and XSSF</title>
|
||
<p>
|
||
A comment is a rich text note that is attached to &
|
||
associated with a cell, separate from other cell content.
|
||
Comment content is stored separate from the cell, and is displayed in a drawing object (like a text box)
|
||
that is separate from, but associated with, a cell
|
||
</p>
|
||
<source>
|
||
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
|
||
|
||
CreationHelper factory = wb.getCreationHelper();
|
||
|
||
Sheet sheet = wb.createSheet();
|
||
|
||
Row row = sheet.createRow(3);
|
||
Cell cell = row.createCell(5);
|
||
cell.setCellValue("F4");
|
||
|
||
Drawing drawing = sheet.createDrawingPatriarch();
|
||
|
||
// When the comment box is visible, have it show in a 1x3 space
|
||
ClientAnchor anchor = factory.createClientAnchor();
|
||
anchor.setCol1(cell.getColumnIndex());
|
||
anchor.setCol2(cell.getColumnIndex()+1);
|
||
anchor.setRow1(row.getRowNum());
|
||
anchor.setRow2(row.getRowNum()+3);
|
||
|
||
// Create the comment and set the text+author
|
||
Comment comment = drawing.createCellComment(anchor);
|
||
RichTextString str = factory.createRichTextString("Hello, World!");
|
||
comment.setString(str);
|
||
comment.setAuthor("Apache POI");
|
||
|
||
// Assign the comment to the cell
|
||
cell.setCellComment(comment);
|
||
|
||
String fname = "comment-xssf.xls";
|
||
if(wb instanceof XSSFWorkbook) fname += "x";
|
||
try (OutputStream out = new FileOutputStream(fname)) {
|
||
wb.write(out);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
<p>
|
||
Reading cell comments
|
||
</p>
|
||
<source>
|
||
Cell cell = sheet.get(3).getColumn(1);
|
||
Comment comment = cell.getCellComment();
|
||
if (comment != null) {
|
||
RichTextString str = comment.getString();
|
||
String author = comment.getAuthor();
|
||
}
|
||
// alternatively you can retrieve cell comments by (row, column)
|
||
comment = sheet.getCellComment(3, 1);
|
||
</source>
|
||
|
||
<p>To get all the comments on a sheet:</p>
|
||
<source>
|
||
Map<CellAddress, Comment> comments = sheet.getCellComments();
|
||
Comment commentA1 = comments.get(new CellAddress(0, 0));
|
||
Comment commentB1 = comments.get(new CellAddress(0, 1));
|
||
for (Entry<CellAddress, ? extends Comment> e : comments.entrySet()) {
|
||
CellAddress loc = e.getKey();
|
||
Comment comment = e.getValue();
|
||
System.out.println("Comment at " + loc + ": " +
|
||
"[" + comment.getAuthor() + "] " + comment.getString().getString());
|
||
}
|
||
</source>
|
||
</section>
|
||
|
||
<anchor id="Autofit"/>
|
||
<section><title>Adjust column width to fit the contents</title>
|
||
<source>
|
||
Sheet sheet = workbook.getSheetAt(0);
|
||
sheet.autoSizeColumn(0); //adjust width of the first column
|
||
sheet.autoSizeColumn(1); //adjust width of the second column
|
||
</source>
|
||
<p>
|
||
For SXSSFWorkbooks only, because the random access window is likely to exclude most of the rows
|
||
in the worksheet, which are needed for computing the best-fit width of a column, the columns must
|
||
be tracked for auto-sizing prior to flushing any rows.
|
||
</p>
|
||
<source>
|
||
SXSSFWorkbook workbook = new SXSSFWorkbook();
|
||
SXSSFSheet sheet = workbook.createSheet();
|
||
sheet.trackColumnForAutoSizing(0);
|
||
sheet.trackColumnForAutoSizing(1);
|
||
// If you have a Collection of column indices, see SXSSFSheet#trackColumnForAutoSizing(Collection<Integer>)
|
||
// or roll your own for-loop.
|
||
// Alternatively, use SXSSFSheet#trackAllColumnsForAutoSizing() if the columns that will be auto-sized aren't
|
||
// known in advance or you are upgrading existing code and are trying to minimize changes. Keep in mind
|
||
// that tracking all columns will require more memory and CPU cycles, as the best-fit width is calculated
|
||
// on all tracked columns on every row that is flushed.
|
||
|
||
// create some cells
|
||
for (int r=0; r < 10; r++) {
|
||
Row row = sheet.createRow(r);
|
||
for (int c; c < 10; c++) {
|
||
Cell cell = row.createCell(c);
|
||
cell.setCellValue("Cell " + c.getAddress().formatAsString());
|
||
}
|
||
}
|
||
|
||
// Auto-size the columns.
|
||
sheet.autoSizeColumn(0);
|
||
sheet.autoSizeColumn(1);
|
||
</source>
|
||
<p>
|
||
Note, that Sheet#autoSizeColumn() does not evaluate formula cells,
|
||
the width of formula cells is calculated based on the cached formula result.
|
||
If your workbook has many formulas then it is a good idea to evaluate them before auto-sizing.
|
||
</p>
|
||
<warning>
|
||
To calculate column width Sheet.autoSizeColumn uses Java2D classes
|
||
that throw exception if graphical environment is not available. In case if graphical environment
|
||
is not available, you must tell Java that you are running in headless mode and
|
||
set the following system property: <code> java.awt.headless=true </code>.
|
||
You should also ensure that the fonts you use in your workbook are
|
||
available to Java.
|
||
</warning>
|
||
</section>
|
||
<anchor id="Hyperlinks"/>
|
||
<section><title>How to read hyperlinks</title>
|
||
<source>
|
||
Sheet sheet = workbook.getSheetAt(0);
|
||
|
||
Cell cell = sheet.getRow(0).getCell(0);
|
||
Hyperlink link = cell.getHyperlink();
|
||
if(link != null){
|
||
System.out.println(link.getAddress());
|
||
}
|
||
</source>
|
||
</section>
|
||
<section><title>How to create hyperlinks</title>
|
||
<source>
|
||
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
|
||
CreationHelper createHelper = wb.getCreationHelper();
|
||
|
||
//cell style for hyperlinks
|
||
//by default hyperlinks are blue and underlined
|
||
CellStyle hlink_style = wb.createCellStyle();
|
||
Font hlink_font = wb.createFont();
|
||
hlink_font.setUnderline(Font.U_SINGLE);
|
||
hlink_font.setColor(IndexedColors.BLUE.getIndex());
|
||
hlink_style.setFont(hlink_font);
|
||
|
||
Cell cell;
|
||
Sheet sheet = wb.createSheet("Hyperlinks");
|
||
//URL
|
||
cell = sheet.createRow(0).createCell(0);
|
||
cell.setCellValue("URL Link");
|
||
|
||
Hyperlink link = createHelper.createHyperlink(HyperlinkType.URL);
|
||
link.setAddress("https://poi.apache.org/");
|
||
cell.setHyperlink(link);
|
||
cell.setCellStyle(hlink_style);
|
||
|
||
//link to a file in the current directory
|
||
cell = sheet.createRow(1).createCell(0);
|
||
cell.setCellValue("File Link");
|
||
link = createHelper.createHyperlink(HyperlinkType.FILE);
|
||
link.setAddress("link1.xls");
|
||
cell.setHyperlink(link);
|
||
cell.setCellStyle(hlink_style);
|
||
|
||
//e-mail link
|
||
cell = sheet.createRow(2).createCell(0);
|
||
cell.setCellValue("Email Link");
|
||
link = createHelper.createHyperlink(HyperlinkType.EMAIL);
|
||
//note, if subject contains white spaces, make sure they are url-encoded
|
||
link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
|
||
cell.setHyperlink(link);
|
||
cell.setCellStyle(hlink_style);
|
||
|
||
//link to a place in this workbook
|
||
|
||
//create a target sheet and cell
|
||
Sheet sheet2 = wb.createSheet("Target Sheet");
|
||
sheet2.createRow(0).createCell(0).setCellValue("Target Cell");
|
||
|
||
cell = sheet.createRow(3).createCell(0);
|
||
cell.setCellValue("Worksheet Link");
|
||
Hyperlink link2 = createHelper.createHyperlink(HyperlinkType.DOCUMENT);
|
||
link2.setAddress("'Target Sheet'!A1");
|
||
cell.setHyperlink(link2);
|
||
cell.setCellStyle(hlink_style);
|
||
|
||
try (OutputStream out = new FileOutputStream("hyperinks.xlsx")) {
|
||
wb.write(out);
|
||
}
|
||
|
||
wb.close();
|
||
</source>
|
||
</section>
|
||
<anchor id="Validation"/>
|
||
<section><title>Data Validations</title>
|
||
<p>
|
||
As of version 3.8, POI has slightly different syntax to work with data validations with .xls and .xlsx formats.
|
||
</p>
|
||
<section>
|
||
<title>hssf.usermodel (binary .xls format)</title>
|
||
<p><strong>Check the value a user enters into a cell against one or more predefined value(s).</strong></p>
|
||
<p>The following code will limit the value the user can enter into cell A1 to one of three integer values, 10, 20 or 30.</p>
|
||
<source>
|
||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||
HSSFSheet sheet = workbook.createSheet("Data Validation");
|
||
CellRangeAddressList addressList = new CellRangeAddressList(
|
||
0, 0, 0, 0);
|
||
DVConstraint dvConstraint = DVConstraint.createExplicitListConstraint(
|
||
new String[]{"10", "20", "30"});
|
||
DataValidation dataValidation = new HSSFDataValidation
|
||
(addressList, dvConstraint);
|
||
dataValidation.setSuppressDropDownArrow(true);
|
||
sheet.addValidationData(dataValidation);
|
||
</source>
|
||
<p><strong> Drop Down Lists:</strong></p>
|
||
<p>This code will do the same but offer the user a drop down list to select a value from.</p>
|
||
<source>
|
||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||
HSSFSheet sheet = workbook.createSheet("Data Validation");
|
||
CellRangeAddressList addressList = new CellRangeAddressList(
|
||
0, 0, 0, 0);
|
||
DVConstraint dvConstraint = DVConstraint.createExplicitListConstraint(
|
||
new String[]{"10", "20", "30"});
|
||
DataValidation dataValidation = new HSSFDataValidation
|
||
(addressList, dvConstraint);
|
||
dataValidation.setSuppressDropDownArrow(false);
|
||
sheet.addValidationData(dataValidation);
|
||
</source>
|
||
<p><strong>Messages On Error:</strong></p>
|
||
<p>To create a message box that will be shown to the user if the value they enter is invalid.</p>
|
||
<source>
|
||
dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
|
||
dataValidation.createErrorBox("Box Title", "Message Text");
|
||
</source>
|
||
<p>Replace 'Box Title' with the text you wish to display in the message box's title bar
|
||
and 'Message Text' with the text of your error message.</p>
|
||
<p><strong>Prompts:</strong></p>
|
||
<p>To create a prompt that the user will see when the cell containing the data validation receives focus</p>
|
||
<source>
|
||
dataValidation.createPromptBox("Title", "Message Text");
|
||
dataValidation.setShowPromptBox(true);
|
||
</source>
|
||
<p>The text encapsulated in the first parameter passed to the createPromptBox() method will appear emboldened
|
||
and as a title to the prompt whilst the second will be displayed as the text of the message.
|
||
The createExplicitListConstraint() method can be passed and array of String(s) containing interger, floating point, dates or text values.</p>
|
||
|
||
<p><strong>Further Data Validations:</strong></p>
|
||
<p>To obtain a validation that would check the value entered was, for example, an integer between 10 and 100,
|
||
use the DVConstraint.createNumericConstraint(int, int, String, String) factory method.</p>
|
||
<source>
|
||
dvConstraint = DVConstraint.createNumericConstraint(
|
||
DVConstraint.ValidationType.INTEGER,
|
||
DVConstraint.OperatorType.BETWEEN, "10", "100");
|
||
</source>
|
||
<p>Look at the javadoc for the other validation and operator types; also note that not all validation
|
||
types are supported for this method. The values passed to the two String parameters can be formulas; the '=' symbol is used to denote a formula</p>
|
||
<source>
|
||
dvConstraint = DVConstraint.createNumericConstraint(
|
||
DVConstraint.ValidationType.INTEGER,
|
||
DVConstraint.OperatorType.BETWEEN, "=SUM(A1:A3)", "100");
|
||
</source>
|
||
<p>It is not possible to create a drop down list if the createNumericConstraint() method is called,
|
||
the setSuppressDropDownArrow(false) method call will simply be ignored.</p>
|
||
<p>Date and time constraints can be created by calling the createDateConstraint(int, String, String, String)
|
||
or the createTimeConstraint(int, String, String). Both are very similar to the above and are explained in the javadoc. </p>
|
||
<p><strong>Creating Data Validations From Spreadsheet Cells.</strong></p>
|
||
<p>The contents of specific cells can be used to provide the values for the data validation
|
||
and the DVConstraint.createFormulaListConstraint(String) method supports this.
|
||
To specify that the values come from a contiguous range of cells do either of the following:</p>
|
||
<source>
|
||
dvConstraint = DVConstraint.createFormulaListConstraint("$A$1:$A$3");
|
||
</source>
|
||
<p>or</p>
|
||
<source>
|
||
Name namedRange = workbook.createName();
|
||
namedRange.setNameName("list1");
|
||
namedRange.setRefersToFormula("$A$1:$A$3");
|
||
dvConstraint = DVConstraint.createFormulaListConstraint("list1");
|
||
</source>
|
||
<p>and in both cases the user will be able to select from a drop down list containing the values from cells A1, A2 and A3.</p>
|
||
<p>The data does not have to be as the data validation. To select the data from a different sheet however, the sheet
|
||
must be given a name when created and that name should be used in the formula. So assuming the existence of a sheet named 'Data Sheet' this will work:</p>
|
||
<source>
|
||
Name namedRange = workbook.createName();
|
||
namedRange.setNameName("list1");
|
||
namedRange.setRefersToFormula("'Data Sheet'!$A$1:$A$3");
|
||
dvConstraint = DVConstraint.createFormulaListConstraint("list1");
|
||
</source>
|
||
<p>as will this:</p>
|
||
<source>
|
||
dvConstraint = DVConstraint.createFormulaListConstraint("'Data Sheet'!$A$1:$A$3");
|
||
</source>
|
||
<p>whilst this will not:</p>
|
||
<source>
|
||
Name namedRange = workbook.createName();
|
||
namedRange.setNameName("list1");
|
||
namedRange.setRefersToFormula("'Sheet1'!$A$1:$A$3");
|
||
dvConstraint = DVConstraint.createFormulaListConstraint("list1");
|
||
</source><p>and nor will this:</p><source>
|
||
dvConstraint = DVConstraint.createFormulaListConstraint("'Sheet1'!$A$1:$A$3");
|
||
</source>
|
||
</section>
|
||
<section>
|
||
<title>xssf.usermodel (.xlsx format)</title>
|
||
<p>
|
||
Data validations work similarly when you are creating an xml based, SpreadsheetML,
|
||
workbook file; but there are differences. Explicit casts are required, for example,
|
||
in a few places as much of the support for data validations in the xssf stream was
|
||
built into the unifying ss stream, of which more later. Other differences are
|
||
noted with comments in the code.
|
||
</p>
|
||
|
||
<p><strong>Check the value the user enters into a cell against one or more predefined value(s).</strong></p>
|
||
<source>
|
||
XSSFWorkbook workbook = new XSSFWorkbook();
|
||
XSSFSheet sheet = workbook.createSheet("Data Validation");
|
||
XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheet);
|
||
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)
|
||
dvHelper.createExplicitListConstraint(new String[]{"11", "21", "31"});
|
||
CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
|
||
XSSFDataValidation validation =(XSSFDataValidation)dvHelper.createValidation(
|
||
dvConstraint, addressList);
|
||
|
||
// Here the boolean value false is passed to the setSuppressDropDownArrow()
|
||
// method. In the hssf.usermodel examples above, the value passed to this
|
||
// method is true.
|
||
validation.setSuppressDropDownArrow(false);
|
||
|
||
// Note this extra method call. If this method call is omitted, or if the
|
||
// boolean value false is passed, then Excel will not validate the value the
|
||
// user enters into the cell.
|
||
validation.setShowErrorBox(true);
|
||
sheet.addValidationData(validation);
|
||
</source>
|
||
|
||
<p><strong>Drop Down Lists:</strong></p>
|
||
<p>This code will do the same but offer the user a drop down list to select a value from.</p>
|
||
<source>
|
||
XSSFWorkbook workbook = new XSSFWorkbook();
|
||
XSSFSheet sheet = workbook.createSheet("Data Validation");
|
||
XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheet);
|
||
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)
|
||
dvHelper.createExplicitListConstraint(new String[]{"11", "21", "31"});
|
||
CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
|
||
XSSFDataValidation validation = (XSSFDataValidation)dvHelper.createValidation(
|
||
dvConstraint, addressList);
|
||
validation.setShowErrorBox(true);
|
||
sheet.addValidationData(validation);
|
||
</source>
|
||
<p>Note that the call to the setSuppressDropDowmArrow() method can either be simply excluded or replaced with:</p>
|
||
<source>
|
||
validation.setSuppressDropDownArrow(true);
|
||
</source>
|
||
|
||
<p><strong>Prompts and Error Messages:</strong></p>
|
||
<p>
|
||
These both exactly mirror the hssf.usermodel so please refer to the 'Messages On Error:' and 'Prompts:' sections above.
|
||
</p>
|
||
|
||
<p><strong>Further Data Validations:</strong></p>
|
||
<p>
|
||
To obtain a validation that would check the value entered was, for example,
|
||
an integer between 10 and 100, use the XSSFDataValidationHelper(s) createNumericConstraint(int, int, String, String) factory method.
|
||
</p>
|
||
<source>
|
||
|
||
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)
|
||
dvHelper.createNumericConstraint(
|
||
XSSFDataValidationConstraint.ValidationType.INTEGER,
|
||
XSSFDataValidationConstraint.OperatorType.BETWEEN,
|
||
"10", "100");
|
||
</source>
|
||
<p>
|
||
The values passed to the final two String parameters can be formulas; the '=' symbol is used to denote a formula.
|
||
Thus, the following would create a validation the allows values only if they fall between the results of summing two cell ranges
|
||
</p>
|
||
<source>
|
||
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)
|
||
dvHelper.createNumericConstraint(
|
||
XSSFDataValidationConstraint.ValidationType.INTEGER,
|
||
XSSFDataValidationConstraint.OperatorType.BETWEEN,
|
||
"=SUM(A1:A10)", "=SUM(B24:B27)");
|
||
</source>
|
||
<p>
|
||
It is not possible to create a drop down list if the createNumericConstraint() method is called,
|
||
the setSuppressDropDownArrow(true) method call will simply be ignored.
|
||
</p>
|
||
<p>
|
||
Please check the javadoc for other constraint types as examples for those will not be included here.
|
||
There are, for example, methods defined on the XSSFDataValidationHelper class allowing you to create
|
||
the following types of constraint; date, time, decimal, integer, numeric, formula, text length and custom constraints.
|
||
</p>
|
||
<p><strong>Creating Data Validations From Spread Sheet Cells:</strong></p>
|
||
<p>
|
||
One other type of constraint not mentioned above is the formula list constraint.
|
||
It allows you to create a validation that takes it value(s) from a range of cells. This code
|
||
</p>
|
||
<source>
|
||
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)
|
||
dvHelper.createFormulaListConstraint("$A$1:$F$1");
|
||
</source>
|
||
|
||
<p>
|
||
would create a validation that took it's values from cells in the range A1 to F1.
|
||
</p>
|
||
<p>
|
||
The usefulness of this technique can be extended if you use named ranges like this;
|
||
</p>
|
||
|
||
<source>
|
||
XSSFName name = workbook.createName();
|
||
name.setNameName("data");
|
||
name.setRefersToFormula("$B$1:$F$1");
|
||
XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheet);
|
||
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)
|
||
dvHelper.createFormulaListConstraint("data");
|
||
CellRangeAddressList addressList = new CellRangeAddressList(
|
||
0, 0, 0, 0);
|
||
XSSFDataValidation validation = (XSSFDataValidation)
|
||
dvHelper.createValidation(dvConstraint, addressList);
|
||
validation.setSuppressDropDownArrow(true);
|
||
validation.setShowErrorBox(true);
|
||
sheet.addValidationData(validation);
|
||
</source>
|
||
<p>
|
||
OpenOffice Calc has slightly different rules with regard to the scope of names.
|
||
Excel supports both Workbook and Sheet scope for a name but Calc does not, it seems only to support Sheet scope for a name.
|
||
Thus it is often best to fully qualify the name for the region or area something like this;
|
||
</p>
|
||
<source>
|
||
XSSFName name = workbook.createName();
|
||
name.setNameName("data");
|
||
name.setRefersToFormula("'Data Validation'!$B$1:$F$1");
|
||
....
|
||
</source>
|
||
<p>
|
||
This does open a further, interesting opportunity however and that is to place all of the data for the validation(s) into named ranges of cells on a hidden sheet within the workbook. These ranges can then be explicitly identified in the setRefersToFormula() method argument.
|
||
</p>
|
||
</section>
|
||
<section><title>ss.usermodel</title>
|
||
<p>
|
||
The classes within the ss.usermodel package allow developers to create code that can be used
|
||
to generate both binary (.xls) and SpreadsheetML (.xlsx) workbooks.
|
||
</p>
|
||
<p>
|
||
The techniques used to create data validations share much in common with the xssf.usermodel examples above.
|
||
As a result just one or two examples will be presented here.
|
||
</p>
|
||
<p><strong>Check the value the user enters into a cell against one or more predefined value(s).</strong></p>
|
||
<source>
|
||
Workbook workbook = new XSSFWorkbook(); // or new HSSFWorkbook
|
||
Sheet sheet = workbook.createSheet("Data Validation");
|
||
DataValidationHelper dvHelper = sheet.getDataValidationHelper();
|
||
DataValidationConstraint dvConstraint = dvHelper.createExplicitListConstraint(
|
||
new String[]{"13", "23", "33"});
|
||
CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
|
||
DataValidation validation = dvHelper.createValidation(
|
||
dvConstraint, addressList);
|
||
// Note the check on the actual type of the DataValidation object.
|
||
// If it is an instance of the XSSFDataValidation class then the
|
||
// boolean value 'false' must be passed to the setSuppressDropDownArrow()
|
||
// method and an explicit call made to the setShowErrorBox() method.
|
||
if(validation instanceof XSSFDataValidation) {
|
||
validation.setSuppressDropDownArrow(false);
|
||
validation.setShowErrorBox(true);
|
||
}
|
||
else {
|
||
// If the Datavalidation contains an instance of the HSSFDataValidation
|
||
// class then 'true' should be passed to the setSuppressDropDownArrow()
|
||
// method and the call to setShowErrorBox() is not necessary.
|
||
validation.setSuppressDropDownArrow(true);
|
||
}
|
||
sheet.addValidationData(validation);
|
||
</source>
|
||
|
||
<p><strong>Drop Down Lists:</strong></p>
|
||
|
||
<p>This code will do the same but offer the user a drop down list to select a value from.</p>
|
||
|
||
<source>
|
||
Workbook workbook = new XSSFWorkbook(); // or new HSSFWorkbook
|
||
Sheet sheet = workbook.createSheet("Data Validation");
|
||
DataValidationHelper dvHelper = sheet.getDataValidationHelper();
|
||
DataValidationConstraint dvConstraint = dvHelper.createExplicitListConstraint(
|
||
new String[]{"13", "23", "33"});
|
||
CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
|
||
DataValidation validation = dvHelper.createValidation(
|
||
dvConstraint, addressList);
|
||
// Note the check on the actual type of the DataValidation object.
|
||
// If it is an instance of the XSSFDataValidation class then the
|
||
// boolean value 'false' must be passed to the setSuppressDropDownArrow()
|
||
// method and an explicit call made to the setShowErrorBox() method.
|
||
if(validation instanceof XSSFDataValidation) {
|
||
validation.setSuppressDropDownArrow(true);
|
||
validation.setShowErrorBox(true);
|
||
}
|
||
else {
|
||
// If the Datavalidation contains an instance of the HSSFDataValidation
|
||
// class then 'true' should be passed to the setSuppressDropDownArrow()
|
||
// method and the call to setShowErrorBox() is not necessary.
|
||
validation.setSuppressDropDownArrow(false);
|
||
}
|
||
sheet.addValidationData(validation);
|
||
</source>
|
||
|
||
<p><strong>Prompts and Error Messages:</strong></p>
|
||
<p>
|
||
These both exactly mirror the hssf.usermodel so please refer to the 'Messages On Error:' and 'Prompts:' sections above.
|
||
</p>
|
||
<p>
|
||
As the differences between the ss.usermodel and xssf.usermodel examples are small -
|
||
restricted largely to the way the DataValidationHelper is obtained, the lack of any
|
||
need to explicitly cast data types and the small difference in behaviour between
|
||
the hssf and xssf interpretation of the setSuppressDropDowmArrow() method,
|
||
no further examples will be included in this section.
|
||
</p>
|
||
<p><strong>Advanced Data Validations.</strong></p>
|
||
<p><strong>Dependent Drop Down Lists.</strong></p>
|
||
<p>
|
||
In some cases, it may be necessary to present to the user a sheet which contains more than one drop down list.
|
||
Further, the choice the user makes in one drop down list may affect the options that are presented to them in
|
||
the second or subsequent drop down lists. One technique that may be used to implement this behaviour will now be explained.
|
||
</p>
|
||
<p>
|
||
There are two keys to the technique; one is to use named areas or regions of cells to hold the data for the drop down lists,
|
||
the second is to use the INDIRECT() function to convert between the name and the actual addresses of the cells.
|
||
In the example section there is a complete working example- called LinkedDropDownLists.java -
|
||
that demonstrates how to create linked or dependent drop down lists. Only the more relevant points are explained here.
|
||
</p>
|
||
<p>
|
||
To create two drop down lists where the options shown in the second depend upon the selection made in the first,
|
||
begin by creating a named region of cells to hold all of the data for populating the first drop down list.
|
||
Next, create a data validation that will look to this named area for its data, something like this;
|
||
</p>
|
||
<source>
|
||
CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
|
||
DataValidationHelper dvHelper = sheet.getDataValidationHelper();
|
||
DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint(
|
||
"CHOICES");
|
||
DataValidation validation = dvHelper.createValidation(
|
||
dvConstraint, addressList);
|
||
sheet.addValidationData(validation);
|
||
</source>
|
||
<p>
|
||
Note that the name of the area - in the example above it is 'CHOICES' -
|
||
is simply passed to the createFormulaListConstraint() method. This is sufficient
|
||
to cause Excel to populate the drop down list with data from that named region.
|
||
</p>
|
||
<p>
|
||
Next, for each of the options the user could select in the first drop down list,
|
||
create a matching named region of cells. The name of that region should match the
|
||
text the user could select in the first drop down list. Note, in the example,
|
||
all upper case letters are used in the names of the regions of cells.
|
||
</p>
|
||
|
||
<p>
|
||
Now, very similar code can be used to create a second, linked, drop down list;
|
||
</p>
|
||
|
||
<source>
|
||
CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 1, 1);
|
||
DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint(
|
||
"INDIRECT(UPPER($A$1))");
|
||
DataValidation validation = dvHelper.createValidation(
|
||
dvConstraint, addressList);
|
||
sheet.addValidationData(validation);
|
||
</source>
|
||
|
||
<p>
|
||
The key here is in the following Excel function - INDIRECT(UPPER($A$1)) - which is used to populate the second,
|
||
linked, drop down list. Working from the inner-most pair of brackets, it instructs Excel to look
|
||
at the contents of cell A1, to convert what it reads there into upper case – as upper case letters are used
|
||
in the names of each region - and then convert this name into the addresses of those cells that contain
|
||
the data to populate another drop down list.
|
||
</p>
|
||
</section>
|
||
</section>
|
||
<anchor id="Embedded"/>
|
||
<section><title>Embedded Objects</title>
|
||
<p>It is possible to perform more detailed processing of an embedded Excel, Word or PowerPoint document,
|
||
or to work with any other type of embedded object.</p>
|
||
<p><strong>HSSF:</strong></p>
|
||
<source>
|
||
POIFSFileSystem fs = new POIFSFileSystem(new File("excel_with_embedded.xls"));
|
||
HSSFWorkbook workbook = new HSSFWorkbook(fs);
|
||
for (HSSFObjectData obj : workbook.getAllEmbeddedObjects()) {
|
||
//the OLE2 Class Name of the object
|
||
String oleName = obj.getOLE2ClassName();
|
||
if (oleName.equals("Worksheet")) {
|
||
DirectoryNode dn = (DirectoryNode) obj.getDirectory();
|
||
HSSFWorkbook embeddedWorkbook = new HSSFWorkbook(dn, false);
|
||
//System.out.println(entry.getName() + ": " + embeddedWorkbook.getNumberOfSheets());
|
||
} else if (oleName.equals("Document")) {
|
||
DirectoryNode dn = (DirectoryNode) obj.getDirectory();
|
||
HWPFDocument embeddedWordDocument = new HWPFDocument(dn);
|
||
//System.out.println(entry.getName() + ": " + embeddedWordDocument.getRange().text());
|
||
} else if (oleName.equals("Presentation")) {
|
||
DirectoryNode dn = (DirectoryNode) obj.getDirectory();
|
||
SlideShow<?,?> embeddedPowerPointDocument = new HSLFSlideShow(dn);
|
||
//System.out.println(entry.getName() + ": " + embeddedPowerPointDocument.getSlides().length);
|
||
} else {
|
||
if(obj.hasDirectoryEntry()){
|
||
// The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is
|
||
DirectoryNode dn = (DirectoryNode) obj.getDirectory();
|
||
for (Entry entry : dn) {
|
||
//System.out.println(oleName + "." + entry.getName());
|
||
}
|
||
} else {
|
||
// There is no DirectoryEntry
|
||
// Recover the object's data from the HSSFObjectData instance.
|
||
byte[] objectData = obj.getObjectData();
|
||
}
|
||
}
|
||
}
|
||
</source>
|
||
<p><strong>XSSF:</strong></p>
|
||
<source>
|
||
XSSFWorkbook workbook = new XSSFWorkbook("excel_with_embeded.xlsx");
|
||
for (PackagePart pPart : workbook.getAllEmbeddedParts()) {
|
||
String contentType = pPart.getContentType();
|
||
// Excel Workbook - either binary or OpenXML
|
||
if (contentType.equals("application/vnd.ms-excel")) {
|
||
HSSFWorkbook embeddedWorkbook = new HSSFWorkbook(pPart.getInputStream());
|
||
}
|
||
// Excel Workbook - OpenXML file format
|
||
else if (contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
|
||
OPCPackage docPackage = OPCPackage.open(pPart.getInputStream());
|
||
XSSFWorkbook embeddedWorkbook = new XSSFWorkbook(docPackage);
|
||
}
|
||
// Word Document - binary (OLE2CDF) file format
|
||
else if (contentType.equals("application/msword")) {
|
||
HWPFDocument document = new HWPFDocument(pPart.getInputStream());
|
||
}
|
||
// Word Document - OpenXML file format
|
||
else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
|
||
OPCPackage docPackage = OPCPackage.open(pPart.getInputStream());
|
||
XWPFDocument document = new XWPFDocument(docPackage);
|
||
}
|
||
// PowerPoint Document - binary file format
|
||
else if (contentType.equals("application/vnd.ms-powerpoint")) {
|
||
HSLFSlideShow slideShow = new HSLFSlideShow(pPart.getInputStream());
|
||
}
|
||
// PowerPoint Document - OpenXML file format
|
||
else if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) {
|
||
OPCPackage docPackage = OPCPackage.open(pPart.getInputStream());
|
||
XSLFSlideShow slideShow = new XSLFSlideShow(docPackage);
|
||
}
|
||
// Any other type of embedded object.
|
||
else {
|
||
System.out.println("Unknown Embedded Document: " + contentType);
|
||
InputStream inputStream = pPart.getInputStream();
|
||
}
|
||
}
|
||
</source>
|
||
</section>
|
||
<anchor id="Autofilter"/>
|
||
<p>(Since POI-3.7)</p>
|
||
<section><title>Autofilters</title>
|
||
<source>
|
||
Workbook wb = new HSSFWorkbook(); //or new XSSFWorkbook();
|
||
Sheet sheet = wb.createSheet();
|
||
sheet.setAutoFilter(CellRangeAddress.valueOf("C5:F200"));
|
||
</source>
|
||
</section>
|
||
<anchor id="ConditionalFormatting"/>
|
||
<section><title>Conditional Formatting</title>
|
||
<source>
|
||
Workbook workbook = new HSSFWorkbook(); // or new XSSFWorkbook();
|
||
Sheet sheet = workbook.createSheet();
|
||
|
||
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
|
||
|
||
ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(ComparisonOperator.EQUAL, "0");
|
||
FontFormatting fontFmt = rule1.createFontFormatting();
|
||
fontFmt.setFontStyle(true, false);
|
||
fontFmt.setFontColorIndex(IndexedColors.DARK_RED.index);
|
||
|
||
BorderFormatting bordFmt = rule1.createBorderFormatting();
|
||
bordFmt.setBorderBottom(BorderStyle.THIN);
|
||
bordFmt.setBorderTop(BorderStyle.THICK);
|
||
bordFmt.setBorderLeft(BorderStyle.DASHED);
|
||
bordFmt.setBorderRight(BorderStyle.DOTTED);
|
||
|
||
PatternFormatting patternFmt = rule1.createPatternFormatting();
|
||
patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index);
|
||
|
||
ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "-10", "10");
|
||
ConditionalFormattingRule [] cfRules =
|
||
{
|
||
rule1, rule2
|
||
};
|
||
|
||
CellRangeAddress[] regions = {
|
||
CellRangeAddress.valueOf("A3:A5")
|
||
};
|
||
|
||
sheetCF.addConditionalFormatting(regions, cfRules);
|
||
</source>
|
||
<p> See more examples on Excel conditional formatting in
|
||
<a href="https://github.com/apache/poi/tree/trunk/poi-examples/src/main/java/org/apache/poi/examples/ss/ConditionalFormats.java">ConditionalFormats.java</a>
|
||
</p>
|
||
|
||
</section>
|
||
<anchor id="Hiding"/>
|
||
<section><title>Hiding and Un-Hiding Rows</title>
|
||
<p>
|
||
Using Excel, it is possible to hide a row on a worksheet by selecting that row (or rows),
|
||
right clicking once on the right hand mouse button and selecting 'Hide' from the pop-up menu that appears.
|
||
</p>
|
||
<p>
|
||
To emulate this using POI, simply call the setZeroHeight() method on an instance of either
|
||
XSSFRow or HSSFRow (the method is defined on the ss.usermodel.Row interface that both classes implement), like this:
|
||
</p>
|
||
<source>
|
||
Workbook workbook = new XSSFWorkbook(); // OR new HSSFWorkbook()
|
||
Sheet sheet = workbook.createSheet(0);
|
||
Row row = workbook.createRow(0);
|
||
row.setZeroHeight();
|
||
</source>
|
||
<p>
|
||
If the file were saved away to disc now, then the first row on the first sheet would not be visible.
|
||
</p>
|
||
<p>
|
||
Using Excel, it is possible to unhide previously hidden rows by selecting the row above and the row below
|
||
the one that is hidden and then pressing and holding down the Ctrl key, the Shift and the pressing
|
||
the number 9 before releasing them all.
|
||
</p>
|
||
<p>
|
||
To emulate this behaviour using POI do something like this:
|
||
</p>
|
||
<source>
|
||
Workbook workbook = WorkbookFactory.create(new File(.......));
|
||
Sheet = workbook.getSheetAt(0);
|
||
Iterator<Row> row Iter = sheet.iterator();
|
||
while(rowIter.hasNext()) {
|
||
Row row = rowIter.next();
|
||
if(row.getZeroHeight()) {
|
||
row.setZeroHeight(false);
|
||
}
|
||
}
|
||
</source>
|
||
<p>
|
||
If the file were saved away to disc now, any previously hidden rows on the first sheet of the workbook would now be visible.
|
||
</p>
|
||
<p>
|
||
The example illustrates two features. Firstly, that it is possible to unhide a row simply by calling the setZeroHeight()
|
||
method and passing the boolean value 'false'. Secondly, it illustrates how to test whether a row is hidden or not.
|
||
Simply call the getZeroHeight() method and it will return 'true' if the row is hidden, 'false' otherwise.
|
||
</p>
|
||
</section>
|
||
<anchor id="CellProperties"/>
|
||
<section><title>Setting Cell Properties</title>
|
||
<p>
|
||
Sometimes it is easier or more efficient to create a spreadsheet with basic styles and then apply special styles to certain cells
|
||
such as drawing borders around a range of cells or setting fills for a region. CellUtil.setCellProperties lets you do that without creating
|
||
a bunch of unnecessary intermediate styles in your spreadsheet.
|
||
</p>
|
||
<p>
|
||
Properties are created as a Map and applied to a cell in the following manner.
|
||
</p>
|
||
<source>
|
||
Workbook workbook = new XSSFWorkbook(); // OR new HSSFWorkbook()
|
||
Sheet sheet = workbook.createSheet("Sheet1");
|
||
Map<String, Object> properties = new HashMap<String, Object>();
|
||
|
||
// border around a cell
|
||
properties.put(CellUtil.BORDER_TOP, BorderStyle.MEDIUM);
|
||
properties.put(CellUtil.BORDER_BOTTOM, BorderStyle.MEDIUM);
|
||
properties.put(CellUtil.BORDER_LEFT, BorderStyle.MEDIUM);
|
||
properties.put(CellUtil.BORDER_RIGHT, BorderStyle.MEDIUM);
|
||
|
||
// Give it a color (RED)
|
||
properties.put(CellUtil.TOP_BORDER_COLOR, IndexedColors.RED.getIndex());
|
||
properties.put(CellUtil.BOTTOM_BORDER_COLOR, IndexedColors.RED.getIndex());
|
||
properties.put(CellUtil.LEFT_BORDER_COLOR, IndexedColors.RED.getIndex());
|
||
properties.put(CellUtil.RIGHT_BORDER_COLOR, IndexedColors.RED.getIndex());
|
||
|
||
// Apply the borders to the cell at B2
|
||
Row row = sheet.createRow(1);
|
||
Cell cell = row.createCell(1);
|
||
CellUtil.setCellStyleProperties(cell, properties);
|
||
|
||
// Apply the borders to a 3x3 region starting at D4
|
||
for (int ix=3; ix <= 5; ix++) {
|
||
row = sheet.createRow(ix);
|
||
for (int iy = 3; iy <= 5; iy++) {
|
||
cell = row.createCell(iy);
|
||
CellUtil.setCellStyleProperties(cell, properties);
|
||
}
|
||
}
|
||
</source>
|
||
|
||
<p>
|
||
NOTE: This does not replace the properties of the cell, it merges the properties you have put into the Map with the
|
||
cell's existing style properties. If a property already exists, it is replaced with the new property. If a property does not
|
||
exist, it is added. This method will not remove CellStyle properties.
|
||
</p>
|
||
</section>
|
||
<anchor id="DrawingBorders"/>
|
||
<section>
|
||
<title>Drawing Borders</title>
|
||
<p>
|
||
In Excel, you can apply a set of borders on an entire workbook region at the press of a button. The PropertyTemplate
|
||
object simulates this with methods and constants defined to allow drawing top, bottom, left, right, horizontal,
|
||
vertical, inside, outside, or all borders around a range of cells. Additional methods allow for applying colors
|
||
to the borders.
|
||
</p>
|
||
<p>
|
||
It works like this: you create a PropertyTemplate object which is a container for the borders you wish to apply to a
|
||
sheet. Then you add borders and colors to the PropertyTemplate, and finally apply it to whichever sheets you need
|
||
that set of borders on. You can create multiple PropertyTemplate objects and apply them to a single sheet, or you can
|
||
apply the same PropertyTemplate object to multiple sheets. It is just like a preprinted form.
|
||
</p>
|
||
<p>
|
||
Enums:
|
||
</p>
|
||
<dl>
|
||
<dt>BorderStyle</dt>
|
||
<dd>
|
||
Defines the look of the border, is it thick or thin, solid or dashed, single or double.
|
||
This enum replaces the CellStyle.BORDER_XXXXX constants which have been deprecated. The PropertyTemplate will not
|
||
support the older style BORDER_XXXXX constants. A special value of BorderStyle.NONE will remove the border from
|
||
a Cell once it is applied.
|
||
</dd>
|
||
<dt>BorderExtent</dt>
|
||
<dd>
|
||
Describes the portion of the region that the BorderStyle will apply to. For example, TOP, BOTTOM, INSIDE, or OUTSIDE.
|
||
A special value of BorderExtent.NONE will remove the border from the PropertyTemplate. When the template is applied,
|
||
no change will be made to a cell border where no border properties exist in the PropertyTemplate.
|
||
</dd>
|
||
</dl>
|
||
<source>
|
||
// draw borders (three 3x3 grids)
|
||
PropertyTemplate pt = new PropertyTemplate();
|
||
// #1) these borders will all be medium in default color
|
||
pt.drawBorders(new CellRangeAddress(1, 3, 1, 3),
|
||
BorderStyle.MEDIUM, BorderExtent.ALL);
|
||
// #2) these cells will have medium outside borders and thin inside borders
|
||
pt.drawBorders(new CellRangeAddress(5, 7, 1, 3),
|
||
BorderStyle.MEDIUM, BorderExtent.OUTSIDE);
|
||
pt.drawBorders(new CellRangeAddress(5, 7, 1, 3), BorderStyle.THIN,
|
||
BorderExtent.INSIDE);
|
||
// #3) these cells will all be medium weight with different colors for the
|
||
// outside, inside horizontal, and inside vertical borders. The center
|
||
// cell will have no borders.
|
||
pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
|
||
BorderStyle.MEDIUM, IndexedColors.RED.getIndex(),
|
||
BorderExtent.OUTSIDE);
|
||
pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
|
||
BorderStyle.MEDIUM, IndexedColors.BLUE.getIndex(),
|
||
BorderExtent.INSIDE_VERTICAL);
|
||
pt.drawBorders(new CellRangeAddress(9, 11, 1, 3),
|
||
BorderStyle.MEDIUM, IndexedColors.GREEN.getIndex(),
|
||
BorderExtent.INSIDE_HORIZONTAL);
|
||
pt.drawBorders(new CellRangeAddress(10, 10, 2, 2),
|
||
BorderStyle.NONE,
|
||
BorderExtent.ALL);
|
||
|
||
// apply borders to sheet
|
||
Workbook wb = new XSSFWorkbook();
|
||
Sheet sh = wb.createSheet("Sheet1");
|
||
pt.applyBorders(sh);
|
||
</source>
|
||
<p>
|
||
NOTE: The last pt.drawBorders() call removes the borders from the range by using BorderStyle.NONE. Like
|
||
setCellStyleProperties, the applyBorders method merges the properties of a cell style, so existing borders
|
||
are changed only if they are replaced by something else, or removed only if they are replaced by
|
||
BorderStyle.NONE. To remove a color from a border, use IndexedColor.AUTOMATIC.getIndex().
|
||
</p>
|
||
<p>Additionally, to remove a border or color from the PropertyTemplate object, use BorderExtent.NONE.</p>
|
||
<p>
|
||
This does not work with diagonal borders yet.
|
||
</p>
|
||
</section>
|
||
<anchor id="PivotTable"/>
|
||
<section><title>Creating a Pivot Table</title>
|
||
<p>
|
||
Pivot Tables are a powerful feature of spreadsheet files. You can create a pivot table with the following piece of code.
|
||
</p>
|
||
<source>
|
||
XSSFWorkbook wb = new XSSFWorkbook();
|
||
XSSFSheet sheet = wb.createSheet();
|
||
|
||
//Create some data to build the pivot table on
|
||
setCellData(sheet);
|
||
|
||
XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:D4"), new CellReference("H5"));
|
||
//Configure the pivot table
|
||
//Use first column as row label
|
||
pivotTable.addRowLabel(0);
|
||
//Sum up the second column
|
||
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1);
|
||
//Set the third column as filter
|
||
pivotTable.addColumnLabel(DataConsolidateFunction.AVERAGE, 2);
|
||
//Add filter on forth column
|
||
pivotTable.addReportFilter(3);
|
||
</source>
|
||
</section>
|
||
<anchor id="RichText"/>
|
||
<section><title>Cells with multiple styles (Rich Text Strings)</title>
|
||
<p>
|
||
To apply a single set of text formatting (colour, style, font etc)
|
||
to a cell, you should create a
|
||
<a href="/../apidocs/dev/org/apache/poi/ss/usermodel/CellStyle.html">CellStyle</a>
|
||
for the workbook, then apply to the cells.
|
||
</p>
|
||
<source>
|
||
// HSSF Example
|
||
HSSFCell hssfCell = row.createCell(idx);
|
||
//rich text consists of two runs
|
||
HSSFRichTextString richString = new HSSFRichTextString( "Hello, World!" );
|
||
richString.applyFont( 0, 6, font1 );
|
||
richString.applyFont( 6, 13, font2 );
|
||
hssfCell.setCellValue( richString );
|
||
|
||
|
||
// XSSF Example
|
||
XSSFCell cell = row.createCell(1);
|
||
XSSFRichTextString rt = new XSSFRichTextString("The quick brown fox");
|
||
|
||
XSSFFont font1 = wb.createFont();
|
||
font1.setBold(true);
|
||
font1.setColor(new XSSFColor(new java.awt.Color(255, 0, 0)));
|
||
rt.applyFont(0, 10, font1);
|
||
|
||
XSSFFont font2 = wb.createFont();
|
||
font2.setItalic(true);
|
||
font2.setUnderline(XSSFFont.U_DOUBLE);
|
||
font2.setColor(new XSSFColor(new java.awt.Color(0, 255, 0)));
|
||
rt.applyFont(10, 19, font2);
|
||
|
||
XSSFFont font3 = wb.createFont();
|
||
font3.setColor(new XSSFColor(new java.awt.Color(0, 0, 255)));
|
||
rt.append(" Jumped over the lazy dog", font3);
|
||
|
||
cell.setCellValue(rt);
|
||
</source>
|
||
<p>
|
||
To apply different formatting to different parts of a cell, you
|
||
need to use
|
||
<a href="../../apidocs/dev/org/apache/poi/ss/usermodel/RichTextString.html">RichTextString</a>,
|
||
which permits styling of parts of the text within the cell.
|
||
</p>
|
||
<p>
|
||
There are some slight differences between HSSF and XSSF, especially
|
||
around font colours (the two formats store colours quite differently
|
||
internally), refer to the
|
||
<a href="../../apidocs/dev/org/apache/poi/hssf/usermodel/HSSFRichTextString.html">HSSF Rich Text String</a>
|
||
and
|
||
<a href="../../apidocs/dev/org/apache/poi/xssf/usermodel/XSSFRichTextString.html">XSSF Rich Text String</a>
|
||
javadocs for more details.
|
||
</p>
|
||
</section>
|
||
</body>
|
||
</document>
|