EXCEL :: CLASS_LIBRARY_TOOLS_V1.0 - Classes utilitaires - Fichier Log, Gestion de pile d'exécution, isExists, Paramètres, Collection, Dictionnaire

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

oguruma

XLDnaute Impliqué
Bonjour le Forum,
ci-joint un classeur Excel dans lequel vous trouverez une série de classes utilitaires. Certaines sont déjà connues car elles sont utilisées dans les différentes livraisons d'utilitaires en téléchargements que j'ai effectué. En particulier Cls_CollectionParameters, SpeedMacro, Cls_MessagesDialog.
1746206899476.png

Les nouvelles classes :
Cls_LogFile : combinée avec Cls_LogFileDefine : elle permet d'implémenter un fichier log afin de tracer les traitements
Cls_StackModule : elle permet d'empiler et de dépiler les différents appels de procédures et de fonctions. En cas d'erreur il suffit de dépiler le contenu de la pile afin de savoir par où sont passés les traitements. En effet sauf erreur, VBA ne dispose pas de fonctions qui renvoie la procédure active au moment de son exécution.
Cls_ObjectExists : cette classe comporter quelques fonctions permettant de tester la présence de fichiers, de dossiers, d'objets comme les tableaux, les shapes, les graphiques, les TCD, les connexions PowerQuery
Cls_ToolsString : cette classe complète les fonctions Left et Right. Elle a l'avantage de pouvoir préciser un délimiteur/séparateur texte et aussi de faire la recherche dans les deux sens via le suffixe Back

Test des différentes classes dans l'onglet DEMOs
1746207417688.png



Cls_LogFile

Il est possible d'afficher la log générée dans une fenêtre
1746207555288.png

1746207675836.png

et dans un fichier
1746207590767.png


[02-05-2025 19:20:30] : Initialisation de la log
[02-05-2025 19:20:30] : Fichier log D:\DATA\10__DEVELOPPEMENTS__EXCEL__LABS\§__LAB14_TOOLS\$LIBMAC_FILELOG$2025_05_02.log
[02-05-2025 19:20:30] : Ligne 1
[02-05-2025 19:20:30] : Ligne 2
[02-05-2025 19:20:30] : Ligne 3

Afin que cette log soit activée il est nécessaire d'implémenter un tableau de paramètres comme suit
1746207710471.png


Cls_StackModule

1746207826056.png

1746207847024.png

1746207867462.png


1746207902380.png

1746207927061.png


En cas de répétition de modules cas des appels récursifs un index est créé comme -§0001 suffixé au nom du module
1746208009136.png

1746208023601.png


le module5 ne figure plus dans la pile

1746208037481.png

1746208050744.png


tous les appels au module1 ne figurent plus dans la pile

Dans la manière de procéder (voir le code de démonstration) il suffit d'appeler la fonction avec le nom de la procédure à empiler et de dépiler à la sortie de la procédure - bien entendu cela suppose un peu de rigueur dans votre code et de ne pas oublier de dépiler à chaque sortie ou d'empiler à chaque entrée

cas avec une provocation d'erreur
1746208482100.png
1746208496424.png
1746208507721.png

1746208520663.png
1746208533828.png

1746208547825.png

==> l'erreur a eu lieu à l'étape 3 c'est la dernière qui a été empilée et donc conservée car c'est la gestion d'erreur qui a pris le relai.

Pour le reste des tests voir les boutons dans l'onglet ainsi que le code de test et les classes

VB:
Option Explicit

Const FILELOG As String = "$LIBMAC_FILELOG$"

Private pWb_MACRO As Workbook
Private pFileNameLog As String
Private pLogFileCollection As Collection
Private pObjLogLine As Cls_LogFileDefine
Private pLogFileStatusOK As Boolean
Private pNbLines As Long


Private Sub Class_Initialize()
    Dim oParamLog As Cls_CollectionParameters
   
    Set oParamLog = New Cls_CollectionParameters
    Call oParamLog.Imp_Parameters_Instanciate
   
    ' On va récupérer le paramètre d'activation
    If UCase(oParamLog.Imp_Parameters_GetParameter("LOGFILE")) = "OUI" Then
        pLogFileStatusOK = True
    Else
        pLogFileStatusOK = False
    End If
   
    ' Si la log est active on initialise la collection qui va contenir la log
    If pLogFileStatusOK Then
        Set pWb_MACRO = ThisWorkbook
        pFileNameLog = ThisWorkbook.Path & "\" & FILELOG & Format(Now, "yyyy_mm_dd") & ".log"
        Set pLogFileCollection = New Collection
        If pLogFileStatusOK Then InitLog
    End If
