Praca na tablicach jest chlebem powszednim każdego programisty VBA. Pomimo tego, że możemy tworzyć tablice o wielu wymiarach, w praktyce wystarczą nam dwa. Tablice jedno i dwuwymiarowe różnią się od siebie w wielu aspektach. W tym artykule pokażę Ci kiedy tablice są indeksowane od 0, a kiedy od 1. Omówię też temat transpozycji w kontekście przenoszenia danych do zakresu komórek.
Tablica typu Array
Na pierwszy ogień idzie tablica utworzona za pomocą polecenia Array. Taka tablica nazywana jest często stałoelementową lub statyczną. Wynika to, z faktu, że widząc tablicę utworzoną w taki sposób, zakładamy jej niezmienność.
Taką tablicę możemy zadeklarować np. tak:
1 2 3 4 5 |
Dim avTygodnie1 As Variant avTygodnie1 = Array("poniedziałek", "wtorek", "środa", _ "czwartek", "piątek", "sobota", "niedziela") |
Co ciekawe, taką tablicę możemy modyfikować! Możemy zmieniać jej poszczególne elementy jak i zwiększać rozmiar poleceniem ReDim. Odradzam jednak takie postępowanie, ponieważ nasz kod będzie mylący dla innych. Większość programistów VBA traktuje taką tablicę właśnie jako stałoelementową.
Z taką tablicą wiąże się kilka ważnych informacji:
- Indeksowanie rozpoczyna się od 0, a nie od 1, co pokazuje okienko Locals. Poniedziałkowi jest przypisany numer 0.
- Jest to tablica pozioma, a nie pionowa. Taka tablica jednowymiarowa składa się z jednego wiersza i siedmiu kolumn. Nie odwrotnie – jak sądzi wiele osób.
- Jeżeli chcemy zaczytać dane do zakresu poziomego np. A1:G1 to nie musimy jej transponować. Instrukcja Arkusz1.Range(„A1:G1”).Value = avTygodnie1 zadziała prawidłowo.
Jeżeli chcemy taką tablicę wstawić do zakresu pionowego A1:A7, to w wyniku otrzymamy tylko jej pierwszy element – powtórzony siedmiokrotnie.
Musimy ją więc koniecznie przetransponować.
Poniższa instrukcja zadziała prawidłowo. Tablica z nazwami dni tygodnia zostanie pomyślnie wstawiona do zakresu pionowego.
Arkusz1.Range(„A1:A7”).Value =WorksheetFunction.Transpose(avTygodnie1)
Tablica (1 To 7)
Zadeklarujmy drugą tablicę poleceniem Dim asTygodnie2(1 To 7) As String i przypiszmy jej wartości w pętli. Elementami tablicy ponownie będą pełne nazwy dni tygodnia.
1 2 3 4 5 6 |
Dim asTygodnie2(1 To 7) For x = 1 To 7 asTygodnie2(x) = WeekdayName(x) Next x |
Zauważ, że mamy tutaj dodatkową zmienną x, która jest typu Byte. Pełni ona rolę licznika.
Tak naprawdę asTygodnie2 od tablicy avTygodnie1 różni się tym, że indeksowanie zaczyna się od 1, a nie od 0. Jest to także tablica typu String, a nie Variant. Mogliśmy ją zadeklarować w ten sposób, ponieważ wartości przypisywaliśmy w pętli, a nie instrukcją Array.
Warto zauważyć, że sami ustaliliśmy dolną i górną granicę tablicy (1 To 7). Polecam zdecydowanie takie podejście! Jest czytelnie i nie ma przykrych niespodzianek. Deklarując tablicę: Dim asTygodnie2(7) As String mielibyśmy w niej tak naprawdę… 8 elementów. Wynika to z faktu, że tablice są indeksowane domyślnie od 0.
Jest to tablica jednowymiarowa, więc transpozycji musimy użyć tylko wtedy, gdy chcemy wstawić dane do zakresu pionowego A1:A7 (tak jak w pierwszym przypadku).
Tablica (1 To 7, 1 To 1)
Tablicę dwuwymiarową musimy postrzegać jako tabelę złożoną z wierszy i kolumn. Pierwszy wymiar dotyczy liczby wierszy, drugi zaś – liczby kolumn.
Tablica asTygodnie3(1 To 7, 1 To 1) As String będzie się więc składać z siedmiu wierszy i jednej kolumny.
1 2 3 4 5 6 |
Dim asTygodnie3(1 To 7, 1 To 1) As String For x = 1 To 7 asTygodnie3(x, 1) = WeekdayName(x) Next x |
Jak się pewnie domyślasz, trzeba tutaj postąpić odwrotnie niż w dwóch poprzednich przypadkach. Do zakresu pionowego A1:A7 dane wstawimy bez problemu. Chcąc natomiast wstawić dni tygodnia do zakresu poziomego A1:G1, musimy użyć transpozycji.
Tablica (1 To 1, 1 To 7)
Tablica dwuwymiarowa asTygodnie4(1 To 1, 1 To 7) As String składa się z jednego wiersza i siedmiu kolumn.
1 2 3 4 5 6 |
Dim asTygodnie4(1 To 1, 1 To 7) As String For x = 1 To 7 asTygodnie4(1, x) = WeekdayName(x) Next x |
Jest to tablica, która spełnia wymogi jednowymiarowej, ale nią nie jest.
Chcąc przekonwertować ją po postaci tablicy jednowymiarowej, musimy użyć…. podwójnej transpozycji.
Skoro posiada ona tylko jeden wiersz, to zachowuje się tak samo jak tablice z pierwszych dwóch przykładów i inaczej niż tablica z przykładu nr 3. Chcąc wgrać dane z tablicy do zakresu pionowego – musimy użyć pojedynczej transpozycji.
Podsumowanie
O czym musimy pamiętać pracując na tablicach?
- Każda tablica utworzona w VBA jest domyślnie indeksowana od 0. Przykładem może być tablica utworzona poleceniem Array. Jest to tzw. tablica stałoelementowa i nie powinniśmy zmieniać ani jej rozmiaru, ani wartości poszczególnych elementów.
- VBA posiada instrukcję Option Base 1, którą umieszczamy na samej górze modułu. Indeksuje ona od 1 każdą tablicę zadeklarowaną w module. Jej użycie nie jest jednak zalecane i wspomniałem o niej jako o ciekawostce.
- Każda tablica utworzona na bazie komórek arkusza jest indeksowana od 1. Nie ma znaczenia czy utworzyliśmy tablicę jedno czy dwuwymiarową. Pierwszy element zawsze otrzyma pozycję nr 1.
- Tablica jednowymiarowa jest tablicą poziomą, a nie pionową. Chcąc wgrać ją do zakresu pionowego – musimy użyć transpozycji.
- Pierwszy wymiar tablicy dwuwymiarowej dotyczy wierszy, drugi wymiar dotyczy kolumn.