Chvíli mi opravdu trvalo, než jsem pochopil, co ta procedura dělá. Teprve nakonec mi došlo: v té proceduře strávíte 99,9% času tím nejpomaleji možným plněním buněk a jen její nepatrný zbytek bude počítat pomocí funkce, případně vzorce, zaokrouhlené hodnoty.
Toto není test na rychlost funkce, toto je test na pomalost práce s buňkami.
Přesto odpovím: přes hodnotové pole cca třicetkrát rychleji. Z toho JPG se nedalo vyčíst víc než výsledky, v žádném případě konkrétní způsob použití. Čísla ale říkají, že použití nebylo nejvhodnější. Zkušenost mne naučila, abych přestal říkat "líp to nejde", protože poctivější je říct "líp to neumím".
to elCHa:
>>>(RoundX) jsem integroval do souboru, který obsahuje desetitisíce výpočtů a události change a je prošpikován kódem. Tam už prohrála a to jsem musel počet cyklů snížit na 100 (oba spodní případy - u toho prvního jsem zapomněl změnit text).
To s naprostou jistotou není způsobeno tou funkcí samotnou, ale jejím nevhodným použitím.
>>>Pokud toto někdo má, jedná se o pokročilého uživatele, který na to přijde, zjistí příčinu a opraví si. (Týká se změny chování funkce bez změny jejího jména)
To je chyba úvahy. Stovky mých sešitů běhají někdy už deset let po světě mezi jejich (často anonymními) uživateli a stále dobře slouží. Jak by tito uživatelé, postižení novým chováním funkcí, měli hledat, co se to stalo, že jim jejich starý dobrý sešit začal běhat za roh? Jednorázové psaní sešitů "sám pro sebe" je málo produktivní využití vývojářské práce.
>>>UDF je pomalejší, protože si ji musím napsat a odladit.
Pro jednorázové použití - naprostý souhlas. Pro úlohy s dlouhou životností - argument nanic. Čím víc uživatelů má úlohu používat a čím déle to mají činit, tím víc se vyplácí do úlohy vložit vývojářskou práci. Čas, ušetřený v provozu, by měl vždycky zaplatit čas vývojáře. Když mohu ušetřit stovky hodin v provozu, neměl bych se ohánět hodinovou vývojářskou pracností. Je to stejné jako s fixními a provozními náklady.
>>>UDF je nehorázně otravná a pomalá, když potřebuji ladit nějaký projekt (krokovat) a je v listu obsažena několikrát (mohou to být stovky - vlastní zkušenost).
Podobnou zkušenost jsem měl před lety taky. Pak jsem se zamyslel a našel jednoduchý způsob, jak ladit jeden samotný vzoreček: stačí na tu chvíli vypnout Volatile.
Vypadá to, že jste se trefil. Je to zvláštní, ale nevzpomínám si, že bych někdy událost Terminate použil. Budu se muset podívat do chytrých knih, co všechno UserForm.Terminate dělá. Člověk se má pořád co učit. Možnost zeptat se je k nezaplacení. Jednou vím já, jindy někdo jiný. Už Werich zpíval "ten umí to a ten zas tohle, a všichni dohromady uděláme moc". Dík!
Při experimentování s formulářem o proměnné velikosti jsem narazil na zvláštnost, pro kterou neznám vysvětlení ani programátorsky čisté řešení.
Pokud sešit zavolám k jinému otevřenému sešitu, zobrazí se v tom dosud aktivním sešitě můj zavolaný nemodální formulář. To funguje dobře, to chci.
Zavřením nemodálního formuláře křížkem vpravo nahoře se zavře i celý sešit s formulářem. I to je dobře, tak jsem se to snažil napsat.
Potíž nastala, když jsem se po zavření pokusil opět svůj sešit otevřít (aniž bych mezitím přerušil práci s Excelem). Z důvodů, které jsem neodhalil, vznikne při tom chyba 429. Po přeskočení chyby se sešit otevře, ale bez nového otevření formuláře. Během hledání příčiny vadného chování jsem s překvapením zjistil, že opakovaný pokus o otevření už projde bez závady. A tak nyní mám v událostní proceduře Workbook_Open
následující nehezkou konstrukci
On Error Resume Next
PoloPruh.Show 0
If Err <> 0 Then
PoloPruh.Show 0
End If
Prostě, když se to nepovede napoprvé, tak to zkusím podruhé - a uspěji. Nic ošklivějšího jsem snad nikdy nenapsal. Protože to ale funguje a já lepší řešení nemám, tak to tam je.
Pokud někdo odhalí příčinu a najde čistší řešení, udělá mi tím radost. Inkriminovaný sešit je v příloze.
Odklon od českých názvů k angličtině (a následné zapomenutí těch českých názvů) by vážně znehodnotilo spoustu české literatury jak v knižní, tak v elektronické podobě, která s českými názvy samozřejmě pracuje. Proto je celá diskuse o opuštění českých názvů trochu akademická.
Důkazem, že nejsme sami, kdo si z lokálních názvů funkcí utahuje, je půvabný návrh polského názvu pro IF:
CHCELIPANTOTOBOTAMTO.
Mohu uvést českou (a zcela autentickou) podobu podmíněného příkazu v jazyce MAT-5 (jazyk vymyslel Ing.Formandl kolem roku 1965):
JELI A3:B20 SKOKNA 120:150:90
(vyhodnoť rozdíl A3 a B20; pro <0 skoč na řádek 120, pro =0 na řádek 150 a pro >0 skoč na řádek 90).
Než jsem potkal Excel, věřil jsem, že už takovou ptákovinu nikdy nepotkám. Mýlil jsem se ...
Pro svůj archiv jsem přehled upravil a doplnil o některé poznatky z proběhlé diskuse. Zejména jsem si ale do přehledu vložil ten výkonový test, o kterém jsem se již zmínil. Kdo chce, může si novou verzí přepsat tu původní.
Mně osobně se tahle diskuse opravdu líbila a přinesla mi skutečný užitek. Na některých otázkách jsme se vzácně shodli. O jiných si myslím, že stojí zato je zrekapitulovat:
Lubo: mně by také zajímalo, proč přidávají další fce, když stačí opravit ty staré. Pokud se bojí zpětné kompatibility, tak se bojí špatně.
Obávám se, že to není tak jednoduché. Pokud by oprava změnila chování funkce a v některém starém sešitu by tu chybou někdo vědomě využíval, začal by se ten starý sešit chovat vadně. Změna chování funkce si podle mne přímo vynucuje nové jméno funkce.
marjankaj: No pri zaokrúhľovaní záporných čísel pri MROUND možno použiť napríklad =MROUND(A1;SIGN(A1)*5)
Tohle by v žádném případě nemělo zaniknout! Je to pěkné a úplné řešení toho problému; jenom by se nemělo zapomenout na to, že k tomu je také nutno zakázat záporný interval pro druhý parametr. Jen se sám sebe ptám, jak tahle zjevná chyba funkce mohla uniknout Microsoftu...
elCHa: Určitě bych ale nepoužil pomalou UDF a raději se obrátil na rychlejší ROUND.
Každé tvrzení má mít své opodstatnění. Proto jsem provedl svůj výkonový test, o kterém píšu shora.
elCHa: Navíc - pokud jsem to pochopil CEILING, FLOOR jsou přeložené, ale ty s tečkou už ne...
Jak to tak vypadá, jména funkcí listu jsou přeložena vždycky a všechna. Jen u některých je pro "překlad" použito jejich originální znění. Jinými slovy: moje brojení proti českým názvům má snadné technické řešení. To spočívá v prosté výměně jednoho souboru v knihovně Excelu za jiný. V tom okamžiku začnou vzorce na listu pracovat s originálními jmény funkcí (ale s českou interpunkcí !!). Kdybych hodně hledal, tak jména těch souborů k záměně někde vyštrachám.
Nějak se k vám rady nehrnou a ani vy nepospícháte s dodáním podkladů. Když jsem si nechal proběhnout možnosti, jaké má v daném případě "téměř úplný začátečník", vychází mi snad jediná rada. Zkuste začít souhrnem. V nápovědě se podívejte, jak se s ním pracuje a jaké poskytuje možnosti. Když to shledáte účelné, přihrajte nová data pod ta předchozí a všechno setřiďte sloupcem, který nese jednoznačnou identifikaci výrobku. Když z toho teď uděláte souhrn po výrobcích, dostanete první nástin jakéhosi přehledu o nich. Dál už asi budete muset použít vlastní hlavu, pokud se ovšem nenajde někdo, kdo vaši práci udělá za vás...
Ještě že existují staré dobré manuály. U Walkenbacha jsem našel "podmíněné formátování čísel" a s trochou násilí jsem sesmolil formát, který u mne pracuje správně. Ten formát vypadá hrozně:
[<1000]0,00;[>999999]#\.###\.000,00;#\.##0,00
Když ale funguje, tak se dá použít !
to marjankaj: žádná mezera nevadí; zbytečné # se vynechají, natvrdo vložené \. se zobrazí ...
dodatečné upřesnění: místo >999999 je správnější >=1000000
marjankaj radí dobře, až na to, že kratší číslo, např. 1234, se zobrazí jako .1.234,00. Pokud ta tečka vlevo nevadí, je to řešení.
Úloha, jak jste ji shora popsal, není úplně začátečnická. Hlavní komplikace spočívá v tom, že roční přírůstek může obsahovat nové výrobky a jiné výrobky v něm mohou chybět. Pokud si na to netroufáte s VBA (to myslím u vás nehrozí) bude to chtít poměrně rafinované ruční zpracování. Těžká rada! Žádnou jednoduchou neznám ...
Ze zvědavosti jsem si provedl výkonový test pro milion výpočtů funkce listu Ceiling proti shodnému zadání pro milion výpočtů funkce RoundX. Toto je výsledek srovnání:
milion realizací =Ceiling(123.456, 0.1) ........ 4,570 sec,
milion realizací =RoundX(123.456, 0.1, 1) ... 5,551 sec.
Ano Ceiling počítá o něco rychleji, ale sekunda rozdílu na milion výpočtů celou dobu zpracování úlohy prodlouží právě o tu jednu sekundu!
to marjankaj: OO Calc se tady opravdu moc nezmiňuje. Jeho StarBasic jsem si prohlédl jen zběžně, ale z logiky věci se mi zdá, že by mohl UDF umět. Víc než z devadesáti procent má VBA se StarBascem shodný kód. Zatím jsem si ale nenašel čas na to, abych otestoval, jak nejlépe převést VBA do StarBasicu a následně ho odladit. Kdyby s tím někdo měl zkušenost, rád se poučím!
Jinak svůj RoundX jsem napsal spíš kvůli tomu, abych si dokázal, že to dokážu. Jak už jsem napsal, všechno zaokrouhluji stejnou standardní funkcí, pro níž ovšem vhodně upravím vstupní parametry. Vzorec na listu u mne aby pohledal!
Pomalost UDF je jedna z rozšířených pověr o VBA. Samozřejmě lze napsat UDF, které nám umožní uvařit si kafe, než se spočítá. Ale znám i taková UDF, která v rychlosti moc nezaostávají za složitějšími vzorci, a někdy jsou dokonce rychlejší. RoundX mezi ty nejrychlejší funkce patřit nebude, ale s výjimkou obsluhy velkých oblastí na listu nebude ani příliš zdržovat. Vzhledem k tomu, že jsem si dělal výkonové testy na některé ze svých UDF, vím co říkám.
Podle mne si věc kritiku zaslouží. Z pohledu začátečníka je velmi frustrující, když mu Excel nabízí osm způsobů zaokrouhlení, které se v popisu liší často velmi nezřetelně. I z pohledu znalostí Excelu na běžné úrovni je těžké k uchápání, proč ZAOKR.DOLŮ a ZAOKR.NAHORU mají v druhém parametru interval, zatímco ZAOKROUHLIT tam má počet desetinných míst. A problém zaokrouhlit záporné číslo pro MROUND je už jen třešinka na dortu.
Jako ukázku toho, že nepotřebuji mít osm podmíněně fungujících zaokrouhlovacích funkcí, uvádím svou uživatelsky definovanou funkci (UDF) se jménem RoundX. Tato jediná funkce pokrývá všech osm vyjmenovaných funkcí a ještě navíc varianty, které Excelu jaksi už nestálo zato pokrýt. Je napsaná ve VBA a používá výhradně to, co VBA samo umí.
Funkce RoundX je obsahem přílohy včetně testů její funkčnosti. Přes veškerou snahu o odladění nevylučuji, že může mít mouchy (já o nich nevím). Tu funkci dávám do oběhu spíš jako ukázku toho, že to jde takto napsat. Prosím každého, kdo by funkci RoundX chtěl prakticky využít, aby si její fungování sám napřed prověřil. Pokud najde vady, prosím o jejich sdělení (nejlépe na můj mail, aby se toto fórum odlehčilo).
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.