środa, 18 grudnia 2013

Narzędzia programisty VBA

Oczywiście, że podstawowym środowiskiem pracy programisty VBA pozostaje Integrated Developer Editor (IDE) dostarczany w pakiecie Office. Nie mniej istnieje kilka narzędzi pomocniczych, które można zintegrować ze środowiskiem lub jako osobne aplikacje mogą stać się niezastąpioną pomocą w codziennej pracy z VBA. Oto kilka przykładowych programów wartych polecenia i uwagi.

1. EZ-Tool 
 Link do strony dostawcy: www

Narzędzie instalowane jako dodatek środowiska IDE. Wspiera programistę w szeregu czynności: tworzenie procedur, zarządzanie komentarzami, obsługą błędów. Dostarcza schematy dla ADO. W moim odczuciu narzędzie w stylu 'must have'.

2. RibbonX Visual Designer 2010
Link do strony dostawcy: www

Narzędzie wspomagające tworzenie elementów wstążki- zakładek, przycisków i innych kontrolek.

3. Excel VBA Code Cleaner
Link do strony dostawcy: www

Jak sama nazwa wskazuje narzędzie oczyszczające kod ze zbędnych elementów. Narzędzie polecane w przypadku dużych projektów, projektów tworzonych w dłuższych okresach czasu, itp.



piątek, 13 grudnia 2013

Unikalne wartości tablicy Array (2/2)

Kontynuując poprzedni wpis o tym samym tytule tym razem trzecia z technik odnajdywania unikalnych elementów kolekcji. Technika ta opiera się o wykorzystanie słownika Dictionary. Wszystkich czytelników, których rozwiązanie to w jakiś sposób zainteresuje odsyłam do tej strony, na której znaleźć można dodatkowe informacje.

Poniższy kod, korzystając z obiektu słownika, zwróci do arkusza unikalne wartości z tablicy. Wewnątrz kodu zawarte zostały dodatkowe informacje i komentarze wyjaśniające cały mechanizm.

01Sub Unikaty_słownik()
02  
03    'tworzymy obiekt zewnętrznej biblioteki _
04     wykorzystując późne wiązanie
05    Dim Słownik As Object
06    Set Słownik = CreateObject("Scripting.Dictionary")
07    
08    Dim Element As Variant
09    Dim arrTablica As Variant
10    Dim i As Long
11 
12    'nasza przykładowa tablica
13    arrTablica = Array("Do", "Re", "Mi", "Do", "Fa", "Sol", _
14                "Re", "Mi", "Fa", "La", "Do", "Si", _
15                "Do", "Re", "Mi", _
16                "fa", "sol", "LA", "sI")
17 
18    'tworzymy słownik
19    For Each Element In arrTablica
20        'wymaga stosowania funkcji konwersji tekstu
21         Słownik(StrConv(Element, vbProperCase)) = 1
22    Next
23 
24    'zwracamy elementy do arkusza
25    For Each Element In Słownik.keys
26        i = i + 1
27        Cells(i, 1) = Element
28    Next
29 
30    'Wynik: Do,Re,Mi,Fa,Sol,La,Si
31 
32End Sub

Na koniec kluczowe pytanie, którą technikę użyć- kolekcję czy słownik. Osobiście nie udzielę jednoznacznej odpowiedzi, ale wskażę na kilka różnic i podobieństw boldem oznaczając lepsze rozwiązanie.

a) Kolekcja jest obiektem wbudowanym języka VBA, Słownik wymaga tworzenia referencji do osobnej biblioteki.

b) Kolekcja wymaga stosowania obsługi błędów czego nie ma w przypadku Słownika i co jest rozwiązaniem (pozornie?) bardziej profesjonalnym.

c) Dodawanie elementu do kolekcji ignoruje wielkość liter, słownik uwzględnia wielkość liter przez co wymaga stosowanie dodatkowych technik VBA.

d) Kolekcja posiada ograniczony zasób metod i właściwości podczas gdy słownik pozostaje bardziej elastyczny pod względem szerszych zastosowań.

poniedziałek, 9 grudnia 2013

Unikalne wartości tablicy Array (1/2)

 Jak skutecznie odnaleźć unikalne wartości z tablicy Array?
 powyższe pytanie usłyszałem podczas kursu VBA prowadzonego ostatnio w Warszawie.

Osobiście stosuję dwie (lub trzy) techniki odszukiwania unikatów:

Technika 1. wartości tablicy wrzucamy w pionowy, czysty obszar arkusza, następnie stosując polecenie usuwania duplikatów (RemoveDuplicates) pozbywamy się zbędnych elementów, a następnie wynik pobieramy do naszej tablicy w kodzie VBA. Przyznam jednak, że rozwiązanie to nie należy do najbardziej efektywnych.

