Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Automatyzacja pracy z Wordem — wprowadzenie do pisania makr VBA

W dzisiejszym wpisie chciałbym Wam przybliżyć potężne narzędzie dołączone do pakietu MS Office jakim jest VBA (Visual Basic for Applications). Nie wiele osób słyszało o istnieniu VBA, a jeszcze mniej z niego korzysta. Możliwości VBA są ogromne, a w przypadku Excela, zamieniają go wręcz w platformę programistyczną. Takie stwierdzenie może wydawać się naciągane, ale wystarczy przejrzeć takie pozycje książkowe jak Excel. Programowanie dla profesjonalistów. aby się przekonać, że Excel w połączeniu z VBA staje się czymś więcej niż arkuszem kalkulacyjnym.

Co to jest VBA?

VBA jest językiem programowania opartym na Visual Basicu w wersji 6. Jest dołączony do poszczególnych programów pakietu MS Office wraz z prostym edytorem. Co ciekawe, występuje jednak nie tylko w MS Office. Można go spotkać również takich programach jak AutoCAD, Wordperfect czy Corel Draw, a także WPS Office Pro. W uproszczeniu można powiedzieć, że służy do pisania makr, a więc do zautomatyzowania pewnych czynności w pracy z programem. Jest idealny w sytuacjach, kiedy wielokrotnie wykonujemy serię tych samych czynności. Za pomocą VBA możemy zamienić te czynności w skrypt, który wykona je automatycznie za nas z naciśnięciem jednego przycisku.

VBA a makra

Być może niektórzy z Was słyszeli o czymś takim jak makra (makrodefinicje) w Wordzie i nawet kiedyś z nich skorzystali, ale nie słyszeli niczego o VBA. Programy MS Office (z wyjątkiem Outlooka) mają dołączony rejestrator makr, który zamienia wykonywane przez nas czynności w trakcie nagrywania makra na kod VBA. Zwykły użytkownik nie jest tego świadomy, bo nigdzie tego nie widać. Odtwarzane makro odbywa się na podstawie zapisanego skryptu VBA. Jest to idealne rozwiązanie dla mniej zaawansowanych użytkowników, którzy chcą zautomatyzować swoją pracę z Wordem. Niestety rejestrator makr ma pewne ograniczenia. Nie jest w stanie zarejestrować wszystkich czynności. Nie można też za jego pomocą wykonać wielu procesów automatyzacji wymagających wyższego poziomu abstrakcji. Możemy przykładowo nagrać makro, w którym zmieniamy kolor wierszy tabeli dla wierszy 1, 3, 5, 7, 9. I makro będzie wspaniale się spisywało, ale tylko w tabelkach z 9-cioma wierszami. Gdy dodamy więcej wierszy, nasze makro nie uwzględni nowo dodanych wierszy. W takich sytuacjach trzeba albo edytować automatycznie utworzone makro, albo po prostu napisać swoje od podstaw.

Czy to jest trudne?

Moja przygoda z programowaniem zaczęła się właśnie od VBA. Z pewnością VBA nie jest najlepszym językiem do nauki programowania, ale z drugiej strony jest on bardzo łatwy i intuicyjny. Proste makra można tworzyć nawet bez podstaw programowania. W bardziej złożonych skryptach konieczne jest poznanie koncepcji instrukcji warunkowych i pętli.
Moim zdaniem VBA jest na tyle proste, że osoby, które nie zamierzają się uczyć programowania, są w stanie opanować go na tyle dobrze, by stworzyć wiele ciekawych automatyzacji.

Od czego zacząć?

Do nauki VBA polecam starsze wersje pakietu Office. Dawno już nie miałem do czynienia z VBA i ostatnim razem, gdy robiłem coś w pracy, pracowałem na Office 2010. Pisząc ten wpis postanowiłem sprawdzić wersję 2013 i mam wrażenie, że rejestrator makr został zoptymalizowany. Wcześniejsze wersje charakteryzowały się sporą nadprodukcją kodu. Przykładowo rejestrując makro, w którym chciałem pogrubić czcionkę w zaznaczonym fragmencie tekstu, stara wersja rejestratora makr generowała kod, w którym ustawiała chyba wszystkie możliwe rzeczy związane z czcionką, mimo że zmieniane jest tylko pogrubienie. W efekcie otrzymywało się 20 linijek kodu zamiast 1. Optymalizacja może się więc wydawać dobrą rzeczą, jednakże z punktu widzenia poznawania VBA jest to utrudnienie. Rejestrator makr był bowiem idealnym narzędziem do poznawania modelu obiektowego VBA danego programu - w tym przypadku Worda. Dzięki tym 20 linijkom, po samej zmianie grubości czcionki, od razu wiedziałem także jak zmienić jej rozmiar, styl, samą czcionkę itd. Dostawałem gotowca.

