がんばれ! isKanjiメソッドくん!!!!!!!!

文字列から漢字のみ抽出する

isKanjiメソッドを強引に使う

前回

akashi-keirin.hatenablog.com

作成したisKanjiメソッドの使いどころを無理矢理発明した。

準備

まず、

f:id:akashi_keirin:20171209212736j:plain

f:id:akashi_keirin:20171209212804j:plain

こんな風にシートを作っておいて、A1セルに「TextCell」、C2セルに「BaseCell」と名前を定義しておく。ちなみに、シートには「Main」と名前を付けている。

んで、コマンドボタンを押したら、C2セルから下にずらーっとA1セルの文字列から漢字だけを抽出して1列に並べる。

ついでに、D列にはそれぞれの漢字の読みも書き込んでしまおう。

もちろん、何の役に立つのかは分からない。諸君が自分で考えてくれたまえ。これは役に立つツール類の紹介ではなくて、私自身の勉強なのだ。

コーディング

とりあえず、コードを載っけてしまおう。

リスト1 標準モジュール
Public Sub pickOutAndOrderKanji()
  Dim Sh As Worksheet
  Set Sh = ThisWorkbook.Worksheets("Main")
  Dim textCell As Range
  Set textCell = Sh.Range("TextCell")
  Dim baseCell As Range
  Set baseCell = Sh.Range("BaseCell")
  baseCell.CurrentRegion.ClearContents
  Dim wholeString As String
  wholeString = textCell.Value
  If Len(wholeString) < 1 Then _
      makeUserSick ("文字がないやんけぼけー!"): Exit Sub    '……(1)'
  Dim i As Integer
  Dim n As Integer
  Dim targetChar As String
  Dim tmp As String
  n = 0
  For i = 1 To Len(wholeString)    '……(2)'
    targetChar = Mid(wholeString, i, 1)    '……(3)'
    If isKanji(targetChar) Then    '……(4)'
      With baseCell
        .Offset(n, 0).Value = targetChar    '……(5)'
        tmp = Application.GetPhonetic(targetChar)    '……(6)'
        tmp = StrConv(tmp, vbHiragana)
        .Offset(n, 1).Value = tmp
      End With
      n = n + 1    '……(7)'
    End If
  Next
End Sub

出だしの7行は、「Main」シートやら文字列の入ったセルやら基準になるセルなんかを変数にぶち込んだり、前回の書き込みを削除したり、といった処理。

んで、準備ができたら、まず(1)の

If Len(wholeString) < 1 Then _
    makeUserSick ("文字がないやんけぼけー!"): Exit Sub

で処理対象文字列を調べる。文字数が0だったらそもそも処理する意味がないので、ここで終了。ちなみに、makeUserSickメソッドというのは、このとき作成したもの。

ここからが処理の中心。(2)からのForループでは、

For i = 1 To Len(wholeString)

開始・終了条件をこのように設定。1文字目から最終文字目までをループ処理する。

んで、Forブロックの中身へ。

(3)の

targetChar = Mid(wholeString, i, 1)

では、Mid関数を使って1文字を切り出し、変数targetCharにぶち込む。

(4)の

If isKanji(targetChar) Then

では、このとき作成したisKanjiメソッドでtargetCharの中身が漢字かどうかを判定。True、すなわち漢字だったら以下の処理を行う。

まず(5)。

.Offset(n, 0).Value = targetChar

C列に文字を書き込む。isKanjiメソッドがTrueを返しているのだから、漢字が書き込まれることになる。

で、(6)からの3行。

tmp = Application.GetPhonetic(targetChar)
tmp = StrConv(tmp, vbHiragana)
.Offset(n, 1).Value = tmp

まず、

tmp = Application.GetPhonetic(targetChar)

Application.GetPhoneticメソッドを用いて、読み仮名を変数tmpにぶち込む。ただ、この時点ではtmpの中身はカタカナなので、次の

tmp = StrConv(tmp, vbHiragana)

でStrConv関数を用いて平仮名に変えてtmpにぶち込む。

最後に

.Offset(n, 1).Value = tmp

でD2セルから数えて上から n 番目(開始は0)のセルにtmpの中身を書き込む。

最後に(7)の

n = n + 1

で n をインクリメントする。

実行結果

上掲のpickOutAndOrderKanjiメソッドをコマンドボタンに登録し、ボタンクリックで実行してみる。

ちなみに、A1セルに入っている文字列は、

お前はアホか。アホちゃいまんねん、馬鹿ですねん。競輪は日本の国技です。「C#(シーシャープ)」は、完全にオブジェクト指向プログラミング(OOP)のための言語です。こう書くと何か難しい言語のような感じを受けるかも知れませんが、心配はいりません。オブジェクト指向プログラミングでは、難しいことは全部カプセル化し、プログラマはその恩恵を受けるだけなのです。

というものとする。

f:id:akashi_keirin:20171209212821j:plain

ほい。この通り、うまく行って……

ない!!!!!!!!

orz

よく見ると、11行目、もともと「C」(半角アルファベットの"C")、「#」(半角記号の"#")だったところが、漢字でもないのに出力されてしまっている。これが、このとき申し上げたisKanjiメソッドの致命的な欠陥です。

何がイカンのか

原因は非常にカンタン。

f:id:akashi_keirin:20171209212830j:plain

たとえば、1バイト文字の文字コード「DF」(半角カタカナの半濁点"゚")を調べてみる。

f:id:akashi_keirin:20171209212843j:plain

10進数に直すと「223」、つまり、正の数なんである。

このとき、漢字かどうかの判定をどうしていたか。

Asc(char) >= &H889F

こんな条件式で判定していたのである。

2バイト文字の文字コードは全て負の数だったので、こんな条件式では当然1バイト文字は全てTrueになってしまうのである。

コードの修正

そこで、isKanjiメソッドのコードを以下のように修正する。

スト2 標準モジュール
Public Function isKanji(ByVal targetCharacter As String) As Boolean
  Dim char As String
  char = targetCharacter
  If Len(char) <> 1 Then Err.Raise Number:=10001, _
                                   Description:="引数は1文字のみにしてください。"
  If Asc(char) > 0 Then isKanji = False: Exit Function    '……(*)'
  If Asc(char) >= &H889F Then
    isKanji = True
  Else
    isKanji = False
  End If
End Function

付け加えたのは(*)の

If Asc(char) > 0 Then isKanji = False: Exit Function

だけ。要するに、文字コードが正の数だったら即Falseを返してFunctionを抜けるようにしているだけ。

テスト

生まれ変わったisKanjiメソッドをテストしてみる。

イミディエイト・ウインドウで

?isKanji("F")

を始めいろいろな1バイト文字を引数にしてisKanjiメソッドを実行してみると、

f:id:akashi_keirin:20171209212852j:plain

ほれ、ちゃんと期待したとおりの結果が出ている。

おわりに

これで一件落着、めでたしめでたし……と思いきや、

f:id:akashi_keirin:20171209212901j:plain

orz

わがisKanjiメソッドの運命やいかに!(続きません)

@akashi_keirin on Twitter