Automatyzacja pracy z Wordem — pomysł na papier firmowy
Mój poprzedni wpis na temat VBA został przyjęty raczej pozytywnie, postanowiłem więc pójść za ciosem i przychylić się do próśb czytelników, rozwijając temat o przykłady kodu, które można wykorzystać do zautomatyzowania wstawiana nagłówków i stopek w dokumentach firmowych. Sam stosowałem te rozwiązania z powodzeniem. Zaczynałem od najprostszego wariantu i stopniowo doskonaliłem metodę, wzbogacając ją o nowe warianty i możliwości. Podobnie zamierzam postąpić w tym wpisie, zaczynając od najprostszego do zautomatyzowania przypadku.
Nagłówki w papierze firmowym
Temat papieru firmowego jest za pewne dobrze znany wszystkim pracującym. Polityka firmy w tym zakresie bywa różna. Jedni zamawiają gotowy papier firmowy w drukarni, inni zaś drukują na czystym papierze, wstawiając dane firmy w nagłówek dokumentu. To drugie rozwiązanie być może jest tańsze, ale z pewnością bardziej kłopotliwe. Każdorazowe wstawianie nagłówkowa do dokumentu jest z pewnością upierdliwe. Dokumenty można powielać, tworzyć nowy na bazie starego, posiadającego już nagłówek, ale to też nie jest rozwiązanie idealne. Może się bowiem zdarzyć, że uległy zmianie dane teleadresowe albo logo firmy i nagle mamy setki albo i tysiące dokumentów z nagłówkiem zawierającym nieaktualne dane. Mam swój sposób rozwiązujący ten problem. Być może to również nie jest rozwiązanie idealne i nie każdemu podpasuje, aczkolwiek warto się z nim zapoznać chociażby po to, aby poznać pewne techniki w pracy z makrami VBA i zainspirować się do własnych, być może lepszych rozwiązań.
Nagłówek jako zewnętrzny plik
Mój pomysł na papier firmowy opiera się na założeniu, że skoro dane z nagłówka mogą się zmieniać, to fajnie by było, gdybyśmy je edytowali tylko w jednym dokumencie, a nie we wszystkich zawierających nagłówki firmowe. Dlatego proponuję utworzyć taki dokument, nazwać go np. nagłówek.docx i zapisać w jakimś sensownym miejscu, które przez dłuższy czas nie będzie zmieniało swojego położenia. Jeśli nie mamy firmowego serwera, a korzystamy z wielu stanowisk z Wordem, możemy zapisać go np. w Dropboxie. Podobnie uczyniłbym z plikiem normal.dotm, w którym są zapisane nasze makra. Na każdym stanowisku z Wordem wskazałbym ścieżkę do pliku normal.dotm w Dropboxie, dzięki czemu, jeśli dokonamy zmiany w naszych makra, to będą one automatycznie zaktualizowane dla wszystkich stanowisk.
Nagłówek wygodnie formatuje się jako tabelę bez obramowań. Oczywiście każdy może zrobić po swojemu, wedle upodobań i przyzwyczajeń. Teraz musimy napisać makro, które będzie nam wstawiać do dokumentu ten nagłówek. Makra VBA obsługują pewien zakres domyślnie zdefiniowanych zdarzeń. Oznacza to, że jeśli takowe zdarzenie zaistnieje, to automatycznie wywołuje ono nasze makro. Przykładem takiego zdarzenia może być otworzenie dokumentu w Wordzie. Takie makra mają z góry określone, zarezerwowane nazwy. Spotkałem się z kilkoma nazwami makr reagującymi na otwierany dokument. Z mojego doświadczenia wynika, że najlepiej spisuje się makro o nazwie AutoOpen. Szczerze mówiąc to nie wiem na czym polegają różnice między poszczególnymi makrami reagującymi na to samo zdarzenie, ale z doświadczenia wiem, że makro Document_Open wykrzacza się na próbie wejścia do nagłówka dokumentu, a AutoOpen nie. Teoretycznie różnica jest taka, że Document_Open umieszczane jest bezpośrednio w dokumencie, więc możemy jest stosować dla wybranego dokumentu, a AutoOpen wstawia się do modułu, a więc ma za zadanie działać globalnie. Nigdzie jednak nie znalazłem wyjaśnienia dlaczego Document_Open krzaczy się z operacjami na nagłówku, a AutoOpen nie.
Wstawianie dokumentu do nagłówka
Makro wstawiające nasz dokument z nagłówkiem do nagłówka każdego otwieranego dokumentu ma następujący kod:
Sub AutoOpen() ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Range.InsertFile FileName:="C:\Users\MojaFirma\Desktop\nagłówek.docx", Range:="", _ ConfirmConversions:=False, link:=True, Attachment:=False End Sub
Jak widać nie jest to nic strasznie skomplikowanego. Z aktywnego (właśnie otworzonego) dokumentu wybieramy pierwszą sekcję (jeśli nie mamy w dokumencie podziału na sekcje, to zawsze mamy jedną sekcję), a w niej nagłówki z opcją podstawowego nagłówka (jednakowego dla wszystkich stron). W jego zakresie wstawiamy plik podając ścieżkę do uprzednio zapisanego pliku z nagłówkiem.
Może się zdarzyć, że chcemy mieć inny nagłówek na pierwszej stronie niż na innych. W takiej sytuacji należy dokonać kilku drobnych modyfikacji w kodzie. Po pierwsze musimy najpierw ustawić w dokumencie opcję, że nagłówek pierwszej strony ma być inny niż pozostałych. Następnie dla nagłówka pierwszej strony zamieniamy typ nagłówka z wdHeaderFooterPrimary na wdHeaderFooterFirstPage. Następnie wstawiamy pozostałe nagłówki z opcją wdHeaderFooterPrimary podając odpowiednią lokalizację do pliku.
Sub AutoOpen() ActiveDocument.PageSetup.DifferentFirstPageHeaderFooter = True ActiveDocument.Sections(1).Headers(wdHeaderFooterFirstPage).Range.InsertFile FileName:="C:\Users\Jarosław\Desktop\nagłówek.docx", Range:="", _ ConfirmConversions:=False, link:=True, Attachment:=False ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Range.InsertFile FileName:="C:\Users\Jarosław\Desktop\dalszeNagłówki.docx", Range:="", _ ConfirmConversions:=False, link:=True, Attachment:=False End Sub
Dla osób znających język angielski nie jest tajemnicą, że w pierwszej linijce kodu ustawiamy ustawienia strony aktywnego dokumentu, a w nich nagłówek pierwszej strony innych od pozostałych stron.
Drukowanie z różnych szuflad drukarki
Niektóre firmy mogą chcieć korzystać z systemu hybrydowego - tzn. papier firmowy z drukarni z nadrukowanym kolorowym logo i własnoręcznie nadrukowywane dane teleadresowe firmy w nagłówku. Jeśli w takiej sytuacji będziemy chcieli mieć pierwszą stronę z logo firmowym, a pozostałe strony drukowane już na zwykłym papierze (cóż, oszczędności) to pojawia nam się kłopot drukowania. Normalnie musielibyśmy drukować oddzielnie pierwszą kartkę i oddzielnie resztę dokumentu, bo podejrzewam, że papier firmowy z logo będzie znajdować się w innej kieszeni drukarki. W takiej sytuacji można rozważyć drukowanie dokumentów za pomocą makra VBA. Istnieje możliwość określania w kodzie numerów stron, które mają zostać wydrukowane. Nie będę w tym wpisie wdawać się w szczegóły, ale podpowiem tylko że istnieje możliwość wyboru tacy drukarki z poziomu VBA. Dzięki temu możemy za jednym zamachem wydrukować cały dokument, przydzielając odpowiednie strony dokumentu odpowiednim tacom drukarki. Podpowiem tylko jak wygląda przykładowy wybór tacy:
ActiveDocument.PageSetup.FirstPageTray = wdPrinterUpperBin
Dywersyfikacja nagłówków
Nie każda firma ma jeden szablon nagłówka czy stopki dla wszystkich swoich dokumentów. Być może każdy dział ma swój oddzielny nagłówek, albo stosowane są różne nagłówki w zależności od rodzaju dokumentu. Może być też tak, że w pewnych dokumentach w ogóle nie chcemy stosować nagłówków. Nasze makro w obecnej postaci wstawia nagłówki do absolutnie każdego otwieranego dokumentu. Co gorsza, jeśli otworzymy jakiś dokument, który do tej pory nie posiadał nagłówka i nie chcemy zmieniać tego stanu rzeczy, to nasze makro wstawi go przy każdym otworzeniu i trzeba ręcznie go usuwać.
Rozwiązanie tego problemu jest bardzo proste. Trzeba powiedzieć naszemu skryptowi jak traktować poszczególne dokumenty. Najłatwiej jest, gdy poszczególne typy dokumentów są zapisane w różnych folderach. Podejrzewam, że większość osób posiada jakąś sensowną strukturę katalogów. Można ją wykorzystać do identyfikacji typów dokumentów. Aby wykryć lokalizację z jakiej jest otwierany dokument możemy użyć następującego kodu:
Sub AutoOpen() Dim Lokalizacja As String Lokalizacja = ActiveDocument.Path If (Lokalizacja = "D:\Dropbox\Produkcja") Then 'Kod wstawiający nagłówek do dokumentów działu produkcji End If End Sub
Jeżeli nasza struktura katalogów jest rozbudowana (a przeważnie właśnie tak jest) to możemy ustawić warunek na określony poziom w strukturze katalogów. Powiedzmy, że najwyższym poziomem katalogów, dla których chcemy zastosować dany typ nagłówka jest katalog produkcja. Obecna postać makra sprawdza lokalizację dokumentu, a nam bardziej by pasowało, aby skrypt sprawdzał czy lokalizacja danego dokumentu zawiera się w naszym folderze Produkcja. W tym celu należy skorzystać z jakiejś wbudowanej funkcji VBA przetwarzającej ciągi znaków. Ja użyję funkcji InStr, która przyjmuje trzy argumenty: pozycję początkową, ciąg1 i ciąg2. Funkcja ta porównuje ze sobą dwa ciągi znaków i zwraca pozycję pierwszego pojawienia się drugiego ciągu w pierwszym ciągu. Jeśli drugi ciąg nie pojawia się w pierwszym ciągu, to zwraca 0. Jeśli więc mamy, że nasz pierwszy ciąg reprezentuje lokalizację otwieranego dokumentu, a nasz drugi ciąg to lokalizacja folderu Produkcja: "D:\Dropbox\Produkcja", to jeśli ten otwierany dokument będzie mieć np. lokalizację: "D:\Dropbox\Produkcja\2014\Pisma" to funkcja zwróci wartość 1 (bo lokalizacja folderu Produkcja zawiera się w lokalizacji otwieranego dokumentu i zaczyna się od 1 znaku), a jeśli lokalizacja miałaby np. postać: "D:\Dropbox\Księgowość\2013\Wyliczenia" to funkcja zwróci 0. Na tej podstawie możemy przebudować nasze makro do następującej postaci:
Sub AutoOpen() Dim Lokalizacja As String Dim Produkcja As String Dim dokProdukcyjny As Integer Produkcja = "D:\Dropbox\Produkcja" Lokalizacja = ActiveDocument.Path dokProdukcyjny = InStr(1, Lokalizacja, Produkcja) If (Not dokProdukcyjny = 0) Then 'Kod wstawiający nagłówek do dokumentów działu produkcji End If End Sub
Można powiedzieć prościej, że sprawdzamy czy Lokalizacja otwieranego dokumentu zaczyna się od ciągu znaków "D:\Dropbox\Produkcja". Jeśli tak, to wiemy, że należy do dokumentu wstawić nagłówek typowy dla dokumentów produkcyjnych.
Podsumowanie
Makra VBA mają to do siebie, że w większości przypadków zaspakajają bardzo specyficzne potrzeby. Ciężko jest wymyślić usprawnienia, które mogłyby być przydatne dla każdego. Najlepiej jest poznać specyfikę pracy danej firmy, zaobserwować powtarzające się czynności, które dałoby się zautomatyzować lub w rozmowie z pracownikami odkryć czego im brakuje w pracy z Wordem na ich konkretnym stanowisku pracy. Patrząc z tej perspektywy na makra VBA mogę śmiało pokusić się o stwierdzenie, że najlepiej predysponowanymi osobami do pisania makr VBA, są sami pracownicy. Oczywiście, że można spotkać nawet całe aplikacje komercyjnie napisane w VBA (przeważnie na bazie Accessa lub Excela), ale w większości przypadków istnieje duże zapotrzebowanie na drobne usprawnienia, które stopniem trudności nie przerastają przeciętnego pasjonata komputerów. Dlatego zachęcam wszystkich do próbowania tworzenia takich usprawnień. Daje to wiele satysfakcji, a przy okazji ułatwia życie.