SXSSF Excel table

SXSSF with Excel table

我正在尝试在流式工作簿 (SXSSFWorkbook) 中创建 Excel table。 API 不直接支持它,但我通过访问底层 XSSFWorkbook (workbook.getXSSFWorkbook) 取得了一些成功。

当我在 Excel (2007) 中打开文件时,它显示 "Excel found unreadable content in "test.xlsx”。是否要恢复此工作簿的内容?”。单击“是”成功修复了工作簿,我得到了正确的结果。

日志显示 "Repaired Records: Table from /xl/tables/table1.xml part (Table)"。

有人知道如何避免 Excel 错误吗?

下面是一个例子:

public class SXSSFTest {

    private static final int NB_ROWS = 5;
    private static final int NB_COLS = 5;

    public static void main(String[] args) throws Exception {

        try (SXSSFWorkbook workbook = new SXSSFWorkbook();
             FileOutputStream outputStream = new FileOutputStream("C:\test.xlsx")) {

            SXSSFSheet sheet = workbook.createSheet();

            fillSheet(sheet);

            String dataRange = new AreaReference(
                    new CellReference(0, 0),
                    new CellReference(NB_ROWS - 1, NB_COLS - 1))
                    .formatAsString();

            CTTable cttable = workbook.getXSSFWorkbook()
                    .getSheetAt(0)
                    .createTable()
                    .getCTTable();

            CTTableStyleInfo tableStyle = cttable.addNewTableStyleInfo();
            tableStyle.setName("TableStyleMedium17");

            cttable.setRef(dataRange);
            cttable.setDisplayName("TABLE");
            cttable.setName("TABLE");
            cttable.setId(1L);

            CTTableColumns columns = cttable.addNewTableColumns();
            columns.setCount(NB_COLS);

            for (int c = 0; c < NB_COLS; c++) {
                CTTableColumn column = columns.addNewTableColumn();
                column.setName("Column" + c);
                column.setId(c + 1L);
            }

            cttable.setAutoFilter(CTAutoFilter.Factory.newInstance());

            workbook.write(outputStream);
        }
    }

    private static void fillSheet(SXSSFSheet sheet) {
        for (int rowNb = 0; rowNb < NB_ROWS; rowNb++) {
            SXSSFRow row = sheet.createRow(rowNb);

            for (int colNb = 0; colNb < NB_COLS; colNb++) {
                SXSSFCell cell = row.createCell(colNb);
                cell.setCellValue("Cell-" + colNb);
            }
        }
    }
}

table 第一行的单元格值必须与列名对应。

您在 main 方法中的代码将列命名为 Column0 ... Column4 但您在 fillSheet 方法中的代码写入 "Cell-0" ... "Cell-4" 到第一行的单元格中。这不匹配。

您可以像这样更改 fillSheet 方法:

...
    private static void fillSheet(SXSSFSheet sheet) {
        for (int rowNb = 0; rowNb < NB_ROWS; rowNb++) {
            SXSSFRow row = sheet.createRow(rowNb);

            for (int colNb = 0; colNb < NB_COLS; colNb++) {
                SXSSFCell cell = row.createCell(colNb);
                if (rowNb==0) cell.setCellValue("Column" + colNb); //first row are column names
                else cell.setCellValue("Cell-" + colNb);
            }
        }
    }
...

这是一个更新版本,修复了一些已弃用方法的用法(使用 POI 4.1.2 测试)。请注意,它不再需要手动创建列和设置 ID,一切都由 createTable(dataRange):

完成
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;

import java.io.FileOutputStream;

public class SXSSFTest {

    private static final int NB_ROWS = 5;
    private static final int NB_COLS = 5;

    public static void main(String[] args) throws Exception {

        try (SXSSFWorkbook workbook = new SXSSFWorkbook();
             FileOutputStream outputStream = new FileOutputStream("C:\test.xlsx")) {

            SXSSFSheet sheet = workbook.createSheet();

            fillSheet(sheet);

            AreaReference dataRange = new AreaReference(
                    new CellReference(0, 0),
                    new CellReference(NB_ROWS - 1, NB_COLS - 1),
                    SpreadsheetVersion.EXCEL2007
            );

            CTTable cttable = workbook.getXSSFWorkbook()
                    .getSheetAt(0)
                    .createTable(dataRange)
                    .getCTTable();

            CTTableStyleInfo tableStyle = cttable.addNewTableStyleInfo();
            tableStyle.setName("TableStyleMedium17");

            cttable.setDisplayName("TABLE");
            cttable.setName("TABLE");

            CTTableColumns columns = cttable.getTableColumns();

            for (int c = 0; c < NB_COLS; c++) {
                CTTableColumn column = columns.getTableColumnArray(c);
                column.setName("Column title " + c);
            }

            cttable.setAutoFilter(CTAutoFilter.Factory.newInstance());

            workbook.write(outputStream);
        }
    }

    private static void fillSheet(SXSSFSheet sheet) {
        for (int rowNb = 0; rowNb < NB_ROWS; rowNb++) {
            SXSSFRow row = sheet.createRow(rowNb);

            for (int colNb = 0; colNb < NB_COLS; colNb++) {
                SXSSFCell cell = row.createCell(colNb);
                if (rowNb == 0) {
                    cell.setCellValue("Column title " + colNb); //first row are column names
                } else {
                    cell.setCellValue("Cell-" + colNb);
                }
            }
        }
    }
}