Na początek proponuję więc nagrać proste makro. W tym celu musimy wejść w ustawienia programu Word i z lewej strony wybrać "Dostosowywanie wstążki". Tam musimy zaznaczyć checkoxa przy karcie "Deweloper". Dzięki temu pojawią nam się na wstążce narzędzia związane z VBA. Przechodzimy do karty deweloper i naciskamy "Zarejestruj makro". Wyskoczy nam okienko, w którym wpisujemy nazwę nowego makro. Inne opcje na razie nas nie interesują. Kursor myszy zmieni się - pojawi się ikonka kasety magnetofonowej, wskazującej że jesteśmy w trybie rejestracji makra. Od tej pory nasze czynności zostaną zapamiętane i zapisane jako kod VBA. Na początek proponuję zmienić czcionkę pojedynczego wyrazy, na którym akurat stoimy na pogrubioną. Aby zakończyć naciskamy "Zatrzymanie rejestrowania" w karcie Deweloper lub przycisk kwadracika na dolnym pasku.
Właśnie zarejestrowaliśmy nasze nowe makro. Jak je obejrzeć? Możemy z karty Deweloper wybrać "Visual Basic" lub nacisnąć skrót klawiszowy ALT+F11.

Z lewej strony mamy drzewo wskazujące gdzie są zapisane nasze makra. Zazwyczaj zapisujemy nasze makra w pliku normal.dotm (domyślnie tak są zapisywane makra). Jest to plik szablonu. Makra zapisane w tym pliku będą dostępne dla wszystkich dokumentów Worda. Istnieje też możliwość zapisania makra w konkretnym dokumencie.
Po prawej stronie mamy zapisane same makra. Poszczególne makra są oddzielone poziomymi liniami. Każde makro ma następującą postać:Sub NazwaMakra() instrukcje End Sub

Instrukcje są poleceniami, które ma wykonać Word. W naszym przypadku instrukcja ma postać:

Selection.Font.Bold = wdToggle

Omówię teraz pokrótce poszczególne elementy tej instrukcji. Selection reprezentuje w kodzie obszar zaznaczenia tekstu. Jeżeli nic nie jest zaznaczone (nie ma koloru tła wskazującego na zaznaczone litery) to zaznaczony jest pojedynczy znak, który stoi w tekście bezpośrednio za migającym kursorem.
Jeśli w edytorze VBA wpiszemy sobie Selection i postawimy kropkę to pojawi nam się rozwijana lista różnych poleceń. W uproszczeniu można powiedzieć, że zawiera ona różne rzeczy, jakie możemy zrobić z zaznaczeniem. Na tej liście znajduje się Font - czyli zbiór rzeczy jakie możemy zrobić z czcionką naszego zaznaczenia. Kolejna kropka, postawiona po Font, znów pokaże nam listę. Tym razem będzie to lista rzeczy jakie możemy zrobić z czcionką. Na tej liście mamy Bold, czyli pogrubienie. Tak więc całe wyrażenie po lewej stronie znaku równości oznacza ustawienia pogrubienia czcionki zaznaczonego fragmentu tekstu. A jakie mogą być te ustawienia? Najogólniej mówiąc pogrubienie może być albo włączone albo wyłączone, przy czym efekt ten możemy osiągnąć na dwa sposoby.
Znak równości przypisuje właściwości czcionki jaką jest Bold konkretną wartość (ustawienie). Samo wdToggle nie oznacza ani włączenia, ani wyłączenia pogrubienia. Jest on przełącznikiem. Taki zapis sprawia, że za każdym razem, gdy będziemy uruchamiać nasze makro, najpierw będzie sprawdzane, czy pogrubienie w zaznaczeniu jest włączone czy nie, a następnie będzie zmieniać jego stan na przeciwny. Działa więc to dokładnie tak samo, jakbyśmy przyciskali przycisk pogrubienia (B) w karcie narzędzi głównych. Możemy jednak zmienić nieco to działanie wpisując zamiast wdToggle wartość logiczną true lub false (prawda lub fałsz):

Selection.Font.Bold = True

Tak zapisane makro będzie zawsze ustawiać pogrubienie zaznaczonego tekstu bez względu na to czy wcześniej było ono pogrubione czy nie.

Testowanie kodu

