今日を乗り切るExcel研究所

Excel に働かされていませんか

セルのテキスト中の全角文字と半角文字を変換したい

Excel シートのテキストデータの全角・半角文字を変換・置換する手順と、それを自動化するマクロを検討します。

全角文字と半角文字

日本語の文字コードには歴史的経緯のためか、英数字・記号・カタカナの文字に全角と半角の2種類の文字種があって区別されます。

説明文などのテキストデータで全角・半角が統一されていないのは見苦しいだけでなく、文書の信頼性が問われます。

またデータとしても、システムによっては両者を区別しなかったり、どちらかに自動変換(正規化)されることもあるのですが、基本的に、全角と半角が混在していると何かとトラブルの元になりやすいです。

半角カタカナは最近使われなくはなってきていますが、かつては印字スペースの節約のためにも使われ、今でもレシートや通帳の印字でよく使われています。

Excelで半角カタカナを使う理由は無いはずなのですが、古いシステムとの連携データ作成などでまだ需要は残っているようです。

手作業で全角・半角の文字置換をするには

Word には全角・半角を置換するコマンドがあるようですが、Excelでは提供されていません。

その代り、文字種を変換する関数が用意されていて、数式で使用できます。

  • ASC() 全角→半角変換
  • JIS() 半角→全角変換

ASC()/JIS()は全ての英数字・記号・カタカナを変換し、それ以外の文字には影響しませんので、文章テキストをそのまま処理できます。

ただ、たとえばテキストデータ中にある英数字を半角に統一するために ASC() を使うと、文章中のカタカナまで半角カタカナになってしまいます。説明文のような自然文が主体のテキストデータでは、もう少し細やかな制御が欲しいところです。

また、関数を使った変換には作業用のセルをいったん用意し、数式データをやり取りすることになります。作業的に難しい事ではないのですが、ちょっと億劫です。

ここでは、少し無理やりですが、キー操作だけでASC()/JIS()関数処理を行う手順を考えます。

ある列にあるテキストを半角に変換したいとします。

