rubyによるMS-Word操縦 〜 マクロの取扱い

最終更新日: 2015/01/11

 MS-Wordのマクロの取扱いについて記します。

 マクロについての組み込み・取り出し、削除、一覧情報の取得、実行などを扱います。

    

 以降で掲げるサンプルスクリプトを実行した環境は次のとおり。

 サンプルのスクリプトは、いずれもrubyスクリプトです。 macro_wrd.zipに含まれています。

 MS-Wordを自動操縦するためのruby用ライブラリ wrdap.rb は、 wrdap104.zip に含まれています。


《目次》


<はじめに>

 MS-Wordでマクロを扱う場合の仕組みとして、まずプロジェクト(VBProject)というのがあり、その中に複数のコンポーネント(VBComponent)が含まれています。そして、コンポーネントの本体(ソースコード)を見ると、「Sub Macro1 …… End Sub」などのマクロ(プロシージャ)が書かれています。一つのコンポーネントに複数のプロシージャが書かれていることもしばしばです。

 コンポーネントには、標準モジュールとかクラスモジュールなどの種類(Type)と、「Module1」とか「Class1」などの名前(Name)の属性があります。これら属性の値は、component.Type(数値)、component.Name(文字列)で知ることができます。

 wrdap.rb(v1.04)のメソッドが対象とするのは、コンポーネントのタイプ 1:標準モジュール、2:クラスモジュール、3:ユーザーフォームの3種類です。他にタイプ 100 の ThisDocument などがありますが、それらは対象にしません。以下の解説でも、タイプ1〜3を取り上げます。

目次に戻る


1. マクロを利用するための準備

 rubyスクリプトでマクロの組み込みや取り出しを行う場合、MS-Wordのマクロのセキュリティを調整する必要があります。

 MS-WordをGUI操作して、次の設定変更を行います。具体的な操作方法は、MS-Wordのバージョンによって違うのでここでは言及しません。他のサイトなどを参考にして下さい。

    

a. 「Visual Basic プロジェクトへのアクセスを信頼する」をonにする。

 この調整は、rubyスクリプトでマクロを扱う場合、必須です。

    

b. マクロのセキュリティレベルの調整

 rubyスクリプトでMS-Wordを操縦するだけなら、マクロのセキュリティレベルを気にする必要はないと思います。

 ただ、rubyスクリプトでワード文書にマクロを組み込んで、後でその文書を開いてGUI操作中にマクロを実行しようとする場合は、マクロのセキュリティレベルをゆるめる必要があります。

 ワードのメニューの「マクロのセキュリティ」において、「すべてのマクロを有効にする」にします。

目次に戻る


2. 文字列を媒介とするマクロの組み込みと取り出し

(1) マクロの組み込み(macro_add)

 rubyスクリプトで、変数 str にマクロのソースコードが記録されているとします。つまり “Sub Macro1 …… End Sub” が str にセットされているものとします。

 このとき、docが1つのワード文書を指しているとすれば、

doc.macro_add(str)

と記述することで、マクロを組み込むことができます。標準モジュールの「Module1」という名前のコンポーネントとして組み込まれます。「Module1」が既に存在するのであれば「Module2」になります。

 ワード文書の先頭に「はじめに」という1行を挿入するマクロの組み込み例を示します。

 組み込むだけでは何なので、それを実行してからワード文書を保存して終了することにします。保存されたワード文書の先頭には「はじめに」が書き込まれているはずです。

 マクロの実行は、「doc.macro_run(“Macro1”)」で行います。

    

−−−− wmcr01.rb ここから
# encoding: Windows-31J
require "wrdap"
str = DATA.read  # マクロソースコードをstrに代入
filename = "wmcr01.doc"
File.unlink(filename)  if test(?e, filename)
Wrdap.new(filename) do |doc|
  component = doc.macro_add(str)  # マクロの組込み
  puts "#{component.Name}にマクロを組み込みました."
  doc.macro_run("Macro1")  # マクロの実行
  doc.save  # 文書の保存
end

__END__
Sub Macro1
    Dim rng As Range
    Set rng = ActiveDocument.Range(0,0)
    With rng
        .InsertParagraph
        .InsertBefore "はじめに"
    End With
End Sub
−−−− wmcr01.rb ここまで

    

 「str = DATA.read」は、スクリプトの最後の方にある「__END__」よりも後ろを読み込んで、それを文字列 str に代入するものです。マクロのソースコードの代入です。

 変数 str への代入は、もちろん「str = “Sub Macro1 ……”」のようにしてもいいわけですが、後で長めのVBAプログラムも出てくるので、rubyスクリプトと交じってごちゃごちゃしないよう、VBAプログラムを最後の方に置くようにしました。

    

 「doc.macro_add(str)」とした場合、コンポーネント(今回は標準モジュール)の名前をどうするかは、MS-Wordにお任せになります。

 どんな名前が割り当てられたかを知りたい場合は、

component = doc.macro_add(str)

として、component.Name の値を確認します。component.Type の方は、数値が代入されているはずです。1なら標準モジュール、2であればクラスモジュールなどです。

 コンポーネントの名前を指定したい時は、

doc.macro_add(str, 1, "Module5")

のようにします。第2引数がタイプ、第3引数が名前です。

    

 マクロがテキストファイルに書かれている場合は、

doc.macro_add("macro.txt")

のようにして、引数にファイル名を与えることができます。

 第1引数の文字列が、キャリッジリターン(CR)も改行(LF)も含んでおらず、かつ、それがファイル名として有効な場合(実際に該当のファイルが存在する場合)、その文字列をファイル名とみなして、その中身をマクロとして組み込みます。

    

 macro_run(“Macro1”) は、Macro1を実行します。

 もしMacro1が引数を受け取るタイプのものであれば、「macro_run(“Macro1”, arg1, arg2)」のようにします。

 macro_runにはrunという別名が割り当てられているので、doc.run(“Macro1”) のように書くこともできます。


(2) マクロのソースコードの取り出し(macro_code)

 ワード文書に組み込まれているマクロのソースコードを取り出して、文字列に代入するには、

str = doc.macro_code()

のようにします。この場合、引数を省略しているので、タイプ1〜3の全コンポーネントのソースコードを取得します。

str = doc.macro_code(1, "Module1")

とすれば、標準モジュールで「Module1」というコンポーネントのソースコードを取り出します。

str = doc.macro_code(1)

のように、タイプのみ指定して、名前を省略すると、タイプ1(標準モジュール)である全コンポーネントのソースコードを取り出します。

    

 取り出したソースコード(文字列)には、要所要所に

' <<type:Standard,  name:Module1>>

