Office Guru

Tóba hulló vízcsepp - ismét Powerpointban rajzolgatunk

2016. január 06. - Office Guru

Exceles fejtörők után most ismét a másik kedvenc témám kerül terítékre, azaz Powerpointban fogunk kicsit rajzolgatni, ami bár elsőre valószínűleg ostobaságnak tűnhet, de csak azok számára, akiknek nem volt még égető szükségük egy igazán figyelemfelkeltő, vizuális prezentáció elkészítésére igen rövid időtávon belül. Úgyhogy rá is térnék a mai "rajzunkra", ami elég egyszerű és nem túlságosan kreatív kis forma lesz, mégis hasznos lehet egy-egy diánk feldobására, ráadásul roppant gyorsan elkészíthető: tóba hulló vízcsepp avagy egy pillangó szárnyának apró csapása akár vihart is előidézhet sok ezer kilométerrel távolabb.

Első lépésként a Ribbonunk Home füle alatt található Drawing szekcióból szúrjunk be egy kört a diánkra, majd a szintén eme szekcióban található Shape Fill funkció segítségével távolítsuk el a kitöltést:

660.jpg

661.jpgMég mindig a Drawing funkciócsoportban maradunk és a Shape Outline funkció használatával vastagítsuk meg most már kitöltetlen körünk körvonalait:

662.jpgEzután következő lépésként CTRL+C és CTRL+V használatával másoljuk le körünket, majd az új másolatot kijelölve, jobb gombbal való kattintás után lépjünk a Format Shape menücsoportba, ahol a Size paramétercsoportban előbb állítsuk be a Lock aspect ratio pipát (így megtartjuk körünk arányait az eredetihez képest), majd értelemszerűen a Height értéket növeljük meg egy kicsit:

663.jpgEzután ezt az új kört húzzuk rá az eredetire, majd most már a másolatot másoljuk le megint és azzal játsszuk el ugyanígy az előbb említett méretnövelést:

664.jpgCsináljuk ezt egy darabig, amíg a megfelelő számú hullámunk nem lesz meg körökből:

665.jpgAz összes kört kijelölve és jobb gombbal kattintva csoportosítsuk össze őket a Group funkció használatával:

666.jpgEzután az így létrejött egyesített formára kattintsunk jobb gombbal és a Format Shapes menücsoportban a 3-D Rotation funkciócsoport alatt állítsunk be egy Off Axis döntést:

667.jpg

668.jpgMi következik most? A csepp, ami aláhullik tavunkba, ezt pedig a Drawing szekcióból egy Teardrop forma beszúrásával tudjuk létrehozni:

669.jpgAlapesetben ez a forma meg van döntve 45 fokban, úgyhogy a Format Shape menücsoportban a Rotation paraméter -45 fokra állításával szépen egyenesbe tudjuk hozni:

670.jpgAztán színezgessük, formázgassuk, építsünk köré kék hátteret, amit szeretnénk:

671.jpg

Formulák helyett ismerkedjünk a PIVOT-táblák összes beépített lehetőségével

Az egyik kedves Olvasó kérdése ihlette a mai posztot, amelynek publikálását azért gondoltam szükségesnek, mert egy rendkívül jó beépített Excel-funkcióról van szó, de néha még én is inkább formulákban gondolkodom egy-egy olyan probléma kapcsán, amely ezzel pillanatok alatt kivégezhető lenne.

Adott tehát a következő kis táblázat, roppant egyszerű felépítéssel, ami adott napokra tartalmazza mondjuk a kiadásaink, bevételeink, látogatóink stb. számát:

650.jpgEzt szeretnénk összesíteni mondjuk akár heti, kétheti vagy negyedéves periódusokra (szándékosan nem írtam havit és évest, mert azok azért egyszerűbbek még formulákkal is). Ne gondolkodjunk azonnal formulákban, az Excel PIVOT-tábláinak van egy csodálatos kis beépített funkciója, amit most mindjárt meg is mutatok.

Első lépésként tehát a táblánkból varázsoljunk egy PIVOT-táblát, amelynek sorai (ROWS) legyenek a napok dátumai, az értékek pedig egyértelműen az összegek (VALUES):

651.jpgEzután kattintsunk az első sorunkra (az első Row Labelre), ami jelen esetben 1/1/2015 és kattintsunk a jobb egérgombbal, majd válasszuk ki a Group funkciót:

652.jpgA felugró kis ablak pedig szerintem már magától értetődően kínálja fel a lehetőségeket, amelyekre szükségünk van.

653.jpgHa havi vagy éves szinten összesítenénk, akkor azt a funkció defaultban kínálja nekünk (negyedévenként szintén), de ha bizonyos meghatározott napszám szerint összesítenénk, akkor kattintsunk csak a Grouping By Days opcióra és a Number of days mezőbe írjuk be a napok számát, amely szerint összesítenénk, tehát kéthetinél 14-et, hetinél hetet.

655.jpgHa megvan, kattintsunk okét és már rendben is vagyunk, formulák és trükközés nélkül ott van, amit akartunk:

656.jpg

Újévi munkalapos megjelenítő illetve elrejtő makró

Remélhetőleg mindenkinek jól telt 2015 utolsó és 2016 első napja eddig, itt most afféle bemelegítő jelleggel egy aprócska makróval indítjuk az új évet, amely nem fog mást csinálni, mint egy Excel-fájlban, ahol minden hónapunk külön sheeten szerepel, mindig csak azt a sheetet jeleníti meg megnyitáskor, amelyik hónapban éppen vagyunk. Tényleg elég egyszerű kis kód, de erre a napra talán elég is lesz ennyi.