Pisząc lub modyfikując bardziej złożone makra będziemy potrzebowali sprawdzać / testować zachowanie się naszego skryptu lub jego fragmentów. W tym celu warto poznać kilka podstawowych technik przydatnych przy takim testowaniu. Po pierwsze bardzo pomocne jest wykomentowanie fragmentu kodu - zaznaczenie kodu jako komentarz tak, aby interpreter języka pomijał te linijki i traktował jako komentarz (informację dla programisty). W tym celu należy na początku linijki napisać znaku pojedynczego cudzysłowu. Warto dostsować sobie pasek narzędziowy (prawy przycisk myszki w dowolnym miejscu paska i wybrać Customize..) poprzez dodanie z kategorii edit comment block i uncommnent block. Pozwalają one na automatyczne komentowanie i odkomentowanie wielu linijek jednocześnie.

Przykład zastosowania komentowania kodu

Jeśli mamy naszą pierwszą linijkę kodu:Selection.Font.Bold = wdTogglei chcemy przetestować działanie makra zamieniając wdToggle na True, możemy skopiować całą linijkę, wykomentować ją i pod spodem wkleić skopiowaną linijkę i w niej zmienić wdToggle na True:

'Selection.Font.Bold = wdToggle Selection.Font.Bold = True

Dzięki takiemu zabiegowi możemy szybko wrócić do pierwotnej wersji kodu, jeśli uznamy, że nowo testowany przez nas fragment nie działa tak, jakbyśmy oczekiwali. Podany przeze mnie przykład jest oczywiście banalny i łatwo zapamiętać i wrócić do wdToggle bez kopiowania i komentowania kodu, a jeśli będziemy mieli do przetestowania kilkadziesiąt linijek kodu, zawierających zagnieżdżone pętle z instrukcjami warunkowymi, to wtedy komentowanie kodu będzie niezbędne.

MessageBox

Testując kod, wielokrotnie napotykamy na sytuacje, w których chcemy sprawdzić jaka jest wartość danego wyrażenia. W przypadku pogrubienia możemy oczywiście zobaczyć w Wordzie gdzie stoi kursor i sprawdzić organoleptycznie czy zaznaczony fragment jest pogrubiony. Jednakże są sytuacje, w których określenie wartości nie jest takie proste i potrzebne jest wsparcie w samym kodzie. Jednym z nich jest MessageBox. Jest to okienko, które pojawia się w programie wyświetlając komunikat. Możemy tak napisać kod, by treścią komunikatu była wartość sprawdzanego przez nas wyrażenia.

MsgBox (Selection.Font.Bold)

Aby przetestować nasz kod, musimy uruchomić makro. Możemy to zrobić z poziomu edytora VBA naciskając klawisz F5 lub z poziomu Worda z karty Deweloper wybierając Makra (lub ALT+F8) i tam uruchom.

Po uruchomieniu makra wyskoczy okienko z komunikatem. Treść komunikatu będzie wartością liczbową. Wartość wyrażenia rzadko kiedy jest wyświetlana tak, jak w kodzie, czyli np. true, false. W przypadku pogrubienia dostajemy 0, jeśli zaznaczenie nie jest pogrubione, -1, jeśli jest pogrubione lub 99999999 jeśli zaznaczenie jest częściowo pogrubione. Znajomość tych wartości jest bardzo przydatna, gdy chcemy budować instrukcje warunkowe. Są to takie instrukcje, które wykonują różne wersje kodu, w zależności od spełnienia bądź nie zadanego warunku. Ogólna postać instrukcji warunkowej jest następująca:

Jeżeli (spełniony jest ten warunek) to wtedy wykonaj taka instrukcję jeżeli zaś(spełniony jest ten warunek) to wtedy wykonaj taką instrukcję w przeciwnym razie wykonaj tą instrukcję koniec bloku jeżeli

Możemy wykorzystać taką instrukcję do wyświetlenia komunikatu w zależności od stanu pogrubienia zaznaczenia.

If (Selection.Font.Bold = -1) Then MsgBox ("Ten fragment jest pogrubiony") ElseIf (Selection.Font.Bold = 0) Then MsgBox ("Ten fragment NIE jest pogrubiony") Else: MsgBox ("Ten fragment jest częściowo pogrubiony") End If

W zależności od tego, jaką wartość przyjmie Bold, wyświetli się jeden z trzech komunikatów. MsgBox nie jest jednak najlepszym narzędziem do testowania kodu, zwłaszcza gdy chcemy sprawdzić wiele wartości, np. wyświetlić listę pewnych wartości.
W takiej sytuacji musielibyśmy klikać OK dla każdej wartości na liście, co jest bardzo kłopotliwe.

Immediate Window

Możemy zastąpić MsgBox komunikatami wyświetlanymi w tzw. 'Immediate Window", które włączamy w edytorze VBA skrótem klawiszowy CTRL+G. Komendą zastępującą MsgBox jest Debug.Print.
Pokażę teraz jak przy pomocy Debug.Print wyświetlić w immediate window zawartość zaznaczenia oraz jego długość liczoną w znakach.

