167_住所データを都道府県・市区町村に分割・結合する方法

VBA
スポンサーリンク
スポンサーリンク

この記事でできること

VBAで住所データを「都道府県」「市区町村」「番地以降」に自動分割できるようになる。逆に、分割された住所を1つに結合する方法も扱う。

対象:住所の分割・結合を手作業でやっている人、VBA初心者。

所要時間:コピペ → 実行まで5分。

どんな場面で使う?

住所データの分割・結合は、事務系の業務で驚くほど頻繁に発生する作業です。以下のようなケースに心当たりがあれば、このマクロがそのまま使えます。

  • 顧客リストの地域別集計 — 全国の顧客データから都道府県ごとの件数を集計したい。住所が1列にまとまっていると、ピボットテーブルで集計する前に都道府県を分離する必要がある
  • DM・宛名印刷の前処理 — 宛名ラベルのフォーマットが「都道府県」「市区町村」「番地」の3段に分かれている場合、1列の住所データを3分割しなければならない
  • 拠点ごとの売上分析 — 売上データに紐づいた住所から都道府県を抽出し、エリア別の売上を可視化する。営業拠点の見直しや地域戦略の検討に使う
  • 住所データの名寄せ・重複チェック — 表記ゆれのある住所データを統一するために、まず都道府県と市区町村に分割してから比較する。「東京都新宿区」と「東京都 新宿区」を同一とみなすための前処理になる
  • 郵便番号マスタとの突合 — 住所から都道府県・市区町村を分割し、郵便番号マスタと照合して郵便番号を自動付与する。引越し通知や住所変更の処理で使う

件数が少なければ手作業でもなんとかなるけれど、100件を超えたあたりからミスが急増する。マクロなら数千件でも数秒で終わるし、判定ロジックが毎回同じなのでブレがない。

導入

顧客リストや送付先一覧で「東京都千代田区丸の内1-1-1」のような住所を都道府県だけ抜き出したい場面、実務で意外と多い。自分も以前、500件の住所データを都道府県と市区町村に手で分けていた。目がチカチカして、正直もう二度とやりたくないと思った(共感)。

都道府県は47パターンしかないから、VBAで先頭の数文字をチェックするだけで自動分割できる。これを覚えてからは、住所データの整形が10分で終わるようになった(実感)。

この記事で、同じ作業に苦しんでいる人が一気に楽になればうれしい(動機)。

住所内の全角数字・半角数字のバラつきが気になる場合は、先に 全角⇔半角を一括変換してデータを統一する方法(/041)で統一してから処理すると精度が上がる。

完成イメージ(Before / After)

Before(実行前)

A
1 住所
2 東京都千代田区丸の内1-1-1
3 大阪府大阪市北区梅田2-2-2
4 北海道札幌市中央区北1条西2丁目
5 神奈川県横浜市中区山下町1番地

After(実行後)

A B C D
1 住所 都道府県 市区町村 番地以降
2 東京都千代田区丸の内1-1-1 東京都 千代田区 丸の内1-1-1
3 大阪府大阪市北区梅田2-2-2 大阪府 大阪市北区 梅田2-2-2
4 北海道札幌市中央区北1条西2丁目 北海道 札幌市中央区 北1条西2丁目
5 神奈川県横浜市中区山下町1番地 神奈川県 横浜市中区 山下町1番地

B・C・D列に分割された住所が出力される。

手順(コピペ → 実行まで5分)

実行前の注意:既存のデータが入っているExcelファイルで実行する場合は、先にファイルをコピーしてバックアップを取ること。B〜D列にデータがあると上書きされる。

ステップ1:Excelファイルをマクロ有効ブック(.xlsm)で保存する

  1. Excelを開く(新規でも既存でもOK)
  2. 「ファイル」→「名前を付けて保存」
  3. ファイルの種類を 「Excel マクロ有効ブック (*.xlsm)」 に変更して保存

.xlsx のままだとマクロが保存されない。必ず .xlsm にする。

ステップ2:VBE(コードを書く画面)を開く

  1. Alt + F11 キーを押す
  2. VBE(Visual Basic Editor)が開く

ステップ3:標準モジュールを挿入する

  1. VBEのメニュー「挿入」→「標準モジュール」をクリック
  2. 右側に白い画面(コードウィンドウ)が表示される

ステップ4:コードを貼り付けて実行する

下の「コード(基本版)」をコピーして、コードウィンドウに貼り付ける。Alt + F8 →「SplitAddress」を選択して「実行」。

