Apache POI （WORD文書） 逆引きリファレンス

Apache POIを利用したWORD文書の作成方法のTipsを、忘備録として記録しておく。

# 準備などなど
Apache POIのHPは[こちら](https://poi.apache.org/index.html)。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/5d1e6096-5e29-3a28-ad69-5e60326e0748.png)

ここからダウンロードなどする。
ヘルプもここからたどれる。

# 文書

## 文書の作成

```java
import org.apache.poi.xwpf.usermodel.XWPFDocument;

XWPFDocument document = new XWPFDocument();
```

## 段落の作成

```java
import org.apache.poi.xwpf.usermodel.XWPFParagraph;

XWPFParagraph paragraph = document.createParagraph();
```

### センタリング
もちろん、左寄せ（LEFT）や右寄せ（RIGHT）等も可能。

```java
paragraph.setAlignment(ParagraphAlignment.CENTER);
```

### インデント
単位は目盛×200。
（目盛が1/10ポイントだから？）

```java
paragraph.setIndentationLeft(4*200);
```

## 文の作成
1行を複数の文で分割するイメージ。

```java
import org.apache.poi.xwpf.usermodel.XWPFRun;

XWPFRun run = paragraph.createRun();
```

### 本文

```java
run.setText("本文");
```

### 改行

```java
run.addCarriageReturn();
```

### 装飾
それぞれ設定はいろいろ変えられる。

```java
run.setFontFamily("ＭＳ 明朝");  // フォント
run.setFontSize(22);  // フォントサイズ
run.setColor("ff0000");  // 文字色
run.setBold(true);  // 太字
run.setItalic(true);  // イタリック
run.setUnderline(UnderlinePatterns.SINGLE);  // 下線
```

※下線は、文の最後につながるスペース列の下には表示されないので注意（最後にノーブレークスペースを入れることで回避可能）

### ハイライト
もちろん、他の色の設定可能。

```java
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHighlightColor;

run.getCTR().addNewRPr().addNewHighlight().setVal(STHighlightColor.YELLOW);  // ハイライト
```

## 出力
docxファイルとかに出力。

```java
document.write(outputStream);
```

# 罫線

## 罫線の作成

```java
import org.apache.poi.xwpf.usermodel.XWPFTable;

XWPFTable table = document.createTable(3, 2); // 横:3、縦:2
```

## カラム内の段落の取得
取得した段落に対して、通常のように設定が可能。
1つのカラムに1つの段落はあらかじめ作成されている。

```java
paragraph = table.getRow(i).getCell(j).getParagraphs().get(0);
```

段落の追加も可能。

```java
paragraph = table.getRow(i).getCell(j).addParagraph();
```

## 幅
単位はポイント×20。

```java
table.setWidth(10304);
```

カラムの幅は、最初の行だけ指定すればよい。

```java
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblLayoutType;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;

CTTblLayoutType type = table.getCTTbl().getTblPr().addNewTblLayout();
type.setType(STTblLayoutType.FIXED);  // 固定幅を設定

CTTc ctTc = table.getRow(0).getCell(j).getCTTc();
CTTcPr tcPr = (ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr());
CTTblWidth tblWidth = (tcPr.isSetTcW() ? tcPr.getTcW() : tcPr.addNewTcW());
tblWidth.setW(BigInteger.valueOf(3780);
```

## 上下位置
中央（CENTER）以外に上（TOP）や下（BOTTOM）も設定可能。

```java
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableCell.XWPFVertAlign;

XWPFTableCell tblCell = table.getRow(i).getCell(j);
tblCell.setVerticalAlignment(XWPFVertAlign.CENTER);
```

## マージン
上、左、下、右の順。
単位はポイント×20。

```java
table.setCellMargins(20, 20, 20, 20);
```

## 罫線の配置位置
センタリングの場合。
（左寄せ：LEFT、右寄せ：RIGHT、などなど）

```java
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;

CTTblPr tblPr = table.getCTTbl().getTblPr();
CTJc jc = (tblPr.isSetJc() ? tblPr.getJc() : tblPr.addNewJc());
jc.setVal(STJc.CENTER);
```

## 線種等の変更
カラムの上の線の種類と太さを変更。
（上：Top、下：Bottom、左：Left、右：Right）
線種は通常（SINGLE）、太さの違う二重線（THIN_THICK_SMALL_GAP）、無し（NIL ※NONEではない）など。
太さの単位はポイント×8。

```java
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcBorders;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;

CTTc ctTc = table.getRow(i).getCell(j).getCTTc();
CTTcPr tcPr = (ctTc.isSetTcPr() ? ctTc.getTcPr() :　ctTc.addNewTcPr());
CTTcBorders tblBorders = (tcPr.isSetTcBorders() ? tcPr.getTcBorders() : tcPr.addNewTcBorders());
CTBorder ctbTop = (tblBorders.isSetTop() ? tblBorders.getTop() : tblBorders.addNewTop());
ctbTop.setVal(STBorder.SINGLE);
ctbTop.setSz(BigInteger.valueOf(4));
```

# その他

## 用紙設定
A4を設定した場合。
横向きにするときは「PORTRAIT」を「LANDSCAPE」に。
用紙サイズ等の単位はポイント×20。
それぞれの用紙サイズは[こちら](https://www.gnu.org/software/gv/manual/html_node/Paper-Keywords-and-paper-size-in-points.html)を参照。
マージン、ヘッダ・フッタは単位がmmではなくポイント×20なので要注意。

```java
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STPageOrientation
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageMar;

CTDocument1 doc1 = document.getDocument();
CTBody body = doc1.getBody();
CTSectPr section = (body.isSetSectPr() ? body.getSectPr() : body.addNewSectPr());

// 用紙サイズ
CTPageSz pageSize = (section.isSetPgSz() ? section.getPgSz() : section.addNewPgSz());
pageSize.setOrient(STPageOrientation.PORTRAIT);
pageSize.setW(BigInteger.valueOf(595*20));
pageSize.setH(BigInteger.valueOf(842*20));

// マージン
CTPageMar pageMar = (section.isSetPgMar() ? section.getPgMar() : section.addNewPgMar());
pageMar.setTop(BigInteger.valueOf(851));
pageMar.setBottom(BigInteger.valueOf(851));
pageMar.setLeft(BigInteger.valueOf(851));
pageMar.setRight(BigInteger.valueOf(851));

// ヘッダ、フッタ
pageMar.setHeader(BigInteger.valueOf(851));
pageMar.setFooter(BigInteger.valueOf(851));
```

※WORDでmmで設定して、オプションで単位をポイントにして確認するとよい
![image1.png](https://qiita-image-store.s3.amazonaws.com/0/130771/8b73e73c-372c-c411-210d-f7446e736003.png)


# 参考
WORDで調べたい文章を作成し、XMLで出力すると、意外と設定値などわかることがある。
![image2.png](https://qiita-image-store.s3.amazonaws.com/0/130771/fe0f7672-b1cc-4a91-48b6-0632f5ea8c07.png)