WordのインデントをVBAで操作する

# はじめに
Microsoft Wordのインデントは、英語版に日本語版の設定を重ねたことによるのか、とてもクセがあるものになっています。
文頭が揃わず、イライラさせられることも多いのではないでしょうか。

さらに、インデントをVBAで操作しようとすると、それぞれのプロパティが複雑に絡み合い、一筋縄ではいきませんでした。

以下は、Wordのインデントに関する覚書です。

# Wordのインデント
まず、Wordのインデントを確認しておきます。

## インデントの種類

* 字下げインデント
![doc1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29598/a87ef889-7fd1-93ba-c53c-ec239cc386a9.png)
「最初の行(S)」に「字下げ」を設定することで1行目を字下げすることができます。
「インデント」「左(L)」に設定した数値分、2行目以下がインデントされます。
これに「字下げ」の「幅(Y)」に設定した数値分、1行目が字下げインデントされます。

* ぶら下げインデント
![doc2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29598/854c4df7-8494-5345-f110-4610c6e0e8eb.png)
「最初の行(S)」に「ぶら下げ」を設定することで1行目を字下げすることができます。
「インデント」「左(L)」に設定した数値分、1行目がインデントされます。
これに「ぶら下げ」の「幅(Y)」に設定した数値分、2行目以下がぶら下げインデントされます。

## インデントの単位
![config3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29598/f39afbe6-4cb4-ff1a-d38e-b41e1ba20a9a.png)
「字」単位以外に、「mm」単位でもインデント幅を設定することができます。
しかし、「mm」単位だとうまく行頭が揃いません。
また、「字」単位と混在することがVBAでの操作でも支障を来す原因となっています。

# VBAにおけるインデント関係のプロパティ
[ParagraphFormatオブジェクト](https://docs.microsoft.com/ja-jp/office/vba/api/word.paragraphformat "ParagraphFormat オブジェクト (Word)")のプロパティとして、次の４つがあります。
* (A)[LeftIndent](https://docs.microsoft.com/ja-jp/office/vba/api/word.paragraphformat.leftindent "ParagraphFormat.LeftIndent プロパティ (Word)")
* (B)[CharacterUnitLeftIndent](https://docs.microsoft.com/ja-jp/office/vba/api/word.paragraphformat.characterunitleftindent "ParagraphFormat.CharacterUnitLeftIndent プロパティ (Word)")
* (C)[FirstLineIndent](https://docs.microsoft.com/ja-jp/office/vba/api/word.paragraphformat.firstlineindent "")
* (D)[CharacterUnitFirstLineIndent](https://docs.microsoft.com/ja-jp/office/vba/api/word.paragraphformat.characterunitfirstlineindent "ParagraphFormat.CharacterUnitFirstLineIndent プロパティ (Word)")

(A)LeftIndent と (B)CharacterUnitLeftIndent が全体のインデント幅を設定するプロパティです。
そして、(C)FirstLineIndent と (D)CharacterUnitFirstLineIndent が字下げ・ぶら下げ幅のプロパティです。

また、(A)LeftIndent と (C)FirstLineIndent が「mm単位」のインデント幅と紐付けされるプロパティで、単位は「ポイント」です。これに対し、(B)CharacterUnitLeftIndent と (D)CharacterUnitFirstLineIndent が「字単位」のインデント幅と紐付けされるプロパティで、単位は「字」です。
以下、便宜上、前者を「非char系」、後者を「char系」と総称します。

# 各プロパティの関係
(A)LeftIndent に値を設定すれば、(B)CharacterUnitLeftIndent に反映され、逆もまた真なり…であればいいのですが、そうはなりません。
非char系とchar系は完全に独立しています。
また、そもそも、どの部分を示す値なのかすら異なります。
そして、非char系の設定とchar系の設定が相互に邪魔をし合うことすらあります。

## 各プロパティの値が示すもの
* (A)LeftIndent … 2行目以下の絶対的なインデント幅
* (B)CharacterUnitLeftIndent … 段落全体の突出部のインデント幅
* (C)FirstLineIndent … LeftIndentを基準とする1行目の相対的なインデント幅
* (D)CharacterUnitFirstLineIndent … プラスの値なら字下げ幅、マイナスならぶら下げ幅

ひとことで表せば上記のとおりですが、以下、具体的に見ていきます。

### 字下げの場合
字下げの場合、結果としてchar系と非char系の値が示すものは異なりません。
(B)CharacterUnitLeftIndent が適用される段落全体の突出部が2行目となり、(A)LeftIndent の適用行と同じとなるからです。

* 非char系(LeftIndent・FirstLineIndent)
![doc1_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29598/0e46e59e-6bc6-74c7-1a6f-825667117174.png)

* char系(CharacterUnitLeftIndent・CharacterUnitFirstLineIndent)
![doc1_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29598/a92ea414-2dd4-932f-37c5-575924bf5ef5.png)

### ぶら下げの場合
ぶら下げの場合、char系と非char系の値が示すものは違ってきます。
(B)CharacterUnitLeftIndent が適用される段落全体の突出部は1行目となり、(A)LeftIndent が適用される2行目以下と異なることとなるからです。

* 非char系(LeftIndent・FirstLineIndent)
![doc2_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29598/395fdd8d-7e3e-8413-05cc-039a4d5b63df.png)


* char系(CharacterUnitLeftIndent・CharacterUnitFirstLineIndent)
![doc2_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29598/da566e76-273e-af6a-63eb-eb5034cf3ecb.png)

## 各プロパティの優先関係
非char系とchar系との間には、次のような関係があります。
1. char系の値が0ならば、非char系の値が実際のインデントに反映される。
1. char系に値が設定されれば、その前に非char系に0以外の値が設定されていても、char系の値が実際のインデントに反映される。
1. char系に値が設定されていると、非char系の値を変更することができない。

ですので、VBAで各プロパティを操作しようとするときには、次のことに気を付ける必要があります。

* char系のプロパティにインデント幅として0を設定しようとしても、これに対応する非char系のプロパティに値が設定されている場合、上記1.のルールが適用されてしまい、思わぬ結果となる。このため、char系のプロパティに0を設定する前に、対応する非char系のプロパティの値も0にしておく必要がある。
* 非char系に値を設定しようとする場合、その前に、これに対応するchar系のプロパティの値を0にしておく必要がある。