ひらがな・カタカナ相互変換プログラム – Evaluateメソッドの使い方

Kana Converter – How to use Evaluate Method


 

はじめに

・動作は無保証です。
・Excel 2016 + Windows 10、Excel 2010 + Windows 7で動作確認しています。
・ファイルはここからダウンロードしてください。

会社で、取扱う取引先名(会社名)のカタカナのフリガナの頭文字をひらがなに変換するプログラムを作成しました。

イセタン           => い
ゲンキショウジ       => け
トウキュウデンテツ     => と
フジツウ           => ふ
パナソニック         => は
ロックオン          => ろ
ヴェネツィアセイサクジョ => へ

濁音(例えばガ行)の頭文字は清音(カ行)の頭文字に、半濁音(パ行)の頭文字は清音(ハ行)の頭文字に変換する、というしばり(ルール)もありました。

しかし、ウェブで公開するにあたって、ひらがなをカタカナに変換するプログラムを追加し、「ひらがな・カタカナ相互変換プログラム」としました。

いせたん           => イ
げんきしょうじ       => ケ
とうきゅうでんてつ     => ト
ふじつう           => フ
ぱなそにっく         => ハ
ろっくおん          => ロ
ヴぇねつぃあせいさくじょ => へ

 

ワークシートの説明

上の図をごらんください。「C2」セルに会社名などのカタカナのフリガナ(ひらがなのふりがな)を入力してEnterキーを押すと、「C3」セルにひらがな(カタカナ)の頭文字1文字を表示します。

このプログラムで特に説明したいのは、Evaluateメソッドの使い方と「文字コードの整理」の方法です。以下、順に説明します。

ですが、1点だけ、ワークシートについて説明したい部分があります。

「D2」セルに関数が設定されているのですが、その関数がこちら。

ちなみに「D2」セルと「D3」セルの文字は非表示に設定してあります。

=IF(C2="","",IF(AND(CODE(C2)>=9505,CODE(C2)<=9588),CODE(C2)-256,IF(AND(CODE(C2)>=9249,CODE(C2)<=9331),CODE(C2)+256,"")))

このセルに関数を設定しているのは、ここで用いられているCODE関数がVBAのWorksheetFunctionプロパティで使えないワークシート関数だからです。CODE関数は引数に文字を指定すると、その文字コードを返す関数ですが、CODEWorksheetFunctionオブジェクトのメソッドではないのです。ですので、モジュールに普通に記述するとエラーが発生します。普通とは次のような例をいいます。

Dim myCode As Long
If Range(C2).Value = "" Then
    myCode = ""
ElseIf WorksheetFunction.Code(Range(C2).Value) >= 9505, And _
       WorksheetFunction.Code(Range(C2).Value) <= 9588 Then
    myCode = WorksheetFunction.Code(Range(C2)) - 256
ElseIf WorksheetFunction.Code(Range(C2).Value) >= 9249, And _
       WorksheetFunction.Code(Range(C2).Value) <= 9331 Then
    myCode = WorksheetFunction.Code(Range(C2)) + 256
Enf If

この命令文はエラーになります。上に書いたとおり、CodeWorksheetFunctionのメソッドではないから実行できないのです。だから、セルに関数を設定し、計算をさせています。

これに対して、たとえば、Replace関数はワークシート関数であり、Worksheetfunctionのメソッドでもあるので、次の例は実行できます。

Dim myString As String
myString = Worksheetfunction.Replace(Range(C2), vbLf, vbCrLf)

このように使いづらいCODE関数ですが、どうしてもプログラム上で使いたい場合はEvaluateメソッドとともに使用します。

 

このプログラムのソースコード

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    Switch = True

    If Not Intersect(Target, Cells(2, 3)) Is Nothing Then
        If Len(Cells(2, 3).Value) = 0 Then
            Range(Cells(3, 3), Cells(3, 4)).Value = ""
        Else
            Dim myCode As Long
            myCode = Evaluate("CODE(C2)")   '[CODE(C2)]
            Select Case myCode
                'ひらがな => カタカナ
                Case 9249 To 9258
                    Call S_NormalConverter
                Case 9259 To 9282
                    Call S_DivideByTwo_1
                Case 9283
                    Call S_NormalConverter
                Case 9284 To 9289
                    Call S_DivideByTwo_2
                Case 9290 To 9294
                    Call S_NormalConverter
                Case 9295 To 9309
                    Call S_DivideByThree_1
                Case 9310 To 9331
                    Call S_NormalConverter
                'カタカナ => ひらがな
                Case 9505 To 9514
                    Call S_NormalConverter
                Case 9515 To 9538
                    Call S_DivideByTwo_1
                Case 9539
                    Call S_NormalConverter
                Case 9540 To 9545
                    Call S_DivideByTwo_2
                Case 9546 To 9550
                    Call S_NormalConverter
                Case 9551 To 9565
                    Call S_DivideByThree_2
                Case 9566 To 9587
                    Call S_NormalConverter
                Case 9588
                    Call S_VConverter
                Case Else
                    MsgBox "ひらがな、またはカタカナを" & _
                           "入力してください。", vbExclamation
                    Range(Cells(3, 3), Cells(3, 4)).Value = ""
            End Select
        End If
    End If

    Switch = False