コード(基本版)― 都道府県を抽出する

まずは都道府県の抽出だけに絞った最小コード。都道府県は「北海道」「東京都」「大阪府」「京都府」と「〜県」の47パターンしかないので、先頭の文字数で判定できる。


Sub SplitAddress()

    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim addr As String
    Dim pref As String

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    ' ヘッダー出力
    ws.Cells(1, 2).Value = "都道府県"
    ws.Cells(1, 3).Value = "それ以降"

    For i = 2 To lastRow
        addr = Trim(ws.Cells(i, 1).Value)

        If addr = "" Then GoTo NextRow

        pref = ExtractPrefecture(addr)

        If pref <> "" Then
            ws.Cells(i, 2).Value = pref
            ws.Cells(i, 3).Value = Mid(addr, Len(pref) + 1)
        Else
            ws.Cells(i, 2).Value = "(判定不可)"
            ws.Cells(i, 3).Value = addr
        End If

NextRow:
    Next i

    MsgBox lastRow - 1 & " 件を処理しました。", vbInformation

End Sub

' ★ 都道府県を判定して返す関数
Function ExtractPrefecture(ByVal addr As String) As String

    ' 北海道(3文字)
    If Left(addr, 3) = "北海道" Then
        ExtractPrefecture = "北海道"
        Exit Function
    End If

    ' 東京都(3文字)
    If Left(addr, 3) = "東京都" Then
        ExtractPrefecture = "東京都"
        Exit Function
    End If

    ' 大阪府・京都府(3文字)
    If Left(addr, 3) = "大阪府" Or Left(addr, 3) = "京都府" Then
        ExtractPrefecture = Left(addr, 3)
        Exit Function
    End If

    ' その他の県(4文字目が「県」)
    If Mid(addr, 4, 1) = "県" Then
        ExtractPrefecture = Left(addr, 4)
        Exit Function
    End If

    ' 3文字目が「県」のパターン(例:三重県、奈良県、滋賀県、etc.)
    If Mid(addr, 3, 1) = "県" Then
        ExtractPrefecture = Left(addr, 3)
        Exit Function
    End If

    ExtractPrefecture = ""

End Function

ポイント:都道府県名は「北海道」=3文字、「東京都」「大阪府」「京都府」=3文字、それ以外の県=3文字または4文字。この5パターンで47都道府県すべてカバーできる。

基本版コードの流れを詳しく解説:

メインの SplitAddress プロシージャは、A列の各行を順番にループで処理しています。Trim で前後のスペースを除去しているのは、コピペでデータを入力したときに先頭や末尾にスペースが紛れ込むケースがよくあるためです。空文字チェックの後、ExtractPrefecture 関数を呼び出して都道府県を判定しています。

ExtractPrefecture 関数のロジックは、都道府県名の文字数パターンを利用した条件分岐です。日本の都道府県は「北海道」「東京都」「大阪府」「京都府」の4つが特殊パターンで、残り43県は「〇〇県」(3文字)か「〇〇〇県」(4文字)のどちらかです。4文字目が「県」かどうかを先にチェックし、次に3文字目が「県」かどうかをチェックする順序が重要です。この順序を逆にすると、「神奈川県」が「神奈川」の3文字で切れてしまい、「県」が残ってしまいます。

戻り値の都道府県名を使って Mid(addr, Len(pref) + 1) で残りの文字列を取り出しています。Mid関数の開始位置に Len(pref) + 1 を指定することで、都道府県名の直後から文字列を取得できます。

コード(実務版)― 都道府県+市区町村+番地の3分割+結合+郵便番号紐づけ

実務では都道府県だけでなく、市区町村と番地以降も分けたいケースが多い。さらに、分割した住所を結合したり、郵便番号シートと紐づけたりするパターンも入れた。自分はこの実務版を使ってから、住所データの整形作業を丸ごとマクロに任せるようになった。


