Syntaxe VBA : ‘.’ vs. ‘!’

Êtes-vous adepte du Dot (.) ou du Bang (!) dans vos syntaxes VBA ? Connaissez-vous la différence entre les 2 ? Dans cet article nous allons essayer d’y voir plus clair.

Un peu d’histoire pour comprendre

Bang (!) le séparateur historique

En 1992, lorsque Access est paru, il n’y avait que 2 possibilités pour automatiser les processus :

  • Les Macros
  • Les expressions
  • Access Basic dérivé de Visual Basic, qui deviendra avec Access 2.0 le célèbre VBA.

Pour accéder aux composants des formulaires et des états, le séparateur adopté fut le point d’exclamation (Bang en anglais). Toute la documentation Access Basic se résumant au manuel de programmation d’Access indiquait le Bang (!) comme séparateur.

Le Dot (.) modernise Access Basic

En version 2.0 d’Access le point (. Dot) fait son apparition et avec lui une fonctionnalité très attendue : L’autocomplétion.

Cette liste de membres ajoute du confort au développement en VBA et permet aux plus curieux une exploration des modèles objets utilisés.
Il faut au préalable avoir coché son utilisation dans VBE/Outils/Options :

Le F2 (explorateur d’objets) vient complété cette offre de service.

Bang ! vs. Dot .

On l’aura compris pour avoir une bonne maitrise du code et une courbe d’autoformation améliorée, l’utilisation du Dot (.) est à privilégier.
Doit-on abandonner le Bang pour autant ? La réponse est clairement Non !
Il a une signification, il désigne l’élément (méthode/propriété) par défaut de certaines classes.

'Code exemple
Dim rst as dao.Recordset
Set rst = currentdb.openrecordset("Select id, nom, prenom From tClient;", dbopensnapshot)

'cette syntaxe 
debug.print rst.fields("nom").value
' est equivalente à celle-ci
debug.print rst!nom.value

Avec l’Explorateur d’Objets de VBA (F2) on peut vérifier si un membre est déclaré « par défaut ».

Le point bleu sur l’icône + l’intitulé « Membre par défaut » dans la description du membre.

Utilisation de Bang (!) et ses exceptions

L’utilisation du Bang (!) dans les collections pourrait être simple s’il ne souffrait pas de quelques exceptions.
La collection Form et Report indique que « Controls » (collection des controls) est le membre par défaut. Mais étrangement il peut aussi désigner la colonne d’une table ou d’une requête indiqué dans la source du formulaire ou de l’état si celle-ci n’a pas de « Control » (zone de texte, zone de liste…) liée.

Autrement dit pour une source du formulaire comme ceci :

SELECT id, nom, prenom FROM tClient;

Où seul Nom et Prénom aurait leur zone de texte insérée dans le formulaire/état on pourrait très bien utiliser le Bang (!) dans VBA pour faire référence à Id qui lui n’a pas de « Control ».

'fonctionne
Me!Id
'ne fonctionne pas
Me.Id

Conclusion

L’utilisation du Dot (.) est donc primordial pour travailler avec VBA. D’ailleurs lorsqu’on regarde les problèmes remontés dans les forums sur du code qui provoque des erreurs du type « Membre inconnu » on remarque souvent que le Bang (!) est employé à tous les étages.

Certain diront que le code verbeux est proscrire mais il s’agit d’une habitude qui permet plusieurs années après la conception de mieux s’y retrouver. C’est pour cela que je n’emploie le Bang (!) que pour son exception, jamais pour le le membre par défaut.

Et vous, quelle habitude avez-vous et qu’utilisez vous majoritairement ?
Est-ce que ce billet va vous faire changer vos habitudes ?

VBA : Split()

Split() est une fonction pratique et largement utilisée. A partir d’une chaine de texte elle renvoie un objet Tableau (Array) composé de ses éléments en utilisant le séparateur désigné.

Par exemple :

Dim monTexte as String
Dim monTableau as Variant
montexte = "Bonjour je suis Sam"

monTableau = Split(montexte, " ")

Dans l’exemple ci-dessus le tableau montableau contiendra :
montableau(0) >> « Bonjour »
montableau(1) >> « je »
montableau(2) >> « suis »
montableau(3) >> « Sam »

On peut donc utiliser un boucle (Do, While, For) pour parcourir le tableau, comme on peut utiliser l’indice comme c’est fait dans la liste précédente.

Split renvoie un objet tableau, Split() est un tableau

Si Split est un tableau on peut l’utiliser en tant que tel sans l’affecter à une variable.
Dans l’exemple suivant on récupère directement l’item du tableau.

Dim monPrenom as String
monPrenom = Split(montexte, " ")(3)

La variable monPrenom vaudra :
monPrenom >> « Sam »

Le paramètre (3) accolé directement à la fonction Split() peut vous paraitre étrange au premier regard pourtant ce n’est ni plus ni moins que l’indice du tableau.

Split et conclusion

Lorsqu’on veut récupérer une valeur et que l’on connait avec certitude sa position, utiliser cette syntaxe est plus rapide, cependant lorsqu’on veut utiliser plus d’une valeur l’utilisation classique est plus performante.

ACCESS : Filtrer une zone de liste déroulante à l’appuie d’une touche.

Dans ce petit billet nous allons mettre en œuvre un système de filtrage d’une zone de liste déroulante en temps réel. Pour cela nous avons besoin d’une table et d’un formulaire contenant une zone de liste déroulante.

La liste déroulante

Créer une liste déroulante dont le nom sera « lmFiltre », puis réglons quelques propriétés pour quelle affiche les données de la table. Pour l’exemple j’utilise la table système MSysObjects.

Contenu : SELECT [MSysObjects].[Id], [MSysObjects].[Name] FROM MSysObjects;
Nbre colonnes : 2
Largeurs colonnes : 0cm;2,54cm

La colonne Name sera visualisée et le filtre agira sur celle-ci.

Le code VBA

Allez sur la propriété « Sur touche relâchée » cliquez que le bouton de création et sélectionnez Générateur de code et entrez le code suivant :

Private Sub lmFiltre_KeyUp(KeyCode As Integer, Shift As Integer)
'ce n'est pas un caractère A-Z a-z (à affiner) ni un Espace
If (KeyCode < 64 Or KeyCode > 123) And Not KeyCode = 32 And Not Shift=1 Then
   strlist = ""
   Me.lmFiltre.RowSource = "SELECT MSysObjects.Id, MSysObjects.Name " & _ " FROM MSysObjects;"
   Me.lmFiltre.Text = ""
Else
   strlist = strlist & Chr(KeyCode) 'ajoute la touche pressée
   Me.lmFiltre.RowSource = "SELECT MSysObjects.Id, MSysObjects.Name " & _ " FROM  MSysObjects where MSysObjects.Name like """ & strlist & "*"";"
End If
End Sub

Pour le fonctionnement nous avons besoin de déclarer une variable publique au formulaire. Placez-vous juste après les premières lignes d’option du module de formulaire.

Option Compare Database
Option Explicit

Dim strlist As String

Comment ça fonctionne ?

A chaque touche appuyée et relâchée, l’évènement « Sur souris relâchée » est invoqué. Le code (KeyCode) de la touche est analysé.
Si c’est 27, soit la touche Echap, on vide le filtre contenu dans strListe et on affecte à la source la requête d’origine ; sans la condition Where.
Si le code est compris entre 64 et 123 (caractère a-z A-Z, chiffres virgule…) on ajoute le code sous forme de caractère ( Chr(KeyCode) ) à la liste et on applique le filtre.
La condition Where utilise un Like. On peut modifier le comportement du filtre en agissant sur les « jokers » du Like.

Conclusion

Voilà c’est posé, il n’y a plus qu’à compiler et tester.

Avertissement

Ce code montre une méthode mais n’est pas parfait, en effet certains caractères ne sont pas pris en compte comme les caractères accentués. A vous de jouer pour les ajouter.

VBA : Débogage, les bonnes pratiques (1)

Dans cette série de billets nous allons délivrer des conseils, détailler des techniques et mettre en pratique le débogage au travers d’exemples simples.

Introduction

Le débogage est l’action de suivre le déroulement du code pour en observer le comportement et corriger des problèmes ou bugs. Tout développement passe par cette phase dont la durée varie suivant la maîtrise du langage.
La facilité de débogage est proportionnelle à la simplicité du code. Faites un code simple, efficace et vous aurez d’autant plus de facilité à le déboguer.

Qu’est-ce que VBE ?

VBE est l’acronyme de Visual Basic Editor, soit l’éditeur Visual Basic Application commun à tous les produits de la suite Office et autre produit intégrant le langage de programmation VBA. C’est avec lui que nous allons travailler tout au long de ces billets.