End Sub

Private Property Let Switch(ByVal Flag As Boolean)
    With Application
        .ScreenUpdating = Not Flag
        .EnableEvents = Not Flag
    End With
End Property

Private Sub S_NormalConverter()
    Cells(3, 4).Value = ""
    Cells(3, 3).Value = Evaluate("CHAR(D2)")            '[CHAR(D2)]
End Sub

Private Sub S_DivideByTwo_1()
    If Evaluate("MOD(D2, 2)") = 0 Then                  '[MOD(D2, 2)]
        Cells(3, 4).Value = Cells(2, 4).Value - 1
        Cells(3, 3).Value = Evaluate("CHAR(D3)")        '[CHAR(D3)]
    Else
        Cells(3, 4).Value = ""
        Cells(3, 3).Value = Evaluate("CHAR(D2)")        '[CHAR(D2)]
    End If
End Sub

Private Sub S_DivideByTwo_2()
    If Evaluate("MOD(D2, 2)") = 1 Then                  '[MOD(D2, 2)]
        Cells(3, 4).Value = Cells(2, 4).Value - 1
        Cells(3, 3).Value = Evaluate("CHAR(D3)")        '[CHAR(D3)]
    Else
        Cells(3, 4).Value = ""
        Cells(3, 3).Value = Evaluate("CHAR(D2)")        '[CHAR(C3)]
    End If
End Sub

Private Sub S_DivideByThree_1()
    Select Case Evaluate("MOD(D2, 3)")                  '[MOD(D2, 3)]
        Case 0
            Cells(3, 4).Value = Cells(2, 4).Value - 1
            Cells(3, 3).Value = Evaluate("CHAR(D3)")    '[CHAR(D3)]
        Case 1
            Cells(3, 4).Value = Cells(2, 4).Value - 2
            Cells(3, 3).Value = Evaluate("CHAR(D3)")    '[CHAR(D3)]
        Case 2
            Cells(3, 4).Value = ""
            Cells(3, 3).Value = Evaluate("CHAR(D2)")    '[CHAR(D2)]
    End Select
End Sub

Private Sub S_DivideByThree_2()
    Select Case Evaluate("MOD(D2, 3)")                  '[MOD(D2, 3)]
        Case 0
            Cells(3, 4).Value = Cells(2, 4).Value - 2
            Cells(3, 3).Value = Evaluate("CHAR(D3)")    '[CHAR(D3)]
        Case 1
            Cells(3, 4).Value = ""
            Cells(3, 3).Value = Evaluate("CHAR(D2)")    '[CHAR(D2)]
        Case 2
            Cells(3, 4).Value = Cells(2, 4).Value - 1
            Cells(3, 3).Value = Evaluate("CHAR(D3)")    '[CHAR(D3)]
    End Select
End Sub

Sub S_VConverter()
    If Len(Cells(2, 3).Value) = 1 Then
        Cells(3, 3).Value = "ふ"
    Else
        Select Case Left(Cells(2, 3).Value, 2)
            Case "ヴァ", "ヴぁ"
                Cells(3, 3).Value = "は"
            Case "ヴィ", "ヴぃ"
                Cells(3, 3).Value = "ひ"
            Case "ヴェ", "ヴぇ"
                Cells(3, 3).Value = "へ"
            Case "ヴォ", "ヴぉ"
                Cells(3, 3).Value = "ほ"
            Case Else
                Cells(3, 3).Value = "ふ"
        End Select
    End If
End Sub

 

Worksheet_Changeプロシージャとは

ワークシートのセルのいずれかの値が変更されたとき起動するイベントプロシージャです。「ひらがな・カタカナ相互変換プログラム」シートのシートモジュールに書いています。このプロシージャでは、

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Cells(2, 3)) Is Nothing Then
    ~~~~~~~~~~~~
    End If