Sub SplitAddressFull()

    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim addr As String
    Dim pref As String
    Dim remaining As String
    Dim city As String
    Dim street As String

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    ' ヘッダー出力
    ws.Cells(1, 2).Value = "都道府県"
    ws.Cells(1, 3).Value = "市区町村"
    ws.Cells(1, 4).Value = "番地以降"

    For i = 2 To lastRow
        addr = Trim(ws.Cells(i, 1).Value)

        If addr = "" Then GoTo NextRow

        ' ★ Step1: 都道府県を抽出
        pref = ExtractPrefecture(addr)

        If pref = "" Then
            ws.Cells(i, 2).Value = "(判定不可)"
            ws.Cells(i, 3).Value = ""
            ws.Cells(i, 4).Value = addr
            GoTo NextRow
        End If

        ws.Cells(i, 2).Value = pref
        remaining = Mid(addr, Len(pref) + 1)

        ' ★ Step2: 市区町村を抽出
        city = ExtractCity(remaining)

        If city <> "" Then
            ws.Cells(i, 3).Value = city
            ws.Cells(i, 4).Value = Mid(remaining, Len(city) + 1)
        Else
            ws.Cells(i, 3).Value = ""
            ws.Cells(i, 4).Value = remaining
        End If

NextRow:
    Next i

    MsgBox lastRow - 1 & " 件を処理しました。", vbInformation

End Sub

' ★ 都道府県を判定して返す関数(基本版と同じ)
Function ExtractPrefecture(ByVal addr As String) As String

    If Left(addr, 3) = "北海道" Then
        ExtractPrefecture = "北海道": Exit Function
    End If
    If Left(addr, 3) = "東京都" Then
        ExtractPrefecture = "東京都": Exit Function
    End If
    If Left(addr, 3) = "大阪府" Or Left(addr, 3) = "京都府" Then
        ExtractPrefecture = Left(addr, 3): Exit Function
    End If
    If Mid(addr, 4, 1) = "県" Then
        ExtractPrefecture = Left(addr, 4): Exit Function
    End If
    If Mid(addr, 3, 1) = "県" Then
        ExtractPrefecture = Left(addr, 3): Exit Function
    End If

    ExtractPrefecture = ""

End Function

' ★ 市区町村を抽出する関数
Function ExtractCity(ByVal addr As String) As String

    Dim pos As Long

    ' 政令指定都市パターン:「○○市○○区」まで取得
    ' まず「市」を探す
    pos = InStr(addr, "市")
    If pos > 0 Then
        ' 「市」の後に「区」があるか(政令指定都市)
        Dim kuPos As Long
        kuPos = InStr(pos + 1, addr, "区")
        If kuPos > 0 And kuPos <= pos + 4 Then
            ' 「○○市○○区」まで取得(政令指定都市)
            ExtractCity = Left(addr, kuPos)
            Exit Function
        End If
        ' 通常の市
        ExtractCity = Left(addr, pos)
        Exit Function
    End If

    ' 「区」を探す(東京23区パターン)
    pos = InStr(addr, "区")
    If pos > 0 Then
        ExtractCity = Left(addr, pos)
        Exit Function
    End If

    ' 「町」を探す(郡+町パターン)
    pos = InStr(addr, "町")
    If pos > 0 Then
        ExtractCity = Left(addr, pos)
        Exit Function
    End If

    ' 「村」を探す
    pos = InStr(addr, "村")
    If pos > 0 Then
        ExtractCity = Left(addr, pos)
        Exit Function
    End If

    ' 「郡」を探す
    pos = InStr(addr, "郡")
    If pos > 0 Then
        ExtractCity = Left(addr, pos)
        Exit Function
    End If

    ExtractCity = ""

End Function

' ★ 分割された住所を結合するマクロ(B・C・D列 → E列)
Sub CombineAddress()

    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row

    ws.Cells(1, 5).Value = "結合住所"

    For i = 2 To lastRow
        ws.Cells(i, 5).Value = ws.Cells(i, 2).Value _
                              & ws.Cells(i, 3).Value _
                              & ws.Cells(i, 4).Value
    Next i

    MsgBox lastRow - 1 & " 件を結合しました。", vbInformation

End Sub

