ID tematu: 68718
 |
Tablice dwuwymiarowe w VBA - wypełnianie wierszami/kolumnami |
Autor |
Wiadomość |
Maciej Gonet
Excel Expert

Wersja: Win Office 2016
Pomógł: 2033 razy Posty: 6431
|
Wysłany: 19-08-2020, 10:42 Tablice dwuwymiarowe w VBA - wypełnianie wierszami/kolumnami
|
|
|
Zazwyczaj przyjmuje się, że tablice dwuwymiarowe w VBA należy wypełniać indywidualnie iterując po każdym elemencie. Od tej ogólnej zasady istnieją jednak wyjątki pozwalające wypełniać tablice całymi wierszami lub kolumnami. Pozwala to czasem skrócić czas obliczeń. Przeglądałem ostatnio pod tym kątem zasoby internetu i stwierdziłem, że temat ten nie jest często poruszany, może więc warto przyjrzeć mu się trochę bliżej.
W załączonym tekście i pliku omawiam typowe przypadki pracy z tablicami. Możliwość zapisu całych wierszy lub kolumn jest konsekwencją zastosowania nietypowej struktury tablicy.
Tablice dwuwymiarowe w VBA.docx
|
Pobierz Plik ściągnięto 38 raz(y) 16.72 KB |
Tablice2W_wierszami_kolumnami.xlsm
|
Pobierz Plik ściągnięto 36 raz(y) 23.14 KB |
|
|
 | ID posta:
390936
|
|
|
 |
|
|
|
Marecki
Excel Expert


Wersja: Win Office 2019
Pomógł: 2496 razy Posty: 8293
|
Wysłany: 18-02-2021, 10:41
|
|
|
To ja dorzucę do przykładu Macieja, rozwiązanie API funkcją CopyMemory.
Rozwiązanie w Arkuszu2.
Tablice2W_wierszami_kolumnami.xlsm
|
Pobierz Plik ściągnięto 9 raz(y) 32.3 KB |
|
_________________ Hardware - ta część komputera, którą można kopnąć kiedy software przestanie funkcjonować.
Szkolenia z Excela , FB
Office 2019 Professional Plus , Windows 10 x64
Pozdrawiam, były mkkk23 teraz Marecki. |
|
 | ID posta:
400603
|
|
|
 |
|
|
Maciej Gonet
Excel Expert

Wersja: Win Office 2016
Pomógł: 2033 razy Posty: 6431
|
Wysłany: 18-02-2021, 11:28
|
|
|
Ładnie , może się przydać, ale przydałyby się komentarze dla osób mniej biegłych w API, co jest istotne, a co nie.
Na przykład, czy tablice muszą być deklarowane z nawiasami
Kod: | Dim Tbl1() As Variant | czy wystarczy?
Po co na końcu każdej procedury kasujesz Erase tablice zadeklarowane lokalnie? Logicznie rzecz biorąc one się powinny same skasować po zakończeniu procedury. |
|
 | ID posta:
400608
|
|
|
 |
|
|
Marecki
Excel Expert