End Sub

として、プロシージャが起動する原因となるセルを「C2」セルに限定しています。

Intersectメソッドは、

Intersect(Rangeオブジェクト1、Rangeオブジェクト2)

という書式で、Rangeオブジェクト1とRangeオブジェクト2で共通するRangeオブジェクトを返します。

共通するRangeオブジェクトがない場合は、Nothingを返します。

「C2」セルとの共通範囲がNothingでないかどうかを判定するには、

If Not Intersect(Target, Cells(2, 3)) Is Nothing

という書式にします。

共通範囲が「C2」セルだったら、すなわち、プロシージャの適用範囲が「C2」セルのみだったら「~~~~~~~~~~~~」に記述された命令を実行する、ということになります。

Worksheet_Changeプロシージャの使い方は、この使い方が多いです。あるセルの値が変更したら何らかの命令を実行したい、ただ、直接そのような操作を実現するプロシージャはない、したがって、Worksheet_Changeプロシージャでセル範囲を限定して命令を実行する、というパターンが多いと思います。

 

「Switch」プロパティプロシージャとは

Switch = True
~~~~~~~~~~~~
Switch = False

Worksheet_Changeプロシージャの中で、プロシージャ名の変数SwitchTrueFalseを代入して使います。

Private Property Let Switch(ByVal Flag As Boolean)
    With Application
        .ScreenUpdating = Not Flag
        .EnableEvents = Not Flag
    End With
End Property

標準モジュールやシートモジュール(オブジェクトモジュールの1つ)で使われるプロパティプロシージャは、Property Letプロシージャが多いと思います。Property Letプロシージャはプロパティに値を設定します。

 

Evaluateメソッドとは

Evaluateメソッドとは、このプロシージャでいえば、WorkshetFunctionオブジェクトのメソッドではないワークシート関数を実行するためのメソッドです。このプロシージャでは、CODE関数や、CHAR関数、MOD関数に使用しています。

myCode = Evaluate("CODE(C2)")               '[CODE(C2)]
Cells(3, 3).Value = Evaluate("CHAR(D2)")    '[CHAR(D2)]
If Evaluate("MOD(D2, 2)") = 0 Then          '[MOD(D2, 2)]

Evaluateメソッドの中は、ダブルクォーテーションで囲み、その中はセルに記入するのと同じ書き方をする必要があります。本当はもっと複雑な使い方ができるのですが、まずはこのような書き方を覚えましょう。

上の例の右側にあるコメントでは、Evaluateメソッドの省略形を表示しています。[~~~]と、大かっこ(スクエアブランケット)で関数を囲むと、Evaluate("~~~")と書いたのと同じ意味になります。

しかし、この大かっこを使った省略形は、非常にわかりづらいので、あまり使わないほうがいいでしょう。鶏が先か卵が先かということにもなりますが、この省略形はあまり使われないので、わかりづらく、他人様に伝えづらいのが非常に大きな欠点です。

 

文字コードの整理

ひらがなとカタカナを相互変換するには、文字コードを用いて、文字を数値で表すことが必要です。

下の図を見てください。

かなと文字コードの対応を「文字コード表」シートに表したものですが、濁音・半濁音は清音に変換するというルールに基づいて、薄いみどりや青でその対応を表しています。

頭文字が「が」で文字コードが「9260」であるものは、濁音は清音に変換するので、文字コード「9259」である頭文字「か」に変更します。

1つ目の性質

ひらがなとカタカナの文字コードにはある規則性があります。

ひらがなの「あ」の文字コードは「9250」、カタカナの「ア」の文字コードは「9506」。その差をとると「256」になります。

その他の文字についても、ひらがなとカタカナの文字コードの差はすべて「256」になります。

この性質を用いてひらがなとカタカナの変換をおこないます。

2つ目の性質

清音と濁音、半濁音のあいだにもある規則性があります。

「文字コード表」シートに色付けして表したように、清音と濁音、半濁音は文字コードが隣り合っています。

「か」の文字コードは「9259」、「が」の文字コードは「9260」ですので、文字コードを2で割って余りが「1」なのが清音、余りが「0」なのが濁音で、濁音のほうが必ず大きな文字コードになっています。

したがって、文字コードの数字を2で割って余りが「0」、つまり余りがないものの文字コードの数字から「1」を引いてやればすべて清音に変換できます。

