IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

VBA : apprendre à créer et gérer le fichier de log d'une application Office
Un billet blog de Pierre Fauconnier

Le , par Pierre Fauconnier

0PARTAGES

Salut.

Il est courant de devoir consigner certains évènements survenant lors de l'utilisation d'une application, VBA ou autre, et ces données sont souvent écrites dans un fichier de log. Que ce soit à l'ouverture ou la fermeture du fichier, lorsque certaines erreurs surviennent, ou lors de manipulations délicates des données, conserver une trace de "ce qui s'est passé" est un bon moyen de pouvoir suivre l'utilisation d'une appli et de la déboguer rapidement lorsqu'un problème survient.

Le traçage d'un fichier Excel à l'aide d'un mouchard (??), l'historique d'un fichier, la liste des utilisateurs du fichiers et ce qu'on y fait (sélection d'une feuille que l'on pense inutilisée, par exemple, ...) sont des activités qui peuvent renseigner sur l'utilisation d'un fichier et donner des pistes d'améliorations intéressantes.

Cadre de travail

Dans ce billet, je généralisais l'écriture dans un fichier texte grâce à une procédure générique, de manière à ajouter de l'abstraction et à ne plus devoir se préoccuper de la technique d'écriture dans un fichier. En effet, devoir écrire dans un fichier texte requiert de savoir ouvrir un fichier (un "canal"), d'utiliser des instructions pour dire que l'on remplace le contenu ou que l'on en ajoute, sans oublier bien entendu de fermer le fichier après écriture. Tout cela peut être inclus dans une procédure au nom évocateur de WriteLinesInTextFile qui est appelée comme une instruction native du VBA et qui pourrait être stockée dans un module "Tools" comme je l'explique dans ce billet, puisque générique à VBA et donc, non spécifique à une techno particulière.

Code vba : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Sub WriteLinesInTextFile(Filename As String, Lines, Optional Replace As Boolean) 
  Dim Channel As Long 
  Dim i As Long 
  
  Channel = FreeFile 
  If Replace Then 
    Open Filename For Output As Channel 
  Else 
    Open Filename For Append As Channel 
  End If 
  For i = LBound(Lines) To UBound(Lines) 
    Print #Channel, Lines(i) 
  Next i 
  Close Channel 
End Sub
Code : Sélectionner tout
Tools.WriteLinesInTextFile "c:\data\temp\Monfichier.txt", Array("Pierre", "Martine", "Manon"), True
.

Cahier des charges

Poursuivons dans la systématisation de notre approche de programmation en formalisant l'écriture de logs lors de l'utilisation de notre application.

En général, un fichier de log est créé pour être aisément lisible. Ce sera donc souvent un simple fichier texte dons la ligne est structurée, plus rarement un CSV, même si ce format peut être pratique pour une exploitation rapide en Excel. Chaque développeur fera "à sa sauce" en la matière. Ce qui importe, c'est que le fichier soit exploitable et qu'il permette de savoir rapidement ce qui s'est passé dans l'appli. On pourrait ainsi avoir un fichier de log qui ne reprend que les erreurs survenues durant l'exécution, un log à l'ouverture et la fermeture, un log à l'enregistrement du fichier, etc...

Pour l'exemple, notre cahier des charges mentionne que l'on souhaite:
  • un log pour l'ouverture du fichier;
  • un log pour la fermeture du fichier;
  • un log pour la sauvegarde du fichier;
  • un log pour certaines erreurs que l'on veut pouvoir tracer;
  • le log reprendra également le moment du log, ainsi que l'utilisateur actif.


Création de la ligne de log

Regardons d'abord où et comment coder l'écriture du log.

Dans la mesure où le log dépend de l'application, il semblera normal que la fonction d'écriture du log se trouve dans le module de l'application. Fidèle à mes bonnes pratiques de codage et comme je le mentionne dans un billet de blog cité plus haut, mes développements contiennent un module appTools qui reprend des fonctions spécifiques de mon application (récupération de paramètres, version et date de l'application, nom de l'application à utiliser dans les msgbox, etc). Tout naturellement, j'insérerai dans ce module la fonction WriteLog qui reprendra les données prévues dans le cahier des charges.

