No a kým som urobil progres, napíšete, že ho netreba
Neva skúste. Neskôr pozriem aj na ten Váš súbor.
Tu som urobil aj nejaký popis + drobné úpravy makra. Tento Váš príspevok som si prečítal až po tom, čo som to dokončil, každopádne mne to funguje, aj na USB (root aj adresár) aj na internom HDD (root aj adresár).
Ešte premýšľam, či by sa dalo (a či by sa mi chcelo), celé to prekopať tak, že by si najskôr urobilo zoznam súborov (možno kolekcia aj s objektami súborov/adresárov, možno len pole súborov urobené rovnakým spôsobom len bez načítavania informácií). Až následne by sa v druhom kole načítavali informácie o súboroch. Získame počet súborov na spracovanie a môžeme zobraziť progres. No na rýchlosti ale stratíme 2x. Raz duplicitným cyklom a raz spomaľovaním pri vypisovaní progresu. No získame prehľad.
O koľkých súboroch a akej celkovej veľkosti sa tu väčšinou bavíme? Nech si to skúsim nasimulovať.
V procedúre GetFiles ten riadok s Dir() už byť nemá. Naopak som tam ja zabudol dať ešte deklaráciu premennej CountHidden
CountHidden as Long
Pre lepšiu čitateľnosť kódu ešte odporúčam zarovnať vždy na rovnakú úroveň tabulátorom začiatok a koniec konkrétneho cyklu For-Next, priradenia With-End With, alebo podmienky If-Else-End If.
No a čo tie prvé 2 stĺpce, to nechcete radšej tiež v tom makre urobiť? Príde mi zbytočné následné rozkopírovanie vzorcov.
Zatiaľ nevidím problém...
Ešte sa rozpíšte o tom, aká veľká, alebo ako končí oblasť KRITERIUM.
Môže sa stať že bude hodnota z B rovnaká aj pre inú skupinu z A?
Budú vždy rovnaké skupiny v A zoradené všetky za sebou?
Problém a riešenie sú jednoduché.
Problém:
Tento riadok v pôvodnom kóde kontroluje existenciu adresára. To je v poriadku, takto to používam aj ja. Ale nie v parametrizovanej procedúre, kde je vstupný parameter priamo objekt adresára. Teda je jasné, že adresár existuje, keď do procedúry vstupuje ako objekt (teda overený). Preto som tento riadok, ktorý v tomto prípade robí duplicitné overenie existencie, odstránil. Keďže ale Dir() používa parameter vbDirectory, tak vbHidden neberie. Preto sa cez tento riadok nedostane "System Volume Information" (systémový skrytý adresár). Odbočka - ak by ste niekedy potreboval, aby cez Len(Dir()) prešiel aj skrytý adresár použite parameter vbDirectory + vbHidden. Takže odstránením tohto riadku z kódu sa skrytý adresár dostane ďalej na spracovanie.
If Len(Dir(objFolder.Path, vbDirectory)) = 0 Then Exit Sub
Riešenie:
Je jednoduché. Vo volacom rekurzívnom cykle použijeme vylúčenie skrytých adresárov:
Namiesto
GetFiles obj
použijeme
If Not obj.Attributes And 2 Then GetFiles obj
a skrytý adresár ani len nevstúpi do procedúry.
Čo si ale treba sekundárne uvedomiť je, že takto môžeme mať v neskrytom adresári skrytý súbor. A ten nám vypíšu obe verzie makra. Logicky. Takže to eliminujeme tak, že aj v cykle čítania súborov dáme overenie atribútu Hidden:
For Each obj In objFolder.Files
radek = radek + 1
...
Next obj
doplníme
For Each obj In objFolder.Files
If obj.Attributes And 2 Then
CountHidden = CountHidden + 1
Else
radek = radek + 1
...
End If
Next obj
If CountHidden > 0 Then CountFiles = CountFiles - CountHidden: ReDim Preserve Info(3 To 8, 1 To CountFiles) 'oprava väčšieho poľa pri Hidden
To WS som tam dal hlavne pre zjednodušenie zápisu. Mne sa to tak lepšie číta. Rozdiel v rýchlosti v tomto prípade bude 0. Ak by ale išlo o veľké množstvo operácii s Worksheets(Hárok), bolo by WS ako premenná rýchlejšie.
GetDetailsOf je pomalé. Nevidím dôvod, prečo zisťovať príponu alebo adresár súboru pomocou GetDetailsOf ???
Skúšal som to na rôznych typoch súboru, dátových, skladieb, videí od adresárov 500 MB až po cca 500 GB. A všade bolo pôvodné makro o 100-150% pomalšie. Minimálne!
Prechádzanie súborov ako takých som neriešil, teda nieje žiadny dôvod, prečo by Vám malo makro ukázať iné súbory. Nič také nepozorujem, ja mám výsledky rovnaké.
Nepoužívajte na všetky info stále GetDetailsOf. Toto trvá iba polku času.
Príklad na hyperlink
Ja by som dal tie prvé riadky takto, ale netuším čo chcete s tým potom robiť.
(*** POZOR v riadku s Table.ReplaceValue fórum maže viaceré medzery za sebou. Postupne sa nahrádza 5,4,3,2 medzier !)
File = Csv.Document(File.Contents(FileName),[Encoding=65001, QuoteStyle=QuoteStyle.None]),
#"Nahradená hodnota" = Table.ReplaceValue(Table.ReplaceValue(Table.ReplaceValue(Table.ReplaceValue(File," "," ",Replacer.ReplaceText,{"Column1"})," "," ",Replacer.ReplaceText,{"Column1"})," "," ",Replacer.ReplaceText,{"Column1"})," "," ",Replacer.ReplaceText,{"Column1"}),
TextFromFile = Table.ReplaceValue(#"Nahradená hodnota","- ","-",Replacer.ReplaceText,{"Column1"}),
//vytvorenie tabuľky dát
#"Filtrované riadky" = Table.SelectRows(TextFromFile, each Text.StartsWith([Column1], "Date") or Text.StartsWith([Column1], "> ")),
#"Nahradená hodnota4" = Table.ReplaceValue(#"Filtrované riadky","> ","",Replacer.ReplaceText,{"Column1"}),
#"Rozdeliť stĺpec podľa oddeľovača" = Table.SplitColumn(#"Nahradená hodnota4", "Column1", Splitter.SplitTextByDelimiter(" ", QuoteStyle.Csv), {"Column1.1", "Column1.2", "Column1.3", "Column1.4", "Column1.5"}),
#"Hlavičky so zvýšenou úrovňou" = Table.PromoteHeaders(#"Rozdeliť stĺpec podľa oddeľovača", [PromoteAllScalars=true]),
#"Zlúčené stĺpce" = Table.CombineColumns(#"Hlavičky so zvýšenou úrovňou",{"Date", "Hour"},Combiner.CombineTextByDelimiter(" ", QuoteStyle.None),"DateHour"),
#"Zmenený typ4" = Table.TransformColumnTypes(#"Zlúčené stĺpce",{{"DateHour", type datetime}}),
#"Zmenený typ pomocou miestneho nastavenia" = Table.TransformColumnTypes(#"Zmenený typ4", {{"T_Set", type text}, {"T_Eff", type number}, {"T_Rec", type number}}, "en-US"),
...
Inak ten hypertextový odkaz je predsa jednoduchý. K Tabuľke (v Exceli, nie v PQ) pridáte stĺpec so vzorcom. Buď ako 1. alebo ako posledný stĺpec. Podľa toho, či chcete mať iba Batch číslo (ktoré pravdepodobne nakoniec nebude číslo ale znaky), alebo názov súboru, alebo celú cestu, a pod. Použije sa napr. skrytý stĺpec, ktorý PQ vyplní, a vzorec sa iba odkáže na súbor z tohto stĺpca. Je to jednoduché, ale nebudem opäť meniť PQ dotaz, pokým nedáte ako PRESNE má vyzerať výsledok. Už sú to 3 strany s jednou úpravou za druhou. Uznajte sám, že takéto dávkovanie požiadaviek je ako "Neverending Story" - a to je na nervy ...
Píšem to stále dookola v každom treťom vlákne - priložte manuálne vytvorenú požadovanú formu výsledku. Teda nielen pokusy s nesprávnymi výsledkami, formátmi a pod, ale aj to čo chcete dosiahnuť. Podľa toho riešiteľ ľahšie a rýchlejšie zistí, čo má byť výsledok.
EDIT:
Moment, musím priložiť prílohu s osekaným PQ, lebo fórum maže viaceré medzery za sebou ...
Ten Lubov kód je pre mňa tiež nepochopiteľný
PQ je pre mňa okrajová záležitosť. A tie jeho techniky, sila.
Upravil som ten môj podľa požiadaviek.
Tie medzery s mínusmi sú problém min v 2 stĺpcoch
PR03(kPa)
PR01(kPa)
no potom sú bez mínusu napr. v Humidity(%), ale počítal som, že to môže nastať kdekoľvek. Preto som najskôr odstránil akékoľvek spojené medzery, a následne nahradil "- " (mínus a medzera) iba znakom "-", čo mi potom dalo možnosť deliť riadok na stĺpce pomocou zostávajúcich medzier.
Ako sme to robili? Ja osobne neovládam PQ tak dobre ako Lubo (a iný), takže niečo ako vidieť podľa názvov premenných je naklikané v menu PQ, zvyšok som dopísal ručne. Nevadí, že neviem, ako sa presne píše syntax danej funkcie (pozor - navyše CaseSensitive), veď máme Google. Ak chcem napr. text zľava, vygooglim si "power query left" a dozviem sa, že funkcia sa nevolá Text.Left ale Text.Start ...
Veľa vecí som si ale pospájal v jednom riadku, je to neprehľadnejšie, ale nenaskrolujem sa toľko.
Ale aj tak musíte mať trochu programátorské myslenie.
AK ide o všetky čísla riadkov:
Sub IDRadku()
Dim Oblast As Range, ARE As Range, aID(), Count As Long, IDCount As Long, i As Long, R As Long
Set Oblast = Selection
For Each ARE In Oblast.Areas
Count = ARE.Rows.Count
R = ARE.Row - 1
ReDim Preserve aID(1 To IDCount + Count)
For i = 1 To Count
aID(IDCount + i) = R + i
Next i
IDCount = IDCount + Count
Next ARE
End Sub
Ak ide o adresy riadkov (1 riadok znamená "1:1"):
Sub IDRadku2()
aID = Split(Replace(Selection.EntireRow.Address, "$", ""), ",")
End Sub
Ak ide o označenia riadkov podoblastí (1 riadok znamená "1"):
Sub IDRadku3()
Dim i As Long, aID() As String, tmpID() As String
aID = Split(Replace(Selection.EntireRow.Address, "$", ""), ",")
For i = 0 To UBound(aID)
tmpID = Split(aID(i), ":")
If tmpID(0) = tmpID(1) Then aID(i) = tmpID(0)
Next i
End Sub
Lubove znalosti a skúsenosti sú obrovské, málokto sa mu tu vyrovná (mňa nevynímajúc). Tieto jeho podnety a príklady som ešte neskúšal. V prvom rade totiž musím pochopiť "wo co tady go". A to sa mi nechce. Radšej (ak bude čas, ako vidieť na mojej absencii)), tak dorobím tie požadované ďalšie 3 stĺpce do môjho riešenia, ktorému rozumiem, a chápem ako fungujú jednotlivé kroky, a prečo som ich tam dal, čo som chcel dosiahnuť.
Bod 4. HT odkazy - to v PQ asi nepôjde.
To číslo "Filmy 92" znamená čo? Že pod Filmy je 92 filmov?
A tiež by sa šikla príloha s nejakými dátami..
Na to je najlepšia príloha ...
nemusí to nájsť datumbunka
.Find(What:=datumbunka)
a rng bude nothing. vymalované.
Možno treba konverziu dátumu na Long. Treba prílohu, to bude prkotina...
Oblíbený formulář Faktura byl vylepšen a rozšířen.
Více se dočtete zde.
Používáte podnikový systém Helios iNuvio? Potřebujete pomoci se správou nebo vyvinout SQL proceduru? Více informací naleznete na stránce Helios iNuvio.