これは、逆のパターンで、余りが「0」なのが清音、余りが「1」なのが濁音というパターンもあります。

半濁音の場合

半濁音があるのは「は行」「ば行」「ぱ行」のひらがなとカタカナに限られます。

ここでは、清音・濁音・半濁音の3つがあるので、文字コードを3で割ってやります。

「は」は文字コードが「9295」、「ば」は文字コードが「9296」、「ぱ」は文字コードが「9297」ですので、余りが「1」であるのが清音、余りが「2」であるのが濁音、余りが「0」であるのが半濁音ということになります。

したがって、3で割って「割り切れる」ものは文字コードの数字から「2」を引いて、3で割って「2余る」ものは文字コードの数字から「1」を引くと、すべて清音に変換できます。

これには、もう1つ、3で割って「2余る」ものが清音になるパターンもあります。

例外について

「ヴ」については、文字列を「ヴァ」「ヴィ」「ヴ」「ヴェ」「ヴォ」に分類して、それぞれの場合に、「は」「ひ」「ふ」「へ」「ほ」に変換します。

プログラムに反映

Dim myCode As Long
myCode = Evaluate("CODE(C2)")   '[CODE(C2)]
Select Case myCode
    'ひらがな => カタカナ
    Case 9249 To 9258
        Call S_NormalConverter
    Case 9259 To 9282
        Call S_DivideByTwo_1
    Case 9283
        Call S_NormalConverter
    Case 9284 To 9289
        Call S_DivideByTwo_2
    Case 9290 To 9294
        Call S_NormalConverter
    Case 9295 To 9309
        Call S_DivideByThree_1
    Case 9310 To 9331
        Call S_NormalConverter
    'カタカナ => ひらがな
    Case 9505 To 9514
        Call S_NormalConverter
    Case 9515 To 9538
        Call S_DivideByTwo_1
    Case 9539
        Call S_NormalConverter
    Case 9540 To 9545
        Call S_DivideByTwo_2
    Case 9546 To 9550
        Call S_NormalConverter
    Case 9551 To 9565
        Call S_DivideByThree_2
    Case 9566 To 9587
        Call S_NormalConverter
    Case 9588
        Call S_VConverter
    Case Else
        MsgBox "ひらがな、またはカタカナを" & _
               "入力してください。", vbExclamation
        Range(Cells(3, 3), Cells(3, 4)).Value = ""
End Select

上述の性質に基づいて、文字コードを分類し、上のソースコードに反映しました。

S_NormalConverterは通常の変換をおこなうサブプロシージャです。

S_DivideByTwo_1S_DivideByTwo_2は文字コードを2で割るサブプロシージャです。

S_DivideByThree_1S_DivideByThree_2は文字コードを3で割るサブプロシージャです。

 

文字コードの変換をおこなうサブプロシージャ

通常の変換をおこなうサブプロシージャ

Private Sub S_NormalConverter()
    Cells(3, 4).Value = ""
    Cells(3, 3).Value = Evaluate("CHAR(D2)")            '[CHAR(D2)]
End Sub

入力された文字を元に、「ひらがな・カタカナ相互変換プログラム」シート上の「D2」セルに設定されている関数に基づいて、文字コードの変換は自動的におこなわれています。

その関数の答えに基づいて、Cells(3, 3).Value = Evaluate("CHAR(D2)")という命令文で「C3」セルに変換後の文字を表示します。

CHAR関数は、文字コードを基準に文字自体を表示する関数です。

文字コードを2で割るサブプロシージャ

Private Sub S_DivideByTwo_1()
    If Evaluate("MOD(D2, 2)") = 0 Then                  '[MOD(D2, 2)]
        Cells(3, 4).Value = Cells(2, 4).Value - 1
        Cells(3, 3).Value = Evaluate("CHAR(D3)")        '[CHAR(D3)]
    Else
        Cells(3, 4).Value = ""
        Cells(3, 3).Value = Evaluate("CHAR(D2)")        '[CHAR(D2)]
    End If
End Sub

Private Sub S_DivideByTwo_2()
    If Evaluate("MOD(D2, 2)") = 1 Then                  '[MOD(D2, 2)]
        Cells(3, 4).Value = Cells(2, 4).Value - 1
        Cells(3, 3).Value = Evaluate("CHAR(D3)")        '[CHAR(D3)]
    Else
        Cells(3, 4).Value = ""
        Cells(3, 3).Value = Evaluate("CHAR(D2)")        '[CHAR(C3)]
    End If
End Sub