' ★ 郵便番号シートと紐づけるマクロ
' 前提:Sheet2に「郵便番号, 都道府県, 市区町村」の一覧がある
Sub MatchZipCode()

    Dim wsData As Worksheet
    Dim wsZip As Worksheet
    Dim lastRowData As Long
    Dim lastRowZip As Long
    Dim i As Long, j As Long
    Dim pref As String
    Dim city As String
    Dim matched As Boolean

    Set wsData = Sheets("Sheet1")   ' 住所データのシート
    Set wsZip = Sheets("Sheet2")    ' 郵便番号マスタのシート

    lastRowData = wsData.Cells(wsData.Rows.Count, 2).End(xlUp).Row
    lastRowZip = wsZip.Cells(wsZip.Rows.Count, 1).End(xlUp).Row

    wsData.Cells(1, 6).Value = "郵便番号"

    For i = 2 To lastRowData
        pref = Trim(wsData.Cells(i, 2).Value)  ' 都道府県
        city = Trim(wsData.Cells(i, 3).Value)   ' 市区町村

        If pref = "" Then GoTo NextData

        matched = False

        ' 郵便番号マスタを検索
        For j = 2 To lastRowZip
            If wsZip.Cells(j, 2).Value = pref And _
               InStr(city, wsZip.Cells(j, 3).Value) > 0 Then
                wsData.Cells(i, 6).Value = wsZip.Cells(j, 1).Value
                matched = True
                Exit For
            End If
        Next j

        If Not matched Then
            wsData.Cells(i, 6).Value = "(該当なし)"
        End If

NextData:
    Next i

    MsgBox "郵便番号の紐づけが完了しました。", vbInformation

End Sub

郵便番号マスタは日本郵便のサイトからCSVでダウンロードできる。CSVファイルをExcelに正しく取り込む方法(/072)の手順でSheet2に取り込んでおけば、MatchZipCode で自動紐づけできる。ただし住所の表記ゆれがあると一致しないことがある。事前に セルの文字列を一括置換する方法(/034)でデータを統一しておくのがおすすめ。

よくある落とし穴5選

# 症状 原因 対策
1 都道府県が「(判定不可)」になる 住所の先頭にスペースや郵便番号が入っている 処理前に Trim でスペースを除去する。郵便番号付きの場合は先に郵便番号部分を除去してから都道府県判定する
2 「三重県」「奈良県」など3文字の県が4文字目で判定されて失敗する 「県」の位置が3文字目か4文字目かの判定順序が間違っている コード内で4文字目の「県」を先にチェックし、その後3文字目の「県」をチェックする(上記コードはこの順序になっている)
3 政令指定都市(大阪市北区など)で市区町村の分割がおかしい 「市」で切ると「大阪市」、「区」で切ると「大阪市北区」になるが、処理順序によっては「市」だけで切れてしまう 「市」の後に「区」が続くパターンを先に判定する。自分もこれに気づかず、500件のデータを作り直した苦い経験がある
4 「町」で分割すると町名の途中で切れる(例:「八王子市高尾町」→ 市区町村が「八王子市高尾町」ではなく途中で切れる) 町名に「町」が含まれているため、最初の「町」で切ってしまう 市→区→町→村の優先順位で判定し、「市」や「区」で先に切れた場合は「町」の判定をスキップする
5 全角・半角の数字が混在していて番地の抽出がずれる 住所データ内で「1丁目」と「1丁目」が混在している 全角⇔半角を一括変換してデータを統一する方法(/041)で先に統一してから処理する
6 「府中市」が東京都と広島県で区別できない 同名の市区町村が複数の都道府県に存在する 都道府県を先に分離してから市区町村を判定する(上記コードはこの順序になっている)。都道府県の情報なしに市区町村だけでは正確な判定ができない
7 郵便番号マスタとの紐づけで「(該当なし)」が多い 住所の表記ゆれ(「ケ」「ヶ」「が」の違い、旧字体など)でマスタと一致しない セルの文字列を一括置換する方法(/034)で表記ゆれを統一してから紐づけする。完全一致ではなくInStr関数での部分一致に切り替えるのも有効

VBAで住所から都道府県が分割できないときの対処法

「マクロを実行したら都道府県が『(判定不可)』になる」という場合、原因は住所の先頭に余計な文字が入っていることがほとんどだ。よくあるのは「〒100-0001 東京都千代田区…」のように郵便番号が付いているパターンや、先頭に全角スペースが入っているパターン。自分も500件の顧客リストで50件ほど判定不可になって焦ったが、原因はすべて先頭のスペースか郵便番号だった。対処法は、Splitに渡す前に Replace で「〒」や郵便番号部分を除去し、Trim で前後のスペースを取り除くこと。事前のデータクリーニングだけで判定精度は劇的に上がる。

VBAで住所の市区町村が正しく取得できないときの対処法

「市区町村の分割結果がおかしい。途中で切れてしまう」という場合、原因は「市」「区」「町」「村」の文字が住所の中に複数回出現することだ。たとえば「八王子市高尾町」では「市」と「町」の両方にヒットし、InStrの判定順序によっては意図しない位置で分割される。対処法は、上記の実務版コードのように「市」→「区」→「町」→「村」の優先順位で判定し、「市」で先に切れた場合は「町」の判定をスキップする設計にすること。政令指定都市(大阪市北区など)では「市」の直後に「区」が来るパターンを先に判定するのがコツだ。

