ローカルアプリでGoogle Mapsを使ってみる
Posted By 茜丸@昼勤務 on 2009年10月9日
通常、Google Mapsというものは、ウェブで使うものです。本来ローカルアプリケーションで使用するようなものではないのですし、また使う為には結構面倒くさいことをしなければなりません。ですが、そのメリットは大きく、自分が主につかっているAccessのようなデータベースから直接にデータを流しこんだり、連携機能を提供したりすることが可能です。今回書いてみる内容は、ウェブブラウザーコントロールを使って、Google Maps APIを仕込んだHTMLを表示させ、連携させるテクニックです。HTML側の機能を充実させれば、かなりいろいろなことができるんじゃないだろうかと思います(KML出力機能はすでに実現しているので、それを読み込んでみたりとかも面白そうだ)。
スクリーンショットの地図の部分はサブフォームで実現しており、親フォームの職員コードとリンクして動きます。サブフォームにはフォーム前面にWebBrowser Controlを貼り付け、このときのフォーム名をgooglemaps、コントロールをWebBrowser0と命名してあります。読み込むHTMLファイルは、map.htmlとし、この中には普通のGoogle Maps APIを用いて作成したコードが入っています。Mapはマップ本体と見えないですが、テキストボックスを1つ用意してあるだけです。親フォームは、給与マスタービューアという名前となっています。
まずは、フォームをロードした時のコードを記します。
Private Sub Form_Load()
Dim URL As String
Dim HStyl As HTMLStyle
Dim IsSet As Boolean
URL = CurrentProject.path & "\map.html"
WebBrowser0.navigate URL
'あえてエラー処理をさせる
On Error Resume Next
Err = 0
IsSet = False
Do Until IsSet
With WebBrowser0.Document.body.Style
.border = "0" '枠線はなくす
.overflow = "hidden" 'スクロールバーは非表示とする
End With
Select Case Err 'エラー処理
Case 0: IsSet = True
Case 91: Err = 0
Case Else: IsSet = True
End Select
DoEvents
Loop
Do While WebBrowser0.Busy = True
'反応を待つための空ループ
DoEvents
Loop
WebBrowser0.Document.all.address2.value = Form_給与マスタービューア.address.value
'フォームをSubmitする
WebBrowser0.Document.Forms(0).all(1).Click
End Sub
次にレコードを移動した際のコードを記します。
Private Sub Form_Current() Form_googlemaps!WebBrowser0.Document.all.address2.value = Form_給与マスタービューア.address.value 'フォームをSubmitする Form_googlemaps!WebBrowser0.Document.Forms(0).all(1).Click End Sub
これらは一体何をやっているのかというと、親フォームである給与マスタービューアのaddressというテキストボックスの住所を取得し、サブフォームに配置したWebBrowser Control内に表示させたmap.htmlの中にあるテキストボックスに値を入れて、ボタンを押させているわけです。もっとマシなやり方があるのかもしれませんが、思いつきませんでした。また、WebBrowser Controlに関する資料も非常に少なく、苦労しました(さらにそれをAccessでやろうなんてのも普通いないでしょうね)。とりわけ、Form_LoadやForm_Currentにある、WebBrowser0.Document以下のコード、これが肝であり、address2やForm(0)は、map.html内のテキストボックスフォームに対しての参照です。
Map.htmlはサブフォームの表示領域に合わせてあり、テキストボックスは見えなくなっていますが、確かにそこに存在します。さて、そのmap.htmlのコードを見てみます。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<head>
<script src="http://maps.google.com/maps?file=api&v=2&key=ここにGoogle Maps API キーを入れておく" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var map;
var geocoder;
// 初期化
function initAddress(){
if ( GBrowserIsCompatible() ) {
map = new GMap2(document.getElementById("map"));
// 初期化する時は適当な緯度経度を指定しておく。今回は薩摩硫黄島がそれ。
map.setCenter(new GLatLng(30.79788400,130.27896900), 15);
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.addControl(new GOverviewMapControl());
map.setMapType(G_NORMAL_MAP);
var marker=new GMarker(map.getCenter());
map.addOverlay(marker);
var url = 'myplaces.kml';
var gx = new GGeoXml(url);
map.addOverlay(gx);
// map.addOverlay(new GStreetviewOverlay());
// ジオコーディングオブジェクトの生成
geocoder = new GClientGeocoder();
}
}
// 地図を移動する
function moveAddress( ADDRESS ){
if ( geocoder ) {
// getLatLngに住所情報を渡し、コールバック関数で地図を移動させる
geocoder.getLatLng(
ADDRESS, function( latlng ){
if ( latlng ) {
// コールバック関数から受け取った引数を使って地図を移動
map.setCenter(latlng, 15);
// マーカーを表示
var marker = new GMarker(latlng);
map.addOverlay(marker);
}
}
);
}
}
//]]>
</script>
</head>
<body onload="initAddress()" onunload="GUnload()" style="margin:0px; padding:0px;">
<div id="map" style="width:755px; height:365px; margin:0px; padding:0px;"></div>
<form action="#" onsubmit="moveAddress(this.address2.value); return false">
<input type="text" name="address2" value="" />
<button type="submit" name="btn01">移動する</button>
</form>
</body>
</html>
あまり、Google Maps APIに詳しくないので、サンプルサイトからのコードに手を加えたものとなっています。他にも、Google Earthプラグインをつかったページを用意することも可能です。ですが、ブラウザ上で動いていることになっているので、Access側で参照設定が別途必要かといったら必要ありません。表示するためのプラグインもブラウザのプラグインとして読み込まれますので、フラッシュの表示等も同様です。
問題点が一つあって、WebBrowser Controlは、どうも2個3個表示させたり、多くデータを表示させ続けていると、メモリリークを起こしどんどん肥大化していくことがあるという点。これは避けようのないことで、こちらでは手が打てませんが、画面のように1つ表示させるくらいなら全く平気です。KMLの読み込みも問題ありません。できれば、Mozilla ActiveX Controlを使いたいところなんですが、どうも仕様が異なるみたいで、しかもこちらはもっと資料がない。公式サイトにあるActiveX Controlは古いため、たとえばLunascapeなどで使われているコンパイルされたコントロールを使う手立てか、ソースコードから自分でビルドしなければなりません。
とまぁ、こんな具合に、ブラウザコントロールを用いることで連携を図ることで、Google Mapsをローカルアプリケーションとして利用することが可能です。改造は親プログラム側ではなく、map.htmlのほうを中心に改造することで機能増強できます。その際にmap.html内のformの順番に注意してコントロールをしなければなりませんが。今回のような単純なものをベースに作るとよいでしょう。
ちなみに、スクショの下のほうにある地球儀のボタン。押すと、登録している全員分の住所がKML化して、出力されます。コードは以下の通り。絞り込みをするため、使っているクエリの名前は、住所エクスポートテストという名前です。また、XSLT処理を行っているので、ac20072kml.xslというXSLファイルを使用。実は大分前にも紹介したものですが、再度紹介いたします。
Private Sub コマンド114_Click()
Dim stExFile As String
Dim stExXsl As String
Dim stFile_Add As String
On Error GoTo Err_コマンド114_Click
stExXsl = CurrentProject.path & "\ac20072kml.xsl"
stExFile = CurrentProject.path & "\address.xml"
stFile_Add = CurrentProject.path & "\address.kml"
Application.ExportXML acExportQuery, "住所エクスポートテスト", stExFile
Application.TransformXML stExFile, stExXsl, stFile_Add, False, acPromptScript
End Sub
ExportXMLとTransformXMLは、Access特有のメソッドでこれのおかげでかなりお手軽にXSLT処理を施した上に、XMLファイル化ができるので、非常に便利です。ac20072kml.xslの中身は非常に単純です。前回も紹介したものですが、これも以下に記しておきます。もっとマシなXSLを記述できれば、データベースの中身をグルーピングした状態でKML化もできます。全ては、XSLの書き方次第ですので、合わせて勉強しておきたいところです。
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:fx="#fx-functions" exclude-result-prefixes="msxsl fx"> <xsl:output method="xml" encoding="UTF-8" /> <xsl:template match="//dataroot" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <kml xmlns="http://earth.google.com/kml/2.1"> <Document> <Folder> <name>Access2007 to KML</name> <xsl:for-each select="住所エクスポートテスト"> <Placemark> <name><xsl:value-of select="職員コード" /></name> <visibility>0</visibility> <address><xsl:value-of select="address" /></address> </Placemark> </xsl:for-each> </Folder> </Document> </kml> </xsl:template> </xsl:stylesheet>
2行目のコードは、Access2007でXSLT処理を行う上での決めごとなので、必ずつけなくてはいけないようです。KML化と直接関係のあるものではありませんが、こういうもんだということで、覚えておく必要のあるものです。こんな具合に、なかなかに手間ではありますが、ローカルアプリケーションでGoogle Mapsを使うと結構面白いことが可能ですし、Google Earth APIを使って、COM APIをたたくアプリを内蔵しても面白い。後者の場合挙動を事細かに制御が可能なので、できればこちらのほうが望ましいですし、Mapなどは、ネットワークリンクを読み込ませてオーバーレイすれば良いので、よりアプリケーション的なことをやらせることが可能です(COM APIは難しいので、なかなか勉強するといっても自分もできていません・・・情けない話です)。
Comments
5 Responses to “ローカルアプリでGoogle Mapsを使ってみる”
Leave a Reply
注記: コメントは管理者が承認されるまでの間遅れて表示されます。承認後、表示されるようになります。コメントを再送信する必要性はありませんスパムコメント防止の為、ご協力くださいませ。
こんにちわ、以前よりAccess上でGooglemapが使えたらと思っていたところこちらの
サイトを見つけました。大変初歩的な質問だとは思うのですが、GoogleAPIキーを取得する際には
登録ページの”使用する Web サイトの URL “欄にはなんと入力すればよいのでしょうか?
ローカルアプリの場合はどういう扱いなのか理解できず・・。
map.htmlのある場所を”file:///d:/files/管理台帳/map.html”のように指定してみたところ無効
だというメッセージが。
もしよろしければお教えくださいませんでしょうか。
どうも。マニアックなネタにコメントをありがとうございます。
Access上で使う場合は、いわゆるウェブ上ではないので、申請をする場合のURLは、http://localhost/でOKです。
早速のご返事ありがとうございます。
教えていただいた通り、http://code.google.com/intl/ja/apis/maps/signup.html
にてhttp://localhost/と指定しましたところ、
”要求されたページは無効です”と表示されてしまいました。
Googleアカウントにログインしてから同じことを試してみましたが
やはり無効とでました。
私がなにか手順を勘違いしているのでしょうか・・。
自分でも調べてみますね、お手数おかけしました。
どうも、Houhouさん。
試しに今、やってみましたが、問題なく取得できました。以下スクリーンショット
http://virtual.haru.gs/blogup/src/ge0348.png
Google Accountでログインした状態で取得しています。手順は間違えていないと思います。ブラウザの問題かもしれませんね。
ちなみに自分は、FireFox 3.5を使っています。
今一度検証してみると、
IE8, Safari, FireFox, Google Cromeの4つで試してみたところ、ログインしない状態で取得しようとすると、Houhouさんと同じ現象になりました。
また、JavaScript OFFでも同様で、ブラウザの問題であり手順の問題じゃないと思われます。
もし取得できなければ、捨てアカウントでも結構なので、コードの乗っているページを送りますので、その際はまたメールアドレスを教えていただければお送りいたします。