Debug.Print (Selection) Debug.Print (Selection.Characters.Count)

Pierwsza linijka wyświetli w oknie treść zaznaczenia, druga zaś zlicza ilość znaków w zaznaczeniu. Jeśli więc napiszemy sobie w wordzie dobreprogramy, zaznaczymy i uruchomimy makro to otrzymamy:

dobreprogramy 13

Zaczynamy programować

Na początku napisałem, że można stworzyć proste i użyteczne makra bez znajomości zasad programowania. Rejestrator makr nie używa nawet takich podstawowych elementów programowania jakimi są zmienne, instrukcje warunkowe czy pętle. Gdy zaczynamy się uczyć jak tworzyć makra nie są one potrzebne. Jednakże, gdy już oswoimy się edytorem VBA, poznamy podstawowe elementy, którymi manipulujemy w makrach takie, jak zaznaczenie, wyrazy, znaki, czcionki itp. będziemy mieć co raz więcej pomysłów na kolejne, bardziej złożone makra. Z czasem, a nastąpi to raczej dosyć szybko, uświadomimy sobie, że pewnych pomysłów nie jesteśmy w stanie zrealizować rejestratorem makr. Zaczniemy sami pisać instrukcje, ale ciągle będzie nam brakowało odpowiednich narzędzi do zrealizowania bardziej ambitnych pomysłów. Pewnych rzeczy nie da się po prostu zrobić bez podstawowych elementów programowania.

Zmienne

Zmienne są pierwszym takim elementem. Każda zmienna musi mieć swoją unikalną nazwę, przy pomocy której będziemy się do niej odwoływać. Zadaniem zmiennych jest przechowywanie wartości. Jak sama nazwa wskazuje, wartość przechowywana przez zmienną może ulegać zmianie w czasie wykonywania kodu. VBA jest bardzo liberalne w zakresie zasad tworzenia zmiennych. W większości języków programowania zmienne muszą być przed pierwszym użyciem zadeklarowane. Co więcej, zmienna taka musi mieć określony typ danych, jaki będzie przechowywać. Jeśli więc będziemy przechowywać w niej liczby całkowite, to musimy ją zadeklarować jako zmienną typu liczb całkowitych. W VBA nie ma takiej konieczności. Jest to duże ułatwienie dla osób, które nie miały do tej pory styczności z programowaniem. Wystarczającą i prawidłową konstrukcją jest więc taki zapis:iloscWyrazow = Selection.Words.CountW ten sposób tworzymy zmienną o nazwie iloscWyrazów i przypisujemy jej wartość liczbową równą ilości wyrazów w zaznaczeniu. Aby sprawdzić czy nasza zmienna faktycznie działa, możemy wyświetlić jej zawartość:Debug.Print (iloscWyrazow)Ja jednak zachęcam do deklarowania zmiennych. Choć może się wydawać to zbytecznym wysiłkiem, jest to bardzo pomocne. Po pierwsze unikniemy w ten sposób wielu błędów. Interpreter rozróżnia wielkość liter. Jeśli więc pomylimy się i napiszemy:Debug.Print (iloscwyrazow)to nie uzyskamy prawidłowej wartości, ponieważ interpreter nie zrozumie, że chodzi nam o zmienną pisaną przez duże W. Zmienne uprzednio zadeklarowane, zostaną automatycznie poprawione w trakcie pisania. Co więcej, jeśli nie pamiętamy dokładnie nazwy zmiennej, to po napisaniu pierwszych liter możemy użyć skrótu CTRL+SPACJA, który automatycznie dopisze nam nazwę zadeklarowanej zmiennej do końca.
Zmienne deklarujemy słówkiem Dim (co jest bodajże skrótem do declare in module) poprzedzającym nazwę zmiennej:

Dim iloscWyrazow As Integer iloscWyrazow = Selection.Words.Count Debug.Print (iloscWyrazow)

Wyrażenie "As Integer" jest również opcjonalne i oznacza ono określenie typu danych przechowywanych przez zmienną, w tym przypadku to liczby całkowite. VBA potrafi automatycznie rozpoznawać typy danych, dlatego osoby początkujące mogą sobie tym nie zaprzątać głowy. Podaję to bardziej jako ciekawostkę.

Pętle

Kolejnym podstawowym elementem programowania są pętle. Są to wielokrotnie powtarzane bloki instrukcji. Może to być nawet jedna instrukcja powtarzana wielokrotnie. Jeśli więc przykładowo chcielibyśmy kazać Wordowi by narysował linię składającą się z kropek to kazalibyśmy mu wielokrotnie wykonać jedną prostą instrukcję: napisz znak kropki. Jest kilka podstawowych rodzajów pętli. ja pokażę najprostszą z nich - pętle "for".
Powtarzana ona daną instrukcję / blok instrukcji zadaną z góry ilość razy. Ilością kroków (powtórzeń) pętli steruje tzw. zmienna sterująca. Często jest nazywana "i" od ang. integer - liczba całkowita, ale możemy ją sobie nazwać dowolnie, np. licznik. W każdym języku programowania ta pętla ma w kodzie nieco inną postać, ale ogólnie można ją przedstawić tak:
Dla wartości zmiennej sterującej od 1 do 10 wykonuj następujący kod.
Dla lepszego zrozumienia podam najprostszy możliwy przykład.For licznik = 1 To 10 Debug.Print (licznik) Next licznik

W każdym kroku pętli zmienna licznik przyjmuje kolejno wartości od 1 do 10. Pętle for stosujemy, gdy wiemy ile razy ma się ona "przekręcić". Dlatego przeważnie zanim zaczniemy pętle, musimy ustalić liczebność jakiegoś zbioru, na którym będziemy wykonywać operacje. Wytłumaczę to na przykładzie wyrazów w zaznaczeniu.Dim iloscWyrazow iloscWyrazow = Selection.Words.Count For licznik = 1 To iloscWyrazow Debug.Print (Selection.Words(licznik)) Next licznik

W powyższym kodzie wykorzystujemy fakt, że Words jest ponumerowanym zbiorem elementów, zwanym w programowaniu tablicą. W tym przypadku jest to zbiór wyrazów z naszego zaznaczonego tekstu. Do każdego elementu takiego zbioru możemy się odwołać poprzez tzw. indeks tego elementu, czyli jego numer. Elementy są ponumerowane wedle kolejności występowania w tekście. Pierwszy element ma numer 1. W większości języków programowania pierwszy element tablicy ma indeks równy 0, ale w VBA domyślnie numerowanie elementów tablicy zaczyna się do 1. Można to zmienić, ale w wielu przypadkach tak jest łatwiej (np. numeracja wierszy w Excelu też zaczyna się od 1).
Wracając do powyższego przykładu, zmienna iloscWyrazow przyjmuje wartość równą ilości wyrazów znajdujących się w zaznaczonym przez nas tekście, jeszcze przed rozpoczęciem pętli. To bardzo ważne! Pętla wykona tyle kroków, ile jest wyrazów. Zmienna licznik początkowo ma wartość 1. Po każdym wykonaniu instrukcji wyświetlenia wyrazu, zwiększy swoją wartość o 1. Dzięki temu za każdym razem ze zbioru wyrazów Words jest wybierany kolejny wyraz zaznaczenia i wyświetlany w immediate window.

Prosty przykład zastosowania VBA w Wordzie

Powiedzmy, że mamy prostą tabelkę jak na zrzucie ekranu poniżej.

Pokaże jak zrobić, aby za pomocą makra VBA pokolorować nieparzyste wiersze tabeli licząc bez nagłówka.

Dim tabela Dim wiersze Dim licznik tabela = Selection.Tables(1) wiersze = tabela.Rows.Count For licznik = 2 To wiersze Step 2 tabela.Rows(licznik).Shading.BackgroundPatternColor = wdColorGray10 Next licznik

Najpierw deklarujemy trzy zmienne. Pierwsza z nich będzie reprezentowała naszą tabelę, druga ilość wierszy w tabeli, a trzecia to zmienna sterująca pętlą. Tables jest zbiorem tabel w obrębie zaznaczenia. Zakładam, że przed uruchomieniem makra staniemy kursorem myszy gdziekolwiek w obrębie interesującej nas tabeli. Ponieważ będzie to jedyna tabela w obszarze zaznaczenia, będzie to pierwsza tabela w zbiorze Tables. Następnie zapisujemy do zmiennej wiersze ilość wierszy naszej tabeli przez funkcję Count wywołaną na rzecz zbioru wierszy tabeli Rows. Mając tak przygotowane zmienne zaczynamy pętlę. Pętla ta wygląda minimalnie inaczej od poprzedniej. Pojawia się bowiem słówko Step, które określa rozmiar kroku pętli. Step 2 sprawia, że zmienna sterująca licznik będzie się zwiększała po każdym przebiegu pętli o 2, a nie o 1 jak jest domyślnie. Odliczanie zaczynamy od 2, bowiem chcemy pominąć pierwszy wiersz, który jest nagłówkiem. W każdym kroku pętli wybieramy z tabeli pojedynczy wiersz o indeksie równym wartości zmiennej sterującej licznik. Za pierwszym razem będzie to 2, później 4 (zwiększamy o zawsze o 2), później 6 itd. W ten sposób w każdym kolejnym kroku pętli będziemy wybierać co drugi wiersz tabeli. Oczywiście, gdybyśmy z jakiegoś powodu chcieli wybrać co trzeci lub co czwarty wiersz tabeli, to możemy ustawić wartość Step na 3 lub 4. Gdy mamy już wybrany wiersz, to po kropce wybieramy właściwość wiersza jaką jest Shading, czyli cieniowanie, a po kolejnej kropce BackgroundPatternColor czyli kolor tła, jakim chcemy zamalować wiersz. Wszystkie te "nazwy" możemy szybko uzyskać rejestrując makro rejestratorem makr i zmieniając kolor tła pojedynczego wiersza. W uzyskanym kodzie otrzymamy wszystkie potrzebne informacje, które potem wykorzystamy we własnym kodzie. Po znaku równości wpisujemy wd (skrót od Word) i naciskamy CTRL+Spacja. Pojawia się nam lista dostępnych kolorów. Ja wybrałem szary 10%. Po wykonaniu makra tabelka wygląda następująco:

