Excel&VBA解説サイト「エクセルの神髄」様出題の問題集、
「VBA100本ノック」に対する私の回答と解説のページです。
100本ノックの出題リストはこちらから
excel-ubara.com
出題:ITをDXに変換(文字列操作)
#VBA100本ノック 72本目
引数の文字列に以下の処理を行い文字列で返すFunctionを作成。
全ての"IT"を"DX"に置換
※大小文字全半角問わず
※直前または直後がアルファベットの場合は対象外
※空白及び'は除いて判定
置換する:"IT","と IT","itは","IT 99"
しない:"GIT","site","It's","it is"

◇ 出題ページはこちら
ソースコード
Option Explicit ' 100本ノック072:ITをDXに変換(文字列操作) Function ReplaceIT→DX(str元文字列 As String) As String Dim str結果値 As String: str結果値 = str元文字列 ' IT判定用の半角大文字に統一したテキスト Dim str判定用 As String str判定用 = StrConv(str元文字列, vbUpperCase + vbNarrow) ' ITをひとつずつ検索 Dim ITの位置 As Long Dim ひとつ前のITの位置 As Long Dim i As Long, 判定文字 As String Do ' 前回のITの次のITを検索(なければExit) ITの位置 = InStr(ひとつ前のITの位置 + 1, str判定用, "IT") If ITの位置 = 0 Then ReplaceIT→DX = str結果値 Exit Function End If ' ITの" ","'"ではないひとつ前の文字が英字か判定 Dim is前の文字が英字 As Boolean: is前の文字が英字 = False For i = 1 To ITの位置 - 1 判定文字 = Mid(str判定用, ITの位置 - i, 1) If 判定文字 <> " " And 判定文字 <> "'" Then If 判定文字 Like "[A-Z]" Then: is前の文字が英字 = True Exit For End If Next ' ITの" ","'"ではないひとつ後ろの文字が英字か判定 Dim is後ろの文字が英字 As Boolean: is後ろの文字が英字 = False For i = 2 To Len(str判定用) - ITの位置 判定文字 = Mid(str判定用, ITの位置 + i, 1) If 判定文字 <> " " And 判定文字 <> "'" Then If 判定文字 Like "[A-Z]" Then is後ろの文字が英字 = True Exit For End If Next ' ITの両側が英字でなければDXに置換 If (is前の文字が英字 Or is後ろの文字が英字) = False Then Mid(str結果値, ITの位置, 2) = "DX" End If ひとつ前のITの位置 = ITの位置 Loop End Function
解説
各見出しコメントの通りのロジックで処理を進めています。
まずは「IT」を検索し、そのITのひとつ前/ひとつ後ろの文字を判定して、
どちらも英字ではなかった場合は置換を実行しています。
置換の実行はITとDXの文字数が一致してくれているため、
Midステートメントで実行しています。
Midは右辺に書くとMid関数ではなくステートメントとして動き、
第○文字目からn文字分を置き換えることが出来ます。
今回のように「同じ文字でも置換するものとしないものがある」際には、
便利に扱えるステートメントですので覚えておきましょう。
ひとつ前/ひとつ後ろの文字をただ判定するだけなら一重ループでよいのですが、
今回は半角スペースとシングルクォートを無視する必要があるため、
前方・後方に再度ループを回す必要があります。
このあたりのロジックは変数名をしっかりつけると頭を整理しやすくなる、
というか雑な変数名にすると頭がパンクします。
本コードの命名をひとつ参考にしてみてください。
最後にひとつ、変数の使い方についてですが、
今回のこちら↓のコード、
ITの位置 = InStr(ひとつ前のITの位置 + 1, str判定用, "IT")
これは以下のコード↓でも全く同じ動きになります。
ITの位置 = InStr(ITの位置 + 1, str判定用, "IT")
この代入が行われるまではITの位置には前回のITの位置が入っていますからね。
↓こちらのコードは無駄と言えば無駄な処理をしています。
ひとつ前のITの位置 = ITの位置
とはいえ、たかがLong変数ひとつの消費メモリと、代入1回の処理時間は、
このFunctionを1億回呼んでも0といっていい程度です。
こういった複雑な処理では脳の負担を少しでも減らすことが重要ですので、
(↑の変数を用意した方が分かりやすいと思う方は、)
躊躇せずにこういった説明変数を使っていきましょう。