WORD VBAで湯婆婆

# はじめに
　湯婆婆とは、映画「千と千尋の神隠し」の登場人物です。それをヒントに実装したものが、@Nemesisさんの[Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2)の記事です。
　それ以降、主人公の萩野千尋と湯婆婆とが契約を交わすときのやりとりをプログラム言語やスクリプト等で実装するのが流行っています。
　[毎日自動更新】湯婆婆 LGTMランキング！](https://qiita.com/torifukukaiou/items/c8361231cdc56e493245)から、みなさまの湯婆婆コードを見ると、あらゆる環境にて湯婆婆を実装したくてたまらなくなりますので、Microsoft WORD環境にも湯婆婆を実装してみました。
　なお、この前には、[Autohotkeyでトースト湯婆婆](https://qiita.com/kenichiro_ayaki/items/efbf33fed123e106c2be)の記事を書いています。

# 湯婆婆とは
[湯婆婆](https://dic.pixiv.net/a/%E6%B9%AF%E5%A9%86%E5%A9%86)とは、以下のようなキャラクターです。

![thumb-chihiro016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266273/705e9b10-daec-bed1-8274-a6af7baef5c1.png)
（画像はジブリのフリー素材から引用しました。）
> 八百万の神々が集うと言われる湯屋「油屋」の経営主である強欲な魔女。
二頭身という人間離れした体格で、とにかく顔がでかい。風貌自体も額の大きなイボに大きな鼻、アイシャドウとバシバシの睫毛が特徴の大きな目、大きな口と中々強烈で、怒って詰め寄って来たときの顔はかなり恐い。双子の姉に銭婆がいるが、性格の違いからソリが合わず離れて暮らしている。

> 引越し先の新居へ向かう途中、偶然にも彼女の経営する油屋のある異世界に迷い込んでしまった荻野一家は、両親は神様の食事に手を出したことで豚に変えられ、二人の娘・荻野千尋は両親を救い出し元いた世界に戻るために湯婆婆の下で働くことになる。
>出典：ピクシブ百科事典より

　ところで、違う場所に迷い込んで、自分の称する名前とは別の名前で呼ばれてしまうというのは、「アルプスの少女ハイジ」のハイジのオマージュじゃないかなと、つらつら思いました。
　ハイジは、デーテ叔母さんに連れていかれたフランクフルトのゼーゼマン家で、執事のロッテンマイヤーに「あなたの名前はアーデルハイドです。」と呼ばれて怒り、「私はハイジよ、他に名前なんてないわ。」と叫ぶのです。

　なお、「ハイジ(Heidi)」とは、「アーデルハイド(Adelheid)」の愛称（略称）であり、「アーデルハイド(Adelheid)」が正式名です。ロッテンマイヤーさんはドイツ式に厳密に正式な名前を呼んでいたにすぎません。
　（ここまで書いて、ロッテンマイヤー女史をプログラム言語で実装するという考えが浮かんだ。何時になるかは不明。）

# VBAとは
　VBA（Visual Basic Application）とは、主にマイクロソフト製のMicrosoft Officeシリーズに搭載されているプログラミング言語です。Microsoft Office環境でアドインを作成する方法のひとつです。簡単にプログラミングできて、クラスライブラリなども作れます。但しVBAで書いたコードは、基本として隠蔽できません。そしてVBAはクセが強い言語なので、他言語に慣れている方は戸惑うことが多いとおもいます。
　Office環境では、他にはC#やVB.NETなどで記述できるVSTOや、HTML、CSS、および JavaScript などの一般的な Web テクノロジを使えるOfficeアドインがあります。また、Excelに限り、C++で記述できるXLLがあります。

# 湯婆婆リボン
　最初に作るべきは、湯婆婆リボンです。しかし、このプログラムは、パワーワード揃いですね。

![湯婆婆リボン1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266273/79069b47-69cd-c2bd-46a0-fe98036e87c2.png)

このリボンは、WORDのマクロ有効テンプレートに以下のXMLと、湯婆婆の64pixel四方の画像アイコン（.png)を付けることで実装できます。

　追記：デフォルトで有効なWORDのマクロ有効テンプレートは、以下です。なお、ユーザが、このNormal.dotm ファイルを削除しても、WORD が自動作成します。

　C:/ユーザー/(ログイン名)/AppData/Roaming/Microsoft/Template/Normal.dotm

　なお、一連のコーディングが終わったら、リネームしたのち、以下のフォルダに移動させててもよいです。ここではソースコードの編集はできません。

　C:/ユーザー/(ログイン名)/AppData/Roaming/Microsoft/Word/STARTUP

```xml:CustomUI.xml
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
	<ribbon startFromScratch="false">
		<tabs>
			<tab idMso="TabAddIns" label="yubaba">
				<group id="yubabaGroupJP" label="yubaba">
					<button id="yubaba" label="湯婆婆" image="yubaba64" size="large" onAction="Callback_yubaba" screentip="VBA湯婆婆" />
				</group>
			</tab>
		</tabs>
	</ribbon>
</customUI>
```
このXMLでは、WORDにyubabaタブを作り、その中にyubabaグループを作り、ボタンにyubaba64アイコンを表示させます。
![yubaba64.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266273/416703a4-8f7d-4093-9f5c-a33167180808.png)
この湯婆婆ボタンがクリックされたときには、Callback_yubaba が呼び出されます。
このボタンにマウスカーソルを載せると、ツールチップとして「VBA湯婆婆」を表示させます。

このXMLをワードのマクロ有効ファイルに設定ツールとしては、Custom UI Editor があります。
[Custom UI Editorの最新版がGitHubで公開されました。](https://www.ka-net.org/blog/?p=8945)を参考に、導入なさってください。
![CustomUIEditor.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266273/ee308548-868c-2099-09e8-299248dd6b06.png)

なお自分は、Office Ribbon Editor を使っていますが、サポート終了のようです。

# 動作

　湯婆婆「契約書だよ。そこ（乙）に名前を書きな。」をWORDのテキストとして表示し、契約書ダイアログを表示します。

![契約書.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266273/447e17c4-c57e-1be4-43be-09ae38772363.png)

　名前を入れると、湯婆婆が名前をダメ出ししたのち、１文字の名前を新たに付けます。

![契約完了2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266273/2df094cb-d9d1-6725-6c99-327565eb3140.png)

　名前を入力せずにOKボタンをクリックすると、VBA湯婆婆がクラッシュします。

![クラッシュ湯婆婆.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266273/14211e9e-585b-df62-cc96-4c45c8f5f9f7.png)

# ソースコードとその解説

## Callback_yubabaの解説
```vb:コールバック変数を受ける
Sub Callback_yubaba(control As IRibbonControl)
    Call VBAyubaba
End Sub
```
　XMLのコールバックを受けて、VBAyubabaサブルーチンを呼び出します。

## VBAyubabaサブルーチンの解説

```vb:VBAyubaba
Sub VBAyubaba()
    Selection.TypeParagraph
    Selection.TypeText Text:="湯婆婆「契約書だよ。そこ（乙）に名前を書きな。」"
    Selection.TypeParagraph
    
    ' 湯婆婆の契約書
    Load yubabaContract
    yubabaContract.Show 1
        
    ' 名前をダメ出し
    Selection.TypeText Text:="湯婆婆「フン、" & yourName & "というのかい。贅沢な名だねぇ。」"
    Selection.TypeParagraph
        
    ' 新しい名前を付ける
    Dim newName As String
    newName = Mid(yourName, Rnd() * (Len(yourName) - 1) + 1, 1)
    Selection.TypeText Text:="湯婆婆「今からお前の名前は" & newName & "だ。いいかい、" & newName & "だよ。分かったら返事をするんだ、" & newName & "！！」"
End Sub
```

　Selectionオブジェクトとは、ワード文書の現在の選択範囲のことをいいます。通常はカーソル位置です。
　Selection.TypeParagraph は、現在の選択位置にパラグラフを挿入するメソッドです。
　Selection.TypeText Text:= は、現在の選択位置にテキストを挿入するメソッドです。
　そして、別途作成したyubabaContract フォームを呼び出します。この呼び出しにより、大域変数の yourName に入力した文字が設定されます。

　新しい名前を付けるため、文字列長を算出するlen()関数と、乱数生成のRnd()関数と、文字列から指定位置の文字列を取り出すMid()関数を呼び出します。

## yubabaContract.Frm（契約書フォーム）の解説
```vb:yubabaContract.Frm
VERSION 5.00
Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} yubabaContract 
   Caption         =   "VBA湯婆婆"
   ClientHeight    =   1710
   ClientLeft      =   120
   ClientTop       =   465
   ClientWidth     =   4560
   OleObjectBlob   =   "yubabaContract.frx":0000
   StartUpPosition =   1  'オーナー フォームの中央
End
Attribute VB_Name = "yubabaContract"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit

Private Sub OKButton1_Click()
    yourName = TextBox1.Value
    Unload Me
End Sub

Private Sub UserForm_Initialize()

End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    yourName = TextBox1.Value
    Unload Me
End Sub
```
　契約書の文言はバイナリのリソースとして持っているようです。
　TextBox1は、乙の名前を入力するためのテキストボックスです。
　OKButton1_Clickサブルーチンは、OKボタンが押されたときの処理です。テキストボックスの値 TextBox1.Value を大域変数 yourNameに設定して、Unload Me で、このダイアログを閉じます。
　UserForm_QueryCloseサブルーチンは、ダイアログの閉じるボタンが押されたときの処理です。OKButton1_Clickと同様な処理を実行します。
　UserForm_Initializeサブルーチンは、コンストラクタ代わりに使えます。

　面白いのは、VBA においてフォーム（ダイアログ）は、ダイアログのリソースと、リソースが操作されたときのアクションを記述するクラスとが融合されていることです。
　なかなかよく設計されているとおもいます。

# まとめ
　以上のようにして、VBAでも湯婆婆を実装できました。本当は契約書を含めてワード画面上で完結させたかったのですが、乙の名前欄以外に入力されたときのエラー処理があまりにも面倒なので止めました。
　このように、標準入出力以外で湯婆婆を実装するのは、もしかしたら邪道なのかもしれません。しかし、標準入出力以外で湯婆婆をどのように実装するかを考えるのは、ユーザインタフェースに関するよい練習となるようにおもいます。