Bonjour, je suis nouveau sur le forum mais bricole depuis environ un an avec VBA pour des besoins professionnels. Voilà un mois, j’ai commencé un nouveau projet afin d’automatiser la production de spécifications. Sur proposition d’un collègue, j’ai tenté de rendre la structure la plus flexible possible, au moyen d’objets dont les propriétés ne sont pas fixées dans le code, mais paramétrées dans une feuille Excel (nommée « CodeSheet »), lue ensuite par le code pour créer la bonne classe d’objet (l’objet en question s’appelle « Cb »). Ainsi, si dans le futur une nouvelle propriété est nécessaire, il sera facile pour les collègues de l’ajouter sans devoir bricoler dans le code. J’ai en quelque sorte des « propriétés dynamiques ». Si la théorie et la structure du code est claire, une erreur quelque part fait que mon code ne marche qu’une fois, j’aimerais que vous m’aidiez dans la recherche de cette erreur.
Pour réaliser ceci, j’ai une fonction qui vient à l’initialisation du fichier lire la feuille « CodeSheet » et écrit le code de la classe avec les propriétés requises.
Mon module de la classe Cb est donc comme ceci (ici, je montre deux propriétés) :
Ensuite, pour pouvoir les lire j’ai adapté le code présent sur cette page : http://www.amolpandey.com/2012/08/05...erties-getset/
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 Dim VarItemCode As String Dim VarDesignationCode As String Property Let DesignationCode(Variable As String) VarDesignationCode = Variable End Property Property Get DesignationCode() As String DesignationCode = VarDesignationCode End Property Property Get LignDesignationCode() As Long LignDesignationCode = 6 End Property Property Let ItemCode(Variable As String) VarItemCode = Variable End Property Property Get ItemCode() As String ItemCode = VarItemCode End Property Property Get LignItemCode() As Long LignItemCode = 5 End Property
Voici la fonction pour aller lire et assigner une valeur aux propriétés « dynamiques » :
Le module dynamique se présente comme ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 Function DynamicObjectProperty(oObject As Cb, PropertyName As String, Optional PropertyValue As Variant) Dim VBAEditor As VBIDE.VBE Dim VBProj As VBIDE.VBProject Dim VBComp As VBIDE.VBComponent, getLineNo As Integer, setLineNo As Integer Dim CodeMod As VBIDE.CodeModule, codeString As String, IsInsertedCode As Boolean Set VBAEditor = Application.VBE Set VBProj = Application.ThisWorkbook.VBProject Set VBComp = VBProj.VBComponents("DynamicModule") Set CodeMod = VBComp.CodeModule 'IsInsertedCode = False 'DynamicObjectProperty = False getLineNo = 6 setLineNo = 2 If IsMissing(PropertyValue) Then codeString = CodeMod.Lines(getLineNo - 1, 1) 'Get the function/sub header line to identify the operation Else codeString = CodeMod.Lines(setLineNo - 1, 1) 'Get the function/sub header line to identify the operation End If If InStr(1, codeString, "Get", vbTextCompare) > 0 Then CodeMod.InsertLines getLineNo, "DynamicOjectPropertyGetter = obj." & PropertyName DynamicObjectProperty = DynamicModule.DynamicOjectPropertyGetter(oObject) CodeMod.DeleteLines getLineNo ElseIf InStr(1, codeString, "Set", vbTextCompare) > 0 Then CodeMod.InsertLines setLineNo, "obj." & PropertyName & " = value" DynamicModule.DynamicOjectPropertySetter oObject, PropertyValue DynamicObjectProperty = True CodeMod.DeleteLines setLineNo End If End Function
Dans ma procédure pour obtenir le résultat souhaité j’initialise mon objet (ici ListofInputcbs est une collection) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 Public Sub DynamicOjectPropertySetter(Obj As Cb, value As Variant) 'Code Replacer: Set End Sub Public Function DynamicOjectPropertyGetter(Obj As Cb) As Variant 'Code Replacer: Get End Function
Ensuite je vais lire dans ma feuille où sont entrées les données (« input data »). Je veux récupérer « Locallign » qui me permet de savoir à quelle ligne est ma propriété dans la feuille « CodeSheet » afin de savoir quoi remplir dans ma feuille de résultat.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 Dim Localcb As Cb Set Localcb = ListofInputcbs.Item("Cbinput" & Inputnumber)
Le code ci-dessus est dans une boucle. Mon problème est le suivant : alors que la valeur de mes LocalKey (dans mon exemple ici ItemCode ou DesignationCode) évolue avec la boucle, la Locallign récupérée par le code reste toujours la même (et ce malgré un grand nombre de tours de boucle). Ainsi les Debug.Print me renvoie ici :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 Dim LocalKey As String Dim LocalLign As Long LocalKey = Sheets("input data").Cells(Index, 1).value Debug.Print LocalKey & LocalKey LocalLign = DynamicObjectProperty(Localcb, "Lign" & LocalKey) Debug.Print LocalLign & LocalLign Call Completor(Localcb, LocalLign, LocalKey)
Cela à mon avis montre que le code n’est pas complétement faux (il marche une fois) mais a une erreur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 LocalKey ItemCode LocalLign 5 LocalKey DesignationCode LocalLign 5
Si j’enlève la lignede DynamicObjectProperty je vois que la ligne est bien copiée :
Code : Sélectionner tout - Visualiser dans une fenêtre à part CodeMod.DeleteLines getLineNo
Si je fige le code. C'est-à-dire, que je mets juste "Obj.ItemCode = value", ca marche très bien ! Debug.Print DynamicOjectPropertyGetter(Localcb) renvoie 5.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 Public Sub DynamicOjectPropertySetter(Obj As Cb, value As Variant) 'Code Replacer: Set Obj.ItemCode = value Obj.DesignationCode = value End Sub Public Function DynamicOjectPropertyGetter(Obj As Cb) As Variant 'Code Replacer: Get DynamicOjectPropertyGetter = Obj.LignItemCode DynamicOjectPropertyGetter = Obj.LignDesignationCode End Function
Si je démarre mon code avec une autre propriété par exemple DesignationCode au lieu d’ItemCode, le problème reste identique. LocalLign vaut alors 6… et reste à 6.
On a l’impression que Excel ne lit pas le module tel qu’il est écris au moment de la lecture, mais tel qu’il ait au moment du lancement de la procédure, ou du moins qu’il n’actualise pas assez.
Avez-vous des idées ? Merci.
Partager