
Office Space へようこそ。Office Space は、Microsoft® Office アプリケーションのスクリプト作成に関するヒントとテクニックを紹介するコラムです。毎週火曜日と木曜日に新しいヒントを掲載します。過去のヒントについては、Office Space アーカイブを参照してください。Microsoft Office でのスクリプト作成について質問がある場合は、scripter@microsoft.com (英語のみ) までお送りください。すべての質問に回答することはできないかもしれませんが、可能な限り対応いたします。
ビデオ ゲームがお好きな方は、チート コードをすべて把握していることでしょう。チート コードを使用して、ゲーム機に秘密のメッセージを入力するかジョイスティックにある指定された一連のボタンを押すと、ほら。突然、無限の富、不死、つまり神のような力を得ることになります。ご推察のとおり、殺されることは負けることを意味するゲームの世界では、不死はとてもありがたいことです。それがおそらく、そうですね、フェア コードではなくチート コードと呼んでいる理由です。
お気付きでないかもしれませんが、Microsoft Word には独自のチート コードのセットが用意されています。Microsoft Word のチート コードでは、無限の富や神のような力は与えられませんが (少なくとも我々が知っているチート コードではありません)、ワード プロセッシング生活をずっと楽にすることができます。たとえば、すべて小文字で入力した語句があり、本当はすべて大文字にしたいと思っているとします。問題はありません。テキストを選択し、Ctrl+Shift+A キーを押します。ほらね。すべて大文字になりました。別の語句を非表示テキストとして書式設定したいですか。語句を強調表示し、Ctrl+Shift+H キーを押します。数え上げればきりがありません。まだまだあります。
これらは非常にかっこい方法ですが、問題があります。十中八九、Microsoft Word のキーボード ショートカットをすべては記憶していません (そのようなショートカットが何百もあるという事実を考慮すれば当然のことです)。それで一体どうやって Microsoft Word コマンドとそれに対応するチート コードのリストを手に入れることができますか。
そのとおりです。これらのショートカットの多くは、Word のヘルプ ファイルにあります。そうです。それらの多くは、おそらくインターネットでも見つけることができます。しかし、Word のキーボード ショートカットのリストを取得するには面白くない方法です。同じ情報を取得するための、もっとかっこいい方法があります。
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.ListCommands(True)
そうです。スクリプトです。たった 3 行のスクリプトで起動します。まず Word.Application オブジェクトのインスタンスを作成し、Visible プロパティを True に設定します。これによって Word が開始され、画面上に表示されます。続いて ListCommands メソッドを呼び出し、True パラメータを渡します。True パラメータでは、ListCommands に Word コマンド (組み込みコマンドとカスタマイズしたコマンドの両方) をすべて返すように指示します。ListCommands に False を渡すと、カスタマイズしたコマンドのみのコレクションが返されます。
この 3 行のスクリプトを実行すると、Word 文書は自動的に次のようになります。

このグラフィックを拡大表示するには、ここをクリックしてください。
非常にかっこいいですね。最初の列 (コマンド名) には、Word コマンドが表示されます。列 2 (補助キー) と列 3 (キー) では、そのコマンドのキーボード ショートカット (ある場合) が表示されます。表を詳しく見ると、Activate Object コマンドにはキーボード ショートカットがありませんが、All Caps コマンドにはキーボード ショートカット (Ctrl+Shift+A キー) があることがわかります。
Activate Object |
|
| |
All Caps | Ctrl+Shift+ | A |
リストはここから続き、100 をはるかに越える Microsoft Word 2003 のコマンドを記録します。3 行のスクリプトにしては悪くないと思いませんか。
ところで、我々が面倒だと思っていたらどうですか。大丈夫です。我々が "もっと面倒" だと思っていたらコラムをちょうどここで終わらせることができますし、皆さんにはツールキットに追加する気の利いたささやかなスクリプトが残ります。そうは言っても、Word コマンドのおよそ 4 分の 3 にキーボード ショートカットがないことも否定できません。それにもかかわらず、表では Activate Object などショートカットのないすべてのコマンドがショートカットのあるコマンドと混合してます。それでも大丈夫です。しかし、いわゆるチート コードにしか興味がない場合、大量の関係のない情報を取り除く必要があります。それで次のように考え始めました。スクリプトを修正して、キーボード ショートカットのないコマンドをすべて削除する方法はないだろうか。
そうです。我々はその答えを既に知っています。もちろん、その方法はあります。我々が知る限り、ショートカットのあるコマンドだけを一覧表示する方法はありません。したがって、次善の策を取りました。以前にやったように、コマンドをすべて一覧表示します。続いて、表を 1 行ずつ調べて、コマンドにキーボード ショートカットがあるかどうかをチェックします。キーボード ショートカットがある場合はそのままにしておき、ない場合はその行を削除します。終了すると、コマンドの新規リストは次のようになります。

