it-swarm-eu.dev

Kdy použít třídu ve VBA?

Kdy je vhodné použít třídu v jazyce Visual Basic for Applications (VBA)?

Předpokládám, že zrychlený vývoj a redukce zavádění chyb je společným přínosem pro většinu jazyků, které podporují OOP. Ale s VBA existuje určité kritérium? 

37

Záleží na tom, kdo bude kód vyvíjet a udržovat. Typické "Power User" makro spisovatelů hacking malé ad-hoc aplikace mohou být zmateni pomocí tříd. Pro seriózní vývoj jsou však důvody použití tříd stejné jako v jiných jazycích. Máte stejná omezení jako VB6 - žádné dědictví - ale můžete mít polymorfismus pomocí rozhraní.

Dobré využití tříd je reprezentovat entity a sbírky subjektů. Například často vidím kód VBA, který zkopíruje rozsah aplikace Excel do dvourozměrného pole, a poté manipuluje s dvojrozměrným polem s kódem jako:

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

Je lépe čitelné kopírovat rozsah do kolekce objektů s vhodně pojmenovanými vlastnostmi, například:

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

Dalším příkladem je použití tříd k implementaci vzoru návrhu RAII (google for the). Například jedna věc, kterou mohu potřebovat, je odemknout pracovní list, provést nějaké manipulace a pak jej znovu chránit. Použití třídy zajistí, že pracovní list bude vždy chráněn, i když dojde k chybě ve vašem kódu:

--- 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

Poté můžete tento kód zjednodušit:

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

   ... manipulate myWorksheet - may raise an error

End Sub 

Když tento Sub ukončí, objWorksheetProtector zmizí mimo rozsah a list je znovu chráněn.

50
Joe

Myslím, že kritéria jsou stejná jako ostatní jazyky

Pokud potřebujete spojit několik dat a některé metody a také specificky zpracovat to, co se stane, když je objekt vytvořen/ukončen, třídy jsou ideální

řekni, jestli máš několik procedur, které oheň, když otevřete formulář a jeden z nich trvá dlouho, můžete se rozhodnout, že chcete, aby čas každé etapě ...... 

Můžete vytvořit třídu stopek s metodami pro zřejmé funkce pro spouštění a zastavování, poté můžete přidat funkci, kterou chcete načíst čas a oznámit ji v textovém souboru pomocí argumentu představujícího název procesu, který je načasován. Dalo by se napsat logiku, aby se zaznamenaly jen nejpomalejší výkony pro vyšetřování. 

Potom můžete přidat objekt průběhu s metodami pro jeho otevření a zavření a zobrazení názvů aktuální akce spolu s časy v ms a pravděpodobným časem zbývajícím na základě předchozích uložených přehledů atd.

Dalším příkladem může být, pokud se vám nelíbí odpad od skupiny uživatelů aplikace Access, můžete si vytvořit vlastní třídu uživatelů s metodami pro přihlášení a odhlášení a funkce pro řízení přístupu uživatelů/auditování/protokolování určitých akcí/sledování chyb atd. 

Samozřejmě, že byste to mohli udělat s použitím řady nesouvisejících metod a spousty proměnných průchodů, ale abych to všechno zapouzdřilo do třídy, zdá se mi to lepší. 

Dříve nebo později se přiblížíte hranicím VBA, ale jeho poměrně mocný jazyk a pokud vás k tomu vaše společnost váže, můžete z ní skutečně dostat nějaká dobrá, komplexní řešení. 

8
ajp

Třídy jsou velmi užitečné při řešení složitějších funkcí rozhraní API, a zejména v případě, že vyžadují strukturu dat.

Funkce GetOpenFileName () a GetSaveFileName () například používají strukturu OPENFILENAME s mnoha členy. možná nebudete muset využít všech z nich, ale jsou tam a měli by být inicializováni.

Líbí se mi zabalit strukturu (UDT) a deklarace funkcí API do třídy CfileDialog. Událost Class_Initialize nastaví výchozí hodnoty členů struktury, takže když používám třídu, musím pouze nastavit členy, které chci změnit (prostřednictvím procedur Vlastnosti). Konstanty příznaků jsou implementovány jako Enum. Chcete-li například vybrat tabulku, kterou chcete otevřít, může kód vypadat takto:

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

Třída nastaví výchozí adresář na Moje dokumenty, i když bych ho chtěl změnit pomocí vlastnosti InitDir. 

To je jen jeden příklad toho, jak může být třída velmi užitečná v aplikaci VBA.

5
Mike