Szóval adott a következő Excel-fájl és benne 12 sheet:

640.jpgAnnyit szeretnénk csak, hogy mostantól minden egyes megnyitáskor csak az adott hónap sheetje legyen látható, a többi legyen rejtett. Úgyhogy most menjünk a VBA-editorba és Workbookunk Open (megnyitási) eseményéhez rendeljünk hozzá egy kódot, amit el is kezdünk szépen feltölteni, szokás szerint első lépésként a változók, konstans értékek létrehozásával. Most amire szükségünk lesz, az az, hogy betöltsük sheetjeink számát egy változóba:

AllSheets = Worksheets.Count

Illetve az kell még, hogy egy változóba betöltsük a mai dátumot a sheetjeink megnevezése szerinti formátumban, tehát jelen esetben a hárombetűs hónap megnevezéssel:

currentperiod = Format(Date, "mmm")

Jegyezzük meg, hogy VBA-ban Date utasítással kapjuk vissza a mai dátumot (csak dátumot, időhöz Time, időhöz és dátumohoz Now parancs kell), Format utasítással pedig arra a formátumra tudjuk formázni, amilyenre akarjuk. Ez utóbbi egyébként egy rendkívül hasznos és sokat tudó kis utasítás, vannak már előre elnevezett formátumok (például a Long Date) és mi is definiálhatjuk a saját verziónkat, ráadásul nagyjából bármire használható.

641.jpgHa ez megvan, akkor nagyjából már csak egy For...Next ciklusra van szükségünk, amely egy IF vizsgálatot fog végrehajtani annyiszor, ahány sheetünk van. A megszokott módon, tehát az első sheettől kezdve az AllSheets változónkban meghatározott darabszámig nézzük meg, hogy a Sheetünk neve megegyezik-e a fentebb már deklarált currentperiod változóval és ha nem, akkor rejtse el az adott munkalapot.

Amit ehhez tudnunk kell, az az, hogy egy sheet nevét a Sheets.Name paranccsal tudjuk megkapni (és persze még több más módon is) valamint a Sheets.Visible paraméter állítgatásával (mondjuk True vagy False most elég nekünk) tudjuk elrejteni vagy megjeleníteni az adott munkalapot.

Így már azt is tudjuk, hogy ez pontosan mit fog csinálni:

For i = 1 To AllSheets
With Sheets(i)
.Visible = False
If .Name = currentperiod Then .Visible = True
End With
Next i

Első lépésként alapvetően az összes sheetet elrejtjük és csak ott jelenítjük meg, ahol a sheet neve teljesíteni az IF-ben megszabott feltételt.

642.jpgÉs ezzel már kész is vagyunk, úgy működik, mint a szél, ráadásul nem is terheltük meg az agyunkat így az év első napján.

643.jpg

Ünnepi időszakra érdekes fejtörő - lehet szórakozni Excellel is

Itt az év vége, valószínűleg mindenki már csak egy kis feltöltődésre, kikapcsolódásra vágyik, úgyhogy ennek megfelelően most nem makrókról, Powerpointos rajzolgatásról, WORD-formátumokról lesz szó, hanem egy kis Excel-fejtörővel dolgoztatjuk meg agytekervényeinket.

A kérdés alapvetően roppant egyszerű: mondjuk meg egy cellában szereplő szövegről, hogy az ott szereplő szavak kezdőbetűi azonosak-e vagy sem, valahogy így:

630.jpgAz összes ilyen problémánál a megoldás kulcsa az ötlet, amellyel elérhetjük a célunkat, a megvalósítás már önmagában nem nagy dolog, gondoljunk csak vissza mondjuk az egy cellába beszúrható több link kérdésköréről. Az ötlet itt egy SUBSTITUTE függvény és egy IF egymásba ágyazása lenne a következő metódus szerint.

Annak érdekében, hogy a nagy és kisbetűk ne számítsanak, első lépésként UPPER függvény segítségével A oszlopban szereplő szövegünk minden betűjét nagybetűvé varázsoljuk:

=UPPER(A1)

Ezután jön a képbe a SUBSTITUTE függvény, amely az első paramétereként megadott szövegben, a második paramétereként megadott szövegrészt a harmadik paramétereként megadott szövegrészre cseréli le. A mi esetünkben megfogjuk a nagybetűs A1 cellánkat, majd a szóközök A1 szövegünk első karakterével összefűzött tartalmát lecseréljük szimplán semmire (""). A szóközöket A1 szövegünk első karakterével a következő módon fűzhetjük össze:

=" "&LEFT(UPPER(A1),1)

Használhatunk CONCATENATE függvényt is értelemszerűen, a LEFT függvényről pedig tudjuk, hogy az első paramétereként megadott szöveg bal oldalából vág le annyi karaktert, amennyit második paraméterként megadunk.

Szóval ezt kell most szépen lecserélnünk az UPPER(A1) szövegben semmire:

=SUBSTITUTE(UPPER(A1)," "&LEFT(UPPER(A1),1),"")

Itt tartunk most:

631.jpgCsak a megértés szempontjából a megoldás következő részét egy újabb oszlopban fogom felvázolni a kis táblázatunkban, amely rész nem más lesz, mint a fenti SUBSTITUTE megismétlése, azzal a különbséggel, hogy most nem fűzzük össze a szóközöket az első karakterekkel, szimplán lecseréljük őket semmire (""):

=SUBSTITUTE(UPPER(A1)," ","")

