色の付いた文字部分を(  )に変換するマクロ

ラボ

色の付いた文字部分を(  )に変換する


 このように部分的に色付けされたセル内の文字列を、右のようにカッコと空白に変換するプログラムです。テストの問題文を作る際に便利かと思います。
 また、If文からSelect Case文への変換の仕方を見ていきたいと思います。

使い方

 A1セルの内容をB1セルに変換して表示します。
 A1セルを2回クリックして、編集モードにして(  )にしたい部分をドラッグして文字色を変更してください。

 文字色は標準の黒以外ならなんでもOKです。
 また、数式バーからも変更できます。

プログラム解説

 方針としては、Charactersというプロパティでセル内の文字列を1つずつ取り出せるので、その文字が色付きか判断して行きます。
 さらに、カッコで括らなければいけないので、色付きに変化しかた否かをBoolean変数を用いて判断するようにしました。

Sub macro1()
    Dim i As Long, bColor As Boolean, chrC As Long
    Dim str As String
    
    str = ""
    bColor = False
    
    Debug.Print Range("A1").Characters(1, 1).Font.Color
    
    For i = 1 To Len(Range("A1"))
        chrC = Range("A1").Characters(i, 1).Font.Color
        If chrC <> 0 Then
            If bColor Then
                str = str & " "
            Else
                str = str & "("
                bColor = True
            End If
        Else
            If bColor Then
                str = str & ")" & Range("A1").Characters(i, 1).Text
                bColor = False
            Else
                str = str & Range("A1").Characters(i, 1).Text
            End If
            
        End If
    Next i
    
    If bColor Then
        str = str & ")"
    End If

    Range("B1") = str

End Sub

 For文の中で、色付き文字か?色付き文字が継続されているか?を判断しています。
 最後にForループの後に閉じ括弧が必要か判断しています。

If文をまとめた書き方

 さて、macro1 は If文が入れ子になっており、処理は異なるものの内部のIf文は2回目と同じに並んできます。
 少々冗長なので、これをAndを使って、入れ子の無いIf文に変更してみます。

Sub macro2()

    Dim i As Long, bColor As Boolean, chrC As Long
    Dim str As String
    
    str = ""
    bColor = False
    
    Debug.Print Range("A1").Characters(1, 1).Font.Color
    
    For i = 1 To Len(Range("A1"))
        chrC = Range("A1").Characters(i, 1).Font.Color
        If chrC <> 0 And bColor Then
            str = str & " "
        
        ElseIf chrC <> 0 And bColor = False Then
            str = str & "("
            bColor = True
        
        ElseIf chrC = 0 And bColor Then
            str = str & ")" & Range("A1").Characters(i, 1).Text
            bColor = False
        
        ElseIf chrC = 0 And bColor = False Then
            str = str & Range("A1").Characters(i, 1).Text
        
        End If
    Next i
    
    If bColor Then
        str = str & ")"
    End If
    
    Range("B1") = str

End Sub

 この形ですと、分岐処理がどのような条件のときに処理されるのかがわかりやすくなります。
 このままでも良いのですが、分岐要素が3つ4つと増えてきたときには、また冗長になっていく事が目に見えています。

 そこで、Select Case文を使って分岐処理と分岐後の処理を2つに分けてみましょう。

Select Case文を使った書き方

 今回はBoolean変数のようにTrue・Falseで分けられるような条件が複数ある場合を想定します。
 この場合1・0で置き換えられるので、2進法を使って再現できます。
 以下の図を見てください。

 2つの条件の場合は2の2乗で0~3の値で表現できます。
 条件が3つ4つと増えたら、3列、4列と増やし2の3乗、2の4乗と要素数が増えます。

 やり方としては、最初の条件は、2の0乗で0か1を加え、次の条件では2の1乗で0か2を加えます。
 実際のコードの方がわかりやすいと思いますので、以下をご覧ください。

Sub macro3()

    Dim i As Long, bColor As Boolean, chrC As Long
    Dim str As String
    Dim n As Long
    
    str = ""
    bColor = False
    
    Debug.Print Range("A1").Characters(1, 1).Font.Color
    
    For i = 1 To Len(Range("A1"))
        '/////////// 判定部分 ///////////
        n = 0
        '黒文字?
        If Range("A1").Characters(i, 1).Font.Color = 0 Then
            n = 1
        End If
        '色変化あり?
        If bColor Then
            n = n + 2
        End If
        
        '////////// 分岐部分 ///////////
        Select Case n
            Case 0  '黒以外 色変更なし
                str = str & "("
                bColor = True
                
            Case 1 '黒 色変更なし
                str = str & Range("A1").Characters(i, 1).Text
                
            Case 2  '黒以外 色変更あり
                str = str & " "
            
            Case 3  '黒 色変更あり
                str = str & ")" & Range("A1").Characters(i, 1).Text
                bColor = False
                
        End Select
    
    Next i
    
    If bColor Then
        str = str & ")"
    End If
        
    Range("B1") = str

End Sub

 ここでは n という整数の変数を用意して、最初の条件が True なら 1を加え、次の条件が True なら 2を加えています。
 もし3つ目の条件があれば、その時は4を加えます。

 一応3つの条件の時の値の分布をみておきましょう。

 あとは、Select Case で条件にあう処理を書けばOKです。

まとめ

 今回は If文から Select Case文に変換する方法として、2進法を用いた例を紹介しました。
 条件に関しては、True・Falseで分けられるような場合でしか使えませんが、条件がたくさんあるような場合に、条件判断部分とそれぞれの処理部分を分けて記述できるので見通しの良いコードを書くことができると思います。

 サンプルコードは、改造すればテスト問題の作成とかに役に立つかもしれませんので役立てて頂ければと思います。
 macro1,2,3は動作は全く同じです。

タイトルとURLをコピーしました