czwartek, 31 października 2013

Niemodalne okienko MsgBox

Standardowe okienko MsgBox występujące w języku VBA ma tą (niekiedy uciążliwą) cechę, że jest okienkiem modalnym. Modalnym czyli takim, które należy zamknąć aby móc powrócić do pracy z aplikacją znajdującą się w tle. Jak więc wywołać proste okienko z przyciskami Tak/Nie/Anuluj w trybie niemodalnym? Jest kilka możliwych wariantów spośród których skupię się szczegółowo tylko na jednym.

Wariant A. Należy stworzyć okno UserForm, a następnie wyświetlić go w trybie niemodalnym:


Wariant B. Wykorzystać okienko znajdujące się w zewnętrznej bibliotece Windows Script Hosting. Poniżej prezentuję kompletny kod, który wyświetla okienko z trzema przyciskami oraz wykonuje akcję zależnie od wybranego przycisku.


Rozwiązanie to posiada dodatkową opcję, która pozwala określić czas, przez jaki okienko będzie widoczne. Niestety, parametr ten nie działa stabilnie. W praktyce tylko ustawienie czasu oczekiwania na 1 sekundę gwarantuje ukrycie okna. W przypadku dłuższego czasu oczekiwania okienko i tak oczekuje na akcję za strony użytkownika. Być może błąd ten zależny jest od wersji oprogramowania nie mniej nie udało mi się odnaleźć informacji na temat rozwiązania tego problemu.

Dodatkowe informacje na temat okna Popup z biblioteki Windows Scripting znajdziecie Państwo pod tym linkiem.

wtorek, 22 października 2013

Losowy dokument w Wordzie

Tworząc szereg rozwiązań w VBA dla aplikacji MS Word często testuję określone techniki korzystając z przykładowego 'losowego' dokumentu. Dokument taki można stworzyć w bardzo prosty sposób wykorzystując ukryte polecenia aplikacji MS Word. W tym celu proszę utworzyć nowy pusty dokument w Word'zie i wykorzystać jedną z poniższych technik.

Wariant 1. Aby stworzyć losowy tekst 'Lorem ipsum' sięgamy po polecenie:

=Lorem()
które należy wpisać w pierwszym linii dokumentu i wcisnąć enter. W wyniku otrzymamy trzy paragrafy losowego tekstu.

Rozwiązanie to posiada możliwość parametryzowania:

=Lorem(10) 
utworzy 10 paragrafów z losową ilością zdań

=Lorem(10,3)
utworzy 10 paragrafów i po trzy zdania w każdym paragrafie.

Wariant 2. Jeżeli tekst, z których chcemy pracować ma być w języku polskim sięgamy wtedy po polecenie:

=Rand()
które działa podobnie jak prezentowane powyżej polecenie Lorem. Dostępne więc będą wiarianty:

=Rand(10)
=Rand(10,3)

które odpowiednio definiują ilość paragrafów i zdań w każdym paragrafie.

Technika ta przyda się w jednym z kolejnych wpisów, który wkrótce pojawi się w sekcji Strefa Wiedzy. Strefa Wiedzy prowadzona jest jako rozszerzenie dla kursów VBA organizowanych przez naszą firmę w Krakowie, Warszawie i Wrocławiu.

środa, 16 października 2013

Metoda Find w aplikacji MS Word- Przykład 1

Metoda .Find to jedno z bardziej przydatnych narzędzi nie tylko w Wordzie, ale także w Excelu (o czym wkrótce napiszę kilka postów). Ogólna zasada działania metody jest prosta- Znajdź >> Zaznacz. O wiele częściej sięgamy po to rozwiązanie w konfiguracji Znajdź >> Zamień. Tak czy inaczej w pracy z metodą .Find warto zawsze:

a) skorzystać z rejestratora makr
b) wykorzystać umiejętnie znaki specjalne (Wildcards) dostępne w pracy z tą metodą.

Od czasu do czasu przedstawię proste przykłady pracy z techniką Znajdź >> Zamień. Na początek następujące zadanie:

Dokument składa się z szeregu 12-to cyfrowych liczb umieszczonych w kolejnych paragrafach. Zadanie polega na wstawieniu pojedynczych cudzysłowów na początku i końcu każdego ciągu oraz na umieszczeniu wszystkich wpisów w jednej linii. Poniższy zrzut ekran pokazuje sytuację przed i po. Nieprzypadkowo na zrzucie ekranu dostrzec można również znaki podziału paragrafu, które będą kluczowe w rozwiązaniu problemu.


Podejście A. Teoretycznie możemy wykorzystać pętle i przeszukać cały dokument na okoliczność ciągów znaku uprzednio częściowo dokonawszy zamiany znaku paragrafu na przecinek. Rozwiązanie choć skuteczne to nieefektywne  i nie będzie tu prezentowane.

Podejście B. Wykorzystując dwukrotnie metodę .Find >> .Replace osiągniemy nasz cel. Proszę zwrócić uwagę na parametr .Wildcards ustawiony odmiennie w pierwszej i drugiej części kodu.


