En-têtes de modules VBA

STephane

XLDnaute Occasionnel
bonjour,

Microsoft Visual Basic Editor permet l'insertion de lignes de déclarations dans les feuilles de code, mais à ma connaissance ne permet pas d'insérer un en-tête indiquant l'auteur, la date, le but, les fonctions/procédures utilisées ....

Des add-ins permettent cela mais sont plus ou moins bien et plus ou moins facilement paramétrables. Certains gèrent les modèles d'en-tête à l'aide de fichiers XML ou XSD, mais j'ai dû mal avec ça ;-)

Du coup, j'essaye pour le plaisir de bidouiller, voilà donc mes débuts.
Le principe fonctionne mais mes routines ratent la moitié des procédures.



Public Enum VBALineType
VBALine_Blank = 0
VBALine_Comment = 1
VBALine_LibraryFunction = 2
VBALine_Procedure = 3
VBALine_Function = 4
End Enum

Const TPL_DIVIDER_DASH = "'---------------------------------------------------------------------------------------"
Const TPL_MODULE_NAME = "' Module : "
Const TPL_MODULE_AUTHOR = "' Author : "
Const TPL_MODULE_DATE = "' Date : "
Const TPL_MODULE_PURPOSE = "' Purpose : "
Const TPL_MARKER2FIND = "Option Explicit" 'Used in procedure VBE_TPL_INSERT
Const TPL_FORMAT_DATE = "DDDD DD MMMM YYYY"
Private Sub DeleteDummyKeys(ByVal vsGUID As String, ByVal vsVersion As String)

Sub VBE_TPL_INSERT_DEMO()
Call VBE_TPL_INSERT(varWorkbook:=ThisWorkbook, DeleteOldLines:=True, InsertRoutinesList:=True) , ConcernedVBComponents:=Array("ThisWorkbook", "Module1"))
End Sub

'=========== LA PRINCIPALE PROCEDURE

Sub VBE_TPL_INSERT(Optional Marker2Find As String = TPL_MARKER2FIND, _
Optional DeleteOldLines As Boolean, _
Optional InsertRoutinesList As Boolean, _
Optional ConcernedVBComponents As Variant, _
Optional varWorkbook As Variant, _
Optional ModuleAuthor As String, _
Optional ModuleDate As Variant, _
Optional ModulePurpose As String, _
Optional LineAtTop As String = TPL_DIVIDER_DASH, _
Optional LineAtBottom As String = TPL_DIVIDER_DASH)
'Solution designed by STephane
'This solution requires the below constants
'Const TPL_DIVIDER_DASH = "'---------------------------------------------------------------------------------------"
'Const TPL_MODULE_NAME= "' Module : "
'Const TPL_MODULE_AUTHOR = "' Author : "
'Const TPL_MODULE_DATE = "' Date : "
'Const TPL_MODULE_PURPOSE = "' Purpose : "
'Const TPL_NAME = ""
'Const TPL_MARKER2FIND = "Option Explicit" 'Used in procedure VBE_TPL_INSERT
'Const TPL_FORMAT_DATE="DDDD DD MMMM YYYY"
Dim MarkerLine As Long 'ligne du délimiteur pour l'insertion du template
Dim MarkerFound As Variant 'pour rechercher le délimiteur
Dim CodeLines As String 'pour manipuler les lignes de code
Dim VBCompColl As New Collection 'collection de modules qui comprendra tous les modules du projet,
Dim ConcernedComponent As Variant ' ou bien ceux donnés à spécifier dans l'appel de la fonction
Dim VBCodeMod As VBIDE.CodeModule '
Dim VBCompModule As VBIDE.CodeModule '
Dim lstartline As Long, lcount As Long, LinesCnt As Long 'index & compteurs
'French comment : Le classeur traité est le classeur actif ou bien le classeur passé en paramètre.
'Si le paramètre est passé et de type chaîne, il faut intervenir pour créer la variable objet.
'English comment :
'The processed workbook is the active one or the parameter-passed workbook.
'In case the parameter is kind of string, we have to create the object variable.
If Not IsMissing(varWorkbook) And TypeName(varWorkbook) = "string" Then
Set varWorkbook = Workbooks(varWorkbook)
ElseIf IsMissing(varWorkbook) = True Then
Set varWorkbook = ActiveWorkbook
End If
'French comment : quelques instructions qui pourraient évoluer vers la gestion d'un éventuel modèle d'en-tête externe
'English comment : some instructions line that could evolve to manage external header template
Dim ExternalFile As Variant
If IsMissing(ExternalFile) Or IsEmpty(ExternalFile) Then
ModuleAuthor = TPL_MODULE_AUTHOR & IIf(ModuleAuthor <> "", ModuleAuthor, Application.UserName)
ModuleDate = TPL_MODULE_DATE & Application.WorksheetFunction.Proper(Format(IIf(IsMissing(ModuleDate) = False, ModuleDate, Date), TPL_FORMAT_DATE))
End If
'Trvail sur le projet visual Basic / Work on the visual basic project
With varWorkbook.VBProject

'French comment :
' détermination des modules à processer, soit tous soit ceux passés dans l'appel,
' et mémorisation dans une collection
'English comment :
' determining modules to be processed, either all of them, either these transmitted in the function call,
' and also memorizing them into a collection
If Not IsMissing(ConcernedVBComponents) Then
For Each ConcernedComponent In ConcernedVBComponents
Set VBCompModule = .VBComponents(ConcernedComponent).CodeModule
VBCompColl.Add Item:=VBCompModule
Next ConcernedComponent
Else
For Each ConcernedComponent In varWorkbook.VBProject.VBComponents
Set VBCompModule = ConcernedComponent.CodeModule
VBCompColl.Add Item:=VBCompModule
Next ConcernedComponent

End If

'French comment : boucle sur les fichiers à processer
'English comment : loop on modules to be processed
For Each VBCompModule In VBCompColl

With VBCompModule

CodeLines = LineAtTop & vbCr & _
TPL_MODULE_NAME & .Parent.name & vbCr & _
ModuleAuthor & vbCr & ModuleDate & vbCr & _
TPL_MODULE_PURPOSE & vbCr & LineAtBottom & vbCr & "'"

'Recherche de la chaîne avant laquelle insérer le modèle
'Finding the line before which the template is to be inserted
If Not IsMissing(Marker2Find) Then
For MarkerLine = 1 To .CountOfLines
MarkerFound = .Find(Marker2Find, MarkerLine, 1, .CountOfLines, -1) ' True, False, False)
If MarkerFound = True Then Exit For
Next
End If
If DeleteOldLines Then
If MarkerLine > 1 Then
LinesCnt = MarkerLine - 1
VBCompModule.DeleteLines 1, LinesCnt
MarkerLine = 1
End If
End If
'insérer le template s'il y a des lignes de déclaration
If .CountOfDeclarationLines = 0 Then GoTo nnext
'insérer le template
.InsertLines MarkerLine, CodeLines

'insertion de la liste de procédures
If InsertRoutinesList Then
MarkerLine = MarkerLine + 6 + 1 '6= nb de lignes du template
Call VBE_TPL_BuildRoutinesList(VBCompModule, MarkerLine)
End If
End With
nnext:
'Next i
Next VBCompModule
End With
End Sub
'========== FIN DE LA PROCEDURE



Function vbe_LineInfo(ModuleObject As VBIDE.CodeModule, TheLine As Long) As VBALineType
'Solution designed by STephane
Dim AllKinds As New Collection
AllKinds.Add vbext_pk_Get
AllKinds.Add vbext_pk_Set
AllKinds.Add vbext_pk_Let
AllKinds.Add vbext_pk_Proc
Dim LaLigne As String
LaLigne = ModuleObject.Lines(TheLine, 1)
If Trim(LaLigne) = vbNullString Then vbe_LineInfo = 0: Exit Function
If Left(Trim(LaLigne), 1) = "'" Then vbe_LineInfo = 1: Exit Function
If InStr(1, LaLigne, " Declare Function ") Then vbe_LineInfo = 2: Exit Function
For i = 1 To AllKinds.count
If Len(ModuleObject.ProcOfLine(TheLine, AllKinds(i))) Then
If InStr(1, LaLigne, " Function ") Then
vbe_LineInfo = 3
ElseIf InStr(1, LaLigne, " Sub ") Then
vbe_LineInfo = 4
End If
Exit Function
End If
Next i
End Function
Function VBE_TPL_BuildRoutinesList(ModuleObject As VBIDE.CodeModule, TheLine As Long) As Variant
'Dresser la liste des procédures et fonctions
Dim F_LF As Boolean, F_F As Boolean, F_P As Boolean
Dim ProcKind As VBIDE.vbext_ProcKind
Dim VBA_LibraryFunctions() As Variant
Dim VBA_Procedures() As Variant
Dim VBA_Functions() As Variant
Dim RoutinesList As Variant
Dim ProcName As String
Dim LineNum As Long
Dim DimArray As Long
On Error Resume Next
ReDim Preserve VBA_Functions(0)
ReDim Preserve VBA_LibraryFunctions(0)
ReDim Preserve VBA_Procedures(0)
With ModuleObject
'la liste généré est à incomplete, 2 facteurs peut-être :
' - le compte de lignes de déclaration
' - regarder du côté de vbe_lineinfo
For LineNum = 1 To .CountOfLines
ProcName = .ProcOfLine(LineNum, ProcKind)
If ProcName <> "" Then
Select Case vbe_LineInfo(ModuleObject, LineNum)
Case VBALine_Function
F_F = True
If IsEmpty(VBA_Functions(0)) = False Then _
ReDim Preserve VBA_Functions(UBound(VBA_Functions) + 1)
VBA_Functions(UBound(VBA_Functions)) = "'" & vbTab & ProcName
Case VBALine_LibraryFunction
F_LF = True
If IsEmpty(VBA_LibraryFunctions(0)) = False Then _
ReDim Preserve VBA_LibraryFunctions(UBound(VBA_LibraryFunctions))
VBA_LibraryFunctions(UBound(VBA_LibraryFunctions)) = "'" & vbTab & ProcName
Case VBALine_Procedure
F_P = True
If IsEmpty(VBA_Procedures(0)) = False Then _
ReDim Preserve VBA_Procedures(UBound(VBA_Procedures))
VBA_Procedures(UBound(VBA_Procedures)) = "'" & vbTab & ProcName
End Select
End If
Next LineNum
End With
RoutinesList = IIf(F_LF = True, "' Library Functions : <<" & vbCr & Join(VBA_LibraryFunctions, vbCr) & vbCr & "' >>" & vbCr, "") _
& IIf(F_F = True, "' Functions : <<" & vbCr & Join(VBA_Functions, vbCr) & vbCr & "' >>" & vbCr, "") _
& IIf(F_P = True, "' Procedures : <<" & vbCr & Join(VBA_Procedures, vbCr) & vbCr & "' >>" & vbCr & "'", "")
If RoutinesList <> "" Then
ModuleObject.InsertLines TheLine, RoutinesList
End If
End Function




j'avais aussi créé cette fonction
Function vbe_IsRoutineDeclaration(ModuleObject As VBIDE.CodeModule, TheLine As Long) As Boolean
'Solution designed by STephane
Dim AllKinds As New Collection
AllKinds.Add vbext_pk_Get
AllKinds.Add vbext_pk_Set
AllKinds.Add vbext_pk_Let
AllKinds.Add vbext_pk_Proc
For i = 1 To AllKinds.count
If Len(ModuleObject.ProcOfLine(TheLine, AllKinds(i))) Then
vbe_IsRoutineDeclaration = True
Exit Function
End If
Next i
End Function
 

G.David

XLDnaute Impliqué
Re : En-têtes de modules VBA

si il le fait grâce à une petite manip
outil
macro
nouvelle macro
renseigements( titre de la macro ; ce classeur)
arreter l'enregistrement
Alt F11 et devant nos zieux zéblouïs un module avec une macro

Code:
Sub une_entete()
'
' une_entete Macro
' Macro enregistrée le 12/09/2008 par DAVID Guy juste pour le fun ou pour le montrer
End Sub
'
'
'emploi des balises de code simplifie la lecture (au passage ) c'est # dans les icônes au-dessus de la fenêtre d'écriture et ça donne ça
Code:
Public Enum VBALineType
VBALine_Blank = 0
VBALine_Comment = 1
VBALine_LibraryFunction = 2
VBALine_Procedure = 3
VBALine_Function = 4
End Enum

Const TPL_DIVIDER_DASH = "'---------------------------------------------------------------------------------------"
Const TPL_MODULE_NAME = "' Module    : "
Const TPL_MODULE_AUTHOR = "' Author    : "
Const TPL_MODULE_DATE = "' Date      : "
Const TPL_MODULE_PURPOSE = "' Purpose   : "
Const TPL_MARKER2FIND = "Option Explicit"   'Used in procedure VBE_TPL_INSERT
Const TPL_FORMAT_DATE = "DDDD DD MMMM YYYY"
Private Sub DeleteDummyKeys(ByVal vsGUID As String, ByVal vsVersion As String)

Sub VBE_TPL_INSERT_DEMO()
Call VBE_TPL_INSERT(varWorkbook:=ThisWorkbook, DeleteOldLines:=True, InsertRoutinesList:=True) , ConcernedVBComponents:=Array("ThisWorkbook", "Module1"))
End Sub

'=========== LA PRINCIPALE PROCEDURE

Sub VBE_TPL_INSERT(Optional Marker2Find As String = TPL_MARKER2FIND, _
                   Optional DeleteOldLines As Boolean, _
                   Optional InsertRoutinesList As Boolean, _
                   Optional ConcernedVBComponents As Variant, _
                   Optional varWorkbook As Variant, _
                   Optional ModuleAuthor As String, _
                   Optional ModuleDate As Variant, _
                   Optional ModulePurpose As String, _
                   Optional LineAtTop As String = TPL_DIVIDER_DASH, _
                   Optional LineAtBottom As String = TPL_DIVIDER_DASH)
'Solution designed by STephane
'This solution requires the below constants
'Const TPL_DIVIDER_DASH = "'---------------------------------------------------------------------------------------"
'Const TPL_MODULE_NAME= "' Module    : "
'Const TPL_MODULE_AUTHOR = "' Author    : "
'Const TPL_MODULE_DATE = "' Date    : "
'Const TPL_MODULE_PURPOSE = "' Purpose    : "
'Const TPL_NAME = ""
'Const TPL_MARKER2FIND = "Option Explicit"   'Used in procedure VBE_TPL_INSERT
'Const TPL_FORMAT_DATE="DDDD DD MMMM YYYY"
Dim MarkerLine As Long      'ligne du délimiteur pour l'insertion du template
Dim MarkerFound As Variant           'pour rechercher le délimiteur
Dim CodeLines As String              'pour manipuler les lignes de code
Dim VBCompColl As New Collection     'collection de modules qui comprendra tous les modules du projet,
Dim ConcernedComponent As Variant    ' ou bien ceux donnés à spécifier dans l'appel de la fonction
Dim VBCodeMod As VBIDE.CodeModule    '
Dim VBCompModule As VBIDE.CodeModule '
Dim lstartline As Long, lcount As Long, LinesCnt As Long 'index & compteurs
'French comment : Le classeur traité est le classeur actif ou bien le classeur passé en paramètre.
'Si le paramètre est passé et de type chaîne, il faut intervenir pour créer la variable objet.
'English comment :
'The processed workbook is the active one or the parameter-passed workbook.
'In case the parameter is kind of string, we have to create the object variable.
If Not IsMissing(varWorkbook) And TypeName(varWorkbook) = "string" Then
        Set varWorkbook = Workbooks(varWorkbook)
ElseIf IsMissing(varWorkbook) = True Then
    Set varWorkbook = ActiveWorkbook
End If
'French comment : quelques instructions qui pourraient évoluer vers la gestion d'un éventuel modèle d'en-tête externe
'English comment : some instructions line that could evolve to manage external header template
Dim ExternalFile As Variant
If IsMissing(ExternalFile) Or IsEmpty(ExternalFile) Then
    ModuleAuthor = TPL_MODULE_AUTHOR & IIf(ModuleAuthor <> "", ModuleAuthor, Application.UserName)
ModuleDate = TPL_MODULE_DATE & Application.WorksheetFunction.Proper(Format(IIf(Is Missing(ModuleDate) = False, ModuleDate, Date), TPL_FORMAT_DATE))
End If
'Trvail sur le projet visual Basic / Work on the visual basic project
With varWorkbook.VBProject
    
'French comment :
'   détermination des modules à processer, soit tous soit ceux passés dans l'appel,
'   et mémorisation dans une collection
'English comment :
'   determining modules to be processed, either all of them, either these transmitted in the function call,
'   and also memorizing them into a collection
    If Not IsMissing(ConcernedVBComponents) Then
        For Each ConcernedComponent In ConcernedVBComponents
            Set VBCompModule = .VBComponents(ConcernedComponent).CodeModule
            VBCompColl.Add Item:=VBCompModule
        Next ConcernedComponent
    Else
        For Each ConcernedComponent In varWorkbook.VBProject.VBComponents
            Set VBCompModule = ConcernedComponent.CodeModule
            VBCompColl.Add Item:=VBCompModule
        Next ConcernedComponent
        
    End If
    
'French comment : boucle sur les fichiers à processer
'English comment : loop on modules to be processed
    For Each VBCompModule In VBCompColl
        
        With VBCompModule
            
            CodeLines = LineAtTop & vbCr & _
                TPL_MODULE_NAME & .Parent.name & vbCr & _
                ModuleAuthor & vbCr & ModuleDate & vbCr & _
                    TPL_MODULE_PURPOSE & vbCr & LineAtBottom & vbCr & "'"
            
            'Recherche de la chaîne avant laquelle insérer le modèle
            'Finding the line before which the template is to be inserted
            If Not IsMissing(Marker2Find) Then
                For MarkerLine = 1 To .CountOfLines
                    MarkerFound = .Find(Marker2Find, MarkerLine, 1, .CountOfLines, -1) ' True, False, False)
                    If MarkerFound = True Then Exit For
                Next
            End If
                If DeleteOldLines Then
            If MarkerLine > 1 Then
                LinesCnt = MarkerLine - 1
                VBCompModule.DeleteLines 1, LinesCnt
                MarkerLine = 1
            End If
        End If
        'insérer le template s'il y a des lignes de déclaration
        If .CountOfDeclarationLines = 0 Then GoTo nnext
       'insérer le template
        .InsertLines MarkerLine, CodeLines
        
        'insertion de la liste de procédures
        If InsertRoutinesList Then
        MarkerLine = MarkerLine + 6 + 1 '6= nb de lignes du template
             Call VBE_TPL_BuildRoutinesList(VBCompModule, MarkerLine)
        End If
      End With
nnext:
'Next i
Next VBCompModule
End With
End Sub
'========== FIN DE LA PROCEDURE
 
 
 
Function vbe_LineInfo(ModuleObject As VBIDE.CodeModule, TheLine As Long) As VBALineType
'Solution designed by STephane
Dim AllKinds As New Collection
AllKinds.Add vbext_pk_Get
AllKinds.Add vbext_pk_Set
AllKinds.Add vbext_pk_Let
AllKinds.Add vbext_pk_Proc
Dim LaLigne As String
LaLigne = ModuleObject.Lines(TheLine, 1)
If Trim(LaLigne) = vbNullString Then vbe_LineInfo = 0: Exit Function
If Left(Trim(LaLigne), 1) = "'" Then vbe_LineInfo = 1: Exit Function
If InStr(1, LaLigne, " Declare Function ") Then vbe_LineInfo = 2: Exit Function
For i = 1 To AllKinds.count
    If Len(ModuleObject.ProcOfLine(TheLine, AllKinds(i))) Then
        If InStr(1, LaLigne, " Function ") Then
            vbe_LineInfo = 3
        ElseIf InStr(1, LaLigne, " Sub ") Then
            vbe_LineInfo = 4
        End If
        Exit Function
    End If
Next i
End Function
Function VBE_TPL_BuildRoutinesList(ModuleObject As VBIDE.CodeModule, TheLine As Long) As Variant
'Dresser la liste des procédures et fonctions
Dim F_LF As Boolean, F_F As Boolean, F_P As Boolean
Dim ProcKind As VBIDE.vbext_ProcKind
Dim VBA_LibraryFunctions() As Variant
Dim VBA_Procedures() As Variant
Dim VBA_Functions() As Variant
Dim RoutinesList As Variant
Dim ProcName As String
Dim LineNum As Long
Dim DimArray As Long
On Error Resume Next
ReDim Preserve VBA_Functions(0)
ReDim Preserve VBA_LibraryFunctions(0)
ReDim Preserve VBA_Procedures(0)
With ModuleObject
'la liste généré est à incomplete, 2 facteurs peut-être :
'   - le compte de lignes de déclaration
'   - regarder du côté de vbe_lineinfo
    For LineNum = 1 To .CountOfLines
        ProcName = .ProcOfLine(LineNum, ProcKind)
        If ProcName <> "" Then
            Select Case vbe_LineInfo(ModuleObject, LineNum)
                Case VBALine_Function
                    F_F = True
                    If IsEmpty(VBA_Functions(0)) = False Then _
                        ReDim Preserve VBA_Functions(UBound(VBA_Functions) + 1)
                    VBA_Functions(UBound(VBA_Functions)) = "'" & vbTab & ProcName
                Case VBALine_LibraryFunction
                    F_LF = True
                    If IsEmpty(VBA_LibraryFunctions(0)) = False Then _
                        ReDim Preserve VBA_LibraryFunctions(UBound(VBA_LibraryFunctions))
                    VBA_LibraryFunctions(UBound(VBA_LibraryFunctions)) = "'" & vbTab & ProcName
                Case VBALine_Procedure
                    F_P = True
                    If IsEmpty(VBA_Procedures(0)) = False Then _
                        ReDim Preserve VBA_Procedures(UBound(VBA_Procedures))
                    VBA_Procedures(UBound(VBA_Procedures)) = "'" & vbTab & ProcName
            End Select
        End If
    Next LineNum
End With
RoutinesList = IIf(F_LF = True, "' Library Functions : <<" & vbCr & Join(VBA_LibraryFunctions, vbCr) & vbCr & "' >>" & vbCr, "") _
& IIf(F_F = True, "' Functions : <<" & vbCr & Join(VBA_Functions, vbCr) & vbCr & "' >>" & vbCr, "") _
& IIf(F_P = True, "' Procedures : <<" & vbCr & Join(VBA_Procedures, vbCr) & vbCr & "' >>" & vbCr & "'", "")
If RoutinesList <> "" Then
   ModuleObject.InsertLines TheLine, RoutinesList
End If
End Function
autrement plus lisible non?
surtout sur gros travail
Cordialement
G.David
 
Dernière édition:

STephane

XLDnaute Occasionnel
Re : En-têtes de modules VBA

bonjour,

oui G.David je le savias pour le module, merci de me rappeler au bon usage de la balise Code, c'est sûr que sinon c'est pas très lisible.

MZTools est un outil que je connaissais avec quelques très bonnes fonctions. Je l'ai installé il y a qlq temps mais j'ai pas eu envie de creuser le système de templates.

bonne journée
 

STephane

XLDnaute Occasionnel
Re : En-têtes de modules VBA

Version plus complète en pièce jointe.
Opérationnelle mais boguée.
Cela semble bien fonctionner si l'instruction "option explicit" existe déjà.

L'insertion risque de se passer au milieu des lignes de commentaires et déclarations déjà existantes en haut du module, voire en plein milieu.

Autres points :
  • Le tri des procédures n'est pas encore faite.
  • La liste des déclarations de librairies n'est pas opérationnelle.
  • La gestion d'un template externe n'est pas faite, elle serait envisageable pour le cartouche principale mais pas pour la liste des procédures & fonctions, à moins de passer par un XML.
 

Discussions similaires

Statistiques des forums

Discussions
312 216
Messages
2 086 351
Membres
103 195
dernier inscrit
martel.jg