今、東京都の東京タワー、福島県のフォレストパークあだたら、岐阜県のハリヨ公園など、住所データが5万件ぐらいあります。
東京都港区芝公園4丁目2−8
福島県安達郡大玉村玉井字長久保68
岐阜県山県市大森
・
・
この中から、
港区
安達郡
山県市
など、都道府県名を除いた市区町村名(区名)のみ抽出したいのです。
東京都港区
福島県安達郡
岐阜県山県市
でも構いません。
というのもおそらく都道府県名は岐阜県の山県市のみ気を付ければ、「*県」を空白に置換して消去、東京都・大阪府・京都府を置換で消去すれば、事足りるからです。
しかし市区町村の抽出は、千葉県の市川市など、「市*」を「市」に置換すると、市区町村が消えて「市」だけになってしまいますし。
「郡」は郡上市とか郡山市とか、置換して消去というやり方では市区町村名の表示がおかしくなる可能性もあります。
気を付けて少し時間をかければ置換して抽出できるのですが…「もっと効率的な方法がある!」ようでしたら、ご教授いただけますとありがたいです。
よろしくお願い致します。
以下のコードを標準モジュールに貼り付けて、extract_city サブルーチンを実行してください。
A列の住所から市区町村郡を切り出して、B列にセットします。
Sub extract_city() source_col = 1 ' A列 : 住所 dest_col = 2 ' B列 : 市区町村 last_row = Cells(Rows.Count, source_col).End(xlUp).Row Set re_z = CreateObject("VBScript.RegExp") Dim re_c(7) For i = 0 To 7 Set re_c(i) = CreateObject("VBScript.RegExp") Next re_z.Pattern = "^(.{2}[都道府]|.{2,3}[県])(.+)" re_c(0).Pattern = "^(郡山市|市川市|市原市|郡上市|蒲郡市|四日市市|大和郡山市|廿日市市|小郡市|野々市市|高市郡|余市郡)" re_c(1).Pattern = "^([^郡]+郡)" re_c(2).Pattern = "^([^市]+市)" re_c(3).Pattern = "^([^区]+区)" re_c(4).Pattern = "^([^町]+町)" re_c(5).Pattern = "^([^村]+村)" re_c(6).Pattern = "^([^区]+区)" ' 東京都用 re_c(7).Pattern = "^([^市]+市)" ' 東京都用 For r = 2 To last_row s = Cells(r, source_col).Value Set mat = re_z.Execute(s) If mat.Count = 0 Then Cells(r, dest_col).Value = "都道府県が見つかりません" GoTo Continue End If Z = mat(0).SubMatches(0) s = mat(0).SubMatches(1) i_begin = 0 i_end = 5 If Z = "東京都" Then i_begin = 6 i_end = 7 End If For i = i_begin To i_end Set mat = re_c(i).Execute(s) If mat.Count > 0 Then If i <> 1 Then Cells(r, dest_col).Value = mat(0).SubMatches(0) Else ' 「郡」だけ特別扱い Set mat2 = re_c(2).Execute(s) ' 「市」を含む? If mat2.Count > 0 Then '短い方を採択 If Len(mat(0).SubMatches(0)) > Len(mat2(0).SubMatches(0)) Then Cells(r, dest_col).Value = mat2(0).SubMatches(0) Else Cells(r, dest_col).Value = mat(0).SubMatches(0) End If Else Cells(r, dest_col).Value = mat(0).SubMatches(0) End If End If GoTo Continue End If ' DoEvents Next Continue: Next End Sub
五万件だと数分かかると思います。
その間にもシートを操作したいのであれば、末尾の方でコメントにしてある DoEvents を活かしてください。
コメントを外すと、完了までの時間は更に長くなりますが、処理中にもシートの操作ができます。
処理内容の説明をしておきます。
「郡→市→区→町→村」の順番で検索すると、エラーの発生を最小にすることができます
上記のロジックを参考にしました。
ただ、「郡」や「市」を市の名前に含む9件を例外扱いにしただけでは、以下のような住所が適切に扱えません。
山形県南陽市郡山
大阪府交野市郡津
山口県山口市小郡
鹿児島県鹿児島市郡元町
そこらあたりを、実際の住所データ(何かの回答の折に使った 9000件くらいの全国の)を使いながらロジックを調整しました。
「郡」が見つかった場合には、「市」でも探してみて、短い方を採用しています。
それでも、「奈良県高市郡」、「北海道余市郡」は正しく抽出できないので、特別扱いにしています。
対象の住所によっては、正しく処理できないものがあると思います。
コメントで紹介されている総務省の「全国地方公共団体コード」から表引きにすることもちらっと考えましたが、
と思って止めました。
後、質問では「郡」を切り出しの対象にしているのでそのような処理にしていますが、「郡」で切ってしまうと、「町」や「村」が抽出されないと思います。
入力済みの住所データ次第ですが、「○○郡△△村」のような表記になっているはずなので。
#「郡」も例外的なのがもっとあるんだろうなあ...
「郡の変遷」に 2014年4月1日時点での「郡」の情報がまとめられていて、「郡」の名称に「市」が入るのは、「余市」と「高市」だけっぽいことは確認しました。
「町」、「村」の切り取りは、まとめて先頭一致の表引きでも良いでしょう(遅いけど)。
表引きでも、素直に表と照らし合わせるだけでは駄目でヒューリスティックなロジックにならざるを得なし、市区町村のリストは頻繁ではないにしても更新が入りますので使い続けるつもりのプログラムなら保守が必要。
だったら表なんか使わなくても良いかなあ、という印象です。
の完全なリストが手に入る。
全部で 1894件。
これを長い順に並べ替えて、住所から都道府県を切り取った文字列と先頭一致で比較して一致したら採用。
「郡は要らない」とか「郡の方を採用」は、一覧にある文字列を加工する感じでしょうか。
ロジックは単純になりますね。
# 総務省の「全国地方公共団体コード」の方は 1741 件で、150件ほど差があるのは廃止になったものを一部含んでいるからかな?
# 総務省の「全国地方公共団体コード」の方は 1741 件で、150件ほど差があるのは廃止になったものを一部含んでいるからかな?
いや、郵便番号の方は「○○市○○区」の表記だからだった。
一部の差異を除いて、ほぼ同じ。
漢字の表記の違いが2件と、「郡」ではなく「島」という表記が 2件(三宅島と八丈島)。
東京都だからだなあ、きっと。
良くも悪くも入手できる一覧は最新なので、市区町村を切り出す対象の住所に古いものが含まれると、取りこぼしがありそうです。
ぼくが試したデータでは 2.8% を取りこぼしているので、プログラムで切り出した方が例外が少ないという結果になります。
一覧表のデータは、プログラムで切り出した値の検算に使うのが良いかな、という気がしました。
moon-fondu様
こんにちは。
私はプログラマなので、市区町村データとマッチして取得しています。
例)総務省のサイトでEXCELで用意されています。
http://www.soumu.go.jp/denshijiti/code.html
例)Yahooではプログラムが作れる人ならWEB APIで用意されています。
http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/addressdirectory.html
【注意事項】
・「ケ」と「ヶ」の違いもあるかも知れません。
・漢字の違いに注意が必要かも知れません。
龍ケ崎市、竜ヶ崎市 等々
・市区町村をどこまで取得するかも検討が必要です。
札幌市 までか?
札幌市中央区 までか?
・市区町村合併により町名変更も注意する必要があります。
以上、ご検討ください。
違う方法を試したければ、市区町村名のリストが使えそうですね
http://www.soumu.go.jp/denshijiti/code.html