「D2」セルに表示される文字コードを2で割って、清音の場合は「D2」セルの文字コードをそのままCHAR関数に代入、濁音の場合は「D2」セルの文字コードから1を引いたものを「D3」セルに代入し、Cells(3, 3).Value = Evaluate("CHAR(D3)")という命令文で「C3」セルに変換後の文字を表示します。

MOD関数は、割り算をし、余りを求めます。

MOD(D2, 2)は、「D2」セルに表示される文字コードを2で割って余りを求めます。

文字コードを3で割るサブプロシージャ

Private Sub S_DivideByThree_1()
    Select Case Evaluate("MOD(D2, 3)")                  '[MOD(D2, 3)]
        Case 0
            Cells(3, 4).Value = Cells(2, 4).Value - 1
            Cells(3, 3).Value = Evaluate("CHAR(D3)")    '[CHAR(D3)]
        Case 1
            Cells(3, 4).Value = Cells(2, 4).Value - 2
            Cells(3, 3).Value = Evaluate("CHAR(D3)")    '[CHAR(D3)]
        Case 2
            Cells(3, 4).Value = ""
            Cells(3, 3).Value = Evaluate("CHAR(D2)")    '[CHAR(D2)]
    End Select
End Sub

Private Sub S_DivideByThree_2()
    Select Case Evaluate("MOD(D2, 3)")                  '[MOD(D2, 3)]
        Case 0
            Cells(3, 4).Value = Cells(2, 4).Value - 2
            Cells(3, 3).Value = Evaluate("CHAR(D3)")    '[CHAR(D3)]
        Case 1
            Cells(3, 4).Value = ""
            Cells(3, 3).Value = Evaluate("CHAR(D2)")    '[CHAR(D2)]
        Case 2
            Cells(3, 4).Value = Cells(2, 4).Value - 1
            Cells(3, 3).Value = Evaluate("CHAR(D3)")    '[CHAR(D3)]
    End Select
End Sub

「D2」セルに表示される文字コードを3で割って、余りが「2」の場合に清音になるケースでは、余りが「0」の場合に濁音になり、余りが「1」の場合に半濁音になります。

「D2」セルに表示される文字コードを3で割って、余りが「1」の場合に清音になるケースでは、余りが「2」の場合に濁音になり、余りが「0」の場合に半濁音になります。

濁音・半濁音の場合は、「D2」セルの文字コードからそれぞれ、1、2、を引いた文字コードを「D3」セルに代入し、Cells(3, 3).Value = Evaluate("CHAR(D3)")という命令文で「C3」セルに変換後の文字を表示します。

例外の場合のサブプロシージャ

Sub S_VConverter()
    If Len(Cells(2, 3).Value) = 1 Then
        Cells(3, 3).Value = "ふ"
    Else
        Select Case Left(Cells(2, 3).Value, 2)
            Case "ヴァ", "ヴぁ"
                Cells(3, 3).Value = "は"
            Case "ヴィ", "ヴぃ"
                Cells(3, 3).Value = "ひ"
            Case "ヴェ", "ヴぇ"
                Cells(3, 3).Value = "へ"
            Case "ヴォ", "ヴぉ"
                Cells(3, 3).Value = "ほ"
            Case Else
                Cells(3, 3).Value = "ふ"
        End Select
    End If
End Sub

「C2」セルの文字列の頭文字が「ヴ」の場合は、文字列が「ヴ」1文字の場合は「ふ」に、「ヴァ(ヴぁ)」「ヴィ(ヴぃ)」「ヴェ(ヴぇ)」「ヴォ(ヴぉ)」の場合は、それぞれ「は」「ひ」「へ」「ほ」に変換します。それ以外の場合は「ふ」に変換します。

 

「MOD」には実は別の使い方があります

ここで今まで使ってきたMODはワークシート関数ですが、実はVBAにはMOD演算子があります。

Evaluate("MOD(D2, 2)") => Cells(2, 4).Value Mod 2
Evaluate("MOD(D3, 2)") => Cells(3, 4).Value Mod 2

Cells(3, 4).Value / 2の「/」の代わりに「Mod」を使えば、余りが返ってきます。

ここでは説明の都合上、すべてEvaluate関数で説明するため、Mod演算子は一番最後に説明しました。

 

おわりに

今回は非常にニッチなニーズに応えたマクロなのですが、Evaluateメソッドの使い方、文字コード表の整理の仕方はおもしろいなと思い、記事にしてみました。

コメントを残す