RowやCellをイテレータで処理する場合は未定義の行やセルに気を付ける
発生した問題
Apache POIを利用するシステム開発プロジェクトでは「指定したシートを読み込み、2次元配列に変換する」というようなAPIを作成することがあります。自分がかかわっているプロジェクトでもそのようなAPIが提供されており、おおよそ以下のように実装されていました (読み込ませるシートはすべて文字列になっている想定)
try (Workbook book = WorkbookFactory.create(Paths.get("target-book.xlsx").toFile())) {
Sheet sheet = book.getSheet("target-sheet");
List<List<String>> lists = new ArrayList<>();
for (Row row : sheet) {
List<String> list = new ArrayList<>();
for (Cell cell : row) {
list.add(cell.getStringCellValue());
}
lists.add(list);
}
doSomeThing(lists);
}
さてこの実装は少なくともこのAPIを提供したチームが公表していた仕様を満たしていませんでした。たとえばこのAPIを使って以下のようなExcelを読み込ませたとします。
このシートは以下のような二次元配列に変換されます。
[A1, B1, C1, D1, E1],
[B2, D2],
[A4, B4, C4, D4, E4]
しかしAPI提供チームがうたっていた仕様では、このExcelシートは以下のように変換されるはずでした。
[A1, B1, C1, D1, E1],
[ , B2, , D2],
[],
[A4, B4, C4, D4, E4]
つまり、空の行や空のセルについても適切に処理するというのがAPI仕様でしたが、実装はそのようになっていませんでした。
原因と対策
原因はRow
やCell
の読み込みにイテレータを利用していることです。Sheet
はIteratable<Row>
を、 Row
はIterable<Cell>
をそれぞれ実装していますが、これらを利用すると、未定義の行や未定義のセルについては、存在しないものとしてスキップします。上述の例でいうと、3行目やA2セルやA3セルは、Apache POI上、未定義として扱われてしまい、イテレータ読み込みではないものとしてスキップされてしまいます。
こういう空の行や空のセルをうまくハンドリングするには、Sheet.getRow
やRow.getCell
を使う必要があります。今回の場合は以下のように実装を修正しました。
try (Workbook book = WorkbookFactory.create(Paths.get("target-book.xlsx").toFile())) {
Sheet sheet = book.getSheet("target-sheet");
List<List<String>> lists = new ArrayList<>();
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
List<String> list = new ArrayList<>();
int len = (row == null) ? 0 : row.getLastCellNum();
for (int j = 0; j < len; j++) {
Cell cell = row.getCell(j);
list.add((cell == null) ? "" : cell.getStringCellValue());
}
lists.add(list);
}
doSomeThing(lists);
}
環境情報 (pom.xml抜粋)
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
Author And Source
この問題について(RowやCellをイテレータで処理する場合は未定義の行やセルに気を付ける), 我々は、より多くの情報をここで見つけました https://qiita.com/neko_the_shadow/items/8982cc5102421952a999著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .