Find の注意点・トラブルシュート

Findオブジェクトを使った検索・置換はWordの自動化にはよく使うので、戸惑う場面も多くなります。Findの注意点やトラブルシュートをまとめて紹介します。

検索と置換

テキスト検索で対象が存在するのに検出されない

原因 : Selection.Find と 実行時のカーソル位置

Selection.Find では、実行時のカーソル位置を起点に検索されます。検索対象の語句の途中にカーソルを置いて実行すると、その部分が検出されない場合があります。

.Wrap = wdFindStop を指定している場合
カーソルがある語句は検出されません。

.Wrap =  wdFindContinue を指定している場合
.Forward の指定によって異なるので要注意です。カーソルがある語句は、True (前方検索)の場合は検出されますが、False(後方検索) の場合は検出されません。

対策 : 実行時のカーソル位置に影響されないようにする

全文検索の際は、カーソル位置の影響がないRangeオブジェクトを使い、文書先頭からスタートするようにしましょう。

Set myRange = ActiveDocument.Content
'または Set myRange = ActiveDocument.Range(0, 0)
With myRange.Find
    '(以下略)

検出されたりされなかったりする

原因 : 前回の検索・置換の影響

Wordは前回の検索・置換時の指定を記憶しています。これはマクロだけでなくユーザーがダイアログボックスから実行したものも含まれます。 Findで指定しないプロパティには記憶されている指定が使われるので、前回の操作次第でマクロの動作に違いが生じます。

対策 : 必要なプロパティの指定は省略しない

Wordのデフォルトに関係なく、検出に影響するプロパティはすべて指定するようにします。

ClearFormatting は、フォントやスタイルなどの書式関連の指定をリセットします。ダイアログボックスの[書式を削除]ボタンに相当します。
MatchCaseなどの検索オプション関連はリセットされないので注意してください。
本サイトでもそうですが、サンプルコードでは本題に関連しないプロパティの指定は省略していたりします。サンプルを流用する場合は、必要なプロパティを補うようにしましょう。

6182 エラーになる

エラー6182

原因 : MatchPhrase、MatchWildcards、MatchSoundsLike、MatchAllWordForms、MatchFuzzy のうち True を指定できるのは1つのみ

Wordの起動直後はMatchFuzzyがTrueの状態なので、そのまま例えばMatchWildcardsをTrueにするとこのエラーになります。また、記憶されている前回の検索・置換時の指定が影響している可能性もあります。

ダイアログボックスではどれかをオンにすると他は自動的にオフになるのですが、VBAでは同様の制御はされずエラーになってしまいます。
対策 : True を指定するものを最後に記述する

これらのプロパティのどれかにTrueを指定する場合は、5つのプロパティを省力しないで記述し、Trueにするものを最後に記述します。

With myRange.Find
  .MatchPhrase = False
  .MatchSoundsLike = False
  .MatchAllWordForms = False
  .MatchFuzzy = False
  .MatchWildcards = True 'Trueのものを最後に記述
End With
Findを関数化して汎用的に使用する場合は、FindのこれらのプロパティにはすべてFalseを指定し、ExcuteTrueを再指定したりします。
myFind.Execute(MatchWildcards:=True)

無限ループになる

検出済みのものが再度検出されてしまう構造になっていると、いつまでも処理が終わらない「無限ループ」になってしまいます。例えば、テキストで検索して文字色を変える場合、テキストは変わらないので再検出される可能性があります。

原因と対策(1) : Wrap の指定

.Wrap = wdFindContinue が指定されていると、文書の終端まで処理が終わると始端に戻り、検出対象がなくなるまで繰り返されます。上記の例のように検索対象がなくならないものは無限になってしまいます。

.Wrap = wdFindStop を指定して、文書の終端で処理を終了するようにします。

原因と対策(2) : 検出範囲の強制クリア

通常は、対象が検出されると次の検索はそれ以降の範囲が対象になるのですが、検出箇所に対する処理によっては検出範囲がそのまま次の検索対象になってしまい、無限ループになることがあります。

myRange.Collapse Direction:=wdCollapseEnd を記述しておくと、次の検索対象を明確に検出範囲以降にできます。

ワイルドカード使用時の段落記号

[検索と置換]ダイアログボックスで、[ワイルドカードを使用する]にして[検索する文字列]に段落記号を指定しようとしても、[特殊文字]ボタンからの選択肢には段落記号がありません。段落記号の検索はできないのでしょうか。

対策: 文字コード”13″で検索可能

段落記号の検索には、“^13” または Chr(13) を指定します。^13はダイアログボックスでも使えます。

段落記号への置換には、“^p” を指定します。ダイアログボックスでも[置換後の文字列]には[特殊文字]ボタンからの選択肢に段落記号があります。

With myRng.Find
  .Text = Chr(13) 'または"^13"
  .Replacement.Text = "^p"
  '(以下略)
“^13″と”^p”の違い
“^13″やChr(13) は、段落記号の「文字」であり書式を引き継ぎません。検索テキストとしてはこの違いは関係ないので問題なく使えます。置換にも使うことはできますが、置換後に書式が引き継がれないなどのトラブル要因になるので、 “^p” を指定するのが無難ということになります。
タイトルとURLをコピーしました