文字列のカッコで括られた部分だけを狙い撃ちで削除するマクロ (2)
ネストされたカッコにも対応する
前回の記事が、この過疎ブログには珍しく反響があったので、ちょっと追加。
Replaceメソッドを使う方あり、Split関数を使う方あり、果ては正規表現を使うツワモノまで現れる始末……。
こうなったら、私も意地になって改良を加えますよー!
前回のコードの欠点
始めカッコがあったらスイッチオン、終わりカッコに出会ったらスイッチオフ、という単純なつくりなので、
たとえばこんなふうにカッコが設置されていたら、
途端に破綻……orz
そこで、少しだけコードに改良を加える。
改良したコード
リスト1
Sub deleteContents() Dim objCell As Range Dim objStr As String For Each objCell In Selection objStr = objCell.Value objCell.Value = _ deleteContentsEnclosedByBracket _ (objStr, "(", ")") Next End Sub Private Function deleteContentsEnclosedByBracket _ (ByVal objStr As String, _ ByVal startBracket As String, _ ByVal endBracket As String) As String Dim enableToDelete As Boolean Dim tmp As String Dim chr As String Dim i As Integer Dim n As Integer n = 0 For i = 1 To Len(objStr) chr = Mid(objStr, i, 1) If chr = startBracket Then n = n + 1 '……(1)' enableToDelete = True End If If chr = endBracket Then n = n - 1 '……(2)' If n = 0 Then '……(3)' enableToDelete = False chr = "" End If End If If enableToDelete = False Then tmp = tmp & chr End If If enableToDelete = True Then End If Next deleteContentsEnclosedByBracket = tmp End Function
リスト1の説明
改良ポイントは、
カウンタ式フラグ n を導入した
こと。
まず、(1)のところ。
If chr = startBracket Then n = n + 1 enableToDelete = True End If
開始カッコと出会うたびに n をインクリメントする。
んで、(2)と(3)。
If chr = endBracket Then n = n - 1 '……(2)' If n = 0 Then '……(3)' enableToDelete = False chr = "" End If End if
終わりカッコに出会うたびに、逆に n をデクリメントする。これが(2)。
で、n が 0 になっていたら、削除可能フラグをOffにした上で、終わりカッコを""にする。
たとえば、対象文字列が ( (ち~んw) )! だったとすると、
- Forループ1回目で「(」に出会うので、削除可能フラグenableToDeleteはTrue、n が1になる
削除フラグOnなので、「(」はtmpには追加されない→消されたように見える - Forループ2回目で「(」に出会うので、削除可能フラグenableToDeleteはTrue、n が2になる
削除フラグOnなので、「(」はtmpには追加されない→消されたように見える - Forループ3回目
削除可能フラグenableToDeleteがTrueなので「ち」はtmpに追加されない→消されたように見える - Forループ4回目
削除可能フラグenableToDeleteがTrueなので「~」はtmpに追加されない→消されたように見える - Forループ5回目
削除可能フラグenableToDeleteがTrueなので「ん」はtmpに追加されない→消されたように見える - Forループ6回目
削除可能フラグenableToDeleteがTrueなので「w」はtmpに追加されない→消されたように見える - Forループ7回目で「)」に出会うのが、n が1になるだけなので、削除可能フラグenableToDeleteはTrueのまま
削除可能フラグenableToDeleteがTrueなので「)」はtmpに追加されない→消されたように見える - Forループ8回目で「)」に出会い、今度は n が 0 になるので、削除可能フラグenableToDeleteがFalseになる
削除フラグOffになるが、「)」は""になるのでtmpには追加されない→消されたように見える - Forループ9回目、enableToDeleteはFalseになっているので、「!」はtmpに追加される
という流れで、カッコ内の文字列が除去され、「!」だけが残ることになる。
実行結果
この状態で実行すると、
ほれ、この通り。カッコがネストされていても望む結果が得られた。
おわりに
コレ、むきになって更新するようなことなのかね……???