![]() | Je souhaiterais disposer d'une carte géographique (ou routière) sur laquelle je pourrais visualiser des lieux précis, épingler des points repères, les gérer, les afficher et les commenter à ma guise... et le tout sur Excel ! C'est un sujet qui ne manque pas d'intérêt, d'autant qu'une vraie solution permettrait de construire des applications originales au fin de présentation ou de gestion de tout ordre (gestion de clientèle, gestion de parc automobiles ou de matériel, etc...). Attention toutefois au respect des droits d'utilisation en cas d'applications commerciales notamment... |
Quels sont les éléments de base dont j'ai besoin ?
Si j'obtenais ces prérequis, quels sont les outils ou fonctionnalités dont j'aimerais disposer ?
Qui d'entre nous n'a jamais fait une recherche d'itinéraire sur des sites web comme ViaMichelin ou Mappy par exemple ?
Vous l'avez deviné… c'est ce type de carte qui conviendrait à ce projet !
Mais peut-on obtenir l'équivalent sur Excel et le piloter par VBA ?
La réponse est oui ! Mais il convient toutefois de noter que :
Virtual Earth ou la Cartographie selon Microsoft
Présentation de l'outil et préparatifs
A l'instar de Google avec Google Maps, Microsoft met à disposition de tous, Virtual Earth, un outil de localisation géographique développé pour ses services "Windows Live". C'est cet API contrôle de carte qui a attiré mon attention. Les cartes présentées souffrent toutefois d'un léger défaut : elles sont en version anglophone. Bien que ce ne soit pas trop gênant, lorsqu'on observe l'hexagone par exemple, on peut y voir ci et là, trois ou quatre noms de nos régions françaises traduits dans la langue de shakespeare...
Voici une démonstration fonctionnelle de Virtual Earth
vous pouvez naviguer sur la carte ci-dessous à l'aide la souris et zoomer avec la roulette ou en cliquant sur +/-
(il semble que les utilisateurs de Mac ne puissent voir cette démonstration que sous FireFox)
Par programmation, il est ensuite possible d'afficher des points repères personnalisés avec bulle d'info,
comme dans l'illustration ci-dessous.
On peut obtenir également la même chose en vue aérienne.
Cet outil de localisation géographique possède de très nombreuses possibilités en terme de paramétrages, de fonctions et méthodes disponibles. Pour cet article, je me contenterai d'en présenter uniquement les fonctions de base, je vous laisse explorer et tester le reste (je n'ai d'ailleurs pas encore tout exploré moi-même)...
Si vous possédez quelques notions HTML et Javascript, je vous conseille vivement de consulter le Virtual Earth Interactive SDK ainsi que Virtual Earth Map Control 5.0 de la library MSDN.
De part la conception de ce contrôle, l'affichage ainsi que le paramétrage de Virtual Earth sont gérés par JavaScripts. Seules quelques lignes de code HTML et JavaScript suffisent à assurer la connexion avec les scripts de contrôle Virtual Earth en ligne et donc à permettre ensuite le pilotage de l'outil par programmation.
Bien que mon objectif soit d'afficher les cartes géographiques directement dans un WebBrowser et de créer un projet VBA, le fichier d'initialisation HTML reste toutefois obligatoire et il faudra donc le créer sur le disque dur.
Je réduis cependant ce fichier HTML au strict nécessaire, et toutes les commandes dont j'aurai besoin pour mener à bien le projet pourront être générées par la suite, "à la volée", directement par code VBA.
src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=5">
var map = null;
function GetMap()
{
map = new VEMap('myMap');
map.LoadMap();
}
onload='GetMap();'>
ASTUCE
Au lieu de créer manuellement ce fichier "ve_connexion.html" sur le disque dur, il est également possible de le générer directement à l'aide de VBA à l'ouverture du classeur Excel (création dans le répertoire de l'application ou dans un répertoire temporaire), puis de le supprimer en fin de session. Cette solution a l'avantage de permettre la distribution d'un seul et unique fichier XLS, mais aussi d'être certain que le fichier d'initialisation HTML sera bien présent au bon endroit. Le travail devient ainsi plus propre et plus sûr.
J'utilise d'ailleurs cette solution dans l'application mDF XLmap développée en parallèle de cet article...
Les préparatifs sont maintenant terminés, je vais pouvoir me consacrer au classeur Excel et son projet VBA.
Le Classeur Excel et son projet VBA
Dans le répertoire spécialement réservé pour ce projet, je vais maintenant créer un classeur Excel nommé "ExempleVirtualEarth.xls".
Direction l'éditeur VBE (ALT + F11), je vais construire l'interface de mon application.
Dans le projet, j'insère donc un Userform, les contrôles et propriétés suivants :
Contrôles | Name | Caption | Left | Top | Width | Height |
Userform | Userform1 | Exemple d'utilisation de l'API Virtual Earth | - | - | 650 | 445 |
WebBrowser | WebBrowser1 | - | 6 | 6 | 500 | 410 |
CommandButton | btnZPlus | Zoom + | 516 | 162 | 54 | 18 |
CommandButton | btnZMoins | Zoom - | 588 | 162 | 48 | 18 |
CommandButton | btnCentrer | Centrer la carte (sur France) | 516 | 186 | 120 | 18 |
CommandButton | btnAjout | Ajouter un repère au centre | 516 | 258 | 120 | 18 |
CommandButton | btnRaz | Effacer les points repères | 516 | 282 | 120 | 18 |
CommandButton | btnAdr | Atteindre une adresse | 516 | 318 | 120 | 18 |
CommandButton | btnQuit | Quitter | 516 | 396 | 120 | 18 |
CheckBox | chkNav | Navigateur intégré | 522 | 216 | 90 | 15 |
CheckBox | chkMini | Mini carte | 522 | 234 | 90 | 15 |
OptionButton | optKms | Echelle en Kilomètres | 522 | 348 | 105 | 15 |
OptionButton | optMil | Echelle en Miles | 522 | 366 | 105 | 15 |
Ce qui devrait donner quelque chose comme ceci :
Le code VBA
En premier, je crée une procédure pour charger et afficher le Userform et je l'associe à un bouton (ou une image) placé sur la feuille de calcul. J'utilise une simple fonction Dir() pour vérifier la présence du fichier d'initialisation HTML (qui devrait être dans le même dossier que le classeur Excel). Cette procédure contient le code suivant :
Dim FichierHtml As String
FichierHtml = ThisWorkbook.Path & "ve_connexion.html"
'Vérifier l'existence du fichier d'intialisation HTML avant lancement
If Dir(FichierHtml) <> "" Then
UserForm1.Show
Else
MsgBox "Le fichier """ & FichierHtml & """ est introuvable !" _
& vbLf & vbLf & "Opération annulée.", vbOKOnly, "myDearFriend!"
End If
Le module de code du Userform :
Dans le module de code du Userform cette fois, je crée l'évènement Initialize(). C'est ici que je fais le lien entre le contrôle WebBrowser et l'API Virtual Earth. Au chargement du USF, la méthode Navigate va lire le fichier d'initialisation Html et lancer ainsi la connexion avec le contrôle de carte :
Private Sub UserForm_Initialize()
'Connexion au contrôle de carte en ligne
WebBrowser1.Navigate ThisWorkbook.Path & "ve_connexion.html"
End Sub
Je le disais plus haut : « l'API Virtual Earth se pilote à l'aide de commandes ou fonctions JavaScript ».
Pour lancer des fonctions JavaScript depuis VBA, il convient d'utiliser la méthode DHTML execScript qui s'applique à l'objet window (dans le cas présent, cet objet sera la fenêtre contenant le document web).
Cela se fait de cette façon :
La méthode execScriptWebBrowser1.Document.parentWindow.execScript "LaFonction();", "Javascript"
LaFonction(); est ici une chaîne de caractères représentant la fonction JavaScript à exécuter.
Comme je vais devoir lancer plusieurs fonctions JavaScript dans cette application, et pour clarifier le code VBA au maximum, je crée une procédure qui assurera la bonne syntaxe lors de chaque appel :
Private Sub EnvoiScript(Js As String)
WebBrowser1.Document.parentWindow.execScript Js, "Javascript"
End Sub
Ainsi, lorsque je voudrai lancer une Fonction() JavaScript depuis mon module de code, il me suffira simplement d'appeler la procédure EnvoiScript et de lui passer la chaîne de commande en argument, comme ceci :
EnvoiScript "LaFonction();"
Je m'occupe maintenant des évènements associés à chaque contrôle du Userform.
Je commence par les contrôles CommandButton :
Private Sub btnZPlus_Click()
EnvoiScript "map.ZoomIn();"
End Sub
Private Sub btnZMoins_Click()
EnvoiScript "map.ZoomOut();"
End Sub
Private Sub btnCentrer_Click()
'Permet de re-centrer l'affichage de la carte dans le WebBrowser sur
'des coordonnées Latitude/Longitude prédéterminées et de définir un zoom (valeur de 1 à 19)
EnvoiScript "map.SetCenterAndZoom(new VELatLong(47.010225655683485, 2.3291015625000036), 6);"
End Sub
Par défaut, lors de la connexion le contrôle de carte Virtual Earth présente le territoire américain. Peut-être voudriez-vous voir afficher l'hexagone dès l'ouverture du Userform au lieu des Etats-Unis ? Dans ce cas, plusieurs solutions peuvent être envisager, mais la solution la plus simple reste d'insérer directement les coordonnées Latitude/Longitude souhaitées dans la méthode LoadMap() que l'on trouve dans le fichier d'initialisation Html.
Dans ce fichier, on pourra donc remplacer :
map.LoadMap() par map.LoadMap(new VELatLong(47.010225655683485, 2.3291015625000036), 6);
Private Sub btnAjout_Click()
Dim T As String
'Ajouter un point repère (Pushpin) au centre de la carte
T = "var shape = new VEShape(VEShapeType.Pushpin, map.GetCenter());" _
& "shape.SetTitle('Exemple de point repère');" _
& "shape.SetDescription('Ceci est le symbole de point repère par défaut "_
& "fourni par Virtual Earth');" _
& "map.AddShape(shape);"
EnvoiScript T
End Sub
Private Sub btnRAZ_Click()
'Supprime tous les repères "épinglés" sur la carte
EnvoiScript "map.DeleteAllShapes();"
End Sub
Private Sub btnAdr_Click()
Dim T As String
'Rechercher et afficher un lieu en fonction de l'adresse saisie dans une InputBox
T = "Saisissez une adresse complète pour optimiser les chances de résultat. Les éléments " _
& vbLf & "[Numéro et nom de rue] , [Code Postal et Ville] , [Pays]" _
& vbLf & "doivent être saisis dans l'ordre et séparés par une virgule." _
& vbLf & vbLf & "Exemple :" _
& vbLf & "7 rue de la liberté,21000 dijon,france"
T = InputBox(T, "Atteindre un lieu...")
If T <> "" Then
'Attention, ici l'apostrophe remplace les guillemets dans les instructions JavaScript.
'Aussi, si l'adresse saisie contient une apostrophe, il convient de faire précéder cette
'dernière par un caractère pour éviter un plantage du script. Et pour assurer une
'compatibilité avec Excel97, j'utilise la fonction de feuille de calcul Substitute()
'au lieu de la fonction Replace().
T = Application.Substitute(T, "'", "'")
'On emploie la méthode "Find()" pour rechercher l'adresse.
'Syntaxe :
'VEMap.Find(what, where, findType, shapeLayer, startIndex, numberOfResults,
'showResults, createResults, useDefaultDisambiguation, setBestMapView, callback);
EnvoiScript "map.Find(null, '" & T & "');"
End If
End Sub
Private Sub btnQuit_Click()
Unload Me
End Sub
Je passe ensuite aux contrôles de type Checkbox :
Private Sub chkNav_Click()
'Affiche ou supprime le navigateur Web interne
EnvoiScript IIf(chkNav.Value, "map.ShowDashboard();", "map.HideDashboard();")
End Sub
Private Sub chkMini_Click()
'Affiche ou supprime la mini carte de navigation
EnvoiScript IIf(chkMini.Value, "map.ShowMiniMap();", "map.HideMiniMap();")
End Sub
Je termine maintenant par les deux derniers contrôles de type OptionButton du Userform.
Private Sub optKms_Click()
EnvoiScript "map.SetScaleBarDistanceUnit(VEDistanceUnit.Kilometers);"
End Sub
Private Sub optMil_Click()
EnvoiScript "map.SetScaleBarDistanceUnit(VEDistanceUnit.Miles);"
End Sub
Eh bien, mon projet de test est maintenant terminé !
Evidemment, ces quelques procédures et méthodes ne représentent qu'une petite partie de ce qu'il est possible d'obtenir avec un tel outil. Mais personnellement, je trouve déjà ça assez bluffant !
Persuadé de l'intérêt de ce projet, j'espère vous avoir donné envie de poursuivre l'investigation sur ce sujet. Consultez et testez la documentation mise à votre disposition (voir les liens plus haut dans cet article).
Pour ma part, c'est décidé, je vais continuer à travailler dans cette voie qui, sur un support Excel, ouvre des perspectives innovantes et vraiment très intéressantes...
Cet article décrit en détail la création d'un projet Excel-VBA de test de géolocalisation grâce au contrôle de carte Virtual Earth de Microsoft.
mDF Exemple Virtual Earth : le projet décrit dans cet article et le code VBA correspondant accessible.