Podejście C. Kluczowe w tym wariancie jest zastąpienie symbolu znaku paragrafu. W miejsce '^p' wstawiamy inny odpowiednik nowego paragrafu wyrażony jako '^13', który nie powoduje kolizji z ustawionym naprzemiennie parametrem .Wildcards w powyższym przykładzie. Dzięki temu nasze ostateczne rozwiązanie staje się jeszcze bardziej kompaktowe.

Prowadząc szkolenie z VBA zawsze staram się prezentować rozwiązania optymalne, choć często wychodzę od rozwiązań naturalnych-intuicyjnych by następnie móc zaprezentować ewolucję rozwiązania podobnie jak ma to miejsce powyżej.

czwartek, 10 października 2013

Podręczna paleta kolorów wypełnienia

Wyobraźmy sobie sytuację, w której chcemy ułatwić użytkownikowi nanoszenie kolorów w określonym obszarze arkusza. Odpowiednie kolory mogą oznaczać status danego produktu, zamówienia, tworzyć kolorystyczną informacje o postępie zdarzenia, itp. Ot np. spójrzmy na poniższy układ prostej tabeli wraz z wyświetlonym szybkim menu podręcznym przyspieszającym kolorowanie.


Poniżej w kilku krokach prezentuję technikę tworzenia niniejszego rozwiązania.

Krok 1. Procedura tworząca i wyświetlająca menu podręczne z paletą kolorystyczną. Procedura ta wykorzystuje tradycyjne techniki tworzenia menu oparte o obiekty/kolekcje CommandBar/CommandBars.

Krok 2. Jak łatwo zauważyć w powyższej procedurze tworzone menu jest tymczasowe. Niezbędna jest więc procedura usuwania paska zaraz po tym gdy zostanie wykorzystany.

Krok 3. Wykorzystamy obsługę zdarzenia BeforeRightClick w celu wyświetlenia menu tylko w kolumnie C odpowiedniego arkusza. Co ważne, poniższe rozwiązanie wyświetli nasze nowe menu po kliknięciu prawym klawiszem myszy. Nadal pozostawimy użytkownikowi dostęp do standardowego menu podręcznego o ile wybierze na klawiaturze konfigurację Shift + F10.

I na koniec mała wskazówka- wykorzystana w kroku 1 metoda .ShowPopup posiada dodatkowe, opcjonalne parametry, które umożliwiają wskazanie miejsca, w którym ma zostać wyświetlone nasze menu podręczne.
Tworzenie interakcji i rozwiązań ułatwiających pracę z Excelem (i innymi aplikacjami Office) jest ważną umiejętnością każdego programisty co staram się często podkreślać prowadząc kurs z programowania w VBA.

piątek, 4 października 2013

Przechowywanie wartości zmiennych po zamknięciu pliku

Szukając odpowiedni na pytanie jak przechować zmienne po zamknięciu pliku przychodzi mi do głowy szereg pomysłów. Na początek wymienię kilka z nich- wykorzystując komórkę w arkuszu (tylko Excel), korzystając z właściwości dokumentu, korzystając z kolekcji Variables (tylko Word), korzystając z rejestru komputera (tylko lokalnie, nie przenoszone z plikiem).

Relatywnie ciekawą techniką jest jednak wykorzystanie instrukcji Put (dla zapisu) i Get (dla odczytu) z zapisem do pliku tekstowego. Rozwiązanie to mam kilka dodatkowych zalet:
1.  można szybko i skutecznie przechować wartości tablic, co nie jest możliwe w rozwiązaniach alternatywnych,
2. utworzony plik tekstowy sprawia wrażenie zaszyfrowanego, nie każdy będzie w stanie odczytać jego zawartość.

Skoro są zalety to i zazwyczaj istnieją wady rozwiązania. Otóż i owszem- ograniczona wielkość zmiennej- dla tablicy będzie to niewiele ponad 3000 rekordów.

Jak działa taki mechanizm? Jak wygląda kod zapisu i odczytu?

Wyobraźmy sobie taką oto sytuację, że obszar tabeli Excela A1:E7 chcemy zapisać w postaci zmiennej tablicowej i przesłać w postaci pliku tekstowego do innej osoby.


W celu zapisu posłużymy się takim poniższym przykładowym kodem. Dodatkowe parametry zostały opisane w postaci komentarzy wewnątrz kodu.


Jeżeli operacja powiodła się w domyślnej lokalizacji znajdziemy plik o nazwie "Array.To.File.VBA.bin". Próba otwarcia tego pliku w prostych edytorach tekstu da nam następujący lub podobny efekt:




Plik jest niewielki i jednocześnie sprawia wrażenie jakoby zawartość była zaszyfrowana. Teraz możemy przesłać plik do odbiorcy.

W jaki sposób możemy odczytać nasz plik. Wystarczy uruchomić poniższą procedurę aby wartość naszej tabeli została wprowadzona do arkusza Excel począwszy od aktywnie zaznaczonej komórki. (Dodatkowe uwagi dot. kodu w postaci komentarzy poniżej)


Przydatne linki referencyjne do strony Microsoft MSDN:

Put Statement
Get Statement