のようなコメント行が挿入されています。これは、コンポーネントのタイプと名前をコメントとして挿入したものです。オリジナルのソースコードにはありません。

    

 サンプルの wmcr02.rb は、二つのマクロを組み込んで、後の方でそれを文字列として取り出し、ファイル wmcr02.txt に書き出しています。

 一つ目のマクロMacro1は、文書の先頭に「昨日は朝から雨が降っていた。」という1行を挿入します。

 2つ目のMacro2は、「雨」を太字にするものです。

 前掲の wmcr01.rb と共通するところが多いですが、参考まで下に掲げます。

    

−−−− wmcr02.rb ここから
# encoding: Windows-31J
require "wrdap"
str = DATA.read  # マクロソースコードをstrに代入
filename = "wmcr02.doc"
File.unlink(filename)  if test(?e, filename)
Wrdap.new(filename) do |doc|
  doc.macro_add(str)  # マクロの組込み
  doc.macro_run("Macro1")
  doc.macro_run("Macro2")
  code_str = doc.macro_code()  # マクロのソースコードを取得
  File.open("wmcr02.txt", "w") {|ff|  ff.print code_str}
  doc.save
end

__END__
Sub Macro1
    Dim rng As Range
    Set rng = ActiveDocument.Range(0,0)
    With rng
        .InsertParagraph
        .InsertBefore "昨日は朝から雨が降っていた。"
    End With
End Sub

Sub Macro2
  Dim rng As Range
  Set rng = ActiveDocument.Content
  rng.Find.Execute FindText:="雨", Forward:=True
  If rng.Find.Found = True Then rng.Bold = True
End Sub
−−−− wmcr02.rb ここまで

    

 Macro2において、最初、変数rngには文書全体を指し示すRangeをセットするわけですが、rng.Find.Executeで「雨」を栓索すると(そして、みつかると)、rngは、「雨」だけを指し示すRangeに変更されるようです。

 そのため、「rng.Bold = True」とすれば、「雨」だけが太字になります。

目次に戻る


3. 組み込まれているコンポーネントの情報を取得する

 この項では、コンポーネントのタイプ、名前、ソースコード、そのソースコードに書かれているプロシージャ名の一覧を取得する方法を取り上げます。プロシージャ名は、これまでのサンプルでいうと Macro1, Macro2 といった名前のことです。

 情報取得の前に、標準モジュールしか組み込まれていないのはつまらないので、クラスモジュールも組み込むことにします。そのやり方から始めます。

    

(1) クラスモジュールの組み込み

 サンプルの wmcr03.rb では、JamDocというクラスを設定しています。ごく簡単なクラスで、メンバー変数を持たず、二つのメソッドがあるだけです。わざわざクラスにしなくても、そのまま標準モジュールにして差し支えない内容ですが、あえてクラスにしてみます。

 このクラスの目的は、ワード文書にテキストファイルもしくは別のワード文書を取り込むというものです。

 メソッド MergeText(fname) がテキストファイルの取り込み、MergeDoc(fname) は別のワード文書の取り込みに用います。

    

 rubyでクラスを設定する時は、「class JamDoc …… end」のように書きますが、VBAでクラスを設ける場合は、ソースコード中に「JamDoc」というクラス名を書く必要がありません。

 「doc.macro_add(str, 2, “JamDoc”)」のようにして、コンポーネントを組み込む際に、クラスモジュールの名前「JamDoc」を指定します。すると、これがクラスの名前になります。

    

 wmcr03.rb では、クラス JamDoc をテストするためのマクロ Macro1(fname) を標準モジュールとして組み込んでいます。

 この Macro1 を実行する際、引数として “test.txt” のように拡張子が「.txt」のファイル名を引きわたすと、テキストファイルが取り込まれます。それ以外の拡張子の場合は、ワード文書として取り込まれます。いずれも文書末尾に追加挿入されます。

 テキストファイルは単純な挿入の形で取り込まれますが、ワード文書は、セクション区切りを挿入した上で、ページも改める形で取り込まれます。

 この項の本旨はコンポーネントの情報を取得することですが、とりあえずそれは横に置いておいて、wmcr03.rb では、クラスモジュールと標準モジュールの組み込み、およびその実行を行っています。

 ここで作成されるワード文書 wmcr03.doc は、以降の wmcr04.rb〜wmcr06.rb で使うので、消去せずに残しておいて下さい。

 以下、wmcr03.rb を掲げます。

    

