POI开发指南1

  |   0 评论   |   0 浏览

POI开发指南1,来源

创建一个新的工作簿

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);
}

这里应当注意的是,创建空的工作簿是无法打开的。HSSX=>.xls文件 XSSF=>.xlsx文件

创建一个新表

Workbook wb = new HSSFWorkbook();  // or new XSSFWorkbook();
Sheet sheet1 = wb.createSheet("new sheet");
Sheet sheet2 = wb.createSheet("second sheet");
// 请注意,工作表名称是Excel,不能超过31个字符
// 并且不能包含以下任何字符:
// 0x0000
// 0x0003
// 冒号 (:)
// 反斜杠 (\)
// 星号 (*)
// 问号 (?)
// 正斜杠 (/)
// 开方括号([)
// 右方括号 (])
// 你可以使用方法 org.apache.poi.ss.util.WorkbookUtil#createSafeSheetName(String nameProposal)}
// 通过安全的方式创建一个有效的名字, 此实用程序用空格替换无效字符 (' ')
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);
}

创建单元格

Workbook wb = new HSSFWorkbook();
//Workbook wb = new XSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper();
Sheet sheet = wb.createSheet("new sheet");
//创建一行并在其中放置一些单元格。行是基于0的。
Row row = sheet.createRow(0);
// 创建单元格并在其中输入值。
Cell cell = row.createCell(0);
cell.setCellValue(1);
// 或者在一行上操作
row.createCell(1).setCellValue(1.2);
row.createCell(2).setCellValue(
     createHelper.createRichTextString("This is a string"));
row.createCell(3).setCellValue(true);
//将输出写入文件
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}

创建日期单元格

Workbook wb = new HSSFWorkbook();
//Workbook wb = new XSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper();
Sheet sheet = wb.createSheet("new sheet");
// 创建一行并在其中放置一些单元格。行是基于0的。
Row row = sheet.createRow(0);
// 创建一个单元格并在其中输入日期值。第一个单元格的样式不是日期。
Cell cell = row.createCell(0);
cell.setCellValue(new Date());
//我们将第二个单元格设置为日期(和时间)。
//从工作簿中创建新的单元格样式很重要,否则最终可能会修改内置样式,
//不仅影响此单元格,而且影响其他单元格。
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);
//你还可以将日期设置为java.util.Calendar
cell = row.createCell(2);
cell.setCellValue(Calendar.getInstance());
cell.setCellStyle(cellStyle);
// 将输出写入文件
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}

使用不同类型的单元格

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);
//将输出写入文件
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}

文件与输入流

打开工作簿时,.xls HSSFWorkbook或.xlsx XSSFWorkbook都可以从文件或InputStream加载工作簿。使用文件对象可以降低内存消耗,而InputStream需要更多内存,因为它必须缓冲整个文件。

// 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"));

如果直接使用HSSFWorkbook或XSSFWorkbook,通常应通过poifsffilesystem或OPCPackage来完全控制生命周期(包括完成时关闭文件):

如果使用WorkbookFactory,很容易使用其中一个:

// 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();

演示各种对齐选项

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();
}
/**
 * 创建单元格并以某种方式对齐。
 *
 * @param wb     工作簿
 * @param row    要在其中创建单元格的行
 * @param column 要在其中创建单元格的列号
 * @param halign 单元格的水平对齐方式。
 * @param valign 单元格的垂直对齐方式。
 */
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);
}

使用边框

Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("new sheet");
// 创建一行并在其中放置一些单元格。行是基于0的。
Row row = sheet.createRow(1);
// Create a cell and put a value in it.
Cell cell = row.createCell(1);
cell.setCellValue(4);
//在单元格周围设置边框样式。
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);
// 将输出写入文件
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}
                    
wb.close();

在行和单元格上迭代

有时,您只想遍历工作簿中的所有工作表、工作表中的所有行或一行中的所有单元格。这可以通过简单的for循环实现。

通过调用workbook.sheetIterator()、sheet.rowIterator()和row.cellIterator()或隐式使用for each循环,可以使用这些迭代器。请注意,rowIterator和cellIterator在已创建的行或单元格上迭代,跳过空行和单元格。

for (Sheet sheet : wb ) {
    for (Row row : sheet) {
        for (Cell cell : row) {
            // Do something here
        }
    }
}

遍历单元格,并控制缺少的/空白单元格

