LoginSignup
8
10

More than 5 years have passed since last update.

Apache POI で拡張for文を使うときの注意点

Posted at

これは何?

Apache Poiを使ってExcelを読み込むプログラムを書いた時にはまったのでメモ。

環境

  • Java8(jdk1.8.0_102)
  • Apache Poi(3.14)
  • eclipse

再現メモ

Maven

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>apachePoiTest</groupId>
    <artifactId>apachePoiTest</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.14</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.14</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.14</version>
        </dependency>
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <javac.target>1.8</javac.target>
    </properties>


</project>

Java

package apachePoiTest;

import java.io.FileInputStream;

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;

public class Test {

    private static final String xlsxFileAddress = "G:\\work\\Test.xlsx";

    public static void main(String[] args) {
        try {

            // 共通インターフェースを扱える、WorkbookFactoryで読み込む
            Workbook wb = WorkbookFactory.create(new FileInputStream(xlsxFileAddress));

            // 全セルを表示する
            for (Sheet sheet : wb) {
                for (Row row : sheet) {

                    test1(row);
                    System.out.println();
                    test2(row);

                }
            }

            wb.close();

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

        }

    }

    private static void test1(Row row) {

        System.out.println("標準のfor文で回すパターン");

        for (int i = 0; i < 5; i++) {
            Cell cell = row.getCell(i);
            System.out.print(getCellValue(cell));
            System.out.print(" , ");
        }
        System.out.println();

    }

    private static void test2(Row row) {

        System.out.println("拡張for文で回すパターン");
        for (Cell cell : row) {
            System.out.print(getCellValue(cell));
            System.out.print(" , ");
        }
        System.out.println();

    }

    private static Object getCellValue(Cell cell) {

        if (cell == null) {
            return "";
        }

        switch (cell.getCellType()) {

        case Cell.CELL_TYPE_STRING:
            return cell.getRichStringCellValue().getString();

        case Cell.CELL_TYPE_NUMERIC:
            return cell.getNumericCellValue();

        case Cell.CELL_TYPE_BOOLEAN:
            return cell.getBooleanCellValue();

        case Cell.CELL_TYPE_FORMULA:
            return cell.getCellFormula();

        default:
            return null;

        }

    }
}

テスト用Excel

excel.PNG

何が起こるのか

拡張For文でcellを読んだ時は、D1のセルが読み飛ばされてしまう。

標準のfor文で回すパターン
Cell1 , Cell2 , Cell3 ,  , Cell5 , 

拡張for文で回すパターン
Cell1 , Cell2 , Cell3 , Cell5 , 

結論

  • 空白がある可能性があるExcelデータを読み込むときは、セルの数は事前に確認してfor文で回す回数を明記すること。
  • 拡張for文は便利だけど、このようなトラップもあるということを知っておく必要がある。(普通のListとか配列なら問題ないけど)

有識者へのお願い

この仕様について明記されている資料等知ってましたら教えてください。

8
10
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10