poniedziałek, 25 marca 2013

MS Word- liczba słów w dokumencie odpowiadających formatowaniu

Jakiś czas temu pomagałem jednemu z forumowiczów rozwiązać problem zliczania słów, które spełniają określone kryterium formatowania. Makro miało działać dla dużego dokumentu liczącego kilkadziesiąt stron, miało być oczywiście stworzone dla Worda.
Jak to zrobić?? Jeżeli pierwszą myślą jest 'pętla dla każdego słowa' to powiem ok, taka była też pierwsza myśl pytającego. Nie mniej dla 50 stron działało to dość długo, a w dodatku nie przynosiło oczekiwanych rezultatów. Lepszym rozwiązaniem jest wykorzystać owo 'A w VBA' (o czym piszę osobno) czyli sięgnąć po mechanizm 'Szukaj'.
Poniżej gotowy kod dla bieżącego dokumentu liczący słowa pogrubione i (standardowo) podkreślone oraz nie wyróżnione kolorem. Inne opcje wyszukiwania mogą zostać zastosowane przez analogię.

Osobom początkującym zwrócę uwagę na nieskończoną pętlę Do Loop- proszę pamiętać, że taka konstrukcja jest możliwa o ile gdzieś w kodzie, w celu uniknięcia nieskończonego zapętlenia, występuje parametr kończący działanie pętli Exit Do.
01Sub CountWords()
02    Dim rngWords As Range
03    Set rngWords = ActiveDocument.Content
04    
05    Dim boldUnderCount As Long
06 
07Do
08    With rngWords.Find
09        .Highlight = False
10        .Font.Bold = True
11        .Font.Underline = True
12        .Forward = True
13        .Execute
14    End With
15    
16    If rngWords.Find.Found = True Then
17        'opcjonalnie gdy chcemy śledzić efekt
18        rngWords.Select
19        boldUnderCount = boldUnderCount + _
20                   rngWords.ComputeStatistics(wdStatisticWords)
21    Else
22        Exit Do
23    End If
24Loop
25  
26    MsgBox "Znaleziono " & boldUnderCount & " słów."
27End Sub

środa, 20 marca 2013

Funkcja Format

Muszę przyznać, że funkcja Format należy do tych, których nie doceniam. No, może bez przesady, po prostu nie miałem okazji zbyt często sięgać po nią mając na podorędziu zestaw funkcji VBA oraz inne umiejętności programistyczne. Wobec jednak faktu, że funkcja oferuje wiele korzyści związanych z formatowaniem zwracanych wartości poświęcę jej niniejszy wpis skupiając się na wybranych i najbardziej praktycznych przypadkach.

1. Formatowanie daty to najczęstsze skojarzenie z funkcją format. Zobaczmy kilka możliwych konstrukcji i zwracane z ich wykorzystaniem wartości:

01Sub Format_Data()
02 
03    Dim Teraz As Date
04        Teraz = now
05        
06        Debug.Print "dzień tygodnia: " & Format(Teraz, "dddd")
07                '>wtorek
08        Debug.Print "dzień miesiąca: " & Format(Teraz, "mmmm")
09                '>marzec
10        Debug.Print "długa data: " & Format(Teraz, "dddddd")
11        Debug.Print "długa data: " & Format(varMix, "Long date")
12                '>w obu przypadkach: 10 marzec 2013
13    
14End Sub

a ponadto cały zestaw dat krótki, fragmentów godziny, itp. Wszystko oczywiście ukryte w parametrach funkcji odpowiednio umieszczonych w cudzysłowach.

2. Formatowanie liczb. Tu oczywiście do dyspozycji mamy cały zestaw możliwości. Sięgnijmy więc po przykład dla liczby Pi.
01Sub Format_Liczby()
02 
03    Dim liczbaPI As Double
04        liczbaPI = WorksheetFunction.Pi()
05        
06        Debug.Print "format rozszerzony: " & _
07                Format(liczbaPI, "0000.0000")
08                '>0003.1416
09        Debug.Print "procent: " & Format(liczbaPI, "##.##%")
10                '>314.16%
11        Debug.Print "format księgowy: " & _
12                Format(liczbaPI * 10000, "# ###.00")
13                '>31 415,93
14    
15End Sub