Najlepsze w naszym makro jest to, że możemy dodać nawet i 100 wierszy, a makro dostosuje się do nowej ilości wierszy i wykona zadanie tak samo szybko. Jest to niemożliwe do wykonania makrem zarejestrowanym przez rejestrator. Ale na tym nie koniec. Powiedzmy, że chcemy aby nasza tabelka miała w pierwszej kolumnie ponumerowane komórki. W tym celu dopiszemy kilka instrukcji wewnątrz naszej pętli.

For licznik = 2 To wiersze Step 2 tabela.Rows(licznik).Shading.BackgroundPatternColor = wdColorGray10 tabela.Rows(licznik).Cells(1).Range.Text = licznik - 1 If (Not licznik = wiersze) Then tabela.Rows(licznik + 1).Cells(1).Range.Text = licznik End If Next licznik

Po cieniowaniu dodałem linijkę, w której dla danego wiersza wybieram pierwszą komórkę tego wiersza (pierwszą kolumnę) i poprzez właściwość Text wpisuję tam liczbę równą co do wartości licznikowi minus 1. Odejmujemy 1 ponieważ zaczynamy numerowanie od drugiego wiersza wartością 1. Ponieważ nasza pętla wykonuje skoki co 2, w każdym kroku pętli trzeba obsłużyć dwa wiersze jednocześnie: bieżący - równy licznikowi oraz następny. Aby edytować następny wiersz, względem bieżącego (wskazanego wartością licznika) podajemy w indeksie wiersza licznik + 1. Wartość wpisywane tekstu tym razem równa jest licznikowi. Jednakże tak zmodyfikowany zapis jest nieprawidłowy dla ostatniego wiersza tabeli. Nie możemy w kodzie odnosić się do wiersza o indeksie licznik + 1 w ostatnim wierszu tabeli, ponieważ taki wiersz (ostatni + 1) nie istnieje. Dlatego zanim wykonamy taką instrukcję, musimy się upewnić, że będzie ona wykonywana wszędzie poza ostatnim wierszem. W tym celu skorzystamy z konstrukcji instrukcji warunkowej z warunkiem licznik nie jest równy ilości wierszy tabeli.

Takie makro można przerobić sobie tak, aby każda wstawiana przez nas tabela miała automatycznie ponumerowane wiersze w pierwszej kolumnie i pokolorowany co drugi wiersz. Nasze makra mogą być uruchamiane skrótem klawiszowym lub własnym przyciskiem na wstążce. Nie będę w tym wpisie omawiać sposobów na uzyskanie takiego efektu, bo jest to zagadnienie na tyle obszerne, że wymagałoby oddzielnego wpisu.

Podsumowanie

Makrodefinicje, zwłaszcza te pisane własnoręcznie, potrafią znacząco zwiększyć możliwości Worda, przyspieszyć pracę, wyręczyć nas w żmudnych, powtarzających się czynnościach. W tym wpisie pokazałem jedynie proste przykłady, aby wyjaśnić podstawowe zasady działania makr i VBA. Możliwości są jednak niemal nieograniczone. Można przykładowo stworzyć makro, które będzie nam zamieniać wartość liczbową na słowną, co może być bardzo przydatne przy różnych rachunkach. Analogicznie można zamieniać daty. Wiele zależy od charakteru naszej pracy. Jeśli korzystamy z szablonów, które zawierają powtarzalne dane, możemy stworzyć makro, które przy zapisie nowego dokumentu z szablonu, będzie pobierać informacje z nazwy tego dokumentu (np. imię i nazwisko osoby, której dotyczy dokument) i wstawia w odpowiednie miejsca w dokumencie i to zanim zaczniemy prace z tym dokumentem. Możemy znacząco przyspieszyć formatowanie dokumentu, efektywniej wykorzystać style. VBA potrafi odczytywać dane z systemu plików, a także pobierać dane z innych dokumentów i to nie tylko Worda, ale także pozostałych programów Office'a. Excel czy Outlook dają jeszcze większe do popisu makrom VBA. Dlatego warto je znać, zwłaszcza gdy staramy się wycisnąć z tych programów jak najwięcej. 