Wersja: Win Office 2019
Pomógł: 2496 razy Posty: 8293
|
Wysłany: 18-02-2021, 12:10
|
|
|
Maciej Gonet napisał/a: | ale przydałyby się komentarze | Wiedziałem że nie będzie łatwo.
Tablice nie muszą być deklarowane z nawiasami.
Ja stosuję taki zapis gdy wiem że będę operował na tablicach.
Drugi plus dla tego zapisu to taki, że już na samym początku przeglądania procedury widzimy po zmiennych co dana zmienna będzie przechowywać.
Pomocne w przypadku przeglądania rozbudowanych procedur - długich.
Instrukcja Erase w tym przypadku jest zbędna, ale stosuję ją by wyrobić w sobie taki nawyk, który z kolei jest pomocny w przypadku wykorzystania takiej zmiennej w dalszej części kodu np. dla innego zakresu. Po prostu zwalniam zmienną tablicową i przydzieloną jej pamięć.
Jeszcze takie krótkie info, i tu cytat master_mix-a Cytat: | Elementy tablicy wielowymiarowych ułożone są w sposób przedstawiony poniżej
(przykład pokazuje rozłożenie elementów tablicy dwuwymiarowej Tbl(1 To 5, 1 To 5)
(1,1) (2,1) (3,1) (4,1) (5,1) (1,2) (2,2) (3,2) (4,2) …….. (5,5)
Z takiego rozłożenia elementów w pamięci wynika fakt, iż zmiany rozmiarów tablicy mogą być wykonywane
tylko na ostatnim wymiarze. | Powyższy cytat tłumaczy też użycie w kodzie instrukcji Application.Transpose. Wiem że Transpose ma swoje ograniczenia, ale są alternatywy by to ominąć, ale to już temat do innego wątku.
Jeszcze słowo o funkcji ZeroMemory.
Musimy ją stosować zawsze do tablicy, w której dochodzi do zmiany alokacji pamięci(elementów tablicy).
Bez zwolnienia tej pamięci dochodzi często do crash-a Excela.
Ważna uwaga - nie możemy zastąpić funkcji ZeroMemory funkcją Erase. |
_________________ Hardware - ta część komputera, którą można kopnąć kiedy software przestanie funkcjonować.
Szkolenia z Excela , FB
Office 2019 Professional Plus , Windows 10 x64
Pozdrawiam, były mkkk23 teraz Marecki. |
|
 | ID posta:
400611
|
|
|
 |
|
|
Rafał B.
Stały bywalec Excelforum


Wersja: Win Office 2016
Pomógł: 36 razy Posty: 253
|
Wysłany: 18-02-2021, 12:38
|
|
|
Robiłeś może testy wydajności na większych danych czy faktycznie gra jest warta świeczki, żeby wykorzystywać zabawy z pamięcią? Gdzieś na liście projektów "for fun" mam zamknięcie pomysłu Macieja w zgrabnej, wygodnej do użytku klasie. Dlatego pytam, bo jak różnica wydajności będzie mała, to nie angażowałbym API ze względu braku kompatybilności z Mac. A jak znaczna, to w sumie można dodać kolejny #IF w kompilacji warunkowej. |
_________________ Jest niemal niemożliwe nauczenie dobrego programowania uczniów, którzy byli narażeni na kontakt z BASIC: jako potencjalni programiści są okaleczeni, bez nadziei na poprawę. (Edsger Dijkstra, pionier informatyki).
Po części dotyczy również VBA. |
|
|
 | ID posta:
400613
|
|
|
 |
|
|
Marecki
Excel Expert


Wersja: Win Office 2019
Pomógł: 2496 razy Posty: 8293
|
Wysłany: 18-02-2021, 16:08
|
|
|
Moim zdaniem warto.
Programowanie niskopoziomowe zawsze będzie szybsze od wysokopoziomowego.
Z ciekawości zrobię testy na dużych tablicach i dam znać.
Edit:
Zrobiłem, ale na "małej" tablicy (1 to 65536, 1 to 15)
65536 to maksymalna wartość, z która poradzi sobie funkcja Transpose.
Nie chciałem już kombinować z pętlami by ominąć ową funkcję, więc zostałem przy tym wymiarze.
Czas dla API dwukrotnie krótszy.
Do testów : Kod: | Option Explicit
#If VBA7 And Win64 Then
Public Declare PtrSafe Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (ByVal Destination As Any, ByVal iLen As LongPtr)
Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As LongPtr)
Public Const iSize As LongPtr = 24
#Else
Public Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (ByVal Destination As Any, ByVal iLen As Long)
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)
Public Const iSize As Long = 16
#End If
Sub Start()
Dim i As Long
Dim j As Long
Dim Start As Single
Dim Tbl1(1 To 65536, 1 To 15)
Dim Tbl2(1 To 65536, 1 To 1)
For i = 1 To UBound(Tbl1, 1)
For j = 1 To UBound(Tbl1, 2)
Tbl1(i, j) = Int((999 * Rnd) + 1)
Next j
Next i
Range("A1").Resize(i - 1, j - 1).Value = Tbl1
For i = 1 To UBound(Tbl2, 1)
Tbl2(i, 1) = i
Next i
Range("Q1").Resize(i - 1).Value = Tbl2
Range("S1:S65536").Value = Range("O1:O65536").Value
Start = Timer
Call Zamien_kolumne_v1
Debug.Print "Makro ""Zamien_kolumne_v1"" wykonywało się : " & Format(Timer - Start, "0.00") & " sec."
Start = Timer
Call Zamien_kolumne_v2
Debug.Print "Makro ""Zamien_kolumne_v2"" wykonywało się : " & Format(Timer - Start, "0.00") & " sec."
End Sub
Sub Zamien_kolumne_v1()
Dim Tbl1
Dim x, i As Long
ReDim x(1 To 15)
Tbl1 = Range("A1:O65536").Value
With Application
For i = 1 To 14
x(i) = .Transpose(.Index(Tbl1, 0, i))
Next i
x(15) = .Transpose(Range("Q1:Q65536").Value)
Range("S1").Resize(65536, 15) = .Transpose(x)
End With
End Sub
Sub Zamien_kolumne_v2()
Dim Tbl1() As Variant
Dim Tbl2() As Variant
Tbl1 = Range("A1:O65536").Value
Tbl2 = Range("Q1:Q65536").Value
CopyMemory VarPtr(Tbl1(1, 15)), VarPtr(Tbl2(1, 1)), iSize * UBound(Tbl2)
Range("AJ1").Resize(65536, 15).Value = Tbl1
ZeroMemory VarPtr(Tbl1(1, 1)), UBound(Tbl1, 1) * UBound(Tbl1, 2) * iSize
Erase Tbl1, Tbl2
End Sub | Zamieniamy tutaj ostatnią kolumnę tablicy. |
_________________ Hardware - ta część komputera, którą można kopnąć kiedy software przestanie funkcjonować.
Szkolenia z Excela , FB
Office 2019 Professional Plus , Windows 10 x64
Pozdrawiam, były mkkk23 teraz Marecki. |
|
|
 | ID posta:
400634
|
|
|
 |
|
|
|
Nie możesz pisać nowych tematów Nie możesz odpowiadać w tematach Nie możesz zmieniać swoich postów Nie możesz usuwać swoich postów Nie możesz głosować w ankietach Nie możesz załączać plików na tym forum Możesz ściągać załączniki na tym forum
|
Dodaj temat do Ulubionych Wersja do druku
|
 |
Strona używa plików cookies.
Kliknij tutaj, żeby dowiedzieć się jaki jest cel używania cookies oraz jak zmienić ustawienia cookie w przeglądarce.
Korzystając ze strony użytkownik wyraża zgodę na używanie plików cookies, zgodnie z bieżącymi ustawieniami przeglądarki.
Sprawdź, w jaki sposób przetwarzamy dane osobowe
|