632.jpgKövetkező lépésként egy LEN függvényt kell beiktatnunk az eddigi megoldás-részeinkbe, ami ugyebár nem csinál mást, mint a paramétereként megadott szöveg karakterszámát adja vissza (ez mondjuk trailing space levadászására is jó lehet).

Mindkét fentebb említett SUBSTITUTE függvénystruktúránk hosszúságát határozzuk meg, majd vonjuk ki őket az eredeti szövegünk hosszúságából - ergó amit így megkapunk, az egyrészt az eltávolított szóközeink és kezdőbetűink száma másrészt szimplán a szóközeink száma:

=LEN(UPPER(A1))-LEN(SUBSTITUTE(UPPER(A1)," "&LEFT(UPPER(A1),1),""))
=LEN(UPPER(A1))-LEN(SUBSTITUTE(UPPER(A1)," ",""))

Szóval most már van két számunk:

633.jpgMihez kezdjünk ezzel? A kulcs abban rejlik, hogy az első karaktereket is eltávolító megoldás-részünket még el kell osztanunk kettővel is, hiszen azzal meg tudjuk határozni, hogy pontosan hány kezdőbetűt vettünk ki amiatt, hogy megegyezik az első szó kezdőbetűjével:

=(LEN(UPPER(A1))-LEN(SUBSTITUTE(UPPER(A1)," "&LEFT(UPPER(A1),1),"")))/2

634.jpgUgyebár ha az összes kezdőbetű azonos, akkor pontosan azt a számot kapjuk meg, ahány szóközünk van a szövegben - következésképpen már csak meg kell vizsgálnunk, hogy az első és a második megoldás-részünk megegyezik-e, mert ha igen, az azt jelenti, hogy minden kezdőbetűnk azonos a szövegben. Ezt a vizsgálatot pedig egy szimpla IF függvénnyel tudjuk elvégezni így:

=IF((LEN(UPPER(A1))-LEN(SUBSTITUTE(UPPER(A1)," "&LEFT(UPPER(A1),1),"")))/2=LEN(UPPER(A1))-LEN(SUBSTITUTE(UPPER(A1)," ","")),"Az összes kezdőbetű azonos","Nem azonos a kezdőbetű")

635.jpg

Diagramok formázgatása megadott feltételek szerint VBA-kóddal

Projektes státuszjelentésekben, bevételről szóló beszámolókban időnként hasznos lehet, ha bizonyos státuszú, bizonyos telephelyhez köthető elemeinket kiemelten tudjuk prezentálni diagramos formában, ehhez fog segítséget nyújtani a következőkben bemutatásra kerülő kis makró, ami nem tesz mást, mint az általunk megadott paraméterek alapján egy diagramban bizonyos oszlopok, sorok színét fogja megváltoztatni.

Legyen a kiindulópontunk a következő apró kis táblázat:

620.jpgMost készítsünk ebből egy teljesen egyszerű oszlopdiagramot (persze lehet akár háromdimenziós oszlop vagy "bar" is) mondjuk a lentieknek megfelelően:

621.jpgEnnek az elkészítéséről már nem fogok részletesen írni, korábbi posztokban részletesen taglaltam a diagramok elkészítésének menetét, ha valakinek segítségre lenne szüksége, jelezze nekem valamilyen kommunikációs csatornán. Az igényesebb megvalósítás érdekében (persze azért az igazi igényességtől ez messze lesz) szúrjunk be még a Ribbonunk Developer füle alatt található Controls szekció Insert parancsával egy gombot is, ami kattintással fogja elindítani a kis színezésünket.

622.jpgEhhez fogjuk aztán majd hozzárendelni azt a makrót, ami az x tengelyünk elnevezései közül mondjuk Gyömrő esetében átszínezi az oszlopot, mert például erre a városra szeretnénk nagyon koncentrálni bemutatónkban (de hangsúlyozom, lehet akár érték, akár más paraméter alapján is átdolgozni a makrót).

Kattintsunk jobb gombbal a gombon és View Code parancsot használjuk:

623.jpgÉs máris a VBA-editorban vagyunk, ahol szépen a kattintás eseményünkhöz kidolgozhatjuk a kódot, amit szeretnénk kattintás esetén lefuttatni. Ahogy megszoktuk, első lépésként kezdjük változók deklarálásával, méghozzá kapásból néggyel.

Kell egy változó Chart típussal magának a táblázatunknak, kell egy változó Series típussal a táblázatunk összes adatmező sorozatának tárolására (itt gondoljunk például mondjuk az X vagy Y tengely megnevezéseire, sor illetve oszlopértékeire) illetve még két változó Integer típussal, amelyekre majd a ciklusunkban lesz szükség - hiszen itt is csak ciklussal tudjuk végignézni az összes megnevezésünket a diagramban:

624.jpgMost lássunk hozzá és kezdjük feltölteni a változóinkat, azaz állítsunk be kezdőértéket, legalább a táblázatoshoz illetve az adatmezőshöz. Amikor egy Chart aktív objektum, akkor az ActiveChart tulajdonsággal tudunk rá hivatkozni, így az első esetben c változónk kezdőértéke legyen az ActiveChart, tehát a diagramunk - itt álljunk meg arra a gondolatra, hogy ha nincs éppen kijelölve a diagramunk vagy más diagramok is vannak más sheeteken a táblázatunkban, akkor mindenképpen aktiválni kell a megfelelőt az Activate utasítással. Itt most annyiban leegyszerűsítettem a kódot, hogy ettől eltekintek.

S változónkat pedig ActiveChart objektumunk SeriesCollection(1) tulajdonságával kell feltöltenünk, ami az aktív objektumunk első sheetjén szereplő diagramunk első adatsorának (series - a tengelyeinket szereplő nevek) értékeit fogja visszaadni, jelen esetben városaink nevét töltjük be ide.