【手順例】

  1. 対象データ範囲を選択します
    f:id:shego:20170516230921p:plain:w235
  2. 作業用のセル(列)を挿入します
    • キー操作: Ctrl + Shift + +Entry
      f:id:shego:20170516231010p:plain:w235
  3. 作業用セルに文字種を変換する数式を入力します
    • キー操作(半角): =asc(Ctrl + Enter
    • キー操作(全角): =jis(Ctrl + Enter
      f:id:shego:20170516231907p:plain
  4. 変換文字をコピーし、元データのセルに値として貼り付けます

    • キー操作: Ctrl + CShift + Ctrl + Alt + VVEnter
      f:id:shego:20170516231125p:plain:w235
  5. 作業用セル(列)を選択し削除します

    • キー操作: Shift + Ctrl + -
      f:id:shego:20170516231156p:plain:w235

慣れるにはちょっと無理があります。素直に作業用の別シートでコピー&ペーストしながら加工したほうが早そうです。

 



全角・半角文字を変換するマクロ

セルのテキストで全角・半角を変換するマクロを作成してみました。

変換したいテキストのセルを選択して、本マクロを実行するとセル内のテキストの文字種が変換されます。

変換対象としたい文字種をある程度選べるように、変換パターンによって複数のマクロに分けました。

たとえば、「文字種変換_半角→全角」マクロはカタカナ、英数字、記号等をすべて半角文字にしますが、「文字種変換_全角英数→半角英数」マクロは英数字のみ半角に変換します。

適宜必要なマクロを選んで実行してください。

使用上の注意点として、本マクロは選択範囲のセルの全ての文字を変換処理しますが、元に戻すことができません。

大切なデータを安全に扱うためには、いったん別シートにコピーしてから処理するか、ファイルをバックアップしておくなど、慎重に操作されることをお勧めします。

Option Explicit

Sub 文字種変換_全角→半角()
    replaceRangeText Selection.Cells, proc:="strConvNarrow"
End Sub

Sub 文字種変換_半角→全角()
    replaceRangeText Selection.Cells, proc:="strConvWide"
End Sub

Sub 文字種変換_全角英数→半角英数()
    replaceRangeText Selection.Cells, proc:="replaceRegex", target:="[0-9A-Za-z_]+", func:="strConvNarrow"
End Sub

Sub 文字種変換_半角英数→全角英数()
    replaceRangeText Selection.Cells, proc:="replaceRegex", target:="\w+", func:="strConvWide"
End Sub

Sub 文字種変換_全角カナ→半角カナ()
    replaceRangeText Selection.Cells, proc:="replaceRegex", target:="[。「」ーァ-ヶ]+", func:="strConvNarrow"
End Sub

Sub 文字種変換_半角カナ→全角カナ()
    replaceRangeText Selection.Cells, proc:="replaceRegex", target:="[。「-゚]+", func:="strConvWide"
End Sub

Sub 文字種変換_全角記号→半角記号()
    replaceRangeText Selection.Cells, proc:="replaceRegex", _
        target:="[\uFF01-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF40\uFF5B-\uFF5E\u201D\u2019\uFFE5\u2018]+", _
        func:="strConvNarrow"
End Sub

Sub 文字種変換_半角記号→全角記号()
    replaceRangeText Selection.Cells, proc:="replaceRegex", _
        target:="[\u0021-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]+", _
        func:="strConvWide"
End Sub

Sub replaceRangeText(rng As Range, proc As String, Optional target As Variant, Optional func As Variant)
    Application.ScreenUpdating = False
    On Error GoTo finish
    
    Dim txtArea As Range
    Dim txtCol As Range
    Dim text As String
    
    If WorksheetFunction.CountA(rng) = 0 Then
        Beep
    ElseIf rng.Cells.Count = 1 Then
        If VarType(rng.Value) = vbString Then
            rng.Value = Application.Run(proc, rng.Value, target, func)
        End If
    Else
        For Each txtArea In rng.SpecialCells(xlCellTypeConstants, xlTextValues).Areas
            For Each txtCol In txtArea.Columns
                text = joinColumnValues(txtCol, vbNullChar)
                text = Application.Run(proc, text, target, func)
                txtCol.Value = splitTranspose(text, vbNullChar)
            Next
        Next
        rng.Select
    End If
finish:
    If Err.Number <> 0 Then MsgBox Err.Description
    Application.ScreenUpdating = True
End Sub

Private Function joinColumnValues(col As Range, delim As String) As String
    Dim vals As Variant
    Dim arr() As String
    Dim i As Integer
    
    If col.Cells.Count = 1 Then
        joinColumnValues = col.Value
    Else
        vals = col.Value
        ReDim arr(1 To UBound(vals, 1))
        For i = 1 To UBound(arr)
            arr(i) = vals(i, 1)
        Next
        joinColumnValues = Join(arr, delim)
    End If
End Function

Private Function splitTranspose(text As String, delim As String) As Variant
    Dim vals As Variant
    Dim arr() As String
    Dim i As Integer
    
    arr = Split(text, delim)
    ReDim vals(1 To UBound(arr) + 1, 1 To 1)
    For i = 0 To UBound(arr)
        vals(i + 1, 1) = arr(i)
    Next
    splitTranspose = vals
End Function
    
Private Function strConvNarrow(text As String) As String
    strConvNarrow = StrConv(text, vbNarrow)
End Function

Private Function strConvWide(text As String) As String
    strConvWide = StrConv(text, vbWide)
End Function

Private Function replaceRegex(text As String, targetPattern As String, replaceFunc As String) As String
    Dim regex As Object
    Dim matches As Object
    
    Set regex = CreateObject("VBScript.RegExp")
    regex.Global = True
    regex.pattern = "(" & targetPattern & "|^)(.|\r|\n)*?(?=" & targetPattern & "|$)"
    regex.MultiLine = False
    
    Set matches = regex.Execute(text)
    If matches.Count = 0 Then
        replaceRegex = text
        Exit Function
    End If
    
    Dim fragment As String
    Dim match As String
    Dim arr() As String
    ReDim arr(matches.Count - 1)
    
    Dim i As Integer
    For i = 0 To matches.Count - 1
        fragment = matches(i).Value
        match = matches(i).SubMatches(0)
        arr(i) = Replace(fragment, match, Application.Run(replaceFunc, match), 1, 1)
    Next
    replaceRegex = Join(arr, "")
End Function

【使い方】

  1. 上記 VBA プログラムを標準モジュールにコピー&ペーストします
  2. 文字種置換したいセル範囲を選択します
  3. 希望する文字種置換を行うマクロを実行します
  4. セル内容のテキストが対象となる文字が置換されています

 【注意】 本マクロによる処理結果は、「元に戻す」(Undo)ことが出来ません。

まとめ

Excel のテキスト置換コマンドに全角・半角の文字種を変換する機能がなく、ASC()/JIS()関数を利用した手順を考えましたがテキスト置換の代わりとしては手順につらいところがあります。

一方、マクロでは、セル範囲指定による一括置換ができるうえ、ASC()/JIS()関数よりきめの細かい文字種処理を提供も可能になりました。

本記事の内容は Windows 10 の Excel 2013 で確認しました。