End Sub

Property Get FileNameLog()
    FileNameLog = pFileNameLog
End Property

Property Get isLogActive()
    isLogActive = pLogFileStatusOK
End Property

Property Get NbLines()
    NbLines = pNbLines
End Property

Sub AddLogLine(hLogLine As Variant)
    If pLogFileStatusOK Then
        Set pObjLogLine = New Cls_LogFileDefine
        pObjLogLine.sTimeStamp = "[" & Format(Now, "dd-mm-yyyy hh:mm:ss") & "] : "
        pObjLogLine.sDescription = hLogLine
        pLogFileCollection.Add pObjLogLine, Key:=CStr(pLogFileCollection.Count + 1)
        pNbLines = pNbLines + 1
    End If
End Sub

Function GetLog() As Variant
    If pLogFileStatusOK Then
        Dim vLog As Variant
        Dim idx As Long
        ReDim vLog(0)
        idx = -1
        For Each pObjLogLine In pLogFileCollection
            idx = idx + 1
            ReDim Preserve vLog(idx)
            vLog(idx) = pObjLogLine.sTimeStamp & pObjLogLine.sDescription
        Next
        GetLog = vLog
    End If
End Function

Sub GetLogToFrm()
    If pLogFileStatusOK Then
        Dim sLog As String
        For Each pObjLogLine In pLogFileCollection
            sLog = sLog & pObjLogLine.sTimeStamp & pObjLogLine.sDescription & vbLf
        Next
        frm_SCRIPT.Caption = pFileNameLog
        frm_SCRIPT.txt_SCRIPT.Value = sLog
        frm_SCRIPT.Show 1
    End If
End Sub

Sub GetLogToFile()
    If pLogFileStatusOK Then
        Dim sLog As String
        Dim iFp As Integer
        iFp = FreeFile
        Close
        Open pFileNameLog For Output As iFp
        For Each pObjLogLine In pLogFileCollection
            sLog = pObjLogLine.sTimeStamp & pObjLogLine.sDescription
            Print #iFp, sLog
        Next
        Close
    End If
End Sub

Sub InitLog()
    If pLogFileStatusOK Then
        Call AddLogLine("Initialisation de la log")
        Call AddLogLine("Fichier log " & pFileNameLog)
    End If
End Sub

Private Sub Class_Terminate()
    Set pLogFileCollection = Nothing
    Set pObjLogLine = Nothing
End Sub

VB:
Option Explicit

Public sTimeStamp As String
Public sDescription As String

VB:
Option Explicit


Private pWb_MACRO As Workbook
Private pStack As Object

Private Sub Class_Initialize()
    Set pWb_MACRO = ThisWorkbook
    Set pStack = CreateObject("Scripting.Dictionary")
End Sub

Sub Push(hKey As String, Optional hValue As String)
    Const DELIM = "-§"
    If Not pStack.exists(hKey) Then
        pStack.Add hKey, hValue
    Else
        pStack.Add hKey & DELIM & Right("0000" & CStr(pStack.Count), 4), hValue
    End If
End Sub

Sub Pop(hKey As String)
    If pStack.exists(hKey) Then
        pStack.Remove (hKey)
    End If
End Sub

Sub PopAll(hKey As String)
    Const VERSION = 5
    Const DELIM = "-§"
    Dim sKey As String
    Dim vStack As Variant
    Dim iLenStack As Integer
    Dim iPos As Integer
    For Each vStack In pStack
        iPos = InStr(1, vStack, DELIM)
        If iPos > 0 Then
            sKey = Left(vStack, Len(vStack) - VERSION - 1)
        Else
            sKey = vStack
        End If
        If hKey = sKey Then
            If pStack.exists(vStack) Then
                pStack.Remove (vStack)
            End If
        End If
    Next
End Sub

Function GetStackToString(Optional hSep As String = " ") As String
    Dim szStack As String
    Dim vStack As Variant
    GetStackToString = ""
    For Each vStack In pStack
        szStack = szStack & hSep & vStack
    Next
    GetStackToString = Trim(szStack)