On y accède au choix après l’ouverture d’un fichier Access :
·         Avec la combinaison de touches Alt + F11,
·         En ouvrant un nouveau module ou un existant,
·         En ouvrant ou créant un événement du type [Procédure Evènementielle] d’un formulaire/état.
·         Pour les versions récentes via le ruban Créer/ Autre /Menu Macro/ Module ou Module de classe.

Cet éditeur comporte un menu, des barres d’outils ainsi que plusieurs fenêtres.

L’interface de VBE disponibles dans chaque produit VB-Like.

Nous allons aborder tour à tour chacune d’elles au fur et à mesure de notre besoin.

Premiers réglages : Réduire les risques d’erreurs

Le débogage commence avant l’écriture de la moindre ligne de code. En effet, au-delà de la bonne connaissance du produit il existe quelques précautions à prendre pour limiter le risque d’erreurs de codage. Il faut en premier lieu utiliser les meilleurs réglages de l’éditeur VB (Visual Basic Editeur, VBE).

Les réglages de VBE

Avant de commencer l’écriture de la moindre ligne de code vous devez vous assurer des réglages des options de l’éditeur VB.

Réglage de l’éditeur

Vérification automatique de syntaxe

Cette option est intéressante lorsque vous débutez car elle vous signale les erreurs lors du changement de ligne et vous propose un accès à la rubrique d’aide la plus adéquate pour résoudre le problème.
Dans le cas d’une erreur sur la ligne, la ligne apparait en rouge. Si la vérification automatique de syntaxe est active, le mot clef posant problème est signalé et un message d’erreur s’affiche.

Avec la vérification automatique de syntaxe :

Lorsque le curseur n’est plus sur la ligne comportant l’erreur.

Erreur de compilation avec la vérification active.

Sans la vérification :

Erreur de compilation sans la vérification active.

Activée ou non la ligne apparaitra en rouge si elle comporte une erreur, la différence est uniquement sur l’affichage ou non du message.

Lorsque vous faites de la concaténation de texte, comme des requêtes SQL dans le code (les plus intégristes me traiteront d’hérétique), ou de la copie de code cette option peut vite devenir agaçante. Personnellement je désactive cette option.

Déclaration des variables obligatoires

Vivement conseillée en toute circonstance, cette option permet d’ajouter sur tous les nouveaux modules, l’instruction Option Explicit en en-tête. Cela oblige le développeur à déclarer chaque variable avant son utilisation. Vous réduisez ainsi les erreurs liées aux mauvais noms de variables souvent causées par des fautes de frappe.
Très fréquente, cette erreur conduit à un code qui ne plante pas mais qui ne fait pas ce qu’on lui demande. C’est souvent le plus difficile à déboguer.
Si vous avez déjà commencé à coder lorsque vous lisez ces lignes, il n’est pas trop tard pour ajouter cette option dans tous vos modules y compris ceux des formulaires et des états, cependant vous devrez le faire manuellement.
Cette instruction vient immédiatement après Option Compare.

Option Compare Database
Option Explicit

Notez qu’en l’absence de déclaration, une variable est de type Variant comme une variable déclaré sans type. Le type Variant est  très gourmand en mémoire.

Complément automatique des instructions

Cette option ajoute un confort et une rapidité en mettant à disposition la complétion de code. La complétion, souvent désignée sous le terme d’auto-complétion ou intellisense, se comporte de différentes manières.

1er cas d’utilisation

Lorsque vous saisissez un début d’instruction et que vous appuyez simultanément sur CTRL+Espace  plusieurs cas de figure peuvent se produire.
INFORMATION : Les cas sont ceux rencontrés avec les références standards.

Une seule correspondance

Il n’existe qu’une instruction possible, votre saisie est automatique complétée.
Entrez Doc et CTRL+Espace, le mot clé DoCmd s’affiche.

Plusieurs correspondances possibles

Il existe plusieurs instructions qui répondent à cette saisie. Une liste déroulante s’affiche, l’instruction choisie est celle qui correspond à la saisie.
Entrez Do et CTRL+Espace et la liste s’affiche.

La liste d’auto complétion

Utilisez les touches de déplacement et la tabulation pour valider ou la souri ou encore compléter le mot clef.
Pour annuler utilisez la touche Echap.

2ème cas d’utilisation

Lorsque vous utilisez le nom d’un objet ou d’une classe et que vous saisissez le point, la même liste déroulante s’ouvre avec les choix possibles pour cet objet.

Les méthodes et propriétés d’un objet connu.

3ème cas d’utilisation