625.jpgA ciklusban felhasználásra kerülő l változónkba pedig töltsük be az aktív diagramunk első adatsorának adatmező darabszámát, avagy VBA-ra átfordítva az:

ActiveChart.SeriesCollection(1).Points.Count

utasítást, ami ebben a kódban már meghivatkozható a korábbi változók felhasználásával.

626.jpgSok már nincs hátra, ahogy kitalálhattuk, következik a ciklusunk maga, azaz a másik változónkba töltött egyes kezdőértéktől egészen az l változónkba az előbb már betöltött adatmező darabszámig futtasson egy IF utasítást, méghozzá a következőkben kifejtettet.

Előbb azonban két dolgot kell megértenünk, az egyik az ActiveChart.SeriesCollection(1).XValues tulajdonság, ami konkrétan az aktív táblázatunk első adatsorozatából adja vissza az x tengely értékét a megadott helyre vonatkozóan, a másik pedig a Right funkció, ami teljesen ugyanúgy működik VBA-ban, mint az Excelben, azaz a paramétereként megadott darabszámnyi karaktert fog nekünk visszadobni a megadott szöveg jobb oldaláról.

Így pedig össze is állt nagyjából If utasításunk első sora:

If Right(s.XValues(i), 40) = "Gyömrő" Then

Ha az ActiveChart.SeriesCollection(1) x tengelyének i helyén szereplő érték utolsó negyven karaktere az mondjuk, hogy Gyömrő akkor ugrik a második sorra, ahol az

s.Points(i).Interior.Color = RGB(255, 0, 0)

utasítással fogjuk szépen az ActiveChart.SeriesCollection(1) i-edik pontjának színét átállítani RGB(255, 0, 0) színre, ami a piros.

Fekete: RGB(0, 0, 0)
Fehér: RGB(255, 255, 255)
Zöld: RGB(0, 255, 0)
Kék: RGB(0, 0, 255)

És ha ezzel megvagyunk, akkor csak le kell zárnunk az IF-et és a FOR ciklust:

627.jpg

Most futtassuk le a makrót. Oppá, hibaüzenetet kaptunk:

629.jpgEzt a részt könnyedén kivehettem volna a posztból, de úgy gondoltam talán hasznos lehet egy kis közös problémamegoldás is, szóval mit jelenthet az üzenet? Az üzenet szerint egyértelműen valamelyik változónkkal lehet a probléma. Na de melyikkel? Ahogy végigfutjuk ezt a tényleg roppant aprócska kis kódot, egyből szemünkbe ötlik a fent már emlegetett megoldás, azaz c változónk kezdőértékének ActiveChartra való beállítása. Hiszen ha a gombra kattintunk, akkor nem lehet kijelölve a diagramunk!

Azaz egyetlen egy plusz sorra van szükségünk a kód elején még (mindenképpen a Set c = ActiveChart elé), ami nem tesz mást, mint a gomb lenyomása után kijelöli a táblánkat, valahogy így:

ActiveSheet.ChartObjects("Chart 4").Activate

Azaz aktív sheetünk Chart 4 névre hallgató diagramjának (ezt a nevet diagramunk tulajdonságai közül tudjuk kinyerni) aktiválása.

És most már szépen lefut:

628.jpg

Két egyszerű kérdés - és ismét bevetésre kerül a titkos fegyver, a SUMPRODUCT

A hosszabb szünet utáni visszatérésemre két egyszerűbb kérdés megválaszolását terveztem, remélhetőleg mindkettő segítség lesz azok számára, akik hasonlóval szembesültek, de nem volt kéznél megoldás vagy ötlet. Ezek közül az első egy elég egyszerű kérdés, mondjuk projektes dashboardokban vagy tervekben merülhet fel, hogyan lehet egy cellában megadott szöveges érték alapján színezni például a cella hátterét vagy a szövegünket magát. Ami itt beugrik valószínűleg mindenkinek, az a Conditional Formatting, na de a kérdés, hogyan csináljuk meg?

Adott a lenti aprócska kis táblánk, benne egy projekt néhány részfeladatával és a hozzá tartozó státusz értékekkel, amelyet egy Validation List tartalmaz:

610.jpgAzt szeretném elérni, hogy a Teljesült státusznál a háttér zöld legyen, a Folyamatban státusznál narancssárga, míg a Még nem kezdődött el státusznál legyen piros. A Ribbonunk Home füle alatt lévő Styles szekcióból tehát hívjuk meg a Conditional Formattingot és hozzunk létre egy új szabályt (New Rule):

611.jpgItt az utolsó lehetőséget, a Formula alapján történő formázási szabályt válasszuk:

612.jpgA Formula sorába írjuk be a következőt:

=$F5="Teljesült"

Majd kicsivel lentebb a Format gombra kattintsunk és az itt felugró formázási szabály közül a Fill fül alatt határozzunk meg egy színt, Teljesült státusz esetén tehát a zöldet:

613.jpgMajd okézzuk el. Ha most megnézzük a táblánkat, láthatjuk, hogy ha a listából kiválasztjuk a Teljesült státuszt, akkor a háttér értelemszerűen zöldre vált:

614.jpgA további teendőnk ismét az F5-ös cellán állva két új szabály létrehozása Conditional Formattingon belül az előbbieknek megfelelően, a narancssárga illetve a piros szín szabályaira. Ha az elkészült, akkor már csak másolnunk kell ezt a cellát a Státusz oszlopunkon belül és meg is van a végeredményünk:

615.jpgMondjuk, hogy ez inkább bemelegítő gyakorlat volt, hiszen valószínűleg sokak számára nem írtam újdonságot, úgyhogy folytassuk is a másik kérdéssel, amire választ keresünk és találunk.

Maradjunk a fentebb készített kis táblánknál, de módosítsuk annyiban a feladványt, hogy hozzunk létre egy Overall mezőt, ahol projektünk összesített státuszát vizsgáljuk:

616.jpgA feladatunk annyi lenne, hogy a Projekt állapota sorban jelenítsük meg a Folyamatban szót, ha bármelyik értékünk a feladatlistában még mindig nincs Teljesült státuszban, ha pedig minden Teljesült státuszban van, akkor legyen az összesített állapot is Teljesült. Mindenképpen szeretnénk, hogy üres cellák esetén is helyesen működjön és ne zavarja meg az adott cellák formátuma sem. Ezekkel a feltételekkel az IF használata már kicsit nehézkesebb lesz, ezért váltsunk át az én titkos kedvencemre is, a SUMPRODUCT függvényre, amelyről tudjuk az általános definíciót, azaz hogy két vagy több tömb elemeit szorozza majd adja össze, tehát a két tömb egymással egy sorban lévő elemeit összeszorozza majd az eredményeket szummázza. De bővebben róla példákkal itt:

SUMPRODUCT - A szuperfegyver

Szóval hogy folytassuk? Két dologra lesz szükségünk, elsőként egy SUMPRODUCT-ra, valahogy így:

=SUMPRODUCT(--(F5:F7="Folyamatban"))

Mit tesz ez? Fogjuk az F5:F7 tartományt, mint tömb meghivatkozzuk, majd az egyenlővé tétellel arra utasítjuk a függvényt, hogy a "Folyamatban" értéket tartalmazó cellákat keresse meg. A kötőjel (illetve a dupla kötőjel) Boolean (IGAZ,HAMIS - TRUE, FALSE) értékeket alakít egyesekké és nullákká, tehát ha talál a függvény a tartományunkban "Folyamatban" értéket, akkor kapunk egy egyest, ha nem, akkor egy nullát.

Innentől kezdve pedig már szabad az út, hiszen nem kell nagyon mást tennünk, mint két IF-et és két SUMPRODUCT-ot egymásba ágyazni:

=IF(SUMPRODUCT(--(F5:F7="Folyamatban")),"Folyamatban",IF(SUMPRODUCT(--(F5:F7="Még nem kezdődött el")),"Folyamatban","Teljesült"))

Lefordítva tehát ha az F5:F7 tartományban van Folyamatban érték, akkor kiírja, hogy projektünk még folyamatban van, ha nincs, akkor megnézi, hogy van-e "Még nem kezdődött el" érték, mert ha van, akkor még mindig folyamatban van a munkánk, ellenkező esetben viszont "Teljesült" a státusz.

617.jpg

Tanuljunk formákat szerkeszteni Powerpointban: ezúttal a lépcső van terítéken

Ha már itt a hétvége, akkor én is könnyebb témák felé evezek és ismét szerkesztgetek egy kicsit Powerpointban, ezúttal egy olyan lépcsős forma lesz terítéken, amelyet felhasználhatunk projektünk állapotának bemutatására, elmúlt éves teljesítményünk értékelésére - hangsúlyozni kell persze itt a poszt elején, hogy ez kizárólag csak egy ötlet, egy kiinduló lépés, könnyedén formálható, alakítgatható saját szánk íze szerint, hiszen ahogy látni fogjuk a végén, ez még nem az, amit tökéletesnek hívhatunk.

Első lépésként a Ribbonunk Insert füle alatt található Illustrations szekcióból szúrjunk a Shapes menü alól mondjuk három lekerekített szélű téglalapot, majd helyezzük szépen egymás alá őket:

590.jpg

591.jpgEzután a formákra kattintva megjelenő Drawing Tools Format füle alatt a Shape Styles csoport menüi segítségével, előbb színezzük őket különböző színekre (Shape Fill), majd a Shape Outline menüvel távolítsuk el a körvonalakat is:

592.jpgA megszokott módon csoportosítsuk össze a három formánkat, mondjuk CTRL lenyomása mellett kattintva kijelöljük egyszerre mind a hármat, majd jobb gombbal kattintva a Group menü segítségével egyesítsük őket egy formává a könnyebb kezelés érdekében:

593.jpgA most már egy formának számító ábránkra ismét jobb gombbal kattintva menjünk be a Format Shape menübe, hiszen itt fogunk konkrétan lépcsőket varázsolni a téglalapjainkból:

594.jpgA jobb oldalt megjelenő menüstruktúrában a középső kis ikonra kattintva jutunk a formánkra vonatkozó Shape hatásokhoz, ahol elsőként a 3-D Rotationre van szükségünk és az előre beállított döntések közül válasszuk ki a tőlünk hátrafelé megdőlő (Relaxed) perspektívanézetet:

595.jpgEzután értelemszerűen ugyanitt, a Perspective beállítási lehetőség alatt a szög növelésével-csökkentésével még állítgathatjuk, ahogy akarjuk a döntést:

596.jpgEzután szintén itt, a formánkra vonatkozó Shape hatások beállításainál menjünk át a a 3-D Format alá, ahol tegyünk egy kis kiemelkedést még a formánkra a Top Bevel beállításával, mondjuk Cross típussal:

597.jpgAztán a mélységet (Depth) is állítsuk legalább harminc pontos nagyságra (ne felejtsük el, hogy most a három formánkból létrejött egységről van szó):