End Function

Function getCount() As Integer
    getCount = pStack.Count
End Function

Sub ClearStack()
    Set pStack = Nothing
End Sub

Private Sub Class_Terminate()
    Set pStack = Nothing
End Sub

VB:
Option Explicit

Function StringLeft(hSourceString As String, hSearchString As String) As String
    Dim iPos As Integer
    iPos = InStr(hSourceString, hSearchString)
    If iPos > 0 Then iPos = iPos - 1
    StringLeft = Left(hSourceString, iPos)
End Function

Function StringRight(hSourceString As String, hSearchString As String) As String
    Dim iPos As Integer
    Dim iStart As Integer
    Dim iLen As Integer
    iPos = InStr(hSourceString, hSearchString)
    iLen = Len(hSourceString)
    iStart = iLen - iPos
    StringRight = Right(hSourceString, iStart)
End Function

Function StringLeftBack(hSourceString As String, hSearchString As String) As String
    Dim sSourceStringBack As String
    Dim sSearchStringBack As String
    Dim sTurnBack As String
    Dim iPos As Integer
    Dim iNdx As Integer
    Dim iLengthString As Integer
    Dim iStartString As Integer
    Dim sTmpResult As String

    For iNdx = Len(hSourceString) To 1 Step -1
        sSourceStringBack = sSourceStringBack & Mid(hSourceString, iNdx, 1)
    Next
    For iNdx = Len(hSearchString) To 1 Step -1
        sSearchStringBack = sSearchStringBack & Mid(hSearchString, iNdx, 1)
    Next
    iPos = InStr(sSourceStringBack, sSearchStringBack)
    iLengthString = Len(sSourceStringBack)
    iStartString = iLengthString - iPos
    sTmpResult = Right(sSourceStringBack, iStartString)
    For iNdx = Len(sTmpResult) To 1 Step -1
        sTurnBack = sTurnBack & Mid(sTmpResult, iNdx, 1)
    Next
    StringLeftBack = sTurnBack
End Function
 
Function StringRightBack(hSourceString As String, hSearchString As String) As String
    Dim sSourceStringBack As String
    Dim sSearchStringBack As String
    Dim sTurnBack As String
    Dim iPos As Integer
    Dim iNdx As Integer
    Dim iLengthString As Integer
    Dim iStartString As Integer
    Dim sTmpResult As String

    For iNdx = Len(hSourceString) To 1 Step -1
        sSourceStringBack = sSourceStringBack & Mid(hSourceString, iNdx, 1)
    Next
    For iNdx = Len(hSearchString) To 1 Step -1
        sSearchStringBack = sSearchStringBack & Mid(hSearchString, iNdx, 1)
    Next
    iPos = InStr(sSourceStringBack, sSearchStringBack)
    If iPos > 0 Then iPos = iPos - 1
    sTmpResult = Left(sSourceStringBack, iPos)
    For iNdx = Len(sTmpResult) To 1 Step -1
        sTurnBack = sTurnBack & Mid(sTmpResult, iNdx, 1)
    Next
    StringRightBack = sTurnBack
 End Function

VB:
Option Explicit

'**********************************************************************
'* Vérifie si la feuille existe
'**********************************************************************
Public Function isWkExists(hWb As Workbook, hWKName As String) As Boolean
    Dim wkItem As Worksheet
    isWkExists = False
    For Each wkItem In hWb.Worksheets
        If UCase(wkItem.Name) = UCase(hWKName) Then
            isWkExists = True
            Exit For
        End If
    Next
End Function

'**********************************************************************
'* Enumère tous les objets du classeur actif
'**********************************************************************
Function enumWbListObjects(hWb As Workbook, Optional hToString As Boolean = -1, Optional hSep As String = " ") As Variant
    Dim objItem As ListObject
    Dim sName As String
    Dim vResult As Variant
    Dim wk As Worksheet
    Dim idx As Integer
    If hToString Then
        vResult = ""
    Else
        ReDim vResult(0)
    End If
    idx = -1
    For Each wk In hWb.Worksheets
        For Each objItem In wk.ListObjects
            If hToString Then
                vResult = vResult & hSep & objItem.Name
            Else
                idx = idx + 1
                ReDim Preserve vResult(idx)
                vResult(idx) = objItem.Name
            End If
        Next
    Next
    enumWbListObjects = vResult
End Function

'**********************************************************************
'* Vérifie si l'objet existe dans la feuille Worksheet
'**********************************************************************
Function isObjectExists(hWk As Worksheet, hObjame As String) As Boolean
    Dim objItem As Object
    isObjectExists = False
    For Each objItem In hWk.ListObjects
        If UCase(objItem.Name) = UCase(hObjame) Then
            isObjectExists = True
            Exit For
        End If
    Next
End Function

'**********************************************************************
'* Vérifie si l'objet existe dans le classeur
'**********************************************************************
Function isObjectWbExists(hWb As Workbook, hObjame As String) As Boolean
    Dim objItem As Object
    Dim wk As Worksheet
    isObjectWbExists = False
    For Each wk In hWb.Worksheets
        For Each objItem In wk.ListObjects
            If UCase(objItem.Name) = UCase(hObjame) Then
                isObjectWbExists = True
                Exit For
            End If
        Next
    Next
End Function

'*****************************************************************************
'* Vérifie si l'objet existe dans la feuille Worksheet en passant une chaine
'*****************************************************************************
Function isObjectWkStringExists(hWb As Workbook, hWk As String, hObjame As String) As Boolean
    Dim objItem As Object
    Dim oWk As Worksheet
    isObjectWkStringExists = False
    If isWkExists(hWb, hWk) Then
        Set oWk = hWb.Worksheets(hWk)
        For Each objItem In oWk.ListObjects
            If UCase(objItem.Name) = UCase(hObjame) Then
                isObjectWkStringExists = True
                Exit For
            End If
        Next
    End If
End Function

'**********************************************************************
'* Vérifie si le champ nommé existe
'**********************************************************************
Function isExistsRange(hRange As String) As Boolean
    Dim wb As Workbook
    Dim v As Name
    isExistsRange = False
    Set wb = ActiveWorkbook
    For Each v In wb.Names
        If v.Name = hRange Then
            isExistsRange = True
            Exit Function
        End If
    Next
End Function

'**********************************************************************
'* Enumère les requêtes de connexion dans une feuille
'**********************************************************************
Function enumWkQueriesConnection(hWk As Worksheet, Optional hPos As Integer = 11, Optional hToString As Boolean = -1) As Variant
    Dim oListObject As ListObject
    Dim oQueryTable As QueryTable
    Dim sName As String
    Dim vResult As Variant
    Dim idx As Integer
    If hToString Then
        vResult = ""
    Else
        ReDim vResult(0)
    End If
    idx = -1
    If hWk.ListObjects.Count > 0 Then
        For Each oListObject In hWk.ListObjects
            Set oQueryTable = Nothing
            On Error Resume Next
            Set oQueryTable = oListObject.QueryTable
            On Error GoTo -1
            If Not oQueryTable Is Nothing Then
                sName = hWk.Parent.Queries(Mid(oListObject.QueryTable.WorkbookConnection.Name, hPos)).Name
                If hToString Then
                    vResult = vResult & " " & sName
                Else
                    idx = idx + 1
                    ReDim Preserve vResult(idx)
                    vResult(idx) = sName
                End If
            End If
        Next
    End If
    enumWkQueriesConnection = vResult
End Function

'**********************************************************************
'* Enumère les requêtes de connexion dans un classeur
'**********************************************************************
Function enumWbWkQueriesConnection(hWb As Workbook, Optional hPos As Integer = 11, Optional hToString As Boolean = -1, Optional hSep As String = " ") As Variant
    Dim oListObject As ListObject
    Dim oQueryTable As QueryTable
    Dim wk As Worksheet
    Dim sName As String
    Dim sfullname
    Dim vResult As Variant
    Dim idx As Integer
    If hToString Then
        vResult = ""
    Else
        ReDim vResult(0)
    End If
    idx = -1
    For Each wk In hWb.Worksheets
        If wk.ListObjects.Count > 0 Then
            For Each oListObject In wk.ListObjects
                Set oQueryTable = Nothing
                On Error Resume Next
                Set oQueryTable = oListObject.QueryTable
                On Error GoTo -1
                If Not oQueryTable Is Nothing Then
                    sfullname = oListObject.QueryTable.WorkbookConnection.Name
                    sName = wk.Parent.Queries(Mid(oListObject.QueryTable.WorkbookConnection.Name, hPos)).Name
                    If hToString Then
                        vResult = vResult & hSep & sName & " (" & sfullname & ")"
                    Else
                        idx = idx + 1
                        ReDim Preserve vResult(idx)
                        vResult(idx) = sName
                    End If
                End If
            Next
        End If
    Next
    enumWbWkQueriesConnection = vResult
End Function

'**********************************************************************
'* Vérifie si la requête PowerQuery Existe
'**********************************************************************
Function isExistsWbWorkbookQuery(hWb As Workbook, hName As String) As Boolean
    Dim oWbQuery As WorkbookQuery
    isExistsWbWorkbookQuery = False
    For Each oWbQuery In hWb.Queries
        If hName = oWbQuery.Name Then
            isExistsWbWorkbookQuery = True
            Exit For
        End If
    Next
End Function

'**********************************************************************
'* Vérifie si le tableau a requête PowerQuery
'**********************************************************************
Function isExistsQueryTable(hWb As Workbook, hWk As String, hQueryTable As String) As Boolean
    Dim oListObject As ListObject
    Dim oQueryTable As QueryTable
    Dim wk As Worksheet
    isExistsQueryTable = False
    Set oQueryTable = Nothing
    Set oListObject = Nothing
    If isWkExists(hWb, hWk) Then
        Set wk = hWb.Worksheets(hWk)
        If isObjectExists(wk, hQueryTable) Then
            Set oListObject = ThisWorkbook.Worksheets(hWk).ListObjects(hQueryTable)
            On Error Resume Next
            Set oQueryTable = oListObject.QueryTable
            If Not oQueryTable Is Nothing Then
                isExistsQueryTable = True
            End If
        End If
    End If
    On Error GoTo -1
End Function

'**********************************************************************
'* On vérifie si le fichier existe
'**********************************************************************
Function isFileExists(szFile As String) As Boolean
    Dim oFSO As Object
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    isFileExists = oFSO.FileExists(szFile)
End Function

'**********************************************************************
'* On vérifie si le dossier existe
'**********************************************************************
Function isFolderExists(szFolder As String)
    Dim oFSO As Object
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    isFolderExists = oFSO.FolderExists(szFolder)
End Function

'**********************************************************************
'* On vérifie si le dossier existe - autre méthode
'**********************************************************************
Function isFolderExists2(sDossier As String)
    If sDossier <> "" And Len(Dir(sDossier, vbDirectory)) > 0 Then
       isFolderExists2 = True
    Else
       isFolderExists2 = False
    End If
End Function

'**********************************************************************
'* On vérifie si le TCD existe dans le classeur
'**********************************************************************
Function isTCDWbExists(hWb As Workbook, hTCD As String)
    Dim oPivotTable As PivotTable
    Dim wk As Worksheet
    isTCDWbExists = False
    For Each wk In hWb.Worksheets
        For Each oPivotTable In wk.PivotTables
            If UCase(oPivotTable.Name) = UCase(hTCD) Then
                isTCDWbExists = True
                Exit For
            End If
        Next
    Next
End Function

'**********************************************************************
'* On vérifie si la shape existe dans le classeur
'**********************************************************************
Function isShapeWbExists(hWb As Workbook, hShape As String)
    Dim oShape As Shape
    Dim wk As Worksheet
    isShapeWbExists = False
    For Each wk In hWb.Worksheets
        For Each oShape In wk.Shapes
            If oShape.Name = hShape Then
                isShapeWbExists = True
                Exit For
            End If
        Next
    Next
End Function

'**********************************************************************
'* On vérifie si le graph existe dans le classeur
'**********************************************************************
Function isChartObjectWbExists(hWb As Workbook, hChart As String)
    Dim oChartObject As ChartObject
    Dim wk As Worksheet
    isChartObjectWbExists = False
    For Each wk In hWb.Worksheets
        For Each oChartObject In wk.ChartObjects
            If oChartObject.Name = hChart Then
                isChartObjectWbExists = True
                Exit For
            End If
        Next
    Next
End Function
 

Pièces jointes

Dernière édition:
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Réponses
1
Affichages
2 K
Retour