指定した文字列に挟まれた箇所を取得する(Word)

補足 指定した文字列に挟まれた箇所を取得する

akashi-keirin.hatenablog.com

の補足。

ワイルドカードを用いたらもっと簡単にできるので、書いておきます。

目次

こんなことができます

たとえば、

「《》」で括られた箇所を取得したい!

というときに、引数に「」と「」を指定してやると、後方にある直近の当該箇所を指し示すRangeオブジェクトを取得することができます。

考え方

FindオブジェクトのTextプロパティに、ワイルドカードを用いて文字列を指定する。

それだけ。たったそれだけ。

たとえば、〝「《》」で括られた箇所〟が必要なら、Textプロパティを、

With Selection.Find
  .Text = "《" & "*" & "》"
	' 以下省略'
    :
    :
End With

とすればよい。

指定した文字列に挟まれた箇所を取得するFunction

さっさとコードを書いてしまおう。

リスト1 標準モジュールFormatStrings
Public Function GetSandwichedRange( _
            ByVal StartChar As String, _
            ByVal EndChar As String) As Range
  Dim ret As Range
  Set ret = Nothing
  With Selection.Find
    .Text = StartChar & "*" & EndChar
    .Replacement.Text = ""
    .Wrap = wdFindStop
    .Format = False
    .Highlight = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchByte = False
    .MatchAllWordForms = False
    .MatchPhrase = False
    .MatchSoundsLike = False
    .MatchFuzzy = False    '……(*)'
    .MatchWildcards = True
  End With
  Call Selection.Find.Execute
  If Not Selection.Find.Found Then GoTo ReturnObject
  Set ret = Selection.Range
ReturnObject:
  Set GetSandwichedRange = ret
End Function

気をつけないといけないのは、(*)のところ。

今回は、ワイルドカードを有効にするためにMatchWildcardsプロパティをTrueに設定したいのだが、だからといって、たとえば

.MatchWildcards = True
.MatchFuzzy = False

という順でコードを書くと、

f:id:akashi_keirin:20210131095157j:plain

という実行時エラーに見舞われるのである。

これは、先のエラーメッセージに挙げられている「MatchPhrase」、「MatchWildcards」、「MatchSoundsLike」、「MatchAllWordForms」、「MatchFuzzy」の各プロパティのうち、唯一「MatchFuzzy」プロパティのみが、初期値Trueであるという事情による。

つまり、MatchFuzzyFalseにする前に、「MatchPhrase」、「MatchWildcards」、「MatchSoundsLike」、「MatchAllWordForms」のうちどれか一つでもTrueにすると、

「MatchPhrase、MatchWildcards、MatchSoundsLike、MatchAllWordForms、MatchFuzzyパラメータ」を「同時に True に設定」した呼ばわり

されることになるのである!

まさに、天に二日なし!!!!!!!!

たぶん、多くの人は、Findオブジェクトを利用するコードなんてコピッペして使い回しているはずなので(ですよね?)、初めから「.MatchFuzzy」はMatch一族の中で一番上に置いておくのが良いかもしれない。

おっと、話がそれた。

このGetSandwichedRangeメソッドを用いれば、

たとえば、

f:id:akashi_keirin:20210131095159j:plain

この状態で、次のコードをイミディエイトで実行すると、

?GetSandwichedRange("《", "》").Text

f:id:akashi_keirin:20210131095202j:plain

こうなる。意図どおりの結果。

指定した文字列に挟まれた箇所を置換するメソッドはこんなに短くなります

前回のリスト2のコードは、次のように劇的に(?)短くなる。

スト2 標準モジュールFormatStrings
Public Function ReplaceSpecifiedRange( _
            ByVal StartChar As String, _
            ByVal EndChar As String, _
   Optional ByVal ReplaceText As String = "") As Boolean
  ReplaceSpecifiedRange = False
  Dim tgtRange As Range
  Set tgtRange = GetSandwichedRange(StartChar, EndChar)
  If tgtRange Is Nothing Then Exit Function
  tgtRange.Text = ReplaceText
  ReplaceSpecifiedRange = True
End Function

まっ たく 簡単 だ

おわりに

ただ、なんとなく今回の方式の方が遅い気がする。

ちょいと測ってみたら、

f:id:akashi_keirin:20210131095205j:plain

やっぱり少しだけ遅い。(何度も実験したわけではないので、毎回こうなるかどうなのかは不明。)

うーん……。何なのだろう。