Excelで都道府県抽出の「=LEFT(A2,3+(MID(A2,4,1)="県"))」関数式は使ってはいけない

=LEFT(A2,3+(MID(A2,4,1)="県")) とは

Xで「=LEFT(A2,3+(MID(A2,4,1)="県"))」関数式に関するポストがバズってました。

「=LEFT(A2,3+(MID(A2,4,1)="県"))」は住所から都道府県を抽出する関数式で、例えばA2が「和歌山県和歌山市西954-6」の場合、「=LEFT(A2,3+(MID(A2,4,1)="県"))」をB2で使用すると「和歌山県」を抽出できます。

住所から都道府県を抽出したサンプル

一見すると便利な関数ですが、いくつかの問題がある関数式なので使用してはいけません。

問題1 都道府県でなくても抽出される

「=LEFT(A2,3+(MID(A2,4,1)="県"))」は「MID(A2,4,1)="県"」で「県」が含まれている場合はTRUE(1)、含まれていない場合はFALSE(0)を返します。

これにより、TRUEなら「=LEFT(A2,3+1)」、FALSEなら「=LEFT(A2,3+0)」で抽出します。

つまり、都道府県でなくても「=LEFT(A2,3+0)」で抽出されるのです。

そのため、例えば「京都市下京区山川町861-16」の場合は「京都市」が表示されてしまいます。

問題2 エラーが表示されない

問題1のように「京都市」などが表示されてしまうと、都道府県が含まれていないことに気づきにくいです。

都道府県が含まれていない場合はわかりやすくエラーを返すほうが好ましいです。

問題3 県などが含まれる市区町村だと使えなくなる

現在の市区町村には「県」で始まるところは存在しませんが、例えば今後「山梨県県北市」のように県が付く市区町村が追加されると、「MID(A2,4,1)="県"」では「山梨県県」で抽出してしまうため、正しく判定できなくなってしまいます。

カスタム関数で抽出する方法

ExcelやGoogleスプレッドシートではカスタム関数という自作の関数が作成できます。

カスタム関数による都道府県の抽出であれば、「=LEFT(A2,3+(MID(A2,4,1)="県"))」のときのような「都道府県でなくても抽出される」や「エラーを返さない」などのデメリットを解消できます。

Excelの場合はVBAを使用することにより、以下のように都道府県を抽出するカスタム関数を作成可能です。

VBA
Function GetPrefecture(str As String) As String
    Dim prefectures As Variant
    Dim i As Integer
    
    prefectures = Array("北海道", "青森県", "岩手県", "宮城県", "秋田県", "山形県", "福島県", _
                        "茨城県", "栃木県", "群馬県", "埼玉県", "千葉県", "東京都", "神奈川県", _
                        "新潟県", "富山県", "石川県", "福井県", "山梨県", "長野県", "岐阜県", _
                        "静岡県", "愛知県", "三重県", "滋賀県", "京都府", "大阪府", "兵庫県", _
                        "奈良県", "和歌山県", "鳥取県", "島根県", "岡山県", "広島県", "山口県", _
                        "徳島県", "香川県", "愛媛県", "高知県", "福岡県", "佐賀県", "長崎県", _
                        "熊本県", "大分県", "宮崎県", "鹿児島県", "沖縄県")

    For i = LBound(prefectures) To UBound(prefectures)
        If Left(str, Len(prefectures(i))) = prefectures(i) Then
            GetPrefecture = prefectures(i)
            Exit Function
        End If
    Next i
    
    GetPrefecture = "⚠️文字列の先頭が都道府県ではありません!"
End Function

Googleスプレッドシートの場合はApps Scriptを使用することにより、以下のように都道府県を抽出するカスタム関数を作成可能です。

Apps Script
const prefectures = [
  '北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県', 
  '茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県', 
  '新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県', '岐阜県', 
  '静岡県', '愛知県', '三重県', '滋賀県', '京都府', '大阪府', '兵庫県', 
  '奈良県', '和歌山県', '鳥取県', '島根県', '岡山県', '広島県', '山口県', 
  '徳島県', '香川県', '愛媛県', '高知県', '福岡県', '佐賀県', '長崎県', 
  '熊本県', '大分県', '宮崎県', '鹿児島県', '沖縄県'
]

function getPrefecture(str) {
  const prefecture = prefectures.find(p => str.startsWith(p))
  return prefecture ? prefecture : '⚠️文字列の先頭が都道府県ではありません!'
}

通常の関数とシートのデータだけで作成する方法

Googleスプレッドシートの場合、Apps Scriptがサーバーサイドで実行されるため、セルに「Loading...」が一時的に表示されてしまい、表示されるのが遅いです。

もし、「Loading...」を表示させたくない場合は、通常の関数とシートのデータだけで作成する方法を使用します。

やり方は、まず「prefectures」シートを作成し、A1からA47のセルに都道府県を記入します。

「prefectures」シートは編集されないように、念のためロック(保護)を有効にしたほうが良いです。

次に以下の関数を作成してA2以降に都道府県が含まれているか判定します。

=IFERROR(
  INDEX(prefectures!$A$1:$A$47, MATCH(TRUE, ARRAYFORMULA(LEFT(A2, LEN(prefectures!$A$1:$A$47)) = prefectures!$A$1:$A$47), 0)),
  "⚠️文字列の先頭が都道府県ではありません!"
)

「prefectures」シートの都道府県のデータをARRAYFORMULAで配列として取得し、MATCHとINDEXで一致した都道府県を返します。

住所に都道府県が存在しない場合は、IFERRORで「⚠️文字列の先頭が都道府県ではありません!」を表示させます。

住所から都道府県を抽出したサンプル