我正在尝试使用Apache Poi将 ResultSet写入Excel(* .xlsx)表。
Office Excel中的表对象错误
但是,即使它写入Excel文件时没有任何错误,当我尝试在Office Excel 2013中打开它时,它会显示错误并删除表对象以仅提供纯数据视图。
以下是粗略的示例代码using this example:
public static void writeExcel(ResultSet rs, int sqliteRowCount, String dir) {
System.out.println("Writing Excel(*.xlsx) File...");
XSSFWorkbook workbook = null;
try {
if (rs != null) {
// Get ResultSet MetaData
ResultSetMetaData rsmd = rs.getMetaData();
// Number of columns
int numColumns = rsmd.getColumnCount();
// Number of rows
// + 1 for headers
int numRows = sqliteRowCount + 1;
workbook = new XSSFWorkbook();
// Create Excel Table
XSSFSheet sheet = workbook.createSheet("Text");
XSSFTable table = sheet.createTable();
table.setDisplayName("Test");
CTTable cttable;
cttable = table.getCTTable();
// Style configurations
CTTableStyleInfo style = cttable.addNewTableStyleInfo();
style.setName("TableStyleMedium16");
style.setShowColumnStripes(false);
style.setShowRowStripes(true);
// Set Table Span Area
AreaReference reference = new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1));
cttable.setRef(reference.formatAsString());
cttable.setId(1);
cttable.setName("Test");
cttable.setDisplayName("Test");
cttable.setTotalsRowCount(numRows);
cttable.setTotalsRowShown(false);
// Create Columns
CTTableColumns columns = cttable.addNewTableColumns();
columns.setCount(numColumns);
// Create Column, Row, Cell Objects
CTTableColumn column;
XSSFRow row;
// Add Header and Columns
XSSFRow headerRow = sheet.createRow(0);
for (int i = 0; i < numColumns; i++) {
column = columns.addNewTableColumn();
column.setName("Column" + (i + 1));
column.setId(i + 1);
headerRow.createCell(i).setCellValue(rsmd.getColumnLabel(i + 1));
}
// Write each row from ResultSet
int rowNumber = 1;
while (rs.next()) {
row = sheet.createRow(rowNumber);
for (int y = 0; y < numColumns; y++) {
row.createCell(y).setCellValue(rs.getString(y + 1));
}
rowNumber++;
}
// Set AutoFilter
CTAutoFilter fltr = CTAutoFilter.Factory.newInstance();
fltr.setRef((new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1))).formatAsString());
cttable.setAutoFilter(fltr);
// sheet.setAutoFilter(CellRangeAddress.valueOf((new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1))).formatAsString()));
// Freeze Pan
sheet.createFreezePane(0, 1, 0, 2);
}
} catch (SQLException ex) {
System.out.println("SQL Error while writing Excel file!");
} finally {
try {
// Let's write the excel file now
if (workbook != null) {
String excelDir = dir + File.separator + "workbook.xlsx";
try (final FileOutputStream out = new FileOutputStream(excelDir)) {
workbook.write(out);
}
}
} catch (IOException ex) {
System.out.println("IO Error while writing Excel summary file!");
}
}
}
我知道我的代码有问题,但无法解决。 任何想法,为什么会发生这种情况,我的代码中可能存在错误。
更新1:
如果使用Apache POI创建Excel档案中的表格XML文件
<?xml version="1.0" encoding="UTF-8"?>
<table displayName="Test" ref="A1:B881" id="1" name="Test" totalsRowCount="881" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" totalsRowShown="0"><autoFilter ref="A1:B881"/><tableColumns count="2"><tableColumn name="ID" id="1"/><tableColumn name="Name" id="2"/><tableStyleInfo name="TableStyleMedium2" showColumnStripes="true" showRowStripes="true"/></table>
如果手动创建表,则在Excel归档中使用表格XML文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="1" name="Table1" displayName="Table1" ref="A1:B881" totalsRowShown="0"><autoFilter ref="A1:B881"/><tableColumns count="2"><tableColumn id="1" name="ID"/><tableColumn id="2" name="Name"/></tableColumns><tableStyleInfo name="TableStyleLight9" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0"/></table>
此外,如果我打开Excel存档,它在Apache POI创建的主题文件夹中没有主题文件夹,但它存在于Office Excel中手动创建的主题文件夹中。奇怪。
更新2: 示例可执行代码(使用Netbeans):
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package apachepoi_exceltest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyleInfo;
/**
*
*/
public class ApachePOI_ExcelTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
String outputDir = "Your Local Directory Here";
// TODO code application logic here
HashMap<String, String> dataMap = new HashMap<>();
dataMap.put("ID 1", "Dummy Name 1");
dataMap.put("ID 2", "Dummy Name 2");
dataMap.put("ID 3", "Dummy Name 3");
dataMap.put("ID 4", "Dummy Name 4");
writeExcel(dataMap, outputDir);
}
private static void writeExcel(HashMap<String, String> dataMap, String outputDir) {
System.out.println("Writing Excel(*.xlsx) Summary File...");
XSSFWorkbook workbook = null;
try {
// Number of columns
int numColumns = 2; // ID and Name
// Number of rows
int numRows = dataMap.size() + 1; // +1 for header
// Create Workbook
workbook = new XSSFWorkbook();
// Create Excel Table
XSSFSheet sheet = workbook.createSheet("Summary");
XSSFTable table = sheet.createTable();
table.setDisplayName("Test");
CTTable cttable;
cttable = table.getCTTable();
// Style configurations
CTTableStyleInfo style = cttable.addNewTableStyleInfo();
style.setName("TableStyleMedium16");
style.setShowColumnStripes(false);
style.setShowRowStripes(true);
// Set Tabel Span Area
AreaReference reference = new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1));
cttable.setRef(reference.formatAsString());
cttable.setId(1);
cttable.setName("Test");
cttable.setDisplayName("Test");
cttable.setTotalsRowCount(numRows);
cttable.setTotalsRowShown(false);
// Create Columns
CTTableColumns columns = cttable.addNewTableColumns();
columns.setCount(numColumns);
// Create Column, Row, Cell Objects
CTTableColumn column;
XSSFRow row;
// Add ID Header
column = columns.addNewTableColumn();
column.setName("Column" + (1));
column.setId(1);
// Add Name Header
column = columns.addNewTableColumn();
column.setName("Column" + (1));
column.setId(1);
// Add Header Row
XSSFRow headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("ID");
headerRow.createCell(1).setCellValue("Name");
int rowNumber = 1;
for (Map.Entry<String, String> entry : dataMap.entrySet()) {
String id = entry.getKey();
String name = entry.getValue();
row = sheet.createRow(rowNumber);
row.createCell(0).setCellValue(id);
row.createCell(1).setCellValue(name);
rowNumber++;
}
// Set Filter (Below three lines code somehow not working in this example, so setting AutoFilter to WorkSheet)
// CTAutoFilter fltr = CTAutoFilter.Factory.newInstance();
// fltr.setRef((new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1))).formatAsString());
// cttable.setAutoFilter(fltr);
sheet.setAutoFilter(CellRangeAddress.valueOf((new AreaReference(new CellReference(0, 0), new CellReference(numRows - 1, numColumns - 1))).formatAsString()));
// Freeze First Row as header Row
sheet.createFreezePane(0, 1, 0, 2);
} catch (Exception ex) {
System.out.println("Error while writing Excel summary file!");
} finally {
try {
// Lets write the Excel File Now
if (workbook != null) {
String excelDir = outputDir + File.separator + "workbook.xlsx";
try (final FileOutputStream out = new FileOutputStream(excelDir)) {
workbook.write(out);
}
}
} catch (IOException ex) {
System.out.println("IO Error while writing Excel summary file!");
}
}
}
}
使用的库:
OOXML-架构-1.1.jar
POI-3.11-beta2-20140822.jar
POI-OOXML-3.11-beta2-20140822.jar
的xmlbeans-2.6.0.jar
答案 0 :(得分:3)
您的代码有什么问题是存在一行。 “cttable.setTotalsRowCount(numRows行);” 删除它,一切都会工作。 如果有疑问,请比较在Excel中手动创建的某些工作表的XML定义和使用Apache POI创建的定义
答案 1 :(得分:0)
我遇到了同样的问题。
深入挖掘,我发现对于XLSX包中的某些表XML数据,Excel在执行修复后正在将单个>
更改为>
。来自POI的XML是有意义的(使用<
和>
来包围XML元素)所以我不知道为什么微软会选择破解它。
如果你的情况相同,我不必过于担心。
如果你想看看你是否有这个特殊的区别:
答案 2 :(得分:0)
您尚未正确创建表格。 检查:
在末尾删除空的第一个标题列(POI BUG)
<强> CTTable()getTableColumns()removeTableColumn(0); 强>
将debug放入XSSFTable.class,方法updateHeaders()。
如果您的表格未正确创建,则
XSSFRow row = sheet.getRow(headerRow);
中的
将为NULL
/**
* Synchronize table headers with cell values in the parent sheet.
* Headers <em>must</em> be in sync, otherwise Excel will display a
* "Found unreadable content" message on startup.
*/
@SuppressWarnings("deprecation")
public void updateHeaders(){
XSSFSheet sheet = (XSSFSheet)getParent();
CellReference ref = getStartCellReference();
if(ref == null) return;
int headerRow = ref.getRow();
int firstHeaderColumn = ref.getCol();
XSSFRow row = sheet.getRow(headerRow);
if (row != null && row.getCTRow().validate()) {
int cellnum = firstHeaderColumn;
for (CTTableColumn col : getCTTable().getTableColumns().getTableColumnArray()) {
XSSFCell cell = row.getCell(cellnum);
if (cell != null) {
col.setName(cell.getStringCellValue());
}
cellnum++;
}
}
}