2014-08-29 4 views
7

Я пытаюсь написать ResultSet to Excel (* .xlsx) Таблица с использованием Apache Poi.Таблица результатов в Excel (* .xlsx) с использованием Apache POI

Invalid Ошибка Таблица объектов в Office Excel

Однако, несмотря на то, что записывает файл Excel без каких-либо ошибок, когда я пытаюсь открыть его в Office Excel 2013, он показывает ошибку и удаляет объект таблицы чтобы получить только простой вид данных.

Message while opening file

Message after removing errors

Вот грубый Пример кода 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!"); 
     } 
    } 
} 

Я знаю, что что-то случилось с моим кодом, но не могу понять это. Любая идея, почему это происходит, где была бы потенциальная ошибка в моем коде.

Update 1:

Таблица XML файл в архиве Excel, если создается с помощью 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> 

таблицы XML-файл в архиве Excel, если таблица, созданная вручную

<?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. Странный.

Update 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

пои-3,11 -beta2-20140822.jar

пои-OOXML-3,11-beta2-20140822.jar

XMLBeans-2.6.0.jar

+0

Вы уверены, что используете последнюю версию Apache POI? (3.11 beta 2 на момент написания) – Gagravarr

+0

@Gagravarr: да, я использую точно такую ​​же версию. – Indigo

+0

Хмм, надоедливый ... Может ли Apache POI читать файл, созданный без ошибок? Может ли он увидеть стол? А как насчет Open Office - поддерживает ли этот файл файл + видеть таблицу или присоединяется к Excel в жалобах? – Gagravarr

ответ

0

Я была такая же проблема.

Копая глубоко, я обнаружил, что для некоторых XML-данных таблицы в пакете XLSX Excel меняет один > на &gt; после выполнения ремонта. XML из POI имеет смысл (используйте < и > для окружения элементов XML), поэтому я понятия не имею, почему Microsoft решает его разбить.

Если это тот же случай для вас, я бы не стал слишком беспокоиться об этом.

Если вы хотите увидеть, если у вас есть это особое значение:

  1. Создать XLSX с POI
  2. Ремонт XLSX с Excel и сохранить в новом файле
  3. Открыть оба файла с ZIP редактора (например, 7Zip)
  4. поиск х/столы/table1.xml
  5. Экспорт как XML-файлы (POI и Excel-ремонтировали)
  6. Diff файлы
+0

Все должно быть экранировано при написании Apache POI (он использует библиотеку XML, которая должна это делать). Какой элемент вы должны изменить? – Gagravarr

+0

Экземпляр, который я исследовал, не включал никаких изменений в данные. Это было прочитано из файла XLSX, созданного в Excel, и сохранили его для нового действия файла (никаких других действий не было выполнено). POI читается в '>' конвертируется в '>', но Excel видел это как плохое изменение. –

+0

Можете ли вы опубликовать фрагмент xml из до и после, чтобы мы могли видеть, для какого xml-элемента это происходит? – Gagravarr

0

Вы не создали свою таблицу правильно. Проверка:

  • Вы создали столбцы заголовков в cttable?
  • Созданы ли те же заголовковые столбцы через cell.setCellValue?
  • Удалить пустой первый столбец заголовка (POI BUG) в конце

    CTTable() getTableColumns() removeTableColumn (0)..;

Put отладки в 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++; 
     } 
    } 
} 
3

Что случилось с вашим кодом является наличие одной линии. "cttable.setTotalsRowCount (numRows);" Удалите его, и все будет работать. Если вы сомневаетесь, сравните определения XML какой-либо рабочей таблицы, созданной вручную в Excel, и определения, созданные с помощью Apache POI.

Смежные вопросы