3. Przykład przedostatni dotyczy formatowania tekstu.

01Sub Format_Tekst()
02    Dim strTekst As String
03        strTekst = "Projekt VBA Szkolenia VBA"
04        
05        Debug.Print "z wielkich liter: " & Format(strTekst, ">")
06                '>PROJEKT VBA SZKOLENIA VBA
07        Debug.Print "z małych liter: " & Format(strTekst, "<")
08                '>projekt vba szkolenia vba
09                
10End Sub

4. Ostatni zestaw przykładów to dodatkowe możliwości formatowania wartości liczbowych ze względu na znak liczby i opcjonalny wynik zero.
01Sub Format_Ciekawostki()
02 
03    Dim varMix As Variant
04    varMix = -100000
05    Debug.Print "Ciekawostka 1: " & _
06        Format(varMix, "##0 PLN;-##0 PLN")
07        '>-100 PLN
08    varMix = 0
09    Debug.Print "Ciekawostka 2: " & _
10        Format(varMix, "# ##0 PLN;-# ##0 PLN;Zero")
11        '>Zero
12    
13End Sub

No dobrze, dla osób, które dobrnęły do końca 2 ważne informacje- tradycyjnie informacja dobra i zła. Ta dobra jest taka, że konstrukcja parametrów formatowania jest tożsama z tą, którą większość z osób zna z Excela jako niestandardowe formatowanie komórek. A zła informacja jest taka, że funkcja Format zwraca... tekst (String), nawet wtedy gdy formatowaniu poddajemy wartości liczbowe.

czwartek, 14 marca 2013

Obszar komórek Range 3D

Technika pracy z obszarami 3D posiada swoje odniesienie do standardowych rozwiązań znanych z Excela. Po jednoczesnym zaznaczeniu kilku arkuszy wprowadzając wartości do jednego z nich automatycznie tworzymy adekwatne wpisy do tych samych zakresów komórek we wszystkich zaznaczonych arkuszach.

Podobną technikę możemy zastosować korzystając z VBA. Poniższy przykład generuje wpisy we wszystkich 3 arkuszach zaznaczonych poleceniem Select.

1Sub Obszar_3D_Select()
2 
3    'odpowiedni efekty tylko tylko z zaznaczeniem
4    Sheets(Array(1, 2, 3)).Select
5    Range("A1:E1").Select
6    Selection = "A"
7    
8End Sub

Co jednak ważne- powyższa technika wymaga zaznaczenia komórek przed ich wypełnieniem. Poniższy przykład, choć intuicyjnie zgodny z powyższym nie daje identycznego rezultatu.
1Sub Obszar_3D_bez_Select()
2 
3    'nie uzyskamy efektu bez zaznaczenia komórek
4    Sheets(Array(1, 2, 3)).Select
5    Range("A2:E2").Value = 1
6 
7End Sub

Inne adekwatne rozwiązanie prezentuje poniższy przykład wykorzystujący specjalną właściwość obiektu Worksheet.
01Sub Obszar_3D_inaczej()
02 
03    With Worksheets(1).Range("A3:E3")
04        .Value = "ABC"
05        .Interior.Color = vbBlue
06    End With
07 
08    'technika z wykorzystaniem metody FillAcrossSheets
09    Worksheets.FillAcrossSheets Worksheets(1).Range("A3:E3")
10 
11End Sub

piątek, 8 marca 2013

Nie zapomnieć o A w VBA...