このグラフィックを拡大表示するには、ここをクリックします。
ずいぶんかっこよくなりましたね。とりわけ修正されたスクリプトは、一見したところやや不可解ですが、それほど多くのコード行を必要としません。
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.ListCommands(True)
Set objDoc = objWord.Documents(1)
Set objTable = objDoc.Tables(1)
For i = 1 to objTable.Rows.Count
strText = objTable.Cell(i,2).Range.Text
strText = strText & objTable.Cell(i,3).Range.Text
intLength = Len(strText)
If intLength <= 4 Then
objTable.Rows(i).Delete
i = i - 1
End If
Next
そうですね。おそらく "やや" というよりは "少し" 不可解ですね。コードにざっと目をとおし、何を実行しているか説明していきましょう。この修正スクリプトの最初の 3 行は、元のスクリプトと同じです。Word のインスタンスを作成し、ListCommands メソッドを呼び出して Microsoft Word コマンドすべての表を自動作成します。続いて、次の 2 行のコードを使用して一組のオブジェクトへの参照を作成します。1 つは現在の文書への参照 (objDoc)、もう 1 つはその文書の最初の表への参照 (objTable) です。
Set objDoc = objWord.Documents(1) Set objTable = objDoc.Tables(1)
文書には 1 つの表しかないため、objTable は現在、Word コマンドがすべて含まれる表を指しています。ここまでは順調です。
そこから、1 から表の行数だけ実行する For Next ループを設定します (たとえば、表に 4,362 行ある場合、ループは 4,362 回実行されます)。次のコード行で、この処理を行っています。
For i = 1 to objTable.Rows.Count
For Next ループでは何を実行しますか。まず、表のセル "i, 2" の Text プロパティの値と等しい変数 strText を設定します。つまり、strText には、セル "i, 2" に入力されている値が含まれます。首をかしげている方のために説明しますと、セルは行番号、列番号の順に参照され、i はループ変数です。したがってループを最初に実行すると、"i, 2" は行 1、列 2 を参照し、2 回目のループでは "i, 2" は行 2、列 2 を参照し、以降順に繰り返されます。
次に、strText に strText の現在の値とセル "i, 3" に入力されている値を割り当てます。列 2 と同様、列 3 に注目するのはなぜでしょうか。キーボード ショートカットの大部分は、補助キーとキーから構成されています。たとえば、Ctrl+Shift と A などです。ただし、いくつかのショートカットはキーのみで構成されてます (たとえば、ヘルプ用の F1 キー)。つまり、列 2 だけをチェックすることはできません。値がない場合は、ショートカット キーがないと仮定しますがそうとも限りません。代わりに、列 2 の値と列 3 の値を "結合" する必要があります。
文字列をつなぎ合わせた後、Len 関数を使用して文字列の文字数をカウントします。この数は、変数 intLength に格納されます。これはスクリプトの厄介な部分です。Activate Object コマンドを確認すると、補助キーとキーの両方のセルが空白であることがわかります。そのため、どちらのセルにもテキストがなく長さ (文字数) はゼロであると推測するかもしれません。しかし大変興味深いことに、そんなことはありません。そうではなく、空白セルには実際、復帰と改行 (キーボードで Enter キーを押すのと同等) が含まれており、したがって 2 つの空のセルには合計 4 つの文字 (セルごとに 1 つの復帰と改行) が含まれています。これが、このコード行を使用して文字列長に 4 つ以下の文字が含まれているかどうかを確認する理由です。
If intLength <= 4 Then
文字列に 4 つ以下の文字が含まれている場合は、補助キーとキー列の両方が空白であると推測します。そうでない場合は、文字列に 5 文字以上の文字 (2 つの復帰、2 つの改行、および少なくとも 1 つの他の文字) が含まれている必要あります。4 つ以下の文字がある場合は、次の 2 行のコードを実行します。
objTable.Rows(i).Delete i = i - 1
最初の行で表の現在の行を削除します。2 行目で、i の値を i - 1 にリセットします。なぜでしょうか。表の 3 行目にいるとします。行を削除します。すると、表の次の行は行 4 になりますか。いいえ。実際は行 3 です。これは、前の行 3 を削除したとき、表のすべての行が 1 つ上に移動したためです。行 4 として使用されていた行は、現在、行 3 になっています。i の値を調整することによって、行をスキップしないようにします。
少し混乱しますね。すみません。スクリプトを数回実行すれば、おそらくどのように動作するかわかるでしょう。ちなみに、スクリプトを実際に実行すると、終わるまで 15 分以上かかる場合がありますので、あらかじめご了承ください。これは、このように非常に大きな表の読み込みには非常に時間がかかるためです。スクリプトの完了にはしばらく時間がかかりますが、この場合古いことわざに真実があります。果報は寝て待て。