在某些情况下,迭代时,需要完全控制如何处理丢失或空白行和单元格,并且需要确保访问每个单元格,而不仅仅是访问文件中定义的单元格。(CellIterator只返回文件中定义的单元格,这些单元格主要是具有值或样式的单元格,但它依赖于Excel)。

在这种情况下,应该获取行的第一列和最后一列信息,然后调用getCell(int,MissingCellPolicy)来获取单元格。使用MissingCellPolicy控制空白或空单元格的处理方式。

// 决定要处理的行
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) {
      //整排都是空的
      // 按需处理
      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) {
         // 此单元格中的电子表格为空
      } else {
         // Do something useful with the cell's contents
      }
   }
}

获取单元格内容

要获取单元格的内容,首先需要知道它是什么类型的单元格(例如,向字符串单元格询问其数字内容将获得NumberFormatException)。所以,您需要打开单元格的类型,然后为该单元格调用适当的getter。

在下面的代码中,我们循环一张纸中的每个单元格,打印出单元格的引用(如A3),然后打印出单元格的内容。

// 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(" - ");
        // 通过获取单元格值并应用任何数据格式(Date、0.00、1.23e9、1.23等)获取单元格中显示的文本
        String text = formatter.formatCellValue(cell);
        System.out.println(text);
        // 或者,获取值并自行格式化
        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();
        }
    }
}

文本提取

对于大多数文本提取需求,标准的ExcelExtractor类应该提供您需要的所有内容。

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();
}
对于非常奇特的文本提取,XLS到CSV等,请看/src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java

