Excel Forum - Porady, Pomoc,  Excel Help, Excel FAQ Strona Główna
 FAQ  RegulaminRegulamin  Szukaj   Użytkownicy   Grupy   Rejestracja   Profil   Twoje wiadomości   Zaloguj 


Poprzedni temat «» Następny temat
ID tematu: 68718 Skopiuj do schowka 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 Skopiuj do schowka
 
 
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 Skopiuj do schowka
 
 
Maciej Gonet 
Excel Expert


Wersja: Win Office 2016
Pomógł: 2033 razy
Posty: 6431
Wysłany: 18-02-2021, 11:28   

Ładnie :clap , 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?
Kod:
Dim Tbl1

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 Skopiuj do schowka
 
 
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. :cry:

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 Skopiuj do schowka
 
 
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 Skopiuj do schowka
 
 
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 Skopiuj do schowka
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
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

Skocz do:  

Powered by phpBB modified by Przemo © 2003 phpBB Group
Theme xandgreen created by spleen& Programosy modified v0.3 by warna
Opieka techniczna www.marketingNET.pl

Archiwum

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