Neřekl bych, že existuje konkrétní kritérium, ale nikdy jsem nenašel užitečné místo pro použití tříd v kódu VBA. V mé mysli je to tak svázané s existujícími modely v okolí aplikací sady Office, které přidávají další abstrakci mimo tento objektový model, což jen zaměňuje věci.

To neznamená, že jeden nemohl najít užitečné místo pro třídu ve VBA, nebo udělat dokonale užitečné věci pomocí třídy, jen že jsem je nikdy nenašel v tomto prostředí užitečný.

5
cori

Kód VBA můžete také znovu použít bez použití skutečných tříd. Například pokud máte volané VBACode. K libovolné funkci nebo podřízenému modulu můžete přistupovat s následující syntaxí:

VBCode.mysub(param1, param2)

Pokud vytvoříte odkaz na šablonu/doc (jako byste dll), můžete kód z jiných projektů odkazovat stejným způsobem.

3
JonnyGold

Vývoj softwaru, a to i s aplikací Microsoft Access, pomocí objektově orientovaného programování je obecně dobrou praxí. To umožní škálovatelnost v budoucnosti tím, že dovolí objekty být volně spojený, spolu s množstvím výhod. To v podstatě znamená, že objekty ve vašem systému budou méně závislé na sobě, takže refactoring se stává mnohem snazší. Toho lze dosáhnout pomocí modulu Class Class. Nevýhodou je, že ve VBA nelze provádět dědičnost třídy nebo polymorfismus. Nakonec neexistuje žádné tvrdé a rychlé pravidlo týkající se používání tříd, pouze osvědčených postupů. Ale mějte na paměti, že jak vaše aplikace roste, je snazší udržovat pomocí tříd. 

2
jinsungy

Pro rekurzi dat (a.k.a. BOM handling) je vlastní třída kriticky užitečná a myslím, že někdy je to nepostradatelné. Rekurzivní funkci můžete provést bez modulu třídy, ale mnoho problémů s daty nelze efektivně řešit. 

(Nevím, proč lidé nejsou v peddlingu knihovny BOM sady pro VBA. Možná, že nástroje XML udělaly rozdíl.) 

Více instancí formuláře je běžná aplikace třídy (mnoho problémů s automatizací je jinak neřešitelných), předpokládám, že otázka je o custom classes. 

2
Smandoli

Používám třídy, pokud chci vytvořit self-encapsulated balíček kódu, který budu používat v mnoha projektech VBA, které se setkávají pro různé klienty.

2
Jason TEPOORTEN

Používám třídy, když potřebuji něco udělat a třída to udělá nejlépe :) Například pokud potřebujete reagovat na (nebo zachytit) události, pak potřebujete třídu. Někteří lidé nenávidí UDTs (uživatelem definované typy), ale líbí se mi, takže je používám, pokud chci prostý anglický samo dokumentující kód. Pharmacy.NCPDP je mnohem snazší číst pak strPhrmNum :) Ale UDT je ​​omezený, takže říkám, že chci mít možnost nastavit Pharmacy.NCPDP a mít všechny ostatní vlastnosti naplnit. A já také chci, aby to nebylo možné náhodně změnit data. Pak potřebuji třídu, protože v UDT nemáte žádné vlastnosti. 

Další úvahou je pouze jednoduchá čitelnost. Pokud děláte složité datové struktury, je to často prospěšné vědět, že stačí zavolat Company.Owner.Phone.AreaCode pak se snaží sledovat, kde je vše strukturované. Zvláště pro lidi, kteří musí udržet tuto kódovou základnu 2 roky poté, co jste odešli :)

Můj vlastní dva centy je "Code With Purpose". Nepoužívejte třídu bez důvodu. Ale pokud máte důvod, pak to udělejte :)

2
Oorang

Můžete definovat třídu sql wrapper v přístupu, který je pohodlnější než sady záznamů a querydefs. Například pokud chcete aktualizovat tabulku na základě kritérií v jiné související tabulce, nelze použít spojení. Dalo by se vám vytvořit vba recorset a querydef, aby to bylo jednodušší s třídou. Také vaše aplikace může mít nějaký koncept, který potřebuje více než 2 tabulky. Např. Aplikaci sledujete incidenty. Incident má několik atributů, které budou mít v několika tabulkách {uživatelé a jejich kontakty nebo profily, popis incidentů; sledování stavu; Kontrolní seznamy, které pomohou důstojníkovi podpory odpovědět na incident; Odpověď ...} . Chcete-li sledovat všechny dotazy a vztahy, oop může být užitečné. Je to úleva být schopen udělat Incident.Update (xxx) namísto všech kódování ...

0
Bellow Akambi