インストラクターのネタ帳でお馴染みの伊藤さんが先日下記の記事をアップされました。
・Word VBAのSelection.InsertBreakの書式
http://www.relief.jp/itnote/archives/word-vba-selection-insertbreak-method.php
SelectionオブジェクトのInsertBreakメソッドの引数(Type)の型がVariantになっているので自動メンバー表示されない、というものです。
伊藤さんも書いておられるように、SelectionオブジェクトのGoToメソッドといい、Wordマクロを書いていると「メンバー表示してくれれば良いのに!」と思うことがままあります。
ここで一つ気になるのが、“[Type As WdBreakType]のように型指定されていないのは一体いつからなんだろう?”ということです。
Word VBAのはじまり
Wordには元々マクロ機能が搭載されていましたが、当初は今ある「VBA」ではなく「WordBasic」が使われていました。
下図はWord 95でマクロを書いているところですが、今では当たり前のように使っているVisual Basic Editorすらありません。
構文は今のVBAと似ているものの、WordBasicは約900のコマンドがフラットなリストで構成されているのに対して、VBAのオブジェクトは階層構造を成しています。
それでは、一体いつからこのWordBasicからVBAに切り替わったのでしょうか?
― 答えは「Word 97」です。
WordBASIC was a subset of Microsoft QuickBASIC customized for word-processing. It was replaced by Visual Basic for Applications (VBA) when Word 97 was released.
WordBasic より
「Office 97試用レポート」にも詳しく当時の状況が書かれています。
今回のOfficeアプリケーションの中で、最も変更されたのがこのWordである。というのは、従来ワードは、マクロ言語としてWordBASICが使われていたが、今回ようやくVBA(Visual BASIC Application Edition)対応になったのである。Wordは、マイクロソフトのアプリケーションとして、始めてBASICによるマクロ機能が装備された のだが、それが仇となって、VBA対応が遅れていたのである。すでにWordBASICで書かれた膨大なマクロがユーザーの手元にあり、これとの互換性を保つ必要があったのだ。Excel 95では、2つのマクロを同時にサポートするという形で互換性を維持したが、Excelのマクロは、BASICともいえない奇妙なもの(なにせセルの中にマクロを入れていき、変数もマクロシート内のセルを使うというもの)だったので、どうしようもなかったからである。
ところがWordBASICは、QuickBASICの流れを汲むBASICでありながら、マクロ特有の「カーソル移動やメニュー選択を代行する」形式であり、自動変換による移行はかなり大変な作業だったと想像される。そのためか、Windows 95登場に合わせた32bit化が最優先であった前バージョンでは、VBAとの統合が見送られていた。
VBA対応でなかったということは、WordBASICの中でOLEオブジェクトの扱いがちゃんとできないとか、他のアプリケーションからの制御はWordBASICで行なわねばならないといった問題があったのである。
Word 97では、従来のマクロ(これはテンプレートに保存されている)は、読み込みと同時にVBAに変換される。そのままテンプレートをセーブすれば、マクロはすべてVBAに変換されてセーブされる。
今のWord VBAがWord 97から始まった、ということが分かったところで、実際にWord 97でInsertBreakメソッドがどうなっているのか確認してみましょう。
Word 97でのInsertBreakメソッド
InsertBreakメソッドは、WordBasicでも「InsertBreakステートメント」としてすでに存在していました。
これがWord 97になると、下図のような形になりました。
比較用にWord 2010の画面と並べてみましたが、まったく変わりがないです。
つまり、InsertBreakメソッドは最初から引数(Type)の型がVariantだったわけですね。
伊藤さんの記事にある「Selection.GoTo」や「Selection.GoToNext」も今と変わりがありません。
なぜ引数の型がVariantになっているのか?
上図の「Selection.GoTo」と「Selection.GoToNext」を見比べてみると、指定することが必須である引数は型指定されていて、必須ではないoptionalな引数はVariantになっているように思えます。
ただ、ExportAsFixedFormatメソッドの引数、OptimizeForなどを見ると、必須ではない引数であっても、下図のように型指定(WdExportOptimizeFor)されていることが分かります。
InsertBreakメソッドやGoToメソッドとExportAsFixedFormatメソッドでは何が違うのか?
大きく異なる点があるとすれば、メソッドが追加されたバージョンでしょう。
InsertBreakメソッドやGoToメソッドがWord 97から存在しているのに対し、ExportAsFixedFormatメソッドが追加されたのはWord 2007です。
つまり、比較的最近追加されたメソッドは引数が必須でなくても型指定されているのではないかと思います(もちろん、勝手な推測になりますが)。
というわけで、上記をまとめると、
- 昔から存在している。
- 引数が必須ではない。
この2点が、メソッドの引数がVariantになっている条件である、そんな感じがします。
この条件を踏まえた上で、WordBasic時代から存在し、Word 97でもそのまま受け継がれている「InsertCrossReference」メソッドを見てみると、下図のように必須な引数・ReferenceKindがWdReferenceKind型として指定されていることが確認できます。
(ReferenceTypeも必須な引数ですが、メソッドの説明文に“使用できる値は、WdReferenceType クラスまたは WdCaptionLabelID クラスの定数、あるいはユーザー定義の図表番号のラベルです。”とあるため、こちらはVariantにするしかないのでしょう。ReferenceItemも同様に複数の型の値が入る可能性があります。)
以上のように、“メソッドの引数がVariantになっている条件”は何となく見えてきたのですが、肝心の“なぜそうなっているか?”は分かりません・・・。
WordBasicユーザーがVBAに代わっても「InsertBreak 6」といった感じで書けるよう、後方互換のためにこのような仕様にしたのか、はたまた別の理由があるのか、このあたりはWord MVPの新田さんが海外のMVPに聞いてくださるとのことなので、その答えに期待したいと思います。
@kinuasa @kiyotoi なるほど。なんか微妙ですねぇ。貴重な情報ありがとうございます。一貫性がないのは、何か経緯があるかも。VBAやっている海外のMVPの方々に聞いてみます。
— 新田順也 (@nittajunya) 2015, 3月 2
・・・と、ここまで長々書いておきながら、結局最後は丸投げという、実に私らしいオチでした。
2015/05/21 追記:
本件について、Word MVPの新田さんが海外のMVPさんにまで問い合わせてくださいました。新田さん、ありがとうございます!
・【Wordマクロ】定数が自動メンバー表示される?されない?
http://ameblo.jp/gidgeerock/entry-12029293948.html
今回は自動メンバー表示の謎について、真相を究明するには至りませんでしたが、いずれは謎を解き明かしたいですね!!
この記事へのコメントはありません。