5 votes

Puis-je passer un module VBA comme argument à une sous-fonction ?

J'essaie de refactoriser du code Excel VBA (Excel 2016, VBA 7.1) afin d'éliminer les sous-programmes répétitifs pour des raisons de maintenabilité. Plusieurs des sous-routines ne diffèrent que par le groupe de constantes globales qu'elles utilisent, donc ce que j'essaie essentiellement de faire est de regrouper les globales dans une structure de données de type struct afin que je puisse les passer dans une fonction commune comme argument.

Notez que les groupes de constantes globales ont certains points communs, mais pas tous, par ex :

Global Const GROUP1_SHEET As String = "Sheet1"
Global Const GROUP1_FIRST_ROW As Long = 2
Global Const GROUP1_LAST_COL As Long = 15
Global Const GROUP1_SOME_COL_OFFSET = 4

Global Const GROUP2_SHEET As String = "Sheet2"
Global Const GROUP2_FIRST_ROW As Long = 2
Global Const GROUP2_LAST_COL As Long = 8
Global Const GROUP2_ANOTHER_COL_OFFSET = 2

Et il y a des sous-routines différentes pour chaque groupe, par exemple :

Dans Sheet1 :

Private Sub DoSomething()
    Set w = Worksheets(GROUP1_SHEET)
    'some code
End Sub

Dans Sheet2 :

Private Sub DoSomething()
    Set w = Worksheets(GROUP2_SHEET)
    'same code as above
End Sub

Il y en a des dizaines. Inutile de dire que ce code est un cauchemar à lire, sans parler de sa maintenance.

Ce que j'essaie de faire pour l'instant, c'est de diviser les groupes en modules séparés et de les définir comme propriétés, de manière similaire à ce qui est décrit dans cette question . Le problème est que je ne sais pas comment passer le module (c'est-à-dire le groupe de globaux) à la fonction en tant qu'argument.

Dans le nouveau module GROUP1 :

Public Property Get SHEET() As String
    SHEET = "Sheet1"
End Property

Et cela fonctionne comme je le veux :

Public Sub ShowPopup()
    MsgBox GROUP1.SHEET
End Sub

Mais la passer comme argument ne le fait pas :

Public Sub Popup(inModule As Object)
    MsgBox inModule.SHEET
End Sub

Public Sub ShowPopUp()
    Popup GROUP1
End Sub

Rien de ce que j'ai essayé ne fonctionne à la place de "Object" dans l'exemple ci-dessus. J'obtiens soit "ByRef Argument type mismatch", soit "Expected variable or procedure, not module", en fonction de ce que je mets.

Alors, puis-je passer un module comme ça (peut-être sous la forme d'une chaîne et l'évaluer d'une manière ou d'une autre ?), ou dois-je utiliser un autre moyen de regrouper les globaux ?

4voto

Victor K Points 624

Vous ne pouvez pas passer des modules réguliers en tant qu'arguments (techniquement, vous pouvez passer une chaîne de caractères et utiliser la commande Application.Run mais cela peut être un cauchemar à gérer), mais vous pouvez passer des cours.

Les classes peuvent avoir une portée globale. Donc, techniquement, vous pouvez les instancier à un moment donné (en ouvrant un classeur par exemple) et les utiliser ensuite à n'importe quel moment. Je dirais que les globaux sont bien dans certains cas, mais la plupart du temps, vous pouvez (et peut-être devriez) vous en passer. Je vous encourage à examiner le sujet de la portée globale et les raisons pour lesquelles elle est souvent considérée comme mauvaise.

Vous pouvez avoir une classe comme ça :

GroupClass:
Option Explicit
Private Type TypeGroup
    WS as WorkSheet
    FirstRow as Long
    FirstCol as Long
    ColumnOffset as Long
End Type
Private This as TypeGroup
Public Function Initialize(Byval WS as Sheet, Byval FirstRow as Long, ByVal FirstCol as Long, ByVal ColumnOffset as Long)
With This
    Set .WS = WS
    .FirstRow = FirstRow
    .FirstCol = FirscCol
    .ColumnOffset = ColumnOffset
End with
End Function
Public Property Get Name() as String
    Name = This.WS.Name
End Property

Alors vous pouvez l'utiliser comme ceci :

Public Sub Popup(Group As GroupClass)
    MsgBox Group.Name
End Sub

Public Sub ShowPopUp()
    Dim Group1 as GroupClass
    Set Group1 = New GroupClass
    Group1.Initialize Worksheets("Sheet1"),2,15,4
    Popup Group1
End 

La raison pour laquelle j'utilise Private Type y Private This as TypeGroup peuvent être trouvés ici . Certains avertissements concernant l'instanciation des classes peuvent être vu ici . Selon ce que vous faites, l'organisation de vos classes peut être très différente. Vous pouvez lire sur les interfaces, l'immuabilité, quand utiliser les getters/setters, l'encapsulation et d'autres sujets ailleurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X