V článku Tabulka aneb Seznam čili ListObject jsme se věnovali Tabulkám z pohledu práce na listu. Dnes si je osaháme prostřednictvím kódu VBA, kde jim není vyhrazen podle očekávání objekt Table, ale ListObject. Následující procedury najdete v přiloženém sešitu a doporučuji je odkrokovat při současném zobrazení listu s Tabulkou. Tabulka pro VBA ProExcel.cz
V kódu najdete hodně poznámek ohledně posunu buněk pod Tabulkou. K němu (ne vždy) dochází, pokud v Tabulce mažete/přidáváte řádky nebo měníte zobrazení Řádku souhrnů. Pokud toto řešit nechcete, tak se držte toho, co bylo řečeno posledně do prostoru pod Tabulkou již nevkládejte žádné s ní nesouvisející hodnoty. 0 0 0 Sub TabulkaCasti() With lotabulka 'celá tabulka.range.select 'hlavička tabulky.headerrowrange.select 'datová část tabulky.databodyrange.select 'datová část tabulky (konstanty, tj. bez vzorců).databodyrange.specialcells(xlcelltypeconstants).select 'druhý sloupec tabulky.listcolumns().range.select 'datová část druhého sloupce tabulky.listcolumns().databodyrange.select 'třetí datový řádek tabulky.listrows().range.select 'řádek souhrnů (pokud je zobrazen) '.ShowTotals = True.TotalsRowRange.Select ProExcel.cz
0 Sub TabulkaVlastnosti() With lotabulka 'počet řádků včetně hlavičky (a řádku souhrnů) intpocetradku =.Range.Rows.Count 'počet datových řádků intpocetzaznamu =.ListRows.Count 0 0 Sub TestBunkaTabulky() Dim rngbunka As Range Dim blnbunkatabulky As Boolean Set rngbunka = ActiveCell On Error Resume Next 'je buňka součástí Tabulky? blnbunkatabulky = (rngbunka.listobject.name <> "") On Error GoTo 0 If blnbunkatabulky = True Then 'výběr datové oblasti Tabulky, jíž je buňka součástí rngbunka.listobject.databodyrange.select ProExcel.cz
0 0 Sub PridaniJednohoRadku() 'zobrazení řádku souhrnů není na překážku With lotabulka 'vložení nového řádku na konec tabulky.listrows.add 'vložení nového řádku na konec tabulky 'buňky pod tabulkou se neposunou.listrows.add AlwaysInsert:=False 'pozn. Zobrazení/skrytí řádku souhrnů posouvá 'buňky ležící pod Tabulkou vždy... 'vložení nového řádku nad. záznam 'tj. definujeme pozici nového řádku.listrows.add () ProExcel.cz
0 0 0 0 Sub PridaniDatNaKonec() 'Zack Barresse Dim arrpridavanadata As Variant Dim inpocetradku As Integer Dim intpocetsloupcu As Integer 'převzetí dat, zde z oblasti buněk do pole arrpridavanadata = wshlist.range("b0:d").value 'rozměry datového bloku (pole) inpocetradku = UBound(arrPridavanaData, ) intpocetsloupcu = UBound(arrPridavanaData, ) 'nutné skrytí řádku souhrnů, pokud je zobrazen 'pozor, dojde k posunu buněk ležících pod Tabulkou lotabulka.showtotals = False With lotabulka.databodyrange 'přidání dat na konec Tabulky 'neposouvá buňky ležící pod Tabulkou.Resize(inPocetRadku, intpocetsloupcu).offset(.rows.count).value = _ arrpridavanadata 'zobrazení řádku souhrnů 'pozor, dojde k posunu buněk ležících pod Tabulkou 'lotabulka.showtotals = True 'oživení filtru If lotabulka.showautofilter = True Then lotabulka.autofilter.applyfilter Pozn. Řádek souhrnů je sice chytrý, ale někdy nám prostě překáží. ProExcel.cz
0 0 0 Sub VlozeniDat() 'Zack Barresse Dim arrpridavanadata As Variant Dim inpocetradku As Integer Dim intpocetsloupcu As Integer 'převzetí dat, zde z oblasti buněk do pole arrpridavanadata = wshlist.range("b0:d").value 'rozměry datového bloku (pole) inpocetradku = UBound(arrPridavanaData, ) intpocetsloupcu = UBound(arrPridavanaData, ) With lotabulka.databodyrange 'přidání dat mezi a. řádek Tabulky 'tj. pod. řádek 'neposouvá buňky ležící pod Tabulkou.Resize(inPocetRadku).Offset().Insert Shift:=xlShiftDown.Resize(inPocetRadku, intpocetsloupcu).offset().value = _ arrpridavanadata 'oživení filtru If lotabulka.showautofilter = True Then lotabulka.autofilter.applyfilter Pokud se nepletu, Tabulku průvodci na listu nativně nabízejí pro zdroje dat z Microsoft Access, Microsoft Excel a pravděpodobně i z Microsoft SQL nebo třeba MySQL. V případě textových souborů (CSV) to trochu skřípe. Je otázka, zda-li jít cestou QueryTable či OLEDB (ADO, schema.ini). O tom ale zase někdy jindy. Nyní se podíváme na filtrování. ProExcel.cz
0 0 0 0 Sub TabulkaFiltr() 'zapnutí/vypnutí filtru Tabulky 'lotabulka.range.autofilter 'striktní obsah (Richtr) lotabulka.range.autofilter Field:=, Criteria:="=Richtr" 'striktní obsah (vše kromě položky Richtr) lotabulka.range.autofilter Field:=, Criteria:="<>Richtr" 'obsah (položky začínající na písmeno K) '?... jeden znak, *... žádný nebo více znaků lotabulka.range.autofilter Field:=, Criteria:="=K*" 'striktní obsah (Koch nebo Morávek) lotabulka.range.autofilter Field:=, Criteria:="=Koch", Operator:=xlOr, _ Criteria:="=Morávek" 'striktní obsah (Koch, Morávek, Sochor) lotabulka.range.autofilter Field:=, Criteria:=Array("Koch", "Morávek", _ "Sochor"), Operator:=xlFilterValues 'není nástroj pro "vše kromě položek z následujícího výčtu" 'lze řešit negací úlohy nebo přes rozšířený filtr, tzn. 'OBCHODNIK OBCHODNIK OBCHODNIK '<>Koch <>Morávek <>Sochor 'v případě datumu je nutný americký formát mm/dd/yyyy 'a to bez ohledu na výstup ze Záznamníku maker 'tj. např. Criteria:=">=0//0" 'lze si pomoci funkcemi CLng, CDate 'oživení filtru (po aktualizaci dat) 'If lotabulka.showautofilter = True Then ' lotabulka.autofilter.applyfilter ' Pozor na jednu nebezpečnou věc. V rámci filtru a parametru Criteria očekává Excel String a to i v případě čísel a testování rovnosti (regulérně bychom měli doplňovat znak =, např. Criteria:= = ). ProExcel.cz
Běžně si Excel s předaným číselným typem (Integer) poradí i bez uvedeného rovnítka, ale rozhodně tento stav nesmí nastat při užití Operator:= xlfiltervalues. Jestliže takto definovanému filtru předhodíte jednu hodnotu číselného typu, tak Excel začne dělat psí kusy, přestane fungovat překreslování a aplikace nepůjde korektně zavřít. Jedná se podle mě o neošetřený stav a bug. 0 0 Sub ResetFiltruTabulky() 'pokud Tabulka používá filtr... If lotabulka.showautofilter Then 'pokud je filtr aktivní If lotabulka.autofilter.filtermode Then 'zobrazení všech dat lotabulka.autofilter.showalldata Pucování tabulky od dat lze řešit dvojím způsobem. Osobně jsem si oblíbil druhý z nich. ProExcel.cz
0 0 Sub VycisteniTabulky() 'vymazání všech datových řádků tabulky 'nelze aplikovat na Tabulce bez datových řádků If lotabulka.listrows.count > 0 Then lotabulka.databodyrange.delete 'výsledek: 'podobjekt DataBodyRange = Nothing 'Tabulka zobrazuje jeden fiktivní datový řádek (bez vzorců) 'Rows.Count = pro hlavičku + fiktivní řádek 'ale (!) ListRows.Count = 0 'dojde k posunu buněk ležících pod Tabulkou 'pro další práci je nutné přidat alespoň jeden řádek lotabulka.listrows.add 'dojde k navrácení případných vzorců ve sloupcích 'pozn. vzorce se uchovávají v../xl/tables/table?.xml 'buňky ležící pod Tabulkou se neposunou ProExcel.cz
0 0 Sub VycisteniTabulky() 'operace proběhnou jen na minimálně jednořádkové 'vyplněné datové oblasti On Error Resume Next Application.ScreenUpdating = False With lotabulka.databodyrange 'odstranění všech řádků kromě prvního.resize(.rows.count - ).Offset().Delete 'vyčistění zbylého řádku od hodnot (vzorce ponechány).specialcells(xlcelltypeconstants).clearcontents On Error GoTo 0 Application.ScreenUpdating = True Příloha (váže se i k předchozímu článku): tabulka.zip ProExcel.cz 0