598.jpgMost valahol itt járunk:

599.jpgEzután jön az utolsó lépés, ami konkrétan a lépcső kialakítása lesz, ezt a 3-D Rotation alatt tudjuk beállítani, méghozzá a Distance from ground menü segítségével. Ki kell jelölnünk az egységes formánkon belül a második alkotóelemet (ki tudjuk, nincs ok az aggodalomra), majd itt állítsuk a Distance from ground értéket 25 pontra, majd a harmadiknál 50 pontra:

600.jpgÉs meg is vagyunk, innen kezdve pedig már színezgethetünk, árnyékolgathatunk, nyilakat rajzolgathatunk, szövegeket helyezhetünk el és értelemszerűen bővíthetjük is:

601.jpg

Szín szerinti összegzés néhány soros VBA-kóddal

Nem kérdés, hogy áttekinthetőség, azonnali vizuális megjelenítés szempontjából igencsak hasznos celláink hátterének színét megváltoztatni, ráadásul így könnyen szűrhetünk is azokra a pontokra, számokra, amelyekkel úgy gondoljuk, hogy foglalkoznunk kell vagy amelyekre különösen büszkék vagyunk.

Na de műveletet már nem ilyen könnyű végezni a különféle színekben pompázó celláinkkal, sőt megkockáztatom azt is (de kérlek, cáfoljatok meg hozzászólásokban), hogy segédcellák, segédoszlopok nélkül közvetlenül, makró nélkül nem igazán fog menni mondjuk a piros háttérrel bíró celláink értékének összeadása egy bizonyos táblázatban. Úgyhogy most egy olyan kis makrót fogunk készíteni, amelyik mondjuk összeadja egyetlen lépésben a bizonyos színű celláink értékeit.

Adott tehát a következő kis feladvány, a feladatunk az lenne, hogy egyetlen lépésben, segédcellák nélkül határozzuk meg az adott város szumma árbevételét:

580.jpgElső lépésként szépen lépjünk be a VBA editorba, majd jobb gombbal való kattintás után a bal oldali projekt ablakban, szúrjunk be egy modult, itt fogjuk majd szépen deklarálni a funkciónkat, hiszen ezúttal egy funkcióra lesz majd szükségünk, amit meghívhatunk az Excelben. Szóval ha létrehoztuk a modulunkat, hozzuk létre a funkciót neve illetve mögötte zárójelben paraméterei megadásával:

581.jpg
Az első paraméterünk a formulában majd a például szolgáló cella színe lesz, az azután következő paraméter pedig az a tartomány, ahol szín szerint akarunk majd összegezni.

Ezután két változóra lesz szükségünk, mindkettő Integer típussal, az egyikbe majd a például szolgáló cellánk színének colorindexét töltjük be, a másikba pedig majd konkrétan az összegzésünk eredményét fogjuk "kumulálni".

582.jpgKövetkező lépésként a CellColorValue nevű változónkat állítsuk be úgy, hogy majd a funkciónk első paramétereként megadott szín colorindexét vegye fel:

583.jpgAhogy erről már volt szó, ezt a .Interior.ColorIndex utasítással tudjuk megtenni.

Most következik az egész aprócska makró legfontosabb része, mégpedig a For Each In ... Next ciklus, amelyben szépen végigmegyünk a megadott tartományon és az első paraméterként megadott színnel bíró cellák értékét összegzi. Egyszerűen gondoljuk csak át, hogy pontosan mit akarunk, majd kezdjük el leírni VBA-parancsokkal a gondolatainkat. Azaz minden egyes cella esetében a tartományunkban, ha az adott cella colorindexe megegyezik a színparaméterünket tartalmazó változóval akkor a másik változónkba kezdjük el bevinni az értékeket az összegzés céljából. Majd ezt ismételjük meg annyiszor, ahány cellánk van a tartományban. Ez így néz tehát VBA-nyelvre fordítva:

For Each Cell In Tartomanyom
If Cell.Interior.ColorIndex = CellColorValue Then
Sumvalue = WorksheetFunction.Sum(Cell, Sumvalue)
End If
Next Cell

584.jpgSzerintem az egyetlen ismeretlen rész ebben a ciklusban a WorksheetFunction.Sum nevű utasítás, amely egy olyan utasítás, ami a zárójelben mögötte megadott számokat, argumentumokat, tehát tartományt fog összegezni.

A mostani esetünkben tehát a WorksheetFunction.Sum(Cell, Sumvalue) azt teszi, hogy az adott színnel bíró cellánk értékét és a Sumvalue változó korábbi értékét összeadja, kumulálja, egészen tartományunk végéig.

Innen már csak egyetlen lépés van hátra, méghozzá az, hogy funkciónkat tegyük egyenlővé a Sumvalue változó végső, ciklus lezárása utáni értékével, hiszen ez lesz majd az eredmény, amit a cellánkba várunk. És persze hát zárjuk le a funkciót:

585.jpgFüggvényünk most már használható, úgyhogy szépen menjünk vissza Excelbe, ahol például Miskolc esetében

=ColorSum(J3,G3:G12)

funkció felhasználásával megkapjuk az eredményünket.

586.jpg

Folytassuk VBA-tanulmányainkat: makróval készítsünk főoldalt munkalapjainhoz!

Az elmúlt napokban valami influenzaszerű kórság megakadályozott benne, hogy posztoljak, nagyjából örültem, hogy élek - de ez már a múlt, folytassuk tanulmányainkat, közös gondolkodásunkat egy kis Excellel, azon belül is makrózzunk, hiszen általában minden, magát tapasztaltnak tartó Excel-felhasználó ezt a szintet szeretné megugrani, ha még nem tette meg korábban.