windows porady programowanie

Komentarze

0 nowych
DjLeo MODERATOR BLOGA  17 #1 02.11.2014 19:22

Wow, kawał dobrej roboty... niech ktoś mi powie, że jest źle z blogami :) Rewelacyjne wpisy ostatnio się pojawiają. Brawo...

Co do samego wpisu, to VBA niekiedy bywa pomocne. Temat jak najbardziej godny kontynuowania.

Autor edytował komentarz.
Kaleson   4 #2 02.11.2014 19:36

Jak sprawa wygląda w LO? Widziałem, że można pisać makra w Basicu i chyba Javie...

kaisuj   10 #3 02.11.2014 19:50

@Kaleson: Szczerze mówiąc to pisania makr w LibreOffice jest w porównaniu z VBA jakimś koszmarem. Rejestrator makr wali dziesiątkami linii kodu dla najprostszych operacji i jest to kod mocno skomplikowany. Nie udało mi się opanować tej sztuki, mimo sporego doświadczenia z VBA.

sgj   10 #4 02.11.2014 20:47

LibreOffice Writer:

Sub Macro1

dim tables as object
Dim tabela as object
dim rows as object
Dim wiersze as integer
Dim licznik as integer

tables = ThisComponent.TextTables
tabela = tables.getByIndex(0)

rows = tabela.rows

wiersze = rows.Count

For licznik = 2 To wiersze Step 2
tabela.Rows(licznik).setPropertyValue("BackColor",RGB(237,28,36))
Next licznik

End Sub

Autor edytował komentarz.
kaisuj   10 #5 02.11.2014 21:06

@sgj: Poważnie? Jestem w szoku! Coś się musiało zmienić, bo jak ja próbowałem pisać makra w basicu w LibreOffice, to wyglądało to kompletnie inaczej. Aż zaraz sprawdzę!

Sprawdziłem i u mnie rejestrator wygenerował taki kod na pogrubienie czcionki:

sub Testowe
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 = "Bold"
args1(0).Value = true

dispatcher.executeDispatch(document, ".uno:Bold", "", 0, args1())

end sub

Co ciekawe sprawdziłem Twój kod. Pomijając fakt, że zakres pętli był źle określony, bo numeracja tablic zaczyna się tutaj od 0, to kod działa!
Wygląda to tak, jakby były dwa zupełnie różne modele obiektowe. Jeden jest wykorzystywany przez rejestrator makr, a drugi Ty wpisałeś z palca. Znasz może jakąś dokumentację do tego? Kiedyś miałem plan aby przenieść swoje skrypty VBA do LibreOffice'a, ale poległem. Twój kod otworzył mi oczy i widzę, że moje dawne plany są możliwe do zrealizowania.

Autor edytował komentarz.
sgj   10 #6 02.11.2014 21:38

Z dokumentacją jest cięzko. Jakies podstawy są na wiki OpenOffice. Jak już chce się przepisać jakiś kod to po miejscach gdzie daje błędami idzie się dokopać po googlach jak powinno być. Ogólnie jak patrze to trzeba szukać do openoffice, bo przez lata jest tego troche w sieci.

Autor edytował komentarz.
pocolog   11 #7 02.11.2014 21:54

@sgj, @kaisuj: z o wiele błahszymi problemami zawsze sięgam do dokumentacji openoffice bo jest dłużej na rynku i łatwiej odszukać problem a praktycznie bliźniacze rozwiązania.

Vidivarius   13 #8 02.11.2014 23:00

@kaisuj
No!! Wpis pierwsza klasa. Bardzo mi się podobał. Tym bardziej, że sam muszę robić podobne makra na swoje potrzeby.
Mam nadzieję, że jeszcze poświęcisz jakieś wpisy makrom, szczególnie tym dla Worda, bo mam w rażenie, że w polskich internetach to nie za wiele jest tego w formie nie wymagającej od czytelnika znajomości programowania.
Dzięki za wpis, dodany do ulubionych.

slimak12   2 #9 03.11.2014 08:57

Na prawdę świetny Wpis. Sam korzystam z Makr, lecz nigdy ich nie tworzyłem :)

samonek4   3 #10 03.11.2014 09:20

