ExcelでPDFを作成→iTextでタグ情報を読み込む

普通はExcel形式で保存してPOIで読み込むことが多いんだけど、訳あってPDF形式で保存した場合でもテーブル形式のタグ情報が保存されるので、ここから値が取得できる。

## Javaソース

ライブラリはiTextを使用。
タグ構造の読み込みはTaggedPdfReaderToolクラスで行う。

```java
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.TaggedPdfReaderTool;

public class ReadPdf {
    public static void main(String[] args) {
        PdfReader reader = null;
        try {
            // PDFの読み込み
            reader = new PdfReader("Book1.pdf");

            // 構造化タグの取得
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            TaggedPdfReaderTool taggedReader = new TaggedPdfReaderTool();
            taggedReader.convertToXml(reader, out, "UTF-8");

            // DOMの生成
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(new ByteArrayInputStream(out.toByteArray()));

            // ファイルに書き込む
            Transformer tf = TransformerFactory.newInstance().newTransformer();
            tf.setOutputProperty(OutputKeys.INDENT, "yes");
            tf.setOutputProperty(OutputKeys.METHOD, "xml");
            tf.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "4");
            tf.transform(new DOMSource(doc), new StreamResult(new File("Book1.xml")));
        } catch (IOException | ParserConfigurationException | SAXException | TransformerException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }
}
```

## Excelファイル

![excel-sheet.png](https://qiita-image-store.s3.amazonaws.com/0/35192/c19439d0-2484-9693-36ea-6eaa88ddb6cb.png)

名前を付けて保存＞PDFまはたXPS＞オプション＞「アクセシビリティ用のドキュメント構造タグ」をチェックして保存。
![excel-save-option.png](https://qiita-image-store.s3.amazonaws.com/0/35192/12d2ca6e-fd6f-8277-667a-9d8bcb80f1d6.png)

## PDFから取得したタグ構造

HTMLのテーブルのようなタグ構造になっている。

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Workbook>
    <Worksheet>
        <Table>
            <TR>
                <TD>
                    <P>ABC Report</P>
                </TD>
            </TR>
            <TR>
                <TD>
                    <P>2014/3/24</P>
                </TD>
            </TR>
            <TR>
                <TD>
                    <P>Goup1</P>
                </TD>
            </TR>
            <TR>
                <TD>
                    <P>Item1-1</P>
                </TD>
                <TD>
                    <P>Value1-1</P>
                </TD>
            </TR>
            <TR>
                <TD>
                    <P>Item1-2</P>
                </TD>
                <TD>
                    <P>Value1-2</P>
                </TD>
            </TR>
            <TR>
                <TD>
                    <P>Group2</P>
                </TD>
            </TR>
            <TR>
                <TD>
                    <P>Item2-1</P>
                </TD>
                <TD>
                    <P>Value2-1</P>
                </TD>
            </TR>
            <TR>
                <TD>
                    <P>Item2-2</P>
                </TD>
                <TD>
                    <P>Value2-2</P>
                </TD>
            </TR>
        </Table>
    </Worksheet>
</Workbook>
```

表にするとこんな感じ
※空白セルは出力されないので列がずれていることに注意

|列1|列2|
|:-----------|:-----------|
|ABC Report | |
|2014/3/24| |
|Goup1| |
|Item1-1|Value1-1|
|Item1-2|Value1-2|
|Goup2| |
|Item2-1|Value2-1|
|Item2-2|Value2-2|