【Word VBA】RangeオブジェクトとSelectionオブジェクト(2)

2010年6月10日

今回は、どうやってSelectionオブジェクトをRangeオブジェクトに書き換えるかについて説明します。

通常、selectionを使うときには、「選択される文字列はカーソルの動きに影響される」と理解するとイメージしやすくなると思います。

例えば、「2010年6月10日」という文字列が文中に示されていて、「2010年」を選択したあとに、カーソルを別の場所に移動させると、「2010年」の選択は解除されます。

カーソルを「10日」の後に移動します。

このとおり、「2010年」の選択は解除されますね。

これは、みなさん感覚でお気づきのことと思いますが、プログラミングでは結構重要です。

Selectionオブジェクトで文字列を選択すると、同様のことがおこります。

つまり、選択範囲は常にカーソルと連動しますので、次の文字列を選択すると、前回選択したものは保持されません

これは、前回の「RangeオブジェクトとSelectionオブジェクト」の記事で説明したとおりです。

さて、今日は、上記のようなSelectionオブジェクトでの検索とRangeオブジェクトでの検索の違いを少し体験できるプログラムを書いてみました。

オブジェクトって何だ?って言う方も、ひとまず見てみるだけでも違いがわかると思います。

オブジェクトの意味は、使っているうちに理解がおいついてくると思いますので、ひとまずは使うことから始めましょう。

私自身、まだ、学びながらプログラムを作成している最中ですので、理解不足もありますが、ひとまず自分が理解している範囲で説明したいと思います。

プログラム概要

同じ動作をするマクロを4つの表現で書いてみました。

<作用>

「任意の全角数字一桁以上の文字列」+「年」の組み合わせを検索して、検索結果を表示させます。

ワイルドカードを用いた検索ですね。

ワイルドカードと言えば、「ワイルドカード検索・置換の事例集 」。

水野麻子さんが無料で公開されている電子書籍をご覧ください。

これに勝るマクロのワイルドカードの実用資料は今のところないと思います。

では、例文として「2010年6月10日」と文章中に書いてください。

プログラムを実行すると、検索結果として「2010年」とメッセージボックスに表示されます。

<プログラム種類>

  • プログラム1:マクロの記録をもとにSelectionオブジェクトを用いて書いたもの
  • プログラム2:プログラム1をRangeオブジェクトで書き換えたもの
  • プログラム3:プログラム2を簡潔に書き直したもの
  • プログラム4:プログラム3を別表現に書き直したもの

プログラム1


Sub selection_test_1()

 Selection.Find.ClearFormatting

 With Selection.Find
  .Text = "[0-9]{1,}年"
  .Replacement.Text = ""
  .Forward = True
  .Wrap = wdFindContinue
  .Format = False
  .MatchCase = False
  .MatchWholeWord = False
  .MatchByte = False
  .MatchAllWordForms = False
  .MatchSoundsLike = False
  .MatchFuzzy = False
  .MatchWildcards = True
 End With
 
 Selection.Find.Execute
 
 MsgBox Selection

End Sub

3~20行で、検索して、22行で結果表示をしています。

文書中の「2010年」が選択されて、メッセージボックスで「2010年」が表示されますね。


検索するコードは、マクロの記録機能を使いました。

プログラム2へ書き換え

これを、Rangeオブジェクトに書き換えます。

書き換えるコツは、Googleのワードマクロのニュースグループの記事の5件目のコメントをご覧ください。

Set myRange = Selection.Range

この記事を読んで以来、なにかとこの表現を使っています。

プログラム2


Sub selection_test_2()
 
 Dim myRange As Range
 
 Set myRange = Selection.Range
 
 With myRange.Find
  .Text = "[0-9]{1,}年"
  .Replacement.Text = ""
  .Forward = True
  .Wrap = wdFindContinue
  .Format = False
  .MatchCase = False
  .MatchWholeWord = False
  .MatchByte = False
  .MatchAllWordForms = False
  .MatchSoundsLike = False
  .MatchFuzzy = False
  .MatchWildcards = True
 End With
 
 myRange.Find.Execute
 
 MsgBox myRange
 
 Set myRange = Nothing