Prawie codziennie korzystam z makr Excela. Niektóre są bardzo długie - po kilka stron. Jak ktoś ma doświadczenie w programowaniu w innych językach to szybko załapie język VBA. W internecie można znaleźć mnóstwo e-boków na temat pisania makr( np. Walkenbach). Podstawowa wada makr VBA to fakt, że są interpretowane przez co czasami działają bardzo powoli - w tym przypadku można tworzyć pomocnicze biblioteki DLL w C++ i wywoływać je z kodu VBA. Można też optymalizować kod VBA tak aby działał szybciej - są na to pewne tricki np.:
http://www.cpearson.com/excel/optimize.htm
http://www.excelitems.com/2010/12/optimize-vba-code-for-faster-macros.html

W przypadku bardzo dużych danych dobrze jest je wczytać do tablicy i obliczenia wykonywać w pamięci.

Polecam również narzędzie do translacji MS VBA to OpenOffice VBA:
http://www.business-spreadsheets.com/vba2oo.asp

Autor edytował komentarz.
CzarnaZmija   8 #11 03.11.2014 10:33

super wpis!
właśnie stawiam pierwsze kroki z markami więc dla mnie to bardzo pożyteczny wpis.
Oby więcej takich!

Pablo_Wawa   9 #12 03.11.2014 13:37

Według mnie powinieneś jeszcze napisać o wygodnym podglądzie obiektów w Debuggerze/Edytorze kodu (prawoklik na elemencie -> Add watch) - tam ładnie można sobie zobaczyć "zawartość" danego obiektu.

_qaz7   6 #13 03.11.2014 16:26

kilka ciekawostek o automatyzacji można znaleźć w necie - np. budowanie wykresów w Excelu Powershellem, itd

https://www.simple-talk.com/dotnet/.net-tools/com-automation-of-office-applicati.../

czy

http://learn-powershell.net/2012/12/24/powershell-and-excel-adding-a-chart-and-h.../

  #14 03.11.2014 16:57

Mam nadzieje że to tylko pierwszy odcinek długiej i obiecującej serii:)

Neo   11 #15 03.11.2014 18:00

Ciekawy wpis, miło się czytało. Widzę że coraz więcej fajnych wpisów pojawia się na łamach DP. ;) Fajnie fajnie. :)

  #16 04.11.2014 11:46

Może ktoś z was polecić aktualną książkę do nauki VBA i tworzeniu makr w Excel 2013? Coś co już ktoś sprawdził i będzie pomocne przy samodzielnej nauce dla nowicjusza.

kaisuj   10 #17 04.11.2014 13:30

@Spartenor (niezalogowany): Moim zdaniem najlepiej jest jednak uczyć się z googli. Masz konkretny problem do rozwiązania i szukasz konkretnych rozwiązań. W książce możesz nie mieć życiowych przykładów, albo tylko takie, które i tak Ci się do niczego nie przydadzą. Jednak jeśli chcesz poczytać książki to z pewnością mogę polecić Ci autora - John Walkenbach - guru Excela i VBA.
Do Excela 2013 ma np. http://helion.pl/ksiazki/excel-2013-pl-programowanie-w-vba-vademecum-walkenbacha...
Nie miałem w rękach tej książki, ale czytałem inne jego książki i wertowałem jego stronę z przykładowymi rozwiązaniami.

yuwo   7 #18 04.11.2014 22:45

Ciekawy wpis. Nikt by się nie obraził, gdybyś przygotował kilka praktycznych przykładów wykorzystania makr - oczywiście takich usprawniających (automatyzujących) pracę w Wordzie.

Ja wykorzystuję makra do formatowania tekstu za pomocą przycisku. Jest to bardzo wygodne. Zamiast bawić wybieraniem kilku opcji klika się jeden przycisk i gotowe.

  #19 12.08.2016 01:25

Jaką instrukcją wyszukać kolejny rysunek a potem go zaznaczyć i pobrać do schowka?
Poniższa instrukcja nie działa, gdyż nie rozróżnia rysunków i równań w formacie "Equation.3".
Selection.GoTo What:=wdGoToGraphic, Which:=wdGoToNext, Count:=1
Chodzi o to aby równania były ignorowane a makro kopiowało tylko kolejne rysunki.

  #20 12.08.2016 01:50

Jaką instrukcją wyszukać w tekście Word kolejny rysunek, a potem go zaznaczyć i pobrać do schowka?
Poniższa instrukcja nie działa, gdyż nie rozróżnia rysunków i równań w formacie "Equation.3".
Selection.GoTo What:=wdGoToGraphic, Which:=wdGoToNext, Count:=1
Powyższa instrukcja zaznacza także kolejnie równia, a chodzi o to aby równania były ignorowane a makro kopiowało tylko kolejne rysunki.