Apache POI を使用した Excel の操作はずいぶん昔からコードを書いていた。
PushbackInputStream を使用する - Oboe吹きプログラマの黙示録
Excel 拡張子 (xls) (xlsx) 両方に対応した操作 Apache POI (2) - Oboe吹きプログラマの黙示録
Excel 拡張子 (xls) (xlsx) 両方に対応した操作 Apache POI(1) - Oboe吹きプログラマの黙示録
Apache POI でExcel 日付読込み(2) - Oboe吹きプログラマの黙示録
Apache POI でExcel 日付読込み - Oboe吹きプログラマの黙示録
Apache POI 入力規則リストの生成 - Oboe吹きプログラマの黙示録
Apache POI Excel 入力規則の読み込み(2) - Oboe吹きプログラマの黙示録
Apache POI Excel入力規則の読み込み(1) - Oboe吹きプログラマの黙示録
先日書いた ExcelWorker にさらにメソッドを追加する。
/** * Sheet ⇒ 読込みObject * @param <R> * @param sheetName シート名 * @param func Function<Sheet, R> * @return R */ public <R> R readSheetValue(String sheetName, Function<Sheet, R> func) { return Optional.ofNullable(book.getSheet(sheetName)).map(func::apply).orElse(null); } /** * Sheet の全行 ⇒ 読込みObjecのリスト * @param <R> * @param sheetName シート名 * @param func Function<Row, R> * @return List<R> */ public <R> List<R> readRowList(String sheetName, Function<Row, R> func) { Sheet sheet = book.getSheet(sheetName); if (sheet==null) return new ArrayList<>(); int last = sheet.getLastRowNum(); return IntStream.range(0, last).boxed().map(i->func.apply(sheet.getRow(i))).collect(Collectors.toList()); } /** * Sheet の全行 ⇒ 読込みObjecのリスト(行番号認識して) * @param <R> * @param sheetName シート名 * @param func Function<Integer, Row, R> * @return List<R> */ public <R> List<R> readRowList(String sheetName, BiFunction<Integer, Row, R> func) { Sheet sheet = book.getSheet(sheetName); if (sheet==null) return new ArrayList<>(); int last = sheet.getLastRowNum(); return IntStream.range(0, last).boxed().map(i->func.apply(i, sheet.getRow(i))).collect(Collectors.toList()); }
Excel 拡張子 (xls) (xlsx) 両方に対応した操作 Apache POI (2) - Oboe吹きプログラマの黙示録
で書いていた、 Excelworker もいいかげん、まとめたものにしておきたい。
import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.FileMagic; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.Cell; 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; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.util.IOUtils; /** * ExcelWorker */ public class ExcelWorker implements Closeable{ private Workbook book; private static final int MAX_PATTERN_LENGTH = 44; /** * コンストラクタ(File指定) * @param inst 読込み対象ExcelのInputStream * @throws IOException * @throws EncryptedDocumentException */ public ExcelWorker(InputStream inst) throws EncryptedDocumentException, IOException { PushbackInputStream inp = new PushbackInputStream(inst, MAX_PATTERN_LENGTH); byte[] data = new byte[MAX_PATTERN_LENGTH]; inp.read(data, 0, MAX_PATTERN_LENGTH); inp.unread(data); FileMagic fm = FileMagic.valueOf(data); if (FileMagic.OOXML==fm){ book = new XSSFWorkbook(inp); }else if(FileMagic.OLE2==fm){ book = new HSSFWorkbook(inp); }else { book = WorkbookFactory.create(inp); } } /** * コンストラクタ(File指定) * @param file 読込み対象ExcelのFile * @throws IOException * @throws EncryptedDocumentException */ public ExcelWorker(File file) throws EncryptedDocumentException, IOException{ FileMagic fm = valueFileMagic(file); if (fm==FileMagic.OOXML) { book = new XSSFWorkbook(new FileInputStream(file)); }else if(fm==FileMagic.OLE2){ book = new HSSFWorkbook(new FileInputStream(file)); }else { book = WorkbookFactory.create(new FileInputStream(file)); } } private FileMagic valueFileMagic(File file) throws IOException { try(FileInputStream fis = new FileInputStream(file)) { byte[] data = new byte[MAX_PATTERN_LENGTH]; int read = IOUtils.readFully(fis, data, 0, MAX_PATTERN_LENGTH); if(read == -1) { return FileMagic.UNKNOWN; } data = Arrays.copyOf(data, read); return FileMagic.valueOf(data); } } /** * Excelバージョンを返す * @return SpreadsheetVersion,EXCEL2007 か。SpreadsheetVersion,EXCEL97 を返します */ public SpreadsheetVersion getSpreadsheetVersion() { return book.getSpreadsheetVersion(); } /** * Apche POI Workbook参照 * @return */ public Workbook getWorkbook() { return book; } /** * 先頭シート読み出し行(Row) Consumer を実行 * * @param action Consumer<Row> */ public void readFirstSheet(Consumer<Row> action) { Sheet sheet = book.getSheetAt(0); IntStream.rangeClosed(0, sheet.getLastRowNum()).mapToObj(n->sheet.getRow(n)).forEach(row->action.accept(row)); } /** * 制限付き先頭シート読み出し行(Row) Consumer を実行 * * @param pre 制限として指定する Predicate<Row> * @param action Consumer<Row> */ public void readFirstSheet(Predicate<Row> pre, Consumer<Row> action) { Sheet sheet = book.getSheetAt(0); IntStream.rangeClosed(0, sheet.getLastRowNum()).mapToObj(n->sheet.getRow(n)).filter(pre).forEach(row->action.accept(row)); } /** * 全ての Sheet Stream */ public Stream<Sheet> getSheets(){ return IntStream.range(0, book.getNumberOfSheets()).mapToObj(n->book.getSheetAt(n)); } /** * 全てのSheet読み出しConsumerを実行 * @param action Consumer<Sheet> */ public void getSheets(Consumer<Sheet> action){ IntStream.range(0, book.getNumberOfSheets()).mapToObj(n->book.getSheetAt(n)).forEach(action); } /** * Sheet ⇒ 読込みObject * @param <R> * @param sheetName シート名 * @param func Function<Sheet, R> * @return R */ public <R> R readSheetValue(String sheetName, Function<Sheet, R> func) { return Optional.ofNullable(book.getSheet(sheetName)).map(func::apply).orElse(null); } /** * Sheet の全行 ⇒ 読込みObjecのリスト * @param <R> * @param sheetName シート名 * @param func Function<Row, R> * @return List<R> */ public <R> List<R> readRowList(String sheetName, Function<Row, R> func) { Sheet sheet = book.getSheet(sheetName); if (sheet==null) return new ArrayList<>(); int last = sheet.getLastRowNum(); return IntStream.range(0, last).boxed().map(i->func.apply(sheet.getRow(i))).collect(Collectors.toList()); } /** * Sheet の全行 ⇒ 読込みObjecのリスト(行番号認識して) * @param <R> * @param sheetName シート名 * @param func Function<Integer, Row, R> * @return List<R> */ public <R> List<R> readRowList(String sheetName, BiFunction<Integer, Row, R> func) { Sheet sheet = book.getSheet(sheetName); if (sheet==null) return new ArrayList<>(); int last = sheet.getLastRowNum(); return IntStream.range(0, last).boxed().map(i->func.apply(i, sheet.getRow(i))).collect(Collectors.toList()); } /** * 全てのSheet読み出しConsumerを実行 * @param action Consumer<Sheet> */ public static Stream<Row> getRowStream(Sheet sheet) { return IntStream.rangeClosed(0, sheet.getLastRowNum()).mapToObj(n->sheet.getRow(n)); } /** * 行からセルのStreamを取得 * @param row Row * @return Stream<Cell> */ public static Stream<Cell> getCellStream(Row row){ return IntStream.range(0, row.getLastCellNum()).mapToObj(n->row.getCell(n)); } /** * シートデフォルト名で新規シート作成、先頭シートを size - 1 個クローンする。 * @param book 作成対象Workbook * @param size 新規作成シート数 * @return 作成したシートのStream */ public static Stream<Sheet> createAndSheets(Workbook book, int size) { book.createSheet(); for(int n=1; n < size;n++) { book.cloneSheet(0); } return StreamSupport.stream(Spliterators.spliteratorUnknownSize(book.sheetIterator(), Spliterator.ORDERED), false); } /** * シート名を指定した新規シート作成 * @param book 作成対象Workbook * @param names 新規作成するシート名、可変長配列 * @return 作成したシートのStream */ public static Stream<Sheet> createAndSheets(Workbook book, String...names) { book.createSheet(names[0]); for(int n=1; n < names.length;n++) { book.createSheet(names[n]); } return StreamSupport.stream(Spliterators.spliteratorUnknownSize(book.sheetIterator(), Spliterator.ORDERED), false); } @Override public void close() throws IOException{ book.close(); } }