公共施設の維持管理のためGISにプロットしたり,防災マップを作成したりなど,大量の住所データから位置情報データ(緯度・経度)に変換する必要がある場合,ジオコーディングサービスを使って処理することが可能です。逆ジオコーディングの事例同様,Yahoo!のWebサービスを使った例です。
汎用性を持たせるため,やはりジオコーディング部分を関数として作成することを考えます。
つまり,住所(文字列)を引数として与えて,位置情報(緯度・経度)が戻り値となります。通常,一つの関数で戻り値を複数とできませんので,以下のような対応が考えられます。
- 緯度と経度が戻り値となる関数を別々に作り,同じ引数(住所)で2回呼び出す。
- 緯度と経度をつなげた文字列が戻り値となる関数を作り,呼び出し側で分離する。
- 緯度と経度の情報をもつユーザー定義型変数を定義し,1つの関数で戻るようにする。
上記のうち,3の方法が最もスマートと考えられますので,このパターンでコーディングします。
下図のように,A2セルに入力した住所から緯度・経度に変換し,B2~C2セルに出力する簡単な例とします。
1 2 3 4 5 6 |
Option Explicit Type Coordinate '座標をユーザー定義 Lat As Single '緯度 Latitude Lon As Single '経度 Longitude End Type |
標準モジュールの宣言セクションにCoodinate(座標)を定義します。Single型で緯度と経度を持たせます。
次に実行部分を下に続けて入力します。
7 8 9 10 11 12 13 14 15 16 17 18 |
Sub ジオコーディングテスト() Dim 座標 As Coordinate, 住所 As String 住所 = Range("A2") 座標 = GeoCoding(住所) '座標へ変換 Range("B2").Value = 座標.Lat '緯度をセルに表示 Range("C2").Value = 座標.Lon '経度をセルに表示 End Sub |
10行目
座標という変数を定義したCoordinate型で宣言します。
13行目
新しく作るGeoCodingという関数で座標へ変換します。引数は住所(文字列)で,戻り値はCoordinate型で緯度・経度が戻ってきます。
15~16行目
ユーザー定義したCoordinate型は.Latで緯度,.Lonで経度が得られます。
次にGeoCoding関数を作成します。
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
'住所から座標(緯度,経度)へ変換する Function GeoCoding(Jusho As String) As Coordinate Dim xReq As MSXML2.XMLHTTP60 Dim xDoc As MSXML2.DOMDocument60 Dim Url As String 'ローカルサーチAPI 上から順にAPIキー,住所(URLエンコードされた文字列) Url = "http://map.yahooapis.jp/LocalSearchService/V1/LocalSearch" + _ "?appid=<あなたのアプリケーションID>" + _ "&p=" + UrlEncode(Jusho) Set xReq = New MSXML2.XMLHTTP60 'XMLHTTPオブジェクトをセット With xReq .Open "GET", Url, varAsync:=False '読み込み待ちを行うため非同期モードで通信を開始 .send 'リクエストを送信 If .Status <> 200 Then Exit Function 'リクエストが成功しなかったら終了 Set xDoc = .responseXML '受信したXMLをDOMDocumentにして処理する End With With xDoc If .getElementsByTagName("Count").Item(0).Text = 0 Then '見つからなかったら GeoCoding.Lat = 0 '緯度・経度とも0を返す GeoCoding.Lon = 0 Else '見つかったら With .getElementsByTagName("DatumWgs84").Item(0) '世界測地系の座標で GeoCoding.Lat = .ChildNodes(0).Text '1番目の子ノード(緯度)を返す GeoCoding.Lon = .ChildNodes(1).Text '2番目の子ノード(経度)を返す End With End If End With Set xReq = Nothing Set xDoc = Nothing End Function |
21行目
GeoCodeingという関数を定義しています。Jushoという文字列を引数に,Coordinate型の戻り値になっています。
23~24行目
ジオコーディングではAPIからXML形式でデータを受信しますので,その処理のためにXML通信やドキュメントなどのオブジェクトを用意する必要があります。XMLを利用できるよう,VBEの参照設定から Microsoft XML, V6.0 を選択しておきます。
28~30行目
APIへのリクエストURLを作成しています。オプションの?p=以降には住所を指定しますが,UTF-8でURLエンコードした文字列が必要となるため,さらに別の関数UrlEncodeをあとで作成します。
逆ジオコーディングと同様に,Yahoo!デベロッパーネットワークで公開されている地図サービス(YOLP)のAPIを用います。
<あなたのアプリケーションID>には,Yahoo!デベロッパーネットワークに登録して取得したアプリケーションIDで置き換えます。
詳細な利用方法や利用規約などは以下のリンクから確認して下さい。
32~39行目
ローカルサーチAPIでリクエストするためのXMLオブジェクトを作成し,ジオコーディングのリクエストを行い,XML形式で受信します。
41~51行目
得られたXMLデータ内のCountタグで条件分岐し,0なら見つからなかったので,緯度・経度は0として返すようにします。
見つかった場合は1以上となり,1番最初のDatumWgs84タグ(世界測地系)の1番目の子ノードLatから緯度,2番目の子ノードLonから経度を取得します。
次に,UTF-8でURLエンコードする関数を作ります。ここでは割愛しますが,検索すれば他サイトで詳しく解説が載っていると思います。
57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
Function UrlEncode(url As String) As String Dim SC As Object Set SC = CreateObject("ScriptControl") With SC .Language = "Jscript" UrlEncode = .CodeObject.encodeURIComponent(url) End With Set SC = Nothing End Function |
57 |
これで完成しましたので,マクロを実行してみます。
実際,リクエストによって位置情報が見つかった場合,以下のようなXMLデータが得られます。この場合,住所による位置情報と郵便番号による位置情報の2件見つかっているため,Countが2となっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?xml version="1.0"?> <LocalSearchResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:yahoo:jp:maps http://map.yahooapis.jp/LocalSearchService/V1/LocalSearchResponse.xsd"> <Count>2</Count> <ViewCount>2</ViewCount> <Query>東京都新宿区西新宿2丁目8-1</Query> <Item> <Category>Address</Category> <Title>東京都新宿区西新宿2丁目8-1</Title> <Address>東京都新宿区西新宿2丁目8-1</Address> <AddressLevel>6</AddressLevel> <DatumTky97> <Lat>35.68595000</Lat> <Lon>139.69487500</Lon> </DatumTky97> <DatumWgs84> <Lat>35.68918461</Lat> <Lon>139.69164748</Lon> </DatumWgs84> <Url/> </Item> <Item> <Category>Zipcode</Category> <Title>〒163-8001</Title> <Address>東京都新宿区西新宿2丁目8?1</Address> <AddressLevel>0</AddressLevel> <DatumTky97> <Lat>35.68627042377263</Lat> <Lon>139.69494060163743</Lon> </DatumTky97> <DatumWgs84> <Lat>35.68950500</Lat> <Lon>139.69171306</Lon> </DatumWgs84> <Url/> </Item> </LocalSearchResult> |
もし実際にない住所を入力した場合は見つかりませんので,以下のようにCountが0と得られます。
1 2 3 4 5 |
<?xml version="1.0"?> <LocalSearchResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:yahoo:jp:maps http://map.yahooapis.jp/LocalSearchService/V1/LocalSearchResponse.xsd"> <Count>0</Count> <ViewCount>0</ViewCount> </LocalSearchResult> |
ダウンロード
上記の手順で作成することが可能ですが、自分で作るのは面倒という方は、上記のコードを含んだサンプルファイルをGumroadからダウンロードできます。