2013年6月4日 星期二

用 Java 處理 Microsoft Excel (2):使用 Apache Poi

續前文「用 Java 處理 Microsoft Excel (1):使用 JXL
目標一樣是要把包含某些 key 的列全部刪掉~這次改用 Apache Poi [1] 來嘗試。

範例程式碼如下:
private static void searchRowInExcelUsingPoi (File excelFile, File excelFileNew) {
  int count = 0;
  FileInputStream fis = null;
  FileOutputStream fos = null;
  HSSFWorkbook workbook = null;
  
  try {
    fis = new FileInputStream(excelFile);
    //Get the workbook instance for XLS file 
    workbook = new HSSFWorkbook(fis);
     
    //Get first sheet from the workbook
    HSSFSheet sheet = workbook.getSheet("test");
    
    ArrayList<Row> list = new ArrayList<Row>();
     
    //Get iterator to all the rows in current sheet
    Iterator<Row> rowIterator = sheet.iterator();
    while(rowIterator.hasNext()) {
      Row row = rowIterator.next();
      Iterator<Cell> cellIter = row.cellIterator();
      if(cellIter.hasNext()) {
        // Get the key name.
        String key = row.cellIterator().next().getStringCellValue();
        if(key != null && key.length() > 0) {
          // Flag the row when it is found that should be removed.
          if(keyMap.get(key) != null)
            list.add(row);
        }
      }
    }
    
    // Remove the flagged row.
    for(Row row: list) {
      System.out.println("Remove #" + (++count) + ": " + row.cellIterator().next().getStringCellValue());
      sheet.removeRow(row);
    }
    
    fos = new FileOutputStream(excelFileNew);
    workbook.write(fos);
  } catch (Exception e) {
    e.printStackTrace();
  } finally {
    try {
      if(fos != null) fos.close();
      if(fis != null) fis.close();
    } catch (IOException e) {}
  }
}

處理過程中,因為使用 Iterator 的關係,如果直接邊掃邊刪除 Row,Java 會拋出 java.util.ConcurrentModificationException
也就是同時對同一個物件進行讀取和寫入,導致物件可能發生不一致的 Concurrent 問題。
因此這裡的處理方法是先把要刪掉的 Row 暫存到一個 ArrayList 上,然後等全掃完以後再一次進行刪除。

不過最後刪除完成的 Excel 檔,那些刪除的資料列其實都還在,只是內容變成空值了。
也許如果想把內容也刪掉,可能就要用建立新的 Sheet 的方式,把沒有被刪掉的資料列全都寫到新的 Sheet 裡吧。
但由於不知道 Apache Poi 可以保留多少資料列的排版資訊,因此這裡就沒有考慮這個作法了。

參考資料:
1、Apache POI - the Java API for Microsoft Documents
2、Read / Write Excel File In Java Using Apache POI

沒有留言: