I. Introduction▲
L'éditeur de macros, aussi appelé Visual Basic Editor ou VBE, est l'environnement dans
lequel vous pouvez modifier les macros que vous avez enregistré, écrire de
nouvelles macros et de nouveaux programmes VBA.
L'éditeur VBE peut être modifié dynamiquement par macro. C'est l'objet de ce tutoriel.
Vous pouvez de cette manière automatiser:
* L'activation des références (Librairies).
* L'importation et l'exportation des modules.
* La création, modification ou suppression des macros dans vos classeurs.
* La création des objets par macros et leur associer des procédures évènementielles.
* Le déclenchement de macros.
La majeur partie des procédures utilisées nécessite d'activer la référence
Microsoft Visual Basic for Applications Extensibility 5.3.
Dans l'éditeur de macros (Alt+F11):
Menu Outils
Références
Cochez la ligne "Microsoft Visual Basic for Applications Extensibility 5.3"
Cliquez sur "OK" pour valider.
II. Informations générales▲
II-A. Quelques manipulations de base ▲
Pour commencer, voici quelques exemples simples pour manipuler l'éditeur de macros.
Récupérer la version VBE installée.
Sub afficherLaVersionVBE()
MsgBox Application.VBE.Version
End Sub
Ouvrir l'éditeur de macros (L'équivalent de Alt+F11).
Sub OuvreVBA()
Application.VBE.MainWindow.Visible = True
End Sub
Fermer l'éditeur de macros.
Sub FermeVBA()
Application.VBE.MainWindow.Visible = False
End Sub
Modifier le nom du projet (Le nom par défaut est "VBAProject").
Application.VBE.ActiveVBProject.Name = "MonProjet"
II-B. La propriété VBComponents▲
La propriété VBComponents renvoie la collection de composants contenue dans un projet.
* ThisWorkbook.
* L'ensemble des feuilles (CodeName).
* L'ensemble des modules Standards et modules de Classe.
* Les UserForm.
Voici deux méthodes pour lister les composants du classeur actif.
Sub boucleVBComponents_V01()
Dim i As Integer
For i = 1 To ActiveWorkbook.VBProject.VBComponents.Count
Debug.Print ActiveWorkbook.VBProject.VBComponents(i).Name
Next
End SubSub boucleVBComponents_V02()
Dim VBComp As VBComponent
For Each VBComp In ActiveWorkbook.VBProject.VBComponents
Debug.Print VBComp.Name
Next
End Sub
Remarque:
Lorsque vous devez spécifier le nom d'une feuille dans la propriété
VBComponents, il s'agit du
CodeName et pas le nom de l'onglet.
II-C. La propriété CodeModule▲
La propriété CodeModule permet de modifier, ajouter, supprimer ou renvoyer des informations
sur le contenu des procédures, pour chacun des composants.
Un exemple pour compter les lignes de macros dans chaque composant du classeur
actif.
Dim VBComp As VBComponent
Dim Mdl As CodeModule
For Each VBComp In ActiveWorkbook.VBProject.VBComponents
Set Mdl = VBComp.CodeModule
Debug.Print VBComp.Name & ": " & Mdl.CountOfLines
Next
II-D. Automatiser la numérotation des lignes▲
La fonction ERL permet de récupérer le numéro de ligne qui a provoqué une erreur
à condition d'avoir préalablement numéroté les lignes dans l'éditeur de macros.
L'exemple suivant renvoie 8.
Option Explicit
Sub laProcedure()
4 Dim x As Integer
6 On Error GoTo errHandler
8 x = 5 / 0 'provoque une erreur (division par zéro)
10 Exit Sub
11 errHandler:
12 MsgBox "Une erreur est survenue , Ligne : " & Erl() & _
vbCrLf & "Numéro d'erreur : " & Err.Number & vbCrLf & Err.Description
14 End Sub
Remarque:
* Si la ligne x = 5 / 0 n'est pas numérotée, la fonction ERL renvoie le numéro de la
derniere ligne précédant l'erreur (6).
* ERL renvoie 0 s'il n'y a pas d'erreur dans la procédure.
* ERL renvoie 0 si aucune ligne n'est numérotée dans la macro.
Vous allez me dire, Comment faire pour numéroter rapidement les lignes d'une macro
et ne pas être obligé de le faire manuellement?
Vous pouvez installer l'Add-In MZ-Tools
qui fait cela très bien.
Sinon, juste pour le fun, la procédure suivante Numérote les lignes de la macro "laProcedure"
dans le "Module1".
Option Explicit
Option Compare Text
Sub testAjout()
'"laProcedure" est la macro dont vous souhaitez numéroter les lignes
NumerotationLignesProcedure "Module1", "laProcedure"
End Sub
Sub NumerotationLignesProcedure(nomModule As String, nomMacro As String)
'
'Cet exemple ne gère pas les erreurs s'il existe déja une numérotation
'
Dim Debut As Integer, Lignes As Integer, x As Integer
Dim Texte As String, strVar As String
With ThisWorkbook.VBProject.VBComponents(nomModule).CodeModule
Debut = .ProcStartLine(nomMacro, 0)
Lignes = .ProcCountLines(nomMacro, 0)
End With
For x = Debut + 2 To Debut + Lignes - 1
With ThisWorkbook.VBProject.VBComponents(nomModule).CodeModule
Texte = .Lines(x, 1)
strVar = Application.WorksheetFunction.Substitute(Texte, " ", "")
strVar = Application.WorksheetFunction.Substitute(strVar, vbCrLf, "")
strVar = Application.WorksheetFunction.Substitute(strVar, vbTab, "")
'Adaptez les filtres en fonction de vos projets.
'Remarque: les arguments PrivateFunction et PublicFunction sont volontairement accolés.
'
If strVar <> "" And _
Left(strVar, 3) <> "Sub" And _
Left(strVar, 10) <> "PrivateSub" And _
Left(strVar, 9) <> "PublicSub" And _
Left(strVar, 8) <> "Function" And _
Left(strVar, 15) <> "PrivateFunction" And _
Left(strVar, 14) <> "PublicFunction" And _
Right(ThisWorkbook.VBProject.VBComponents(nomModule). _
CodeModule.Lines(x - 1, 1), 1) <> "_" _
Then .ReplaceLine x, x & " " & Texte
End With
Next
End Sub
Et une procédure pour supprimer la numérotation:
Sub testSuppression()
supprimeNumerotationLignes "Module1", "laProcedure"
End Sub
Sub supprimeNumerotationLignes(nomModule As String, nomMacro As String)
Dim Debut As Integer, Lignes As Integer, x As Integer
Dim Texte As String, strVar As String
Dim Valeur As Integer
With ThisWorkbook.VBProject.VBComponents(nomModule).CodeModule
Debut = .ProcStartLine(nomMacro, 0)
Lignes = .ProcCountLines(nomMacro, 0)
End With
For x = Debut + 2 To Debut + Lignes - 1
With ThisWorkbook.VBProject.VBComponents(nomModule).CodeModule
Texte = .Lines(x, 1)
Valeur = Val(Texte)
If Valeur <> 0 Then
strVar = Mid(Texte, Len(CStr(Valeur)) + 2)
Else
strVar = Texte
End If
.ReplaceLine x, strVar
End With
Next
End Sub
III. Les références et macros complémentaires▲
III-A. Les références▲
Ce chapitre montre comment manipuler les références par macros.
Les références, aussi appelées bibliothèques ou librairies, offrent de nombreuses
possibilités lorsqu'elles sont activées.
Quelques exemples d'utilisation parmi les nombreuses bibliothèques disponibles:
* Le modèle ADO (ActiveX Data Objects)
pour manipuler les bases de données.
* La librairie DSO
pour lire et modifier les propriétés des documents Office.
* La librairie Windows Image Acquisition
pour manipuler les images et gérer les WebCams.
* ...etc...
Vous pouvez aussi utiliser les références pour piloter d'autres applications:
par exemple Word,
Windows Media Player,
Outlook, Power Point...
Un exemple de procédure pour lister les références actives.
Dim Ref As Reference
For Each Ref In ThisWorkbook.VBProject.References
Debug.Print Ref.Name 'Nom
Debug.Print Ref.FullPath 'Chemin complet
Debug.Print Ref.Description 'Description de la référence
Debug.Print Ref.IsBroken 'Indique si la référence est manquante
Debug.Print Ref.Major & "." & Ref.Minor 'Version
Debug.Print "---"
Next Ref
Ajouter une référence dans votre projet.
'Ajoute la référence Outlook pour OfficeXP
Dim x As String
x = "C:\Program Files\Microsoft Office\Office10\MSOUTL.OLB"
ThisWorkbook.VBProject.References.AddFromFile x
Désactiver les références manquantes.
Dim Ref As Reference
'La procédure boucle sur la collection de références et supprime celles qui sont
'spécifiées manquantes.
For Each Ref In ThisWorkbook.VBProject.References
If Ref.IsBroken = True Then _
ThisWorkbook.VBProject.References.Remove Ref
Next Ref
III-B. Les macros complémentaires▲
Une macro complémentaire (.xla), aussi appelée AddIn, est un
classeur Excel dont les feuilles sont masquées et que vous pouvez charger dès
l'ouverture d'Excel. Les classeurs .xla sont principalement
utilisés pour stocker les procédures et les fonctions VBA personnelles que vous
utilisez régulièrement dans Excel.
Un exemple pour automatiser l'installation d'une macro complémentaire.
Sub installationMacroComplementaire()
Dim oAddIn As AddIn
'L'argument TRUE: de type Variant facultatif. Ignoré si le fichier complémentaire est
'sur le disque dur. Affectez-lui la valeur True pour copier la macro complémentaire sur
'votre disque dur si elle est sur support amovible (disquette ou CD-ROM).
'Affectez-lui la valeur False pour la laisser sur le support amovible.
'Si vous ne spécifiez pas cet argument, une boîte de dialogue s'affiche et vous
'demande de choisir.
Set oAddIn = Application.AddIns.Add("F:\leFichier.xla", True)
oAddIn.Installed = True
End Sub
Lister les macros complémentaires.
Sub listeMacrosComplementaires()
Dim i As Integer
For i = 1 To Application.AddIns.Count
Debug.Print Application.AddIns(i).Title
Debug.Print Application.AddIns(i).Name
Debug.Print Application.AddIns(i).FullName
Debug.Print Application.AddIns(i).Installed
Debug.Print "---"
Next
End Sub
Vérifier si une macro complémentaire est installée.
Option Explicit
Option Compare Text
Sub controler_Si_MacroComplementaire_Installee()
Dim X As AddIn
Dim laMacro As String
laMacro = "solver.xla"
For Each X In Application.AddIns
If laMacro = X.Name Then
If X.Installed = True Then
MsgBox "la macro complémentaire " & laMacro & " est installée."
Else
MsgBox "la macro complémentaire " & laMacro & " n'est pas installée."
End If
Exit Sub
End If
Next X
MsgBox "la macro complémentaire " & laMacro & " n'a pas été trouvée."
End Sub
Imprimer la Feuil1 d'un classeur xla.
With Workbooks("Test.xla")
.IsAddin = False
.Worksheets("Feuil1").PrintOut Copies:=1, Collate:=True
.IsAddin = True
End With
Activer l'utilitaire d'analyse (Funcres.xla) et l'utilitaire d'analyse-VBA (atpvbaen.xls)
Dim oAddIn As AddIn
Set oAddIn = Application.AddIns.Add _
(Filename:=Application.LibraryPath & "\analyse\analys32.xll")
oAddIn.Installed = True
Application.RegisterXLL "Analys32.xll"
Workbooks.Open Application.LibraryPath & "\analyse\atpvbaen.xla"
AddIns("Utilitaire d'analyse - VBA").Installed = True
IV. Gérer les modules et les procédures▲
Ce chapitre propose des exemples pour manipuler les modules et les procédures contenus dans les classeurs.
IV-A. Créer▲
Créer un nouveau module, le renommer et y insérer une macro.
Sub creationModule()
'Nécéssite d'activer la référence
'"Visual basic For Application Extensibility 5.3"
'
Dim Wb As Workbook
Dim VBComp As VBComponent
Dim X As Integer
'Définit le classeur cible
Set Wb = Workbooks("Classeur1.xls")
'Ajoute un module standard dans le classeur
Set VBComp = Wb.VBProject.VBComponents.Add(1)
'Renomme le module
VBComp.Name = "NouveauModule"
'Ajoute une macro dans le module
With VBComp.CodeModule
X = .CountOfLines
.InsertLines X + 1, "Sub laMacro()"
.InsertLines X + 2, "Range(""A1"").Value = ""Coucou"""
.InsertLines X + 3, "End Sub"
End With
End Sub
Utilisez Wb.VBProject.VBComponents.Add(2) pour créer un module de classe.
Utilisez Wb.VBProject.VBComponents.Add(3) pour créer un UserForm.
Créer une macro dynamiquement.
Cet exemple permet d'ajouter une procédure évènementielle SelectionChange
dans la Feuil1 du classeur actif.
Sub creationMacro()
Dim X As Integer
With ActiveWorkbook.VBProject.VBComponents("Feuil1").CodeModule
X = .CountOfLines
.InsertLines X + 1, "Private Sub Worksheet_SelectionChange(ByVal Target As Range)"
'Chr(38) permet d'insérer le symbole & dans la procédure.
.InsertLines X + 2, _
"MsgBox ""La cellule sélectionnée: """ & Chr(38) & " Target.Address,,""Message"" "
.InsertLines X + 3, "End Sub"
End With
End Sub
Un autre exemple complet:
Récupérer toutes les procédures d'un classeur endommagé.
IV-B. Lire▲
Lister toutes les procédures d'un classeur dans la feuille de calcul.
Sub listeMacros()
'Nécéssite d'activer la référence
'"Visual basic For Application Extensibility 5.3"
'
Dim i As Integer, Ajout As Integer, x As Integer
Dim Msg As String
Dim VBCmp As VBComponent
Dim Wb As Workbook
'Indiquez le nom du classeur ouvert
'Set Wb = ThisWorkbook
Set Wb = Workbooks("Classeur1.xls")
Ajout = 1
For Each VBCmp In Wb.VBProject.VBComponents
Msg = VBCmp.Name
With Cells(Ajout, 1)
.Interior.ColorIndex = 6
.Value = Msg
End With
x = Wb.VBProject.VBComponents(Msg).CodeModule.CountOfLines
For i = 1 To x
Cells(Ajout + i, 1) = _
Wb.VBProject.VBComponents(Msg).CodeModule.Lines(i, 1)
Next
Ajout = Ajout + x + 2
Next VBCmp
End Sub
Afficher le contenu d'une macro précise.
Sub Test()
'Nécéssite d'activer la référence
'"Visual basic For Application Extensibility 5.3"
'
'Affiche la macro "testMacro" contenue dans la Module1 du Classeur1.xls
MsgBox recupereContenuMacro(Workbooks("Classeur1.xls"), "Module1", "testMacro")
'exemple pour récupérer la procédure évènementielle "Workbook_Open" dans le module objet ThisWorkbook:
MsgBox recupereContenuMacro(Workbooks("Classeur1.xls"), "ThisWorkbook", "Workbook_Open")
End Sub
Function recupereContenuMacro(Wb As Workbook, Mdl As String, NomMacro As String)
Dim Debut As Integer, Fin As Integer, i As Integer
Dim Resultat As String
With Wb.VBProject.VBComponents(Mdl).CodeModule
Debut = .ProcStartLine(NomMacro, vbext_pk_Proc)
Fin = .ProcCountLines(NomMacro, vbext_pk_Proc) + Debut
For i = Debut To Fin
Resultat = Resultat & .Lines(i, 1) & vbCr
Next
End With
recupereContenuMacro = Resultat
End Function
Vérifier l'existence d'un module dans le classeur.
Sub Test()
'Nécéssite d'activer la référence
'"Visual basic For Application Extensibility 5.3"
'
MsgBox VerifierExistenceModule(Workbooks("NomClasseur.xls"), "Module2")
End Sub
Function VerifierExistenceModule(Wb As Workbook, Mdl As String) As Boolean
Dim VBComp As VBComponent
On Error Resume Next
Set VBComp = Wb.VBProject.VBComponents(Mdl)
If VBComp Is Nothing Then
VerifierExistenceModule = False
Else
VerifierExistenceModule = True
End If
End Function
Vérifier l'existence d'une macro dans le classeur.
Sub Test()
'Nécéssite d'activer la référence
'"Visual basic For Application Extensibility 5.3"
'
MsgBox VerifierExistenceMacro(Workbooks("NomClasseur.xls"), "testMacro")
End Sub
Function VerifierExistenceMacro(Wb As Workbook, NomMacro As String) As Boolean
Dim x As Integer
Dim vbcomp As VBComponent
For Each vbcomp In Wb.VBProject.VBComponents
On Error Resume Next
x = vbcomp.CodeModule.ProcStartLine(NomMacro, 0)
If x > 0 Then Exit For
Next vbcomp
If x = 0 Then
VerifierExistenceMacro = False
Else
VerifierExistenceMacro = True
End If
End Function
IV-C. Modifier▲
Remplacer un mot dans toutes les procédures d'un classeur.
Cet exemple remplace la chaîne "Feuil1" par "Feuil3".
Sub RemplacementMotDansProcedure()
'Nécéssite d'activer la référence
'"Visual basic For Application Extensibility 5.3"
'
Dim Ancien As String, Nouveau As String, Cible As String
Dim VBComp As VBComponent
Dim i As Integer
Dim Wb As Workbook
Set Wb = Workbooks("NomClasseur.xls")
Ancien = "Feuil1"
Nouveau = "Feuil3"
For Each VBComp In Wb.VBProject.VBComponents
For i = 1 To VBComp.CodeModule.CountOfLines
Cible = VBComp.CodeModule.Lines(i, 1)
Cible = Replace(Cible, Ancien, Nouveau)
VBComp.CodeModule.ReplaceLine i, Cible
Next i
Next VBComp
End Sub
Renommer un module.
Sub Test()
Dim Wb As Workbook
Set Wb = Workbooks("NomClasseur.xls")
RenommeModule Wb, "Module1", "NouveauNom"
End Sub
Sub RenommeModule(Wb As Workbook, Ancien As String, Nouveau As String)
Dim VBComp As VBComponent
Set VBComp = Wb.VBProject.VBComponents(Ancien)
VBComp.Name = Nouveau
End Sub
Remplacer une macro dans tous les modèles Word .DOT d'un répertoire.
(Procédure VBA Word).
Sub remplacement_Macro_WordDot()
'http://www.developpez.net/forums/viewtopic.php?p=2011706#2011706
Dim Debut As Integer, Lignes As Integer, X As Integer
Dim Fichier As String, Direction As String
Dim Doc As Document
Application.ScreenUpdating = False
'boucle sur tous les fichiers .dot du repertoire
Direction = "C:\Documents and Settings\michel\dossier\general\excel"
Fichier = Dir(Direction & "\*.dot")
Do While Fichier <> ""
Set Doc = Documents.Open(Direction & "\" & Fichier)
'suppression de la macro nommée "essai" dans Module1
With Doc.VBProject.VBComponents("Module1").CodeModule
Debut = .ProcStartLine("essai", 0)
Lignes = .ProcCountLines("essai", 0)
.DeleteLines Debut, Lignes
End With
'ajoute la macro nommée "MaNouvelleMacro" dans Module1
With Doc.VBProject.VBComponents("Module1").CodeModule
X = .CountOfLines
.InsertLines X + 1, "Sub MaNouvelleMacro()"
.InsertLines X + 2, "MsgBox ""Coucou"",VBinformation "
.InsertLines X + 3, "End Sub"
End With
DoEvents
Doc.Close True
Set Doc = Nothing
Fichier = Dir
Loop
Application.ScreenUpdating = True
End Sub
IV-D. Supprimer▲
Supprimer le module nommé "Module2" dans le classeur contenant cette macro.
Sub supprimerUnModule()
With ThisWorkbook.VBProject.VBComponents
.Remove .Item("Module2")
End With
End Sub
Supprimer tous les modules vides dans le classeur actif.
Sub supprimerTousModulesVides()
Dim vbComp As VBComponent
Dim i As Integer, j As Integer
For Each vbComp In ActiveWorkbook.VBProject.VBComponents
If vbComp.Type = 1 Then
i = vbComp.CodeModule.CountOfDeclarationLines + 1
j = vbComp.CodeModule.CountOfLines
If j < i Then ActiveWorkbook.VBProject.VBComponents.Remove vbComp
End If
Next
End Sub
Sauvegarder le classeur contenant cette macro, puis supprimer la totalité
des procédures.
La macro "SupprimeTout" est aussi détruite.
Sub SupprimeTout()
'Enregistre le classeur et supprime la totalité des procédures
Dim VbComp As VBComponent
'Enregistre le classeur
ThisWorkbook.SaveAs "C:\Sauvegarde.xls"
For Each VbComp In ThisWorkbook.VBProject.VBComponents
Select Case VbComp.Type
Case 1 To 3
ThisWorkbook.VBProject.VBComponents.Remove VbComp
Case Else
With VbComp.CodeModule
.DeleteLines 1, .CountOfLines
End With
End Select
Next VbComp
'Sauvegarde les modifications
ThisWorkbook.Save
End Sub
Supprimer une macro précise nommée "Macro1" dans le "Module3".
Sub test()
'Nécéssite d'activer la référence
'"Visual basic For Application Extensibility 5.3"
'
Dim Wb As Workbook
Set Wb = Workbooks("Classeur1.xls")
SupprimerMacroPrecise Wb, "Module3", "Macro1"
'Un autre exemple pour supprimer un procédure évènementielle
'SupprimerMacroPrecise Wb, "ThisWorkbook", "Workbook_Open"
End Sub
Sub SupprimerMacroPrecise(Wb As Workbook, Mdl As String, NomMacro As String)
Dim Debut As Integer, Lignes As Integer
With Wb.VBProject.VBComponents(Mdl).CodeModule
Debut = .ProcStartLine(NomMacro, 0)
Lignes = .ProcCountLines(NomMacro, 0)
.DeleteLines Debut, Lignes
End With
End Sub
IV-E. Importer et Exporter▲
Excel possède une méthode d'export pour enregistrer les composants dans des
fichiers séparés: au format .bas pour les modules et .frm pour les UserForm. Vous
pouvez ensuite utiliser la méthode d'import pour réutiliser les composants dans
d'autres classeurs.
L'exemple suivant exporte 3 modules et 1 UserForm du classeur contenant la
macro. Ensuite la procédure boucle sur tous les classeurs d'un répertoire cible
afin d'y importer ces modules et UserForm.
Sub Export_Import_Module_Et_Userform()
Dim Fichier As String, Repertoire As String
Dim Wb As Workbook
Dim i As Byte
Application.ScreenUpdating = False
'-----------------------------------
'Export du UserForm1 et de 3 Modules nommés Module1, Module2 et Module3
'qui sont dans le classeur contenant cette macro.
ThisWorkbook.VBProject.VBComponents("UserForm1").Export "C:\copieUSF.frm"
For i = 1 To 3
ThisWorkbook.VBProject.VBComponents("Module" & i).Export "C:\copieModule" & i & ".bas"
Next i
'-----------------------------------
'Adaptez le répertoire des classeurs à modifier
Repertoire = "C:\Documents and Settings\michel\dossier"
Fichier = Dir(Repertoire & "\*.xls")
'Boucle sur les classeurs du répertoire cible
Do While Fichier <> ""
Set Wb = Workbooks.Open(Repertoire & "\" & Fichier)
'----------------------------------
'La procédure ne gère pas les erreurs si le nom des modules existe déja
'dans les classeurs.
With Wb.VBProject 'Transfert l'USF et les modules dans les classeurs
.VBComponents.Import "C:\copieUSF.frm"
For i = 1 To 3
.VBComponents.Import "C:\copieModule" & i & ".bas"
Next i
End With
Wb.Close True
Fichier = Dir
Loop
Application.ScreenUpdating = True
MsgBox "Opération terminée."
End Sub
L'exemple suivant montre comment importer et remplacer les procédures du module ThisWorkbook.
Il est possible de sauvegarder la procédure d'un module ThisWorkbook en l'enregistrant sur le
disque dur (extension de fichier .cls). Vous pouvez ensuite réimporter ce fichier dans un autre
classeur, pour par exemple effectuer la mise d'une procédure.
Lors de l'import, le fichier va être créé comme un module de classe et non en lieu et place du
module ThisWorkbook.
La procédure ci dessous permet d'automatiser le chargement du fichier .cls et le remplacement des
macros dans le module objet ThisWorkbook.
'Nécessite d'activer la référence "Microsoft Visual Basic for Applications Extensibility 5.3"
Dim Wb As Workbook
Dim oModule As CodeModule
Dim VbComp As VBComponent
Dim x As Integer
Dim Cible As String
Cible = "NomModule"
'Définit le classeur de destination (qui doit être préalablement ouvert).
Set Wb = Workbooks("NomClasseur.xls")
'Charge le module dans le classeur
Set VbComp = Wb.VBProject.VBComponents.Import("C:\ThisWorkbook.cls")
'Le renomme (pour le supprimer plus facilement ultérieurement
VbComp.Name = Cible
Set oModule = VbComp.CodeModule
'Transfère les données chargées dans ThisWorkbook.
'Attention les données existantes dans "ThisWorkbook" sont écrasées.
With Wb.VBProject.VBComponents("ThisWorkbook").CodeModule
x = .CountOfLines
.DeleteLines 1, x
.InsertLines 1, oModule.Lines(1, oModule.CountOfLines)
End With
'Suppression du module précédemment chargé
With Wb.VBProject.VBComponents
.Remove .Item(Cible)
End With
V. Gérer les objets▲
Les objets peuvent être les feuilles de calcul, les UserForm, les contrôles...
Ce chapitre montre comment manipuler les objets et leurs propriétés. Vous y trouverez
aussi deux méthodes pour associer des procédures évènementielles à ces objets:
* En "dur": Ecriture des nouvelles macros directement dans l'éditeur VBE, comme cela
a été vu dans le chapitre IV-A.
* En utilisant un module de classe.
V-A. Créer▲
Il est parfois utile de créer des objets dynamiquement, par exemple pour afficher
une série de contrôles dont vous ne connaissez pas à l'avance le nombre nécessaire.
Voici une solution pour ajouter une série de CheckBox dynamiquement dans un
UserForm, et gérer les évènements de ces nouveaux contrôles à partir
d'un module de classe.
'--------------------------------------
'Procédure de création des CheckBoxs à placer dans l'UserForm.
'L'UserForm doit préalablement contenir un bouton nommé CommandButton1
Option Explicit
Private Sub CommandButton1_Click()
Dim Obj As Control
Dim Cl As Classe1
Dim i As Integer
Set Collect = New Collection
For i = 1 To 3 'boucle pour la création des CheckBox
Set Obj = Me.Controls.Add("forms.Checkbox.1")
With Obj
.Name = "moncheckbox" & i
.Object.Caption = "le texte" & i
.Left = 140
.Top = 30 * i + 10
.Width = 50
.Height = 20
End With
'ajout de l'objet dans la classe
Set Cl = New Classe1
Set Cl.ChkBx = Obj
Collect.Add Cl
Next i
End Sub
'--------------------------------------'--------------------------------------
'A placer dans un module standard
Option Explicit
Public Collect As Collection
'--------------------------------------'--------------------------------------
'A placer dans un module de classe nommé "Classe1"
'
Option Explicit
Public WithEvents ChkBx As MSForms.CheckBox
'Exemple pour gérer l'évènement clic sur les objets type CheckBox
Private Sub ChkBx_Click()
'cet exemple affiche le nom et la valeur de l'objet cliqué
MsgBox ChkBx.Name & ": " & ChkBx.Value
End Sub
'--------------------------------------
Cet exemple montre comment créer un UserForm et une ListBox par macro ainsi
qu'une macro évènementielle "Click" pour la ListBox.
Option Explicit
Dim Usf As Object
Sub lancementProcedure()
Dim X As Object
Dim i As Integer
Dim strList As String
strList = "ListBox1"
Set X = creationUserForm_Et_listBox_Dynamique(strList)
For i = 1 To 10
X.Controls(strList).AddItem "Donnee " & i
Next i
X.Show
ThisWorkbook.VBProject.VBComponents.Remove Usf
Set Usf = Nothing
End Sub
Function creationUserForm_Et_listBox_Dynamique(nomListe As String) As Object
Dim ObjListBox As Object
Dim j As Integer
Set Usf = ThisWorkbook.VBProject.VBComponents.Add(3)
With Usf
.Properties("Caption") = "Mon UserForm"
.Properties("Width") = 300
.Properties("Height") = 200
End With
Set ObjListBox = Usf.Designer.Controls.Add("Forms.ListBox.1")
With ObjListBox
.Left = 20: .Top = 10: .Width = 90: .Height = 140
.Name = nomListe
.Object.ColumnCount = 1
.Object.ColumnWidths = 70
End With
With Usf.CodeModule
j = .CountOfLines
.InsertLines j + 1, "Sub " & nomListe & "_Click()"
.InsertLines j + 2, "If Not " & nomListe & ".ListIndex = -1 Then MsgBox " & nomListe
.InsertLines j + 3, "End Sub"
End With
VBA.UserForms.Add (Usf.Name)
Set creationUserForm_Et_listBox_Dynamique = UserForms(UserForms.Count - 1)
End Function
Cet exemple permet de créer une nouvelle feuille de calcul et d'y ajouter un
bouton.
La procédure associée au nouveau bouton supprime le contenu des cellules.
Dim Ws As Worksheet
Dim Obj As OLEObject
Dim laMacro As String
Dim x As Integer
Set Ws = Sheets.Add 'Ajoute une nouvelle feuille
'ajoute un CommandButton dans la nouvelle feuille
Set Obj = Ws.OLEObjects.Add("Forms.CommandButton.1")
With Obj
.Name = "monBouton" 'renomme le bouton
.Left = 50 'position horizontale par rapport au bord gauche de la feuille
.Top = 50 'position verticale par rapport au bord haut de la feuille
.Width = 150 'largeur
.Height = 30 'hauteur
.Object.Caption = "Supprimer données feuille"
End With
'Spécifie le contenu de la macro qui sera associée au bouton
laMacro = "Sub monBouton_Click()" & vbCrLf
laMacro = laMacro & "Cells.Clear" & vbCrLf
laMacro = laMacro & "End Sub"
'Ajoute la procédure dans la feuille
With ThisWorkbook.VBProject.VBComponents(ActiveSheet.Name).CodeModule
x = .CountOfLines + 1
.InsertLines x, laMacro
End With
Il existe une deuxième méthode pour associer la procédure évènementielle au
bouton.
Dim Ws As Worksheet
Dim Obj As OLEObject
Dim laMacro As String
Dim x As Integer
Set Ws = Sheets.Add 'Ajoute une nouvelle feuille
'ajoute un CommandButton dans la nouvelle feuille
Set Obj = Ws.OLEObjects.Add("Forms.CommandButton.1")
With Obj
.Name = "monBouton" 'renomme le bouton
.Left = 50 'position horizontale par rapport au bord gauche de la feuille
.Top = 50 'position verticale par rapport au bord haut de la feuille
.Width = 150 'largeur
.Height = 30 'hauteur
.Object.Caption = "Supprimer données feuille"
End With
'Ajoute la procédure dans la feuille
With ThisWorkbook.VBProject.VBComponents(ActiveSheet.Name).CodeModule
.CreateEventProc "Click", "monBouton"
x = .ProcStartLine("monBouton_Click", vbext_pk_Proc)
.InsertLines x + 2, "Cells.Clear"
End With
V-B. Lire▲
Boucler sur la collection de contrôles dans la feuille de calcul "Feuil1".
Sub boucleControlesFeuille()
Dim Obj As OLEObject
For Each Obj In Feuil1.OLEObjects
Debug.Print Obj.Name 'Nom
Debug.Print TypeName(Obj.Object) 'Type de contrôle
Next Obj
End Sub
Boucler sur la collection de contrôles dans un UserForm.
Dim Ctrl As Control
For Each Ctrl In Me.Controls
Debug.Print Ctrl.Name 'Nom
Debug.Print TypeName(Ctrl) 'Type de contrôle
Next Ctrl
Compter le nombre de UserForm dans un classeur.
Sub CompteUserForm()
Dim Wb As Workbook
Dim VBComp As VBComponent
Dim Valeur As Byte
Set Wb = Workbooks("leClasseur.xls")
For Each VBComp In Wb.VBProject.VBComponents
If VBComp.Type = 3 Then Valeur = Valeur + 1
Next VBComp
MsgBox " Il y a " & Valeur & " UserForm dans le fichier " & Wb.Name
End Sub
Lister les propriétés d'un UserForm.
Dim i As Integer
Dim VBcomp As Object
On Error Resume Next
Set VBcomp = ThisWorkbook.VBProject.VBComponents("UserForm1")
For i = 1 To VBcomp.Properties.Count
Debug.Print VBcomp.Properties(i).Name & ": " & VBcomp.Properties(i).Value
Next i
V-C. Modifier▲
Cet exemple permet de modifier les propriétés d'un UserForm
Celui ci ne doit pas être en cours d'affichage.
'Change la couleur de fond du UserForm.
ThisWorkbook.VBProject.VBComponents("UserForm1").Properties("backcolor") = RGB(200, 200, 200)
Modifier les propriétés d'un objet CommandButton contenu dans un UserForm.
Celui ci ne doit pas être en cours d'affichage.
'Change la couleur de fond du CommandButton
ThisWorkbook.VBProject.VBComponents("UserForm1"). _
Designer.Controls("CommandButton1").BackColor = RGB(225, 0, 0)
Changer le CodeName d'une Feuille.
Le CodeName correspond à la propriété Name de la feuille de calcul, à ne pas
confondre avec le nom de l'onglet.
L'utilisation du CodeName est particulièrement pratique lors de la rédaction de vos
procédures car Il permet:
* l'affichage de la saisie semi automatique.
* de faire référence à une feuille dans la macro, sans nécéssité de modification
lorsque le nom de l'onglet est changé.
Le CodeName et le nom de l'onglet sont identiques lors de l'ouverture d'un
classeur vierge mais la
modification du nom de l'un n'entraine pas la modification de l'autre.
Un exemple pour modifier le CodeName de la 1ere feuille du classeur.
Remarque: Le codeName ne doit pas contenir d'espace.
Sub RenommerCodeName()
Dim Ws As Worksheet
'Spécifie la 1ere feuille dans le classeur contenant cette macro.
Set Ws = ThisWorkbook.Sheets(1)
'Attention: le nouveau nom ne doit pas contenir d'espace.
ThisWorkbook.VBProject.VBComponents(Ws.CodeName).Name = "NouveauNom"
End Sub
V-D. Supprimer▲
Supprimer un UserForm par macro.
L'UserForm ne doit pas être en cours d'affichage.
Sub suppressionUSF()
'Nécéssite d'activer la référence
'Microsoft Visual Basic for Applications Extensibility 5.3
'L'UserForm ne doit pas être en cours d'affichage
Dim VBComp As VBComponent
Set VBComp = ThisWorkbook.VBProject.VBComponents("UserForm1")
ThisWorkbook.VBProject.VBComponents.Remove VBComp
End Sub
Supprimer un CommandButton placé dans la feuille de calcul "Feuil1".
Dim Obj As OLEObject
Set Obj = Sheets("Feuil1").OLEObjects("monBouton")
Obj.Delete
Supprimer les contrôles qui ont été créés dynamiquement dans un UserForm.
(Voir l'exemple des CheckBox dans le 1er exemple du chapitre V-V-A)
Private Sub CommandButton2_Click()
Dim i As Integer
For i = Me.Controls.Count - 1 To 0 Step -1
'Attention la procédure est sensible à la casse.
If TypeName(Me.Controls(i)) = "CheckBox" Then _
Me.Controls.Remove Me.Controls(i).Name
Next i
End Sub
VI. L'éxécution des macros▲
Ce dernier chapitre propose quelques procédures pour déclencher des macros lorsque
l'instruction Call ne peut pas être utilisée:
* Lancer une macro dont le nom ou les arguments sont contenus dans des variables.
* Déclencher les procédures évènementielles des UserForm.
* Déclencher les procédures contenues dans d'autres classeurs.
La méthode Run permet de déclencher des macros,
et notamment évènementielles.
'Déclenche l'évènement Open du module objet ThisWorkbook
Application.Run "ThisWorkbook.Workbook_Open"
'Déclenche l'évènement Click d'un CommandButton placé dans la Feuil1
Application.Run "Feuil1.CommandButton1_Click"
Les anciennes macros XL4 peuvent aussi être utilisées pour lancer les macros.
Cet exemple éxécute une macro dont le nom est contenu dans une variable String.
Dim sVar As String
'http://support.microsoft.com/kb/q108519/
sVar = "NomMacro"
Application.ExecuteExcel4Macro "RUN(""" & sVar & """)"
Utilisez la fonction CallByName pour déclencher une procédure évènementielle
d'un contrôle contenu dans un UserForm.
Important: Le préfixe "Private" doit être préalablement supprimé.
CallByName UserForm1, "CommandButton1_Click", VbMethod
Utilisez la propriété Caller pour renvoyer le nom de l'objet appelant la macro.
MsgBox Application.Caller
Cette propriété est particulièrement intéressante lorsqu'une même macro est
attachée à plusieurs objets (par exemple des formes automatiques) et que vous souhaitez
retrouver la source du déclenchement.
Quelques exemples pour éxécuter une macro contenue dans un autre classeur ouvert.
Il suffit d'utiliser la méthode Run
en précisant le nom du classeur.
Application.Run "NomClasseur.xls!Module1.NomMacro"
'déclenche une procédure évènementielle ThisWorkbook
'Application.Run "NomClasseur.xls!ThisWorkbook.Workbook_Open"
'déclenche l'évènement Click d'un CommandButton placé dans la Feuil1
'Application.Run "NomClasseur.xls!Feuil1.CommandButton1_Click"
Vous pouvez aussi spécifier les arguments d'une procédure.
Application.Run "NomClasseur.xls!Module1.NomMacro", "Argument1", "Argument2"
Remarque:
Si le nom du classeur contient des espaces ou des caractères spéciaux, le nom
doit être encadré par des quotes.
Application.Run "'Nom du Classeur.xls'!Module1.NomMacro"





