VBA : Afficher/Cacher le ruban à la demande

Cette fois-ci je vous livre l’une de mes astuces que j’utilise systématiquement dans toutes mes applications : Afficher/Cacher le ruban à la demande.

La méthode est simple, une variable globale permet de fixer l’état du ruban. Un raccourci dans une macro Autokey permet de changer l’état du ruban et une fonction VBA affiche ou cache le ruban suivant l’état de la variable.

Option Compare Database 
Option Explicit 

Dim StateRibbon As Boolean 

Function DisplayRibbon() 
' Auteur : Fabrice CONSTANS (MVP) 
' Description : Affiche/cache le ruban 
' ctrl+shift+R 
Nz StateRibbon, False  
' 1er passage initialise à faux 
' (ribbon invisible) 
DoCmd.ShowToolbar "Ribbon", IIf(StateRibbon, acToolbarNo, acToolbarYes) 
StateRibbon = Not StateRibbon  ' inverse la valeur 

End Function

Le raccourci :

+^{R}  ExecuterCode DisplayRibbon()

Cacher le ruban permet de cacher également les boutons Restaurer/ Fermer ce qui donne une touche professionnelle à l’application.

Bonne utilisation !

VBA : Connaître le nom du formulaire/état et le contrôle actif

Dans la rubrique d’assistance à la maintenance d’application voici un bout de code à coupler à une macro  AutoKeys.

Lorsque vous devez intervenir sur une vieille application ou une application volumineuse, ce code vous rendra le service de ne pas avoir à chercher le formulaire et le contrôle actif parmi les multitudes de bibliothèques et de formulaires ou états. Cerise sur le gâteau si vous ouvrez l’éditeur VBA vous serez automatiquement positionné sur son module.

Son fonctionnement est simple ; Il repère le nom retourné par Screen.Activeform et Screen. Activecontrole et essaye de trouver le code dans le VBE components.

Function msgNameBase() 
' Auteur : Fabrice CONSTANS MVP 
' Description : renvoie le nom : de l'objet, de la base pour l'objet 
' actif 
On Error GoTo Err_msgNomBase 

Dim strNomBase As String 
Dim sCurfrm As String, sExt As String 
Dim sCurControle As String 
Dim i As Integer 

sExt = "form_" ' c'est un formulaire par défaut. 
' recupère le nom du forms, si c'est un report ' il part en erreur (voir traitement des erreurs) 

sCurfrm = Screen.ActiveForm.Name 
sCurControle = Screen.ActiveControl.Name 

' si le nom n'existe pas (voir erreur) 
Curfrm = Application.VBE.VBProjects(i).VBComponents(sExt & _ sCurfrm).Name 
GoTo Exit_msgNomBase Err_msgNomBase: 

