Apache POIでWordのファイルを読み込む


前書き

Apache POI を使って Excel のデータを読み込むことはよくある(?)ことだと思うけれど、先日今度は悲しくも
Word のデータを読み込む必要が生じたので、ここにメモを残す。

Apache POIによるWordファイルの編集 - M12i.によると、Word 内のデータは Range > Section > Paragraph > CharacterRun の階層構造で取得できるらしい。

というわけで、とりあえずどういう構造になっているのか全体を表示してみる。

ソースコード

build.gradle
...
repositories {
  mavenCentral()
}

dependencies {
  compile 'org.apache.poi:poi-scratchpad:3.11'
}

これは 2003 形式の Word ファイルを読み取っている。

Main.java
package com.example;

import java.util.stream.IntStream;

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.CharacterRun;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.hwpf.usermodel.Section;

public class Main {

  public static void main(String[] args) throws Exception {
    // クラスパス上に配置したWordファイルを読み込む。
    HWPFDocument document =
        new HWPFDocument(Main.class.getResourceAsStream("/sample.doc"));

    // ドキュメント全体を読み込む。
    Range text = document.getRange();

    IntStream.range(0, text.numSections()).forEach(sNo -> {
      Section section = text.getSection(sNo);

      IntStream.range(0, section.numParagraphs()).forEach(pNo -> {
        Paragraph paragraph = section.getParagraph(pNo);

        IntStream.range(0, paragraph.numCharacterRuns()).forEach(cNo -> {
          CharacterRun characterRun = paragraph.getCharacterRun(cNo);

          System.out.printf("%d:%d:%d:%s", sNo, pNo, cNo, characterRun.text());
          System.out.println();

        });
      });
    });

  }

}

Java 8 使いこなせてる感があまりないけれど、これでとりあえず全文 CharacterRun に分解した状態で表示できる。

残念ながら、謎の文字が紛れていてなかなか辛みある。