全角の数字と記号を半角に置換するときの注意|Excel VBA |
セルに入力された特定の文字列を置換する方法には、RangeオブジェクトのReplaceメソッドやReplace関数があります。
前者のReplaceメソッドは、単一のセルだけでなくセル範囲に対して置換できる点が便利です。
たとえば、セルA1:A100の中に含まれる文字列「モーグ」を「moug」に置換するとき、Replace関数ではSample1のようにループを使ってセル1つ1つに対して置換を行うことになるのに対し、
Sub Sample1()
Dim c As Range
For Each c In Range("A1:A100")
c.Value = Replace(c.Value, "モーグ", "moug")
Next c
End Sub
Replaceメソッドを使うとSample2のように1行で簡単に記述できます。
また、対象のセル範囲が広くなると、速度もReplaceメソッドの方が有利になります。
Sub Sample2()
Range("A1:A100").Replace "モーグ", "moug", xlPart
End Sub
ただし、Replaceメソッドでは思うように置換できないケースがあります。
試してみましょう。次のサンプルは全角の数字と記号を半角に置換するマクロです。
Sub Sample3()
Dim c As Range
Dim i As Long
For Each c In Range("A1:A6")
With c
.Replace "−", "-", xlPart
.Replace "/", "/", xlPart
.Replace ":", ":", xlPart
For i = 0 To 9
.Replace StrConv(CStr(i), vbWide), CStr(i)
Next i
End With
Next c
End Sub
A列に表示形式「文字列」で次のようなデータが入力されているとき、Sample3を実行すると次のようになります。
セルA6はデータ内に含まれる数値と記号だけが半角に置換され、表示形式も変更ありません。
しかし、セルA1〜A5のように置換後のデータが日付や時刻、数値とみなされる場合には、設定されていた書式が解除され、勝手に形式を変えられます。
元のデータが、住所の番地やページ番号、比などを表すものだとしたら、まったく意図しないデータになってしまうことになります。
Replace関数はこのようなデータでも問題なく置換できますが、前述のとおりRangeオブジェクト1つ1つに対して置換処理をするので、対象セルが多い場合は処理が重くなります。
そんなときは、ワークシート関数を使ってみましょう。
次のサンプルは、ワークシート関数のSubstitute関数で置換するマクロです。
Sub Sample4()
Dim i As Long
With Range("A1:A6")
.Value = Application.Substitute(.Cells, "−", "-")
.Value = Application.Substitute(.Cells, "/", "/")
.Value = Application.Substitute(.Cells, ":", ":")
For i = 0 To 9
.Value = _
Application.Substitute(.Cells, StrConv(CStr(i), vbWide), CStr(i))
Next i
End With
End Sub
実行すると、次のようになります。
セル範囲に対して実行できるので、処理速度もReplaceメソッドとほぼ同じです。
ワークシート関数には、全角文字を半角にするAsc関数もあります。
Asc関数を使うと、置換前後の値を記述する必要がありません。
上記のデータの場合、Sample4のSubstitute関数と同じ結果が得られます。
Sub Sample5()
Range("A1:A6").Value = Application.Asc(Range("A1:A6"))
End Sub
ただし、Asc関数は全角カタカナを半角カタカナに置換するため、電話番号や郵便番号にはいいですが、住所の置換には不向きでしょう。
ケースに応じて使い分けてください。
ワークシート関数のSubstitute関数とAsc関数は、
(1) Application.ワークシート関数
とすると、セル範囲に対して置換できるのに対し、
(2) WorksheetFunction.ワークシート関数
のようにすると、単一セルに対してのみ置換可能になります。
本記事のように複数のセルに対して処理を行うとき、(2)の方法で記述すると「型が一致しません」の実行時エラーになるので注意してください。