41 votes

Quand utiliser une classe dans VBA?

Quand est-il approprié d'utiliser une classe dans Visual Basic pour Applications (VBA)?

Je suppose que le développement accéléré et la réduction de l'introduction de bogues sont un avantage commun pour la plupart des langues qui prennent en charge la POO. Mais avec VBA, y a-t-il un critère spécifique?

55voto

Joe Points 60749

Cela dépend de qui va développer et maintenir le code. Typique "Power User" macro écrivains piratage petites ad-hoc applications peuvent ainsi être confondu à l'aide de classes. Mais grave pour le développement, les raisons pour utiliser les classes sont les mêmes que dans d'autres langues. Vous avez les mêmes restrictions que VB6 - pas d'héritage - mais vous pouvez avoir du polymorphisme par l'utilisation d'interfaces.

Une bonne utilisation de classes pour représenter des entités et des collections d'entités. Par exemple, je vois souvent des code VBA qui copie une plage Excel dans un tableau à deux dimensions, puis manipule le tableau à deux dimensions avec un code comme:

Total = 0
For i = 0 To NumRows-1
    Total = Total + (OrderArray(i,1) * OrderArray(i,3))
Next i

C'est plus lisible pour copier la plage dans une collection d'objets de façon appropriée les propriétés nommées, quelque chose comme:

Total = 0
For Each objOrder in colOrders
    Total = Total + objOrder.Quantity * objOrder.Price
Next i

Un autre exemple est l'utilisation de classes pour mettre en œuvre le RAII modèle de conception (google pour elle). Par exemple, une chose que j'ai peut-être besoin de faire est d'ôter la protection d'une feuille de calcul, quelques manipulations, puis la protéger de nouveau. À l'aide d'une classe assure que la feuille de calcul sera toujours protégée à nouveau, même si une erreur se produit dans votre code:

--- WorksheetProtector class module ---

Private m_objWorksheet As Worksheet
Private m_sPassword As String

Public Sub Unprotect(Worksheet As Worksheet, Password As String)
    ' Nothing to do if we didn't define a password for the worksheet
    If Len(Password) = 0 Then Exit Sub

    ' If the worksheet is already unprotected, nothing to do
    If Not Worksheet.ProtectContents Then Exit Sub

    ' Unprotect the worksheet
    Worksheet.Unprotect Password

    ' Remember the worksheet and password so we can protect again
    Set m_objWorksheet = Worksheet
    m_sPassword = Password
End Sub

Public Sub Protect()
    ' Protects the worksheet with the same password used to unprotect it
    If m_objWorksheet Is Nothing Then Exit Sub
    If Len(m_sPassword) = 0 Then Exit Sub

    ' If the worksheet is already protected, nothing to do
    If m_objWorksheet.ProtectContents Then Exit Sub

    m_objWorksheet.Protect m_sPassword
    Set m_objWorksheet = Nothing
    m_sPassword = ""
End Sub

Private Sub Class_Terminate()
    ' Reprotect the worksheet when this object goes out of scope
    On Error Resume Next
    Protect
End Sub

Vous pouvez ensuite l'utiliser pour simplifier votre code:

Public Sub DoSomething()
   Dim objWorksheetProtector as WorksheetProtector
   Set objWorksheetProtector = New WorksheetProtector
   objWorksheetProtector.Unprotect myWorksheet, myPassword

   ... manipulate myWorksheet - may raise an error

End Sub 

Lorsque ce Sous-sorties, objWorksheetProtector est hors de portée, et de la feuille de calcul est protégée à nouveau.

10voto

ajp Points 106

Je pense que le critère de sélection est la même que dans d'autres langues

Si vous avez besoin de lier ensemble plusieurs morceaux de données et certaines méthodes et également traiter spécifiquement ce qui se passe lorsque l'objet est créé/résilié, les classes sont idéales

dire si vous avez quelques procédures de feu lorsque vous ouvrez un formulaire et l'un d'eux est de prendre beaucoup de temps, vous pouvez décider que vous voulez du temps à chaque étape......