Ezúttal sem egy komplex kóddal fogunk foglalkozni, hiszen ahhoz még jópár VBA-poszton szeretnék végigmenni, hogy az alapdolgok menjenek mindenkinek - viszont mindenképpen hasznos dologról lesz szó, hiszen aki olyan Excel-fájlban dolgozik, amelyben akár sok tucat worksheet található, egy Summary (Összegző) oldalra mindenkinek szüksége van. Kell, hogy szüksége legyen, hiszen egyébként könnyen átláthatatlan és kaotikus fájlokat adhatunk ki a kezünkből, ami nem biztos, hogy jó fényt vet ránk.

Szóval ma egy nagyon rövid kis kódot fogunk készíteni, ami nem tesz majd mást, mint az első sheetünkre létrehoz egy Summary oldalt szépen linkelve a többi sheetünkre, amelyeken pedig az A1 cellába egy, a summary oldalra visszamutató linket helyez majd el.

Azzal most már nem fogok foglalkozni, hogy tudunk kódot felvinni VBA-ban, hiszen erről már írtam többször, úgyhogy onnan veszem fel a történet fonalát, hogy a VBA editorban vagyunk és a Workbook objektumunkban elkezdjük írni a kis kódunkat. Ennek első lépéseként egyrészt defináljuk Subunk nevét, majd létre kell hoznunk két változót, egyet Worksheet típussal, hiszen ide töltjük majd be munkalapjainkat, egy másikat pedig egyszerű Integer típusként, ezt fogjuk majd a ciklusunkban használni a sheetek számának nyomonkövetésére. Ennek első kiindulóértékeként állítsunk be egy egyest.

560.jpgAhogy már volt róla szó, a With...End With parancs a közötte felsorolt utasításokat hajtja végre ugyanarra az objektumra vonatkozóan, tehát jelentős mennyiségű gépelést megspórol nekünk, és ezt most itt is be fogjuk vetni, méghozzá az Me objektum felhasználásával. Mi is az az Me?

Az Me mindig arra az ún. szülő objektumra hivatkozik, amelyikben a kódunk csücsül, tehát jelen esetünkben az egész első munkalapra, azaz Me nagyjából a Worksheets("Sheet1"). utasítással lesz egyenlő. Ezt azért célszerű használni, mert ezzel egyrészt átláthatóbb lesz a kódunk, másrészt nem kell törődnünk többé holmi névváltozásokkal a későbbiekben.

Tehát most fogjuk elkészíteni az első sheetünkön a linkeket a többi sheetre. Mondjuk pakoljuk a linkeket az első oszlopba, tehát ClearContents utasítással ürítsük ki az első oszlopot, majd az első cellába írjuk be, hogy "Summary of worksheets", aztán legyen a cellánk neve Summary, hogy később már így tudjunk hivatkozni rá. Ahogy látni fogjuk, szépen használjuk a With...End With parancsot:

561.jpgEzután jön az a lépés, amelyben egy For Each...In Next ciklus bevetésével az első munkalapunktól kezdve végigmegyünk az összes munkalapunkon és megnöveljük r változónk értékét eggyel. Erre azért van szükségünk, mert ebből a változóból fogjuk kiolvasni azt, hogy hányadik sheeten vagyunk, hiszen a Summary sheeten annyiadik sorba kell majd a linket is bevinni az adott munkalapra. Célszerű beletenni egy egyszerű IF utasítást is, hogy ezt csak akkor csinálja meg, ha nem a Summary sheetünkről van szó, mert azzal eléggé nem a kívánt eredményt érnénk el:

562.jpgMost van hátra még egy, esetleg két lépés, attól függően, hogy akarunk-e az aktuális sheetek első cellájába egy Summary sheetre mutató linket vagy sem. Mindenesetre mi most teszünk minden sheet A1-es cellájába egy visszafelé mutató linket, amelynek első lépéseként elnevezzük minden egyes sheetünk A1-es celláját egy konstans "Start_" szöveg és az adott worksheet index tulajdonsága segítségével, amely utóbbi az adott sheet helyzetét adja vissza sheetjeink halmazában.

Ezután pedig alkalmazzuk a Hyperlinks.Add metódust, amelynek fel kell töltenünk szépen a paramétereit:

Anchor - ez maga a a linkünk helye
Address - a linkünk címe
SubAddress - ide a belső hivatkozási címeket írjuk
ScreenTip - ha akarjuk, hogy az egér odahúzása esetén kiírjon valamit
TextToDisplay - ezt fogja megjeleníteni

Ergó a mi esetünkben:

With ws

.Range("A1").Name = "Start_" & ws.Index
.Hyperlinks.Add Anchor:=.Range("A1"), Address:="", _
SubAddress:="Summary", TextToDisplay:="Vissza a Summary sheetre!"

Elnevezzük szépen az A1-es cellánkat minden sheeten (kivéve értelemszerűen a Summaryt, hiszen még mindig a fent megnyitott IF-ben vagyunk), majd itt létrehozunk egy linket, amely a Summary sheetre fog majd mutatni és szövegként megjeleníti a "Vissza a summary sheetre!" mondatot. Address kötelező paraméter, de most nincs rá szükségünk, ezért üresen visszük fel.

563.jpgUtolsó lépésként pedig nagyjából ugyanezekkel az utasításokkal és paraméterekkel Me (azaz a Sheet1) megfelelő celláit is frissítjük a sheetek linkjeivel:

Me.Hyperlinks.Add Anchor:=Me.Cells(r, 1), Address:="", _
SubAddress:="Start_" & ws.Index, TextToDisplay:=ws.Name

Két dolgot vegyünk észre, egyrészt, hogy az r paramétert itt használjuk fel, hiszen így tudjuk megszámolni, hányadik sorba írja hányadik sheetet, másrészt, hogy a SubAddress paraméterünk az előző With ciklusban a sheetek A1-es cellájának adott név lesz majd.

Ezzel már csak az IF ciklusunkat kell bezárni és Next utasítással ugrunk a következő worksheetre.564.jpg

565.jpg

566.jpg

 

Ha valaki nem szeretne gépelni, akkor itt a másolható kód:

Sub Summary_generator()
Dim ws As Worksheet
Dim r As Integer
r = 1
With Me
.Columns(1).ClearContents
.Cells(1, 1) = "Summary of worksheets"
.Cells(1, 1).Name = "Summary"
End With

For Each ws In Worksheets

If ws.Name <> Me.Name Then

r = r + 1

With ws

.Range("A1").Name = "Start_" & ws.Index
.Hyperlinks.Add Anchor:=.Range("A1"), Address:="", _
SubAddress:="Summary", TextToDisplay:="Back to summary sheet!"

End With

Me.Hyperlinks.Add Anchor:=Me.Cells(r, 1), Address:="", _
SubAddress:="Start_" & ws.Index, TextToDisplay:=ws.Name

End If

Next ws

End Sub

 

Néhány Outlook-gondolat avagy a kikapcsolhatatlan funkció története

A mai Outlookos íráshoz a kezdő lökést az Outlook 2013 egyik roppant idegesítő beépített üzenete adta, hiszen bármennyire is érthetőek a beépítés okai, roppantul frusztráló, hogy Tárgy nélkül képtelenség üzenetet küldeni anélkül, hogy ne kapnánk meg a "Do you want to send this message without a subject?" felugró ablakát. A már az Outlook 2010-ben is benne lévő funkciót az azt a verziót megelőző években folyamatosan követelték felhasználók és publicisták, főként két okból: egyrészt azért, hogy így is küzdeni lehessen a spamek mindent elárasztó özöne ellen, másrészt főleg azért, mert sok felhasználó szívesen szűr a tárgyra (üres tárgymezőnél például gyakori a törlő szabály) és roppantul frusztrálták őket az üres tárggyal érkező üzenetek.

unnamed.pngPersze, érthető, hogy ha egy küldő 10-20 levelet küld nekünk naponta, akkor az ő üzenetei között pár hónap távlatából is megtalálni egy bizonyos ügy szövegét, szinte lehetetlen erőfeszítésnek tűnhet, de ez még mindig nem magyarázza, hogy miért nem lehet ezt a funkciót kikapcsolni - az ilyen típusú és formájú üzenetek felett egyébként is eljárt már az idő. Szóval egyszerű megoldás nincs, VBA-val megoldható az ügy, de talán akkora fáradtságot nem ér meg. Mindenesetre ha valakit érdekel a megoldás, akkor jelezze és ejtek róla szót, de ismétlem, ezzel még együtt lehet élni.

De ha már Outlookról írtam, néhány apró screenshotot és gondolatot bedobnék itt olyan lehetőségekről, amelyeket célszerű és érdekes használnunk.

Elsőként kezdjük egy túlságosan nem fontos, ám részemről régóta hiányolt lehetőséggel, azaz a modul kicsit személyesebbre szabásával, amelyet az Outlook Options alatt tehetünk meg, a General fülnél lévő Office Background és Theme menük állításával változtathatjuk az Outlook színét és különféle mintákat is elhelyezhetünk rajta:

00005.bmpSokáig fel sem tűnik a felhasználónak, de mostantól a leveleink főablakánál fent van egy apró kis gomb, amellyel a korábbi Filter opció helyett már kapásból tudunk az olvasatlan leveleinkre szűrni:

00001.bmpÉn mondjuk mindent elkövettem mindig, hogy az Inbox minimális mennyiségű, tényleg csak a fontos kérdéseket, nyitott ügyeket tartalmazó levelekből álljon, de azok számára, akik rendszereznek a bejövő postafiókon belül, ez jó lehetőség.

Többször, több felhasználónál láttam már tényleges használat közben azt a csúszkát a jobb sarokban, amelynek segítségével a leveleink betűméretét lehet pillanatok alatt felnagyítani:

00004.bmpNincs új a nap alatt, de azért gondoltam megemlítem, hiszen így roppant könnyedén láthatjuk betűinket bármilyen képernyőn és ez mondjuk egy sötét szobában vagy egy apró kivetítőnél hasznos lehet.

De ezek csak apróságok, mindenkinek ajánlott felderíteni a modulban rejlő lehetőségeket, hiszen bár a 2010-hez képest a 2013-as Outlook nagyon nem lépett előre, mégis vannak olyan újításai, amelyek nem voltak ismerősek korábban - a 2007-hez képest pedig óriási az ugrás. Gondoljunk például arra, hogy mennyivel egyszerűbb megosztani a Naptárunkat valaki mással, mennyire létfontosságú információként került be az időjárásról beszámoló dobozka vagy mondjuk mennyivel könnyebb lett egyetlen képen megnézni összes kontaktunk összes adatát. Az meg, hogy a 2007-hez képest a 2013-ban már Ribbonunk van, talán említést sem érdemel, annyira fontos változás. Hajrá, felfedezők!

süti beállítások módosítása
Mobil