【Java】Excelの値を読み込んで、JavaBeanに設定する

はじめに

現在結合テスト用のアプリを開発していて、結合テスト実施時の画面からの入力パターンはExcelにまとめています。テスト実施者はExcelを見て、画面にExcelの値を入力します。しかし、入力項目が多いため手入力だと実施するときに時間がかかってしまいます。 そこで、Excelの値を読み込んで自動的に入力項目を設定するようにします。ここで説明するのはそのための機能です。 apache poiを利用します。

イメージ

パターン2を指定すると、パターン2列の値がJavaBeanに設定されます。 f:id:ukiukichan:20161204210914p:plain

利用例

入力パターンと値を設定したいJavaBeanを指定します。

package test;

public class Main {
    public static void main(String[] args) {
        Form form = new Form();
        InputForm inputForm = new InputForm("./src/main/resources/test/input.xlsx", "sheet1");
        inputForm.inputForm("パターン2", form);
        
        // 確認用
        System.out.println("id:" + form.getId());
        System.out.println("name:" + form.getName());
        System.out.println("birthday:" + form.getBirthday());
    }

}

クラス一覧

  • ExcelReader Excelを読み込んで、2次元配列を返します。

  • inputForm JavaBeanにExcelの値を設定します。

  • Form JavaBeanです。

前提

Maven の設定

<!-- 省略 -->
  <dependencies>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.15</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.15</version>
    </dependency>
  </dependencies>
<!-- 省略 -->

ExcelReader

apache poi でExcelファイルを読み込み、2次元配列を返します。

package test;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
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.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class ExcelReader {
    public Object[][] read(String path, String sheetName) {
        try {
            BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(new File(path)));
            Workbook book = WorkbookFactory.create(inputStream);
            Sheet sheet = book.getSheet(sheetName);
            
            Object[][] table = new Object[sheet.getLastRowNum() + 1][];
            
            Iterator<Row> rowIterator = sheet.rowIterator();
            int rowCount = 0;

            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                Object[] record = new Object[row.getLastCellNum()];

                Iterator<Cell> cellIterator = row.cellIterator();
                int cellCount = 0;

                while (cellIterator.hasNext()) {
                    Cell cell = cellIterator.next();
                    switch (cell.getCellTypeEnum()) {
                    case STRING :
                        record[cellCount] = cell.getStringCellValue();
                        cellCount++;
                        break;
                    case NUMERIC :
                        record[cellCount] = DateUtil.isCellDateFormatted(cell) ? cell.getDateCellValue() : cell.getNumericCellValue();
                        cellCount++;
                        break;
                    }
                }
                table[rowCount] = record;
                rowCount++;
            }
            return table;
            
        } catch (InvalidFormatException | IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}

InputForm

シート名と入力値パターンを指定して、JavaBeanに値を設定します。 ExcelReaderを利用します。

package test;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;

public class InputForm {
    private static final String STRING = "String";
    private static final String DATE = "Date";
    private static final String BIGDECIMAL = "BigDecimal";
    
    private String path;
    private String sheetName;
    
    public InputForm(String path, String sheetName) {
        this.path = path;
        this.sheetName = sheetName;
    }
    
    public <T> void inputForm(String pattern, T target) {
        // Excelを読む
        Object[][] table = new ExcelReader().read(path, sheetName);
        
        // 指定されたパターンが何列目か取得する。
        Object[] firstRow = table[0];
        int count = 0;
        while (true) {
            Object cell = firstRow[count];
            if (pattern.equals(String.valueOf(cell))) {
                break;
            }
            count++;
        }
        int columnIndex = count;
        
        // 1行目のヘッダはスキップし、JavaBeanにExcelの値を設定する
        Arrays.stream(table).skip(1).forEach(row -> {
            String name = String.valueOf(row[0]);
            String type = String.valueOf(row[1]);
            Object value = row[columnIndex];
            try {
                Field field = target.getClass().getDeclaredField(name);
                field.setAccessible(true);

                switch (type) {
                case STRING :
                    field.set(target, (String) String.valueOf(value));
                    break;
                case DATE :
                    field.set(target, (Date) value);
                    break;
                case BIGDECIMAL :
                    field.set(target, new BigDecimal(String.valueOf(value)));
                    break;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

}

Form

JavaBeanです。

package test;

import java.math.BigDecimal;
import java.util.Date;

public class Form {
    private BigDecimal id;
    private String name;
    private Date birthday;
    public BigDecimal getId() {
        return id;
    }
    public void setId(BigDecimal id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

}

終わりに

エラーの制御はしていません。 クラス名がイマイチなので、いい名前が思いついたら修正します。 指摘いただけると嬉しいです。宜しくお願いします。