−−−− wmcr03.rb ここから
# encoding: Windows-31J
require "wrdap"
txt_file = Wrd::fullpath( "insert01.txt" )  # 取り込むテキストファイル
doc_file = Wrd::fullpath( "insert02.doc" )  # 取り込むワード文書
filename = "wmcr03.doc"  # これから作るワード文書
cls_str, mdl_str = DATA.read.split(/\n########*\n+/)  # マクロ定義の読込み
File.unlink(filename)  if test(?e, filename)
Wrdap.new(filename) do |doc|
  doc.macro_add(cls_str, 2, "JamDoc")  # クラスモジュールの組み込み
  doc.macro_add(mdl_str)  # 標準モジュールの組み込み
  doc.macro_run("Macro1", txt_file)  # マクロ実行(テキストファイルの取込み)
  doc.macro_run("Macro1", doc_file)  # マクロ実行(ワード文書の取込み)
  doc.save  # 文書の保存
end

__END__
' JamDocというクラスの定義。2つのメソッドを持つ。
Sub MergeText(fname As String)  'テキストファイルの取込み
  Dim rng As Range
  Set rng = ActiveDocument.Content  '文書全体を代入
  rng.Collapse Direction:=wdCollapseEnd  '範囲解除&範囲末尾に移動
  rng.InsertFile FileName:=fname, _
      Range:="", ConfirmConversions:=False, _
      Link:=False, Attachment:=False
  Set rng = Nothing
End Sub

Sub MergeDoc(fname As String)  'ワード文書の取込み
  Dim rng As Range
  Set rng = ActiveDocument.Content  '文書全体を代入
  rng.Collapse Direction:=wdCollapseEnd  '範囲解除&範囲末尾に移動
  With rng
    .InsertBreak wdSectionBreakNextPage  '次のページ上にセクション区切りを挿入
    .InsertFile fname
    .Collapse Direction:=wdCollapseEnd  '範囲解除&範囲末尾に移動
  End With
  Set rng = Nothing
End Sub

########
' JamDocクラスを利用するためのマクロ
Sub Macro1(fname As String)
    Dim jam As JamDoc
    Set jam = New JamDoc
  If LCase(fname) Like "*.txt" Then
      jam.MergeText(fname)
  Else
      jam.MergeDoc(fname)
  End If
End Sub
−−−− wmcr03.rb ここまで

    

 VBAノソースコードは、「########」という行で区切られています。それより前がクラスモジュール、それより後が標準モジュールです。

 rubyスクリプトの先頭に近いところで

  cls_str, mdl_str = DATA.read.split(/\n########*\n+/)

としているのは、「########」を区切りとして、cls_strにクラスモジュールのソースコードを、mdl_strに標準モジュールのソースコードを代入するものです。


(2) コンポーネントに関する情報の取得(macro_list, macro_name)

 コンポーネントのソースコードを macro_code() で得られることは先述したとおりです。

 その他、ワード文書に組み込まれているコンポーネントのタイプと名前の組みを得る macro_list() があります。このメソッドに対する引数(type, name)の与え方は、macro_code() と同様です。

 戻り値は [[type1, name1], [type2, name2], ……] のような配列です。

 全コンポーネントの一覧を出力するには次のようにします。

    

  mlist = doc.macro_list()
  mlist.each do |type, name|
      printf("type:%d  name:%s\n", type, name)
  end

    

 なお、macro_list2() を用いると、該当のコンポーネントオブジェクトを配列に入れて返します。使い方は macro_list() と同じです。

    

 次に、プロシージャ名の取得ですが、これは macro_name() で行います。

 引数を与えなければ、タイプ1〜3の全コンポーネントのプロシージャ名を取得します。

 「doc.macro_name(1, “Module1”)」のようにすると、標準モジュール「Module1」に含まれるプロシージャの名前群を取得します。

 戻り値が少々ややこしいですが、ハッシュの形で返されます。ハッシュの key は、コンポーネントを指す [type, name] 形式の配列です。具体的には「[1, “Module1”]」などです。これが key です。

 ハッシュの value の方は、プロシージャ名を要素とする配列で、例えば「[“Macro1”, “Macro2”]」のような形になります。

 プロシージャ名の一覧を出力するには、例えば次のようにします。

    

  hs = doc.macro_name()
  hs.each do |key, proc_names|
      type, name = key
      printf("%d %s: ", type, name)
      puts proc_names.join(", ")
  end

    

 サンプル wmcr04.rb は、上の macro_list, macro_name を wmcr03.doc に対して適用しています。

 また、各コンポーネントのソースコードは、macro_code() で取得して、それをテキストファイルに書き出しています。

 以下、wmcr04.rb を掲げます。

    

−−−− wmcr04.rb ここから
# encoding: Windows-31J
require "wrdap"
filename = "wmcr03.doc"
Wrdap.new(filename) do |doc|
      # コンポーネントの type, name を出力
  puts "コンポーネント一覧"
  mlist = doc.macro_list()
  mlist.each do |type, name|
    printf("type:%d  name:%s\n", type, name)
  end
  printf("\n")
      # プロシージャ名一覧の出力
  puts "プロシージャ名一覧"
  hs = doc.macro_name
  hs.each do |key, proc_names|
    type, name = key
    printf("%d %s: ", type, name)
    puts proc_names.join(", ")
  end
      # ソースコードをファイルに出力
  mlist.each do |type, name|
    str = doc.macro_code(type, name)
    fname = "#{name}_code.txt"
    File.open(fname, "w") {|ff|  ff.write str}
  end
end
−−−− wmcr04.rb ここまで

(3) 別のワード文書へのマクロのコピーおよびマクロの削除(macro_remove)

 各コンポーネントの情報を取得できるようになったので、それらを別のワード文書にコピーしてみます。

 マクロを別のワード文書にコピーすることについては、後述の macro_export, macro_import を使う方が確実です。これらはファイルを経由してコピーする方法です。

 一方、ここで紹介するのは、ファイルを介さずにコピーする方法です。wmcr05.rbがそのサンプルです。

 二つのワード文書 wmcr03.doc と wmcr05.doc を同時に開いて、前者のコンポーネント情報を取得し、それに基づいて後者にマクロを組み込みます。

 macro_remove(マクロの削除)を別にすれば、これまで紹介したメソッドだけで行っていますので、説明を付け加える必要はないと思います。

 以下、wmcr05.rbを掲げます。

 このスクリプトを実行する時は、wmcr03.doc, insert01.txt, insert02.doc の3つのファイルがカレントディレクトリにないとエラーになるので注意して下さい。

    

−−−− wmcr05.rb ここから
# encoding: Windows-31J
require "wrdap"
txt_file = Wrd::fullpath( "insert01.txt" )  # 取り込むテキストファイル
doc_file = Wrd::fullpath( "insert02.doc" )  # 取り込むワード文書
File.unlink("wmcr05.doc")  if test(?e, "wmcr05.doc")
wrd = Wrdap.new  # ワードの起動
wrd.opens_once("wmcr03.doc", "wmcr05.doc") do |doc1, doc2|
  doc2.macro_remove  # 念のためdoc2(wmcr05.doc)のマクロを削除
  mlist = doc1.macro_list
  mlist.each do |type, name|
    str = doc1.macro_code(type, name)
    doc2.macro_add(str, type, name)
  end
  doc2.macro_run("Macro1", txt_file)  # テキストファイル取込み
  doc2.macro_run("Macro1", doc_file)  # 別のワード文書取込み
  doc2.save  # wmcr05.docの保存
end
wrd.quit  # ワードの終了
−−−− wmcr05.rb ここまで

    

 「doc2.macro_remove」は、doc2(wmcr05.doc)に組み込まれているタイプ1〜3の全コンポーネントを削除します。doc2にマクロが何も組み込まれていなければ、結果として何も行われません。

 「doc.macro_remove(1, “Module1”)」のように引数を指定すれば、標準モジュールの「Module1」だけを削除します。

 「doc.macro_remove(1)」のようにタイプだけ指定すれば、該当のタイプ1(標準モジュール)を総て削除します。

 「doc.macro_remove(nil, “Module5”)」とすれば、タイプを問わず、「Module5」という名前のコンポーネントを削除します。

    

[補足]

 wmcr05.rb で採用したマクロコピーの方法は、要するにマクロのソースコードをコピーしているだけです。ソースコード以外の情報も必要になるケースでは適切なコピーが行われないことになります。

 例えば、コンポーネントのタイプ3(ユーザーフォーム)には、多くの場合、ソースコード以外にも付随情報があります。なので、wmcr05.rbのやり方でコピーすることはできません。

 標準モジュールとクラスモジュールについては概ね大丈夫だと思いますが、確実にコピーするなら、次項の macro_export, macro_import を用いるのがいいと思います。

目次に戻る


4. ファイルを媒介とするマクロの書き出しと読み込み

 ここでは、マクロをファイルとして書き出す方法と、そのファイルを読み込んでマクロを組み込む方法について記します。

 ここでいうファイルは、単にマクロのソースコードが書かれているものではなく、コンポーネントの各種Attributeが一緒に記録されているファイルです。

    

(1) マクロの書き出し(macro_export)

 「doc.macro_export()」とすれば、タイプ1〜3のコンポーネント総てをファイルとして書き出します。

 そのとき、標準モジュールの拡張子は “.bas”、クラスモジュールは “.cls”、ユーザーフォームは “.frm” になります。

 ファイル名本体(拡張子を除く)は、コンポーネントの名前がそのまま用いられます。つまり「Module1」とか「Class1」などになります。ファイル名は、「Module1.bas」 「Class1.cls」のようになります。

 ファイルが書き出されるフォルダは、ワード文書が存在するのと同じフォルダです。

 「doc.macro_export(1, “Module1”)」とすれば、「Module1.bas」だけが書き出されます。

 macro_export() の戻り値は、出力成功コンポーネントのタイプと名前の組みが複数含まれる配列 [[type1, name1], [type2, name2]] などになります。

 何も出力しなかった時は、空配列 [] を返します。

 rubyスクリプト中で、漏れなくexportが行われたかどうかをチェックするには、例えば次のような方法があります。

  full_list = doc.macro_list
  export_list = doc.macro_export
  ary = full_list - export_list

 上のようにして、ary が空配列 [] でない時は、exportに失敗したコンポーネントがあることになります。

    

 ワード文書 wmcr03.doc の全コンポーネントを書き出すrubyスクリプト wmcr06a.rb を下に掲げます。ごく簡単なものです。

 これを実行すると、Module1.bas, JamDoc.cls の二つのファイルが書き出されます。

    

−−−− wmcr06a.rb ここから
# encoding: Windows-31J
require "wrdap"
Wrdap.new("wmcr03.doc") do |doc|
  doc.macro_export
end
−−−− wmcr06a.rb ここまで

    

[補足]

 macro_export()の第3引数に true を与えると、書き出しファイル名にワード文書名を付加します。「test.doc!Module1.bas」のようなファイル名に書き出します。

 すべてのコンポーネントをワード文書名つきで書き出すには

  doc.macro_export(nil, nil, true)

とします。


(2) マクロの読み込み(macro_import)

 「doc.macro_import(“Module1.bas”)」とすれば、ファイル「Module1.bas」を読み込みます。

 「doc.macro_import(“Module1.bas”, true)」のように、第2引数として true または false を指定できます。これは、ワード文書内に既に同名のコンポーネントがあるかどうかをチェックするかしないかのフラグです。いわば重複チェックの有無です。

 第2引数が true だと、重複チェックを行います。指定したファイルが「Module1.bas」のとき、拡張子を除いた「Module1」という名前のコンポーネントがワード文書中に既に存在するかを確認し、存在する場合は読込みを行いません。

 false であれば、重複チェックは行わず、ファイルを読み込みます。その場合のコンポーネントの名前は、MS-Wordが自動的に調整することになります。

 第2引数のデフォルト値は false です。

 先述の macro_export で書き出したファイルを、別のワード文書において macro_import で読み込めば、そのワード文書に同じマクロを組み込むことができます。

 macro_import() の戻り値は、読み込みによって生成されたコンポーネントのタイプと名前 [type, name] となります。

 読み込みが行われなかった時は nil を返します。

    

 先の wmcr06a.rb で書き出された Module1.bas, JamDoc.cls を読み込むサンプル wmcr06b.rb を下に掲げます。ワード文書 wmcr06.doc に読み込みます。

 マクロがちゃんと組み込まれているのを確認する意味で、Macro1を実行しています。そのため insert01.txt, insert02.doc も必要になるので注意して下さい。

    

−−−− wmcr06b.rb ここから
# encoding: Windows-31J
require "wrdap"
txt_file = Wrd::fullpath( "insert01.txt" )  # 取り込むテキストファイル
doc_file = Wrd::fullpath( "insert02.doc" )  # 取り込むワード文書
File.unlink("wmcr06.doc")  if test(?e, "wmcr06.doc")
Wrdap.new("wmcr06.doc") do |doc|
  doc.macro_remove  # 念のためマクロを削除
  Dir.glob("*.bas\0*.cls\0*.frm") do |filename|
    doc.macro_import(filename)
  end
      # 読み込んだマクロを試しに実行してみる
  doc.macro_run("Macro1", txt_file)
  doc.macro_run("Macro1", doc_file)
  doc.save
end
−−−− wmcr06b.rb ここまで

    

 「Dir.glob(“.bas\0.cls\0*.frm”) ……」は、3種類のワイルドカード指定 *.bas, *.cls, *.frm に該当するファイルの名前を検出するものです。”\0” は、3つのワイルドカードを区切るための区切り文字です。

 「.frm」に該当するファイルはみつからないと思いますが、「.bas」と「*.cls」は一つづつ検出されるはずです。その検出されたファイルを macro_import() で読み込んでいます。

 正しく読み込みが行われていれば、wmcr06.doc でも Macro1() を実行できるはずなので、macro_run() でそれを実行しています。

    

 以上、wrdap.rbで用意した「マクロを取り扱うためのメソッド」についての説明は一通り終了です。

目次に戻る


5. 標準テンプレートの取扱い

 これまで取り上げた macro_code(), macro_add() などのメソッドは、作業中のワード文書(ActiveDocument)に帰属するものでした。それらメソッドを使ってマクロを登録すると、作業中のワード文書にそれが組み込まれます。

 一方、ワードを起動した場合、暗黙のうちに取り扱われる標準テンプレートの Normal.dot というファイルがあります。Word2007以降では Normal.dotm です。ActiveDocumentとは別に、こちらにマクロを組み込むこともできます。

 以下では、標準テンプレートにマクロを組み込んだり、標準テンプレートに登録されているマクロの情報を取り出す方法について述べます。といっても、これまで言及してきた macro_code(), macro_add() などをほぼそのまま用いるだけです。

    

(1) 標準テンプレートに関する情報の確認

 標準テンプレートは、VBA風に書くと Application.NormalTemplate で参照できます。

 そのファイル名は Application.NormalTemplate.Name で知ることができます。ファイル名のフルパスを知りたければ Application.NormalTemplate.FullName を見ます。

 rubyでそれらを確認するためのスクリプトを下に掲げます。

    

−−−− wmcr07.rb ここから
# encoding: Windows-31J
require "wrdap"
filename = "dummy.doc"
Wrdap.new(filename) do |doc|
  puts doc.Application.NormalTemplate.Name
  puts doc.Application.NormalTemplate.FullName
  puts doc.app.ntpl.Name
  puts doc.app.ntpl.FullName
end
−−−− wmcr07.rb ここまで

    

 上では puts の書かれた行が4行出てきます。最初の2行と、その後の2行は、見た目は違いますが実質的に同じものです。最初の2行がVBAに即した記述、後半の2行はwrdap独自の記述です。

 後半に出てくる doc.app は、「wrd = Wrdap.new」とした場合のwrdに該当します。このオブジェクトには ntpl というメソッドがあり、NormalTemplateを指し示しています。

    

 上のスクリプトで、わざわざ dummy.doc をオープンしています。このワード文書に何か処理を加えているわけではないので、「開かなくてもいいのではないか?」と思われるかもしれません。

 しかし、実際に試してみると、ワード文書を何も開かない状態で標準テンプレートを取り扱おうとしても、うまくいきません。何か1つくらいは文書を開いていないと駄目なようです。

    

 それから、VBAの書き方でいうと、ActiveDocument.AttachedTemplate というのがあります。作業中のワード文書に結びつけられているテンプレートを参照するものです。

 これを確認してみると、いつもというわけではないでしょうが、通常は NormalTemplate と同じものを指し示しています。

 rubyで記述すると次のようになります。

  puts doc.obj.AttachedTemplate.Name
  puts doc.obj.AttachedTemplate.FullName

 「doc.obj」は、VBAの ActiveDocument に該当します。

    

 標準テンプレートに何が書かれているかをテキストとして取得し、合わせて、標準テンプレートのバックアップファイルをカレントディレクトリに保存するサンプルを掲げてみます。

 バックアップファイルの名前は、backup.dot あるいは backup.dotm です。

    

−−−− wmcr08.rb ここから
# encoding: Windows-31J
require "wrdap"
wrd = Wrdap.new
wrd.opens("dummy.doc")
fname = wrd.ntpl.Name
out_file = Wrd::fullpath("backup" + File.extname(fname))
tpl_doc = wrd.ntpl.OpenAsDocument  # テンプレートを文書として開く
str = tpl_doc.Content.Text  # 内容をテキストとして取得
tpl_doc.SaveAs('FileName'=>out_file)  # テンプレートのBackUp保存
tpl_doc.Close('SaveChanges'=>WdDoNotSaveChanges)  # テンプレートを閉じる
wrd.quit
puts "テンプレートの内容: #{str}"
−−−− wmcr08.rb ここまで

    

 標準テンプレートを文書として開く時は、OpenAsDocument というメソッドを用います。

 標準テンプレートの内容をテキストとして取り出しても、おそらく改行コードが書かれているだけ、つまり、実質的には空っぽだと思いますが、上のスクリプトでは一応、標準出力に出力しています。


(2) 標準テンプレートに関するマクロの操作

 先に述べた macro_code() や macro_add() などのメソッドは、Wrdap.new で生成されるオブジェクトについても定義されており、同じように使うことができます。例えば次のような具合です。

    

  wrd = Wrdap.new
  wrd.opens("dummy.doc")
  wrd.macro_add(str, 1, "DummyTest")  # マクロの登録
  wrd.macro_run("Normal.DummyTest.Macro1")  # マクロの実行
  puts wrd.macro_code()  # マクロのソースコードを出力
  wrd.quit

    

 上のようにしてマクロを登録すると、標準テンプレートに組み込まれます。ある特定のワード文書に組み込まれるわけではないので、どんなワード文書を処理している時でもそのマクロを利用できます。

 標準テンプレートは、暗黙のうちに保存されるようなので、わざわざ保存するための処理を施す必要はありません。

    

 標準テンプレートにマクロを登録したり、それを実行する場合に注意しなければならないのは、個別のワード文書に登録されているマクロなどと混同しないことです。Module1 というモジュール名や Macro1 というプロシージャ名は有り触れた名前なので、標準テンプレートでは、できれば別の名前にした方が無難だと思います。

 また、マクロを実行する時は、マクロの名前をモジュール名等を含めたフルネームで指定するのが安全です。標準テンプレートに登録されているマクロの場合、「Normal.Module1.Macro1」のようになります。こうしておけば、標準テンプレート以外に登録されているマクロと混同してしまう危険を避けられます。

    

 といったことに留意しながら、標準テンプレートにおけるマクロの取扱いを書いてみたのが wmcr09.rb です。

 wmcr01.rbを少し変形したマクロ(文書の冒頭に現在時刻を挿入するもの)を標準テンプレートに登録します。プロシージャ名は Macro1 ですが、モジュール名をDummyTestにしています。

 このマクロが標準テンプレートにずっと残ってしまうのは気持ちよくないので、スクリプトの最後の方で削除しています。

 以下、wmcr09.rb です。

    

−−−− wmcr09.rb ここから
# encoding: Windows-31J
require "wrdap"
str = DATA.read  # マクロソースコードをstrに代入
filename = "wmcr09.doc"
File.unlink(filename)  if test(?e, filename)
module_name = "DummyTest"
wrd = Wrdap.new
wrd.opens(filename) do |doc|
  component = wrd.macro_add(str, 1, module_name)  # マクロの組込み
  puts "#{component.Name}にマクロを組み込みました."
  wrd.macro_run("Normal.#{module_name}.Macro1")  # マクロの実行
  doc.save
end
wrd.quit

filename = "wmcr09b.doc"
File.unlink(filename)  if test(?e, filename)
wrd = Wrdap.new
wrd.opens(filename) do |doc|
  str = wrd.macro_code
  puts str
  wrd.macro_run("Normal.#{module_name}.Macro1")  # マクロの実行
  doc.save
  wrd.macro_remove(1, module_name)  # 今回登録したマクロを消去
end
wrd.quit

__END__
Sub Macro1
    Dim rng As Range
    Set rng = ActiveDocument.Range(0,0)
    With rng
        .InsertParagraph
        .InsertDateTime DateTimeFormat:="HH':'mm':'ss", _
            InsertAsField:=False, InsertAsFullWidth:=False, _
            DateLanguage:=wdJapanese, CalendarType:=wdCalendarWestern
    End With
End Sub
−−−− wmcr09.rb ここまで

    

 上ではワードを2回起動しています。標準テンプレートに登録したマクロが、別のワード文書を開いている時にも使えるかどうかを確認するためそのようにしました。

 あと、あまり利用することはないと思いますが、「wrd.ntpl = xxx」のようにして、ntplの値をNormalTemplateとは別のものに切り替えることができます。

 例えば、ActiveDocument.AttachedTemplate が NormalTemplate とは異なるテンプレートを指し示している場合、rubyの記述で次のようにすると、macro_add() などのメソッドが NormalTemplate ではなく ActiveDocument.AttachedTemplate の方に適用されるようになります。

    

  wrd = Wrdap.new
  wrd.opens("test.doc") do |doc|
    wrd.ntpl = doc.obj.AttachedTemplate
    wrd.macro_add(str, 1, "TestModule")
  end
  wrd.quit

    

 なお、「wrd.ntpl = nil」とすれば、ntplの値がnilになるのでなく NormalTemplate に戻ります。

 標準テンプレートにおけるマクロの取扱いに関する説明は、これくらいにします。

 マクロにショートカットキーを割り当てる場合も、標準テンプレートのマクロなのか、個別のワード文書のマクロなのかの区別が必要になりますが、それについては後述します。

目次に戻る


6. マクロの取扱いに関するその他のノウハウ

 MS-Wordのマクロを扱う際に、比較的よく用いると思われるノウハウを補足的に記します。

    

(1) マクロのフルネーム

 Module1 と Module2 の両方に Macro1 という名前のマクロが登録されていたとします。このとき、その二つのマクロを実行するには、それぞれ次のようにします。

  doc.macro_run("Module1.Macro1")
  doc.macro_run("Module2.Macro1")

 モジュール名の後に半角ピリオドを置いて、その後にマクロの名前を記します。

 全モジュールを見わたして、同名のマクロが他にないのであれば、わざわざモジュール名を付けなくて大丈夫です。

 ここには掲げませんが、サンプルとして wmcr10.rb を同梱しておきます。内容は wmcr02.rb と同じです。

 1つ目のマクロで、文書の先頭に「昨日は朝から雨が降っていた。」という1行を挿入し、2つ目のマクロでは「雨」を太字にします。

 2つのマクロの名前をあえて Macro1 という同じものにして、1つ目をModule1、2つ目をModule2に組み込んでいます。

    

 ところで、標準テンプレートにもマクロを登録できることは前述したとおりですが、そちらにも Module1.Macro1, Module2.Macro1 がある場合はどうしたらいいでしょうか。

 標準テンプレートのマクロを実行したい時は、Normal.Module1.Macro1, Normal.Module2.Macro1 とします。これがマクロのフルネームです。

 ワードは、おそらく、作業中の文書に登録されているマクロから探索をはじめて、その後に標準テンプレートのマクロを探索するのだと思います。

 なので、作業中の文書のマクロを呼び出す際は、モジュール名よりも大きな枠組みの名前を省略してかまわないと思います。

 省略せずに、あえてフルネームを指定するとすれば、作業中の文書のマクロには Project を付けます。Project.Module1.Macro1 というような名前がフルネームです。

 正直なところ、Projectが作業中の文書への帰属を必ず示すものなのかどうかについて、明示している解説をみつけることができませんでした。なので確証があるわけではありませんが、たぶん大丈夫だと思います。


(2) マクロのショートカットキー設定(Keybindings.Add)

 組み込んだマクロにショートカットキーを割り当てる場合、VBAでいうところの「Application.Keybindings.Add()」を用います。

 ショートカットキーを割り当てると、MS-WordをGUI操作している最中に、例えば、コントロールキーとシフトキーを押しながらuキーをたたくことによって、マクロを実行できるようになります。

 rubyスクリプトでこの Keybindings.Add を実行するサンプル wmcr11.rb を下に掲げます。

 wmcr01.rbを少し書き換えて、文書の先頭に「はじめに」という行を挿入するマクロに、ショートカットキーを割り当てます。

 新たに生成されたwmcr11.docを開いてGUI操作している時に、キーボードから「コントロール+シフト+u」を入力すると、Macro1が実行されて、「はじめに」が冒頭に挿入されます。

 以下、サンプル wmcr11.rb です。

    

−−−− wmcr11.rb ここから
# encoding: Windows-31J
require "wrdap"
str = DATA.read  # マクロソースコードをstrに代入
filename = "wmcr11.doc"
File.unlink(filename)  if test(?e, filename)
Wrdap.new(filename) do |doc|
  doc.macro_add(str, 1, "Module1")  # マクロの組込み
  app = doc.Application
  app.CustomizationContext = doc.obj  # 保存先を作業中の文書にする
  key_code = app.BuildKeyCode(WdKeyControl, WdKeyShift, WdKeyU)
  app.Keybindings.Add('KeyCategory'=>WdKeyCategoryMacro,
      'Command'=>"Module1.Macro1",
      'KeyCode'=>key_code)
  doc.save  # 文書の保存
end

__END__
Sub Macro1
    Dim rng As Range
    Set rng = ActiveDocument.Range(0,0)
    With rng
        .InsertParagraph
        .InsertBefore "はじめに"
    End With
End Sub
−−−− wmcr11.rb ここまで

    

 KeyBindings.Add() には次の引数をわたします。

    

 第1引数のKeyCategoryとして指定できる値は次のものです。

定数名 説明
WdKeyCategoryNil -1 キーの割り当てはない
WdKeyCategoryDisable 0 キーを無効にする
WdKeyCategoryCommand 1 キーをコマンドに割り当てる
WdKeyCategoryMacro 2 キーをマクロに割り当てる
WdKeyCategoryFont 3 キーをフォントに割り当てる
WdKeyCategoryAutoText 4 キーを定型句に割り当てる
WdKeyCategoryStyle 5 キーをスタイルに割り当てる
WdKeyCategorySymbol 6 キーを記号に割り当てる
WdKeyCategoryPrefix 7 キーを接頭辞に割り当てる

    

 第3引数の KeyCode として指定できるのは、下の98種類、もしくは、それらの組合せです。


定数名 16進 説明
WdKeyBackspace 8 0x08 BackSpaceキー
WdKeyTab 9 0x09 Tabキー
WdKeyNumeric5Special 12 0x0c .ちキー
WdKeyReturn 13 0x0d Enterキー
WdKeyPause 19 0x13 Pauseキー
WdKeyEsc 27 0x1b Escキー
WdKeySpacebar 32 0x20 Spaceキー
WdKeyPageUp 33 0x21 PageUpキー
WdKeyPageDown 34 0x22 PageDownキー
WdKeyEnd 35 0x23 Endキー
WdKeyHome 36 0x24 Homeキー
WdKeyInsert 45 0x2d Insキー
WdKeyDelete 46 0x2e Delキー
WdKey0 48 0x30 0キー
WdKey1 49 0x31 1キー
WdKey2 50 0x32 2キー
WdKey3 51 0x33 3キー
WdKey4 52 0x34 4キー
WdKey5 53 0x35 5キー
WdKey6 54 0x36 6キー
WdKey7 55 0x37 7キー
WdKey8 56 0x38 8キー
WdKey9 57 0x39 9キー
WdKeyA 65 0x41 Aキー
WdKeyB 66 0x42 Bキー
WdKeyC 67 0x43 Cキー
WdKeyD 68 0x44 Dキー
WdKeyE 69 0x45 Eキー
WdKeyF 70 0x46 Fキー
WdKeyG 71 0x47 Gキー
WdKeyH 72 0x48 Hキー
WdKeyI 73 0x49 Iキー
WdKeyJ 74 0x4a Jキー
WdKeyK 75 0x4b Kキー
WdKeyL 76 0x4c Lキー
WdKeyM 77 0x4d Mキー
WdKeyN 78 0x4e Nキー
WdKeyO 79 0x4f Oキー
WdKeyP 80 0x50 Pキー
WdKeyQ 81 0x51 Qキー
WdKeyR 82 0x52 Rキー
WdKeyS 83 0x53 Sキー
WdKeyT 84 0x54 Tキー
WdKeyU 85 0x55 Uキー
WdKeyV 86 0x56 Vキー
WdKeyW 87 0x57 Wキー
WdKeyX 88 0x58 Xキー
WdKeyY 89 0x59 Yキー
WdKeyZ 90 0x5a Zキー
WdKeyNumeric0 96 0x60 0キー
WdKeyNumeric1 97 0x61 1キー
WdKeyNumeric2 98 0x62 2キー
WdKeyNumeric3 99 0x63 3キー
WdKeyNumeric4 100 0x64 4キー
WdKeyNumeric5 101 0x65 5キー
WdKeyNumeric6 102 0x66 6キー
WdKeyNumeric7 103 0x67 7キー
WdKeyNumeric8 104 0x68 8キー
WdKeyNumeric9 105 0x69 9キー
WdKeyNumericMultiply 106 0x6a *キー(テンキー)
WdKeyNumericAdd 107 0x6b +キー(テンキー)
WdKeyNumericSubtract 109 0x6d -キー(テンキー)
WdKeyNumericDecimal 110 0x6e .キー(テンキー)
WdKeyNumericDivide 111 0x6f /キー(テンキー)
WdKeyF1 112 0x70 F1キー
WdKeyF2 113 0x71 F2キー
WdKeyF3 114 0x72 F3キー
WdKeyF4 115 0x73 F4キー
WdKeyF5 116 0x74 F5キー
WdKeyF6 117 0x75 F6キー
WdKeyF7 118 0x76 F7キー
WdKeyF8 119 0x77 F8キー
WdKeyF9 120 0x78 F9キー
WdKeyF10 121 0x79 F10キー
WdKeyF11 122 0x7a F11キー
WdKeyF12 123 0x7b F12キー
WdKeyF13 124 0x7c F13キー
WdKeyF14 125 0x7d F14キー
WdKeyF15 126 0x7e F15キー
WdKeyF16 127 0x7f F16キー
WdKeyScrollLock 145 0x91 ScrollLockキー
WdKeySemiColon 186 0xba ;キー
WdKeyEquals 187 0xbb =キー
WdKeyComma 188 0xbc ,キー
WdKeyHyphen 189 0xbd -キー
WdKeyPeriod 190 0xbe .キー
WdKeySlash 191 0xbf /キー
WdKeyBackSingleQuote 192 0xc0 `キー
WdKeyOpenSquareBrace 219 0xdb [キー
WdKeyBackSlash 220 0xdc \キー
WdKeyCloseSquareBrace 221 0xdd ]キー
WdKeySingleQuote 222 0xde ‘キー
WdNoKey 255 0xff 指定キーなし
WdKeyShift 256 0x100 Shiftキー
WdKeyCommand 512 0x200 Ctrlキー
WdKeyControl 512 0x200 Ctrlキー
WdKeyAlt 1024 0x400 Altキー
WdKeyOption 1024 0x400 マウスのオプションキー

目次に戻る


 シフトキーやコントロールキーと、アルファベットキーや数字キーを組み合わせる場合は、サンプルで記述したように BuildKeyCode() を用いてキーコードを算出します。

 実は、BuildKeyCode() を用いなくても、キーに対応する整数値をプラスしてもかまいません。単純な ‘+’ でもいいでしょうし、ビット演算子の論理和 ‘|’ でもいいと思います。例えば次のように算出できます。

  key_code = WdKeyControl + WdKeyShift + WdKeyU

    

 「app.CustomizationContext = doc.obj」というのは、ショートカットキーの保存先を作業中の文書(ActiveDocument)に設定するものです。

 通常、この設定をしない時は、標準テンプレート(NormalTemplate)が保存先になっていると思います。

 CustomizationContextは、「ユーザー設定」ダイアログボックスにおいて「ツール」→「コマンド」→「保存先」の値に対応するようです。

 標準テンプレートにショートカットキーの割当情報を保存したい時は、VBA形式で下のように書きます。

  CustomizationContext = NormalTemplate

 CustomizationContextもNormalTemplateも、Globalの下で定義されているものです。なので上のように書くことができます。

 しかし、rubyでは単にCustomizationContextとだけ書くわけにはいかないので、あえてApplicationに帰属する形にして、次のように書くことになります。

  app.CustomizationContext = app.NormalTemplate

 言わずもがなですが、今回の wmcr11.rb は、マクロを作業中の文書に登録しているので、標準テンプレートにショートカットキーを保存するのは避けるのがいいと思います。

    

 それから、マクロに対してショートカットキーを割り当てている場合、そのショートカットキーを無効にするには、KeyBinding.Disableを用います。エッセンスのみ抜き出すと次のとおり。

    

  key_code = app.BuildKeyCode(WdKeyControl, WdKeyShift, WdKeyU)
  key_binding = app.FindKey(key_code)
  ary = nil
  if key_binding.Command != ""  # キーに割り当てられているものがある
    ary = [key_binding.KeyString, key_binding.Command]
    key_binding.Disable  # キーの割り当てを無効にする
  end
  if ary != nil
    printf("'%s' → '%s' を無効にしました.\n", ary[0], ary[1])
  else
    puts "該当のキーに割り当てられているものがみつかりませんでした."
  end

    

 FindKey() は、指定のキーコードにまつわる1つのKeyBindingオブジェクトを返します。この戻り値は、wmcr11.rbにおいて KeyBindings.Add() によって生成されたオブジェクトと同一です。

 この戻り値を変数kbに代入したとすると、kb.Command で割り当てられているコマンドやマクロの名前を知ることができます。この値が空文字列 “” であれば、該当のキーコードに割り当てられているものがないことを意味します。

 kb.KeyString は、キーコードを整数値ではなく文字列で示すものです。

 kb.Disable とすれば、kb.Command が “” になり、キーの割り当てが無効になります。

 ここには掲げませんが、キーの割り当てを無効にするためのサンプル wmcr11b.rb, wmcr11c.rb を同梱しておきます。一つは FindKey() を用いる例、もう一つは KeyBindings.each を用いる例です。

 FindKey() を用いる方が作業効率はいいと思いますが、KeyBindings.each でKeyBindingオブジェクトを一つづつ辿る方法は、汎用性が高く応用がきくといえます。例えば、Macro1という名前のすべてのマクロ(モジュール名は問わない)に対し、すべてのキーの割り当てを無効にする、といった処理を行えます。

 ここでは取り上げませんが、他に KeysBoundTo() というのもあります。指定された項目に割り当てられているすべてのキーの組み合わせを表すオブジェクトを取得します。引数として Command や KeyCategory を指定できます。


(3) MS-Word2007以降のdocmファイル

 これまでのサンプルは、拡張子が “.doc” のワード文書を扱ってきました。

 一方、MS-Word2007以降では、マクロ付きのワード文書として、拡張子 “.docm” を扱うことができます。

 もし MS-Word2007 以降を動かせる環境にあるなら、これまでのサンプルの wmcr01.doc などを wmcr01.docm のように変更しても、そのまま問題なく動きます。

 MS-Wordのバージョンが判然としない場合に、2003までならdoc、2007以降の時はdocmにしたいということであれば、例えば次のようにします。

    

wrd = Wrdap.new
filename = (wrd.word_version < 12.0) ? "test.doc" : "test.docm"
wrd.opens(filename) do |doc|
    …………
end
wrd.quit

    

 参考まで、wmcr01.rb を上の流儀で書き換えたものを wmcr12.rb として同梱しておきます。


(4) ユーザーフォームの例

 コンポーネントのタイプ1〜3を対象にすると言いながら、タイプ3(ユーザーフォーム)については触れないままでした。

 遅ればせながら、ここでサンプルとして wmcr13.rb を掲げておきます。

 SampleFormという名前のコンポーネント(ユーザーフォーム)を設けて、それにテキストボックス、リストボックス、コマンドボタン2つの計4つを貼り付けます。そして、そのユーザーフォームをテストするための標準モジュールを組み込みます。プロシージャ名は Macro1 です。最後に、このテストのためのマクロにショートカットキーを割り当てます。これら一連の作業は rubyスクリプト側で行います。

 VBAソースコードの方では、Finishボタンとキャンセルボタンがおされた時の終了処理のほか、テキストボックス・リストボックス・コマンドボタンのプロパティ設定等を行っています。

    

 wmcr13.rbを実行すると wmcr13.doc が作られます。これをMS-Wordで開いてGUI操作します。

 Macro1が組み込まれているので、それを実行します。ショートカットキー「コントロール+シフト+u」を入力すると、そのマクロが実行されるはずです。

 テキストボックスとリストボックスでそれぞれ適当に入力または選択し、Finishというコマンドボタンをクリックすると、入力・選択したものがそれぞれ第1パラグラフと第2パラグラフに書き込まれます。

 キャンセルボタンをクリックすると(エスケープキーを押すのでもよい)、何も行わずに文書編集の状態に戻ります。

 以下、wmcr13.rb です。

    

−−−− wmcr13.rb ここから
# encoding: Windows-31J
require "wrdap"
uf_str, mdl_str = DATA.read.split(/\n########\n+/)
filename = "wmcr13.doc"
File.unlink(filename)  if test(?e, filename)
Wrdap.new(filename) do |doc|
  uf = doc.macro_add(uf_str, 3, "SampleForm")  # add UserForm component
  uf.Designer.Controls.Add("Forms.TextBox.1")  # add TextBox
  uf.Designer.Controls.Add("Forms.ListBox.1")  # add ListBox
  uf.Designer.Controls.Add("Forms.CommandButton.1")  # add CommandButton
  uf.Designer.Controls.Add("Forms.CommandButton.1")  # add CommandButton
  doc.macro_add(mdl_str, 1, "Module1")  # add standard module component
  app = doc.Application
  app.CustomizationContext = doc.obj  # 保存先を作業中の文書にする
  app.Keybindings.Add('KeyCategory'=>WdKeyCategoryMacro,
      'Command'=>"Module1.Macro1",
      'KeyCode'=>WdKeyControl + WdKeyShift + WdKeyU)
  slc = doc.Application.Selection
  slc.TypeText "ユーザーフォームをテストするためのドキュメント"
  slc.TypeParagraph()
  slc.TypeText "コントロールキー+シフトキー+Uを入力して、ユーザーフォームを試して下さい。"
  slc.TypeParagraph()
  doc.save
end

__END__
' UserForm module
Private Sub CommandButton1_Click()
    ActiveDocument.Paragraphs(1).Range.Text = Me.TextBox1.Value & vbCrLf
    ActiveDocument.Paragraphs(2).Range.Text = Me.ListBox1.Value & vbCrLf
    Unload Me
End Sub

Private Sub CommandButton2_Click()
    Unload Me
End Sub

Private Sub UserForm_Initialize()
    With TextBox1
        .AutoSize = True
        .MultiLine = False
    End With
    With ListBox1
        .AddItem "月曜日"
        .AddItem "火曜日"
        .AddItem "水曜日"
        .AddItem "木曜日"
        .AddItem "金曜日"
    End With
    With CommandButton1
        .Caption = "Finish"
    End With
    With CommandButton2
        .Caption = "Cancel"
        .Cancel = True
    End With
End Sub

########
' standard module
Sub Macro1()
    SampleForm.Show
End Sub
−−−− wmcr13.rb ここまで

    

 上記スクリプトで作成される wmcr13.doc に対して macro_export を適用すると(wmcr06a.rb参照)、SampleForm.frm の他に SampleForm.frx というファイルも書き出されます。前者はテキストファイル、後者はバイナリーファイルです。

 このユーザーフォームに関する二つのファイルを macro_import で読み込む時は、テキストファイルの SampleForm.frm の方を読み込めば大丈夫です。そうすれば、バイナリーの方も付随して読み込まれます。バイナリーファイルが同じフォルダにないと正しく読込みが行われないので注意して下さい。

 なお、wmcr13.rbで設定したショートカットキーの割当を解除するためのスクリプト wmcr13b.rb を同梱しておきますので、必要に応じて実行して下さい。

 また、コマンドボタンとして cmdOK, cmdCancel の記述がよく用いられるようなので、その名前を用いるサンプルをwmcr13c.rbとして同梱しておきます。FinishボタンでなくOKボタンにして、エンターキーの押下がOKボタンのクリックと同じ扱いになるよう設定しています。

    

 ワード文書においてユーザーフォームを利用する典型的なケースは、定型文書の雛形テンプレートにそれを組み込んで、ユーザーが入力・選択したものを所定の箇所に挿入する、というケースだと思います。

 そうした例をサンプルで示せればとも思いましたが、雛形テンプレートの処理については様々な事柄が関係してきて、実践的なものであればあるほど、サンプルとしては複雑で分かりにくくなると考えてやめました(弁解モード)。

    

 それから、ワード文書を開くと、直ちにユーザーフォームが立ち上がるようにするといったノウハウも、比較的よく利用されると思います。

 wmcr13.rbの中の「Sub Macro1()」のところを「Sub AutoOpen()」に書き換えれば、wmcr13.docを開いた時に直ちにユーザーフォームが立ち上がるようになります。その場合は、マクロにショートカットキーを割り当てる必要がないので、rubyスクリプトの該当箇所を削除する必要があります。

 また、あまりお勧めはできませんが、標準テンプレート(NormalTemplate)に「Sub AutoExec() …… End Sub」という標準モジュールを組み込めば、ワード文書を開いた直後にそれが立ち上がるようになります。


(5) VBEの非表示

 最後に、VBE(Visual Basic Editor)を非表示にする方法を記しておきます。

 VBA記述では「Application.VBE.MainWindow.Visible = False」と書きます。

 rubyでは(wrdap利用時)「doc.app.obj.VBE.MainWindow.Visible = false」です。

目次に戻る


 マクロの取扱いについて、この辺でおわりにします。

    

〜 以上 〜

    

Copyright (C) T. Yoshiizumi, 2015 All rights reserved.


wrdap.rbのページへ

トップページへ