End Sub

とりあえず、Rangeオブジェクトに書き換えました。

単純に、SelectionをSelection.Rangeとしただけです。


このとおり、カーソルは最初の位置と変わりません。(マクロを実行する前と同じ位置です。)

そして、検索された文字列「2010年」がメッセージボックスに表示されました。

また、Rangeオブジェクトで検索する場合には、検索窓の設定と連動しないこともメリットのひとつです。

通常、Selectionオブジェクトでマクロを書くと、マクロで使った検索文字列や書式の設定が、手動で検索をする場合の「検索と置換」画面の設定に反映されてしまいます。

なので、マクロの最後に、検索条件を初期化するプログラム文を入れた方がうれしいですね(今回は書いていません)。

または、逆に、前回手動で「検索と置換」画面で設定した検索条件(書式・検索文字列など)が、マクロを実行するときに反映されてしまいます。

よって、Selectionオブジェクトでマクロを書く場合には、前回の検索と置換の条件を、マクロの最初で一旦初期化(クリア)する必要があるわけです。

しかし、Rangeオブジェクトの場合には、上記のようなマクロの最初と最後の「検索と置換」条件の初期化の必要がありません。

というわけで、プログラム1の3行目のに記載されている「検索フォーマットの初期化」のコード

Selection.Find.ClearFormatting

を削除しました。

実行すると分かりますが、カーソルは移動せず、かつ、見つけた文字列を選択していないのですが、検索結果が表示されます。

(文書中に対応する文字列がない場合には、メッセージボックスは空欄になります)

26行でmyRangeを解除しています。

これは、myRangeとしてセットしたオブジェクトを、そのプログラム内で解除しているわけです。

プログラミングでのくせにしましょう。

プログラム3へ書き換え

さて、さらに簡素化。

●プログラム3


Sub selection_test_3()
 
 Dim myRange As Range
 
 Set myRange = Selection.Range
 
 With myRange.Find
  .Text = "[0-9]{1,}年"
  .Forward = True
  .Wrap = wdFindContinue
  .MatchWildcards = True
 End With
 
 myRange.Find.Execute
 
 MsgBox myRange
 
 Set myRange = Nothing

End Sub

必要と思われる要素だけに削りました。

Selectionオブジェクトの場合にも、マクロの記録で作成したコードから、必要なものだけを記載してプログラムをスリム化することができます。

今回はワイルドカード検索なので、その旨を指示しています(11行)。

あと、全文検索にして(10行)、カーソルの移動方向を下向き(9行)にしています。

プログラム4へ書き換え

書き方の参考例です。

同じ検索の条件を別の書き方にする一例です。

●プログラム4


Sub selection_test_4()

 Dim myRange As Range
 
 Set myRange = Selection.Range
 
 myRange.Find.Execute _
    FindText:="[0-9]{1,}年", _
    MatchWildcards:=True, Wrap:=wdFindContinue, _
    Forward:=True
           
 MsgBox myRange
 
 Set myRange = Nothing

End Sub

プログラム3の7行から12行の内容を、プログラム4では、7行~9行にまとめてあります。

「Microsoft Visual Basicのヘルプ」(VBEでF1ボタンを押すと表示)やニューズグループの例文を見て学びました。

自然言語(英語や日本語)には、同じ意味を伝える文章であっても、様々な表現方法がありますね。

わかりやすいものとわかりにくいものがあります。

プログラム言語にも同じ意味でも様々な表現方法があり、またわかりやすい、わかりにくいがあると思います。

当然、読み手の知識量にもよりますが。。。まだ私には読めないプログラム文がたくさんあります。

今回の例ではわかりやすさはあまりかわらないかもしれませんが、冗長か簡潔かという点での違いでしょうか。

あと、書く際に、手間が省けますね。

プログラムが複雑になると処理速度にもかかわることみたいですが、上記の程度であれば、気にする必要はないですね。

関連記事

RangeオブジェクトとSelectionオブジェクト

RangeオブジェクトとSelectionオブジェクト(2) ←今ココ

-コード
-, , ,