Code vba : Sélectionner tout
1
2
3
4
5
6
7
8
9
Sub WriteLog(Message As String) 
  Dim DateLog As String 
  Dim FileName As String 
  
  DateLog = Format(Now, "yyyy-mm-ddThh:nn:ss") 
  FileName = ThisWorkbook.Path & "\" & Replace(ThisWorkbook.Name, ".", "_") & ".log" 
  Message = DateLog & " | " & Environ("username") & " | " & Message 
  Tools.WriteLinesInTextFile FileName, Array(Message), False 
End Sub

Normalement, cette fonction se passe de commentaires. Elle formate la ligne du log en reprenant le moment du log normalisé, le nom de l'utilisateur puis le message reçu en argument. Elle crée aussi le nom du fichier de log qui reprend le nom du fichier et lui ajoute l'extension .log. Lorsque la ligne de log est créée, la fonction appelle la fonction générique Tools.WriteLinesInTexteFile vue en début de billet. On remarque donc ici que le programmeur n'a pas besoin de savoir comment on écrit dans un fichier texte avec Open, Append, Close & Cie, il utilise la fonction de appTools qui elle-même utilise la fonction du Tools. On lui a donc bien permis de faire abstraction de toute la mécanique d'écriture.

Création des logs lors d'évènements ou à des moments clé de l'exécution

Il suffit maintenant au programmeur d'appeler la fonction appTools.WriteLog lors de la survenance d'évènements ou erreurs, ou à des passages clé du code. Pour coller au cahier des charges, voici les évènements de classeur qui doivent déclencher l'écriture d'un log. On remarque ici que l'on se contente de passer le message à WriteLog puisque c'est cette fonction qui va composer la ligne du log.

Code vba : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
Private Sub Workbook_BeforeClose(Cancel As Boolean) 
  appTools.WriteLog "Fermeture du fichier" 
End Sub 
  
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) 
  appTools.WriteLog "Enregistrement du fichier" 
End Sub 
  
Private Sub Workbook_Open() 
  appTools.WriteLog "Ouverture du fichier" 
End Sub

Voici également une erreur qui doit déclencher l'écriture du log (c'est, évidemment, pour l'exemple). On remarquera que comme le message est un peu particulier puisqu'il reprend le numéro et la description de l'erreur, on passe par un appTools.LogError qui utilise l'erreur active pour constituer le message qui sera envoyé à appTools.WriteLog qui lui même formatera la ligne pour l'envoyer à Tools.WriteLinesInTextFile.

Code vba : Sélectionner tout
1
2
3
4
5
6
7
8
Sub Test() 
  On Error GoTo Catch 
  
  Debug.Print 5 / 0 
  
Catch: 
  If Err <> 0 Then appTools.LogError 
End Sub
Code : Sélectionner tout
1
2
3
4
5
6
Sub LogError() 
  Dim Message As String 
   
  Message = Err.Number & " - " & Err.Source & " - " & Err.Description 
  WriteLog Message 
End Sub

Voici, pour l'exemple, le contenu du fichier Log après quelques utilisations (ouverture, erreur division par zéro, enregistrement, fermeture, puis à nouveau ouverture, et fermeture après travail et demande d'enregistrement lors de la fermeture).

Code text : Sélectionner tout
1
2
3
4
5
6
7
2021-09-16T20:22:41 | PierreFauconnier | Ouverture du fichier 
2021-09-16T20:33:44 | PierreFauconnier | 11 - VBAProject - Division par zéro 
2021-09-16T20:33:46 | PierreFauconnier | Enregistrement du fichier 
2021-09-16T20:33:53 | PierreFauconnier | Fermeture du fichier 
2021-09-16T20:35:29 | PierreFauconnier | Ouverture du fichier 
2021-09-16T20:38:15 | PierreFauconnier | Fermeture du fichier 
2021-09-16T20:38:18 | PierreFauconnier | Enregistrement du fichier


Conclusions

On remarque, à nouveau, qu'une approche systématique de nos développements nous permet de créer du code récupérable d'un projet à l'autre. La constitution de bibliothèques contenant VOS fonctions et procédures va vous permettre un gain de temps et une fiabilité accrue sur vos développements.

N'hésitez pas à commenter ce billet. C'est toujours intéressant d'avoir un retour sur mes astuces et bonnes pratiques

Une erreur dans cette actualité ? Signalez-le nous !