使用 Apache POI 将结果集转换为 Excel (*.xlsx) 表 [英] ResultSet to Excel (*.xlsx) Table Using Apache POI
问题描述
我正在尝试使用 Apache Poi 将 ResultSet 写入 Excel (*.xlsx) 表.
I am trying to write ResultSet to Excel (*.xlsx) Table using Apache Poi.
Office Excel 中的表格对象无效错误
但是,即使它写入 Excel 文件没有任何错误,当我尝试在 Office Excel 2013 中打开它时,它显示错误并删除表对象以仅提供纯数据视图.
However, even though it writes the Excel file without any error, when I try to open it in Office Excel 2013, it shows an error and removes the table object to give only plain data view.
这里是粗略的示例代码 使用这个例子:
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!");
}
}
}
我知道我的代码有问题,但无法弄清楚.任何想法,为什么会发生这种情况,我的代码中哪里有潜在的错误.
I know something is wrong with my code, but can't figure it out. Any idea, why this is happening, where would be potential mistake in my code.
更新 1:
Excel 存档中的表格 XML 文件(如果使用 Apache POI 创建)
Table XML file in Excel archive if created using Apache POI
<?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 文件
Table XML file in Excel archive if table created manually
<?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 中手动创建的文件夹中.奇怪的.
In addition, if I open the Excel archive, it does not have a theme folder in the one created by Apache POI but it is present in the one create manually in Office Excel. Strange.
更新 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-schemas-1.1.jar
ooxml-schemas-1.1.jar
poi-3.11-beta2-20140822.jar
poi-3.11-beta2-20140822.jar
poi-ooxml-3.11-beta2-20140822.jar
poi-ooxml-3.11-beta2-20140822.jar
xmlbeans-2.6.0.jar
xmlbeans-2.6.0.jar
推荐答案
您的代码有什么问题是只有一行."cttable.setTotalsRowCount(numRows);"删除它,一切都会起作用.如果有疑问,比较一些在 Excel 中手动创建的工作表的 XML 定义和使用 Apache POI 创建的定义
What's wrong with your code is a presence of a single line. "cttable.setTotalsRowCount(numRows);" Remove it and everything will work. If in doubt, compare the XML definitions of some working table created manually in Excel and the definitions created with Apache POI
这篇关于使用 Apache POI 将结果集转换为 Excel (*.xlsx) 表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!