Swego czasu trafiłem na obszerny artykuł napisany przez specjalistę od VBA poświęcony roli 'A' w 'VBA'... Niestety nie zapisałem linku do owego artykułu, być może można go odnaleźć w sieci. Niemniej treść owego można by skrócić do kilku prostych zdań, z którymi bardzo się zgadzam.

Nie twórzmy makr wszędzie tam, gdzie istnieją proste rozwiązania dostępne po stronie samej aplikacji Excel (czy innej aplikacji Office). A jeżeli już musimy tworzyć makro, to w pierwszej kolejności wykorzystajmy funkcjonalność gotowych rozwiązań, które znamy z aplikacji Excela.

Jednym z najprostszych i najważniejszych przypadków owego A w VBA jest kwestia wykorzystania funkcji arkuszowych, do których mamy dostęp z pomocą kolekcji WorksheetFunction... i temu tematowi, kwestii wykorzystania instrukcji WorksheetFunction poświęcę wkrótce kilka osobnych wpisów.

piątek, 1 marca 2013

Wybrany wiersz z tablicy Array

Na ostatnim szkoleniu padło pozornie proste pytanie: w jaki sposób pobrać jeden wybrany wiersz tablicy Array i zwrócić go w całości do wskazanego wiersza arkusza Excel?

Oto i rozwiązanie, w którym tworzona jest dwuwymiarowa tabela Array 10x10 (wypełniona następnie kolejnymi wartościami). Następnie korzystając z funkcji arkuszowej Index pobieramy 5 wiersz bazowej tablicy Array (w wyniku czego tworzona jest tablica pośrednia), która trafia do kolejnych komórek arkusza względem bieżącej komórki aktywnej.
01Sub WybranyWierszArray()
02 
03    Dim TBL(10, 10) As Variant
04    Dim i!, j!
05    
06    For i = 1 To 10
07        For j = 1 To 10
08            TBL(i, j) = i * 10000 + j
09        Next j
10    Next i
11 
12    Dim TBLSliced As Variant
13        TBLSliced = WorksheetFunction.Index(TBL, 5, 0)
14    
15    ActiveCell.Resize(1, UBound(TBLSliced, 1)) = TBLSliced
16End Sub

Tytułem wstępu

To nie ma być klasyczny blog choć powstaje w oparciu o klasyczną technologię przeznaczoną dla bloggerów. Taki wybór podyktowany jest z jednej strony wygodą twórcy niniejszej strony- o wiele prościej zarządzać tekstami, łatwo można wykorzystać gadżety stworzone specjalnie dla tego typu rozwiązań.

Z drugiej jednak strony forma tego typu redakcji jest znana, powszechna i akceptowana przez szerokie rzesze współczesnych internautów, w tym przez potencjalnych czytelników tej strony, przyszłych poszukiwaczy rozwiązań, o których informacje będą tu zamieszczane.

A o czym będę pisał? Z niegwarantowaną regularnością o wszystkim, co w jakiś sposób wyda mi się: istotne, pomijane choć ważne, zapomniane a warte przypomnienia, ciekawe lub bardzo oryginalne.
Będę pisał w tematach związanych z tematyką Visual Basic for Application (VBA), głównie VBA dla Excela lecz także VBA dla innych aplikacji pakietu Office. Z pewnością wspomnę także o SQL, C# (C Sharp), LINQ, .NET, COM, DLL, może o XLL, RAD, Excel DNA, itp.

I tak wiem, zgadzam się z większością z Was, chyba wszystko zostało już napisane. Sam często poszukuję rozwiązań w internecie. I najczęściej je tam znajduję. Strona ta ma w dużej mierze wspomagać w procesie edukacji z obszarów VBA wszystkich moich dotychczasowych kursantów, a być może zachęcić innych do uczestnictwa w prowadzonych przeze mnie kursach. Będę starał się w sposób ciekawy przedstawiać najciekawsze przykłady ze szkoleń, wywołane przez uczestników szkoleń, znalezione w sieci, opracowane przeze mnie.