## 填充和颜色
```Java
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("new sheet");
// 创建一行并在其中放置一些单元格。行是基于0的。
Row row = sheet.createRow(1);
//浅绿色背景
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);
//橙色“前景”,前景是填充前景而不是字体颜色。
style = wb.createCellStyle();
style.setFillForegroundColor(IndexedColors.ORANGE.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cell = row.createCell(2);
cell.setCellValue("X");
cell.setCellStyle(style);
//将输出写入文件
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}
wb.close();

合并单元格

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();

使用字体

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);
// 创建一个新字体并改变它。
Font font = wb.createFont();
font.setFontHeightInPoints((short)24);
font.setFontName("Courier New");
font.setItalic(true);
font.setStrikeout(true);
// 字体被设置为一种样式,因此创建一个新的样式以供使用。
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);
//注意,工作簿中唯一字体的最大数量限制为32767个。您应该在应用程序中重复使用字体,而不是为每个单元格创建字体。示例:
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}
wb.close();

错误的演示

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);
}

正确的演示

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);
}

自定义颜色

自定义HSSF颜色:

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);
}

自定义XSSF:颜色

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);

读取和重写工作簿

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);
    }
}

在单元格中使用换行符

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");
//若要启用换行符,需要将单元格样式设置为wrap=true
CellStyle cs = wb.createCellStyle();
cs.setWrapText(true);
cell.setCellStyle(cs);
//增加行高以容纳两行文本
row.setHeightInPoints((2*sheet.getDefaultRowHeightInPoints()));
//调整列宽以适应内容
sheet.autoSizeColumn(2);
try (OutputStream fileOut = new FileOutputStream("ooxml-newlines.xlsx")) {
    wb.write(fileOut);
}
wb.close();

数据格式

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();

将工作表调整为一页

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);
//为电子表格创建各种单元格和行。
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}
wb.close();

设置打印区域

Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("Sheet1");
//设置第一张纸的打印区域
wb.setPrintArea(0, "$A$1:$C$2");
//或者:
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();

在页脚上设置页码

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() );
// 为电子表格创建各种单元格和行。
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}
wb.close();

使用便利功能

便利功能提供实用功能,例如在合并区域周围设置边框和更改样式属性,而不显式创建新样式。

Workbook wb = new HSSFWorkbook();  // or new XSSFWorkbook()
Sheet sheet1 = wb.createSheet( "new sheet" );
//创建合并区域
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 );
//设置边框和边框颜色。
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);
// 显示了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();

在工作表上上移或下移行

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);

将图纸设置为选定的

Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("row sheet");
sheet.setSelected(true);

设置缩放比例

缩放以分数表示。例如,要表示75%的缩放,使用3表示分子,使用4表示分母。

Workbook wb = new HSSFWorkbook();
Sheet sheet1 = wb.createSheet("new sheet");
sheet1.setZoom(75);   // 75%放大率

拆分和冻结窗格

可以创建两种类型的窗格:冻结窗格和拆分窗格。

冻结窗格按列和行拆分。使用以下机制创建冻结窗格:
前两个参数是要拆分的列和行。后两个参数指示右下象限中可见的单元格。

拆分窗格的显示方式不同。分割区域分为四个独立的工作区域。分割发生在像素级,用户可以通过将分割拖到新位置来调整分割。

sheet2.createSplitPane( 2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT );

第一个参数是拆分的x位置。这是1/20分。在这种情况下,一个点似乎等于一个像素。第二个参数是分割的y位置。又是1/20分。
最后一个参数指示当前具有焦点的窗格。这将是Sheet.PANE_LOWER_LEFT、PANE_LOWER_RIGHT、PANE_UPPER_RIGHT或PANE_UPPER_LEFT之一。
使用以下调用创建拆分窗格:
sheet1.createFreezePane( 3, 2, 3, 2 );

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");
// 只冻结一行
sheet1.createFreezePane( 0, 1, 0, 1 );
// 只冻结一列
sheet2.createFreezePane( 1, 0, 1, 0 );
// 冻结列和行(忘记右下象限的滚动位置)。
sheet3.createFreezePane( 2, 2 );
// 创建一个左下方为活动象限的拆分
sheet4.createSplitPane( 2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT );
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}

重复行和列

通过使用Sheet类中的setRepeatingRows()和setRepeatingColumns()方法,可以在打印输出中设置重复的行和列。

这些方法需要一个CellRangeAddress参数,该参数指定要重复的行或列的范围。对于setRepeatingRows(),它应该指定要重复的行的范围,列部分跨越所有列。对于setRepeatingColumns(),它应该指定要重复的列的范围,行部分跨越所有行。如果参数为空,则将删除重复的行或列。

Workbook wb = new HSSFWorkbook();           // or new XSSFWorkbook();
Sheet sheet1 = wb.createSheet("Sheet1");
Sheet sheet2 = wb.createSheet("Sheet2");
// 将行设置为在第一张工作表中从第4行重复到第5行。
sheet1.setRepeatingRows(CellRangeAddress.valueOf("4:5"));
// 将列设置为在第二个工作表中从A列重复到C列
sheet2.setRepeatingColumns(CellRangeAddress.valueOf("A:C"));
try (OutputStream fileOut = new FileOutputStream("workbook.xls")) {
    wb.write(fileOut);
}

页眉和页脚

示例用于页眉,但直接应用于页脚。

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);
}

页眉和页脚的XSSF增强

例如页眉,但直接应用于页脚。注意,上面的基本页眉和页脚示例适用于XSSF工作簿和HSSF工作簿。HSSFHeader不适用于XSSF工作簿。

XSSF能够处理第一页的页眉和页脚,以及偶数/奇数页眉和页脚。所有页眉/页脚属性标志也可以在XSSF中处理。奇数页眉和页脚是默认的页眉和页脚。它显示在不显示第一页页眉或偶数页页眉的所有页上。也就是说,如果偶数页眉/页脚不存在,则奇数页眉/页脚显示在偶数页上。如果第一页页眉/页脚不存在,则在第一页上显示奇数页眉/页脚。如果未设置偶数/奇数属性,则与不存在的偶数页眉/页脚相同。如果第一页属性不存在,则与不存在的第一页页眉/页脚相同。

Workbook wb = new XSSFWorkbook();
XSSFSheet sheet = (XSSFSheet) wb.createSheet("new sheet");
// 创建第一页页眉
Header header = sheet.getFirstHeader();
header.setCenter("Center First Page Header");
header.setLeft("Left First Page Header");
header.setRight("Right First Page Header");
//创建偶数页标题
Header header2 = sheet.getEvenHeader();
der2.setCenter("Center Even Page Header");
header2.setLeft("Left Even Page Header");
header2.setRight("Right Even Page Header");
// 创建奇数页眉
Header header3 = sheet.getOddHeader();
der3.setCenter("Center Odd Page Header");
header3.setLeft("Left Odd Page Header");
header3.setRight("Right Odd Page Header");
//设置/删除标题属性
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);
}

绘制形状

POI支持使用Microsoft Office绘图工具绘制形状。工作表上的形状按组和形状的层次结构组织。最上层的是族长。这在纸上根本看不到。若要开始绘制,需要在HSSFSheet类上调用create家长。这样可以删除存储在该工作表中的任何其他形状信息。默认情况下,除非调用此方法,否则POI将在工作表中单独保留形状记录。

要创建形状,必须执行以下步骤:

  • 创建族长。
  • 创建定位点以将形状定位到图纸上。
  • 让族长创造这个形状。
  • 设置形状类型(直线、椭圆形、矩形等)
  • 设置与形状有关的任何其他样式细节。(如:线厚等)
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);

文本框是使用不同的调用创建的:

HSSFTextbox textbox1 = patriarch.createTextbox(
        new HSSFClientAnchor(0,0,0,0,(short)1,1,(short)2,2));
textbox1.setString(new HSSFRichTextString("This is a test") );

可以使用不同的字体为文本框中的部分文本设置样式。以下是方法:

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 );

正如可以使用Excel手动完成一样,可以将形状分组在一起。这是通过调用createGroup()然后使用这些组创建形状来完成的。

Warning
Any group you create should contain at least two other shapes or subgroups.

以下是如何创建形状组:

// Create a shape group.
HSSFShapeGroup group = patriarch.createGroup(
        new HSSFClientAnchor(0,0,900,200,(short)2,2,(short)2,2));
// 在组中创建几行。
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);

如果你仔细观察,你会发现添加到组中的形状使用了一种新类型的锚:HSSFChildAnchor。结果是创建的组有自己的坐标空间来放置形状。POI默认为(0,01023255),但您可以根据需要进行更改。以下是方法:

myGroup.setCoordinates(10,10,20,20); // top-left, bottom-right

如果在一个组中创建一个组,它也将有自己的坐标空间。

设置形状样式

默认情况下,形状看起来有点简单。但是,可以对形状应用不同的样式。目前可以做的事情有:

  • 更改填充颜色。
  • 做一个没有填充颜色的形状。
  • 更改线条的厚度。
  • 更改线条的样式。虚线,虚线。
  • 更改线条颜色。

下面是一个这样做的例子:

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);

形状和图形2d

虽然本地POI形状绘制命令是在形状中绘制形状的推荐方法,但有时需要使用标准API与外部库兼容。考虑到这一点,我们为 Graphics 和Graphics2d创建了一些包装器。

Warning
不过,在继续之前,务必不要让Graphics2d与Microsoft Office绘图命令的功能不匹配。旧的图形类提供了更接近的匹配,但仍然是一个方钉在圆孔。

所有图形命令都会发出到HSSFShapeGroup中。这是怎么做到的:

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 );

我们做的第一件事是创建组并设置它的坐标以匹配我们计划绘制的图形。接下来,我们计算一个合理的fontSizeMultiplier,然后创建EscherGraphics2d对象。因为我们真正想要的是一个Graphics2d对象,所以我们创建一个EscherGraphics2d对象并传入我们创建的graphics对象。最后,我们调用一个绘制到EscherGraphics2d对象的例程。

每个像素的垂直点值得更多的解释。将图形调用转换为escher绘图调用的困难之一是Excel没有绝对像素位置的概念。它测量“字符”中的单元格宽度和点中的单元格高度。不幸的是,它并没有准确定义它所测量的字符类型。这大概是因为Excel将在不同的平台上使用不同的字体,甚至在同一个平台上使用不同的字体。

由于这个限制,我们不得不实现verticalPointsPerPixel的概念。这是发出drawString()等命令时字体应缩放的大小。要计算此值,请使用以下公式:

multipler = groupHeightInPoints / heightOfGroup

组的高度是通过计算形状边界框的y坐标之间的差来计算的。组的高度可以使用名为HSSFClientAnchor.getAnchorHeightInPoints()的便利计算

图形类支持的许多函数都不完整。下面是一些已知有效的函数。

  • fillRect()
  • fillOval()
  • drawString()
  • drawOval()
  • drawLine()
  • clearRect()

不受支持的函数将使用POI日志记录基础结构返回和记录消息(默认情况下禁用)。

Outlining

大纲非常适合将部分信息分组在一起,并且可以使用POI API轻松地添加到列和行中。以下是方法:

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);
}

要折叠(或展开)大纲,请使用以下调用:

sheet1.setRowGroupCollapsed( 7, true );
sheet1.setColumnGroupCollapsed( 4, true );

您选择的行/列应包含已创建的组。它可以在组内的任何位置。


标题:POI开发指南1
作者:MingGH
地址:https://runnable.run/articles/2020/01/13/1578907295858.html