ResultSet到Excel(* .xlsx)表使用Apache POI

我正在尝试使用Apache Poi将ResultSet写入Excel(* .xlsx)表

Office Excel中无效的表格对象错误

但是,即使它在没有任何错误的情况下写入Excel文件,但当我尝试在Office Excel 2013中打开它时,它将显示一个错误并删除表格对象以仅显示纯数据视图。

消息,同时打开文件

消除错误后的消息

以下是使用此示例的粗略示例代码:

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创build,则使用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> 

如果手动创build表,则在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创build的主题文件夹,但是它存在于Office Excel中手动创build的文件夹中。 奇怪。

更新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

你的代码有什么问题是单行的出现。 “cttable.setTotalsRowCount(numRows行);” 删除它,一切都会工作。 如果有疑问,请比较Excel中手动创build的某些工作表的XML定义和使用Apache POI创build的定义

我遇到过同样的问题。

深入挖掘,我发现对于XLSX包中的某些表格XML数据,Excel正在将单个>更改为> 在执行修理之后。 来自POI的XML是有意义的(使用<>来包围XML元素),所以我不知道为什么微软select打破它。

如果你的情况相同,我也不会太担心。

如果你想看看你是否有这个特别的区别:

  1. 用POI创buildXLSX
  2. 用Excel修复XLSX并保存到新文件
  3. 用ZIP编辑器打开这两个文件(例如7Zip)
  4. findxl / tables / table1.xml
  5. 导出这两个XML文件(POI和Excel修复)
  6. 区分这些文件

您尚未正确创build表格。 检查:

  • 你在cttable中创build了标题列吗?
  • 您是否通过cell.setCellValue创build了相同的标题列?
  • 删除空的第一个标题列(POI BUG)结束

    CTTable()getTableColumns()removeTableColumn(0)。。

把debugging到XSSFTable.class,方法updateHeaders()。

如果你的表格没有正确创build,那么

 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++; } } }