Excel 2003 - Makro na určenie vzťahu medzi susednými bunkami (rozdiel hodnôt)
Mám tabuľku v Exceli 2003 a v nej je v jednom stĺpci určitá hodnota, ktorá postupne v každom riadku klesá. Niekedy by sa mi zišlo miesto zapísania tejto hodnoty napísať vo vedľajšom stĺpci, o koľko znížiť danú hodnotu, čiže:
B C
1 80
2 78 2
3 75 3
Ide mi o to, že buď zadám hodnotu v prvom alebo v druhom stĺpci a tá druhá sa vypočíta automaticky. Bez makra si zrejme neporadím. V živote som makrá nerobil. Základný jazyk BASIC z dôb Quick BASICu poznám. Potrebujem vedieť toto:
1. Ako otvoriť okno na zápis makra?
2. Ako zapísať makro?
Viem, že musím urobiť niečo takéto v makre:
B3=B2-C3 OR C3=B2-B3
A teraz mi prosím poraďte.
VBA Editor spustíš cez Tools / Macro / Visual Basic Editor (Alt+F11). Po dvojitom kliknutí na meno listu zošita Excel, v ktorom chceš mať makro, môžeš začať písať samotný program. Obslužné makro pre nejakú udalosť vytvoríš buď výberom z dvoch komboboxov, ktoré sú nad miestom pre kód makra (napr. v prvom vyberieš Worksheet, v druhom Change) alebo priamo zapíšeš (Private Sub Worksheet_Change(ByVal Target As Range)).
V argumente Target je rozsah buniek, v ktorých nastala zmena. Stačí skontrolovať, či sa medzi nimi nachádza niektorá z buniek, po zmene ktorej chceš prepočítať nejaké hodnoty, a potom už len výsledok zapísať do zošita. Treba myslieť aj na to, aby sa funkcia nevolala zbytočne (alebo donekonečna) pri zmene bunky samotným makrom.
Napríklad jednoduché makro, ktoré po zmene bunky doplní o riadok nižšie hodnotu zväčšenú o jednotku, by mohlo vyzerať takto:
1. Ako zistím z Target o ktorý stĺpec sa jedná (B, C)?
2. Ako zariadim, aby sa nevolala metóda rekurzívne po zmene bunky? Nejakým globálnym parametrom?
Ak sa to dá takto, ako si zadefinujem globálny parameter? Teda niečo ako iniciálizácia počiatočnou hodnotou?
Číslo riadka a stĺpca ľavej hornej bunky rozsahu Target zistíš pomocou Target.Row a Target.Column. Predpokladám, že po stlačení klávesy F1 sa dozvieš viac (aj klávesa F2 je zaujímavá). Asi budeš chcieť prebehnúť všetky bunky v rozsahu Target pomocou konštrukcie For Each.
Ukážka toho, ako zabrániť rekurzívnemu volaniu obsluhy udalosti, je v mojom predchádzajúcom príspevku - nastavením Application.EnableEvents. Tu musíš myslieť na to, aby si túto vlastnosť na konci nastavil na True, pretože inak by si domakroval. Preto je tam použité OnError, aby sa to spamätalo aj v prípade nejakej chyby.
Dá sa to robiť aj cez globálnu premennú, ale celý program je potom o trochu neprehľadnejší. Globálnu premennú si vytvoríš rovnako, ako vo všetkých iných programovacích jazykoch, ktoré globálne premenné podporujú - umiestniš deklaráciu premennej mimo definíciu funkcie/procedúry (Dim Zmena As Boolean).
Tu je výsledok, jedná sa o stĺpce O a P:
Edit: Zabudol som napísať, že to nefunguje. Niečo mi tam zrejme chýba.
Target.Row je číslo riadka. A nechceš vlastne Target.Column? To je pre zmenu číslo stĺpca.
BTW: Target je rozsah, takže to kľudne môže byť viacero buniek. Preto by som ten rozsah upravil pomocou metódy Resize na jednu bunku.
Opravil som to. Ja mám večný bordel v Row a Column. Kedysi to bol problém s Width a Height. Teraz je výsledný kód tento:
Pracuje to správne, len nerozumiem ako použiť Resize. Pozerám aj do helpu, ale nechápem tomu. Ide o to, že naraz zmením viac buniek, že? Dobre, ale ako s tým súvisí Resize? Ako zistí, ktorú bunku mi má vybrať?
Edit: Keď zmením viac buniek naraz (kopírovanie a tak, tak sa to vykonať nemusí, ale ako to zariadim? Medzitým som ešte pridal podmienku, že Row musí byť viac ako 3, inak sa to nevykoná.
Pri spracovaní zmeny nejakého rozsahu sa často zabúda na to, že sa môže meniť viacero buniek naraz, t.j. rozsah Target neobsahuje len jednu bunku. Riešení môže byť viacero. Môže sa napríklad spracovať každá bunka rozsahu pomocou cyklu For Each, čo však môže robiť problém pri zmene veľkého rozsahu buniek. Alebo sa môže spracovať len jedna bunka (ľavá horná) celého rozsahu, čo môže občas vadiť.
Keby si chcel spracovávať zmenu v každej bunke, môžeš to napísať nejako takto:
Ak by si chcel spracovávať len prvú bunku, tak by to mohlo vyzerať takto:
Zistiť, či bolo zmenených viacero buniek naraz, je jednoduché:
Tvoj program by som prepísal asi do takéhoto tvaru:
Veľmi pekne ďakujem. Veľmi si mi pomohol. Myslím, že na mnohé veci vôbec nebudem potrebovať Delphi, stačí sa pohrať s Excelom.
Zaujímalo by ma, či by niečo takéto fungovalo v OpenOffice?
Na co Makro ?
Stačí do C2 dát "=B1-B2", pak to C2 chytit za růžek a stáhnout dolů,
kam až potřebuješ. Vzorec se automaticky mění.
Vzorec nestačí, pretože tú hodnotu v stĺpci C nechce dostať vždy len výpočtom, ale niekedy tam chce dosadiť konkrétnu hodnotu, z ktorej sa spätne vypočíta hodnota v stĺpci B.
Aha.