できるだけ正確に、住所を3分割（都道府県・市区町村・その他）する(VBA)

#機能
#### 分割例
- 福井県あわら市○○1-1-1　→　福井県　あわら市　○○1-1-1

####郡の省略にも対応
町村の前にある郡は省略される場合もあるので、どちらにも対応する。

- 福井県三方郡美浜町△△1-1-1　→　福井県　三方郡美浜町　△△1-1-1
- 福井県美浜町△△1-1-1　→　福井県　美浜町　△△1-1-1

#### できるだけ正確に
できるだけ正確に、とは、都道府県・市区町村へ分割する際に、都道府県・市区町村の元データが不正確な場合は、分割せず、その他に配置する、ということです。

- 足羽県あわら市○○1-1-1　→　足羽県は昔あったが今は無いので、その他に配置される。

### ダウンロード
次のページでダウンロードできます。
https://ganges.pro/customer/blog/split-address-vba/

### 比較用データ
- 比較用データを、ワークシート[City]に配置します。
- 統計で見る日本＞市区町村名・コード＞市区町村を探す でダウンロードできるデータを利用します。
- また、北海道の行政区分が振興局になっているものは、北海道郡追加・北海道町村追加に、郡と町村を、手動で記載します。
- https://www.e-stat.go.jp/municipalities/cities/areacode

###留意点

- 檮原町→略式表記「梼原町」では分割できない
- 七ヶ宿町など、「ヶ」が「ケ」では分割できない
- 支庁は住所表記とは無関係。例：三宅村は「東京都三宅村」が住所。「東京都三宅支庁三宅村」という表記は誤り。

#作成理由
- 元データが正確で無い場合が多数あり、その場合は、分割できなかったということを分かるようにしたいため。

#プログラムについて
- VBAで作成したのは久しぶりで、書き方をかなり忘れていました・・・。
- C#に移植しました。[できるだけ正確に、住所を3分割（都道府県・市区町村・その他）する(C#)](https://qiita.com/hiro_t/items/aee87c1357a96cabd01f)
- 計算は、かなり遅いです。計算方法を手動にしておくと良いでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/4403bbf9-c951-d36e-7ce1-c93c81c187d4.png)



```vb
'概要：  住所を「都道府県」「市区町村（郡を含む・含まないの両方に対応）」「残りの住所」の3つに分割して、3つのセルに表示する
'        例　福井県あわら市○○1-1-1　→　福井県　あわら市　○○1-1-1
'            福井県三方郡美浜町△△1-1-1 →　福井県　三方郡美浜町　△△1-1-1
'        ワークシートCityのデータを基にする
'　　　　統計で見る日本＞市区町村名・コード＞市区町村を探す でダウンロードできるデータを利用します。
'        北海道の行政区分が振興局になっているものは、北海道郡追加・北海道町村追加に、郡と町村を記載すること。
'　　　　https://www.e-stat.go.jp/municipalities/cities/areacode
'留意点：
'檮原町→略式表記「梼原町」では分割できない
'七ヶ宿町など、「ヶ」が「ケ」では分割できない
'支庁は住所表記とは無関係。例：三宅村は「東京都三宅村」が住所。「東京都三宅支庁三宅村」という表記は誤り。
'作成：  2020-06-16 Ganges
'更新：  2020-06-16 Ganges
'https://ganges.pro/
Function GetAddress(address As Range)

    Dim result(0, 2) As String
    Dim addressTrim As String
    Dim address2 As String
    Dim cityName As String    '市区町村
    Dim lastAddress As String    '3つ目のセルの住所

    addressTrim = Trim(address.Value)    '住所の前後の空白は削除

    If (addressTrim = "") Then
        GetAddress = result
        Exit Function
    End If

    left4 = Left(addressTrim, 4)
    left3 = Left(addressTrim, 3)

    If (left4 = "神奈川県" Or left4 = "和歌山県" Or left4 = "鹿児島県") Then

        result(0, 0) = left4
        address2 = Right(addressTrim, Len(addressTrim) - 4)

    ElseIf (left3 = "北海道" Or left3 = "青森県" Or left3 = "岩手県" Or left3 = "宮城県" Or left3 = "秋田県" Or left3 = "山形県" Or _
            left3 = "福島県" Or left3 = "茨城県" Or left3 = "栃木県" Or left3 = "群馬県" Or left3 = "埼玉県" Or left3 = "千葉県" Or _
            left3 = "東京都" Or left3 = "新潟県" Or left3 = "富山県" Or left3 = "石川県" Or left3 = "福井県" Or left3 = "山梨県" Or _
            left3 = "長野県" Or left3 = "岐阜県" Or left3 = "静岡県" Or left3 = "愛知県" Or left3 = "三重県" Or left3 = "滋賀県" Or _
            left3 = "京都府" Or left3 = "大阪府" Or left3 = "兵庫県" Or left3 = "奈良県" Or left3 = "鳥取県" Or left3 = "島根県" Or _
            left3 = "岡山県" Or left3 = "広島県" Or left3 = "山口県" Or left3 = "徳島県" Or left3 = "香川県" Or left3 = "愛媛県" Or _
            left3 = "高知県" Or left3 = "福岡県" Or left3 = "佐賀県" Or left3 = "長崎県" Or left3 = "熊本県" Or _
            left3 = "大分県" Or left3 = "宮崎県" Or left3 = "沖縄県") Then

        result(0, 0) = left3
        address2 = Right(addressTrim, Len(addressTrim) - 3)
        result(0, 1) = Right(addressTrim, Len(addressTrim) - 3)

    Else

        address2 = addressTrim    '住所が、都道府県の文字列で始まらない場合

    End If


    lastAddress = address2


    Dim lastRow As Integer
    lastRow = Worksheets("City").Cells(1, 1).End(xlDown).Row    'Cityの1列目には、空欄が無いことを前提として最後の行番号を取得

    Set city = Worksheets("City").Range("A1:H" & lastRow)


    Dim isFinded
    Dim temp As String
    For Each r2 In city.Rows

        If (r2.Columns(5) <> "") Then
            If (Right(r2.Columns(3), 3) <> "振興局") Then
                temp = r2.Columns(3) & r2.Columns(5)  '政令市･郡･支庁･振興局等 + 市区町村
            Else
                temp = r2.Columns(9) & r2.Columns(10)  '北海道郡追加 + 北海道町村追加
            End If

            If (InStr(address2, temp) = 1) Then
                cityName = temp
                lastAddress = Right(address2, Len(address2) - Len(temp))
                isFinded = True    '郡がついた町村の場合は、Trueにして抜ける
                Exit For
            End If

        End If

    Next r2



    '「東村」と「東村山市」があるので、Columns(5)は、本来は文字数の多い順に調べないといけない。
    'ただ、東村より、東村山市がCityのワークシートで前の行にあるので、以下の処理で不都合はない
    'これは、東村以外にはないので、この処理で不都合は現時点ではない。
    If (isFinded = False) Then

        For Each r2 In city.Rows

            If (r2.Columns(5) <> "") Then
                temp = r2.Columns(5)    '市区町村。北海道の振興局がある行も、5列目の町村で良い。9,10列目の町村と行が入れ替わっていても良い。

                If (InStr(address2, temp) = 1) Then
                    cityName = temp
                    lastAddress = Right(address2, Len(address2) - Len(temp))
                    isFinded = True
                    Exit For

                End If
            End If

        Next r2

    End If

    result(0, 1) = cityName    '市区町村
    result(0, 2) = lastAddress    'それ以外

    GetAddress = result

End Function
```