如何使用 Apache POI 将 Excel 文档中的区域转换为 table?
How do I convert an area in an Excel doc to a table using Apache POI?
我编写了一个应用程序,它从数据库中获取数据并使用 Apache POI 库中的 XSSF 类 根据所述数据创建 Excel 文档。我已经导入了 poi、poi-ooxml 和 poi-ooxml-schemas,所有版本都是 4.1.0。
文件写得很好,打开文件时没有错误,直到我取消注释 table 创建代码,我将在下面粘贴:
CellReference topLeft = new CellReference(sheet.getRow(3).getCell(0));
CellReference bottomRight = new CellReference(sheet.getRow(nextRow-1).getCell(3));
AreaReference tableArea = workbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
XSSFTable dataTable = sheet.createTable(tableArea);
我添加了一些额外的字段只是为了排除一些潜在的问题:
int test = dataTable.getEndRowIndex(); //Returns 968, as expected
tableArea = dataTable.getArea(); //The area remains A4 to D968, as expected
int testColumns = dataTable.getColumnCount(); //Returns 4, as expected
int testRows = dataTable.getRowCount(); //Returns 968, as expected
取消注释上述代码后尝试打开工作簿时,出现以下错误:
"We found a problem with some content in 'filename.xlsx'. Do you want us to try and recover as much as we can? If you trust the source of this workbook, click yes."
点击是后,出现的数据没有table存在,并显示以下错误:
"Removed Part: /xl/tables/table1.xml part with XML error. (Table) Load error. Line 2, column 94."
这令人困惑,因为所有迹象都表明 table 中应该只有 4 列...任何人都知道可能发生了什么以及如何解决它?
您的 XSSFTable
缺少姓名。至少必须使用 XSSFTable.setDisplayName.
设置显示名称
所以 dataTable.setDisplayName("Table1");
应该可以解决您的问题。
如何检测?
首先创建一个简单的完整示例。然后,在使用 Excel
打开结果后,注意 /xl/tables/table1.xml
的 row/column 错误是关于什么的。然后在解压缩 *.xlsx
后打开 /xl/tables/table1.xml
。现在你应该发现,错误的XML
是:
<table id="1" ref="A4:D..." xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><tableColumns count="4">
错误紧接在 <table id="1" ref="A4:D..." xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
之后。所以第一个标签似乎不完整。
现在将其与 XML
Excel
本身创建的进行比较。您会发现 Excel
table
元素总是会设置 name="TableN" displayName="TableN"
。
完整示例:
import java.io.FileOutputStream;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import java.util.GregorianCalendar;
class CreateExcelTable {
public static void main(String[] args) throws Exception {
Object[][] data = new Object[][] {
new Object[] {"Text", "Date", "Number", "Boolean"},
new Object[] {"Text 1", new GregorianCalendar(2020, 0, 1), 1234d, true},
new Object[] {"Text 2", new GregorianCalendar(2020, 1, 15), 5678d, true},
new Object[] {"Text 3", new GregorianCalendar(2020, 2, 1), 90.1234, false},
new Object[] {"Text 4", new GregorianCalendar(2020, 3, 15), 567.89, false}
};
try (XSSFWorkbook workbook = new XSSFWorkbook();
FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {
XSSFCellStyle dateCellStyle = workbook.createCellStyle();
dateCellStyle.setDataFormat(14);
XSSFSheet sheet = workbook.createSheet();
XSSFRow row = sheet.createRow(0);
XSSFCell cell = row.createCell(0);
cell.setCellValue("Lorem ipsum");
row = sheet.createRow(1);
cell = row.createCell(0);
cell.setCellValue("semit dolor");
int nextRow = 3;
int nextCol = 0;
for (Object[] dataRow : data) {
row = sheet.createRow(nextRow++);
nextCol = 0;
for (Object value : dataRow) {
cell = row.createCell(nextCol++);
if (value instanceof String) cell.setCellValue((String)value);
else if (value instanceof GregorianCalendar) {
cell.setCellValue((GregorianCalendar)value);
cell.setCellStyle(dateCellStyle);
}
else if (value instanceof Double) cell.setCellValue((Double)value);
else if (value instanceof Boolean) cell.setCellValue((Boolean)value);
}
}
CellReference topLeft = new CellReference(sheet.getRow(3).getCell(0));
CellReference bottomRight = new CellReference(sheet.getRow(nextRow-1).getCell(3));
AreaReference tableArea = workbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
XSSFTable dataTable = sheet.createTable(tableArea);
//dataTable.setName("Table1");
dataTable.setDisplayName("Table1");
/*
//this styles the table as Excel would do per default
dataTable.getCTTable().addNewTableStyleInfo();
XSSFTableStyleInfo style = (XSSFTableStyleInfo)dataTable.getStyle();
style.setName("TableStyleMedium2");
style.setShowColumnStripes(false);
style.setShowRowStripes(true);
dataTable.getCTTable().addNewAutoFilter().setRef(tableArea.formatAsString());
*/
workbook.write(fileout);
}
}
}
我编写了一个应用程序,它从数据库中获取数据并使用 Apache POI 库中的 XSSF 类 根据所述数据创建 Excel 文档。我已经导入了 poi、poi-ooxml 和 poi-ooxml-schemas,所有版本都是 4.1.0。
文件写得很好,打开文件时没有错误,直到我取消注释 table 创建代码,我将在下面粘贴:
CellReference topLeft = new CellReference(sheet.getRow(3).getCell(0));
CellReference bottomRight = new CellReference(sheet.getRow(nextRow-1).getCell(3));
AreaReference tableArea = workbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
XSSFTable dataTable = sheet.createTable(tableArea);
我添加了一些额外的字段只是为了排除一些潜在的问题:
int test = dataTable.getEndRowIndex(); //Returns 968, as expected
tableArea = dataTable.getArea(); //The area remains A4 to D968, as expected
int testColumns = dataTable.getColumnCount(); //Returns 4, as expected
int testRows = dataTable.getRowCount(); //Returns 968, as expected
取消注释上述代码后尝试打开工作簿时,出现以下错误:
"We found a problem with some content in 'filename.xlsx'. Do you want us to try and recover as much as we can? If you trust the source of this workbook, click yes."
点击是后,出现的数据没有table存在,并显示以下错误: "Removed Part: /xl/tables/table1.xml part with XML error. (Table) Load error. Line 2, column 94."
这令人困惑,因为所有迹象都表明 table 中应该只有 4 列...任何人都知道可能发生了什么以及如何解决它?
您的 XSSFTable
缺少姓名。至少必须使用 XSSFTable.setDisplayName.
所以 dataTable.setDisplayName("Table1");
应该可以解决您的问题。
如何检测?
首先创建一个简单的完整示例。然后,在使用 Excel
打开结果后,注意 /xl/tables/table1.xml
的 row/column 错误是关于什么的。然后在解压缩 *.xlsx
后打开 /xl/tables/table1.xml
。现在你应该发现,错误的XML
是:
<table id="1" ref="A4:D..." xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><tableColumns count="4">
错误紧接在 <table id="1" ref="A4:D..." xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
之后。所以第一个标签似乎不完整。
现在将其与 XML
Excel
本身创建的进行比较。您会发现 Excel
table
元素总是会设置 name="TableN" displayName="TableN"
。
完整示例:
import java.io.FileOutputStream;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import java.util.GregorianCalendar;
class CreateExcelTable {
public static void main(String[] args) throws Exception {
Object[][] data = new Object[][] {
new Object[] {"Text", "Date", "Number", "Boolean"},
new Object[] {"Text 1", new GregorianCalendar(2020, 0, 1), 1234d, true},
new Object[] {"Text 2", new GregorianCalendar(2020, 1, 15), 5678d, true},
new Object[] {"Text 3", new GregorianCalendar(2020, 2, 1), 90.1234, false},
new Object[] {"Text 4", new GregorianCalendar(2020, 3, 15), 567.89, false}
};
try (XSSFWorkbook workbook = new XSSFWorkbook();
FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {
XSSFCellStyle dateCellStyle = workbook.createCellStyle();
dateCellStyle.setDataFormat(14);
XSSFSheet sheet = workbook.createSheet();
XSSFRow row = sheet.createRow(0);
XSSFCell cell = row.createCell(0);
cell.setCellValue("Lorem ipsum");
row = sheet.createRow(1);
cell = row.createCell(0);
cell.setCellValue("semit dolor");
int nextRow = 3;
int nextCol = 0;
for (Object[] dataRow : data) {
row = sheet.createRow(nextRow++);
nextCol = 0;
for (Object value : dataRow) {
cell = row.createCell(nextCol++);
if (value instanceof String) cell.setCellValue((String)value);
else if (value instanceof GregorianCalendar) {
cell.setCellValue((GregorianCalendar)value);
cell.setCellStyle(dateCellStyle);
}
else if (value instanceof Double) cell.setCellValue((Double)value);
else if (value instanceof Boolean) cell.setCellValue((Boolean)value);
}
}
CellReference topLeft = new CellReference(sheet.getRow(3).getCell(0));
CellReference bottomRight = new CellReference(sheet.getRow(nextRow-1).getCell(3));
AreaReference tableArea = workbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
XSSFTable dataTable = sheet.createTable(tableArea);
//dataTable.setName("Table1");
dataTable.setDisplayName("Table1");
/*
//this styles the table as Excel would do per default
dataTable.getCTTable().addNewTableStyleInfo();
XSSFTableStyleInfo style = (XSSFTableStyleInfo)dataTable.getStyle();
style.setName("TableStyleMedium2");
style.setShowColumnStripes(false);
style.setShowRowStripes(true);
dataTable.getCTTable().addNewAutoFilter().setRef(tableArea.formatAsString());
*/
workbook.write(fileout);
}
}
}