我正在尝试在流工作簿(SXSSFWorkbook)中创建Excel表。它不直接受API支持,但我通过访问底层的XSSFWorkbook(workbook.getXSSFWorkbook)取得了一些成功。
当我在Excel(2007)中打开文件时,它说“Excel在”test.xlsx“中找到了不可读的内容。你想恢复这个工作簿的内容吗?”单击是成功修复工作簿,我得到了正确的结果。
日志显示“修复的记录:来自/xl/tables/table1.xml部分(表)的表”。
任何人都知道如何避免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);
}
}
}
}
答案 0 :(得分:4)
表格第一行中的单元格值必须与列名称相对应。
main
方法中的代码为列Column0
... Column4
命名,但fillSheet
方法中的代码会写入&#34; Cell-0&#34; ......&#34; Cell-4&#34;进入第一排的细胞。这不匹配。
您可以像这样更改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);
}
}
}
...
答案 1 :(得分:0)
这是一个更新的版本,修复了不赞成使用的方法的几种用法(已通过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);
}
}
}
}
}