Psal jsem to již dříve z pohledu možných chyb způsobených makrem při pádu, respektive při chybném ladění kdy nedojde k zavření skrytě otevřeného souboru. Obě záležitosti mají svá pro a proti.
Dá se to také použít současně – tedy „vzorc v makru". Je to jakýsi kompromis mezi jistotou a rychlostí. Zase jen „rychlou jehlou" :
Sub Main_1
Dim Sheets, Sheet As Object
Dim Cell, Cell1 As Object
Dim sVal, sVar as string
Dim iVal as long
Sheets = ThisComponent.getSheets()
Sheet = Sheets.getByName("Adresy_Calc")
Sheet2= Sheets.getByName("Tabulka výsledků")
sTimer = Timer()
For i = 2 To 38 '6 'cyklus upravte podle potřeby
Cell = Sheet. getCellByPosition (0 , i)
sVal = Cell.String
Cell2 = Sheet2.getCellByPosition (2 , i)
'Poznámka1 Vzorec 1 je po opakovaném testu as o 6% pomalejší, nežli vzorec s IF
'Cell2.Formula = "=DDE(""soffice"";""" & sval & """;""List2.A2"")"
Cell2.Formula = "=IF(ISNA(DDE(""soffice"";""" & sval & """;""List2.A2""))=1;"""";DDE(""soffice"";""" & sval & """;""List2.A2""))"
'Poznámka2 Vzorec s ISNA je rychlejší v cyklu, nežli Vzorec 1 - cca 6%
'Poznámka3 test IF IsNumeric(Cell2.Value) Then způsobuje podivnou chybu. Přepíše na číslo správně výsledek bez chybného načtení
' Pokud je podmínka vyhodnocena jako nepravda zapíše do buňky nulu. Tuto nulu nelze v cyklu změnit na string (""), ani
' jinak odstranit například pomocí oCellRange.clearContents(abcd), nebo RemoveRange
' ani nahraným makrem (UNO). nepomohl ani čas (WAIT). Jde to přepsat po zastavení cyklu všemi postupy
IF Cell2.Value > 0 Then 'Tato podmínka nemusí vždy vyhovovat - potom například zadáme Cell2.Value <> 0
iVal = Cell2.Value
Cell2.Value = iVal
Else
Cell2.String = ""
End If
Next i
eTimer = Timer() - sTimer
print eTimer/36
End Sub
Mělo by to chodit ve Vašich sešitech, ale musíte upřesnit sešity. Je to napasované na ten můj sešit. Princip je jednoduchý. Makrem Main_1 vkládáme vzorec s IF(ISNA(DDE(…))). Je to možné také pomocí DDE bez IF, nebo snad i pomocí IsError. Vzorec s IF se mi jevil jako rychlejší, ale Calc je v tomto smyslu docela nestabilní.
Vzorec ihned vyhodnotíme na číslo > 0 (respektive číslo <> 0) a vložíme jej už jen jako číslo. Pokud této podmínce neodpovídá – není tam nic. Tím zaručujeme, že by se žádný odkaz neměl udržet, a pokud ano tak jen dík pádu při výkonu makra. (To je řešení při manuálním vkládání vzorců. Výsledek načteme a vložíme jinak – jen čísla – a odkaz jako propojení je pryč.)
Je tam také test časem (cyklus na 36 souborů a proto čas eTimer/36). Čas je hrozně dlouhý, ale je to kompromis.
Upravil jsem to ještě na jednorázový vzorec, který se převádí na číslo, nebo nic (""). Ten startuje tak, že se spustí na správném řádku – sešitě nezáleží – zapisuje do správných kolonek. Pokud ho budete používat ve svých sešitech musíte posunout řádky tak aby odpovídaly „čtený" a „zapisovaný". Já jsem posunul v listu1 hlavičku tak, aby byl stejný řádek pro oba sešity. Je to příprava pro „function", ale to bych udělal až při požadavku – takže zase jen „rychle".
Sub Main_2 'Vhodné k volání jednotlivého dne. Je jedno z jakého sešitu voláte - jde jen o řádek na kterém stojíte
Dim Sheets, Sheet As Object
Dim Cell, Cell1 As Object
Dim sVal, sVar as string
Dim iVal as long
Sheets = ThisComponent.getSheets()
Sheet = Sheets.getByName("Adresy_Calc")
Sheet2= Sheets.getByName("Tabulka výsledků")
sTimer = Timer() 'Případně smazat - slouží k testování
i = ThisComponent.CurrentController.getSelection().RangeAddress.StartRow
Cell = Sheet. getCellByPosition (0 , i)
sVal = Cell.String
Cell2 = Sheet2.getCellByPosition (2 , i)
Cell2.Formula = "=IF(ISNA(DDE(""soffice"";""" & sval & """;""List2.A2""))=1;"""";DDE(""soffice"";""" & sval & """;""List2.A2""))"
IF Cell2.Value > 0 Then 'Tato podmínka nemusí vždy vyhovovat - potom například zadáme Cell2.Value <> 0
iVal = Cell2.Value
Cell2.Value = iVal
Else
Cell2.String = ""
End If
' Tohle až k End Sub můžete smazat a s tím také sTimer = Timer() je to kvůli testování
eTimer = Timer() - sTimer
MsgBox(" Otestování tohoto případu trvalo " & eTimer & " vteřin",64,"Test časové náročnosti")
End Sub
Takže k variantám typu: soubor je a je zdravý, soubor je poškozen, soubor je zamčený, soubor není, práce se soubory je zkomplikovaná zmrveností po předešlém pádu systém, jistě i něco dalšího se "stavem souborů" - přibývá i varianta soubor je otevřený a vzorce se do něj teprve dodaly vs. soubor se poté zavřel a znovuotevřel již se vzorci.
Já bych řešení viděl asi jen v makru a to ještě z důvodu rychlosti, neboť když jsem zkusil třeba 30 vzorců s DDE na 30 existujících souborů, tak po odkliku hlášky zda aktualizovat externí zdroje jsem čekal asi 6 vteřin než se načetly buňky z 30-ti malých souborů. Pro několik stovek souborů to při vytíženosti serveru nebo zahlcenosti sítě nebo otevírání větších souborů může být nejspíš buď nechutně pomalé nebo možná i dojít na zásek keplu. V makru se alespoň jako malý bonus dá udělat ukazatel průběhu nebo nezahlcovat kepl tím, že by naráz musel vykonávat několik stovek požadavků :-).
@neutr: naprostý souhlas že když tazatel nějak nekomunikuje tak nemá cenu se tomu dále věnovat. Možná taky nemá čas, nevím, ale ode mně je to v tuto chvíli vše. Jednak je to tak náročná problematika že by mě byla schopná snad "utavit", a jednak jsem nově rozšířil svůj axiom o ms office. Dřív to bylo něco ve stylu: "jak je to z ms office tak je to špatně! (a nemá cenu se tomu věnovat, akorát by to utavilo)". Teď to mám ještě s tím "jak do toho někdo míchá ms office, tak je to špatně!" A ta fce IFERROR je dle toho odkazu ve třetím příspěvku tazatele excelovská.
]]>=IF(ISNA(DDE("soffice";A3;"List.I3"));"";DDE("soffice";A3;"List.I3"))
Přičemž v buňce A3 je cesta k souboru a konstatuji, že tohle funguje bez jakékoliv hlášky o chybějícím souboru.
A to jsem myslel, že bez makra (s ON ERROR GOTO) to nepůjde... :-)
Mimochodem, jde to i maticově a tím lze vracet celé pole dat.
]]> Ono je to schůdné podle mne jak vzorci, tak makrem a i v kombinaci obou způsobů. Makro má oproti vzorcům také nevýhody – nejenom výhody. Makro musí otevírat sešit a potom z něho může číst (vzorce to dělají jakoby mimochodem a když vznikne chyba vyhodí hlášení). Makrem je možné zjistit snadněji o jakou chybu jde.
Ve skutečnosti by mělo stačit jen z úvodního cyklu (v Main) volat „OtevřiSkrytý" a ten vybavit „OnError GoTo". Když se vyskytne chyba, tak nejspíš do správné buňky dát například nulu, nebo i příčinu – to by mělo primárně zajistit IsMissing, ale volání ONError GoTo" se bude chovat jako „FileExist", takže test na přístupnost můžeme obejít s tím že nás příčina nezajímá.
Ale to co je dobré vědět, je skutečnost, že například když z nějakého důvodu LO (AOO, nebo celý OS) spadne, zůstane „načatý" soubor v rozpakovaném stavu a vyžaduje obnovu. Toto se stává často při ladění.
Takhle se to může opakovat, a nakonec tam bude hodně chybných souborů, přestože původně tam žádné takové nebyly. Takto otevřené soubory nehlásí potřebu obnovit, ale chovají se jako chyba když na ně makro najede. Správně by se to mělo testovat právě tím IsMissing – chtělo by to ale nepovinný parametr. Bez nepovinného parametru se to chovalo vždy jako „slepé" hlášení typu FileExists – tedy s výsledkem – je to přístupný soubor ANO/NE.
Bohu žel jde možná o to, že původní kód je z Ooo a nemusí v LO fungovat úplně spolehlivě. To je dnes problém mnoha rutin. Jít do hloubky a dohledat z dokumentace je možné – ale velice náročné a při tom nemusí fungovat ani XrayTool.
Určitě budete souhlasit, že vynaložit spoustu práce na něco, co nemá řádnou poptávku, ani odezvu nemá smysl. Když to udělám bez odezvy – tak už jenom pro sebe protože mne to jako problém zaujalo. To už je pro mne dnes přepych a tak to vlastně dělám lajdácky.
S těmi sorty mám také dost zkušeností. Máte pravdu v tom, že v Basicu naprogramovaný sort s k tomu vestavěnému nemůže ani čuchnout. Je to dáno úrovní jazyka. Pomalejší nežli Basic už je snad jenom UNO. Mne zklamání z řadících (nesprávně třídících) algoritmů v Basicu přivedlo k novému algoritmu pro faktoriál (což je speciální případ Variací bez opakování). Nejčastější algoritmus doloval pomocí MODULO, ale to jde bezpečně jenom do 17!, přestože vzorec umí vyjádřit i více – konkrétně do 170!. Nedá se ale podle toho pracovat s MODULO malých čísel pro konstrukci množin faktoriálu. Jde to pouze u deklarace INT, ale LONG už zaokrouhluje – nedá se to použít. OD 171! už sešit vyhazuje #Value! Přesto já dělám bez problémů například 256! protože nepoužívám Modulo. Taková vychytávka umožňuje například používat celý 8-bitový zdroj jako zdroj Vernamovy šifry (zdroj mnoha různých tabulek které se z faktoriálu čísla 256 generují jako rozpis). Vernamova šifra
Takových a podobných věcí mám mnoho včetně nových verzí kombinatorických vzorců a generátorů, nebo jiných udělátek. Už dávno jsem se rozhodl, že vše ostatní (včetně fóra) potlačím do pozadí – ale skutečnost je jiná. Snad se mi to povede dřív nežli mi bude sedmdesát :-(
=DDE("soffice";"file:/d:/office/adresáře/2015_xls/pokusdělitxml/kraje/jihočeský/jihočeský_ods/Blatná.ods";"List2.B5")
Zde jsem vytvořil sešit s obsahem buňky B5 - výsledek se vrátil tak jak je požadováno. Následně jsem udělal stejný odkaz na jiný soubor, který už ale neobsahuje List2 a tím pádem ani buňku B5 s obsahem (číslo). Vzorec vyhodil chybu N/A. Proto jsem spřáhl do vzorce s ISNA takto :
=IF(ISNA(DDE("soffice";"file:/d:/office/adresáře/2015_xls/pokusdělitxml/kraje/jihočeský/jihočeský_ods/České Budějovice.ods";"List2.B5"))=1;"";DDE("soffice";"file:/d:/office/adresáře/2015_xls/pokusdělitxml/kraje/jihočeský/jihočeský_ods/České Budějovice.ods";"List2.B5"))
A nyní je místo chybové hlášky jen prázdná buňka. To ještě nemusí být řešení pro chybu neexistujícího souboru, ale popisuji cestu jakou se dopracujeme ke správnému řešení :
Otestuje me chybu - zjistíme jakou hlášku vrací a na tu potom postavíme dotaz pro IF. Takhle by to mělo jít i s Indirect a podobně. Prostě vzorce umí otevřít i zavřený sešit.
Ta smyčka se 3 opakováními namísto 366: Vysvětlím jak jsem k tomu došel :-). Jak jsem spustil makro Main tak to na mě hned vybaflo chybový msgbox z fce Nacti_Skryty takže jsem se jal zkoumat proč vlastně - a všiml si chybky v parametru "MacroExecutionMode", což ale nebyl důvod chybové hlášky.
Mimochodem před pár týdny jsem právě tento parametr zkoumal a přemýšlel jestli není nějaké bezpečnostní riziko, že se dá tímto parametrem povolit spustit makra makrem otevíranému souboru bez dotazu. Došel jsem k názoru že ne, že když povolíte souboru makra, tak nemá moc smysl blokovat to, že může otevřít jiný soubor a rovnou mu též povolit makra. Možná proto, že jsem nad tím ne tak dávno víc hloubal, tak mě jeho chybná syntaxe uhodila hned do oka :-). Ale i tak jsem to pro jistotu ověřil v Pitonyakově bibli..
Důvod chyby ale byl o řádek niž v LoadComponentFromUrl - konkrétně to oURL = ConvertToUrl(Str) 'Uvědomil jsem si že tam máte jiný formát URL. Čili jsem to překomentoval aby mi to běželo. Pak už to šlo spustit a přečetl jsem i odklikal ty msgboxy - a samozřejmě využil toho přerušovacího msgboxu. Pak jsem zkusil dát url na neexistující soubor a hned mi to hodilo další chybu z Nacti_Skryty, neboť fce getURLStruct jeho url předala k otevření i když neexistoval. Takže ještě malá úprava aby to testovalo pomocí FileExists a to když jsem pustil, tak první ukázkový soubor to samozřejmě načetlo, ale od druhého do konce smyčky už to na mě pouze plivalo hlášky "Soubor nelze načíst - zřejmě neexistuje." - už se to k tomu ukončovacímu msgboxu do fce Nacti_Skryty ani nedostalo :-). Zkusil jsem sice párkrát po stisku Esc rychle kliknout na ikonku ukončující běh makra v Basic editoru, ale to bylo beznadějné, ten msgbox nabíhal příliš rychle. Ale nakonec alespoň nezvítězila "hrubá síla" Ctrl+Alt+Del a prostě jsem holt "trpělivě" držel Esc s tím, že 366 msgboxů problikne snad rychle. Ale až tak rychlé to taky nebylo :-).
Já nemám moc v oblibě upozorňovat uživatele msgboxy. Již kdysi jste mě upozorňoval, že to je ale mnohdy užitečné s čímž souhlasím - a tak jsem se to naučil víc používat. Nicméně mě to většinou nebaví a to z důvodu, že mi nejdou kombinace a nemám je rád. A někdy se stane, že v programu může nastat několik variant na které by mohlo být vhodné upozornit uživatele nějakým msgboxem, ale vychytat kolikrát všechny ty varianty znamená naládovat tam třeba více proměnných a vícero If Then jenom pro ty různé msgboxy - a to já nerad, kor když by se někdy na nějaké upozornění hodil třeba 4 či 5-ti tlačítkový msgbox kterými však Libre nedisponuje.
Co se týká toho urychlení tak jsem to holt špatně pochopil. Já myslel že to, že to označujete za pomalé, se vztahuje k tomu testování existence souboru a jeho otevírání. Nenapadlo mě že tou pomalostí myslíte až následné načítání či zpracovávání dat z již otevřeného souboru. Ale bylo mi právě divné, že by šlo nějak zrychlit to otevírání souborů a proto jsem vznesl dotaz.
Rychlé zpracování dat je samozřejmě žádoucí a řekl bych že by mělo být mnohdy i prvořadé. S tím mám nějaké zkušenosti a dokonce i dva programátorské úspěchy - arabskou transkripci jsem v jednom případě dokázal zrychlit z asi 3 hodin na 3 minuty; a makro které mi umožňuje setřídit soubor s vyvíjeným fontem jsem z 5 minut načítání souboru a 20 minut ukládání (nyní má ten soubor asi 150tis. řádků) dokázal zrychlit asi na 15 vteřin. Obojí bylo o tom zjistit jaké a jak naparametrované funkce běží či parsují co nejrychleji. Nebylo to jednoduché, ale povedlo se. No a jak již mám trochu zkušeností s nějakými těmi "většími" daty a jejich parsováním, tak už sem kolikrát musel ukončovat přes Ctrl+Alt+Del, neboť jsem to měl právě v nějaké velké smyčce a kolikrát se zděsil z toho, jak je to oproti očekávání pomalé. Takže jsem zvyklý právě na to dělat pro ukázky rovnou spíše malé smyčky :-).
Naposledy jsem takto testoval QuickSort v Basicu (z ODT https://wiki.documentfoundation.org/Mac … Primitives; v Libre 7.1 už je z toho knihovna ScriptForge ale QuickSort tam není, je tam HeapSort) a pro 100tis. položek v poli jsem to po minutě už nevydržel a CtrlAltDel. To Calc to setřídil v pohodě během chviličky. Takže na operace s daty většího pole bude kolikrát lepší využít Calc než se snažit to dělat přímo s tím polem. Nebo jsem si říkal, že se možná pro nějaké operace s velkými poli zkusím naučit něco z Pythonu, jestli by to v něm třeba neběželo rychleji - přeci jen v Nápovědě je jak pouštět makra Pythonu/Basicu v tom druhém. Ale zatím to nepotřebuji tak ne.
Jinak jsem moc rád že jste soubor nezamkl, neb jsem se opět dozvěděl něco nového (konkrétně jsem vůbec neznal com.sun.star.util.URLTransformer a com.sun.star.util.URL). Já beru ukázky na fóru jako příklady ve kterých se klidně mohou vyskytnout chyby a nijak se vás nesnažím "osočit" z jakéhosi lajdáctví či nepořádnosti. A vůbec jsem nechtěl nějak hnidopišsky opravovat chyby, to věru ne. Nicméně proběhlo to jak jsem popsal, takže mi přišlo dobré upozornit na něco co my "neštymovalo" a doufal že se to vyjasní :-).
nebo spíš efektivnější je klást si otázky co a proč autor opravdu chce, nebo potřebuje.
Vy jste již před lety zmiňoval že vaší zálibou je kombinatorika a je to dle mého názoru vidět na tom, jak jste schopen řešit problémy. Nicméně já se nesnažím vymýšlet co by autor dotazu mohl potřebovat, neboť jednak na to nemám ani praktické zkušenosti (přeci jen zkušenosti mám jen ze svých programátorských výtvorů); nemám na to ani znalosti (neb mě ponejvíce zajímá jen to, o čem nějak instinktivně "potuším" že by se mi mohlo dále hodit); a nemám ani čas ani chuť pouštět se do návrhu a realizace nějakého komplexnějšího systému - neb to bývá časově, znalostně i "psychicky" mnohdy strašně náročné.
Takže přemýšlím pouze nad tím, jak vyřešit dotaz; nikoliv nad tím, jak by se "celý systém" třeba dal "udělat lépe". No a vycházím také z toho, že když někdo vznese dotaz na fóru, tak to bude většinou znamenat, že neumí moc programovat. Kdyby programovat uměl, tak si to předpokládám spíše namakruje sám. No a když někdo neumí moc programovat, tak to pro mě také znamená, že mu tak snadno nepůjdou ani různá "komplexnější" řešení + že na jejich naučení a zrealizování stejně nejspíš nebude mít čas :-). Proto nad možnými "vylepšeními systému uživatele" ani nepřemýšlím - neb beztak bych prostě nebyl schopen (ani ochoten) se na jejich vzniku více podílet, skutečně mám dost práce se svými vlastními výtvory.
Prosím nezamykejte ty ukázky i když nejsou třeba úplně odladěné nebo estetické. Dá se kolikrát zjistit něco nového i když třeba z hlediska tématu to nic nového spíše neevokuje :-). Už i váš postřeh o tom, že je rychlejší načíst seznam souborů z adresáře než testovat existenci všech souborů ze seznamu stojí za to. Kdybyste to měl zamčené, tak bych to při chybě nejspíš ignoroval a nechal být a "námitku" nevznesl - a pak by třeba ani tento zajímavý postřeh nemusel "vyplout na povrch" - nebo by "vyplul" třeba až po nějakém vyčerpávajícím pokus/omyl :-).
Myslím že nyní je to nejspíš vyjasněné :-).
]]>Funkce getURLStruct - test existence souboru nikoliv testem vstupního parametru service$, ale pomocí fileExists.
A ve funkci Nacti_Skryty v tom argumentu pro nevykonávání maker chybí "e"
rem if isMissing(service) then
if fileExists(sUrl) then
....
oArgs(1).Name="MacroExecutionMode"
Jedna věc je můj postup práce. Poměrně rychle poskládám makra a otestuji základní funkce. Neladím, jen test zda to funguje. Proto často svoje kódy zamykám – což se Vám moc nepozdávalo. Ale často je taková snaha bez odezvy. Když je odezva a zájem – odladím vše tak jak se má. Stejně jako případné zrychlení.
Nevím co myslíte tím : „A ve funkci Nacti_Skryty v tom argumentu pro nevykonávání maker chybí "e"". Nic takového nevidím, a makro chodí.
IsMissing je trošku širší pojem než FileExist. Soubor může existovat, ale poškozený, stejně tak zamčený a podle parametrů by se mělo dát nastavit jak – „myslím že jen pro čtení", podobně by to mělo být pro „sdílení". Ale to nevím jistě – jenom jsem si poznamenal makro které vykazuje i nepotřebné kódy převzaté z původního makra. Tohle čistím až když dělám finální úpravy. Otestoval jsem a fungovalo to a měl jsem to asi zamknout. Příště to už takhle neudělám.
A ve funcki Main je lepší si v té smyčce For dát pro zkoušení třeba jen hodnotu 3 a nikoliv 366, já po opravě kódu držel snad minutu Esc aby zmizely MsgBoxy než proběhlo těch 366 pokusů :-).
Tato poznámka mi říká, že jste nerozpoznal text upozorňující na to, že se dá skončit cyklus okamžitě – nevím ale číst umíte. Jen jste možná poupravil originální kód a skočil z cyklu For nakonec (nebo obě hlášky smazal).
msgbox(" Jen ukázka jak jsou načteny buňky. Schází uložení do tabulky" & _
" - to se musí upřesnit. O struktuře Vaší tabulky nevím vůbec nic." & Chr(13) & Chr(9) & sText & "",64,"Ukázkový výstup")
print "Skončit - stiskni ZRUŠIT, jinak bude cyklus pokračovat."
oDoc.close(true)
End Sub
V prvém případě (první vložená verze) makro končilo chybou a cyklus se zastaví, proto jsem to ponechal bez úpravy. Kdyby byla chyba i ve druhém případě, cyklus by také skončil.
Také je otázkou zda máte vhodný adresář s 365-ti soubory. Jak je logické zapsat své dva soubory pro test na první stránce a nechat cyklus For bez úpravy?
Já mám jenom vhodný soubor - ten s „čitelnou URL" a uvědomil jsem si, že „barevnej" nikoliv. Možná bych mohl najít některý další, ale to nevím. Také bych mohl seznam přejet makrem, abych to měl zkonvertované – to jsem pokládal za zbytečné. Mám proto otestováno na původním typu URL (a URI jsem netestoval – byl by to skok přímo do buňky). Můj soubor neobsahuje čísla, ale texty. Když zadám čísla, výstup mi ukáže povídání a 11 řádků s nulami. Když je tam „string", normálně je vypsán. URL je vypsáno makrem a potom teprve při otevírání souboru udělám ConvertTo Url().
To jsem si uvědomil až ráno „barevnej" to má už ve zkonvertované formě a té by nemělo vadit opakované konvertování (ConvertToUrl() - chybu by to dát nemělo). Přes to jsem upravil načítání a původní ponechal jako zakomentované.
To s tím ulož.to je nějaký kejkl a tak jsem informoval o Vašem postupu a ráno přidal pro jistotu postup, který jsem aktuálně otestoval.
@neutr: Jak to prosím myslíte s tím zrychlením? Otestujete existenci souboru a když existuje tak se načte pomocí LoadComponentFromUrl aby bylo možné získávat data. Já bych to udělal stejně tak. Ono se na tom dá něco zrychlit?
Když postavím makro – tak jen v pomalé verzi. Většinou se načítá buňka po buňce. Když je buněk více, je potřebné načíst vkládané hodnoty, nebo výstupy do array. Jde o rychlost a jak jistě víte o celkovou optimalizaci, zkrácení a promazání kódu spolu s přehledností. Toto se dělá nejlépe při ladění – testují se časy jednotlivých rutin. Z toho pak zjistím co se vyplatí udělat, nebo dál hledat například rychlejší kód (často Basic místo UNO a podobně).
Původní informace od autora byla taková, že načítá 365 souborů a zde už array sehraje důležitou úlohu. Dokonce by mohlo být až 5x 365 souborů.
I když to není úplně zřejmé, může jít také pouze o hledání jediného souboru z toho celku 365 u kterého se načítá 5 buněk z řádku. Je možné, že některý sloupec z celku 5 obsahuje vzorce a nikoliv přímo vklady hodnot. Například porovnání stejného dne a ze 2 různých let, nebo plán + skutečnost a podobně. Potom budou zřejmě v dalších sloupcích jen vzorce pro výpočet. Jak je na obrázku vidět zřejmě vše slouží jen pro vytvoření grafů (podle autora soubory neukládá, ale co tím myslel také nevím).
Také si představím, že graf je utvořen podle součtů v 2. řádku (záhlaví sloupců s číslem 1. až 5, respektive pořadí 3. až 7. sloupec, tedy C až G). Tyto součty jsou zřejmě kumulativní. To znamená, že kumulace se sčítá od začátku roku až k aktuálnímu dni. Proto průměrná kumulace činí 365/2 záznamů. První jen jediný řádek a poslední 365 řádků.
Jedná se o ekonomické ukazatele, kde se může projevit i nějaká oprava (dobropis či něco podobného) co změní původní hodnoty v tabulce – a to i zpětně. Takže logicky je potom potřeba načíst upravené hodnoty => opakované načtení všech hodnot existujících sešitů. Vzorce je možné aktualizovat – chvilku to trvá, ale nová data se tam dostanou. Makrem by se to muselo opakovaně iterovat – a to je důvod „zrychlení" pomocí array.
Přes to si myslím, že by bylo řešením jenom věcně zadat položku aktuálně hledaného datumu a najít jediný aktuální soubor. Znamená to makro bez iterace spouštění jen třeba s tím, že se makro spustí na určitém řádku ( - ten odpovídá datumu, protože zdroj má datum podle (řádek – 1) a cílová tabulka (řádek-2). Sloupce jsou posunuté o dva. Ve zdroji sloupec 0 odpovídá v tabulce sloupci 2.
Podobně by to mohl být například InputBox, nebo skutečný dialog s polem datum, číslo, nebo i text… prostě nějak zadat datum, nebo pořadové číslo dne. Forma provedení také může být různá od funkce zadávané jako vzorec až po makro, které kontroluje existující záznamy na změnu a zapíše na správný řádek jenom jediný výsledek místo přepisu všech existujících souborů.
K chybě neexistujících souborů : Je mnohem rychlejší aktuálně načíst všechny soubory, které existují ve stejném adresáři. Tyto existující nahrát do prvního listu. Někdy je vydáván každý den soubor se stejným názvem a je potřebné mu udělat samostatnou složku – a nebo přejmenovat. Jde o systém - co se jeví jako vhodnější. Ani soubory samostatně v adresáři není problém načíst makrem stejně jako soubory z jediné složky.
Dotaz na existenci souboru se omezí na záznam v listu1 a nehledá se v adresáři. Naimportované URL mohou být v relaci s řádkem který se rovná dni. Tam kde soubor nebude – nebude žádný text a vzorec otevře jenom existující Url. Jde pouze a jenom o správný koncept. Ovšem pro uživatele je správným konceptem ten kterému rozumí, protože ho sám vymyslel. Ovšem někdy je autorem „vyšší moc" a tak je nutné se zeptat tak jak jsem to udělal ve svém prvním příspěvku, nebo přímo nabídnout „lepší" systematiku. To se opět neobejde bez dotazů. Takže za takové postupy do hloubky jsem byl opakovaně kritizován.
Co tím chci říct? Třeba to, že je sice správné hledat chyby v kódu, ale ještě lepší, nebo spíš efektivnější je klást si otázky co a proč autor opravdu chce, nebo potřebuje. Když byste to dělal dobře, tak se nebudete ptát „proč přepisovat na rychlejší kód". Takže nyní je to na autorovi, ten sice přímo o makro nepožádal, ale uvedl nahrané makro. Z toho jsem dovodil, že by měl zájem. Nyní je na místě čekat na upřesnění.
]]>Funkce getURLStruct - test existence souboru nikoliv testem vstupního parametru service$, ale pomocí fileExists.
A ve funkci Nacti_Skryty v tom argumentu pro nevykonávání maker chybí "e"
rem if isMissing(service) then
if fileExists(sUrl) then
....
oArgs(1).Name="MacroExecutionMode"
A ve funcki Main je lepší si v té smyčce For dát pro zkoušení třeba jen hodnotu 3 a nikoliv 366, já po opravě kódu držel snad minutu Esc aby zmizely MsgBoxy než proběhlo těch 366 pokusů :-).
Opravená verze zde: https://uloz.to/tamhle/4NcjFg1snsU6
Když uloz.to ten soubor zobrazí na černém pozadí namísto aby nabídlo klasický dialog pro rychlé či pomalé stažení (podobně jako když prohlížeč otevře pdf soubor), tak vpravo nahoře na tom černém pozadí kliknout na Detail souboru a skočí to do klasického prostředí s nabídkou stažení. Já na nahrání posledních dvou ukázek myslel že uloz.to se již vrátilo k normálu neb už mi to ty soubory na černém pozadí neotevíralo a nabízelo rovnou ten klasický dialog pro rychlé/pomalé stažení, ale zde je vidět že je to někdy stále nepříjemné.
@neutr: Jak to prosím myslíte s tím zrychlením? Otestujete existenci souboru a když existuje tak se načte pomocí LoadComponentFromUrl aby bylo možné získávat data. Já bych to udělal stejně tak. Ono se na tom dá něco zrychlit?
]]>Bez dalšího upřesnění se Vám to nepodaří rozchodit. Navíc by se to mělo přepsat do rychlých maker. Ale pokud bych neměl čas a podobně, tak je schopen jak kamlan, tak LADER vše dopilovat.
Přeji úspěch
PS uvědomil jsem si, že máte ukázku URL v obrázku který jste postnul. Ta má jiný formát - přepsal jsem makro abyste mohl použít hned Váš formát a odblokoval jsem chybové ukončení cyklu v makru Nacti_Skryty. Nyní už by to mělo být zřetelnější.
Upřesnění by mělo spočívat v tom jaké buňky se ve zdrojovém sešitě načítají - Pro 1.1.2021 jsou to buňky A2 (do C3), B2 (do D3), C2 (do E3), D2 (do F3), E2 (do G3)?
Stačí vyhledat soubor podle datumu? To by bylo rychlé a obešlo by se to i bez seznamu na prvním listu (já používám výpis adres souborů makrem takže tam mám jen existující soubory narozdíl od Vás, kdy kopírujete adresy pod sebe a upravujete vzorcem. Potom se stane, že odkázaný soubor "ještě neexistuje" a volání způsobí chybu). Z makra by mohla vypadnout funkce ověřující existenci souboru a obsah by se spouštěl jako vzorec - prakticky jen makrem Nacti_Skryty - upraveným jako funkce která by buď vypsala hodnotu, nebo by oznámila, že soubor neexistuje.
REM ***** BASIC *****
sub Main
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "ToPoint"
args1(0).Value = "$C$3:$G$3"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args1())
rem ----------------------------------------------------------------------
dim args2(0) as new com.sun.star.beans.PropertyValue
args2(0).Name = "EndCell"
args2(0).Value = "$G$367"
dispatcher.executeDispatch(document, ".uno:AutoFill", "", 0, args2())
rem ----------------------------------------------------------------------
dim args3(0) as new com.sun.star.beans.PropertyValue
args3(0).Name = "ToPoint"
args3(0).Value = "$C$3:$G$367"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args3())
end sub
Nicméně zastávám názor, že vzorcem to jde také, ale musí se použít zapozdřené funkce do IF. Lze stanovit podminku AND ve které se vyhodnotí obě záležitosti. Nejlepší testovací funkcí je skutečně ISERRER, ale může to být i jinak.
]]>Tyhle dva příklady neodstraní chybovou hlášku:
=IF(ISNUMBER(Odkaz)=1;IFERROR(xyz;"");"")
nebo třeba
=IF(ISNUMBER(Odkaz)=1;INDIRECT(odkaz);"")
Pokud se chcete chybových hlášek zbavit, musíte Zabalit do IF() (nebo IFS(). Správně by měl být vložen dotaz na ISNUMBER(Odkaz, nebo Indirect a pod.). Potom zabaleno v IF by to bylo takto :
=IF(ISNUMBER(Odkaz)=1;IFERROR(xyz;"");"")
nebo třeba
=IF(ISNUMBER(Odkaz)=1;INDIRECT(odkaz);"")
Pochopitelně podobných konstrukcí může být více. Dokonce bych viděl jako dobrou cestu makro (případně i funkci). V basicu existuje test ISMISSING který šáhne do externího adresáře a zjistí zda je cesta i soubor přítomen. Zjistit hodnotu z určité buňky už není problém nakopírovat jako číslo. Tedy to ušetří i dost místa místo vzorců - a hlavně žádné chybové hlášky.
Nevím kolik těch externích sešitů máte, ale může jich být opravdu hodně a sešit může začít padat objemem dat dík vzorcům které jsou těžké.