VBAで住所の全角半角が混在して分割結果がずれるときの対処法

「番地部分の数字が全角と半角で混在していて、結合後のデータが不揃いになる」という場合、原因はデータ入力時の統一ルールがないことだ。「1丁目」と「1丁目」が混在していると、結合後に見た目がバラバラになるし、文字列検索でもヒットしない。対処法は、住所分割の処理に入る前に 全角⇔半角を一括変換する方法(/041) でStrConv関数を使って数字を半角に統一しておくこと。自分はマクロの冒頭で全角半角変換を必ず入れるようにしてから、結合後のデータの整合性が格段に上がった。

住所分割をさらに正確にするコツ

住所データの分割精度を上げるには、事前のデータクリーニングが重要になる。自分が500件以上の住所データを処理してきた経験から、以下の3つを事前にやっておくと「(判定不可)」の発生率がほぼゼロになる。

  1. 先頭のスペース・郵便番号を除去する — 「〒100-0001 東京都…」のようなデータは、そのまま処理すると都道府県判定が失敗する。Replaceで「〒」以降の郵便番号とスペースを除去してからSplit処理に回すのがコツ。セルの文字列を一括置換する方法が参考になる。
  2. 全角・半角を統一する — 番地の数字表記が「1丁目」と「1丁目」で混在していると、結合後のデータが不揃いになる。全角⇔半角を一括変換する方法で先に統一しておくと、後工程がスムーズ。
  3. 「ケ」「ヶ」「が」の表記ゆれを統一する — 「茅ヶ崎市」「茅ケ崎市」のように同じ住所でも表記が異なる場合がある。郵便番号マスタとの紐づけ前にReplace関数で統一しておくと一致率が上がる。

FAQ

Q1: 都道府県の47パターンを全部コード内に書く必要がある?

A: いいえ。上記のコードでは「北海道」「東京都」「大阪府」「京都府」の4つを個別判定し、残りは「3文字目または4文字目が県」で一括判定している。47個を列挙する必要はない。

Q2: 正規表現で分割したほうが正確?

A: 正規表現でも可能だが、都道府県の判定はパターンが限定的なので、上記のようなシンプルな文字列比較で十分。市区町村の分割は複雑になるので、正規表現のほうがスッキリ書ける場合もある。正規表現で複雑な文字列を検索・置換する方法(/066)を参照。

Q3: 郵便番号からの逆引き(郵便番号→住所)はできる?

A: できる。郵便番号マスタのSheet2を使って、VLOOKUP的な処理をVBAで書けばよい。上記の MatchZipCode を逆にして、郵便番号をキーに都道府県・市区町村を取得する形に変更する。

Q4: 住所が「〒100-0001 東京都千代田区…」のように郵便番号付きの場合は?

A: 先に郵便番号部分を除去する前処理を入れる。文字列から必要な部分だけ抽出する方法(/166)のInStr + Midのパターンで「〒」以降の数字部分を取り除いてから都道府県判定する。

Q5: 処理速度が遅い場合の対策は?

A: 数千件以上を処理する場合は、データを配列に読み込んでから処理し、最後にまとめてシートに書き戻すと大幅に速くなる。文字列を区切り文字で分割して取り出す方法(/064)でも使っている配列パターンが参考になる。

まとめ

この記事で、住所データを都道府県・市区町村・番地以降に自動分割し、結合や郵便番号紐づけもできるようになった。

  • 基本版:都道府県の47パターンを5つの条件分岐で判定
  • 実務版:市区町村の分割(政令指定都市対応)+結合+郵便番号マスタとの紐づけ
  • 事前処理:全角半角の統一、スペース除去をやっておくと精度が上がる

住所データの整形は地味だけど、手作業でやると件数に比例して時間がかかる。マクロに任せれば数秒で終わる。しかも判定ロジックが毎回同じなので、手作業で発生する「途中から集中力が切れてミスる」という問題がなくなる。一度マクロを作ってしまえば、次に同じ作業が発生したときはボタン1つで終わる。住所データの分割・結合は定期的に発生する業務が多いから、マクロ化の投資対効果は非常に高い。

次にやりたくなること

コメント

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