Dans certains cas, comme la déclaration de variables typées, la complétion entre en action après avoir entré le mot clé AS.

Les types d’objets et autre énumération.

On rencontre aussi ce fonctionnement lorsque l’instruction saisie nécessite un paramètre Enum, La méthode « OpenRecordset » de DAO en est un parfait exemple. Voir le tutoriel sur les déclarations Enum ici.

Conclusion
Avec la complétion vous n’aurez plus d’excuses pour avoir inventé des noms de méthodes ou propriétés farfelues. Si vous êtes un peu curieux vous pourrez explorer les composants d’un objet, en action avec l’aide vous découvrirez ainsi de nouvelles méthodes et propriétés.

La complétion fonctionne également avec vos bibliothèques de fonctions, procédures et classes ainsi qu’avec les contrôles, propriétés et méthodes des formulaires et états.
La complétion ne fonctionne pas dans les cas suivants :
• Quand il y a une erreur identifiée (ligne en rouge) non corrigée.
• L’objet que vous utilisez n’existe pas (bibliothèque non référencée, nom farfelu…)
• L’objet n’est pas typé précisément (Late Binding) c’est le cas pour Variant et Object par exemple.

Notez que dans ce dernier cas vous pouvez utilisez la méthode « Early Binding » durant la conception, puis le transformer en « Late Binding » par la suite. Cette technique est décrite dans le billet traitant du Binding.

La complétion est donc essentielle pour éviter les fautes de frappe et l’utilisation de propriétés ou méthodes inexistantes et également dans le perfectionnement de votre apprentissage d’une bibliothèque.

Formater une adresse postale

Voici un petit code qui permet de formater une adresse postal. Il est à insérer en dessous des lignes d’options (Option Compare…) d’un module standard (pas dans le formulaire) :

Valeur saisie : 115, impasse de la petite reine
Valeur formatée : 115, Impasse de la Petite Reine

Const particules= " de ; du ; d'; des ; l'; la ; le ; les ; en " 
'rajouter les mots en minuscule à ne pas mettre en majuscule 

Public Function formatAdresse(strAdresse As Variant) As String 
Dim strA As String 
Dim arrParticules() As String 
Dim i As Long 

If IsNull(strAdresse) Then Exit Function 
'si c'est null on ne traite pas 
If strAdresse = "" Then Exit Function 
'si c'est vide on ne traite pas 

arrParticules = Split(particules, ";") 
'toutes les premieres lettres en majuscule 
strA = StrConv(strAdresse, vbProperCase) 
For i = 0 To UBound(arrParticules) 
    strA = Replace(strA, arrParticules(i), LCase(arrParticules(i))) 
    'supprime la majuscule 
Next 
formatAdresse = strA 

End Function

On renseigne la constante avec les mots que l’on ne veut pas mettre en majuscule.
1) le strconv() met toutes les 1ère lettre de chaque mot en majuscule.
2) la boucle For remplace les mots trouvés qui correspondent à ceux de la constante.

L’appel de la fonction

Sélectionner la zone de texte de l’adresse que j’ai nommé Adresse, l’évènement Après MAJ et mettre ceci :

Private Sub Adresse_AfterUpdate()     
    Me.Adresse.Value = formatAdresse(Me.Adresse.Value) 
End Sub

« Adresse » est le nom de la zone de texte. Elle doit être remplacée par le nom de celle que vous souhaitez traiter.

Tri d’enregistrements sur le contenu d’une zone de liste déroulante

Il est fréquent et même commun d’utiliser des listes déroulantes dans des formulaires.

Dans le cas où le contenu affiché n’est pas présent dans la source de données, il est difficile de faire un tri sur cette donnée.

Je vous livre ici une astuce qui va vous permettre de faire un tri de la source du formulaire à partir des données affichées dans la liste.

Admettons une liste nommée LmAdherent dont le champ affiché est nommé Nom_Adherent et provient d’une source externe au formulaire.

Dans ce cas sur l’évènement Sur Ouverture indiqué cette syntaxe :

Me.OrderBy = "[Lookup_LmAdherent].[Nom_Adherent]" 
Me.OrderByOn = True

Chaque fois que vous ouvrirez le formulaire, il apparaitra trié sur le contenu Nom_Adherent alors que cette données n’est pas contenu dans la source du formulaire.

Vous pouvez découvrir d’autre syntaxe en observant ce qui se passe dans la propriété OrderBy du formulaire lorsque vous utilisez le tri du menu contextuel.