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

Vous avez lu gratuitement 0 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer � vous proposer des publications.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer � vous proposer des publications.