2016-05-21 9 views
2

私はapache poiを使い慣れていないので、Excelのファイルを行数に基づいて複数のファイルに分割したいと思っていました。apache poiを使用して行数に基づいて複数のファイルにExcelファイルを分割する方法は?

たとえば、data.xlsxは15k行、新しいファイルは5k行のdata_1.xlsx、data_2.xlsxは5~10k、data_3xlsxは10~15kである必要があります。

+0

これをよく読んで質問を改善してください: –

答えて

4

私はあなたを持っています。

package com.industries.seanimus; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 

import org.apache.poi.EncryptedDocumentException; 
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 
import org.apache.poi.openxml4j.opc.OPCPackage; 
import org.apache.poi.ss.usermodel.Cell; 
import org.apache.poi.ss.usermodel.DateUtil; 
import org.apache.poi.ss.usermodel.Row; 
import org.apache.poi.xssf.streaming.SXSSFCell; 
import org.apache.poi.xssf.streaming.SXSSFRow; 
import org.apache.poi.xssf.streaming.SXSSFSheet; 
import org.apache.poi.xssf.streaming.SXSSFWorkbook; 
import org.apache.poi.xssf.usermodel.XSSFSheet; 
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

public class ReportSplitter { 

    private final String fileName; 
    private final int maxRows; 

    public ReportSplitter(String fileName, final int maxRows) { 

     ZipSecureFile.setMinInflateRatio(0); 

     this.fileName = fileName; 
     this.maxRows = maxRows; 

     try { 
      /* Read in the original Excel file. */ 
      OPCPackage pkg = OPCPackage.open(new File(fileName)); 
      XSSFWorkbook workbook = new XSSFWorkbook(pkg); 
      XSSFSheet sheet = workbook.getSheetAt(0); 

      /* Only split if there are more rows than the desired amount. */ 
      if (sheet.getPhysicalNumberOfRows() >= maxRows) { 
       List<SXSSFWorkbook> wbs = splitWorkbook(workbook); 
       writeWorkBooks(wbs); 
      } 
      pkg.close(); 
     } 
     catch (EncryptedDocumentException | IOException | InvalidFormatException e) { 
      e.printStackTrace(); 
     } 
    } 

    private List<SXSSFWorkbook> splitWorkbook(XSSFWorkbook workbook) { 

     List<SXSSFWorkbook> workbooks = new ArrayList<SXSSFWorkbook>(); 

     SXSSFWorkbook wb = new SXSSFWorkbook(); 
     SXSSFSheet sh = wb.createSheet(); 

     SXSSFRow newRow; 
     SXSSFCell newCell; 

     int rowCount = 0; 
     int colCount = 0; 

     XSSFSheet sheet = workbook.getSheetAt(0); 

     for (Row row : sheet) { 
      newRow = sh.createRow(rowCount++); 

      /* Time to create a new workbook? */ 
      if (rowCount == maxRows) { 
       workbooks.add(wb); 
       wb = new SXSSFWorkbook(); 
       sh = wb.createSheet(); 
       rowCount = 0; 
      } 

      for (Cell cell : row) { 
       newCell = newRow.createCell(colCount++); 
       newCell = setValue(newCell, cell); 

       CellStyle newStyle = wb.createCellStyle(); 
       newStyle.cloneStyleFrom(cell.getCellStyle()); 
       newCell.setCellStyle(newStyle); 
      } 
      colCount = 0; 
     } 

     /* Only add the last workbook if it has content */ 
     if (wb.getSheetAt(0).getPhysicalNumberOfRows() > 0) { 
      workbooks.add(wb); 
     } 
     return workbooks; 
    } 

    /* 
    * Grabbing cell contents can be tricky. We first need to determine what 
    * type of cell it is. 
    */ 
    private SXSSFCell setValue(SXSSFCell newCell, Cell cell) { 
     switch (cell.getCellType()) { 
     case Cell.CELL_TYPE_STRING: 
      newCell.setCellValue(cell.getRichStringCellValue().getString()); 
      break; 
     case Cell.CELL_TYPE_NUMERIC: 
      if (DateUtil.isCellDateFormatted(cell)) { 
       newCell.setCellValue(cell.getDateCellValue()); 
      } else { 
       newCell.setCellValue(cell.getNumericCellValue()); 
      } 
      break; 
     case Cell.CELL_TYPE_BOOLEAN: 
      newCell.setCellValue(cell.getBooleanCellValue()); 
      break; 
     case Cell.CELL_TYPE_FORMULA: 
      newCell.setCellFormula(cell.getCellFormula()); 
      break; 
     default: 
      System.out.println("Could not determine cell type"); 
     } 
     return newCell; 
    } 

    /* Write all the workbooks to disk. */ 
    private void writeWorkBooks(List<SXSSFWorkbook> wbs) { 
     FileOutputStream out; 
     try { 
      for (int i = 0; i < wbs.size(); i++) { 
       String newFileName = fileName.substring(0, fileName.length() - 5); 
       out = new FileOutputStream(new File(newFileName + "_" + (i + 1) + ".xlsx")); 
       wbs.get(i).write(out); 
       out.close(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args){ 
     /* This will create a new workbook every 1000 rows. */ 
     new ReportSplitter("Data.xlsx", 1000); 
    } 

} 

いくつかの注意事項:

  • ワークブックを書き込むためには、私は SXSSFWorkbookを使用しています。これは、 がHSSFまたはXSSFより速く、すべてをのメモリに保存していないため、書き込み前に(恐ろしいgc混乱を引き起こします)、 となります。

  • Busy Developer's GuideのApache POIを学ぶためにあなたの友人がある;)

お楽しみください!


編集:セルスタイルもコピーするようにコードを更新しました。これに注意する2つのこと:

  • スタイルをコピーすると、処理が大幅に遅くなります。
  • POIはエラーを検出しジップ爆弾を投げ、圧縮されていないことを大きすぎるになるかもしれtemplateファイルを作成します。これは、最低インフレ率をZipSecureFile.setMinInflateRatio(0)で変更することで解決できます。
+1

これはどのように必要なスタイルと他の関連するアーティファクトを複製しますか?それとも、すべてがデフォルトのスタイルを使用していると仮定していますか? – jmarkmurphy

+0

基本的なスタイル(フォント、整列、罫線、色など)をコピーするようにコードを更新しました。しかし、Excelワークブックにはさまざまなプロパティがあり、多くのデータを扱うときには大きな遅延が発生します。特に必要なものがあれば追加することができますが、ほとんどが最初に存在しないときはすべてをコピーしようとするのは間違いでしょう。 – Seanimus

+0

Seanimusさんに感謝しています。 – rambo

関連する問題