środa, 15 lipca 2009

Arkusze z Klasą

Język programowania dostarcza nam szereg funkcjonalności. Jedną z nich są klasy użytkownika. W odróżnieniu od modułów które mogą zawierać luźno powiązany ze sobą kod, klasa stanowi hermetyczną całość ściśle ze sobą powiązaną. Wymaga to bardziej abstrakcyjnego myślenia podczas programowania, niemniej jednak nagrodą są funkcjonalności niedostępne w podejściu modułowym.
Pracę z klasami rozpoczniemy od zrozumienia jak to w ogóle działa, gdyż bez tego nie ma co się brać za pisania :)

Klasa jest swego rodzaju kontenerem na inne elementy odseparowane w ramach tego pojemnika od innych części programu, dzięki czemu taką klasę można później swobodnie wykorzystać w innym projekcie. Tu muszę zaznaczyć że bezwzględnie należy stosować zasadę separacji i nie odwoływania się do jakiegoś elementu nadrzędnego. Powodem tego mogą być nieoczekiwane efekty w momencie gdyby przyszło nam do głowy stworzyć kolejną instancję klasy w obiekcie. Dojście do tego dlaczego mamy błąd było by niewątpliwie kłopotliwe.

Klasa jako taka nie może być wywołana jak zwykła funkcja lub procedura, musi być zadeklarowana do jakiegoś obiektu. Dopiero taki obiekt udostępnia nam dostęp do metod i właściwości publicznych w ramach danej klasy, są to odpowiednio odpowiedniki procedur i zmiennych. Osobnym elementem wymagającym szczególnego omówienia są Eventy, gdyż te nie mają odpowiednika w świecie modułów.

Event to zdarzenie które możemy stworzyć i wykorzystać do własnych celów. Działanie eventu jest bardzo proste. Mamy np. jakąś procedurę w klasie, procedura się wykonuje i w pewnym momencie następuje wyzwolenie event-a czyli wywołanie instrukcji RaiseEvent. W tym momencie następuje coś nieoczekiwanego z punktu widzenia podejścia standardowego, a mianowicie program przeskakuje do podprogramu obsługi event-a znajdującego się w kodzie głównym, czyli w miejscu gdzie nastąpiło wywołanie procedury z klasy.

Może brzmi to dziwnie, ale każdy bardziej zaawansowany programista VBA doskonale zna np. zdarzenia które oprogramowuje w skoroszycie np. Private Sub Worksheet_SelectionChange(ByVal Target As Range) lub Private Sub Worksheet_Calculate(). Widać tutaj pewną prawidłowość nazwa procedury składa się z dwu cześci rozdzielonych znakiem _. Pierwsza część to nazwa obiektu w którym programujemy Event-y, zaś część po znaku _ to nazwa eventu zadeklarowanego w klasie, reszta to parametry Eventu jakie będą przekazane do programu głównego.

Tu przedstawię ciekawostkę: nie można zadeklarować klasy w taki sposób aby tworzyła się samodzielnie instancja klasy wraz z obsługą Eventów. Ponadto Eventy są obsługiwane tylko w innych obiektach będących klasami czyli userformach, arkuszach, formularzach innych klasach. Nie są obsługiwane w modułach. O czym ja piszę :) bo pewnie brzmi to trochę po chińsku.
Chodzi mi o to że klasę można deklarować na dwa sposoby:

dim a as new clTest
a.test

Coś takiego możemy zadeklarować w dowolnym miejscu, działa to tak że klasa clTest działa dopiero po pierwszym użyciu. dzięki czemu nie musimy sobie zaprzątać głowy tym że np. instancja klasy nie jest zadeklarowana. Jeżeli jednak chcielibyśmy korzystać z dobrodziejstw Eventów trzeba postąpić w sposób bardziej wyrafinowany:

private WithEvents a as clTest

public sub wywolaj
set a = new clTest
a.test
end sub

private Sub a_test_event ()
msgbox ("a ku ku")
end sub

Jak widzimy w procedurze Wywołaj jawnie deklarujemy nową instancję klasy, co może być kłopotliwe przy wielokrotnym wykorzystani tej metody. Z odsieczą przyjdzie nam mała funkcja pozwalająca sprawdzić czy obiekt jest zadeklarowany:

Function IsNothing(vObject) As Boolean
On Error Resume Next
IsNothing = vObject Is Nothing
If Err.Number <> 0 Then IsNothing = True
End Function

Dzięki takiej funkcji możemy sprawdzić czy obiekt już został zadeklarowany.

public sub wywolaj
if IsNothing(a) then
set a = new clTest
end if
a.test
end sub

W takiej konstrukcji obiekt będzie tworzony tylko w momencie gdy jest niezadeklarowany.

Oddzielną kwestią jest to co się dzieje podczas tworzenia nowego obiektu. Klasy jako takie posiadają mechanizm konstruktora i destruktora czyli podprogramu uruchamianego w momencie tworzenia lub niszczenia obiektu klasy. bardzo praktycznym przykładem wykorzystania konstruktora i destruktora jest połączenie się z bazą danych i stworzenie obiektu ADODB.Connection podtrzymującego połączenie przez cały czas życia klasy czyli aż do zniszczenia obiektu lub wciśnięciu guzika Stop w edytorze VBA.

Deklaracja konstruktora i desruktora:

Private Sub Class_Initialize()
' kod konstruktora
End Sub

Private Sub Class_Terminate()
' kod destruktora
End Sub

Brak komentarzy:

Prześlij komentarz