Technika 2. o wiele łatwiej i skuteczniej będzie sięgnąć po obiekt kolekcji (Collection) w VBA. W tym celu wykorzystamy fakt, że dodanie elementu do kolekcji, nie jest możliwe jeżeli element taki już istnieje. Jeżeli podejmujemy taką próbę to kompilator zwraca błąd wykonania. W naszej procedurze zignorujemy taki błąd w wyniku czego zignorujemy jednocześnie dany element.

01Sub Unikaty_kolekcja()
02  
03    Dim arrKolekcja As New Collection
04    Dim Element As Variant
05    Dim arrTablica As Variant
06    Dim i As Long
07 
08    'nasza przykładowa tablica
09    arrTablica = Array("Do", "Re", "Mi", "Do", "Fa", "Sol", _
10                "Re", "Mi", "Fa", "La", "Do", "Si", _
11                "Do", "Re", "Mi", _
12                "fa", "sol", "LA", "sI")
13 
14    'ignorujemy błąd powtarzajacych się elementów
15    On Error Resume Next
16    'tworzymy kolekcję
17    For Each Element In arrTablica
18         arrKolekcja.Add Element, Element
19    Next
20 
21    'przywracamy standardową obsługę błędów
22    On Error GoTo 0
23 
24     
25    'zwracamy elementy kolekcji do arkusza
26    For i = 1 To arrKolekcja.Count
27        Cells(i, 1) = arrKolekcja(i)
28    Next
29 
30    'Wynik: Do,Re,Mi,Fa,Sol,La,Si
31 
32End Sub

Więcej informacji na temat kolekcji znaleźć można pod tym linkiem.
Kolekcje nie są jedynym czysto programistycznym sposobem na uzyskanie unikatów z tablicy. O alternatywnej technice napiszę w osobnym poście. Zapraszam do lektury już wkrótce.

poniedziałek, 2 grudnia 2013

Co w rzeczywistości zawiera komórka w Excelu?

Z pytaniem umieszczonym w tytule niniejszego posta spotkałem się kilkukrotnie, zarówno przeglądając różne wpisy i pytania na forach internetowych, jak również prowadząc szkolenie z zakresu VBA dla Excela. Chodzi bowiem o sytuację, w której chcemy określić rodzaj informacji zawartej w komórce z uwzględnieniem rodzaju formatowania jaki został zastosowany w danym zakresie arkusza.

Gdzie jednak znajduje się problem? Z punktu widzenia VBA liczba, data, czas i procent- wszystkie te elementy są liczbami. Także wartość Prawda/Fałsz w praktyce jest liczbą odpowiadającą 1 lub 0. W naszej sytuacji określić rzeczywisty typ danych znajdujących się w komórce.

W celu rozwiązania tego problemu wystarczy skonstruować prostą funkcję, której pełną postać znajdziecie Państwo poniżej. Kluczowa w tej funkcji pozostaje kolejność sprawdzania poszczególnych typów. Prześledźmy to na przykładzie typu liczbowego, który sprawdzany jest jako ostatni. Musimy się najpierw upewnić, że podane wartości nie są żadnym z typów: datą, wartością czasu, procentem lub wartością Prawda/Fałsz. Każdy z tych typów będąc domyślnie numerycznym zostałby więc rozpoznany jako liczba. Tymczasem nasza funkcja wydaje się działać prawidłowo co prezentuje poniższy zrzut ekranu.


01Public Function TypWartości(KOMÓRKA As Range)
02    
03    If IsEmpty(KOMÓRKA) Then
04                TypWartości = "PUSTA"
05    ElseIf Application.IsText(KOMÓRKA) Then
06                TypWartości = "TEKSTOWA"
07    ElseIf Application.IsLogical(KOMÓRKA) Then
08                TypWartości = "LOGICZNA"
09    ElseIf Application.IsErr(KOMÓRKA) Or Application.IsError(KOMÓRKA) Then
10                TypWartości = "BŁĄD"
11    ElseIf IsDate(KOMÓRKA) Then
12                TypWartości = "DATA"
13    ElseIf InStr(1, KOMÓRKA.Text, ":") <> 0 Then
14                TypWartości = "CZAS"
15    ElseIf Right(KOMÓRKA.Text, 1) = "%" Then
16                TypWartości = "PROCENT"
17    ElseIf IsNumeric(KOMÓRKA) Then
18                TypWartości = "LICZBA"
19    End If
20End Function