Pro informace o výuce Excelu klikněte zde
V návodu na odstranění netisknutelých znaků v oblasti jsem ukázal jak efektivní a rychlé může být zpracování hodnot v poli.
Tady tuto techniku rozepíšu o trochu vice.
1. Načtení oblasti do 2Dpole
Vytvořil jsem oblast 1000 řádků a 100 sloupců (tj. 100 000 buněk) a do každé buňky v oblasti jsem vložit hodnoty.
1.1. Můžeme procházet oblast a vkládat hodnoty do pole
Sub OblastDoPole1()
Dim Pole() 'Definování dynamického pole
Dim Oblast As Range
Dim r As Long, s As Long
Dim cas As Date
cas = Timer
Set Oblast = ActiveSheet.UsedRange
'Určení velikosti pole podle oblasti
ReDim Pole(1 To Oblast.Rows.Count, 1 To Oblast.Columns.Count)
'Procházení oblasti v cyklu a vkládání hodnot do pole
For r = 1 To Oblast.Rows.Count
For s = 1 To Oblast.Columns.Count
'Zápis Oblast.Range("A1") vrací pravou horní buňku oblasti
Pole(r, s) = Oblast.Range("A1").Offset(r - 1, s - 1)
Next s
Next r
Set Oblast = Nothing
MsgBox "Oblast načtena do pole za: " & Format(Timer - cas, "0.0"), vbInformation
End Sub
Doba trvání načtení do pole za: 3,5 s.
1.2. Lepší způsob načtení oblasti do pole
Sub OblastDoPole2() Dim Pole As Variant 'musí být typ Variant, bez závorek Dim cas As Date cas = Timer 'Timto způsobem získáme vždy dvourozměrné pole, spodní hranice začíná od 1 Pole = ActiveSheet.UsedRange MsgBox "Oblast načtena do pole za: " & Format(Timer - cas, "0.0"), vbInformation End Sub
Doba trvání na mém počítači: 0,2 s.
2. Zápis dvourozměrného pole do oblasti
Pokud vložíme oblast do pole, můžeme stejným způsobem vložit pole zpátky do oblasti.
ActiveSheet.UsedRange = Pole
Ale v mnoha případech potřebujeme upravit velikost oblasti podle velikosti pole.
Range("A1").Resize(UBound(Pole, 1) - LBound(Pole, 1) + 1, UBound(Pole, 2) - LBound(Pole, 2) + 1) = Pole
Kde:
LBound(Pole, 1) nám vrací spodní hranici prvního rozměru
LBound(Pole, 2) nám vrací spodní hranici druhého rozměru
UBound(Pole, 1) nám vrací horní hranici prvního rozměru
UBound(Pole, 2) nám vrací horní hranici druhého rozměru.
Spodní hranice nemusí začínat od nuly, proto zjišťuji hodnotu spodní hranice o odečítám od horní.
Tak dostanu univerzální zápis nezávislý na spodní hranici pole.
3. Užitečné funkce při práci s poli
Pokud pracujeme s poli, potřebujeme zjistit, zda proměnná je typu pole.
Function JePrazdnePole(Pole As Variant) As Boolean
Dim SpodniRozmer As Long
Dim HorniRozmer As Long
JePrazdnePole = True
On Error Resume Next
If Not IsArray(Pole) Then Exit Function
HorniRozmer = UBound(Pole, 1)
If Err.Number = 0 Then
Err.Clear
SpodniRozmer = LBound(Pole)
'Občas se může stát,
'že zjištění horního rozměru nám nevrátí chybu,
'i když je pole prázdné, ale hodnotu -1
If HorniRozmer > SpodniRozmer Then JePrazdnePole = False
End If
End Function
Zkouška funkce
Sub ZkoukaNaPrazdnePole
Dim Pole As Variant
Dim Pole2() As Variant 'Definování dynamického pole
Dim Pole3(10,2) As Variant 'Definování statického pole
Debug.Print JePrazdnePole (Pole) 'Vrátí True
Pole = Range("A1:B10")
Debug.Print JePrazdnePole (Pole) 'Vrátí False
Debug.Print JePrazdnePole (Pole2) 'Vrátí True
Debug.Print JePrazdnePole (Pole3) 'Vrátí False
End Sub
Další užitečná funkce zjišťuje počet rozměrů pole.
Function PocetRozmeruPole(Pole As Variant) As Integer
' Vrací počet rozměrů pole
Dim Pocet As Integer
Dim Velikost As Integer
On Error Resume Next
'Ve smyčce zjišťujeme počet rozměrů pole do té doby, než nastane chyba
Do
Pocet = Pocet + 1
Velikost = UBound(Pole, Pocet)
Loop Until Err.Number <> 0
PocetRozmeruPole = Pocet - 1
End Function
Transpozice dvourozměrného pole. Pro transpozici pole můžeme použit vestavěnou funkci Excelu Transpose.
Pole = Application.WorksheetFunction.Transpose(Pole)
Nesmíme zapomenout, že takto můžeme transponovat jen dynamicky definované pole. Pokud se takto pokusíme transponovat pole deklarované Dim Pole(0 To 10, 1 To 100) Excel vrátí chybu.
Funkce Transpose má ve starších verzích Excelu své limity, viz.: http://support.microsoft.com/default.aspx?scid=kb;en-us;177991
Pro tyto případy můžeme transponovat pole pomocí této procedury:
Sub Transponuj2DPole(Pole As Variant)
Dim tmpPole As Variant
Dim lb1 As Long, lb2 As Long, ub1 As Long, ub2 As Long
Dim r As Long, s As Long
lb1 = LBound(Pole, 1)
lb2 = LBound(Pole, 2)
ub1 = UBound(Pole, 1)
ub2 = UBound(Pole, 2)
ReDim tmpPole(lb2 To lb2 + ub2 - lb2, lb1 To lb1 + ub1 - lb1)
For r = LBound(Pole, 2) To UBound(Pole, 2)
For s = LBound(Pole, 1) To UBound(Pole, 1)
tmpPole(r, s) = Pole(s, r)
Next s
Next r
Erase Pole
Pole = tmpPole
End Sub
4. Dva příklady vytvoření pole a následně hromadný zápis do buněk
Vytvoření měsíčního kalendáře podle aktuálního měsíce a následné vložení do listu
Sub vlozMesicniKalendardoListu()
Dim r As Integer, s As Integer
Dim poleDatumu(1 To 6, 1 To 7) As Date
Dim prvniDen As Date
Dim denTydne As Integer
prvniDen = DateSerial(Year(Date), Month(Date), 1)
denTydne = Weekday(prvniDen, vbMonday)
prvniDen = prvniDen - denTydne + 1
For r = 1 To 6
For s = 1 To 7
poleDatumu(r, s) = prvniDen
prvniDen = prvniDen + 1
Next s
Next r
With Range("A1").Resize(UBound(poleDatumu, 1) - LBound(poleDatumu, 1) + 1, UBound(poleDatumu, 2) - LBound(poleDatumu, 2) + 1)
.NumberFormat = "dd.mm.yy ddd"
.Value = poleDatumu
.Columns.AutoFit
End With
End Sub
Vytvoření ročního kalendáře podle aktuálního roku a následné vložení do listu
Sub vlozRocniKalendardoListu()
Dim r As Integer, s As Integer
Dim poleDatumu(1 To 53, 1 To 7) As Date
Dim prvniDen As Date
Dim denTydne As Integer
prvniDen = DateSerial(Year(Date), 1, 1)
denTydne = Weekday(prvniDen, vbMonday)
prvniDen = prvniDen - denTydne + 1
For r = 1 To 53
For s = 1 To 7
poleDatumu(r, s) = prvniDen
prvniDen = prvniDen + 1
Next s
Next r
With Range("A1").Resize(UBound(poleDatumu, 1) - LBound(poleDatumu, 1) + 1, UBound(poleDatumu, 2) - LBound(poleDatumu, 2) + 1)
.NumberFormat = "dd.mm.yy ddd"
.Value = poleDatumu
.Columns.AutoFit
End With
End Sub
Díky.
Jediný odkaz na netu, kde je to „polopaticky“ vysvětleno