Vous pouvez créer un chronomètre classe avec des méthodes pour les fonctions évidentes pour le démarrage et l'arrêt, vous pouvez alors ajouter une fonction pour récupérer le temps de la mesure et de rapport dans un fichier texte, à l'aide d'un argument représentant le nom du processus à chronométrer. Vous pourriez logique d'écriture de journal que le plus lent des représentations à des fins d'enquête.

Vous pouvez alors ajouter une barre de progression de l'objet avec les méthodes de l'ouvrir et de le fermer et afficher les noms de l'action en cours, avec des moments de ms et probables de temps restant sur la base de précédents rapports stockés, etc

Un autre exemple pourrait être si vous n'aimez pas l'Accès de l'utilisateur groupe de la foutaise, vous pouvez créer votre propre classe avec des méthodes pour loging dans et hors et les fonctionnalités au niveau du groupe de contrôle d'accès d'utilisateur/d'audit/de journalisation certaines actions/suivi des erreurs, etc

Bien sûr, vous pouvez le faire en utilisant un ensemble de sans rapport avec les méthodes et les lots de la variable de passage, mais d'avoir tout encapsulé dans une classe juste me semble mieux.

Vous le faites tôt ou tard à proximité de la limite de VBA, mais son tout à fait un langage puissant et si votre entreprise vous lie à elle, vous pouvez réellement obtenir quelques bonnes solutions complexes hors de lui.

6voto

Mike Points 41

Les Classes sont très utiles lorsqu'il s'agit de la plus complexe des fonctions de l'API, et en particulier quand ils ont besoin d'une structure de données.

Par exemple, le GetOpenFileName() et GetSaveFileName() les fonctions d'un OPENFILENAME stucture avec de nombreux membres. vous ne pourriez pas besoin de prendre avantage de tous, mais ils sont là et doit être initialisé.

Je tiens à envelopper la structure (UDT) et l'API déclarations de fonction dans une classe CfileDialog. L'événement Class_Initialize définit les valeurs par défaut de la structure de ses membres, de sorte que lorsque j'utilise la classe, j'ai seulement besoin de définir les membres de la je veux changer (par le biais de procédures de Propriété). Drapeau constantes sont mis en œuvre comme un Enum. Ainsi, par exemple, de choisir une feuille de calcul pour l'ouvrir, mon code ressemble à ceci:

Dim strFileName As String
Dim dlgXLS As New CFileDialog

With dlgXLS
  .Title = "Choose a Spreadsheet"
  .Filter = "Excel (*.xls)|*.xls|All Files (*.*)|*.*"
  .Flags = ofnFileMustExist OR ofnExplorer

  If OpenFileDialog() Then
    strFileName = .FileName
  End If
End With
Set dlgXLS = Nothing

La classe définit le répertoire par défaut dans Mes Documents, et que si je voulais je pouvais la changer avec le InitDir de la propriété.

C'est juste un exemple de comment une classe peut être extrêmement bénéfique dans une application VBA.

3voto

cori Points 4356

Je ne dirais pas qu'il existe un critère spécifique, mais je n'ai jamais vraiment trouvé d'endroit utile pour utiliser les classes dans le code VBA. Dans mon esprit, c'est tellement lié aux modèles existants autour des applications Office que l'ajout d'abstraction supplémentaire en dehors de ce modèle d'objet confond simplement les choses.

Cela ne veut pas dire que l' on ne pouvait pas trouver un endroit utile pour une classe dans VBA, ou faire des choses parfaitement utiles en utilisant une classe, juste que je ne les ai jamais trouvées utiles dans cet environnement.

1voto

JonnyGold Points 512

Vous pouvez également réutiliser le code VBA sans utiliser de classes réelles. Par exemple, si vous avez un VBACode appelé. Vous pouvez accéder à n'importe quelle fonction ou sous-module dans n'importe quel module avec la syntaxe suivante:

 VBCode.mysub(param1, param2)
 

Si vous créez une référence à un modèle / doc (comme vous le feriez pour une dll), vous pouvez référencer le code d'autres projets de la même manière.

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