' TRAITEMENT POUR UN ETAT. 
If Err = 2475 Then 
   ' ce n'est pas un form (2476 ce n'est pas un report) 
   ' on capture le nom du report sCurfrm = Screen.ActiveReport.Name 
   ' le prefixe pour un report  
   sExt = "Report_" Resume Next 

   ' on continue 
ElseIf Err = 9 Then 
   'Erreur 
   i = i + 1 
   If i > Application.VBE.VBProjects.Count Then 
      MsgBox "Impossible de trouver " & sCurfrm & _ " dans l'application." 
      Exit Function 
   End If 

   Resume 
ElseIf Err > 0 Then 
   MsgBox "Erreur non prévue :" & Err.Number & "---" & _ Err.Description 
   Exit Function 
End If 
Exit_msgNomBase: 
MsgBox IIf(sExt = "form_", "Forms", "Report") & " : " & _ sCurfrm & vbCrLf & _ "Controle : " & sCurControle & vbCrLf & _ "Base : " & Application.VBE.VBProjects(i).Name 

End Function

L’intérêt est évidemment de pouvoir le déclencher n’importe quand dans l’IHM, c’est pour cela qu’il faut le coupler à une macro AutoKeys.

Bonne utilisation !

VBA : Désélection zone de liste

Lorsque vous utilisez une zone de liste sans sélection multiple, il peut arriver d’avoir besoin de désélectionner la ligne. Inutile de vous acharner sur la ligne sélectionnée avec votre souris, elle restera en surbrillance.

Je vous livre ici ma méthode pour enlever la sélection :

Dim itSel As Integer 

Private Sub Form_Open(Cancel As Integer) 
   'initialise à -1 pour ne pas perturber la première sélection 
   itSel = -1 
End Sub 

Private Sub Liste_Click() 
   'la selection est identique à la précédent 
   If Me.Liste.ListIndex = itSel Then 
      Me.Liste.ListIndex = -1 
      'on déselectionne itSel = -1 
   Else 
      'on fixe le choix pour la prochaine comparaison 
      itSel = Me.Liste.ListIndex 
   End If 
End Sub

La liste se nomme Liste. On déclare une variable globale au  formulaire, que l’on nomme itSel, elle permettra de conserver le précédent choix opéré, soit un entier positif pour une sélection et -1 pour la dé-sélection.

Sur l’ouverture du formulaire on considère que rien n’est sélectionné et on attribue la valeur -1 à itSel. Lorsqu’on clique sur la zone de liste, on vérifie si le clic correspond à la sélection en cours au moyen de la propriété ListIndex.

Cette propriété retourne un entier de 0 à x ou x est le dernier item de la liste. Lorsque qu’on attribue une valeur à ListIndex l’item correspond est sélectionné, par contre si l’on met -1 aucune ligne n’est sélectionnée.

Bonne utilisation !

ACCESS : Réparer un fichier accdb ou mdb

Avec Microsoft Access, il peut arriver d’avoir du code VBA lié aux formulaires ou aux états qui ne soit plus accessible ou qui provoque des erreurs inexplicables. C’est rageant ! Surtout que les moyens de réparation sont rares. Je vous livre ici une méthode qui, pour moi, a fait ses preuves dans de nombreux cas. Cela consiste à traiter le fichier avec deux commandes.

Attention vous devez traiter uniquement une copie de la base endommagée. C’est pour cette raison que le fichier est copié avant d’être traité.

Voici donc un batch (.cmd) qui peut être utilisé directement par Windows.

rem @echo off 
echo --------------- GUIDE D'UTILISATION -------------------------------- 
echo Copiez ce fichier dans le répertoire racine à traiter. 
echo Decompile et compacte le fichier. 
echo Enfoncé la touche Shift pour la première passe. 
echo -------------------------------------------------------------------- 
echo AUTEUR : FABRICE CONSTANS MVP 

copy %1 %1.sav 
SET NoExecuteApplication = "Oui" 
"C:\Program files\Microsoft Office\OFFICE14\MSACCESS.EXE" %1 /Decompile 
"C:\Program files\Microsoft Office\OFFICE14\MSACCESS.EXE" %1 /Compact 
SET NoExecuteApplication=

Faites-glisser la copie de votre application sur le batch en maintenant le shift appuyé pour éviter l’exécution du code. Lorsque la barre de progression d’Access est terminée fermez l’application pour démarrer le compactage. Vous décompilez (reconstruction des liens VBA) et compactez la base. Vous pouvez l’utilisé à partir de la version 97.

Notez que suivant la version d’Access vous devrez remplacer le chemin MSACCESS.EXE par le votre.

NoExecuteApplication permet à votre application de ne pas s’exécuter lors de ce traitement. Il faut dans l’application prévoir ce cas en utilisant ce code dans votre procédure de démarrage de l’application :

'debogage, decompil, compactage 
If Not Environ("NoExecuteApplication") = "" Then 
   'autres traitements possibles en post livraison 
   Application.Quit 
   'quitte 
End If

Bonne utilisation !

VBA : Fermeture en cascade des fenêtres de code

Mes développements me confrontent souvent à des applications volumineuses où le code prend une place importante. Dans ce cas, et tant que l’application n’est pas compilée (mde / accde), l’éditeur Visual Basic ou VBE (Alt-F11) ouvre toutes les fenêtres de code y compris celles des bibliothèques non compilées ou non protégées.

Ce comportement se produit également lors de l’exécution de l’application même si l’éditeur VBA n’est pas ouvert. Cela encombre la pile GDI jusqu’à saturation. J’ai donc créé un bout de code pour refermer les fenêtres de code.

Public Function CloseAllVbeWindows() 
' Auteur : Fabrice CONSTANS MVP 
' Ferme toutes les fenêtres du VBE 
' permet de réduire les handles GDI et d'éviter la saturation mémoire. 

   Dim i As Integer 
   Dim j As Integer 
   On Error Resume Next 
   For i = 1 To Application.VBE.VBProjects.Count 
      For j = 1 To Application.VBE.VBProjects(i).VBE.Windows.Count 
         If Application.VBE.VBProjects(i).VBE.Windows(j).Type = 0 Then 
            '_ 'Or Application.VBE.VBProjects(i).VBE.Windows(j).Type = 6 Then 
            ' les fenetres de code + la fenetre projet 
            Application.VBE.VBProjects(i).VBE.Windows(j).Close 
         End If 
      Next 
   Next 

   Exit Function 
End Function

Vous pouvez appeler cette procédure après le chargement de votre application ou sur une macro AutoKeys.

Bonne utilisation !

ACCESS : Contrôle OLE lié et application manquante

Dans les applications MS Access, il peut arriver d’avoir des contrôles OLE liés à des applications qui ne sont pas ou plus installées. Dans ce cas, toutes les tentatives d’interventions se soldent par le message :

Impossible de modifier cette propriété : elle est en lecture seule.

ou encore.

Le serveur OLE n'est pas inscrit. Pour l'inscrire, réinstallez-le.

Une seule méthode pour s’en débarrasser :

Clic-droit sur l’objet, Remplacer par…, Image

Un joli message s’affiche :

Vous ne pouvez pas annuler cette opération et ne pourrez plus modifier cet objet.

Cliquez sur Oui.

Votre objet est à nouveau accessible mais bien entendu, pas avec l’application originelle puisque celle-ci n’est pas installée.

Bonne utilisation !

VBA : Rechercher un mot dans toutes les requêtes

Les modifications d’une application conséquente sont souvent difficiles à réaliser, surtout dans le cas des requêtes. Dans ce billet je vous propose un bout de code pour rechercher un mot, complet ou non, dans toutes les requêtes d’un fichier MS Access.

Function SnifQuery(Optional strText As String = "") 
   On Error GoTo errSub 
   Dim db As DAO.Database 
   Dim qry As DAO.QueryDef 

   Set db = CodeDb 

   ' si rien n'est transmis on demande le mot 
   If strText = "" Then 
      strText = InputBox("Indiquez le mot à rechercher dans les requêtes." & _ 
           vbCrLf & "Ce mot peut être incomplet.", "Mot à rechercher", "") 
      If strText = "" Then Exit Function 
   End If 

   ' balaye toutes les requêtes 
   For Each qry In db.QueryDefs 
      'si on trouve le mot 
      If qry.sql Like "*" & strText & "*" Then 
         ' on ouvre la requête 
         DoCmd.OpenQuery qry.Name, acViewDesign 
      End If 
   Next 

   ' on est propre donc on ferme le chose dont on ne se sert plus. 
   Set qry = Nothing 
   Set db = Nothing 
   Exit Function 
   
   errSub: 
   Resume Next
 
End Function

Pour le lancement vous pouvez passer par la fenêtre Exécution de VBE ou encore créer une macro Autokeys.

  • Ouvrez une nouvelle macro.
  • Affichez la colonne Nom de macro.
  • Entrez le raccourci souhaité. Exemple +^{Q}
  • Dans la colonne Action sélectionnez ExécuterCode.
  • Indiquez dans le nom de la fonction SnifQuery().

Lorsque vous utiliserez Ctrl+Shift+Q la fonction sera appelée.

Attention ce bout de code ne fait pas de recherche dans les requêtes des bibliothèques.

Bonne utilisation !

VBA : Transformer du texte en numérique

Cette petite fonction sans prétention permet de transformer une chaine de caractères en valeur numérique. « Quoi de nouveau ! » me direz-vous. A la différence des fonctions natives de types Val(), CDbl() et autre, cette fonction épure tous les caractères non numérique en tenant compte du signe et du séparateur décimal.

Function fSupprimerAlpha(mValeur As Variant) As Variant '------------------------------------------------------ 
' Procedure   : fSupprimerAlpha / Function 
' Author      : fabrice CONSTANS (MVP) 
' Date        : 03/06/2012 ' Modified : 
' Description : épure une chaine de caractère pour retourner une valeur numérique 
'      tient compte du sép. décimal et des + et - 
' Parameters  : mValeur contient la valeur à transformer 
' Return Value : retourne une valeur numérique valide '------------------------------------------------------ 
Dim i As Integer 

   If IsNull(mValeur) Or Len(mValeur) = 0 Then 
      fSupprimerAlpha = Null 
      Exit Function 
   End If 

   ' à inverser suivant le type de séparateur utilisé 
    mValeur = Replace(mValeur, ",", ".") 
    ' supprime tous les caracteres alpha 
    For i = 1 To Len(mValeur) 
       ' tout ce qui n'est pas numérique sauf +,- et sepérateur dec. 
       If Not IsNumeric(Mid(mValeur, i, 1)) And _
            Not Mid(mValeur, i, 1) Like " *[,,.]*" And _ 
            Not Mid(mValeur, i, 1) Like "*[+,-]*" Then 
          ' remplace par un espace 
          mValeur = Replace(mValeur, Mid(mValeur, i, 1), " ") 
       End If 
    Next ' renvoi la nouvelle valeur sans les espaces 
    fSupprimerAlpha = Replace(mValeur, " ", "") 
End Function

Vous pouvez facilement y faire appel depuis une requête par exemple.

Bonne utilisation !

Astuce PC : Mes ports USB ne sont plus reconnus

Comme souvent le lecteur de cartes tout-en-un du poste de ma femme est en rideau. Les unités n’apparaissent pas sur le poste de travail. Après une recherche sur Internet je trouve une manip qui semble débile à sa lecture mais qui fait fureur tant les réponses positives sont nombreuses. Cette manipulation est très simple et ne nécessite aucune manipulation du système, et le plus curieux c’est qu’elle fonctionne !

  • Éteignez votre pc.
  • Mettez l’interrupteur de l’alimentation sur Off (à l’arrière du pc).
  • Débranchez le câble d’alimentation.
  • Sur portable débranchez la batterie.
  • Appuyez pendant 15 secondes sur le bouton de démarrage (oui sans n’avoir rien rebranché !).
  • Reconnectez votre câble d’alimentation.
  • Remettez l’interrupteur de l’alimentation sur On.
  • Démarrez votre pc.

Normalement les unités du lecteur de cartes sont revenus. Cette manipulation vide l’électricité résiduelle de la carte mère.

Bonne utilisation !

VBA : Formater une adresse postale

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

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, ";") 
   strA = StrConv(strAdresse, vbProperCase)
   'toutes les premieres lettres en majuscule
 
   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.

Bonne utilisation !