You are on page 1of 499

Spis Treści

SPIS TREŚCI........................................................................................................................................................ 1
CZĘŚĆ I PROJEKTOWANIE BAZY DANYCH .......................................................................................... 21
ROZDZIAŁ 1. CO NOWEGO W ACCESSIE 2000.................................................................................. 22
Nowy interfejs użytkownika .......................................................................................................................... 22
Zmiany w VBE .............................................................................................................................................. 23
Strony dostępu do danych............................................................................................................................. 24
Podarkusze danych....................................................................................................................................... 24
Autokorekta nazw ......................................................................................................................................... 25
ADO jako domyślny system dostępu do danych .......................................................................................... 25
Współpraca online........................................................................................................................................ 25
Access jako interfejs użytkownika dla SQL Server....................................................................................... 26
ROZDZIAŁ 2. PLANOWANIE PROCESU ROZWOJU ......................................................................... 27
Określenie wymagań .................................................................................................................................... 28
Dlaczego faza wymagań jest tak ważna? ................................................................................................. 28
Odnalezienie rzeczywistego problemu..................................................................................................... 28
Śledztwo ................................................................................................................................................... 28
Diagramy procesu..................................................................................................................................... 29
Identyfikacja zakresu projektu ................................................................................................................. 30
Spisywanie wymagań ............................................................................................................................... 30
Architektura.................................................................................................................................................. 31
Planowanie rozwoju ..................................................................................................................................... 31
Strategia dostarczania............................................................................................................................... 32
Styl............................................................................................................................................................ 33
Standardy.................................................................................................................................................. 33
Standardy nazewnictwa ........................................................................................................................ 34
Standardy kodowania ........................................................................................................................... 34
Konstrukcja .................................................................................................................................................. 34
Dziel i rządź: działania w fazie Konstrukcja............................................................................................ 34
Edycje i kompilacje .................................................................................................................................. 35
Szczegółowy projekt ................................................................................................................................ 38
Kontrola projektu ..................................................................................................................................... 39
Tworzenie aplikacji .................................................................................................................................. 39
Kontrola aplikacji ..................................................................................................................................... 39
Testowanie................................................................................................................................................ 39
Testowanie modułu .............................................................................................................................. 39
Testowanie aplikacji............................................................................................................................. 40
Testowanie instalacji i konfiguracji...................................................................................................... 40
Odnajdywanie usterek .............................................................................................................................. 41
Kontrola wersji ......................................................................................................................................... 43
ROZDZIAŁ 3. PROJEKT BAZY DANYCH I NORMALIZACJA ....................................................... 45
Spis treści 2

Relacyjne systemy zarządzania bazami danych (RDBMS)........................................................................... 45


Zasady relacyjne dr Codda ....................................................................................................................... 45
Teoria projektowania relacyjnego ............................................................................................................... 47
Korzyści z używania modelu relacyjnego................................................................................................ 47
Tabele i niepowtarzalność ........................................................................................................................ 48
Klucze obce i domeny .............................................................................................................................. 48
Relacje ...................................................................................................................................................... 49
Relacja jeden-do-jednego ..................................................................................................................... 49
Relacja jeden-do-wielu......................................................................................................................... 49
Relacja wiele-do-wielu......................................................................................................................... 50
Podarkusze danych ........................................................................................................................... 50
Normalizacja danych ................................................................................................................................ 51
Pierwsza postać normalna .................................................................................................................... 51
Druga postać normalna......................................................................................................................... 52
Trzecia postać normalna....................................................................................................................... 52
Korzyści z normalizacji........................................................................................................................ 53
Zasady integralności danych .................................................................................................................... 53
ROZDZIAŁ 4. ZAAWANSOWANE KWERENDY.................................................................................. 54
Kwerendy w Accesie 2000 ............................................................................................................................ 54
Tworzenie zaawansowanych kwerend.......................................................................................................... 55
Użycie kwerendy........................................................................................................................................... 55
Właściwości kwerendy.................................................................................................................................. 56
Siatka QBE ................................................................................................................................................... 56
Panel tabel.................................................................................................................................................... 58
Umieszczanie tabeli lub kwerendy w panelu tabel................................................................................... 58
Tworzenie relacji w panelu tabel.............................................................................................................. 58
Siatka kwerendy............................................................................................................................................ 61
Umieszczanie pól w siatce kwerendy....................................................................................................... 62
Określanie kolejności sortowania, wyświetlania rezultatów oraz wybór kryteriów kwerendy ............... 62
Kwerendy podsumowujące ........................................................................................................................... 62
Funkcja agregująca Policz........................................................................................................................ 63
Funkcja agregująca Średnia...................................................................................................................... 64
Funkcje agregujące Minimum i Maksimum ............................................................................................ 64
Funkcje agregujące Pierwszy i Ostatni .................................................................................................... 65
Funkcje agregujące Odchylenie standardowe i Wariancja....................................................................... 65
Funkcja Wyrażenie................................................................................................................................... 65
Warunek Gdzie......................................................................................................................................... 66
Użycie kwerend krzyżowych ......................................................................................................................... 67
Użycie kwerend parametrycznych ................................................................................................................ 69
Tworzenie parametrów dla kwerendy w siatce QBE ............................................................................... 70
Tworzenie parametrów w kwerendach korzystających z programu ........................................................ 71
Tworzenie kwerend parametrycznych – siatka QBE a program ............................................................. 71
Wykonywanie kwerendy parametrycznej poprzez program ................................................................... 71
Wykonywanie kwerendy poprzez zbiór parametrów ............................................................................... 72
Kwerendy przekazujące ................................................................................................................................ 72
Tworzenie kwerendy przekazującej ......................................................................................................... 73
Kwerendy definiujące dane .......................................................................................................................... 73
Tworzenie nowej tabeli ............................................................................................................................ 74
Modyfikowanie tabeli............................................................................................................................... 74
Tworzenie indeksów................................................................................................................................. 75
Usuwanie tabeli ........................................................................................................................................ 75
Określanie właściwości pól ...................................................................................................................... 75
3

Optymalizowanie kwerend............................................................................................................................ 76
ROZDZIAŁ 5. JET 4.0 – SILNIK BAZ DANYCH MICROSOFT .......................................................... 77
Historia Microsoft Jet .................................................................................................................................. 77
Jet 1.0........................................................................................................................................................ 77
Jet 1.1........................................................................................................................................................ 77
Jet 2.0........................................................................................................................................................ 77
Jet 2.5........................................................................................................................................................ 78
Jet 3.0........................................................................................................................................................ 78
Jet 3.5........................................................................................................................................................ 78
Jet 3.51...................................................................................................................................................... 78
Jet 4.0........................................................................................................................................................ 78
Przyszłe wersje Microsoft Jet................................................................................................................... 79
Praktyczne zastosowanie nowych opcji silnika Jet 4.0 ............................................................................... 79
Wbudowany dostawca baz danych OLE.................................................................................................. 79
Blokowanie na poziomie rekordu............................................................................................................. 79
Pełna obsługa Unicode ............................................................................................................................. 79
Czym jest Unicode?.............................................................................................................................. 79
Obsługa Unicode 1.1 w silniku Jet 4.0 ..................................................................................................... 80
Sortowanie kompatybilne z NT............................................................................................................ 81
Typy danych Jet........................................................................................................................................ 81
Ulepszenia opcji Autonumerowanie......................................................................................................... 82
Przeszukiwalne pola Memo...................................................................................................................... 83
Kontrola połączeń i zamknięcie bierne .................................................................................................... 83
Nowa składnia SQL.................................................................................................................................. 84
Zabezpieczenia ..................................................................................................................................... 84
Definiowanie widoków i procedur ....................................................................................................... 85
Wywoływanie parametrów................................................................................................................... 85
Transakcje............................................................................................................................................. 85
Tworzenie tabel DDL ........................................................................................................................... 86
CZĘŚĆ II DOSTĘP DO DANYCH .................................................................................................................. 88
ROZDZIAŁ 6. WPROWADZENIE DO OBIEKTÓW DANYCH ACTIVEX ...................................... 89
Historia dostępu do danych.......................................................................................................................... 89
Firmowe interfejsy API ............................................................................................................................ 89
Open Database Connectivity (ODBC) ..................................................................................................... 89
Microsoft Jet/Obiekty Data Access (DAO).............................................................................................. 90
Zdalne obiekty danych (RDO) i ODBCDirect ......................................................................................... 90
Universal Data Access ................................................................................................................................. 90
Obiekty ActiveX Data (ADO) ....................................................................................................................... 91
ADO 1.0 ................................................................................................................................................... 91
ADO 1.5 ................................................................................................................................................... 91
ADO 2.0 ................................................................................................................................................... 91
ADO 2.1 ................................................................................................................................................... 91
Model obiektowy ADO ................................................................................................................................. 92
Obiekt Connection.................................................................................................................................... 93
Otwarcie połączenia w Accessie 2000 ................................................................................................. 93
Wykonywanie wyrażeń SQL w obiekcie Connection.............................................................................. 94
Obiekty ADO: Recordset .............................................................................................................................. 94
Użycie Recordset z obiektami Command i Parameter ............................................................................. 96
Wykonywanie kwerendy funkcjonalnej poprzez obiekt Command........................................................ 98
Obiekty Field i Property ........................................................................................................................... 99
Obiekty ADO: Error ................................................................................................................................... 100
Spis treści 4

Przejście z obiektów DAO do ADO ............................................................................................................ 101


Konwersja z poprzednich wersji Accessa .............................................................................................. 101
Czy warto przejść na obiekty ADO? ...................................................................................................... 101
Schemat konwersji ............................................................................................................................. 101
Kiedy nie dokonywać konwersji? ...................................................................................................... 102
Porównanie modelu obiektowego ADO i DAO ......................................................................................... 102
ROZDZIAŁ 7. ZAAWANSOWANE ADO............................................................................................... 104
Użycie dostawcy OLE DB dla Jet w Accessie 2000 ................................................................................... 104
CurrentProject.Connection ..................................................................................................................... 106
Rola Microsoft Data Links w podłączaniu się do bazy danych ............................................................ 106
Zarządzanie plikami UDL .................................................................................................................. 108
Programowe zarządzanie plikami UDL ............................................................................................. 108
Uzyskanie poprzez ADO dostępu do danych w bazach nierelacyjnych ..................................................... 110
Lista użytkowników Jet.......................................................................................................................... 110
Tworzone zestawy rekordów.................................................................................................................. 110
Kształtowanie danych............................................................................................................................. 111
Zaawansowana obróbka danych przy użyciu ADO.................................................................................... 113
Modyfikowanie danych w zestawie rekordów ....................................................................................... 113
Dodawanie rekordu ............................................................................................................................ 114
Trwałe zestawy rekordów....................................................................................................................... 115
Definiowanie danych przy użyciu ADOX ................................................................................................... 117
Obiekt Catalog........................................................................................................................................ 117
Tworzenie bazy danych.......................................................................................................................... 117
Tworzenie tabel i pól .............................................................................................................................. 118
Tworzenie dołączonej tabeli............................................................................................................... 118
Ustawianie właściwości pola.............................................................................................................. 119
Tworzenie indeksu ................................................................................................................................. 119
Tworzenie relacji w ADOX.................................................................................................................... 120
Tworzenie kwerend w ADOX................................................................................................................ 121
Tworzenie widoku .............................................................................................................................. 121
Tworzenie procedury.......................................................................................................................... 122
Modyfikowanie wyrażenia SQL kwerendy........................................................................................ 122
CZĘŚĆ III INTERFEJS UŻYTKOWNIKA ................................................................................................ 124
ROZDZIAŁ 8. PROJEKTOWANIE FORMULARZA........................................................................... 125
Właściwości formularza ............................................................................................................................. 125
Zakładka Dane........................................................................................................................................ 126
Źródło rekordów................................................................................................................................. 126
Edycja dozwolona .............................................................................................................................. 126
Usuwanie dozwolone ......................................................................................................................... 126
Dodawanie dozwolone ....................................................................................................................... 126
Wprowadzanie danych ....................................................................................................................... 126
Filtry dozwolone, Filtr, Uporządkuj według ...................................................................................... 126
Zakładka Format..................................................................................................................................... 126
Widok domyślny ................................................................................................................................ 126
Dostępne widoki................................................................................................................................. 127
Paski przewijania................................................................................................................................ 127
Selektory rekordów ............................................................................................................................ 127
Przyciski nawigacyjne ........................................................................................................................ 127
Styl obramowania............................................................................................................................... 127
Pole menu sterowania......................................................................................................................... 127
Przyciski Min Max ............................................................................................................................. 127
5

Przycisk Zamknij................................................................................................................................ 127


Zakładka Inne ......................................................................................................................................... 128
Modalny.............................................................................................................................................. 128
Podręczny ........................................................................................................................................... 128
Pasek menu, pasek narzędzi ............................................................................................................... 128
Menu podręczne ................................................................................................................................. 128
Pasek menu podręcznego ................................................................................................................... 128
Metka.................................................................................................................................................. 128
Ma moduł ........................................................................................................................................... 128
Zezwolenie na zmiany projektu.......................................................................................................... 129
Użyteczne właściwości nie znajdujące się na arkuszu właściwości ..................................................... 129
Argumenty otwarcia (OpenArgs) ....................................................................................................... 129
Właściwości użytkownika .................................................................................................................. 129
Zdarzenia ................................................................................................................................................ 130
Otwarcie formularza........................................................................................................................... 130
Zamknięcie formularza....................................................................................................................... 131
Zmiana rozmiaru formularza.............................................................................................................. 131
Maksymalizowanie formularza .......................................................................................................... 131
Przywrócenie zminimalizowanego formularza .................................................................................. 131
Formanty formularza w Accessie ............................................................................................................... 131
Formant Lista rozwijana......................................................................................................................... 131
Użycie zdarzenia Not In List.............................................................................................................. 131
Tworzenie automatycznie rozwijającej się listy rozwijanej............................................................... 132
Tworzenie własnych list rozwijanych ................................................................................................ 132
Pobieranie więcej niż jednej wartości z pola listy i listy rozwijanej.................................................. 133
Pole listy ................................................................................................................................................. 133
Pole listy wielokrotnego wyboru............................................................................................................ 133
Ustawienia właściwości ..................................................................................................................... 134
Podformularze ........................................................................................................................................ 134
Dodawanie podformularzy ................................................................................................................. 134
Tworzenie odniesienia dla podformularza ......................................................................................... 135
Wbudowany formant Karta .................................................................................................................... 135
Grupa opcji ............................................................................................................................................. 135
Podręczne menu...................................................................................................................................... 136
Hiperłącza............................................................................................................................................... 136
ROZDZIAŁ 9. ROZBUDOWA FORMULARZY PRZY UŻYCIU FORMANTÓW ACTIVEX....... 137
Jak korzystać z formantów ActiveX ............................................................................................................ 137
Typy formantów ActiveX....................................................................................................................... 137
Gdzie znaleźć formanty ActiveX?.......................................................................................................... 138
Czy formanty ActiveX są bezpieczne?................................................................................................... 138
Czy mogę korzystać z formantów ActiveX i rozpowszechniać je w moich aplikacjach? .................... 138
Użycie formantów ActiveX ......................................................................................................................... 139
Instalowanie formantu ActiveX ............................................................................................................. 139
Rejestrowanie formantów ActiveX ........................................................................................................ 139
Dodawanie formantu ActiveX do formularza ........................................................................................ 139
Ustawianie właściwości formantu ActiveX ........................................................................................... 140
Pisanie kodu umożliwiającego wykonywanie metod i reagowanie na zdarzenia ................................. 141
21 formantów ActiveX ................................................................................................................................ 141
Formant Animation ................................................................................................................................ 142
Formant Calendar ................................................................................................................................... 143
Formant Common Dialog....................................................................................................................... 143
Formant DateTimePicker ....................................................................................................................... 144
Spis treści 6

Formant FlatScrollBar ............................................................................................................................ 145


Formant ImageCombo............................................................................................................................ 145
Formant ImageList ................................................................................................................................. 146
Formant ListView................................................................................................................................... 147
Formant MAPISession ........................................................................................................................... 149
Formant MAPIMessages ........................................................................................................................ 149
Formant MonthView .............................................................................................................................. 150
Formant ProgressBar .............................................................................................................................. 151
Formant RichText................................................................................................................................... 152
Formant Slider ........................................................................................................................................ 152
Formant StatusBar .................................................................................................................................. 153
Formant SysInfo ..................................................................................................................................... 154
Formant TabStrip ................................................................................................................................... 155
Formant Toolbar..................................................................................................................................... 155
Formant TreeView.................................................................................................................................. 156
Formant UpDown................................................................................................................................... 157
Formant WebBrowser ............................................................................................................................ 158
Dystrybucja formantów ActiveX................................................................................................................. 159
ROZDZIAŁ 10. TWORZENIE RAPORTÓW......................................................................................... 160
Czym są raporty?........................................................................................................................................ 160
Struktura raportów w Accessie................................................................................................................... 161
Tworzenie prostych raportów przy użyciu kreatora.................................................................................. 161
Dostosowywanie raportów ......................................................................................................................... 163
Zmiana źródła rekordów w raporcie....................................................................................................... 163
Zmiana struktury grupowania w raporcie............................................................................................... 164
Umieszczenie grupowania w raporcie.................................................................................................... 165
Użycie funkcji w raporcie ...................................................................................................................... 166
Użycie funkcji obliczeniowych .......................................................................................................... 166
Użycie Funkcji Immediate IF............................................................................................................. 166
Użycie własnych funkcji w module raportu....................................................................................... 167
Użycie własnych funkcji w osobnym module.................................................................................... 167
Użycie konkatenacji ........................................................................................................................... 168
Praca z podraportami ................................................................................................................................ 169
Tworzenie prostego podraportu.............................................................................................................. 170
Tworzenie prostych etykiet adresowych ................................................................................................ 171
Publikowanie raportu................................................................................................................................. 172
Metody publikowania raportów ............................................................................................................. 172
Użycie wbudowanych metod Accessa do eksportowania raportów................................................... 173
Użycie łączy pakietu Office do publikowania raportów .................................................................... 174
Problemy związane z publikacją ........................................................................................................ 174
Użycie poczty elektronicznej do publikowania raportów .................................................................. 174
Modyfikowanie raportu podczas jego działania ....................................................................................... 174
Filtrowanie i sortowanie ......................................................................................................................... 174
Trzymaj grupę razem.......................................................................................................................... 175
HasData .............................................................................................................................................. 175
Zdarzenia raportu (podczas jego działania)............................................................................................ 175
Przy otwarciu...................................................................................................................................... 175
Przy aktywowaniu, przy dezaktywowaniu ......................................................................................... 175
Przy braku danych .............................................................................................................................. 176
Przy błędzie ........................................................................................................................................ 176
Przy stronie......................................................................................................................................... 176
Przy zamknięciu ................................................................................................................................. 176
7

Właściwość Sekcja ................................................................................................................................. 176


Nazwa ................................................................................................................................................. 176
Wysokość ........................................................................................................................................... 177
Widoczny............................................................................................................................................ 177
Właściwości sekcji związane z procesem projektowania ..................................................................... 177
Można powiększać, można zmniejszać.............................................................................................. 177
Nowy wiersz lub kolumna.................................................................................................................. 177
Powtórz sekcję.................................................................................................................................... 178
Właściwości sekcji (podczas działania raportu)..................................................................................... 178
Wymuszaj nową stronę....................................................................................................................... 178
Trzymaj razem.................................................................................................................................... 178
PrzenieśUkład, NastępnyRekord i DrukujSekcję............................................................................... 178
LiczbaFormatowań ............................................................................................................................. 179
LiczbaDrukowań ................................................................................................................................ 179
ByłKontynuowany, BędzieKontynuowany........................................................................................ 179
Programowe tworzenie raportów............................................................................................................... 179
Tworzenie źródła rekordów.................................................................................................................... 179
Tworzenie obiektu Raport ...................................................................................................................... 180
Tworzenie sekcji..................................................................................................................................... 182
Wskazówki .................................................................................................................................................. 182
Tworzenie grupowania dwutygodniowego ............................................................................................ 182
Ukryj powtarzające się dane................................................................................................................... 182
Alfabetyczne grupowanie danych .......................................................................................................... 182
Tworzenie numerowanych list ............................................................................................................... 183
Tworzenie pustych linii co n znaków..................................................................................................... 183
Zerowanie numeru strony dla nowych grup........................................................................................... 184
Rysowanie pionowych linii .................................................................................................................... 184
Przesuwanie numerów parzystych i nieparzystych stron ....................................................................... 184
Identyfikacja użytkownika drukującego raport ...................................................................................... 184
Wyrównanie stron do oprawy ................................................................................................................ 185
Obliczanie podsumowań strony ............................................................................................................. 185
Precyzyjne przesuwanie formantów....................................................................................................... 185
CZĘŚĆ IV TAJNIKI VBA ............................................................................................................................. 187
ROZDZIAŁ 11. TWORZENIE OBIEKTÓW PRZY UŻYCIU MODUŁÓW KLAS.......................... 188
Korzyści z używania obiektów .................................................................................................................... 189
Ukrywanie złożoności ............................................................................................................................ 189
Użycie technologii Microsoft IntelliSense ............................................................................................. 189
Organizowanie kodu............................................................................................................................... 190
Dopuszczenie przeglądania obiektów w Object Browser ...................................................................... 190
Tworzenie wielu egzemplarzy obiektów................................................................................................ 190
Tworzenie kodu łatwego do aktualizacji i utrzymania........................................................................... 190
Ograniczenie dostępu do kodu ............................................................................................................... 190
Tworzenie przenośnego kodu................................................................................................................. 191
Przegląd obiektów, właściwości i metod .................................................................................................... 191
Tworzenie klas ............................................................................................................................................ 191
Wstawianie modułu klasowego.............................................................................................................. 191
Tworzenie właściwości ............................................................................................................................... 192
Użycie zmiennych publicznych.............................................................................................................. 192
Użycie procedur właściwości ................................................................................................................. 192
Tworzenie w module zmiennych prywatnych........................................................................................ 193
Property Let ........................................................................................................................................ 193
Property Get ....................................................................................................................................... 193
Spis treści 8

Property Set ........................................................................................................................................ 194


Zmienna publiczna czy procedury właściwości ..................................................................................... 194
Tworzenie wyliczeniowych typów danych ............................................................................................ 194
Tworzenie metod......................................................................................................................................... 196
Użycie metod.......................................................................................................................................... 196
Tworzenie zdarzeń ...................................................................................................................................... 196
Użycie zdarzeń ....................................................................................................................................... 197
Uruchamianie zdarzeń „Przy inicjacji” i „Przy zakończeniu” .............................................................. 198
Użycie obiektów.......................................................................................................................................... 198
Tworzenie zmiennej obiektu .................................................................................................................. 198
Przypisywanie zmiennej obiektu do obiektu.......................................................................................... 198
Użycie obiektu........................................................................................................................................ 199
Zwalnianie obiektu ................................................................................................................................. 199
Tworzenie wielu egzemplarzy obiektów ..................................................................................................... 199
Przegląd innych obiektów........................................................................................................................... 200
Obiekt TextFile....................................................................................................................................... 200
Obiekt Timer .......................................................................................................................................... 200
Obiekt Sound .......................................................................................................................................... 201
Obiekt Letter........................................................................................................................................... 202
Obiekt Outlook ....................................................................................................................................... 203
Implementacja obiektu obsługi błędów ...................................................................................................... 204
Użycie obiektów w połączeniu z kolekcjami VBA...................................................................................... 204
Tworzenie kolekcji VBA........................................................................................................................ 205
Właściwości i metody kolekcji VBA ..................................................................................................... 205
Dodawanie obiektów do kolekcji ....................................................................................................... 205
Odnoszenie się do określonych obiektów .......................................................................................... 206
Tworzenie pętli po obiektach kolekcji ............................................................................................... 206
Usuwanie pojedynczych obiektów ..................................................................................................... 206
Usuwanie wszystkich obiektów ......................................................................................................... 206
Zwalnianie zmiennej obiektu ............................................................................................................. 207
ROZDZIAŁ 12. USUWANIE BŁĘDÓW W APLIKACJACH ACCESSA........................................... 208
Usuwanie błędów logicznych ..................................................................................................................... 208
Praca z Visual Basic Development Environment (IDE)............................................................................. 209
Project Explorer...................................................................................................................................... 209
Okno Code.............................................................................................................................................. 209
Okno Properties ...................................................................................................................................... 210
Okno Immediate ..................................................................................................................................... 210
Okno Locals ........................................................................................................................................... 210
Okno Watch............................................................................................................................................ 210
Object Browser....................................................................................................................................... 211
Okno Call Stack...................................................................................................................................... 211
Obiekt Debug.............................................................................................................................................. 211
Debug.Print............................................................................................................................................. 211
Debug.Assert .......................................................................................................................................... 212
Użycie okna Immediate............................................................................................................................... 212
Podglądanie zmiennych.......................................................................................................................... 212
Zmiana wartości zmiennych................................................................................................................... 212
Wyświetlanie wartości funkcji wbudowanych....................................................................................... 213
Uruchamianie funkcji własnych ............................................................................................................. 213
Uruchamianie własnych procedur .......................................................................................................... 213
Wskazówki pomocne w korzystaniu z okna Immediate ........................................................................ 213
Uruchamianie instrukcji w oknie Immediate ..................................................................................... 213
9

Poruszanie się po oknie Immediate .................................................................................................... 213


Usuwanie kodu w oknie Immediate ................................................................................................... 213
Użycie programu uruchomieniowego......................................................................................................... 213
Ustawianie punktów zatrzymania........................................................................................................... 214
Przechodzenie przez kod ........................................................................................................................ 214
Krokowe wykonywanie kodu............................................................................................................. 214
Wykonywanie procedur...................................................................................................................... 214
Wykonywanie kodu do końca procedury ........................................................................................... 214
Wykonanie do pozycji kursora........................................................................................................... 215
Wybór kolejnej instrukcji ................................................................................................................... 215
Kontynuacja wykonywania kodu ....................................................................................................... 215
Ponowne uruchamianie kodu ............................................................................................................. 215
Podglądanie wartości zmiennych ........................................................................................................... 215
Użycie podczas usuwania błędów technologii Microsoft IntelliSense ................................................. 215
Użycie okna Locals ................................................................................................................................ 216
Użycie okna Watch................................................................................................................................. 216
Użycie okna Call Stack .......................................................................................................................... 216
Użycie kompilacji warunkowej................................................................................................................... 217
Pisanie solidnego kodu ........................................................................................................................... 217
Deklaruj zmienne w osobnych liniach programu............................................................................... 217
Deklaruj zmienne w jak najwęższym zakresie................................................................................... 218
Używaj określonych typów danych.................................................................................................... 218
Niszcz zmienne obiektów................................................................................................................... 218
Używaj słowa kluczowego TypeOf.................................................................................................... 218
Używaj Me zamiast Screen.ActiveForm i Screen.ActiveControl ...................................................... 218
Używaj narzędzia do obsługi błędów................................................................................................. 218
Używaj Option Explicit...................................................................................................................... 218
Numeracja od 0 czy od 1? .................................................................................................................. 218
Natychmiast naprawiaj błędy ............................................................................................................. 218
Używaj komentarzy............................................................................................................................ 218
Używaj znaku kontynuacji wiersza .................................................................................................... 219
Używaj krótkich procedur .................................................................................................................. 219
Używaj standaryzowanych konwencji nazewnictwa ......................................................................... 219
Nigdy nie używaj Stop ....................................................................................................................... 219
Nie usuwaj błędów przy użyciu okien komunikatu ........................................................................... 219
Testowanie aplikacji................................................................................................................................... 220
Ćwiczenie technik usuwania błędów .......................................................................................................... 220
ROZDZIAŁ 13. PROFESJONALNA OBSŁUGA BŁĘDÓW ................................................................ 221
Usuwanie błędów składni ........................................................................................................................... 221
Usuwanie błędów logicznych ..................................................................................................................... 223
Usuwanie błędów wykrytych w trakcie użytkowania ................................................................................ 223
Proste narzędzie do obsługi błędów ....................................................................................................... 223
On Error GoTo ErrorHandler ............................................................................................................. 223
ExitHere.............................................................................................................................................. 223
ErrorHandler....................................................................................................................................... 224
Resume ExitHere................................................................................................................................ 224
Przebieg programu z narzędziem do obsługi błędów............................................................................. 224
Obiekt Err ............................................................................................................................................... 225
Err.Clear ............................................................................................................................................. 225
Err.Raise ............................................................................................................................................. 225
Reagowanie na błędy.............................................................................................................................. 226
Instrukcje Resume .................................................................................................................................. 227
Spis treści 10

Resume ............................................................................................................................................... 227


Resume Next ...................................................................................................................................... 227
Uzyskiwanie dodatkowych informacji o błędzie ................................................................................... 227
Zaawansowane narzędzie do obsługi błędów......................................................................................... 228
Moduł klasowy Error (Obiekt) ............................................................................................................... 229
Właściwości obiektu cError ............................................................................................................... 229
Metody obiektu cError ....................................................................................................................... 230
Przeglądanie obiektu cError w Object Browser ................................................................................. 231
Przetwarzanie błędu............................................................................................................................ 231
Doświadczenie użytkownika końcowego........................................................................................... 232
Identyfikowanie problemów sprzętowych ......................................................................................... 234
Sporządzanie raportów o błędach....................................................................................................... 234
Opcje obiektu cError .......................................................................................................................... 235
Odwołania do interfejsu API systemu Windows ............................................................................... 236
Błędy w różnych aplikacjach ...................................................................................................................... 237
Obsługa błędów w procedurach zagnieżdżonych...................................................................................... 237
Zaawansowane zagadnienia związane z błędami ..................................................................................... 237
Procedury zdarzeń związane z błędami.................................................................................................. 237
On Error GoTo 0 ................................................................................................................................ 238
On Error Resume Next ....................................................................................................................... 238
Metoda AccessError ........................................................................................................................... 238
Inne funkcje związane z błędami ........................................................................................................... 238
Ustawienie opcji wyłapujących błędy .................................................................................................... 238
ROZDZIAŁ 14. OPTYMALIZACJA APLIKACJI ................................................................................ 240
Ulepszanie podstaw: optymalizacja sprzętu i systemu Windows ............................................................... 241
Instalowanie aplikacji w celu uzyskania optymalnej wydajności.............................................................. 242
Optymalizacja silnika bazy danych Jet ...................................................................................................... 242
Bezpieczne modyfikowanie ustawień silnika Jet ................................................................................... 246
Narzędzia służące do pomiaru wydajności ............................................................................................... 247
Spojrzenie za kulisy .................................................................................................................................... 248
Optymalizacja bazy danych od podstaw..................................................................................................... 249
Projektowanie tabel w celu osiągnięcia poprawy wydajności .............................................................. 249
Normalizacja danych w celu osiągnięcia poprawy wydajności ............................................................ 249
Tworzenie indeksów w celu przyspieszenia pracy kwerend................................................................. 250
Wcześniejsze tworzenie relacji jako sposób na poprawę wydajności................................................... 250
Poprawa wydajności kwerend.................................................................................................................... 250
Wybór typu zestawu wyników zapewniającego optymalną wydajność................................................ 252
Zwiększenie szybkości kwerend .................................................................................................................. 253
Przyspieszenie funkcjonowania formularzy .............................................................................................. 255
Zacznijmy od początku........................................................................................................................... 255
Szybsze pobieranie rysunków ................................................................................................................ 255
Podstawowy, szybki formularz .............................................................................................................. 256
Szybsze drukowanie raportów................................................................................................................ 258
Pisanie szybkiego kodu............................................................................................................................... 258
Użycie pamięci przez kod ...................................................................................................................... 259
Praca z modułami ................................................................................................................................... 259
Kompilowanie kodu ............................................................................................................................... 259
Dekompilacja.......................................................................................................................................... 259
Tworzenie pliku MDE............................................................................................................................ 260
Użycie Option Explicit ........................................................................................................................... 260
Precyzyjne wybieranie rozmiaru zmiennych.......................................................................................... 260
Oszczędzanie przestrzeni stosu przy użyciu zmiennych typu string..................................................... 260
11

Dokładne określanie typu obiektów ....................................................................................................... 260


Umieszczenie kodu we wnętrzu procedury zamiast odwoływania się do innych funkcji .................... 261
Zmiana True i False................................................................................................................................ 261
Użycie Len() zamiast pustego ciągu....................................................................................................... 261
Użycie True i False zamiast zera............................................................................................................ 261
Szybkie odwołania do obiektów............................................................................................................. 261
Użycie szybkich tablic............................................................................................................................ 262
Używaj stałych, gdy jest to tylko możliwe............................................................................................. 262
Właściwe użycie zakładek (Bookmarks)................................................................................................ 262
Zamykaj i niszcz..................................................................................................................................... 263
Używaj SQL zamiast DAO .................................................................................................................... 263
Użycie indeksowania kolekcji................................................................................................................ 263
Tworzenie szybszych pętli ..................................................................................................................... 263
Usuń z kodu IIF() ................................................................................................................................... 264
Porządkowanie Select Case.................................................................................................................... 264
Używaj Execute zamiast RunSQL ......................................................................................................... 264
Używaj A2KU_Timer ............................................................................................................................ 264
Testuj wydajność transakcji ................................................................................................................... 264
Kontroluj odświeżanie............................................................................................................................ 264
Używaj wczesnego wiązania i zwracaj uwagę na odniesienia ActiveX ............................................... 265
Przejście do architektury klient-serwer .................................................................................................. 265
Chleba i igrzysk...................................................................................................................................... 265
CZĘŚĆ V ACCESS I ARCHITEKTURA KLIENT-SERWER ................................................................. 266
ROZDZIAŁ 15. WPROWADZENIE DO PROJEKTÓW PROGRAMU MICROSOFT ACCESS
ORAZ NARZĘDZI WIZUALNYCH ......................................................................................................... 267
Wprowadzenie do projektów programu Microsoft Access......................................................................... 267
Wady i zalety ADP................................................................................................................................. 267
Użycie ADP ................................................................................................................................................ 268
Tworzenie ADP ...................................................................................................................................... 268
Nowe okno bazy danych ........................................................................................................................ 269
Praca z ADP i istniejącymi bazami danych serwera SQL ......................................................................... 270
Praca z tabelami...................................................................................................................................... 270
Widoki w serwerze SQL ........................................................................................................................ 271
Procedury przechowywane..................................................................................................................... 272
Diagramy bazy danych ........................................................................................................................... 272
Formularze, strony, raporty i moduły..................................................................................................... 273
Zarządzanie serwerem SQL poprzez ADP............................................................................................. 273
Składowanie i odtwarzanie................................................................................................................. 273
Replikacja serwera SQL ..................................................................................................................... 274
Bezpieczeństwo .................................................................................................................................. 274
Powtórne przyłączenie do bazy serwera SQL ........................................................................................ 275
Tworzenie projektu opartego na nowej bazie danych ............................................................................... 276
Tworzenie tabel .......................................................................................................................................... 276
Ustawienie właściwości tabeli i indeksów ......................................................................................... 277
Tworzenie zależności na diagramie bazy danych .................................................................................. 277
Tworzenie kaskad poprzez wyzwalacze................................................................................................. 278
Tworzenie widoków ............................................................................................................................... 278
Tworzenie procedur przechowywanych................................................................................................. 279
Tworzenie aplikacji w Accessie ............................................................................................................. 279
Tworzenie plików ADE...................................................................................................................... 279
Zakończenie: przenoszenie bazy danych Access 97 na serwer SQL i do pliku ADP....................... 280
Spis treści 12

ROZDZIAŁ 16. TWORZENIE INTERFEJSU UŻYTKOWNIKA DLA MICROSOFT SQL SERVER


........................................................................................................................................................................ 281
Architektura klient-serwer: OLE DB kontra ODBC .................................................................................. 281
Tworzenie połączenia z serwerem SQL...................................................................................................... 281
Tworzenie źródła danych ODBC (DSN)................................................................................................ 282
Łączenie tabel......................................................................................................................................... 282
Wady tabel połączonych..................................................................................................................... 283
Połączenie najlepszych metod: wypełnianie tabel podczas startu aplikacji...................................... 283
Procedury przechowywane i kwerendy przekazujące ............................................................................... 284
Tworzenie raportów opartych na procedurach przechowywanych poprzez zapytania przekazujące .... 284
Raportowanie z serwera SQL w Accessie .................................................................................................. 286
Zaawansowane możliwości: przekazywanie parametrów do procedury przechowywanej w czasie
działania programu ................................................................................................................................. 286
Dodatkowe filtrowanie danych raportu .................................................................................................. 287
Formularze w aplikacji............................................................................................................................... 288
Formularze związane.............................................................................................................................. 288
Formularze niezwiązane......................................................................................................................... 289
Zaawansowane właściwości: dostawca OLE DB dla serwera SQL .......................................................... 290
Następny zestaw wyników ..................................................................................................................... 290
Wykonywanie poleceń z parametrami ........................................................................................................ 291
Długa droga ............................................................................................................................................ 291
Użycie metody CreateParameters........................................................................................................... 292
Użycie Refresh ....................................................................................................................................... 292
Obsługa zwracanych wartości ................................................................................................................ 293
Wykonanie procedury bez obiektu Command ....................................................................................... 294
Użycie klasy Connection............................................................................................................................. 294
Użycie klasy Connection w aplikacji ..................................................................................................... 295
ROZDZIAŁ 17. INTERFEJS ACCESSA 2000 DO ORACLE'A .......................................................... 296
Dostęp do danych Oracle'a przez Accessa................................................................................................. 296
Tabele połączone .................................................................................................................................... 297
Tworzenie ciągu połączenia ODBC ................................................................................................... 297
Tworzenia nazwy źródła danych ........................................................................................................ 297
Koszt połączenia z Oracle'em............................................................................................................. 298
Kwerendy przekazujące (SPT) ............................................................................................................... 298
Określanie właściwości kwerend przekazujących.............................................................................. 299
Składnia kwerend przekazujących ..................................................................................................... 299
Wielkość liter...................................................................................................................................... 299
Wyrażenie Select ................................................................................................................................ 300
Klauzula WHERE .............................................................................................................................. 300
Definiowanie zależności..................................................................................................................... 300
Użycie znaków specjalnych ................................................................................................................... 300
Użycie Null i Not Null ....................................................................................................................... 300
Tworzenie wyrażeń Insert .................................................................................................................. 301
Tworzenie wyrażeń Update................................................................................................................ 301
Użycie Group By/Having ................................................................................................................... 301
Funkcje w Oracle'u i Accessie.................................................................................................................... 301
Ciągi ....................................................................................................................................................... 302
Łączenie.............................................................................................................................................. 302
Initcap, Lower, Upper......................................................................................................................... 302
Instr..................................................................................................................................................... 303
LTrim/RTrim...................................................................................................................................... 303
Soundex .............................................................................................................................................. 304
13

Substr.................................................................................................................................................. 304
Decode................................................................................................................................................ 305
Obliczenia w Oracle'u ............................................................................................................................ 305
Ceil()................................................................................................................................................... 305
Floor()................................................................................................................................................. 305
Nvl() ................................................................................................................................................... 306
Round()............................................................................................................................................... 306
Sign() .................................................................................................................................................. 306
Trunc()................................................................................................................................................ 306
Greatest/Least ..................................................................................................................................... 306
Obliczenia na datach............................................................................................................................... 307
Arytmetyka ......................................................................................................................................... 307
Sysdate................................................................................................................................................ 307
Add_Months ....................................................................................................................................... 307
Months_Between................................................................................................................................ 307
Next_Day() ......................................................................................................................................... 308
To_Date() ........................................................................................................................................... 308
Problem roku 2000 ............................................................................................................................. 308
Poznajemy widoki i procedury przechowywane........................................................................................ 309
Tworzenie widoków ............................................................................................................................... 309
Połączenie z Oracle'em poprzez ADO ................................................................................................... 310
Parametry............................................................................................................................................ 311
Tworzenie procedur przechowywanych................................................................................................. 312
Uruchamianie procedury ........................................................................................................................ 313
Tworzenie niezwiązanego interfejsu do Oracle'a....................................................................................... 313
Tworzenie niezwiązanego interfejsu ...................................................................................................... 314
Tworzenie zmiennych globalnych...................................................................................................... 314
Ładowanie danych i inicjalizacja formularza..................................................................................... 315
Programowanie przycisków sterujących ............................................................................................ 315
Zmiana danych Oracle'a przy użyciu formularza............................................................................... 317
Wstawienie danych do Oracle'a przy użyciu formularza ................................................................... 318
Zapisywanie danych do Oracle'a przy użyciu formularza.................................................................. 318
Usuwanie danych przy użyciu formularza ......................................................................................... 319
Zamykanie połączenia z Oracle'em.................................................................................................... 319
CZĘŚĆ VI WSPÓŁOPERATYWNOŚĆ ....................................................................................................... 321
ROZDZIAŁ 18. UŻYCIE AUTOMATYZACJI ACTIVEX ................................................................... 322
Co to jest automatyzacja ActiveX ............................................................................................................... 322
Dlaczego używamy automatyzacji.............................................................................................................. 322
Różnice między serwerem automatyzacji a klientem automatyzacji ......................................................... 323
Określanie zasobów wymaganych przez automatyzację ........................................................................... 323
Wielka trójka .............................................................................................................................................. 323
Tworzenie i ustanowienie odwołania do innej aplikacji ............................................................................ 323
Ustanawianie odwołania do innej aplikacji............................................................................................ 323
Przegląd obiektów, właściwości i metod................................................................................................ 324
Poznajemy strukturę obiektów ............................................................................................................... 324
Użycie narzędzia Object Browser .......................................................................................................... 324
Tworzenie zmiennej obiektowej............................................................................................................. 326
Odwołanie do pracującej aplikacji ......................................................................................................... 326
Przypisywanie zmiennej obiektowej do aplikacji ...................................................................................... 326
Tworzenie egzemplarza aplikacji ............................................................................................................... 327
Jednoczesne użycie funkcji GetObject i New ........................................................................................ 327
Użycie wczesnego i późnego łączenia typów ........................................................................................ 327
Spis treści 14

Użycie funkcji CreateObject .................................................................................................................. 328


Kiedy nie można uzyskać odwołania do aplikacji ............................................................................. 328
Co wtedy, gdy użytkownik ma inną wersję aplikacji? ....................................................................... 328
Użycie metod i właściwości obiektów automatyzacji ................................................................................. 329
Ustawianie właściwości obiektu ............................................................................................................ 329
Wykonywanie metod obiektów.............................................................................................................. 329
Zwalnianie obiektów automatyzacji ........................................................................................................... 329
Łączymy wszystko razem ............................................................................................................................ 329
Zamykanie aplikacji serwera automatyzacji ............................................................................................. 330
Użycie właściwości UserControl do sprawdzenia, w jaki sposób została otwarta aplikacja .................... 330
Użycie WithEvents w celu udostępnienia zdarzeń serwera automatyzacji ................................................ 331
Uruchamiamy WithEvents ..................................................................................................................... 331
Techniki i wskazówki do automatyzacji...................................................................................................... 332
Ustanowienie odwołania, użycie wczesnego wiązania typów i słowa kluczowego New.................... 332
Użycie istniejącego egzemplarza aplikacji, jeżeli jest ona uruchomiona.............................................. 333
Wyłącz odświeżanie ekranu ................................................................................................................... 333
Informacja o przetwarzaniu.................................................................................................................... 333
Wykonywanie programu przez serwer automatyzacji ........................................................................... 334
Użycie konstrukcji With/End With ........................................................................................................ 334
Zwalnianie zmiennych obiektowych...................................................................................................... 334
Nie wyświetlaj okien dialogowych i komunikatów ............................................................................... 334
Używaj obsługi błędów .......................................................................................................................... 334
ROZDZIAŁ 19. INTEGRACJA Z OFFICE 2000 ................................................................................... 335
Powody integracji z Office 2000 ................................................................................................................ 336
Użycie Worda......................................................................................................................................... 336
Użycie Excela......................................................................................................................................... 336
Użycie PowerPoint ................................................................................................................................. 336
Użycie Outlooka..................................................................................................................................... 336
Użycie Graph.......................................................................................................................................... 337
Użycie MapPoint .................................................................................................................................... 337
Użycie FrontPage ................................................................................................................................... 337
Użycie Bindera ....................................................................................................................................... 337
Wybór właściwego narzędzia ..................................................................................................................... 337
Wszędzie VBA ............................................................................................................................................. 337
Użycie rejestratora makr do pisania kodu ................................................................................................. 338
Użycie makr automatycznych ..................................................................................................................... 339
Microsoft Forms ......................................................................................................................................... 339
Object Browser........................................................................................................................................... 339
Nazwy klas aplikacji Office ........................................................................................................................ 340
Przykład automatyzacji .............................................................................................................................. 340
Automatyzacja Worda ................................................................................................................................ 341
Model obiektów Worda.......................................................................................................................... 342
Użycie szablonów Worda....................................................................................................................... 342
Wstawianie danych do dokumentu Worda............................................................................................. 343
Korespondencja seryjna...................................................................................................................... 343
Zakładki.............................................................................................................................................. 345
Zastępowanie...................................................................................................................................... 345
Przykłady kodu automatyzacji Worda.................................................................................................... 345
Formatowanie dokumentów ............................................................................................................... 345
Użycie stylów dokumentu .................................................................................................................. 346
Autokorekta ........................................................................................................................................ 346
Autotekst ............................................................................................................................................ 346
15

Autopodsumowanie............................................................................................................................ 346
Widoki dokumentu ............................................................................................................................. 347
Spis treści ........................................................................................................................................... 347
Przypisy .............................................................................................................................................. 347
Nagłówki ............................................................................................................................................ 347
Stopki.................................................................................................................................................. 347
Hiperłącza........................................................................................................................................... 347
Tworzenie tabel .................................................................................................................................. 348
Ustawienia strony ............................................................................................................................... 348
Podgląd wydruku................................................................................................................................ 348
Drukowanie dokumentów, kopert i etykiet ........................................................................................ 348
Pola ..................................................................................................................................................... 348
Informacje o dokumencie ................................................................................................................... 349
Inne możliwości Worda...................................................................................................................... 350
Automatyzacja Excela ................................................................................................................................ 350
Model obiektów Excela.......................................................................................................................... 350
Przykłady automatyzacji Excela............................................................................................................. 351
Formatowanie dokumentów Excela ................................................................................................... 351
Tworzenie wykresów.......................................................................................................................... 351
Użycie właściwości Parent ................................................................................................................. 352
Automatyzacja PowerPoint ........................................................................................................................ 352
Model obiektów PowerPoint .................................................................................................................. 353
Przykłady automatyzacji PowerPoint..................................................................................................... 353
Dodanie slajdu .................................................................................................................................... 353
Dodanie efektu przejścia .................................................................................................................... 354
Wstawianie danych i formatowanie slajdów...................................................................................... 354
Wstawienie rysunku do slajdu............................................................................................................ 354
Uruchamianie prezentacji................................................................................................................... 354
Automatyzacja Outlook .............................................................................................................................. 354
Model obiektów Outlook........................................................................................................................ 355
Przykłady automatyzacji Outlook .......................................................................................................... 355
Dodawanie i wyświetlanie folderów .................................................................................................. 355
Dodawanie nowego zadania i wyświetlenie zadań ............................................................................ 356
Tworzenie wiadomości e-mail z załącznikiem................................................................................... 356
Tworzenie elementów Outlooka......................................................................................................... 357
Wyświetlanie domyślnych folderów .................................................................................................. 357
Wyświetlenie foldera publicznego ..................................................................................................... 357
Szukanie elementu w Outlooku.......................................................................................................... 357
Filtrowanie elementów w Outlooku ................................................................................................... 357
Automatyzacja Graph................................................................................................................................. 358
Model obiektów Graph........................................................................................................................... 358
Tworzenie wykresu ................................................................................................................................ 358
Przykłady automatyzacji Graph ............................................................................................................. 359
Automatyzacja MapPoint ........................................................................................................................... 359
Model obiektów MapPoint ..................................................................................................................... 359
Przykłady automatyzacji MapPoint........................................................................................................ 360
Automatyzacja FrontPage .......................................................................................................................... 360
Model obiektów FrontPage .................................................................................................................... 360
Przykłady automatyzacji FrontPage ....................................................................................................... 361
Automatyzacja Bindera .............................................................................................................................. 362
Model obiektów Bindera ........................................................................................................................ 362
Przykłady automatyzacji Bindera........................................................................................................... 362
Zabezpieczanie dokumentów, szablonów i kodu programu ....................................................................... 363
Spis treści 16

ROZDZIAŁ 20. UŻYCIE VISUAL BASIC Z ACCESSEM ................................................................... 364


Tworzenie komponentów ActiveX............................................................................................................... 364
Czym są komponenty ActiveX............................................................................................................... 364
Różnice między ActiveX EXE i ActiveX DLL ..................................................................................... 365
Tworzenie komponentu ActiveX ........................................................................................................... 365
Kompilowanie biblioteki DLL ............................................................................................................... 367
Użycie komponentu ActiveX cSound .................................................................................................... 368
Użycie komponentu w innych aplikacjach............................................................................................. 369
Dystrybucja komponentów ActiveX ...................................................................................................... 369
Instalowanie komponentu................................................................................................................... 369
Tworzenie programu instalacyjnego przy użyciu Package and Deployment Wizard ....................... 369
Rozprowadzanie plików przy użyciu kreatora Package and Deployment Wizard............................ 373
Wpisy w rejestrze ............................................................................................................................... 375
Zgodność komponentów .................................................................................................................... 375
Komponent obsługi błędów.................................................................................................................... 376
Dane modułu obsługi błędów............................................................................................................. 377
Komponent cError .............................................................................................................................. 377
Tworzenie formantów ActiveX.................................................................................................................... 377
Rodzaje formantów ActiveX.................................................................................................................. 377
Atrybuty formantów ActiveX................................................................................................................. 378
Tworzenie programowych formantów ActiveX..................................................................................... 378
Utworzenie projektu dla formantu ActiveX ....................................................................................... 378
Tworzenie interfejsu........................................................................................................................... 379
Ustawianie właściwości projektu ....................................................................................................... 380
Zapisywanie projektu ......................................................................................................................... 380
Dodawanie metod i zdarzeń ............................................................................................................... 380
Użycie kreatora ActiveX Control Interface Wizard........................................................................... 380
Dodajemy kod do formantu ActiveX ................................................................................................. 382
Wywoływanie zdarzenia ................................................................................................................ 382
Użycie zdarzenia ReadProperties ................................................................................................... 383
Testowanie formantu ActiveX w Visual Basicu ................................................................................ 383
Użycie formantu Timer na formularzu Accessa................................................................................. 385
Tworzenie wielu formantów Timer.................................................................................................... 385
Rozprowadzanie formantu ActiveX Timer ........................................................................................ 386
Tworzenie okna właściwości.............................................................................................................. 386
Użycie okna właściwości ................................................................................................................... 387
Użycie formantu Timer w innych aplikacjach ................................................................................... 387
Tworzenie formantów ActiveX interfejsu użytkownika ........................................................................ 387
Tworzenie interfejsu użytkownika ..................................................................................................... 387
Ustawienie właściwości projektu ....................................................................................................... 388
Zapisywanie projektu ......................................................................................................................... 388
Testowanie formantu na formularzu Visual Basica ........................................................................... 388
Użycie formantu cSlider na formularzu Accessa ............................................................................... 388
Dystrybucja formantu ActiveX cSlider .............................................................................................. 389
Użycie formantu cSlider w innych aplikacjach.................................................................................. 389
Tworzenie instalacyjnego pakietu internetowego .............................................................................. 389
Użycie formantu cSlider na stronie WWW........................................................................................ 391
CZĘŚĆ VII ZAGADNIENIA WIELODOSTĘPU ........................................................................................ 393
ROZDZIAŁ 21. ZAGADNIENIA WIELODOSTĘPU, SERWER PLIKÓW, BLOKOWANIE ........ 394
Konflikty ..................................................................................................................................................... 394
Konfiguracja............................................................................................................................................... 395
Access i blokady Jet.................................................................................................................................... 395
17

Omówienie blokowania.......................................................................................................................... 396


Blokowanie stron kontra blokowanie rekordów................................................................................. 396
Plik LDB................................................................................................................................................. 397
Optymistyczne i pesymistyczne blokowanie rekordów ......................................................................... 397
Blokowanie optymistyczne ................................................................................................................ 397
Blokowanie pesymistyczne ................................................................................................................ 397
Blokowanie rekordów ........................................................................................................................ 398
Właściwość RecordLocks w interfejsie związanym .............................................................................. 398
Metody blokowania silnika Jet............................................................................................................... 398
Określanie stanu blokad ..................................................................................................................... 398
Sprawdzanie blokad............................................................................................................................ 400
Użycie blokowania stron .................................................................................................................... 401
Obsługa błędów blokowania .................................................................................................................. 401
Ustawienia blokowania Accessa ........................................................................................................ 401
Konflikty zapisu ................................................................................................................................. 401
Zablokowany rekord........................................................................................................................... 402
Transakcje........................................................................................................................................... 402
Blokady Oracle/SQL Server ....................................................................................................................... 403
ROZDZIAŁ 22. REPLIKACJA I JRO ..................................................................................................... 404
Kiedy użyć replikacji .................................................................................................................................. 404
Kiedy nie używać replikacji........................................................................................................................ 405
Przystosowanie bazy do replikacji ............................................................................................................. 405
Replikacja przy użyciu aktówki .................................................................................................................. 405
Użycie interfejsu użytkownika .................................................................................................................... 406
Wybór między obiektami lokalnymi i replikowanymi........................................................................... 408
Planowanie topologii replikacji.............................................................................................................. 409
Wybór schematu sterowanego................................................................................................................ 411
Synchronizacja bezpośrednia ............................................................................................................. 411
Synchronizacja pośrednia................................................................................................................... 411
Wybór schematu niesterowanego........................................................................................................... 411
Jet i model obiektowy replikacji ................................................................................................................. 411
Poznajemy JRO ...................................................................................................................................... 412
Opis metod i właściwości JRO ................................................................................................................... 413
Właściwość ActiveConnection............................................................................................................... 413
Właściwość ConflictFunction ................................................................................................................ 413
Właściwość ConflictTables .................................................................................................................... 415
Właściwość DesignMasterID ................................................................................................................. 416
Obiekty repliki ............................................................................................................................................ 416
Właściwość ReplicaID ........................................................................................................................... 416
Właściwość ReplicaType ....................................................................................................................... 416
Właściwość RetentionPeriod.................................................................................................................. 416
Właściwość Visibility............................................................................................................................. 417
Metoda CreateReplica ............................................................................................................................ 417
Metoda GetObjectReplicability.............................................................................................................. 418
Metoda MakeReplicable......................................................................................................................... 418
Metoda PopulatePartial .......................................................................................................................... 419
Metoda SetObjectReplicability .............................................................................................................. 420
Metoda Synchronize............................................................................................................................... 420
Kolekcja Filters .......................................................................................................................................... 421
Właściwość Count .................................................................................................................................. 421
Metoda Item ........................................................................................................................................... 421
Metoda Append ...................................................................................................................................... 422
Spis treści 18

Metoda Delete ........................................................................................................................................ 422


Metoda Refresh ...................................................................................................................................... 422
Obiekt Filter ........................................................................................................................................... 422
Właściwość FilterCriteria................................................................................................................... 422
Właściwość FilterType....................................................................................................................... 422
Właściwość TableName ..................................................................................................................... 423
ROZDZIAŁ 23. BEZPIECZEŃSTWO ..................................................................................................... 424
Elementy bezpieczeństwa............................................................................................................................ 424
Zabezpieczenie bazy danych hasłem...................................................................................................... 424
System bezpieczeństwa grupy roboczej ................................................................................................. 425
Tworzenie grupy roboczej .......................................................................................................................... 426
Użytkownicy i grupy ................................................................................................................................... 427
Omówienie domyślnych ustawień użytkowników i grup ...................................................................... 428
Tworzenie użytkowników ...................................................................................................................... 428
Ustawianie i zmiana hasła użytkownika................................................................................................. 429
Tworzenie grup....................................................................................................................................... 429
Przypisywanie użytkowników do grup .................................................................................................. 430
Rozróżnianie między domyślnymi i specjalnymi grupami i użytkownikami ....................................... 430
Poznajemy uprawnienia.......................................................................................................................... 430
Tworzenie systemu bezpieczeństwa przy użyciu opcji startowych ............................................................. 432
Zagadnienia bezpieczeństwa przy użyciu replikacji................................................................................... 432
Ochrona podzielonych baz danych............................................................................................................. 433
Opcja With OwnerAccess ...................................................................................................................... 434
Bezpieczeństwo systemu klient-serwer ....................................................................................................... 434
Zarządzanie użytkownikami................................................................................................................... 434
Wyliczanie grup i użytkowników oraz wyświetlanie przynależności.................................................... 435
Identyfikacja bieżących użytkowników za pomocą ADOX .................................................................. 436
Wyszukiwanie użytkowników z pustym hasłem.................................................................................... 437
Ustawianie i usuwanie hasła................................................................................................................... 438
Zarządzanie grupami .............................................................................................................................. 438
Zarządzanie właściwością obiektów ...................................................................................................... 438
Zarządzanie wieloma aplikacjami .......................................................................................................... 438
Użycie SQL ............................................................................................................................................ 439
Create.................................................................................................................................................. 439
Add User............................................................................................................................................. 439
Grant/Revoke...................................................................................................................................... 439
Drop.................................................................................................................................................... 440
Zabezpieczanie bazy danych krok po kroku ............................................................................................... 440
Częste błędy bezpieczeństwa ...................................................................................................................... 440
CZĘŚĆ VIII PUBLIKOWANIE W SIECI ZA POMOCĄ ACCESSA 2000 ............................................ 442
ROZDZIAŁ 24. KONFIGURACJA SERWERA WWW DLA PUBLIKOWANIA W SIECI WWW .. 443
Środowisko programistyczne a środowisko produkcyjne........................................................................... 443
Wybór platformy......................................................................................................................................... 444
Personal Web Server i Peer Web Services ............................................................................................. 444
Internet Information Server .................................................................................................................... 444
Co to jest Option Pack................................................................................................................................ 445
Uruchomienie serwera WWW .................................................................................................................... 446
Instalacja................................................................................................................................................. 446
NT Option Pack dla Windows 95/98...................................................................................................... 446
Dostępne komponenty instalacji......................................................................................................... 446
Opcje instalacji: minimalna, typowa i niestandardowa...................................................................... 448
19

Microsoft Transaction Server 2.0 ........................................................................................................... 449


Co to jest broker transakcji? ............................................................................................................... 449
Zarządzanie i konfiguracja serwera WWW................................................................................................ 450
Personal Web Manager........................................................................................................................... 450
Microsoft Management Console ............................................................................................................ 451
Konfiguracja Internet Information Server .......................................................................................... 451
Zabezpieczanie aplikacji WWW ................................................................................................................. 455
Różnice pomiędzy witryną a katalogiem wirtualnym ................................................................................. 456
Co to jest IUSER ? ................................................................................................................................. 457
Typ systemu plików ............................................................................................................................... 457
Struktura katalogów i wymagane uprawnienia ...................................................................................... 458
ASP/HTML – położenie i uprawnienia.................................................................................................. 458
Bazy danych – położenie i uprawnienia................................................................................................. 459
ROZDZIAŁ 25. PRZENOSZENIE ACCESSA 2000 DO SIECI WWW
ZA POMOCĄ KOMPONENTÓW SIECIOWYCH OFFICE ................................................................ 460
Czym są komponenty sieciowe Office......................................................................................................... 460
Co potrafią komponenty sieciowe Office............................................................................................... 461
Wymagane licencje na użycie komponentów sieciowych .................................................................... 461
Użycie formantu Office Arkusz................................................................................................................... 461
Rozpoczynamy ....................................................................................................................................... 461
Użycie formantu w Accessie .................................................................................................................. 462
Użycie formantu Office Wykres .................................................................................................................. 463
Rozpoczynamy ....................................................................................................................................... 464
Użycie formantu w Accessie .................................................................................................................. 464
Użycie formantu Office Tabela przestawna ............................................................................................... 465
Rozpoczynamy ....................................................................................................................................... 466
ROZDZIAŁ 26. UŻYCIE STRON DOSTĘPU DO DANYCH ............................................................... 467
Czym są strony dostępu do danych?........................................................................................................... 467
Architektura oraz wymagania stron dostępu do danych............................................................................ 467
Tworzenie Twojej pierwszej strony dostępu do danych ............................................................................. 468
Oglądanie strony dostępu do danych...................................................................................................... 470
Tworzenie interaktywnych odnośników...................................................................................................... 471
Łączenie komponentów sieciowych Office z DAP ...................................................................................... 472
Dodanie komponentu sieciowego Arkusz Excel.................................................................................... 473
Dodanie komponentu sieciowego Wykres ............................................................................................. 473
Skrypty w stronach dostępu do danych ...................................................................................................... 474
Zmiana źródła danych w trakcie działania strony .................................................................................. 475
ROZDZIAŁ 27. PUBLIKOWANIE W SIECI PRZY UŻYCIU ACCESSA 2000 I ACTIVE SERVER
PAGES........................................................................................................................................................... 477
Użycie Active Server Pages ........................................................................................................................ 477
Architektura Active Server Pages............................................................................................................... 478
Active Server Pages kontra CGI............................................................................................................. 478
Uruchomienie stron ASP........................................................................................................................ 478
Rozpoczynamy pracę z Active Server Pages ............................................................................................. 479
Konstrukcja kodu ASP ........................................................................................................................... 480
Ograniczenia eksportu stron ASP........................................................................................................... 481
Active Server Pages.................................................................................................................................... 481
Silnik ASP .............................................................................................................................................. 481
Skrypty wykonywane na serwerze ......................................................................................................... 481
Użycie VBScript na stronach ASP ......................................................................................................... 484
Obiekty aplikacji i sesji .......................................................................................................................... 486
Spis treści 20

Użycie obiektu aplikacji ..................................................................................................................... 486


Użycie obiektu sesji............................................................................................................................ 486
Użycie obiektów żądań i odpowiedzi..................................................................................................... 486
Obiekt Response................................................................................................................................. 487
Response.Redirect .............................................................................................................................. 487
Response.Write................................................................................................................................... 487
Obiekt Request ....................................................................................................................................... 487
Plik global.asa ........................................................................................................................................ 487
Przykłady użycia obiektów ASP ............................................................................................................ 488
Użycie ADO w aplikacjach ASP............................................................................................................ 489
Przykład: tworzenie strony WWW dostępnej dla członków grupy ............................................................. 490
Publikacja w sieci z Accessa 2000 przy użyciu XML ................................................................................. 494
Podstawy XML....................................................................................................................................... 494
Programowe tworzenie pliku XML........................................................................................................ 496
Tworzenie wykresów przy użyciu formantu Wykres ................................................................................... 498
Część I
Projektowanie bazy danych
Rozdział 1.
Co nowego w Accessie 2000
W tym rozdziale:
u Nowy interfejs użytkownika.
u Zmiany w VBE.
u Strony dostępu do danych.
u Podarkusze danych.
u Autokorekta nazw.
u ADO jako domyślny system dostępu do danych.
u Współpraca online.
u Access jako interfejs użytkownika dla SQL Server.

Gdy na rynku pojawiła się pierwsza wersja programu Access, trudno było przypuszczać, że kiedyś stanie się on tak
potężnym narzędziem jakim jest Access 2000. Ci, którzy korzystali z Accessa 1.0, pamiętają z pewnością aplikację o
następujących cechach: maksymalnej wielkości pliku ograniczonej do 128 MB, braku zdolności transakcyjnych, braku
narzędzi programistycznych z prawdziwego zdarzenia, statycznych paskach narzędzi, braku integralności referencyjnej
oraz bardzo niskiej wydajności. Pomimo wyżej wymienionych wad w owym czasie program ten nie miał sobie równych.
Zawdzięczał to łatwym w obsłudze narzędziom konstrukcyjnym, dynasetom oraz konstruktorowi kwerend. Z każdym
uaktualnieniem Access stawał się coraz potężniejszym i bardziej użytecznym narzędziem oraz systemem rozwoju.

Użytkownicy oraz programiści pracujący z Accessem z zadowoleniem przyjmowali kolejne ulepszenia silnika bazy danych
aż do wersji 4.0. Wówczas to, Access posiadał już przetwarzanie transakcyjne, integralność referencyjną, zdolności
replikacyjne, ulepszone zarządzanie współbieżnością, a ponadto działał szybciej i dużo stabilniej. Ponadto program
początkowo posiadający proste makra języka Access VB został wyposażony w pełną obsługę VBA wraz ze środowiskiem
rozwoju prawie identycznym z Visual Studio w wersji 6.0. Poprawiono także interfejs narzędzi. Obsługa narzędzi innych pro-
ducentów oraz formantów ActiveX znacznie poszerzyły dostępne programistom możliwości projektowania. Wraz z
pojawieniem się na rynku Accessa 95 i 97 programiści uzyskali możliwość tworzenia wielu kopii formularzy. Wersja 97
umożliwiła im również korzystanie z Active Server Pages, rozszerzając tym samym zasięg Accessa na Internet.

Na przestrzeni lat, usprawnienia Accessa można liczyć w setkach. Dziś ulepszenia, jakie wprowadzono w Accessie 2000,
są naprawdę zadziwiające. Różnice między Accessem 2000 a jego poprzednią wersją są prawie tak duże jak różnice
między jego pierwszą wersją i Accessem 97. Nie ulega wątpliwości, iż miliony docelowych użytkowników i programistów
Accessa uznają jego nową wersję za elastyczne i niezwykle użyteczne narzędzie. Z pewnością również kolejne miliony
przekonają się o jego zaletach i zaczną z niego korzystać w nadchodzących miesiącach i latach.

Nowy interfejs użytkownika


Pierwszą rzeczą, jaką zauważysz po uruchomieniu Accessa 2000, jest jego nowy interfejs. Microsoft postanowił
ujednolicić graficzny interfejs użytkownika we wszystkich swoich aplikacjach, włączając w to Access. Okno bazy danych
posiada pasek zawierający grupy obiektów dostępnych dla programisty, co upodabnia Access do programu Microsoft
Outlook. Nie jest to tylko zabieg kosmetyczny. Dzięki temu możesz tworzyć dowolne, logiczne grupy, ze skrótami do
właściwych obiektów. Przykładowo, możesz utworzyć grupę „Zamówienia i Sprzedaż”, a następnie w obrębie tej grupy
umieścić skróty do kwerend, formularzy, raportów, stron, makr i modułów powiązanych z zamówieniami i sprzedażą.
Dzięki temu unikniesz czasochłonnych poszukiwań wśród wszystkich obiektów. Tę przydatną cechę ilustruje rysunek 1.1.
23 Rozdział 1. ♦ Co nowego w Accessie 2000

Rysunek 1.1.
Wszystko,
co jest związane
z zamówieniami
i sprzedażą, znajduje
się w jednym miejscu

Mniej widoczną, lecz równie ważną zmianą, jest wyświetlanie w menu Accessa 2000 jedynie najczęściej używanych
poleceń. Dwukrotne kliknięcie menu lub kliknięcie znaku rozwijającego spowoduje wyświetlenie pozostałych poleceń.
Czynność tę przedstawiliśmy na rysunku 1.2
Rysunek 1.2.
Rozwijane menu
pomagają
zapobiegać
bałaganowi

Kreatory służące tworzeniu i edycji obiektów również mają odpowiednie, przyporządkowane im miejsca, dzięki czemu
zawsze wiesz, gdzie się znajdują. Ta kontekstowa dostępność pozwoli programistom zaoszczędzić czas.

Zwiększono również zestaw dostępnych funkcji obecnej już od dawna w systemie Windows opcji – schowka. Teraz możesz
skopiować do schowka kilka elementów, a następnie zgodnie z potrzebą wklejać je do dokumentu. Dzięki temu znacznie
łatwiej jest zmieniać układ funkcji lub ustawiać właściwości obiektu.

Zmiany w VBE
Kolejną kosmetyczną zmianą jest wygląd środowiska Visual Basic (VBE – ang. Visual Basic Environment). Teraz, zamiast
otwierać moduł, jakby to był zwykły plik tekstowy, Access posiada osobną przestrzeń roboczą służącą do pisania,
usuwania błędów oraz uruchamiania projektów Accessa 2000. Tym samym środowisko programistyczne Accessa
osiągnęło poziom pozostałych programów pakietu Office i zawiera teraz zintegrowane środowisko programowania (IDE –
ang. Integrated Development Environment). Jeśli kiedykolwiek pracowałeś z VBA w Office 97 lub z Visual Basic, nowe,
przedstawione na rysunku 1.3, VBE Accessa 2000 nie będzie Ci obce.

Dzięki możliwości umieszczania pasków narzędzi i okien w dowolnym miejscu będziesz mógł dostosować miejsce pracy
do swoich potrzeb. Jedno z okien może zawierać kod programu, który piszesz, natomiast w innym możesz przeglądać
właściwości dowolnego obiektu. W trzecim oknie mogą być wyświetlone formularze, raporty, moduły i klasy w bazie
danych. W jeszcze innym oknie, takie narzędzia jak okienko bezpośrednie lub okienko zmiennych lokalnych (które w tej
wersji są osobnymi oknami) pomogą Ci usuwać błędy w kodzie programu.

W przeciwieństwie do VB wszystkie moduły utworzone w tym osobnym, zintegrowanym środowisku przechowywane są


w pliku .MDB wraz ze wszystkimi obiektami bazy danych. Jednakże, możesz z łatwością importować i eksportować pliki
typu *.bas, *.cls i *.frm do i z Accessa 2000.
Część I ♦ Projektowanie bazy danych 24

Rysunek 1.3.
Środowisko VBE
jest teraz
w dużym stopniu
konfigurowalne

Strony dostępu do danych


Możliwości, jakie Access stwarza programistom, również zostały rozszerzone o nowy obiekt – strony dostępu do danych
(DAP – ang. Data Access Pages). Umożliwiają one użytkownikom tworzenie stron sieci Web, powiązanych z danymi w
taki sam sposób jak formularze lub raporty. Wystarczy umieścić na stronie kilka specjalnych formantów, ustawić kilka
właściwości, zapisać je w intra- bądź Internecie, a inni użytkownicy będą mogli korzystać z nich za pomocą przeglądarki.
Strony te mogą zawierać również pogrupowane dane (ang. Grouped Data Access Pages). Takie strony umożliwiają użyt-
kownikom interaktywne zagłębienie się w dane przy użyciu przeglądarki. Może okazać się, że strony dostępu do danych są
najszybszym sposobem na współdzielenie danych i zestawu funkcji interfejsu z użytkownikami. Strony te mogą także być
alternatywnym sposobem rozpowszechniania plików typu MDE.

Elementy sterujące stron dostępu do danych przedstawionych na rysunku 1.4 korzystają z wewnętrznych elementów
HTML oraz formantów COM. Posiadają one także bogaty zasób obiektów i współpracują z Visual Basic Scripting Edition,
skryptami Java oraz komponentami Office Web Components. Oznacza to, iż nabyte uprzednio umiejętności projektowania
stron sieci Web mogą być z łatwością przeniesione do Accessa 2000.

Podarkusze danych
Kolejną z cech interfejsu użytkownika Accessa 2000, która z pewnością będzie bardzo użyteczna, są podarkusze danych.
Dzięki nim możesz praktycznie bez wysiłku tworzyć edytowalne, hierarchiczne grupy danych, rozszerzane przez kliknięcie
małego znaku plus.
Rysunek 1.4.
Dane i zestaw
funkcji mogą być
przeglądane
z poziomu aplikacji
lub przeglądarki
25 Rozdział 1. ♦ Co nowego w Accessie 2000

Rysunek 1.5.
Kliknięcie znaku plus
powoduje
wyświetlenie
powiązanych danych

Grupy te możesz umieścić w dowolnym miejscu w widoku arkusza danych. Uzyskane dzięki temu trójwymiarowe
spojrzenie na dane z pewnością znajdzie wiele zastosowań i może stać się szybką i prostą alternatywą dla formantu Tree.

Autokorekta nazw
Kolejną bardzo przydatną cechą Accessa 2000 jest autokorekta nazw. W poprzednich wersjach Accessa musiałeś bardzo
uważać podczas zmiany nazwy obiektu, gdyż Access nie rozpoznawał nowej nazwy dopóty, dopóki nie uaktualniłeś
wszystkich obiektów z nią powiązanych. Access 2000 automatycznie wykona to męczące zadanie za Ciebie, więc gdy
uznasz, że dane pole powinno nazywać się inaczej, możesz zmienić jego nazwę w dowolnym momencie, a aplikacja będzie
wciąż działać poprawnie.

ADO jako domyślny system


dostępu do danych
Gdy spojrzymy do wewnątrz, w Accessie zmieniono domyślny system dostępu do danych. Zamiast znanych, lecz
pamięciochłonnych obiektów Data Access (DAO), do pobierania i zarządzania danymi Access używa obiektów Active
Data (ADO). Korzyści płynące z ADO są bardzo liczne: prostszy interfejs, płaska struktura, użycie tych samych technik i
interfejsów między podobnymi źródłami danych, możliwość pobierania i zarządzania danymi z innych źródeł niż tylko
programy typu RDBMS, a także zapowiedź większej wydajności i rozszerzonych opcji. Mimo iż Access współpracuje
z obiektami DAO, Microsoft nie będzie już rozbudowywał tego systemu. Tak więc, jeśli nie miałeś jeszcze okazji
pracować z ADO, szczegółowy opis tego zagadnienia znajdziesz w rozdziale 6. „Wprowadzenie do obiektów danych
ActiveX” i 7. „Zaawansowane ADO”.

Oprócz ADO, również dostawcy OLEDB dostarczają podobnych interfejsów dla szerokiej gamy źródeł danych w
standardzie Microsoft’s Universal Data Access. Ustawienia dla dostawców OLEDB mogą być również zapisane w pliku
typu Universal Data Link (UDL), co znacznie ułatwia kontrolowanie (i zmianę) źródeł danych.

Współpraca online
Współpraca online jest szczególnie wartościowa dla programistów, którzy współpracują ze sobą mimo dzielącej ich
odległości. Po rozpoczęciu spotkania programiści mogą wymieniać uwagi o projektach za pomocą serwera listy, a także
korzystać z takich opcji jak wspólna tablica, aby efektywnie wyrażać swoje pomysły.
Część I ♦ Projektowanie bazy danych 26

Access jako interfejs użytkownika dla SQL Server


Bez wątpienia najciekawszą z nowych opcji Accessa 2000 jest nowy typ projektu aplikacji: Microsoft Access Project
(*.adp). Projektom tym, będącym zapowiedzią nadchodzącej ery Accessa, poświęcimy w tej książce dużo miejsca. Access
był zawsze zdalną bazą danych działającą w ramach środowiska serwera plików i był ograniczony do ilości

danych, z którą jego silnik Jet mógł sobie poradzić, oraz ilości użytkowników, których mógł obsłużyć. Microsoft Access
Project nie posiada takich ograniczeń, gdyż jest prawdziwym interfejsem użytkownika dla SQL Server i Microsoft Data
Engine.

Dzięki obsłudze OLEDB, Access 2000 może całkowicie pominąć Jet i współpracować bezpośrednio z innymi silnikami
baz danych. Podczas tworzenia bazy danych w Accessie 2000 użytkownik może utworzyć Project, a następnie wybrać
między dołączonym do pakietu Office 2000 Microsoft Data Engine (MSDE) a SQL Server 6.0 i 7.0. Każdy z nich jest w
stanie obsługiwać tysiące użytkowników i terabajty danych. Access jest środowiskiem rozwoju i administrowania dla SQL
Servera, a utworzona aplikacja staje się prawdziwym klientem w relacji klient-serwer.

Access Project nie zawiera żadnych danych, tabel czy kwerend. Jest bezpośrednio połączony z zapleczem i umożliwia
tworzenie, przeglądanie i modyfikowanie tabel w bazie, przechowywanych procedur, widoków i diagramów bazy danych. W
porównaniu do poprzednich wersji Accessa możemy mówić o radykalnej zmianie. Mimo iż wielu programistów dołączało
tabele z SQL Server i Oracle, kwerendy na nich oparte były wykonywane lokalnie (uruchomienie kwerendy opartej na
dołączonej tabeli powoduje przeniesienie danych na komputer klienta). Niektórzy programiści tworzyli kwerendy
przekazujące, dzięki czemu serwer wykonywał większość obliczeń, ale to dość specyficzny przypadek. Dołączona tabela
nie mogła być modyfikowana, a stworzenie i obsługa widoków i przechowywanych procedur, pobranych za pomocą
kwerendy przekazującej, mogły wymagać osobnych narzędzi administracyjnych. Ograniczenia te powodowały opóźnienia w
realizacji projektu i wymagały zaangażowania dodatkowych pracowników wówczas, gdy nie było to pożądane. Access
Projects umożliwiły programistom tworzenie całego projektu aplikacji klient-serwer samemu i bez użycia dodatkowych
narzędzi.

Przedstawiciele Microsoftu są przekonani o tym, iż ta opcja zyska sobie aprobatę użytkowników i przyczyni się do sukcesu
tego programu. Aby było to możliwe, typy danych Accessa dostosowano do SQL Server, uaktualniono składnię SQL, by
była zgodna ze standardami ANSI, a także uaktualniono kreatory i narzędzia wspomagające nową architekturę klient-serwer.
Stworzono także nowe narzędzia służące do tworzenia i zarządzania obiektami po stronie serwera w widoku Projekt klienta.
Także inne zwykłe czynności administracyjne, jak zabezpieczenia, sporządzanie kopii zapasowych i replikacja, mogą być
zarządzane przez Access 2000.
Rozdział 2.
Planowanie procesu rozwoju
W tym rozdziale:
u Określenie wymagań.
u Architektura.
u Planowanie rozwoju.
u Konstrukcja.

W pozostałych rozdziałach tej książki opisane są wszystkie potężne narzędzia i opcje, jakie oferuje Access 2000. Jednakże,
nawet po opanowaniu tego materiału, gdy będziesz już świetnym programistą, sukces Twoich projektów wciąż będzie
niepewny, jeśli nie zrozumiesz, jak ważny dla ich powodzenia jest proces rozwoju. Nawet, jeśli świetnie programujesz, to
efektem braku dobrze zaplanowanego procesu lub zgranej grupy współpracowników może być niezadowalający wynik
projektu.

W tym rozdziale zawarliśmy kilka kluczowych informacji oraz czynności dotyczących zespołu i procesu rozwoju.
Chcielibyśmy pomóc Ci w budowaniu udanych projektów, poprzez stworzenie Twojego własnego, efektywnego i opartego
na sprawdzonych metodach procesu rozwoju. Opisanie tych zagadnień w pełni zajęłoby nam całą książkę.

Udany proces rozwoju skupia się na czterech kluczowych etapach projektu: Wymaganiach, Architekturze, Planowaniu
Rozwoju oraz właściwej fazie Konstrukcji. W fazie Wymagania, będziesz zbierał i analizował rzeczywiste potrzeby
użytkowników. W fazie Architektura wybierzesz układ, technologie i narzędzia rozwoju, które w najlepszy sposób te
potrzeby zaspokoją. Podczas fazy Planowanie rozwoju sporządzisz plan rozwoju, który będzie opisywał sposób, w jaki
projekt będzie wdrożony, ustalisz niezbędną liczbę programistów oraz koszty całego przedsięwzięcia. Ostatnia faza
rozwoju to tworzenie aplikacji.

Rysunek 2.1 przedstawia cztery fazy procesu rozwoju, począwszy od określenia wymagań, aż do tworzenia aplikacji. Zawiera
on również niektóre z edycji programu, wypuszczane podczas tej fazy. W tym rozdziale szczegółowo scharakteryzujemy
każdą z faz.

Rysunek 2.1.
Proces rozwoju
Część I ♦ Projektowanie bazy danych 28

Określenie wymagań
Określenie i analiza wymagań jest najważniejszą czynnością wpływającą na jakość aplikacji. Wielokrotnie byliśmy
świadkami projektów, które upadały na skutek nieprecyzyjnie bądź błędnie zdefiniowanych wymagań.

Dlaczego faza wymagań jest tak ważna?


Prawidłowo zidentyfikowane i przeanalizowane wymagania pozwolą zmniejszyć liczbę nieprzewidzianych zmian, które
trzeba będzie później wprowadzić. Eksperci z przemysłu software’owego stwierdzili, że koszty ponoszone na
wprowadzanie zmian, rosną o mnożnik zawierający się między 5 a 10, podczas przejścia na każdy kolejny etap procesu
rozwoju. Przykładowo, jeśli klient zauważy błąd w wymaganiach, który zostanie poprawiony w fazie wymagań, zmiana
zajmie godzinę. Jeśli błąd zostanie zauważony dopiero po włączeniu tej opcji w projekt, wprowadzenie zmiany zajmie 10
godzin. Jeśli element ten został już zintegrowany i przetestowany z resztą aplikacji, naprawa błędu może potrwać 50
godzin. Jeśli problem wynikł dopiero po dostarczeniu aplikacji do klienta, jego rozwiązanie zajmie blisko 100 godzin.

Dlaczego aż tak dużo? Po pierwsze, wymagania powinny być uaktualniane. Projekt i kod programu muszą być
analizowane, aby ocenić czy zmiany są konieczne. Wówczas zmiany te muszą być wprowadzone, a różne moduły,
kwerendy, formularze i raporty przetestowane. Sama aplikacja musi być osobno przetestowana, aby mieć pewność, że
zmiany odniosły przewidywany skutek i nie spowodowały wystąpienia kolejnych błędów. Wreszcie, poprawiona aplikacja
musi być ponownie dostarczona do każdego z użytkowników.

Oczywiście, podane tu mnożniki to średnie wartości dla tej gałęzi przemysłu, a nie wartości absolutne. W zależności od
rozmiaru zmian, koszty mogą być od nich niższe bądź wyższe. Jeśli błąd odbił się negatywnie na działalności klienta,
koszty mogą być astronomiczne.

Odnalezienie rzeczywistego problemu


Określenie wymagań należy rozpocząć od ustalenia zakresu aplikacji. Nie ulega wątpliwości, że klient ma problem, który,
jak sądzi, może być rozwiązany za pomocą programu komputerowego. Jednak klient nie zawsze może właściwie
zdefiniować ów problem.

Aby zilustrować proces rozwoju, przez cały ten rozdział będziemy używać
przykładu „Sprawozdanie o kosztach pracowników”.

Przykładowo, klient może zamówić dla swoich pracowników system, który będzie służył do wprowadzania i drukowania
raportów o poniesionych kosztach. Po przeprowadzeniu analizy możesz stwierdzić, że rzeczywistą potrzebą klienta jest
automatyzacja wprowadzania, podziału, zatwierdzania i przetwarzania całego procesu związanego z raportami o kosztach.
Odnajdywanie takich różnic należy do twoich zadań. Czasami klient myśli o rozwiązaniu, które jest zbyt małe, aby
rozwiązać jego problem. Równie często zdarza się, że klient myśli o rozwiązaniu, które jest zbyt obszerne i złożone. Aby
zrozumieć jak aplikacja współdziała z pozostałymi częściami działalności klienta, powinieneś koniecznie poszerzyć zasięg
procesu określania wymagań ponad oczekiwany zysk z jej funkcjonowania.

Śledztwo
Aby określić, jaki problem rzeczywiście wymaga rozwiązania i właściwie ustalić wymagania, musisz na chwilę stać się
detektywem.

Oto kilka pomocnych wskazówek:


u Gdy poszukujesz kluczowych informacji o funkcjonowaniu procesu, nigdy nie opieraj się na opiniach innych
osób.
u Wielokrotnie w procesach handlowych można wyróżnić oficjalny sposób, w jaki proces powinien przebiegać oraz
sposób, w jaki rzeczywiście przebiega. Powinieneś poznać obydwa.
u Bądź otwarty i słuchaj uważnie. Pierwsze Twoje pomysły (i klienta) na rozwiązanie problemu powinny zostać
zapisane i odłożone, dopóki nie zostaną potwierdzone za pomocą obserwacji i analiz.
u W tabeli 2.1 znajdziesz przykłady typowych wymagań klientów.
29 Rozdział 2. ♦ Planowanie procesu rozwoju

Pierwszym etapem śledztwa jest określenie wszystkich uczestników procesu. Przez uczestnika rozumiemy osobę, grupę lub
dział, który jest zainteresowany procesem lub aplikacją. Uczestnikami są menedżerowie, osoby nadzorujące oraz
pracownicy bezpośrednio odpowiedzialni za każdy z zaangażowanych w proces działów. Uczestnikami są także ci
użytkownicy aktualnego procesu, którzy staną się użytkownikami tworzonej przez Ciebie aplikacji. Niektóre z grup
uczestników będą tak duże, że będziesz je musiał ograniczyć tylko do kilku przedstawicieli. W trakcie trwania śledztwa
możesz odkryć nowych uczestników, których będziesz musiał dołączyć. Dodatkowym zyskiem z uwzględnienia
uczestników w procesie określania wymagań jest uzyskany dzięki temu wzrost ich poczucia przynależności do nowego
systemu. Zauważysz większą chęć do współpracy i pomoc przy dostarczaniu i uruchamianiu aplikacji u klienta.

Kontynuujmy nasz przykład sprawozdania o kosztach. Zechcesz przeprowadzić wywiady z kilkoma reprezentatywnymi
użytkownikami, z których część rzadko ponosi jakiekolwiek wydatki, część często podróżuje, a także z kilkoma
przeciętnymi użytkownikami. Później porozmawiasz z kilkoma osobami z działu płac, które co miesiąc zajmują się prze-
twarzaniem tych sprawozdań oraz przedstawionych rachunków.

Teraz rozpoczyna się prawdziwe śledztwo. Porozmawiaj z każdym uczestnikiem. Zadawaj wiele pytań, słuchaj uważnie i
sporządzaj notatki. Pytaj, jak działa aktualny system oraz co im się w nim podoba lub nie. Zapytaj także, co chcieliby
zmienić.

Z tych notatek możesz ułożyć prawdziwy obraz aktualnego procesu i sposobu działania firmy. Przeanalizuj aktualny proces
i zanotuj wszystkie potencjalne gniazda zapalne i wąskie gardła. Pamiętaj także o zebraniu wszystkich wad, zalet, życzeń i
marzeń, o których dowiedziałeś się podczas wywiadów.

Diagramy procesu
Diagramy procesu są doskonałym sposobem na opisanie sposobu działania procesu handlowego. Przedstawiony na rysunku
2.2 diagram ilustruje przykład sprawozdania o kosztach. Diagramy te przedstawiają interakcje zachodzące między głównymi
osobami, grupami i działami zaangażowanymi w proces. Poszczególne kroki lub czynności w procesie następują od lewej
do prawej i przedstawione są za pomocą prostokątów. Kroki te pochłaniają wpływy z lewej strony i powodują powstawanie
wyników z prawej. Pionowe strzałki oznaczają wszystkie wewnętrzne zasady handlowe bądź zewnętrzne uregulowania i
ograniczenia. Romby przedstawiają podejmowane w trakcie trwania procesu decyzje.

Jako że pozioma oś przedstawia czas, wszelkie opóźnienia i czasochłonne czynności są łatwe do zidentyfikowania. Po
przeanalizowaniu przedstawionego na diagramie aktualnego procesu oraz potrzeb uczestników można narysować drugi
diagram, który będzie ilustrował proces po wprowadzeniu zmian.
Rysunek 2.2.
Przykład diagramu
procesu rozliczania
kosztów podróży

Diagramy procesu, takie jak ten na rysunku 2.2, są bardzo proste w tworzeniu i zrozumiałe dla wszystkich uczestników. Po
zobaczeniu diagramu wielu z uczestników będzie zaskoczonych stopniem skomplikowania i złożonością aktualnego
procesu. Jeśli sporządzanie diagramu procesu rozpoczniesz odpowiednio wcześnie, będziesz mógł go modyfikować
podczas rozmów z uczestnikami. Diagramy procesu mogą znacznie ułatwić Ci stworzenie scenariusza i prowadzenie
wywiadów. Każdy uczestnik będzie mógł teraz wyjaśnić i pokazać szczegóły całego procesu.

Możesz uznać za przydatne stworzenie hierarchii diagramów procesu. Na najwyższym poziomie znajdzie się diagram
opisujący cały proces, a poniżej będą diagramy ilustrujące w powiększeniu poszczególne jego etapy. Podprocesy mogą być
przedstawione ze szczegółami na osobnych diagramach procesu. Podejście hierarchiczne często ułatwia zrozumienie
skomplikowanych diagramów.

Każdy diagram procesu powinien być tworzony na dużej kartce papieru, a


nie przy użyciu komputera. Rysowanie na papierze zabiera mniej czasu i
umożliwia większą interakcję. Jest także mniej uciążliwe i bardziej czytelne.
Część I ♦ Projektowanie bazy danych 30

Aby ograniczyć konieczne poprawki i zmiany, jako elementów procesu


można używać naklejanych karteczek. Po otrzymaniu ostatecznego diagramu
procesu można go przerysować przy użyciu Microsoft Worda 2000 lub
Visio.

Identyfikacja zakresu projektu


Współpracuj z klientem, aby właściwie określić zakres aplikacji. Pamiętaj, że chodzi tu o zakres długoterminowy, a nie
koncentrujący się na tej fazie projektu.

W przykładzie ze sprawozdaniem o kosztach programiści i decydenci doszli do porozumienia co do zakresu aplikacji.


Uzgodnili, iż aplikacja powinna zautomatyzować rozliczanie zaliczek, zgłaszanie zapotrzebowania na delegacje oraz cały
proces zgłaszania kosztów począwszy od pojawienia się zapotrzebowania na delegację u pracownika, aż

do uwzględnienia rachunków za podróż w dziale księgowości. Zdecydowano również pominąć systemy księgowe i sam
proces rezerwowania biletów. Te elementy nie zostały uwzględnione w zakresie aplikacji.

Spisywanie wymagań
Przedstawienie wymagań na piśmie jest najlepszym sposobem komunikacji pomiędzy programistą a klientem. Praktyka ta
umożliwia wyeliminowanie nieporozumień. Forma pisemna nie oznacza, iż musi to być koniecznie dokument oficjalny.
Istnieje wiele skutecznych sposobów na przekazywanie wymagań: przykładowe raporty, formularze, diagramy procesu lub
rysunki. Spisywanie wymagań nie jest wcale trudne. Wystarczy zadbać o to, by klient mógł bez trudu je przeczytać i
zrozumieć.

Oto jakie pytania możesz zadać, aby sprawdzić, czy właściwie zidentyfikowałeś wymagania:
u Czy opisuje potrzebę, czy raczej sposób jej realizacji?
u Czy może być zweryfikowane po jego wprowadzeniu?
u Czy jest jednoznaczne?
u Czy w pełni opisuje potrzebę?
u Czy razem z pozostałymi wymaganiami stanowi jednolitą całość?

W tabeli 2.1 umieściliśmy przykłady wielu rodzajów wymagań, których użycie powinieneś rozważyć. Wymagania te
posłużą jako część umowy. Wydrukuj tę wersję dokumentacji wymagań i poproś klienta o jej podpisanie. Ten dokument
stanie się podstawą dalszego rozwoju aplikacji. Od tego momentu musisz zacząć zastanawiać się nad wpływem zmian w
wymaganiach na planowany budżet i harmonogram. Pamiętaj, aby po dokonaniu zmian zweryfikować budżet,
harmonogram i wszystkie pozostałe powiązane wymagania oraz dokumentację projektu.

Utwórz bazę danych zawierającą wszystkie wymagania. Dla każdego z wy-


magań dołącz numer identyfikacyjny, typ, opis, datę, źródło, zysk oraz
sposób weryfikacji wymagania po jego implementacji, wagę i inne.

Tabela 2.1.
Typy wymagań

Typ wymagań Opis Przykład


Funkcjonalne Wymagania te opisują żądane funkcje Użytkownik będzie w stanie
lub cechy oraz zasady handlowe, które nadać priorytet klienta na:
ich dotyczą Krytyczny,
Wysoki,
Średni,
Niski

Tabela 2.1.
Typy wymagań (ciąg dalszy)
31 Rozdział 2. ♦ Planowanie procesu rozwoju

Typ wymagań Opis Przykład


Wydajność Wymagania dotyczące wydajności Baza danych powinna poprzez zakładową
zawierają: sieć LAN obsługiwać do 20
Szybkość, użytkowników, ze standardowym czasem
odpowiedzi wysokości 200 ms
Czas reakcji,
Pojemność,
Wielkość bazy danych
Bezpieczeństwo Wymagania dotyczące bezpieczeństwa Wszyscy użytkownicy muszą się do
obejmują ograniczenia w użytkowaniu aplikacji logować. Każdy użytkownik
i dostępie do opcji aplikacji oraz danych będzie członkiem jednej z następujących
grup bezpieczeństwa:
Użytkownik,
Administrator,
Menedżer
Skalowalność Skalowalność dotyczy zdolności do Aplikacja musi obsługiwać 50 aktualnych
powiększania ilości danych, użytkowników oraz dodatkowo 50
użytkowników, witryn lub częstotliwości użytkowników, którzy zostaną dołączeni
zbierania danych na przestrzeni najbliższych dwóch lat
Rozszerzalność Wymagania dotyczące rozszerzalności Aplikacja będzie tak skonstruowana
charakteryzują zdolność do poszerzania i zaimplementowana, aby można było
aplikacji o dodatkowe opcje w kolejnych dodać obsługę faktur klientów
wersjach.
Konfigurowalność Konfigurowalność mierzy łatwość, Administrator będzie miał możliwość
z jaką parametry aplikacji mogą być corocznego uaktualniania stawek
zmieniane przez klienta, bez ubezpieczeniowych
konieczności ingerencji zespołu
programistów
Kompatybilność Kompatybilność to zdolność aplikacji do Program będzie zainstalowany
jej instalowania i funkcjonowania w systemach Win95, Win98 i Win NT 4.0
w różnych środowiskach sprzętowych Workstation, z minimum 8MB pamięci
i programowych, a także do interakcji oraz 200MB dostępnej przestrzeni
z innymi aplikacjami dyskowej
Dostępność Dostępność służy do określenia ile Administrator bazy musi zarezerwować
godzin lub jaką część czasu aplikacja sobie czas od 22:00 do 23:00 wieczorem,
jest w stanie wykonywać pracę, do której aby sporządzać zapasowe kopie danych
została skonstruowana
Łatwość w użyciu Wymaganie to służy określeniu stopnia, Aplikacja zawiera moduł Pomoc online,
w jakim przeszkoleni użytkownicy mogą który obejmuje 90% jej opcji
korzystać z systemu
Łatwość w nauce Wymaganie to jest miarą łatwości oraz Po jednodniowym treningu użytkownicy
czasu, w jakim użytkownicy są w stanie powinni być w wystarczającym stopniu
poznać system zaznajomieni z aplikacją, aby rozpocząć
z nią pracę

Architektura
Po przeanalizowaniu zapisanych wymagań klienta możesz wybrać odpowiednią architekturę, technologie i narzędzia
rozwoju. Czy aplikacja klienta powinna być oparta na Excelu, Accesie czy VB? A może, za pomocą ASP i XML, powinna
korzystać z sieci Web? Czy można zastosować konstrukcję dwuwarstwową, czy może n-warstwowa byłaby lepsza? Czy
motorem bazy danych będzie Jet-MDB, SQL-MSDE, SQL Server czy Oracle? Oto kilka ważnych pytań, z których każde
będzie miało duży wpływ na produkt końcowy. Dopiero, gdy na nie odpowiesz, będziesz mógł właściwie określić budżet
i harmonogram prac.

Planowanie rozwoju
Po podjęciu decyzji dotyczących wymagań i architektury powinieneś zastanowić się nad najlepszym sposobem
skonstruowania aplikacji. Czy wszystkie opcje i zestawy funkcji powinny być umieszczone w wersji 1.0, czy może
Część I ♦ Projektowanie bazy danych 32

powinieneś część z nich umieścić dopiero w następnych wersjach? Niezależnie od tego, którą z metod wybierzesz, nim
przejdziesz dalej, powinieneś zastanowić się nad budżetem i harmonogramem.

Być może już sporządziłeś wstępny plan projektu, który został zaakceptowany i dzięki temu dotarłeś do tej fazy projektu.
Ta wstępna wersja opierała się na przewidywanych wymaganiach i zakresie aplikacji, a także sporządzonym z dużym
przybliżeniem budżecie i harmonogramie. Jeśli posiadasz taki wstępny plan, teraz nadeszła chwila, by go skorygować. Jeśli
taki plan jeszcze nie istnieje, teraz powinieneś go napisać. Po zakończeniu fazy Wymagania masz już wystarczająco dużo
informacji, by sporządzić listę zadań, listę zasobów, harmonogram i budżet.

Programiści powinni posiadać stałą kontrolę nad czasem. Najlepszym spo-


sobem na wykształcenie w sobie umiejętności przewidywania jest po-
równywanie własnych prognoz z czasem, który jest faktycznie niezbędny do
wykonania danej czynności.

Strategia dostarczania
Staraj się unikać umieszczania każdego pomysłu i przydatnych opcji w jednej, olbrzymiej edycji. Prawie zawsze lepiej jest
zaplanować kilka dodatkowych wersji.

Wróćmy do przykładu ze sprawozdaniem o kosztach. Podczas spotkań programistów z decydentami dyskutowano na temat
możliwego zakresu aplikacji, harmonogramu prac i budżetu. Zgodzono się, iż wersja 1.0 powinna skoncentrować się na
automatyzacji tworzenia, zatwierdzania, podziału i kontroli raportów o kosztach. Kolejna wersja, z numerem 2.0,
zautomatyzuje tworzenie, zatwierdzanie, podział i kontrolę procesu rozliczania zaliczek na poczet delegacji. Rysunek 2.3
przedstawia kolejne etapy rozwoju aplikacji oraz przykłady możliwych edycji. Na rysunku 2.4 znajduje się poprawiony
diagram procesu, pokazujący, która z planowanych w obecnej strategii dostarczania dwóch wersji obejmuje poszczególne
etapy procesu.

Rysunek 2.3.
Przykład strategii
dostarczania
33 Rozdział 2. ♦ Planowanie procesu rozwoju

Rysunek 2.4.
Przykład diagramu
procesu dotyczącego
sprawozdania
o kosztach
i delegacjach,
uwzględniający
strategię dostarczania

Styl
Profesjonalne aplikacje zawsze charakteryzują się jednolitym wyglądem i sposobem działania. Jeśli do zamykania
niektórych formularzy używamy przycisku Anuluj, a innych Zamknij, użytkownicy szybko się pogubią, co spowoduje wzrost
kosztów szkolenia i pomocy. Jeśli jeden z programistów lubi, gdy każde pole w formularzu umieszczone jest w osobnym,
wklęsłym okienku, a wyświetlane dane są zawsze pogrubione, podczas gdy inny projektuje formularze z pogrubionymi
etykietami i płaskimi polami tekstowymi, aplikacja będzie sprawiała wrażenie niespójnej. Decyzje co do tych cech podejmij
na początku procesu rozwoju i spraw, by wszyscy programiści się z nimi zapoznali, zanim przejmą własne rozwiązania.

Oto kilka typów elementów stylu, które powinieneś określić w swoim standardzie:
u Układ formularza (na przykład: rozmieszczenie formantów, rozmiar i proporcje formularza).
u Grupowanie pól (na przykład: wklęsłe ramki czy proste linie)
u Określenie dla pól i etykiet rodzaju, koloru, rozmiaru i stylu czcionki (pogrubienie/kursywa)
u Nazwy oraz sposoby reagowania przycisków (na przykład: Anuluj, Zamknij czy Zakończ?)
u Wskazanie użytkownikowi, czy formularze są przeznaczone tylko do odczytu, czy też można je edytować.
u Sposób komunikacji z użytkownikiem (na przykład: zwięzły bądź rozwlekły).

Zamiast tracić czas na pisanie oficjalnego dokumentu, utwórz po prostu bazę


danych z zestawem formularzy i raportów zawierającym przykłady naj-
częściej używanych formantów. Plik ten może być rozwijającym się przy-
kładem preferowanych przez Ciebie stylów interfejsu użytkownika. Jeszcze
lepiej będzie, jeśli oprócz formularzy zamieścisz tam także kod opisujący
poruszanie się po formularzach i inne powszechnie używane zestawy funkcji.
Formularze te posłużą jako standardowe szablony dla twoich produktów.

Standardy
Bez standaryzacji pracy programistów aplikacje staną się bardzo kłopotliwe w obsłudze i użytkowaniu.
Zasada 1: Standardy dużo ulepszają.
Zasada 2: Standardy same w sobie nic nie ulepszają.

Podstawowym celem standaryzacji jest ujednolicenie efektów pracy członków zespołu programistów. To, że wszyscy piszą
w „dobrym” stylu, jest sprawą drugorzędną.

Nie trać czasu na spory, co jest w danym momencie najlepsze – po prostu


wybierz dobrą metodę, przekonaj do niej innych i trzymaj się jej.
Część I ♦ Projektowanie bazy danych 34

Najbardziej powszechne typy standardów to nazewnictwo i kodowanie. Standardy te znacznie ułatwiają czytanie i
przeglądanie kodu programu, a także upraszczają późniejsze czynności serwisowe.

Standardy nazewnictwa
Poniższy przykład korzysta z przyrostkowego standardu nazewnictwa i czynności wykonywane przez programistę są
oczywiste.
DblLodgingTotal = Double(intNights) * dblRate

Natomiast kolejny przykład nie jest już taki oczywisty.


x = Text7 * Text12

Oto kluczowe elementy większości standardów nazewnictwa:


u przedrostki obiektowe (na przykład: txt, cbo, lst...);
u przedrostki typów danych (na przykład: sgl, int, str...);
u typowe nazwy baz (na przykład: użycie Acct lub Account);
u typowe skrótowce (na przykład: stat = status).

Standardy kodowania
Oto przykłady elementów, które możesz chcieć określić w standardach kodowania:
u komentarze nagłówków;
u komentarze w kodzie;
u wcięcia;
u rozmiar podprocedur i funkcji (na przykład: maksymalnie 60 wierszy);
u użycie instrukcji Option Explicit.

Istnieją określone standardy nazewnictwa dotyczące rozwoju aplikacji w śro-


dowiskach Access/VBA/Office/VB. Dwa najpopularniejsze to konwencje
nazewnictwa Reddicka i Leszynskiego. Zaletą korzystania z tych konwencji
jest to, że nowi programiści zatrudnieni przez Twoją firmę mogą już je znać.
Poza tym, konwencje te są używane w fachowej prasie, książkach oraz w
materiałach szkoleniowych. Wybierz jedną z nich i konsekwentnie się jej
trzymaj.

Konstrukcja
Aby podnieść wydajność zespołu w fazie Konstrukcja możesz stosować kilka technik. W tej części omówimy zagadnienia
związane z podziałem zadań między programistami oraz kontrolować projekt i proces jego wdrażania. Przekonamy Cię
także do dokładnego przetestowania aplikacji i znalezienia wszystkich dotychczas popełnionych błędów.

Dziel i rządź: działania w fazie Konstrukcja


Istnieje wiele podejść do fazy Konstrukcja. Możesz zacząć od wdrożenia najtrudniejszych i najbardziej niepewnych części
aplikacji lub rozpocząć od tych najłatwiejszych części. Możesz także zacząć od formularzy i zakończyć na raportach.
Mimo iż wszystkie te podejścia są prawidłowe, wielu programistów osiągnęło sukces, zaczynając od stworzenia solidnych
podstaw i na nich budując resztę aplikacji. Podstawy najczęściej składają się z projektu tabel, nakreślenia głównych
formularzy i często używanych modułów i funkcji. Działanie takie ma na celu stworzenie działającego rdzenia, stanowiące-
go podstawę działania każdego z programistów. Jeśli chodzi o formularze, dobrze jest poświęcić trochę czasu na
stworzenie jednego lub dwóch, które później posłużą jako szablony dla następnych.
35 Rozdział 2. ♦ Planowanie procesu rozwoju

Nadeszła odpowiednia chwila, by zainwestować w tworzenie komponentów,


które będziesz mógł wykorzystywać wielokrotnie. Wysiłek włożony w
zaprojektowanie i testowanie tych elementów zacznie zwracać się z każdym
ich użyciem.

Ważne jest, aby podczas tworzenia podstaw aplikacji zespół programistów ściśle ze sobą współpracował. Wówczas to
zapadają najważniejsze decyzje, a także definiowane są interfejsy. Po stworzeniu tych podstaw dużo łatwiej jest
programistom pracować osobno lub podzielić się na mniejsze grupy.

Istnieją dwa wydajne sposoby dzielenia procesu wdrożenia między grupy: według obiektów Accessa lub według obiektów
aplikacji. Gdy dzielimy zadania według obiektów Accessa, jeden z zespołów koncentruje się na formularzach, inny na
raportach, a może zaistnieć potrzeba utworzenia trzeciego zespołu, który zajmie się kodowaniem reguł handlowych i
dostarczeniu procedur wspomagających. Jeśli używasz architektury zorientowanej na obiekty, możesz rozdzielić zadania
według obiektów aplikacji. Przykładowo, jeden z zespołów zająłby się tworzeniem obiektów Sprawozdania o kosztach
(moduły, tabele, formularze, raporty), a inny tworzeniem obiektów związanych z Zatwierdzaniem (moduły, tabele,
formularze, raporty).

Rysunek 2.5 przedstawia pięć etapów postępowania wszystkich zespołów w fazie Konstrukcja.

Rysunek 2.5.
Etapy fazy Konstrukcja

Ten sam sposób postępowania wykorzystywany jest na różnych poziomach procesu rozwoju. Na najwyższym z nich diagram ten
opisuje powstawanie całej aplikacji na przestrzeni kilku miesięcy, począwszy od sporządzenia szczegółowego projektu, aż do
ostatecznych testów aplikacji. Na dużo niższym poziomie ten sam diagram mógłby opisywać, jak jeden programista spędza
popołudnie na opracowywaniu jednej z zamówionych opcji.

Podczas trwania fazy Konstrukcja wypuszcza się zazwyczaj kilka wersji programu. Najczęściej są to: prototyp sprawdzający
funkcjonalność graficznego interfejsu użytkownika (GUI); kilka wersji alfa, dzięki którym otrzymujemy wstępne uwagi od
użytkowników; jedna lub dwie wersje beta, umożliwiające użytkownikom przetestowanie aplikacji w rzeczywistych
warunkach; i wreszcie oficjalna wersja 1.0, dostarczana wszystkim użytkownikom.

Edycje i kompilacje
Wraz ze wzrostem złożoności aplikacji i projektu ważności nabiera śledzenie wszystkich wypuszczanych wersji aplikacji.
Co pewien czas twórz (patrz następna wskazówka) edycję aplikacji zawierającą ostatnie poprawki i zmiany dokonane przez
wszystkich programistów. Robiąc to codziennie lub co dwa dni, każdy z programistów ma dostęp do najnowszych
poprawek. W tabeli 2.2 znajdziesz przykłady edycji, które mogą powstać podczas rozwoju aplikacji.

Kompilacja
Kompilacja jest nową wersją aplikacji. Najczęściej zawiera ona umieszczoną
w systemie klienta bazę danych wraz ze wszystkimi powiązanymi z nią plikami
typu DLL i EXE oraz znajdujące się na serwerze pliki danych. Dla
wewnętrznych potrzeb zespołu programistów podczas rozwoju aplikacji
powstanie wiele kompilacji. W rzeczywistości tylko kilka z nich trafia do
użytkowników. Przykład w tabeli 2.2 przedstawia projekt, podczas którego
powstało 178 kompilacji, ale tylko szesnaście edycji (definicja edycji
znajduje się poniżej).
Część I ♦ Projektowanie bazy danych 36

Edycja
Edycja to kompilacja, która zostaje wypuszczona poza zespół programistów.
Zazwyczaj jest ono przekazywane jednemu lub więcej użytkownikom
końcowym.

Nie przejmuj się za bardzo ilością kompilacji. Ich duża ilość nie jest oznaką
słabości procesu rozwoju, lecz ostrożności, z jaką go przeprowadzasz.

Tabela 2.2.
Przykłady edycji

Edycja Kompilacja
Prototyp 1
Prototyp 2
V1.0 Alfa 1 12
V1.0 Alfa 2 27
V1.0 Beta 1 42
V1.0 Beta 2 56
Wersja 1.0 EK1 88
Wersja 1.0 EK2 89
Wersja 1.0 89
Wersja 1.1 EK1 93
Wersja 1.1 93
Wersja 1.2 EK1 97
Wersja 1.2 EK2 98
Wersja 1.2 98
Wersja 2.0 135
Wersja 3.0 178

Tworzenie nowej kompilacji (rysunek 2.6) należy rozpocząć od zebrania w jedną całość zmian i dodatków od wszystkich
programistów. Czasami ich integracja jest równie prosta jak import nowego raportu do interfejsu bazy danych. Częściej
jednak dodanie nowego formularza lub modułu pociąga za sobą konieczność dokonania zmian w jednym lub więcej
formularzach, aby uwzględnić w nich nowy zestaw funkcji. Może się okazać, że dwóch programistów będzie musiało
połączyć swe siły i zintegrować te zmiany. Po wkomponowaniu w kompilację wszystkich dodatków i zmian możesz zaktu-
alizować nazwę edycji/kompilacji wyświetlaną przez aplikację.

Rysunek 2.6.
Tworzenie kompilacji

Pamiętaj o wstawieniu aktualnej nazwy edycji i kompilacji w startowym for-


mularzu aplikacji oraz formularzu „O programie” otwieranym z poziomu
menu Pomoc. To ułatwia określenie, w której wersji znaleziono błąd.
37 Rozdział 2. ♦ Planowanie procesu rozwoju

Przykładowo: „Wersja 1.0 edycja 89 – 2/24/2000”.

To także idealny moment na wykonanie kopii zapasowej całej kompilacji. Kopia ta powinna zawierać zarówno bazę
danych, jak i wszystkie pliki, które uległy modyfikacji przy przejściu z jednej kompilacji do drugiej. Ponieważ w projekt
włożono już znaczące zasoby i czas, warto sporządzić tę kopię na osobnym nośniku.

Aby upewnić się, że poszczególne części właściwie ze sobą współpracują, po stworzeniu nowej kompilacji każdorazowo
powinieneś przeprowadzać testy integralności. Po stwierdzeniu, iż nowa kompilacja działa bez zarzutu, powinieneś
dostarczyć je każdemu członkowi zespołu. Umieść kopię aplikacji w ogólnodostępnym katalogu, by każdy z programistów
i testerów miał do niego dostęp. Jeśli to możliwe, skorzystaj z funkcji narzędzia służącego do kontroli wersji, takiego jak
Microsoft Visual SourceSafe. Dzięki temu będziesz mógł budować i śledzić tworzone kompilacje, a także ograniczyć
problemy powstające na skutek zmian dokonywanych przez kilku programistów.

Jeśli nie korzystasz z Visual SourceSafe, procedury archiwizacyjne stają się


jeszcze ważniejsze.

Niektóre kompilacje powstają na różnych etapach procesu rozwoju (patrz przykłady w tabeli 2.2 i na rysunku 2.8). Podczas
fazy koncepcyjnej lub zbierania wymagań dobrze jest stworzyć jeden lub kilka prototypów, które pozwolą użytkownikom
ocenić wygląd proponowanego GUI. Później, gdy kilka z podstawowych opcji już działa, bardzo przydatnym może okazać
się przekazanie jednemu lub dwa użytkownikom edycji alfa. Dzięki temu będziesz znał ich opinię, co może pozwolić Ci
znacznie zmniejszyć ryzyko niepowodzenia. Gdy aplikacja jest już prawie gotowa, dostarczenie użytkownikom do testów
wersji beta znacznie podwyższy jakość produktu końcowego. Większość z tych edycji powstaje dla każdej z głównych
wersji (duże zmiany) i mniejszych poprawek (małe zmiany). Przed wypuszczeniem ostatecznej wersji warto też oddać
użytkownikom do testów jedną lub kilka edycji-kandydatek (EK1, EK2 i tak dalej).

Aby utworzyć edycję, weź prawidłowo działającą kompilację i przygotuj pakiet instalacyjny. Czynność ta może być tak
prosta jak spakowanie interfejsu bazy danych albo tak skomplikowana jak stworzenie profesjonalnego skryptu
instalacyjnego przy użyciu zawartego w Office 2000 Developer’s Edition narzędzia instalacyjnego. W obu przypadkach,
edycja powinna być przetestowana na kilku komputerach, aby upewnić się, że działa bez zarzutu (rysunek 2.7).

Gdy produkt z pozytywnym wynikiem przejdzie fazę testów, przekaż go do zainstalowania użytkownikom. Do każdej wersji
dołącz „Informacje o edycji”. Wylicz w nich nowe opcje, zmiany i znane problemy. Nawet jeśli użytkownik nigdy ich nie
przeczyta, przydają się one programistom, gdyż czytając je, wiedzą, co w danej edycji zostało zmienione. Nie zapomnij o
aktualizacji dokumentacji użytkownika, za każdym razem, gdy dokonujesz zmian w aplikacji. Nieaktualna dokumentacja jest
gorsza niż całkowity jej brak.
Rysunek 2.7.
Tworzenie edycji

W czasie trwania projektu utworzonych zostanie wiele edycji i kompilacji. Na rysunku 2.8 przedstawiono przykład cyklu,
w którym tworzone są edycje i kompilacje. Każda kompilacja daje programistom, testerom, a czasami nawet
użytkownikom okazję do przetestowania aplikacji i podzielenia się z resztą zespołu swoimi uwagami i spostrzeżeniami.
Nazywane są one często usterkami lub problemami. W zależności od ich ważności w stosunku do kontynuacji rozwoju
aplikacji poprawienie ich następuje już w następnej kompilacji lub też odkładane jest na później.
Część I ♦ Projektowanie bazy danych 38

Rysunek 2.8.
Przykład cyklu
kompilacji i edycji

Szczegółowy projekt
Mimo iż w większości opcji i zadań sposób ich implementacji w aplikacji jest oczywisty, zdarza się (w pięciu do dwudziestu
procent przypadków), że wymaga to chwili zastanowienia. Do typowych przykładów należą moduły, formularze nawigacyjne,
skomplikowane algorytmy i rzadkie techniki automatyzacyjne. Projekt takich opcji lub zadań powinien być w jakiś sposób
udokumentowany. Pozostaw po swoich decyzjach i sposobie ich uwzględnienia w projekcie jakiś ślad. Może on przydać
się tobie lub komuś innemu, gdy nadejdzie potrzeba dokonania pewnych zmian. Zachowaj dokumentację dotyczącą pro-
jektu do czasu, gdy wyjaśnione zostaną wszelkie wątpliwości.

Doskonałym sposobem na opisanie niestandardowych algorytmów jest umie-


szczenie w procedurze lub funkcji komentarzy w pseudokodzie. Pseudokod
jest to uproszczony kod VBA, dołączony jako komentarz opisujący
implementowany w danym miejscu kodu proces. Dokładna składnia nie jest
ważna. Opisujesz jedynie algorytm użyty w VBA. Poniższy przykład
przedstawia użycie pseudokodu w nagłówku procedury.
Public Sub ProcessAllUpdates()
' Comments : Get the updated mail from MAPI Inbox,
' unattatch it and update the current database.
' Parameters : <none>
' Returns : <none>
' Created : Tuesday, July 27, 1999 11:44 PM by Joe Developer
' Pseudo Code :
' --------------------------------------------------------------
' Sub ProcessUpdates()
' UpdateCount = 0
' UnattatchAllUpdates()
' Open a recordset from tblDownloadReceivedResults
' For each <Update file> in Recordset
' ProcessOneUpdate()
' If succesful Then
' Delete Update file
' Increment(UpdateCount)
' Next
' --------------------------------------------------------------
39 Rozdział 2. ♦ Planowanie procesu rozwoju

Kontrola projektu
Kontrola projektu polega na skonsultowaniu problemów wynikłych podczas tworzenia projektu oraz sposobów ich
rozwiązania z osobami trzecimi. Konsultacja ta może być całkiem nieformalna, ale równie dobrze może przybrać formę
oficjalnej prezentacji podczas zebrania członków zespołu. Często zdarza się, że podczas opisywania projektu innym
osobom zauważasz nowe problemy lub lepsze rozwiązania. Inny programista często znajduje to, co Ty przeoczyłeś. To
doskonały moment, by wykryć błędy w aplikacji, zanim rozpoczniesz czasochłonne kodowanie i testowanie.

Tworzenie aplikacji
Tworzenie aplikacji jest tym etapem procesu rozwoju, który klientom, użytkownikom i niedoświadczonym programistom
kojarzy się z procesem pisania programu. Podczas tej fazy powstają formularze i raporty oraz pisany jest kod programu.
Większość rozdziałów tej książki obejmuje zagadnienia związane z tą fazą procesu rozwoju.

Kontrola aplikacji
Kontrola aplikacji (lub kodu programu) przypomina kontrolę projektu, z tą różnicą, że dotyczy efektów jego wdrożenia.
Zazwyczaj kontrola tworzonych formularzy, raportów, kwerend, a także kodu programu niesie ze sobą wiele korzyści.
Podobnie jak to miało miejsce w przypadku kontroli projektu, przez samo opisywanie tego, co zrobiłeś i jak to działa,
zauważasz elementy, które wcześniej przeoczyłeś. Osoba trzecia, patrząc na Twoją pracę, może zauważyć coś, co
pominąłeś. Ty lub osoba, z którą konsultujesz aplikację, możecie odnaleźć błędy powstałe w trakcie jej tworzenia, w jej
projekcie, architekturze lub wymaganiach klienta. Pamiętaj, że im wcześniej błąd jest odnaleziony, tym mniej kosztuje jego
naprawienie.

Kontrole kodu programu przynoszą dodatkową korzyść w postaci podnoszenia umiejętności programistów. Aby to osiągnąć,
poproś doświadczonych programistów, by kontrolę kodu programu zlecali nowym lub mniej doświadczonym członkom
zespołu. Inną korzyścią jest poznanie przez programistów części aplikacji pisanych przez ich kolegów.

Konsekwentne używanie standardów nazewnictwa i kodowania znacznie


ułatwia i skraca proces kontroli kodu programu. Pozwala także uniknąć
dyskusji na temat przewagi jednych stylów nad innymi.

Jeśli jesteś samotnym programistą (chodzi nam oczywiście o to, że nie pra-
cujesz w zespole), znajdź innego programistę i dokonujcie wzajemnej
kontroli kodu. Poświęcony temu czas szybko się wam zwróci. Bardzo
pomocne mogą być tu grupy użytkowników.

Testowanie
Testowanie w procesie rozwoju odbywa się na kilku poziomach: jednostki, aplikacji, konfiguracji i instalacji.

Testowanie modułu
Przed rozpoczęciem tworzenia opcji lub obiektu zastanów się, jak zamierzasz je testować. Po utworzeniu danego elementu
przeprowadź zaplanowane testy, aby sprawdzić, czy jego działanie jest zgodne z Twoimi intencjami oraz czy można ten
element dołączyć do reszty aplikacji. Z doświadczenia wiemy, iż 20% czasu tworzenia aplikacji powinno się poświęcić na
testowanie wszystkich opcji i obiektów. Przykładowo, jeśli poświęciłeś siedem godzin na opracowanie algorytmu i trzy
godziny na napisanie go i usunięcie błędów, to można założyć, że testowanie go powinno zabrać Ci około dwóch godzin.

Jeśli testujesz podprogram, funkcję lub moduł, przetestuj wszystkie możliwe parametry wejściowe, poprzez wprowadzenie
zarówno oczekiwanych, jak i nieoczekiwanych wartości. Podczas testowania nowego formularza upewnij się, że sprawdziłeś,
czy wszystkie

formanty działają poprawnie. Przede wszystkim sprawdź, czy prawidłowo funkcjonują: kontrola poprawności
wprowadzanych danych, zablokowane pola, kolejność klawisza Tab, wstawianie nowych rekordów, jednolitość stylów i
poruszanie się po formularzu.
Część I ♦ Projektowanie bazy danych 40

Testowanie aplikacji
Testowania aplikacji (lub systemu) dokonuje się na całej aplikacji po umieszczeniu w niej wszystkich opcji. Istnieje kilka
przyczyn uzasadniających wykonywanie tego typu testów. Najważniejszą z nich jest stwierdzenie, czy aplikacja
uwzględnia wszystkie wymagania zgłoszone przez klienta. Drugą z przyczyn jest określenie, w jakim stopniu aplikacja jest
gotowa do wypuszczenia jej na rynek.

Oto przykłady testów, które powinieneś wykonać:


u Przetestuj zachowanie aplikacji, gdy tabele są puste.
u Sprawdź różne rozdzielczości ekranu.
u Przetestuj oba ustawienia rozmiaru czcionki we Właściwościach ekranu systemu Windows (Małe czcionki i Duże
czcionki).
u Zastosuj kilka różnych zestawów kolorów we Właściwościach ekranu systemu Windows.
u Sprawdź, jak wyglądają wydruki na kilku różnych drukarkach (uwzględnij zwłaszcza markę i model drukarki
posiadanej przez klienta).
u Przetestuj aplikację zarówno z włączoną jak i wyłączoną opcją Autoukrywanie paska Narzędzi systemu Windows.
u Sprawdź, czy pomoc „Co to jest?”, etykietki narzędzi i pasek stanu odpowiadają właściwym polom.
u Sprawdź kolejność klawisza Tab na każdym formularzu.
u Upewnij się, że klawisze skrótu na każdym formularzu są identyczne.
u Przetestuj na każdym formularzu działanie klawiszy domyślnych (Enter i Esc).
u Sprawdź jednolitość stylów na każdym formularzu i raporcie.

Testowanie instalacji i konfiguracji


W rzeczywistości rzadko się zdarza, by komputery użytkowników były takie same jak komputery programistów. Używają
one innego oprogramowania, ilość pamięci jest różna, często korzystają z dziwnych drukarek i jeszcze dziwniejszych kart
graficznych. Innymi słowy, komputery użytkowników czynią życie programistów ciekawszym. Ta różnorodność
konfiguracji ma duży wpływ na łatwość instalacji aplikacji, a także na jej późniejsze działanie. Jeśli to możliwe, postaraj się
przetestować aplikację w najgorszym środowisku, jakie możesz sobie wyobrazić. W przypadku większych projektów rozważ
wykorzystanie do tego celu wyspecjalizowanej firmy. Oferują one laboratoria przepełnione zarówno nowym, jak i starszym
sprzętem oraz oprogramowaniem.

Instalację i sprawdzenie funkcjonowania aplikacji przeprowadź zarówno na


„czystym”, jak i na „brudnym” komputerze. Przez „czysty” komputer rozu-
miemy taki, gdzie na niedawno sformatowanym dysku zainstalowano tylko
system operacyjny i niezbędne oprogramowanie (tak jak na fabrycznie
nowym komputerze). „Brudny” komputer to taki, na którym w dłuższym
okresie czasu instalowano wiele wersji różnych aplikacji. Testowanie
aplikacji na obu rodzajach komputerów pozwoli odnaleźć nieoczekiwane
problemy związane z plikami typu DLL, ustawieniami rejestru, szablonami i
innymi wspomagającymi plikami. Do szybkiego odtwarzania różnych
konfiguracji komputera warto użyć oprogramowania służącego do
sporządzania obrazu dysku.

Nie oczekuj, że przeprowadzenie testów pozwoli Ci odkryć wszystkie błędy.


Większość aplikacji jest zbyt skomplikowana, aby można było przetestować
każdą możliwą kombinację wartości danych i ścieżek wykonywania. Dlatego
właśnie tak ważne są wcześniejsze działania, czyli określenie wymagań,
planowanie oraz kontrole projektu i aplikacji. Stanowią one pierwszy i
jednocześnie najlepszy sposób na wyeliminowanie błędów. Dużo łatwiej jest
zapobiegać usterkom przez dokładne projektowanie niż odnajdywać je i
usuwać później.
41 Rozdział 2. ♦ Planowanie procesu rozwoju

Odnajdywanie usterek
Przez usterkę rozumiemy każdy błąd, niedociągnięcie bądź problem związany z funkcjonowaniem aplikacji. Może to być
błąd w dokumencie, narzędziu bądź we wdrożeniu aplikacji. Usterki mogą być odnajdywane na każdym etapie procesu
rozwoju i wszystkie powinny być zgłaszane.

Każda z poniższych czynności może ukazać istniejące usterki:


u Kontrola projektu i aplikacji – usterki odkryte w fazie kontroli to zarówno niezgodność z przyjętymi standardami
jak i usterki w samym projekcie.
u Kontrola dokumentów – podczas kontroli dokumentów można odkryć wiele potencjalnych usterek. Może
brakować dokumentu zawierającego wymagania lub mogą być one niewłaściwie zdefiniowane. Dokumentacja
projektu może nie obejmować wszystkich wymagań lub po prostu zawierać błędy.
u Testowanie – najczęstszymi usterkami wykrywanymi w tej fazie są błędy w kodzie programu. Można wówczas
również odkryć błędy w dokumentacji, gdyż to właśnie na jej podstawie testy powinny się odbywać.
u Obsługa klienta – podczas testowania wersji beta lub po dostarczeniu aplikacji do klienta błędy stwierdzone przez
użytkowników zostaną przekazane bezpośrednio do programisty lub personelu zajmującego się obsługą klientów.
System zbierania informacji o błędach powinien także dawać użytkownikom możliwość zgłaszania pomysłów
ulepszenia aplikacji.
u Obsługa błędów – jeśli używasz automatycznego zgłaszania błędów, które opisaliśmy w rozdziale 13.
„Profesjonalna obsługa błędów”, informacje o błędach mogą być przesyłane pocztą elektroniczną lub zapisywane
w specjalnym pliku na komputerze klienta.

Niezależnie od tego, z jakiego źródła pochodzi informacja o błędzie oraz kto ją zgłasza, musi ona być udokumentowana.
Wszystkie informacje o błędach przechowuj w jednym miejscu. Informacje umieszczone na różnych kartkach czy w e-
mailach możesz zgubić lub zwyczajnie o nich zapomnieć. Możesz używać dostępnego w sprzedaży narzędzia służącego do
śledzenia błędów, stworzyć osobną bazę danych w Accessie lub zapisywać usterki na komputerze przenośnym.

Jakkolwiek przechowujesz informacje o błędach, będziesz potrzebował procesu zapewniającego, że każda usterka jest
analizowana. Zauważ, że „analizowana” nie musi koniecznie oznaczać „naprawiana”. Może się zdarzyć, że w zależności od
tego jak poważny jest błąd i jak często występuje, zdecydujesz się go nie naprawiać.

Każda usterka powinna przejść ten sam proces, począwszy od jej stwierdzenia aż do rozwiązania.
1. Zaraz po odkryciu błędu informacje o nim wprowadź do systemu kontroli błędów. Tabela 2.3 zawiera listę
informacji, które według nas powinieneś zbierać. W tabelach od 2.4 do 2.8 znajdziesz dalszy opis informacji o
usterkach.
2. Zespół programistów powinien co pewien czas przejrzeć nierozpatrzone usterki i określić ważność każdej z nich.
Decyzja ta powinna być oparta na wadze, częstości występowania i powtarzalności każdej usterki. Następnym
krokiem jest przydzielenie zadania rozwiązania problemu jednemu z programistów.
3. Programista naprawia usterkę lub stwierdza, że nie zaszła taka konieczność. Do niego należy także uaktualnienie
opisu i statusu rozwiązania problemu. Jeśli usterka została zlikwidowana, status rozwiązania problemu zostanie
zmieniony na „poprawiono”.
4. Jeśli to możliwe, inny członek zespołu sprawdza wszystkie poprawione błędy. Wówczas status rozwiązania
problemu zmieniany jest na „sprawdzono”.

Tabela 2.3.
Informacje o usterkach

Pole danych Opis


Unikatowy identyfikator Można używać kolejnych liczb. Jeśli informacje o usterkach
wprowadza kilka osób, upewnij się, że liczby te się nie powtarzają
Opis usterki Opisz wygląd potencjalnego błędu, łącznie z kodami błędów
i sposobem działania, który do jego wystąpienia prowadzi
Znalezione przez Nazwisko osoby zgłaszającej usterkę
Kiedy znaleziono Data i godzina odkrycia
Oczekiwane rezultaty Co miało się stać?

Tabela 2.3.
Informacje o usterkach (ciąg dalszy)
Część I ♦ Projektowanie bazy danych 42

Pole danych Opis


Gdzie odnaleziono Sporządź listę dokumentów i elementów programu, których zgłaszane
usterki mogą dotyczyć (na przykład: dokument zawierający informacje
o wymaganiach, dokumentacja dotycząca architektury, nazwa
formularza, nazwa raportu, nazwa modułu)
Wersja Określ wersję dokumentu lub bazy danych (na przykład: Beta 2.1,
kompilacja 36, dokument dotyczący wymagań z dnia 29/06/2000
i tak dalej)
Oprogramowanie i konfiguracja Sporządź listę istotnych informacji dotyczących konfiguracji
komputera komputera, jak rozdzielczość ekranu, ilość wyświetlanych kolorów,
ilość pamięci, wolna przestrzeń dyskowa, system operacyjny,
jednocześnie używane oprogramowanie i tak dalej
Waga Jak poważny jest wykryty problem? Patrz tabela 2.4
Częstotliwość Jak często błąd występuje? Patrz tabela 2.5
Powtarzalność Jak łatwo doprowadzić do ponownego wystąpienia błędu? Patrz
tabela 2.6
Ważność Jak ważne jest naprawienie tej usterki? Patrz tabela 2.7
Osoba odpowiedzialna Który z programistów zajmie się rozwiązaniem tego problemu?
Status rozwiązania problemu Jaki jest status usterki? Patrz tabela 2.8
Opis rozwiązania problemu W jaki sposób „poprawiono”? Dlaczego „odłożono na później” lub
„zignorowano”?

Tabela 2.4.
Waga usterki

Waga Kryteria
Krytyczna Niepełny zestaw funkcji bądź utrata danych
Poważna Opcja nie działa tak jak zaplanowano; zmniejszenie użyteczności.
Przeciętna Powoduje, iż aplikacja zawiesza się, lecz nie w sposób krytyczny; nie
następuje utrata danych
Niska Kosmetyczny problem lub prośba o ulepszenie danej opcji

Tabela 2.5.
Częstotliwość występowania

Częstotliwość Kryteria
Powszechna Użytkownik podczas normalnego korzystania z aplikacji z łatwością
zauważy usterkę, co najmniej raz za każdym użyciem. (Na przykład:
zamykając główny formularz)

Tabela 2.5.
Częstotliwość występowania (ciąg dalszy)

Częstotliwość Kryteria
Okazjonalna Jest mało prawdopodobne, by użytkownik trafiał na usterkę za każdym
razem, gdy używa produktu, lecz prawdopodobnie kiedyś ją zauważy.
(Na przykład: usterka występuje tylko podczas drukowania
dwustronicowej faktury)
Rzadka Bardzo mała część użytkowników zauważy tę usterkę. (Na przykład:
usterka dotyczy tylko określonych kart graficznych)

Tabela 2.6.
Powtarzalność usterki

Powtarzalność Kryteria
Zawsze Usterka powtarza się zawsze.
43 Rozdział 2. ♦ Planowanie procesu rozwoju

Nieciągła Usterka zwykle występuje, ale nie zawsze.


Raz Usterkę zaobserwowano raz, nie przeprowadzono dalszych testów
powtarzalności.
Niepowtarzalna Usterkę zaobserwowano raz i nie udało jej się powtórzyć.

Tabela 2.7.
Ważność naprawienia usterki

Ważność Opis
Krytyczna Musi zostać naprawiona
Wysoka Powinna zostać naprawiona, jeśli to tylko możliwe
Przeciętna Naprawić, jeśli starczy czasu
Przełożyć na później Nie trzeba naprawiać w tym momencie

Tabela 2.8.
Rozwiązanie problemu

Rozwiązanie Opis
Nie rozwiązano Problem nowy i jeszcze nie analizowany
Zignorowano Element działa tak, jak zaplanowano
Odłożono na później Problem nie zostanie rozwiązany w tym momencie
Poprawiono Problem został rozwiązany i czeka na sprawdzenie
Sprawdzono Naprawiony element został przetestowany i usterka jest usunięta

Możesz usprawnić proces rozwoju, odnajdując przyczyny leżące u podstaw


powstawania usterek. Określając, jak i gdzie powstała usterka, możesz
znaleźć sposób na uniknięcie tego w przyszłości. Najczęstsze z takich
przyczyn to: błędy w projektowaniu i kodowaniu, braki w wymaganiach lub
niejednoznaczne ich zdefiniowanie, a także niewystarczające przeszkolenie
programistów i klientów.

Kontrola wersji
Istnieje wiele przyczyn, dla których powinieneś w jakiś sposób kontrolować wersje aplikacji w procesie rozwoju. Za
każdym razem, gdy zespół składa się z więcej niż jednego programisty, pojawia się kilka przeszkód. Początkowo
sprawowanie kontroli nad wersjami wydaje się całkiem proste. Wystarczy przechowywać „główną” bazę danych na
serwerze i uważnie przydzielać tworzenie i obsługę obiektów różnym programistom.

Łatwe, prawda? Niestety, jak bardzo byś się nie starał temu zapobiec, pewnym jest, że dwóch programistów dokona
jednoczesnych zmian w tym samym obiekcie. Być może otworzą dany formularz w tym samym momencie i jeden z nich
doda pole, podczas gdy drugi naprawia funkcję. Obydwaj zapiszą zmiany w „głównej” bazie danych. Ten, który to zrobi
jako drugi, wygrywa – nadpisze zmiany zapisane przez pierwszego programistę. Przy odrobinie szczęścia, pierwszy
programista przetestuje swoją pracę i zauważy, że dokonane przez niego zmiany zniknęły. W innym przypadku, problem
zostanie zauważony później. Nie ma nic gorszego niż ponowne wykonywanie tych samych czynności. Jednakże problem
ten może zostać rozwiązany przez monitorowanie i kontrolowanie uprawnień do dokonywania zmian obiektów.

Inną przyczyną, dla której warto wdrożyć kontrolę wersji, jest możliwość identyfikacji i odtworzenia poprzedniej,
działającej wersji aplikacji. Może się zdarzyć, że będziesz chciał sprawdzić, czy dany problem występował we
wcześniejszych wersjach. Odtworzenie poprzedniej wersji przydaje się również, gdy zaplanowane zmiany nie odniosły za-
mierzonych efektów i chcesz je cofnąć. Takie sytuacje zdarzają się niezależnie od rozmiaru zespołu programistów.

Istnieje kilka technik i narzędzi, za pomocą których można rozwiązać problemy związane z kontrolą wersji.
Prawdopodobnie najlepszym rozwiązaniem jest zakup specjalnie do tego przeznaczonego narzędzia. Najpopularniejszym z
nich jest Microsoft Visual SourceSafe, ponieważ program ten jest mocno zintegrowany z Accessem 2000. Możesz także
wdrażać różne metody, aby sprostać wyzwaniom związanym z kontrolą wersji aplikacji.
Część I ♦ Projektowanie bazy danych 44

Aby rozwiązać kwestię współpracy wielu programistów, możesz sporządzić listę współdzielonych obiektów „głównej”
bazy danych. Może to być plik tekstowy lub tabela w Accessie, z której programiści będą mogli sprawdzić, czy dany obiekt
jest w danej chwili dostępny oraz wpisać czas pobrania i zwrotu danego obiektu. Jednak, by metoda ta była skuteczna,
ustalona procedura musi być bez wyjątków przestrzegana.

Innym wyjściem z tej sytuacji jest okresowe sporządzanie kopii zapasowej wszystkich plików powiązanych z aplikacją w
postaci nowego podkatalogu lub pliku typu ZIP. Pamiętaj jednak o tym, by podkatalogom i plikom typu ZIP nadawać
zrozumiałe nazwy, zawierające kompilację, wersję i datę. Proces ten możesz zautomatyzować z poziomu Accessa 2000.

Access różni się od innych narzędzi programistycznych, gdyż zapisuje


wszystkie obiekty w jednym pliku typu MDB. Wiele z dostępnych w sprze-
daży narzędzi do kontroli wersji jest w stanie śledzić jedynie osobne pliki.
Ograniczenie to sprawia, iż każdorazowo zachodzi konieczność pobierania i
zwracania całej bazy danych. Dość nieporęczne, prawda? Upewnij się, że
narzędzie, którego zakup rozważasz, wspiera Microsoft Accessa, śledząc
jego pojedyncze obiekty.
Rozdział 3.
Projekt bazy danych
i normalizacja
W tym rozdziale:
u Relacyjne systemy zarządzania bazami danych.
u Teoria projektowania relacyjnego.

W trakcie tworzenia aplikacji w Accessie 2000 powinieneś przez cały czas pamiętać, że każda z tworzonych przez Ciebie
aplikacji jest bazą danych. Aby tworzyć szybsze i bardziej wydajne aplikacje, musisz poznać i zrozumieć pojęcie
normalizacji baz danych
– temat tego rozdziału. Mimo iż być może miałeś już okazję zapoznać się z normalizacją baz danych na różnych szkoleniach,
powinieneś przyjrzeć się teorii relacyjnej w odniesieniu do Accessa.

Relacyjne systemy zarządzania bazami danych (RDBMS)


W książkach i czasopismach, jakie czytasz, wielokrotnie możesz spotkać się z pojęciem – relacyjne systemy zarządzania
bazami danych (ang. Relational Database Managment Systems – RDBMS). Możesz zapytać, co Access ma wspólnego z
modelem RDBMS. Model ten został stworzony w 1970 roku przez pracownika firmy IBM, dr E.F. Codda. Celem
ustalonych w modelu RDBMS zasad było uniezależnienie funkcjonowania interfejsów od zmian dokonywanych w modelu
danych. Produkty RDBMS używają wspólnych elementów danych, takich jak CustomerID, aby połączyć wiersze w dwóch
różnych tabelach, między którymi zachodziła relacja, a także używają tych pól w sprzężeniu. Istnieje 13 zasad, które
produkt musi spełnić, aby można go było nazwać Relacyjnym Systemem Zarządzania Bazami Danych. Niektórzy z
krytyków Accessa twierdzą, że nie

spełnia on tych wymagań, jednakże ja się z tym nie zgadzam i uważam, że nie jest błędem zaliczenie Accessa do grupy
projektów RDBMS. Oto 13 zasad relacyjnych i ich zastosowanie w Accessie.

Zasady relacyjne dr Codda


Access spełnia wszystkie z 13 zasad relacyjnych dr Codda. Tabela 3.1 zawiera nazwę i opis każdej z nich, a także
komentarz o zastosowaniu tych zasad w Accessie.

Tabela 3.1.
Zasady relacyjne dr Codda

Zasada
Nazwa zasady Opis Komentarz dotyczący Accessa
dr Codda
Zasada 0. Zasada tworzenia Każdy program typu RDBMS musi Access był pierwszą na rynku,
być w stanie zarządzać bazami danych działającą w systemie Windows
jedynie za pomocą swoich zdolności bazą danych, która przestrzegała
relacyjnych. Jeśli system działa na tej zasady. Access,
zasadach operowania danymi rekord- w przeciwieństwie do niektórych
po-rekordzie, nie możemy go nazywać systemów, nie stosuje numeracji
Część I ♦ Projektowanie bazy danych 46

systemem w pełni relacyjnym rekordów


Zasada 1. Informacja Wszystkie dane w relacyjnej bazie Access przechowuje dane jako
przedstawiane są jako wartości tabele, w aparacie baz danych Jet
w tabelach. Dane nie mogą być
przechowywane w żaden inny sposób
Zasada 2. Gwarantowany Poprzez użycie kombinacji wartości Access przestrzega tej zasady
dostęp klucza podstawowego, nazwy tabeli poprzez użycie kluczy głównych.
i nazwy kolumny, musi istnieć dostęp Jeśli sam nie utworzysz w tabeli
do dowolnej partii danych klucza głównego, Access zażąda,
abyś to zrobił
Zasada 3. Brakujące Program musi obsługiwać wartości Access obsługuje wartości Null
informacje Null. Wartości te przedstawiają dla brakujących informacji.
brakujące lub bezużyteczne informacje Jednocześnie pozwala uniknąć
wprowadzania wartości Null
poprzez użycie pól wymaganych.
Zasada 4. Katalog systemu Opis bazy danych lub „katalog” na Katalog ten umieszczony jest
poziomie logicznym jako wartości w aparacie bazy danych
tabelaryczne. Język relacyjny (SQL) Microsoft Jet. Do stworzenia
powinien móc działać na projekcie zapytania dotyczącego katalogu
bazy danych w taki sam sposób, w jaki systemu możesz użyć obiektu
działa na danych przechowywanych Active Data o nazwie
w strukturze OpenSchema (patrz rozdział 5.
„Jet 4.0 – silnik baz danych
Microsoft). SQL DDL daje Ci
możliwość tworzenia tabel,
indeksów itp.

Tabela 3.1.
Zasady relacyjne dr Codda (ciąg dalszy)

Zasada
Nazwa zasady Opis Komentarz dotyczący Accessa
dr Codda
Zasada 5. Kompletny język Program typu RDBMS musi Access (Jet) w pełni obsługuje
obsługiwać jasno określony język SQL dla operowania danymi,
do operowania danymi (SQL), który określania widoków (kwerendy
w pełni obsługuje definiowanie wybierające) i ograniczeń
i operowanie danymi, określanie integralności (Okno Relacje
widoku, ograniczenia integralności, i komenda UTWÓRZ
ograniczenia transakcyjne OGRANICZENIE)
i autoryzację
Zasada 6. Uaktualnianie Wszystkie widoki mogą być Access był pierwszą bazą
widoków systemowo uaktualnione. danych, umożliwiającą użycie
W prawdziwym programie typu kwerend aktualizujących
RDBMS, większość (ale nie
wszystkie) widoków może być
uaktualniana
Zasada 7. Ustawianie Program typu RDBMS musi nie tylko Access spełnia to wymaganie
poziomu potrafić pobierać zestawy danych. poprzez użycie kwerend
uaktualnień Musi także potrafić wstawiać, funkcjonalnych
aktualizować i usuwać dane jako
zestaw relacyjny
Zasada 8. Fizyczna Dane i aplikacja muszą być od siebie Access umożliwia Ci
niezależność fizycznie niezależne. Odpowiedni modyfikowanie obiektów bazy
danych program typu RDBMS lub danych, bez konieczności
„optymalizator” powinny móc śledzić dokonywania zmian w reszcie
fizyczne zmiany w danych. aplikacji. Jet zawiera także
Przykładowo, aplikacje RDBMS nie logiczny aparat przechowywania
powinny ulegać modyfikacji na skutek
dodania bądź usunięcia z tabeli
indeksu
Zasada 9. Logiczna Gdy to tylko możliwe, aplikacja Gdy tworzysz w Accessie
niezależność powinna być niezależna od zmian kwerendę, możesz ją z łatwością
danych dokonywanych w tabelach połączyć z formularzem lub
podstawowych. Przykładowo, raportem, jakby to była tabela
d t b l ł id k
47 Rozdział 3. ♦ Projekt bazy danych i normalizacja

gdy tabele są łączone w widok,


nie powinny następować zmiany
w kodzie
Zasada 10. Niezależność Integralność danych musi być Mimo iż Microsoft nie umieścił
integralności definiowalna w języku relacyjnym w dokumentacji informacji na
i przechowywana w katalogu. temat przechowywania
Ograniczenia w integralności danych integralności przez aparat Jet,
mogą być wbudowane w aplikację, możesz tworzyć zasady
jednakże podejście to jest obce dla integralności poprzez SQL.
modelu relacyjnego. W modelu Jet przechowuje te informacje
relacyjnym integralność powinna być w projekcie bazy danych jako
naturalną cechą projektu bazy danych. część katalogu.

Tabela 3.1.
Zasady relacyjne dr Codda (ciąg dalszy)

Zasada
Nazwa zasady Opis Komentarz dotyczący Accessa
dr Codda
Zasada 11. Niezależność Zdolności programu typu RDBMS nie Ponieważ silnik Jet przechowuje
podziału będą ograniczone dzięki umieszczeniu swoje zasady integralności
jego komponentów w osobnych danych na poziomie aparatu,
bazach danych. pozostałe jego komponenty nie
mają wpływu na zasady
integralności.
Zasada 12. Brak podwersji Jeśli program RDBMS posiada język Access umożliwia Ci użycie
typu „jeden rekord jednocześnie”, obiektów DAO i ADO, aby
język ten nie może być używany do operować jednym rekordem
omijania zasad integralności lub jednocześnie poprzez
ograniczeń języka relacyjnego. aktualizowalne zestawy
Dlatego też nie wystarczy, by zasady rekordów. Dzięki tym
relacyjne zarządzały programem typu narzędziom do operowania
RDBMS, ale muszą być prawami danymi nie możesz naruszyć
nadrzędnymi. zasad integralności.

Relacyjne systemy zarządzania bazami danych przeważają w kilku punktach nad innymi systemami, w szczególności w
procesie projektowania. Programy typu RDBMS korzystają z teorii projektowania relacyjnego, aby tworzyć własne modele
projektowe baz danych. Na tym skupimy się w następnej części tego rozdziału.

Teoria projektowania relacyjnego


Teoria projektowania relacyjnego, opracowana przez dr Codda w celu rozbudowania zasad relacyjnych, składa się z
następujących kategorii:
u Tabele i niepowtarzalność.
u Klucze obce i domeny.
u Relacje.
u Normalizacja danych.
u Zasady integralności.

Korzyści z używania modelu relacyjnego


Korzystając z teorii projektowania relacyjnego uzyskujesz zalety płynące z lat poszukiwań najlepszego sposobu
zarządzania danymi. Niektóre z nich, jakie otrzymasz w wyniku normalizacji bazy danych, to:
u Pewność integralności danych.
u Skuteczność przechowywania danych.
u Możliwość rozwoju bazy danych.
u Zachowanie bazy danych jest przewidywalne, gdyż jest ona zgodna z wielokrotnie przetestowanymi zasadami.
u Ponieważ przestrzegasz tych zasad, inni projektanci baz danych mogą dużo łatwiej zrozumieć Twój projekt.
Część I ♦ Projektowanie bazy danych 48

u Okno Relacje staje się samo w sobie dokumentem.


u Zmiany w schemacie bazy danych są łatwe we wdrożeniu.

Tabele i niepowtarzalność
Kiedy tworzysz aplikacje bazy danych, każda tabela przedstawia odrębną jednostkę lub proces występujący w
rzeczywistym świecie. Będziesz tworzył tabele kontrolujące ludzi, wydarzenia, transakcje finansowe i przedmioty (np.
produkty). Zgodnie z teorią relacyjną, musisz przechowywać wszystkie dane w tabelach (zasada 1.) oraz, że tabela składa
się z unikatowych wierszy i kolumn (zasada 2.). Sposobem na zapewnienie unikalności każdej z zasad jest ustawienie
klucza głównego dla każdego wiersza.

Klucz główny to pole lub grupa pól (mówimy wtedy o wielopolowym kluczu głównym), które jest unikatowym
identyfikatorem tego wiersza. Klucz główny musi być unikatowy. W przeciwnym bowiem wypadku dochodziłoby do
naruszenia zasady 2. Access pozwala Ci uczynić pole kluczem głównym, poprzez nadanie mu wartości Klucz w widoku
Projekt tabeli. Access sprawdzi wówczas, czy dane w tym polu są unikatowe i nie występują w nim duplikaty. Czasami,
gdy przestrzegamy reguł handlowych, podanie unikatowej wartości dla każdego wiersza może być trudne. Przykładowo,
możesz utworzyć przedstawiony na rysunku 3.1 system zarządzający kontaktami.

Rysunek 3.1.
Przykładowa,
nieznormalizowana
tabela

Podczas projektowania systemu zarządzającego kontaktami, jako klucz możesz wybrać Nazwisko, Telefon lub e-mail (pola takie
powszechnie nazywane są „polami-kandydatami”). Ogólna zasada projektowania baz danych głosi, że klucz powinien być jak
najprostszy, unikatowy i jak najrzadziej zmieniany. Nazwisko może się zmieniać na skutek zawarcia małżeństwa, rozwodu itp.
Numery telefonów i adresy e-mail zmieniają się ciągle. Dobrym kluczem byłby numer PESEL, ale co, gdy dana osoba nie jest
obywatelem polskim? W tej sytuacji Access umożliwia Ci utworzenie pola Autonumerowanie, które stanie się polem klucza
podstawowego. Autonumerowanie jest samogenerującą się wartością liczbową, która będzie wzrastać z każdym nowym
rekordem. Istnieją dwa typy Autonumerowania:
u Wartości całkowite;
u Id replikacji lub GUID (używany w replikacji). Więcej informacji na ten temat znajdziesz w rozdziale 22.
„Replikacja i JRO”.
Istnieje kilka sposobów na manipulowanie Autonumerowaniem w aparacie
Jet, co nie było możliwe we wcześniejszych wersjach Accessa. Możesz teraz
ustawić wartość, o jaką Autonumerowanie będzie przyrastać, a także sprawić,
by było odliczane wstecz. Więcej szczegółów na ten temat znajdziesz w
rozdziale 5. Mimo iż wartość, o jaką Autonumerowanie przyrasta, może być
kontrolowana, pamiętaj, że Autonumerowanie nie oznacza numeru rekordu.

Klucze obce i domeny


Klucz główny staje się bardzo ważny, gdy chcesz go użyć w innej tabeli. Sytuację taką przedstawiono na rysunku 3.2.

Rysunek 3.2.
Tabela z dwoma
kluczami obcymi

Jak widać na rysunku 3.2, można przechowywać wartość klucza głównego jednej tabeli, aby przedstawiać rekordy w innej
tabeli. Wówczas mówimy o kluczu obcym, który będzie podstawą opisanych w następnej części relacji. Przedstawiona na
rysunku 3.2 tabela trelContactInfo przechowuje dwa obce klucze: ContactID i ContactTypeID. ContactID to klucz główny
tabeli tblContact, a ContactTypeID to klucz główny tabeli tlkpContactType.
49 Rozdział 3. ♦ Projekt bazy danych i normalizacja

Gdy używasz kluczy obcych, będą się one zawsze znajdować w tej samej domenie. Domeny są to zbiory wartości, z
których pobierane są kolumny. Dobrym przykładem jest StudentID. Jego domeną są wszystkie dostępne w systemie
numery PESEL.

Relacje
Gdy definiujesz klucze główne i klucze obce, masz do czynienia z relacjami. Przez relacje rozumiemy zasady obsługiwane
na poziomie silnika bazy danych (patrz: Zasada 4. dr Codda). Access wyróżnia trzy różne typy relacji:
u relacja jeden-do-jednego;
u relacja jeden-do-wielu;
u relacja wiele-do-wielu.

Aby tworzyć relacje w Accessie, naciśnij znajdujący się w na pasku narzędzi przycisk Relacje lub wybierz
Narzędzia⇒Relacje, aby otworzyć okno Relacje.

Relacja jeden-do-jednego
Dwie tabele łączy relacja jeden-do-jednego, gdy każdemu wierszowi z jednej tabeli przyporządkowany jest co najwyżej
jeden wiersz z drugiej tabeli.

Na rysunku 3.3 znajduje się przykład relacji jeden-do-jednego. Ten typ relacji jest najrzadziej spotykany, ponieważ w
większości przypadków możesz powiązane informacje umieszczać w jednej tabeli. Jednakże, ze względów
bezpieczeństwa, możesz zdecydować, iż należy informacje rozdzielić na dwie tabele. Również skomplikowane transakcje
finansowe zawierają wiele relacji jeden-do-jednego.

Rysunek 3.3.
Relacja
jeden-do-jednego

Relacja jeden-do-wielu
Najpopularniejszy typ relacji, relacja jeden-do-wielu, występuje wtedy, gdy tabela ma wiele (lub nie ma w ogóle)
powiązanych rekordów w drugiej tabeli. Przykładem może być relacja Customer do Order lub przedstawiona na rysunku
3.4 relacja Contact do ContactInfo. Czasami tabela po stronie „jeden” nazywana jest tabelą odnośnika. Zazwyczaj, tabele
odnośnika zawierają informacje, które będą przekazywane do innych tabel (na przykład, nazwy województw lub kody
pocztowe). Podczas adaptowania konwencji nazewnictwa dobrze jest dla tabeli odnośnika użyć przedrostka tlkp.

Rysunek 3.4.
Relacja
jeden-do-wielu
Część I ♦ Projektowanie bazy danych 50

Relacja wiele-do-wielu
O relacji wiele-do-wielu mówimy wówczas, gdy każdemu wierszowi z jednej tabeli odpowiada wiele wierszy w drugiej
tabeli, a każdemu wierszowi z drugiej tabeli odpowiada wiele wierszy w pierwszej. Jedynym sposobem na przedstawienie w
Accessie relacji wiele-do-wielu jest użycie tabeli „łączącej”, w której jako klucze obce znajdują się klucze główne obu
tabel.

Rysunek 3.5 przedstawia relację wiele-do-wielu między tabelami tblContact i tlkpContactType, utworzoną za pomocą tabeli
łączącej trelContactInfo. Tabela tblContact zawiera wszystkie kontakty w bazie danych. Tabela tlkpContactType zawiera
sposoby porozumiewania się: Faks, Email, Telefon i Pager. Tabela łącząca zawiera odnośnik do pól Faks i Telefon oraz
Kontaktu, tak więc gdy za pomocą pola Kontakt dodaje się do listy nowy sposób porozumiewania się (jak na przykład adres
sieci Web), możesz w tabeli odnośnika (tlkpContactType) dodać pozycję „Adres sieci Web” i dodać łączący rekord do
tabeli trelContactInfo. To najbardziej elastyczny sposób budowania systemu zarządzania kontaktami, gdyż nie będą
występować puste pola, dajmy na to „Telefon2”. Nie będziesz również musiał dodawać nowych pól, gdy będziesz dodawał
do listy następny sposób porozumiewania się. Gdy korzystasz z tabeli łączącej, najlepiej jest użyć konwencji nazewnictwa
„trel”.

Rysunek 3.5.
Relacja
wiele-do-wielu

Podarkusze danych

Jedną z nowych opcji Accessa 2000 są podarkusze danych – nowy sposób przeglądania powiązanych danych w widoku
arkusza danych. Podarkusze danych, jak ten na rysunku 3.6, są „poszerzonym” widokiem powiązanych danych.
Podarkusze danych automatycznie odczytują relacje w bazie i wyświetlają powiązane tabele. Nie zawsze jest to najlepszy
sposób na przeglądanie powiązanych danych, tak jak to ma miejsce w przypadku przedstawionej na rysunku 3.6 relacji
wiele-do-wielu.

Aby zoptymalizować widok podarkuszy danych, możesz utworzyć kwerendę, która połączy dane z powiązanych tabel tak,
by wyświetlone były opisy, a nie klucze obce. Następnie otwórz tabelę w widoku Projekt i spójrz na właściwości tabeli
(rysunek 3.7). W polu Nazwa podarkusza danych wybierz nazwę utworzonej kwerendy. Być może będziesz również
musiał ustawić właściwości podrzędnego i nadrzędnego pola łączącego, jeśli Access nie rozpozna ich automatycznie.
Rysunek 3.6.
Podarkusz danych
Accessa 2000
51 Rozdział 3. ♦ Projekt bazy danych i normalizacja

Rysunek 3.7.
Właściwości
podarkusza danych

Tabela 3.2.
Właściwości podarkusza danych

Nazwa właściwości Opis


Nazwa podarkusza danych Nazwa kwerendy, która posłuży do wypełnienia podarkusza danych
Podrzędne pola łączące Pole w podrzędnej tabeli (lub kwerendzie), które ma być połączone
z polem w aktualnej tabeli
Nadrzędne pola łączące Pole w aktualnej tabeli, które ma być połączone z polem w podrzędnej
tabeli lub kwerendzie
Wysokość podarkusza danych Wysokość podarkusza danych (w calach)
Rozwinięty podarkusz danych Wartość tak/nie, określająca, czy podczas otwierania tabeli podarkusz
danych ma być domyślnie rozwinięty

Normalizacja danych
Zgodnie z zestawem zasad dr Codda proces projektowania bazy danych nazywany jest normalizacją danych. Dr Codd wyróżnia
sześć poziomów normalizacji. Skoncentrujemy się tutaj na trzech z nich, gdyż mają one największy wpływ na decyzje dotyczące
projektu bazy:
u Pierwsza postać normalna.
u Druga postać normalna.
u Trzecia postać normalna.

Pierwsza postać normalna


W pierwszej postaci normalnej wszystkie kolumny w tabeli muszą posiadać wartości atomowe. Innymi słowy, każde pole
może zawierać tylko jedną wartość, a nie listę wartości lub powtarzającą się grupę danych. Wiele kartotekowych baz
danych przechowuje dane w ten sposób, co znacznie utrudnia ich przeszukiwanie.

Rysunek 3.8 przedstawia przykład tabeli, która nie jest w pierwszej postaci normalnej, ponieważ w kolumnie ContactInfo
przechowywana jest tablica wartości. Rysunek 3.9 jest przykładem tabeli w pierwszej postaci normalnej, gdyż w żadnej z
kolumn nie występują powtarzające się informacje.

Rysunek 3.8.
Tabela jest nie
będąca w pierwszej
postaci normalnej
Część I ♦ Projektowanie bazy danych 52

Rysunek 3.9.
Tabela w pierwszej
postaci normalnej,
ale nie w drugiej
postaci normalnej

Druga postać normalna


Mimo iż tabela przedstawiona na rysunku 3.9 jest w pierwszej postaci normalnej, nie jest jednak w drugiej postaci
normalnej. Mówimy, że tabela jest w drugiej postaci normalnej, gdy jest w pierwszej postaci normalnej i jednocześnie
każde z jej pól nie będących polem klucza głównego jest w pełni zależne od całego klucza głównego. Innymi słowy, część
informacji może być przechowywana w innej tabeli i pobierana z niej poprzez odnośnik. Spójrz na tabelę na rysunku 3.9.
Klucz główny składa się z ContactID, ContactInfoID i ContactInfo. Czy kolumna ContactName zależy od części klucza:
ContactInfoID i ContactInfo? Nie, gdyż jest zależna od pola ContactID. Aby przekształcić tę tabelę do drugiej postaci
normalnej, należy informacje o kliencie umieścić w osobnej tabeli odnośnika i utworzyć pomiędzy tabelami przedstawioną
na rysunku 3.10 relację jeden-do-wielu. Tabele te są teraz w drugiej postaci normalnej.

Trzecia postać normalna


Mimo iż tabele na rysunku 3.10 są w pierwszej i drugiej postaci normalnej, nie są jednak w trzeciej postaci normalnej. Z
tabelą w trzeciej postaci normalnej mamy do czynienia, gdy wszystkie pola, nie będące polami klucza głównego, są
wzajemnie zależne.
Rysunek 3.10.
Tabela jest w drugiej
postaci normalnej,
ale nie w trzeciej
postaci normalnej

Dobrym przykładem zależności jest pole obliczeniowe (korzystniej jest nie przechowywać pól obliczeniowych, tylko
wyświetlać wyniki obliczeń jako część kwerendy). Na rysunku 3.10 druga tabela przechowuje pola ContactInfoID i
ContactType (opis). Jeśli wartość pola ContactType poznajesz dzięki polu ContactInfoID, tabela nie jest w trzeciej postaci
normalnej.

Aby otrzymać trzecią postać normalną, wyodrębnij z ContactInfo trzecią tabelę i utwórz między tabelami ContactInfo i
ContactDetails relację jeden-do-wielu, tak jak na rysunku 3.11.
53 Rozdział 3. ♦ Projekt bazy danych i normalizacja

Rysunek 3.11.
Tabele w trzeciej
postaci normalnej

Korzyści z normalizacji
W poprzednim przykładzie, zyskałeś wiele, normalizując początkową, przedstawioną na rysunku 3.8 tabelę. Tabela
początkowa zawierała sposoby porozumiewania się w tablicy wartości, co prawie całkowicie uniemożliwiało przeszukiwanie
zawartości pola Faks. Dodatkowo, gdy zmieniał się numer telefonu kontaktu lub zachodziła potrzeba dodania nowego
sposobu porozumiewania się, jak na przykład adres e-mail, edycja danych była utrudniona i łatwo było o błędy. Pierwsza
postać normalna znacznie poprawiła sytuację i zwiększyła elastyczność w kontrolowaniu numerów telefonów, faksów i
adresów
e-mail naszych kontaktów.

W przedstawionej na rysunku 3.9 tabeli, która jest w pierwszej, lecz nie jest w drugiej postaci normalnej, zarządzanie
danymi dotyczącymi kontaktów jest utrudnione, gdyż informacje wielokrotnie się powtarzają. Jeśli masz w bazie 10
numerów telefonów i przechowujesz to samo nazwisko 10 razy, to jest to nie tylko strata przestrzeni dyskowej, ale również
problem, gdy zachodzi potrzeba uaktualnienia wszystkich 10 wpisów, gdy dana osoba zmieniła nazwisko. Utrzymanie
spójności w tym przypadku może Cię kosztować dużo wysiłku.

Tabele na rysunku 3.10, mimo iż są w pierwszej i drugiej postaci normalnej (wszystkie kolumny zależą od całego klucza),
nie są w trzeciej postaci normalnej. Przenosząc dane i uzyskując trzecią postać normalną, uzyskujesz większą elastyczność
modelu danych, gdyż teraz możesz zarządzać typami kontaktów w osobnej tabeli.

Zasady integralności danych


Podczas normalizowania danych powinieneś również uwzględnić zasady integralności danych. Większość z zastosowanych
zasad będzie zależeć od zdefiniowanych relacji. Podczas określania relacji możesz dodatkowo ustawić kaskadowe
aktualizowanie i usuwanie rekordów.

Ustawienie aktualizowania kaskadowego rekordów daje Ci pewność, że gdy aktualizujesz wartość klucza podstawowego
tabeli „jeden”, zmiana ta odniesie skutek w tabelach „wielu”. Przykładowo, powiedzmy, że masz tabelę odnośnika dla
Stanów Zjednoczonych. W tabeli tej znajduje się miasto Nowy Jork, z kluczem podstawowym NY i opisem Nowego Jorku.
Wyobraź sobie, że miasto to odłączyło się i stworzyło swój własny stan (to nie jest fikcja, prawie do tego doszło w roku
1789!). Gdy zmienisz wartości NY na NY1 (lub coś bardziej opisowego), wartości NY we wszystkich podrzędnych tabelach
zostaną zmienione na NY1. Jeśli aktualizowanie kaskadowe nie było włączone, musiałbyś dodać rekord NY1 do tabeli
odnośnika, zaktualizować wszystkie rekordy w podrzędnej tabeli, a następnie usunąć z tabeli odnośnika rekord NY.

Włączenie usuwania kaskadowego daje Ci pewność, że gdy usuwasz rekord z tabeli „jeden”, usuniesz również wszystkie
rekordy z tabeli „wielu”. Ma to swoje dobre i złe strony. Jeśli usuwasz jednego z klientów, a usuwanie kaskadowe było
włączone, usunięte zostaną wszystkie faktury po stronie „wielu”. W przeciwnym wypadku, usunięcie rekordu z tabeli
„jeden” nie będzie wykonane, dopóki nie usuniesz wszystkich rekordów z tabeli „wielu”.
Rozdział 4.
Zaawansowane kwerendy
W tym rozdziale:
u Kwerendy w Accesie 2000.
u Tworzenie zaawansowanych kwerend.
u Użycie kwerend.
u Właściwości kwerendy.
u Siatka QBE.
u Panel tabel.
u Siatka kwerendy.
u Kwerendy podsumowujące.
u Użycie kwerend krzyżowych.
u Użycie kwerend parametrycznych.
u Kwerendy przekazujące.
u Kwerendy definiujące dane.
u Optymalizowanie kwerend.

Kwerendy są elementami napędowymi baz danych Accessa. Występują w kilku formach i rodzajach. Mogą być zapisywane
w bazie (jak tabele) lub działać tylko w pamięci komputera. Do ich tworzenia można używać poleceń SQL lub graficznego
interfejsu użytkownika nazywanego tabelą QBE. Kwerenda może zarówno przedstawiać dane w takiej postaci, w jakiej
występują w bazie, jak również przed wyświetleniem grupować je i przeliczać. Kwerenda Accessa może już przed
uruchomieniem wiedzieć, co powinna wykonać lub zadawać użytkownikowi dodatkowe pytania. Kwerendy potrafią także
aktualizować dane, tworzyć i usuwać rekordy, a nawet zmieniać strukturę bazy. Kwerendy w Accessie mogą pracować z
danymi przechowywanymi w plikach typu MDB, innych, przyłączonych do Accessa źródłach danych, a nawet bazach
danych typu klient-serwer (np. Oracle i Microsoft SQL Server). Są one najszybszym i najpewniejszym sposobem
efektywnej interakcji z danymi w relacyjnej bazie danych.

Rozdział ten poświęcony jest zaawansowanym odmianom tego potężnego narzędzia.

Kwerendy w Accesie 2000


Dokładna konstrukcja bazy danych w połączeniu z możliwościami, jakie dają kwerendy, umożliwiają zaspokojenie części
najprostszych, codziennych potrzeb w zarządzaniu danymi. Jednocześnie mogą pomóc w rozwiązaniu najbardziej
złożonych problemów, gdyż relacyjna struktura pozwala na logiczne grupowanie danych. Dzięki temu, pomiędzy
powiązanymi obiektami można tworzyć użyteczne połączenia. W relacyjnej bazie danych masz wgląd w te dane, których w
danym momencie potrzebujesz.

Weźmy za przykład rachunek telefoniczny. Raz w miesiącu operator sieci telefonicznej przysyła Ci rachunek za swoje
usługi, a jeśli sobie tego zażyczysz – szczegółowy wykaz rozmów. Wykaz ten zawiera wszystkie informacje o
przeprowadzonych w poprzednim miesiącu rozmowach telefonicznych: datę, godzinę, numer telefonu osoby, do której
dzwoniłeś, czas trwania rozmowy, ilość naliczonych impulsów oraz całkowity koszt rozmowy. To bardzo dużo informacji,
55 Rozdział 4. ♦ Zaawansowane kwerendy

jednakże na podstawie samego wykazu trudno jest odpowiedzieć na najbardziej nawet podstawowe pytania. Dużo
wygodniej byłoby móc połączyć go z książką adresową. Gdyby to było możliwe, mógłbyś dokładnie stwierdzić, do kogo
dzwoniłeś, kiedy to było i ile Cię ta rozmowa kosztowała. Mógłbyś wówczas obliczyć, ile pieniędzy wydałeś na rozmowy
z pracownikami danego klienta i na jaką kwotę należy poszczególnych klientów obciążyć.

Mogłoby się wydawać, że takiej obróbki danych można dokonać przy użyciu innych narzędzi niż relacyjna baza danych.
Jednakże z prawidłowo zaprojektowaną bazą danych obróbka ta będzie banalnie łatwa, wiarygodna i szybka.

Tworzenie zaawansowanych kwerend


Kwerendy, podobnie jak tabele i formularze, są obiektami bazy danych i przechowywane są w znajdującej się w głównym
oknie bazy grupie Kwerendy (skróty do nich mogą być przechowywane w dowolnej, stworzonej przez programistę grupie).

Tworzenie kwerend wymaga ustalenia różnych właściwości, które nadzorują sposób, w jaki kwerend, się zachowuje
podczas jej uruchamiania. Możesz zacząć od samej kwerendy.

Wszystkie zapisane kwerendy możesz przeglądać, klikając obiekt Kwerendy znajdujący się w oknie Grupy głównego okna
bazy danych. Kliknięcie prawym przyciskiem myszy którejś z pojedynczych kwerend powoduje wyświetlenie
odpowiadającego jej okna dialogowego Właściwości (rysunek 4.1).
Rysunek 4.1.
Okno dialogowe
Właściwości
wybranej kwerendy

Użycie kwerendy
Podobnie jak w przypadku wszystkich innych obiektów baz danych Accessa możesz stosować nazwy o długości nie
przekraczającej 255 znaków. Również wszystkie konwencje nazewnictwa używane w przypadku pozostałych obiektów
mają zastosowanie do kwerend. Okno Właściwości zawiera także informacje o typie danej kwerendy. Możesz tam również
znaleźć jej opis. Jest to bardzo ważna właściwość. Staranny projektant baz danych powinien z niej korzystać tak często, jak
tylko to możliwe. Porządny opis umożliwi Ci stwierdzenie, jaką czynność dana kwerenda miała wykonać. Również inni
programiści docenią wagę opisu, gdy przyjdzie im pracować z utworzoną przez Ciebie kwerendą. Okno Właściwości
zawiera także datę utworzenia kwerendy oraz datę ostatniej modyfikacji, automatycznie aktualizowaną przez Access.
Zgodnie z domyślnym ustawieniem właścicielem kwerendy jest osoba, która ją utworzyła. Ma to znaczenie dla za-
bezpieczeń bazy (temat ten został szczegółowo omówiony w rozdziale 23., „Bezpieczeństwo”). Na dole okna znajdują się
dwa pola wyboru. Zaznaczenie pola Ukryty spowoduje, iż obiekt ten nie będzie widoczny dla użytkowników w głównym
oknie bazy danych. Dzięki temu będziesz mógł zapobiec przypadkowym zmianom tego obiektu.

Pole wyboru Replikowalny informuje, czy dany obiekt jest elementem schematu replikacji, który przygotowałeś dla bazy
danych. Mówimy, że obiekt jest replikowalny, gdy poprzez operację replikacji jest modyfikowany przez inny obiekt,
najczęściej bardziej aktualną wersję samego siebie. Więcej informacji o replikacji znajdziesz w rozdziale 22. „Replikacja i
JRO”.

Innym sposobem na ukrycie kwerendy przed uczestnikami jest umieszcze-


nie na początku jej nazwy liter USYS (np. USYS_myquery). Aby prze-
glądać takie obiekty, musisz w menu Narzędzia otworzyć okno dialogowe
Opcje i zaznaczyć pole wyboru Obiekty systemowe.
Część I ♦ Projektowanie bazy danych 56

Microsoft również ukrywa różne obiekty, używając do tego celu przedrost-


ka MSYS. Nie możesz dopuścić, by użytkownicy uzyskali dostęp do tych
tabel systemowych, bo ich zmiana może doprowadzić do uszkodzenia bazy.
Również programiści powinni unikać używania ich, gdyż Microsoft nie
gwarantuje umieszczenia ich w kolejnej wersji. Upewnij się, że tabele
systemowe są ukryte, zanim przekażesz bazę do rąk użytkowników.

Właściwości kwerendy
Ponieważ zachowanie kwerendy zależy bezpośrednio od ustawień właściwości, ważnym jest zrozumienie, czym te właściwości
są i jak funkcjonują. Tak więc, zanim przejdziemy do zaawansowanych opcji kwerend, przyjrzyjmy się podstawowym
kwerendom i określeniom, jakich będziemy używać podczas projektowania bardziej zaawansowanych kwerend.

Siatka QBE
Access ułatwia Ci tworzenie kwerend, umożliwiając graficzne ich ułożenie w siatce QBE (rysunek 4.2). Wszystkie źródła
danych, niezależnie od tego czy są to wbudowane czy dołączane tabele, albo nawet inne kwerendy wybierające, mogą być
w taki sam sposób rozmieszczane w siatki QBE. W interfejsie siatki QBE znajdują się relacje między tabelami (tabele i
kwerendy wyglądają w niej tak samo), polecenia sortowania i grupowania oraz kryteria.

Rysunek 4.2.
Siatka QBE
podzielona jest na
dwie podstawowe
części: panel
z tabelami u góry
i siatkę kwerendy
u dołu

Kliknij prawym przyciskiem myszy w dowolnym miejscu okna panelu tabel. Z kontekstowego menu wybierz Właściwości,
aby wyświetlić właściwości kwerendy. Oto lista wszystkich właściwości kwerendy:
u Opis – taka sama właściwość dostępna jest z poziomu obiektu.
u Wyprowadź wszystkie pola – ustawienie tej właściwości na Tak powoduje ten sam skutek co zaznaczenie opcji
Pokaż w każdym polu kwerendy. Dzięki temu również wszystkie pola danej kwerendy są dostępne dla innych
kwerend, formularzy i raportów.
u Najwyższe wartości – jeśli chcesz zobaczyć tylko 5 najdroższych produktów, ustaw tę właściwość. Możesz
używać również wielkości procentowych. Właściwość ta umożliwia wybranie górnych 5, 10, 25 lub 100 rekordów
(albo 5% bądź 25%), lecz możesz ustawić tę opcję w dowolny sposób. Właściwość ta jest stosowana do pola,
które w siatce QBE znajduje się najbardziej z lewej strony. Jeśli w kwerendzie, od lewej do prawej znajdują się
trzy pola ([nazwa produktu], [koszt jednostkowy] i [cena hurtowa]) i chcesz zobaczyć pięć najdroższych produktów,
według [ceny hurtowej], musisz pole [cena hurtowa] posortować malejąco. Jeśli pole [cena jednostkowa] również
posortujesz, pięć górnych elementów będzie wyświetlonych na bazie pola [cena jednostkowa]. Jeśli żadne z pól
nie jest posortowane, pięć pierwszych rekordów będzie przedstawionych bez sortowania.
u Wartości unikatowe – właściwość ta umożliwia otrzymanie reprezentatywnej listy wartości danego pola. Jeśli
podczas pracy z tabelą Zamówienia chcesz zobaczyć, które produkty zostały zamówione, możesz użyć tej
właściwości, aby z setek zamówień wyodrębnić kilkadziesiąt produktów.
u Rekordy unikatowe – właściwość ta jest podobna do właściwości Wartości unikatowe, z tą jednak różnicą, że działa
na wielu polach. Wynik kombinacji tych pól musi być unikatowy.
u Uaktywnij uprawnienia – podczas zabezpieczania bazy danych musisz mieć możliwość zablokowania tabel w taki
sposób, aby użytkownicy nie mogli ich edytować bez Twojej kontroli. Jednocześnie, użytkownicy będą musieli
mieć możliwość pracować z tymi tabelami i zawartymi w nich danymi. Poprzez ustawienie tej właściwości możesz
pozwolić użytkownikowi uruchamiać kwerendę tak, jakby miał uprawnienia właściciela tabeli. W ten sposób, w
zabezpieczonej bazie, użytkownicy mogą w kontrolowany sposób usuwać i aktualizować dane nawet, jeśli
57 Rozdział 4. ♦ Zaawansowane kwerendy

ustawione uprawnienia normalnie by im na to nie pozwalały. Bez tej właściwości trudno jest zabezpieczać dane w
bazie i jednocześnie umożliwiać użytkownikom wykonywanie na nich operacji.

u Źródłowa baza danych – domyślnie ustawiona jest bieżąca baza danych. To domyślne ustawienie dotyczy również
danych dołączanych do innej bazy Accessa. Gdyby dane były umieszczone w innej bazie, z którą nie istniałoby
połączenie, właściwość ta zawierałaby ścieżkę dostępu i nazwę pliku.
u Źródłowy ciąg połączenia – właściwość ta zawiera nazwę aplikacji, której użyto do tworzenia zewnętrznego źródła
bazy danych. Obie właściwości, Źródłowa baza danych i Źródłowy ciąg połączenia, umożliwiają Accessowi użycie
zewnętrznych, niepołączonych danych.
u Blokowanie rekordów – właściwość ta umożliwia określenie, w jaki sposób kwerenda będzie w systemie
wieloużytkownikowym rozwiązywać kwestie wielodostępu. Problem taki pojawia się, gdy dwóch lub więcej
użytkowników spróbuje dokonać zmian w tym samym rekordzie. Istnieją trzy opcje dla tej właściwości – Bez
blokowania, Wszystkie rekordy i Edytowany rekord. Opcje te dotyczą jedynie rekordów związanych z działaniem
kwerendy, a nie wszystkich rekordów źródłowej tabeli. Jeśli wybrana została opcja Bez blokowania, możliwe jest
dokonywanie zmian w rekordzie przez jednego użytkownika, podczas gdy pracują z nim inni użytkownicy.
Pierwszy z nich, który zapisze zmiany na dysku – wygrywa. Access ostrzega użytkowników, że pracują z rekor-
dem, który został zmieniony przez innego użytkownika. Każdy z nich musi zdecydować, jak rozwiązać tę kwestię.
Istnieją następujące możliwości – zrezygnować z własnych zmian, nadpisać zmiany innego użytkownika lub też
skopiować zmiany do Schowka i później zdecydować, co robić dalej. Po wybraniu opcji Wszystkie rekordy inni
użytkownicy nie będą mogli edytować rekordów kontrolowanych przez tę kwerendę, dopóki pierwszy użytkownik
nie zakończy pracy. Opcja Edytowany rekord dotyczy jedynie rekordu w danym momencie edytowanego przez
użytkownika.
u Typ zestawu rekordów – właściwość ta pozwala na określenie, czy używany przez formularz bądź raport zestaw
rekordów to Dynamiczny, Dynamiczny (Niespójny) czy Migawka. Opcja Dynamiczny umożliwia aktualizowanie w
relacji strony Wiele. Ustawienie Dynamiczny (Niespójny) umożliwia aktualizowanie obu stron relacji. Ważnym
jest zapamiętanie, że użycie opcji Dynamiczny (Niespójny) może mieć poważny wpływ na integralność danych.
Najlepiej korzystać z tego ustawienia w momencie, gdy relacja ma włączone wymuszanie więzów integralności i
kaskadowe aktualizowanie rekordów i to dopiero po przeprowadzeniu dokładnych testów. Ustawienie Migawka
uniemożliwia użytkownikom edytowanie danych, jednakże kwerenda działa wówczas szybciej niż w przypadku
dynamicznego zestawu rekordów. Każdy z powyższych wyborów ma wpływ na wydajność i możliwości
edytowania danych.
u Czas oczekiwania ODBC – jeśli kwerenda ma korzystać z sieci, właściwość ta określa, jak długo kwerenda ma
czekać na rezultaty. Jednostką miary jest sekunda, a domyślne ustawienie to 60 sekund. Mimo iż możesz zmieniać
tę liczbę, inne zmienne będą miały wpływ na wydajność. Obciążenie sieci i sposób buforowania plików na
serwerze mogą powodować ciągłe zmiany czasu odpowiedzi. Tak więc ustawienie tej wartości musi się odbyć
metodą prób i błędów. Ważne, by nie ustawić zbyt długiego oczekiwania, gdyż może się zdarzyć, że użytkownik
oczekuje na rezultaty, podczas gdy serwer faktycznie nie działa.
u Filtr – doskonałe narzędzie programistyczne dla początkujących. Coś jak automatyczny konstruktor kwerend. Jeśli
użytkownik uruchamia kwerendę, a następnie musi ograniczyć rezultaty, może wybrać wartość w zestawie
rezultatów i użyć przycisków filtra, aby wypełnić tę właściwość tak, by przypominała kryteria. Tego wszystkiego
może dokonać, nie znając składni sekcji kryteria tabeli QBE.
u Uporządkuj według – ta przypominająca Filtr właściwość umożliwia początkującym użytkownikom uruchomić
kwerendę, a następnie zmienić sposób sortowania jej rezultatów poprzez wybranie wartości w zestawie rezultatów.
Polecenie dla tego sortowania zawarte jest w tej właściwości.
u Maksymalna liczba rekordów – wpisanie wartości liczbowej w tym polu ogranicza liczbę zwracanych przez
kwerendę rekordów, niezależnie od tego ile rekordów w rzeczywistości spełnia kryteria kwerendy. Jeśli kwerenda
normalnie zwraca 500 rekordów, a właściwość ta ustawiona jest na 17, to kwerenda zwróci jedynie pierwszych 17
rekordów. Nie ma możliwości otrzymania dodatkowych rekordów bez zmiany tej właściwości.
u Nazwa podarkusza danych (NOWOŚĆ) – to jedna z nowych właściwości w Accessie 2000. Możesz dzięki niej
tworzyć kwerendy, które umożliwią Ci dogłębną analizę danych. Gdy utworzyłeś kwerendę wyświetlającą
wielkość sprzedaży według produktów, możesz ustawić tę właściwość na tabelę lub kwerendę zawierającą opisy
zamówień. Po uruchomieniu kwerendy zobaczysz podsumowanie wielkości sprzedaży według produktów oraz
przycisk, po kliknięciu którego zobaczysz szczegóły składające się na tę sumę.
u Podrzędne pole łączące (NOWOŚĆ) – jest to pole podarkusza danych, najczęściej pole klucza, które odpowiada
polu w głównej kwerendzie.
u Nadrzędne pole łączące (NOWOŚĆ) – jest to pole głównej kwerendy, najczęściej pole klucza, które odpowiada
polu w podarkuszu danych. Aby podarkusz danych działał, pole to musi być widoczne w rezultatach kwerendy.
Część I ♦ Projektowanie bazy danych 58

u Wysokość podarkusza danych (NOWOŚĆ) – wartość w calach, określająca wysokość wyświetlanego podarkusza
danych.
u Rozwinięty podarkusz danych (NOWOŚĆ) – jeśli właściwość ta ustawiona jest na Tak, szczegóły podarkusza
danych będą wyświetlane po otwarciu kwerendy. Jeśli ustawiona jest na Nie, użytkownik będzie musiał nacisnąć
przycisk, aby przejść do szczegółów podarkusza.

Mimo iż możliwym jest aktualizowanie danych poprzez podarkusz, zmiany


te są uwzględniane w obliczeniach kwerendy dopiero po jej ponownym
uruchomieniu.

Czas oczekiwania ODBC jest mierzony w sekundach i domyślnie ustawio-


ny na 60 sekund. Jednakże ustawienie tej właściwości na zero nie oznacza,
iż kwerenda będzie ciągle „prosiła” o odpowiedź. Ustawienie takie
powoduje wyłączenie tej opcji, co sprawia, że nie zostanie wyświetlony
żaden komunikat o przekroczeniu czasu oczekiwania.

Panel tabel
Wszystkie tabele i kwerendy użyte w danej kwerendzie znajdują się w górnym panelu okna – panelu tabel. Wyświetlane są
jako niewielkie, zawierające listę pól okna. Jeśli w panelu tym umieścisz kwerendę, wyświetlone zostaną jedynie pola,
które mają być umieszczone w rezultatach tej kwerendy. Linia między tabelami przedstawia istniejącą między nimi relację.
Relacje ustawione w oknie dialogowym Relacje są tu wyświetlane automatycznie. Funkcja ta nazywa się Autosprzęganie i
pozwala Accessowi zakładać istnienie powiązań między polami o tej samej nazwie i tym samym lub kompatybilnym typie
danych. Autosprzęganie niespodziewanie tworzy między nimi kwerendę. Może się zdarzyć, że dwa pola o tej samej nazwie
nie pozostają ze sobą w relacji, więc sprawdź

wszystkie relacje w kwerendzie przed jej użyciem. Możesz wyłączyć Autosprzęganie, otwierając z poziomu menu
Narzędzia okno dialogowe Opcje. Opcja Włącz autosprzęganie znajduje się na zakładce Tabele/Kwerendy.

Tworzenie relacji w kwerendzie lub pozwolenie na to Accessowi odnosi


skutek jedynie dla działania tej kwerendy. Dla osiągnięcia lepszych i bardziej
wiarygodnych efektów ustalaj relacje między obiektami w oknie Relacje.
Dzięki temu, w razie potrzeby będziesz mógł bez problemów włączyć
wymuszanie więzów integralności lub kaskadowe aktualizowanie i
usuwanie rekordów.

Umieszczanie tabeli lub kwerendy w panelu tabel


Umieszczanie tabel lub kwerend w panelu tabel jest proste. Gdy po raz pierwszy tworzysz kwerendę i przechodzisz do
widoku Projekt kwerendy, Access „poprosi” Cię o wybranie tabel lub kwerendy, których będziesz chciał używać.
Wyświetlone okno dialogowe posiada trzy zakładki, jedną dla tabel, jedną dla kwerend i jedną dla obu typów obiektów.
Jeśli musisz dodać tabelę lub kwerendę po zamknięciu tego okna dialogowego, możesz je przywrócić, wybierając z menu
Kwerenda opcję Pokaż tabelę. Możesz także użyć znajdującego się na pasku narzędzi przycisku Pokaż tabelę.

Górna część okna kwerendy jest dość duża, więc możesz rozszerzać tabele, klikając i przeciągając ich krawędzie. Jeśli
kwerenda korzysta z wielu tabel, możliwe jest przesuwanie zawartości okna, dzięki czemu tabele są dobrze widoczne.
Możesz również skorzystać z tej przestrzeni i umieścić w niej mniej ważne tabele (np. tabele odnośników), co pozwoli Ci
zlikwidować bałagan w tym oknie.

Tworzenie relacji w panelu tabel


Jeśli nie utworzyłeś relacji między tabelami na poziomie bazy danych poprzez okno Relacje, możesz utworzyć je ad hoc, z
poziomu kwerendy. Aby to zrobić, kliknij nazwę pola w jednej tabeli i przeciągnij je na pole w drugiej tabeli. Pomiędzy
tymi polami powstanie linia sprzężenia i od tego momentu będą się one zachowywać, jakby istniała między nimi relacja.
59 Rozdział 4. ♦ Zaawansowane kwerendy

Do linii sprzężenia mogą być również dołączone takie znaki jak symbol nieskończoności czy cyfra 1. Znaki te informują Cię
o charakterze relacji między polami i wyświetlane są, gdy relacja została utworzona na poziomie bazy danych. Jeśli
tworzysz relację na poziomie bazy danych, masz do dyspozycji trzy typy relacji: jeden do jednego, jeden do wielu i wiele
do wielu. Linia sprzężenia przedstawia charakter relacji poprzez umieszczenie cyfry 1 po stronie jednej relacji i symbolu
nieskończoności po stronie wielu. Każdy znak może się znajdować po obu stronach relacji. Istnienie tych znaków nie musi
oznaczać, iż faktycznie po stronie jeden występuje jeden rekord, a po stronie wielu jest ich kilka. Określają one jedynie
potencjał relacji danych. Ich zadaniem jest pomóc w zdecydowaniu, co z daną kwerendą można zrobić.

Jak wszystkie obiekty linia sprzężenia również ma swoje właściwości. W przypadku większości z nich po kliknięciu
obiektu prawym klawiszem myszy wyświetlone zostaje menu kontekstowe, z którego można wybrać opcję Właściwości.
Właściwości linii sprzężenia wyświetlane są po dwukrotnym kliknięciu linii lewym przyciskiem myszy. Jeśli relacja
została utworzona na poziomie bazy danych, możesz z menu Widok wybrać pozycję Właściwości sprzężenia. Czynność tę
przedstawia rysunek 4.3.

Rysunek 4.3.
Możesz otworzyć
okno Właściwości
sprzężenia, klikając
dwukrotnie jego linię

Okno właściwości sprzężenia różni się od okien właściwości innych obiektów. Zawiera ono cztery rozwijane listy (dwie z
nazwami tabel i dwie z nazwami pól) oraz trzy, wzajemnie wykluczające się pola wyboru. Określają one typ tworzonej
relacji. Są to następujące opcje:
u Sprzężenie wewnętrzne – jest to ustawienie domyślne. Ten typ relacji przedstawia prosta linia między dwoma
polami. Rezultatem kwerendy z relacją ustaloną na bazie sprzężenia wewnętrznego będą wszystkie rekordy, w
których dwa, objęte relacją pola są takie same. Innymi słowy, jeśli kwerenda zawierała klientów i zamówienia,
połączone poprzez pola IDklienta, w rezultatach kwerendy znaleźliby się jedynie klienci, którzy złożyli
zamówienia i zamówienia powiązane z klientami w tabeli Klienci.
u Lewe sprzężenie zewnętrzne (ang. outer join) – linia przedstawiająca to sprzężenie będzie z jednej strony
zakończona strzałką. Ten typ sprzężenia pozwala dominować jednej ze stron. Dominująca strona relacji wskazuje
na stronę podporządkowaną. Oznacza to, że kwerenda z Klientami i Zamówieniami, gdzie występowałoby lewe
sprzężenie zewnętrzne (linia sprzężenia skierowana w stronę tabeli Zamówienia), wyświetliłaby wszystkich
klientów, niezależnie od tego, czy składali jakiekolwiek zamówienia. Jednakże nie wyświetliłaby zamówień
nieprzyporządkowanych do żadnego z klientów.
u Prawe sprzężenie zewnętrzne – linia przedstawiająca to sprzężenie również będzie zakończona strzałką z jednej
strony. Ten typ relacji również pozwala jednej ze stron dominować. Dominująca strona relacji wskazuje na stronę
podporządkowaną. Kwerenda z Klientami i Zamówieniami, gdzie występowałoby prawe sprzężenie zewnętrzne
(linia sprzężenia skierowana w stronę tabeli Klienci), wyświetlałaby wszystkie złożone zamówienia, niezależnie od
tego, czy były składane przez określonych klientów. Jednakże nie wyświetliłaby klientów, którzy nie składali
zamówień.

Rozwijane listy w tym oknie dialogowym umożliwiają określenie, których tabel i pól po odpowiedniej stronie sprzężenie
ma dotyczyć. Jest to nowe rozwiązanie. Wcześniej, lewa i prawa strona relacji były przedmiotem zmian w zależności od
sposobu zbudowania kwerendy. W większości przypadków, integralność referencyjna wymusza użycie prawego bądź
lewego sprzężenia zewnętrznego. To tak, jakbyś mógł otrzymać klientów, którzy nie składali zamówień, ale nie mógł
jednocześnie otrzymywać zamówień, do których nie ma przyporządkowanych klientów. Jeśli uda Ci się otrzymać nie-
przyporządkowane rekordy w wyniku zarówno prawego jak i lewego sprzężenia zewnętrznego tej samej relacji, to znaczy,
że coś jest nie w porządku z integralnością danych. Rekordy znajdujące się po podporządkowanej stronie relacji i nie
posiadające pary po stronie dominującej nazywamy rekordami osieroconymi. Rekordy zagubione są zazwyczaj niewidocz-
ne podczas zwykłych operacji dokonywanych na bazie danych, jednakże wywołują statystyczne niezgodności w sytuacji,
gdy kwerenda oparta jest na podporządkowanej tabeli, bez użycia tabeli dominującej. Innymi słowy, raporty o
zamówieniach poszczególnych produktów mogą nie zgadzać się z raportami o zamówieniach według klientów.

Ważne, by nie myliły Ci się pojęcia lewe sprzężenie i prawe sprzężenie. Może się zdarzyć, że w tabeli QBE lewe sprzężenie
będzie wskazywać w prawo, a prawe w lewo. Jest to mylące zwłaszcza wtedy, gdy już kontrolujesz to, co jest po prawej i to
co po lewej stronie. Najważniejsze, byś pamiętał, że dominująca strona wyświetla wszystkie rekordy, nawet jeśli nie
odpowiadają one żadnym rekordom ze strony podporządkowanej.
Część I ♦ Projektowanie bazy danych 60

Inna z opcji w tym oknie dialogowym umożliwia tworzenie za jego pomocą kolejnej relacji. Kliknięcie przycisku Nowe
spowoduje wyświetlenie okna dialogowego, z poziomu którego możesz niespodziewanie ustanowić relację między
istniejącymi tabelami.

Poniższe rysunki przedstawiają różne rezultaty kwerendy opartej na tabelach Klienci i Zamówienia. Rezultaty sprzężenia
wewnętrznego znajdują się na rysunku 4.4, a odpowiadające mu wyrażenie SQL na wydruku 4.1.

Rysunek 4.4.
Dziesięciu klientów
z najmniejszą ilością
zamówień
w sprzężeniu
wewnętrznym

Wydruk 4.1. Wyrażenie SQL dla kwerendy z rysunku 4.4


SELECT TOP 10 Klienci.NazwaFirmy, Count(Zamówienia.IDzamówienia) AS PoliczOfIDzamówienia
FROM Klienci INNER JOIN Zamówienia ON Klienci.IDklienta = Zamówienia.IDklienta
GROUP BY Klienci.NazwaFirmy
ORDER BY Count(Zamówienia.IDzamówienia);

Kwerenda ta przedstawia ilość zamówień każdego z klientów i używa sprzężenia wewnętrznego, więc wyświetlane są
jedynie rekordy mające swoje odpowiedniki po obu stronach relacji.

Porównaj te wyniki z wynikami na rysunku 4.5 i wydrukiem 4.2.

Rysunek 4.5.
Dwunastu klientów
z najmniejszą ilością
zamówień
w sprzężeniu
zewnętrznym

Wydruk 4.2. Wyrażenie SQL dla kwerendy z rysunku 4.5


SELECT TOP 10 Klienci.NazwaFirmy, Count(Zamówienia.IDzamówienia) AS PoliczOfIDzamówienia
FROM Klienci LEFT JOIN Zamówienia ON Klienci.IDklienta = Zamówienia.IDklienta
GROUP BY Klienci.NazwaFirmy
ORDER BY Count(Zamówienia.IDzamówienia);

Rysunek 4.4 wygląda zwyczajnie; wszystko wydaje się być w porządku, ale rezultaty kwerendy nie są prawdziwe.
Sprzężenie wewnętrzne na rysunku 4.5 wskazuje, iż istnieją dwaj klienci, którzy nie składali żadnych zamówień i nie zostali
uwzględnieni w rezultatach kwerendy ze sprzężeniem wewnętrznym. Ponieważ pole wyświetlane po stronie Zamówienia
jest sumowane, pokazywany rezultat to zero. Normalnie, brakujący rekord po stronie podporządkowanej byłby
przedstawiony jako Null.

Kwerenda pokazująca rekordy nie posiadające swoich odpowiedników to po prostu sprzężenie zewnętrzne z kryterium
klucza obcego ustawionym na Null. Bez takiego ustawienia kryterium mógłbyś pośród wszystkich rekordów przeoczyć
tych kilka pustych pól. Przykład takiej sytuacji przedstawia rysunek 4.6 i wydruk 4.3.

Rysunek 4.6.
Klienci, którzy nie
składali zamówień

Wydruk 4.3. Wyrażenie SQL dla kwerendy z rysunku 4.6


SELECT Klienci.NazwaFirmy, Zamówienia.IDzamówienia
61 Rozdział 4. ♦ Zaawansowane kwerendy

FROM Klienci LEFT JOIN Zamówienia ON Klienci.IDklienta = Zamówienia.IDklienta


WHERE (((Zamówienia.IDzamówienia) Is Null));

Kwerenda wyświetla dwa rekordy zamiast dziesięciu lub dwunastu, jak to miało miejsce w przypadku braku ustawienia
kryterium Null na kluczu obcym.

Podsumowując, nie wystarczy, że właściwe pola w odpowiednich tabelach połączone są relacją. Typ tej relacji musi być
odpowiedni, by zapewnić zgodny z prawdą zestaw rezultatów kwerendy. Dwie kwerendy oparte na tych samych
tabelach i polach mogą dawać zupełnie różne rezultaty, jeśli typ relacji między polami jest różny. Wyrażenia SQL kwe-
rend na rysunkach 4.4 i 4.5 różnią się tylko jednym słowem (spójrz na rysunki 4.7 i 4.8). Jeśli w przykładzie Northwind
występowałby rekord zagubiony, inne wyrażenie SQL mogłoby spowodować jego wyświetlenie, po zmianie słowa Left
(lewe) na Inner (wewnętrzne) (równie dobrze słowo Inner można zamienić na Right (prawe)). Po raz kolejny
otrzymujemy zupełnie inny zestaw rezultatów, zmieniając w relacji zaledwie jedno słowo.

Rysunek 4.7.
SQL dla sprzężenia
wewnętrznego

Wydruk 4.4. Wyrażenie SQL dla kwerendy z rysunku 4.7


SELECT TOP 10 Klienci.NazwaFirmy, Count(Zamówienia.IDzamówienia) AS PoliczOfIDzamówienia
FROM Klienci INNER JOIN Zamówienia ON Klienci.IDklienta = Zamówienia.IDklienta
GROUP BY Klienci.NazwaFirmy
ORDER BY Count(Zamówienia.IDzamówienia);

Rysunek 4.8.
Dziesięciu\ klientów
z najmniejszą ilością
zamówień
w sprzężeniu
wewnętrznym

Wydruk 4.5. Wydruk SQL dla kwerendy z rysunku 4.8


SELECT TOP 10 Klienci.NazwaFirmy, Count(Zamówienia.IDzamówienia) AS PoliczOfIDzamówienia
FROM Klienci LEFT JOIN Zamówienia ON Klienci.IDklienta = Zamówienia.IDklienta
GROUP BY Klienci.NazwaFirmy
ORDER BY Count(Zamówienia.IDzamówienia);

Ponieważ istnieją rekordy z takimi samymi wartościami, kwerenda wyświetla 12 rekordów, mimo iż żądano 10
najwyższych.

Łatwiej jest zaznaczyć przekątną linię sprzężenia niż pionową czy poziomą.
Przemieszczanie tabel lub przesuwanie ich pól może ułatwić Ci wybieranie
linii sprzężenia.

Siatka kwerendy
W dolnej połowie okna znajduje się tabela kwerendy. Tutaj możesz wybrać pola, które mają być widoczne w rezultatach
kwerendy, kolejność sortowania, informacje o grupowaniu, obliczenia, informacje o aktualizacji i dołączaniu oraz
kryteriach, według których kwerenda będzie wybierać rekordy. Tutaj odbywa się największa część pracy związanej z
tworzeniem kwerendy.
Część I ♦ Projektowanie bazy danych 62

Umieszczanie pól w siatce kwerendy


Umieszczanie pól w kwerendzie może się odbywać na kilka sposobów:
u Dwukrotne kliknięcie – dwukrotne kliknięcie nazwy pola w tabeli powoduje przeniesienie go do pierwszego
wolnego miejsca w siatce kwerendy.
u Kliknij i przeciągnij – możesz umieszczać pola, klikając i przeciągając je do dowolnej kolumny w siatce kwerendy.
u Kliknięcie z klawiszem Ctrl – kliknięcie jednego pola, przytrzymanie klawisza Ctrl i kliknięcie innych pól w tej
samej tabeli umożliwi Ci przeniesienie ich wszystkich jednocześnie do siatki kwerendy.
u Dwukrotne kliknięcie paska z nazwą tabeli – dwukrotne kliknięcie paska z nazwą tabeli spowoduje zaznaczenie
wszystkich jej pól. Przeciągnij zaznaczone w ten sposób pola do siatki kwerendy. Możesz również użyć kliknięcia
z klawiszem Ctrl, aby z usunąć niektóre z zaznaczonych pól.
u Gwiazdka – pierwsza pozycja w tabeli to znak gwiazdki. Dwukrotne kliknięcie lub przeciągnięcie go do siatki
kwerendy spowoduje utworzenie pojedynczego wpisu w siatce, lecz w rezultatach kwerendy widoczne będą
wszystkie pola z tabeli.
u Wybierz pola w siatce kwerendy – pierwszy wiersz siatki kwerendy wskazuje, które pole jest aktualnie używane.
Umieszczenie punktu wprowadzania w tym wierszu umożliwi Ci wybór pola. Uważaj, aby przez przypadek nie
wybrać pola z niewłaściwej tabeli. Następny wiersz siatki kwerendy, Tabela, może znacznie ułatwić korzystanie z
tego sposobu.

Użycie drugiego wiersza siatki QBE jest opcjonalne, jednakże w Accessie 2000 jest on stale wyświetlany. Wiersz Tabela
wskazuje projektantowi kwerendy, z której tabeli dane pole pochodzi. Ułatwia to pracę, gdy w więcej niż jednej tabeli
występują pola o podobnych nazwach. Możesz użyć tego wiersza, aby szybko zmienić tabelę źródłową dla dowolnego z
pól w siatce QBE.

Określanie kolejności sortowania, wyświetlania rezultatów oraz wybór


kryteriów kwerendy
Wiersz Sortuj umożliwia Ci określenie sposobu, w jaki kwerenda sortuje wiersze rezultatów. Każde z pól możesz sortować
Rosnąco, Malejąco lub pozostawić je bez sortowania. Gdy do sortowania wybrane jest więcej niż jedno pole, o kolejności
sortowanie decyduje kolejność pól od lewej do prawej.

Czwarty wiersz określa, czy pole jest wyświetlane w rezultatach kwerendy. Nawet, jeśli pole nie jest wyświetlane, wciąż
może wpływać na rezultaty kwerendy. Aby kwerenda była wykonywana, co najmniej jedno pole musi być wyświetlane w
jej rezultatach.

Piąty i wszystkie pozostałe wiersze przeznaczone są dla warunków. Wiersze dotyczące warunków zawierają wartości
służące do wybierania wierszy do zestawu rekordów. Mogą również zawierać procedury SQL, jednakże technika ta nie jest
zalecana, gdyż procedury SQL muszą być wykonywane dla każdego rekordu w możliwym zestawie rezultatów kwerendy,
zanim zostanie wyświetlony rezultat końcowy. Zazwyczaj ten sam efekt można uzyskać przez użycie podkwerend.

Możesz wielokrotnie dodawać pola do tabeli QBE, wyłączać opcję Pokaż i


kontrolować sortowanie zestawu rezultatów bez zmieniania kolejności pól.

Jeśli zajdzie taka potrzeba, do tabeli QBE możesz dodać kolejny wiersz: Podsumowanie. Aby uzyskać dostęp do tego
wiersza kliknij znajdujący się na pasku narzędzi przycisk Sumy lub wybierz tę opcję z menu Widok. Włączenie opcji Sumy
zmienia nieco charakter kwerendy. Te zagregowane kwerendy pozwalają Ci na twórcze kształtowanie zestawu rezultatów.
Szczegóły użycia wiersza Podsumowanie omówione zostaną w następnej części tego rozdziału.

Kwerendy podsumowujące
Zazwyczaj zestaw rezultatów kwerendy zawiera tak wiele informacji, że jest dla użytkownika bezużyteczny. Aby to
zmienić, Access umożliwia Ci tworzenie podsumowania danych za pomocą kwerend podsumowujących.
63 Rozdział 4. ♦ Zaawansowane kwerendy

Aby utworzyć podsumowanie klientów i ich zakupów, możesz w dołączonej do Accessa 2000 bazie Northwind utworzyć
nową kwerendę. Gdy skończysz, kwerenda będzie wyświetlać listę klientów i zakupionych przez nich produktów jako listę
unikatowych kombinacji.

Aby rozpocząć pracę z tą kwerendą, umieść w panelu tabel następujące tabele: Klienci, Zamówienia, Opisy zamówień i
Produkty.

Z tabeli Klienci przenieś do siatki kwerendy pole NazwaFirmy, a z tabeli Produkty – pole NazwaProduktu. Posortuj
kwerendę według NazwaFirmy i NazwaProduktu. Uruchom kwerendę, klikając znajdujący się na pasku narzędzi symbol
czerwonego wykrzyknika lub wybierając Kwerenda⇒Uruchom. Jeśli dokładnie przyjrzysz się rysunkowi 4.9, zauważysz,
że niektórzy z klientów występują w zestawie rezultatów więcej niż raz. Wyrażenie SQL dla rysunku 4.9 znajduje się na
wydruku 4.6.

Wydruk 4.6. Wyrażenie SQL dla kwerendy z rysunku 4.9


SELECT Klienci.NazwaFirmy, Produkty.NazwaProduktu
FROM Produkty INNER JOIN ((Klienci INNER JOIN Zamówienia ON Klienci.IDklienta = Zamówienia.IDklienta) INNER JOIN
[Opisy zamówień] ON Zamówienia.IDzamówienia = [Opisy zamówień].IDzamówienia) ON Produkty.IDproduktu = [Opisy
zamówień].IDproduktu
ORDER BY Klienci.NazwaFirmy, Produkty.NazwaProduktu;

Rysunek 4.9.
Niektórzy klienci
pojawiają się
kilkakrotnie dla tego
samego produktu,
gdyż zamówili go
więcej niż raz

Powróć do widoku Projekt kwerendy i kliknij znajdujący się na pasku narzędzi przycisk Sumy lub wybierz tę opcję z menu
Widok. Wiersz podsumowania pojawi się w siatce kwerendy z wybraną dla obu pól opcją Grupuj według. Oznacza to, że
kwerenda zmniejszy rozmiar zestawu rekordów tak, by wyświetlał tylko jeden raz każdą kombinację wartości NazwaFirmy
i NazwaProduktu. Uruchom kwerendę ponownie, a zobaczysz, że nazwy firm i produktów się nie powtarzają.
Spowodowało to usunięcie z zestawu setek rekordów.

Możesz korzystać z opcji Grupuj według nawet dla dziesięciu pól, pamiętaj jednak, że użycie tej opcji dla każdego
zbędnego pola spowalnia pracę kwerendy i powoduje wyświetlenie dodatkowych wierszy w zestawie rezultatów. Używaj
opcji Grupuj według tylko dla pól, które są niezbędne dla uzyskania pożądanych rezultatów. W polu z zaznaczoną opcją
Grupuj według nie możesz wprowadzać wartości [nazwatabeli].*.

Opcja Sumy jest rozbudowana i posiada wiele innych możliwości. Wprowadzając do kwerendy wiersz Podsumowanie,
masz do dyspozycji dwanaście opcji. Dziewięć z nich to funkcje agregujące, co oznacza, że wykonują one na danych różne
obliczenia. Teraz przyjrzymy się każdej z nich.

Żadna z funkcji agregujących nie uwzględnia w swoich obliczeniach war-


tości Null. Jeśli chcesz to zmienić, musisz przekształcić wartości Null na
zera, korzystając z kwerendy aktualizującej lub polecenia
IIF(IsNull([nazwapola]),0,[nazwapola]), aby kwerenda wyświe-
tlała wartości zero.

Funkcja agregująca Policz


Aby zobaczyć, ile zamówień złożył każdy z klientów, musisz zmodyfikować kwerendę. Zamiast pola NazwaProduktu
wprowadź z tabeli Zamówienia pole IDzamówienia i w wierszu Podsumowanie wybierz wartość Policz. Usuń z panelu
tabele Opisy zamówień i Produkty.

Gdy uruchamiasz kwerendę agregującą ważne jest, by nie znajdowało się w niej nic zbędnego. Prawie wszystko co
znajduje się w siatce QBE może mieć wpływ na działanie funkcji agregującej. Jeśli nie usuniesz tych tabel (mimo iż nie
Część I ♦ Projektowanie bazy danych 64

używasz ich w siatce QBE), spowodują one, że kwerenda będzie zliczać wszystkie zamówione produkty, a nie zamówienia
(rysunek 4.10 i wydruk 4.7).

Rysunek 4.10.
Zliczanie zamówień
klientów

Wydruk 4.7. Wyrażenie SQL dla kwerendy z rysunku 4.10


SELECT Klienci.NazwaFirmy, Count(Zamówienia.IDzamówienia) AS PoliczOfIDzamówienia
FROM Klienci INNER JOIN Zamówienia ON Klienci.IDklienta = Zamówienia.IDklienta
GROUP BY Klienci.NazwaFirmy

Zauważ, że na rysunku 4.10 nie zachodzi potrzeba określenia kolejności sortowania. Prosta kwerenda agregująca sama
sortuje rezultaty według pola grupowania. Jeśli nie określisz kolejności sortowania, określana jest ona przez położenie od
lewej do prawej strony pól z opcją Grupuj według.

Funkcja agregująca Średnia


Aby zobaczyć średnią cenę danej kategorii produktów, utwórz kwerendę opartą jedynie na tabeli Produkty. W siatce
kwerendy umieść pola IDkategorii i CenaJednostkowa, dodaj wiersz Podsumowanie i ustaw opcję podsumowania w polu
CenaJednostkowa na Średnia (rysunek 4.11 i wydruk 4.8).

Rysunek 4.11.
Siatka QBE
kwerendy
obliczającej średnią

Wydruk 4.8. Wyrażenie SQL dla kwerendy z rysunku 4.11


SELECT Produkty.IDkategorii, Avg(Produkty.CenaJednostkowa) AS ŚredniaOfCenaJednostkowa
FROM Produkty
GROUP BY Produkty.IDkategorii;

Funkcja agregująca Średnia działa zarówno na polach typu Liczba, Data/Godzina, Walutowy i Autonumerowanie i
wyświetla średnią wartość danej grupy pól.

Funkcje agregujące Minimum i Maksimum


Funkcje Min/Maks mogą być przydatne, gdy chcesz uzyskać największą wartość w danym polu. Na przykład w sytuacji,
gdy chcesz zobaczyć datę ostatniego zamówienia każdego z klientów. Aby tego dokonać, utwórz kwerendę z tabelami
Klienci i Zamówienia, połączonymi za pomocą pola IDklienta. Umieść w siatce kwerendy pola NazwaFirmy i DataZamówienia.
Dodaj wiersz Podsumowanie i ustaw opcję podsumowania pola DataZamówienia na Maksimum. Uzyskasz w ten sposób
datę ostatniego zamówienia każdego z klientów. Ustawienie tej opcji na Minimum spowoduje wyświetlenie najwcześ-
niejszego, zarejestrowanego zamówienia każdego z klientów. Możesz nawet wyświetlać je obok siebie, dodając ponownie
pole DataZamówienia i wybierając Maksimum dla jednego i Minimum dla drugiego z nich.
65 Rozdział 4. ♦ Zaawansowane kwerendy

Funkcje agregujące Pierwszy i Ostatni


Na pierwszy rzut oka, funkcje Pierwszy i Ostatni mogą przypominać Minimum i Maksimum, w rzeczywistości jednak
bardzo się od siebie różnią. Minimum i Maksimum oceniają przedstawiane dane. Pierwszy i Ostatni po prostu pobierają
pierwszą lub ostatnią wartość napotkaną przez kwerendę, co czasami daje zaskakujące rezultaty. Radzimy z ostrożnością
korzystać z tych funkcji, najlepiej na uprzednio posortowanych, tymczasowych tabelach. Użycie tych opcji na
nieposortowanej lub posortowanej w niewłaściwy

sposób tabeli da subiektywne wyniki. Stanie się tak dlatego, że dla funkcji Pierwszy i Ostatni najważniejsza jest kolejność
przedstawienia pól, a powiązania danych z innymi polami są nieważne.

Funkcji tych użyjesz, aby uzyskać listę najdroższych produktów w każdej kategorii. Lista ta będzie zawierać pola
NazwaKategorii, NazwaProduktu i CenaJednostkowa. Utwórz nową kwerendę, opartą na tabelach Kategorie i Produkty. W
siatce QBE umieść pole NazwaKategorii z tabeli Kategorie oraz pola NazwaProduktu i CenaJednostkowa z tabeli Produkty.
Ustaw kolejność sortowania pola NazwaKategorii na Rosnąco i CenaJednostkowa na Malejąco.

Z menu Kwerenda wybierz Kwerenda tworząca tabele i nazwij nową tabelę Kategorie i Produkty Sortowane według Ceny.
Uruchom kwerendę. W nowej tabeli powinno znaleźć się ponad 70 nowych rekordów. Teraz możesz utworzyć kwerendę
korzystającą z funkcji Pierwszy i Ostatni.

Utwórz nową kwerendę i wyświetl w panelu tabelę Kategorie i Produkty sortowane według ceny. Wszystkie jej pola umieść
w siatce kwerendy. Dodaj wiersz Podsumowanie i ustaw funkcję agregującą w polu NazwaProduktu na Pierwszy, a
następnie w polu CenaJednostkowa również na Pierwszy. Uruchom kwerendę, a zobaczysz najdroższy produkt w każdej
kategorii. Jeśli funkcje Pierwszy zamienisz na Ostatni, zobaczysz najtańszy produkt w każdej kategorii. Ustawienie jednego
z pól na Pierwszy, a drugiego na Ostatni pokaże, jak funkcje te pobierają dane z różnych wierszy w zestawie rekordów, ale
przedstawia je tak, jakby były częścią tego samego rekordu. Spróbuj użyć takiej samej kwerendy na początkowej tabeli, a
zobaczysz jak bardzo funkcje Pierwszy i Ostatni zależą od uprzedniego sortowania. Aby funkcje Pierwszy i Ostatni działały
efektywnie, sortowanie rekordów musi być wykonane świadomie (tak jak zrobiliśmy to w tymczasowej tabeli) lub poprzez
indeksy tabel. W tym konkretnym przykładzie, funkcje Pierwszy i Ostatni mogłyby być zastąpione przez Minimum i
Maksimum, jednakże w przypadku pola NazwaProduktu możliwe byłoby jedynie użycie tych pierwszych.

Funkcje agregujące Odchylenie standardowe i Wariancja


Odchylenie standardowe (OdchStd) i Wariancja dokonują obliczeń na wartościach danego pola. Wystarczy utworzyć
kwerendę grupującą dane w dowolny sposób. Zaznacz odpowiednie pole i ustaw opcję wiersza Podsumowanie na OdchStd
lub Wariancja. Odchylenie standardowe i Wariancja wykorzystują metodę próbkowania opartą na mianowniku (n – 1),
gdzie n równe jest liczbie rekordów w zestawie rezultatów. Metoda ta używana jest w analizie statystycznej.

Kolejne dwie opcje podsumowujące – Wyrażenie i Gdzie – nie są funkcjami agregującymi.

Funkcja Wyrażenie
Wyrażenie umożliwia przedstawienie obliczeń w rezultatach kwerendy, jednakże obliczenia te muszą zawierać funkcję
agregującą. Używaj tej opcji, gdy chcesz w kwerendzie przedstawić wynik wielu funkcji. Przykładowe wyrażenie znajduje
się na rysunku 4.12 (wyrażenie SQL na wydruku 4.9).

Rysunek 4.12.
Zestaw rezultatów
z wyrażeniem

Wydruk 4.9. Wyrażenie SQL dla kwerendy z rysunku 4.12


SELECT Kategorie.NazwaKategorii, Count(Produkty.NazwaProduktu) AS PoliczOfNazwaProduktu,
Sum([CenaJednostkowa])*1.05 AS [Przykladowe Wyrażenie]
FROM Kategorie INNER JOIN Produkty ON Kategorie.IDkategorii = Produkty.IDkategorii
GROUP BY Kategorie.NazwaKategorii;
Część I ♦ Projektowanie bazy danych 66

W tym przykładzie zliczasz produkty, a następnie podnosisz średnią cenę każdej kategorii o 5%. Aby tego dokonać,
ustawiasz wartość wiersza Podsumowanie danego pola na Wyrażenie, a następnie zapisujesz wzór używający funkcji
agregującej. Jeśli w zapisanym wyrażeniu brak będzie funkcji agregującej, Access wyświetli komunikat o błędzie, a
kwerenda nie zostanie wykonana.

Warunek Gdzie
Zastosowanie kryteriów w kwerendzie agregującej odbywa się przez użycie polecenia Gdzie lub przez wprowadzenie
kryteriów do siatki QBE, jak to ma miejsce w przypadku zwykłej kwerendy wybierającej. Istnieją jednak różnice między
tymi sposobami i wybór ich może mieć wpływ na zachowanie kwerendy. Podczas użycia polecenia Gdzie kwerenda
najpierw stosuje kryteria, dołączając lub wyłączając rekordy, zanim zostaną one pogrupowane.

Jeśli wprowadzisz kryteria w innym polu bez użycia polecenia Gdzie, kryteria będą stosowane dopiero po zakończeniu
grupowania. Przed kryteriami wyrażonymi bez użycia polecenia Gdzie, w SQL występować będzie polecenie Having.

Różnice są proste, lecz bardzo ważne. Jeśli z kwerendy agregującej chcesz usunąć sprzedaż zagraniczną, użyj polecenia
Gdzie. Jeśli chcesz jednocześnie zobaczyć jedynie rezultaty, których wynik zliczania jest wyższy niż 1000, wyraź to w polu
wykonującym polecenie Policz. Kryterium wykluczające sprzedaż zagraniczną powinno być wpisane w siatce kwerendy
dla pola KrajOdbiorcy i wyrażone w SQL za pomocą wyrażenia Having. Polecenie Having przydaje się przy stosowaniu
kryteriów na dokonanych obliczeniach. Przykłady użycia tego polecenia znajdują się na rysunku 4.13 i wydruku 4.10.

Rysunek 4.13.
Kwerenda używająca
pleceń Where
i Having
w siatce QBE

Wydruk 4.10. Wyrażenie SQL dla kwerendy z rysunku 4.13


SELECT Kategorie.NazwaKategorii,
Count(Produkty.NazwaProduktu) AS PoliczOfNazwaProduktu,
Sum([Opisy zamówień].Ilość) AS SumaOfIlość
FROM (Kategorie
INNER JOIN Produkty ON Kategorie.IDkategorii = Produkty.IDkategorii)
INNER JOIN ((Klienci
INNER JOIN Zamówienia ON KLienci.IDklienta = Zamówienia.IDklienta)
INNER JOIN [Opisy zamówień] ON Zamówienia.IDzamówienia = [Opisy zamówień].IDzamówienia) ON Produkty.IDproduktu =
[Opisy zamówień].IDproduktu
WHERE (((Zamówienia.KrajOdbiorcy)="USA"))
GROUP BY Kategorie.NazwaKategorii
HAVING (((Sum([Opisy zamówień].Ilość))>1000));

Łatwym sposobem na zapamiętanie kolejności wykonywania wyrażeń z


fraz Where i Having jest przeglądanie wyrażeń SQL tworzonych przez
każdą kwerendę. Fraza Having zawsze jest za frazą Group by.
67 Rozdział 4. ♦ Zaawansowane kwerendy

Użycie kwerend krzyżowych


Kwerendy krzyżowe i agregujące są do siebie bardzo zbliżone. Kwerenda krzyżowa posiada wiele zdolności analitycznych.
W typowej kwerendzie wybierającej pola wyświetlane są u góry zestawu rezultatów, a lista wartości poniżej, jako
pojedyncze rekordy. W kwerendzie agregującej pola również znajdują się u góry zestawu rezultatów, jednakże poniżej
wyświetlane są wartości będące podsumowanymi danymi. Kwerenda krzyżowa umożliwia Ci tak przekształcić
podsumowania uzyskane dzięki kwerendzie agregującej, że wartości będące rezultatami jednej z grup rozmieszczone są u
góry zestawu rezultatów. Utworzona przez lewą kolumnę i górny wiersz zestawu rezultatów macierz wypełniana jest
żądanymi przez Ciebie obliczeniami. W wyniku tego otrzymujemy coś na kształt tabeli przestawnej.

Prosta kwerenda krzyżowa składa się przynajmniej z trzech elementów: Nagłówka wiersza, Nagłówka kolumny i Wartości.
Kwerenda ta może korzystać z zestawu rezultatów dowolnej kwerendy wybierającej.

Aby utworzyć kwerendę krzyżową, w wyniku której podzielimy klientów według kategorii zamawianych produktów, będziemy
potrzebować następujących tabel: Klienci, Kategorie, Produkty, Zamówienia i Opisy zamówień. Z tabeli Klienci wybierz pole
NazwaFirmy, z tabeli Kategorie pole NazwaKategorii, a z tabeli Opisy zamówień pole Ilość.

Aby kwerendę wybierającą przekształcić w krzyżową, wybierz z menu Kwerenda opcję Kwerenda krzyżowa. Po
przekształceniu w siatce kwerendy pojawi się nowy wiersz (rysunek 4.14 i wydruk 4.11). Wiersz ten umożliwi Ci
przyporządkowanie pola do odpowiednich elementów kwerendy krzyżowej. Pole NazwaFirmy ustaw jako Nagłówek wier-
sza, pole NazwaKategorii jako Nagłówek kolumny (ta część będzie wyświetlana u góry zestawu rezultatów), pole Ilość jako
Wartość, a w wierszu Podsumowanie tego pola wybierz Suma. Po uruchomieniu kwerendy Access automatycznie utworzy
sumę na każdym przecięciu klienta i produktu.

Rysunek 4.14.
Kwerenda krzyżowa
w siatce QBE

Wydruk 4.11. Wyrażenie SQL dla kwerendy z rysunku 4.14


TRANSFORM Sum([Opisy zamówień].Ilość) AS SumaOfIlość
SELECT Klienci.NazwaFirmy
FROM (Kategorie INNER JOIN Produkty
ON Kategorie.IDkategorii = Produkty.IDkategorii)
INNER JOIN ((Klienci INNER JOIN Zamówienia
ON Klienci.IDklienta = Zamówienia.IDklienta)
INNER JOIN [Opisy zamówień] ON Zamówienia.IDzamówienia = [Opisy zamówień].IDzamówienia)
ON Produkty.IDproduktu = [Opisy zamówień].IDproduktu
WHERE (((Zamówienia.DataZamówienia) Between #1/1/1998# And #12/31/1998#))
GROUP BY Klienci.NazwaFirmy
PIVOT "Q" & CStr(DatePart("Q",[DataZamówienia]));

Możliwe jest ustawienie w kwerendzie krzyżowej więcej niż jednego pola jako Nagłówka wiersza, jednakże może być tylko
jeden Nagłówek kolumny i jedna Wartość. To dałoby hierarchiczny widok danych, ze wzrastającym stopniem
szczegółowości wraz z przesuwaniem się od lewej do prawej. Aby zobaczyć jak to działa, możesz jako Nagłówki wiersza
dodać pola Kraj i Region.

W polu Wartość możesz wprowadzić również własne obliczenia. Zamień w siatce Ilość na następujące wyrażenie:
Expr1: IIF(Sum([Ilość])>=50, "High", "Low")

Ten fragment kodu korzysta z funkcji agregującej, aby wyświetlić wartość w kwerendzie krzyżowej.
Część I ♦ Projektowanie bazy danych 68

W wierszu Podsumowanie dla tego pola ustaw wartość Wyrażenie. Po uruchomieniu kwerendy w tabeli zobaczysz wynik
IIf(). Wyrażenia, które tworzysz w kwerendzie krzyżowej, muszą być kompatybilne z wyrażeniami, które napisałbyś dla
innej kwerendy agregującej.

W podobny sposób kwerenda może zawierać wynik wyrażenia w nagłówku wiersza bądź kolumny. Poniższa kwerenda
(przedstawiona na rysunkach 4.15 i 4.16 oraz wydruku 4.12) korzysta z wyrażenia, aby podzielić dane w nagłówkach
kolumn na ćwiartki. Wyrażenie przestawne wygląda w następujący sposób:
"Q" & CStr(DatePart("Q", [OrderDate]))

Wydruk 4.12. Wyrażenie SQL dla kwerend z rysunków 4.15 i 4.16


TRANSFORM Sum([Opisy zamówień].Ilość) AS SumaOfIlość
SELECT Klienci.NazwaFirmy
FROM Kategorie INNER JOIN (Produkty
ON Kategorie.IDkategorii = Produkty.IDkategorii)
INNER JOIN ((Klienci INNER JOIN Zamówienia
ON Klienci.IDklienta = Zamówienia.IDklienta)
INNER JOIN [Opisy zamówień] ON Zamówienia.IDzamówienia = [Opisy zamówień].IDzamówienia)
ON Produkty.IDproduktu = [Opisy zamówień].IDproduktu)
WHERE (((Zamówienia.DataZamówienia) Between #1/1/1998# And #12/31/1998#))
GROUP BY Klienci.NazwaFirmy
PIVOT "Q" & CStr(DatePart("Q", [DataZamówienia]));

Aby kwerenda krzyżowa uwzględniła dokonane zmiany, musisz ją zamknąć i na nowo otworzyć.
Rysunek 4.15.
Zmodyfikowana
kwerenda krzyżowa
w siatce QBE

Rysunek 4.16.
Zestaw rezultatów
zmodyfikowanej
kwerendy krzyżowej
69 Rozdział 4. ♦ Zaawansowane kwerendy

Użycie kwerend parametrycznych


Kwerendy parametryczne nie są osobnym typem kwerend. Wymagają one po prostu interwencji użytkownika. Wszystkie
kwerendy przed ich uruchomieniem mogą żądać podania określonych informacji. Pewnie zdarzyło Ci się podczas
tworzenia kwerendy wprowadzić niepoprawną nazwę pola lub wartość. Gdy próbowałeś uruchomić tę kwerendę, zostałeś
poproszony o zidentyfikowanie tych informacji. Jeśli faktycznie Ci się to przydarzyło, stworzyłeś wówczas kwerendę
parametryczną. Teraz również to zrobisz, jednakże będziemy kontrolować to, co się dzieje. Dobrym przykładem będzie
kwerenda oparta na tabeli Klienci i zawierająca pola NazwaFirmy, Przedstawiciel i Telefon. Kwerenda ta przedstawiona jest
na rysunku 4.17, a odpowiadające jej wyrażenie SQL znajduje się na wydruku 4.13.

Rysunek 4.17.
Podstawa dla prostej
kwerendy
parametrycznej

Wydruk 4.13. Wyrażenie SQL dla kwerendy z rysunku 4.17


SELECT Klienci.NazwaFirmy, Klienci.Przedstawiciel, Klienci.Telefon
FROM Klienci
ORDER BY Klienci.Przedstawiciel;

Gdy uruchomisz tę kwerendę, otrzymasz listę wszystkich klientów, ich przedstawicieli oraz wszystkich numerów
telefonów. Można jednak wprowadzić wartość kryterium w taki sposób, aby uzyskać informacje o przedstawicielu
konkretnego klienta. Ilustruje to rysunek 4.18 i wydruk 4.14.

Wydruk 4.14. Wyrażenie SQL dla kwerendy z rysunku 4.18


SELECT Klienci.NazwaFirmy, Klienci.Przedstawiciel, Klienci.Telefon
FROM Klienci
WHERE (((Klienci.NazwaFirmy)="Frankenversand"))
ORDER BY Klienci.Przedstawiciel;

Działa całkiem nieźle, jednakże dość męczące jest każdorazowe modyfikowanie kryteriów i uruchamianie kwerendy.
Rozwiązanie to jest także mało praktyczne, jeśli z tej aplikacji mają korzystać osoby nie zaznajomione z siatką QBE
Accessa. Zamiast tego możesz utworzyć parametr dla tej kwerendy i pozwolić mu funkcjonować jako prymitywny interfejs
dla użytkowników. Dzięki użyciu kwerendy parametrycznej kryteria są zmieniane, a użytkownicy nie muszą borykać się z
projektowaniem kwerendy.
Część I ♦ Projektowanie bazy danych 70

Rysunek 4.18.
Kwerenda z prostym
kryterium
w siatce QBE

Tworzenie parametrów dla kwerendy w siatce QBE


Aby utworzyć parametr w siatce QBE, wybierz z menu Kwerenda opcję Parametry. Wyświetlone zostanie okno dialogowe,
w którym możesz umieścić parametry, które chcesz ustawić. Mimo iż można tworzyć kwerendy parametryczne bez użycia
okna dialogowego, umożliwia ono kontrolowanie kolejności przedstawiania parametrów oraz typów danych dla każdego z nich.
Po umieszczeniu parametrów w oknie dialogowym możesz rozmieścić je na właściwych miejscach w siatce kwerendy.
Parametr w siatce kwerendy musi dokładnie odpowiadać parametrowi w oknie dialogowym. Jeśli parametr będzie istniał
jedynie w oknie dialogowym, kwerenda poprosi użytkownika o podanie informacji, jednakże nie będzie wiedzieć, jak ma
je zastosować.

W kwerendzie opartej na tabelach Klienci, Zamówienia, Opisy zamówień i Produkty umieść pola IDklienta, NazwaFirmy,
DataZamówienia, NazwaProduktu, CenaJednostkowa, Ilość i Rabat. Posortuj kwerendę malejąco według DataZamówienia i
rosnąco według NazwaProduktu. Z menu Kwerenda wybierz opcję Parametry. Wprowadź pierwszy parametr jako ID klienta
z typem danych tekst. W pierwszej linii sekcji kryteria pola IDklienta wprowadź [ID klienta]. Jest to informacja dla
kwerendy, że ma akceptować parametr tekstowy nazwany ID klienta i użyć go w kwerendzie jako kryterium pola IDklienta.
Ta kwerenda parametryczna przedstawiona jest na rysunku 4.19, a odpowiadające jej wyrażenie SQL na wydruku 4.15.

Wydruk 4.15. Wyrażenie SQL dla kwerendy z rysunku 4.19


PARAMETERS [ID Klienta] Text;
SELECT Klienci.NazwaFirmy, Zamówienia.IDzamówienia, Zamówienia.DataZamówienia,
Produkty.NazwaProduktu, [Opisy zamówień].CenaJednostkowa,
[Opisy zamówień].Ilość, [Opisy zamówień].Rabat
FROM Produkty
INNER JOIN ((Klienci INNER JOIN Zamówienia
ON Klienci.IDklienta = Zamówienia.IDklienta)
Rysunek 4.19.
Umieszczanie
parametru
w kwerendzie
w siatce QBE
71 Rozdział 4. ♦ Zaawansowane kwerendy

INNER JOIN [Opisy zamówień] ON Zamówienia.IDzamówienia = [Opisy zamówień].IDzamówienia)


ON Produkty.IDproduktu = [Opisy zamówień].IDproduktu
WHERE (((Klienci.IDklienta)=[IDklienta]))
ORDER BY Zamówienia.DataZamówienia DESC, Produkty.NazwaProduktu;

Uruchom kwerendę i w odpowiedzi na pytanie o parametr wpisz Quick. W zestawie rezultatów znajdą się wszystkie
rekordy, w których IDklienta to Quick.

Parametrem może być zdanie o maksymalnej długości 255 znaków. Umożliwia to zadawanie użytkownikom pytań o
kryteria w bardziej zrozumiały lub po prostu bardziej grzeczny sposób. Zmień parametr i sposób jego przedstawienia na
Proszę wprowadzić kod klienta.

Teraz kwerenda, pytając klienta, użyje powyższego zdania.

Tworzenie parametrów w kwerendach korzystających z programu


Kwerendy parametryczne mogą działać w aplikacjach w inny sposób – poprzez program. Parametry tworzą w kwerendzie
zbiór, do którego możesz zwracać się podczas wykonywania kwerendy w kodzie VBA. Ma to swoje dobre strony. W
interfejsie użytkownika możesz pobrać wszystkie parametry poprzez formularz, jednocześnie kontrolując typ danych i ich
poprawność, a następnie umieścić je wszystkie w kwerendzie parametrycznej. Umożliwia to użytkownikowi całościowe
przeglądanie tego, co wpisuje, i dokonywanie
zmian przed otrzymaniem zestawu rekordów. Podczas normalnego wykonywania kwerendy parametrycznej użytkownik nie
ma możliwości powrotu do poprzednich parametrów. Po wpisaniu wartości może jedynie iść dalej lub anulować kwerendę.

Tworzenie kwerend parametrycznych


– siatka QBE a program
Często programiści wykonują procedury SQL poprzez kod. W wielu przypadkach sposób ten sprawdza się doskonale,
jednakże nie jest pozbawiony wad. Po pierwsze, procedury SQL mogą być niezrozumiałe lub niedostępne dla innych,
mniej doświadczonych programistów, których zadaniem w przyszłości może być obsługa tej aplikacji. Może to doprowadzić
do błędów w jej działaniu. Użycie kwerendy parametrycznej umożliwia innym programistom, posiadającym oczywiście
odpowiednie uprawnienia, modyfikowanie kwerendy poprzez siatkę QBE, co może być uważane za wspólny mianownik
użytkowników i programistów Accessa. Najważniejszy jest fakt, że w większości przypadków kwerenda parametryczna
jest najszybszym i najbardziej wiarygodnym sposobem na wykonywanie kwerendy bez zmiany jej kryteriów lub
właściwości. Dzieje się tak, ponieważ Access kompiluje kwerendy, więc Jet ma już gotowy ich profil wykonywania. Krótko
mówiąc, ciąg SQL w kodzie nie jest zoptymalizowany, a kwerenda parametryczna może być optymalizowana. Kiedy
kwerenda parametryczna jest we właściwy sposób wykonywana poprzez program, użytkownik nie jest proszony o podawanie
żadnych informacji.

Wykonywanie kwerendy parametrycznej


poprzez program
Teraz pokażemy, w jaki sposób kwerenda parametryczna może być wykonywana poprzez kod. Wydruk 4.16 akceptuje
nazwę kwerendy i jeden parametr, a następnie używa tych argumentów, aby otworzyć daną kwerendę i policzyć jej rekordy.
Zwracana wartość to ilość rekordów w zestawie rekordów. Możesz uruchamiać tę funkcję z okna Analiza programu lub
poprzez zdarzenie na formularzu.

Wydruk 4.16. Funkcja wykonująca kwerendę parametryczną poprzez kod


Function RunParameterQuery (QryName As String, CustID As String)
'Funkcja ta uruchomi kwerendę parametryczną, która
'pobiera ID klienta jako argument
'Argumenty:
' QryName – Nazwa kwerendy parametrycznej
' CustID – Ciąg identyfikujący klienta
'Z "Access 2000 – Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston
Dim db As Database
Dim qrydef As QueryDef
Dim rs As Recordset
Set db = CurrentDb()
Set qrydef = db.QueryDefs (QryName)
'Tutaj parametrowi nadajemy nazwę.
Qrydef ("ID klienta") = CustID
Set rs = qrydef.OpenRecordset()
RunParamQuery = rs.RecordCount
Rs.Close
Część I ♦ Projektowanie bazy danych 72

End Function

Wykonywanie kwerendy poprzez zbiór parametrów


Wydruk 4.17 wykorzystuje w kwerendzie zbiór parametrów. Umieszczając w argumentach funkcji słowo kluczowe
ParamArray, możesz używać jej z różnymi kwerendami parametrycznymi, niezależnie od ilości wymaganych przez nie
parametrów. Funkcja wykonuje pętlę poprzez tablicę ParamArgs() i przyznaje parametry w kolejności ich podawania.
Aby użyć tej funkcji, uruchom ją z okna Analiza programu. Otrzymany rezultat to ilość rekordów. Kilkukrotne
uruchomienie tej funkcji zaowocuje przyspieszeniem pracy kwerend parametrycznych.

Wydruk 4.17. Funkcja uruchamiająca kwerendy parametryczne ze zmienną ilością parametrów


Function OpenParamQuery (QryName, _
ParamArray ParamArgs() As Variant) As Long
'Z "Access 2000 – Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston
'Argumenty
' QryName – Nazwa kwerendy prametrycznej
' ParamArgs – Zmienna lista wartości wprowadzanych do
' parametrów kwerendy. Muszą być
' ułożone w takiej kolejności, w jakiej spodziewa się ich kwerenda.
Dim db As Database
Dim qrydef As QueryDef
Dim i As Integer
Dim rs As Recordset
Dim rscount As Long
On Erro GoTo OpenParameterQuery_Error
Setdb = CurrentDb()
Set qry = db.QueryDefs(QueryName)
'Przejdź przez wszystkie parametry I przyznawaj je według indeksów
For i = 0 To Ubound(ParamArgs())
qry.Parameters(i) = ParamArgs(i)
Next
Set rs = qry.OpenRecordset(dbOpenSnapshot)
OpenParameterQuery = rs.RecordCount
OpenParamQuery_Exit:
Set qry = Nothing
rs.Close
Exit Function
OpenParamQuery_Error:
OpenParamQuery = 0
GoTo OpenParamQuery_Exit
End Function

Jeśli dokonasz parametryzacji zagnieżdżonej kwerendy, wciąż będzie ist-


niał tylko jeden zbiór parametrów.

Kwerendy przekazujące
Access posiada umiejętność łączenia tabel z innych źródeł danych i tworzenia opartych na nich kwerend tak, jakby były
utworzone w Accessie. Oprócz tego, Access może również przesyłać kwerendy do innych baz danych. W takiej sytuacji,
obca baza sama przetwarza swoje dane i zwraca jedynie zestaw rezultatów.

Głównymi przyczynami, dla których warto używać kwerend przekazujących, są: wydajność i przepustowość sieci. Gdy
dołączasz tabelę z bazy typu klient-serwer (np. SQL Server lub Oracle) i uruchamiasz kwerendę opartą na tej tabeli, serwer
nie jest w stanie stwierdzić, czego od niego oczekujesz. Nawet, gdyby serwer mógł zobaczyć procedurę SQL Accessa, nie
mógłby jej zinterpretować, gdyż jest napisana w innym dialekcie SQL niż ten używany przez serwery. Wówczas serwer
może tylko przesłać olbrzymie ilości informacji na komputer klienta i pozostawić wszystkie obliczenia silnikowi Jet. W
przypadku dużych baz operacja taka może spowolnić działanie sieci i w żadnym wypadku nie można jej nazwać
efektywnym korzystaniem z serwera. Zamiast tego, możesz, korzystając z kwerendy przekazującej, „spotkać” serwer w pół
drogi.

Kwerenda przekazująca jest jedną z kwerend charakterystycznych dla języka SQL, co oznacza, że będziesz musiał ją
napisać w SQL. A tak właściwie, to w dialekcie SQL serwera. Wiele opcji, z których możesz korzystać w Accessie, nie jest
dostępnych w kwerendach przekazujących. Jednakże wzrost prędkości i zmniejszenie obciążenia sieci zrekompensują to z
nawiązką.
73 Rozdział 4. ♦ Zaawansowane kwerendy

Tworzenie kwerendy przekazującej


Kwerenda przekazująca tworzona jest tak jak każda inna kwerenda, z tą różnicą, że nie dodaje się do niej żadnych tabel. Po
jej utworzeniu z menu Kwerenda wybierz opcję Wyłącznie SQL, a następnie Przekazująca. Spowoduje to zamianę okna
Kwerenda w okno SQL. Istnieją tylko dwie właściwości, ważne dla uruchamiania kwerendy przekazującej: sama procedura
SQL i ciąg połączenia. Procedura SQL zawiera polecenia dla serwera we właściwej, zrozumiałej dla niego składni SQL.
Ciąg połączenia zawiera informacje niezbędne, by kwerenda mogła skontaktować się z serwerem.

Oto przykład możliwego ciągu połączenia:


ODBC;
DRIVER=SQL SERVER;
SERVER=Access2000UnleashedServer;
UID=sa;
DATABASE=PUBS;
TRUSTED_CONNECTION=YES

ODBC (Open Database Connectivity) to przedrostek ciągu połączenia. Poprzedza on zawsze ciągi połączenia do baz danych
SQL Server, Oracle, Informix i Sybase. Każde źródło danych ODBC używa sterownika, aby tłumaczyć polecenia ODBC.
Nazwa zazwyczaj przypomina nazwę oprogramowania serwera. Server to właściwy adres, pod którym znajduje się baza
danych. UID (User ID) informuje serwer, kim jesteś. W ciągu połączenia może być również przechowywane hasło,
jednakże nie jest to zalecane. Na jednym serwerze może znajdować się wiele baz danych. Warunek Database wskazuje
kwerendzie odpowiednią bazę. Trusted Connection umożliwia dostanie się do serwera, jeśli masz na nim utworzony
profil, któremu serwer „ufa”.

Jeśli nie jesteś pewien, jak ciąg połączenia powinien wyglądać, skontaktuj się z administratorem bazy danych lub skopiuj
ciąg połączenia z dołączonej tabeli. Następnie wklej go do właściwości ciągu połączenia kwerendy i zmodyfikuj opisane
wcześniej właściwości.

Po ustawieniu właściwości możesz wprowadzić wyrażenie SQL o składni właściwej dla serwera, do którego adresowana
będzie kwerenda. Oto przykład prostego wyrażenia SQL dla bazy SQL Server. Rezultat przedstawiony jest na rysunku
4.20.
Select * from klienci Where Kraj = 'USA'

Rysunek 4.20.
Wynik kwerendy
przekazującej SQL

Teraz siecią przesyłany jest jedynie zestaw rezultatów, ponieważ całą pracę wykonał serwer. Następnym krokiem jest
stworzenie widoków i procedur przechowywanych na serwerze. Procedury przechowywane na serwerze mogą być
uruchamiane z poziomu kwerendy przekazującej, poprzez podanie ich nazw i wszystkich wymaganych parametrów.
Dodatkową zaletą tego sposobu jest to, iż serwer może polegać na własnych zdolnościach optymalizacyjnych i profilach
wykonania, aby uzyskać jeszcze większą wydajność.

Kwerendy definiujące dane


Poza umiejętnością manipulowania danym zawartymi w tabelach kwerendy Accessa mogą również tworzyć, modyfikować i
usuwać tabele w Accessie w taki sposób, by nadać aplikacji umiejętność inteligentnej pracy z danymi.
Część I ♦ Projektowanie bazy danych 74

Kwerendy definiujące dane mogą działać na tabelach Jet, lecz nie tylko. Jeśli zajdzie potrzeba definiowania danych w tabelach
nie utworzonych przez mechanizm Jet, zadziałać mogą obiekty DAO. Jeśli musisz definiować dane w tabelach baz SQL
Server lub Oracle, możesz skorzystać z podobnych opcji w ich językach SQL. Wykonuj ich definiujące dane procedury
SQL poprzez kwerendy przekazujące Accessa.

Kwerendy definiujące dane dokonują ciągłych modyfikacji w liczbie, struk-


turze i właściwościach tabel, indeksów i relacji. Zanim zaczniesz z nimi
pracować, sporządź kopię zapasową swojej bazy i uruchom je w kopii
swojego projektu.

Kwerendy definiujące dane posiadają podstawowy schemat, którego zrozumienie znacznie ułatwia korzystanie z nich.
Zaczynają się słowem kluczowym Create Table, Alter Table lub Drop Table, po którym występuje nazwa tabeli.
Kolejnym elementem jest umieszczona w nawiasie sekcja definiująca pole. Po niej występuje nazwa pola, jego typ danych, a
następnie rozmiar pola (w nawiasie). Sekcja definiująca dane może być dowolnej długości. Po każdej definicji pola może
występować warunek ograniczający, ustawiający indeksy, klucze i klucze: obcy lub nadający polu wartość NOT NULL. Wa-
runek ograniczający jest opcjonalny.

Tworzenie nowej tabeli


Logicznym początkiem pracy z kwerendami definiującymi dane jest procedura Create Table. Jak sama nazwa wskazuje,
będzie ona tworzyła tabelę, jednakże jej zdolności do tego się nie ograniczają. Korzystając z kwerendy tworzącej tabele,
możesz utworzyć tabele z poziomu siatki QBE, jednakże ten sposób nie umożliwia określenia rozmiaru i ograniczeń pola,
indeksów oraz relacji.

Korzystając z procedur definiujących dane w kwerendzie charakterystycznej dla języka SQL, możesz tworzyć lub
modyfikować tabele w taki sam sposób, jak dokonujesz zmian w tabeli w widoku Projekt.

Składnia prostej procedury Create Table wygląda następująco:


Create Table nazwatabeli (pole1 typdanych (rozmiar), pole2 typdanych (rozmiar),...,);

Budować kwerendy można jedynie w oparciu o zamknięte w danym mo-


mencie tabele.

Aby utworzyć tabelę zawierającą dwa pola o długości 15 znaków, możesz użyć następującej procedury:
CREATE TABLE TestTable (FirstName TEXT (15), LastName TEXT (15));

Po uruchomieniu tej kwerendy i odświeżeniu zawartości bazy zauważysz nową tabelę. Będąc w widoku Projekt zauważysz
również, że długość obu pól ustawiona jest na 15 znaków. Gdybyś użył tradycyjnej kwerendy tworzącej tabele, pola
miałyby długość 255 znaków. Rozmiar pola jest opcjonalną częścią procedury. Gdyby go w niej nie umieścić, pola miałyby
długość 255 znaków. Dobrze jest korzystać z tego polecenia, kiedy to tylko możliwe.

Modyfikowanie tabeli
Po utworzeniu tabeli możliwe jest modyfikowanie jej zawartości przy użyciu kwerend definiujących dane. Polecenie
Alter Table powoduje dodanie pola do tabeli. Podstawowe polecenie Alter Table ma następującą składnię:
ALTER TABLE nazwatabeli ADD
nazwapola1 typdanych (rozmiar),
nazwapola2 typdanych (rozmiar);

Aby zmodyfikować tabelę, dodając do niej dwa nowe pola, możesz użyć następującego polecenia:
Alter Table TestTable Add
Phone Text (10),
Fax Text (10),
Cellular Text (10);

Utworzone w ten sposób pola mogą być dalej określane za pomocą warunków ograniczających. Warunki te omówimy
jednak osobno. Nowością w Accessie 2000 jest możliwość dodawania więcej niż jednego pola jednocześnie. Jednakże
wciąż konieczne jest korzystanie z osobnych poleceń Drop do usuwania pól z tabeli.
75 Rozdział 4. ♦ Zaawansowane kwerendy

Alter Table TestTable drop Phone;

I
Alter Table TestTable drop Fax;

I
Alter Table TestTable drop Cellular;

Tworzenie indeksów
Po utworzeniu, zaimportowaniu bądź dołączeniu tabeli może zaistnieć konieczność utworzenia indeksu. Umożliwia to
polecenie Create Index.

Podstawowa składnia tego polecenia jest następująca:


CREATE [UNIQUE] INDEX nazwaindeksu
ON nazwatabeli (nazwapola1 ASC/DESC nazwapola2 ASC/DESC...)
[WITH Primary/Disallow Null/Ignore Null]

Jeśli indeks ma zawierać tylko wartości unikatowe, użyj słowa kluczowego UNIQUE. Warunek opcjonalny WITH umożliwia
wymuszenie zasad poprawności. Indeks może zakazać użycia wartości Null poprzez użycie Disallow Null. Opcja
Ignore Null dopuszcza rekordy z wartością Null w indeksowanym polu, jednakże usuwa je z indeksu. Gdy używane
jest słowo kluczowe PRIMARY, może zastępować słowo UNIQUE.

Poniższe wyrażenie utworzy indeks w nowej tabeli:


Create Index Nazwisko on TabelaTestowa(Nazwisko) with primary;

Zauważ, że dla polecenia CREATE INDEX składnia jest nieco inna. W tym przypadku nazwa pola poprzedza nazwę tabeli.

Sprawdź w projekcie tabeli, aby potwierdzić utworzenie klucza podstawowego w polu Nazwisko.

Możliwe jest tworzenie indeksów w tabelach połączonych ze źródłem da-


nych ODBC, jeśli tabele te nie posiadają jeszcze indeksu. W tym przy-
padku, indeksy nie znajdują się na serwerze. Rezydują w Accessie jako
dynamiczne odnośniki do pól z danymi. Serwer nie zauważa tych pseu-
doindeksów i nie są wymagane specjalne pozwolenia, aby je tworzyć. Aby
tego dokonać, użyj tej samej składni jak dla tabel źródłowych.
Pseudoindeksów używaj w przypadkach, gdy źródło ODBC nie posiada
własnego indeksu, a użytkownicy muszą aktualizować dane.

Usuwanie tabeli
Aby usunąć tabelę z bazy danych lub usunąć indeks z tabeli, użyj polecenia DROP TABLE lub DROP INDEX.
DROP TABLE nazwatabeli/[nazwaindeksu ON nazwatabeli]

Poniższe wyrażenie usunie z bazy tabelę i wszystkie zawarte w niej dane:


DROP TABEL TabelaTestowa

Określanie właściwości pól


Warunki ograniczające pozwalają na określenie pozostałych właściwości pól. Właściwości te można podzielić na dwie grupy:
klucze i relacje. Warunki ograniczające umieszczane są w po definicji pola w wyrażeniu definiującym dane. W warunku nie
jest stosowana interpunkcja, tak więc ważna jest kolejność.

Gdy określamy klucze, składnia jest następująca:


CONSTRAINT nazwawarunku PRIMARY KEY/UNIQUE/NOT NULL

Gdy określamy relacje dla tabeli lub pola, składnia warunku ograniczającego jest nieco inna:
Część I ♦ Projektowanie bazy danych 76

CONSTRAINT nazwarelacji REFERENCES nazwainnejtabeli (nazwapowiązanegopola)

Gdy tworzysz relacje między dwoma polami, za pomocą warunku CONSTRAINT, pamiętaj, że typy danych tych pól muszą
być takie same lub kompatybilne.

Znajdujące się na wydruku 4.18 wyrażenie definiujące dane tworzy tabelę z polem IDpracownika, o typie danych Long.
Pole to jest kluczem głównym tabeli. Tworzy ona również relację między tym polem i polem Idpracownika w tabeli
Pracownicy. Wyrażenie to tworzy jednocześnie pola Imię, Nazwisko i Telefon.

Wydruk 4.18. Użycie warunków podczas tworzenia pól


CREATE TABLE TabelaTestowa
(IDpracownika Long CONSTRAINT myFieldConstraint
PRIMARY KEY Constraint myRelations references Pracownicy (IDpracownika),
Imię TEXT,
Nazwisko TEXT,
Telefon TEXT)

Po uruchomieniu tej kwerendy otwórz okno Relacje i dodaj do niego tabelę TabelaTestowa. Access automatycznie rozpozna
relację między tabelami Pracownicy i TabelaTestowa.

Optymalizowanie kwerend
Oto kilka czynności, które może wykonać programista, aby zapewnić odpowiednią wydajność kwerendy:
u Indeksuj sprzężone pola po obu stronach relacji. Dotyczy to również tabel nie tworzonych przez mechanizm Jet.
u Gdy pomiędzy dwoma tabelami istnieje więcej niż jedno pole sprzężone, ustaw pola w siatce kwerendy w taki
sposób, w jaki występują w swoich tabelach.
u Utwórz indeks dla pól, których będziesz używał do sortowania. Nieindeksowane pola sortuj tylko w ostateczności.
u Upewnij się, że dla wszystkich pól wybrałeś właściwy typ danych i rozmiar. Rozmiar pól powinien być możliwie
najmniejszy.
u Nie przeciążaj siatki QBE. Używaj tylko pól niezbędnych dla zestawu rezultatów.
u Nie umieszczaj pól obliczanych w zagnieżdżonej kwerendzie. Zamiast tego, obliczenia wykonuj na końcu
sekwencji kwerend lub, jeśli to tylko możliwe, na formularzu i raporcie.
u Staraj się unikać korzystania z pól Grupuj według. Pola te zabierają dużo miejsca i mogą niekorzystnie wpływać na
wydajność. Jeśli pogrupowane pola mają indeksy, spróbuj używać ich w takiej samej kolejności, w jakiej
występują w tabeli.
u Kwerenda podsumowująca ze sprzężeniami może być bardziej wydajna po podzieleniu jej na dwie osobne
kwerendy. Pierwsza z nich wykonuje sprzężenie, a kwerenda grupująca korzysta z zestawu rezultatów pierwszej.
u Umieszczenie kryteriów po jednej zamiast po drugiej stronie relacji może mieć również wpływ na wydajność.
Zazwyczaj kwerenda z kryterium po stronie Jeden relacji jest szybsza, lecz eksperymentowanie może dać inne
wyniki.
u Formularze i Raporty zawsze działają szybciej, gdy są oparte na tabeli. Gdy to tylko możliwe, z zestawu
rezultatów twórz tabelę, na której będziesz opierał formularze i raporty.
u Kwerendy krzyżowe działają szybciej, gdy w nagłówku kolumny nie umieszczono żadnych obliczeń. Mimo iż
obliczenia te są czasami konieczne dla podsumowań, unikaj umieszczania ich jedynie ze względów
kosmetycznych.
u Używaj kwerend parametrycznych poprzez kod zamiast ciągów SQL w kodzie. Ponieważ kwerendy
parametryczne są obiektami kompilowanymi i mają profil wykonania, zazwyczaj będą działać szybciej niż
odpowiadający im ciąg SQL.

Gdy tylko to możliwe, korzystaj z techniki Accessa 2000 klient-serwer.


Rozdział 5.
Jet 4.0 – silnik baz danych Microsoft
W tym rozdziale:
u Historia Microsoft Jet.
u Praktyczne zastosowanie nowych opcji silnika Jet 4.0.

Access 2000 jest zaawansowanym interfejsem użytkownika dla silnika baz danych Microsoft Jet 4.0. Niezależnie od tego,
czy jesteś tego świadom, Jet zarządza bazą danych zawartą w pliku MDB. Gdy uruchamiasz plik typu MDB poprzez
obiekty DAO lub ADO, również używasz do tego silnika Microsoft Jet. Przechowuje on tabele, indeksy i kwerendy, które
uruchamia poprzez wbudowany mechanizm zapytań. Jet jest rozbudowaną, wyposażoną w kompletny zestaw funkcji,
wielowątkową, relacyjną bazą danych.

Historia Microsoft Jet


Dzisiaj Microsoft Jet używany jest jako aparat bazy danych w ponad 30 produktach firmy Microsoft. Można wśród nich
wymienić (oprócz, rzecz jasna, Accessa) takie programy, jak Project, Money, Team Manager, a nawet edukacyjne gry dla
dzieci. Jet całkowicie zdominował rynek domowych baz danych, gdyż każda jego edycja zawiera coraz nowocześniejsze
technologie. Cofnijmy się teraz odrobinę, aby prześledzić historię Microsoft Jet.

Jet 1.0
Historia Microsoft Jet rozpoczyna się ponad dziesięć lat temu, kiedy to w firmie Microsoft rozpoczęto wdrażanie projektu
Access. Gdy w 1992 roku Access 1.0 trafił na półki sklepowe, razem z nim na rynek domowych baz danych wszedł Jet 1.0.
Zawierał on wiele bardzo potrzebnych opcji domowych baz danych, jak definiowanie danych, kwe-

rendy, zabezpieczenia i indeksowanie. Jet był jednocześnie produktem pionierskim, gdyż zawierał wiele nowych opcji, jak
na przykład: kwerendy aktualizujące, heterogeniczne sprzężenia danych i możliwość tworzenia kwerendy w oparciu o inną
kwerendę. Opcje te umożliwiły programowi Microsoft Access osiągnąć pozycję najpopularniejszej domowej bazy danych.

Jet 1.1
Sukces Accessa był zaskoczeniem dla wszystkich, łącznie z firmą Microsoft. W maju 1993 roku wydano Access 1.1 oraz
Visual Basic 3.0, a razem z nimi Jet 1.1. Ta edycja umożliwiała programistom korzystanie z wielu nowych opcji:
poprawionej, zgodnej ze standardem ODBC komunikacji i nowych sterowników ODBC. Od tej pory zaprzestano tworzenia
kodu programu poprzez interfejs API ODBC, a dostęp do danych ODBC stał się możliwy dla każdego. Jet 1.1 umożliwił
również swoim użytkownikom łatwe dołączanie zewnętrznych danych, zwłaszcza w nowym formacie Microsoft FoxPro.
Poprawiono biblioteki obiektów DAO, a maksymalny rozmiar bazy Jet wzrósł ze 128 MB do 1,1 GB.

Jet 2.0
Jet 2.0 został wprowadzony na rynek w kwietniu 1994 roku wraz z bardzo popularnym Accessem 2.0. Dzięki takim opcjom
jak wymuszanie reguł poprawności na poziomie silnika bazy, czy integralności referencyjnej Jet 2.0 stał się nowoczesnym
Część I ♦ Projektowanie bazy danych 78

aparatem baz danych. Aby zwiększyć jego wydajność, dodano również zapożyczoną z FOX-a technologię Rushmore oraz
poprawiono funkcjonowanie SQL i obiektów DAO. Jet 2.0 był również, bardziej niż poprzednie wersje, zgodny z ANSI.

Jet 2.5
W październiku 1994 roku firma Microsoft wypuściła na rynek pakiet Service Pack do Accessa 2.0 oraz pakiet
sterowników ODBC Desktop Drivers Pack 2.0. Były to również narodziny Jet 2.5. W tej wersji do konstruowania wyrażeń
Jet używał już VBA, a wsparcie dla źródeł danych ODBC uległo znacznej poprawie. Ulepszono także obsługę aplikacji
przeznaczonych dla wielu użytkowników.

Jet 3.0
Gdy pod koniec 1995 roku Microsoft wypuścił na rynek Access 95, silnik Jet został wprowadzony w 32-bitowe
środowisko. Jet stał się zatem 32-bitowym silnikiem baz danych, posiadającym zdolność replikacji danych, a także
ulepszone opcje ODBC i DAO. Jet 3.0 był bardzo szybkim silnikiem baz danych.

Jet 3.5
Wraz z wprowadzeniem na rynek w styczniu 1997 roku pakietu Office 97 oddano do rąk użytkowników Jet 3.5. Był on już
w pełni 32-bitowym silnikiem baz danych, którego największym ulepszeniem był znaczny wzrost wydajności. Jet 3.5
zawierał także nowe zdolności buforowania danych, poprawione blokowanie stron, ulepszenia w pracy kwerend,
ODBCDirect oraz programowe anulowanie poleceń zapisu na dysk. Replikacja została rozszerzona o repliki częściowe, a
wsparcie danych zewnętrznych o obsługę danych HTML i Exchange.

Jet 3.51
Wypuszczenie na rynek w połowie 1997 roku Jet 3.51, będącego kontynuacją Jet 3.5, prawie nie zostało zauważone. Nowy
Jet zawierał ulepszoną metodę defragmentowania i naprawiania plików typu MDB. Opcja naprawiania została włączona w
znacznie poprawiony proces defragmentowania. W Jet 3.51 poprawiono błędy dotyczące niskopoziomowej obsługi wielu
użytkowników, jednakże najważniejsze w nim było narzędzie do defragmentowania i naprawy JetCOMP.exe,
korzystające z nowej opcji defragmentującej.

Jet 4.0
W czerwcu 1999 roku, wraz z pakietem Office 2000, Microsoft wypuścił na rynek Jet 4.0. Edycja ta była tym, na co czekali
wszyscy programiści. Jet 4.0 zawiera więcej funkcji niż wszystkie poprzednie wersje razem wzięte. Większość z nich
została dodana dzięki uwzględnieniu zgromadzonych przez lata próśb i uwag programistów. Wersja 4.0 to bardzo
rozbudowany program, zawierający tak zaawansowane opcje, jak:
u nowy wbudowany dostawca baz danych OLE;
u blokowanie na poziomie rekordów;
u pełna obsługa Unicode;
u ulepszone typy danych;
u poprawione funkcje Autonumerowania;
u przeszukiwalne pola typu Memo;
u poprawki trybu przeznaczonego dla wielu użytkowników;
u ulepszenia w replikacji;
u nowa składnia SQL (bardziej zgodna z ANSI 92).

Gdy poznasz te opcje i będziesz przy ich użyciu budował aplikacje, z trudem będziesz mógł sobie wyobrazić, jak
wyglądała Twoja praca, gdy tych opcji nie było.
79 Rozdział 5. ♦ Jet 4.0 – silnik baz danych Microsoft

Przyszłe wersje Microsoft Jet


Na początku 1998 roku pojawiły się plotki, że era Jet ma się ku końcowi. Wraz z pakietem Office 2000 Microsoft wydał
„domową” wersję SQL Server 7.0 i typ projektów Accessa, który był alternatywą dla Jet (ADP – patrz rozdział 15.
„Wprowadzenie do projektów programu Microsoft Access oraz narzędzi wizualnych”). Wraz z obiektami ADO 2.0 i
Universal Data Access, Microsoft wypuścił bazy danych OLE jako metodę dostępu do danych w architekturze klient-
serwer (więcej informacji o bazach danych OLE i obiektach ADO w rozdziale 6. „Wprowadzenie do obiektów danych
ActiveX” i 7. „Zaawansowane ADO”). ADO 2.0 i bazy danych OLE porozumiewają się ze źródłem danych bezpośrednio
poprzez OLE. Ponieważ Microsoft chciał korzystać z baz OLE dla architektury klient-serwer poprzez ADP, klienci uznali,
że to już koniec Jet. Microsoft zaprzeczył tym plotkom na wielu konferencjach prasowych i zapewnił, że silnik Jet będzie
nadal umieszczany w produktach tej firmy.

Praktyczne zastosowanie
nowych opcji silnika Jet 4.0
W rozdziale tym omówimy zaawansowane opcje silnika baz danych Microsoft Jet 4.0. Wszystkie przykłady kodu działają
w Accessie 2000, a po dokonaniu drobnych modyfikacji w Visual Basic 5 lub 6.

Wbudowany dostawca baz danych OLE


Jeśli jeszcze tego nie wiesz, strategia dostępu do danych Microsoftu opiera się aktualnie na obiektach ActiveX Data
Objects (ADO) (więcej informacji o obiektach ADO w rozdziale 6. „Wprowadzenie do obiektów danych ActiveX” i 7.
„Zaawansowane ADO”). Działanie obiektów ADO oparte jest na koncepcji powszechnego dostępu do danych, wy-
korzystującego do komunikowania się ze źródłami danych wbudowanych dostawców.

ADO 1.0 zawierało losowego dostawcę dla ODBC, tak więc gdybyś używał Jet i ADO, byłbyś zmuszony do korzystania z
warstwy ODBC. Jet 4.0 posiada wbudowanego dostawcę baz danych OLE o nazwie kodowej JOLT 4.0. Umożliwia Ci to
wykorzystywanie ADO jako metodologii dostępu do danych w aparacie Jet. Poprzez JOLT masz dostęp do zestawu funkcji
Jet, a ponadto do kilku opcji charakterystycznych dla JOLT. Temat ten będzie poruszany jeszcze kilkakrotnie w dalszej
części tej książki.

Blokowanie na poziomie rekordu


Tak, nie pomyliłeś się! Jet 4.0 obsługuje blokowanie na poziomie rekordu! Teraz możesz poprawić współbieżność
aplikacji, blokując jeden wiersz, a nie jak to miało miejsce wcześniej – całą stronę. Blokowanie na poziomie rekordu może
wpłynąć na znaczne zwiększenie wydajności obszernych, transakcyjnych baz danych. W niektórych testach, blokowanie na
poziomie rekordu umożliwiło sześciokrotną poprawę wydajności w stosunku do blokowania na poziomie strony.
Programowa obsługa blokowania na poziomie rekordu będzie dostępna w ADO i Accessie, ale nie w DAO. Bezpośrednią ko-
rzyścią z blokowania na poziomie rekordu jest koniec konfliktów z blokowaniem stron. Więcej na temat blokowania na
poziomie wiersza w rozdziale 21. „Zagadnienia wielodostępu, serwer plików, blokowanie”.

Pełna obsługa Unicode


Jet 4.0 przechowuje wszystkie dane o znakach (wszystkie pola typu Tekst i Memo) w kodzie Unicode. Umożliwia to łatwe
przełączanie się pomiędzy językami i zestawami znaków w aplikacji. Teraz, gdy konwertujesz coś na inny język lub
alfabet, masz 100% gwarancji zgodności danych po konwersji.

Czym jest Unicode?


Dzisiaj na świecie istnieje wiele nakładających się na siebie standardów kodowania znaków tekstowych. W przypadku
istnienia tak wielu różnych zestawów znaków dla stron kodowych proces tworzenia jednego, międzynarodowego kodu
podstawowego jest wyjątkowo trudny. Mniej więcej dziesięć lat temu firmy Apple i Xerox zaczęły wspólnie opracowywać
nowy standard zestawu znaków. W 1991 roku firmy te założyły konsorcjum Unicode. Obecnie jego członkami są między
innymi: Microsoft, Apple, AT&T, Compaq, Digital, Ecological Linguistics, Hewlett-Packard, IBM, Lotus, NeXT, Novell,
Reuters oraz wiele innych firm.
Część I ♦ Projektowanie bazy danych 80

Na początku lat dziewięćdziesiątych International Standards Organisation (ISO), w połączeniu z konsorcjum Unicode,
rozpoczęła prace nad podobnym standardem. Dzięki tej współpracy wydane w 1993 roku Unicode 1.1 i ISO 10646 są
identyczne.

Do przedstawiania znaków tekstowych ze wszystkich języków poza chińskim kod Unicode korzysta z 16-bitowego
schematu kodowania znaków o stałej szerokości. Kod Unicode rozwiązuje problem dużej liczby języków stron kodowych i
umożliwia wymianę i współdzielenie danych między wieloma językami bez ryzyka uszkodzenia.

Obsługa Unicode 1.1 w silniku Jet 4.0


Aby umieścić kod Unicode w silniku Jet 4.0, rozmiar strony danych został zwiększony do 4 KB. Umożliwiło to zmianę
ograniczenia wielkości pliku typu MDB z 1,07 GB do 2,14 GB. Ponieważ Unicode przechowuje dane w większych
stronach, rozmiar niektórych baz (z dużą ilością danych tekstowych) może się zwiększyć. Jednakże Jet umożliwia
kompresję kodu Unicode. Opcja Kompresja Unicode jest również dostępna podczas projektowania tabel w Accessie
(rysunek 5.1).
Rysunek 5.1.
Opcja Kompresja
Unicode w tabeli
w widoku Projekt

Kompresja indeksu jest domyślnie włączona i jeśli konwertujesz aplikację z


poprzedniego formatu pliku, wszystkie typy znaków będą miały włączoną
opcję Kompresja Unicode. Jeśli jednak baza danych jest już w formacie
pliku Jet 4.0, aby włączyć kompresję Unicode, właściwość ta musi zostać
ustawiona. Kompresja Unicode nie działa na polach typu Memo o rozmiarze
przekraczającym 4 kB, posiadających na stronie inne wiersze.

Aby przy użyciu SQL określić kolumnę, która będzie używać kompresji, podczas tworzenia tabeli z DDL użyj nowego
znacznika WITH COMPRESSION:
CREATE TABLE MyTable (MyCompressedField CHARACTER (255) WITH COMPRESSION)

Ta klauzula SQL dostępna jest jedynie poprzez kod VBA i ADO. Powyższe wyrażenie SQL możesz wykonać poprzez
aktualne połączenie ADO projektu VBA (wydruk 5.1).

Wydruk 5.1. Tworzenie skompresowanego pola Unicode w VBA


Private Sub cmdUnicode_Click()
'Procedura ta spowoduje utworzenie tabeli MyTable i
'skompresowanego pola w standardzie Unicode o nazwie MyCoolCounter
'Kod ten może być uruchamiany jedynie poprzez ADO w VBA
'i nie jest obsługiwany przez DAO
'Z książki "Access 2000 Księga Eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim strSQL As String

On Error GoTo Proc_Err


'Utwórz procedurę SQL
strSQL = "CREATE TABLE MyTable (MyCompressedField CHARACTER(255) WITH COMPRESSION)"
'Wykonaj procedurę SQL na
'aktualnym połączeniu ADO
81 Rozdział 5. ♦ Jet 4.0 – silnik baz danych Microsoft

CurrentProject.Connection.Execute strSQL

'Sukces
MsgBox "Tabela Utworzona OK", vbInformation

Proc_Exit:
Exit Sub
Proc_Err:
'Określ, czy tabela istnieje
If Err.Number = -2147217900 Then
MsgBox "Obiekt już istnieje. Usuń go i spróbuj jeszcze raz",_
vbCritical
Else
MsgBox Err.Description, vbCritical
End If

Resume Proc_Exit

End Sub

Sortowanie kompatybilne z NT
Umieszczenie kodu Unicode w silniku Jet 4.0 umożliwiło mu korzystanie z mechanizmu sortowania opartego na zestawie
funkcji Microsoft Windows NT. Ten nowy mechanizm sortujący używany jest przez Jet również w systemach Windows 95 i
98. W systemach tych możliwe jest również właściwe sortowanie wszystkich dostępnych w Windows NT języków, zamiast
jedynie domyślnego języka systemu, który Windows 95 obsługuje w swoim sortowaniu ANSI. Pozwala to szybciej i łatwiej
tworzyć międzynarodowe aplikacje, ponieważ teraz działa jednolite sortowanie we wszystkich systemach operacyjnych.

Microsoft SQL Server 7.0 i Visual Basic 6 używają do sortowania tego sa-
mego zestawu funkcji, czego rezultatem jest jednolitość między pro-
duktami.

Typy danych Jet


Tabela 5.1 zawiera przegląd typów danych Jet. Typy danych w silniku Jet 4.0 zostały poprawione, aby lepiej
współpracować z SQL Server. Aby ułatwić przenoszenie i replikowanie baz danych Jet do SQL Server, typy danych
zostały do siebie upodobnione. Nazwy typów danych Jet nie zawsze są takie same jak w Accessie. Access tłumaczy je za
Ciebie.

Tabela 5.1.
Przegląd typów danych Jet 4.0

Typ danych Jet Nazwa w Accessie Uwagi


Character Tekst Maksymalna długość to 255 znaków. Dzięki obsłudze Unicode
długość ta dotyczy wszystkich języków.
Dopuszczalne synonimy: Char, Varchar, Character Varying,
Nchar, National Character, National Char, Nvarchar,
National Character Varying i National Char Varying.

Tabela 5.1.
Przegląd typów danych Jet 4.0 (ciąg dalszy)

Typ danych Jet Nazwa w Accessie Uwagi


Użycie słowa Tekst bez określenia długości ma teraz inne
znaczenie. Jest synonimem dla Memo. To przybliża znaczenie
słowa Tekst silnika Jet do jego znaczenia w Microsoft SQL
Server.
Możesz wciąż używać słowa Tekst z określeniem długości,
na przykład TEKST (100), aby określić stałą ilość znaków
w kolumnie.
Poniższy przykład ilustruje użycie TEKST do określania typu
danych:
CREATE TABLE t1 (c1 TEXT) oznacza to samo, co CREATE
TABLE t1 (c1 MEMO) i zbliżone jest do definicji i składni
słowa TEXT w SQL Server.
CREATE TABLE t1 (c1 TEXT (100)) oznacza to samo co
Część I ♦ Projektowanie bazy danych 82

CREATE TABLE t1 (c1 CHAR (100)) i zapewnia


kompatybilność z większością już istniejących aplikacji
Microsoft Jet.
LongText Memo Maksymalna długość (w bajtach) wynosi teraz około 2.14 GB,
czyli w przybliżeniu 1.07 miliarda znaków.
Dopuszczalne synonimy to Text, Ntext, Memo, LongChar
i Note.
Binary Obiekt OLE Maksymalna długość to 255 znaków. Dopuszczalne
synonimy: Varbinary, Binary, Varying oraz Bir
Varying.

LongBinary Obiekt OLE Maksymalna długość wynosi teraz około 2,14 GB.
DateTime Data/Godzina Synonim Timestamp nie jest już akceptowany, a słowo
Timestamp w SQL Server nie odpowiada dokładnie
znaczeniu typu danych Data/Godzina.
Single Pojedyncza precyzja Dopuszczalne synonimy: Real, Float4 oraz IEEESingle.
Double Podwójna precyzja Dopuszczalne synonimy to Float, Double Precision,
Float8 i IEEEDouble.
Synonim Numeric nie jest już akceptowany dla tego typu
danych. Słowo Numeric używane jest do zdefiniowania
kolumny jako określonego typu danych, odpowiadającego
typom danych Decimal bądź Numeric w SQL Server.
Byte Bajt Jedyny dopuszczalny synonim to Tinyint.
Integer Liczba całkowita Dopuszczalne synonimy: Smallint, Integer2 oraz Short.
LongInteger Liczba całkowita długa Dopuszczalne synonimy: Int, Integer oraz Counter.
Nie jest już akceptowane słowo AutoIncrement. Więcej
informacji na ten temat znajdziesz w części
o autoinkrementacji kolumn.

Tabela 5.1.
Przegląd typów danych Jet 4.0 (ciąg dalszy)

Typ danych Jet Nazwa w Accessie Uwagi


Currency Walutowy Dopuszczalny synonim to Money.
Dane otrzymywane poprzez ODBC w formacie SQL_DECIMAL
lub SQL_NUMERIC (na przykład: SQL Server Decimal lub
Numeric) są kojarzone z typem danych Walutowy aparatu Jet.
Boolean Tak/Nie Dopuszczalne synonimy: Bit, Logical, Logical1 oraz YesNo.
GUID IDreplikacji Jedyny dopuszczalny synonim to UniqueIdentifier.
Decimal Dziesiętne Typ danych Dziesiętne jest nowością w aparacie Microsoft
Jet 4.0.
Jest to dokładny typ danych, przyjmujący wartości z zakresu
1028-1 do –1028-1. Możesz zdefiniować zarówno precyzję
(1-28) i skalę (0 – zdefiniowana precyzja). Domyślne
ustawienia precyzji i skali to odpowiednio 18 i 0.
Dopuszczalne synonimy to Dec i Numeric.
Dane otrzymywane poprzez ODBC w formacie SQL_DECIMAL
lub SQL_NUMERIC będą teraz kojarzone z typem danych
Dziesiętne aparatu Jet, a nie Walutowy.
Zauważ, że ten typ danych obsługiwany jest jedynie
przez ADO.

Ulepszenia opcji Autonumerowanie


Jet 4.0 daje pełną kontrolę nad polem typu Autonumerowanie. Masz teraz możliwość określenia punktu początkowego i
przedziału licznika. Możesz sprawić, by pole Autonumerowanie zaczynało się od 1000 i przyrastało o 100. Te funkcje
dostępne są jedynie poprzez SQL DDL do ADO/JOLT. Korzyścią, jaką dzięki temu otrzymujemy, jest większa kontrola
83 Rozdział 5. ♦ Jet 4.0 – silnik baz danych Microsoft

nad sekwencjami klucza podstawowego. Aby utworzyć tabelę o nazwie MyCoolCounter z Autonumerowaniem
rozpoczynającym się od 1000 i przyrastającym o 100 w polu CoolCounter użyj następującej składni SQL:
CREATE TABLE MyCoolCounter (CoolCounter IDENTITY (1000,100), myTextField CHAR)

Aby w dowolnym momencie modyfikować wartość początkową i przyrost, użyj polecenia ALTER TABLE. Przykładowo, by
zmienić punkt początkowy na 5000, a przyrost na 10, składnia jest następująca:
ALTER TABLE MyCoolCounter ALTER COLUMN CoolCounter IDENTITY (5000,10)

Możesz zawsze odnaleźć ostatnią wstawioną wartość, korzystając z polecenia SELECT @@IDENTITY. Inaczej będzie
zachowywać się baza w przypadku użycia wartości przyrostowych innych niż jeden. Jeśli wartość przyrostu jest inna niż
jeden, Jet nie zresetuje następnej wartości do maksymalnej dopuszczalnej wartości w tabeli.

Podobnie jak w poprzednich wersjach Jet domyślne ustawienie uniemożliwia użytkownikom edycję danych typu Licznik.
Jednakże administratorzy będą mieli możliwość nadania użytkownikom praw, umożliwiających im aktualizowanie danych
typu Licznik.

Przeszukiwalne pola Memo


W poprzednich wersjach Accessa i Jet pola typu Memo nie mogły być indeksowane. W silniku Jet 4.0 indeksowaniu
podlega pierwszych 255 znaków. Podczas przeszukiwania z użyciem znaków zastępczych (*) używany jest jedynie indeks.
Mimo iż funkcja ta działa poprawnie, ogranicza przeszukiwanie do pierwszych 255 znaków. Bierz to pod uwagę podczas
przeszukiwania pól Memo, bo jeśli kryterium, według którego przeszukujesz, nie mieści się w tym zakresie,
przeszukiwanie nie da właściwych rezultatów.

Kontrola połączeń i zamknięcie bierne


Wśród innych opcji związanych z obsługa wielu użytkowników należy wymienić nową Listę użytkowników, wyliczającą
wszystkich użytkowników bazy poprzez ADO, jak miało to miejsce w przypadku narzędzia LDBView. Opcja Kontrola
połączeń umożliwi Ci odmówienie dostępu do bazy. Mimo iż nie możesz „wyrzucić” innego użytkownika, możesz
zabezpieczyć się przed podłączaniem się do bazy nowych użytkowników. Opcja ta, wraz z zestawem funkcji Listy
użytkowników, pozwala biernie zamknąć bazę danych, a następnie, gdy wszyscy inni użytkownicy są odłączeni, otworzyć
bazę z wyłącznością. Znajdujący się na wydruku 5.2 kod programu przedstawia użycie Listy użytkowników z biernym
zamknięciem.

Wydruk 5.2. Użycie Listy użytkowników w ADO


Sub UserRoster(strPath As String)
Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset

Set conn = New ADODB.Connection

With conn
.Provider = "Microsoft.Jet.OLEDB.4.0"
.ConnectionString = "data source=" & strPath
.Open
End With

Set rst = conn.OpenSchema(adSchemaProviderSpecific, , _


"{947bb102-5d43-11d1-bdbf-00c04fb92675}")

Do Until rst.EOF
Debug.Print rst!COMPUTER_NAME
Debug.Print rst!LOGIN_NAME
Debug.Print rst!CONNECTED
Debug.Print rst!SUSPECTED_STATE

rst.MoveNext
Loop

End Sub

Otwieramy połączenie ADO do bazy danych, a następnie ustawiamy właściwość obiektu Jet OLEDB.Connection na 1. Tak
długo, jak obiekt połączenia ma wyznaczony zakres, żaden nowy użytkownik nie zostanie podłączony do bazy. Program
znajdujący się na wydruku 5.2 otwiera jednocześnie listę użytkowników jako zestaw rekordów ADO. Aby otworzyć listę
użytkowników, używamy metody połączenia z obiektem OpenSchema. Wymaga to przekazanie dość długiego identyfikatora
GUID dla obiektu ADO w celu wskazania Listy użytkowników. W ten sposób otrzymamy zestaw rekordów z nazwą kom-
putera, użytkownika (poprzez Jet Security lub Admin (przy braku zabezpieczeń), polem Connected, wskazującym czy dany
użytkownik jest połączony z bazą, oraz polem Suspected_State, stwierdzającym, czy istnieje podejrzenie uszkodzenia
bazy.
Część I ♦ Projektowanie bazy danych 84

Nowa składnia SQL


Do Jet 4.0 dodano wiele rozszerzeń SQL, aby mógł on obsługiwać nowy zestaw funkcji i był bardziej zgodny z ANSI 92
SQL. Dodatkową korzyścią jest fakt, iż większość z tych rozszerzeń ułatwia pisanie wyrażeń SQL funkcjonujących między
Jet a SQL Server. Ulepszenia SQL obejmują:
u Zabezpieczenia.
u Definiowanie widoków i procedur.
u Wywoływanie parametrów.
u Transakcje.
u Tworzenie i modyfikację tabel DDL.

Zabezpieczenia
Dzięki nowej składni, SQL obsługuje definiowanie zabezpieczeń bazy danych. Bezpośrednią z tego korzyścią jest
ułatwienie programowej obsługi zabezpieczeń. Możesz teraz zrezygnować z ADO i DAO na korzyść SQL, aby zaspokajać
swoje potrzeby w zakresie bezpieczeństwa. Poniższe wydruki zawierają rozszerzenia SQL obsługujące zabezpieczenia w
Jet 4.0:
CREATE/ADD/ALTER/DROP USER/GROUP
GRANT/REVOKE

Zabezpieczenia mogą być stosowane na poziomie następujących obiektów: CONTAINER (kontener), INDEX (indeks), QUERY
(kwerenda) i TABLE (tabela). Procedura na wydruku 5.3 przedstawia jak utworzyć na tabeli tblCustomers posiadającej
pełne uprawnienia grupę o nazwie SuperGroup. Następnie kod spowoduje odebranie tej grupie pozwolenia usuwania
danych z tabeli tblCustomers, po czym utworzy użytkownika o imieniu Steve i haśle Batman, aby na końcu dodać go do
grupy SuperGroup.

Wydruk 5.3. Ustawianie zabezpieczeń w Jet 4.0


Private Sub cmdSecurity_Click()
'Procedura ta spowoduje otwarcie pliku MDB z określonym plikiem 'zabezpieczeń,
ªa następnie dodanie użytkowników i grup
'Kod ten może być uruchamiany jedynie poprzez ADO w VBA
'i nie jest obsługiwany przez DAO
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim conn As ADODB.Connection

On Error GoTo Proc_Err

Set conn = New ADODB.Connection

'Ustaw połączenie do bazy danych


'używając ADO i określając w ciągu połączenia bazę systemową
With conn
.Provider = "Microsoft.Jet.OLEDB.4.0"
.ConnectionString = "data source=" & strPath & _
";Jet OLEDB:System database=" & strMDWPath
.Open
End With

'Wykonaj procedury SQL


conn.Execute "CREATE GROUP SuperGroup"
conn.Execute "GRANT SELECT, DELETE, INSERT, UPDATE ON tblCustomers TO ªSuperGroup"
conn.Execute "REVOKE DELETE ON tblCustomers From SuperGroup"
conn.Execute "CREATE USER Steve Batman"
conn.Execute "ADD USER Steve to SuperGroup"

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description, vbCritical
Resume Proc_Exit

End Sub

Funkcje zabezpieczeń SQL w Jet 4.0 zostały również wyposażone w możliwość tworzenia bądź nadawania hasła w
następujący sposób:
85 Rozdział 5. ♦ Jet 4.0 – silnik baz danych Microsoft

ALTER DATABASE PASSWORD NewPass OldPass

Definiowanie widoków i procedur


Jet 4.0 umożliwia zdefiniowanie zapisanej kwerendy jako widok lub procedurę. Widok może być zdefiniowany jako
nieparametryczna, zwracająca wiersze kwerenda. Procedurami nazywamy wszystkie nie korzystające z DDL i UNION
czynności oraz kwerendy parametryczne. Widoki i procedury możesz tworzyć zarówno poprzez ADO, jak i nową składnię
SQL Jet: CREATE VIEW i CREATE PROCEDURE. Nowa składnia jest bardziej kompatybilna z ANSI 92 i umożliwia
łatwiejsze przenoszenie widoków i Jet do innych baz ANSI 92 SQL, jak na przykład SQL Server. Poniższy kod SQL
tworzy widok i procedur.
CREATE VIEW qryAllCustomers AS SELECT * FROM tblCustomers
CREATE PROCEDURE qryAllCustomers_DEL AS DELETE * FROM tblCustomers

Wywoływanie parametrów
Poprzez ADO Jet 4.0 obsługuje teraz podawanie parametrów poprzez listę, co przypomina w działaniu wykonywanie
zapisanej parametrycznej procedury SQL Server. Zapisana kwerenda qryParameterQuery posiada dwa parametry –
EmployeeID i DepID:
PARAMETERS [EmployeeID] Long, [DepID] Long;
SELECT Employees.EmployeeID, Employees.[First Name],
Employees.[Last Name], Employees.Phone, Employees.[Dept ID]
FROM Employees
WHERE (((Employees.EmployeeID)=[EmployeeID])
AND ((Employees.[Dept ID])=[DepID]));

Podawanie parametrów i wykonywanie kwerendy parametrycznej jest teraz bardzo łatwe dzięki składni EXEC:
EXEC qryParameterQuery 1, 4179

Ten kod SQL podaje następujące wartości parametrów: EmployeeID=1 i DepID=4179. Parametry musisz podawać w
takiej kolejności, w jakiej znajdują się w kodzie SQL. Kod na wydruku 5.4 przedstawia, jak otwierać zestaw rekordów
ADO oparty na kwerendzie qryParameterQuery.

Wydruk 5.4. Otwieranie kwerendy parametrycznej w ADO


Private Sub cmdPramQuery_Click()
'Procedura ta spowoduje otwarcie kwerendy parametrycznej
'przy użyciu nowej składni EXEC
'Kod ten może być uruchamiany jedynie poprzez ADO w VBA
'i nie jest obsługiwany przez DAO
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim rst As ADODB.Recordset

On Error GoTo Proc_Err

Set rst = New ADODB.Recordset

'Otwórz zestaw rekordów oparty na


'wykonywanej kwerendzie parametrycznej
rst.Open "Exec qryParameterQuery 1", CurrentProject.Connection

'Display the results


MsgBox rst![FirstName]

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description, vbCritical
Resume Proc_Exit

End Sub

Transakcje
SQL Jet 4.0 obsługuje teraz transakcje. Transakcja musi obowiązkowo rozpoczynać się w następujący sposób:
BEGIN TRANSACTION

Aby utworzyć lub cofnąć transakcję, użyj odpowiednio poniższych poleceń:


ROLLBACK
ROLLBACK TRANSACTION
Część I ♦ Projektowanie bazy danych 86

Kod na wydruku 5.5 przedstawia, w jaki sposób można edytować i usuwać rekordy w jednej transakcji. Zauważ, że
transakcja musi rozpoczynać się w innej linii niż linia wyrażenia SQL.

Wydruk 5.5. Transakcje w SQL Jet 4.0


Sub Jet40Transaction()

Dim conn As ADODB.Connection


Set conn = CurrentProject.Connection

With conn
.Provider = "Microsoft.Jet.OLEDB.4.0"
.ConnectionString= "data source=" & Application.CurrentProject.Path & "employee_2k.mdb"
.Open
End With

'Execute the SQL Statements


conn.Execute "BEGIN TRANSACTION"
conn.Execute "UPDATE Employees SET Employees.HomePhone = " & _
Chr(39) & "2129560615" & Chr(39) & _
"WHERE (((Employees.EmployeeID)=1))"
conn.Execute "DELETE" &vbNewLine & _
"From tasks" & vbNewLine & _
"WHERE (((Tasks.[Emp ID])=1)); "
Conn.Execute "COMMIT TRANSACTION"

End Sub

Tworzenie tabel DDL


W Microsoft Jet 4.0 polecenie CREATE TABLE jest znacznie potężniejsze. Najbardziej interesującą opcją nowych
rozszerzeń SQL w silniku Jet 4.0 jest opcja CHECK CONSTRAINTS. Umożliwia ona rozszerzenie reguł biznesowych na
więcej niż jedną tabelę. Możesz użyć SQL do odnalezienia informacji w kilku tabelach, a następnie użyć tych informacji do
wymuszenia określonych warunków na nowo wstawianych rekordach. Załóżmy, że mamy tabele Customers (Klienci) i
Credit Limit (Limit kredytu). Możesz nakazać silnikowi Jet wymuszenie reguły biznesowej, która spowoduje, że nowo wsta-
wiany rekord może być zaakceptowany jedynie w sytuacji, gdy przyjmuje wartości niższe od przyjętego limitu
kredytowego. Ograniczenie to zdefiniowałbyś poprzez SQL w następujący sposób:
CHECK (<SQL Condition>)

Poniższy kod tworzy tabelę z ograniczeniem w polu CREDITLIMIT:


CREATE TABLE Customers (CustId IDENTITY (100,10),
CFrstNm VARCHAR(10), CLstNm VARCHAR(15), CustomerLimit DOUBLE,
CHECK (CustomerLimit <= (SELECT SUM (CreditLimit) FROM CreditLimit)));

Kod na wydruku 5.6 przedstawia, jak utworzyć tabelę CreditLimit, wprowadzić wartość, utworzyć tabelę Customers wraz z
ograniczeniem, a następnie jak spróbować wstawiać wiersze. Pierwszy rekord zostanie zaakceptowany, a drugi będzie
odrzucony ze względu na przekroczony limit kredytu.

Wydruk 5.6. Użycie ograniczeń


Private Sub cmdCreateConstraint_Click()
'Procedura ta spowoduje utworzenie 2 tabel, z których jedna
'będzie zawierać ograniczenie oparte na drugiej tabeli
'Kod ten może być uruchamiany jedynie poprzez ADO w VBA
'i nie jest obsługiwany przez DAO
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston
Dim conn As ADODB.Connection

On Error GoTo Proc_Err

Set conn = CurrentProject.Connection

'Utwórz tabelę sprawdzającą limit kredytu


conn.Execute "CREATE TABLE CreditLimit (CreditLimit DOUBLE);"
'Wprowadź limit kredytu
conn.Execute "INSERT INTO CreditLimit VALUES (100);"
'Utwórz tabelę Customers (Klienci) z ograniczeniem
conn.Execute "CREATE TABLE Customers_Con (CustId IDENTITY (100,"&_
" 10), CFrstNm VARCHAR(10), CLstNm VARCHAR(15), " & _
"CustomerLimit DOUBLE, CHECK (CustomerLimit <= " & _
"(SELECT SUM (CreditLimit) FROM CreditLimit)));"

'Dokonaj wprowadzenia
conn.Execute "INSERT INTO Customers_Con (CLstNm, CFrstNm, CustomerLimit)" & _
"VALUES ('Collins', 'Kevin', 100);"

'Przejdzie do tej linii, gdy limit kredytu złamie regułę


conn.Execute "INSERT INTO Customers_Con (CLstNm, CFrstNm, CustomerLimit)" & _
87 Rozdział 5. ♦ Jet 4.0 – silnik baz danych Microsoft

"VALUES ('Forte', 'Stephen', 101);"

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description, vbCritical
Resume Proc_Exit

End Sub

Gdy nakładasz ograniczenie na pole, Jet uniemożliwi Ci wprowadzenie w tym polu wartości niezgodnej z tą zasadą.
Rysunek 5.2 przedstawia komunikat o błędzie wywołany przez ostatni wiersz kodu na wydruku 5.6.

Rysunek 5.2.
Komunikat o błędzie
wyświetlany
w momencie
naruszenia
ograniczenia
Część II
Dostęp do danych
Rozdział 6.
Wprowadzenie
do obiektów danych ActiveX
W tym rozdziale:
u Historia dostępu do danych.
u Universal Data Access.
u Obiekty ActiveX Data (ADO).
u Model obiektowy ActiveX Data.
u Obiekty ADO: Recordset.
u Obiekty ADO: Error.
u Przejście z obiektów DAO do ADO.
u Porównanie modelu obiektowego ADO i DAO.

Wraz z wypuszczeniem na rynek pakietu Office 2000 do rąk użytkowników trafiły też obiekty ActiveX Data. Zastąpiły one
obiekty DAO oraz standard ODBCDirect i stały się jedyną metodą dostępu do danych zarówno dla Jet, jak i dla
architektury klient-serwer. Od tego momentu wystarczy nauczyć się jednej metody oraz jednego modelu obiektu.

Historia dostępu do danych


Teraz pokażemy, jak wyglądała droga do obiektów ADO. Spoglądając na nią, będziesz mógł docenić korzyści płynące z
ich używania.

Firmowe interfejsy API


Zanim Microsoft wprowadził na rynek swoje pierwsze produkty, jedyna droga na uzyskanie programowego dostępu do
danych prowadziła przez interfejsy API poszczególnych firm. Zmuszało to programistów do poznawania różnych API dla
każdego z systemów baz danych, dla których tworzyli aplikacje. Nie trzeba chyba dodawać, że rozwiązanie to było bardzo
niewygodne.

Open Database Connectivity (ODBC)


Kilka lat temu Microsoft wprowadził na rynek specyfikację Open Database Connectivity (ODBC). Był to ogólny,
programowy interfejs API, umożliwiający programistom tworzenie aplikacji dla każdej bazy danych, posiadającej
sterownik ODBC. Wymagało to wprawdzie znajomości API ODBC, ale nie trzeba już było poznawać interfejsu każdej ba-
zy, dla której tworzono aplikacje. API ODBC nie był łatwy w użyciu, jednakże był pierwszym krokiem na drodze do
rozwiązania problemu istnienia tak wielu API. Jak wiecie, ODBC szybko stał się standardową metodą dostępu do danych.
Część II ♦ Dostęp do danych 90

Microsoft Jet/Obiekty Data Access (DAO)


Gdy wraz z Accessem 1.0 do rąk użytkowników trafił Microsoft Jet i obiekty Data Access (DAO), dostęp do danych został
znacznie ułatwiony. Obiekty DAO dostarczały standardowego sposobu dostępu do danych dla Jet. Dodatkowo Jet mógł
poprzez ODBC komunikować się z wieloma źródłami danych zgodnymi z ODBC, oraz z innymi bazami danych. Z silnika
Microsoft Jet korzystały miliony użytkowników, aby dzięki jednemu modelowi obiektu dostępu danych uzyskać dostęp do
różnych baz.

Zdalne obiekty danych (RDO) i ODBCDirect


Wydając Visual Basic 4.0 Enterprise Edition, Microsoft wprowadził nowy model obiektowy dla źródeł ODBC, zdalne
obiekty danych (RDO – ang. Remote Database Objects). Obiekty RDO umożliwiały dostęp do danych ODBC z
pominięciem Jet. Uzyskano dzięki temu wzrost szybkości działania aplikacji. Mimo iż obiekty RDO były krokiem naprzód,
programiści (w tym również autorzy tej książki) nie byli zadowoleni z konieczności uczenia się dwóch modeli obiektowych
dostępu do danych. Większość z nich pracowała już z obiektami DAO i nigdy nie nauczyła się obsługiwać RDO. Odpowie-
dzią Microsoftu było ODBCDirect, rozszerzenie modelu obiektowego DAO, które wykorzystywało obiekty RDO jako
metody dostępu do zewnętrznych danych bez użycia Jet. Istniały już wówczas cztery metody dostępu do danych: API
ODBC, DAO, RDO oraz ODBCDirect. Pomnażanie modeli obiektu osiągnęło punkt krytyczny i jasnym było, że coś należy
z tym zrobić. Stąd inicjatywa Microsoftu o nazwie Universal Data Access.

Universal Data Access


Gdy istniało tak wiele metod dostępu do danych, Microsoft postanowił, poprzez inicjatywę Universal Data Access,
stworzyć nowy standard. Pierwszym etapem jej wprowadzania były bazy danych OLE – otwarta specyfikacja
zaprojektowana jako kontynuacja sukcesu ODBC. Bazy danych OLE to otwarty standard, umożliwiający dostęp do każde-
go rodzaju danych. ODBC stworzono jako metodę dostępu do danych w bazach relacyjnych, podczas gdy bazy danych OLE
zaprojektowano z myślą zarówno o relacyjnych jak i nierelacyjnych źródłach danych (skrzynki pocztowe, tekstowe i
graficzne dane w sieci WWW, usługi katalogowe oraz przechowywane na komputerach klasy mainframe dane IMS i
VSAM). ODBC używa sterowników ODBC do komunikowania się ze źródłami danych, natomiast bazy danych OLE
wykorzystują do tego celu dostawców danych. Bazy danych OLE umożliwiają nauczenie się tylko jednego modelu
obiektowego dla wszystkich baz a nawet używanie tego modelu podczas pracy z nierelacyjnymi źródłami danych.
Technologia OLE to znaczny postęp w porównaniu z ODBC, ponieważ potrafi porozumiewać się z wieloma różnymi
źródłami danych. Aby zapewnić kompatybilność z poprzednimi wersjami, do baz danych OLE dołączono dostawcę dla
ODBC. Dzisiaj istnieją również dostawcy dla Jet, SQL Server, Oracle, NT 5 Active Directory i wielu innych programów.

Rysunek 6.1 przedstawia aktualny wygląd technologii Universal Data Access. Głównymi obiektami dostępu do danych baz
OLE są obiekty ActiveX Data (ADO). Jak widzisz, zarówno bezpośrednio, jak i poprzez obiekty ADO, bazy danych OLE
mogą komunikować się z innymi bazami (relacyjnymi lub nie) oraz danymi na komputerze głównym za pomocą jednego
interfejsu.

Rysunek 6.1
Schemat dostępu do
danych – stan na
dzień dzisiejszy
91 Rozdział 6. ♦ Wprowadzenie do obiektów danych Active X

Obiekty ActiveX Data (ADO)


Obiekty ActiveX Data (ADO) to model obiektowy, którego możesz używać w celu pobierania danych z baz OLE.
Technologia ta istniała już od pewnego czasu, a od wersji 2.0 stała się preferowaną przez Microsoft metodą dostępu do
danych. Przyjrzyjmy się historii obiektów ADO.

ADO 1.0
Po wprowadzeniu na rynek w końcu roku 1996 obiekty ADO używane były głównie jako metoda dostępu do danych poprzez
skrypt w opartych na Active Server Pages aplikacjach internetowych. Posiadały one jedynie podstawowy zestaw funkcji
służący jako dostęp do danych w architekturze typu klient-serwer. W tym czasie obiekty ADO służyły jako podzestaw dla
popularnych modeli obiektów DAO i RDO. Programiści używali jedynego dostępnego dostawcy OLEDB – ogólnego
dostawcy dla wszystkich źródeł danych ODBC.

ADO 1.5
Jesienią 1997 roku Microsoft wprowadził na rynek ADO 1.5 oraz Microsoft Data Access Components 1.0 (MDAC) i IIS
4.0. Obiekty ADO w wersji 1.5 zawierały między innymi: Remote Data Services (RDS) i obsługę zestawów rekordów
odłączonych od bazy. Pierwszym dostawcą baz danych OLE, który ujrzał światło dzienne, był dostawca dla aparatu Jet o
nazwie JOLT.

ADO 2.0
Latem 1998 roku, wraz z wypuszczeniem wersji 2.0 MDAC, powstała trzecia wersja obiektów ADO – ADO 2.0. Był to
prawie nadzestaw RDO 2.0 i DAO 3.5, zawierający dodatkowo kilka interesujących opcji. Do ADO 2.0 dołączono również
dostawców baz danych OLE dla Jet, SQL Server i Oracle. Wiele z nowych opcji było już wcześniej wykorzystanych w
obiektach RDO i DAO, włączając w to operacje asynchroniczne i powtórną synchronizację poprzez kursory klienta. Obiekty
ADO zawierały też zupełnie nowe technologie, jak:
u Microsoft Data Links.
u Stałe zestawy rekordów.
u Zestawy rekordów tworzone przez użytkownika.
u Zestawy rekordów OLAP.

Wszystkie te technologie opisane są w rozdziale 7., „Zaawansowane ADO”.

ADO 2.1
Wydane wraz z SQL Serverem 7.0, pakietem Office 2000 i Internet Explorerem 5.0 obiekty ADO w wersji 2.1 zawierają
wszystkie opcje umieszczone w wersji 2.0 oraz dwa nowe modele obiektu:
u ADO – dla operacji DDL i zabezpieczeń (ADOX);
u JRO (Jet Replication Objects) – dla opcji replikacji oraz funkcji zmniejszania i naprawiania baz danych w silniku
Jet.
Do operacji związanych z Accessem i silnikiem Jet nie należy używać wer-
sji ADO dostarczanej wraz z SQL Serverem 7.0. Zawiera ona błędy i nie
wszystkie opcje opisane w tym i pozostałych rozdziałach będą w niej
funkcjonować. Upewnij się, że używasz wersji ADO dostarczanej wraz z
pakietem Office 2000 lub systemem NT 2000.

ADOX najlepiej współpracuje z JOLT, jednakże działa również z SQL Server i innymi dostawcami. JRO jest
rozszerzeniem przeznaczonym dla Jet, używanym głównie podczas replikacji. Model ADOX omówiony zostanie w
następnym rozdziale, a JRO w rozdziale 22., „Replikacja i JRO”.

Jak wszystko w tej branży obiekty ADO i bazy danych OLE są przez cały
czas udoskonalane. Trudno jest czasami nadążyć za zmianami. Jako że
Mi ft d j j bi któ ADO i l ż i d ki t Offi
Część II ♦ Dostęp do danych 92

Microsoft wydaje nowe wersje obiektów ADO niezależnie od pakietu Office


i naszej książki, więcej informacji i najnowsze szczegóły znajdziesz na
stronie WWW poświęconej tym zagadnieniom. Umieszczono na niej
mnóstwo próbek kodu i dokumentacji technicznej. Strona ta przedstawiona
jest na rysunku 6.2 i znajduje się pod adresem http://
www.microsoft.com/data.

Rysunek 6.2.
Strona WWW
dotycząca obiektów
ADO i baz OLE

Model obiektowy ADO


Model obiektu ADO jest bardzo prosty i płaski. W przeciwieństwie do modeli DAO i RDO model ADO nie jest
hierarchiczny. Znajduje się on na rysunku 6.3.
Rysunek 6.3.
Model obiektowy
ADO

Model obiektowy ADO składa się z siedmiu obiektów:


u Connection.
u Recordset.
u Command.
u Parameter.
u Field.
u Property.
u Error.

Ponieważ obiekty ADO oparte są na wspólnym modelu obiektowym (COM), tworzenie ich powinno być Ci już znane.
Przykładowo, możesz utworzyć obiekt połączenia ADO w taki sposób:
Dim conn As ADODB.Connection
Set conn= New ADODB.Connection
93 Rozdział 6. ♦ Wprowadzenie do obiektów danych Active X

Po utworzeniu obiektu możesz ustawić jego właściwości lub uruchomić go, na czym skupimy się w pozostałej części tego
rozdziału.

Obiekt Connection
Obiekt Connection przedstawia fizyczne połączenie do bazy lub dostawcy danych. Możesz otworzyć połączenie,
wskazując obiektowi Connection, którego dostawcy ma użyć, oraz określając ciąg połączeniowy. Kod ten przedstawiony
jest na wydruku 6.1 i znajdziesz go w pliku Rozdz06.mdb na dołączonej do książki płycie CD-ROM.

Wydruk 6.1. Łączenie z bazą danych Accessa poprzez ADO i obiekt Connection
Sub ConnectToDatabase()
'Procedura ta spowoduje utworzenie połączenia z bazą
'danych Accessa przy użyciu dostawcy OLE DB dla Jeta
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim conn As ADODB.Connection

On Error GoTo Proc_Err


'Utwórz obiekt połączenia
Set conn = New ADODB.Connection
With conn
'Ustaw właściwość dostarczyciela
'W ten sposób nakazujemy Ado użycie JOLT
.Provider = "Microsoft.Jet.OLEDB.4.0"
'W ciągu połączenia określ ścieżkę
'W tym miejscu możesz określić informacje
'dotyczące zabezpieczeń (co opisaliśmy w kolejnych rozdziałach)
.ConnectionString = "data source=C:\northwind.mdb"
'W ten sposób określamy tryb otwarcia bazy
'Możesz teraz dokonać wyboru między trybem "z wyłącznością"
'a "tylko do odczytu"
.Mode = adModeReadWrite
'Use the open method
.Open
End With

MsgBox "Połączony poprzez " & conn.Provider & _


" dostawcę OLE DB!", vbInformation

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description, vbCritical
Resume Proc_Exit
End Sub

Na wydruku tym wykorzystaliśmy następujące właściwości obiektu Connection:


u Provider.

u ConnectionString.

u Mode.

Provider jest ciągiem przedstawiającym unikatowy ProgID wybranego dostawcy OLEDB. My wybraliśmy
„Microsoft.Jet.4.0”, który jest dostawcą OLEDB dla Jet 4.0. Ciąg połączeniowy (ConnectionString) to określenie
ścieżki dostępu do bazy oraz innych informacji dotyczących połączenia, jak na przykład lokalizacja pliku grupy roboczej,
czy zabezpieczenia (więcej informacji o zabezpieczeniach w rozdziale 23.). Później ustawiliśmy właściwość Mode na stałą
ADO adModeReadWrite. Umożliwia nam to uruchomienie bazy danych w trybie Odczyt/Zapis. W tym miejscu możesz
również nakazać otwieranie bazy danych jedynie w trybie tylko do odczytu.

Otwarcie połączenia w Accessie 2000


Gdy używasz ADO w aplikacji działającej w Accessie 2000, określenie ciągu połączeniowego do tej samej bazy jest
krótsze. Ponieważ Access sam korzysta z globalnego obiektu Connection (jak CurrentDB w starszych wersjach DAO),
możesz określić właściwość Connection, używając obiektu CurrentProject.Connection:
Dim conn As ADODB.Connection
Set conn = CurrentProject.Connection
Część II ♦ Dostęp do danych 94

Wykonywanie wyrażeń SQL w obiekcie Connection


W aktualnym obiekcie Connection możesz wykonywać instrukcje SQL. Przypomina to wykonywanie metod z obiektu
bazy danych w DAO.

Wydruk 6.2 przedstawia, jak wykonywać wyrażenie SQL w obiekcie Connection.

Wydruk 6.2. Wykonywanie wyrażenia SQL w obiekcie Connection


Sub ConnExecute()
'Procedura ta spowoduje utworzenie połączenia z bazą
'danych Accessa przy użyciu dostawcy OLE DB dla Jeta,
'a następnie wykona polecenie
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim conn As ADODB.Connection


Dim strSQL As String
Dim lngRecordsAffected As Long

On Error GoTo Proc_Err


'Utwórz obiekt połączenia
Set conn = New ADODB.Connection

With conn
'Ustaw właściwość dostarczyciela
'W ten sposób nakazujemy Ado użycie JOLT'a
.Provider = "Microsoft.Jet.OLEDB.4.0"
'W ciągu połączenia określ ścieżkę
.ConnectionString = "data source=C:\northwind.mdb"
.Mode = adModeReadWrite
.Open
End With

'SQL Statement
strSQL = "UPDATE Customers SET Customers.Region = " & _
Chr(39) & "YK" & Chr(39) & vbNewLine & _
"WHERE (((Customers.Region)=" & _
Chr(39) & "BC" & Chr(39) & "));"

conn.Execute strSQL, lngRecordsAffected

MsgBox lngRecordsAffected & " rekordy zaktualizowane!", vbInformation

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description, vbCritical
Resume Proc_Exit
End Sub

Nasze wyrażenie zmieni wszystkie wiersze tabeli Customers, w których wartość pola Region="BC", w taki sposób, by
wartość tego pola była równa "YK". Zauważ, że możesz dowiedzieć się, ile rekordów zostało zmienionych, dodając
zmienną do metody Execute, a następnie sprawdzając wartość tej zmiennej.

Obiekty ADO: Recordset


Obiekt Recordset jest programowym zbiorem danych pochodzących z tabeli, kwerendy lub procedury SQL. Posiada on pola,
w których znajdują się dane z wierszy tabeli lub kwerendy, na której jest oparty. Aby otworzyć ten obiekt, musisz użyć
następującej składni:
Recordsetobject.Open "Statement", _
ActiveConnection, CursorType, LockType, Options

W tabeli 6.1 znajdują się opisy każdego z parametrów.

Wydruk 6.3 przedstawia, jak otworzyć zestaw rekordów oparty na tabeli Customers. Utworzyliśmy połączenie oparte na
aktualnej bazie danych, a następnie otwarliśmy zestaw rekordów z kursorem tylko do przekazania, tylko do odczytu.
Użyliśmy także parametru adCmdTableDirect, który „każe” Accessowi otworzyć tabelę bezpośrednio.

Wydruk 6.3. Otwarcie obiektu Recordset


Sub OpenRecordset()
'Procedura ta spowoduje otwarcie w aktualnej bazie
95 Rozdział 6. ♦ Wprowadzenie do obiektów danych Active X

'zestawu rekordów opartego na tabeli Customers,


'a następnie wydrukuje te rekordy
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim conn As ADODB.Connection


Dim rst As ADODB.Recordset

On Error GoTo Proc_Err

'Utwórz połączenie
Set conn = CurrentProject.Connection

'Utwórz nowy zestaw rekordów


Set rst = New ADODB.Recordset

'Otwórz zestaw rekordów


rst.Open "Customers", _
conn, adOpenForwardOnly, adLockReadOnly, adCmdTableDirect

'Utwórz pętlę w zestawie rekordów


Do Until rst.EOF
Debug.Print rst!CompanyName
rst.MoveNext
Loop

'Zamknij i usuń zestaw rekordów


rst.Close
Set rst = Nothing

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description, vbCritical
Resume Proc_Exit

End Sub

Tabela 6.1.
Parametry otwarcia obiektu Recordset

Argument Wymagany Uwagi Domyślnie


Statement Tak Nazwa tabeli, kwerendy bądź prawidłowe –
wyrażenie SQL
ActiveConnection Tak Prawidłowy obiekt Connection bądź –
prawidłowy ciąg połączenia
Cursor Type Nie adOpenDynamic – Możliwość adOpenForwardOnly
przeglądania zmian w zestawie rekordów,
nawet tych dokonanych przez innych
użytkowników
adOpenForwardOnly – Przekazywanie
dalej jedynie nieprzewijalnych zestawów
rekordów
adOpenKeyset – Brak możliwości
przeglądania zmian dokonanych przez
innych użytkowników; możliwość
przeglądania zmian dokonanych przez
aktualnego użytkownika
adOpenStatic – Brak możliwości
przeglądania zmian w zestawie rekordów
Lock Type Nie adLockBatchOptimistic – Blokuje adLockReadOnly
rekordy w programie wsadowym
adLockOptimistic – Blokowanie
optymistyczne
adLockPessimistic – Blokowanie
pesymistyczne
adLockReadOnly – Tylko do odczytu
Options Nie adCmdFile – otwarcie przechowywanego adCmdUnknown
na dysku zestawu rekordów
adCmdStoredProc – Przechowywana
procedura SQL Server lub kwerenda
Część II ♦ Dostęp do danych 96

Accessa
adCmdTable – wykonanie na tabeli
polecenia Select * From
adCmdTableDirect – Bezpośrednie
otwarcie tabeli (jak db OpenTable w DAO)
adCmdText – Procedura SQL
adCmdUnknown – Wartość nieznana,
Access określi ją za ciebie

Na wydruku 6.3 użyliśmy obiektu Connection, bazującego na aktualnym połączeniu:


'Otwórz zestaw rekordów
rst.Open "Customers", _
conn, adOpenForwardOnly, adLockReadOnly, adCmdTableDirect

W Accessie 2000 możesz użyć wyrażenia CurrentProject.Connection:


'Otwórz zestaw rekordów
rst.Open "Customers", _
CurrentProject.Connection, _
adOpenForwardOnly, adLockReadOnly, adCmdTableDirect

Możesz także dodać informacje o połączeniu – ciąg oraz polecenie dynamicznego otwarcia połączenia bez obiektu
Connection:
'Otwórz zestaw rekordów
rst.Open "Customers", "provider=Microsoft.Jet.OLEDB.4.0; " & _
"data source c:\northwind.mdb", _
adOpenForwardOnly, adLockReadOnly, adCmdTableDirect

Dodatkowo, oprócz otwarcia tabeli, możesz również otworzyć zestaw rekordów oparty na wyrażeniu SQL:
Rst.Open "Select * From Customers Where CustomerID= ALFKI", _
CurrentProject.Connection, _
adOpenForwardOnly, adLockReadOnly, adCmdTableDirect

Jak wiadomo, jedną z najważniejszych opcji silnika Jet jest wydajna praca z zewnętrznymi danymi. Aby otworzyć
zewnętrzne źródło danych, będziesz musiał zmodyfikować ciąg połączenia. Źródło danych musi wskazywać na zewnętrzny
plik, do którego chcesz uzyskać dostęp (tekstowy, DBF, Excela lub inny), a także musi być ustawiona właściwość
„Zaawansowane właściwości” indeksowego dostępu sekwencyjnego do plików. Kolejny przykład fragmentu kodu
przedstawia, w jaki sposób Jet może poprzez ADO uzyskać dostęp do arkusza kalkulacyjnego Excel 8.0. W poniższym
przykładzie otworzymy zestaw rekordów oparty na danych w arkuszu „Sheet1” pliku Customers.xls:
Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset

With conn
.Provider = "Provider=Microsoft.Jet.OLEDB.4.0."
.ConnectionString = "Data Source=C:\excel\Customers.xls;" &_
"Extended Properties=Excel 8.0;"
.Open
End With
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
rst.Open "Sheet1$", conn, _
adOpenDynamic, adLockOptimistic, adCmdTableDirect

Użycie Recordset z obiektami Command i Parameter


Obiekt Command przedstawia dość specyficzne polecenie, które będziesz wykonywał na źródle danych poprzez jego
dostawcę. Przykładem polecenia jest kwerenda funkcjonalna. Możesz również użyć Command w połączeniu z obiektem
Parameter, w celu wykona-
nia kwerend parametrycznych w Accessie lub procedur przechowywanych serwera SQL. Obiekt Parameter odnosi się do
parametru lub argumentu związanego z obiektem Command.
Przyjrzyjmy się teraz, w jaki sposób wykonać zapisaną kwerendę
parametryczną Accessa. Kwerenda ta znajduje się na płycie CD-ROM, w
pliku Rozdz06.mdb, pod nazwą qryCustOrders_Prm. Oto jej treść w SQL:
PARAMETERS OrderID Long;
SELECT Orders.*
FROM Orders AS Orders
WHERE (((Orders.OrderID)=[OrderID]));
97 Rozdział 6. ♦ Wprowadzenie do obiektów danych Active X

W siatce QBE Accessa zdefiniowaliśmy naszą kwerendę i utworzyliśmy dla niej parametr, korzystając ze znajdującej się w
menu Kwerenda opcji Parametry. Parametry zdefiniowaliśmy w sposób przedstawiony na rysunku 6.4.

Rysunek 6.4.
Okno dialogowe
Parametry
kwerendy

Teraz tworzymy obiekt Command i określamy, którego obiektu Connection będziemy używać i jaki to typ polecenia.
Każemy mu użyć utworzonego przed chwilą obiektu Connection, a następnie wskazujemy na znajdującą się w bazie
kwerendę qryCustOrders_Prm. Możesz użyć tych samych opcji dla zestawu rekordów w przypadku obiektu Command.
Dim cmd as ADODB.Command
Set cmd = New ADODB.Command

With cmd
.ActiveConnection = conn
.CommandText = “qryCustOrders_Prm"
.CommandType = adCmdStoredProc
End With

Ustawiliśmy właściwość CommandType na adCmdStoredProc, ponieważ ADO/Jolt traktuje zapisane kwerendy jak
procedury. Następnym rodzajem CommandType jest adCmdTable, używane w starszych wersjach Jet.

Gdy konwertujesz aplikacje z Jet 3.51 do 4.0 w Accessie 2000 lub VB6,
pamiętaj o różnicy w działaniu tych dwóch metod. W przypadku Jet 3.51
musisz określić CommandType jako adCmdTable, natomiast w aparacie Jet
4.0 powinieneś użyć adCmdStoredProc.

Aby ustawić informacje o parametrze, wystarczy określić cztery właściwości: Name, Type, Value i Direction. Nazwę
(Name) i typ danych (Type) wpisz takie same jak w zapisanej kwerendzie Jet. Będziesz musiał również określić właściwość
Direction, która informuje ADO, czy parametr jest wartością wejściową, wyjściową czy zwracaną. Teraz ustaw wartość
parametru, opierając się na tym, co użytkownik określił w aplikacji, a następnie dodaj parametr do zbioru parametrów
obiektu Command.

Gdy używasz obiektów Command, Jet obsługuje jedynie parametry wejścio-


we. SQL Server oraz inne serwery baz danych potrafią obsługiwać pa-
rametry wyjściowe w zapisanych procedurach, tak więc nie próbuj wpro-
wadzać parametrów wyjściowych.

With prm
.Name = "OrderID"
.Value = 10248
.Type = adInteger
.Direction = adParamInput
End With
cmd.Parameters.Append prm

Teraz korzystamy z metody Execute obiektu Command, aby utworzyć obiekt Recordset. Możesz użyć danych z zestawu
rekordów, aby wypełnić pola tekstowe w formularzu VB lub wykonać obliczenia. Aby otrzymać dane z wykonanego pole-
cenia, musisz ustawić Recordset na wykonane polecenie w następujący sposób:
Set rst = cmd.Execute

Wydruk 6.4 łączy te wszystkie przykłady i otwiera zestaw rekordów oparty na wykonanym poleceniu.

Wydruk 6.4. Wykonywanie polecenia


Sub OpenRecordsetviaCommand()
'Procedura ta spowoduje otwarcie w aktualnej bazie
'zestawu rekordów opartego na obiekcie Command,
'Obiekt ten będzie odwoływał się do znajdującej się w bazie
'kwerendy qryCustOrders_Prm
Część II ♦ Dostęp do danych 98

'Z książki "Access 2000 Księga eksperta" (Helion)


'Autorzy: Forte, Howe, Ralston

Dim conn As ADODB.Connection


Dim rst As ADODB.Recordset
Dim cmd As ADODB.Command
Dim prm As ADODB.Parameter

On Error GoTo Proc_Err

'Utwórz połączenie
Set conn = CurrentProject.Connection

Set cmd = New ADODB.Command

With cmd
.ActiveConnection = conn
.CommandText = "qryCustOrders_Prm"
.CommandType = adCmdTable
End With

Set prm = New ADODB.Parameter

With prm
.Name = "OrderID"
.Value = 10248
.Type = adInteger
.Direction = adParamInput
End With
cmd.Parameters.Append prm

Set rst = cmd.Execute

'Utwórz pętlę w zestawie rekordów


Do Until rst.EOF
Debug.Print rst!OrderDate
rst.MoveNext
Loop
'Zamknij i usuń zestaw rekordów
rst.Close
Set rst = Nothing
Set cmd = Nothing
Set prm = Nothing
Set conn = Nothing

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description, vbCritical
Resume Proc_Exit
End Sub

Wykonywanie kwerendy funkcjonalnej


poprzez obiekt Command
Możesz wykonywać zapisane kwerendy funkcjonalne Accessa poprzez
obiekt Command. W pliku Rozdz06.mdb znajduje się kwerenda
qryUpdateTitle, aktualizująca stanowisko każdego z pracowników w
tabeli Customers, od Account Manager do Account Executive. Oto ta
kwerenda w języku SQL:
UPDATE Customers SET Customers.ContactTitle = "Account Executive"
WHERE (((Customers.ContactTitle)="Account Manager"));

Aby uruchomić tę kwerendę programowo poprzez ADO, musisz utworzyć obiekt Command, skojarzyć go z obiektem
Connection i wykonać. Wydruk 6.5 przedstawia, jak tę czynność wykonać.

Wydruk 6.5. Wykonywanie kwerendy funkcjonalnej Accessa poprzez ADO


Sub ActionQueryCmd()
'Procedura ta spowoduje uruchomienie kwerendy funkcjonalnej
'poprzez obiekt Command, a następnie wydrukuje właściwości
'zestawu rekordów
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim cmd As ADODB.Command


Dim lngRecordsAffected As Long
99 Rozdział 6. ♦ Wprowadzenie do obiektów danych Active X

On Error GoTo Proc_Err

Set cmd = New ADODB.Command


Dim rst As ADODB.Recordset

With cmd
'Połącz z aktualną bazą danych
.ActiveConnection = CurrentProject.Connection
'Nazwa kwerendy w Accessie
.CommandText = "qryUpdateTitle"
'Ustaw tę własciwość jako adCmdStoredProc, Jet zaklasyfikuje
'Zapisane Kwerendy jako procedury dla obiektu Command
.CommandType = adCmdStoredProc
'Uruchom kwerendę
.Execute, lngRecordsAffected
End With

MsgBox lngRecordsAffected & " rekordy zaktualizowane!", _


vbInformation
Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub

Obiekty Field i Property


Obiekty Field i Property świetnie nadają się do odnajdywania informacji o tabeli lub zestawie rekordów. Obiekt Field
przedstawia każdą kolumnę pól w zestawie rekordów. Obiekt Property przedstawia każdą właściwość, niezależnie od
tego, jakiego obiektu dotyczy kwerenda. Możesz przechodzić przez każde pole w zestawie rekordów lub właściwość
zmiennej obiektu poprzez składnię For...Each – patrz wydruk 6.6.

Wydruk 6.6. Wykorzystanie obiektów Field i Property poprzez ADO


Sub FieldandProperty()
'Procedura ta spowoduje wydrukowanie wszystkich pól
'zestawu rekordów wraz z ich wartościami oraz właściwości
'zestawu rekordów
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston
Dim rst As ADODB.Recordset
Dim fld As ADODB.Field
Dim prp As ADODB.Property

On Error GoTo Proc_Err

Set rst = New ADODB.Recordset


'Otwórz zestaw rekordów oparty na tabeli klienci
rst.Open "Customers", CurrentProject.Connection

'Wydrukuj nazwę i wartość każdego pola


Debug.Print "Table Fields:"
For Each fld In rst.Fields
Debug.Print fld.Name & ": " & fld.Value
Next fld

'Wydrukuj właściwości tabeli


Debug.Print
Debug.Print "Table Properites:"
For Each prp In rst.Properties
Debug.Print prp.Name
Next prp

rst.Close
Set rst = Nothing
Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub
Część II ♦ Dostęp do danych 100

Obiekty ADO: Error


Podczas pisania kodu zdarza się popełnić błąd lub umożliwić dokonywanie zmian poza kontrolą użytkownika (jak na
przykład umożliwić administratorowi sieci LAN przeniesienie bazy danych bez poinformowania Cię o tym). Obiekt
Connection posiada zbiór obiektów Error, które przedstawiają każdy z występujących błędów. Obiekt Error posiada
kilka istotnych właściwości. Umieściliśmy je w tabeli 6.2.

Tabela 6.2.
Główne właściwości obiektu Error

Właściwość Komentarz
Description Opis błędu
Number Numer błędu ADO
Native Error Numer błędu dostawcy
SQL State Kod błędu charakterystyczny dla dostawcy. W silniku Jet oznacza on dawny numer
błędu DAO
Source Źródło błędu. W naszym przypadku będzie to Jet

Ponieważ dowolny błąd w kodzie może powodować wiele błędów ADO, możesz przeglądać zbiór błędów obiektu
Connection, a następnie sprawdzać poszczególne właściwości. Jeśli użyłeś w aplikacji kodu opartego na dawnej
numeracji błędów DAO, aby uzyskać kompatybilność wstecz będziesz zmuszony użyć właściwości SQLState. Dzięki niej
uzyskasz dawny kod błędu DAO. Możesz przeglądać zbiór błędów, korzystając z obiektu Error (wydruk 6.7). Wynik
działania programu z wydruku 6.7 znajduje się na rysunku 6.5.

Wydruk 6.7. Użycie obiektu Error


Sub ConnErrHandle()
'Procedura ta wymusi powstanie błędu, a następnie
'użyje obiektu Error w celu uzyskania informacji o tym błędzie
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset

On Error GoTo Proc_Err


Set conn = CurrentProject.Connection
Set rst = New ADODB.Recordset
Rysunek 6.5.
Komunikat o błędzie
wykorzystujący
obiekt Error

'Wymuś błąd
rst.Open "badTable", conn

Proc_Exit:
Exit Sub
Proc_Err:
Dim adoErr As ADODB.Error
'Przejdź przez każdy z błędów
'w zbiorze błędów połączenia
For Each adoErr In conn.Errors
101 Rozdział 6. ♦ Wprowadzenie do obiektów danych Active X

'Dla każdego z błędów wyświetl komunikat


MsgBox "Błąd ADO: " & adoErr.Description & _
vbNewLine & "Błąd wewnętrzny: " & _
adoErr.NativeError & _
vbNewLine & "Procedura SQL: " & _
adoErr.SQLState & _
vbNewLine & "Źródło: " & _
adoErr.Source, vbCritical, _
"Kod błędu: " & adoErr.Number
Next adoErr

Resume Proc_Exit

End Sub

Przejście z obiektów DAO do ADO


Wstęp do obiektów ADO wykazał, że istnieje wiele podobieństw między nimi a obiektami DAO. Przez całą tę książkę
będziemy pokazywać, w jaki sposób możesz korzystać z obiektów ADO, porównując je do DAO. Ta część stanowi wstęp
do procesu konwersji oraz porównanie tych dwóch modeli obiektu.

Konwersja z poprzednich wersji Accessa


Podczas przeprowadzania konwersji z poprzedniej wersji bazy danych Accessa do Accessa 2000 powinieneś wziąć pod
uwagę, że ADO jest nową, domyślną metodą dostępu do danych. Może to powodować zamieszanie podczas tworzenia
obiektu o tej samej nazwie w ADO jak i w DAO (na przykład „recordset”). Jeśli w Accessie użyjesz następującego kodu:
Dim db As Database
Dim rst as Recordset

Access 2000 przyjmie, że zmienna rst będzie rekordem ADO, a nie DAO, ponieważ ADO domyślnie znajduje się wyżej w
odwołaniach VBA. Przed dokonaniem konwersji baz danych z Accessa 97, 95 lub innych powinieneś przed nazwami
obiektów DAO umieścić przedrostek DAO. Powyższy kod powinien wyglądać następująco:
Dim db As DAO.Database
Dim rst as DAO.Recordset

Pozwoli to wyeliminować możliwość pomyłki w zmiennych obiektu DAO podczas konwersji.

Czy warto przejść na obiekty ADO?


W wypadku tworzenia nowej aplikacji w Accessie 2000 odpowiedź jest jedna: używać ADO. Lecz co w sytuacji, gdy
konwertujemy do Accessa 2000 już istniejąca aplikację? Wówczas przejście na obiekty ADO również powinno być brane pod
uwagę. Z pewnością zechcesz przejść na obiekty ADO jak najszybciej, by móc korzystać z opcji niedostępnych w DAO. Poza
tym, Microsoft zapowiedział odejście od technologii DAO, więc w kolejnych wersjach Accessa obiekty DAO nie będą
bezpośrednio obsługiwane. Ponieważ przyszłość należy do technologii ADO, powinieneś poważnie rozważyć jej wprowadzenie.
Czy masz na to czas? Pieniądze? Elementami, które powinieneś brać w tych rozważaniach pod uwagę, powinny być poziom
Twoich umiejętności oraz wysokość budżetu.

Książka ta oraz znajdująca się na stronie WWW Microsoftu dokumentacja dotycząca obiektów ADO
(http://www.microsoft.com.data) powinny przygotować Cię do nauki obsługiwania tej technologii. W następnej części
znajduje się opis przygotowania typowego planu konwersji.

Poznanie technologii ADO i proces konwersji kodu aplikacji z DAO do ADO powinny być częścią budżetu
przeznaczonego na konwersję. Proces konwersji do Accessa 2000 wymaga więcej czasu niż typowa konwersja. Postępując
według poniższych wskazówek, będziesz mógł zaoszczędzić dużo czasu, pieniędzy i wysiłku.

Schemat konwersji
W tej części pokażemy, jak powinieneś podejść do procesu konwersji aplikacji z DAO do ADO. Pamiętaj, zawsze
sporządzaj kopie zapasowe swojej pracy!
5. Uruchom Accessa 97. Jeśli aplikacja jest w starszej wersji niż Access 97, najpierw musisz ją skonwertować do
Accessa 97.
6. Przeanalizuj koszty. Dokonaj analizy bazy danych, aby określić, jak wiele procedur używa DAO. Następnie
sporządź w Excelu listę wszystkich procedur i oceń, ile czasu zajmie konwersja każdej z nich.
Część II ♦ Dostęp do danych 102

7. Ze strony WWW Microsoftu pobierz i zainstaluj ADO 2.1.


8. Rozpocznij konwersję od procedur, które nie komunikują się z innymi. Gdy skończysz konwersję jednej procedury,
dwukrotnie ją przetestuj. Dopiero wtedy przejdź do kolejnej. W zależności od wielkości bazy danych, operacja ta
może trwać dni lub nawet tygodnie.
9. Nie usuwaj starych procedur. Zmieniaj ich nazwy na NazwaProcedury_DAO, dodając na końcu _DAO, aby móc
szybko zmienić nazwę procedury ADO (używającej końcówki _ADO) i podmienić procedurę DAO podczas
testowania.
10. Po skonwertowaniu kodu w osobnych procedurach zacznij oględziny kodu tych większych i bardziej złożonych.
Nie trać czasu na poprawianie innych rzeczy w tych procedurach. Na dokonanie poprawek przyjdzie czas później.
Zmień tylko kod DAO. Użyj tej samej metodologii testowania, co w punkcie 5.
11. Po skonwertowaniu całego kodu przetestuj jednocześnie obie wersje aplikacji. Później przekaż nową aplikację do
testów innemu programiście.
12. Utwórz metody, które umożliwią użytkownikom łatwe wycofywanie dokonanych zmian. Dzięki temu, jeśli
aplikacja powoduje błędy w danych, użytkownicy będą mogli powrócić do poprzedniego stanu.
13. Oddaj do rąk użytkowników wersję beta, by mogli przetestować ją w codziennym użyciu. Do testowania wersji
ADO wybierz kilku wiarygodnych użytkowników. Nie usuwaj poprzedniej, działającej wersji DAO. Utwórz skrót
do niej, na wypadek wystąpienia błędów zakłócających pracę użytkowników.
14. Gdy jesteś już pewien, że użytkownicy w wystarczający sposób przetestowali aplikację, przeprowadź konwersję
do Accessa 2000 i powtórz kroki 7–9.

Upewnij się, że użytkownicy faktycznie testują aplikację!


Aby sprawdzić, czy użytkownicy faktycznie testują aplikację w wystarcza-
jący sposób, możesz dołączyć do niej technikę, której używamy my. Nie
chcemy być obarczani odpowiedzialnością za błędy, które użytkownik
mógł znaleźć podczas testowania, więc w wersjach beta umieszczamy
bardzo szczegółowe oprogramowanie monitorujące. Podczas uruchamiania
każdej procedury, nawet tak prostej jak przycisk Zamknij, zapisujemy w
bazie wszelkie informacje. Dzięki temu wiemy, jak często dany użytkownik
uruchamiał określoną procedurę, a nawet jak często tworzył dany raport.
Później analizujemy te dane i w zależności od wyników tej analizy prosimy
użytkowników o przetestowanie określonych części aplikacji. Procedura ta
daje nam pewność, że użytkownicy przetestowali wszystkie elementy,
zanim przekształcimy wersję beta w wersję końcową.

Kiedy nie dokonywać konwersji?


Niewielkie projekty, z małym budżetem, nie powinny być konwertowane do technologii ADO. Jak widzisz, procedura
testowania składa się z wielu etapów. Jeśli użytkownicy nie są w stanie pokryć kosztów testowania, zaniechaj konwersji.
Technologia DAO działa zadowalająco w Accessie 2000. Co więcej, w DAO 3.6 poprawiono kilka błędów, tak więc kod
napisany w tej technologii powinien bez żadnych modyfikacji działać lepiej w Accessie 2000 niż 97.

W trakcie czytania tej książki natrafisz na operacje, które DAO wykonuje lepiej niż ADO (niektóre operacje dotyczące
DDL oraz zabezpieczeń). Jeśli aplikacja w znacznej części opiera się na tych technikach, lepiej będzie jej nie konwertować
lub zdecydować się na połączenie obu technologii.

Porównanie modelu obiektowego


ADO i DAO
DAO posiada olbrzymi model obiektowy, składający się z ponad 50 elementów. Model obiektowy w technologii ADO jest
dużo mniejszy i zawiera ich jedynie 7. Gdzie podziała się reszta? W tej części zobaczysz, jak wygląda porównanie dostępu
do danych

w obu tych technologiach. Temat ten został omówiony w rozdziałach 22. „Replikacja i JRO” i 7. „Zaawansowane ADO”.
103 Rozdział 6. ♦ Wprowadzenie do obiektów danych Active X

W tabeli 6.3 znajdziesz najbardziej powszechne obiekty związane z dostępem do danych w DAO i ich odpowiedniki w
technologii ADO.

Tabela 6.3.
Porównanie obiektów DAO i ADO

Obiekt DAO Obiekt ADO


DBEngine Brak
Workspace Brak
Database Connection
Recordset Recordset
Field Field
QueryDef Command
Parameter Parameter
Error Error
Rozdział 7.
Zaawansowane ADO
W tym rozdziale:
u Użycie dostawcy OLE DB dla Accessa.
u Uzyskanie poprzez ADO dostępu do danych w bazach nierelacyjnych.
u Zaawansowana obróbka danych przy użyciu ADO.
u Definiowanie danych przy użyciu ADOX.

Teraz, kiedy już umiesz używać obiektów ADO i porównałeś je z DAO, przyjrzyj się tym cechom ADO, które pomogą Ci
tworzyć aplikacje w Accessie 2000.

Użycie dostawcy OLE DB dla Jet w Accessie 2000


Gdy używasz ADO w aplikacjach Accessa, najprawdopodobniej będziesz korzystał z dostawcy OLE DB dla Jet (użycie
dostawcy OLE DB dla SQL Server jest omówione w rozdziale 15). Dostawca ten pozwala na bezpośredni dostęp do plików
typu MDB. Zdolność bezpośredniej komunikacji ze źródłem danych to wielki krok naprzód dla ADO. Aby użyć dostawcy
OLE DB dla Jet, musisz podać jego nazwę i pełną ścieżkę dostępu do bazy danych jako część ciągu połączeniowego. Aby
zachować przejrzystość, umieszczono w ADO właściwość Provider, której odpowiednie ustawienie umożliwi użycie
dostawcy dla Jet. Jego unikatowym CLASSID w ciągu połączenia jest: Microsoft.Jet.OLEDB.4.0. Poniższy przykład
przedstawia, jak tworzyć połączenie do bazy Microsoft Accessa przy użyciu dostawcy OLE DB dla Jet:
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection

With conn
.Provider = "Microsoft.Jet.OLE.DB.4.0"
.ConnectionString = "data source= C:\databases\sample.mdb"
.Open
End With

Jeśli zachodzi konieczność określenia innych informacji dotyczących połączenia (np. hasło bazy danych czy plik grupy
roboczej), dołącz je do ciągu połączeniowego, poprzedzając średnikiem. W tabeli 7.1 znajdziesz charakterystyczne dla
dostawcy właściwości połączenia, których możesz użyć w ciągu połączeniowym. Inne charakterystyczne dla dostarczyciela
właściwości, które znajdują się w zbiorze właściwości połączenia, zostaną zignorowane.

Tabela 7.1.
Właściwości ciągów połączenia charakterystyczne dla dostawcy OLE DB dla Microsoft Jet

Nazwa Opis
Jet OLEDB:Registry Path Ścieżka dostępu do klucza rejestru dla Jet. Nie zawiera
znacznika HKEY_LOCAL_MACHINE. Wartość ta może
zostać zamieniona na drugorzędną lokalizację w celu
przechowywania wartości rejestru aplikacji, które nie są
współdzielone z innymi aplikacjami korzystającymi z Jet
na tym komputerze.
Przykładowo, ustawienie dla Accessa 2000 to:
SOFTWARE\Microsoft\Office\9.0\Access\Jet\4.0\Engines
Jet OLEDB:System database Lokalizacja systemowej bazy Jet, która ma być używana
przez określonych użytkowników. Powoduje to
105 Rozdział 7. ♦ Zaawansowane ADO

unieważnienie wartości ustalonej w rejestrze lub klucza


rejestru systemdb używanego wraz z Jet
OLEDB:Registry Path. Właściwość ta może zawierać
ścieżkę dostępu do pliku.
Jet OLEDB:Database Password Hasło używane do otwarcia bazy danych. Od hasła
użytkownika różni się tym, że hasło bazy danych dotyczy
pliku a nie konkretnego użytkownika. Więcej informacji
znajdziesz w rozdziale 21. „Zagadnienia wielodostępu,
serwer plików, blokowanie”.
Jet OLEDB:Engine Type Określenie silnika, który aktualnie jest wykorzystywany
w celu uzyskania dostępu do danych.
Jet OLEDB:Database Locking Mode Tryb używany podczas blokowania bazy danych. Więcej
informacji w rozdziale 21., dotyczącym obsługi wielu
użytkowników. Zauważ, że baza może być otwarta tylko
w jednym trybie jednocześnie. Użytkownik, który jako
pierwszy otwiera bazę, określa jej tryb blokowania.
Jet OLEDB:Global Partial Bulk Ops Właściwość ta określa zachowanie Jet w przypadku błędu
w masowych operacjach SQL DML. Może zostać
unieważniona przez ustawienie właściwości Jet na
OLEDB:Partial Bulk Ops.
Jet OLEDB:Global Bulk Transactions Określa, czy masowe operacje SQL są wykonywane.
Właściwość ta wskazuje ustawienie domyślne dla
wszystkich operacji w aktualnym połączeniu.

Oprócz właściwości umieszczonych w tabeli 7.1 silnik bazy danych Microsoft Jet posiada kilka opcji, których ustawienie określa
zachowanie silnika. Opcje te często mają bezpośredni wpływ na jego wydajność. Domyślnie, po uruchomieniu Jet używane są
wartości znajdujące się w rejestrze, w kluczu \HKEY_LOCAL_MACHINES\Software\Microsoft\Jet. Istnieje jednak
możliwość tymczasowego unieważnienia tych ustawień. W przypadku ADO wartości te stanowią część ciągu połączenia.
Stałe ciągu połączenia znajdują się w tabeli 7.2.

Tabela 7.2.
Opcje ciągu połączenia ADO

DAO ADO
dbPageTimeout Jet OLEDB:Page Timeout
dbSharedAsyncDelay Jet OLEDB:Shared Async Delay
dbExclusiveAsyncDelay Jet OLEDB:Exclusive Async Delay
dbLockRetry Jet OLEDB:Lock Retry
dbUserCommitSync Jet OLEDB:User Commit Sync
dbImplicitCommitSync Jet OLEDB:Implicit Commit Sync
dbMaxBufferSize Jet OLEDB:Max Buffer Size
dbMaxLocksPerFile Jet OLEDB:Max Locks Per File
dbLockDelay Jet OLEDB:Lock Delay
dbRecycleLVs Jet OLEDB:Recycle Long-Valued Pages
dbFlushTransactionTimeout Jet OLEDB:Flush transaction Timeout

Poniższy fragment kodu powoduje otwarcie zabezpieczonej bazy, określając jej hasło i plik grupy roboczej:
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection

With conn
.Provider = "Microsoft.Jet.OLE.DB.4.0"
.ConnectionString = "data source= C:\databases\sample.mdb"&_
";Jet OLEDB:Database Password=supersecret " & _
"; OLEDB:System database=" & _
"c:\windows\system\system.mdw"
.Open
End With
Część II ♦ Dostęp do danych 106

CurrentProject.Connection
Gdy chcesz uzyskać dostęp do aktualnej bazy poprzez kod ADO, Access umożliwia Ci pójście na skróty. Oddaje do Twojej
dyspozycji odnośnik do obiektu Connection
– CurrentProject.Connection. Używając tej składni, możesz z łatwością przydzielić aktualnej bazie obiekt
Connection. Polecenie CurrentProject.Connection dostępne jest jedynie w kodzie VBA Accessa 2000. Użycie tej
składni przedstawia poniższy fragment kodu:
Dim conn As ADODB.Connection
Set conn = CurrentProject.Connection

CurrentProject.Connection pozwala zaoszczędzić czas, jeśli chcesz otworzyć zestaw rekordów. Możesz wykorzystać
zdolność ADO do dynamicznego tworzenia połączenia poprzez polecenie Open:
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
rst.Open "Customers", CurrentProject.Connection

Zalecamy ostrożność podczas korzystania z CurrentProject.Con-


nection. Pamiętaj, że polecenie to nie może być używane w innym
środowisku niż Access 2000. Jeśli zamierzasz wykorzystać swój kod w
innej aplikacji niż Access (np. Visual Basic), do utworzenia połączenia
musisz użyć dłuższej składni.

Rola Microsoft Data Links


w podłączaniu się do bazy danych
Teraz, gdy obiekty ADO są podstawowym sposobem uzyskiwania dostępu do danych, twórcy Accessa uznali że
programiści potrzebują standardowego sposobu obsługiwania, ładowania, otwierania i zarządzania informacjami o
połączeniu OLE DB, przypominającego dawne narzędzie do zarządzania i administrowania sterownikami ODBC. Możliwość
tę dają Microsoft Universal Data Links (UDL). Mechanizm UDL umożliwia zapisywanie informacji o połączeniu w pliku
UDL, a następnie otwarcie obiektu Connection w ADO, na podstawie informacji zapisanych w tym pliku. Możliwość ta
będzie bardzo przydatna, gdy chcesz przetestować podłączenie bazy danych do różnych komputerów bez zmiany kodu.

Mechanizm Microsoft Universal Data Links składa się z:


u graficznego interfejsu użytkownika, służącego do tworzenia połączeń OLE DB;
u interfejsu automatyzacji.

Zanim zaczniesz używać UDL w aplikacjach VB lub VBA, musisz najpierw je utworzyć. Tworzenie UDL nie jest
skomplikowane. Uruchom Eksploratora Windows, z menu Plik wybierz Nowy, a następnie Microsoft Data Link (rysunek 7.1).

Po utworzeniu pliku UDL kliknij go dwukrotnie, aby rozpocząć edycję. Przedstawiony na rysunku 7.2 pierwszy ekran
zawiera listę wszystkich zainstalowanych na Twoim komputerze dostawców OLE DB. Wybierz jednego z nich i kliknij
Dalej, aby przejść do zakładki Połączenie. Teraz możesz określić wszystkie, charakterystyczne dla dostawcy informacje
dotyczące połączenia (rysunek 7.3). W naszym przykładzie użyliśmy dostawcy OLE DB dla Jet, więc musieliśmy określić
ścieżkę dostępu, identyfikator użytkownika i hasło (gdybyśmy wybrali SQL Server, musielibyśmy podać nazwę serwera
i bazy danych). Następna zakładka, Zaawansowane, służy do określenia właściwości dostawcy, które zazwyczaj ustalane
są przez takie polecenia jak CommandTimeout. Ostatnia zakładka, Wszystkie, jest podsumowaniem wszystkich wybranych
właściwości.
107 Rozdział 7. ♦ Zaawansowane ADO

Rysunek 7.1.
Tworzenie nowego
pliku UDL

Rysunek 7.2.
Wybór dostawcy
OLE DB

Rysunek 7.3.
Wprowadzanie
informacji
o połączeniu

Teraz, gdy utworzyłeś już plik UDL, możesz umieścić go w kodzie VBA, aby utworzyć w ADO obiekt Connection.
Składnia jest prosta. Utwórz obiekt Connection, tak jak to zwykle robisz, i użyj obiektu Open. Następnie wskaż plik UDL
za pomocą identyfikatora File Name:
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection
Conn.Open "File Name=c:\chapter7.udl;"

Fragment kodu na wydruku 7.1 znajduje się w umieszczonym na


dołączonej do książki płycie CD. Przedstawia on, jak utworzyć obiekt
Connection oparty na pliku UDL, umieszczonym w folderze bazy danych
Northwind. Łączysz się z bazą i wypełniasz okno za wartością tabeli
Customers. Bardzo przydatną cechą tego kodu jest to, że jeśli będziesz
chciał użyć bazy Northwind w wersji SQL, wystarczy zmienić
właściwości pliku UDL i uruchomić kod ponownie.
Wydruk 7.1. Użycie UDL w kodzie VBA
Część II ♦ Dostęp do danych 108

Private Sub OpenViaLink()


' Procedura używa połączenia ADO, pobierając informacje
' o połączeniu z pliku Microsoft UDL
' Następnie otwierany jest recordset
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston

Dim conn As ADODB.Connection


Dim rst As ADODB.Recordset

On Error GoTo Proc_Err

Set conn = New ADODB.Connection


' Otwarcie połączenia poprzez plik UDL
' Pozwala to dynamicznie zmienić bazę danych, zmieniając
' plik UDL
conn.Open "File Name=c:\chapter7.udl;"

Set rst = New ADODB.Recordset


' Otwarcie wyniku wyrażenia SQL
rst.Open "Select * From Customers", conn

' Przeglądamy wynik i wypisujemy wartości


Do Until rst.EOF
Debug.Print rst!CompanyName
rst.MoveNext
Loop

' Porządki
rst.Close
conn.Close

Set rst = Nothing


Set conn = Nothing

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Zarządzanie plikami UDL


Istnieją dwa sposoby zarządzania plikami UDL. Pierwszy – poprzez ich interfejs użytkownika. W Panelu sterowania
systemu Windows znajduje się ikona Microsoft Data Links, która umożliwia wyświetlenie listy wszystkich plików UDL we
wskazanym folderze (rysunek 7.4). Łatwiej jest jednak użyć Eksploratora Windows i bezpośrednio otworzyć żądany plik.

Rysunek 7.4.
Zarządzanie
plikami UDL

Programowe zarządzanie plikami UDL


Ponieważ pliki UDL posiadają swój własny interfejs automatyzacji, możesz nimi zarządzać i kontrolować je programowo. Aby
użyć UDL w kodzie VBA, ustaw odwołanie na typ biblioteki o nazwie Microsoft OLE DB Service Component 1.0 Type Library
(rysunek 7.5).
109 Rozdział 7. ♦ Zaawansowane ADO

Rysunek 7.5.
Ustawianie
odnośnika na
Microsoft OLE DB
Service Component
1.0 Type Library

Po ustawienie odwołania możesz rozpocząć zarządzanie plikami UDL. Dodatkowo możesz poprosić użytkownika o
podanie informacji o połączeniu OLE DB poprzez okna dialogowe UDL. Możliwość ta jest przydatna w prototypowych
aplikacjach lub wersjach demonstracyjnych produktów przeznaczonych dla użytkowników zaznajomionych z
funkcjonowaniem Microsoft Data Links. Możesz tego dokonać, wykorzystując metodę PromptNew obiektu DataLinks.
Kod na wydruku 7.2 prosi użytkownika o podanie informacji o połączeniu OLE DB poprzez okno dialogowe UDL, a
następnie łączy się z bazą danych i otwiera zestaw rekordów.

Wydruk 7.2. Programowe UDL


Private Sub OpenUDLDialog()
' Procedura używa interfejsu automatyzacji
' UDL do utworzenia połączenia
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston

Dim strConnect As String


Dim rst As ADODB.Recordset

' Odwołanie do Microsoft UDL


Dim udl As MSDASC.DataLinks

On Error GoTo Proc Err

' Tworzenie obiektu Data Link


Set udl = New MSDASC.DataLinks

' Ustawienie obiektu connection na podstawie


' okna dialogowego nowego Data Link
strConnect = udl.PromptNew

Set rst = New ADODB.Recordset


' Otwarcie wyniku na podstawie
' danych wprowadzonych przez użytkownika
' do okna Data Link
rst.Open "Select * From Customers", strConnect
' Wyświetl pierwszy rekord
MsgBox rst!CompanyName

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub
Część II ♦ Dostęp do danych 110

Uzyskanie poprzez ADO dostępu do danych w bazach


nierelacyjnych
Nawiązując do omówionego w rozdziale 6. wykorzystania Accessa do komunikowania się z danymi nierelacyjnymi (jak
np. Excel), ADO posiada kilka zaawansowanych opcji, które ułatwią Ci pracę z tym typem danych. Teraz przyjrzymy się
opcjom:
u Lista użytkowników Jet.
u Tworzenie zestawów rekordów.
u Kształtowanie danych.

Lista użytkowników Jet


Dostawca OLE DB dla Jet umożliwi Ci otwarcie zestawu rekordów zawierającego nazwy użytkowników aktualnie
zalogowanych do bazy, której nazwę określisz w połączeniu. Dzięki temu nie będziesz już musiał korzystać z
dostarczanego z poprzednimi wersjami Jet narzędzia LDBView. Kod na wydruku 7.3 przedstawia sposób utworzenia
zestawów rekordów z aktualnymi użytkownikami bazy danych. W listingu tym użyliśmy metody OpenSchema obiektu
Connection z parametrem charakterystycznym dla aparatu JET/JOLT. Zauważ, że ADO nie podpowiada Ci żadnych
stałych. Będziesz musiał ręcznie wprowadzić wartość GUID: ({947bb102-5d43-11d1-bdbf-00c04fb92675}). Pozostaje
nam mieć nadzieję, że niedogodność ta zostanie poprawiona w kolejnej wersji obiektów ADO.

Wydruk 7.3. Użycie listy użytkowników


Sub UserRoster()
' Procedura używa listy użytkowników
' do sprawdzenia, kto jest zalogowany do bazy danych
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston

Dim conn As ADODB.Connection


Dim rst As ADODB.Recordset

On Error GoTo Proc Err

Set conn = New ADODB.Connection

' Otwarcie bazy danych


With conn
.Provider = "Microsoft.Jet.OLEDB.4.O"
.ConnectionString = "data source=f:\employee.mdb"
.Open
End With

' Tworzenie wyniku opartego na ilości użytkowników


' bazy danych
Set rst = conn.OpenSchema(adSchemaProviderSpecific, , _
"{947bb102-5d43-iidl-bdbf-00c04fb92675}")

' Dla każdego użytkownika wypisz nazwę jego komputera i


' inne informacje
Do Until rst.EOF
Debug.Print rst!COMPUTER_NAME
Debug.Print rst!LOGIN_NAME
Debug.Print rst!CONNECTED
Debug.Print rst!SUSPECTED STATE

rst.MoveNext
Loop

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub

Tworzone zestawy rekordów


Obiekty ADO stwarzają Ci możliwość tworzenia zestawów rekordów „z niczego”. Możesz teraz korzystać z metod
Fields.Append i AddNew, aby dodawać pola i dane do zestawu rekordów. Technika ta nadaje się świetnie do tworzenia
111 Rozdział 7. ♦ Zaawansowane ADO

procedur pobierających dane z nierelacyjnych źródeł (np. folder z plikami) i zwracających zestaw rekordów. Dzięki ADO
aplikacja może przez cały czas współpracować z zestawami rekordów, a kod aplikacji jest dużo prostszy. Poniższy
przykład przedstawia sposób utworzenia zestawu rekordów zawierającego nazwy plików znajdujących się w określonym
folderze. Jeśli umieścisz ten kod w module, będziesz go mógł użyć w wielu aplikacjach. Przykładowo, my
wykorzystaliśmy go do sporządzenia listy wszystkich plików typu ZIP w katalogu serwera FTP, a następnie przejrzenia ich
i utworzenia strony, z której można te pliki pobrać. Przewagą tej techniki nad dostawcą NT Active OLE DB jest fakt, iż
działa ona w systemie Windows 95. Wydruk 7.4 przedstawia w jaki sposób można otworzyć zestaw rekordów oparty na
liście nazw plików w folderze.

Wydruk 7.4. Tworzenie zestawu rekordów z nierelacyjnych danych


Sub CreatableRst_Files(strPath As String)
'Oto przykład tworzenia zestawu rekordów
'z danych nierelacyjnych
'Tworzy zestaw rekordów składający się z nazw i rozszerzeń plików
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim rst As ADODB.Recordset

On Error GoTo Proc_Err

Set rst = New ADODB.Recordset

With rst
'Wykonaj operacje lokalne
.CursorLocation = adUseClient

'Teraz dodaj pole


.Fields.Append "FileName", adVarChar, 255, adFldRowID
.Fields.Append "Extention", adChar, 3, adFldFixed

'Otwórz rst
.Open , , adOpenStatic, adLockBatchOptimistic

'Upewnij się, że w ścieżce dostępu znajduje się znak \


If Right(strPath, 1) <> "\" Then strPath = strPath & "\"

'Pobierz listę wszystkich plików w folderze, a następnie


'dodaj je do zestawu rekordów
strPath = Dir(strPath & "*.*", vbNormal)
' Nie umieszczaj wpisów . i ..
Do While strPath > ""
'Teraz dodaj do rst nowy rekord
.AddNew Array("FileName", "Extention"), _
Array(strPath, Right(strPath, 3))

strPath = Dir
Loop

.MoveFirst

'Wydrukuj pliki
Do Until .EOF
Debug.Print !FileName
rst.MoveNext
Loop

End With

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Kształtowanie danych
Umożliwienie przeglądania danych w zhierarchizowany sposób w obiektach ADO jest bardzo proste. Możesz użyć nowej
zdolności ADO, o nazwie Data Shaping (ang. kształtowanie danych), aby przeglądać nadrzędne i podrzędne rekordy w
jednym zestawie. Możesz użyć dostawcy MSDataShape OLE DB do tworzenia hierarchii opartych na relacjach i hierarchii
grupowania. Tworzenie tego typu hierarchicznych zestawów rekordów może ułatwić dość pracochłonną obróbkę
hierarchicznych danych. Przykładowo, na rysunku 7.6 znajduje się grupowa hierarchia wszystkich zamówień klientów z bazy
Northwind, przeglądana w nowej siatce o nazwie Microsoft Hierarchical FlexGrid (wersja OLAP popularnej FlexGrid).
Formant ten dołączony jest do pakietu Office 2000 w wersji Developer Edition oraz do Visual Basic 6 (nasze wartości i listingi
napisane zostały w VB 6 i używają bazy danych Accessa jako źródła danych). Zwróć uwagę na znak plus znajdujący się przy
każdym z rekordów. Umożliwia on rozszerzanie każdego z rekordów i przeglądanie jego szczegółów, co przedstawia rysunek
7.7. Zanim powstał dostawca MSDataShape OLE DB, utworzenie takiej siatki wymagało napisania wielu linijek kodu.
Część II ♦ Dostęp do danych 112

Rysunek 7.6.
Zestaw rekordów
uzyskany poprzez
dostawcę
MSDataShape OLE
DB w Visual Basic

Rysunek 7.7.
Zestaw rekordów
GrupujWedług
w Visual Basic

Wydruk 7.5. Tworzenie rekordu z ukształtowanymi danymi i wypełnianie siatki MSHFlexGrid w VB


Sub CubeGroupHierarchy()
'Wypełnij formant MSFLEXGRID
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

'Kod do wypełnienia zestawu rekordów


Dim rst As ADODB.Recordset
Dim strConnect As String

Set rst = New ADODB.Recordset

'Ustaw właściwości połączenia


'Każ ADO użyć dostarczyciela OLE DB dla Data Shaping
'Następnie podłącz wbudowanego dostarczyciela OLE DB do
'wybranego źródła danych
strConnect = "Provider=MSDataShape" & _
";data provider=Microsoft.Jet.OLEDB.4.0" & _
";data source=" & App.path & "\sample.mdb"

'Wprowadź SQL Data Shape


rst.Source = "shape {Select customerid, " & _
"Region from Customers} rst1 " & _
"COMPUTE COUNT (rst1.customerid) AS CustCount, rst1 By Region "
rst.ActiveConnection = strConnect
rst.Open , , adOpenStatic, adLockBatchOptimistic

'Pokaż RST
Set frmADO.MSHFlexGrid1.Recordset = rst

End Sub

Jak widać w tym fragmencie kodu, musisz użyć specjalnej, powiązanej z Data Shaping składni SQL. Kompletną listę
zastosowań tej składni znajdziesz w dostarczanym wraz z Visual Basic 6 i pakietem Office Developer 2000 dokumentacji
MSDN oraz na stronie WWW pod adresem http://www.microsoft.com/data. Możesz również użyć tego kodu do operacji
Data Shaping i przeniesienia danych do programu Microsoft Excel. Kod na wydruku 7.6 przedstawia sposób, jak za
pomocą poprzedniego przykładu przenieść dane do arkusza programu Excel.

Wydruk 7.6. Użycie Data Shaping w programie Microsoft Excel


Sub CUBRelation()
'Użycie OLAP z Microsoft Excel
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim rst As ADODB.Recordset


Dim strConnect As String

Set rst = New ADODB.Recordset

'Ustaw właściwości połączenia


'Nakaż ADO użycie dostarczyciela OLE DB dla Data Shaping
'Następnie podłącz wbudowanego dostarczyciela OLE DB do
'wybranego źródła danych
strConnect = "Provider=MSDataShape;" & _
";data provider=Microsoft.Jet.OLEDB.4.0" & _
";data source=C:\sample.mdb"
'Wprowadź SQL Data Shape
rst.Source = "shape {Select * from customers where Customerid='ALFKI'}"&_
113 Rozdział 7. ♦ Zaawansowane ADO

" Append " & _


"({Select * From Orders} As rsOrders " & _
"RELATE customerid to customerid)"

rst.ActiveConnection = strConnect

rst.Open , , adOpenStatic, adLockBatchOptimistic

'Pokaż RST
ShowRSTinExcel rst

End Sub

Sub ShowRSTinExcel(rst As ADODB.Recordset, _


Optional blnSKipClear As Boolean = False)

Dim rstChild As ADODB.Recordset


Dim col As ADODB.Field
Dim intCurrentColumn As Integer
Dim intCurrentRow As Integer

If Not blnSKipClear Then


'Clear out the cells
Cells.Select
Selection.ClearContents
End If
Do Until rst.EOF
intCurrentColumn = intCurrentColumn + 1
If Not blnSKipClear Then
intCurrentRow = 1
Else
intCurrentRow = 2
End If

For Each col In rst.Fields


If col.Type <> adChapter Then
Cells(intCurrentColumn, intCurrentRow) = _
col.Name & ": " & col.Value
Else
Set rstChild = col.Value
ShowRSTinExcel rstChild, True
End If

intCurrentRow = intCurrentRow + 1
Next

rst.MoveNext
Loop

Cells(1, 1).Select

End Sub

Zaawansowana obróbka danych przy użyciu ADO


W ostatnim rozdziale pokazaliśmy, jak tworzyć zestawy rekordów zawierające dane i jak korzystać z obiektów Command.
W tej części pokażemy kilka dodatkowych możliwości obiektów ADO. Przyjrzymy się:
u Modyfikowaniu danych w zestawie rekordów.
u Trwałym zestawom rekordów.

Modyfikowanie danych w zestawie rekordów


Aby modyfikować dane w zestawie rekordów, musisz jedynie przejść do niego i rozpocząć edycję. Po przejściu do
kolejnego rekordu lub użyciu metody Call dokonane przez Ciebie zmiany zostaną zapisane. Jest to duży krok naprzód w
porównaniu z obiektami DAO, gdzie musiałeś najpierw użyć polecenia Edit, a następnie obowiązkowo użyć polecenia
Update. Kod na wydruku 7.7 przedstawia, w jaki sposób można dokonać edycji danych.

Wydruk 7.7. Edycja rekordu


Sub Editrecords()
'Procedura edycji danych
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim rst As ADODB.Recordset


Część II ♦ Dostęp do danych 114

Dim strSQL As String

On Error GoTo Proc Err

' Tworzenie obiektu recordset


Set rst = New ADODB.Recordset

' Wpisz tu wyrażenie SQL zwracające potrzebne dane


strSQL = "Select * From Customers Where CustomerID='Anton'"

' Otwarcie wyniku za pomocą kursora keyset


rst.Open strSQL, CurrentProject.Connection, _
adOpenKeyset, adLockOptimistic
' Zmiana wiersza
rst!CompanyName = "Nowa nazwa"
' Użycie metody Update lub MoveNext
rst.Update

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Szybciej jest otworzyć zestaw rekordów bazujący na wyrażeniu SQL wy-


magającym klucza podstawowego niż otwierać całą tabelę i w niej szukać
żądanego rekordu.

Ponieważ zmiany dokonywane w zestawie rekordów uwzględniane są bez


użycia polecenia Update, jedynie przez przejście do kolejnego rekordu,
zalecamy ostrożność podczas edycji danych.

Dodawanie rekordu
Dodawanie rekordu przebiega w prawie identyczny sposób jak edycja. Musisz otworzyć zestaw rekordów i użyć metody
AddNew. Tak samo jak w przypadku Edit tak i w przypadku Update zastosowanie mają te same zasady. Po dodaniu
rekordu będziesz się znajdował w aktualnym rekordzie. Wydruk 7.8 zawiera przykład dodawania rekordu do tabeli.

Wydruk 7.8. Dodawanie rekordu do tabeli


Sub Addrecords()
' Procedura dodaje nowy rekord do tabeli
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

Dim rst As ADODB.Recordset

On Error GoTo Proc_Err

' Tworzenie obiektu recordset


Set rst = New ADODB.Recordset

With rst
' Otwarcie tabeli
.Open "Authors", CurrentProject.Connection, _
adOpenDynamic, adLockOptimistic, adCmdTableDirect
' Teraz należy użyć AddNew
.AddNew
!AuthorFirstName = "Mike"
!AuthorLastName = "Smith"
.Update
' Po dodaniu rekordem bieżącym jest nowy rekord
MsgBox "ID nowego autora: " & !AuthorID
End With

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub
115 Rozdział 7. ♦ Zaawansowane ADO

Być może zauważyłeś, że otwarłeś tabelę ze stałą adCmdTableDirect. Jeśli użyjesz tej stałej z typem kursora
adOpenDynaset i blokowaniem optymistycznym, osiągniesz taki sam efekt jak przy użyciu polecenia dbOpenTable w
DAO. Tabela 7.3 zawiera wszystkie opcje kursorów i blokowania ADO oraz ich odpowiedniki w DAO.

Tabela 7.3.
Kombinacje obiektów ADO dla Accessa

Typ kursora Opcje i typy blokowania Odpowiednik w DAO


adOpenForwardOnly adLockReadOnly dbOpenSnapShot
dbForwardOnly
AdOpenKeySet adLockReadOnly Brak odpowiednika
AdOpenKeySet adLockPessimistic dnOpenDynaset

Tabela 7.3.
Kombinacje obiektów ADO dla Accessa (ciąg dalszy)

Typ kursora Opcje i typy blokowania Odpowiednik w DAO


AdOpenKeySet adLockOptimistic dnOpenDynaset
AdOpenKeySet adLockBatchOptimistic dnOpenDynaset
AdOpenStatic adLockReadOnly dnOpenDynaset
adOpenDynamic adLockOptimistic dbOpenTable
adCmdTableDirect

Trwałe zestawy rekordów


Dla tych z was, którzy muszą również zadbać o obsługę użytkowników nie podłączonych do sieci, pojęcie trwałości rekordów
to fantastyczny podarunek od firmy z Redmond. Teraz masz bowiem możliwość zapisania zestawu rekordów na dysku i
jego obróbkę w aplikacji VB lub VBA. Później możesz ten zestaw ponownie włączyć do bazy. Aby tego dokonać, otwórz
zestaw rekordów ADO z typem blokowania adLockBatchOptimistic i używając kursora client. Następnie użyj
polecenia Save obiektu Recordset. Musisz określić nazwę pliku i format, w jakim ma być zapisany. ADO oddaje do
Twojej dyspozycji następujące możliwości:
u adPersistADTG;

u adPersistXML.

Jeśli wybierzesz format adPersistADTG lub adPersistXML, będziesz mógł później z łatwością otworzyć ten plik w
ADO. Wydruk 7.9 przedstawia, jak otworzyć zestaw rekordów, zmienić rekord, zapisać zmiany do pliku, otworzyć go
ponownie i włączyć z powrotem do bazy.

Wydruk 7.9. Zapisywanie zestawu rekordów na dysku, jego ponowne otwarcie i ponowne włączenie do bazy danych
Sub RstPersistence Save()
' Przykład pobrania wyniku, odłączenia od bazy danych
' zapisu na dysk a następnie synchronizacji z bazą
' Synchronizacja zachodzi w RstPersistence_Open
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston

Dim strSOL As String


Dim strMsg As String
Dim strNewValue As String
Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset

On Error GoTo Proc Err

strSQL = "Select * From Customers Where CustomerID='ALFKI'"

Set conn = New ADODB.Connection


With conn
.Provider = "Microsoft.Jet.OLEDB.4.O"
.ConnectionString = "data source=c:\sample.mdb"
.Open
End With

Set rst = New ADODB.Recordset

' Należy użyć kursora po stronie klienta


rst.CursorLocation = adUseClient
rst.Open strSQL, conn, adOpenStatic, adLockBatchOptimistic
Część II ♦ Dostęp do danych 116

' Pozwól użytkownikowi zmienić dane, pokazując dane bieżące


strMsg = "Proszę wprowadzić nową nazwę firmy dla: " & _
rst!CompanyName & vbNewLine & _
"ID klienta=" & rst!CustomerID

' Pobierz nową nazwę


strNewValue = InputBox(strMsg)

' Zmień rekord na komputerze klienta i zapisz na dysku


' Nie zmienia to danych w bazie danych
rst.Update "CompanyName", strNewValue
' Zmiana została wprowadzona do recordsetu klienta

On Error Resume Next


' Usuń istniejący plik
Kill "c:\hcado.dat"

On Error GoTo Proc_Err


' Zapisz recordset na dysku
rst.Save "c:\hcado.dat", adPersistADTG

rst.Close
Set rst = Nothing

MsgBox "Zapisane do: c:\hcado.dat", vbInformation

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Sub RstPersiStence Open()


' Przykład pobrania wyniku, odłączenia od bazy danych
' zapisu na dysk a następnie synchronizacji z bazą
' Zapis był wykonany w RstPersistence_Save
' Tu wykonywana jest synchronizacja
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston

Dim conn As ADODB.Connection


Dim rst As ADODB.Recordset
Dim strSQL As String
Dim strMsg As String

On Error GoTo Proc Err

strSQL = "Select * From Customers Where CustomerID='ALFKI'"

' Pobranie nowego recordset z dysku


Set rst = New ADODB.Recordset
rst.Open "c:\hcado.dat", , adOpenStatic, adLockBatchOptimistic, _
adCmdFile

' Pokazanie danych z bazy danych i z dysku


strMsg = "Wartości w bazie danych: " & _
rst!CompanyName.OriginalValue
strMsg = strMsg & vbNewLine & _
"Wartości na dysku: " & rst!CompanyName

' Wyświetl wartości


MsgBox strMsg, vbInformation, "Wartości z bazy i z dysku"

' Teraz uaktualnimy bazę danych wartościami z dysku


' Trzeba ponownie podłączyć się do bazy
Set conn = New ADODB.Connection
With conn
.Provider = "Microsoft.Jet.OLEDB.4.O"
.ConnectionString = "data source=c:\sample.mdb"
.Open
End With

' Powtórne przyłączenie recordsetu do bazy danych i synchronizacja


rst.Active0onnection = conn
rst.UpdateBatch

MsgBox "Baza danych zsynchronizowana !", vbInformation

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub
117 Rozdział 7. ♦ Zaawansowane ADO

Definiowanie danych przy użyciu ADOX


Korzystając z obiektów ADO, możesz z łatwością dokonywać definiowania danych. Aby tworzyć i modyfikować tabele,
kwerendy i inne obiekty związane z danymi, jak na przykład indeksy, musisz skorzystać ze specjalnej biblioteki ADO o
nazwie ADOX. Aby użyć ADOX, musisz ustawić odnośnik na Microsoft ADO Ext. 2.1 For DDL and Security, wybierając z
menu Tools pozycję References (rysunek 7.8).

Rysunek 7.8.
Microsoft ADO Ext.
2.1 For DDL and
Security

Gdy ustawiłeś już odnośnik, jesteś gotów do korzystania z ADOX.

Obiekt Catalog
Gdy korzystasz z ADOX, wszystko co robisz związane jest z obiektem Catalog. Catalog oznacza bazę danych. Pracując
w Accessie, musisz jedynie ustawić właściwość tego obiektu, ActiveConnection, na prawidłowy obiekt Command.
Dim cat As ADOX.Catalog
Set cat = New ADOx.Catalog
'Wskaż obiektowi Catalog
'aktualną bazę danych
cat.ActiveConnection = CurrentProject.Connection

Tworzenie bazy danych


Aby utworzyć nową, pustą bazę danych przy użyciu ADOX, musisz użyć polecenia Create obiektu Catalog i podać
ścieżkę dostępu do nowej bazy (wydruk 7.10).

Wydruk 7.10. Tworzenie bazy danych przy użyciu ADOX


Sub CreateOataBase()
' Procedura tworzy nową bazę danych przy użyciu ADOX
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

' Obiekt catalog w ADOX


Dim cat As ADOx.Catalog

On Error GoTo Proc_Err

Set cat = New ADOx.Catalog


cat.Create "provider=Microsoft.JET.OLEDB.4.0;" & _
"data source=C:\newdb.mdb"
MsgBox "Baza danyh utworzona!", vbInformation

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub
Część II ♦ Dostęp do danych 118

Tworzenie tabel i pól


Aby utworzyć tabelę i jej pola, możesz utworzyć obiekt ADOX o nazwie table i dołączyć do niego kolumny (wydruk 7.11).

Wydruk 7.11. Tworzenie tabel i pól


Sub CreateTable_JOLT4O()
' Przykład tworzy tabelę i jej pola w bieżącej bazie danych
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

' Obiekty ADOX


Dim cat As ADOx.Catalog
Dim tbl As ADOx.Table

On Error GoTo Proc_Err

Set cat = New ADOx.Catalog


' Wskazanie na obiekt Catalog bieżącej bazy danych
cat.ActiveConnection = CurrentProject.Connection

Set tbl = New ADOx.Table


' Tworzy tabelę
With tbl
.Name = "Customer_ADO"
.Columns.Append "CustomerID", adInteger
.Columns.Append "Name_Prefix", adWChar, 25.
.Columns.Append "Name_First", adWChar, 2
.Columns.Append "Name_Last", adWChar, 50
End With

cat.Tables.Append tbl

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Tworzenie dołączonej tabeli


Aby utworzyć w Accessie dołączoną tabelę, musisz utworzyć tabelę i nie dołączać do niej żadnych pól, a następnie ustawić
dwie właściwości:
u Jet OLE DB:Link Datasource;

u JET OLE DB:Remote Table Name.

Jako Link Datasource podaj ścieżkę dostępu do bazy danych, do której chcesz się dołączyć. Jako Remote Table
Name ustaw nazwę tej bazy. Cały przykład znajduje się na wydruku 7.12.

Wydruk 7.12. Tworzenie dołączonej tabeli


Sub CreateAttachedJetTable()
' Tworzy tabelę dołączoną
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston

Dim cat As ADOx.Catalog


Dim tbl As ADOx.Table

Set cat = New ADOx.Catalog


' Otwarcie katalogu
cat.Active0onnection = CurrentProject.Connection

Set tbl = New ADOx.Table


' Tworzenie nowej tabeli

tbl.Name = "Customers_Połączona"
' Skrót dla tworzenia tabel
Set tbl.ParentCatalog = cat

' Ustawienie właściwości połączenia


tbl.Properties("Jet OLEDB:Link Datasource") = _
"F:\backend\datafile.mdb"
tbl.Properties("Jet OLEDB:Remote Table Name") = "Customers"

' Dołącz tabelę do kolekcji tabel


cat.Tables.Append tbl

Set cat = Nothing


119 Rozdział 7. ♦ Zaawansowane ADO

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Ustawianie właściwości pola


W ADOX, po utworzeniu pola, możesz użyć obiektu Column, aby ustawić właściwości charakterystyczne dla tego pola.
Przykładowo, możesz ustawić typ pola na Autonumerowanie, nadając właściwości AutoIncrement wartość True:
Dim col As ADOX.Column
'Wskaż obiektowi Column
'pole CustomerID
Set col = tbl.Columns("CustomerID")
'Ustaw Column na pole typu Autonumerowanie
col.Properties("Autincrement") = True

Istnieją inne właściwości, które możesz ustawić dla obiektu Column. Umieściliśmy je w tabeli 7.4 wraz z ich
odpowiednikami w DAO.

Tabela 7.4.
Właściwości obiektu Field

Pole DAO Obiekt Column w ADOX


Właściwość Wartość Właściwość Wartość
Attributes dbAutoIncrField AutoIncrement True
Attributes dbFixedField ColumnAttributes adColFixed
Attributes dbHyperlinkField Jet OLEDB:Hyperlink True
Attributes dbSystemField

Attributes dbVariableField ColumnAttributes Not adColFixed

Tworzenie indeksu
Tworząc indeks w ADOX, będziesz musiał użyć klucza obiektu. Po jego utworzeniu musisz dołączyć do niego pole, a
następnie określić, czy ma to być klucz podstawowy czy unikatowy i jaka ma być kolejność sortowania:
Set idx = New Adox.Index
'Teraz ustalamy, że będzie to klucz podstawowy,
'sortowany w kolejności malejącej
With idx
.Name = 'Primary Key'
.Columns.Append "CustomerID"
.Columns("CustomerID").SortOrder = adSortDescending
.IndexNulls = adIndexNullsDisallow
.PrimaryKey = True
End With
'Dołączenie indeksu do tabeli
tbl.Indexes.Append idx

Właściwość IndexNulls ustawiona jest domyślnie na adIndexNullsDisallow, co oznacza, że wartości Null nie są w
indeksie dopuszczalne i w przypadku, gdy pole w indeksie będzie taką wartość zawierać, żaden wpis do indeksu nie
zostanie dokonany. W tabeli 7.5 znajdują się wartości akceptowane przez właściwość IndexNulls, wraz z ich
odpowiednikami w DAO.

Tabela 7.5.
Wartości dla właściwości IndexNulls

DAO ADOX Opis


Wymagane Ignore Nulls Index Nulls
True False AdIndexNullsDisallow Wartość Null nie jest akceptowana w polu indeks;
wpis do indeksu nie zostanie dokonany
False True AdIndexNullsIgnore Wartość Null dopuszczona w polu indeks;
wpis do indeksu nie zostanie dokonany
False False AdIndexNullsIgnoreAny Wartość Null dopuszczona w polu indeks;
wpis do indeksu zostanie dokonany
Część II ♦ Dostęp do danych 120

Kod na wydruku 7.13 łączy te wszystkie przykłady, tworząc tabelę pola Autonumerowanie i indeks klucza głównego w tej
tabeli.

Wydruk 7.13. Tworzenie tabeli z polem Autonumerowanie i indeksem klucza głównego


Sub CreateCreateAutoNumberrPK()
'Przykład ten tworzy tabelę
'i pola w aktualnej bazie danych
'Z książki "Access 2000 Księga eksperta" (Helion)
'Autorzy: Forte, Howe, Ralston

'Obiekty ADOX
Dim cat As ADOX.Catalog
Dim tbl As New ADOX.Table
Dim idx As ADOX.Index

On Error GoTo Proc_Err

Set cat = New ADOX.Catalog


'Wskaż obiektowi Catalog
'aktualną bazę danych
cat.ActiveConnection = CurrentProject.Connection

Set tbl = New ADOX.Table


'Teraz tworzymy tabelę
With tbl
.Name = "Customer_ADO"
.ParentCatalog = cat

.Columns.Append "CustomerID", adInteger


'Ustaw pole Autonumerowanie
.Columns("CustomerID").Properties("Autoincrement") = True
.Columns.Append "Name_Prefix", adWChar, 25
.Columns.Append "Name_First", adWChar, 25
.Columns.Append "Name_Last", adWChar, 50
End With
'Dołącz tabelę do obiektu catalog
cat.Tables.Append tbl

'Teraz tworzymy obiekt index


Set idx = New ADOX.Index
'Teraz ustawiamy klucz
'jako klucz podstawowy i
'sortujemy go w porządku malejącym
With idx
.Name = "PrimaryKey"
.Columns.Append "CustomerID"
.Columns("CustomerID").SortOrder = adSortDescending
.IndexNulls = adIndexNullsDisallow
.PrimaryKey = True
End With
'Dołączamy indeks do tabeli
tbl.Indexes.Append idx

'Sprzątamy
Set cat = Nothing

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub

Tworzenie relacji w ADOX


Aby utworzyć relację w ADOX, musisz utworzyć obiekt klucza, określić jego właściwości, a następnie dołączyć ten klucz
do obiektu Table.

Użyj następującej składni:


Cat.Tables("Products").Keys.Append key

Kod na wydruku 7.14 wykonuje wszystkie te czynności oraz tworzy relacje.

Wydruk 7.14. Tworzenie relacji


Sub CreateForeignKey()
'Tworzenie relacji między tabelami
'Products i Categories w bazie Northwind
'Z książki "Access 2000 Księga eksperta" (Helion)
121 Rozdział 7. ♦ Zaawansowane ADO

'Autorzy: Forte, Howe, Ralston

Dim cat As ADOX.Catalog


Dim key As ADOX.key

On Error GoTo Proc_Err

'Tworzenie obiektów ADOx


Set cat = New ADOX.Catalog
Set key = New ADOX.key
'Otwarcie obiektu katalog na aktualną bazę danych
cat.ActiveConnection = CurrentProject.Connection

'Ustawienie właściwości nowego obiektu Key


With key
'Nazwa obiektu Key w bazie
'musi być unikatowa
.Name = "CategoriesProducts"
'Określenie rodzaju klucza
.Type = adKeyForeign
'Określenie strony JEDEN relacji jeden-do-wielu
.RelatedTable = "Categories"
'Określenie strony WIELU
.Columns.Append "CategoryID"
'Pole "jeden" w tabeli po stronie "jeden"
.Columns("CategoryID").RelatedColumn = "CategoryID"
'Określenie aktualizowania kaskadowego
.UpdateRule = adRICascade
End With

'Teraz określ tabele po stronie "wielu"


'i dołącz do niej nowy obiekt Key
cat.Tables("Products").Keys.Append key

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub

Tworzenie kwerend w ADOX


Aby utworzyć kwerendę w ADOX, musisz użyć pustego obiektu Command i ustawić jego właściwość CommandText, a
następnie dołączyć go do aktualnego obiektu catalog:
cmd.CommandText = "Select * FROM Categories"
"Dołącz kwerendę do zbioru
cat.Views.Append "qryCategories", cmd

Gdy odnosisz się do kwerendy w Accessie, musisz pamiętać, że Microsoft Jet 4.0 zarządza wszystkimi tabelami, kwerendami,
polami i indeksami za Ciebie. Microsoft Jet definiuje kwerendy Accessa na dwa sposoby:
u widoki;
u procedury.

Przez widok rozumiemy zwracającą wiersze, nieparametryczną kwerendę, podczas gdy procedura oznacza wszystkie inne
kwerendy.

Tworzenie widoku
Microsoft Jet zajmie się za Ciebie definiowaniem kwerendy. By utworzyć widok, należy utworzyć kwerendę poprzez
obiekt Command (wydruk 7.15).

Wydruk 7.15. Tworzenie widoku w ADOX


Sub CreateView()
' Tworzenie nowej kwerendy (widoku)
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston
Dim cat As ADOx.Catalog
Dim cmd As ApODB.Command

Set cat = New ADOx.Catalog


Set cmd = New ADODB.Command
Część II ♦ Dostęp do danych 122

' Otwarcie katalogu


cat.ActiveConnection = CurrentProject.Connection
' Tworzenie kwerendy
cmd.CommandText = "Select * FROM Categories"
' Dołączenie kwerendy do kolekcji
cat.Views.Append "qryCategories", cmd
Set cat = Nothing
Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Tworzenie procedury
Tworzenie procedury jest równie proste jak tworzenie widoku. Wystarczy zdefiniować właściwość Commandtext i
dołączyć go do obiektu catalog (wydruk 7.16).

Wydruk 7.16. Tworzenie procedury


Sub CreateProcedure()
' Tworzenie kwerendy (procedury)
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston

Dim cat As ADOx.Catalog


Dim cmd As ADODB.Command

Set cat = New ADOx.Catalog


Set cmd = New ADODB.Command

' Otwarcie katalogu


cat.ActiveConnection = CurrentProject.Connection

'Create the komendy


cmd.CommandText = "Parameters [@Region] Text;" & _
"Select * from Employees where Region = [@Region]"

' Tworzenie procedury


cat.Procedures.Append "qryEmployeesRegion", cmd

Set cat = Nothing

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Modyfikowanie wyrażenia SQL kwerendy


Aby zmodyfikować wyrażenie SQL kwerendy, musisz najpierw utworzyć obiekt command oparty na aktualnej kwerendzie
w bazie danych, a następnie zmodyfikować właściwość commandtext i zresetować obiekt command (wydruk 7.17).

Wydruk 7.17. Zmiana wyrażenia SQL


Sub Modify0uerySQL()
' Zmiana wyrażenia SQL kwerendy
' Z książki "Access 2000 Księga eksperta" (Helion)
' Autorzy: Forte, Howe, Ralston

Dim cat As ADOx.Catalog


Dim cmd As ADODB.Command

On Error GoTo Proc Err

Set cat = New ADOx.Catalog


Set cmd = New ADODB.Command

' Otwarcie katalogu


cat.ActiveConnection = CurrentProject.Connection

' Pobranie kwerendy z bazy danych


Set cmd = cat.Procedures("qryEmployeesRegion").Command

' Zmiana wyrażenia SQL


cmd.CommandText = "Parameters [forms]![frmOrder]![txtRegion] Text;" &_
"Select * from Employees " & _
"Where Region = [forms]![frmOrder]![txtRegion] "
123 Rozdział 7. ♦ Zaawansowane ADO

' Zapis zmienionej kwerendy


Set cat.Procedures("qryEmployeesRegion").Command = cmd

Set cat = Nothing

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Zauważysz, że w kodzie ADO znajdującym się na wydruku 7.17 ustawienie właściwości Command obiektu Procedure na
zmodyfikowany obiekt Command powoduje zapisanie zmian. Gdybyśmy nie umieścili tego ostatniego kroku, zmiany nie
zostałyby umieszczone na stałe w bazie danych. Różnica ta wynika z faktu, iż obiekty Command zostały zaprojektowane jako
tymczasowe. Fakt ten ma duże znaczenie, gdyż w DAO obiekty Querydefs uważane były za trwałe. Może Ci się wydawać,
że poniższe fragmenty kodu ADO są równoznaczne:
Set cmd = cat.Procedures("qryEmployeesRegion").Command
cmd.CommandText = "Parameters [@Region] Text;" & _
"Select * from Employees where Region = [@Region]"
Set cat.Procedures("qryEmployeesRegion").Command = cmd

oraz
cat.Procedures("qryEmployeesRegion").CommandText = _
"Parameters [@Region] text;" & _
"Select * from Employees where Region = [@Region] "

Mimo iż pozornie wygląda na to, że działają podobnie, drugi fragment kodu nie spowoduje rzeczywistej aktualizacji
kwerendy w bazie. W drugim przykładzie możesz użyć obiektu Command z jego nowym SQL w kodzie VBA. Jednakże
kiedy zakończysz pracę, zmiany w SQL nie zostaną zapisane w bazie. W pierwszym przypadku, ponieważ nakazujesz
zapisanie cmd, zmiany zostaną uwzględnione w bazie danych.
Część III
Interfejs użytkownika
W tej części:
u Projektowanie formularza.
u Rozbudowa formularzy przy użyciu formantów ActiveX.
u Raporty.
Rozdział 8.
Projektowanie formularza
W tym rozdziale:
u Właściwości formularza.
u Formanty formularza w Accessie.

Formularze decydują o powodzeniu tworzonej aplikacji. Nie dlatego, że są one sercem aplikacji Accessa, lecz dlatego, że
to na pracy z nimi użytkownicy spędzają najwięcej czasu. Dlatego też Twórcy programu dołożyli wszelkich starań, by
formularze w Accessie były jednocześnie proste i potężne.

W rozdziale tym nie zamierzamy wyjaśnić wszystkich szczegółów dotyczących tworzenia formularzy w Accessie (temat ten
jest bardzo obszerny i istnieje wiele dobrych książek, zarówno dla początkujących jak i doświadczonych użytkowników). Aby
przekazać Ci jak najwięcej szczegółów zanadto się nie rozpisując, skupimy się na niektórych ustawieniach i właściwościach
formularza, które mogą ułatwić proces tworzenia oraz pomóc w uzyskaniu rozbudowanego zestawu funkcji. Następnie
przyjrzymy się zastosowaniu niektórych formantów Accessa i pokażemy, jak możesz wykorzystać je w tworzeniu for-
mularzy będących czymś więcej niż tylko narzędziem do wprowadzania danych. Po przeczytaniu tego rozdziału będziesz w
stanie projektować formularze, które nie tylko będą dostarczać użytkownikom szerokiego zestawu funkcji, ale jednocześnie
będą łatwe w obsłudze i estetyczne.

Na początku tego rozdziału przyjrzymy się właściwościom i ustawieniom w Accessie 2000. Następnie przejdziemy do
bardziej zaawansowanych formantów w Przyborniku Accessa, a zwłaszcza pól listy i pól wyboru. Później przyjrzymy się
użyciu przycisków polecenia i przycisków opcji, a następnie pokażemy, jak zwiększyć funkcjonalność formularza i
ograniczyć ilość stron i niepotrzebnych formantów, wykorzystując do tego celu podformularze.

Na koniec przyjrzymy się dołączonym do pakietu Office 2000 w wersji Developer Edition formantom ActiveX oraz
sposobom ich wykorzystania w celu powiększenia zestawu funkcji aplikacji.

Właściwości formularza
Określając właściwości formularza w Accessie 2000, możesz wybierać spośród 81 zdefiniowanych właściwości,
znajdujących się na zakładce Właściwości (rysunek 8.1). Dokładne ich omówienie zajęłoby całą książkę. My skupiliśmy się
na tych właściwościach, które będą miały wpływ na Twoją pracę jako programisty.

Rysunek 8.1.
Okno dialogowe
Właściwości
formularza
Część III ♦ Interfejs użytkownika 126

Zakładka Dane
Formularze w Accessie 2000 są ściśle powiązane z ukrywającymi się za nimi danymi. Możesz bez trudu utworzyć
formularz i rozpocząć wprowadzanie danych bez pisania ani jednej linii kodu. Możesz to zrobić dzięki właściwościom
znajdującym się na zakładce Dane, które jak sama nazwa wskazuje opisują sposób, w jaki formularz powinien przed-
stawiać i współpracować z danymi.

Źródło rekordów
To chyba najczęściej wykorzystywana właściwość formularza. Dzięki niej możesz powiązać formularz z dowolną tabelą,
kwerendą, wyrażeniem SQL lub czymkolwiek innym. Właściwość ta, zależnie od potrzeb, może być określana podczas
projektowania lub też uruchamiania formularza.

Jeśli nie określisz źródła rekordów podczas projektowania, nie będziesz


mógł z nim powiązać pojedynczych pól formularza.

Edycja dozwolona
Po ustawieniu tej właściwości na Tak użytkownicy będą mogli modyfikować dane na formularzu. Inaczej będzie w
przypadku ustawienia Nie. Dzięki temu można w prosty sposób utworzyć formularz tylko do odczytu.

Usuwanie dozwolone
Po ustawieniu tej właściwości na Tak użytkownicy będą mogli usuwać rekordy z formularza. Dzięki tej właściwości masz
kontrolę nad tym, którzy z użytkowników mogą usuwać rekordy z bazy danych.

Dodawanie dozwolone
Po ustawieniu tej właściwości na Nie użytkownicy nie będą mogli dodawać do bazy nowych rekordów. Rozwiązanie to jest
wygodne w sytuacji, gdy wyświetlasz rezultaty kwerendy w widoku arkusza danych, ale nie chcesz, by użytkownicy
dodawali na końcu zestawu rezultatów nowe rekordy.

Wprowadzanie danych
Ustawienie tej właściwości na Tak spowoduje, iż użytkownicy będą mieli możliwość dodawania nowych rekordów,
jednakże bez możliwości przeglądania już istniejących.

Filtry dozwolone, Filtr, Uporządkuj według


Właściwości te umożliwiają zastrzeżenie określonego zestawu rekordów w danym formularzu poprzez użycie warunku
WHERE we właściwości Filtr lub kolejności sortowania we właściwości Uporządkuj według. Właściwość Filtry dozwolone
nakazuje (bądź nie) Accessowi czytanie tych wartości podczas otwierania formularza.

Generalnie, użycie tych właściwości może okazać się nieprzydatne. Używając kwerendy we właściwości Źródło rekordów,
możesz za jednym razem określić parametry i kolejność sortowania. Co więcej, we właściwości Źródło rekordów możesz
skorzystać z optymalizowanych kwerend, co jeszcze bardziej przyśpiesza pracę.

Zakładka Format
Formularze są tymi obiektami, które użytkownik ogląda. Może nie są najważniejszą częścią aplikacji, jednak użytkownicy
o tym nie wiedzą. Wyrabiają sobie opinię na temat aplikacji właśnie na podstawie formularzy. Sposób, w jaki wyglądają,
zachowują się i ułatwiają (bądź utrudniają) codzienne zadania użytkownikom jest bardzo ważny zarówno dla tych
ostatnich, jak i dla Ciebie. Ustawienie właściwości związanych z formatem umożliwi kontrolowanie wyglądu tworzonych
formularzy.

Widok domyślny
Ustawienie tej właściwości nakazuje Accessowi otwarcie formularza w określony sposób. Masz do wyboru następujące
możliwości:
127 Rozdział 8. ♦ Projektowanie formularza

u Formularz pojedynczy – wyświetla rekordy pojedynczo.


u Formularze ciągłe – wyświetla, wiele rekordów, każdy z nich we własnej kopii formularza w części szczegółowej.
u Arkusz danych – podobnie jak arkusz kalkulacyjny wyświetla dane w wierszach i kolumnach.

Dostępne widoki
Ustawiając tę właściwość, możesz ograniczyć ilość sposobów, na jakie użytkownicy będą przeglądać dane. Opcja ta jest
bardzo przydatna, gdy chcesz, aby użytkownicy widzieli tylko jeden rekord jednocześnie lub jedynie dane w arkuszu
danych. Masz do wyboru następujące ustawienia:
u Formularz.
u Arkusz danych.
u Oba.

Paski przewijania
Właściwość ta umożliwia Ci wyłączenie lub włączenie pionowego i poziomego paska przewijania w formularzu.

Selektory rekordów
Właściwość ta włącza lub wyłącza znajdujące się po lewej stronie formularza selektory rekordów. W przypadku
pojedynczych formularzy właściwość ta jest zazwyczaj wyłączona. Dobrze jest jednak ją włączyć w formularzach ciągłych
i arkuszu danych.

Przyciski nawigacyjne
Jeśli chcesz, by Access zajął się przemieszczaniem się po rekordach, ustaw tę właściwość na Tak. Jeśli chcesz tę operację
wykonywać własnoręcznie, wybierz Nie. Pasek nawigacyjny nie będzie wówczas wyświetlany.

Styl obramowania
Formularze w Accessie, w zależności od ich przeznaczenia, mogą być wyświetlane w różnych rodzajach obramowań:
u Zmienny – umożliwia użytkownikom zmianę rozmiaru formularza. Na oknie umieszczone są przyciski Minimalizuj
i Maksymalizuj.
u Dialog – powoduje określenie stałego rozmiaru formularza. Przyciski Minimalizuj i Maksymalizuj są wyłączone.
Ustawienie to doskonale nadaje się do okien komunikatu i rozwijanych formularzy.
u Cienki – powoduje określenie stałego rozmiaru formularza. Przyciski Minimalizuj i Maksymalizuj są włączone.
u Brak – brak jakiegokolwiek obramowania. Ustawienie to sprawdza się w przypadku ekranów tytułowych.

Pole menu sterowania


Właściwość ta określa, czy wyświetlane są przyciski Minimalizuj, Maksymalizuj i Zamknij.

Przyciski Min Max


Gdy ustawisz tę właściwość na Tak, użytkownicy będą mogli minimalizować i maksymalizować formularze na pulpicie.

Przycisk Zamknij
Gdy ustawisz tę właściwość na Tak, użytkownicy będą mogli używać menu kontrolnego do zamykania formularza.

Jeśli ustawisz tę właściwość na Nie, musisz umożliwić użytkownikom zam-


knięcie formularza w inny sposób. W innym razie, będą go mogli zamknąć
jedynie poprzez kombinacje klawiszy Ctrl+F4 bądź Alt+F4 albo przez
zamknięcie Accessa.
Część III ♦ Interfejs użytkownika 128

Zakładka Inne
Właściwości znajdujące się w tej kategorii są równie ważne jak te opisane powyżej. Opisują kilka bardzo ważnych
aspektów zachowania się formularza i pełnią rolę zestawu zaawansowanych właściwości, służących do wykańczania
formularza. Nowością w tej wersji Accessa jest opisana poniżej właściwość Zezwolenie na zmiany projektu.

Modalny
Gdy właściwość ta ustawiona jest na Tak, po otwarciu formularza żaden inny formularz nie będzie dostępny przed
zamknięciem formularza modalnego. Opcja ta sprawdza się jako komunikat o błędzie lub nakaz wykonania przez
użytkownika określonych czynności przed przejściem dalej.

Podręczny
Formularze podręczne są formularzami podrzędnymi w stosunku do okna Accessa. Odróżnia to je od pozostałych
formularzy, które są podrzędne w stosunku do formularza, w którym zostały otwarte. Oznacza to, że formularze podręczne
mogą być umieszczone w dowolnym miejscu na pulpicie Accessa.

Pasek menu, pasek narzędzi


Jeśli stworzyłeś własne menu lub paski narzędzi, które chcesz połączyć z określonym formularzem, ustawienie tej
właściwości spowoduje, że to menu lub pasek zostaną wyświetlone po uruchomieniu formularza.

Menu podręczne
Gdy ustawisz tę właściwość na Tak, za każdym razem, gdy użytkownik użyje na formularzu prawego klawisza myszy,
zostanie wyświetlone menu, które wybrałeś we właściwości Pasek menu podręcznego.

Pasek menu podręcznego


Jeśli stworzyłeś dla formularza menu podręczne, wybranie go w tym miejscu i ustawienie właściwości Menu podręczne na
Tak nakaże Accessowi wyświetlenie tego menu za każdym razem, gdy użytkownik użyje na formularzu prawego klawisza
myszy.

Metka
Właściwość ta może przechowywać dowolną, wybraną przez Ciebie wartość. Możesz pobrać ją z dowolnego miejsca w
aplikacji i zostanie ona zapisana wraz z formularzem.

Jeśli formularz oparty jest na kodzie i ustawisz właściwość Ma moduł na Nie,


cały kod zostanie usunięty. Access powiadomi Cię o tym fakcie.

Ma moduł
Po ustawieniu tej właściwości na Nie Access usunie cały kod, na którym oparty jest formularz. W ten sposób
„odchudzony” formularz bardzo szybko się ładuje.

Jeśli formularz nie zawiera kodu, koniecznie ustaw tę właściwość na Tak. W ten sposób Access nie będzie próbował
kompilować formularza za każdym jego ładowaniem. Nie pisząc kodu, możesz dodatkowo poprawić funkcjonalność
formularza, wstawiając do niego hiperłącze (opisane w dalszej części tego rozdziału) i łącząc go z obiektem w bazie
danych (rysunek 8.2).
129 Rozdział 8. ♦ Projektowanie formularza

Rysunek 8.2.
Okno dialogowe
Wstaw hiperłącze

Zezwolenie na zmiany projektu


Ustawienie tej właściwości na Wszystkie widoki pozostawia po uruchomieniu formularza otwarte okno dialogowe Format,
co umożliwia dokonywanie zmian i oglądanie ich „na żywo” w aplikacji. Nie zapomnij ustawić tej właściwości na Tylko
widok projektu po dokonaniu zmian.

Użyteczne właściwości
nie znajdujące się na arkuszu właściwości
Jak zawsze, rzeczy ukryte są dla nas bardziej interesujące niż te ogólnodostępne. Zasada ta ma zastosowanie do ukrytych
właściwości formularza. W tym przypadku ukryte właściwości ułatwiają tworzenie w Accessie wykorzystujących
formularze, złożonych aplikacji.

Argumenty otwarcia (OpenArgs)


Właściwość ta jest dostępna jedynie wtedy, gdy formularz działa. Dzięki niej po wprowadzeniu ciągu wartości w jednym
formularzu zostanie on automatycznie wprowadzony do drugiego formularza.
'Składnia dla formularza wysyłającego:
Docmd.OpenForm "MyForm", "jakiś ciąg wartości"

'Składnia dla formularza odbierającego:


Dim x as string
If not isnull (OpenArgs) then
X = Me.OpenArgs
'wykonaj specjalne formatowanie
end if

Właściwość ArgumentyOtwarcia przydaje się, gdy do zbierania żądanych informacji używasz formularzy modalnych. Jeśli
chcesz sformatować formularz w inny, zgodny z logiką aplikacji sposób, możesz użyć ArgumentyOtwarcia do wysłania
„wiadomości” do formularza i pobrania jej podczas zdarzenia Form_Open. W trakcie trwania zdarzenia możesz zmienić
wygląd formularza lub zablokować możliwość poruszania się między rekordami, by skoncentrować się na tym rekordzie,
który musisz edytować. Po otwarciu formularza jako okna dialogowego nie będziesz mógł go programowo modyfikować,
więc jedynym sposobem na zapewnienie zgodności z logiką aplikacji będzie użycie właściwości ArgumentyOtwarcia.

Właściwości użytkownika
W sekcji ogólnych deklaracji formularza zadeklarowanie zmiennej jako jawnej lub niejawnej spowoduje utworzenie
właściwości użytkownika. Aby właściwość ta była dostępna również dla innych modułów, musisz zadeklarować zmienną
właściwości jako jawną. Jeśli istnieje potrzeba udostępnienia tej właściwości innym formularzom lub jeśli będziesz chciał
dodać walidację przy pobieraniu bądź ustawianiu tej właściwości, możesz do walidacji wykorzystać metody Property
Get i Property Let.

Załóżmy, że tworzysz aplikację przetwarzającą prawa jazdy i jednym z wymagań jest to, że wiek kierowcy musi być
większy niż 16 lat. Do rozwiązania problemu odczytu i zapisu tej właściwości mógłbyś napisać poniższą regułę
poprawności.

W deklaracjach ogólnych:
' Utwórz w pamięci zmienną intMyAge.
Dim intMyAge as Integer
' Użyj tego kodu, by odczytać wartość wejściową i sprawdzić, czy
Część III ♦ Interfejs użytkownika 130

' odpowiada założonym kryteriom


Public Property Let MyAge(byval intAge as Integer)
If intAge < 16 then
Msgbox "Wiek kierowcy nie może być mniejszy niż 16 lat"
Else
IntMyAge=intAge
End if
End Property

Użyj tego kodu, aby dodać metodę Property Get. Dzięki temu kod będzie dostępny na zewnątrz formularza.
Public Property Get MyAge() as Integer
MyAge = intMyAge
End Property

Gdy chcesz zobaczyć utworzoną właściwość w oknie rozwijanej listy IntelliSense (tak jak ją kodujesz), musisz
zadeklarować zmienną formularza typu Form_nazwa_twojego_formularza.

Zdarzenia
Access posiada ponad 30 zdarzeń, które pomagają kontrolować działanie programu. Bardzo ważnym jest, byś wiedział, w
jakiej kolejności zdarzenia te następują. Poniżej znajdziesz informacje na temat kolejności występowania zdarzeń w
różnych okolicznościach. Niektóre z tych zdarzeń pomijają parametr Cancel (Anuluj), który może być ustawiony na
True, jeśli chcesz zatrzymać otwieranie lub zamykanie formularza. Gdy ustawisz parametr Cancel na True, Access po
zatrzymaniu zdarzenia kontynuuje działanie, wyświetlając komunikat o błędzie 2501. Musisz naprawić ten błąd, w prze-
ciwnym wypadku narażasz się na ryzyko kolejnego błędu Accessa (rysunek 8.3).

Rysunek 8.3.
Błąd Accessa 2501,
wyświetlany po
ustawieniu
parametru Cancel
na True

Działanie systemu operacyjnego Windows oparte jest na zdarzeniach. Oznacza to, iż poza wewnętrznym zegarem
komputera jedynym źródłem działania jest użytkownik. System operacyjny w przeciągu kilku nanosekund odpowiada na
uruchamiane zdarzenia i przekazuje je do aktywnej aplikacji. Na następnej stronie umieściliśmy listę zdarzeń uru-
chamianych podczas pracy użytkownika z formularzem w Accessie.

Otwarcie formularza
Podczas otwierania formularza określone zdarzenia uruchamiane są w przedstawionej poniżej kolejności. Po ustawieniu
parametru Cancel na True, wykonywanie zdarzeń jest zatrzymywane.
15. Otwórz (z opcją Anuluj).
16. Załaduj.
17. Zmień rozmiar.
18. Aktywuj.
19. Aktualny.
20. Wejście do pierwszego formantu.
21. Uzyskanie fokusu przez pierwszy formant.

Jeśli na formularzu nie ma formantów, sam formularz uzyska fokus.

Jeśli w formularzu umieszczony jest podformularz, następujące zdarzenia wykonywane są PRZED zdarzeniem otwarcia
głównego formularza:
1. Otwórz (z opcją Anuluj).
2. Załaduj.
3. Zmień rozmiar.
131 Rozdział 8. ♦ Projektowanie formularza

4. Aktualny.
5. Wejście do pierwszego formantu.
6. Uzyskanie fokusu przez pierwszy formant.

Umożliwia to uzyskanie dostępu do pól podformularza z poziomu zdarzenia Otwórz głównego formularza i w razie
potrzeby daje możliwość anulowania.

Zamknięcie formularza
Podczas zamykania formularza określone zdarzenia uruchamiane są w przedstawionej poniżej kolejności. Po ustawieniu
parametru Cancel na True wykonywanie zdarzeń jest zatrzymywane.
7. Wyładuj (z opcją anuluj).
8. Dezaktywuj.
9. Zamknij.

Zmiana rozmiaru formularza


Gdy zmieniany jest rozmiar formularza, określone zdarzenia uruchamiane są w przedstawionej poniżej kolejności.
10. Zmień rozmiar.
11. Dezaktywuj.

Maksymalizowanie formularza
Gdy formularz jest maksymalizowany, określone zdarzenia uruchamiane są w przedstawionej poniżej kolejności.
12. Zmień rozmiar.

Przywrócenie zminimalizowanego formularza


Gdy formularz jest przywracany, określone zdarzenia uruchamiane są w przedstawionej poniżej kolejności.
13. Aktywuj.
14. Zmień rozmiar.

Formanty formularza w Accessie


Aby pomóc Ci w tworzeniu aplikacji, Access 2000 zawiera wiele wbudowanych formatów. Niektóre z nich, jak na
przykład pole tekstowe, nie zmieniły się zbytnio od czasów Accessa 1.0. W niektórych, jak pole listy, zaszły znaczące
zmiany. W tej części scharakteryzujemy najciekawsze z formantów Accessa.

Formant Lista rozwijana


Listy rozwijane zawierają zestaw uprzednio zdefiniowanych wartości, co ułatwia użytkownikom wprowadzanie danych
poprzez wybieranie z list żądanych wartości. Większość list rozwijanych bazuje na kwerendach lub wyrażeniach SQL i
zwykle zawiera jedną lub dwie kolumny i pole związane. Mimo iż dużej części programistów to wystarcza, istnieją
interesujące właściwości list rozwijanych Accessa 2000, które mogą znacznie zwiększyć ich funkcjonalność.

Użycie zdarzenia Not In List


Zdarzenie Not In List uruchamia się automatycznie, gdy wprowadzana jest wartość, która nie znajduje się na liście.
Umożliwia to programiście zbadanie tej wartości i podjęcie decyzji, co z nią zrobić.

Przykładowo, przyjmijmy, że utworzyłeś listę rozwijaną z klientami i wprowadzono klienta, którego jeszcze nie było na
liście. Korzystając z poniższego kodu, mógłbyś wyłapać ten błąd i zapytać użytkownika, czy chce utworzyć nowego
klienta:
Dim MyResponse AS Variant
Dim Msg As String
Część III ♦ Interfejs użytkownika 132

'Ta procedura uruchamia się tylko wtedy, gdy wykryty zostanie


'obiekt nie znajdujący się na liście
Msg = "Klient "& Newdata &" nie został odnaleziony, _
Czy chcesz dodać do listy klientów?"

'Poinformuj użytkownika o nowej wartości.


MyResponse = MsgBox(Msg, vbInformation + vbYesNo, _
"Klient nie został odnaleziony")

'Jeśli tak, dodaj kod, by zająć się nową wartością.


If MyResponse = vbYes Then

MsgBox "Tu wpisz kod", vbInformation _


+ vbOKOnly, "Gotowy do dodawania"
Me.cboUser = ""

Else

'Jeśli nie, wprowadź kod, aby zapytać użytkownika o poprawną wartość.


MsgBox "Wybierz z listy innego _
Klienta", vbInformation + vbOKOnly, "Wybierz _
innego Klienta"

End If

'Każ Accessowi kontynuować. Opis stałych procedury zdarzenia


'znajdziesz w internetowym pliku pomocy.
Response = acDataErrContinue

Tworzenie automatycznie rozwijającej się listy rozwijanej


Ile razy chciałeś po prostu przejść do pola listy tak, by rozwinęła się automatycznie bez użycia polecenia SendKeys? W
Accessie 97, jedyne co musisz zrobić to wpisać poniższą linijkę kodu do zdarzenia Enter:
ActiveControl.DropDown

To wszystko!

Tworzenie własnych list rozwijanych


Zazwyczaj wartości w rozwijanych polach pochodzą z tabeli lub kwerendy. Ale to nie jest jedyna możliwość. Ustawiając
właściwość Typ źródła wierszy na Lista pól, możesz wybrać przeglądanie pól w bazowej tabeli lub kwerendzie. Możesz
również wybrać w tej właściwości nazwę dowolnej funkcji, która będzie wyświetlać dowolną listę. Nawet, jeśli nie
zauważysz od razu korzyści płynących z takiego rozwiązania, przydaje się ono, gdy chcesz dodać do listy specjalną
wartość jak na przykład Wszystkie. Opcja ta przyda się również, gdy będziesz chciał wyświetlić przydatną dla księgowych,
wyrównaną do prawej listę wartości walutowych. To ostatnie rozwiązanie możliwe jest poprzez umieszczenie spacji po
lewej stronie wartości i wyświetlenie za pomocą czcionki o stałej szerokości (np. Courier).

Oto fragment kodu, znajdujący się w bazie danych Solutions.mdb, który przedstawia sposób, jak dodać u góry listy
rozwijanej wartość specjalną Wszystkie.
Function AddAllToList(ctl As Control, lngID As Long, _
lngRow As Long, lngCol As Long, intCode As Integer) As Variant

' Dodaje u góry listy wartość specjalną "Wszystkie"


' Można dodać "Wszystkie" do różnych kolumn listy

Static dbs As Database, rst As Recordset


Static lngDisplayID As Long
Static intDisplayCol As Integer
Static strDisplayText As String
Dim intSemiColon As Integer

On Error GoTo Err_AddAllToList

Select Case intCode


Case acLBInitialize
' See if function is already in use.
If lngDisplayID <> 0 Then
MsgBox "AddAllToList Jest już używane przez inny formant !"
AddAllToList = False
Exit Function
End If

' Wyłuskanie kolumny do wyświetlenia i wyświetlenie tekstu z


' własności Tag

intDisplayCol = 1.
strDisplayText = "(Wszystkie)"
If Not IsNull(ctl.Tag) Then
intSemiColon = InStr(ctl.Tag, ";")
If intSemiColon = 0 Then
intDisplayCol = Val(ctl.Tag)
133 Rozdział 8. ♦ Projektowanie formularza

Else
intDisplayCol = Val(Left(ctl.Tag, intSemiColon - 1))
strDisplayText = Mid(ctl.Tag, intSemiColon + 1)
End If
End If

' Otwórz recordset zdefiniowany przez własność RowSource


Set dbs = CurrentDb
Set rst = dbs.OpenRecordset(ctl.RowSource, dbOpenSnapshot)

' Zapamiętaj i zwróć lngId


lngDisplayID = Timer
AddAllToList = lngDisplayID
Case acLBOpen
AddAllToList = lngDisplayID
Case acLBGetRowCount
' Zwróć ilość wierszy w wyniku
On Error Resume Next
rst.MoveLast
AddAllToList = rst.RecordCount + 1.
Case acLBGetColumnCount
' Zwróć ilość kolumn w wyniku
AddAllToList = rst.Fields.Count
Case acLBGetColumnWidth
AddAllToList = -1.
Case acLBGetValue
If lngRow = 0 Then
If lngCol = int0isplayCol - 1 Then
AddAllToList = strDisplayText
Else
AddAllToList = Null
End If
Else
rst.MoveFirst
rst.Move lngRow - 1
AddAllToList = rst(lngCol)
End If
Case acLBEnd
lngDisplayID = 0
rst.Close
End Select

Bye_AddAllToList:
Exit Function

Err_AddAllToList:
MsgBox Err.Description, vbOKOnly + vbCritical, "AddAllToList"
AddAllToList = False
Resume Bye_AddAllToList

End Function

Pobieranie więcej niż jednej wartości z pola listy i listy rozwijanej


Korzystając z właściwości Column, możesz pobrać wartość z dowolnej kolumny w polu listy lub listy rozwijanej. W
właściwości Column pierwsza kolumna ma numer 0, druga 1, i tak dalej.

Przykładowo, aby odczytać wartość z czwartej kolumny listy rozwijanej, wpisałbyś:


MyVariantValue = Me!MyComboBox.Column(3)

Pole listy
Pole listy przypomina opisaną powyżej listę rozwijaną. Różnica tkwi w możliwości przeglądania wszystkich możliwych
wartości bez konieczności rozwijania listy. Również w przeciwieństwie do listy rozwijanej, pole listy umożliwia wybranie
kilku wartości jednocześnie. Opcja ta przydaje się w sytuacji, gdy chcesz umożliwić użytkownikowi w tworzonym przez
Ciebie systemie przeglądanie informacji o 5 ze 100 wpisów (faktury, ludzie, płyty CD czy ciężarówki). Ponieważ większość
właściwości pola listy została już opisana, skoncentrujemy się na różnicach.

Pole listy wielokrotnego wyboru


W Accessie 2 istniały sztuczki pozwalające na umożliwienie użytkownikom wybieranie kilku wartości z listy. Począwszy
od Accessa 2000, wybieranie kilku wartości naraz stało się łatwe dzięki polu listy wielokrotnego wyboru. Jednakże
pobieranie wybranych wartości nie zawsze jest tak intuicyjne.
Część III ♦ Interfejs użytkownika 134

Ustawienia właściwości
Aby używać pola listy wielokrotnego wyboru, musisz najpierw utworzyć zwykłe pole listy i później przekształcić je w pole
wielokrotnego wyboru. Możesz tego dokonać, zmieniając znajdującą się na arkuszu właściwości obiektu właściwość Wybór
wielokrotny. W tabeli 8.1 znajdują się możliwe ustawienia.

Tabela 8.1.
Ustawienia właściwości Wybór wielokrotny

Wartość Znaczenie
Brak Wybór wielokrotny nie jest możliwy.
Prosty Elementy wielokrotne wybierane są przez kliknięcie myszką lub naciśnięcie
klawisza spacji.
Rozszerzony Elementy wielokrotne wybierane są przez przytrzymanie klawisza Shift i kliknięcie ich
myszką lub przez przytrzymanie klawisza Shift i naciśnięcie klawisza strzałki (powoduje to
rozszerzenie zaznaczenia od poprzednio wybranego do aktualnego elementu). Możesz
również zaznaczać elementy, przeciągając je myszką. Przytrzymanie klawisza Ctrl
i klinięcie go myszką powoduje jego zaznaczenie lub zniesienie zaznaczenia.

Aby pobrać wartości, będziesz musiał posłużyć się kodem. Przykładowo, by odczytać wartości z listy pracowników,
mógłbyś napisać następujący fragment kodu:
Dim strMsg As String
Dim strName As String
Dim i As Integer

'Utwórz ciąg przechowujący wiadomość.


strMsg = "Wybrano następujących pracowników: " _
& vbCr & vbCr

For i = 1 To Me.lstMulti.ListCount

'Sprawdź, czy użytkownik zaznaczył ten wiersz.


If Me.lstMulti.Selected(i) Then
'Jeśli tak, dodaj pierwszą kolumnę zaznaczonego wiersza
' do ciągu wiadomości.
StrName = Me.lstMulti.Column(0, i)

'Pobierz wartość obiektu (pola związanego) i dodaj ją


'do ciągu. Spowoduje to utworzenie wyświetlanego
'imienia i nazwiska.
StrName = strName & Chr(32) & _ Me.lstMulti.ItemData(i)
strMsg = strMsg & strName & vbCr
End If
Next
MsgBox Msg

Kod ten nie tylko odczytuje wartości z pola listy, ale również wykorzystuje właściwość column w celu pobrania wartości z
więcej niż tylko jednej, związanej kolumny.

Podformularze
Podformularze zawsze były świetnym sposobem na prezentowanie danych w relacji jeden-do-wielu. Korzystając z
nadrzędnego i podrzędnego pola łączącego, programiści mogą z łatwością powiązać ze sobą dane w relacji.

Podformularze posiadają jeszcze jedną bardzo przydatną cechę. Zmieniając właściwość Obiekt źródłowy, programiści mogą
wstawiać do jednego, głównego formularza nieograniczoną ilość podformularzy. Dzięki temu, programiści mogą tworzyć
własne zbiory obiektów, czyli coś, czego nie można było zrobić w Visual Basicu. Zbiory te umożliwiają grupowanie
obiektów i odnoszenie się do nich jako całości.

Dodatkowo, podformularze są doskonałym sposobem na obejście dwudziesto-dwu calowego limitu długości formularzy w
Accessie. Podformularze umożliwiają również szybsze ładowanie formularzy, gdyż nie muszą ładować każdego formularza,
pola listy czy pola memo, którego mógłby potrzebować użytkownik. Programiści mogą kontrolować sposób przedstawiania
danych i ograniczać ilość elementów graficznych lub innych zasobochłonnych obiektów.

Dodawanie podformularzy
Istnieją trzy sposoby dodawania do formularza podformularzy:
135 Rozdział 8. ♦ Projektowanie formularza

u Po otwarciu formularza w widoku Projekt wybierz z przybornika obiekt Podformularz i przeciągnij go na główny
formularz. Utworzony zostanie pusty podformularz. Następnie dodaj obiekt źródłowy oraz nadrzędne i podrzędne
pole łączące.
u Drugi sposób jest jeszcze prostszy. Otwórz główny formularz w widoku Projekt i przejdź do okna bazy danych.
Przeciągnij formularz, którego chcesz użyć jako podformularza z okna bazy danych na główny formularz. Access
spróbuje połączyć nadrzędne i podrzędne pola i ustawić za Ciebie obiekt źródłowy. Access ustawi również
rozmiar podformularza tak, by dobrze pasował do okna głównego formularza. Ręczne wykonywanie tej czynności
może czasami przysporzyć wielu trudności.
u Użyj dołączonego do Accessa kreatora podformularzy.

W Accessie 97 Kreator formantów był domyślnie włączony. W Accessie


2000 jest inaczej. Aby użyć tego kreatora, upewnij się, czy znajdujący się
w Przyborniku przycisk Kreatorzy formantów jest wciśnięty (rysunek
8.4). Gdy tworzysz nowy podformularz w widoku Projekt formularza,
Kreator podformularzy zostanie uruchomiony automatycznie.

Tworzenie odniesienia dla podformularza


Istnieje kilka sposobów tworzenia odniesień dla formantów na podformularzu. Typowa składnia wygląda następująco:
Forms!MyForm!SubFormControlName.Form!ControlName

Metoda ta uległa znacznemu poprawieniu w Accessie 2000, ponieważ zbiór formantów jest domyślnym zbiorem dla
formularza. Teraz możesz stworzyć odniesienie dla tego samego obiektu w następujący sposób:
Forms!MyForm!SubFormControlName!ControlName

lub
Me!MyForm!SubFormControlName!ControlName

W obu przypadkach efekt będzie ten sam.

Aby mieć pewność co do składni, skorzystaj z kreatora wyrażeń (Ctrl+F2).

Rysunek. 8.4.
Przybornik
z wciśniętym
przyciskiem Kreatora
formantów

Wbudowany formant Karta


Innym sposobem na łączenie formantów jest zastosowanie formantu Karta. Jest on jednym z wbudowanych obiektów
Accessa 2000.

Grupa opcji
Programiści Visual Basica mieli do swojej dyspozycji tablice obiektów (czyli możliwość tworzenia odniesień do grupy
formantów za pomocą tej samej nazwy, lecz innego indeksu). Dzięki temu możliwe było znaczne uproszczenie procesu
ustawiania właściwości lub zmiany wartości. Niestety, poza formantem Grupa opcji, w Accessie 2000 nie ma takiej
możliwości.

Dzięki temu formantowi, możesz wewnątrz ramki umieścić pola wyboru, przyciski opcji lub przyciski przełącznika, a
następnie tworzyć odniesienia do każdego obiektu według wartości jego indeksu. Możesz jednym poleceniem (zamiast
pięciu czy sześciu) włączać lub wyłączać właściwość Widoczny obiektów wewnątrz ramki. Możesz także używać
konstrukcji For Each, aby przejść przez wszystkie wartości wewnątrz grupy opcji, zamiast testować każdą z nich osobno.
Część III ♦ Interfejs użytkownika 136

Podręczne menu
Podręczne menu pojawiły się wraz z systemem Windows 95. Większość z tych użytkowników, którzy z Windows 95
powrócili do Windows 3x, przeklina niemożność korzystania z prawego przycisku myszy. Podręczne menu to doskonały
sposób na skrócenie wykonywania najpopularniejszych czynności lub umożliwienie korzystania z charakterystycznych dla
danego obiektu opcji. Formularze, a nawet pojedyncze formanty, mogą posiadać swoje własne menu podręczne, a odrobina
kodu pomoże Ci na bieżąco modyfikować wygląd pasków poleceń.

Aby utworzyć podręczne menu, kliknij dowolny pasek narzędzi lub pasek menu i wybierz Dostosuj. Możesz również wybrać z
menu Widok pozycję Paski narzędzi⇒Dostosuj.
15. Na zakładce Paski narzędzi kliknij Nowy...
16. W polu Nazwa paska narzędzi wpisz dowolną nazwę i kliknij OK.
17. Na zakładce Paski narzędzi kliknij Właściwości.
18. Z listy Typ wybierz Podręczny.
19. Ustaw właściwość Zezwalaj na dostosowanie w żądany sposób i kliknij Zamknij. Nie martw się, nie stracisz tego
paska.
20. W oknie Paski narzędzi kliknij Menu podręczne.
21. Na pasku narzędzi Menu podręczne kliknij kategorię Niestandardowe. Tam znajdziesz swoje nowe menu
podręczne.
22. Aby wykończyć menu, postępuj w następujący sposób:
Dodaj polecenia z okna dialogowego Dostosuj.
Przenoś lub kopiuj polecenia z innych menu.

Hiperłącza
Hiperłącza to niezmiernie przydatne formanty, umożliwiające użytkownikowi przechodzenie za jednym kliknięciem do
formularzy, raportów, arkuszy Excela, dokumentów Worda czy nawet stron WWW. Ponieważ nie kryją one za sobą kodu,
idealnie nadają się do formularzy nawigacyjnych. Można ich używać na „odchudzonych” formularzach (tych z
właściwością Ma moduł ustawioną na Nie). Hiperłącze jest niepołączoną etykietą (etykieta bez obiektu nadrzędnego) z
właściwościami Adres hiperłącza i Podadres hiperłącza ustawionymi na Null.
Rozdział 9.
Rozbudowa formularzy przy użyciu
formantów ActiveX
W tym rozdziale:
u Jak korzystać z formantów ActiveX.
u Użycie formantów ActiveX.
u 21 formantów ActiveX.
u Rozpowszechnianie formantów ActiveX.

Formanty ActiveX umożliwiają zwiększenie zestawu funkcji aplikacji pisanych w Accessie, ułatwiając ich tworzenie i
obsługę. Możliwości, jakie dają programistom, są nieograniczone.

Z tego rozdziału dowiesz się, jakie formanty ActiveX masz do swojej dyspozycji i nauczysz się dodawać je do formularzy
Accessa. Najpierw jednak powiemy, czym są i skąd wzięły się formanty ActiveX.

Jak korzystać z formantów ActiveX


Miałeś już okazję zapoznać się z wbudowanymi formantami, które można umieszczać na formularzach Accessa (np. pola
tekstowe czy przyciski poleceń). Formanty ActiveX działają w bardzo podobny sposób, z tą różnicą, że kod obsługujący
zestaw funkcji formantu ActiveX przechowywany jest w osobnym pliku, który przed użyciem musi zostać zainstalowany.

Formanty ActiveX pozwalają na wzbogacenie tworzonych aplikacji o funkcje, których nie udostępniał Access. Mógłby to
być, na przykład, kalendarz lub formant siatki. Formanty ActiveX są zazwyczaj przechowywane w folderze systemowym i
są plikami o rozszerzeniu OCX lub DLL.

Formanty ActiveX nie są częścią Accessa, jednakże mogą być używane w jego aplikacjach. Działają dokładnie w ten sam
sposób, co pozwala na uzyskanie wysokiej wydajności.

W tym rozdziale pokażemy, jak używać formantów ActiveX w formularzach Accessa, jednakże te same formanty mogą
być użyte w aplikacjach Visual Basic, Office, a nawet w aplikacjach działających w sieci WWW.

Nie każdy formant ActiveX będzie działał we wszystkich aplikacjach. For-


mant świetnie działający w Visual Basicu może nie działać w Accessie i na
odwrót. Aby się przekonać, czy dany formant ActiveX będzie działał w
Accessie, przejrzyj jego dokumentację lub sam przeprowadź odpowiednie
testy.

Typy formantów ActiveX


Istnieją dwa typy formantów ActiveX: formanty związane z procesem projektowania i formanty wykorzystywane podczas
użytkowania aplikacji.
Część III ♦ Interfejs użytkownika 138

Formanty związane z procesem projektowania umieszczane są na formularzach Accessa, lecz nie są nigdy widoczne dla
ostatecznego użytkownika. Formanty te zawierają kod, który powiększa zestaw funkcji dostępnych dla programisty.
Widoczne są one w procesie projektowania, a nie podczas używania aplikacji, tak więc ostateczny użytkownik ich nie
widzi. Przykładem formantów związanych z procesem projektowania są formanty Image oraz Common Dialog.

Formanty wykorzystywane podczas użytkowania aplikacji zawierają interfejs użytkownika, który jest dla ostatecznego
użytkownika widoczny. Omówione w dalszej części tego rozdziału przykłady tego typu formantów to: Toolbar,
MonthView, ListView, a także wiele innych. Formanty tego typu widoczne są zarówno podczas fazy projektowania, jak i
podczas użytkowania aplikacji. W tej drugiej fazie użytkownicy mają możliwość manipulowania formantami w określony
sposób.

Gdzie znaleźć formanty ActiveX?


Bez wątpliwości wiele formantów ActiveX znajduje się już na Twoim komputerze. Być może nawet nie uda Ci się
ustalić pochodzenia części z nich. Oto kilka możliwych źródeł:
u Windows.
u Aplikacje Microsoft Office.
u Visual Basic.
u Internet Explorer.
u Inne aplikacje.
u Inni producenci.
u Pliki pobrane ze stron sieci WWW.
u Formanty ActiveX, które utworzyłeś za pomocą C++, Java czy Visual Basica. Więcej informacji o tworzeniu
własnych formantów ActiveX znajdziesz w rozdziale 20., „Użycie Visual Basic z Accessem”.

Doradzamy testowanie formantów ActiveX przed ich użyciem. Wiele for-


mantów można znaleźć w Internecie. Sprawdź, czy dany formant od-
powiada Twoim potrzebom, zanim go zakupisz.

Czy formanty ActiveX są bezpieczne?


Niekoniecznie. Formanty ActiveX zawierają kod. Złośliwy programista mógłby bez trudu utworzyć formant, który dokona
poważnych uszkodzeń systemu operacyjnego Twojego komputera. Doradzamy korzystanie jedynie z formantów
pochodzących ze sprawdzonych źródeł.

Czy mogę korzystać z formantów ActiveX


i rozpowszechniać je w moich aplikacjach?
To, że dany formant znajduje się na Twoim komputerze, nie oznacza wcale, że możesz z niego korzystać i umieszczać go
w swoich aplikacjach. Powinieneś zadać sobie pytanie: „Czy mam prawo korzystać z danego formantu ActiveX?”

Ważnym jest, by dokładnie przeczytać dotyczącą formantu umowę licencyjną. Przykładowo, mogłeś otrzymać formanty
dokonując zakupu narzędzi programistycznych od firmy Microsoft. Przeczytaj umowę licencyjną, aby sprawdzić, czy
możesz korzystać z tych formantów i rozpowszechniać je bez dodatkowych opłat. Powinieneś postępować w ten sam
sposób, kupując formanty od innych firm.

Formanty, których nie kupowałeś, mogą pochodzić z Internetu. Najprawdopodobniej nie będziesz miał prawa do
umieszczania ich w swoich aplikacjach. Często, gdy próbujesz użyć formantu ActiveX w swojej aplikacji, wyświetlane jest
ostrzeżenie, że nie masz praw do używania i rozpowszechniania tego formantu.

Przestrzeganie umów licencyjnych jest zapewnione z mocy prawa. Niewłaściwe użycie bądź bezprawne
rozpowszechnianie formantu ActiveX jest tym samym co nielegalne kopiowanie oprogramowania. Może być ścigane jak
przestępstwo kryminalne albo pociągnąć za sobą roszczenia odszkodowawcze ze strony poszkodowanego.
139 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Użycie formantów ActiveX


Użycie formantów ActiveX w Accessie wymaga wykonania następujących kroków:
23. Zainstalowania formantu na komputerze.
24. Zarejestrowania formantu.
25. Dodania formantu do formularza.
26. Ustawienia właściwości formantu.
27. Dodania kodu, który umożliwi wykonanie metod i reagowanie na zdarzenia.

Instalowanie formantu ActiveX


Formant ActiveX musi zostać zainstalowany na komputerze, w innym bowiem przypadku, gdy aplikacja będzie chciała go
użyć, wyświetlony zostanie komunikat o błędzie. Oznacza to, że za każdym razem, gdy rozpowszechniasz aplikację,
musisz upewnić się, że dołączyłeś do niej również wymagane formanty ActiveX. O tym jednak w dalszej części tego
rozdziału.

Jeśli rozpowszechniasz aplikację korzystającą z formantów ActiveX, po-


winieneś się upewnić, czy wymagane formanty są zainstalowane na każdym
z komputerów, na których aplikacja będzie uruchamiana. I tak, przykładowe
aplikacje dla tego rozdziału nie będą działać na Twoim komputerze, jeśli nie
zainstalujesz odpowiednich formantów ActiveX.

Rejestrowanie formantów ActiveX


Zanim formant ActiveX zostanie dodany do formularza Accessa, musi zostać zarejestrowany. Aby określić, czy formant
został zarejestrowany, spróbuj dołączyć go do formularza (opis tej czynności znajdziesz w następnym rozdziale). Jeśli Ci się
to uda, znaczy to, że formant został już zarejestrowany. W przeciwnym wypadku musisz zarejestrować go przy użyciu
Accessa.

Niektóre formanty ActiveX rejestrowane są automatycznie po ich zainstalowaniu. Aby zrobić to ręcznie, gdy formularz
otwarty jest w widoku Projekt, z menu Narzędzia wybierz pozycję Formanty ActiveX. Wyświetlone zostanie okno dialogowe
Formanty ActiveX. Wybierz formant, który chcesz zarejestrować i kliknij przycisk Zarejestruj. Wyświetlone zostanie okno
dialogowe Dodaj formant ActiveX. Wybierz odpowiadający wybranemu formantowi plik (.OCX) i kliknij OK. (rysunek 9.1).
Rysunek 9.1.
Okno dialogowe
Dodaj formant
ActiveX

Dodawanie formantu ActiveX do formularza


Jeśli formant ActiveX jest już zarejestrowany, możesz dodać go do formularza. Aby tego dokonać, otwórz formularz w
widoku Projekt i z menu Wstaw wybierz Formant ActiveX lub kliknij znajdujący się w prawym dolnym rogu Przybornika
przycisk Więcej formantów (rysunek 9.2).
Część III ♦ Interfejs użytkownika 140

Rysunek 9.2.
Znajdujący się
w Przyborniku
przycisk Więcej
formantów

przycisk Więcej formantów

Wyświetlone zostanie okno dialogowe Wstawianie formantu ActiveX. Wybierz formant, który chcesz dodać do formularza, i
kliknij przycisk OK. (rysunek 9.3). Okno dialogowe zostanie zamknięte. Na formularzu kliknij miejsce, w którym chcesz
umieścić formant.

Rysunek 9.3.
Wybierz formant
ActiveX, który chcesz
dodać do formularza

Po wstawieniu formantu Access zachowuje odniesienie do właściwej dla niego biblioteki. Aby wyświetlić wszystkie
odniesienia w aplikacji, otwórz edytor Visual Basic i z menu Tools wybierz pozycję References (rysunek 9.4).
Rysunek 9.4.
Formanty ActiveX
wyświetlone
w oknie
dialogowym
References

Ustawianie właściwości formantu ActiveX


Formanty ActiveX posiadają arkusz właściwości identyczny jak wbudowane formanty Accessa. Mają również stronę z
właściwościami przypominającą arkusz właściwości formularza, co znacznie ułatwia ustawianie właściwości. Aby
otworzyć stronę z właściwościami formantu ActiveX, kliknij go prawym klawiszem myszy i z menu kontekstowego
wybierz pozycję Obiekt, a następnie Properties (rysunek 9.5).

Rysunek 9.5.
Strona
z właściwościami
formantu
ImageList
141 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Pisanie kodu umożliwiającego wykonywanie metod


i reagowanie na zdarzenia
W przypadku formantów ActiveX pisanie kodu umożliwiającego wykonywanie metod i reagowanie na zdarzenia nie różni
się niczym od pisania kodu dla wbudowanych formantów Accessa.

Aby uzyskać informacje o właściwościach, metodach i zdarzeniach związanych z formantem, skorzystaj z narzędzia Object
Browser (rysunek 9.6).
Rysunek 9.6.
Korzystaj z narzędzia
Object Browser,
by uzyskać
informacje
o właściwościach,
metodach
i zdarzeniach
związanych
z formantem

21 formantów ActiveX
Teraz omówimy 21 formantów ActiveX. Można by oczywiście wiele napisać o wszystkich formantach ActiveX (których są
setki), ale niektóre z nich dostarczane są przez firmę Microsoft.

W znajdującej się na dołączonym do książki CD-ROM-ie aplika-


cji znajdziesz przykłady kodu użyte we wszystkich z 21 for-
mantów ActiveX.

Tabela 9.1 zawiera nazwę formantu, nazwę jego pliku i opis.

Tabela 9.1.
Przegląd formantów ActiveX

Formant ActiveX Nazwa pliku Opis


Animation MSCOMCT2.OCX Odtwarza w formularzu pliki video (AVI)
Calendar Wyświetla w formularzu kalendarz
Common Dialog COMDLG32.OCX Wyświetla okna dialogowe Otwórz, Zapisz jako, Kolor,
Czcionka, Drukuj i Pomoc
DateTimePicker MSCOMCT2.OCX Rozwijany kalendarz, który umożliwia użytkownikom
wprowadzanie dat
FlatScrollBar MSCOMCT2.OCX Płaski pasek przewijania

Tabela 9.1.
Przegląd formantów ActiveX (ciąg dalszy)

Formant ActiveX Nazwa pliku Opis


ImageCombo MSCOMCTL.OCX Pole kombi zawierające rysunki związane z obiektami
na liście
Część III ♦ Interfejs użytkownika 142

ImageList MSCOMCTL.OCX Zawiera bitmapy i obrazki, które mogą być używane przez
inne formanty
ListView MSCOMCTL.OCX Przedstawia dane na liście na cztery różne sposoby
MAPIMessages MSMAPI32.OCX Wysyła i odbiera wiadomości, wyświetla książki adresowe
i inne opcje związane z pocztą
MAPISession MSMAPI32.OCX Umożliwia rozpoczęcie i zamknięcie sesji MAPI
MonthViev MSCOMCT2.OCX Interfejs w formie kalendarza, umożliwiający przeglądanie
i wybieranie informacji o datach
ProgressBar MSCOMCTL.OCX Wyświetla informacje o stanie zaawansowania
danego procesu
RichText RICHTX32.OCX Umożliwia formatowanie tekstu w polach tekstowych
(zmianę rodzaju czcionki, jej koloru, rozmiaru i inne)
Slider MSCOMCTL.OCX Poziomy i pionowy suwak
StatusBar MSCOMCTL.OCX Umieszcza na formularzu pasek stanu
SysInfo SYSINFO.OCX Odbiera i wysyła informacje o systemie
TabStrip MSCOMCTL.OCX Rozmieszcza zakładki w rzędach i wyświetla na nich
rysunki
ToolBar MSCOMCTL.OCX Umieszcza na formularzu pasek narzędzi
TreeView MSCOMCTL.OCX Wyświetla dane w formacie hierarchicznym
UpDown MSCOMTC2.OCX Umożliwia użytkownikom zwiększanie i zmniejszanie
wartości innego formantu
WebBrowser SHDOCVW.DLL Wyświetla na formularzu przeglądarkę WWW

Znajdujący się na płycie CD-ROM kod dla tego rozdziału zawiera


przykłady każdego z tych formantów.

Formant Animation
Formant ten umożliwia odtwarzanie na formularzu Accessa plików wideo (.AVI) (rysunek 9.7).

Tabela 9.2 zawiera najczęściej używane właściwości i metody dla formantu Animation.
Rysunek 9.7.
Przykład formantu
Animation

Formant Animation nie obsługuje wszystkich plików typu AVI. Przykłado-


wo, formant ten nie współpracuje z plikami AVI zawierającymi dźwięk.
Ponadto plik AVI nie powinien być kompresowany. Jedynym wyjątkiem są
pliki kompresowane przy użyciu kompresji Run-Length.

Tabela 9.2.
Właściwości i metody dla formantu Animation

Obiekt Opis
143 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Właściwość AutoPlay Jeśli właściwość ta jest ustawiona na True, plik AVI odtwarzany jest w pętli od
momentu jego załadowania do formantu. Przy ustawieniu False plik nie jest
odtwarzany aż do wywołania metody Play
Metoda Close Zamyka otwarty plik AVI
Metoda Open Otwiera plik AVI
Metoda Play Odtwarza załadowany do formantu plik AVI
Metoda Stop Zatrzymuje rozpoczęte za pomocą metody Play odtwarzanie pliku AVI

Formant Calendar
Formant Calendar wyświetla w formularzu Accessa kalendarz (rysunek 9.8).

Formant Calendar przydaje się do ustawiania i pobierania wartości daty. W zależności od ustawienia, może on zawierać
dzień, miesiąc i rok. Tabela 9.3 zawiera najczęściej używane właściwości, metody i zdarzenia dla formantu Calendar.

Formant Common Dialog


Dzięki użyciu formantu Common Dialog można z łatwością wyświetlać typowe okna dialogowe systemu Windows –
Otwórz, Zapisz jako, Kolor, Czcionka, Drukuj i Pomoc (rysunek 9.9).
Rysunek 9.8.
Przykład formantu
Calendar

Tabela 9.3.
Właściwości, metody i zdarzenia dla formantu Calendar

Obiekt Opis
Właściwość Day Ustawia dzień miesiąca (1–31)
Właściwość Month Ustawia miesiąc
Właściwość ShowDateSelectors Wyświetla rozwijane pole listy selektora daty
Właściwość Value Ustawia lub pobiera wybraną datę
Właściwość Year Ustawia rok
Metoda NextDay Wyświetla następny dzień
Metoda PreviousDay Wyświetla poprzedni dzień
Metoda Today Wyświetla dzisiejszą datę
Zdarzenie Click Występuje, gdy użytkownik kliknie datę
Część III ♦ Interfejs użytkownika 144

Rysunek 9.9.
Przykład formantu
Common Dialog

Formant ten związany jest z procesem projektowania. Wystarczy wstawić formant do formularza i przywołać metodę
wyświetlającą żądane okno dialogowe. Poniższy kod powoduje wyświetlenie okna dialogowego Kolor:
Me.ActiveXCommonDialogControl.ShowColor

Tabela 9.4 zawiera najczęściej używane właściwości i metody dla formantu Common Dialog.

Tabela 9.4.
Właściwości i metody dla formantu Common Dialog

Obiekt Opis
Właściwość Color Pobiera kolor wybrany w oknach dialogowych Kolor i Czcionka
Właściwość Copies Ilość kopii do wydrukowania z okna dialogowego Drukuj
Właściwość Filter Określa typ lub nazwę pliku dla okien dialogowych Otwórz i Zapisz jako
Właściwość FontName Czcionka wybrana w oknie dialogowym Czcionka
Właściwość FontSize Rozmiar czcionki wybrany w oknie dialogowym Czcionka
Właściwość Orientation Orientacja strony (pionowa lub pozioma) z okna dialogowego Drukuj
Metoda ShowColor Wyświetla okno dialogowe Kolor
Metoda ShowFont Wyświetla okno dialogowe Czcionka
Metoda ShowHelp Wyświetla Pomoc
Metoda ShowOpen Wyświetla okno dialogowe Otwórz
Metoda ShowPrinter Wyświetla okno dialogowe Drukuj
Metoda ShowSave Wyświetla okno dialogowe Zapisz jako

Formant DateTimePicker
Formant DateTimePicker umożliwia wyświetlenie rozwijanego kalendarza, który ułatwia użytkownikom wprowadzanie
dat w formularzu (rysunek 9.10). Przypomina on formant daty programu Outlook, używany do planowania zajęć.

Rysunek 9.10.
Przykład formantu
DateTimePicker

Powyższy przykład przedstawia rozwijany kalendarz służący do wybierania daty. Użytkownik ma również możliwość
zmiany wprowadzonej w tym formancie daty przy użyciu klawiszy strzałek (góra – dół). Przykładowo, gdy wprowadzono
datę 7/15/99, gdzie 7 oznacza miesiąc, 15 – dzień, a 99 – rok, za pomocą klawiszy strzałek można te wartości
zmodyfikować.
145 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Wygląd rozwijanego kalendarza może być zmieniany przy użyciu różnych


zestawów kolorów (patrz właściwości w tabeli 9.5).

Tabela 9.5 zawiera najczęściej używane właściwości dla formantu DateTimePicker.

Tabela 9.5.
Właściwości formantu DateTimePicker

Obiekt Opis
Właściwość CalendarBackColor Ustawia bądź pobiera kolor tła rozwijanego kalendarza
Właściwość CalendarForeColor Ustawia bądź pobiera kolor pierwszego planu kalendarza
rozwijanego
Właściwość CalendarTitleBackColor Ustawia bądź pobiera kolor tła tytułu rozwijanego
kalendarza
Właściwość CalendarTitleForeColor Ustawia bądź pobiera kolor pierwszego planu tytułu
rozwijanego kalendarza
Właściwość CalendartrailingForeColor Ustawia bądź pobiera kolor pierwszego planu dat
w rozwijanym kalendarzu
Właściwość Checkbox Umieszcza w formancie pola wyboru
Właściwości Day, Month i Year Zwraca wybraną wartość
Właściwość DayOfWeek Zwraca dzień tygodnia
Właściwość Format Wyświetla datę długą, datę krótką, czas i inne formanty
Właściwości MinDate i MaxDate Określa zakres daty
Właściwości Second, Minute i Hour Zwraca wybrane właściwości
Właściwość Value Ustawia bądź pobiera wybraną datę/godzinę

Formant FlatScrollBar
Oto nowa wersja suwaka o płaskim wyglądzie (rysunek 9.11). Poprzez zmianę właściwości Orientation możesz wybrać
suwak poziomy lub pionowy.

Rysunek 9.11.
Przykład formantu
FlatScrollBar

Tabela 9.6 zawiera najczęściej używane właściwości formantu FlatScrollBar.

Tabela 9.6.
Właściwości formantu FlatScrollBar

Obiekt Opis
Właściwość Appearance Ustawia bądź pobiera wygląd suwaka. Suwak może być dwu- lub
trójwymiarowy
Właściwość Orientation Ustawia bądź pobiera położenie (poziome lub pionowe) suwaka

Formant ImageCombo
Formant ImageCombo przypomina zwykłe pole listy rozwijalnej, z tą różnicą, że pozycjom na liście można
przyporządkować rysunki (rysunek 9.12). To ułatwia użytkownikom korzystanie z listy.
Część III ♦ Interfejs użytkownika 146

Rysunek 9.12.
Przykład formantu
ImageCombo

Do umieszczenia rysunków w formancie ImageCombo używany jest formant ImageList. Rysunek może być umieszczony
obok tekstu na liście lub w części edycyjnej pola listy. Aby programowo dodawać obiekty do formantu ImageCombo, użyj
metody Add w następujący sposób:
With ctlImageCombo.ComboItems
' Add Index, ItemNames, ListBox Display Name, Image Key Name.
.Add 1, "Cloudy", "Cloudy", "Cloudy"
.Add 2, "Rainy", "Rainy", "Rainy"
.Add 3, "Snowing", "Snowing", "Snowing"
.Add 4, "Sunny", "Sunny", "Sunny"
.Add 5, "Lightning", "Lightning", "Lightning"
End With

Tabela 9.7 zawiera najczęściej używane właściwości, metody i zdarzenia dla formantu ImageCombo.

Tabela 9.7.
Właściwości, metody i zdarzenia dla formantu ImageCombo

Obiekt Opis
Obiekt Collection Zbiór ComboItems (obiektów listy rozwijalnej)
Obiekt Individual Obiekt ComboItem jest obiektem na liście
Właściwość ComboItems Pobiera odnośnik do zbioru ComboItems

Tabela 9.7.
Właściwości, metody i zdarzenia dla formantu ImageCombo (ciąg dalszy)

Obiekt Opis
Właściwość ImageList Przyporządkowuje formant ImageList do ImageCombo
Właściwość Indentation Ustawia bądź pobiera szerokość wcięć (każde wcięcie wynosi
10 pikseli)
Właściwość SelectedItem Wybrany obiekt z listy
Metoda Add Programowe dodawanie obiektów do ImageCombo
Zdarzenie DropDown Występuje po rozwinięciu listy formantu

Formant ImageList
Formant ImageList należy do grupy formantów związanych z procesem projektowania. Jest on niewidoczny dla
ostatecznego użytkownika.

Formant ten służy do przechowywania plików rysunków. Możesz przechowywać wiele typów rysunków: bitmapy (.BMP),
ikony (.ICO), pliki typu .GIF, .DIB, .CUR i .JPG. Z rysunków przechowywanych w formancie ImageList mogą później
korzystać inne formanty. W ten sposób działają omówione w tym rozdziale formanty ActiveX ImageCombo, ListView i
Toolbar.

Dzięki stronie z właściwościami formantu ImageList (rysunek 9.13) dodawanie rysunków jest dość proste. Pamiętaj, że
rysunki dodawane do formantu ImageList muszą być tego samego rozmiaru. Jeśli chcesz korzystać z rysunków o różnych
rozmiarach, musisz użyć kilku formantów ImageList.
147 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Rysunek 9.13.
Strona
z właściwościami
formantu ImageList

Rysunkom dodawanym do formantu ImageList zawsze przyznawane są numery indeksu. Nie powinieneś się na nich
opierać. Zamiast tego, zawsze wprowadzaj wartość Key (wartość klucza) dla każdego rysunku.

Po usunięciu obiektów z formantu ImageList wartości indeksu ulegają


zmianie, więc nie możesz się na nich opierać. Zawsze korzystaj z uni-
katowych wartości klucza i używaj ich przy tworzeniu odniesień do ry-
sunków w kodzie.

Nie przesadzaj z użyciem rysunków w aplikacjach. Formant ImageList


pochłania dużą część pamięci komputera i użycie większej ilości rysunków
może spowodować zmniejszenie wydajności aplikacji. Po otwarciu
formularza zawierającego ten formant wszystkie rysunki przechowywane
są w pamięci.

Tabela 9.8 zawiera najczęściej używane właściwości, metody i zdarzenia dla formantu ImageList.

Tabela 9.8.
Właściwości, metody i zdarzenia dla formantu ImageList

Obiekt Opis
Obiekt Collection Zbiór ListImages
Obiekt Individual Obiekt ListImage jest rysunkiem w formancie
Właściwość Index Unikatowa wartość indeksu dla każdego rysunku
Właściwość Key Wartość tekstowa przyporządkowana rysunkowi
Właściwość ImageCount Aktualna liczba rysunków w formancie ImageList
Metoda Overlay Nadpisywanie jednego rysunku na drugim
Add (dodaj) rysunki Używana w kodzie metoda Add dla zbioru ListImages

Przykład wykorzystania rysunków w formularzu przy użyciu formantu ImageList przedstawiony jest na rysunku 9.14.
Formant ListView może korzystać z rysunków tylko dzięki formantowi ImageList.

Po związaniu formantu ImageList z innym formantem nie możesz do nie-


go dodawać nowych rysunków. Przed umieszczeniem formantu na for-
mularzu upewnij się, że dodałeś wszystkie zaplanowane rysunki. Jeśli
będziesz chciał dodać rysunki do formantu ImageList po związaniu go z
innym formantem, najpierw będziesz musiał je rozłączyć.

Formant ListView
Formant ListView wyświetla listę obiektów na cztery różne sposoby. Jako przykład może posłużyć prawe okno
Eksploratora Windows, w którym użytkownicy mogą przeglądać pliki w formatach Duże ikony, Małe ikony, Lista i
Szczegóły.
Część III ♦ Interfejs użytkownika 148

W formularzach Accessa listy z danymi mogą być wyświetlane w podobny sposób dzięki formantowi ListView (rysunek
9.14). Obiekty na liście mogą być umieszczone z nagłówkami kolumn lub bez nich. Formant ten jest bardzo elastyczny i
umożliwia przeglądanie danych na wiele różnych sposobów.

Rysunek 9.14.
Przykład formantu
ListView

Tabela 9.9 zawiera najczęściej używane obiekty i właściwości formantu ListView.

Tabela 9.9.
Obiekty i właściwości formantu ListView

Obiekt Opis
Obiekt Collection Zbiór ListItems
Obiekt Individual Obiekt ListItem jest obiektem na liście
Obiekt Collection Zbiór ColumnHeaders
Obiekt Individual Obiekt ColumnHeader, tekst nagłówka kolumny
Właściwość AllowColumnReorder Zmienia układ kolumn
Właściwość Arrange Rozmieszcza ikony w formancie
Właściwość ColumnHeaders Tworzy odniesienie zbioru do obiektów ColumnHeader
Właściwość FullRowSelect Wybór całego wiersza
Właściwość GridLines Wyświetla linie siatki w widoku Szczegóły
Właściwość HideColumnHeaders Ukrywa i odkrywa nagłówki kolumn w widoku Szczegóły
Właściwość LabelEdit Umożliwia użytkownikom edytowanie etykiet
Właściwość LabelWrap Zawija etykiety obiektów ListItems
Właściwość MultiSelect Umożliwia użytkownikom zaznaczanie kilku obiektów
Właściwość SelectedItem Określa wybrany ListItem

Tabela 9.9.
Obiekty i właściwości formantu ListView (ciąg dalszy)

Obiekt Opis
Właściwość Sorted Określa, czy obiekty w zbiorze mają być sortowane
Właściwość SortKey Określa, czy obiekty mają być sortowane według właściwości
ListItem Text, czy według indeksu zbioru SubItems

Właściwość SortOrder Sortowanie rosnąco i malejąco


Właściwość SubItems Tablica ciągów wyświetlana w widoku Szczegóły
Właściwość View Ustawia wygląd obiektów: Duże ikony, Małe ikony, Lista
i Szczegóły
149 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Użycie formantu ListView w połączeniu z formantem TreeView znacznie


zwiększa funkcjonalność interfejsu Eksploratora Windows. Jest to bardzo
dobry sposób na przeglądanie danych, gdyż większość użytkowników
miała już okazję poznać ten interfejs.

Formant MAPISession
Interfejs MAPI (ang. Messaging Application Programming Interface) nadzoruje korzystające z poczty aplikacje Accessa.
Formant MAPISession umożliwia rozpoczęcie i zamknięcie sesji MAPI (rysunek 9.15).

Rysunek 9.15.
Przykład formantu
MAPISession

Aby formanty MAPI funkcjonowały poprawnie, konieczne jest zainstalo-


wanie na komputerze usługi MAPI oraz zgodnego z nią systemu poczty
elektronicznej (na przykład Microsoft Exchange).

Formant MAPISession związany używany jest w procesie projektowania i nie są z nim związane żadne zdarzenia.

Tabela 9.10 zawiera najczęściej używane właściwości i metody dla formantu MAPISession.

Tabela 9.10.
Właściwości i metody dla formantu MAPISession

Obiekt Opis
Właściwość DownloadMail Pobiera nowe wiadomości
Właściwość LogonUI Wyświetla okno dialogowe logowania
Właściwość NewSession Tworzy nową sesję pocztową
Właściwość Password Hasło związane z właściwością UserName
Właściwość SessionID Identyfikator aktualnej sesji pocztowej
Właściwość UserName Profil używany do tworzenia nowej sesji pocztowej
Metoda SignOff Wylogowanie użytkownika i zakończenie sesji pocztowej
Metoda SignOn Zalogowanie użytkownika do sesji pocztowej

Formant MAPIMessages
Po otwarciu sesji przez użytkownika za pomocą formantu MAPISession w celu tworzenia nowych wiadomości i
przeglądania starych, wysyłania z załącznikami lub bez, odpowiadania na wiadomości, wyświetlania książek adresowych i
innych czynności można korzystać z formantu MAPIMessages. Przykład wykorzystania tego formantu znajduje się na
rysunku 9.15.

Tabela 9.11 zawiera najczęściej używane właściwości i metody dla formantu MAPIMessages.

Tabela 9.11.
Właściwości i metody dla formantu MAPIMessages

Obiekt Opis
Właściwość AttachmentName Nazwa pliku załącznika
Właściwość MsgCount Ilość wiadomości w zbiorze
Część III ♦ Interfejs użytkownika 150

Właściwość MsgDateReceived Data otrzymania wiadomości


Właściwość MsgID Identyfikator wiadomości
Właściwość MsgNoteText Tekst wiadomości
Właściwość MsgRead Określa, czy wiadomość została przeczytana
Właściwość MsgSent Określa, czy wiadomość została wysłana
Właściwość MsgSubject Temat wiadomości
Właściwość RecipAdress E-mailowy adres odbiorcy
Metoda Compose Pisanie wiadomości
Metoda Copy Kopiowanie wiadomości

Tabela 9.11.
Właściwości i metody dla formantu MAPIMessages (ciąg dalszy)

Obiekt Opis
Metoda Delete Usuwanie wiadomości
Metoda Fetch Tworzenie zbioru z wybranych wiadomości
Metoda Forward Przesyłanie wiadomości dalej
Metoda Reply Odpowiadanie na wiadomość
Metoda Save Zapisywanie wiadomości
Metoda Send Wysyłanie wiadomości

Formant MonthView
Formant ten daje użytkownikom możliwość przeglądania i wybierania dat za pomocą kalendarzowego interfejsu (rysunek
9.16). Ilość wyświetlanych miesięcy i kolorystyka formantu mogą być dowolnie modyfikowane.

Rysunek 9.16.
Przykład formantu
MonthView

Użytkownicy mają możliwość wybierania pojedynczych dat lub zaznaczania ich blokowo przy użyciu właściwości
MultiSelect.

Tabela 9.12 zawiera najczęściej używane właściwości i zdarzenia dla formantu MonthView.

Tabela 9.12.
Właściwości i zdarzenia dla formantu MonthView

Obiekt Opis
Właściwość DayOfWeek Określa dzień tygodnia
Właściwość MinDate/MaxDate Zakres dat wyświetlanych w formancie

Tabela 9.12.
151 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Właściwości i zdarzenia dla formantu MonthView (ciąg dalszy)

Obiekt Opis
Właściwość MaxSelCount Maksymalna możliwa ilość dat do zaznaczenia
Właściwość MonthBackColor Określa kolor tła miesiąca
Właściwość MonthColumns Ilość wyświetlanych kolumn miesięcznych
Właściwość MonthRows Ilość wyświetlanych wierszy miesięcznych
Właściwość MultiSelect Umożliwia zaznaczanie kilku dat jednocześnie
Właściwość SelStart/SelEnd Dolna i górna granica zaznaczenia
Właściwość ShowToday Umożliwia użytkownikowi powrót do dzisiejszej daty
Właściwość StartOfWeek W skrajnej lewej kolumnie wyświetla dzień tygodnia
Właściwość Value Aktualnie wybrana data
Zdarzenie DateClick Kliknięcie daty w formancie
Zdarzenie DateDblClick Dwukrotne kliknięcie daty w formancie
Zdarzenie SelChange Występuje przy nowym wybraniu daty

Formant ProgressBar
Ważne jest, by w przypadku dłuższych procesów informować użytkownika o jego przebiegu. W przeciwnym razie
użytkownik może uznać, że komputer się zawiesił, i zamknąć aplikację. Może to doprowadzić do błędów w programie,
utraty danych i tym podobnych problemów.

Formant ProgressBar dostarcza użytkownikowi informacji o tym, że komputer jest zajęty i określa w przybliżeniu czas,
w jakim proces zostanie zakończony (rysunek 9.17). Możesz dostosowywać wygląd tego formantu, zmieniając jego
położenie oraz minimalne i maksymalne wartości. Umożliwia to zmianę długości paska stanu w zależności od czasu
trwania procesu.

Rysunek 9.17.
Przykład formantu
ProgressBar

Wizualne informowanie użytkownika o przebiegu dłuższego procesu


sprawia, iż wydaje się on być krótszy niż jest w rzeczywistości.

W przypadku długich procesów powinieneś już na początku w części wy-


pełnić formant. Nie jest to być może zbyt uczciwe, bo nie odzwierciedla
rzeczywistego postępu procesu. Jednakże w sytuacji, w której mija
dłuższy czas, zanim wypełni się choćby pierwsza część paska postępu,
może się zdarzyć, że użytkownik wyłączy komputer myśląc, że się
zawiesił.

Tabela 9.13 zawiera najczęściej używane właściwości formantu ProgressBar.

Tabela 9.13.
Właściwości formantu ProgressBar

Obiekt Opis
Właściwość Min/Max Minimalne i maksymalne wartości formantu
Właściwość Orientation Położenie (poziome i pionowe) formantu
Właściwość Scrolling Określa, czy postęp jest wyświetlany skokowo, czy w sposób łagodny
Zdarzenie Value Wartość formantu. Gdy wartość jest zwiększana, postęp wyświetlany
f i t
Część III ♦ Interfejs użytkownika 152

w formancie wzrasta

Formant RichText
Formant RichText dostarcza użytkownikowi zaawansowanych możliwości formatowania tekstu. W przeciwieństwie do
standardowych pól tekstowych formant ten umożliwia stosowanie różnych czcionek i kolorów (rysunek 9.18).

Rysunek 9.18.
Przykład formantu
RichText

Możliwości formantu RichText są następujące:


u Łączenie czcionek, stylów, rozmiarów i kolorów.
u Indeksy dolne i górne.
u Formatowanie akapitów.
u Możliwość pracy z dużymi plikami tekstowymi.
u Zdolność dołączania do pola typu memo w Accessie.
u Możliwość dołączania plików graficznych, ikon i dokumentów.

Tabela 9.14 zawiera najczęściej używane właściwości, metody i zdarzenia dla formantu RichText.

Tabela 9.14.
Właściwości, metody i zdarzenia dla formantu RichText

Obiekt Opis
Właściwość BulletIndent Ustawia bądź pobiera wielkość akapitu
Właściwość FileName Nazwa pliku załadowanego do formantu
Właściwość MaxLength Maksymalna ilość znaków w formancie
Właściwość MultiLine Umożliwia pisanie tekstu w więcej niż jednej linii
Właściwość RightMargin Określa prawy margines
Właściwość ScrollBars Wyświetla poziomy i pionowy pasek przewijania
Właściwość SelAlignment Określa wyrównanie zaznaczonych paragrafów
Właściwości SelBold, SelItalics, Formatuje zaznaczony tekst
SelStrikeThru, SelUnderline

Właściwość SelColor Określa kolor zaznaczonego tekstu


Metoda Find Przegląda formant w poszukiwaniu określonego tekstu
Metoda LoadFile Ładuje do formantu plik tekstowy lub plik .RTF
Metoda SaveFile Zapisuje plik zawarty w formancie
Metoda SelPrint Drukuje zaznaczony tekst
Metode SelChange Występuje, gdy zmianie ulegnie zaznaczenie tekstu lub pozycja
znaku wprowadzania

Formant Slider
Formant Slider może być wykorzystany do wprowadzania lub wyświetlania danych na skali ciągłej (rysunek 9.19).
Modyfikować można przedział zmiany, właściwości ruchu i położenie (poziome i pionowe).
153 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Rysunek 9.19.
Przykład formantu
Slider

Tabela 9.15 zawiera najczęściej używane właściwości, metody i zdarzenia dla formantu Slider.

Tabela 9.15.
Właściwości, metody i zdarzenia dla formantu Slider

Obiekt Opis
Właściwość LargeChange Określa skok suwaka po naciśnięciu klawiszy Page Up i Page Down
oraz kliknięciu jednego z końców suwaka
Właściwośc SmallChange Określa skok suwaka po naciśnięciu klawiszy strzałek (lewo–prawo)
Właściwość Min/Max Minimalna i maksymalna wartość formantu
Właściwość Orientation Położenie formantu (poziome i pionowe)
Właściwość SelectRange Określenie wielkości zaznaczenia
Właściwość Value Aktualna wartość formantu
Metoda ClearSel Usuwa aktualne zaznaczenie formantu
Metoda GetNumTicks Pobiera ilość skoków suwaka pomiędzy wartościami Min i Max
Zdarzenie Scroll Występuje przy ruchu suwaka

Formant StatusBar
Formant ten (pasek stanu) jest wykorzystywany w wielu aplikacjach (np. Word i Excel). Dostarcza on użytkownikowi
wielu informacji (rysunek 9.20).

Rysunek 9.20.
Przykład formantu
StatusBar

Korzystając z właściwości Align, możesz umieścić formant StatusBar w


różnych miejscach formularza (u góry, u dołu, po lewej bądź prawej stro-
nie). Aby być w zgodzie z innymi aplikacjami systemu Windows, na-
leżałoby umieścić pasek stanu u dołu formularza.

Formant StatusBar zawiera obiekty Panel i zbiór Panels, które mogą być użyte do programowego wykonywania
czynności. Przykładowo, jeśli użytkownik kliknie określony panel, wykonana zostanie dana czynność.

Tabela 9.16 zawiera najczęściej używane obiekty, metody i zdarzenia dla formantu StatusBar.

Tabela 9.16.
Obiekty, metody i zdarzenia dla formantu StatusBar

Obiekt Opis
Obiekt Collection Zbiór Panels
Obiekt Individual Obiekt Panel jest obiektem na liście
Część III ♦ Interfejs użytkownika 154

Właściwość Align Określa położenie formantu na formularzu (u góry, u dołu, z lewej lub
prawej strony)
Właściwość SimpleText Ustawia bądź pobiera tekst z formantu, gdy właściwość Style ustawiona
jest na Simple
Właściwość Style Ustawia właściwość stylu, by wyświetlać jedne lub wszystkie panele
Zdarzenie PanelClick Występuje, gdy użytkownik kliknie panel
Zdarzenie PanelDblClick Występuje, gdy użytkownik dwukrotnie kliknie panel

Formant SysInfo
Formant ten umożliwia otrzymywanie informacji o systemie i reagowanie na nie (rysunek 9.21). Może on służyć od
kontrolowania następujących informacji systemowych:
u System operacyjny, jego wersja i numer edycji.
u Zdarzenia na pulpicie, wielkość monitora i zmiany rozdzielczości.
u Zdarzenia związane z Plug and Play.
u Właściwości i zdarzenia związane z zarządzaniem energią.

Rysunek 9.21.
Przykład formantu
SysInfo

Tabela 9.17 zawiera najczęściej używane obiekty, metody i zdarzenia dla formantu SysInfo.

Tabela 9.17.
Obiekty, metody i zdarzenia dla formantu SysInfo

Obiekt Opis
Właściwość ACStatus Wykrywa użycie zasilania prądem zmiennym
Właściwość BatteryFullTime Gdy bateria jest w pełni naładowana, określa jej żywotność
w sekundach

Tabela 9.17.
Obiekty, metody i zdarzenia dla formantu SysInfo (ciąg dalszy)

Obiekt Opis
Właściwość BatteryLifePercent Żywotność baterii w procentach
Właściwość BatteryLifeTime Zwraca ilość sekund pozostałej żywotności baterii
Właściwość BatteryStatus Stan baterii (niski, średni, wysoki, ładowanie)
Właściwość OSBuild Numer wersji systemu operacyjnego
Właściwość OSPlatform System operacyjny (Windows 95, Windows NT)
Właściwość OSVersion Numer edycji systemu operacyjnego
Zdarzenie ConfigChange Występuje w przypadku zmiany profilu sprzętowego
Zdarzenie DeviceArrival Występuje w przypadku dodania do systemu nowego sprzętu
Zdarzenie PowerStatusChanged Występuje w przypadku zmiany stanu zasilania
Zdarzenie PowerSuspend Występuje przed wstrzymaniem pracy komputera
Zdarzenie TimeChanged Występuje w przypadku zmiany ustawienia zegara systemowego
155 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Formant TabStrip
Formant TabStrip przydaje się w sytuacji, gdy pojawia się konieczność umieszczenia wielu formantów na jednym
formularzu (rysunek 9.22). Przy jego użyciu formanty mogą być rozmieszczone na różnych zakładkach. Wygląd i położenie
formantów na zakładkach może być modyfikowane.

Rysunek 9.22.
Przykład formantu
TabStrip

Tabela 9.18 zawiera najczęściej używane obiekty, właściwości, metody i zdarzenia dla formantu TabStrip.

Tabela 9.18.
Obiekty, właściwości, metody i zdarzenia dla formantu TabStrip

Obiekt Opis
Obiekt Collection Zbiór Tabs
Obiekt Individual Obiekt Tab – pojedyncza zakładka
Właściwości ClientHeight, Zwraca współrzędne obszaru wyświetlania formantu
ClientWidth, ClientLeft,
ClientRight

Właściwość ImageList Przyporządkowuje formant ImageList


Właściwość MultiSelect Umożliwia wybór kilku obiektów jednocześnie
Właściwość Placement Umieszcza zakładki u góry, u dołu, po lewej lub po prawej stronie
Właściwość SelectedItem Określa wybraną zakładkę
Właściwość Style Modyfikuje wygląd zakładek (przyciski zwykłe bądź płaskie)
Metoda DeselectAll Usuwa zaznaczenie zakładek
Obiekt Click Występuje po kliknięciu zakładki

Formant Toolbar
Dzięki temu formantowi możesz utworzyć pasek narzędzi dla aplikacji Accessa. Oddaje on do rąk użytkowników graficzny
interfejs, zawierający najczęściej używane obiekty menu (rysunek 9.23).

Rysunek 9.23.
Przykład formantu
Toolbar

Formant Toolbar zawiera obiekty Button (przycisk) i zbiór Buttons. Przyciski mogą być programowo dodawane i
usuwane z formularza. Istnieje również możliwość napisania kodu, który będzie reagował na zdarzenia (najczęściej na
zdarzenie ButtonClick).

Tabela 9.19 zawiera najczęściej używane obiekty, właściwości, metody i zdarzenia dla formantu Toolbar.
Część III ♦ Interfejs użytkownika 156

Tabela 9.19.
Obiekty, właściwości, metody i zdarzenia dla formantu Toolbar

Obiekt Opis
Obiekt Collection Zbiór Buttons

Tabela 9.19.
Obiekty, właściwości, metody i zdarzenia dla formantu Toolbar (ciąg dalszy)

Obiekt Opis
Obiekt Individual Obiekt Button – pojedynczy przycisk
Obiekt Collection Zbiór ButtonMenus
Obiekt Individual Obiekt ButtonMenu – rozwijana lista obiektu Button
Właściwość Align Wyświetla formant u góry, u dołu, po lewej lub po prawej stronie
formularza
Właściwość AllowCustomize Umożliwia użytkownikowi dostosowywanie formantu
Właściwość BorderStyle Określa wygląd ramki formantu
Właściwości ButtonHeight, Wysokość i szerokość znajdujących się na pasku narzędzi
ButtonWidth przycisków
Właściwość ImageList Przyporządkowuje formant ImageControl
Właściwość Style Określa styl formularza (zwykły, transparentny lub tekst na prawo
od rysunku)
Metoda Customize Umożliwia użytkownikowi dostosowywanie paska narzędzi
Metoda RestoreToolbar Przywraca początkowy stan paska narzędzi
Obiekt ButtonClick Występuje po naciśnięciu przycisku
Obiekt ButtonMenuClick Występuje po naciśnięciu przycisku w menu

Formant TreeView
Formant TreeView wyświetla hierarchiczną listę – taką, jaka znajduje się w lewym ok.nie Eksploratora Windows. W
Eksploratorze hierarchiczna lista folderów może być przeglądana na różne sposoby. Na rysunku 9.24 znajduje się przykład
użycia formantu TreeView w formularzu Accessa.

Rysunek 9.24.
Przykład formantu
TreeView

Formant TreeView zawiera obiekty Node (węzeł). Każdy obiekt Node zawiera tekst i rysunki. Po hierarchii formantu
można poruszać programowo, a także rozwijać i zwijać węzły.

Tabela 9.20 zawiera najczęściej używane obiekty, właściwości i zdarzenia dla formantu TreeView.

Tabela 9.20.
Obiekty, właściwości i zdarzenia dla formantu TreeView
157 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Obiekt Opis
Obiekt Collection Zbiór Nodes
Obiekt Individual Obiekt Node – obiekt w formancie TreeView
Właściwość Checkboxes Włącza pola wyboru w formancie
Właściwość Indentation Określa szerokość wcięcia
Właściwość LabelEdit Umożliwia użytkownikom edycję etykiet węzłów
Właściwość LineStyle Określa sposób wyświetlania linii między węzłami
Właściwość SelectedItem Zaznaczony węzeł
Właściwość Sorted Określa sposób sortowania węzła głównego i węzłów podrzędnych
Właściwość Style Określa wygląd każdego z węzłów (tekst, rysunki, plus – minus i linie)
Zdarzenie AfterLabelEdit Występuje, gdy użytkownik dokona edycji etykiety węzła
Zdarzenie Collapse Występuje, gdy węzeł zostanie zwinięty
Zdarzenie Expand Występuje, gdy węzeł zostanie rozwinięty
Zdarzenie NodeClick Występuje po kliknięciu węzła

Obiekt Node posiada własny zestaw przydatnych właściwości (Child,


FirstSibling, LastSibling, Previous, Parent, Next i Root).

Formant UpDown
Formant UpDown ułatwia użytkownikom zmianę wartości liczbowych za pomocą myszy. Składa się on z pary strzałek,
które użytkownik może klikać, by żądana wartość wzrosła bądź zmalała (rysunek 9.25).

Formant UpDown można bez trudu połączyć z innym formantem (np. polem tekstowym), za pomocą właściwości
BuddyControl. Nie ma konieczności pisania dodatkowego kodu. Dzięki użyciu właściwości BuddyControl dwa
formanty będą ze sobą współpracować. Gdy użytkownik kliknie jedną ze strzałek formantu UpDown, wartość w polu
tekstowym automatycznie się zmieni.
Rysunek 9.25.
Przykład formantu
UpDown

Tabela 9.21 zawiera najczęściej używane właściwości i zdarzenia dla formantu UpDown.

Tabela 9.21.
Właściwości i zdarzenia dla formantu UpDown

Obiekt Opis
Właściwość Alignment Umieszcza formant UpDown po lewej lub prawej stronie formantu
związanego
Właściwość AutoBuddy Określa, czy użyto właściwości BuddyControl do ustawienia
formantu związanego
Właściwość BuddyControl Określa nazwę formantu, który ma być formantem związanym
Właściwość BuddyProperty Określa właściwości, dzięki którym można zsynchronizować formant
UpDown z formantem związanym

Właściwość Increment Określa wielkość zmiany formantu


Właściwość Min/Max Minimalna i maksymalna wartość formantu
Właściwość Orientation Określa położenie formantu (poziome lub pionowe)
Właściwość SyncBuddy Określa, czy występuje synchronizacja właściwości Value formantu
f i
Część III ♦ Interfejs użytkownika 158

UpDown z formantem związanym

Właściwość Value Aktualna pozycja wartości przewijanej


Zdarzenie Change Występuje przy zmianie właściwości Value
Zdarzenie DownClick Występuje po naciśnięciu strzałki w dół lub w lewo
Zdarzenie UpClick Występuje po naciśnięciu strzałki w górę lub w prawo

Formant WebBrowser
Formant ten służy do umieszczania przeglądarki Microsoft Internet Explorer wewnątrz formularzy Accessa (rysunek 9.26).
Jaki jest tego cel, skoro większość użytkowników już posiada przeglądarkę na swoim komputerze?
u Przeglądarka ta jest udostępniana użytkownikom bez konieczności opuszczania Accessa.
u Ogranicza dostęp użytkownika do wybranych stron WWW. Kierownictwo niektórych firm zauważyło znaczną
utratę produktywności swoich pracowników, spowodowaną przeglądaniem stron WWW, niezwiązanych z ich
obowiązkami.
Rysunek 9.26.
Przykład formantu
WebBrowser

Dzięki formantowi WebBrowser można użytkownikom nadać dostęp do określonych stron lub uniemożliwić
dostęp do niektórych z nich.

Jeśli na Twoim komputerze zainstalowany jest Internet Explorer (w wersji 3


lub wyższej), zainstalowany jest również formant WebBrowser. Formant
ten nie może być rozpowszechniany osobno w aplikacjach. Musisz więc
sprawdzić, czy użytkownicy posiadają taką przeglądarkę lub przekazać im
całego Internet Explorer’a.

Tabela 9.22 zawiera najczęściej używane właściwości, metody i zdarzenia dla formantu WebBrowser.

Tabela 9.22.
Właściwości, metody i zdarzenia dla formantu WebBrowser

Obiekt Opis
Właściwość AdressBar Pokazuje pasek z adresem strony
Właściwość FullScreen Maksymalizuje okno
Właściwość LocationName Pobiera nazwę strony/pliku
Właściwość LocationURL Pobiera pełną ścieżkę dostępu do strony/pliku
Właściwość MenuBar Pokazuje pasek menu
Właściwość Type Pobiera typ dokumentu w formancie
Metoda GoBack Powrót do poprzedniej strony
Metoda GoForward Przejście do następnej strony
Metoda GoHome Przejście do strony początkowej
Metoda GoSearch Przejście do strony z wyszukiwarką
Metoda Navigate Odświeża aktualną stronę
Metoda Refresh Zatrzymuje otwieranie strony
159 Rozdział 9. ♦ Rozbudowa formularzy przy użyciu formantów ActiveX

Zdarzenie DownloadBegin Występuje po rozpoczęciu otwierania strony

Tabela 9.22.
Właściwości, metody i zdarzenia dla formantu WebBrowser (ciąg dalszy)

Obiekt Opis
Zdarzenie DownloadComplete Występuje po zakończeniu otwierania strony
Zdarzenie StatusChangeText Występuje po zmianie tekstu na pasku stanu
Zdarzenie TitleChange Występuje po zmianie tytułu dokumentu

Dystrybucja formantów ActiveX


Gdy przekazujesz użytkownikom aplikację Accessa, musisz do niej dołączyć wszystkie formanty ActiveX. W przeciwnym
razie aplikacja nie będzie działać prawidłowo. Każdy użyty formant ActiveX musi być poprawnie zainstalowany i
zarejestrowany przez użytkownika. Najłatwiejszym sposobem na udostępnianie formantów jest użycie narzędzia VBA
Package and Deployment Wizard.

Aby tego dokonać, z menu Add-Ins Edytora Visual Basic wybierz pozycję Add-In Manager. Zaznacz VBA Package and
Deployment Wizard. U dołu formularza zaznacz sposób, w jaki narzędzie ma zostać uruchomione, a następnie kliknij OK.
Kreator przeprowadzi Cię przez wszystkie kroki i pomoże utworzyć program instalacyjny dla Twojej aplikacji. Kreator ten
dołączy wszystkie wymagane formanty ActiveX i inne niezbędne pliki.

Po uruchomieniu tego programu przez ostatecznego użytkownika i zainstalowaniu na jego komputerze aplikacji wraz z
powiązanymi z nią plikami aplikacja będzie działać poprawnie. VBA Package and Deployment Wizard dokonuje również
odpowiednich zapisów w rejestrze systemowym komputera użytkownika.
Rozdział 10.
Tworzenie raportów
W tym rozdziale:
u Czym są raporty?
u Struktura raportów w Accessie.
u Tworzenie prostych raportów przy użyciu kreatora.
u Dostosowywanie raportów.
u Praca z podraportami.
u Tworzenie prostych etykiet adresowych.
u Publikowanie raportu.
u Modyfikowanie raportu podczas jego działania.
u Programowe tworzenie raportów.
u Wskazówki.

Po zakończeniu projektowania struktury danych w aplikacji i po stworzeniu formularzy, które ułatwią użytkownikom pracę
z danymi, nadszedł czas na stworzenie raportów. Raporty to najbardziej widoczna część aplikacji. Ludzie, którzy nigdy nie
zobaczą żadnego formularza i nie mają pojęcia, jak poradziłeś sobie z bezpieczeństwem i układem danych, będą oglądać
stworzone przez Ciebie raporty. Tak się składa, że dowiesz się, czy Twoja aplikacja jest dobra, jeśli będziesz często
proszony o nowe raporty lub modyfikacje już istniejących. Praca ta jest równie przyjemna co męcząca, jako że pośród
wszystkich obiektów w Accessie raporty stawiają przed programistami największe wyzwanie.

Czym są raporty?
W tym rozdziale podzielimy raporty na części składowe i omówimy działanie każdej z nich. Przyjrzymy się również kilku
sztuczkom, które sprawią, że nasze raporty z łatwością będą wykonywały z pozoru trudne zadania. W przypadku zadań,
których nie
można wykonać w prosty sposób, pokażemy, jak można modyfikować raport przy użyciu kodu VBA tak, by raport
wykonywał prawie każde Twoje polecenie. Zajmiemy się również raportami związanymi oraz niezwiązanymi, formantami
i podraportami.

Raporty powstały jako narzędzie do tworzenia wydruków. Dlatego też ich możliwości są do pewnego stopnia ograniczone.
W przeciwieństwie do formularzy raporty nie są interaktywne, tak więc po ich wydrukowaniu bądź przejściu do widoku
podgląd wydruku użytkownik nie ma możliwości zmiany wartości lub źródeł danych. Ostateczny wygląd raportu zależy od
sterownika drukarki, ponieważ to, co widzimy, musi być zgodne z parametrami drukarki i rodzajem użytego papieru.

Pomimo tych ograniczeń, raporty Accessa to bardzo elastyczne narzędzia do prezentacji danych. Kluczem do ujarzmienia
ich zdolności jest poznanie obiektu raport i wszystkich jego elementów. Najlepszym sposobem, by to osiągnąć, jest
przyjrzenie się im wszystkim z osobna.
161 Rozdział 10. ♦ Tworzenie raportów

Struktura raportów w Accessie


Raporty w Accessie podzielone są na cztery główne części (sekcje): Nagłówek/Stopka raportu, Nagłówek/Stopka strony,
Nagłówek/Stopka sekcji i szczegóły. Sekcje te porządkują dane w raporcie. Pierwszym w kolejności wydruku elementem
raportu jest Nagłówek/Stopka raportu. Jest tylko jeden taki element. Stopka raportu drukowana jest po wszystkich danych,
lecz przed stopką strony (mimo, iż w widoku Projekt wygląda to inaczej). Każda strona w raporcie może mieć
Nagłówek/Stopkę strony. Mimo iż masz dostęp tylko do jednej sekcji Strona w widoku Projekt, sekcja ta drukowana jest na
każdej stronie raportu. Później pokażemy jak modyfikować Nagłówek/Stopkę strony, by wyglądała inaczej na każdej stronie.
Nagłówki/Stopki sekcji pojawiają się, gdy umieszczasz w raporcie elementy grupowane. W raporcie może być maksymalnie
dziesięć takich sekcji. Niejednokrotnie sprawiają one wiele trudności projektantom raportów. Pokażemy, jak można nimi
zarządzać, by uzyskiwać przydatne informacje. Ostatnia z omawianych sekcji – Szczegóły – wyświetla najbardziej
szczegółowe informacje w raporcie. Istnieje tylko jedna sekcja Szczegóły i umieszczona jest między wszystkimi nagłówkami
i stopkami sekcji, pośrodku widoku Projekt. Rysunek 10.1 przedstawia sekcje raportu w widoku Projekt.

Najprostszym sposobem prezentowania danych w raporcie jest umieszczenie w poszczególnych sekcjach związanych
formantów. Jednakże jest możliwe umieszczenie w dowolnej sekcji innego raportu tak, by pełnił funkcję podraportu. W
tym rozdziale poznasz nowe opcje oraz kwestie związane z użyciem podraportów w Accessie 2000.

Wreszcie obiekt Raport, który jak wszystkie obiekty Accessa 2000 jest pełen właściwości i zdarzeń, które umożliwią
dostosowanie i automatyzację działania raportów. Od czasu Accessa 97 w raportach nie zmieniło się zbyt wiele, jednak
przyjrzymy się zaletom tych właściwości i zdarzeń, by móc tworzyć doskonałe raporty w Accessie 2000.
Rysunek 10.1.
Widok Projekt
raportu Kategorie
i Produkty

Tworzenie prostych raportów


przy użyciu kreatora
Kreator raportów jest chyba najbardziej przydatnym z kreatorów Accessa i mimo iż mało prawdopodobne jest, że da Ci raport
idealnie odpowiadający Twoim potrzebom, to prawdopodobnie zaoszczędzi Ci 90% pracy w 90% raportów. Co więcej, zadania,
które wykona, to najbardziej pracochłonne i nużące z czynności związanych z tworzeniem raportów.

Kreator Raportów może jedynie tworzyć nowe raporty. Po utworzeniu


raportu modyfikacji możesz dokonywać wyłącznie ręcznie

Aby utworzyć raport przy użyciu Kreatora raportów wystarczy z okna dialogowego Nowy raport wybrać pozycję Kreator
raportów (rysunek 10.2).

28. Wybierz źródło danych (w naszym przykładzie używamy tabeli Kategorie) i kliknij przycisk OK.
29. Kreator poprosi o podanie pól, które chcesz umieścić w raporcie. Możesz je wybierać pojedynczo lub umieścić w
raporcie wszystkie pola jednocześnie. Kolejność, w jakiej wybierasz pola, ma wpływ na sortowanie i umieszczenie
formantów w raporcie.
Część III ♦ Interfejs użytkownika 162

30. W kolejnym, przedstawionym na rysunku 10.3, oknie dialogowym możesz określić rodzaj grupowania w raporcie.
Ponieważ nasz przykład jest oparty o jedną tabelę, grupowanie nie jest zbyt użyteczne. Możesz przejść do kolejnego
okna.
Rysunek 10.2.
Okno dialogowe
Nowy raport
z wybranymi
Kreatorem raportów
i tabelą Kategorie

Rysunek 10.3.
Ustawienia
właściwości
Sortowanie
i Grupowanie

W oknie tym mamy możliwość ustawienia sposobu sortowania raportu. Pola mogą być sortowane maksymalnie po
czterech polach w kolejności rosnącej bądź malejącej. Wybierz pola do sortowania: IDkategorii oraz
NazwaProduktu.

31. Po wybraniu kolejności sortowania możesz zdecydować o układzie raportu: kolumnowy, tabelaryczny i
wyjustowany. Możesz także wybrać orientację drukowanego raportu (poziomą bądź pionową). Kolejna opcja umożliwia
dostosowanie szerokości pól tak, by były widoczne na stronie. Nie chodzi tu o przekształcenie czcionki do
odpowiedniego rozmiaru, jak to ma miejsce w przypadku podobnej opcji programu Microsoft Excel. W przypadku
Accessa wybranie tej opcji powoduje zmianę szerokości formantów, by mieściły się na stronie. W rezultacie dane
mogą stać się nieczytelne, bo zostaną obcięte, jeśli szerokość formantu będzie zbyt mała.
W następnym oknie masz do wyboru kilka stylów. Zmieniają one nagłówki, etykiety oraz sekcje raportu i mogą
przy niewielkim wysiłku z Twojej strony nadać raportowi elegancki i estetyczny wygląd.
32. W ostatnim oknie dialogowym powinieneś podać nazwę dla raportu i wybrać, czy chcesz zobaczyć raport, czy
modyfikować go w widoku Projekt.

Mimo iż Kreator utworzył raport, możesz modyfikować go w dowolny sposób, kiedy tylko zechcesz.

Kreator ten może również tworzyć raporty oparte na więcej niż jednym źródle danych. Jeśli utworzyłeś relację między
tabelami w bazie danych, Kreator raportów utworzy dla raportu odpowiednie wyrażenie SQL.
33. Korzystając z kreatora, utwórz ponownie nowy raport. Przejdź do okna dialogowego, gdzie wybierałeś pola, i
dodaj pole NazwaKategorii z tabeli Kategorie (rysunek 10.4).
163 Rozdział 10. ♦ Tworzenie raportów

Rysunek 10.4.
Wybieranie pól
w Kreatorze
raportów

34. Z rozwijanej listy Tabele/Kwerendy wybierz tabelę Produkty, a następnie wybierz pole NazwaProduktu (rysunek
10.5).

Rysunek 10.5.
Oba pola zostały
dodane

35. Przejdź przez okna dialogowe i ustaw sortowanie na pole NazwaProduktu.


36. Nazwij raport „Kategorie i Produkty” i zobacz, jak wygląda.

W widoku Projekt raportu zauważysz, że Kreator raportów utworzył wyrażenie SQL, korzystając z relacji powstałych w
fazie projektowania bazy danych Northwind.

Dostosowywanie raportów
Nie często się zdarza, by raport utworzony przy użyciu kreatora idealnie odpowiadał Twoim potrzebom. By zaoszczędzić
czas, powinieneś w każdej sytuacji korzystać z Kreatora raportów, jednak wiedzy o dostosowywaniu raportów nie da się
niczym zastąpić.

W kilku krokach i dokonując kilku obliczeń możesz zmienić raport Kategorie i Produkty w raport pokazujący zamówienia
produktów według kategorii. Będzie on posiadał źródło rekordów oparte na kilku tabelach, sortowanie, grupowanie,
obliczenia oraz nagłówki i stopki. To elementy, których będziesz używał w 75% raportów Accessa.

Zmiana źródła rekordów w raporcie


Pierwszym krokiem w modyfikowaniu raportu jest zmiana jego źródła rekordów ( rysunek 10.6). Trudno byłoby dokonać
znaczących zmian w raporcie, nie uzyskując właściwych rekordów i pól.
Część III ♦ Interfejs użytkownika 164

Rysunek 10.6.
Właściwość Źródło
rekordów w oknie
właściwości raportu

W oknie właściwości raportu wybierz właściwość Źródło rekordów i kliknij przycisk z wielokropkiem (...), aby uruchomić
Konstruktora kwerend ( rysunek 10.7). Do kwerendy dodaj tabelę Opisy zamówień. Z tabeli Produkty dodaj również pola
Ilośćjednostkowa i IDproduktu. Zamknij Konstruktora kwerend.

Teraz, gdy źródło rekordów zostało zmienione, możesz zmodyfikować raport tak, by przedstawiał dane w użyteczny
sposób.
Rysunek 10.7.
Konstruktor kwerend

Zmiana struktury grupowania w raporcie


Najbardziej znaczącą ze zmian, jakich musisz dokonać, jest zmiana struktury grupowania w raporcie. Gdy dokonujesz
grupowania, każesz raportowi zebrać razem wskazane dane i przedstawić je w blokach. Bloki te nazywane są również
pasmami. Możesz tworzyć je i modyfikować poprzez okno dialogowe Sortowanie i grupowanie. Po utworzeniu pasma gru-
pującego masz do dyspozycji kilka opcji:
u Pole/Wyrażenie – pole lub wyrażenie, które decyduje o grupowaniu raportu.
u Porządek sortowania – sposób prezentowania grupowania. Do wyboru masz Rosnąco lub Malejąco.
u Nagłówek grupy – po umieszczeniu grupy w raporcie możesz zdecydować, czy przed danymi ma znajdować się
wolna przestrzeń, w której zazwyczaj umieszcza się informacje o grupowanych wartościach.
u Stopka grupy – sekcja ta znajduje się po grupie danych. Zazwyczaj zawiera obliczenia i podsumowania danych w
grupie.
u Grupuj według – właściwość ta określa, co będzie decydowało o grupowaniu. Przy ustawieniu Każda wartość dane
będą grupowane według wartości całych elementów, podczas gdy ustawienie Pierwsze znaki spowoduje grupowanie
tylko według pierwszych znaków elementów. Właściwość ta działa łącznie z właściwością Przedział grupowania.
u Przedział grupowania – gdy właściwość Grupuj według ustawiona jest na Interwał, przedział grupowania określa
ilość znaków, która zostanie użyta. Tabela 10.1 zawiera dostępne wartości oraz sytuacje, w których można je wyko-
rzystać.

Tabela 10.1.
Wartości przedziału grupowania i ograniczenia w ich stosowaniu
165 Rozdział 10. ♦ Tworzenie raportów

Ustawienie Wartość Ograniczenie


Każda wartość 0 Dowolny typ danych
Znaki przedrostka 1 Tylko dla pól tekstowych
Rok 2 Tylko dla pól daty
Kwartał 3 Tylko dla pól daty

Tabela 10.1.
Wartości przedziału grupowania i ograniczenia w ich stosowaniu (ciąg dalszy)

Ustawienie Wartość Ograniczenie


Miesiąc 4 Tylko dla pól daty
Tydzień 5 Tylko dla pól daty
Dzień 6 Tylko dla pól daty
Godzina 7 Tylko dla pól daty
Minuta 8 Tylko dla pól daty
Interwał 9 Tylko dla pól liczbowych

Gdy decydujesz się na grupowanie wyrażenia, Access nie będzie w stanie


określić jego wyniku, gdy raport będzie w widoku Projekt. W takim
przypadku, Access przedstawi wszystkie możliwe opcje właściwości Grupuj
według i Przedział grupowania. Upewnij się, że wybrałeś opcję, która będzie
odpowiednia dla tego wyrażenia.

u Trzymaj razem – właściwość ta dotyczy drukowanego raportu i sposobu, w jaki Access będzie próbował zmieścić
dane na tej samej stronie. Wartości dla tej właściwości i efekt ich działania zawiera tabela 10.2.

Tabela 10.2.
Wyjaśnienie ustawień właściwości Trzymaj razem

Ustawienie Wartość Opis


Nie 0 Podział strony występuje w zależności od umiejscowienia
nagłówków, stopek i danych.
Całą grupę 1 Access próbuje umieścić nagłówki, stopki i dane na jednej stronie.
Z pierwszym szczegółem 2 Access próbuje wydrukować nagłówek grupy na tej samej stronie,
co pierwszy rekord szczegółowy.

Umieszczenie grupowania w raporcie


Aby aktywować Grupowanie, wystarczy ustawić nagłówek, stopkę lub oba te elementy. Po wykonaniu tej czynności, w
oknie Sortowanie i grupowanie obok nazwy pola pojawi się mała ikona, a w raporcie w widoku Projekt wyświetlona
zostanie nowa sekcja. Każdy formant umieszczony w tej sekcji będzie tworzył grupę opartą na jego wartościach, zależną
od wybranych ustawień dodatkowych.

W raporcie sumującym sprzedane jednostki produktu w poszczególnych kategoriach grupowanie musi się odbywać według
produktów. Najlepiej do tego celu wykorzystać unikatowy identyfikator. Mimo iż poniższy przykład funkcjonowałby
równie dobrze

z Nazwą Produktu, w rzeczywistości produkty mogą występować w różnych rozmiarach, wagach i konfiguracjach, lecz pod
tą sama nazwą. Użycie pola ID Produktu umożliwi raportowi odróżnienie takich produktów.
37. Z menu Widok wybierz Sortowanie i Grupowanie. Zmień właściwość sortowania NazwaProduktu na IDproduktu i
ustaw właściwość Nagłówek grupy na Tak. Utwórz także Stopkę grupy dla pola kategoria. Elementy te wystarczą
do stworzenia pogrupowanego raportu o kategoriach i produktach.
38. Z listy pól wybierz IDproduktu i umieść w Nagłówku IDproduktu, na prawo od formantu IDkategorii w Nagłówku
Kategorii. Możesz wyciąć i wkleić etykietę formantu IDproduktu do Nagłówka strony.
Część III ♦ Interfejs użytkownika 166

39. Przesuń formant NazwaProduktu z sekcji Szczegóły do Nagłówka IDproduktu. Będziesz musiał połączyć go z jego
etykietą.

Otrzymujemy raport, który zbiera wszystkie kategorie, wielkości ich sprzedaży i tworzy z nich listę. W tej formie raport
przedstawia jedynie listę sprzedanych produktów w każdej kategorii, bez podania wielkości sprzedaży. Do tego celu należy
stworzyć wyrażenie.

Użycie funkcji w raporcie


Aby otrzymywać w raporcie właściwe i pełne informacje, będziesz czasami zmuszony do pisania funkcji, które będą w
raporcie wykonywać obliczenia lub inne czynności. Umieszczenie w raporcie obliczeń może również wpłynąć na poprawę
jego funkcjonowania. Jeśli masz do wyboru umieszczanie funkcji w raporcie lub w podlegającej mu kwerendzie,
powinieneś rozważyć to pierwsze rozwiązanie. Umożliwi to zmniejszenie ilości wykonywanych obliczeń. Teraz opiszemy
użycie funkcji w raporcie.

Użycie funkcji obliczeniowych


Obliczenia w raporcie nie różnią się od obliczeń wykonywanych w innych obiektach Accessa. Jedyna różnica polega na
tym, że w raporcie to samo wyrażenie, w zależności od sekcji, w której znajduje się formant, może dać inne wyniki.
Przyczyna tego faktu jest prosta. Gdy Access przetwarza dane, by utworzyć żądane grupowania, w rzeczywistości
przetwarza różne dane. Więc wyrażenie
Suma ([IlośćJednostkowa])

umieszczone w nagłówku IDproduktu zwróci wartość sprzedaży każdego z produktów. Jeśli umieścimy to wyrażenie w
stopce Kategorii, otrzymamy wartość sprzedaży w danej kategorii.

Aby zobaczyć jak to wygląda w praktyce, utwórz pole tekstowe w nagłówku IDproduktu i wpisz wyrażenie
Suma ([IlośćJednostkowa])

Mimo iż raport nie zawiera formantu o nazwie „IlośćJednostkowa”, pole takie znajduje się w źródle danych i może być
użyte w wyrażeniu. Skopiuj formant do stopki Kategorii.

Przejdź do widoku Podgląd wydruku, powinieneś wtedy zobaczyć taki sam rezultat jak na rysunku 10.8.

Rysunek 10.8.
W zależności od
położenia wyrażenia,
jego wynik zmienia się

Użycie Funkcji Immediate IF


Inną, bardzo użyteczną funkcją, którą można wykorzystać w raporcie, jest funkcja Immediate IF (IIF()). Funkcja ta
umożliwia wykonanie testu If...Then...Else bez konieczności pisania kodu. Sprawdza się ona, gdy należy podsumować
dane bądź podkreślić znaczenie poszczególnych rekordów w raporcie. Zawiera trzy argumenty: warunek, czynność
wykonywaną, gdy warunek jest spełniony oraz czynność wykonywaną, gdy warunek nie jest spełniony. Argumenty
oddzielane są przecinkiem. Aby użyć tej funkcji, napisz warunek, który może być spełniony lub nie (przykładowo, [suma
of ilośćjednostkowa]>=500). Drugim argumentem jest zazwyczaj wartość, jaka jest wyświetlana, gdy warunek został
spełniony (np. „Powyżej”), a trzecim argumentem jest wartość, jaka jest wyświetlana, gdy warunek nie jest spełniony (np.
167 Rozdział 10. ♦ Tworzenie raportów

„Poniżej” lub brak reakcji). Istnieje możliwość zagnieżdżenia funkcji IIF w innej funkcji, tak więc gdy jeden warunek
jest spełniony, przeprowadzany jest kolejny test i tak dalej. Funkcje IIF powinny być używane dość rzadko, gdyż mogą
spowalniać pracę raportu.

Raport może wykorzystywać procedurę IIF do zaznaczania tych produktów, w przypadku których sprzedaż była równa
lub przekroczyła 500 jednostek. Aby to uczynić, z prawej strony nagłówka IDproduktu umieść pole tekstowe i w jego
źródle danych wpisz następującą formułę:
=IIF ([Suma of Ilośćjednostkowa]>=500, "Powyżej", "")

Użycie własnych funkcji w module raportu


Zdarza się, że wyrażenie staje się zbyt złożone, by umieścić je w zwykłej funkcji IIF(). Gdy taka sytuacja ma miejsce,
możesz utworzyć funkcję, która będzie dokładnie odpowiadać Twoim potrzebom, i odwołać się do niej w raporcie.
Przykład na wydruku 10.1 przedstawia, jak można taką funkcję napisać w module raportu i odwołać się do niej z
umieszczonego w raporcie formantu.

Wydruk 10.1. Funkcja w module raportu


' Jak zamienić wartość na ciąg
Function HiLowTest(dblQuantity As Double) As String
If dblQuantity >= 500 Then
HiLowTest = "Powyżej"
Else
HiLowTest = "Poniżej"
End If
End Function

Będąc w widoku Projekt raportu, z menu Widok wybierz Kod programu. Spowoduje to otwarcie modułu raportu, w którym
możesz tworzyć procedury i funkcje wykorzystywane w tym raporcie.

Teraz możesz zamienić funkcję IIF() na:


=HiLowTest ([Suma of Ilośćjednostkowa])

Dzięki temu będziesz w stanie lepiej kontrolować to, co dzieje się w danym momencie w formancie, gdyż możesz nadawać
funkcjom znaczące nazwy. Umieszczenie funkcji w formancie zapewnia jednocześnie zachowanie ciągłości, jeśli
wykorzystujesz te same obliczenia w różnych miejscach raportu.

Użycie własnych funkcji w osobnym module


Zdarza się również, że obliczenia wykonywane w raporcie wykorzystywane są również w formularzu i w kwerendach. W
takich przypadkach dobrze jest napisać funkcję w osobnym module tak, by kwerendy, formularze i raporty danej aplikacji
mogły zawsze otrzymywać zbieżne wyniki. Poniższy przykład przedstawia podstawową funkcję, która poprawia pisownię
danego ciągu znaków. Do tego rodzaju funkcji można odwoływać się z różnych miejsc w aplikacji.

Użyjemy tu nowej funkcji VBA Accessa – Split(). Funkcja ta, w oparciu o wybrany ogranicznik (domyślnie jest nim
znak spacji), podzieli ciąg na elementy tablicy. Funkcja ta może mieć wiele zastosowań w Accessie 2000. W tym
przypadku posłuży do zamiany w nazwach produktów małych liter na duże.

Funkcja ta jest bardzo prosta. Traktuje ciąg jako argument i dzieli go na elementy tablicy (varArray). Następnie, przy
użyciu funkcji UCase(), zamienia pierwszą literę każdego słowa na dużą. Aby zwrócić słowa z zamienionymi literami,
funkcja korzysta z funkcji Left i Right, które umożliwiają oddzielenie pierwszej litery z lewej strony słowa. Później te
grupy liter są ponownie łączone w taki sposób, by znów tworzyły całe słowa.

W ten sam sposób łączone są elementy tablicy, by znów tworzyły jeden ciąg, lecz już z poprawną pisownią. Wydruk 10.2
przedstawia, jak to się dzieje.

Wydruk 10.2. Zmiana małych liter na duże i użycie nowej funkcji Split
Function MakeProper(str As String) As String

On Error GoTo MakeProper_Err

Dim vararray As Variant


Dim i As Integer
Dim strTemp As String

If Len(str) = 0 Then
Resume MakeProper_Exit
End If

' Najpierw zamień wszystkie litery na małe


Część III ♦ Interfejs użytkownika 168

str = LCase(str)

' Split() wypełnia tablicę częściami ciągu


' Split() używa spacji jako domyślnego ogranicznika
vararray = Split(str)

' Przejdź przez tablicę I zamieniaj każdą z pierwszych liter na


' na dużą oraz utwórz strTemp

For i = 0 To Ubound(vararray)
strTemp = strTemp & UCase(Left(vararray(i), 1)) & _
Right(vararray(i), Len(vararray(i)) - 1) & " "
Next
' Usuń zbędne spacje
MakeProper = Trim(strTemp)

MakeProper_Exit:
On Error Resume Next
Exit Function

MakeProper_Err:
MakeProper = ""
Resume MakeProper_Exit

End Function

Użycie konkatenacji
Konkatenacja (łączenie) jest niezwykle często wykorzystywana w zaawansowanych raportach. Umożliwia ona łączenie nazwisk i
adresów tak, by można je było łatwo drukować i prezentować. Gdy łączysz dwa elementy danych, nie mogą one już być
przetwarzane osobno. Innymi słowy, formularz pokazujący połączone imię i nazwisko klienta nie może być wykorzystywany
(bez pisania dużej ilości kodu) do wprowadzania nowych nazwisk.

Konkatenacja wykonywana jest przy użyciu operatora konkatenacji, znaku [&]. Można również używać znaku [+], lecz formuły
łączące numery klientów z numerami kont mogą być wówczas mylące dla programisty. Więcej zastosowań konkatenacji
opiszemy w przedstawionym w dalszej części tego rozdziału przykładzie dotyczącym etykiet adresowych.

Przykład:
="Access" & Space (1) & "2000" & Space (1) & _
"Księga" & Space (1) & "Eksperta"

zwraca
"Access 2000 Księga Eksperta"

Możesz sprawdzić działanie tej funkcji w oknie Immediate. Z menu Widok modułu wybierz Immediate Window lub naciśnij
klawisze Ctrl+G.

W oknie wpisz
?MakeProper ("access 2000 księga eksperta")

I naciśnij Enter. Jeśli wszystko zostało poprawnie wprowadzone, powinieneś otrzymać „Access 2000 Księga Eksperta”.
Podczas dokonywania konkatenacji musisz zwrócić uwagę na składnię w następujących przypadkach:
u Jeśli w nazwach pól występują spacje, nazwy te muszą być umieszczone w kwadratowych nawiasach (na przykład [ID
Zamówienia]). Jednakże dla zachowania przejrzystości dobrze jest używać kwadratowych nawiasów w każdym
przypadku.
u Ciągi tekstów muszą być umieszczone w cudzysłowie ("Uwaga"). Rozważ także użycie Chr(34), gdy masz do
czynienia z cudzysłowem w kodzie.
u Daty muszą być umieszczone między znakami krzyżyka (#7/27/20000#).

Następnym krokiem jest wykorzystanie tej funkcji w raporcie. Spowoduje ona zmianę pisowni nazw produktów z małych
liter na duże. W widoku Projekt raportu zmień właściwość źródła formantu NazwaProduktu na:
=MakeProper ([NazwaProduktu])

W niektórych przypadkach to wystarczy. Jednakże w tym przypadku, sprawa nie jest taka prosta. Ponieważ formant ten nosi
taką samą nazwę jak pole w źródle rekordów raportu, rezultatem funkcji będzie błąd. Oto jeden z powodów, dla których
warto przestrzegać przyjętej konwencji nazewnictwa podczas tworzenia formantów w formularzach i raportach. Ponieważ
do tworzenia raportu korzystałeś z kreatora, nie miałeś wiele do powiedzenia przy nazywaniu jego formantów. Teraz masz
możliwość zmiany nazwy tego formantu. Ponieważ NazwaProduktu jest polem tekstowym, powinieneś zmienić jego nazwę
na txtNazwaProduktu.
169 Rozdział 10. ♦ Tworzenie raportów

Gdy będziesz teraz przeglądał raport w widoku Podgląd wydruku (jak na rysunku 10.9), zauważysz, że w niektórych
przypadkach nazwa produktów została zmieniona.

Jak dotąd nauczyłeś się tworzyć prosty raport oraz trochę bardziej skomplikowany przy użyciu kreatora. Wiesz już, jak
modyfikować raport po jego utworzeniu. Dowiedziałeś się, co to grupowanie, obliczenia i konkatenacja oraz jak
wykorzystywać funkcje w raportach. Tematy te obejmują 90% tworzenia raportów w bazie danych Accessa.

Praca z podraportami
Tak jak w formularzach można było umieszczać podformularze, tak w raportach można umieszczać podraporty. Podraport
jest to raport umieszczony wewnątrz innego raportu, najczęściej służący do pokazywania powiązanych rekordów. Może on
być również wykorzystywany do pokazywania tego samego podzestawu danych w różnych raportach. Używając
podraportu, możesz korzystać z elastyczności, jaką dają Ci dwa raporty.
Rysunek 10.9.
Pierwsze litery nazw
produktów zostały
zmienione

Gdy między rekordami w raporcie głównym a rekordami w podraporcie istnieje relacja jeden-do-wielu, główny raport
nazywany jest raportem nadrzędnym, a podraport podrzędnym. Mimo iż podobny efekt można często osiągnąć dzięki
grupowaniu raportu, podraporty przydają się w sytuacji, gdy chcesz wydrukować rekordy z kilku różnych tabel. Rysunek
10.10 przedstawia kategorię (Napoje) z bazy Northwind i jej podraport o poszczególnych produktach.

Rysunek 10.10.
Czwarta strona
raportu Katalog
w bazie Northwind
przedstawia
elastyczność, jaką
dają podraporty
Część III ♦ Interfejs użytkownika 170

Tworzenie prostego podraportu


W typowym podraporcie istnieje relacja jeden-do-wielu między rekordami podrzędnymi a nadrzędnymi. Zapisz, które z pól
uczestniczą w relacji między dwiema tabelami lub kwerendami.
40. Utwórz raport dla rekordów nadrzędnych. Będzie to raport główny.
41. Utwórz następny raport dla rekordów podrzędnych. Będzie to podraport.
42. W widoku Projekt głównego raportu wyłącz kreator (odpowiedni przycisk znajduje się w przyborniku) i użyj
narzędzia Podraport. W miejscu, gdzie chcesz go umieścić, rozciągnij prostokąt.
43. Jako właściwość podraportu Obiekt źródłowy ustaw nazwę podraportu utworzonego w punkcie 3.
44. Jeśli połączone pola, które wcześniej zapisałeś, mają takie same nazwy, Access automatycznie wypełni właściwości
Nadrzędne pole łączące i Podrzędne pole łączące. Jeśli nazwy ich są różne, nazwa powiązanego pola głównego raportu
powinna być wpisana we właściwości Nadrzędne pole łączące, a we właściwości Podrzędne pole łączące powinna
zostać wpisana nazwa odpowiadającego mu pola podraportu. Jeśli łącze wymaga więcej niż jednego pola, oddziel je
przecinkiem.

We właściwości Podrzędne pole łączące należy umieścić nazwę związane-


go pola, a nie nazwę formantu wyświetlającego to pole. Natomiast we
właściwości Nadrzędne pole łączące można się posłużyć nazwą odpo-
wiedniego formantu.

Jeśli raport główny i podraport są ze sobą powiązane, to, aby raport działał,
właściwości Nadrzędne pole łączące i Podrzędne pole łączące muszą być
ustawione poprawnie. Istnieje możliwość utworzenia konstrukcji raport
główny – podraport bez tworzenia między nimi relacji. W takich
przypadkach można używać wykorzystywanych w wielu raportach
odnośników lub bloków adresowych, lecz wyświetlanych jako podraport w
celu zapewnienia spójności i przejrzystości. Można nawet utworzyć raport
główny, który nie będzie zawierał żadnych rekordów.

Sposób wyświetlania podraportów został w Accessie 2000 znacznie poprawiony. We wcześniejszych wersjach podraport
przedstawiany był jako puste pole w widoku Projekt głównego raportu. Teraz wyświetla on wiele przydatnych informacji o
używanych w podraporcie polach.

Co więcej, istnieje możliwość edycji podraportu w widoku Projekt raportu głównego ( rysunek 10.11). Możliwości
modyfikowania właściwości i formantów podraportu są dużo większe niż kiedyś. Pozwala to zaoszczędzić dużo czasu i
wysiłku. We wcześniejszych wersjach, aby modyfikować podraport, programista musiał otwierać go w osobnym oknie, z
poziomu głównego okna bazy danych.
Rysunek 10.11.
Modyfikowanie
formantów
podraportu
171 Rozdział 10. ♦ Tworzenie raportów

Istnieje jeszcze jeden rodzaj raportu, który różni się nieco od innych, a jest dość często używany: etykiety adresowe. W
następnej części tego rozdziału omówimy ten typ raportów i jego cechy charakterystyczne.

Tworzenie prostych etykiet adresowych


Mimo iż być może jeszcze nigdy nie miałeś potrzeby tworzenia etykiet adresowych, ta sama technika może być
wykorzystana do tworzenia innych rzeczy, na przykład plakietek z nazwiskami, etykiet na dokumentację techniczną,
identyfikatorów wyposażenia itp. Access posiada Kreatora etykiet, który potrafi drukować etykiety w setkach różnych for-
matów. Formaty te mogą być wybierane podczas działania kreatora lub też później.

Aby utworzyć etykiety, utwórz nowy raport i wybierz Kreator etykiet z okna Nowy raport. Jako źródło danych wybierz
tabelę Customers. Kliknięcie OK uruchamia kreator etykiet.
45. Wybieranie formatu etykiet nie jest trudne. Przedstawione na rysunku 10.12 okno dialogowe zawiera dokładne
wymiary najczęściej spotykanych etykiet i według nich automatycznie formatuje raport. Musisz wybrać jednostki
miary (angielskie lub metryczne) oraz typ etykiety (najczęściej spotykany Podawany arkuszami albo Ciągły).
Każdy z dokonywanych przez Ciebie wyborów zmienia liczbę dostępnych produktów. Możesz filtrować etykiety
według ich producentów. Domyślnym ustawieniem jest Avery, gdyż etykiety tego producenta są najczęściej
używane i wielu innych producentów dostosowuje się do ich rozmiarów oraz używa na swoich produktach tych
samych numerów produktów.
Rysunek 10.12.
Wybierz typ etykiety
odpowiadający
etykietom, na których
będziesz drukował

Jeśli znajdziesz się w sytuacji, w której nie będzie etykiety odpowiadającej


Twoim potrzebom, klikając przycisk Dostosuj, możesz utworzyć własny
format etykiety.

46. Gdy znalazłeś etykietę odpowiadającą tym, których używasz, przejdź do następnego okna kreatora, aby wybrać
rodzaj i wielkość czcionki. Ponieważ Windows umożliwia wybór dowolnego rodzaju i wielkości czcionki, może się
zdarzyć, że wybierzesz czcionkę zbyt dużą dla etykiety. W oknie dialogowym zobaczysz jak etykieta będzie
wyglądać w przypadku wybrania danego rodzaju i wielkości czcionki. Dzięki temu unikniesz przykrych
niespodzianek przy drukowaniu etykiet.

47. Naciśnięcie przycisku Dalej spowoduje przejście do kolejnego okna dialogowego (rysunek 10.13), w którym będziesz
mógł określić wygląd etykiety. Duży, pusty obszar po prawej stronie zawiera pola prototypu etykiety. Możesz
przenosić do niego pola ze źródła danych, klikając dwukrotnie lub korzystając z przycisku >. Aby zacząć od nowej
linii, musisz na końcu poprzedniej wcisnąć klawisz Enter. Po utworzeniu linii możesz umieścić jej elementy w
osobnych liniach. Aby usunąć określony element z prototypu, zaznacz go wskaźnikiem myszy i naciśnij klawisz
Delete. Wprowadzanie tekstu odbywa się w sposób standardowy: po prostu kliknij odpowiednie miejsce i pisz.
Każda z czynności, którą wykonujesz na prototypie etykiety, ma wpływ na wszystkie etykiety.

Rysunek 10.13.
Wypełniony prototyp
etykiety
Część III ♦ Interfejs użytkownika 172

Przedstawiony na rysunku 10.13 prototyp etykiety umożliwi tworzenie etykiet zawierających u góry nazwę firmy,
poniżej adres i nazwisko osoby, do której list będzie przeznaczony. Zwróć uwagę na przecinek i spację po
{Miasto}. Znaki te umieszczone zostaną na każdej z etykiet. To samo dotyczy znajdującego się u dołu etykiety
zwrotu „Do wiadomości”.
48. Przejście do następnego okna Kreatora etykiet umożliwia nam zmianę kolejności sortowania etykiet. Możesz je
sortować według kilku pól (na przykład nazwisko, a potem imię) lub według jednego. Jeśli nie określisz kolejności
sortowania, etykiety zostaną ułożone w takiej kolejności, w jakiej znajdują się w źródle rekordów. Podczas
tworzenia dużej ilości etykiet adresowych możesz je posortować według kodu pocztowego (rysunek 10.14).

Rysunek 10.14.
Wybór sortowania po
kodzie pocztowym

49. W ostatnim oknie dialogowym podajmy nazwę raportu. Ponieważ są to etykiety adresowe klientów, wpisujemy
„Korespondencja z klientami”. Możesz również zdecydować, czy otworzyć raport w widoku Projekt, czy też
Podgląd wydruku. Wybór opcji Chcę zmienić projekt etykiety pozwoli zobaczyć, że etykieta to zwykły raport, z
odpowiednio ustawionymi właściwościami.

Wynikiem działania kreatora jest mały raport, zawierający pola odpowiadające każdej z widocznych w prototypie linii.
Zauważ, że kreator połączył oddzielne pola Miasto, Region oraz Kod pocztowy i utworzył z nich jedną linię. Zauważ
również, że kreator otoczył pola funkcją Trim(). Dzięki temu przed i za polami nie występują spacje, które mogłyby
wpłynąć na wyrównanie etykiet. Gdybyś tworzył te etykiety ręcznie, musiałbyś sam utworzyć konkatenację i odwoływać się
do funkcji Trim w każdym formancie. Raport swoimi rozmiarami idealnie odpowiada wybranemu typowi etykiety.
Wysokość i szerokość raportu sprawiają, że dane będą drukowane kolumna po kolumnie i strona po stronie.

Właściwość Trzymaj grupę razem jest ustawiona na Na kolumnę. To, w połączeniu z innymi ustawieniami właściwości,
sprawia, że raport jest szeroki na dwie kolumny i w każdej z nich mieści cztery etykiety.

Jeśli już wcześniej miałeś do czynienia z etykietami, prawdopodobnie nasuwa Ci się kilka pytań. Co jeśli adres zajmuje
więcej niż jedną linię? Jak przesunąć region i kod pocztowy, gdy nazwa miasta jest bardzo długa lub bardzo krótka?
Właściwości Można powiększać i Można zmniejszać dla tych formantów ustawione są na Tak, więc będą one
automatycznie dostosowywać się do zmiany warunków. Dzięki temu nie zachodzi potrzeba tworzenia osobnych
procedur warunkowych, aby brać takie możliwości pod uwagę.

Publikowanie raportu
Access jest doskonałym, lecz nie jedynym narzędziem do zarządzania danymi i tworzenia raportów. Często zdarza się, że
bardzo niewygodnym jest instalowanie u każdego z użytkowników Accessa, by mogli przeglądać i drukować dane z raportów,
a dostarczenie wydrukowanego raportu do więcej niż kilku użytkowników to męczące i czasochłonne zadanie. Co więcej,
niektórzy użytkownicy mogą chcieć obrabiać dane w raporcie po jego otrzymaniu. Raport może zawierać dokładnie to, czego
życzą sobie użytkownicy, jednakże forma i układ, w jakim są prezentowane, mogą sprawić, że dane te będą dla nich prawie
bezużyteczne. Czasami dane z raportu Accessa muszą być opublikowane w inny, bardziej twórczy i dostosowany do potrzeb
użytkowników sposób niż zwykły raport.

Metody publikowania raportów


W tej części omówimy sposoby, na jakie można rozpowszechniać raporty Accessa poprzez programy Word, Excel i pocztę
elektroniczną. Istnieje kilka różnych formatów, które mogą pomóc dopasować raporty do potrzeb użytkowników. Nowym
sposobem na rozpowszechnianie raportów w sieci są strony dostępu do danych. Ponieważ są to jednak osobne obiekty,
omówione zostały w rozdziale 26., „Użycie stron dostępu do danych”.
173 Rozdział 10. ♦ Tworzenie raportów

Pierwszą z decyzji, jakie musisz podjąć przed opublikowaniem danych jest to, czy użytkownicy wymagają sformatowanej,
zawierającej podsumowania wersji danych, czy może zależy im na nieprzetworzonych danych. Jeśli mamy do czynienia z
drugim przypadkiem i użytkowników nie interesuje wygląd, obliczenia, grupowania itp., najlepiej będzie przekazać im dane,
eksportując kwerendę lub tabelę, niż wysyłać raport. Sposób postępowania przy eksportowaniu kwerendy lub tabeli jest
bardzo podobny do eksportowania raportu, jednak w przypadku zestawów rekordów istnieje kilka innych opcji do wyboru.

Najważniejszymi rzeczami, o których należy pamiętać przy publikowaniu raportu, jest to, że opublikowany raport nie
będzie uwzględniał zmian dokonanych w źródle rekordów oraz to, że użytkownicy nie będą mieli możliwości
modyfikowania informacji podsumowujących w celu poznania szczegółów. Jeśli akceptujesz te ograniczenia, reszta tego
rozdziału będzie odpowiadać Twoim potrzebom.

Użycie wbudowanych metod Accessa do eksportowania raportów


Access posiada siedem opcji umożliwiających eksportowanie lub publikowanie raportów (rysunek 10.15). Każda z tych
opcji to inny format pliku, do którego zapisywane są informacje o raporcie i jego układzie. Zostały one opisane w poniższej
tabeli.

Tabela 10.3.
Opcje eksportowania raportów w Accessie

Format pliku Rozszerzenie pliku Opis


Access *.mdb, *.adp, *.mdw Eksportuje cały raport do innej bazy danych w Accessie
Excel *.xls Zapisuje rezultaty raportu w arkuszu danych Excela
(wersja 5 i 7)
Excel *.xls Zapisuje rezultaty raportu w arkuszu danych Excela
(wersja 97 i 2000)
HTML *.html, *.htm Tworzy wersję raportu w języku HTML. Każda ze stron
raportu to osobny plik HTML, indeksowany według
numerów stron (na przykład SprzedażWedługKategorii,
SprzedażWedługKategorii2...) Do poruszania się między
stronami służą automatycznie tworzone hiperłącza
Text *.txt, *.csv, *.tab, *.asc Powszechnie akceptowany format pliku, rozpoznawany
przez prawie każdą aplikację. Wszelkie informacje
o sposobie formatowania zostaną utracone
Rich Text Format *.rtf Format ten zatrzymuje podstawowe informacje o sposobie
formatowania. Rozpoznawany jest przez większość
edytorów tekstu
SnapShot Format *snp Format charakterystyczny dla Accessa. Umożliwia on
przesłanie raportu do osób nie posiadających Accessa.
Wymaga przeglądarki Microsoft Snapshot Viewer

Rysunek 10.15.
Okno dialogowe
Eksportuj

Aby wybrać jeden z omówionych formatów, wystarczy zaznaczyć raport i z menu plik wybrać Eksportuj. Wyświetlone
zostanie okno dialogowe, w którym możesz wybrać lokalizację, nazwę i format pliku.
Część III ♦ Interfejs użytkownika 174

Użycie łączy pakietu Office do publikowania raportów


Innym sposobem na publikowanie raportów są łącza pakietu Office. Przeglądając raport w widoku Podgląd wydruku,
możesz nacisnąć znajdujący się na pasku narzędzi przycisk Łącza Office, a wybrany raport zostanie wysłany do Worda lub
Excela. Wówczas możesz zapisać go w dowolnym miejscu.

Problemy związane z publikacją


Gdy używasz formatów Excel i Text jako wyjściowych, istnieje ryzyko utraty części informacji o sposobach formatowania
raportu, tak więc przed udostępnieniem go użytkownikom sprawdź, czy nadaje się do użytku.

Użycie poczty elektronicznej do publikowania raportów


Wysyłanie raportów pocztą elektroniczną może się odbywać z poziomu Accessa poprzez zgodny z MAPI system pocztowy
(na przykład Microsoft Exchange). Gdy otwarłeś raport w widoku Podgląd wydruku lub po zaznaczeniu go w oknie bazy
danych z menu Plik wybierz Wyślij do. Możesz wysłać raport jako załącznik w formatach HTML, Excel, DOS Text, RTF lub
SnapShot.

Aby przeglądać raport w formacie SnapShot, należy posiadać przeglądarkę SnapShot Viewer. Umożliwia ona przeglądanie
raportu w sposób przypominający widok Podgląd wydruku Accessa. Przydaje się to w szczególności w przypadku
przesyłania raportów pocztą elektroniczną, gdyż umożliwia przeglądanie załączników bez zniekształceń.

Więcej informacji o pisaniu kodu umożliwiającego przesyłanie pocztą elektroniczną raportów i innych obiektów Accessa
znajdziesz w rozdziale 18., „Użycie automatyzacji ActiveX”.

Gdy eksportujesz lub przesyłasz raport oparty na kwerendzie parametrycz-


nej, raport może nie funkcjonować poprawnie. Zastanów się, czy nie będzie
lepiej oprzeć eksportowaną wersję na statycznej tabeli z tym samym
ustawieniem parametrów.

Modyfikowanie raportu
podczas jego działania
Ponieważ raport jest takim samym obiektem jak wszystkie inne obiekty Accessa, istnieje możliwość napisania kodu, który
będzie wpływał na jego właściwości i w określony sposób reagował na zdarzenia. Pozostała część tego rozdziału będzie
poświęcona obiektowi Raport oraz jego właściwościom i zdarzeniom.

Ponieważ formularze i raporty są do siebie podobne, zajmiemy się jedynie cechami charakterystycznymi raportów lub tym
aspektom ich działania, które są dla nich wyjątkowe. Zdarzenia dla raportów i sekcji można podzielić na związane z
procesem projektowania oraz związane z funkcjonowaniem raportu. Podział ten jest bardzo ważny w przypadku roz-
wiązywania poważnych problemów związanych z raportami. Właściwości związane z procesem projektowania mogą być
ustawiane jedynie w widoku Projekt. Gdy raport już działa, nie można tych ustawień modyfikować. Właściwości związane
z funkcjonowaniem raportu mogą być modyfikowane za pomocą kodu, gdy raport jest otwierany, formatowany czy
drukowany, dając Ci dynamiczną kontrolę nad jego wyglądem i zawartością.

Aby modyfikować raport podczas jego funkcjonowania (a także w procesie projektowania) konieczne jest dogłębne
zrozumienie jego właściwości, zdarzeń i obiektów. Przejdźmy do przeglądu tych elementów.

Filtrowanie i sortowanie
Właściwości te działają prawie identycznie jak ich odpowiedniki z formularzy. Korzystając z właściwości Filtr, możesz
ograniczyć zawartość raportu. Filtrowanie działa tylko wówczas, gdy właściwość Filtr włączony ustawiona jest na Tak. Aby
zobaczyć jak działa filtrowanie w formularzu, postępuj w następujący sposób:
50. Otwórz raport Katalog w widoku Projekt.
51. Zmień właściwość Filtr włączony na Tak.
52. We właściwości Filtr wprowadź następujące wyrażenie:
175 Rozdział 10. ♦ Tworzenie raportów

[NazwaKategorii] = "Napoje"

53. Przejdź do widoku Podgląd wydruku. Wyświetlone powinny zostać jedynie napoje.
54. Powróć do widoku Projekt i ustaw właściwość Filtr włączony na Nie.
55. Przejdź do widoku Podgląd wydruku. Wyświetlone zostaną wszystkie kategorie.

Aby użyć tych właściwości w kodzie, mógłbyś utworzyć następujące procedury:


Reports![Katalog].FilterOn=True

lub
Reports![Katalog].Filter=[NazwaKategorii]= "Napoje"

Trzymaj grupę razem


Przy tworzeniu raportów wielokolumnowych może zaistnieć konieczność zachowania grup w kolumnie lub na stronie w
całości. Oto dwie dostępne opcje:
u Na kolumnę – gdy właściwość ta jest użyta łącznie z umieszczoną w oknie dialogowym Sortowanie i grupowanie
właściwością Trzymaj razem, Access spróbuje zmieścić całą grupę w tej samej kolumnie.
u Na stronę – gdy właściwość ta jest użyta łącznie z umieszczoną w oknie dialogowym Sortowanie i grupowanie
właściwością Trzymaj razem, Access spróbuje zmieścić całą grupę na tej samej stronie.

HasData
Gdy raport główny wykonuje obliczenia na podraporcie, w którym nie ma danych, wyrażenie może wyświetlić komunikat o
błędzie. Do określenia, czy istnieją dane dla raportu lub formantu, możesz użyć właściwości HasData. Właściwość ta zwraca
trzy wartości:

Tabela 10.4.
Wartości właściwości HasData

Wartość Opis
Raport niezwiązany Raport nie posiada źródła rekordów
Raport związany, bez rekordów Raport posiada źródło rekordów, lecz jest ono puste
-1 – Raport związany, zawiera rekordy Raport posiada źródło rekordów zawierające co najmniej
jeden rekord

Do sprawdzenia, czy obliczenia powinny być wykonywane, wystarczy prosta formuła:


="Category has " & if ([CategorySubRpt].[Report].[HasData] = -1, _
[CategorySubRpt].[Report]![CatCount],0) & " products."

Zdarzenia raportu (podczas jego działania)


Poniższe zdarzenia to niektóre ze zdarzeń uruchamianych podczas działania raportu. Oznacza to, że uruchamiane są, gdy
raport jest drukowany, zaznaczany itd. Są to zdarzenia, których będziesz używał do kontroli zachowań związanych z
interakcją z użytkownikami lub danymi raportu.

Przy otwarciu
Przy otwarciu jest to pierwsze zdarzenie po uruchomieniu raportu. Występuje przed otwarciem podległej kwerendy. Jest w
takim razie dobrym miejscem na dokonanie programowych zmian w kwerendzie lub na podanie jej określonych
parametrów. Kod napisany w zdarzeniu Przy otwarciu zostanie wykonany, zanim w raporcie stanie się cokolwiek innego.
Po zakończeniu tego zdarzenia raport podejmie działania konieczne do załadowania danych.

Przy aktywowaniu, przy dezaktywowaniu


Zdarzenia te uruchamiane są, gdy raport staje się aktywnym oknem (w przypadku Przy dezaktywowaniu przestaje nim być)
lub gdy rozpoczyna się drukowanie raportu.
Część III ♦ Interfejs użytkownika 176

Przy braku danych


Dawniej, gdy po otwarciu raport nie zawierał żadnych rekordów lub jego filtr nie zwrócił żadnych wierszy, Access
wyświetlał komunikat o błędzie. Na szczęście problem ten został rozwiązany i teraz formanty związane z pustym źródłem
rekordów są po prostu puste. Jednakże zdarzenie Przy braku danych będzie w takim przypadku uruchamiane. Może być
użyte do grzecznego poinformowania użytkowników o braku rekordów i anulowania raportu. Gdyby raport miał
wyświetlać zamówienia według klientów, kod na wydruku 10.3 anuluje raport, gdyby dany klient nie posiadał żadnych
zamówień.

Wydruk 10.3. Anulowanie raportu przy braku danych


Private Sub Report_NoData(Cancel As Integer)
' Ostrzeż użytkownika
MsgBox "Ten klient nie składał zamówień"
' Anuluj otwieranie raportu
Cancel = True
End Sub

Przy błędzie
Jeśli tabela, na której poparty jest raport, otwarta jest przez innego użytkownika z wyłącznością lub po prostu nie istnieje,
aparat Jet stwierdzi błąd i uruchomi zdarzenie raportu Przy błędzie. Zdarzenie to połączone jest z procedurą
AccessError obiektu Application, więc do rozwiązania tego problemu nie możesz użyć Err.Description.

Najlepszym sposobem na radzenie sobie z błędami w raportach jest użycie modułu klasy raportu.

Przy stronie
Zdarzenie to umożliwia dokonywanie zmian w raporcie w ostatnim momencie, tuż przed jego wydrukowaniem lub
przeglądaniem w widoku Podgląd wydruku. Niektóre zmiany (związane na przykład z obramowaniem stron lub
obliczaniem niestandardowych podsumowań) łatwiej jest wykonywać po sformatowaniu raportu, jednak przed jego
wydrukowaniem.

Metoda Line spowoduje narysowanie linii wokół raportu, zanim zostanie on wydrukowany:
Me.Line (0, 0) – (Me.ScaleWidth, MeScaleHeight), , B

Przy zamknięciu
Zdarzenie to występuje zaraz po zamknięciu raportu, jednak przed jego dezaktywacją. Możesz chcieć zamknąć wraz z
raportem formularz służący do wprowadzania parametru lub zmienić pozycję innych okien. Zadania te, jak i inne
porządkujące czynności, mogą być wpisane w zdarzenie Przy zamknięciu.

Właściwość Sekcja
Raport w Accessie może zawierać maksymalnie 25 sekcji: Nagłówek/Stopka raportu, Nagłówek/Stopka strony, Szczegóły
oraz maksymalnie dziesięć Nagłówków/Stopek grup. Właściwość Sekcja zawiera tablicę opisującą wszystkie sekcje
raportu. Do sekcji można tworzyć odniesienia za pomocą numerów ich indeksów w tablicy (a także stałych Accessa).
Sekcje różnią się od innych właściwości Accessa tym, że nie zwracają własnej wartości, lecz odniesienie do sekcji. Aby w
raporcie widoczny był nagłówek raportu, należy użyć następującego kodu:
Reports![Produkty wg kategorii].Section(1).visible=true

lub
Reports![Produkty wg kategorii].Section(acHeader).visible=true

Nazwa
Jak wynika z tabeli 10.5, sekcje raportu posiadają również właściwość Nazwa, której można użyć do tworzenia odniesień.
Aby poprawić przejrzystość raportu, możesz w dowolnym momencie zmienić nazwę sekcji i tworzyć odniesienia,
używając nowo przyznanej nazwy.

Tabela 10.5.
Sekcje wraz z ich indeksami oraz stałymi
177 Rozdział 10. ♦ Tworzenie raportów

Sekcja Indeks Nazwa/Stała


Szczegóły 0 acDetail
Nagłówek 1 acHeader
Stopka 2 acFooter
Nagłówek Strony 3 acPageHeader
Stopka Strony 4 acPageFooter
Nagłówek Grupy – poziom 1 5 Nazwa pola grupy
Stopka Grupy – poziom 1 6 Nazwa pola grupy
Nagłówek Grupy – poziom 2 7 Nazwa pola grupy
Stopka Grupy – poziom 2 8 Nazwa pola grupy
Nagłówek Grupy – poziom 3 ...itd. 9...itd. Nazwa pola grupy

Wysokość
Właściwość ta umożliwia określenie wysokości sekcji.

Widoczny
Właściwość ta sprawia, że sekcja jest widoczna lub nie. Przyjmuje wartości Tak i Nie.

Właściwości sekcji
związane z procesem projektowania
Sekcje posiadają grupę właściwości, które mogą być odczytywane i zmieniane jedynie w procesie projektowania. Ważnym
jest odróżnianie ich od innych właściwości, które dostępne są podczas pracy raportu, po ich ustawieniu.

Można powiększać, można zmniejszać


Są to dwie, różne właściwości, umożliwiające określenie, czy sekcja może zmieniać swój rozmiar, w celu reagowania na
zmiany wielkości formantów. Jeśli w sekcji z właściwością Można powiększać ustawioną na Tak umieścisz formant
zawierający więcej rekordów, dzięki właśnie tej właściwości dane zostaną wyświetlone poprawnie.

Formanty mogą zmieniać swoje rozmiary inaczej niż przewidywałeś, jeśli stykają się z innymi formantami. Ponieważ
właściwość ta dotyczy jedynie wysokości sekcji (nie wpływa na szerokość czy pozycję), pamiętaj, by sprawdzić, czy
formanty na pewno na siębie nie nachodzą.

Duże formanty (np. obiekty OLE) mogą utrudniać zmniejszanie innych formantów w sekcji, ponieważ powiększanie i
zmniejszanie odbywa się linia po linii. W celu zmniejszenia sekcji należy w formancie OLE umieścić pusty obrazek.

Rozmiar nagłówków i stopek stron nie może się zmieniać, więc umieszczone w tych sekcjach formanty muszą odpowiadać
ich rozmiarom.

Nowy wiersz lub kolumna


Przy tworzeniu raportów kolumnowych ustawienia właściwości Nowy wiersz lub kolumna dają Ci dużą kontrolę nad
wyglądem raportu. Ustawienia te opisane są w tabeli 10.6.

Tabela 10.6.
Ustawienia właściwości Nowy wiersz lub kolumna

Nazwa Wartość Opis


Nie 0 Kontrolę nad układem wierszy i kolumn sprawują wartości z okna
dialogowego Ustawienia strony. Są to wartości domyślne.
Przed sekcją 1 Każda sekcja zaczyna się od nowego wiersza lub kolumny.
Jeśli wystarczy miejsca, nowa sekcja może współdzielić kolumnę
lub wiersz.
Po sekcji 2 Po wydrukowaniu sekcji tworzony jest nowy wiersz lub kolumna.
Część III ♦ Interfejs użytkownika 178

Przed i po 3 Każda sekcja zaczyna się od nowego wiersza lub kolumny.

Powtórz sekcję
Użytkownicy i programiści aplikacji Accessa często skarżyli się, że zdarza się, iż gdy grupa przenoszona jest na nową
stronę, jej nagłówek pozostaje na stronie poprzedniej. Ustawienie właściwości Powtórz sekcję na Tak spowoduje, że
nagłówek bieżącej grupy zostanie umieszczony na nowej stronie.

Właściwości sekcji (podczas działania raportu)


Do opisanych poniżej właściwości programista ma dostęp po uruchomieniu raportu. Może dzięki nim modyfikować
zachowanie i wygląd raportów, reagując w ten sposób na zachowanie danych i inne warunki.

Wymuszaj nową stronę


Właściwość ta jest krokiem naprzód w nadzorowaniu podziału strony. Może być ona użyta podczas drukowania raportu.
Ustawiając tę właściwość (opartą na danych ze źródła rekordów), możesz kontrolować podział strony w odniesieniu do
układu sekcji. Tabela 10.7 zawiera ustawienia tej właściwości.

Tabela 10.7.
Ustawienia właściwości Wymuszaj nową stronę

Nazwa Wartość Opis


Nie 0 Ustawienie domyślne. Bieżąca sekcja drukowana jest na bieżącej stronie
Tak 1 Nowa sekcja zaczyna się od nowej strony

Trzymaj razem
Poprawne działanie tej właściwości zależy od spełnienia kilku warunków. Gdy ustawiona jest ona na Tak, Access będzie
usiłował wydrukować całą sekcję na jednej stronie. Jeśli to nie będzie możliwe, spróbuje on umieścić sekcję na nowej
stronie. Jeśli to również się nie powiedzie, grupa zostanie umieszczona na więcej niż jednej stronie. W przeciwieństwie do
analogicznej właściwości dla grupy, w przypadku sekcji Trzymaj razem dotyczy tylko jednej, konkretnej sekcji.

PrzenieśUkład, NastępnyRekord i DrukujSekcję


Właściwości te umożliwiają kontrolowanie tego, co i w jaki sposób jest drukowane.
u PrzenieśUkład – ustawienie True (Prawda) umożliwi Accessowi przejście do drukowania następnego elementu
strony. Ustawienie False (Fałsz) sprawia, że raport nie przechodzi do drukowania następnego elementu strony.
u NastępnyRekord – gdy właściwość ta ustawiona jest na True, raport przejdzie do następnego rekordu ze źródła
rekordów (co nie nastąpi w przypadku ustawienia False).
u DrukujSekcję – ustawienie True – sekcja będzie drukowana, False – nie.

Właściwości te nadzorują sposób, w jaki raport odczytuje dane ze źródła, przygotowuje stronę do wydruku oraz drukuje
daną sekcję. Użyte razem, właściwości te mogą powtarzać dane, tworzyć puste wiersze, drukować różne wiersze w tej
samej linii lub pomijać określone wiersze.

Tabela 10.8 zawiera szczegóły użycia tych właściwości oraz ich rezultaty.

Tabela 10.8.
Sekcje wraz z ich indeksami oraz stałymi

Oczekiwany rezultat MoveLayout NextRecord PrintSection


Drukuj każdy wiersz, jeden po drugim True True True
Zostaw puste miejsce True True False
Powtórz wiersz True False True
Zostaw puste miejsce, pozostań przy tym samym True False False
wierszu danych
179 Rozdział 10. ♦ Tworzenie raportów

Drukuj różne wiersze w tej samej linii False True True


Pozostań w tej samej linii, lecz opuść wiersz danych False True False

LiczbaFormatowań
Właściwość ta zwiększana jest za każdym razem, gdy strona jest formatowana do druku. Sekcja może być formatowana
więcej niż jeden raz. Może się to zdarzyć, gdy sekcja powinna mieścić się na jednej stronie, jednak się nie mieści. W takim
przypadku, Access sformatuje ją raz na pierwotnej stronie i drugi raz na nowej stronie, ustawiając wartość Licz-
baFormatowań na 2. Ma to znaczenie w sytuacji, gdy wykonujesz obliczenia w zdarzeniu Przy formatowaniu, gdyż
obliczenia te mogą wystąpić więcej niż raz, jeśli nie są kontrolowane przez tę właściwość.

LiczbaDrukowań
Właściwość ta zwiększana jest za każdym razem, gdy sekcja jest drukowana. Sekcja może być drukowana więcej niż jeden
raz. Może się to zdarzyć, gdy sekcja powinna mieścić się na jednej stronie, jednak się nie mieści. W takim przypadku, Access
spróbuje wydrukować ją raz na pierwotnej stronie i drugi raz na nowej stronie, ustawiając wartość LiczbaDrukowań na 2.
Ma to znaczenie w sytuacji, gdy wykonujesz obliczenia w zdarzeniu Przy wydruku, gdyż obliczenia te mogą wystąpić
więcej niż raz, jeśli nie są kontrolowane przez tę właściwość.

ByłKontynuowany, BędzieKontynuowany
Są to właściwości o ograniczonym zastosowaniu. Ustawiane są, gdy sekcja przeszła lub przejdzie na nową stronę. Ich
zastosowanie jest ograniczone, gdyż osoba pisząca raport w Accessie nie jest w stanie stwierdzić, czy nakładanie się
spowodowane jest przez dane czy przez puste miejsca. Dlatego też, właściwość BędzieKontynuowany jest zazwyczaj usta-
wiona na True dla każdej strony raportu. Wydaje się, że jedynym sposobem na pokonanie tego braku „inteligencji”
programu jest upewnienie się, iż wysokość sekcji dzieli się równomiernie na możliwą do zadrukowania przestrzeń na
stronie.

Właściwość ByłKontynuowany ustawiana jest w zdarzeniu Przy formatowaniu. Ustawienie True występuje, gdy
kontynuowana była sekcja z poprzedniej strony. Jednakże trudno jest znaleźć zastosowanie dla tej właściwości, gdyż jej
wartość jest ustawiana zbyt późno, by wykorzystać ją w raporcie.

Programowe tworzenie raportów


Prawdopodobnie największym wyzwaniem dla programisty jest stworzenie raportu dla danych, które ulegają ciągłym
zmianom. Wyobraźmy sobie okresowy raport o sprzedaży produktów według regionów. Załóżmy też, że musi mieć on
postać tabeli. Jeśli raport oparty jest na kwerendzie krzyżowej, nazwy kolumn użyte jako ich nagłówki będą się praw-
dopodobnie zmieniać co miesiąc. Będzie to problem dla związanych formantów w raporcie. Jednym z możliwych
rozwiązań jest programowe tworzenie raportu za każdym razem, gdy jest to konieczne. Można tego dokonać przy użyciu
modułu VBA.

Przedstawiony moduł VBA mógłby, z pewnymi poprawkami, zostać umieszczony w zdarzeniu raportu Przy otwarciu i po
prostu modyfikować istniejący raport. By jednak dobrze zrozumieć tworzenie raportu z samego kodu, musi to być osobny
moduł.

Dla zachowania prostoty, w naszym przykładzie używamy obiektów DAO. Ponieważ obiekty ADO nie umożliwiają
tworzenia kwerend krzyżowych, użycie DAO oszczędzi nam konieczności tworzenia tymczasowej tabeli, umożliwi
wykorzystanie znanej już większości czytelników techniki uzyskiwania dostępu do danych oraz skoncentrowanie się na
kwestiach związanych z raportem.

Tworzenie źródła rekordów


Pierwszym krokiem jest stworzenie źródła rekordów. Przedstawiona w listingu 10.4 funkcja o nazwie
MakeCrosstabQuery posiada dwa argumenty danych: datFrom i datTo. Określają one okres, jakiego raport dotyczy. Jeśli
definicja kwerendy nie istnieje, zostanie utworzona przez funkcję. W przeciwnym wypadku po prostu zaktualizowana
zostanie właściwość SQL definicji kwerendy. Do funkcji tej będziemy się odwoływać z funkcji tworzącej raport, jednakże
mogłaby być wykorzystywana przez samą siebie do innych celów.

Wydruk 10.4. Programowe tworzenie kwerendy krzyżowej


Function MakeCrosstabQuery(datFrom As Date, datTo As Date) As Boolean
Część III ♦ Interfejs użytkownika 180

' Obsługa błędów w kodzie


On Error Resume Next

Dim db As Database
Dim qrydef As querydef
Dim strSQL As String

Set db = CurrentDb

' Upewnij się, że znasz wszystkie obiekty w pojemniku, używając


' procedury Refresh (odśwież)
db.QueryDefs.Refresh

' Pobierz kwerendę


Set qrydef = db.QueryDefs("Ilość dostarczona według regionów")

' Jeśli kwerenda nie istnieje, utwórz obiekt. Jeśli obiekt nie
' istnieje, obiekt Err zwróci komunikat o błędzie 3265.
If (3265 = Err) Then

Set qrydef = db.CreateQueryDef( _


"Ilość dostarczona według regionów")

' Jako, że utworzyłeś nowy obiekt, odśwież pojemnik


db.QueryDefs.Refresh

' Zanim przejdziesz dalej, wyzeruj obiekt Err


Err = 0

End If

' Dla skrócenia procedury załóż, że daty są poprawne


datFrom = CStr(datFrom)
datTo = CStr(datTo)

' Utwórz procedurę SQL


strSQL = strSQL & "TRANSFORM Sum([Order Details].Quantity) "
strSQL = strSQL & "AS SumOfQuantity "
strSQL = strSQL & "SELECT Products.ProductName "
strSQL = strSQL & "FROM Products INNER JOIN "
strSQL = strSQL & "(Orders INNER JOIN [Order Details] ON _
Orders.OrderID = "
strSQL = strSQL & "[Order Details].OrderID) ON Products.ProductID _
= [Order Details].ProductID "
strSQL = strSQL & "WHERE (((Orders.OrderDate) Between #" & datFrom _
& "# And #" & datTo & "#) AND "
strSQL = strSQL & "((Orders.ShipRegion) Is Not Null)) "
strSQL = strSQL & "GROUP BY Products.ProductName "
strSQL = strSQL & "ORDER BY Orders.ShipRegion "
strSQL = strSQL & "PIVOT Orders.ShipRegion; "

' Skoro obiekt został już utworzony, wystarczy zmienić


' procedurę SQL zmieniając właściwość SQL
qrydef.SQL = strSQL

If (Err) Then
' W tym miejscu przekaż błąd do twojego modułu zajmującego
' się ich poprawianiem
Exit Function
End If

' Zamknij obiekt Kwerenda


qrydef.Close
db.QueryDefs.Refresh

End Function

Po utworzeniu kwerendy możesz przejść do tworz,enia raportu.

Funkcja PrepareCrosstabReport() zawiera dwa argumenty danych: datFrom i datTo. Zostaną one przekazane do
funkcji MakeCrosstabQuery. Funkcja ta będzie również korzystać z ikony bazy danych, obiektu recordset (zestaw
rekordów), bardzo ważnego obiektu Raport i kilku innych zmiennych, użytych jako liczniki.

Tworzenie obiektu Raport


Funkcja PrepareCrosstabReport() utworzy nową kwerendę, uruchomi ją, a następnie utworzy nowy obiekt Raport, który
będzie zgodny z właściwościami nowej kwerendy. Po utworzeniu obiektu Raport funkcja przejdzie do umieszczenia w
sekcjach raportu formantów oraz związaniu ich ze źródłem danych. Ponieważ Access numeruje formanty w kolejności ich
tworzenia, sprawowanie kontroli nad tym, czy formanty następują po sobie w tej samej kolejności co etykiety, wydaje się
być ułatwione. Aby to osiągnąć, funkcja tworzy etykiety i wiąże formanty w osobnych pętlach. Stopka raportu tworzona
jest przy użyciu procedury RunCommand obiektu DoCmd, a następnie jej właściwość Widoczny (Visible) zmieniana jest na
181 Rozdział 10. ♦ Tworzenie raportów

True. Osobna pętla tworzy i rozmieszcza formanty zawierające funkcję Suma(). Ustawiana jest wysokość sekcji Szczegóły
(Detail), przydzielane jest źródło rekordów, by na końcu otworzyć raport.

Wydruk 10.5. Tworzenie raportu przy użyciu kodu


Public Function PrepareCrosstabReport(datFrom As Date, datTo As Date) As Boolean
On Error GoTo PrepareCrosstabReport_Err
Dim db As Database
Dim DocName As String
Dim rs As Recordset
Dim rpt As Report
Dim i As Integer
Dim x As Integer

Set db = CurrentDb()

'Wyzeruj kwerendę, by używać nowych danych i otwórz ją


MakeCrosstabQuery datFrom, datTo

Set rs = db.OpenRecordset("Ilość dostarczona według regionów")

' Utwórz obiekt Raport


Set rpt = CreateReport("", "")
rpt.Caption = " Ilość dostarczona według regionów Between " & _
datFrom & " and " & datTo
' Teraz musisz utworzyć formanty
Dim ctlNew As Control

' Do wypełnienia jest dziewięć formantów, więc...


If rs.Fields.Count - 1 > 9 Then
x = 9
Else
x = rs.Fields.Count - 1
End If

' Utwórz, rozmieść, zwiąż i sformatuj formanty


For i = 0 To x
Set ctlNew = CreateReportControl(rpt.Name, acTextBox, acDetail)
With ctlNew
.Height = 270
.Width = 1080
.Top = 0
.Left = (60 + .Width) * i
rpt("text" & i).ControlSource = rs.Fields(i).Name
End With
Next

For i = 0 To x
Set ctlNew = CreateReportControl(rpt.Name, acLabel, acPageHeader)
With ctlNew
.Height = 270
.Width = 1080
.Top = 0
.Left = (60 + .Width) * i
' Indeksy przyznawane są bez twojego udziału, więc
' kontroluj je!
rpt("label" & i + x + 1).Caption = rs.Fields(i).Name
End With
Next

DoCmd.RunCommand acCmdReportHdrFtr
rpt.Section(acFooter).Visible = True

For i = 0 To x
Set ctlNew = CreateReportControl(rpt.Name, acTextBox, acFooter)
With ctlNew
.Height = 270
.Width = 1080
.Top = 0
.Left = (60 + .Width) * i
' Indeksy przyznawane są bez twojego udziału, więc
' kontroluj je!
If i = 0 Then
rpt("text" & i + (2 * x) + 2).ControlSource = "='Suma'"
Else
rpt("text" & i + (2 * x) + 2).ControlSource = _
"=sum([" & rs.Fields(i).Name & "])"
End If
End With
Next

rpt.Section("detail").Height = 0

rpt.RecordSource = " Ilość dostarczona według regionów"

DoCmd.OpenReport rpt.Name, acViewPreview


'Normalnie, to zostałoby wydrukowane

PrepareCrosstabReport = True
PrepareCrosstabReport_Exit:
Set rpt = Nothing
Część III ♦ Interfejs użytkownika 182

rs.Close
Exit Function

PrepareCrosstabReport_Err:
PrepareCrosstabReport = False
MsgBox Error$
Resume PrepareCrosstabReport_Exit

End Function

Mamy teraz raport oparty na kwerendzie krzyżowej, który jest dynamicznie tworzony za każdym razem, gdy tego
zażądamy. Ponieważ raport korzysta z wybranego źródła rekordów, nie jest nigdy problemem zmiana nagłówka kolumny
czy ilości regionów, których raport dotyczy (w ramach jego wewnętrznych ograniczeń).

Tworzenie sekcji
Sekcje również mogą być tworzone programowo, jednakże nie wszystkie sekcje tworzone są w ten sam sposób. Aby
utworzyć nagłówki i stopki grup, Access posiada funkcję CreateGroupLevel. Ponieważ pięć standardowych sekcji
(Nagłówek/Stopka raportu, Nagłówek/Stopka strony i Szczegóły) nie jest częścią schematu grupowania raportu, tworzone są
w inny sposób.

Funkcja CreategroupLevel posiada cztery argumenty:


u StrReport – ciąg identyfikujący raport, który chcesz modyfikować.

u StrExpr – wyrażenie poziomu grupy, zazwyczaj nazwa pola, rodzaj obiektu lub data.

u FHeader/FFooter – wartości logiczne, służące do tworzenia dodatkowego nagłówka lub stopki sekcji. Wartość
True – sekcja jest tworzona, False – nie.
createGroupLevel "_Kategorie i produkty" , "newGroupsection" , 1, 1

lub
intSection=createGroupLevel ("_Kategorie i produkty" ,
"newGroupSection" , 1, 1)

Aby utworzyć nagłówki i stopki raportu lub strony, skorzystaj z metody RunCommand obiektu DoCmd:
DoCmd.RunCommand acCmdReportHdrFtr

Wskazówki
Większość aplikacji posiada co najmniej jeden raport, który przysparza wielu problemów. Aby umożliwić Ci radzenie
sobie przynajmniej z częścią z nich, damy teraz kilka wskazówek związanych z raportami.

Tworzenie grupowania dwutygodniowego


Jeśli grupujesz dane na dany dzień i chcesz uzyskać grupowanie dwutygodniowe (na przykład podczas tworzenia listy
płac), w oknie dialogowym Sortowanie i grupowanie ustaw właściwość Grupuj według na Interwał, a właściwość Przedział
grupowania na 2.

Ukryj powtarzające się dane


Może zdarzyć się, że w prostym raporcie tabelarycznym informacja powtarza się w kolejnych wierszach. Aby tego uniknąć,
ustaw właściwość Ukryj Duplikaty danego formantu na Tak. Umożliwi Ci to uzyskanie wyglądu przypominającego
grupowanie, jednak bez użycia sekcji oraz drukowanie danych określających grupę i pierwszej linii szczegółów w tym
samym wierszu.

Alfabetyczne grupowanie danych


W raporcie wyświetlającym listę klientów według pola NazwiskoKlienta możesz, wykonując poniższe kroki,
alfabetycznie podzielić klientów na grupy:
183 Rozdział 10. ♦ Tworzenie raportów

56. W oknie dialogowym Sortowanie i grupowanie ustaw właściwość Grupuj według na Pierwsze znaki.
57. Właściwość Przedział grupowania ustaw na 1 ( rysunek 10.16). Jest to ważne, gdyż stąd właśnie Access wie, ilu
znaków ma użyć, dzieląc klientów na grupy. W takim przypadku, będzie zwracał uwagę na pierwszą literę
nazwiska klienta.

Rysunek 10.16.
Ustawienia
grupowania

58. Ustaw źródło formantu z nazwiskiem klienta na:


=Left([NazwiskoKlienta]], 1)

Tworzenie numerowanych list


Użycie właściwości Suma bieżąca w połączeniu ze źródłem formantu umożliwi raportowi numerowanie obiektów na
liście. Na rysunku 10.17 znajduje się przykład raportu z ponumerowanymi obiektami. Numerowanie może zaczynać się od
nowa dla każdej grupy lub być kontynuowane przez cały raport.

Rysunek 10.17.
Rezultat
numerowania

59. Umieść w raporcie formant, który będzie zawierał numer pozycji.


60. Ustaw źródło formantu na =1. Będzie to początek schematu numerowania.
61. Ustaw właściwość Suma bieżąca formantu na Wszędzie lub W grupie.

Tworzenie pustych linii co n znaków


W rozdziale tym opisaliśmy, jak przy użyciu właściwości PrzenieśUkład, NastępnyRekord i DrukujSekcję tworzyć puste
linie. Wydruk 10.6 jest przykładem takiego kodu. Można go umieścić w większości raportów. By zmienić częstotliwość
tworzenia pustych linii, wystarczy zmodyfikować stałą intSkipLine.

Wydruk 10.6. Tworzenie pustych linii co n znaków


Option Compare Database

Dim intCurrLine As Integer


Const intSkipLine = 3

Private Sub Detail_Format(Cancel) As Integer, FormatCount As Integer)

If intCurrLine Mod (intSkipLine + 1) = 0 Then


Me.NextRecord = False
Me.PrintSection = False
End If
Część III ♦ Interfejs użytkownika 184

intCurrLine = intCurrLine + 1

End Sub

Private Sub Report_Open(Cancel As Integer)

cLines = 0

End Sub

Zerowanie numeru strony dla nowych grup


Ponieważ właściwość Page (strona) sekcji jest zapisywana lub odczytywana podczas uruchamiania raportu, można ją
zmieniać przy każdym formatowaniu nagłówka grupy. Właściwość ta nie powinna być mylona z właściwością Strony,
która nie może być zapisywana podczas działania raportu. Poniższy kod zeruje liczbę stron. Przydaje się on, gdy grupy
zajmują więcej niż jedną stronę.
Sub GroupHeader_Format
Page=1
End Sub

Rysowanie pionowych linii


Tworzenie w raporcie pionowych linii może być dokonane z pomocą zaledwie kilku linijek kodu. Aby rysować linie w
zdarzeniu Przy formatowaniu, ustaw pozycje i wywołaj metodę Line. Używaną tutaj miarą są twipy (1,440 cala).

Wydruk 10.7 zawiera przykład procedury rysującej linię.

Wydruk 10.7. Rysowanie poziomych linii przy użyciu kodu


Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)

Dim x1 As Single

'Pozycja pozioma przeliczona z cali na twipy


x1 = 3 * 1440
' Użyj procedury raportu Line, gdzie
' x1, y1 to współrzędne początkowe, a
' x2, y2 to współrzędne końcowe
Me.Line (x1, 1) – (x1, 32000)

End Sub

Przesuwanie numerów parzystych i nieparzystych stron


Jeśli zajdzie potrzeba umieszczenia numerów stron parzystych po prawej, a nieparzystych po lewej stronie, pomocna będzie
poniższa funkcja. Możesz chcieć jej również użyć przy tworzeniu marginesu do oprawy.

Wydruk 10.8 zawiera przykład takiej techniki.

Wydruk 10.8. Zmiana pozycji numerów parzystych i nieparzystych stron


Private Sub Detail_Print(Cancel As Integer, PrintCount As Integer)

If (Me!txtpagenumber Mod 2 = 0) Then


txtpagenumber.TextAlign = 3 'Lewy
Else
txtpagenumber.TextAlign = 1 'Prawy
End If

End Sub

Identyfikacja użytkownika drukującego raport


Jeśli Twoja baza danych Accessa jest zabezpieczona, możesz określić identyfikator użytkownika drukującego raport oraz
użyć tego identyfikatora do uzyskania nazwiska tego użytkownika. Wpisz poniższe wyrażenie jako źródło niezwiązanego
formantu:
185 Rozdział 10. ♦ Tworzenie raportów

=ObecnyUżytkownik()

lub
=dlookup("TabelaUżytkowników" , "[Nazwisko]", "[IDUżytkownika]= " & ObecnyUżytkownik() & ")

Wyrównanie stron do oprawy


Gdy strony mają być oprawione jak książka, musi być na nich miejsce na umieszczenie oprawy. Oznacza to, iż zawartość
stron nieparzystych musi być przesunięta w prawo, a parzystych w lewo. Czynność taką wykonuje kod z wydruku 10.9.

Wydruk 10.9. Wyrównywanie stron do oprawy


Private Sub PageFooterSection_Format(Cancel As Integer, _
FormatCount As Integer)
Dim ctl As Control
If (Me.Page Mod 2 = 0) 'Strona jest parzysta
For Each ctl In Me.Controls
.Left = .Left + 1440 'przesuwa wszystko o jeden cal w lewo
Next
Else 'strona jest nieparzysta
For Each ctl In Me.Controls
.Left = .Left – 1440 'przesuwa wszystko o jeden cal w prawo
Next
End If
End Sub

Obliczanie podsumowań strony


Access wyświetli komunikat o błędzie, jeśli będziesz próbował umieścić funkcję podsumowującą (np. Suma()) w
formancie znajdującym się w nagłówku lub stopce strony. Ponieważ często pojawia się konieczność podsumowania
strony, jest to dość niewygodne. Z pomocą prostego kodu można wykonać obliczenia podsumowujące wartości na stro-
nie, a następnie wyświetlić je poprzez niezwiązany formant w stopce strony. Aby skorzystać z kodu użytego w
przykładzie, konieczne jest wykonanie następujących czynności:
62. W oparciu o tabelę Faktury utwórz prosty raport. W części Szczegóły umieść pola NazwaOdbiorcy i
CenaJednostkowa.
63. W części Szczegóły umieść ponownie pole CenaJednostkowa i zmień jego nazwę na SumaBieżąca. Ustaw
właściwość Widoczny na Nie i Suma bieżąca na Wszędzie.
64. W stopce strony umieść niezwiązane pole tekstowe i nazwij je txtPageSubtot.
65. Kod z listingu 10.10 wprowadź do zdarzenia stopki strony Przy wydruku.

Wydruk 10.10. Obliczanie podsumowania strony


Option Compare Database
Dim x As Double
Private Sub PageFooterSection_Print(Cancel As Integer, _
PrintCount As Integer)
txtpagesubtot = RunningSum – x
x = RunningSum

End Sub

'Teraz raport będzie zawierał podsumowania stron

Precyzyjne przesuwanie formantów


Aby zminimalizować ryzyko przesunięcia formantów, do ich zaznaczania możesz używać następujących technik:
u Kliknij linijkę, by zaznaczyć formanty znajdujące się w określonym miejscu.
u Kliknij tło raportu i przeciągnij zaznaczenie na odpowiednie formanty bez poruszania ich.
u Do przechodzenia między formantami używaj klawisza Tab.
u Kombinacja klawisza Ctrl i strzałek umożliwia precyzyjne przesuwanie formantu oraz przemieszczanie formantów
między sekcjami.

Kombinacja klawisza Shift i strzałek umożliwia zmianę rozmiaru formantów bez przesuwania ich.
Część III ♦ Interfejs użytkownika 186
Część IV
Tajniki VBA
W tej części:
u Tworzenie obiektów przy użyciu modułów klasowych.
u Usuwanie błędów w aplikacjach Accessa.
u Profesjonalna obsługa błędów.
u Optymalizacja aplikacji.
Rozdział 11.
Tworzenie obiektów przy użyciu
modułów klas
W tym rozdziale:
u Korzyści z używania obiektów.
u Przegląd obiektów, własności i metod.
u Tworzenie klas.
u Tworzenie właściwości.
u Tworzenie metod.
u Tworzenie zdarzeń.
u Użycie obiektów.
u Tworzenie kopii obiektów.
u Przegląd innych obiektów.
u Implementacja obiektu do obsługi błędów.
u Użycie obiektów w połączeniu ze zbiorami VBA.

Tworzenie obiektów jest jednym z najskuteczniejszych sposobów na pisanie i obsługę aplikacji. Zanim przejdziemy do
omówienia korzyści płynących z użycia obiektów, zdefiniujmy podstawowe pojęcia.

Obiekty to rzeczy. Samochody, budynki i komputery to różne typy obiektów. W języku programistów słowo obiekt
oznacza jedną, określoną rzecz, na przykład formularz lub formant. Z pewnością już spotkałeś się z tego typu
wbudowanymi obiektami.

W trakcie swojej ewolucji Microsoft Access stał się programem zorientowanym obiektowo, umożliwiającym tworzenie
własnych obiektów i metod dla tych obiektów. Takie obiekty to na przykład: obiekt klient, obiekt faktura, obiekt
użytkownik, obiekt łącze da-

nych czy obiekt dźwięk. Na dołączonej do książki płycie CD znajdziesz wiele stworzonych przez nas obiektów, które
będziesz mógł wykorzystywać do własnych potrzeb („Tworzenie obiektów z modułów klas.mdb” – rysunek 11.1).

Rysunek 11.1.
Przykłady obiektów
własnych, znajdujące
się na dołączonej
płycie CD-ROM
189 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Obiekty tworzone są przy użyciu modułów klasowych. Moduł klasowy to odrębna, przenośna, zaprojektowana w
określonym celu jednostka kodu. Klasa określa właściwości i metody każdego z obiektów klasy.

Programiści często mieszają pojęcia klasa i obiekt. Klasa to opis lub szablon właściwości i metod obiektu. Gdy programista
chce użyć kodu w module klasy, tworzony jest egzemplarz klasy. Ten egzemplarz to obiekt.

Stąd też określenie „tworzenie egzemplarza obiektu” jest niepoprawne. Obiekt sam w sobie jest egzemplarzem! Pojedynczy
obiekt definiowany jest jako egzemplarz klasy. Z jednej klasy można utworzyć wiele obiektów, z których każdy będzie miał inne
właściwości.

Rozdział ten poświęcony jest tworzeniu obiektów przy użyciu modułów


klasowych. Pamiętaj, że moduły formularza są modułami klasowymi. W
taki sam sposób, jak dodajesz właściwości i metody do własnych obiektów,
możesz też dodawać właściwości i metody do formularzy.

Korzyści z używania obiektów


Z tworzenia i używania obiektów płynie wiele korzyści, w tym: ukrywanie złożonego zestawu funkcji kodu, użycie
IntelliSense, prostsze tworzenie i utrzymanie kodu oraz wiele innych.

Ukrywanie złożoności
Ukrywanie złożoności to jedna z korzyści płynących z używania obiektów. Doświadczony programista może tworzyć
złożone procedury, na przykład procedury Windows API, kod dostępu do danych, procedury ciągów i inne. Mniej
doświadczeni programiści mogą korzystać z obiektów, odwołując się do ich właściwości i metod bez konieczności zro-
zumienia kodu, dzięki któremu obiekty te działają.

Użycie technologii Microsoft IntelliSense


Aby używać obiektu, programista musi jedynie określić jego właściwość
lub metodę przy użyciu technologii IntelliSense (rysunek 11.2).
Przykładowo, jeden ze znajdujących się na naszej płycie CD obiektów to
obiekt służący do obsługi błędów w aplikacjach Accessa. Ponieważ cały
kod tego obiektu zawarty jest w obiekcie cError, programista musi tylko
określić cechy swojego obiektu oraz właściwość lub metodę, której chce
użyć. Przykładowo, gdyby programista chciał, by konsekwencją
wystąpienia błędu w aplikacji było wysłanie e-maila, wystarczyłoby
odwołanie do metody „e-mail”:
Część IV ♦ Tajniki VBA 190

cError.email

Rysunek 11.2.
Obiekty umożliwiają
Ci użycie technologii
Microsoft
IntelliSense

Zauważ, jak proste jest używanie obiektów. Korzystając z technologii Microsoft IntelliSense, wpisujesz po prostu nazwę
obiektu (cError) i kropkę, a wyświetlone zostaną wszystkie właściwości i metody tego obiektu. To znacznie ułatwia
pisanie odpowiedniego kodu.

Organizowanie kodu
Tworzenie klas ułatwia organizowanie kodu, co czyni go łatwiejszym do czytania, przeglądania i obsługiwania. Cały kod
dotyczący konkretnego zestawu funkcji zawarty jest wewnątrz danej klasy. Umieszczanie kodu w tym samym miejscu co
właściwości i metod opisujących obiekt nazywamy hermetyzacją.

Dopuszczenie przeglądania obiektów w Object Browser


Umieszczenie kodu w klasach umożliwia programistom użycie narzędzia Object Browser w celu przeglądania właściwości,
metod i innych informacji o obiekcie. W dalszej części tego rozdziału przyjrzymy się jednemu z obiektów własnych w tym
narzędziu.

Tworzenie wielu egzemplarzy obiektów


Wyobraź sobie, że istnieje fragment kodu, którego używasz wielokrotnie w różnych miejscach aplikacji. W rzeczywistości,
kod ten może być używany niezliczoną ilość razy jednocześnie. Przykładem tego może być kod łączenia do danych. Za
każdym razem, gdy użytkownik poszukuje nowego klienta, otwiera formularz lub używa listy wyboru, z serwera pobierane
są dane. Zamiast tworzyć duplikat kodu w każdej z tych procedur lepiej jest utworzyć obiekt Data Connection,
zawierający kod, który będzie służył do pobierania danych z serwera.

Tworzenie kodu łatwego do aktualizacji i utrzymania


Używając klas, możesz w aplikacji wielokrotnie użyć jednostki kodu bez powtarzania go. Jeśli, przykładowo, w wielu
procedurach powtarzasz kod dostępu do danych, w przypadku gdy zajdzie potrzeba wprowadzenia zmian, każde miejsce, w
którym znajduje się ten kod, musi zostać odnalezione i zmodyfikowane. Postępowanie takie jest bardzo czasochłonne i
mało wydajne. Gdyby w tej sytuacji użyć obiektu Data Connection, aktualizacja i wszystkie zmiany w kodzie dostępu do
danych byłyby dokonywane w jednym miejscu – module klasy.

Ograniczenie dostępu do kodu


Klasy umożliwiają Ci sprawowanie kontroli nad tym, kto i w jakich okolicznościach używa kodu. Dzięki klasom możesz
zabezpieczać właściwości i metody, kontrolując ich pojawianie się na zewnątrz klasy.
191 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Tworzenie przenośnego kodu


Ponieważ moduł klasy jest odrębną jednostką kodu, może być z łatwością przenoszony z jednej aplikacji Accessa do
innych.

Przegląd obiektów, właściwości i metod


Zanim przejdziemy do tworzenia obiektów, zatrzymajmy się przy podstawowych wiadomościach. Jeśli nie będziemy mieli
jasności co do terminów: obiekt, właściwości i metody, przejście do dalszej części rozdziału nie będzie miało sensu.

Obiekt jest to element, który może być programowany, obrabiany i kontrolowany. W Accessie obiektami są formularze,
pola tekstowe, przyciski poleceń i inne. W tym rozdziale zajmiemy się tworzeniem własnych obiektów.

Właściwość jest to cecha obiektu. Może być ona postrzegana jako przymiotnik, gdyż opisuje i charakteryzuje obiekt. W
Accessie właściwościami pola tekstowego są: Nazwa, Widoczny, Kolor pierwszego planu i inne. Większość
właściwości obiektu może być zarówno ustawiana, jak i pobierana. W tym rozdziale pokażem,y jak tworzyć własne
właściwości i kontrolować, czy będą one ustawiane, czy pobierane.

Metoda jest to czynność, jaką można wykonać na obiekcie. Może być ona postrzegana jako czasownik. Przykładowo, jedną
z metod w formularzu Accessa jest Close. W tym rozdziale pokażemy, jak tworzyć własne metody dla obiektów.

Tworzenie klas
Do tworzenia klasy używany jest moduł klasowy. Klasa definiuje właściwości, metody i zdarzenia, tworząc jasno
określony i dobrze opisany interfejs.

Wstawianie modułu klasowego


Tworzenie klasy jest bardzo proste. Trochę więcej wysiłku wymaga dodawanie do obiektu właściwości i metod.

Aby utworzyć klasę, wstaw do swojej aplikacji moduł klasy i nazwij go. Nazwa tego modułu klasy będzie nazwą Twojego
obiektu.

Aby wstawić moduł klasy, z menu Wstaw wybierz Moduł klasy. Uruchomiony zostanie edytor VBA. W oknie kodu możesz
wpisywać dowolne właściwości, metody i zdarzenia dla obiektu. Zanim przejdziemy dalej, nazwij ten moduł klasowy
(rysunek 11.3).

Rysunek 11.3.
Używaj jednolitego
nazewnictwa
modułów klasy

Zwracaj uwagę na nazewnictwo modułów klasy, gdyż będą to nazwy Two-


ich obiektów. W ten sposób programiści, przy użyciu technologii Intel-
liSense, będą uzyskiwali dostęp do napisanego przez Ciebie kodu. Warto
również poprzedzić nazwę obiektu inicjałami firmy, aby móc później bez
trudu stwierdzić, który z obiektów został stworzony przez Twoją firmę.
Część IV ♦ Tajniki VBA 192

Tworzenie właściwości
Istnieją dwa sposoby tworzenia właściwości klasy: zmienne jawne i procedury właściwości.

Kod znajdujący się na dołączonej płycie CD zawiera wiele obiektów. Naj-


prostszy z nich, obiekt cUser, wykorzystamy jako przykład na następnych
stronach. Obiekt cUser przechowuje informacje o aktualnie zalogowanym
użytkowniku, w tym jego lub jej imieniu. Obiekt ten może być użyty, gdy
aplikacja wymaga imienia użytkownika, na przykład przy obsłudze błędów
czy przy zapisywaniu autora notatek czy dokumentów. W naszym
przykładzie wykorzystamy obiekt cUser do zapisywania dat i czasów
logowania użytkowników, a jedno ze zdarzeń tego obiektu wykorzystamy
do wyświetlenia wiadomości witającej użytkownika po zalogowaniu.

Użycie zmiennych publicznych


Właściwość może zostać utworzona przez zadeklarowanie zmiennej publicznej w części deklaracyjnej modułu klasowego.

Poniższy przykład tworzy właściwości Imię i TypUżytkownika obiektu cUser:


Public Imię as String
Public TypUżytkownika as String

Po wykonaniu tego prostego kroku użytkownicy mogą ustawiać i pobierać wartości tych właściwości. Do ustawienia tych
właściwości służy następujący kod:
cUser.Imię = "Michał"
cUser.TypUżytkownika = "Kierownik"

Aby pobrać tę właściwość, wystarczy użyć następującego kodu (rysunek 11.4):


MsgBox cUser.Imię
Rysunek 11.4.
Ustawianie
i pobieranie
właściwości
obiektów jest proste
dzięki technologii
IntelliSense

Użycie procedur właściwości


Właściwości mogą być dodawane do obiektów za pomocą specjalnego typu procedur VBA – procedur właściwości.
Istnieją trzy rodzaje procedur właściwości: Property Let dla pobierania wartości właściwości, Property Get dla
ustawiania wartości właściwości oraz Property Set, która umożliwia traktowanie obiektów jak właściwości.

Procedury właściwości umożliwiają Ci określenie, kto może ustawiać i pobierać wartości właściwości. Kluczem do
zrozumienia funkcjonowania procedur właściwości jest to, że wartość właściwości ukryta jest w zmiennej prywatnej
modułu. Stąd też, pierwszy krok to utworzenie zmiennej prywatnej modułu, a następnie tworzenie instrukcji Property
Let i Property Get.
193 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Procedury właściwości, podobnie jak wszystkie inne procedury, mogą być


ustawiane jako jawne i niejawne. Jawne procedury właściwości dostępne są
dla wszystkich innych procedur we wszystkich modułach. Niejawne
procedury właściwości dostępne są jedynie dla procedur w module, w
którym zostały zadeklarowane.

Tworzenie w module zmiennych prywatnych


Gdy używamy procedur właściwości, wartość właściwości ukryta jest w zmiennej prywatnej modułu. Osoba tworząca
klasę określa, czy właściwość ma być dostępna na zewnątrz, czy nie.

Poniżej znajduje się przykład tworzenia zmiennej niejawnej modułu dla właściwości Imię i TypUżytkownika obiektu
cUser:
Option Explicit
' Utwórz zmienną prywatną w części deklaracyjnej'
Private mstrImię as String
Private mTypUżytkownika as String

Property Let
Procedura Property Let używana jest do ustawiania wartości właściwości. Jeśli nie chcesz, aby inni mieli możliwość
ustawiania wartości właściwości, nie dołączaj tej procedury.

Poniższy przykład tworzy procedurę Property Let dla właściwości Imię obiektu cUser:
Public Property Let Imię (ImięUżytkownika as String)
' Weź wartość wpisaną do (ImięUżytkownika) i zapisz ją w zmiennej
' prywatnej (mstrImię).
mstrImię = ImięUżytkownika
End Property

Przyjrzyjmy się teraz tej procedurze. Po pierwsze, jako że procedura Property Let istnieje, właściwość Imię jest
dostępna na zewnątrz i może zostać ustawiona. Programista mógłby ustawić tę właściwość w następujący sposób:
cUser.Name = "Mariusz"

Gdy Mariusz zostanie wprowadzony w procedurze właściwości, zostanie przekazany do zmiennej ImięUżytkownika.
Procedura Property Let pobiera wartość zmiennej ImięUżytkownika (Mariusz) i ukrywa ją w zmiennej prywatnej
modułu – mstrImię. Procedura ta dotyczy jednego parametru, ale do procedury właściwości można przekazać ich wiele.
Wartość właściwości może być pobrana tylko wtedy, gdy istnieć będzie procedura Property Get.

Property Get
Procedura Property Get umożliwia pobieranie wartości właściwości. Jeśli nie chcesz, by inni mogli pobierać wartość
właściwości, nie dołączaj instrukcji Property Get. Instrukcja ta pobiera wartość właściwości ukrytą w zmiennej
prywatnej i zwraca ją jako wartość właściwości. Poniższy przykład zawiera instrukcję Property Get dla właściwości
Imię obiektu cUser:
Public Property Get Imię () as string
' Weź wartość ukrytą w zmiennej prywatnej (mstrImię) i
' umieść ją w wartości właściwości.
Imię = mstrImię
End Property

Użytkownik może z łatwością pobrać wartość właściwości (jeśli instrukcja Property Get istnieje), korzystając z
poniższego kodu:
MsgBox cUser.Imię

Typ danych Property Let musi być taki sam jak Property Get. Przy-
kładowo, instrukcja Property Let dla właściwości Imię akceptuje argu-
ment typu string (ciąg). W takim przypadku, procedura Property Get
musi również zwracać dane typu string.
Część IV ♦ Tajniki VBA 194

Property Set
Instrukcja Property Set umożliwia Ci tworzenie procedury właściwości, która ustawia odniesienie do dowolnego
obiektu. By określić obiekt, użyj w procedurze Property Set słowa kluczowego Set.

W naszym przykładzie użyliśmy obiektu cForm. Obiekt ten posiada właściwość Form, do której musi być przekazany
obiekt Form. Kod w module klasy cForm jest następujący:
Option Compare Database
' Zadeklaruj zmienną prywatną na poziomie modułu
Private mobjForm as Form
Public Property Get Form() As Variant
' Pobierz obiekt znajdujący się w zmiennej prywatnej (mobjForm) i
' umieść go w wartości właściwości.
Set Form = mobjForm
End Property

Public Property Set Form(FormObject)


' Pobierz przekazany obiekt (FormObject) i zapisz go
' w zmiennej prywatnej(mobjForm)
Set mobjForm = FormObject
End Property

Po załadowaniu frmPropertySet formularz przekazywany jest do właściwości Form. Ponieważ jest to obiekt, używamy
słowa kluczowego Set. Nazwa formularz może być wyświetlona w oknie komunikatu. Oto kod dla formularza
frmPropertySet:
' W tym przykładzie korzystamy z obiektu "cForm". Obiekt
' ten posiada właściwość "Form". Gdy ładowany jest formularz
' (frmPropertySet), przekazywany jest jako obiekt do właściwości
' "Form". Gdy klikniesz przycisk "Property Set", pobrana zostanie
' nazwa formularza.
Private mobjForm As cForm
Private Sub cmdClose_Click()
DoCmd.Close acForm, "frmPropertySet", acSaveNo
EndSub

Private Sub cmdPropertySet_Click()


MsgBox "Obiekt formularz (we właściwości 'Form') nazywa się: " _
& mobjForm.Form.Name, vbInformation, "Przykład Property Set"
End Sub
Private Sub Form_Load()
Set mobjForm = New cForm
Set mobjForm.Form = Forms!frmPropertySet
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set mobjForm = Nothing
End Sub

Zmienna publiczna czy procedury właściwości


Najprostszym sposobem tworzenia właściwości klasy jest użycie zmiennych publicznych. Jednakże rozwiązanie to ma
swoje wady. Zmienne publiczne zawsze są dostępne na zewnątrz. Oznacza to, że nie masz kontroli nad tym, kto ustawia i
pobiera wartości właściwości. Może to doprowadzić do sytuacji, w której inni zmieniają wartość właściwości, na której Ty
się opierasz.

Zaletą procedur właściwości jest to, że umożliwiają tworzenie właściwości tylko-do-odczytu i tylko-do-zapisu.
Przykładowo, jeśli chcesz utworzyć właściwość Hasło, możesz chcieć pozwolić użytkownikom zmieniać je, ale nie
pobierać (tylko-do-zapisu). Aby utworzyć procedurę tylko-do-zapisu, wystarczy dołączyć instrukcję Property Let i jed-
nocześnie nie dołączać instrukcji Property Get.

Korzystając z procedur właściwości, możesz również wykonywać czynności w kodzie podczas ustawiania lub pobierania
właściwości.

Tworzenie wyliczeniowych typów danych


Wyliczeniowy typ danych to wartość właściwości, jaką możesz dostarczyć programistom używającym Twoich obiektów.
Przykładowo, być może zauważyłeś, że gdy podczas ustawiania właściwości Widoczny formularza wpiszesz znak
równości, będziesz mógł z rozwijanej listy wybrać wartości True lub False (rysunek 11.5).
195 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Rysunek 11.5
Z rozwijanej listy
wybierz True
lub False

Możesz dostarczać takie wartości właściwości, tworząc typy wyliczeniowe.

W części deklaracyjnej modułu klasowego do określenia wartości właściwości użyj słowa kluczowego Enum. Przykładowo,
załóżmy, że dla właściwości TypUżytkownika obiektu cUser chcesz dostarczyć rozwijaną listę z następującymi
wartościami: Menedżer, Administracja oraz Nieznany. Kod w części deklaracyjnej będzie następujący:
Public Enum ListaUżytkowników
Menedżer
Administracja
Nieznany
End Enum

Następnym krokiem będzie użycie wyliczeniowego typu danych (ListaUżytkowników) jako typu danych właściwości
TypUżytkownika klasy cUser. Ilustruje to poniższy przykład, z właściwością utworzoną jako zmienna jawna:

Przykład 1. Właściwość zadeklarowana jako zmienna string


Public TypUżytkownika as String

Przykład 2. Właściwość zadeklarowana jako wyliczający typ danych


Public TypUżytkownika as ListaUżytkowników

Wartości właściwości mogą być bez trudu ustawiane przy użyciu rozwijanej listy, dostępnej dzięki technologii IntelliSense
(rysunek 11.6).

Rysunek 11.6.
Przykład
wyliczeniowego typu
danych

Aby można było określić, która ze znajdujących się na liście wartości właściwości została wybrana, każdy typ danych jest
numerowany (rozpoczynając od zera, z przyrostem równym 1).
Część IV ♦ Tajniki VBA 196

Wprowadzone wartości właściwości nie są ograniczone do wyliczeniowych


typów danych. W poprzednim przykładzie, wyliczeniowy typ danych
zawierał trzy elementy: Menedżer, Administracja i Nieznany. VBA
nie uniemożliwia programiście zignorowania wartości z listy i wpisania in-
nych (na przykład Produkcja). Aby ograniczyć możliwość wyboru do

listy, użyj wartości liczbowych elementów z listy. Przykładowo, jeśli na liś-


cie są trzy elementy (i numerowanie rozpoczyna się od zera), możesz
uniemożliwić wprowadzanie elementów mniejszych niż zero i większych
niż dwa.

Tworzenie metod
Metoda jest to czynność, jaką możemy wykonać na obiekcie. Aby utworzyć metodę dla klasy, wystarczy utworzyć
publiczną procedurę lub funkcję. Załóżmy, że za każdym razem, gdy użytkownik loguje się do aplikacji, chcesz zapisywać
czas i datę tego zdarzenia. Poniższy kod utworzy metodę Login, wprowadzającą do tabeli datę i czas zalogowania każdego
z użytkowników.
Public Sub Login()
' Utwórz zmienną obiektu dla zestawu rekordów
Dim rst As ADODB.Recordset
' Utwórz zmienną string
Dim strSQL As String
' Instrukcja SQL dla tblUsers
strSQL = "Select * FROM tblUsers"
' Utwórz zestaw rekordów ADO
Set rst = New ADODB.Recordset
' Otwórz zestaw rekordów
rst.Open strSQL, CurrentProject.Connection, adOpenKeyset, _
adLockOptimistic
' Dodaj nowy rekord
rst.AddNew
' Zapisz czas i datę logowania użytkownika
With rst
!Imię = Me.Name
!Data = Date
!Czas = Time
End With
' Zapisz nowy rekord
rst.Update
' Zamknij zestaw rekordów
rst.Close
' Zniszcz zmienną obiektu
Set rst = Nothing
End Sub

Użycie metod
Do użycia metody przy otwieraniu aplikacji służy następujący kod:
cUser.Login

Zauważ, że użytkownicy tej metody nie muszą rozumieć kodu ADO, aby aktualizować wartość w bazie danych.
Wystarczy, że używają właściwości i metod dostępnych dla obiektu wyświetlanego przez IntelliSense.

Tworzenie zdarzeń
Obiekty w Accessie posiadają swoje zdarzenia. Przykładowo, obiekt formularz posiada zdarzenie Przy załadowaniu, a
przycisk polecenia zdarzenie Przy kliknięciu.

Dla własnych obiektów również możesz tworzyć zdarzenia. W tym celu musisz użyć w części deklaracyjnej słowa
kluczowego Event i określić nazwę zdarzenia. Przykładowo, dodajmy zdarzenie Przy powitaniu, które będzie występowało
po otwarciu aplikacji przez użytkownika. W części deklaracyjnej modułu klasy umieść poniższy kod, który utworzy
wyrażenie:
197 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Event PrzyPowitaniu ()

Aby użyć zdarzenia, umieść je w metodzie obiektu. Służy do tego polecenie Raise. W naszym przykładzie, umieścimy
zdarzenie Przy powitaniu w metodzie Login obiektu cUser.

Gdy użytkownik uruchomi aplikację, nastąpi odwołanie do metody Login. Spowoduje to uruchomienie zdarzenia Przy
powitaniu, które wyświetli ekran powitalny dla użytkownika, zawierający jego Imię. Służy do tego następujący kod:
Public Sub Login()
RaiseEvent PrzyPowitaniu
End If

Te kroki wystarczą, by utworzyć zdarzenie i umieścić je w module klasy. W następnej części omówimy użycie zdarzeń w
formularzu.

Użycie zdarzeń
Aby użyć zdarzenia Przy powitaniu z modułu formularza, w części deklaracyjnej zadeklaruj zmienną obiektu cUser i użyj
słowa kluczowego WithEvents. Umieszczenie tego słowa konieczne jest do użycia zdarzeń obiektu cUser. Użyj
następującego kodu:
' W części deklaracyjnej modułu umieść
Private WithEvents objUser As cUser

Słowo kluczowe WithEvents może być używane jedynie w modułach


klasowych (takim właśnie są moduły formularza). Nie można go jednak
używać w standardowych modułach.

Po zadeklarowaniu używającej słowa kluczowego WithEvents zmiennej na poziomie modułu przyjrzyj się znajdującym
się u góry okna modułu listom wyboru. W lewym polu wybierz obiekt cUser. Następnie w prawej liście wyboru zobaczysz
zdarzenia dla tego obiektu. Wybierz zdarzenie Przy powitaniu, a procedura zostanie wyświetlona w oknie kodu. Tam też
będziesz mógł wpisać kod, który będzie reakcją na zdarzenie.

Poniższy przykład zawiera kod będący reakcją na zdarzenie Przy powitaniu (rysunek 11.7).
Rysunek 11.7.
Procedura
używająca zdarzenia
„Przy powitaniu”
obiektu cUser

W wyniku tego, przy otwieraniu aplikacji przez użytkownika wyświetlany będzie ekran powitalny (rysunek 11.8).
Część IV ♦ Tajniki VBA 198

Rysunek 11.8.
Ekran powitalny

Uruchamianie zdarzeń „Przy inicjacji”


i „Przy zakończeniu”
Moduły klasy zawsze posiadają zdarzenia Przy inicjacji i Przy zakończeniu. Aby użyć tych zdarzeń, wybierz je ze
znajdującej się u góry okna kodu listy wyboru.

Zdarzenie Przy inicjacji uruchamiane jest za każdym razem, gdy obiekt jest tworzony. Przykładowo, jeśli chcesz, aby
określony kod był uruchamiany, gdy tworzony jest obiekt cUser, umieszczasz go w zdarzeniu Przy inicjacji.

Zdarzenie Przy zakończeniu uruchamiane jest za każdym razem, gdy obiekt jest niszczony. Jest to dobre miejsce na
umieszczenie kodu porządkującego, który zamknie połączenia bazy danych, zwolni zmienne obiektów itp.

Użycie obiektów
W tym momencie, obiekt cUser istnieje i posiada właściwości oraz metody. Aby użyć go w module klasy, wystarczy
wpisać nazwę tego obiektu oraz kropkę. IntelliSense wyświetli listę właściwości i metody dla tego obiektu.

Aby użyć obiektu wewnątrz klasy, która go stworzyła, użyj słowa kluczowego Me. Przykładowo, aby ustawić nazwę
użytkownika:
Me.User = "Mariusz"

Użycie tego obiektu z zewnątrz modułu klasy cUser (w formularzach lub modułach standardowych) wymaga wykonania
dwóch czynności. Po pierwsze, zadeklarowania zmiennej obiektu, która zostanie użyta jako odniesienie do obiektu. Drugą
czynnością jest wykorzystanie słowa kluczowego Set do utworzenia odniesienia zmiennej obiektu do obiektu.

Tworzenie zmiennej obiektu


Zmienna jest to fragment pamięci, zarezerwowany w celu przechowywania bądź pobierania informacji. Z pewnością
miałeś już do czynienia ze zmiennymi „prostymi” np. string (ciąg znaków) czy integer (liczba całkowita). Poniżej
znajdziesz przykłady deklarowania i użycia dwóch prostych zmiennych:
Dim strImię as String
Dim I as Integer

StrImię = "Mariusz"
I = 10

W tych przypadkach, zmienne zawierały określony typ danych, a informacje w nich przechowywane mogły być w razie
potrzeby pobierane.

Zmienna obiektu, podobnie do prostych zmiennych, deklarowana jest za pomocą polecenia Dim:
Dim objUser as cUser

Przypisywanie zmiennej obiektu do obiektu


Do tworzenia odniesienia między zmienną obiektu a obiektem używamy słowa kluczowego Set. Na przykład:
199 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Set objUser = New cUser

Zawsze używaj instrukcji Dim i Set w osobnych liniach. Nigdy nie łącz ich
w jednej linii (np. Dim objUser = New cUser). Jeśli to zrobisz, kod
będzie działał dużo wolniej, a Ty nie będziesz wiedział, w którym mo-
mencie obiekt umieszczany jest w pamięci.

Użycie obiektu
Po utworzeniu i ustawieniu zmiennej obiektu będziesz mógł za pomocą IntelliSense używać właściwości i metod obiektu.
Właściwości mogą być ustawiane i pobierane, a metody wykonywane przy użyciu składni z kropką.
Ustawienie wartości właściwości: Obiekt.Właściwość = Wartość
Pobranie wartości właściwości: MsgBox Obiekt.Właściwość

Jeśli, próbując użyć obiektu, zauważysz, że IntelliSense nie pokazuje żad-


nych właściwości i metod, może to oznaczać, że nie utworzyłeś bądź nie
ustawiłeś zmiennej obiektu. Zdarza się jednak, że IntelliSense nie pokazuje
właściwości ani metod, mimo iż kod jest poprawny. Załóż, że napisany przez
Ciebie kod jest poprawny i przetestuj go. Microsoft nie dostarczył technologii
IntelliSense dla każdego elementu kodu.

Zwalnianie obiektu
Gdy zakończyłeś już pracę ze zmienną obiektu, zwolnij go, ustawiając obiekt na Nothing. W ten sposób odzyskasz
zarezerwowane zasoby. Prawidłowa składnia wygląda następująco:
' Zwolnij zmienną obiektu
Set objUser = Nothing

Gdy opisujesz zmienną obiektu, przejdź od razu na koniec procedury


i ustaw zmienną na równą Nothing. Dzięki temu nie zapomnisz jej zwol-
nić po napisaniu długiej procedury.

Tworzenie wielu egzemplarzy obiektów


Klasa posiada zdefiniowany zestaw właściwości i metod. To jak szablon lub schemat. Wyobraź sobie, że otwierasz nowy
dokument w Wordzie. Masz wówczas możliwość użycia szablonu, na przykład List elegancki. Po wybraniu szablonu
dostosowujesz go do własnych potrzeb. Lecz zmian dokonujesz już na nowym dokumencie, nie na szablonie. Dokładnie
tak samo funkcjonują klasy.

Po utworzeniu klasy powstaje kopia obiektu zawierająca podstawowy zestaw właściwości i metod (szablon). Od tego
momentu, obiekt staje się unikatowy i posiada własny zestaw wartości właściwości oraz metod.

Jedną z korzyści modułu klasy jest to, że można tworzyć wiele egzemplarzy klasy. Każda z nich posiada podstawowy
zestaw właściwości i metod, jednak każdą z nich można w różny sposób dostosowywać po utworzeniu obiektu. Załóżmy,
że utworzono pięć obiektów cUser. Każdy z nich posiada różne wartości właściwości i metody. Przykładowo, jeden z nich
może mieć wartość właściwości Imię Mariusz, a inny Beata.

Aby utworzyć kilka egzemplarzy obiektu, wystarczy stworzyć dodatkowe zmienne obiektu i przypisać każdą z nich do
nowego obiektu. Przyjrzyj się poniższemu fragmentowi kodu:
Public Sub WieluUżytkowników()
Dim objUser1 as cUser
Dim objUser2 as cUser

Set objUser1 = New cUser


Set objUser2 = New cUser

ObjUser1.Imię = "Mariusz"
ObjUser2.Imię = "Beata"
Część IV ♦ Tajniki VBA 200

Msgbox "Aktualni użytkownicy to: " & objUser1.Imię & " i "_
objUser2.Imię

Set objUser1 = Nothing


Set objUser2 = Nothing
End Sub

Przegląd innych obiektów


Przykłady z tego rozdziału zawierają wiele klas, które możesz używać
dla swoich potrzeb („tworzenie obiektów przy użyciu modułów
klasy.mdb” na dołączonej do książki płycie CD). Teraz omówimy
pokrótce każdy z tych obiektów.

Obiekt TextFile
Kod tego rozdziału zawiera obiekt cTextFile, który może być użyty do odczytywania i zapisywania informacji w pliku
tekstowym (rysunek 11.9).

Rysunek 11.9.
Przykład obiektu
TextFile

Moduł klasowy zawiera następujący kod:


Private pintFreeFile As Integer
Private pvarInfo As Variant

Public Function ReadLineText(strFileName As String) As String


pintFreeFile = FreeFile
Open strFileName For Input As pintFreeFile
Line Input #pintFreeFile, pvarInfo
ReadLineText = pvarInfo
Close #pintFreeFile

End Function
Public Function ReadAllText(strFileName As String) As String

pintFreeFile = FreeFile
Open strFileName For Input As pintFreeFile
Do Until VBA.EOF(pintFreeFile)
Line Input #pintFreeFile, pvarInfo
ReadAllText = ReadAllText & vbCrLf & pvarInfo
Loop
Close #pintFreeFile
End Function

Public Sub WriteLineText(strFileName As String, strText As String)


pintFreeFile = FreeFile
Open strFileName For Append As pintFreeFile
Write #pintFreeFile, strText
Close #pintFreeFile
End Sub

Obiekt Timer
W kodzie rozdziału znajduje się również moduł klasy cTimer. Moduł ten ma dwa zastosowania: stoper (pozwala obserwować
mijający czas) oraz do powstrzymania wykonywania kodu przez określoną ilość sekund.

Kod w module klasy cTimer jest następujący:


201 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Option Explicit
Private msngStart As Single

Public Sub Wait(lngSeconds As Long)


Do Until Timer > msngStart + lngSeconds
DoEvents
Loop
End Sub

Public Sub StartTimer()


msngStart = Timer

End Sub
Public Function ElapsedTime() As Long
Dim sngTimerStop As Single
sngTimerStop = Timer

ElapsedTime = sngTimerStop - msngStart

msngStart = 0
sngTimerStop = 0

End Function

Formularz frmTimer w bazie „tworzenie obiektów przy użyciu modułów klasy.mdb”” przedstawia, jak korzystać z zegara
w celu określenia pozostającego czasu i stworzenia „stanu oczekiwania”. Patrz rysunek 11.10.
Rysunek 11.10.
Użycie zegara do
określenia
pozostającego czasu
oraz stworzenia
„stanu oczekiwania”

Obiekt Sound
Zadaniem modułu klasy cSound jest odtwarzanie dźwięków w aplikacjach Accessa. Moduł ten zawiera tylko jedną metodę
(PlaySound), która przekazuje plik dźwiękowy do interfejsu API systemu Windows:
' Odwołanie do interfejsu API systemu Windows
Private Declare Function sndPlaySound Lib "winmm.dll" Alias _
"sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags _
As Long) As Long

Public Sub PlaySound(SoundFile As String)

' Odtwarzanie pliku dźwiękowego


sndPlaySound SoundFile, 1

End Sub

Poniższy kod korzysta z obiektu objSound (rysunek 11.11):


Dim objSound As cSound
Set objSound = New Sound
' Jeśli używasz Windows NT, wpisz ścieżkę "C:\WINNT"
objSound.PlaySound "C:\Windows\chimes.wav"
Set objSound = Nothing

Rysunek 11.11.
Przykład obiektu
Sound
Część IV ♦ Tajniki VBA 202

Obiekt Letter
Zadaniem tego modułu klasy jest tworzenie listów w programie Microsoft Word. Listy te tworzone są przy użyciu
korespondencji seryjnej. Do stworzenia listu wykorzystywany jest szablon programu Word, a instrukcja SQL pobiera dane
do listu. Metoda ShowWord (logiczna) określa, czy Word będzie widoczny dla użytkownika. Czasami możesz chcieć
przesłać listy bezpośrednio do drukarki, bez ich edycji.

Oto kod modułu klasy cLetter:


Option Explicit

Private objWord As Word.Application

' Zmienne lokalne, do przechowywania wartości właściwości


Private mvarTemplate As String ' lokalna kopia
Private mvarSQLStatement As String 'lokalna kopia

Public Property Let SQLStatement(ByVal vData As String)


mvarSQLStatement = vData
End Property

Public Property Get SQLStatement() As String


SQLStatement = mvarSQLStatement
End Property

Public Property Let Template(ByVal vData As String)


mvarTemplate = vData
End Property

Public Property Get Template() As String


Template = mvarTemplate
End Property

Public Sub CreateLetter(DatabasePath As String, ShowWord As Boolean)

' Zapisywanie danych o klientach do pliku tymczasowego,


' który zostanie użyty do korespondencji seryjnej.
' Rozwiązanie to jest szybsze niż
' pobieranie danych bezpośrednio z Accessa.
DoCmd.OutputTo acOutputQuery, "qryCustomers", _
acFormatRTF, "C:\Temp.RTF", False

objWord.Documents.Add (Me.Template)

' Uruchomienie korespondencji seryjnej


With objWord.ActiveDocument.MailMerge
.MainDocumentType = wdFormLetters
.OpenDataSource Name:="C:\Temp.rtf"
.Destination = wdSendToNewDocument
.Execute
End With

If ShowWord Then
Me.ShowWord
End If

End Sub

Friend Sub ShowWord()

' Word widoczny dla użytkownika


objWord.Visible = True

End Sub

Private Sub Class_Initialize()

' Przejście do linii występującej po błędzie


On Error Resume Next

' Próba odwołania do Worda, który już jest otwarty


Set objWord = GetObject(, "Word.Application")

' Jeśli PRAWDA, Word nie jest uruchomiony


If objWord Is Nothing Then
' Utwórz nowy egzemplarz aplikacji Word
Set objWord = New Word.Application
' Jeśli PRAWDA, MS Word nie jest zainstalowany
If objWord Is Nothing Then
MsgBox "MS Word nie jest zainstalowany na tym komputerze"
End If
End If

End Sub

Private Sub Class_Terminate()


203 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Set objWord = Nothing

End Sub
Poniższy kod korzysta z właściwości i metod obiektu objLetter:
' Wymiary zmiennych
Dim objLetter As cLetter
Dim strPath As String
StrPath = CurrentProject.Path

' Przydziel zmienne obiektu do obiektu cLetter


Set objLetter = New cLetter

' Szablon Word'a, który będzie użyty w dokumencie


objLetter.Template = strPath & "\Business Services Letter.Dot"

' Instrukcja SQL użyta do pobrania danych dla formularza


objLetter.SQLStatement = "SELECT * FROM tblCustomers"

' Odwołanie do metody "CreateLetter" w celu stworzenia listu


objLetter.CreateLetter strPath & "\Objects.mdb", True

" Zniszczenie zmiennej obiektu


Set objLetter = Nothing

Obiekt Outlook
Moduł klasy cOutlook służy do wyświetlania formularza Nowa wiadomość programu MS Outlook (rysunek 11.12). Jeśli
chcesz umożliwić użytkownikom pisanie wiadomości programu Outlook w aplikacjach Accessa, wystarczy, że odwołasz się
do metody NewEmailMessage.

Oto kod zawarty w module klasy cOutlook:


Option Explicit

Private mobjOutlook As Outlook.Application


Private mMyItem As Object

Public Sub NewEmailMessage(EmailAddress As String)

' Tworzenie nowej wiadomości programu Outlook


Set mMyItem = mobjOutlook.CreateItem(olMailItem)

Rysunek 11.12.
Wyświetlanie
formularza Nowa
wiadomość programu
Outlook w aplikacjach
Accessa

mMyItem.To = EmailAddress

mMyItem.Display

End Sub

Private Sub Class_Initialize()

' Nie zachodzi konieczność użycia instrukcji "GetObject"


' Outlook zawsze otwiera tylko jedną kopię aplikacji
' Użyj słowa kluczowego "New"

' Ustaw zmienną obiektu na aplikację Outlook


Set mobjOutlook = New Outlook.Application

' Jeśli PRAWDA, Outlook nie jest zainstalowany


If mobjOutlook Is Nothing Then

MsgBox "MS Outlook nie jest zainstalowany na tym komputerze"

End If

End Sub

Private Sub Class_Terminate()

' Zwolnij zmienną obiektu


Część IV ♦ Tajniki VBA 204

Set mobjOutlook = Nothing

End Sub

Poniższy kod odwołuje się do metody NewEMailMessage:


' Deklaracja zmiennej obiektu
Dim objOutlook As Outlook

' Przydziel zmienne obiektu do obiektu cOutlook


Set objOutlook = New Outlook
' Odwołanie do metody "NewEMailMessage"
objOutlook.NewEMailMessage "redakcja@helion.com.pl"

' Zniszczenie zmiennej obiektu


Set objOutlook = Nothing

Implementacja obiektu obsługi błędów


W przykładowym kodzie dla rozdziału 13. „Profesjonalna obsługa błędów” znajdziesz obszerny moduł klasowy zajmujący
się obsługą błędów i obejmujący:
u Zapisywanie błędów w tabeli Accessa.
u Zapisywanie błędów w pliku tekstowym.
u Obsługę błędów związanych z pocztą elektroniczną.
u Obsługę błędów zapisu w kalendarzu programu Outlook.

Używając narzędzia Object Browser, przyjrzyj się obiektowi cError (rysunek 11.13).

Rysunek 11.13.
Obiekt cError
w narzędziu
Object Browser

Użycie obiektów
w połączeniu z kolekcjami VBA
Kolekcje VBA to sposób na traktowanie obiektów własnych jako grupy. Przykładowo, jeśli istnieje pięć obiektów cUser i
chcesz na każdym z nich wykonać jakieś działanie, łatwiej i efektywniej będzie traktować te pięć obiektów jak jedną grupę
niż każdy z osobna.

Z pewnością zapoznałeś się już z wbudowanymi kolekcjami (np. „formularze” czy „formanty”). VBA również posiada
obiekt kolekcja (collection). Kolekcja jest to sposób traktowania grupy obiektów, jakby były odrębną jednostką. W życiu
codziennym też spotykamy takie grpy. Dyrygent orkiestry mówi: „A teraz wstaną wszystkie instrumenty dęte”. Jest to dużo
wygodniejsze rozwiązanie niż „Tomasz, Agnieszka, Marta i Rafał, wstańcie”. W podobny sposób można traktować
obiekty.
205 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Najważniejsze w całej tej idei jest to, że kolekcja jest obiektem, który posiada własne metody i właściwości. Oto cechy
obiektu kolekcji:
u Jest obiektem posiadającym własne metody i właściwości.
u Do kolekcji można dodawać różne typy obiektów.
u Jego rozmiar się zmienia. Rośnie wraz z dodawaniem i zmniejsza się wraz z usuwaniem obiektów.
u Elementy kolekcji nie podlegają sortowaniu.
u Elementy kolekcji są indeksowane. Indeksowanie rozpoczyna się od wartości 1.

Tworzenie kolekcji VBA


Ponieważ kolekcje są obiektami, tworzy się je w taki sam sposób jak obiekty. Najpierw deklaruje się zmienną obiektu,
która służy jako odniesienie do kolekcji. Później za pomocą słowa kluczowego Set tworzy się odniesienie zmiennej
obiektu do kolekcji. Poniższy kod tworzy kolekcję użytkowników:
Dim Users as Collection
Set Users = New Collection

Wygodnie jest nazywać zbiory liczbą mnogą nazwy obiektów, które zawie-
rają. Obiekt, który będzie dodawany do zbioru w naszym przykładzie, to
użytkownik (User). Stąd nazwa zbioru – Użytkownicy.

Właściwości i metody kolekcji VBA


Obiekt collection ma bardzo prostą strukturę, na którą składa się jedna właściwość i trzy metody (tabela 11.1).

Tabela 11.1.
Właściwości i metody obiektu collection

Nazwa Typ Opis


Count Właściwość Wskazuje ilość obiektów w zbiorze
Add Metoda Używana do dodawania obiektów do zbioru
Remove Metoda Używana do usuwania obiektów ze zbioru
Item Metoda Używana do tworzenia odniesień do obiektów zbioru. Jest to metoda
domyślna

Dodawanie obiektów do kolekcji


Aby dodawać obiekty do zbioru, użyj metody Add.
Collection.Add Item [, Key][, Before][, After]

Następnie podaj zmienną obiektu dla każdego z obiektów dodawanych do kolekcji. Przykładowo, aby dodać do kolekcji
dwóch użytkowników, użyj zmiennej obiektu dla każdego z nich: objUser1 i objUser2. Następny parametr to wartość
Key (już znana), która będzie użyta do tworzenia odniesienia do obiektu. Jeśli wartość klucza nie jest określona, każdy
obiekt w kolekcji musi być powiązany z numerem indeksu.

Radzimy określanie wartości klucza. Dzięki temu pisanie kodu jest prost-
sze, a sam kod jest bardziej wiarygodny niż numery indeksu. Numery
indeksu mogą ulec zmianie, gdy ze zbioru zostanie usunięty jakiś element lub
gdy inny obiekt zostanie wstawiony w określone miejsce przy użyciu
argumentów metody Add.

W poniższym przykładzie dodamy dwóch użytkowników do kolekcji Użytkownicy:


Dim User1 as cUser
Dim User2 as cUser
Dim Użytkownicy as Collection

Set User1 = New User


Część IV ♦ Tajniki VBA 206

Set User2 = New User


Set Użytkownicy = New Collection
User1.Imię = "Mariusz"
User2.Imię = "Beata"

Użytkownicy.Add User1 = User1.Imię


Użytkownicy.Add User2 = User2.Imię

Set User1 = Nothing


Set User2 = Nothing
Set Użytkownicy = Nothing

Powyższy kod dodaje obiekt User1 do zbioru. Jako klucz służy wartość właściwości Imię obiektu. Obiekt User2 dodany
został w ten sam sposób. Zwróć uwagę na argumenty before i after (przed i po) metody Add, które określają miejsce
obiektu w zbiorze.

Odnoszenie się do określonych obiektów


Do obiektów w kolekcji można odnosić się za pomocą numeru lub wartości klucza. Gdy odnosisz się do obiektu w kolekcji
za pomocą numeru, pamiętaj, że indeksowanie tych obiektów rozpoczyna się od wartości 1. Najprostszym sposobem na
odnoszenie się do obiektów kolekcji jest użycie jako klucza ich nazwy. Poniższy kod przedstawia, jak odnosić się do
określonego obiektu User2, korzystając z obu tych metod. Mimo iż metoda Item nie musi być określona (gdyż jest
metodą domyślną), ułatwia przeglądanie i obsługę kodu.
' Odniesienie do obiektu w kolekcji za pomocą numeru indeksu
MsgBox Użytkownicy.Item(2).Type
' Odniesienie do obiektu w kolekcji za pomocą wartości klucza
MsgBox Użytkownicy.Item ("Mariusz").Type

Tworzenie pętli po obiektach kolekcji


Najłatwiejszym i najefektywniejszym sposobem na tworzenie pętli po obiektach kolekcji jest użycie pętli For Each. Pętla
For Next może być również użyta, jednakże jest wolniejsza.

Aby użyć pętli For Each określ, który obiekt zbioru chcesz zbadać. A oto kod:
' Musisz zadeklarować zmienną obiektu
Dim User as cUser

For Each User in Users


MsgBox User.Type
Next User

Przykład ten sprawdza każdego użytkownika w zbiorze. Zauważ, że poje-


dynczy użytkownicy posiadają zmienne obiektu o nazwach User1 i User2.
Aby użyć pętli For Each, określ ogólną zmienną obiektu o nazwie User.
Taka zmienna obiektu nie musi być przydzielona do obiektu za pomocą
słowa kluczowego Set. Jest to możliwe jedynie w przypadku pętli For
Each.

Usuwanie pojedynczych obiektów


Aby usunąć z kolekcji określone obiekty, użyj numeru indeksu lub wartości klucza.
' Usuwanie obiektu za pomocą numeru indeksu
Użytkownicy.Remove 2

' Usuwanie obiektu za pomocą wartości klucza


Użytkownicy.Remove "Mariusz"

Usuwanie wszystkich obiektów


Aby usunąć wszystkie elementy kolekcji, nie musisz tworzyć pętli po wszystkich obiektach, a następnie wywoływać
metody Remove. Dużo szybciej jest przydzielić obiekt zbiór do nowego zbioru.
' Usuwanie wszystkich elementów zbioru
Set Użytkownicy = New Collection
207 Rozdział 11. ♦ Tworzenie obiektów przy użyciu modułów klas

Zwalnianie zmiennej obiektu


Kolekcje są obiektami, więc tak samo, jak w przypadku wszystkich obiektów, pamiętaj o zwolnieniu zmiennej obiektu
przez ustawienie jej na Nothing.
' Usuwanie zmiennej obiektu kolekcja
Set Użytkownicy = Nothing
Rozdział 12.
Usuwanie błędów w aplikacjach
Accessa
W tym rozdziale:
u Usuwanie błędów logicznych.
u Praca z Visual Basic Development Environment (IDE).
u Obiekt debug.
u Użycie okna Immediate.
u Użycie programu uruchomieniowego.
u Użycie kompilacji warunkowej.
u Testowanie aplikacji.
u Ćwiczenie technik usuwania błędów.

Użycie dołączonych do Accessa narzędzi do usuwania błędów oraz opisanych w tym rozdziale technik usuwania błędów
pozwala na znaczne skrócenie czasu tworzenia aplikacji. Warto więc je poznać, gdyż zaowocuje to zauważalnymi
korzyściami w długim okresie czasu.

Nie myśl, że narzędzia do usuwania błędów przydają się tylko w przypadku bardzo skomplikowanych aplikacji. Zdarza się,
że nawet w najprostszych aplikacjach błędy są trudne do wykrycia.

Ważne, by błędy programu zostały wykryte i poprawione jak najszybciej. Mimo iż część z nich może mieć mały wpływ na
działanie programu, inne mogą naruszyć integralność bazy danych lub wywołać jeszcze poważniejsze konsekwencje.

Usuwanie błędów logicznych


Błędy logiczne występują, gdy wykonywany kod nie przynosi oczekiwanych rezultatów. Naruszona może być logika lub
wykonywanie programu przebiega nieprawidłowo. Gdy kod jest wykonywany, lecz nie daje oczekiwanych rezultatów,
spodziewaj się błędu logicznego.

Większość czasu spędzonego przy uruchamianiu aplikacji zabiera wyszukiwanie i poprawianie błędów logicznych. W tym
rozdziale zostaną przedstawione techniki oraz narzędzia do usuwania takich błędów.

Oto kilka przykładów błędów logicznych:


u Procedura próbuje użyć pola bazy danych, które nie posiada danych (wartość null).
u Błąd w obliczeniach.
u Przetwarzanie operacji w kodzie odbywa się w nieprawidłowej kolejności.
209 Rozdział 12. ♦ Usuwanie błędów w aplikacjach Accessa

Praca z Visual Basic Development Environment (IDE)


W środowisku projektowania Accessa nastąpiła radykalna zmiana. Podobnie jak inne Visual Basic 5 i 6, Word 97 i inne
programy pakietów Office 97 i 2000, Access posiada teraz Visual Basic Development Environment (IDE). Jest to
środowisko projektowania zawierające standardowe środki, umożliwiające projektowanie aplikacji w różnych produk-
tach. Opisane w tym rozdziale techniki usuwania błędów mogą być użyte zarówno podczas tworzenia aplikacji w
Accessie, jak i w Visual Basic i programach pakietu Office. Aby otworzyć IDE, w widoku Projekt formularza, z menu
Widok wybierz pozycję Kod programu. Na IDE składają się różne okna, które mogą być dowolnie zamykane i otwierane
(np. Project, Properties, Immediate i inne). Aby otworzyć w IDE określone okno, wybierz je z menu View. Zamykanie
okien odbywa się poprzez kliknięcie znajdującego się w prawym górnym rogu okna przycisku zamykającego. Gdy
otwierasz IDE, układ okien jest identyczny jak wtedy, gdy po raz ostatni go używałeś. Gdy formularz otwarty jest w
widoku Projekt, możesz pracować z formantami i właściwościami tak jak we wcześniejszych wersjach Accessa.
Jednakże, by przeglądać kod formularza, musisz otworzyć Visual Basic IDE (rysunek 12.1). W rzeczywistości, jest to
odrębna aplikacja.

Mimo, iż Visual Basic IDE jest osobną aplikacją, działa w połączeniu z Accessem. Jeśli aplikacja ta jest otwarta, to
zostanie zamknięta w momencie, w którym zamkniesz Access. Aby zamknąć Visual Basic IDE, z menu File wybierz
Close And Return to Microsoft Access.

Teraz omówimy okna Visual Basic IDE.


Rysunek 12.1.
Visual Basic
Integrated
Development
Environment (IDE)

Project Explorer
Project Explorer wyświetla listę formularzy, raportów i modułów klasy w danej aplikacji Accessa (rysunek 12.2).

Rysunek 12.2.
Okno Project
Explorer

Kliknij dowolny obiekt prawym klawiszem myszy, aby zobaczyć jego kod lub przejść do widoku Projekt formularza. Aby
otworzyć Project Explorer, z menu View wybierz Project Explorer lub naciśnij klawisze Ctrl+R.

Okno Code
Okno Code zawiera kod formularzy, modułów i modułów klasy (rysunek 12.3). Jako programista, spędzisz wiele godzin,
wprowadzając i modyfikując kod w tym oknie. Aby je otworzyć, z menu View wybierz Code lub naciśnij klawisz F7. U góry
okna Code znajdują się dwie rozwijane listy. Lista z lewej strony służy do wybierania obiektów (np. formularzy czy formantów
formularza). Druga lista służy do wybierania metody dla danego obiektu.
Część IV ♦ Tajniki VBA 210

Rysunek 12.3.
Okno Code

Okno Properties
Okno Properties służy do ustawiania i przeglądania właściwości formularzy, raportów i formantów na nich umieszczanych
(rysunek 12.4). Aby je otworzyć, z menu View wybierz Properties lub naciśnij klawisz F4.

Rysunek 12.4.
Okno Properties

Okno Immediate
Okno Immediate może być używane do oceny i ustawiania zmiennych, uruchamiania procedur oraz wykonywania
instrukcji Debug.Print. Aby je otworzyć, z menu View wybierz Immediate window lub naciśnij klawisze Ctrl+G.
Szczegóły związane z funkcjonowaniem tego okna omówimy w dalszej części tego rozdziału.

Okno Locals
Okno Locals przedstawia wyrażenia, wartości i typy wszystkich zmiennych, które są aktualnie analizowane. Aby je
otworzyć, z menu View wybierz Locals window. Szczegóły związane z funkcjonowaniem tego okna omówimy w dalszej
części tego rozdziału.

Okno Watch
Okno Watch może być użyte do obserwowania wartości wyrażeń podczas działania aplikacji. Aby je otworzyć, z menu
View wybierz Watch window. Szczegóły związane z funkcjonowaniem tego okna omówimy w dalszej części tego rozdziału.
211 Rozdział 12. ♦ Usuwanie błędów w aplikacjach Accessa

Object Browser
Aby otworzyć Object Browser, z menu View wybierz Object Browser lub naciśnij F2. Object Browser możesz używać
do przeglądania obiektów, właściwości i metod (rysunek 12.5).

Rysunek 12.5.
Object Browser

Okno Call Stack


Okno Call Stack przedstawia procedury, do których nastąpiło odwołanie. Aby je otworzyć, z menu View wybierz Call Stack
lub naciśnij klawisze Ctrl+L. Szczegóły związane z funkcjonowaniem tego okna omówimy w dalszej części tego rozdziału.

Jak widać, w IDE można korzystać z wielu okien. Dlatego też dużo łatwiej
jest pracować w rozdzielczości 1024 na 768 lub wyższych. Jeszcze lepszym
rozwiązaniem jest nowa opcja systemów Windows 98 i 2000 – multi-
monitor.
Aby ułatwić sobie pracę z oknami, naucz się ich klawiszy skrótów. Umoż-
liwi Ci to ich szybkie otwieranie i zamykanie. W zależności od potrzeb
okna te możesz przesuwać lub zmieniać ich rozmiar. Jeśli zmienisz
położenie okna, możesz mieć trudności z powtórnym umieszczeniem go na
swoim miejscu. Wystarczy wówczas kliknąć dwukrotnie pasek z jego
nazwą.

Obiekt Debug
Obiekt Debug posiada dwie metody, które są bardzo pomocne w usuwaniu błędów aplikacji – Debug.Print i Debug.Assert.

Debug.Print
Korzystając z Debug.Print, możesz wyświetlać informacje w oknie Immediate. Metoda ta może być wykorzystywana w
samym oknie Immediate lub w kodzie.

Aby wyświetlać informacje w oknie Immediate, używaj instrukcji De-


bug.Print w kodzie. Gdy testujesz wyrażenia lub uruchamiasz funkcje
w oknie Immediate, nie musisz wpisywać Debug.Print. Zamiast tego
wpisz znak zapytania ?, dzięki czemu uzyskasz ten sam rezultat.
Część IV ♦ Tajniki VBA 212

W oknie Immediate możesz testować wbudowane funkcje, wartości zestawu rekordów i inne (rysunek 12.6). Przykładowo,
poniższy kod służy do testowania wbudowanej funkcji Len:

Rysunek 12.6.
Do testowania
funkcji w oknie
Immediate używaj
znaku zapytania

Umieszczając w kodzie Debug.Print, w oknie Immediate możesz wyświetlać wartości i inne informacje. Gdy wykonany
zostanie poniższy kod, w oknie Immediate zostanie wyświetlona wartość stanu:
Sub Demo()
Debug.Print rst.States
Select Case rst.States
Case "Washington"
MsgBox "Washington"
Case "Oregon"
MsgBox "Oregon"
Case "California"
MsgBox "California"
End Select
End Sub

Okno Immediate nie przenosi tekstu do nowego wiersza, więc staraj się skrócić rezultat działania procedury. Nie musisz
usuwać instrukcji Debug.Print z kodu, ponieważ ostateczny użytkownik nigdy nie zobaczy okna Immediate. Jeśli
jednak instrukcji tych będzie dużo, będzie to miało wpływ na wydajność aplikacji.

Debug.Assert
Debug.Assert służy do warunkowego zawieszania wykonywania pojedynczych linii kodu. Przykładowo, jeśli instrukcja
napotka Debug.Assert False, wstrzyma wykonywanie tej linii kodu. Umożliwia to przejrzenie aplikacji i usunięcie
błędów.

Nigdy nie używaj w kodzie słowa kluczowego Stop. Jeśli bowiem zapom-
nisz go usunąć, to nie tylko zatrzyma wykonywanie kodu, ale będzie również
zatrzymywać używaną przez użytkowników aplikację. Zamiast tego zawsze
używaj Debug.Assert, ponieważ ta instrukcja jest zawsze usuwana przez
kompilator.

Użycie okna Immediate


Aby otworzyć okno Immediate, przejdź do edytora Visual Basic i z menu View wybierz Immediate Window lub naciśnij
klawisze Ctrl+G. Okno to może być używane do podglądania i ustawiania zmiennych, uruchamiania funkcji i procedur oraz
wyświetlania rezultatów działania instrukcji Debug.Print.

Podglądanie zmiennych
Aby podejrzeć wartość zmiennej w oknie Immediate, wprowadź znak zapytania, a po nim nazwę zmiennej (np. ?
strName). Pamiętaj, że możesz określić wartość zmiennej, ustawiając na niej kursor myszy w trybie pauzy.

Zmiana wartości zmiennych


Aby zmienić wartość zmiennej w oknie Immediate, wprowadź jej nazwę, a po niej znak równości i nową wartość (np. intI
= 10).
213 Rozdział 12. ♦ Usuwanie błędów w aplikacjach Accessa

Wyświetlanie wartości funkcji wbudowanych


Aby wyświetlić wartość funkcji wbudowanej w oknie Immediate, wprowadź znak zapytania, a po nim nazwę funkcji (np. ?
Now).

Uruchamianie funkcji własnych


Aby uruchamiać funkcje własne w oknie Immediate, wprowadź znak zapytania, a po nim nazwę funkcji i jej parametry (np.
? MyFunction).

Uruchamianie własnych procedur


Aby uruchamiać własne procedury w oknie Immediate, wystarczy wprowadzić nazwę procedury i jej parametry (np.
MySubProcedure). Przed nazwą procedury nie wstawiaj znaku zapytania.

Uruchamiając w oknie Immediate procedurę lub funkcję, wpisz jej nazwę


bez znaku zapytania. Jeśli procedura lub funkcja jest modułem formu-
larza, wprowadź przed jej nazwą nazwę tego formularza (np.
frmTest.MySubProcedure).

Wskazówki pomocne w korzystaniu z okna Immediate


Ponieważ spędzisz duża część pracy odbywa się w oknie Immediate, poniższe wskazówki mogą okazać się bardzo
pomocne.

Uruchamianie instrukcji w oknie Immediate


Aby w oknie Immediate uruchomić instrukcję kodu, umieść kursor w dowolnym miejscu tej instrukcji (nie musi to być
początek ani koniec).

Jeśli w oknie Immediate znajduje się kilka instrukcji kodu, nie musisz ich usuwać. Wystarczy, że umieścisz kursor w
instrukcji, którą chcesz uruchomić i naciśniesz klawisz Enter.

Poruszanie się po oknie Immediate


Do przesuwania punktu wprowadzania używaj myszy oraz klawiszy strzałek. Naciśnięcie klawisza Home powoduje
przeniesienie punktu wprowadzania na początek aktualnej linii kodu, a klawisza End na jej koniec.

Klawisze PageUp i PageDown służą do poruszania się po kodzie strona po stronie.

Aby przenieść punkt wprowadzania na początek okna Immediate, naciśnij klawisze Ctrl+Home. Naciśnięcie klawiszy
Ctrl+End spowoduje przeniesienie punktu wprowadzania na koniec okna.

Usuwanie kodu w oknie Immediate


Aby zaznaczyć cały kod w oknie Immediate celem jego usunięcia, będąc na końcu kodu naciśnij klawisze Shift+Ctrl+Home.
Gdy cały kod zostanie zaznaczony, wciśnij klawisz Delete. Jeśli punkt wprowadzania znajduje się na początku kodu,
naciśnij klawisze Shift+Ctrl+End. Gdy kod zostanie zaznaczony, naciśnij klawisz Delete.

Użycie programu uruchomieniowego


Usuwanie błędów w aplikacjach Accessa 2000 nie jest trudne. Wystarczy zatrzymać wykonywanie kodu w określonych
miejscach i przeglądając kod, obserwować jak program jest wykonywany.
Część IV ♦ Tajniki VBA 214

Ustawianie punktów zatrzymania


Punkt zatrzymania zatrzymuje wykonywanie kodu. Aby ustawić punkt zatrzymania, umieść kursor w instrukcji i z menu
Run Edytora Visual Basic wybierz Toggle Breakpoint lub naciśnij klawisz F9. Pamiętaj, że punktów zatrzymania nie można
ustawiać w pustych liniach, komentarzu oraz częściach kodu zawierających instrukcję Dim. Innym sposobem na ustawienie
punktu zatrzymania jest kliknięcie szarego, lewego marginesu okna kodu na wysokości danej instrukcji. Spowoduje to
umieszczenie na lewym marginesie dużej, czerwonej kropki, oznaczającej obecność punktu zatrzymania.

Gdy program zostanie uruchomiony, wykonywanie zostanie zatrzymane w miejscu umieszczenia punktu zatrzymania
(rysunek 12.7). Moduł kodu zostanie automatycznie otwarty, a dana instrukcja zostanie podświetlona na żółto. Możesz
wówczas przejść przez kod, przeglądać lub zmieniać wartości zmiennych itp.

Aby usunąć punkt zatrzymania, z menu Run wybierz Clear All Breakpoints lub naciśnij klawisze Ctrl+Shift+F9.
Rysunek 12.7.
Wykonywanie kodu
zatrzymane
w punkcie
zatrzymania

Przechodzenie przez kod


Gdy wykonywanie kodu jest wstrzymane w punkcie zatrzymania, podświetlona na żółto instrukcja nie została jeszcze
wykonana. Możesz wówczas na kilka sposobów wykonywać kod.

Krokowe wykonywanie kodu


Aby wykonywać instrukcje kodu pojedynczo, z menu Debug Edytora Visual Basic wybierz Step Into lub naciśnij klawisz F8.
Krokowe przechodzenie przez kod jest najbardziej wydajnym sposobem obserwowania, jak program jest wykonywany, oraz
przeglądania wartości zmiennych w kodzie.

Niektórzy programiści uważają za bardzo pomocny pasek narzędzi Debug. Aby


go otworzyć, z menu View wybierz Toolbars, a następnie Debug.

Wykonywanie procedur
Zdarza się, że jedne procedury odwołują się do innych. Procedury, do których się odwołujesz, mogą być pewne (innymi
słowy, pełni przetestowane i bezbłędne). Aby szybko wykonać te procedury i nie przechodzić pojedynczo przez każdą
instrukcję kodu, z menu Debug wybierz Step Over lub naciśnij klawisz F8.

Po zakończeniu wykonywania tej procedury wykonywanie kodu zostanie ponownie zatrzymane. Od tego momentu możesz
kontynuować krokowe przechodzenie przez kod.

Wykonywanie kodu do końca procedury


Przyjmijmy, że przechodzisz przez procedurę, która zawiera odwołania do innych procedur. Gdy znajdziesz się w
procedurze, do której nastąpiło odwołanie, możesz szybko wykonać resztę tej procedury i powrócić do pierwotnej,
215 Rozdział 12. ♦ Usuwanie błędów w aplikacjach Accessa

wybierając z menu Debug pozycję Step Out lub naciskając Ctrl+Shift+F8. Opcja ta przydaje się, gdy zapomniałeś użyć
opcji Step Over, a już znajdujesz się w procedurze.

Wykonanie do pozycji kursora


Gdy przechodzisz przez kod, możesz spowodować wykonanie kodu na pełnej prędkości do miejsca, w którym znajduje się
kursor. Przydaje się to w sytuacji, gdy przechodzisz przez jedną instrukcję kodu i chcesz szybko znaleźć się w innej
instrukcji (np. pętle). Gdy kilkukrotnie przechodzisz przez pętlę, aby sprawdzić, czy działa poprawnie, umieść kursor na jej
końcu i z menu Debug wybierz Run to Cursor lub naciśnij klawisze Ctrl+F8.

Wybór kolejnej instrukcji


Gdy przechodzisz przez kod, możesz ustawić, którą z instrukcji chcesz wykonywać jako następną. Aby tego dokonać,
kliknij prawym klawiszem myszy wybraną linię kodu, a następnie z menu kontekstowego wybierz Set Next Statement.

Kontynuacja wykonywania kodu


Po przejściu przez kod i sprawdzeniu, czy działa poprawnie, możesz chcieć kontynuować jego wykonywanie z pełną
prędkością. Aby tego dokonać, z menu Run wybierz Continue lub naciśnij klawisz F5.

Ponowne uruchamianie kodu


Po znalezieniu i poprawieniu błędów możesz uruchomić żądany fragment kodu ponownie bez zatrzymywania i ponownego
uruchamiania aplikacji. Żółta strzałka na lewej krawędzi okna wskazuje, która instrukcja będzie wykonywana jako
następna. Możesz kliknąć i przeciągnąć tę strzałkę do poprzedniej linii kodu i ponownie uruchomić kod, przez który
uprzednio przechodziłeś.

Podglądanie wartości zmiennych


Podczas usuwania błędów w aplikacji możesz z łatwością określić, jaka jest wartość danej zmiennej. Wystarczy, że w
trybie pauzy przesuniesz nad tą zmienną kursor myszy (rysunek 12.8).

Okno Immediate może być również wykorzystane do wyświetlenia wartości zmiennych. Przykładowo, umieszczenie w
oknie Immediate poniższego tekstu spowoduje zwrócenie wartości zmiennej o nazwie strName:
? strName
Rysunek 12.8.
Określenie wartości
zmiennej w trybie
pauzy

Użycie podczas usuwania błędów


technologii Microsoft IntelliSense
Gdy pojawia się błąd programu i odnalazłeś właściwą linię, sprawdź jej składnię przy użyciu IntelliSense. Technologia ta
pozwala przyspieszyć Twoją pracę, podając Ci podczas pisania kodu sugerowane właściwości i metody obiektów.
Część IV ♦ Tajniki VBA 216

Przykładowo, po wpisaniu nazwy obiektu (np. Recordset lub Application) wpisz kropkę, a zobaczysz, czy użyłeś
właściwej nazwy i pisowni właściwości lub metody. Jeśli na wyświetlonej rozwijanej liście nie znajdziesz danej właściwości
lub metody, będzie to oznaczać, że użyłeś nieprawidłowej składni.

Użycie okna Locals


Okno Locals przedstawia wyrażenia, wartości i typy wszystkich zmiennych, które są aktualnie analizowane. Aby je
otworzyć, z menu View wybierz Locals window.

Rysunek 12.9.
Okno Locals
przedstawia
aktualnie
analizowane
zmienne

Okno Locals może być wykorzystane do zmiany wartości zmiennych. Klik-


nij dwukrotnie wartość zmiennej i wprowadź nową wartość.

Użycie okna Watch


Okno Watch może być użyte do wyliczania wartości wyrażeń podczas działania aplikacji. Przykładowo, jeśli chcesz
zobaczyć, w których miejscach aplikacji zmienna strName ulega zmianie, możesz do tego wykorzystać okno Watch.
Pierwszy krok to wybranie z menu Debug pozycji Add Watch. W oknie dialogowym AddWatch wpisz żądane wyrażenie
(np. strName = "Kowalski"). W oknie tym możesz również wybrać, czy chcesz wyliczać wartość wyrażenia w
określonych procedurach, modułach czy w całej aplikacji (rysunek 12.10). Wybierz w oknie jedną z opcji Watch Type:

Rysunek 12.10.
Aby tworzyć
wyrażenie Watch,
użyj okna
dialogowego Add
Watch

u Watch Expression – monitoruje żądane wyrażenie.


u Break When the Value is True – zatrzymuje kod w trybie pauzy, gdy żądane wyrażenie nie jest spełnione.
u Break When Value Changes – zatrzymuje kod w trybie pauzy, gdy wartość wyrażenia ulega zmianie.

Aby szybko utworzyć wyrażenie Watch, zaznacz dowolne wyrażenie kodu, a następnie z menu Debug wybierz Quick
Watch lub naciśnij klawisz F9. W oknie dialogowym Quick Watch naciśnij przycisk Add.

Rysunek 12.11.
Użycie okna
dialogowego
Quick Watch

Użycie okna Call Stack


Aplikacja może zawierać procedury, które odwołują się do innych procedur, które z kolei odwołują się do innych procedur
itd. Gdy usuwasz błędy w aplikacji, możesz się w pewnym momencie pogubić albo nie być pewnym, które procedury już
były wykonywane. Pokaże Ci to okno Call Stack.
217 Rozdział 12. ♦ Usuwanie błędów w aplikacjach Accessa

Jeżeli przechodzenie przez kod to poruszanie się naprzód, to okno Call Stack umożliwia ci spojrzenie wstecz. Przedstawia,
które procedur były uprzednio wywoływane (rysunek 12.12). Aby otworzyć okno Call Stack, z menu View wybierz Call
Stack lub naciśnij klawisze Ctrl+L.

Rysunek 12.12.
Użyj okna Call Stack,
aby sprawdzić, które
procedury były
uprzednio
wywoływane

Aby przejść do żądanej procedury, wybierz ją w oknie Call Stack i kliknij


przycisk Show (lub po prostu kliknij dwukrotnie procedurę).

Użycie kompilacji warunkowej


Obsługa pojedynczej aplikacji jest dużo łatwiejsza niż tworzenie wielu wersji. Załóżmy, że Twoja aplikacja jest używana w
wielu biurach. Większa część aplikacji jest ogólna i może być używana powszechnie, lecz istnieje niewielka część kodu,
która musi być zindywidualizowana dla potrzeb każdego z biur. Jeśli zdecydujesz się utworzyć wiele wersji aplikacji, ich
obsługa i aktualizacja będzie bardzo trudnym i męczącym zadaniem. Każdy nowy kod ogólny będzie musiał być dodany do
każdej wersji. Ponadto duża ilość wersji znacznie komplikuje obsługę i rozprowadzanie aplikacji.

Najlepszym rozwiązaniem jest stworzenie pojedynczej wersji aplikacji, która będzie się zachowywać w różny sposób, w
zależności od okoliczności. Możesz wybrać, która część kodu aplikacji będzie kompilowana i uruchamiana warunkowo.

Przykładowo, przyjmijmy, że określona część kodu uruchamiana będzie w biurze w Warszawie i nie dotyczy innych biur.
Po pierwsze, wybierz stałą określającą to biuro, np. War. Wprowadź tę stałą jako argument kompilacji warunkowej dla
aplikacji. W edytorze Visual Basic, z menu Tools wybierz Application’s Properties. Otwarte zostanie okno dialogowe Project
Properties. Wybierz zakładkę General. W polu Conditional Compilation Arguments wpisz War = -1. Ustawia to stałą na
True.

Teraz możesz wprowadzić kod, który będzie wykonywany jedynie dla warszawskiej wersji aplikacji. Aby tego dokonać,
umieść kod w konstrukcji kompilacji warunkowej.

Na przykład:
#If War Then
' Kod ten będzie uruchamiany w warszawskiej wersji
' aplikacji.
#End If

Kompilacja warunkowa może być również pomocnym narzędziem do usuwania błędów. Załóżmy, że często opatrujesz
fragmenty kodu komentarzem. Ustaw argument kompilacji warunkowej na fComment = -1. Ten znacznik, komentarz
może być używany w konstrukcji kompilacji warunkowej w celu opatrywania części kodu komentarzem:
#If fComment Then
'Ten kod będzie uruchamiany
#End If

Pisanie solidnego kodu


Nie ma sposobu na całkowite wyeliminowanie potrzeby usuwania błędów w aplikacjach. Jeśli jednak będziesz stosował się
do poniższych wskazówek, prawdopodobieństwo, że kod będzie działał poprawnie i nie będzie zawierał błędów, jest
większe.

Deklaruj zmienne w osobnych liniach programu


Dużo łatwiej jest sprawdzić, czy zmienna została zadeklarowana, jeśli zmienne umieszczane są w osobnych liniach, a nie
długich ciągach znaków. Co więcej, technika ta nie powoduje spowolnienia działania skompilowanych aplikacji.

Możesz również zauważyć, że dużo łatwiej jest odnajdywać zmienne, które


są pogrupowane ze względu na typ danych.
Część IV ♦ Tajniki VBA 218

Deklaruj zmienne w jak najwęższym zakresie


Używaj tak wielu zmiennych lokalnych, jak tylko to możliwe. To nie tylko pomoże zapobiec problemom związanym z ich
zakresem, ale również poprawi wydajność.

Używaj określonych typów danych


Zawsze deklaruj typ danych i używaj najmniejszych, jak tylko to możliwe. Jeśli nie deklarujesz typu danych, używany jest
wariantowy typ danych. Jest to nie tylko rozwiązanie mniej wydajne, gdyż wymaga zaangażowania dodatkowych zasobów,
ale przede wszystkim, w zmiennej o wariantowym typie danych można umieścić dowolne dane. Często prowadzi to do
błędów w programie. Przykładowo, jeśli zmienna powinna przechowywać liczby, a użyto wariantowego typu danych,
mogą zostać użyte inne dane niż liczby lub obiekty, czego konsekwencją będzie błąd.

Niszcz zmienne obiektów


Unikaj błędów zasobów, niszcząc zmienne obiektów. Jeśli istnieje zmienna obiektu o nazwie objWord, zniszcz ją na
końcu procedury, pisząc:
Set objWord = Nothing

Używaj słowa kluczowego TypeOf


Często do procedury ogólnej możesz dołączyć formanty. Przykładowo, przekazujesz formanty pole listy i pole listy
rozwijalnej do ogólnej procedury, która ładuje wartości przy użyciu metody AddItem. Jeśli przekazujesz formant inny niż
wyżej wymienione pola (np. przycisk poleceń), wystąpi błąd, gdyż formant ten nie posiada metody AddItem. W procedurze
użyj słowa kluczowego TypeOf, aby sprawdzić, jaki był typ przekazanego formantu. Umożliwi to uniknięcie błędu.

Używaj Me zamiast Screen.ActiveForm i Screen.ActiveControl


Gdy usuwasz błędy w aplikacji, aktywne jest okno Immediate. Stąd Screen.ActiveForm i Screen.ActiveControl nie
będą działać. Zamiast nich użyj słowa kluczowego Me.

Używaj narzędzia do obsługi błędów


W przypadku wystąpienia błędu, dzięki narzędziu do obsługi błędów będziesz mógł zaoszczędzić dużo czasu, gdyż
ułatwi Ci ono odnalezienie wadliwej instrukcji, informacji o typie błędu, numeru linii i itp. Więcej informacji na ten
temat znajdziesz w rozdziale 13., „Profesjonalna obsługa błędów”.

Używaj Option Explicit


Wymuszaj deklarowanie wszystkich zmiennych, umieszczając Option Explicit u góry każdego modułu kodu. Możesz
ustawić to domyślnie, zaznaczając opcję Require Variable Declaration w opcjach programu. Dzięki deklarowaniu
wszystkich zmiennych unikniesz błędów związanych z błędami w pisowni ich nazw.

Numeracja od 0 czy od 1?
W VBA niektóre elementy numerowane są od 0, a inne od 1. Zależy to od tego, czy zaczynasz liczenie od 0 czy od 1.
Przykładowo, tablice numerowane są od 0, a kolekcje od 1. Jeśli nie jesteś pewien, jak numerowany jest dany obiekt,
sprawdź to. Pomyłka najprawdopodobniej zakończy się błędem.

Natychmiast naprawiaj błędy


Podczas tworzenia aplikacji będzie Cię kusiło, aby ignorować znalezione błędy. Przykładowo, tworząc nową opcję
aplikacji, stwierdzasz błąd w innej części aplikacji. Najlepiej jest się zatrzymać i naprawić ten błąd. Jest to jednak trudne,
bo jesteś skupiony na tym, co właśnie tworzyłeś. Pamiętaj jednak, ze później może być dużo trudniej odnaleźć i poprawić
ten błąd. Najlepiej od razu poprawiać odnalezione błędy.

Używaj komentarzy
Nie oszukujmy się, kilka miesięcy, tygodni czy nawet dni po napisaniu kodu trudno jest pamiętać wszystkie szczegóły
dotyczące konkretnej procedury. Pisz komentarze do kodu, a będzie on łatwiejszy w obsłudze. Komentarze nie zwalniają
219 Rozdział 12. ♦ Usuwanie błędów w aplikacjach Accessa

kodu, ponieważ są pomijane przez kompilator. Aby utworzyć komentarz, przed tekstem umieść pojedynczy cudzysłów. W
oknie kodu komentarze wyświetlane są na zielono.

Do zamiany tekstu w komentarz i przywrócenia stanu poprzedniego używaj


znajdujących się na pasku narzędzi Edit opcji Comment Block i Uncomment
Block.

Używaj znaku kontynuacji wiersza


Konieczność przewijania ekranu, aby zobaczyć kod, który nie mieści się na ekranie, znacznie utrudnia przeglądanie kodu.
Upewnij się, że cały kod widoczny jest w oknie kodu, używając znaku (_) jako znaku kontynuacji linii. Dzięki temu linie
rozdzielone tym znakiem będą traktowane jak jedna całość. Typowym przykładem może być następująca instrukcja SQL:
Dim strSQL as String
strSQL = "SELECT * FROM tblErrorLog" & _
"ORDER BY tblErrorLog.ErrorLogID;"

Używaj krótkich procedur


Długie procedury trudniej zrozumieć i usunąć z nich błędy. Dziel procedury na mniejsze części. Przyjmij, że jeśli nie jesteś
w stanie wydrukować procedury na jednej stronie, powinieneś rozważyć podzielenie jej na mniejsze części.

Używaj standaryzowanych konwencji nazewnictwa


Użycie konwencji nazewnictwa umożliwi Tobie i innym programistom łatwiejsze zrozumienie kodu i usunięcie z niego
błędów. Bardzo często zdarza się, że programista przejmujący aplikację od innego, skarży się na trudności ze
zrozumieniem kodu. Użycie konwencji nazewnictwa w celu nazywania obiektów i zmiennych znacznie ułatwia proces
usuwania błędów.

Nigdy nie używaj Stop


Nigdy nie używaj Stop, aby przejść do trybu pauzy. Jak już wspomnieliśmy wcześniej, zamiast tego używaj
Debug.Assert. Poprawna składnia to Debug.Assert False.

Jeśli zapomnisz usunąć Stop przed oddaniem aplikacji użytkownikom, nie będzie ona działać poprawnie, natomiast
Debug.Assert jest podczas kompilacji usuwane z kodu.

Nie usuwaj błędów przy użyciu okien komunikatu


W przeszłości używanie okien komunikatu było powszechnie stosowaną techniką usuwania błędów w kodzie. Polegała ona
na umieszczaniu w całym kodzie okien komunikatu i na ich podstawie odnajdywaniu wadliwych instrukcji:
Sub Demo()
MsgBox 1
Select Case rst.States
MsgBox 2
Case "Washington"
MsgBox 3
MsgBox "Washington"
MsgBox 4
Case "Oregon"
MsgBox 5
MsgBox "Oregon"
MsgBox 6
Case "California"
MsgBox 7
MsgBox "California"
MsgBox 8
End Select
MsgBox 9

End Sub

Obserwując, które z okien komunikatu wyświetlane jest przed wystąpieniem błędu, możesz określić, w której znajduje się
on linii. Dużo lepszym podejściem jest ustawienie punktu zatrzymania i przejście przez kod. Ustawienie punktu
zatrzymania jest bardziej przydatne, gdyż:
u Jest szybsze niż wpisywanie dużej ilości okien komunikatu.
u Okna komunikatu są modalne, więc nie możesz przejść do okna kodu, aby przejrzeć kod.
Część IV ♦ Tajniki VBA 220

u Przechodząc przez kod przy użyciu programu uruchomieniowego, możesz sprawdzać i zmieniać wartość
zmiennych itp.
u Po naprawieniu błędu nie musisz usuwać wszystkich wstawionych okien komunikatu.
u Nie musisz się martwić, że przypadkowo dostarczysz użytkownikom aplikację, z której zapomniałeś usunąć okien
komunikatu.

Testowanie aplikacji
Zanim przekażesz aplikację do rąk użytkowników, pamiętaj o dogłębnym jej przetestowaniu. Więcej informacji na ten
temat znajdziesz w rozdziale 2. „Planowanie procesu rozwoju”.

Ćwiczenie technik usuwania błędów


Kod znajdujący się na dołączonej do książki płycie CD daje Ci możliwość przećwiczenia omówionych w tym rozdziale
technik usuwania błędów (rysunek 12.13).
Rysunek 12.13.
Przećwicz techniki
usuwania błędów
dzięki znajdującym
się na płycie CD
przykładom kodu
Rozdział 13.
Profesjonalna obsługa błędów
W tym rozdziale:
u Usuwanie błędów składni.
u Usuwanie błędów logicznych.
u Usuwanie błędów wykrytych w trakcie użytkowania.
u Błędy w różnych aplikacjach.
u Obsługa błędów w procedurach zagnieżdżonych.
u Zaawansowane zagadnienia związane z błędami.

Wizytówką profesjonalnej aplikacji jest jej obsługa błędów. Jeśli aplikacja nie radzi sobie poprawnie z błędami, niezależnie
od tego jak jest rozbudowana, użytkownicy będą niezadowoleni.

Program nie posiadający obsługi błędów może się bez ostrzeżenia zamknąć, co zwykle wywołuje u użytkowników
frustrację, gdyż nie wiedzą, dlaczego to się stało i czy bezpiecznie jest kontynuować pracę.

Gdy występuje błąd, użytkownicy powinni otrzymać informację o tym, jak sobie z tym poradzić. Niezrozumiałe informacje są
prawie tak złe jak brak informacji (rysunek 13.1). Ilu użytkowników rozumie lub uważa za przydatne takie sformułowania jak
Niedozwolona operacja, Przepełnienie czy Błąd Ogólnego Zabezpieczenia?

Rysunek 13.1.
Przykład
nieczytelnego
komunikatu
o błędzie

Bez kompleksowej obsługi błędów programiści mogą stracić także cenne sprzężenie zwrotne na temat tego, jak funkcje
ich aplikacji są w rzeczywistości wykorzystywane. Poza tym, odnajdywanie i naprawianie błędów u klientów to bardzo
czasochłonne zadanie. Nie ulega wątpliwości, że w interesie programisty jest szybkie naprawianie błędów programu.

Bez narzędzi do obsługi błędów programiści muszą opierać się na opowieściach użytkowników o tym, co robili, gdy
wystąpił błąd programu. Najczęstszą odpowiedzią użytkownika w takiej sytuacji jest „Nie wiem”. Prowadzi to do
niepotrzebnej i czasochłonnej pracy, polegającej na odnalezieniu i poprawieniu błędów. W tym rozdziale pokażemy, jak
stworzyć zaawansowane narzędzie do obsługi błędów, które pomoże zarówno użytkownikom, jak i Tobie.

Istnieją trzy typy błędów programu: błędy składni, błędy logiczne oraz błędy wykryte w trakcie użytkowania.

Usuwanie błędów składni


Zacznijmy od najprostszego rodzaju błędów programu – błędów składni. Błędy te występują w sytuacji, gdy kod jest
napisany nieprawidłowo. Na przykład, gdy nastąpił błąd w nazwie zmiennej albo słowa kluczowego lub gdy brakuje
fragmentu kodu:
Dim strName as

Oczywiście w tym przypadku brakuje ważnej części kodu. Mianowicie nie określono typu danych. Prawidłowa instrukcja
wyglądałaby w następujący sposób:
Część IV ♦ Tajniki VBA 222

Dim strName as String

Jednym ze sposobów na wyeliminowanie błędów składni jest umieszczenie Option Explicit w pierwszej linii każdego
modułu. Zmusi Cię to do deklarowania każdej ze zmiennych używanych w aplikacji.

Deklarowanie wszystkich zmiennych ważne jest z kilku powodów. Błąd w nazwie zmiennej może mieć poważne
konsekwencje. Jeśli zmienna służy do wprowadzania wartości do bazy danych, może dojść do wprowadzenia
niewłaściwych danych bez żadnego ostrzeżenia. VBA traktuje po prostu nieprawidłowo nazwaną zmienną jako kolejną
zmienną.

W poniższym przykładzie, zmienna BankBalance w drugiej linii napisana jest z błędem:


BankBalance = 4,576.98
RS!BankBalance = BankBalence

VBA nie rozpozna BankBalence jako słowa kluczowego, więc przyjmie, że chcesz zadeklarować nową zmienną typu
Variant z domyślną wartością Empty. W rezultacie, zamiast umieścić w bazie żądaną wartość 4,576.98, umieści tam
wartość Empty.

Deklarowanie zmiennych ma również znaczenie dla optymalizacji pracy aplikacji. Niezadeklarowane zmienne typu
Variant zajmują dużo cennego miejsca. Przykładowo, różnice w zajmowanej przestrzeni dla zmiennej przechowującej
liczbę 5 są następujące:
u Dim bytNumber as Byte (1 bajt);
u Niezadeklarowana zmienna (tylko dane liczbowe) (16 bajtów);
u Niezadeklarowana zmienna (ciąg znaków) (22 bajty).

W tym przykładzie, niezadeklarowanej zmiennej przyznany jest typ danych Variant. Aby wymusić deklarowanie
zmiennych, przejdź do edytora Visual Basic i z menu Tools wybierz Options. Otwarte zostanie okno dialogowe Options.
Na karcie Editor włącz Require Variable Declaration (rysunek 13.2). Spowoduje to wstawianie Option Explicit u góry
każdego modułu. Nie spowoduje jednak aktualizacji już istniejących, pamiętaj więc o umieszczeniu Option Explicit w
każdym już utworzonym module.

Rysunek 13.2.
Aby wymusić
deklarowanie
zmiennych, wybierz
Require Variable
Declaration

Można również spotkać inne błędy składni:


Msggbox "Hi"

lub
EndSeb

Błędy w pisowni tego typu słów zarezerwowanych powodują błędy składni. Podczas pisania kodu, jesteś zwykle o nich
informowany poprzez wyróżnienie błędnie napisanego tekstu oraz ukazanie się komunikatu ostrzegawczego.

W edytorze VBA wybierz z menu głównego Tools, Options. Na zakładce


Editor wyłącz opcję Auto Syntax Check. Nie wyłączy to kontroli składni, a
tylko usunie irytujące okna dialogowe, które pokazują się przy każdym
błędzie składniowym. Błąd będzie zaznaczany poprzez zmianę koloru
czcionki na czerwony.

W oknie dialogowym Options możesz zmieniać niektóre z ustawień kompilatora. Na karcie General znajduje się opcja
Compile on Demand, która umożliwia szybsze funkcjonowanie aplikacji, ponieważ moduły kompilowane są dopiero po ich
223 Rozdział 13. ♦ Profesjonalna obsługa błędów

załadowaniu do wykonania. Przy szybkości współczesnych komputerów zalecamy włączenie tej opcji w celu
wyeliminowania błędów.

Na tej samej karcie znajduje się opcja Background Compile. Po jej włączeniu uruchomione zostanie kompilowanie w tle, w
czasie, gdy komputer jest nieaktywny. Opcja ta może wpłynąć na poprawę szybkości wykonywania aplikacji. Aby ją
włączyć, opcja Compile on Demand musi być również włączona.

Aby mieć pewność, że wszystkie błędy składni zostały wykryte, ważne jest, by przed oddaniem aplikacji do rąk
użytkowników wszystkie moduły zostały skompilowane i zapisane. Z menu Debug wybierz Compile and Save All Modules,
aby skompilować i zapisać każdy moduł w bazie danych, niezależnie od tego czy są załadowane, czy nie.

Usuwanie błędów logicznych


Z błędem logicznym mamy do czynienia, gdy wykonanie kodu nie przynosi oczekiwanych rezultatów. Może to być błąd w
rozumowaniu lub program jest wykonywany nieprawidłowo. Gdy kod jest wykonywany, lecz nie przynosi oczekiwanych
rezultatów, spodziewaj się błędu logicznego.

Do usuwania błędów logicznych używaj rozbudowanego programu uruchomieniowego Microsoft Accessa. Temat ten
został omówiony w rozdziale 12., „Usuwanie błędów w aplikacjach Accessa”.

Usuwanie błędów
wykrytych w trakcie użytkowania
Nie istnieje sposób na wyeliminowanie wszystkich błędów wykrywanych w trakcie użytkowania aplikacji, lecz można się
na nie przygotować. Dlatego też narzędzie do obsługi błędów jest koniecznością.

W profesjonalnej aplikacji narzędzie do obsługi błędów umieszczone jest w każdej procedurze. Nic nie jest zostawione
przypadkowi.

Proste narzędzie do obsługi błędów


Przed omówieniem zaawansowanych narzędzi do obsługi błędów zacznijmy od prostego przykładu:
Sub Demo()
Dim I as Integer
On Error GoTo ErrorHandler
' Błąd programu w tej linii
ExitHere:
Exit Sub
ErrorHandler:
MsgBox "Wystąpił błąd"
Resume ExitHere
End Sub

To proste narzędzie stosuje się do standardowych konwencji programowych, które omówione są w następnej części.

On Error GoTo ErrorHandler


Zgodnie z konwencją, instrukcja ta znajduje się u góry procedury, po instrukcjach Dim. Znajduje się tam dlatego, by każdy
kod, w którym może wystąpić błąd, znajdował się za nią. Jeśli w kodzie pojawi się błąd, instrukcja GoTo przekaże kontrolę
nad programem do narzędzia do obsługi błędów. Narzędzie to znajduje się przy etykiecie ErrorHandler. ErrorHandler
nie jest słowem zarezerwowanym, lecz nazwą procedury (możesz użyć dowolnej nazwy).

Etykiety są łatwe do odnalezienia, gdyż znajdują się na lewym krańcu pro-


cedury i występuje po nich dwukropek.

ExitHere
Ta etykieta jest punktem wyjścia dla procedury. Dobrym zwyczajem jest umieszczanie tylko jednego punktu wyjścia dla
procedury. Jeśli procedura wykonywana jest bez błędów, wykonywany jest kod ExitHere i procedura jest zakończona. Kod w
Część IV ♦ Tajniki VBA 224

części ErrorHandler nie będzie wykonywany, gdyż znajduje się na samym końcu procedury. Wykonywanie kodu nigdy do
tego miejsca procedury nie dojdzie, bo wcześniej nastąpi wyjście.

Etykieta to świetne miejsce na umieszczenie kodu porządkującego. Przykładowo, można w tym miejscu zwolnić zmienne
obiektu, ustawiając je na Nothing, zamknąć bazę danych, przywrócić domyślne ustawienie klepsydry lub włączyć
aktualizację ekranu.

Instrukcja On Error Resume Next powinna być najczęściej pierwszą instrukcją procedury wyjścia. Jest to konieczne,
gdyż niektóre z instrukcji porządkujących mogą same powodować błędy. Przykładowo, jeśli przed otwarciem bazy
wystąpił błąd, a zmienna obiektu ustawiona jest na Nothing w procedurze wyjścia (Set db = Nothing), spowoduje to
powstanie błędu.

Jeśli jest to wolna procedura, na jej początku włączasz klepsydrę i wyłą-


czasz ją na końcu, musisz uważać, by nie „zacięła się” gdzieś pośrodku,
gdy wystąpi błąd. DoCmd.Hourglass False jest przykładem kodu
porządkującego, który powinieneś umieścić w kodzie ExitHere, aby był
wykonywany przed procedurą wyjścia, niezależnie od tego, czy błąd
wystąpił, czy nie.

W kodzie ExitHere przywróć domyślne ustawienie klepsydry. Możesz


włączyć ją na początku procedury. Jeśli błąd wystąpi, zanim wyłączysz
klepsydrę na końcu procedury, wykonywany kod przejdzie do narzędzia do
obsługi błędów, a klepsydra nie zostanie wyłączona. Jeśli w punkcie
wyjścia klepsydra powraca do ustawień domyślnych, zawsze będzie
wyzerowana.

Poniższy fragment kodu to przykład procedury wyjścia zawierającej kod porządkujący:


ExitHere:
On Error Resume Next
DoCmd.Hourglass False
DoCmd.EchoTrue
DoCmd.SetWarnings False
Set rst = Nothing
Set db = Nothing
Exit Sub

ErrorHandler
W tym miejscu znajduje się narzędzie zajmujące się obsługą błędów występujących w trakcie użytkowania programu.
Według konwencji znajduje się on u dołu procedury. Kod tego narzędzia będzie wykonywany tylko w przypadku
wystąpienia błędu. Efektem jego działania powinno być jednak coś więcej niż okno komunikatu z poprzedniego przykładu.
Radzimy dołączanie instrukcji Select Case, która umożliwi reagowanie w określony sposób na wszystkie błędy, jakie
programista może przewidzieć (więcej szczegółów w innej części tego rozdziału – „Reagowanie na błędy”). Narzędzie do
obsługi błędów powinno zawsze kończyć się instrukcją Resume.

Resume ExitHere
Tu następuje przekazanie wykonywania programu do kodu ExitHere.

Przebieg programu z narzędziem do obsługi błędów


Zauważ, jak zmienia się przebieg programu, w którym umieszczono narzędzie do obsługi błędów. Jeśli kod nie ma błędów,
program wykonywany jest w następujący sposób:
Sub Demo()
On Error GoTo ErrorHandler

Prawidłowy kod

ExitHere:
Exit Sub
ErrorHandler:
MsgBox "Wystąpił błąd"
Resume ExitHere
End Sub
225 Rozdział 13. ♦ Profesjonalna obsługa błędów

Jeśli któraś z instrukcji zawiera błąd, przebieg programu ulegnie zmianie, gdyż wykonany zostanie kod narzędzia do
obsługi błędów:
Sub Demo()
On Error GoTo ErrorHandler

Nieprawidłowy kod
ExitHere:
Exit Sub

ErrorHandler:
MsgBox "Wystąpił błąd"
Resume ExitHere
End Sub

Obiekt Err
VBA zawiera obiekt Err, który dostarcza wiele informacji, które możesz wykorzystać w narzędziu do obsługi błędów.
Obiekt Err jest obiektem globalnym, więc nie zachodzi konieczność tworzenia jego egzemplarza.

Oto właściwości obiektu Err:


u Err.Number – numer aktualnego błędu. Numer ten może by wykorzystany do reagowania na różne typy
występujących błędów.
u Err.Description – opis błędu.

u Err.Source – Obiekt lub aplikacja, które wywołały błąd.

u Err.HelpFile – ścieżka dostępu do pliku pomocy Windows. Właściwość ta, użyta razem z HelpContext,
umożliwia umieszczenie w oknie komunikatu przycisku Pomoc.
u Err.HelpContext – identyfikator kontekstu dla tematu w pliku pomocy.

u Err.Last DLL Error – systemowy kod błędu uzyskany przez odwołanie do biblioteki DLL.

Obiekt Err posiada również dwie metody:

Err.Clear
Metoda Clear czyści właściwości obiektu Err. Każde z poniższych rozwiązań powoduje wyczyszczenie właściwości
obiektu Err:
u Odwołanie do metody Clear obiektu Err (Err.Clear).

u Użycie dowolnej instrukcji Resume.


u Wyjście z procedury.
u Użycie instrukcji On Error.

Err.Raise
Metoda Raise generuje błąd związany z użytkowaniem aplikacji. Przydaje się to przy testowaniu aplikacji. Możesz
wykonać symulację błędu związanego z użytkowaniem aplikacji, przekazując kod do metody Raise obiektu Err. Ponadto,
gdy aplikacja odwołuje się do zewnętrznej biblioteki DLL, możesz przekazać wartość błędu z powrotem do aplikacji, która
zajmie się obsługą tego błędu.

Wywołując błędy, możesz generować błędy przez Ciebie definiowane. Pamiętaj jednak, by numer błędu był unikatowy i
dodaj go do stałej vbObjectError. Przykładowo, aby utworzyć numer błędu 50, przydziel do argumentu numeru
vbObjectError + 50:
Err.Number = vbObjectNumber + 50

A oto przykład użycia metody Raise:


Sub Demo (intNumber)
If intNumber = 110 Then
'Wywołaj błąd
Err.Raise vbObjectError + 50, "Moja Aplikacja"
"Liczba nie może być większa niż 100", _
"c:\MyApp\MyApp.Hlp", MyContextID
End If
End Sub
Część IV ♦ Tajniki VBA 226

Metoda Raise posiada pięć argumentów: Number, Source, Description, HelpFile i HelpContext (argumenty te są
takie same jak dla obiektu Err). Składnia wygląda następująco:
Err.Raise (Number, Source, Description, HelpFile, HelpContext)

Używając nazwanych parametrów, możesz przekazać tylko wybrane argumenty, dzięki czemu kod będzie lepiej opisany:
Err.Raise Number:= vbObjectError + 50, Description:= "Błąd Własny"

W poznaniu właściwości i metod obiektu Err pomoże Ci Object Browser.


W dowolnym module kodu naciśnij klawisz F2, wybierz bibliotekę VBA i
kliknij znajdujący się poniżej klas Err Object. Będziesz mógł przejrzeć
jego wszystkie właściwości i metody. Zaznacz dowolną z nich i naciśnij
klawisz F1, a wyświetlona zostanie pomoc na ten temat.

Reagowanie na błędy
Duża część kodu narzędzia do obsługi błędów powinna używać instrukcji Select Case. Spróbuj przewidzieć każdy
możliwy błąd, który może wystąpić, i umieść jego numer na liście w instrukcji Select Case. Wówczas będziesz mógł
radzić sobie z tym błędem we właściwy sposób.

Z przewidywanym błędem można sobie radzić na kilka sposobów:


u Okna komunikatu przedstawiające użytkownikom informacje o błędzie.
u Okna komunikatu przedstawiające użytkownikom informacje o sposobach naprawienia błędu (np. Brak dysku w
napędzie a: ).
u Zignorować błąd i kontynuować wykonywanie programu.
u Zignorować błąd i wyjść z procedury.
u Poprawić kod, by jego wykonywanie mogło być kontynuowane.
u Przejść do innego miejsca w kodzie.

Sytuację tę ilustruje poniższy kod:


ErrorHandler:
Select Case Err.Number
Case 11
If MsgBox ("Wykonałeś dzielenie przez zero, wprowadź " & _
" inną liczbę. Chcesz spróbować ponownie? ", _
vbQuestion + vbYesNo) = vbYes Then
Resume
Else
Resume ExitHere
End If
Case Else
MsgBox "Wystąpił nieoczekiwany błąd. Numer błędu: " & _
Err.Number & "Opis błędu: " & Err.Description
Resume ExitHere
End Select
End Sub

Możesz nawet tworzyć ogólne procedury, które będą obsługiwały błędy określonego typu. Przykładowo, jeśli przyjrzysz się
w bazie danych Access and Jet errors.mdb tabeli błędów Accessa i Jet, zauważysz, że błędy o numerach między 58 a 76
dotyczą błędów plików (np. File already exists, Disk full, Too many files i inne). Mógłbyś stworzyć ogólną procedurę dla
tej grupy błędów i odwoływać się do niej z instrukcji Select Case w narzędziu do obsługi błędów:
ErrorHandler:
Select Case Err.Number
Case 58 to 76
'Ogólna procedura dla obsługi błędów plików
Call FileTypeErrors
Case Else
MsgBox "Wystąpił nieoczekiwany błąd. Numer błędu: " & _
Err.Number & "Opis błędu: " & Err.Description
Resume ExitHere
End Select
End Sub
227 Rozdział 13. ♦ Profesjonalna obsługa błędów

Instrukcje Resume
Poniższe instrukcje Resume umożliwią Ci przekazanie, w przypadku wystąpienia błędu, wykonywania programu do
różnych instrukcji.

Resume
Resume powoduje przekazanie wykonywania kodu do linii, w której wystąpił błąd. Gdy użytkownik zostanie
poinformowany o sposobie rozwiązania błędu, użycie instrukcji Resume spowoduje powrót do instrukcji, w której nastąpił
błąd. Ma to zastosowanie w sytuacji, w której przyczyna powstania błędu została usunięta i chcesz powrócić do tego miej-
sca w kodzie, w którym wystąpił błąd.

Resume Next
Resume Next powoduje przekazanie wykonywania kodu do linii następującej po linii, w której wystąpił błąd. Umożliwia
to wykonanie pozostałej części kodu.

Poniższy diagram ilustruje przebieg programu dla różnych instrukcji Resume (rysunek 13.3).

Rysunek 13.3.
Obsługa błędu przy
użyciu instrukcji
Resume

Uzyskiwanie dodatkowych informacji o błędzie


Narzędzie do obsługi błędów powinno automatycznie zapisywać wszelkie informacje o błędzie, które mogą okazać się
przydatne dla programisty. Im więcej tych informacji zbierze, tym łatwiej będzie programiście odnaleźć i naprawić błąd.

Obiekt Err dostarcza wielu informacji, lecz nie wszystkich. Dobrze zaprojektowane narzędzie do obsługi błędów powinno
dostarczać następujących, dodatkowych informacji o błędzie:
u Numer linii – identyfikuje numer linii, w której wystąpił błąd. Zastanów się, czy nie warto umieścić w każdym
module określonej liczby linii. Numery linii mogłyby być wstawiane po lewej stronie modułu, przed instrukcjami
kodu. Dzięki opcji Find Accessa mógłbyś szybko przechodzić do linii, w której wystąpił błąd (przy założeniu, że
numery linii się nie powtarzają). Numery linii w procedurze nie muszą być umieszczone po kolei.

Obiekt Err nie posiada opcji numerowania linii. Aby numerować


linie, użyj funkcji Erl. Przykład jej zastosowania znajdziesz w
kodzie na dołączonej do książki płycie CD.

u Nazwa formularza lub raportu – przedstawia nazwę formularza lub raportu, w którym wystąpił błąd. Jest to
kwestia przekazania nazwy formularza lub raportu do narzędzia zajmującego się obsługą błędów.
u Nazwa procedury – przedstawia nazwę procedury, w której wystąpił błąd.
u Nazwa aktywnego formantu – przedstawia nazwę formantu, który był aktywny w momencie wystąpienia błędu.
u Wartość aktywnego formantu – przedstawia wartość aktywnego formantu w momencie wystąpienia błędu. Zdarza
się, że błąd występuje tylko w przypadku wprowadzenia określonych wartości. Przykładowo, jeśli błąd występuje,
gdy w polu tekstowym wprowadzana jest wartość większa niż 20,000, to błąd taki można z łatwością
zidentyfikować, przekazując wartość z pola tekstowego do narzędzia zajmującego się obsługą błędów.

Aktywny formant zostanie przekazany do narzędzia zajmującego się


obsługą błędów. Niektóre formanty posiadają wartości, inne nie. Narzędzie
do obsługi błędów powinno przekazać ActiveControl (informację o
aktywnym formancie) do procedury, która oceni jego wartość, używając do
Część IV ♦ Tajniki VBA 228

tego celu wbudowanej funkcji TypeOf. Jeśli formant jest polem


tekstowym, otrzymasz wartość pola tekstowego. Jeśli jednak jest to
przycisk poleceń, nie próbuj uzyskiwać jego wartości, bo spowoduje to
powstanie błędu.

u Identyfikator bieżącego rekordu – przedstawia identyfikator (ID) rekordu, który był wyświetlany w formularzu w
momencie wystąpienia błędu. Czy zdarzyło ci się zauważyć, że jeden, konkretny rekord klienta powoduje więcej
błędów niż inne? Zapisując identyfikator bieżącego rekordu w narzędziu do obsługi błędów, będziesz mógł
porównać ten rekord z innymi, które nie powodują powstawania błędów. Najczęstszym błędem jest brak
wymaganych danych w którymś z pól.
u Nazwa programu – przedstawia nazwę aplikacji, w której wystąpił błąd.

u Poziom błędu – Możesz według własnego uznania przyznać błędom wartości (np. od 1 do 5). Dzięki tej informacji
będzie można mierzyć konieczność korzystania z pomocy osoby zajmującej się serwisowaniem aplikacji.
u Nazwa użytkownika – nazwa aktualnie zalogowanego użytkownika. Zauważyłeś kiedyś, że większość błędów
zdarza się określonym użytkownikom? Określenie, którzy użytkownicy mają najwięcej problemów, może być bardzo
cenne. Wielokrotnie przekonasz się, że problemem nie są błędy w programie, lecz braki w wyszkoleniu
pracowników. Aby otrzymać nazwę użytkownika, możesz użyć ekranu logowania, a w przypadku systemów
Windows 95/98/NT nazwa zalogowanego użytkownika może być uzyskana przez odwołanie do interfejsu API
systemu Windows.

Przykład użycia odwołania do interfejsu API systemu Windows w celu ot-


rzymania nazwy zalogowanego użytkownika w narzędziach do obsługi
błędów znajduje się na dołączonej do książki płycie CD (właściwość
UserName i funkcja GetUserName).

u Data i czas – Data i czas wystąpienia błędu. Informacja ta pomaga w analizowaniu częstotliwości występowania
błędów. Prosty wykres powinien wystarczyć do wykazania, że z czasem błędy występują z mniejszą
częstotliwością.
u Notatki o błędzie – Użytkownicy mogą wprowadzać informacje o tym, co robili w momencie wystąpienia błędu.
Informacje te mogą być wprowadzane w polu tekstowym lub formularzu. Poinformuj użytkowników, że podanie
tych informacji nie jest obowiązkowe. Część z nich nigdy nie sporządzi żadnej notatki o błędzie, lecz inni docenią
możliwość udzielenia Ci informacji.

Dzięki informacjom zdobytym dzięki obiektowi Err oraz innym, opisanym tu sposobom, programiści powinni mieć
wystarczające podstawy do szybkiego i skutecznego naprawienia błędów wykrytych w trakcie użytkowania.

Zaawansowane narzędzie do obsługi błędów


Teraz, gdy wiesz już jak zbudować narzędzie do obsługi błędów na poziomie procedury i jak pobierać informacje o
błędzie, nadszedł czas na stworzenie zaawansowanego narzędzia do obsługi błędów.

Na początku musisz zdecydować, jak to narzędzie zaprojektować i gdzie umieścić kod. Można umieścić cały kod narzędzia
w każdej procedurze, jednakże w ten sposób stworzyłbyś całą masę zbędnego kodu. Nie bez znaczenia byłby fakt, że
modyfikując później narzędzie, musiałbyś dokonywać zmian w każdej procedurze.

Przyjrzyj się umieszczonym na płycie CD narzędziom do obsługi błędów na


poziomie procedury. Mimo iż użycie ogólnego narzędzia jest bardziej
wydajne, jeśli nie masz doświadczenia z takimi narzędziami, powinieneś
zapoznać się również z najbardziej podstawowymi przykładami.

Lepszym podejściem jest użycie ogólnego narzędzia do obsługi błędów dla całej aplikacji. Ogólne narzędzie do obsługi
błędów jest obiektem tworzonym przy użyciu modułu klasy.

Idąc jeszcze dalej, możesz użyć Visual Basica do stworzenia narzędzia do


obsługi błędów, które będzie mogło być używane w każdej aplikacji zgodnej
z modelem COM (Compliant Object Model). Narzędzie takie mogłoby być
229 Rozdział 13. ♦ Profesjonalna obsługa błędów

wykorzystywane do wychwytywania błędów w Accessie, Wordzie, Excelu i


wielu innych aplikacjach. Więcej informacji na ten temat znajdziesz w
rozdziale 19., „Integracja z Office 2000”.

Moduł klasowy Error (Obiekt)


Znajdujący się w kodzie tego rozdziału moduł klasowy cError zawiera właściwości i metody niezbędne do stworzenia
skutecznego narzędzia do obsługi błędów. Obiekt cError zawiera w module klasy całość kodu, który będziesz mógł teraz
wykorzystać. Dzięki technologii IntelliSense, użycie tego obiektu jest dość łatwe.

Jeśli nie miałeś okazji pracować jeszcze z modułami klasy, zajrzyj do roz-
działu 11., Tworzenie obiektów przy użyciu modułów klasowych”.

Właściwości obiektu cError


Obiekt cError posiada właściwości umożliwiające przechwycenie żądanych wartości przez narzędzie do obsługi błędów.
Właściwości te zostały opisane w tabeli 13.1.

Tabela 13.1.
Właściwości obiektu cError

Właściwość Opis
Application Nazwa programu, w którym została stworzona dana aplikacja
(np. MS Access)
AVIFileLocation Nazwa i pełna ścieżka dostępu do pliku AVI, który został odtworzony
przy powiadomieniu o błędzie
Class Nazwa modułu klasy
ComputerName Nazwa komputera, na którym wystąpił błąd
ComputerTotalMemory Całkowita pamięć tego komputera
ComputerAvailableMemory Dostępna pamięć tego komputera
ComputerOperatingSystem System operacyjny i informacje o wersji
ComputerProcessor Informacje o procesorze
ControlName Nazwa aktywnego formantu
ControlValue Wartość aktywnego formantu
CurrentRecordID Identyfikator bieżącego rekordu
Description Opis błędu zwrócony przez obiekt cError
EmailAdress Adres e-mail użyty do powiadomienia o błędzie
ErrorDatabase Nazwa i pełna ścieżka dostępu do bazy danych (np. Accessa lub SQL
Server) zawierającej tabelę z błędami
ErrorNumber Numer błędu zwrócony przez obiekt cError
ErrorTextFile Nazwa i pełna ścieżka dostępu do pliku tekstowego, zawierającego
informacje o błędzie
HelpContext Identyfikator pliku pomocy zwrócony przez obiekt cError
HelpFile Nazwa i pełna ścieżka dostępu do pliku pomocy zwrócona przez
obiekt cError
LastDllError Systemowy kod błędu dla ostatniego odwołania do bibliotek DLL
Level Ustalona wartość oznaczająca wagę błędu
LineNumber Numer linii procedury, w której wystąpił błąd

Tabela 13.1.
Właściwości obiektu cError (ciąg dalszy)
Część IV ♦ Tajniki VBA 230

Właściwość Opis
Note Notatka sporządzona przez użytkownika, opisująca co robił w momencie
wystąpienia błędu
Now Data i czas wystąpienia błędu
Procedure Nazwa procedury, w której wystąpił błąd
SoundFile Nazwa i pełna ścieżka dostępu do pliku dźwiękowego
Source Nazwa obiektu lub aplikacji, która wywołała błąd
User Nazwa użytkownika, który natrafił na błąd
WaitStateFlag Znacznik stanu oczekiwania, używany do wstrzymania
wykonywania kodu
UserEnterNoteFlag Znacznik stwierdzający, czy użytkownik ma być proszony o sporządzenie
notatki o błędzie

W momencie powstania błędu, ustawiana jest większość, jeśli nie wszystkie z tych właściwości. Wówczas można pobrać te
informacje z obiektu cError i umieścić je w oknie komunikatu, e-mailu, kalendarzu, tabeli w bazie danych lub pliku
tekstowym.

Metody obiektu cError


Metody obiektu cError dostarczają programiście użytecznych informacji o błędach. Przykładowo, informacje o błędach
mogą być przesyłane do programisty pocztą elektroniczną lub zapisywane w bazie danych. Metody obiektu cError opisane
są w tabeli 13.2.

Tabela 13.2.
Metody obiektu cError

Metoda Opis
AddToErrorHandlerOutlook Dodaj informacje o błędzie do kalendarza programu Outlook, o nazwie
Calendar ErrorHandler
Clear Czyści obiekt cError
Email W przypadku wystąpienia błędu, korzystając z programu Outlook,
wysyła programiście e-mail
EmailAllErrors Wysyła programiście e-mail, w którego załączniku znajdują się
wszystkie informacje z tabeli z błędami
GetActiveControlValue Pobiera wartość formantu aktywnego w momencie wystąpienia błędu
MessageBox Wyświetla użytkownikom okno komunikatu z informacjami o błędzie
MsgErrorDetails Grupuje informacje o błędzie, w celu umieszczenia ich w oknie
komunikatu lub e-mailu

Tabela 13.2.
Metody obiektu cError (ciąg dalszy)

Metoda Opis
OfficeAssistant W momencie wystąpienia błędu uruchamia Asystenta Pakietu Office
i pyta użytkowników, czy chcą sporządzić notatkę o błędzie
PlaySound W celu zwrócenia uwagi użytkowników w momencie wystąpienia błędu
odtwarza plik dźwiękowy
ProcessError Nadzoruje przetwarzanie informacji o błędzie na podstawie wcześniej
ustalonych zasad
ShowAVIForm Wyświetla formularz zawierający plik AVI, który informuje
użytkowników o wystąpieniu błędu
UserInputBox Wyświetla okno, w którym użytkownicy mogą wprowadzić swoje
uwagi o błędzie
UserName W systemach Windows, Windows NT pobiera nazwę zalogowanego
użytkownika
231 Rozdział 13. ♦ Profesjonalna obsługa błędów

WaitState Przechodzi w stan oczekiwania i wstrzymuje wykonywanie kodu


WriteErrorToTable Zapisuje informacje o błędzie do odpowiedniej tabeli w bazie danych
WriteErrorToTextFile Zapisuje informacje o błędzie do pliku tekstowego

Przeglądanie obiektu cError w Object Browser


Jak pewnie zauważyłeś, obiekt cError posiada wiele właściwości i metod. Aby je przejrzeć, otwórz Object Browser i
wybierz moduł klasy cError (rysunek 13.4).

Rysunek 13.4.
Obiekt cError
widziany w Object
Browser

Przetwarzanie błędu
W momencie wystąpienia błędu, narzędzie do obsługi błędów przekazuje informacje do obiektu cError. Metoda
ProcessError określa sposób przetwarzania błędu. Odwołuje się do tabeli tblErrorOptions (tabela ta opisana jest w
dalszej części rozdziału) w celu uzyskania informacji o tym, czy użytkownik ma sporządzać notatkę o błędzie lub czy
zostanie wysłany e-mail powiadamiający. Kod w metodzie ProcessError jest następujący:
Public Sub ProcessError()
Dim rst As ADODB.Recordset
Dim strSQL As String
Dim strVal As String

strSQL = "SELECT * FROM tblErrorOptions"

' Utwórz zestaw rekordów ADO


Set rst = New ADODB.Recordset

' Otwórz zestaw rekordów ADO


rst.Open strSQL, CurrentProject.Connection, adOpenKeyset, _
adLockOptimistic

Me.ErrorTextFile = rst!ErrorTextFileName

Me.UserEnterNoteFlag = rst!UserEnterNoteAboutError
Me.AVIFileLocation = CurrentProject.Path & rst!AVIFileLocation

Me.SoundFile = CurrentProject.Path & rst!SoundFile

Me.OfficeID = rst!OfficeID
Me.OfficeName = rst!OfficeName

Me.OfficePhoneNumber = rst!OfficePhoneNumber

Me.OfficeFaxNumber = rst!OfficeFaxNumber
If rst!PlaySound Then
' W razie wystąpienia błędu odtwórz dźwięk
CError.PlaySound
End If

If rst!ShowOfficeAssistant Then
' Uruchom Asystenta Pakietu Office
CError.OfficeAssistant
End If

If rst!ShowAVIForm Then
' Otwórz formularz z plikiem AVI
Część IV ♦ Tajniki VBA 232

CError.ShowAVIForm

' Wstrzymaj wykonywanie kodu do zamknięcia formularza


Me.WaitState (True)

'Zamknij formularz AVI


DoCmd.Close acForm, "frmErrorAVI", acSaveNo
End If

' Otwórz formularz, w którym użytkownik będzie mógł


' sporządzić notatkę
If Me.UserEnterNoteFlag Then
DoCmd.OpenForm "frmErrorNote", acNormal
' Wstrzymaj wykonywanie kodu do zamknięcia formularza
Me.WaitState (True)

' Zamknij formularz z notatką


DoCmd.Close acForm, "frmErrorNote", acSaveNo
End If

If rst!ErrorsToAccessTable Then
' Zapisz błąd w tabeli błędów Accessa
CError.WriteErrorToTable
End If

If rst!ErrorsToTextFile Then
' Zapisz błąd w pliku tekstowym
CError.WriteErrorToTextFile
End If

If rst!ErrorsToTextFile Then
' Zapisz błąd w pliku tekstowym
CError.WriteErrorToTextFile
End If

If rst!AddToErrorHandlerCalendar Then
CError.AddToErrorHandlerOutlookCalendar
End If

If rst!ShowMsgBoxErrors Then
' Wyświetl okno komunikatu z informacją o błędzie
CError.MessageBox
End If

' Wyświetl formularz z informacją, że użytkownik


' może kontynuować pracę. Formularz zostanie automatycznie
' zamknięty
' po upływie określonego czasu.
DoCmd.OpenForm "frmErrorDone", acNormal

rst.Close
Set rst = Nothing
End Sub

Jak widzisz, metoda ta może opierać się zarówno na właściwościach, jak i innych metodach obiektu cErrror.
Więcej informacji znajdziesz w kodzie modułu klasy cError.

Doświadczenie użytkownika końcowego


Jak powinna wyglądać obsługa błędów z punktu widzenia użytkownika końcowego? Po pierwsze, należy przyciągnąć jego
uwagę tak, by przestał pracować. Pamiętaj, że błąd może być bardzo poważny i spowodować, na przykład, wprowadzenie
do bazy niewłaściwych danych.

Dzięki odwołaniu do metod obiektu cError wyświetlony zostanie


Asystent Pakietu Office oraz formularz z plikiem AVI, odtworzony
zostanie również sygnał dźwiękowy, informujący o wystąpieniu błędu
(rysunek 13.5). Znajdujący się na płycie CD przykład kodu zawiera
również formularz AVI, powiadamiający użytkownika o błędzie
(rysunek 13.6). Wywołanie takich zdarzeń przy użyciu modułu klasy
cError jest bardzo proste:
cError.OfficeAssistant
cError.AVIForm
cError.Sound
233 Rozdział 13. ♦ Profesjonalna obsługa błędów

Rysunek 13.5.
Asystent pakietu
Office informuje
użytkownika
o wystąpieniu błędu

Rysunek 13.6.
Formularz z plikiem
AVI informuje
o wystąpieniu
błędu

Wówczas możesz użyć obiektu cError do wyświetlenia formularza lub pola, które umożliwią użytkownikom opisanie
czynności, wykonywane w momencie wystąpienia błędu (rysunek 13.7). Niektórzy użytkownicy docenią taką możliwość, inni
po prostu ominą ten krok. Formularz z notatką zawiera informację, że sporządzanie jej nie jest obowiązkowe.

Rysunek 13.7.
Formularz
umożliwiający
użytkownikom
sporządzenie
notatki o błędzie

Można również wyświetlić okno komunikatu zawierające szczegółowe informacje o błędzie (rysunek 13.8).

Ostatni krok to wyświetlenie informacji o tym, że błąd został zapisany i można bezpiecznie kontynuować pracę (rysunek
13.9). Służy do tego formularz, który zamknie się automatycznie po trzech sekundach.

Dzięki tym wszystkim działaniom użytkownicy są przez cały czas wspomagani – nie są po prostu brutalnie wyrzuceni z
aplikacji. Narzędzie do obsługi błędów umożliwi kontynuowanie wykonywania kodu i aplikacja będzie działać nadal.
Użytkownicy będą natychmiast poinformowani o błędzie i będą mieli możliwość przekazania własnych spostrzeżeń. A co
najważniejsze, użytkownicy mają pewność, że informacja o wystąpieniu błędu została przekazana do programisty i że
mogą kontynuować pracę. Dzięki takiej obsłudze błędów użytkownicy będą przekonani o profesjonalizmie Twojej
aplikacji.
Rysunek 13.8.
Okno komunikatu
ze szczegółowymi
informacjami
o błędzie

Rysunek 13.9.
Poinformuj
użytkownika, że
może bezpiecznie
kontynuować pracę
Część IV ♦ Tajniki VBA 234

Identyfikowanie problemów sprzętowych


Czy zdarzyło Ci się kiedyś zauważyć, że niektóre komputery w biurze ciągle generują błędy? Jest to chyba najtrudniejszy
problem do rozwiązania. Problem może być związany ze sprzętem, jego konfiguracją, konfliktem z innymi aplikacjami itp.

Zauważ, że narzędzie do obsługi błędów radzi sobie z tym na kilka sposobów. Obiekt cError posiada właściwości (tabela
13.1), które umożliwiają przechwycenie nazwy komputera, całkowitej i dostępnej wielkości pamięci, systemu operacyjnego i
typu procesora.

Wszystkie te informacje mogą być przydatne we wskazaniu, dlaczego dany komputer sprawia problemy. Podczas gdy inne
działają poprawnie. Najczęstszym problemem jest pamięć, dlatego też w razie wystąpienia błędu zwracaj uwagę na
informacje o całkowitej i dostępnej ilości pamięci.

Sporządzanie raportów o błędach


Gdy już wiesz, jak narzędzie do obsługi błędów odbierane jest przez użytkowników, zobaczmy, co daje programiście, czyli
Tobie. Dzięki obiektowi cError możesz kompilować i analizować błędy programowe na kilka sposobów:
u Raport o błędach – raport o błędach to raport Accessa zawierający informacje z tabeli, w której są zapisane
wszystkie błędy (rysunek 13.10).
u Wysyłanie e-maili o pojedynczych błędach – za każdym razem gdy występuje błąd, związane z nim szczegóły
przesyłane są do Ciebie pocztą elektroniczną przy użyciu metody E-mail (rysunek 13.11).
Rysunek 13.10.
Raport Accessa
zawierający
informacje
o błędach

Rysunek 13.11.
E-mail zawierający
informację
o pojedynczym
błędzie

u Wysyłanie e-maila o wszystkich błędach – przy użyciu metody EmailAllErrors informacje o wszystkich błędach z
tabeli z błędami mogą być przesyłane do Ciebie pocztą elektroniczną jako załącznik wiadomości programu
Outlook. Tabela ta zapisywana jest jako arkusz programu Excel i załączana do wiadomości.
u Zapisywanie informacji o błędzie w bazie danych Accessa – dzięki użyciu metody WriteErrorToTable każdy błąd
dodawany jest do tabeli w bazie danych.
235 Rozdział 13. ♦ Profesjonalna obsługa błędów

u Zapisywanie informacji o błędzie w pliku tekstowym – dzięki użyciu metody WriteErrorToTextFile wszystkie
błędy będą zapisywane w wybranym pliku tekstowym.
u Zapisywanie informacji o błędzie w kalendarzu programu Outlook – informacje o błędach mogą być zapisywane w
kalendarzu programu Outlook i przeglądane

w różnych, zarówno wbudowanych jak i własnych, widokach. Dzięki użyciu metody


AddToErrorHandlerOutlookCalendar informacje o błędach przesyłane są do odpowiedniego kalendarza
(rysunek 13.12).

Rysunek 13.12.
Kalendarz programu
Outlook, zawierający
informacje o błędach

Używając jednej lub kilku metod raportowania, otrzymujesz natychmiastowe powiadomienia o występowaniu błędów.
Posiadasz również wszystkie informacje niezbędne do odnalezienia i naprawienia błędu oraz narzędzia umożliwiające
analizę historyczną.

Opcje obiektu cError


Jak widzisz, rozbudowane narzędzie do obsługi błędów zawiera wiele opcji i możliwości. Niektórzy Twoi klienci będą
chcieli wykorzystać je wszystkie, inni nie.

Wszystkie opcje tego narzędzia znajdują się w tabeli tblErrorOptions.

Tabela 13.3.
Możliwości dostępne w module obsługi błędów

Opcja Opis Typ danych


AccessErrorTableName Nazwa tabeli Accessa zawierającej informacje Tak/Nie
o błędzie
AddToErrorHandlerCalendar Dodawanie błędu do kalendarza programu Outlook Tak/Nie
AVIFileLocation Pełna ścieżka dostępu do pliku AVI odtwarzanego Tekst
w formularzu AVI
DatabaseName Nazwa bazy danych, w której znajduje się tabela Tekst
z informacjami o błędach
DatabasePath Pełna ścieżka dostępu do wspomnianej bazy danych Tekst
EmailAdress Adres e-mail, na który mają być wysyłane informacje Tekst
o błędach

Tabela 13.3.
Możliwości dostępne w module obsługi błędów (ciąg dalszy)

Opcja Opis Typ danych


EmailErrors Powiadamianie o błędach za pomocą poczty Tak/Nie
elektronicznej
ErrorsToAccessTable Zapisywanie informacji o błędzie w tabeli Accessa Tekst
ErrorsToTextFile Zapisywanie informacji o błędzie w pliku tekstowym Tekst
Część IV ♦ Tajniki VBA 236

PlaySound Odtwarzanie dźwięku w przypadku wystąpienia błędu Tak/Nie


ShowAVIForm Otwieranie formularza z plikiem AVI w przypadku Tak/Nie
wystąpienia błędu
ShowMsgBoxerrors Wyświetlanie okna komunikatu z informacją o błędzie Tak/Nie
ShowOfficeAssistant Uruchamianie Asystenta Pakietu Office w przypadku Tak/Nie
wystąpienia błędu
SoundFile Pełna ścieżka dostępu do pliku dźwiękowego Tekst
UserEnterNoteAboutError Umożliwienie użytkownikowi sporządzenia notatki Tak/Nie
o błędzie

W zależności od wybranych opcji narzędzie do obsługi błędów będzie funkcjonować inaczej. Do przechowywania
informacji o opcjach obiektu cError służy tabela, więc kod aplikacji może być od niej zależny. Zamiast umieszczać
wartości nowych opcji w kodzie, możesz je po prostu wprowadzić do tabeli z opcjami. Jest to dużo prostsze rozwiązanie,
gdyż kod sam odnajdzie w tej tabeli potrzebne informacje.

Oczywiście nie należy kazać użytkownikom wprowadzać danych prosto do tabeli. Łatwe aktualizowanie i zmienianie opcji
związanych z błędami umożliwia formularz frmErrorOptions (rysunek 13.13).

Rysunek 13.13.
Formularz,
z poziomu którego
można modyfikować
opcje związane
z obsługą błędów

W tym momencie, masz już nie tylko zaawansowane narzędzie do obsługi błędów, ale co równie ważne, narzędzie, które
jest przyjazne i łatwe w obsłudze.

Odwołania do interfejsu API systemu Windows


Pełen zestaw funkcji, jakie powinno posiadać zaawansowane narzędzie do obsługi błędów, nie byłby możliwy do osiągnięcia bez
kilku odwołań do interfejsu API systemu Windows.

Narzędzie do obsługi błędów otrzymuje nazwę użytkownika, który napotkał błąd. Zamiast prosić użytkownika o podanie
swojej nazwy, narzędzie pobiera ją z interfejsu API. Odwołanie do interfejsu API systemu w systemach Windows
95/98/NT wygląda następująco:
' Odwołanie do interfejsu API systemu Windows w celu pobrania nazwy użytkownika.
Private Declare Function GetUserNAme Lib "advapi32.dll" _
Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long)

W momencie wystąpienia błędu może być odtwarzany wybrany dźwięk, który zaalarmuje użytkowników. Do tego
potrzebne jest również odwołanie do interfejsu API:
' Odwołanie do interfejsu API systemu Windows w celu
' odtworzenia dźwięku.
Private Declare Function sndPlaySound32 Lib "winmm.dll" Alias _
"sndPlaySoundA" (ByVal lpszSoundName As String, _
ByVal uFlags As Long) As Long

Inne odwołania do interfejsu API mogą służyć do pobierania nazwy komputera, informacji o stanie pamięci, systemie
operacyjnym i procesorze.
237 Rozdział 13. ♦ Profesjonalna obsługa błędów

Błędy w różnych aplikacjach


Współczesne aplikacje Accessa zawierają w sobie inne aplikacje i komponenty. Stąd też, błędy mogą pochodzić z wielu
źródeł. W typowej aplikacji Accessa mogą występować błędy związane z samym Accessem, VBA, DAO, ADO lub innymi
aplikacjami (np. Word). Każda aplikacja posiada własne kody błędów, które mogą być zapisywane przez narzędzie do
obsługi błędów.

Przejrzyj znajdującą się na płycie CD bazę danych Access and Jet


database Errors.mdb. Zawiera ona numer i opisy błędów baz
danych Accessa i Jet.

Obsługa błędów
w procedurach zagnieżdżonych
Często w kodzie możesz mieć procedury, które odwołują się do innych procedur, które odwołują się do jeszcze innych
procedur itd. Jak radzić sobie z obsługą błędów w takich przypadkach?

Służy do tego tworzona automatycznie lista zawierająca wszystkie odwołania do procedur (rysunek 13.14). Możesz
przeglądać tę listę w dowolnym momencie, wybierając z menu Tools Edytora Visual Basic pozycję Call Stack.

Rysunek 13.14.
Okno Call Stack

W momencie wystąpienia błędu jego obsługą zajmuje się narzędzie zawarte w bieżącej procedurze. Jeśli jednak w tej
procedurze takie narzędzie nie istnieje, obsługa błędu spadnie na narzędzie z procedury, z której nastąpiło odwołanie.
Innymi słowy, VBA będzie przeszukiwać listę odwołań, aż znajdzie narzędzie do obsługi błędów.

Zwróć uwagę na zagrożenia związane z następującym scenariuszem:


obsługą błędu zajmuje się niewłaściwe narzędzie. Przeznaczone było do
obsługi zupełnie innej instrukcji kodu, w zupełnie innej procedurze niż ta,
w której wystąpił błąd. Stąd też rzeczą podstawową jest umieszczanie
narzędzia do obsługi błędów w każdej procedurze.

Zaawansowane zagadnienia
związane z błędami
Teraz, gdy już wiesz jak radzić sobie z błędami składni, logicznymi oraz błędami związanymi z użytkowaniem aplikacji,
przyjrzyj się bardziej zaawansowanym kwestiom związanym z obsługą błędów.

Procedury zdarzeń związane z błędami


Formularze i raporty w Accessie posiadają zdarzenia Przy błędzie, które można wykorzystać do wyświetlenia dowolnej
wiadomości w razie wystąpienia błędu. Procedura tego zdarzenia posiada dwa argumenty:
u DataErr – numer błędu zwracany przez obiekt Err. Używając tego argumentu, możesz reagować na określone
typy błędów. Jeśli, przykładowo, DataErr jest równe 11, wystąpił błąd dzielenia przez zero.
u Response – określa, czy komunikat o błędzie jest wyświetlany. Argument ten możesz wykorzystać do określenia
sposobu powiadomienia o błędzie. Aby zignorować błąd i wyświetlić własny komunikat o błędzie, użyj stałej
acDataErrContinue. Aby wyświetlić standardowy komunikat Accessa, użyj stałej acDataErrDisplay.
Część IV ♦ Tajniki VBA 238

Typowy fragment kodu wyglądałby następująco:


Private Sub Form_error(DataErr As Integer, Response As Integer)
Dim strMessage As String
If DataErr = 11 Then
Response = acDataErrContinue
StrMessage = "Sprawdź wartość, wykonałeś dzielenie przez zero"
MsgBox strMessage
End If
End Sub

On Error GoTo 0
Powyższa instrukcja wyłącza obsługę błędów w procedurze. Powoduje to również wyzerowanie obiektu Err (tak jak w
przypadku użycia metody Clear obiektu Err (Err.Clear)). Metoda Err.Clear została opisana w jednym z
wcześniejszych rozdziałów książki.

On Error Resume Next

Nie używaj instrukcji On Error Resume Next, gdy nie posiadasz żadne-
go narzędzia do obsługi błędów. W takim przypadku, wykonywanie kodu
będzie kontynuowane, a wszystkie błędy będą ignorowane. Może to mieć
katastrofalne konsekwencje. Przykładowo, w momencie wystąpienia błędu,
który powoduje utratę danych w bazie, ta instrukcja nakaże kontynuację
wykonywania kodu!

Metoda AccessError
Metoda ta może być użyta do zwrócenia opisu błędu Accessa. Przykładowo, wpisując ?AccessError(11) w oknie Immediate
otrzymamy Division by zero (Dzielenie przez zero).

Rysunek 13.15.
Użycie metody
AccessError
w oknie Immediate

Inne funkcje związane z błędami


Poniższe dwie funkcje mogą być bardzo użyteczne:
u IsError – funkcja służąca do określenie, czy zmienna związana z błędem ma wariantowy typ danych
(Variant). Funkcja ta zwraca wartość logiczną.
u CVError – konwertuje wartość zmiennej związanej z błędem na zmienną wariantową.

Ustawienie opcji wyłapujących błędy


W Edytorze Visual Basic, z menu Tools wybierz Options. Na zakładce General znajdziesz opcje regulujące obsługę błędów
przez Access (rysunek 13.16):
239 Rozdział 13. ♦ Profesjonalna obsługa błędów

Rysunek 13.16.
Ustawienia opcji
wyłapujących błędy

u Break on All Errors – w momencie wystąpienia błędu kod zatrzymuje się w danej linii, niezależnie od istnienia
narzędzia do obsługi błędów. Opcja ta jest dobra w momencie usuwania błędów aplikacji, pamiętaj jednak, by ją
wyłączyć, przekazując aplikację użytkownikom.
u Break in Class Module – w momencie wystąpienia błędu kod zatrzymuje się w danej linii jedynie w przypadku
modułów klasy, przy braku narzędzia do obsługi błędów.
u Break on Unhandled Errors – w momencie wystąpienia błędu kod zatrzymuje się w danej linii w każdej
procedurze, nie zawierającej narzędzia do obsługi błędów.

Możesz wyłączyć ustawienie Break on All Errors w procedurze, umieszcza-


jąc u jej góry następujący kod:
Application.SetOption "Break On All Errors", False
Rozdział 14.
Optymalizacja aplikacji
W tym rozdziale:
u Ulepszanie podstaw: optymalizacja sprzętu i systemu Windows.
u Instalowanie aplikacji w celu uzyskania optymalnej wydajności.
u Optymalizacja silnika bazy danych Jet.
u Narzędzia do pomiaru wydajności.
u Spojrzenie za kulisy.
u Optymalizacja bazy danych od podstaw.
u Poprawa wydajności kwerend.
u Zwiększenie szybkości kwerend.
u Przyspieszenie funkcjonowania formularzy.
u Pisanie szybkiego kodu.

Optymalizacja aplikacji jest tematem niekończącej się dyskusji między programistami. Każdemu zależy na osiągnięciu
optymalnego rozwiązania, lecz co w tym przypadku jest rozwiązaniem optymalnym? Jedni uważają za takie dużą szybkość
aplikacji, więc dla nich najlepszymi technikami są najszybsze z nich. Inni uważają, że optymalne rozwiązanie powinno
zapewniać jak największą stabilność aplikacji, nawet za cenę zmniejszonej przez przesadną ostrożność szybkości działania.
Jeszcze inni za cel optymalny uważają jak największą elastyczność i łatwość w obsłudze. Kto ma rację? Jak to często w ży-
ciu bywa, żaden z nich. Optymalizacja polega na znalezieniu równowagi pomiędzy tymi trzema celami.

Rozwiązanie optymalne zapewnia użytkownikowi odpowiednią szybkość. Zazwyczaj użytkownik nie zaakceptuje zbyt
wolnej aplikacji. Jeśli jednak okaże się, że wybór tego rozwiązania prowadzi do utraty danych, będzie niewątpliwie
wyborem złym. Jeśli aplikacja działa z zadowalającą szybkością i do tego jest stabilna, istnieje duże prawdopodobieństwo,
że jej użytkownicy będą zainteresowani jej kolejnymi wersjami. Jednakże niekonwencjonalne rozwiązania w projekcie i
nieortodoksyjne jego wykonanie mogą sprawić, że dobrze przyjęta aplikacja będzie trudna do ulepszenia i rozbudowania.

Pod pewnymi względami, aplikacje są jak samochody. Niewiele osób chciałoby znaleźć się za kierownicą bardzo
szybkiego samochodu, który źle się prowadzi lub ma słabe hamulce. Natomiast większość z nas życzyłaby sobie mieć
samochód, który zapali każdego dnia i zawiezie nas tam, gdzie chcemy. Nie zapominajmy też o tym, że rachunki za serwi-
sowanie tego samochodu nie powinny rujnować naszego budżetu. Mimo iż rozdział ten dotyczy optymalizacji, pamiętaj o
tym, że aplikacja powinna być również stabilna i łatwa w rozbudowie.

W rozdziale tym omówimy wiele technik służących optymalizacji aplikacji. Prawie wszystkie z nich mają jakieś
ograniczenia, a niektóre mogą wręcz spowodować efekty odwrotne do zamierzonych. Nawet najlepsze z nich mogą nie
nadawać się do rozwiązania jakiegoś konkretnego problemu. Kilka technik zastosowanych razem może wzajemnie
pomniejszać efekty swojego działania. Jednakże z rozwagą stosując to, czego nauczy Cię lektura tego rozdziału,
powinieneś umieć poprawić wydajność swoich aplikacji.

Jedynym sposobem na sprawdzenie, czy techniki te będą działać w danym przypadku, jest eksperymentowanie. Rezultaty
mogą być często zaskakujące. Jednocześnie metoda, która w jednym przypadku dała zdumiewające rezultaty, w innym
może nie dać żadnych. Optymalizacja jest bardzo złożonym procesem, gdyż środowisko, w którym pracujemy, jest bardzo
złożone i podlega ciągłym zmianom, a prawdziwy cel optymalizacji jest dość trudny do zdefiniowania. Pisząc o
optymalizacji, należałoby omówić setki zagadnień. W rozdziale tym zaczniemy od omówienia problemów związanych ze
sprzętem i systemem operacyjnym, a zakończymy na różnych technikach kodowania.
241 Rozdział 14. ♦ Optymalizacja aplikacji

Ulepszanie podstaw: optymalizacja sprzętu i systemu Windows


Każdy element Accessa posiada wiele możliwości poprawienia wydajności aplikacji, lecz żaden z nich nie zda się na zbyt
wiele, jeśli aplikacja będzie działać na przestarzałym komputerze, ze zbyt mała ilością pamięci. Zazwyczaj tańszym
rozwiązaniem jest zakup sprzętu niż zapłacenie firmie programistycznej za osiągnięcie tego samego rezultatu. Sprzęt jest
tańszy niż oprogramowanie, a modyfikacje sprzętowe poprawiają funkcjonowanie wszystkich aplikacji uruchamianych na
danym komputerze.

Nie powinno nikogo dziwić, że aplikacja Accessa (lub jakakolwiek inna) będzie działać szybciej na szybszym komputerze.
Jeśli masz możliwość poprawy szybkości komputera, na którym będzie uruchamiana aplikacja, zrób to. Opublikowane przez
Microsoft minimalne wymagania potrzebne do uruchomienia Accessa lub pakietu Office są niczym innym jak właśnie
minimalnymi wymaganiami. Programiści szybko przekonają się, że uruchomienie aplikacji Access na takim komputerze
będzie miało marny efekt. Tak naprawdę, komputer taki powinien spełniać co najmniej poniższe wymagania:
u Procesor Pentium 133 MHz.
u 32 MB RAM (szczególnie w przypadku systemu Windows NT).
u Jeśli masz wybierać między szybszym procesorem a większą ilością pamięci, wybierz pamięć. Jest to najtańszy
sposób na poprawę wydajności komputera. Pamiętaj również, że minimalne wymagania dla komputera, na którym
tworzy się aplikacje ,są dużo wyższe. Programista powinien dysponować komputerem, który posiada między
innymi procesor minimum Pentium 200 MHz oraz 32
– 64 MB RAM.
u Niezależnie od ilości posiadanej pamięci RAM, zawsze istnieje możliwość jej wykorzystania. Access, jak każda
poważna baza danych, do poprawnego funkcjonowania potrzebuje dużo pamięci. Powinieneś podjąć kroki w celu
zapewnienia aplikacji możliwie jak największej ilości pamięci.
u Aby to osiągnąć, usuń wygaszacze ekranu, tapety (chyba że jest to standardowa bitmapa), rysunki z tła i wszystko,
co może być zbędne. Tylko niezbędne aplikacje mogą korzystać z procesora w trakcie działania bazy danych. Im
więcej pamięci dostarczysz Accessowi, tym szybciej będzie działał.
u Nie używaj RAM-dysków. W nowoczesnych, 32-bitowych systemach nie ma na nie miejsca.
u Regularnie opróżniaj kosz i usuwaj pliki tymczasowe (szczególnie te, związane z Internetem i pocztą
elektroniczną). Bazy danych potrzebują do funkcjonowania dużo przestrzeni dyskowej, a takie pliki mogą
zajmować duże jej ilości.
u Korzystaj z narzędzi do defragmentacji dysków. W zależności od systemu operacyjnego, defragmentacja może
być automatyczna lub nie. Pliki komputerowe nie są przechowywane w jednym kawałku. Gdy tworzysz,
edytujesz, zapisujesz i usuwasz pliki, komputer rozdziela je i umieszcza w różnych miejscach. Tak samo jest z
plikami baz danych. Jeśli twardy dysk jest sfragmentowany, nawet proste przeszukiwanie może trwać dłużej niż
normalnie, gdyż komputer musi przeszukać cały dysk, by odnaleźć żądane fragmenty.
u Unikaj kompresji dysków (również kompresji NTFS). Uruchamianie bazy danych na skompresowanym dysku
będzie miało znaczny, negatywny wpływ na wydajność aplikacji.
u Kup większy dysk twardy. W zależności od rozmiaru aplikacji, możesz potrzebować 5 do 10 razy więcej wolnego
miejsca niż wynosi rozmiar pliku MDB. Brak wolnego miejsca spowoduje spadek wydajności dużych kwerend,
spowolni transakcje, kompilację, obsługę, importowanie i działanie kwerend. W ostatnich latach ceny przestrzeni
dyskowej znacznie spadły.
u Wyłącz dziennik programu Outlook. Opcja ta zapisuje każde otwarcie i zamknięcie aplikacji. Może to
spowodować utratę cennej przestrzeni dyskowej i niepotrzebne obciążenie procesora.
u Odbieraj brakującą pamięć. Aplikacje bardzo łatwo zajmują pamięć, lecz gorzej jest z oddawaniem. Otwieranie
wielu aplikacji, w tym Accessa, spowoduje zmniejszenie rzeczywistej, dostępnej ilości pamięci. Zamknięcie
Accessa spowoduje odzyskanie tej pamięci.
u Instaluj system Windows i pakiet Office lokalnie. Nie uruchamiaj ich przez sieć. Wydaje się to dziwne, lecz wciąż
istnieją miejsca, gdzie praktykuje się takie rozwiązania.
u Na poprawę wydajności aplikacji mogą również wpłynąć zmiany w pliku wymiany (pamięci wirtualnej). Gdy
Accessowi zabraknie pamięci, zaczyna korzystać z wirtualnej pamięci na dysku twardym. Jeśli wirtualnej pamięci jest
za mało, Access w celu wykonywania swoich operacji musi ciągle zapisywać i odczytywać informacje z dysku.
Zwiększenie ilości pamięci wirtualnej może poprawić wydajność bazy danych. Pamiętaj jednak, ze zapisywanie i od-
czytywanie informacji z dysku jest znacznie wolniejsze niż korzystanie z pamięci RAM. Zwiększenie pliku wymiany
ma sens tylko wtedy, gdy dysk jest zdefragmentowany.
Część IV ♦ Tajniki VBA 242

Upewnij się, ze plik wymiany nie znajduje się na skompresowanym dysku


lub partycji. Kompresja znacznie spowolni odczytywanie i zapisywanie na
dysku tymczasowych plików, które muszą być w tym miejscu zapisywane.

Wiele z wyżej wymienionych kwestii może być poza Twoją kontrolą, lecz tworząc aplikację Accessa, powinieneś rozważyć je i
w razie konieczności zaproponować. Jako projektant bazy danych Accessa masz większą kontrolę nad tym, czy korzystać z
możliwości optymalizacji.

Wielu programistów używa komputerów dużo szybszych niż te, na których


będzie działać aplikacja. Pamiętaj, by przetestować aplikację na kom-
puterach podobnych do tych, jakich używają przyszli użytkownicy. Jeśli
konfiguracje sprzętowe komputerów użytkowników są różne, pisz aplikację
pod kątem najsłabszego z nich.

Instalowanie aplikacji
w celu uzyskania optymalnej wydajności
Sposób, w jaki skonfigurujesz pliki, z których aplikacja korzysta, może mieć wpływ na jej wydajność. Poniższe wskazówki
powinny pomóc w osiągnięciu prawidłowego funkcjonowania aplikacji i umożliwić Ci skorzystanie z reszty tego rozdziału.
u Oddziel dane od aplikacji. Tworzenie pliku MDB z tabelami, umieszczanie go w sieci i instalowanie na
komputerach użytkowników innego pliku MDB zawierającego kwerendy, formularze, raporty itp. powinno być
standardem. Ma to również wpływ na wydajność, dostępność dla wielu użytkowników i łatwość obsługi aplikacji.
Ze wszystkich zawartych w tym rozdziale sugestii tę powinieneś ignorować tylko z naprawdę ważnych przyczyn.
u Używaj aktualnej wersji pliku grupy roboczej (system.mdw). Mimo iż możliwe jest użycie wcześniejszych wersji
pliku grupy roboczej w aplikacji, użycie aktualnej wersji powinno dać największą wydajność.
u Zmniejszaj bazę danych regularnie. Powinieneś kompaktować bazę za każdym razem, gdy importujesz, usuwasz
lub aktualizujesz większe ilości danych. Kompaktowanie bazy danych powoduje usunięcie pustych miejsc między
stronami danych i ponowne przeliczenie statystyk bazy, używanych w optymalizacji kwerend (więcej na ten temat w
dalszej części rozdziału). Proces ten powoduje również zwolnienie części przestrzeni dyskowej dla innych
procesów. Access 2000 posiada opcję kompaktowania bazy danych przy jej zamykaniu. Z menu Narzędzia
wybierz Opcje i na zakładce Ogólne zaznacz pole Kompaktuj przy zamknięciu. Niektórzy programiści zauważyli,
że we wcześniejszych wersjach Accessa kompaktowanie odnosiło rezultaty tylko wtedy, gdy było wykonywane
dwukrotnie. Spróbuj kompaktować swoją bazę przy uruchamianiu, a dzięki zaznaczeniu opcji Kompaktuj przy
zamknięciu, będzie ona zawsze kompaktowana dwukrotnie.
u Gdy tylko jest to możliwe, instaluj wersję MDE swojej aplikacji. Rozwiązanie to posiada kilka zalet. MDE
wymaga skompilowanych modułów, a moduły takie działają szybciej niż nieskompilowane. MDE daje większą
wydajność przy mniejszym zapotrzebowaniu na RAM i przestrzeń dyskową.

Przed zainstalowaniem MDE upewnij się, że użytkownicy wiedzą, iż żaden


z nich nie będzie w stanie modyfikować aplikacji w tej formie. Ze względu
na dużą popularność Accessa wielu użytkowników chce mieć możliwość
dokonywania późniejszych modyfikacji w aplikacji. Powinieneś również
bardzo dokładnie przetestować taką aplikację, gdyż komunikaty o błędach
MDE są bardzo trudno zrozumiałe.

Optymalizacja silnika bazy danych Jet


Dobrze skonfigurowany komputer i zoptymalizowana instalacja nie dadzą zbyt dużych rezultatów, jeśli nie
zoptymalizujesz samej aplikacji. Aplikacja bazy danych składa się z kilku elementów. Najważniejszym z nich jest silnik
baz danych Jet. Jet znajduje się w centrum prawie wszystkich procesów zachodzących w aplikacjach Accessa i można go
243 Rozdział 14. ♦ Optymalizacja aplikacji

optymalizować tak jak inne elementy baz danych. Optymalizację silnika Jet powinieneś zacząć dopiero po ukończeniu całej
lub prawie całej aplikacji i po rozważeniu różnych technik optymalizacyjnych wewnątrz aplikacji.

Jet 4.0, silnik baz danych Accessa 2000, posiada kilka zalet odróżniających go od wcześniejszych wersji. Takie opcje, jak:
nowe typy danych, kompresja tekstu, indeksowanie pól memo, implementacja ANSI SQL-92, zarządzanie zabezpieczeniami,
zwiększona elastyczność dzięki indeksom klucza obcego, znacznie poszerzony schemat replikacji i poprawione blokowanie,
wpływają na znaczną poprawę wydajności aplikacji. Opcje te

zostały w pełni opisane w innych rozdziałach tej książki. Powinieneś je przejrzeć, by dowiedzieć się więcej o tych ważnych
opcjach. Teraz zajmiemy się jedynie ich wpływem na wydajność aplikacji.

Jet zajmuje się większością kwestii związanych z optymalizacją, bez żadnej interwencji programisty czy użytkownika. Ze
wszystkich czynności, jakie Jet wykonuje, około 15 z nich możesz zobaczyć w rejestrze. Ich ustawienia nie są zbyt
oczywiste i powinieneś podejść do nich z ostrożnością. Zmiana tych ustawień może przynieść efekt odwrotny

do zamierzonego. Nawet, jeśli aplikacja będzie działać szybciej, może mieć negatywny wpływ na inne ważne rzeczy, jak
stabilność czy zarządzanie współbieżnością. Lista dostępnych ustawień rejestru silnika Jet znajduje się w tabeli 14.1.

Tabela 14.1
Ustawienia rejestru dla silnika Jet 4.0

Wartość Stała dla metody


Klucz Opis Miejsce Klucza
Domyślna SetOption
Liczba milisekund, 2000 \HKEY_LOCAL_MACHINES dbExclusive
ExclusiveAsyncDelay

jakie Jet musi \SOFTWARE\MICROSOFT\JET\ AsyncDelay


odczekać przed 4.0\ENGINES\JET4.0
wykonaniem ukrytej
transakcji
w środowisku
z wyłącznością

Gdy w tym miejscu 500 \HKEY_LOCAL_MACHINES dbFlush


FlushTransactionTimeout

wprowadzona jest \SOFTWARE\MICROSOFT\JET Transaction


wartość, wyłączone są \4.0\ENGINES\JET4.0 Timeout
SharedAsyncDelay
i ExclusiveAsyncDelay
.Wartość ta określa
liczbę milisekund do
rozpoczęcia
zapisywania
asynchronicznego, bez
dodawania stron do
bufora
Określa, czy system No (Nie) \HKEY_LOCAL_MACHINES dbImplicit
ImplicitCommitSync

ma czekać na \SOFTWARE\MICROSOFT\JET CommitSync


zakończenie transakcji \4.0\ENGINES\JET4.0
ukrytych przed
kontynuacją innych
procesów. Jeśli
wybrano wartość No,
Jet będzie przetwarzał
transakcje ukryte
asynchronicznie

Tabela 14.1
Ustawienia rejestru dla silnika Jet 4.0 (ciąg dalszy)

Wartość Stała dla metody


Klucz Opis Miejsce Klucza
Domyślna SetOption
Liczba milisekund 100 \HKEY_LOCAL_MACHINES dbLockDelay
LockDlay

zanim Jet podejmie \SOFTWARE\MICROSOFT\JET


następną próbę \4.0\ENGINES\JET4.0
blokowania
Część IV ♦ Tajniki VBA 244

Ilość prób, jakie Jet 20 \HKEY_LOCAL_MACHINES dbLockRetry


LockRetry

podejmie w celu \SOFTWARE\MICROSOFT\JET


zablokowania strony \4.0\ENGINES\JET4.0

Rozmiar bufora silnika 0 \HKEY_LOCAL_MACHINES dbMaxBuffer Size


MaxBufferSize

Jet w kilobajtach \SOFTWARE\MICROSOFT\JET


\4.0\ENGINES\JET4.0

Maksymalna liczba 9500 \HKEY_LOCAL_MACHINES dbMaxLocksPer


MaxLocksPerFile

blokowań dla jednej \SOFTWARE\MICROSOFT\JET File


transakcji. Jeśli \4.0\ENGINES\JET4.0
transakcja wymaga
więcej blokowań,
zostanie ona
podzielona na kilka
innych, które będą
wykonywane osobno.
Ustawienie to może
stwarzać problemy
w przypadku Novell
NetWare 3.1
(Nowość w Accessie 0 \HKEY_LOCAL_MACHINES
PagesLockedToTableLock

2000). Nadaje wyłączny \SOFTWARE\MICROSOFT\JET


dostęp do tabel w celu \4.0\ENGINES\JET4.0
dokonywania
aktualizacji poprzez
programową kontrolę
nad liczbą blokowań
strony, zanim Jet
spróbuje zablokować
całą tabelę. Ustawienie
50 sprawi, że Jet
spróbuje zablokować
tabelę za 51 razem. Jeśli
to się nie uda, Jet
spróbuje kolejny raz za
101 razem. Wartość
zero wyłącza tę opcję

Tabela 14.1
Ustawienia rejestru dla silnika Jet 4.0 (ciąg dalszy)

Wartość Stała dla metody


Klucz Opis Miejsce Klucza
Domyślna SetOption
Ilość czasu, przez jaki 5000 \HKEY_LOCAL_MACHINES dbPageTimeout
PageTimeout

niezablokowana przed \SOFTWARE\MICROSOFT\JET


odczytem strona jest \4.0\ENGINES\JET4.0
przechowywana
w buforze, zanim
zostanie odświeżona.
Czas mierzony jest
w milisekundach
Określa, czy Jet będzie 0 \HKEY_LOCAL_MACHINES dbRecycleLVs
RecycleLVs

odzyskiwał obiekty (wyłączony) \SOFTWARE\MICROSOFT\JET\


OLE, memo i strony 4.0\ENGINES\JET4.0
binarne
245
SharedAsyncDelay Rozdział 14. ♦ Optymalizacja aplikacji

Liczba milisekund, 50 \HKEY_LOCAL_MACHINES dbSharedAsync


jakie Jet musi \SOFTWARE\MICROSOFT\JET Delay
odczekać przed \4.0\ENGINES\JET4.0
wykonaniem ukrytej
transakcji w
środowisku ogólnym

Ilość wątków 3 \HKEY_LOCAL_MACHINES Brak


Threads

używanych w tle \SOFTWARE\MICROSOFT\JET


przez Jet \4.0\ENGINES\JET4.0

Określa, czy system Yes (Tak) \HKEY_LOCAL_MACHINES dbUserCommit


UserCommitSync

czeka na zakończenie \SOFTWARE\MICROSOFT\JET Sync


operacji zapisu przed \4.0\ENGINES\JET4.0
kontynuowaniem
innych procesów. Jeśli
wybrano wartość No,
Jet będzie przetwarzał
transakcje jawne
asynchronicznie
Określa kolejność 1 \HKEY_LOCAL_MACHINES Brak
CompactByPKey

sortowania kluczy \SOFTWARE\MICROSOFT\JET


podstawowych. Jeśli \4.0\ENGINES\JET4.0
wybrano wartość 1,
Jet będzie ustawiał
rekordy według
wartości klucza
podstawowego.
W przypadku
ustawienia 0, rekordy
pozostaną w kolejności
ich wprowadzania
(kolejność naturalna)

Tabela 14.1
Ustawienia rejestru dla silnika Jet 4.0 (ciąg dalszy)

Wartość Stała dla metody


Klucz Opis Miejsce Klucza
Domyślna SetOption
Nazwa i pełna ścieżka acces_path\ \HKEY_LOCAL_MACHINES Brak
SystemDB

dostępu do pliku grupy system.md \SOFTWARE\MICROSOFT\JET


roboczej \4.0\ENGINES\JET4.0

(Nowość w Accessie 1 \HKEY_LOCAL_MACHINES


PrevFormatCompactWith
UNICODECompression

2000). Umożliwia lub \SOFTWARE\MICROSOFT\JET


blokuje kompresję pól \4.0\ENGINES\JET4.0
tekstowych i memo.
Domyślnie kompresja
jest dozwolona.
Część IV ♦ Tajniki VBA 246

Opcja ta jest domyślnie \HKEY_LOCAL_MACHINES Brak

Domyślnie nie zainstalowano


JetShowPlan

zainstalowana. Gdy \SOFTWARE\MICROSOFT\JET


zostanie utworzona \4.0\ENGINES\JET4.0
przez programistę
i ustawiona na On
(uwaga na dużą literę),
Jet tworzy i umieszcza
w bieżącym katalogu
plik tekstowy o nazwie
showplan.out.
Gdy kwerendy są
wykonywane,
informacje o tym
zapisywane są w tym
pliku. Pamiętaj
o wyłączeniu tej opcji
po zakończeniu
tworzenia aplikacji.

Bezpieczne modyfikowanie ustawień silnika Jet


Istnieją trzy sposoby modyfikowania ustawień rejestru silnika Jet:
u Bezpośrednie edytowanie wartości przez Regedit.exe.
u Tworzenie profilu użytkownika w celu pominięcia ustawień domyślnych i odwoływanie się do tego profilu przy
użyciu wiersza poleceń profilu.
u Umożliwienie aplikacjom tymczasowego pomijania ustawień domyślnych poprzez użycie metody SetOption
obiektu bazy danych.

Proponujemy korzystanie z trzeciej opcji. Nie tylko dlatego, że jest prosta w użyciu, ale również dlatego, że umożliwia
modyfikowanie ustawień dla każdej aplikacji z osobna. Aby naprawdę zoptymalizować wydajność, możesz nawet zmieniać
ustawienia w różnych częściach aplikacji.

Technika ta nigdy nie powoduje zmiany ustawień domyślnych, tak więc tworzenie nowych projektów rozpoczyna się w
tym samym miejscu.

Aby tymczasowo pomijać wartości rejestru, nie musisz odwoływać się do interfejsu API. Silnik bazy danych posiada
odpowiednią metodę i dwa argumenty. Składnia jest następująca:
DBEngine.SetOption StałaNazwaUstawienia, Wartość

Przykładowo, wydajność niektórych aktualizacji może wzrosnąć dzięki temu, że Jet będzie czekał przed wykonaniem transakcji
ukrytych. Kod, który czasowo wydłuży czas oczekiwania SharedAsyncDelay do 1 sekundy (1000 milisekund), wygląda
następująco:
DBEngine.SetOption dbSharedAsyncDelay, 1000

Ustawienie to działa do momentu, aż aplikacja dokona jego zmiany za pomocą metody SetOption, DBEngine wyjdzie poza
zakres lub aplikacja zostanie zamknięta. SetOption nie zapisuje wartości do Rejestru. Za pomocą metody SetOption nie
możesz zmieniać wartości domyślnych dla SystemDB, CompactByPKey ani wątków.

Jeśli Twoja aplikacja używa źródła danych ODBC, przejrzyj ustawienia


rejestru w
\HKEY_LOCAL_MACHINES\SOFTWARE\MICROSOFT\JET\4.0
\ENGINES\ODBC.
247 Rozdział 14. ♦ Optymalizacja aplikacji

Narzędzia
służące do pomiaru wydajności
Ważne jest, czy łączny wynik Twoich działań spowodował poprawę, a nie obniżenie wydajności aplikacji. Do
monitorowania i oceny wydajności jednej techniki względem innej służy klika narzędzi. Pierwszym z nich jest zegar, który
mierzy czas wykonywania określonych procesów. Drugim z nich jest nieudokumentowana funkcja, która liczy operacje
wykonywane z użyciem dysku, bufora i blokowania. Trzecie narzędzie to opcja Accessa, dzięki której możesz przeglądać
plan wykonywania kwerendy. Pierwsze dwa z tych rozwiązań możesz stosować na prawie każdej z przedstawionych w tym
rozdziale technik. Plany wykonywania kwerend mają zastosowanie tylko w przypadku optymalizowania pracy kwerend.

Mimo iż VBA posiada funkcję Timer(), może ona być niewystarczająca do oceny działań optymalizacyjnych. Funkcja ta
mierzy w sekundach upływ czasu od momentu 0:00. Jest ona jednak mało precyzyjna i może nie być odpowiednia do
Twoich celów szczególnie, gdy chcesz mierzyć operacje trwające mniej niż 1 sekundę. Wielu programistów używa funkcji
GetTickCount. Mimo iż wydaje się, że funkcja ta zwraca czas w milisekundach, ponieważ jest ona związana z zegarem
komputera, w rzeczywistości mierzy ona czas co 1/18 sekundy, co nie do końca odpowiada milisekundzie. Interfejs API
systemu Windows posiada zegar, który mierzy czas w milisekundach. Funkcja timeGetTime() mierzy upływ czasu od
momentu uruchomienia systemu Windows. Ponieważ używa innego zegara sprzętowego niż GetTickCount, zwraca czas
mierzony z dokładnością do milisekundy.

Używając timeGetTime(), możemy wstawić linię kodu przed i za żądanym miejscem i otrzymamy bardzo dokładny
pomiar długości trwania danej czynności.

Do odwołania się do interfejsu API potrzebujemy dwóch rzeczy: deklaracji funkcji i zmiennej globalnej, która posłuży do
przechowywania początkowego czasu zegara. W części deklaracyjnej modułu wprowadź następujące trzy linie:
Private Declare Function a2ku_apigettime Lib "winmm.dll" _
Alias "timeGetTime" () As Long
Dim lngstartingtime As Long

Teraz możesz utworzyć procedurę, która uruchomi zegar i funkcję, która go zatrzyma.
Sub a2kuStartClock()
lngstartingtime = a2ku_apigettime()
End Sub
Function a2kuEndClock()
a2kuEndClock = a2ku_apigettime() – lngstartingtime
End Function

Wydruk 14.1 ilustruje wykorzystanie tych funkcji do oceny wydajności kwerendy.

Wydruk 14.1. Obliczanie czasu wykonywania kwerendy


Sub QueryTimer(strQueryName As String)

Dim db As Database
Dim qry As QueryDef
Dim rs As Recordset

Set db = CurrentDb()

Set qry = db.QueryDefs(strQueryName)

'Uruchom zegar
a2kuStartClock

Set rs = qry.OpenRecordset()

'Zatrzymaj zegar i wyświetl rezultat w oknie Debug


Debug.Print strQueryName & " Wykonano w: " & a2kuEndClock &_
" milisekund"

rs.Close

End Sub

Aby otrzymać jak najdokładniejsze wyniki, umieść odwołania a2kuStart-


Clock i a2kuEndClock jak najbliżej analizowanej procedury.
Część IV ♦ Tajniki VBA 248

Spojrzenie za kulisy
Mimo iż mierzenie czasu jest ważne, nie pozwala ocenić wydajności w trakcie tworzenia aplikacji. Najprawdopodobniej
tworzenie aplikacji ma miejsce na platformie dużo szybszej niż te, na których będzie używana, a testowanie odbywa się na
mniejszym niż w rzeczywistości zestawie danych. Co więcej, zegar nie daje odpowiedzi na pytanie, jak aplikacja będzie działać
na komputerze z mniejszą ilością pamięci lub mniejszym twardym dyskiem. Aby zajrzeć za kulisy Twojej aplikacji, możesz użyć
kolejnej nieudokumentowanej funkcji: ISAMStats. Funkcja moża dać Ci kilka cennych wskazówek na temat funkcjonowania
aplikacji. Mierzy ona sześć operacji mających wpływ na wydajność: odczyty z dysku, zapisy na dysku, odczyty z bufora, odczyty
z wyprzedzeniem z bufora, ustanowienia blokowania oraz zdjęcia blokowania. Funkcja ta działa zarówno w Accessie 2000, jak i
we wcześniejszych wersjach tego programu. Jej składnia jest bardzo prosta:
DBEngine.ISAMStats (Opcja, [reset])

Oto sześć możliwości argumentu Opcja:

Argument dla Opcja Opis


0 Zapis na dysku
1 Odczyt z dysku
2 Odczyt z bufora
3 Odczyt z bufora (odczyty z wyprzedzeniem)
4 Ustanowienie blokowania
5 Zdjęcie blokowania

Opcjonalny argument reset umożliwia wyzerowanie indywidualnych liczników. W celu użycia tej funkcji do pomiaru
wydajności musisz odjąć jeden odczyt od drugiego lub wyzerować licznik i wykonać operację. Wydruk 14.2 zawiera
przykład użycia funkcji ISAMStats celem pomiaru wydajności:

Wydruk 14.2. Sposób użycia funkcji ISAMStats do pomiaru wydajności


Sub PrintStats()

Dim i As Integer

Debug.Print
Debug.Print "Zapis na dysku: " & ISAMStats(0, False)
Debug.Print "Odczyt z dysku: " & ISAMStats(1, False)
Debug.Print "Odczyt z bufora: " & ISAMStats(2, False)
Debug.Print "Odczyt z wyprzedzeniem z bufora: " & _
ISAMStats(3, False)
Debug.Print "Ustanowienie blokowania: " & ISAMStats(4, False)
Debug.Print "Zdjęcie blokowania: " & ISAMStats(5, False)

For i = 0 To 6
ISAMStats i, True
Next

End Sub

PrintStats pokaże, dlaczego jedna technika może być lepsza od innej. Informacja ta może Ci również pomóc w
dokonaniu racjonalnego wyboru między dwiema technikami, których czas wykonywania w milisekundach jest taki sam.
Dzięki tym informacjom zobaczysz, jak duży wpływ na wydajność różnych technik mają różnice w konfiguracji czy
wielkości zestawu danych.

Funkcje A2KU_TimeClock i PrintStats przydają się tylko w przypadku porównywania różnych technik między sobą.
Co więcej, wyniki tych testów będą wiarygodne tylko wówczas, gdy będziesz je przeprowadzał wielokrotnie, w różnych
warunkach, i wyciągał średnie z ich wyników. Możesz bez trudu połączyć te dwie funkcje w jedną, by za jej pomocą
przeprowadzać odpowiednie testy i sporządzać z nich raporty.

W dalszej części tego rozdziału wykorzystamy te dwie funkcje, aby pokazać, jak można ich używać i jak wykazać różnicę
między dwiema technikami.
249 Rozdział 14. ♦ Optymalizacja aplikacji

Optymalizacja bazy danych od podstaw


Relacyjne bazy danych, do których również zaliczamy Accessa opierają się na tabelach, w których zawarte są informacje.
Sposób, w jaki te tabele oraz relacje między nimi są zaprojektowane, ma duży wpływ na wydajność aplikacji. Jeśli tabele
nie są znormalizowane, zindeksowane, a relacje między nimi ustanowione są w niewłaściwy sposób, wykonanie każdej
kwerendy i procedury będzie zabierać dużo więcej czasu. Najlepsza rzecz, jaką możesz uczynić dla poprawy wydajności
bazy danych, to prawidłowo zaprojektować tabele.

Projektowanie tabel
w celu osiągnięcia poprawy wydajności
Oprócz generalnej zasady, jaką jest normalizacja, podczas tworzenia tabel powinieneś pamiętać o poniższych punktach:
u Gdy pracujesz z połączonymi tabelami, spraw, by łącza między nimi miały charakter stały.
u Negatywny wpływ na wydajność ma użycie w tabelach prostych podarkuszy danych, gdzie podarkusz jest drugą
tabelą, a łącza pola nadrzędnego i podrzędnego używają pól indeksowanych. Jednakże użycie bardziej złożonego
podarkusza danych mogłoby zrównoważyć ten negatywny efekt. Zamiast w tabelach, używaj podarkuszy w
kwerendach. W ten sposób możesz z nich korzystać tylko wtedy, gdy tego potrzebujesz, a nie za każdym razem,
gdy otwierasz tabelę.
u Maski wprowadzania, pola odniesienia i reguły poprawności powinny również być używane tam, gdzie są
potrzebne – w formularzach. Najlepiej jest, by tabele były tak proste jak tylko to możliwe.
u Nie twórz większych pól niż to konieczne. Access rezerwuje miejsce na dane według rozmiaru danego pola.
Możesz zmarnować dużo miejsca (i czasu), używając typów danych lub ustawień właściwości zbyt dużych dla
danych, które znajdują się w tych polach.

Normalizacja danych
w celu osiągnięcia poprawy wydajności
O normalizacji już w tej książce mówiliśmy, teraz tylko zwrócimy uwagę na kilka jej aspektów:
u Znormalizowana baza danych pozwala zaoszczędzić przestrzeń dyskową, gdyż nie powtarza bez potrzeby danych.
u Znormalizowana baza danych używa mniejszej ilości stron danych i stron indeksów, co skraca czas wyszukiwania
danych.
u W znormalizowanej bazie danych prawdopodobieństwo wystąpienia konfliktu lub pomyłki w danych jest
mniejsze, gdyż powtarzają się one rzadziej.
u Kiedy można zrezygnować z normalizacji? Można to zrobić, gdy chcesz oprzeć aplikację na nieznormalizowanych
tabelach, jeśli będą one tabelami tymczasowymi, których tworzenie jest czasochłonne. Jednakże dane powinny
być zawsze przechowywane w znormalizowanej strukturze. Pamiętaj, że będziesz musiał stworzyć procedury,
które będą aktualizować znormalizowaną strukturę o czynności wykonywane, na nieznormalizowanej strukturze –
to może wpłynąć na poprawę wydajności. Łamanie reguł normalizacji powinno być jednak ostatecznością.
u Innym przypadkiem, w którym zazwyczaj możesz bezkarnie rezygnować z normalizacji, jest reguła
powtarzalności danych, gdy dotyczy ona danych drugorzędnych. Często zdarza się, że w jednej tabeli
przechowywanych jest mnóstwo informacji o kliencie lub produkcie, które, jeśli by przestrzegać zasad, powinny
być umieszczone w osobnych tabelach (np. służbowe i domowe numery telefonów, numery faksu, numery
telefonów komórkowych, numery pagerów, adresy e-mail itd.).
u Łam zasady normalizacji tylko wtedy, gdy ma to sens. Może to czasami wpłynąć korzystnie na wydajność części
aplikacji. Pamiętaj jednak, że może się to odbić na stabilności i późniejszej obsłudze bazy danych oraz na
integralności danych.

Idealny schemat normalizacji zakładałby tworzenie tabeli o przedstawicielach z polem ID klienta, typem kontaktu, innym
polem do przechowywania numerów telefonów i jeszcze innym do adresów e-mail. Jest to jednak pewna przesada i osiągnięta
w ten sposób integralność i elastyczność nie zrównoważyłyby utraty wydajności. Całkiem rozsądne jest przechowywanie tych
danych w tabeli o klientach i korzystanie z wyższej wydajności. Jednakże co do zasady, powinieneś normalizować wszystko
co tylko możliwe. Tego właśnie oczekuje silnik Jet, który najlepiej pracuje na znormalizowanych danych.
Część IV ♦ Tajniki VBA 250

Tworzenie indeksów
w celu przyspieszenia pracy kwerend
u Indeksy mogą dziesięciokrotnie przyspieszyć pobieranie danych.
u Indeksy mogą również spowolnić aktualizowanie i wprowadzanie danych, więc unikaj tworzenia zbędnych
indeksów.
u Twórz takie klucze podstawowe, które są zrozumiałe dla danych i dla użytkowników. Z punktu widzenia
wydajności umożliwienie Accessowi tworzenie pól klucza podstawowego przez wstawianie pola Autonumerowanie
jest praktycznie bezużyteczne. Powinieneś używać czegoś, co posiada większe znaczenie, chyba że użytkownicy nie
znajdują innego sposobu na identyfikowanie rekordów. Niech będzie to numer telefonu, numer PESEL, numer
konta, kod sprzedawcy itp. Aby indeks naprawdę wpływał na poprawę wydajności kwerendy, musi być
wykorzystywany w kwerendzie.
u Indeksuj wszystkie te pola w tabeli, których będziesz używał jako kryterium. Indeksowanie kilku pól w tabeli
ułatwi optymalizowanie utworzonych później kwerend.
u Indeksuj pola po obu stronach przewidywanego sprzężenia. Ponieważ pola Numer Zamówienia jest w relacji
zarówno z tabelami Szczegóły Zamówień, jak i Zamówienia, obie te tabele powinny posiadać odpowiedni indeks.
Jeśli jednak masz zamiar tworzyć wiele raportów według pola Data Zamówienia, również to pole powinno być
indeksowane.

Wcześniejsze tworzenie
relacji jako sposób na poprawę wydajności
Do tworzenia relacji między tabelami używaj okna Relacje. Wykonując tę czynność w tym oknie, masz możliwość
określenia właściwości tworzonej relacji. Dzięki temu również poinformujesz Jet o jej istnieniu. Będzie on wówczas w
stanie wykorzystać te informacje do przygotowania bardziej efektywnego planu optymalizacji, który zostanie wy-
korzystany podczas tworzenia kwerend. Ma to wpływ na poprawę wydajności.

Krótko mówiąc, normalizuj dane, gdy jest to konieczne twórz indeksy, bądź oszczędny przy określaniu typów danych i
rozmiarów pól oraz pamiętaj o tworzeniu prostych tabel. Ich celem jest przechowywanie danych, a nie ich prezentowanie.

Poprawa wydajności kwerend


Mimo iż użytkownicy mogą nigdy nie zobaczyć, jak wyglądają kwerendy, to one właśnie wykonują większość pracy w
aplikacji. Relacyjna baza danych byłaby bezużyteczna, gdyby nie można było tworzyć w niej kwerend. Jednak nie wszystkie
kwerendy tworzone są w ten sam sposób. Nawet gdy wykonałeś wszystkie czynności niezbędne do znormalizowania
danych oraz utworzyłeś wszystkie wymagane indeksy, może się okazać, że kwerendy nie będą działać tak szybko jak
powinny. Może się nawet zdarzyć, że dwie kwerendy zwracające ten sam zestaw wyników będą miały różną wydajność.

Aby zrozumieć, jak działa optymalizacja kwerend, musisz poznać sposób, w jaki obchodzi się z nimi Jet. Każda kwerenda
przechodzi cztery etapy:
66. Definicja – przy użyciu jednego z kilku narzędzi tworzona jest instrukcja SQL.
67. Kompilacja – ciąg SQL jest dzielony na części.
68. Optymalizacja – używając działającego w oparciu o koszt algorytmu, Jet tworzy i testuje różne sposoby
otrzymania żądanego zestawu wyników.
69. Wykonanie – używając optymalnego planu, Jet dostarcza użytkownikowi zestaw wyników.

Kwerendę możesz definiować poprzez siatkę QBE, ciąg SQL wykonywany w kodzie, ciąg SQL we właściwości Źródło
wierszy formularza, raportu lub formantu lub w każdy inny sposób, który powoduje powstanie ciągu SQL.

Jet umieszcza części ciągu w hierarchicznej, wewnętrznej strukturze. Części te przypominają słowa kluczowe instrukcji
SQL. Tabela podstawowa użyta przez kwerendę (From) stanowi podstawę. Następnie ustawiane są kolumny zestawu
wyników (Select). Później ustawiane są kryteria i ograniczenia (Where), które musi spełnić kwerenda. Kolejnym ele-
mentem są informacje o relacjach tabeli podstawowej (Join). Ostatnia część to informacja o sposobie sortowania zestawu
wyników (Order by). Struktura ta charakterystyczna jest dla fazy optymalizacji.
251 Rozdział 14. ♦ Optymalizacja aplikacji

Optymalizacja to najbardziej złożony etap. Jet wycenia i oblicza koszt każdego z możliwych rozwiązań. Dokonuje tego na
dwa sposoby: uzyskując dostęp do tabel bazowych i sprawdzając istniejące między nimi sprzężenia. Zrozumienie sposobu,
w jaki Jet postrzega kwerendy, może pomóc Ci w projektowaniu szybszych kwerend w przyszłości.

Jet pobiera wiersze z tabel na trzy sposoby:


u Skanowanie – jest to najdroższe rozwiązanie. Jet przeszukuje każdy wiersz bez użycia indeksu. Kwerenda wymusi
na aparacie Jet skanowanie tabeli jeśli:
Jej ograniczenie dotyczy nieindeksowanego pola.
Duża część wierszy tabeli spełnia kryteria kwerendy.
u Indeksowanie – Jet używa do przeszukiwania wierszy tabeli jej indeksu. Mimo, iż może się zdarzyć, że Jet będzie
odczytywał stronę z danymi więcej niż raz, rozwiązanie to jest dużo szybsze niż skanowanie.
u Optymalizacja Rushmore – opcja ta dostępna jest tylko w sytuacji, w której ustanowione w kwerendzie
ograniczenia dotyczą więcej niż jednego indeksu. Rushmore umożliwia silnikowi Jet znaczne zmniejszenie (w
niektórych przypadkach nawet do zera) ilości odczytywanych stron z danymi. Dzięki użyciu optymalizacji
Rushmore Jet odczytuje jedynie indeksowane strony, co jest rozwiązaniem niezwykle wydajnym.

Oczywistym jest, że jeśli to tylko możliwe, powinieneś unikać skanowania i jak najlepiej wykorzystywać indeksy. Ale jak
sprawdzić, czy najlepsze z rozwiązań – optymalizacja Rushmore – będzie działać na danej kwerendzie? Nie ma sposobu na
włączenie lub wyłączenie technologii Rushmore, nie istnieją również żadne opisujące ją wskaźniki. Jest ona zawsze włączona,
lecz tylko niektóre z rodzajów kwerend mogą z niej korzystać. Aby kwerenda wykorzystywała optymalizację Rushmore
muszą być spełnione trzy warunki:
u Kwerenda musi posiadać kilka indeksów.
u Kryteria kwerendy muszą dotyczyć pól z indeksami.
u Instrukcje kryteriów muszą używać tych indeksów na jeden z trzech sposobów:
u Część wspólna – wyrażenie kryterium z operatorem „AND”. Jet mógłby w tym przypadku skorzystać z
optymalizacji Rushmore, gdyż oba te pola są indeksowane.
WHERE NazwaFirmy='Ernst Handle' And Miasto='Graz'

u Połączenie – wyrażenie kryterium z operatorem „OR”. Jet mógłby w tym przypadku skorzystać z optymalizacji
Rushmore, gdyż oba te pola są indeksowane.
WHERE NazwaFirmy='Ernst Handle' Or Miasto='Graz'

u Zliczanie – podlicza kwerendę, zwracając jedynie liczbę rekordów. Rushmore zoptymalizuje tę kwerendę
nawet przy braku ograniczeń w warunku Where.
SELECT Count(*) FROM Klienci;

Upewnij się, że we wszystkich tabelach, które mogą z tego skorzystać, umieściłeś indeksy. Spróbuj również tak
konstruować kwerendy, by można było uzyskiwać części wspólne i połączenia tych indeksów. Wykorzystanie tych dwóch
wskazówek powinno załatwić sprawę operacji tabel podstawowych w planie wykonywania kwerendy.

Gdy Jet wybrał już sposób dostępu do danych w pojedynczych tabelach, musi sprawdzić, jakie między tabelami występują
relacje. Tę fazę optymalizacji można by nazwać określaniem strategii sprzężenia. W przewidywaniu strategii sprzężenia
planu wykonywania pomoże Ci znajdująca się w tabeli 14.2 charakterystyka typów strategii.

Tabela 14.2.
Typy złączeń: jak działają i jak je rozpoznać

Typ sprzężenia Sposób działania Cechy charakterystyczne Użycie


Indeks-Połączenie Większość pracy Indeksy użyte są po obu Gdy tylko to możliwe
wykonują indeksy stronach relacji. Co najmniej
jeden z indeksów nie
dopuszcza wartości null
(klucz podstawowy).
Wszystkie tabele muszą być
w rodzimym formacie
aparatu Jet

Tabela 14.2.
Typy złączeń: jak działają i jak je rozpoznać

Typ sprzężenia Sposób działania Cechy charakterystyczne Użycie


Część IV ♦ Tajniki VBA 252

Indeks Pierwsza tabela jest Indeks użyty jest w polu Jeśli w drugiej tabeli jest
skanowana, (polach) relacji drugiej tabeli. niewiele rekordów, jeśli jej
a następnie, przy W indeksach tych możliwe są rekordy nie są wyświetlane
użyciu indeksów, wartości null. Ograniczenia nie w zestawie wyników lub
odnajdywane są używają indeksów jeśli ograniczenie
wiersze w drugiej w kryterium pierwszej tabeli
tabeli jest bardzo wąskie
Połączenie Obie tabele Dwie tabele sortowane według Obie tabele są duże
skanowane są sprzężonych pól. Dane z obu i sortowane według pól
jednocześnie tabel wyświetlane są w relacji
w zestawie wyników
Odnośnik Druga tabela jest Brak indeksów w polach Gdy druga tabela jest mała
sortowana sprzężonych obu tabel i nie ma indeksu w polu
i skanowana przed relacji tej tabeli
sprzężeniem
Iteracja Iteracja wiersz po Brak indeksów po obu Tylko na bardzo małych
zagnieżdżona wierszu przez każdą stronach sprzężenia tabelach i gdy nie ma innego
tabelę w relacji rozwiązania

Wybór typu zestawu wyników


zapewniającego optymalną wydajność
Jet bierze również pod uwagę żądany zestaw wyników. Przykładowo, aby przedstawić dynamiczny zestaw rekordów
(dynaset), użyje on planu, który umożliwi efektywne zaprezentowanie pierwszej strony danych nawet, jeśli plan ten
będzie wolniejszy przy prezentowaniu pozostałych rekordów. Do stworzenia dynasetu Jet użyje zestawu unikalnych
wartości klucza, które wskażą wiersze w podległych tabelach podstawowych. Dzięki temu, wystarczy, że Jet zaprezentuje
tylko wartości klucza, a dalsza część rekordów może zostać odsłonięta dopiero, gdy zażyczy sobie tego użytkownik.
Natomiast w przypadku zdjęcia, Jet zbiera wszystkie rekordy i kolumny, zanim zaprezentuje wyniki. Jeśli całe zdjęcie nie
mieści się w pamięci, zostanie przerzucony do pliku wymiany, co będzie miało negatywny wpływ na wydajność. Większą
wydajność uzyskałbyś więc z dużego dynasetu niż dużego zdjęcia.

Najpierw Jet wycenia opcje dostępu do tabel podstawowych. Każdy plan dostępu do tabeli podstawowej otrzymuje ocenę.
Następnie Jet wycenia dostępne opcje sprzężenia i przyznaje im oceny. Jet będzie brał jedynie pod uwagę sprzężenie
wyników relacji z tabelą podstawową. Nie bierze zaś pod uwagę sprzężenia wyników jednego sprzężenia z drugim.
Umożliwia to ograniczenie czasu, jaki Jet poświęci na optymalizację kwerend. Po przeanalizowaniu każdej możliwej strategii
sprzężenia i każdej możliwej strategii dostępu do tabeli podstawowej oraz po uwzględnieniu żądanego typu zestawu wyni-
ków Jet wybierze plan.

W przypadku tabel nie korzystających z ODBC Jet oczyści, zmniejszy i przekaże plan do wykonania.

Taka kompilacja i optymalizacja ma miejsce, gdy po raz pierwszy tworzysz, modyfikujesz lub uruchamiasz kwerendę.
Kwerenda może pozostać nieskompilowana, jeśli zmodyfikujesz ją i zapiszesz, ale nie uruchomisz. Również w przypadku,
gdy modyfikujesz indeksy tabeli lub schemat danych, kwerendy mogą nie być optymalizowane. Pamiętaj, by zawsze przed
dostarczeniem aplikacji użytkownikom otwierać kwerendy w widoku Projekt, zapisywać je i uruchamiać. Dzięki temu
będziesz miał pewność, że kwerendy są skompilowane.

W celu zoptymalizowania kwerend, Jet wykonuje kompleksową ocenę kosztów. Pośród elementów tej oceny znajduje się
przegląd statystyk bazy danych. Statystyki te mówią, ile w bazie danych istnieje stron danych, stron indeksowanych, wierszy w
tabelach i innych elementów. Statystyki te mogą być zniekształcone, jeśli baza została w nieprzewidziany sposób zamknięta,
wstrzymano transakcje lub baza wymaga zmniejszenia. Pamiętaj, by przed optymalizacją wykonać kompaktowanie bazy
danych.

Jak już pisaliśmy wcześniej, Jet tworzy plan wykonywania dla każdej kwerendy. Tworząc w rejestrze wpis
\HKEY_LOCAL_MACHINES\SOFTWARE\MICROSOFT\JET\4.0\ENGINES\DEBUG

i ustawiając jego wartość ciągu na On, Jet utworzy w bieżącym folderze plik tekstowy, zawierający plan wykonywania
kwerendy. Wiele z omówionych już tematów pojawia się w planie optymalizacji kwerendy. Nie masz możliwości
modyfikowania planu, chyba że poprzez zmianę schematu danych, konstrukcję kwerendy lub ograniczenia w kwerendzie.
Im plan bardziej szczegółowy, tym lepiej. Wydruk 14.3 przedstawia plan wykonywania kwerendy Zamówienia Kwartalne
w bazie Northwind.
253 Rozdział 14. ♦ Optymalizacja aplikacji

Wydruk 14.3. Plan wykonywania kwerendy, korzystający z optymalizacji Rushmore


--- Quarterly Orders ---

-Inputs to Query-
Table "Customers"
Using index "Primary Key"
Having Indexes:
Primary Key 91 Entries, 1 page, 91 Values
Which has 1 column, fixed unique, primary – key, no – nulls
Postal Code 91 Entries, 1 page, 87 Values
Which has 1 column, fixed
Company Name 91 Entries, 3 pages, 91 Values
Which has 1 column, fixed
City 91 Entries, 1 page, 69 Values
Which has 1 column, fixed
Table "Orders"
-End inputs to query-

01) Restrict rows of table Orders


using rushmore
for expression "Orders.OrderDate Between #1/1/98# And
#12/31/98#"
02) Outer Join result of "01)" to table "Customers"
using index "Customers!PrimaryKey"
join expression "Orders.CustomerID=Customers.CustomerID"
03) Sort Distinct result of "02)"

Możesz zauważyć sekcję tabeli podstawowej, z analizą indeksów i liczbą elementów, baz danych, indeksowanych stron
oraz przetwarzanych wartości. Zauważ również, że Rushmore może optymalizować tę kwerendę dzięki indeksowi w polu
Data Zmówienia tabeli Zamówienia. Plan rozpoznaje sprzężenie między tabelami Zamówienia i Klienci jako sprzężenie
zewnętrzne. Indeksy i technologia Rushmore sprawiają, że kwerenda ta jest bardzo dobrze zoptymalizowana. Jeśli nie
jesteś pewien, jak zoptymalizowana jest dana kwerenda, przejrzyj jej plan wykonywania. Funkcja SHOWPLAN jest
nieudokumentowana. W przypadku niektórych kwerend nie zwróci planu, niektóre z planów mogą być nieprawidłowe,
wciąż jednak możesz ją wykorzystać.

Wydruk 14.4 przedstawia słabo zoptymalizowaną kwerendę.

Wydruk 14.4. Plan słabo zoptymalizowanej kwerendy, która nie korzysta z zalet optymalizacji aparatu Jet
SELECT Customers.CustomerID, Customers.CompanyName
FROM Customers INNER JOIN Orders ON
Customers.CustomerID = Orders.CustomerID
WHERE ((Not (Orders.ShipCountry)="USA"));
..Customers with Shipping Adress Outside USA

-Inputs to Query-
Table "Orders"
Table "Customers"
Using index "Primary Key"
Having Indexes:
Primary Key 91 Entries, 1 page, 91 Values
Which has 1 column, fixed unique, primary – key, no – nulls
Postal Code 91 Entries, 1 page, 87 Values
Which has 1 column, fixed
Company Name 91 Entries, 3 pages, 91 Values
Which has 1 column, fixed
City 91 Entries, 1 page, 69 Values
Which has 1 column, fixed
-End inputs to query-
01) Restrict rows of table Orders
by scanning
testing expression "Not Orders.ShipCountry="USA"
02) Inner Join result of "01)" to table „Customers”
using index "Customers!PrimaryKey"
join expression "Orders.CustomerID=Customers.CustomerID"

Przyczyną słabości tej kwerendy jest sposób, w jaki obsługuje ograniczenie. Ponieważ ograniczenie to nie używa indeksu,
kwerenda musi przeszukać tabelę i testować każdy z rekordów, by sprawdzić, czy spełnia on założone kryterium. Skanowanie
tabel jest kosztowne. Wprowadzenie indeksu wpłynęłoby na znaczną poprawę wydajności tej kwerendy.

Zwiększenie szybkości kwerend


Optymalizacja kwerend w Jet jest dość rozbudowana, co nie oznacza, że nie możesz zrobić nic w tym kierunku samemu.
Oto kilka wskazówek, które pomogą Ci przyspieszyć pracę kwerend:
u Twórz indeksy dla wszystkich pól, których zamierzasz użyć w kryteriach.
Część IV ♦ Tajniki VBA 254

u Twórz indeksy po obu stronach sprzężeń w kwerendzie.


u Używaj kluczy podstawowych zamiast unikalnych indeksów. Ponieważ klucze podstawowe nie dopuszczają
wartości null, kwerendy będą mogły korzystać z większej ilości typów sprzężeń.
u Nie umieszczaj w zestawie wyników zbędnych kolumn. Przetworzenie i wyświetlenie każdej kolumny zabiera
dużo czasu.
u Unikaj używania złożonych wyrażeń w kwerendach.
u Unikaj używania funkcji IIF() (Immediate IF). IIF() przed podaniem wyniku, ponieważ musi sprawdzić
zarówno prawdziwe jak i fałszywe konsekwencje. Wykonywanie tej operacji dla każdego rekordu znacznie obniża
wydajność.
u Gdy używasz kwerend zagnieżdżonych, umieść obliczenia w ostatniej z nich.
u Używaj Count(*) zamiast Count([IDklienta]), poniważ Rushmore szybciej przetwarza Count(*) – nie
musi szukać wartości null przed zliczaniem.
u Jeśli to możliwe, zamiast operatorów Greater than (więcej niż) i Less than (mniej niż) używaj operatora
Between (między).
u Zazwyczaj (lecz nie zawsze) umieszczenie ograniczenia po stronie „jeden” relacji jest bardziej efektywne. Spróbuj
przesunąć ograniczenia na stronę „wielu” i sprawdzić, jaki to miało wpływ na wydajność. Pamiętaj, by po każdej
modyfikacji kryteriów sprawdzić zestaw wyników.
u Znormalizowane tabele mogą przechowywać dane na mniejszej ilości stron danych i stron indeksowanych. Traktuj
normalizację jako regułę i odstępuj od niej tylko w sytuacjach, gdy nie ma innej alternatywy.
u Gdy to możliwe, zamiast sprzężeń lub złożonych kryteriów OR spróbuj używać podkwerend. Optymalny wybór
zależy od wielu ukrytych czynników i tylko próba może pomóc Ci zdecydować, co wybrać.
u Sprzężeń zewnętrznych używaj tylko wtedy, gdy jest to konieczne, gdyż wymagają one automatycznie
skanowania tabeli nadrzędnej w sprzężeniu.
u Używaj zapisanych kwerend parametrycznych zamiast instrukcji SQL w kodzie. Jet już skompilował kwerendy
parametryczne i przygotował dla nich plan wykonywania (mimo iż nie pokazuje go funkcja SHOWPLAN.OUT).
Użycie skompilowanych i zapisanych kwerend pozwoli uniknąć koniecznej w przypadku ciągu SQL oceny i
optymalizacji silnika Jet. Access kompiluje ciągi SQL użyte jako źródło rekordów lub źródło wierszy w
formularzach, raportach i formantach, więc pozostają one niezmienione.
u Zawsze dostarczaj skompilowane kwerendy.
u Jeśli to tylko możliwe, do obróbki danych zamiast DAO używaj kwerend. Kwerendy (SQL) są w tych zadaniach
prawie zawsze szybsze niż DAO.
u Z uwagą wybieraj typ zestawu wyników. Dynaset będzie potrzebny, gdy będziesz chciał dodawać lub edytować
dane. Zdjęcie lub Zdjęcie do przekazywania będą odpowiednie, jeśli chcesz jedynie odczytywać dane. Zdjęcia
otwierają się dłużej, jednak szybciej się przewijają.
u Jeśli otwierasz zestaw rekordów po to, by tylko dodawać dane, otwórz go z opcją dbAppendOnly. To pozwoli Ci
zapobiec usuwaniu wierszy.
u Testuj kwerendy przekazujące, gdy używasz architektury klient-serwer. Przyjrzyj się również nowym opcjom tej
architektury w Accessie 2000. Kwerendy przekazujące nie zawsze są szybsze niż kwerendy wykonywane
bezpośrednio na tabelach znajdujących się na serwerze, lecz zazwyczaj obciążają sieć w mniejszym stopniu.
u Duże kwerendy mogą być wykonywane lepiej, jeśli ustawisz właściwość UseTransaction (Użyj transakcji) na
False (Nie). W przeciwnym wypadku, Access tworzy tabele tymczasowe. Czasami są one na tyle duże, że mają
negatywny wpływ na wydajność kwerendy.
u Gdy przeprowadzasz kwerendę na danych z serwera, do obsługi tych danych użyj metod CacheStart,
FillCache i EndCache.
u Gdy masz do czynienia z danymi z serwera, unikaj lokalnego przetwarzania. Przez przetwarzanie lokalne
rozumiemy na przykład: złożone polecenie Group by (Grupuj według), w którym użyto słowa kluczowego
Distinct, użycie operatora LIKE w polach tekstowych lub memo, wielokrotne funkcje podsumowujące w
kwerendzie krzyżowej lub kwerendy krzyżowe z warunkiem ORDER. Unikaj także użycia złożonych połączeń
zewnętrznych i wewnętrznych sprzężeń. Użycie takich konstrukcji spowoduje przesłanie dużych ilości danych z
serwera na lokalny komputer i w rezultacie znaczne obniżenie wydajności.
255 Rozdział 14. ♦ Optymalizacja aplikacji

u Kompaktuj bazę regularnie i sprawdzaj, czy statystyki używane przez aparat Jet do optymalizowania kwerend są
poprawne.
u Jeśli to możliwe, w celach testowych wypełniaj swoje aplikacje co najmniej taką ilością danych, jaką będą
wypełnione po zainstalowaniu na komputerach użytkowników. W ten sposób Jet zoptymalizuje kwerendy,
używając statystyk odzwierciedlających rzeczywiste warunki, w jakich kwerendy te będą uruchamiane.
u Indeksuj pola, które będą sortowane.
u Jeśli operujesz na statycznych danych, rozważ utworzenie tabeli na podstawie kwerendy, zamiast ciągle
uruchamiać kwerendę w bazie danych.
u Unikaj używania funkcji podsumowujących (Dlookup()) na tabelach, które nie należą do kwerendy.

Kwerendy są najbardziej skomplikowanymi obiektami Accessa. Na szczęście Jet czuwa nad tym, aby działały one jak
najlepiej. Dzięki informacjom zawartym w tym rozdziale będziesz mógł pomóc silnikowi Jet w przyspieszeniu pracy
kwerend. Do sprawdzenia, które rozwiązania zapewniają najlepszą wydajność, używaj funkcji SHOWPLAN oraz procedur
PrintStats i QueryTimer.

Przyspieszenie
funkcjonowania formularzy
Ponieważ większość swojego czasu pracy użytkownicy spędzą, pracując z formularzami, powinieneś dołożyć starań, by
wysiłek, jaki włożyłeś w optymalizację, nie został zniweczony przez wolne formularze. Przede wszystkim, formularze
powinny być proste i oszczędne.

Zacznijmy od początku
Pierwszą rzeczą, jaką widzą użytkownicy po uruchomieniu aplikacji, jest formularz startowy. Może to być tylko ekran
startowy z nazwą aplikacji oraz informacjami o niej lub panel przełączania, ułatwiający poruszanie się po aplikacji.
Niezależnie od tego, który to z nich, dobrze jest usunąć z niego kod. Umieść kod formularza startowego w standardowym
module i zostaw tylko te procedury, które są niezbędne do uruchomienia aplikacji. Ponieważ formularz będzie teraz ładował
się szybciej, zrobi lepsze wrażenie na użytkowniku. Niektóre z operacji mogą być przeprowadzone później. Po usunięciu
modułu z formularza zmień jego właściwość MaModuł na Nie. Dzięki temu uzyskasz prosty formularz, który powinien
działać lepiej. Jednakże zmieniając właściwość MaModuł na Nie, usuwasz cały kod formularza i jego formantów. Pamiętaj
o umieszczeniu tych funkcji i procedur w standardowym module, zanim zmienisz tę właściwość.

Formularz startowy nie powinien zawierać formantów ActiveX, gdyż ładują się one dużo dłużej niż inne formanty. Jeśli
jesteś zmuszony umieścić na formularzu formant ActiveX, ogranicz wówczas ilość pozostałych formantów.

Wybierz opcję otwierania formularza w menu Autostart zamiast używać samowykonujących się makr.

Szybsze pobieranie rysunków


Użycie rysunków w interfejsie aplikacji to wykorzystanie graficznych możliwości Accessa. Jednakże nie wystarczy po
prostu wstawić rysunki do aplikacji i oczekiwać, że będzie działać tak, jak ta część bazy Northwind, która zawiera zdjęcia
pracowników. W tej części zajmiemy się użyciem elementów graficznych w bazie danych.

Spróbuj używać formantu Obraz dla umieszczania rysunków. Jeśli chodzi o wyświetlanie grafiki, jest dużo bardziej
wydajny niż związane i niezwiązane ramki obiektów.

Podczas ładowania formularza Access musi zamalować lub wyrenderować każdy z umieszczonych na nim formantów. Nic
dziwnego więc, że więcej czasu zajmuje mu renderowanie formantów, które na siebie nachodzą. Aby upewnić się, że
prawidłowo rozmieściłeś formanty i nie nachodzą one na siebie, użyj poleceń Format, Odstępy w pionie i Odstępy w
poziomie.

Staraj się zachować jak najmniejsze nasycenie kolorów na formularzu (najlepsze rozwiązanie to czarno – białe). Im większe
nasycenie kolorów bitmapy, tym więcej pamięci czasu wymagane jest do jej namalowania.

Nie umieszczaj elementów graficznych oraz innych, dużych obiektów (np. pól memo i obiektów OLE) w podstawowych
formularzach, tabelach i kwerendach. Przywołuj je za pomocą osobnych formularzy lub kwerend tylko wtedy, gdy
Część IV ♦ Tajniki VBA 256

użytkownik tego zażąda. Dzięki temu będziesz mógł zapobiec stracie czasu i zasobów na przedstawianie jakiegoś dużego i
pamięciochłonnego obiektu, który w danym momencie może nie być potrzebny. Pamięć użyta do załadowania obiektów
OLE nie jest zwolniona do momentu zamknięcia formularza, więc pamiętaj o zamykaniu formularzy, które nie są Ci już
potrzebne.

Podstawowy, szybki formularz


Największy wpływ na szybkość pracy formularza ma ilość i typ umieszczonych na nim formantów. Każdy formant
pochłania pamięć i zasoby, lecz niektóre więcej niż inne. Dla porównania, związana ramka obiektu pochłania około 40 razy
więcej niż linia. Jeszcze gorzej może być w przypadku formantów ActiveX, w zależności od tego z czego się składają i
jakie jest ich zadanie.

Wybierając formanty do formularza, pamiętaj o informacjach z tabeli 14.3. Można przyjąć, że im większy zestaw funkcji daje
Ci formant, tym więcej zasobów pochłania. Tabela 14.3 zawiera wszystkie formanty znajdujące się na pasku narzędzi
projektu formularza. Policzyliśmy ilość właściwości każdego z nich i modyfikując tę liczbę o złożoność funkcji
wykonywanych przez formant otrzymaliśmy względną wagę. Jest to jednak tylko wskazówka. W rzeczywistości, użycie
zasobów przez formanty formularza określa sposób, w jaki je wykorzystujesz.

Tabela 14.3.
Względne wagi formantów formularza

Typ formantu Względna waga


Prostokąt 1
Linia 1
Podział strony 1
Formant karta (bez formantów) 4
Obraz (bez rysunku) 6
Formant karta 6
Podformularz (co najmniej) 6
Etykieta 8
Przycisk opcji 8
Przycisk polecenia 8
Pole wyboru 8

Tabela 14.3.
Względne wagi formantów formularza (ciąg dalszy)

Typ formantu Względna waga


Grupa opcji (bez formantów) 8
Przycisk przełącznika 9
Pole tekstowe 10
Pole listy (co najmniej) 10
Pole listy rozwijalnej (co najmniej) 10
Formanty ActiveX 20
Niezwiązana ramka obiektu (bez rysunku) >=20
Związana ramka obiektu 30

Niektóre z formantów są wielokrotnie bardziej zasobochłonne niż inne, więc substytucja może okazać się dobrą techniką
optymalizacyjną. Bardzo często zdarza się, że pole listy może zastąpić pole listy wyboru lub nawet podformularz. Rysunki
mogą często korzystać z formantu Image zamiast ramki obiektu, a formant karta pomoże podzielić formularz na szybciej
ładujące się części, renderując jedynie formanty na widocznej karcie. Jeśli użytkownicy mieli już do czynienia z hiperłączami
w Internecie, możesz spróbować zastąpić nimi przyciski poleceń. Jeśli masz możliwość użycia prostszego formularza bez
zmniejszania jego zestawu funkcji, zrób to.

Istnieje kilka innych technik, które poprawią wydajność formantów:


257 Rozdział 14. ♦ Optymalizacja aplikacji

u Ogranicz do minimum liczbę wyświetlanych pól w polach listy i polach listy rozwijalnej, a także indeksuj pola w
nich wyświetlane. W polach listy rozwijalnej wyłączaj opcję Autorozwijanie, ustawiając ją na Nie. Nakazywanie
Accessowi obserwacji i reagowania na każde naciśnięcie klawisza pogarsza wydajność. Używaj tej opcji tylko
wtedy, gdy nie da się tego uniknąć. Jeśli musisz użyć opcji Autorozwijanie, upewnij się, że kolumna, do której
użytkownik wprowadza dane, jest polem tekstowym. Access może użyć tej funkcji jedynie na tekście. Jeśli
wprowadzone dane nie są tekstem, Access będzie musiał je konwertować, co zabierze więcej czasu.
u Jeśli ukrywasz pole związane formantu lista rozwijana, unikaj używania w nim lub w wyświetlanych polach
wyrażeń. Pole listy rozwijalnej nie wyświetli wyników tak szybko, jakby to miało miejsce, gdyby były one
obliczone wcześniej i umieszczone w tabeli.
u Unikaj używania w listach i listach rozwijalnych kwerend z ograniczeniami. Próbuj opierać je na prostych
tabelach. Możesz poprawić wydajność, tworząc tabelę na podstawie kwerendy i aktualizując ją co jakiś czas.
u Podczas odświeżania formularzy lub wszystkich formantów zawierających dane, które mogły ulec zmianie,
używaj metody Requery, która jest dużo szybsza niż Akcja PonówKwerendę makra. Pamiętaj o użyciu tej metody
po każdej aktualizacji lub usuwaniu danych, szczególnie w aplikacjach, których używa wielu użytkowników.
u Zamiast tworzyć jedną, dużą listę rozwijalną, zastanów się, czy nie ma możliwości umieszczenia w formularzu kilku
pól, które będą ograniczały swoją zawartość. Przykładowo, jedna lista rozwijana mogłaby służyć do wyboru woje-
wództw. Wybór ten ograniczałby zawartość drugiej listy do miast na obszarze wybranego województwa. Byłoby to
szybsze i bardziej wydajne rozwiązanie niż jedna lista, zawierająca nazwy wszystkich województw i miast.
u Tak samo, jak musisz być oszczędny w wyborze ilości i typów formantów na formularzu, powinieneś również
przemyśleć ilość pól przedstawianych w podległym formularzowi zestawie rekordów. Mimo iż formularze zawsze
ładują dane z tabeli szybciej niż z kwerendy, istnieje jedno zastrzeżenie. Gdy otwierasz formularz oparty na tabeli,
wszystkie jej pola są ładowane, nawet, jeśli formularz ich nie wyświetla. Czasami lepiej jest oprzeć formularz na
kwerendzie, co pozwoli na usunięcie zbędnych pól z zestawu rekordów.
u Podległy formularzowi zestaw rekordów sortuje jedynie w ostateczności. Wymuszenie zmiany kolejności
rekordów w tym samy czasie, gdy formularz przygotowuje się do ich prezentacji, może zauważalnie wydłużyć
czas otwierania formularza.
u Kiedy piszesz kod formularza (CBF), używaj słowa kluczowego Me. Stała ta zawsze odnosi się do aktywnego
formularz, i działa szybciej niż inne odniesienia.
u W przypadku konstrukcji formularz główny – podformularz, indeksuj nadrzędne i Podrzędne pola łączące. To
znacznie poprawi szybkość odniesień, które te formularze wykonują bardzo często.
u Jeśli użytkownicy nie będą edytować rekordów podformularza, ustaw jego właściwości w odpowiedni sposób.
Edycja dozwolona, Dodawanie dozwolone i Usuwanie dozwolone mają wpływ na wydajność, gdyż zwiększają
zestaw funkcji formularza. Możesz przyspieszyć jego działanie, pozbywając się zbędnych funkcji. W ten sam
sposób możesz przyspieszyć działanie formularza, wybierając odpowiedni zestaw funkcji. Jeśli otwierasz
formularz w celu wprowadzania danych, ustaw właściwość Wprowadzanie danych na Tak, aby nie pobierał on
niepotrzebnie rekordów.
u Co się tyczy ustawiania właściwości formantów i formularza w trakcie jego działania umożliwiaj to jedynie
wtedy, gdy jest to niezbędne i nie powoduje zmniejszenia wydajności.
u Czy dynamiczny zestaw rekordów jest konieczny? Może wystarczyłoby zdjęcie?
u Gdy jest to tylko możliwe, ukrywaj formanty przy użyciu podziału strony i formantu karta. Możesz również
przyspieszyć działanie aplikacji, ukrywając formularze. Dobrze jest w miarę możliwości załadować kilka najczęściej
używanych formularzy tak, by były niewidoczne. Możesz to uczynić podczas uruchamiania aplikacji lub przy
ładowaniu pierwszego formularza. Aby załadować formularz tak, by był niewidoczny, otwórz go z argumentem
WindowMode ustawionym na Hidden:
DoCmd.OpenForm "NazwaFormularza" , , , , acHidden

u Gdy użytkownik będzie chciał wyświetlić formularz, możesz go wyświetlić przy użyciu następującego polecenia:
Forms("NazwaFormularza").setfocus

u Jeśli użytkownik będzie znów potrzebował tego formularza, ukryj go zamiast zamykać. Metoda Hide spowoduje
ukrycie go, lecz pozostanie on załadowany do pamięci.
Formobject.hide

u Możesz znacznie poprawić wydajność interfejsu, unikając ładowania kwerend i formularzy oraz renderowania
formantów. Ceną tego jest zajmowanie pamięci przez ukryte formularze, co może mieć wpływ na inne części
aplikacji. Mimo iż nie możesz użyć tej techniki dla wszystkich formularzy w aplikacji, powinieneś ją zastosować
w przypadku tych najczęściej używanych.
Część IV ♦ Tajniki VBA 258

Gdy masz do czynienia z dużymi zestawami rekordów, spróbuj nie przedstawiać ich użytkownikowi jednocześnie. I tak,
większość użytkowników nie wiedziałaby co zrobić z dziesiątkami tysięcy rekordów naraz. Jeśli jednak z aplikacji korzysta
wielu użytkowników, a formularz otwiera zestaw rekordów oparty na dużej tabeli lub kwerendzie, wydajność aplikacji
spadnie na skutek wąskich gardeł w sieci, ograniczeń bufora, blokowania rekordów i stron oraz przeładowania
użytkowników. Lepiej jest znaleźć sposób na podzielenie danych na logiczne podzestawy przy użyciu ograniczeń. Jeszcze
lepiej jest przedstawiać użytkownikowi rekordy pojedynczo, pobierając je na podstawie klucza podstawowego lub
indeksowanego pola. W przypadku mniejszych aplikacji, może to mieć negatywny wpływ na wydajność, jednakże w
przypadku systemów z wieloma użytkownikami, jest to jedyny sposób. Aby tego dokonać, zmień instrukcje SQL w kodzie,
programowo zmień właściwość Źródło rekordów i ponów kwerendę formularza.

Szybsze drukowanie raportów


Jaki jest pożytek z dobrej bazy danych, jeśli drukowanie raportu zajmuje cały dzień?

Największą, mającą wpływ na wydajność różnicą między formularzami i raportami różnicą jest sposób, w jaki zarządzają
swoimi sekcjami. W formularzu istnieje nagłówek formularza, sekcja szczegółowa i stopka formularza. W raporcie istnieje
nagłówek i stopka raportu, nagłówek i stopka strony, nagłówki i stopki sekcji oraz sekcja szczegółowa. Gdy otwierasz
formularz, kwerenda, na której jest oparty, przeprowadzana jest tylko raz. Gdy otwierasz raport, musi on utworzyć
kwerendę (opartą na tej ze źródła danych) dla każdej sekcji raportu. W przypadku złożonej kwerendy raport musi ją lub jej
części uruchamiać kilkakrotnie.

Oto kilka wskazówek, które mogą wpłynąć na przyspieszenie tworzenia raportów:


u Staraj się, by kwerenda, na której oparty jest formularz, była tak prosta jak tylko to możliwe.
u Obliczenia umieszczaj w raporcie. Gdy obliczenia umieszczone są w kwerendzie, muszą być wykonywane dla
każdego wiersza. Jeśli jednak umieścisz je w raporcie, użytkownik zobaczy wyniki w momencie, gdy Access
wykona obliczenia dla jednej strony raportu.
u Spróbuj oprzeć kwerendę na jak najmniejszej ilości tabel. Ponieważ raport będzie uruchamiał kwerendę więcej niż
raz, możesz utworzyć tabelę z zestawem rezultatów. Raport będzie szybciej przeszukiwał tabelę niż ponownie wy-
konywał kwerendę. Rozwiązanie to może być szczególnie efektywne, gdy masz do czynienia z kwerendą
zawierającą podkwerendę.
u Unikaj podkwerend w źródle raportu. Raport potrzebuje dużo pamięci, a kwerenda z podkwerendą może
pochłaniać więcej pamięci niż to konieczne.
u Czy naprawdę potrzebujesz podraportów? Podraporty nie tylko utrudniają formatowanie danych w taki sposób,
w jaki byś sobie tego życzył, ale również pochłaniają pamięć i pogarszają wydajność raportu. Zdarzają się
jednak sytuacje, w których warto skorzystać z podraportów. Gdy używasz wielu funkcji, użycie podraportu
może okazać się szybszym rozwiązaniem niż kilka odwołań do tych funkcji.
u Unikaj wyrażeń sortujących i grupujących. Aby prawidłowo wyświetlić sortowanie i grupowanie, raport
będzie musiał przeliczyć każde wyrażenie kilkakrotnie. Wykonaj obliczenia tych wartości przed
przekazaniem ich do raportu.
u Indeksuj wszystkie pola używane do sortowania i grupowania. Ponieważ indeksy same sortują rekordy, łatwiej
jest raportowi porządkować i grupować dane wprost z indeksowanych pól.
u Źródło rekordów nie powinno zawierać funkcji podsumowujących (DLookup). Takie rozwiązanie również
wymusi na raporcie wielokrotne przeglądanie danych, co spowolni wyświetlanie raportu.
u Nie ma sensu wyświetlanie raportu wypełnionego komunikatami #Error#. Jeśli raport nie zawiera danych,
poinformuj o tym użytkownika za pomocą komunikatu i zamknij raport. Możesz określić, czy raport zawiera dane
za pomocą właściwości Brak danych i Ma dane.

Wiele z technik umożliwiających poprawę wydajności formularzy ma również zastosowanie do raportów. Ta sekcja była
omówieniem technik charakterystycznych jedynie dla tych drugich.

Pisanie szybkiego kodu


Co się tyczy kodu, istnieje kilka rzeczy, które mogą poprawić szybkość wykonywanych funkcji i procedur. Mimo iż
różnice między jedną techniką a drugą mogą być mierzone w znaczących ułamkach sekundy, wybór najszybszej opcji
może ograniczyć przyszłą rozbudowę aplikacji. Należy być przygotowanym na to, że po pewnym czasie użytkownicy
259 Rozdział 14. ♦ Optymalizacja aplikacji

poproszą o modyfikacje i lepiej jest wówczas mieć możliwość umieszczenia w niej dodatkowych elementów (np.
złożonych procedur sprawdzania poprawności) bez pogorszenia wydajności aplikacji.

Jeśli poświęciłeś trochę czasu na przejrzenie i wdrożenie niektórych z dotychczas omówionych technik, pisany przez
Ciebie kod będzie łatwiejszy do zoptymalizowania. Największą przeszkodą w tym przypadku będzie słaby projekt bazy
danych. Jeśli baza jest źle zaprojektowana, każda funkcja i procedura będzie wykonywana dłużej niż powinna.

Istnieje kilka prostych zasad oraz kilka alternatywnych technik, które sprawią, że funkcje i procedury Twojej aplikacji będą
wykonywane tak szybko jak to tylko możliwe. Część z nich, o ile nie wszystkie, ma raczej nieznaczny wpływ, gdy
występują osobno, jednakże gdy są wykorzystane razem i powtarzane, efekt będzie zauważalny.

Użycie pamięci przez kod


Access używając metody „call-tree loading” przenosi do pamięci wszystkie moduły oraz wszystkie zawarte w nich procedury i
funkcje. Oznacza to, że jeśli funkcja A pierwszego modułu odwołuje się do funkcji B tego samego modułu, która z kolei odwołu-
je się do funkcji C drugiego modułu, to Access załaduje do pamięci całą zawartość obu modułów.

Stąd też dobrze jest łączyć moduły w grupy w przemyślany sposób. Jeśli funkcje i moduły często się do siebie odwołują,
umieść je w tym samym module w celu zmniejszenia ilości załadowań modułu. Usuń również wszystkie zbędne funkcje i
procedury.

VBA ładuje moduł do pamięci również w sytuacji, w której odnosisz się do zmiennych publicznych tego modułu. Zadbaj o
to, by zmienne publiczne również były pogrupowane w modułach w przemyślany sposób.

Praca z modułami
Przed uruchomieniem modułów VBA musi je skompilować. Oznacza to, że VBA będzie kompilować moduł za każdym
razem, gdy będziesz chciał go uruchomić. Może mieć to znaczący wpływ na wydajność aplikacji.

Podczas kompilowania modułu VBA nadaje mu znacznie mniejszą, łatwiej wykonywalną formę. Mimo iż początkowy kod
jest zawsze przechowywany w pliku MDB, Access ładuje i uruchamia skompilowany kod VBA. Ponadto kod VBA nie
zawiera pustych miejsc, komentarzy, nagłówków i zajmuje dużo mniej miejsca niż napisany przez Ciebie kod źródłowy. Jeśli
chcesz uruchomić nieskompilowaną procedurę, VBA musi załadować do pamięci cały kod źródłowy (łącznie z pustymi
miejscami, komentarzem i nieużywanym kodem) i skompilować go przed wykonaniem. Dotyczy to również zawierających
kod formularzy i raportów.

Kompilowanie kodu
Aby skompilować kod, z menu Debug wybierz polecenie Compile nazwaprojektu. Pamiętaj o skompilowaniu aplikacji
przed dostarczeniem jej do klientów.

Dekompilacja
Moduł jest dekompilowany podczas edytowania go. Raport czy formularz dekompilowany jest w momencie
dokonywania w nim jakichkolwiek zmian, nawet bez ingerowania w kod. Tworzenie nowego formularza lub raportu
również pociąga za sobą dekompilację kodu. Podczas tworzenia aplikacji możesz używać opcji Compile on Demand
(aby ją włączyć, z menu Tools wybierz Options. Opcja Compile on Demand znajduje się na zakładce General). Dzięki
temu VBA będzie kompilować moduły aplikacji podczas pracy.

Nową opcją w Accessie 2000 jest Background Compile. Kompilując aplikację w tle, VBA pozwala Ci zaoszczędzić trochę
czasu. Jeśli kiedyś zdarzy Ci się to sprawdzić, skompilowana aplikacja zajmuje więcej miejsca na dysku niż jej
zdekompilowana wersja. Dzieje się tak, gdyż w skompilowanej aplikacji przechowywany jest zarówno źródłowy jak i
skompilowany kod. Nie wpływa to jednak na obniżenie wydajności. Jako, że do pamięci ładowany jest tylko
skompilowany kod, który działa szybciej niż źródłowy, w rzeczywistości następuje znaczna poprawa wydajności.

Ponieważ Access przez cały czas ładuje moduły do pamięci, powinieneś sprawdzić, czy nie zawierają one żadnych zbędnych
elementów (np. nie używanych funkcji czy procedur). Usuń z aplikacji kod, z którego zrezygnowałeś w trakcie procesu
tworzenia. Kompilator musi zajmować się również tym kodem, co spowalnia cały proces. Czasami podczas pisania
aplikacji powinieneś zamknąć projekt, co spowoduje wyczyszczenie pamięci. Nawet po skompilowaniu aplikacji wciąż
będziesz jednak chciał, by jak najmniejsza część kodu ładowana była do pamięci.
Część IV ♦ Tajniki VBA 260

Tworzenie pliku MDE


Najpewniejszym sposobem na to, by aplikacja była stale skompilowana, jest przekazanie jej użytkownikom w postaci pliku
MDE. Plik taki nie zawiera kodu źródłowego i nigdy nie jest kompilowany.

Oprócz kwestii związanych z grupowaniem modułów, zarządzaniem pamięcią i kompilacją, istnieje kilka wskazówek,
których wykorzystanie przy pisaniu kodu pomoże Ci tworzyć szybsze aplikacje.

Użycie Option Explicit


Zawsze używaj Option Explicit, gdyż zmusi cię to do określania typów danych. Jeśli nie określisz typu danych zmiennej,
VBA użyje największego i najbardziej obszernego typu danych. Jak zwykle, największy i najbardziej obszerny oznacza
jednocześnie najwolniejszy. Określanie typu danych zmiennej jest również przydatne ze względu na przejrzystość i
integralność danych.

Precyzyjne wybieranie rozmiaru zmiennych


Podczas określania zmiennej wybieraj zawsze możliwie jak najmniejszy rozmiar. Nie używaj double tam, gdzie
wystarczy integer. Gdy tylko jest to możliwe, używaj ciągów o stałej zamiast o zmiennej długości.

Oszczędzanie przestrzeni stosu


przy użyciu zmiennych typu string
Zmienne typu string należą do najczęściej używanych. Można je podzielić na trzy podtypy:
u Lokalne o stałej długości (nie więcej niż 64 znaki) – zmienne te używają dwóch bajtów na znak i nie korzystają z
obszaru dynamicznego pamięci.
u Lokalne o stałej długości (więcej niż 65 znaków) – zmienne te również używają dwóch bajtów na znak, lecz w
obszarze dynamicznym pamięci. Wymagają również czterech bajtów w stosie, aby wskazywać zmienną w
obszarze dynamicznym pamięci.
u Długość zmienna (długość nie ma znaczenia) – wielkość użytej pamięci dynamicznej zależy od długości zmiennej.
Cztery bajty pamięci stosu użyte są w celu wskazania zmiennej w obszarze dynamicznym.

W przypadku ciągów znaków celem powinno być zmniejszenie ilości wykorzystywanej przez nie pamięci stosu. Spróbuj
zmienić ciągi o zmiennej długości na ciągi o stałej długości. Poniższy przykład przedstawia ciąg o zmiennej długości,
zadeklarowany jako ciąg o stałej długości w celu zmniejszenia używanej pamięci stosu.
Dim strString as string
Static strString as string * 30

Do określenia rozmiaru pól tekstowych o stałym rozmiarze używaj rozmia-


ru pola w tabeli.

Dokładne określanie typu obiektów


Gdy deklarujesz typ obiektu, bądź dokładny. Jeśli kod ma przechodzić przez pola tekstowe formularza, zadeklaruj zmienną
obiektu jako pole tekstowe, nie tylko jako formant. W ten sposób nie wystąpi konieczność używania VBA do sprawdzenia, o
jaki rodzaj formantu chodzi.

Aby zaoszczędzić czas, zamiast


Sub CycleControls(cntl as control)

użyj
Sub CycleControls(cntl as TextBox)
261 Rozdział 14. ♦ Optymalizacja aplikacji

Umieszczenie kodu we wnętrzu procedury


zamiast odwoływania się do innych funkcji
W momencie gdy funkcja lub procedura odwołuje się do innej funkcji lub procedury, występuje klasyczny konflikt między
łatwością w obsłudze a szybkością. Technika ta bardzo ułatwia obsługę, lecz jest mniej wydajna niż umieszczenie kodu w
jednej procedurze. Mogą zdarzyć się sytuacje, w których będziesz zmuszony wybierać między szybkością a łatwością
obsługi, lecz nie rób tego tylko dla zyskania kilku milisekund.

Zmiana True i False


Podczas zmiany znacznika z True na False, nie zachodzi konieczność sprawdzania znacznika wartości w konstrukcji
If...Then...Else. Możesz zaoszczędzić czas i linie kodu, odwracając tę wartość przy użyciu operatora NOT. Ustawiając
zmienną logiczną na to, czym ona nie jest, odwracasz ja.

Zamiast
If bFlag = False then
bFlag=True
Else
bFlag=False
EndIf

użyj
bFlag=Not bFlag

Wykonanie jednej linii kodu zajmuje dużo mniej czasu niż kilku, zawierających dodatkowo ocenę.

Użycie Len() zamiast pustego ciągu


Aby przetestować zmienną typu string w celu sprawdzenia, czy zawiera jakiekolwiek znaki, zamiast porównywania jej
do pustego ciągu (""), użyj funkcji Len(). Funkcja ta dokona oceny szybciej niż porównanie z ciągiem o zerowej długości.
Sub CheckString(strString as string)
If Len(strString) then
MsgBox „Oto ciąg: ” & strString
End If
End Sub

Użycie True i False zamiast zera


Ponieważ True i False są binarne, łatwiejsze jest ich wyliczanie niż liczby zero. Użyj True i False w następujący
sposób:
Function ShowNumber(dblNumber as Double) as string
If dblNumber then
ShowNumber = "Numer to " & dblNumber
EndIf
End Function

Szybkie odwołania do obiektów


W przypadku powtarzających się odwołań do rekordów używaj zmiennych. Dużo szybciej jest odwoływać się do
istniejącej zmiennej formularza, formantu, raportu czy kwerendy niż ponownie odwoływać się do obiektów.

Zamiast ponownie odwoływać się do formularza


Forms![frmMyForm].Height=500
Forms![frmMyForm].Width=500

spróbuj zadeklarować zmienną i odwołać się do niej w ten sposób:


Dim frm as Form
Set frm=Forms![frmMyForm]
frm.Height=500
frm.Width=500

W przypadku większej ilości właściwości obiektu, możesz zmniejszyć ilość odwołań przy użyciu konstrukcji With...End
With. Przydaje się to szczególnie wtedy, gdy ścieżka odwołania jest długa.
Część IV ♦ Tajniki VBA 262

With Forms![frmMainForm]![txtCustomerName]
.left=200
.top=300
.height=200
.width=100
End With

Słowo kluczowe ME oznacza aktywny formularz, więc nie musisz deklarować zmiennej ani odnosić się do obiektu, by go
użyć. Ponieważ jest to możliwe tylko w CBF, nie będziesz mógł umieszczać go w standardowych modułach ogólnych.
With ME
.Height=500
.Width=500
End With

Użycie szybkich tablic


Używaj tablic. Są one przechowywane w pamięci i ładowane są bardzo szybko. Ich powiększenie zajmuje bardzo mało
czasu. Tablice zajmują tyle miejsca, ile w danym momencie potrzebują. Jeśli nie wiesz, ile elementów będziesz musiał
umieścić w tablicy, zamiast tworzyć dużą tablicę z pustymi miejscami, utwórz tablicę dynamiczną.

Jeśli chcesz opróżnić tablicę nie niszcząc jej struktury, możesz użyć słowa kluczowego Erase. Dzięki temu będziesz mógł
wyczyścić tablicę określonego rozmiaru, bez konieczności ponownego jej budowania.
Erase myArray

Jeśli chcesz powiększyć tablicę bez niszczenia danych w niej zawartych, użyj funkcji ReDim z parametrem Preserve.
ReDim Preserve myArray(Ubound(myArray+1))

Tablice często mogą zarządzać danymi z zestawu rekordów. Zamiast otwierać zestaw rekordów z całą jego zawartością,
użyj metody GetRows() i zamknij zestaw rekordów. Dzięki temu pamięć zostanie zwolniona i nie będzie problemów
związanych z obsługą wielu użytkowników. GetRows() posiada jeden argument: liczbę wierszy ładowanych do tablicy.
Dim db as Database
Dim rowArray as Variant
Dim rs as Recordset
Set db=CurrentDB()
Set rs=db.openrecordset("Zamówienia kwartalne")
RowArray=rs.GetRows(rs.RecordCount)
rs.close
...

Po załadowaniu danych do tablicy możesz obrabiać je w dowolny sposób lub umieścić je w niezwiązanym formularzu.

Używaj stałych, gdy jest to tylko możliwe


Za każdym razem, gdy VBA ma pobrać bieżącą wartość zmiennej, musi się do niej odwoływać. Inaczej jest w przypadku
stałych. Stałe poprawiają również czytelność kodu. Zamiast wpisywać wszędzie 12 jako 12 miesięcy, utwórz stałą (na
przykład o nazwie WszystkieMiesiące) i ustaw ją na 12. VBA będzie odczytywać stałą dużo szybciej, a inni programiści będą
wiedzieli, co miałeś na myśli ustawiając stałą. Wadą takiego rozwiązania jest to, że stałe mogą być ustawiane tylko raz i
nie mogą być później zmieniane. Można ich używać do przedstawiania wartości wewnętrznych aplikacji lub wartości zew-
nętrznych, które nigdy nie ulegają zmianie.

Właściwe użycie zakładek (Bookmarks)


Zakładki są bardzo szybkim sposobem poruszania się po rekordach w interfejsie. Pamiętaj, że istnieją dwa rodzaje zakładek:
zakładki dla formularzy i zakładki dla zestawów rekordów. Zakładka formularza jest to tablica zmiennych wariantowych,
dynamicznie przyznawanych do każdego rekordu w podległym zestawie. Zakładka DAO jest to bajtowa tablica, która
definiuje każdy z rekordów w zestawie. Ułatwiające poruszanie się po rekordach zakładki są niszczone i tworzone
ponownie wraz z zestawami rekordów. Nie polegaj na nich, chyba że możesz je kontrolować lub gdy nie będzie to miało nega-
tywnych konsekwencji. Nie przedstawiają one rekordów i nie mają nic wspólnego z kluczem podstawowym. Reprezentują one
jedynie tymczasową pozycję rekordu w serii wierszy. Jakakolwiek obróbka danych powinna być dokonywana w oparciu o
techniki odnoszące się do projektu bazy danych, a nie jedynie pozycji w zestawie rekordów. Używając kwerendy po każdej
operacji aktualizacji i usuwania danych, będziesz każdorazowo niszczył zakładki i tworzył je na nowo. Jeśli Twój interfejs
używa w takich sytuacjach zakładek, będziesz musiał dokładnie kontrolować aktualizację i usuwanie rekordów.

Poniższy kod ilustruje użycie zakładki w formularzu w celu przejścia do poprzedniego rekordu po dokonaniu aktualizacji.
263 Rozdział 14. ♦ Optymalizacja aplikacji

Private Sub Findit_AfterUpdate()


Dim rsclone As Recordset
Dim recordID As Variant
Dim IDValue As Long

Set rsclone = Me.RecordsetClone


IDValue = Me![Findit]
recordID = "ID = " & Value
rsclone.FindFirst recordID
bm = rsclone.Bookmark
Me.Bookmark = bm
End Sub

Użycie zakładki w celu przejścia do poprzedniego rekordu jest o 1300% szybsze niż wykonanie instrukcji FindFirst w
tej samej sytuacji.

Zamykaj i niszcz
Szybki kod to czysty kod. Pamiętaj o zamykaniu zestawów rekordów po zakończeniu pracy z nimi i o ustawianiu obiektów
na Nothing, gdy nie są Ci już więcej potrzebne. Pozostawienie ich ogranicza ilość pamięci dla innych części aplikacji.
rs.Close
Set db=Nothing

Używaj SQL zamiast DAO


Przechodź przez zestawy rekordów tylko wtedy, gdy nie ma innego rozwiązania. Bazy danych Jet są optymalizowane pod
kątem wykorzystania SQL do obróbki danych i ich struktury. Używaj kwerend zamiast DAO w każdej możliwej sytuacji.
Niewiele jest sytuacji, w których obiekty DAO są szybsze niż dobrze zaprojektowana kwerenda. W przeciwieństwie do
obiektów DAO kwerendy posiadają plany wykonywania i mogą korzystać z indeksów.

Jeśli musisz odwoływać się do danych za pomocą modelu obiektowego, zamiast DAO użyj ADO. Obiekty ADO to nowy
standard obróbki i definicji danych poprzez model obiektowy. Technologię DAO można uznać za schyłkową i nie są do
niej wydawane żadne rozszerzenia i poprawki. W książce tej omówiliśmy funkcjonowanie obiektów ADO w kilku
miejscach, zwłaszcza w rozdziale 6. „Wprowadzenie do obiektów danych ActiveX” i 7., „Zaawansowane ADO”.

Użycie indeksowania kolekcji


Gdy masz do czynienia z kolekcjami, jeśli to tylko możliwe używaj ich numerów indeksów. Numery te są wewnętrznymi
identyfikatorami kolekcji. Ich użycie jest dużo szybsze niż innych właściwości (np. nazw). Poniższy przykład ilustruje dwa
sposoby tworzenia

odniesień do aktualnej bazy danych. Użycie Currentdb() powoduje automatyczne odświeżenie kolekcji bazy, co zabiera
trochę czasu. Pierwszy sposób (dbEngine(0)(0)) nie odświeża zbioru.
Set db=DBEngine(0)(0)

jest szybszym rozwiązaniem niż


Set db=Currentdb()
Set cntl=Forms!frmMyForm(0)

i szybszym niż
Set cntl =Forms![frmMyForm]![myControl]

Użycie numeru indeksu elementu zbioru przydaje się w szczególności w przypadku pętli.

Tworzenie szybszych pętli


Tworząc pętlę w kolekcji, zamiast For...Next używaj For...Each. Podczas tworzenia pętli w formantach formularza
For Each cntl on frm
...
Next

będzie działać szybciej niż zwykła pętla For...Next.


Część IV ♦ Tajniki VBA 264

Podczas tworzenia pętli w obiektach Collection będziesz chciał uniknąć zbędnego odświeżania kolekcji. Nawet w
przypadku małych baz danych odświeżanie kolekcji może spowodować znaczny spadek wydajności.

W przypadku użycia pętli For...Next możesz zaoszczędzić czas, nie umieszczając zmiennej w linii Next.
For i = 1 to 100
' zrób co chcesz
Next

Płynące z takiego rozwiązania korzyści są szczególnie widoczne w przypadku pętli zagnieżdżonych. Staraj się również
nie obliczać granicy w linii For. Górna granica powinna być już znana przed rozpoczęciem pętli.
Reccount=rs.recordcount/2
For i=1 to reccount
...
Next

Jeśli nie określisz wartości górnej granicy wcześniej, pętla będzie ją obliczać za każdym przejściem. Jest to strata czasu.

Usuń z kodu IIF()


Nie używaj w kodzie funkcji IIF(). Zanim poda ona swoje wyniki, musi dokonać oceny wszystkich wyrażeń w niej
zawartych. Szybszym rozwiązaniem jest standardowa struktura If...Then...Else.

Porządkowanie Select Case


Używając konstrukcji Select Case, pamiętaj o uporządkowaniu jej w taki sposób, by najczęściej występujące przypadki
znajdowały się u góry. Ponieważ przejście przez Selections związane jest z testowaniem przypadków w kolejności ich
ułożenia, umieszczenie najczęściej występujących u góry umożliwi jak najszybsze opuszczenie struktury.

Używaj Execute zamiast RunSQL


Unikaj pisania kodu w oparciu o polecenie DoCmd. DoCmd znajduje się na najwyższym poziomie kodu VBA. Gdy tylko
istnieje inne rozwiązanie – wybierz je.
DoCmd RunSQL „...”

będzie wolniejszym rozwiązaniem od


Querydef.Execute

Używaj A2KU_Timer
Podczas mierzenia czasu wykonywania operacji w aplikacji używaj znajdującego się na płycie CD zegara A2KU_Timer.
Jest prawie 1000% szybszy niż wszystkie inne.

Testuj wydajność transakcji


Transakcje nie zawsze umożliwiają zaoszczędzenie czasu. Kiedyś mogłeś być pewien, że użycie transakcji spowoduje
przyspieszenie pracy kwerend. Teraz już tak nie jest. Mimo iż transakcje mogą użyć swoich zdolności buforowania, w celu
poprawy wydajności kwerend, mogą jednocześnie spowolnić ich pracę, ze względu na konieczność tworzenia na dysku
tymczasowych plików, w oczekiwaniu na ponowny przebieg.

Kontroluj odświeżanie
Wyłącz Application.Echo lub kontroluj zawartość ekranu. Odświeżanie ekranu zabiera dużo czasu i może spowolnić
pracę aplikacji.
265 Rozdział 14. ♦ Optymalizacja aplikacji

Używaj wczesnego wiązania


i zwracaj uwagę na odniesienia ActiveX
Korzystaj z wczesnego wiązania. Używając formantów ActiveX, upewnij się, że istnieje odniesienie do odpowiedniego
pliku OCX dla tego formantu. Możesz to sprawdzić, wybierając z menu Tools pozycję References. Wczesne wiązanie
może znacznie poprawić wydajność aplikacji.

Przejście do architektury klient-serwer


Staraj się, by projekt aplikacji uwzględniał możliwość przejścia do SQL Server lub Oracle. Jeśli tak się stanie, będziesz mógł
skorzystać z kwerend przekazujących i procedur przechowywanych na serwerze. Może to mieć duży wpływ na wydajność
aplikacji.

Chleba i igrzysk
Jeśli nie jesteś w stanie sprawić, by dana operacja była wykonywana szybko, spraw, by przynajmniej na taką wyglądała.
Jeśli jakiś proces trwa na tyle długo, by wywołać znudzenie użytkownika, wyświetl ekran informujący go o tym, że coś się
dzieje. Użytkownicy często myślą, że aplikacja działa szybko, ponieważ otrzymują o tym informacje.
Część V
Access
i architektura klient-serwer
W tej części:
u Wprowadzenie do projektów programu Microsoft Access oraz narzędzi wizualnych.
u Tworzenie interfejsu użytkownika dla Microsoft SQL Server.
u Interfejs Accessa 2000 do Oracle.
Rozdział 15.
Wprowadzenie do projektów programu
Microsoft Access oraz narzędzi
wizualnych
W tym rozdziale:
u Wprowadzenie do Projektów programu Microsoft Access (ADP).
u Użycie ADP.
u Praca z ADP i istniejącymi bazami danych serwera SQL.
u Tworzenie projektów opartych o nową bazę danych.

Microsoft zintegrował Access 2000 z serwerem SQL, używając jako spoiwa OLE DB. Aby skorzystać z zalet tej integracji,
użyj ADP, nowego typu aplikacji w Accessie. Autorzy zalecają używanie ADP do współpracy z SQL Server 7.0. Jeżeli
chcesz użyć innego serwera niż SQL Server 7.0, zajrzyj do rozdziału 16., „Tworzenie interfejsu użytkownika dla Microsoft
SQL Server” i rozdziału 17. „Access jako interfejs użytkownika dla Oracle”. W tym rozdziale przedstawiony jest sposób
użycia ADP we współpracy z SQL Server 7.0.

Wprowadzenie do projektów programu Microsoft Access


Jako użytkownik Accessa wiesz, że używa on silnika bazy danych Microsoft Jet do zapisywania danych oraz wykonywania
zapytań. Wiele aplikacji Accessa używa serwera bazy danych i połączenia ODBC do zapisywania danych. Aplikacje takie
mogą korzystać z tabel połączonych, zapytań SQL i ODBCDirect. W takich aplikacjach używasz silnika Jet i ODBC, aby
komunikować się z połączonymi tabelami, a aplikacja jest zwykłym plikiem MDB.

Przedstawiciele Microsoftu zrozumieli, że potrzebujesz lepszej integracji z serwerami baz danych. W Accessie 2000 jest
dostępny nowy typ projektu bazy danych nazwany Projektem programu Microsoft Access (ADP), używany do integracji z
SQL Server 7.0. Ponieważ ADP jest silnie związane z OLE DB dla SQL Servera, możesz go użyć tylko z SQL Server 7.0
lub SQL Server 6.5 z zainstalowanym Service Pack 5.

Jeżeli chcesz użyć ADP razem z SQL Server 6.5, SP 5, powinieneś prze-
czytać uwagi do programu Office 2000 i wykonać plik poleceń SQL na
serwerze przed rozpoczęciem pracy z ADP i SQL Serverem 6.5.

Wady i zalety ADP


Gdy rozpatrujesz korzyści płynące z użycia ADP zamiast plików MDB, spójrz na plusy i minusy. Korzyści używania ADP
są następujące:
u Używając ADP, możesz zmieniać strukturę tabel w Accessie, nie możesz tego robić, używając tabel z serwera
jako tabel połączonych.
Część V ♦ Access i architektura klient-serwer 268

u Z ADP masz tylko jedno połączenie do bazy dla wszystkich Twoich obiektów. Używając plików MDB, masz
wiele połączeń. Przykładowo, używając tabeli połączonej, formatka z 10 formantami posiada 10 połączeń do bazy
danych. Używając ADP, jest tylko jedno połączenie.
u ADP jest łatwe w użyciu.
u ADP umożliwiają użycie Accessa jako narzędzia do projektowania aplikacji.

Wadami ADP są:


u ADP ogranicza Cię do używania tylko MS SQL Servera, nie możesz użyć tego typu projektu z bazami Oracle lub
Sybase.
u ADP jest nową technologią, a każda nowa technologia może jeszcze nie być dopracowana.
u Nie możesz tworzyć żadnych lokalnych tabel ani zapytań.

Po przeanalizowaniu plusów i minusów i przeczytaniu tego rozdziału powinieneś wiedzieć wszystko, co jest Ci potrzebne, aby
stwierdzić, czy chcesz użyć ADP w Twoich aplikacjach.

Użycie ADP
Aplikacja ADP jest aplikacją Accessa 2000 z rozszerzeniem ADP. Używa ona serwera SQL jako silnika bazy danych.
Aby móc użyć ADP, musisz zainstalować serwer SQL na Twoim kompu-
terze lub mieć dostęp poprzez sieć do innego serwera SQL. Aby za-
instalować lokalną wersję serwera SQL dla Windows 95/98, postępuj
według wskazówek w instrukcji instalacji SQL Server 7.0. Jeżeli nie
posiadasz SQL Server 7.0, zainstaluj program Microsoft Data Engine
(MSDE), który jest lokalną wersją serwera SQL pozbawioną interfejsu
użytkownika. Znajduje się on na dysku instalacyjnym Office 2000 w ka-
talogu /SQL.

Tworzenie ADP
Aby utworzyć ADP, uruchom Access i wybierz Plik|Nowy z głównego menu. Na ekranie pojawi się okno dialogowe, jak na
rysunku 15.1, w którym wybieramy typ tworzonej aplikacji. Do wyboru masz: Baza danych|Projekt (istniejąca baza
danych) i Projekt (nowa baza danych).

Rysunek 15.1.
Okno dialogowe
Nowy

Gdy wybierzesz Baza danych, utworzysz zwykły plik MDB, który używa silnika bazy danych Jet. Wybranie Projekt
(istniejąca baza danych), spowoduje utworzenie ADP komunikującego się z istniejącą bazą danych na serwerze SQL. Gdy
wybierzesz Projekt (nowa baza danych), rozpoczniesz tworzenie ADP i nowej bazy danych na serwerze.

Utwórz przykładowy projekt oparty o istniejącą bazę danych. Podwójne kliknięcie ikony spowoduje wyświetlenie okna
dialogowego, w którym określa się położenie pliku ADP. Wygląd tego okna pokazany jest na rysunku 15.2.

Po utworzeniu pliku ADP, zostaniesz zapytany o informacje dotyczące bazy danych i serwera SQL, tak jak pokazane jest to
na rysunku 15.3.Pamiętasz, że gdy używałeś Data Links (w rozdziale 7., „Zaawansowane ADO”), musiałeś podać nazwę
serwera, nazwę użytkownika, hasło oraz nazwę bazy danych, której chciałeś użyć. Do naszego przykładu użyjesz bazy
danych „Northwind” w wersji na serwer SQL, która jest dostarczana razem z SQL Server 7.0. Po podłączeniu do bazy
269 Rozdział 15. ♦ Wprowadzenie do projektów programu Microsoft Access

danych pojawi się okno projektu z kilkoma nowymi elementami w oknie bazy danych. Okno to jest pokazane na rysunku
15.4.
Rysunek 15.2.
Określanie
położenia pliku

Rysunek 15.3.
Tworzenie
połączenia
do bazy danych

Rysunek 15.4.
Nowe okno bazy
danych dla ADP

Jeżeli chcesz analizować ten przykład na swoim komputerze, upewnij się,


że masz zainstalowany SQL Server 7.0. Możesz zainstalować lokalną
wersję serwera SQL wraz z bazą Northwind z dysku instalacyjnego Office
2000.

Nowe okno bazy danych


Okno bazy danych dla plików ADP jest inne od tego dla plików MDB (porównaj z rysunkiem 15.4). Nowe okno wyświetla
następujące elementy: tabele, widoki, procedury przechowywane, diagramy baz danych, formularze, raporty, strony,
makra i moduły. W tabela 15.1 został opisany każdy element okna bazy danych.

Tabela 15.1.
Okno obiektów bazy danych dla ADP

Element Opis
Tabele Lista wszystkich tabel w bazie danych serwera SQL. W przeciwieństwie do tabel
połączonych, możesz dodawać, zmieniać i usuwać tabele bezpośrednio na serwerze
Widoki Lista widoków w bazie danych serwera SQL. Możesz dodawać, zmieniać i usuwać widoki
b ś d i
Część V ♦ Access i architektura klient-serwer 270

bezpośrednio na serwerze
Diagramy Lista diagramów bazy danych na serwerze. Możesz tworzyć diagram takimi samymi
bazy danych narzędziami jakie są w Visual InterDev 6.0
Formularze Formularze Accessa w Twojej aplikacji. Formularze są zapisane w pliku ADP, a nie na
serwerze. Mogą być połączone z tabelami, widokami i procedurami przechowywanymi
Raporty Raporty Accessa w Twojej aplikacji. Raporty są zapisane w pliku ADP, a nie na serwerze.
Mogą być połączone z tabelami, widokami i procedurami przechowywanymi
Strony Strony dostępu do danych aplikacji. Nie są one zapisane na serwerze, ale istnieją jako pliki
HTML na dysku (zajrzyj do rozdziału 26. „Użycie stron dostępu do danych”). Mogą być
połączone z tabelami, widokami i procedurami przechowywanymi
Makra Wszystkie Twoje makra. Makra zapisane są w pliku ADP
Moduły Moduły Accessa. Moduły są zapisane w pliku ADP

Praca z ADP
i istniejącymi bazami danych
serwera SQL
W czasie pracy nad projektem ADP może być potrzebne dodawanie, zmienianie i usuwanie obiektów bazy danych. W
rozdziale tym opiszę, w jaki sposób można manipulować obiektami serwera SQL istniejącymi w Twoim projekcie.

Praca z tabelami
ADP nie tworzy połączeń do tabel bazy danych tak jak tradycyjne aplikacje Accessa, lecz posiada bezpośredni dostęp do
tabel serwera SQL z okna bazy danych. Gdy usuwasz tabelę lub zmieniasz jej nazwę w Accessie, usuwasz ją lub zmieniasz
jej nazwę również na serwerze. Chociaż jest to bardzo wygodne, może być niebezpieczne. Powinieneś upewnić się, że
ustawiłeś odpowiednie mechanizmy zabezpieczeń serwera SQL tak, aby ograniczyć dostęp użytkowników do tabel. Jeżeli
chcesz zmienić strukturę tabeli, naciśnij przycisk Projektuj, co spowoduje otwarcie okna edytora struktury tabel, jak jest to
pokazane na rysunku 15.5.

Rysunek 15.5.
Edytor tabel
serwera SQL
w Accessie 2000

Edytor struktury tabel serwera SQL jest bardzo podobny to edytora tabel w Accessie. Należy podać nazwę kolumny i jej
atrybuty. W tabeli 15.2 zestawione są wszystkie dostępne atrybuty kolumn.

Tabela 15.2.
Atrybuty w edytorze struktury tabel serwera SQL

Nazwa atrybutu Opis


ColumnName Nazwa kolumny. Musi być prawidłową nazwą kolumny dla serwera SQL
DataType Typ danych kolumny. Dostępne typy danych przedstawione są poniżej
Length Długość kolumny
Precision Dokładność kolumny. Używane dla kolumn numerycznych
Scale Skala (ilość miejsc po przecinku). Używane dla kolumn numerycznych
Allow Nulls Znacznik określający, czy kolumna może zawierać puste wartości
Default Value Wartość domyślna dla kolumny
Identity Znacznik określający, czy kolumna jest kolumną identyfikatora. W tabeli może
istnieć tylko jedna kolumna identyfikatora
271 Rozdział 15. ♦ Wprowadzenie do projektów programu Microsoft Access

Identity Seed Wartość początkowa kolumny identyfikatora


Identity Increment Liczba, o którą jest zwiększana wartość identyfikatora
Is RowGuid Znacznik określający, czy kolumna identyfikatora jest GUID

Zestawienie typów danych serwera SQL:


u Binary u Nvarchar
u Bit u Real
u Char u Smalldate
u Datatime u Smallint
u Decmil u Smallmoney
u float u Text
u Image u Timestamp
u Int u Tinyint
u Money u Uniqueidentifier
u nchar u Varbinary
u ntext u Varchar
u Numeric

Widoki w serwerze SQL


Używając sekcji Widoki w oknie bazy danych, można administrować widokami serwera SQL. Jedną z największych zalet
korzystania z ADP jest to, że możesz utworzyć widok w Accessie i zapisać go na serwerze. Aby utworzyć widok, kliknij
przycisk Nowy. Pojawi się edytor widoków serwera SQL, jak widać to na rysunku 15.6. Wygląda znajomo? Powinno,
ponieważ został utworzony na wzór sławnego edytora QBE Accessa.

Rysunek 15.6.
Edytor widoków
serwera SQL

Gdy jest uruchomiony edytor, można pokazać listę tabel, wybierając Kwerenda|Pokaż tabelę z głównego menu. Zostanie
uruchomione okno z listą tabel i widoków, z którego można przeciągnąć obiekty do edytora (rysunek 15.7). Dla każdej
tabeli można połączyć pola, tak jak w QBE. Naciśnięcie przycisku SQL pokaże treść zapytania w SQL-u, tak jak pokazane
jest to na rysunku 15.8. Użycie podglądu SQL jest przydatne, jeżeli chcesz nauczyć się SQL-a lub chcesz wstawić
wyrażenie SQL do kodu programu.

Rysunek 15.7.
Edytor widoków
serwera SQL
z tabelami
Część V ♦ Access i architektura klient-serwer 272

Rysunek 15.8.
Edytor widoków
serwera SQL
z podglądem
wyrażenia SQL

Możesz użyć kolumny Criteria do zdefiniowania warunków, aliasów kolumn, grupowania i sortowania. Po utworzeniu
widoku należy go zapisać przed uruchomieniem, ponieważ jest to obiekt istniejący na serwerze.

Procedury przechowywane
Wszystkie procedury przechowywane na serwerze SQL mogą być zarządzane przez Accessa. Po wejściu w sekcję procedur
przechowywanych można dodać, modyfikować, zmienić nazwę lub usunąć procedurę. Aby dodać procedurę przechowywaną,
wybierz przycisk Nowy w oknie bazy danych. Pojawi się edytor procedur przechowywanych Accessa pokazany na rysunku
15.9.

Rysunek 15.9.
Edytor procedur
przechowywanych
Accessa

Chociaż edytor procedur przechowywanych wygląda bardzo prosto, wyniki jego pracy mogą być bardzo efektywne.
Możesz utworzyć każdą poprawną procedurę przechowywaną Transact SQL bezpośrednio w Accessie i zapisać ją na
serwerze SQL.

Aby uruchomić procedurę przechowywaną należy kliknąć dwa razy. Jeżeli procedura posiada parametr, Access „zapyta” o
jego wartość (rysunek 15.10).

Rysunek 15.10.
Parametr procedury
przechowywanej

Diagramy bazy danych


Prawdopodobnie najbardziej interesującą opcją ADP są diagramy bazy danych. Dla tych, którzy nie znają narzędzi baz
danych firmy Microsoft, a które są teraz częścią ADP, wyjaśniam, że diagramy bazy danych umożliwiają zarządzanie i
projektowanie tabel bazy danych w sposób wizualny. Baza danych „Northwind” w wersji na serwer SQL ma utworzony
diagram powiązań. Diagram ten przedstawia zależności w bazie danych oraz pozwala na zmiany powiązań, modyfikację
tabel oraz na dodawanie lub usuwanie kolumn bezpośrednio w oknie edytora diagramu.

Aby edytować diagram bazy danych, kliknij go dwa razy, a zostanie on pokazany na ekranie jak na rysunku 15.11.
273 Rozdział 15. ♦ Wprowadzenie do projektów programu Microsoft Access

Rysunek 15.11.
Diagram bazy
danych serwera SQL

Możesz przesuwać i zmieniać rozmiary tabel za pomocą myszki. Możesz także powiększyć fragment diagramu, aby
ograniczyć widok do określonych tabel. Najlepsze jest to, że możesz wydrukować cały diagram jako dokumentację.
Poprzez kliknięcie prawym klawiszem myszki możesz wybrać podgląd atrybutów kolumn i masz dzięki temu dostęp do
edytora struktury tabeli (rysunek 15.12)!

Rysunek 15.12.
Diagram
bazy danych
serwera SQL
z pokazanymi
atrybutami kolumn

Formularze, strony, raporty i moduły


Użycie formularzy, stron, raportów i modułów nie różni się niczym od użycia tych obiektów w plikach MDB, z tą różnicą,
że teraz obiekty bazy danych są obiektami serwera SQL, a nie obiektami Accessa.

Zarządzanie serwerem SQL poprzez ADP


Chociaż nie ma miejsca w tej książce na szczegółowy opis administrowania serwerem SQL, powinieneś wiedzieć, że
można zarządzać bazą danych na serwerze poprzez aplikację ADP.

Aby zarządzać serwerem, użytkownik ADP musi posiadać właściwe prawa dostępu do serwera SQL. Musisz nadać
użytkownikowi ADP prawa administratora bazy danych. Zapewne, do zarządzania serwerem będziesz chciał stworzyć
oddzielny projekt ADP.

Twoja aplikacja może administrować następującymi obszarami:


u Składowanie i odtwarzanie.
u Replikacja.
u Bezpieczeństwo.

Składowanie i odtwarzanie
Aby sporządzić kopię bieżącej bazy danych, wybierz Narzędzia|Narzędzia bazy danych| Kopia zapasowa z głównego
menu. Access, „zapyta” Cię o miejsce, gdzie ma zapisać kopię, tak jak wygląda to na rysunku 15.13.
Część V ♦ Access i architektura klient-serwer 274

Rysunek 15.13.
Kopia zapasowa
serwera SQL
wykonywana
przez Accessa

Baza danych zostanie zapisana w formacie czytelnym dla normalnej procedury odtwarzania serwera SQL. Możesz także
wybrać Narzędzia|Narzędzia bazy danych|Przywróć z głównego menu, aby przywrócić bazę danych z kopii zapasowej.

Replikacja serwera SQL


W Accessie można utworzyć nowe publikacje, synchronizować repliki oraz rozwiązywać konflikty. Aby utworzyć nową
publikację, wybierz Narzędzia|Replikacja|Utwórz publikację z głównego menu. Na ekranie pojawi się okno replik, pokazane
na rysunku 15.14. Wybierz bazę danych na diagramie i kliknij przycisk Twórz publikację. Uruchomiony zostanie kreator
publikacji pokazany na rysunku 15.15.

Rysunek 15.14.
Okno dialogowe
repliki

Rysunek 15.15.
Kreator publikacji
serwera SQL

Po uruchomieniu kreatora stosuj się do jego zaleceń, aby utworzyć publikację. Całkiem łatwo tworzy się publikację, a
nawet mamy możliwość utworzenia subskrybenta w postaci pliku MDB korzystającego z silnika bazy danych Jet (więcej
informacji znajdziesz w rozdziale 22. „Replikacja i JRO”). Aby zsynchronizować bazę danych z repliką, wybierz:
Narzędzia|Replikacja|Synchronizuj z głównego menu. Można również tak skonfigurować serwer SQL, aby automatycznie
wykonywał synchronizację w określonym przez nas czasie przy użyciu programu Enterprise Manager.

Bezpieczeństwo
Za pomocą Accessa 2000 można zarządzać mechanizmami bezpieczeństwa serwera SQL poprzez wybranie
Narzędzia|Zabezpieczenia|Zabezpieczenia bazy danych. Uruchomione zostanie okno dialogowe zarządzania prawami
dostępu użytkownika, bardzo podobne do używanego w Accessie (rysunek 15.6). Za jego pomocą można dodawać, usuwać
i edytować użytkowników, ich prawa dostępu do bazy, oraz tworzyć grupy użytkowników.
275 Rozdział 15. ♦ Wprowadzenie do projektów programu Microsoft Access

Rysunek 15.16.
System zabezpieczeń
w Accessie 2000
oparty jest o system
zabezpieczeń
w SQL Server 7.0

Zwykle użytkownik, który jest właścicielem bazy danych, ma nazwę DBO, natomiast użytkownik – gość nazywa się Guest.
Role są identyczne z rolami w SQL Server, użytkownik może mieć np. rolę „Administrator systemu”. Aby dowiedzieć się
więcej o systemie bezpieczeństwa, zajrzyj do książek elektronicznych dostarczonych z SQL Server.

Powtórne przyłączenie do bazy serwera SQL


Co się stanie, gdy po utworzeniu aplikacji ADP chciałbyś zainstalować ją u użytkownika w innej sieci komputerowej? Aby
aplikacja prawidłowo działała, musisz zsynchronizować plik ADP tak, aby przyłączył się do właściwej bazy danych. Jak
omawialiśmy w rozdziale 7., używałeś uniwersalnych połączeń danych do zarządzania ciągiem połączeniowym OLE DB
w ADO. Poprzez ustanowienie odwołania do komponentu Microsoft OLE DB ServiceComponent 1.0 Type
Library, w sposób pokazany na rysunku 15.17, możesz użyć interfejsu automatyzacji UDL do synchronizacji aplikacji
ADP z właściwą bazą danych.

Rysunek 15.17.
Ustanowienie
odwołania do
komponentu OLE
DB Service

Po ustanowieniu odwołania można przypisać ciąg połączeniowy do metody PromptNew obiektu DataLink. Następnie
możesz przypisać ten ciąg do metody CurrentProject.OpenConnection, aby aplikacja ADP przyłączyła się do nowej
bazy danych. Fragment programu z wydruku 15.1 przedstawia, w jaki sposób można wykonać taką operację.

Wydruk 15.1. Uaktualnianie połączenia ADP


Sub UpdateConnection()
' Procedura używa interfejsu UDL Automation
' do utworzenia obiektu połączenia
' i użycia tego połączenia do synchronizacji ADP
' Autorzy: Forte, Howe, Ralston
Dim strConnect As String
Dim rst As ADODB.Recordset
' Odwołanie do Microsoft UDL
Dim udl As MSDASC.DataLinks

On Error GoTo Proc_Err


' Tworzenie obiektu Data Link
Set udl = New MSDASC.DataLinks
StrConnect = udl.PromptNew

' Pobranie informacji o połączeniu z UDL i synchronizacja ADP


CurrentProject.OpenConnection strConnect

Proc_Exit:
Exit Sub
Część V ♦ Access i architektura klient-serwer 276

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub

W CurrentProject.Connection ADP używa obiektu MSDataShape


OLE DB oprócz SQL Server OLE DB. Spotkałem się z tym, że niektóre
funkcje ADO działają nieco inaczej w VB, gdy używa się SQL Server
OLE DB bez MSDataShape. Szukaj w Microsoft KnowledgeBase opisu użycia
kodu Accessa 2000 w Visual Basic.

Tworzenie projektu
opartego na nowej bazie danych
W tym rozdziale pokażemy, w jaki sposób użyć narzędzi ADP, aby utworzyć od początku nową bazę danych. Utworzymy
prostą aplikację, która pokaże nam, jak duże możliwości posiada ADP. Uruchom Access 2000 i wybierz z menu Plik|Nowy,
a następnie wybierz z okna dialogowego Nowa baza danych. Access uruchomi kreatora baz danych serwera SQL (rysunek
15.18). Kreator poprosi o podanie nazwy serwera, nazwy użytkownika i jego hasła oraz nazwy bazy danych. Po podaniu
tych informacji Access utworzy na serwerze bazę danych. Teraz jesteś gotowy do tworzenia aplikacji.
Rysunek 15.18.
Kreator
bazy danych SQL

Tworzenie tabel
Chcemy utworzyć prosty system śledzenia wykonywania zadań. Aby to zrealizować, potrzebujemy kilku tabel. Aby
utworzyć tabelę, kliknij Utwórz tabelę w widoku projektu w oknie bazy danych. Zauważ, że jesteś od razu pytany o nazwę
tabeli, ponieważ obiekt ten istnieje na serwerze i musi być zgodny z wymaganiami serwera.

Rysunek 15.19.
Okno wyboru
nazwy tabeli

A teraz utwórz dwie tabele w edytorze, tblWydanie i tlkpTypTransakcji. Opis tblWydanie znajduje się w tabeli 15.3 a
tlkpTypTransakcji w tabeli 15.4.
277 Rozdział 15. ♦ Wprowadzenie do projektów programu Microsoft Access

Tabela 15.3.
Projekt tabeli tblWydanie

Nazwa kolumny Typ danej Opis


IDWydania Int(4) Klucz główny, identyfikator
IDTypTransakcji Int(4) Będzie kluczem obcym
Komentarz Text(16)

Tabela 15.3.
Projekt tabeli tblWydanie (ciąg dalszy)

Nazwa kolumny Typ danej Opis


DataZapisu Datetime Domyślna wartość: getdate()
DataZakończenia Datetime Kolumna może być pusta

Tabela 15.4.
Projekt tabeli tlkpTypTransakcji

Nazwa kolumny Typ danej Opis


IDTypTransakcji Int(4) Klucz główny, identyfikator
OpisTransakcji Varchar(50)

Ustawienie właściwości tabeli i indeksów


Aby ustawić indeksy oraz właściwości tabeli wybierz Widok|Właściwości z głównego menu. Uruchomi się okno dialogowe
pokazane na rysunku 15.20. W tym oknie można ustawić atrybuty indeksu takie jak: unikatowość, poziom wypełnienia, czy
jest indeksem grupowym (CLUSTERED) czy nie. Poprzez edytor struktury tabel ustawiłeś klucz główny, więc istnieje już
dla niego unikatowy indeks.

Rysunek 15.20.
Właściwości tabeli

Tworzenie zależności na diagramie bazy danych


Teraz, gdy masz utworzone dwie tabele (to było TAKIE proste), powinieneś zdefiniować zależności pomiędzy nimi.
Tworzenie zależności pomiędzy tabelami jest bardzo proste przy użyciu ADP. Aby wizualnie zdefiniować związki
pomiędzy tabelami za pomocą diagramu bazy danych, przejdź do sekcji Diagramy bazy danych w oknie bazy danych i
dodaj nowy diagram. Aby wyświetlić listę tabel, wybierz Widok|Pokaż tabele z głównego menu. Następnie przeciągnij
dwie tabele z okna Pokaż tabelę na diagram, jak widać na rysunku 15.21. Aby utworzyć relację, przeciągnij pole z
tblkTypTransakcji do tblWydanie. Przeciągnięcie pola spowoduje otwarcie okna relacji (rysunek 15.22), które pozwoli na
określenie pól wchodzących w skład zależności. Po ustanowieniu zależności zapisz diagram. Pamiętaj, możesz go użyć jako
dokumentację do Twojego projektu.
Część V ♦ Access i architektura klient-serwer 278

Rysunek 15.21.
Tryb edycji
diagramu
bazy danych

Rysunek 15.22.
Właściwości relacji

Tworzenie kaskad poprzez wyzwalacze


SQL Server 7.0 nie zapewnia kaskadowego uaktualniania i kaskadowego kasowania poprzez więzy integralności. Jeżeli
chcesz skorzystać z tego mechanizmu, musisz zrobić to, wykorzystując wyzwalacze. Aby utworzyć lub edytować
wyzwalacz, kliknij prawym przyciskiem na nazwę tabeli w oknie bazy danych i wybierz Wyzwalacze z menu kon-
tekstowego. Uruchomi się okno dialogowe pokazane na rysunku 15.23. Jeżeli wyzwalacz już istnieje, wybierz go lub
kliknij przycisk Nowa, aby utworzyć nowy wyzwalacz.
Rysunek 15.23.
Zarządzanie
wyzwalaczami

Tworzenie widoków
Zamierzasz utworzyć widok na serwerze SQL, który przedstawia wszystkie zakończone transakcje. Aby utworzyć widok,
wybierz Nowy w oknie bazy danych i przeciągnij dwie tabele do edytora, tak jak to jest pokazane na rysunku 15.24.
Utworzyłeś prosty widok, który jest wynikiem zapytania SQL przedstawionego na wydruku 15.2
279 Rozdział 15. ♦ Wprowadzenie do projektów programu Microsoft Access

Rysunek 15.24.
Edytor widoków

Wydruk 15.2. Prosty widok


SELECT tlkpTypTransakcji.OpisTransakcji, tblWydanie.IDWydania,
tblWydanie.Komentarz, tblWydanie.DataZapisu,
tblWydanie.DataZakończenia
FROM tblWydanie INNER JOIN
tlkpTypTransakcji ON
tblWydanie.IDTypTransakcji = tlkpTypTransakcji.IDTypTransakcji
WHERE (tblWydanie.DataZakończenia IS NOT NULL)

Tworzenie procedur przechowywanych


Aby utworzyć procedurę przechowywaną, otwórz edytor procedur i wpisz odpowiednie wyrażenie TSQL. Utworzymy
prostą procedurę, która wybierze jedną transakcję określoną przez jej numer. Kod procedury pokazany jest na wydruku
15.3.

Wydruk 15.3. Prosta procedura przechowywana


Create Procedure "WybierzTransakcje"
@NumerWyd int
As
SELECT tlkpTypTransakcji.OpisTransakcji, tblWydanie.IDWydania,
tblWydanie.Komentarz, tblWydanie.DataZapisu,
tblWydanie.DataZakończenia
FROM tblWydanie INNER JOIN
tlkpTypTransakcji ON
tblWydanie.IDTypTransakcji = tlkpTypTransakcji.IDTypTransakcji
WHERE tblWydanie.IDWydania=@NumerWyd

Tworzenie aplikacji w Accessie


Aby przekonać się, jak łatwo tworzy się aplikacje w Accessie, używając ADP, spójrz na prosty formularz pokazany na
rysunku 15.25. Jest on związany z tabelą tblWydanie i za jego pomocą można wpisywać i przeglądać dane, filtrować, itp.,
tak samo jak w zwykłym pliku MDB. Tworzenie raportów jest równie proste jak w Accessie 97. Po prostu uruchom
kreatora i utwórz swój raport.

Rysunek 15.25.
Nasza formatka

Tworzenie plików ADE


W Accessie 97 wprowadzono w życie nowy pomysł, pliki MDE. Jest to skompilowana i zablokowana wersja pliku MDB.
W Accessie 2000 masz możliwość tworzenia plików MDE dla aplikacji MDB oraz plików ADE dla plików ADP. Aby
Część V ♦ Access i architektura klient-serwer 280

utworzyć plik ADE, wybierz Narzędzia|Narzędzia bazy danych|Utwórz plik ADE, jak widać to na rysunku 15.26. Po
wybraniu lokalizacji pliku Access utworzy tam plik ADE. Od teraz wszystkie formularze, raporty, strony i moduły będą
zablokowane dla użytkownika aplikacji.

Zakończenie: przenoszenie bazy danych Access 97


na serwer SQL i do pliku ADP
We wcześniejszych wersjach Accessa kreator rozbudowy bazy danych nie był doskonały. Potrafił przenieść tabele na
serwer SQL i to wszystko. Zapytania pozostawały w Accessie i były uruchamiane na tabelach połączonych, co było bardzo
nieefektywne. Jeżeli jednak uruchomisz tego samego kreatora z Accessa 2000, otrzymasz dużo lepsze rezultaty. Kreator
zamieni wszystkie „widoki” dla silnika bazy Jet oraz zapytania typu SELECT na widoki serwera SQL, a także procedury
Accessa na procedury przechowywane (jeżeli będzie to możliwe). Następnie zostanie utworzona aplikacja ADP oparta o
serwer SQL. Mimo że jeszcze jest wiele ograniczeń, kreator ten jest wart zainteresowania; w najgorszym razie pomoże Ci
rozpocząć pracę nad przeniesieniem bazy. Jest on bardzo prosty w użyciu, więc wybierz Narzędzia|Narzędzia bazy
danych|Kreator rozbudowy.
Rysunek 15.26.
Tworzenie
pliku ADE
Rozdział 16.
Tworzenie interfejsu użytkownika
dla Microsoft SQL Server
W tym rozdziale:
u Architektura klient-serwer: OLE DB kontra ODBC.
u Tworzenie połączenia z serwerem SQL.
u Procedury przechowywane i kwerendy przekazujące.
u Raportowanie z serwera SQL w Accessie.
u Formularze w aplikacji.
u Zaawansowane właściwości: dostawca OLE DB dla SQL serwera.
u Wykonywanie poleceń z parametrami.
u Użycie klasy Connection.

Od czasu wprowadzenia na rynek Microsoft Access jest uważany za wspaniałe narzędzie do tworzenia interfejsu
użytkownika dla zewnętrznych baz danych. Mimo że Access 2000 ma kilka wspaniałych nowych właściwości do pracy z
SQL Server 7.0 poprzez Projekty programu Access (ADP), właściwości te nie działają dobrze z SQL Server 6.5 i nie
działają wcale poprzez połączenie ODBC. W tym rozdziale pokażemy, jak tworzyć aplikacje oparte na SQL Server 6.5
lub Sybase System 10. W rozdziale 17., „Interfejs Accessa 2000 do Oracle” pokażemy, jak tworzyć aplikacje oparte na
Oracle Enterprise Server.

Architektura klient-serwer: OLE DB kontra ODBC


Systemem klient-serwer nazywamy system, który używa serwera bazy danych (np. SQL Server lub Oracle) do
przechowywania danych oraz aplikacji klientów, które komunikują się z bazą danych (systemy trójwarstwowe, o których
się dużo mówi, mają podobną architekturę za wyjątkiem tego, że logika biznesowa umieszczona jest w oddzielnej logicznej
warstwie).

Aplikacja Accessa typu MDB połączona z serwerem SQL jest w rozumieniu tej architektury klientem. Access, gdy używa
połączenia ODBC, ładuje silnik bazy Jet, który pośredniczy w komunikacji z bazą danych. Aplikacja typu ADP we
współpracy z serwerem SQL używa nowszej technologii OLE DB, która komunikuje się z serwerem bez ładowania silnika
Jet. Chociaż podejście OLE DB ma wiele znaczących plusów, jego największą wadą jest brak wsparcia dla innych
serwerów SQL niż SQL Server. Mimo że ODBC i pliki MDB nie są tak szybkie jak nowe projekty ADP, są jednak
użyteczne i dosyć wydajne, co pokażemy w tym rozdziale.

Tworzenie połączenia z serwerem SQL


Aby rozpocząć pracę z bazą danych na serwerze SQL, należy zestawić z nią połączenie. Ponieważ będziemy używać
połączenia ODBC do komunikacji z bazą, upewnijmy się, że na komputerze, którego używamy, zainstalowany jest
właściwy sterownik. Standardowa instalacja Accessa 2000 instaluje sterownik ODBC do SQL Server (jeżeli chcesz użyć
Część V ♦ Access i architektura klient-serwer 282

Sybase SQL Server, musisz zainstalować właściwy dla niego sterownik ODBC, którego nie ma jednak na płycie z Office
2000). Po zainstalowaniu Accessa 2000 ze sterownikiem ODBC jesteś już gotowy do pracy z serwerem SQL.

Istnieją dwie metodologie dostępu do danych: tabele połączone oraz kwerendy przekazujące. Większość aplikacji używa
obydwu metod. Aby użyć tych metod, najpierw musisz utworzyć systemowe źródło danych ODBC.

Tworzenie źródła danych ODBC (DSN)


Systemowe DSN jest miejscem, gdzie zapisujesz wszystkie informacje o połączeniach ODBC. Każdy DSN posiada
unikatową nazwę, której używają aplikacje. Aby utworzyć DSN na Twoim komputerze, wykonaj następujące czynności.
70. Uruchom Źródła danych ODBC (32 bity) z Panelu sterowania, na zakładce Systemowe DSN naciśnij Dodaj. Gdy
uruchomi się okno dialogowe DSN wybierz SQL Server i naciśnij przycisk Zakończ. Uruchomi się kreator
tworzenia DSN, taki jak na rysunku 16.1.
Rysunek 16.1.
Tworzenie nowego
źródła danych
w Panelu sterowania

71. Na pierwszej stronie kreatora (rysunek 16.1) wprowadź unikatową nazwę DSN (np. NorthWind), ewentualny opis
i nazwę serwera, na którym uruchomiony jest serwer SQL. Naciśnij Dalej, gdy wprowadziłeś te informacje.
72. Na drugiej stronie wprowadza się informacje o systemie użytkowników. Gdy chcesz użyć zwykłego systemu
serwera SQL (lub gdy nie wiesz, jaki chcesz wybrać), zaznacz Uwierzytelnianie serwera SQL, używając ID
logowania i hasła podanego przez użytkownika, wpisz nazwę użytkownika oraz hasło i naciśnij przycisk Dalej
(używając domyślnego użytkownika na SQL Server, nazwa użytkownika to „SA”, a hasło jest puste).
73. Trzecia strona kreatora pokazana jest na rysunku 16.2. Wprowadzasz na niej nazwę bazy danych, do której chcesz
się dołączyć. W celu pokazania przykładów w tym rozdziale przyłączymy się do bazy NorthWind.

Rysunek 16.2.
Wybór domyślnej
bazy danych podczas
tworzenia DSN

74. Czwarta strona zawiera opcje specyficzne dla ODBC, jak śledzenie. Zatwierdź domyślne opcje i naciśnij Zakończ.
75. Ostatnia strona pozwala na sprawdzenie nowo utworzonego połączenia. Dobrze jest sprawdzić tutaj połączenie i w
wypadku niepowodzenia testu, wprowadzić od razu poprawki.

Teraz jesteś gotowy do użycia serwera SQL w aplikacji Access 2000.

Łączenie tabel
Aby zacząć pracę z nowo utworzonym źródłem danych ODBC, najczęściej stosowanym i najłatwiejszym rozwiązaniem
jest połączenie tabel serwera SQL z plikiem MDB. Tym sposobem możesz uruchamiać proste zapytania SQL, aby np.
wypełnić pola listy. Dla naprawdę małych tabel można nawet podłączyć formularze bezpośrednio do tabeli i w ten
sposób umożliwić użytkownikom wprowadzanie danych (więcej informacji o łączeniu formularzy do danych z serwera
SQL znajdziesz w części tego rozdziału zatytułowanej „Formularze w aplikacji”). Aby dołączyć tabele poprzez ODBC,
wykonaj następujące czynności.
283 Rozdział 16. ♦ Tworzenie interfejsu użytkownika dla Microsoft SQL Server

76. Upewnij się, że istnieje prawidłowe źródło danych (zajrzyj do „Tworzenie źródła danych ODBC (DSN)”).
77. Otwórz bazę danych Access i wybierz z menu: Plik|Pobierz dane zewnętrzne|Połącz tabele.
78. Na ekranie pojawi się lista wszystkich źródeł danych ODBC. Wybierz ten DSN, na którym chcesz pracować, i
naciśnij OK.
79. Access wyświetli teraz listę tabel, które możesz dołączyć (rysunek 16.3). Gdy wybierzesz tabele, możesz zapisać
razem z nimi hasło dostępu do bazy danych. Gdy to zrobisz, użytkownicy aplikacji nie będą musieli podać tego
hasła podczas pierwszego uruchomienia aplikacji.

Rysunek 16.3.
Wybór tabel
z bazy danych
ODBC

80. Teraz Access łączy tabele z plikiem MDB. Nazwy tabel poprzedzone zostaną prefiksem „dbo_”, ponieważ
właścicielem tabel w SQL Server jest „Database Owner” (właściciel bazy danych).
81. Gdy w tabeli serwera SQL nie ma zdefiniowanego klucza głównego, Access nie może połączyć takich tabel w trybie
odczytu i zapisu, więc daje Ci możliwość utworzenia lokalnego unikatowego indeksu w sposób pokazany na rysunku
16.4. Jeżeli użyjesz tego mechanizmu, będzie można zapisywać do tabeli, a Jet 4.0 będzie utrzymywał indeks na
Twoim komputerze.

Rysunek 16.4.
Tworzenie
unikatowego
identyfikatora
rekordu

Po połączeniu tabel możesz tworzyć kwerendy, formularze i raporty odnoszące się do tych połączonych tabel.

Wady tabel połączonych


Łączenie tabel ze źródeł danych ODBC do Accessa może być bardzo nieefektywne i niebezpieczne. Silnik Jet musi
pośredniczyć w całej komunikacji pomiędzy serwerem SQL a aplikacją. Jeżeli nie może użyć unikatowego indeksu na
serwerze, może wczytać wszystkie rekordy tabeli do przetwarzania na komputerze klienta. Wyobraź sobie taką sytuację.
Łączysz tabelę z 5 milionami rekordów, tworzysz zapytanie wybierające około 500 rekordów, ale warunek selekcji nie
opiera się o żaden unikatowy indeks. W zależności od projektu tabeli serwer SQL może zwrócić całe 5 milionów rekordów
do posortowania przez silnik Jet! Jeżeli uruchomisz to na niezbyt szybkim komputerze, będzie to trwało godzinami.

Aby wydobyć całą moc z serwera SQL, powinieneś użyć procedur przechowywanych. Procedura przechowywana na
serwerze SQL jest podobna do pytania zapisanego w Accessie. Jest to skompilowane wyrażenie SQL, które pobiera
parametry i zostanie wykonana na serwerze. Wielu programistów wysyła wyrażenia SQL do serwera, ponieważ jest to o
wiele szybsze niż użycie tabel połączonych. Metoda ta jest jednak wolniejsza od procedur przechowywanych, ponieważ
procedura posiada utworzony podczas kompilacji plan wykonania tak, aby zapytanie wykonywało się z największą
możliwą prędkością. Użycie procedur przechowywanych daje najlepsze wyniki przy zaangażowaniu najmniejszym wysiłku.
Oprócz zwiększenia prędkości procedury przechowywane zmniejszają ruch w sieci. Wysyłasz do serwera tylko małe 1 kB
polecenia uruchomienia procedury zamiast dużego 100 kB lub większego nieskompilowanego wyrażenia SQL. W obu
przypadkach serwer odsyła Ci tylko te dane, których potrzebujesz.

Połączenie najlepszych metod:


wypełnianie tabel podczas startu aplikacji
Ponieważ zwykle używam procedur przechowywanych jako podstawowej metody manipulacji danymi w moich
aplikacjach klient-serwer, zwykle używam tabel połączonych do wypełniania list i list rozwijanych danymi
wykorzystywanymi na formatkach i raportach. Aby uzyskać najlepszą wydajność, możesz przy starcie aplikacji tworzyć
kopie tabel serwera do tabel lokalnych. Oczywiście, używaj tej techniki tylko do danych statycznych (nie zmieniających się
zbyt często).
Część V ♦ Access i architektura klient-serwer 284

Technika ta, chociaż bardzo użyteczna, nie jest dostępna w projektach


ADP, które były omawiane w rozdziale 15. „Wprowadzenie do pro-
jektów programu Microsoft Access oraz narzędzi wizualnych”, ponie-
waż lokalne tabele opierają się o silnik Jet, a ADP w ogóle go nie
ładuje.

Procedury przechowywane
i kwerendy przekazujące
Dobrze jest oprzeć raporty Accessa na procedurach przechowywanych, ponieważ są one szybkie i efektywne. Problem
stanowi to, że nie możesz połączyć się z procedurą tak jak, łączysz się z tabelą na serwerze SQL. Możesz jednak użyć
kwerendy przekazującej, aby uzyskać te same możliwości. Kwerenda przekazująca to wyrażenie SQL wysłane do
przetworzenia przez serwer SQL. Silnik Jet nie przetwarza takiego wyrażenia, a Access otrzymuje od serwera wyniki.
Kwerendy przekazujące umożliwiają wykorzystanie całej mocy obliczeniowej serwera bazy danych.

Tworzenie procedur przechowywanych wykracza poza ramy tej książki, jednak jeżeli utworzysz widok w projekcie ADP
(zajrzyj do rozdziału 15.), możesz skopiować wyrażenie z okna podglądu SQL i wstawić je do procedury przechowywanej.
Wydruk 16.1 przedstawia przykład procedury przechowywanej z bazy danych NorthWind, która zwraca informacje o
zamówieniach z zadanego zakresu dat. Wydruk 16.1 tworzy procedurę przechowywaną sp_OrdersByDate, która wymaga
dwóch argumentów, @StartDate i @EndDate.

Wydruk 16.1. Prosta procedura przechowywana


CREATE PROCEDURE dbo.sp_OrdersByDate
@StartDate datetime, @EndDate datetime AS

SELECT Customers.CustomerID, Customers.CompanyName,


Orders.OrderDate, [Order Details].Quantity,
[Order Details].UnitPrice, Quantity*UnitPrice AS TotalAmount
FROM Customers INNER JOIN Orders ON
Customers.CustomerID=Orders.CustomerID INNER JOIN
[Order Details] ON Orders.OrderID = [Order Details].OrderID
Where OrderDate Between @StartDate and @EndDate

Uruchomienie procedury przechowywanej jest proste. Logujemy się do bazy danych i wpisujemy polecenie EXECUTE w
oknie SQL. Jeżeli procedura wymaga parametrów, należy je podać. Aby uruchomić procedurę sp_OrdersByDate
(wydruk 16.1) za pomocą narzędzia SQL Server T/SQL, powinieneś wpisać takie polecenie:
Execute sp_OrdersByDate @StartDate='07/01/94' , @EndDate='09/30/94'

Wynik działania procedury sp_OrdersByDate pokazany jest na rysunku 16.5. Procedura ta zwraca zamówienia klientów
uporządkowane według dat wraz z wartością każdego zamówienia.

Tworzenie raportów opartych na procedurach przechowywanych poprzez


zapytania przekazujące
Aby uruchomić procedurę przechowywaną w zapytaniu przekazującym, należy użyć polecenia Execute, która została
wcześniej omówiona. Możesz utworzyć kwerendę przekazującą poprzez wybranie z menu:
Kwerenda|Wyłącznie SQL|Przekazująca, po przejściu do trybu projektowania zapytań (rysunek 16.6).
285 Rozdział 16. ♦ Tworzenie interfejsu użytkownika dla Microsoft SQL Server

Rysunek 16.5.
Wynik działania
procedury
przechowywanej

Rysunek 16.6.
Tworzenie kwerendy
przekazującej

Nie możesz używać tabeli QBE do tworzenia kwerend przekazujących, musisz wpisywać wyrażenie SQL bezpośrednio do
okna SQL. Należy używać składni SQL zgodnej ze składnią bazowego serwera (w tym rozdziale używamy składni
Microsoft SQL Server 6.5, ale będziemy musieli użyć innej w rozdziale 17. „Interfejs Accessa 2000 do Oracle”, w którym
zajmiemy się bazą Oracle).

Po wpisaniu wyrażenia SQL musisz utworzyć ciąg połączeniowy ODBC. Ciąg ten „mówi” Accessowi, do której bazy
danych ma wysłać wyrażenie SQL. Należy otworzyć okno właściwości i ustawić właściwość Ciąg połączenia ODBC. W
Accessie dostępny jest konstruktor uruchamiany przez naciśnięcie przycisku „...” obok pola właściwość. Możesz samemu
wpisać prawidłowy ciąg połączenia lub uruchomić konstruktor i wybrać właściwe źródło danych ODBC z zainstalowanych
w systemie, tak jak pokazane jest na rysunku 16.7.

Zapisz kwerendę przekazującą jako qsptOrdersbyDate. Zauważ, że kwerenda przekazująca ma inną ikonę niż normalna
kwerenda (jak widać na rysunku 16.8).
Rysunek 16.7.
DSN zainstalowane
w systemie
Część V ♦ Access i architektura klient-serwer 286

Rysunek 16.8.
Zapisana kwerenda
przekazująca

Raportowanie z serwera SQL w Accessie


Jeżeli spytasz doświadczonych programistów, co lubią najbardziej w Accessie, wielu z nich odpowie, że ma on jeden z
najlepszych modułów raportowych. Access umożliwia łatwe tworzenie wspaniałych raportów bardzo szybko, nawet jeżeli
dane nie pochodzą z tabel Accessa. Możliwość łatwego raportowania z danych ODBC sprawia, że Access jest dobrym
wyborem dla całego raportowania w przedsiębiorstwie.

Można tworzyć raporty na wiele sposobów. Najprostszą metodą jest połączenie tabeli ODBC i utworzenie kwerendy w
Accessie jako bazy dla raportu. Mimo że jest to najszybszy sposób stworzenia raportu, nie jest polecany ze względów
opisanych dalej w tym rozdziale.

Zwykle komputery, które służą za serwery baz danych SQL, są dużo szybsze i posiadają więcej pamięci RAM niż średni
komputer w biurze. Prześledzę sposoby na zwiększenie wydajności raportów klient-serwer, aby w pełni skorzystać z mocy
serwerów, na których zainstalowana jest baza danych.

Kolejne przykłady będą oparte o przykładową bazę danych „NorthWind” dostarczaną z SQL Server.

Aby uruchomić raport oparty na kwerendzie przekazującej, uruchom Kreator raportów i wybierz kwerendę przekazującą
qsptOrdersbyDate. Utwórz teraz taki raport, jaki potrzebujesz. Przykład gotowego raportu pokazywany jest na rysunku
16.9. Zapisz gotowy raport jako qsptOrdersbyDate.

Rysunek 16.9.
Raport oparty
o procedurę
przechowywaną

Zaawansowane możliwości:
przekazywanie parametrów do procedury przechowywanej w czasie
działania programu
Jesteś przyzwyczajony do tworzenia kwerend z parametrami na potrzeby raportów w Accessie, które wymagają podania
przez użytkownika dat lub innych wartości. W Accessie, jeżeli użyjesz pola formularza w warunku kwerendy, możesz zapytać
użytkownika o parametr, jak jest to pokazane na rysunku 16.10. Przy użyciu procedur musisz powtórnie utworzyć
polecenie Execute z nowymi parametrami wewnątrz kwerendy przekazującej qsptOrdersbyDate za każdym razem, gdy
287 Rozdział 16. ♦ Tworzenie interfejsu użytkownika dla Microsoft SQL Server

uruchamiasz raport. Na formatce służącej do wprowadzania parametrów, pokazanej na rysunku 16.10, oprogramowane jest
zdarzenie Click tak, aby ustawić właściwą postać wyrażenia Execute w kwerendzie i uruchamia procedurę z nowym
zakresem dat. Kod, który to realizuje, zamieszczony jest na wydruku 16.2. Zauważ, że potrzebujesz odwołania do DAO 3.6
w aplikacji. Aby ustawić to odwołanie, otwórz główny moduł i z głównego menu w edytorze VBE wybierz Tools|References. W
oknie dialogowym zaznacz bibliotekę DAO 3.6 Object Library.

Wydruk 16.2. Zmiana wyrażenia SQL i uruchomienie raportu


Private Sub cmdPrint_Click()
'''''''''''''''''''''''''''''''''''''''
' Przeznaczenie: Zmiana kodu SQL, aby wywołać
' procedurę przechowywaną z nowymi parametrami
''''''''''''''''''''''''''''''''''''''''
Dim db DAO.Database
Dim strSql As String

Rysunek 16.10.
Formularz
pobierania
parametrów
do uruchomienia
raportu

On Error GoTo Click_Err


StrSQL = "Execute sp_OrdersbyDate @StartDate=" & _
Chr(39) & Me.txtStartDate & Chr(39) & _
", @EndDate=" & Chr(39) Me.txtEndDate & Chr(39)

Set db = CurrentDb
Db.QueryDefs("qsptOrdersbyDate").SQL = strSQL
DoCmd.OpenReport "qsptOrdersbyDate", acViewPreview

Click_Exit:
Exit Sub
Click_Err:
MsgBox Err.Description
Resume Click_Exit
End Sub

Dodatkowe filtrowanie danych raportu


Czasami warunek Where w procedurze przechowywanej nie zapewnia dokładnie tych informacji, których potrzebujesz.
Możesz dostać 500 zamówień i chcesz odfiltrować je, określając minimalną wartość zamówienia. Access dostarcza dwóch
metod do filtrowania raportów poprzez metodę DoCmd.OpenReport: można podać nazwę zapisanej kwerendy lub
przekazać warunek Where do raportu. Rysunek 16.10 przedstawia formatkę wprowadzania wartości parametrów, która
umożliwia także przekazanie wartości do filtra, bazującego na wartości zamówienia, oprócz wprowadzenia zakresu dat.
Jeżeli użytkownik zdecyduje się na użycie filtra oprócz zakresu dat, wykonany zostanie kod wywołujący metodę
BuildCriteria z obiektu Application. Prawidłowym filtrem będzie np.: OrderAmount>500. Metoda
BuildCriteria utworzy prawidłowy filtr, który następnie będzie zastosowany podczas wykonania metody
DoCmd.OpenReport. Wydruk 16.3 zawiera kod, który zarówno zmienia wyrażenie SQL w zapytaniu przekazującym, jak i
tworzy filtr.

Wydruk 16.3. Użycie metody BuildCriteria do założenia filtra w raporcie


Function BuildWhere(curAmt As Currency) As String

' Tworzy warunek Where za pomocą metody BildCriteria


BuildWhere = BuildCriteria( "TotalAmount", dbCurrency,
">=" & curAmt)

End Function

Private Sub cmdPrint_Click()


'''''''''''''''''''''''''''''''''''''''
' Przeznaczenie: Zmiana kodu SQL, aby wywołać
' procedurę przechowywaną z nowymi parametrami
' oraz dodaje możliwość filtrowania.
' Filtrowanie jest realizowane poprzez właściwość
' Where Clause metody DoCmd.OpenReport
''''''''''''''''''''''''''''''''''''''''

Dim db DAO.Database
Dim strSql As String
Część V ♦ Access i architektura klient-serwer 288

On Error GoTo Click_Err

StrSQL = "Execute sp_OrdersbyDate @StartDate=" & _


Chr(39) & Me.txtStartDate & Chr(39) & _
", @EndDate=" & Chr(39) Me.txtEndDate & Chr(39)
Set db = CurrentDb
Db.QueryDefs("qsptOrdersbyDate").SQL = strSQL

' Tutaj sprawdzamy, czy jest potrzebny filtr


' tzn. czy jest zaznaczone pole wyboru
if Me.chkFilter Then
'Zastosuj filtr
DoCmd.OpenReport "qsptOrdersbyDate", acViewPreview, , _
BuildWhere(Me.txtFilter)
Else
DoCmd.OpenReport "qsptOrdersbyDate", acViewPreview
End If

Click_Exit:
Exit Sub
Click_Err:
MsgBox Err.Description
Resume Click_Exit
End Sub

I na koniec niezłym pomysłem jest drukowanie w nagłówku raportu informacji o filtrze oraz jego wartości. Dodatkowo
powinieneś ostrzegać użytkownika o pustym raporcie za pomocą zdarzenia raportu NoData. Fragment programu, który to
realizuje, jest na wydruku 16.4.

Wydruk 16.4. Kod w raporcie obsługujący filtr oraz zdarzenie NoData


Private Sub Report_NoData(Cancel As Integer)
' Brak danych!
On Error Resume Next

' Ostrzegaj użytkownika o pustym raporcie


MsgBox "Ten raport nie zawiera danych" & vbNewLine & _
"Proszę podać inny warunek", vbCritical, Me.Name

' Nie otwieraj tego raportu


Cancel = True
End Sub

Private Sub Report_Open (Cancel As Integer)

On Error Resume Next


' Sprawdź, czy zastosowano filtr
If Forms!frmPrintReport!chkFilter Then
' Wpisz w nagłówku raportu warunek filtra
Me.lblFilter.Caption = _
"Raport filtrowany według zamówień > " & _
Forms!frmPrintReport!txtFilter
Me.lblFilter.Visible = True
End If
End Sub

Formularze w aplikacji
Formularze są zwykle centralną częścią aplikacji Accessa. Nie inaczej jest, gdy używasz Accessa jako interfejsu do serwera
SQL. Możesz użyć formularzy w dwóch trybach – związanym i niezwiązanym.

Formularze związane
Jest możliwe oparcie formularzy na procedurach przechowywanych, jednak wtedy możliwy jest tylko odczyt. Jeżeli Twoi
użytkownicy są przyzwyczajeni do formularzy związanych, a ty chcesz użyć ich zamiast tabel połączonych, to nie ma nic
do zrobienia, poza napisaniem zapytania, które ograniczy ilość rekordów wyświetlanych na formularzu. Używając
formularza związanego opartego na procedurze przechowywanej i zapytaniu przekazującym powinieneś zmieniać parametry
procedury przed otwarciem formularza (identycznie jak na wydruku 16.2). Jeżeli masz dużą ilość danych lub chcesz modyfi-
kować dane, użyj ADO i formularzy niezwiązanych w sposób opisany w następnych częściach tego rozdziału.
289 Rozdział 16. ♦ Tworzenie interfejsu użytkownika dla Microsoft SQL Server

Formularze niezwiązane
Gdy używasz formularzy związanych, tracisz sporo czasu na ich obsługę, szczególnie w wypadku dołączonych tabel. W
czasie obsługi dołączonych tabel Jet musi zarządzać komunikacją ODBC. Dodatkowo tworzone są połączenia do bazy
oddzielnie do każdego formantu, co zużywa sporo czasu i pamięci na obsługę. Dobrą alternatywą jest zastosowanie
formularzy niezwiązanych. W niezwiązanych formularzach możesz zapytać użytkownika o klucz główny lub inną szukaną
wartość, a następnie otworzyć zestaw rekordów w ADO i wypełnić pola edycyjne znalezionymi wartościami, tak jak
pokazane jest na rysunku 16.11.

Rysunek 6.11.
Formularz
niezwiązany

Możesz wypełnić listę rozwijalną za pomocą kwerendy przekazującej opartej na procedurze przechowywanej i użyć kodu
przedstawionego na wydruku 16.5 do obsługi zdarzenia After Update.

Wydruk 16.5. Wypełnianie formularza zawarością obiektu recordset


Private Sub cboFind_AfterUpdate()
' Ta funkcja pobierze rekord, bazując na wartości klucza głównego
' i wypełni wartości w niezwiązanym formularzu

Dim conn As ADODB.Connection


Dim rst As ADODB.Recordset
Dim strSQL As String

On Error GoTo Proc_Err

DoCmd.Hourglass False

Set rst = New ADODB.Recordset


Set conn = New ADODB.Connection

' Tworzę wyrażenie SQL, bazując na aktualnej


' wartości pola listy rozwijalnej
strSQL = "Select * from Categories Where CategoryID=" & Me.cboFind

' Tworzenie połączenia ADO do serwera SQL


With conn
.Provider = "SQLOLEDB"
.ConnectionString = "data source=pawel;user id=sa;" & _
"initial catalog=NorthWindCS"

' Tryb tylko do odczytu


.Mode = adModeRead
.Open
End With

' Otwórz Recordset


rst.Open strSQL, conn

' Wypełnij wartości


Me.CategoryID = rst!CategoryID
Me.CategoryName = rst!CategoryName

' Zamknij połączenie


rst.Close
conn.Close

Set conn = Nothing


Set rst = Nothing

Proc_Exit:
DoCmd.Hourglass False
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Gdy zaczniesz tworzyć niezwiązane formularze, będziesz chciał zmieniać, kasować dane oraz wykonywać inne operacje w
ADO. Poniżej opiszemy, jak używać ADO oraz OLE DB dla serwera SQL.
Część V ♦ Access i architektura klient-serwer 290

Zaawansowane właściwości: dostawca OLE DB dla serwera SQL


Aby użyć dostawcy OLE DB dla serwera SQL, musisz upewnić się, czy jest on zainstalowany na komputerze. W trakcie
standardowej instalacji Accessa 2000 instalowany jest także dostawca OLE DB do SQL Server. Po zainstalowaniu
dostawcy możesz używać obiektu połączenia. Aby ustawić obiekt połączenia (ang.: connection), należy użyć składni
przedstawionej na wydruku 16.6.

Wydruk 16.6. Podłączanie do serwera SQL przez OLE DB


Sub SQLServer()
' Procedura podłączenia do serwera SQL

Dim conn As ADODB.Connection

Set conn = New ADODB.Connection

With conn
.Provider = "SQLOLEDB"
.ConnectionString = "data source=(local);" & _
"user id=sa;initial catalog=NorthWindCS"
.Mode = adModeRead
.Open
End With

MsgBox "Połączony z " & conn.Provider, vbInformation


End Sub

Następny zestaw wyników


Jedną z właściwości serwera SQL, której nie dało uzyskać się przy użyciu technologii Jet, jest wykonywanie dwóch
wyrażeń SQL jak jednego. Używając tej właściwości, możesz kilkakrotnie wykonywać wyrażenie SQL zwracające różne
zestawy rekordów, używając jednego obiektu Recordset. Aby to zrobić, użyj metody NextRecordset.

Wydruk 16.7. Użycie NextRecordset


Sub NextRst(strCustomerId As String)
' Użyj ALFKI lub ANTON dla przykładu
' Procedura używa jednego obiektu Recordset dwa razy

Dim cmd As ADODB.Command


Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim strSQL As String

Set conn = New ADODB.Connection


' Podłączenie do serwera SQL
With conn
.Provider = "SQLOLEDB"
.ConnectionString = "data source=(local);" & _
"user id=sa;initial catalog=NorthWindCS"
.Mode = adModeRead
.Open
End With

' Wyrażenie SQL zwracające dwa zestawy wyników


' Możesz to uruchomić tylko na serwerze, który
' wspiera wielokrotne zestawy wyników
strSQL = "Select * From Customers Where CustomerID=" & _
Chr(39) & strCustomerId & Chr(39)
strSQL = strSQL & vbNewLine
strSQL = strSQL & "Select * From Orders Where CustomerID=" & _
Chr(39) & strCustomerId & Chr(39)

Set cmd = New ADODB.Command

With cmd
.CommandText = strSQL
.ActiveConnection = conn
.CommandType = adCmdText
End With
Set rst = cmd.Execute

' Otwarcie pierwszego zestawu wyników


Do Until rst.EOF
Debug.Print rst!CompanyName
rst.MoveNext
Loop

' Pobierz następny zestaw


Set rst = rst.NextRecordset
Do Until rst.EOF
291 Rozdział 16. ♦ Tworzenie interfejsu użytkownika dla Microsoft SQL Server

Debug.Print rst!OrderDate
rst.MoveNext
Loop

rst.Close
conn.Close

Set rst = Nothing


Set cmd = Nothing
Set conn = Nothing
End Sub

Wykonywanie poleceń z parametrami


Wcześniej, w rozdziale 1., kładłem nacisk na korzyści z użycia procedur przechowywanych w aplikacji, wszędzie tam,
gdzie jest to możliwe, aby wykorzystać szybkość wykonania i zmniejszenie ruchu w sieci. Teraz gdy wykorzystujemy
ADO, użycie procedur przechowywanych daje te same korzyści. W ADO, gdy używasz obiektów poleceń dostawcy OLE
DB dla serwera SQL, można odwzorować ten obiekt na procedurę przechowywaną i przekazywać do niej parametry
poprzez obiekty parametrów. Jak większość rzeczy w ADO, można zrobić to na kilka sposobów. W dalszej części roz-
działu prześledzimy najczęstsze sposoby użycia procedur przechowywanych i obiektów poleceń, jednak musisz sam
stwierdzić, który najlepiej pasuje do Twojego stylu programowania. Ja postaram się przekazać moje komentarze, aby
pomóc Ci w tych wyborach.

Długa droga
Najlepiej rozpocząć od najbardziej pracochłonnej metody wykonywania procedur. Chociaż nikt nie będzie chciał pracować
w taki sposób, można nauczyć się kilku rzeczy. Po pierwsze, docenisz inne metody wykonywania procedur, a po drugie,
zrozumiesz zależności pomiędzy obiektami Connection, Command i Parameter, których będziesz używał w swoich
programach. Aby uruchomić polecenie z parametrem, musisz utworzyć obiekt Command i Parameter, a następnie
dołączyć obiekt Parameter do Command (patrz wydruk 16.8).

Wydruk 16.8. Wykonanie polecenia z parametrem


Sub ExecuteCommandwithParms()
' Procedura uruchamia procedurę przechowywaną z parametrami

Dim conn As ADODB.Connection


Dim cmd As ADODB.Command
Dim prm As ADODB.Parameter

Set conn = New ADODB.Connection

' Zestawienie połączenia z bazą danych


With conn
.Provider = "SQLOLEDB"
.ConnectionString = "data source=(local);" & _
"user id=sa;initial catalog=NorthWindCS"
.Open
End With

' Utworzenie i inicjalizacja obiektu Connection


Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = "byroyality"
.CommandType = adCmdStoredProc
End With

' Utworzenie i inicjalizacja obiektu parameter


Set prm = New ADODB.Parameter
With prm
.Name = "@percentage"
.Direction = adParamInput
.Type = adInteger
.Value = 50
End With
cmd.Parameters.Append prm

' Otwarcie obiektu Recordset z wykonanego polecenia


Dim rst As ADODB.Recordset
Set rst = cmd.Execute

' odczytanie wszystkich rekordów wyniku


Do Until rst.EOF
Debug.Print rst!au_id
rst.MoveNext
Loop
Część V ♦ Access i architektura klient-serwer 292

' Zakończenie
rst.Close
conn.Close
Set rst = Nothing
Set conn = Nothing
Set cmd = Nothing
Set prm = Nothing

End Sub

Użycie metody CreateParameters


Prostą metodą obsługi procedur przechowywanych bez pisania dużej ilości kodu jest użycie metody CreateParameter
obiektu Command. Metoda ta nie zmusza Cię do tworzenia obiektu dla każdego parametru aktualnego procedury
przechowywanej, co zmniejsza ilość kodu, szczególnie, jeżeli procedura ma wiele parametrów. Uważam tę metodę za
najmniej uciążliwą do programowania i najbardziej niezawodną do uruchamiania poleceń na SQL Server 6.5 i 7.0. Jak
widać na wydruku 16.9, użycie metody CreateParameter tworzy obiekty parametrów bez dodatkowego kodu.

Wydruk 16.9. Wykonanie polecenia bez obiektu parametru


Sub ExecuteCommandwithCreateParms()
' Wykonanie procedury przechowywanej
' przy użyciu metody CreateParameter

Dim conn As ADODB.Connection


Dim cmd As ADODB.Command

Set conn = New ADODB.Connection

' Zestawienie połączenia z bazą danych


With conn
.Provider = SQLOLEDB
.ConnectionString = "data source=(local);" & _
"user id=sa;initial catalog=NorthWindCS"
.Open
End With

' Utworzenie i inicjalizacja obiektu Connection


Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = "byroyality"
.CommandType = adCmdStoredProc

' Utworzenie informacji parametrów


' używamy metody CreateParameter obiektu
' command, aby uprościć program
.Parameters.Append .CreateParameter("@Percentage", _
adInteger, adParamInput, , 50)
End With

' Otwarcie wyniku wykonania procedury


Dim rst As ADODB.Recordset
Set rst = cmd.Execute

' Odczytanie wszystkich rekordów wyniku


Do Until rst.EOF
Debug.Print rst!au_id
rst.MoveNext
Loop

' Zakończenie
rst.Close
conn.Close
Set rst = Nothing
Set conn = Nothing
Set cmd = Nothing

End Sub

Użycie Refresh
Użycie metody Refresh ze zbioru parametrów obiektu Command jest bardzo podobne do użycia metody
CreateParameter, poza tym, że nie musisz tworzyć żadnego obiektu parametru. Zamiast tego, po podłączeniu do bazy
ustawiasz obiekt Command na procedurę przechowywaną i odświeżasz zbiór parametrów. Operacja ta zwróci zbiór
parametrów gotowych do wypełnienia. Metoda ta pozwala na dużą elastyczność (można tworzyć ogólne obiekty poleceń),
jednak na razie na 100 procent działa jedynie z SQL Server 7.0. Używając SQL Server 6.5, napotkałem kilka problemów,
które spowodowały, że poczekam z użyciem Refresh na następne wersje ADO. Nawet mimo tych ograniczeń powinieneś
293 Rozdział 16. ♦ Tworzenie interfejsu użytkownika dla Microsoft SQL Server

poznać składnię i sposób użycia metody Refresh do użycia z SQL Server 7.0 i kolejnymi wersjami ADO. Ważną rzeczą,
o której należy pamiętać, jest to, że program wykonuje dodatkowe operacje na bazie danych w czasie wykonania metody
Refresh, aby odczytać informacje o parametrach. Mimo prostoty użycia należy zawsze sprawdzić wydajność tego
rozwiązania.

Wydruk 16.10. Użycie metody Refresh obiektu Command


Sub ExecuteCommandwithParmRefresh()
' Wykonanie procedury przechowywanej bez tworzenia
' obiektów Parameter. Pomocne przy procedurach
' z dużą ilością parametrów

Dim conn As ADODB.Connection


Dim cmd As ADODB.Command

Set conn = New ADODB.Connection

' Zestawienie połączenia z bazą danych


With conn
.Provider = SQLOLEDB
.ConnectionString = "data source=(local);" & _
"user id=sa;initial catalog=NorthWindCS"
.Open
End With

' Utworzenie i inicjalizacja obiektu Connection


Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = "byroyality"
.CommandType = adCmdStoredProc

' W tym przykładzie używamy metody Refresh,


' która pobiera parametry z serwera.
' Po jej wykonaniu wypełniamy parametry
' i wykonujemy procedurę. Unikamy tworzenia
' i dołączania parametrów
.Parameters.Refresh
.Parameters("@Percentage").Value = 50
End With

' Otwarcie wyniku wykonania procedury


Dim rst As ADODB.Recordset
Set rst = cmd.Execute

' Odczytanie wszystkich rekordów wyniku


Do Until rst.EOF
Debug.Print rst!au_id
rst.MoveNext
Loop

' Zakończenie
rst.Close
conn.Close
Set rst = Nothing
Set conn = Nothing
Set cmd = Nothing

End Sub

Obsługa zwracanych wartości


Czasami procedura przechowywana zwraca wartość, która świadczy o prawidłowym lub nieprawidłowym wykonaniu
procedury. Może ona również zwrócić wartość identyfikatora nowo dodanego rekordu. W każdym wypadku będziesz
chciał znać wartość zwracaną. ADO pozwala na pobranie wartości zwracanych poprzez odczytanie zbioru parametrów po
wykonaniu polecenia. Na wydruku 16.11 przedstawiony jest program, który wykonuje bardzo prostą procedurę
przechowywaną, zwracającą po prostu wartość 55. Procedura wygląda następująco:
CREATE PROCEDURE sp_CmdWithParm AS
/* Wartość zwracana */
Return 55

Po wykonaniu polecenia możesz odczytać wartość zwracaną z zestawu parametrów, po użyciu metody Refresh (popatrz
poprzedni akapit), identyfikując ją przez numer kolejny wartości zwracanej, tak jak tutaj:
cmd.Parameters(0).Value

Wydruk 16.11. Pobieranie wartości zwracanej


Sub CommandReturnValues()
' Procedura uruchamia procedurę przechowywaną
' i odczytuje zwracaną wartość
' Treść procedury przechowywanej:
Część V ♦ Access i architektura klient-serwer 294

' CREATE PROCEDURE sp_CmdWithParm AS


' /*Wartość zwracana*/
' Return 55
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command

Set conn = New ADODB.Connection


Set cmd = New ADODB.Command

' Zestawienie połączenia z bazą danych


With conn
.Provider = SQLOLEDB
.ConnectionString = "data source=(local);" & _
"user id=sa;initial catalog=NorthWindCS"
.Open
End With

' Utworzenie i inicjalizacja obiektu command


With cmd
.ActiveConnection = conn
.CommandText = "sp_CmdWithParm"
.CommandType = adCmdStoredProc
.Parameters.Refresh
End With

cmd.Execute
MsgBox "Wartość zwracana: " & cmd.Parameters(0).Value

conn.Close
Set conn = Nothing

End Sub

Wykonanie procedury bez obiektu Command


Procedury z parametrami, które zwracają wiersze tabeli, można uruchomić bez używania obiektu Command. Aby to
wykonać, należy utworzyć wyrażenie SQL i użyć metody open obiektu Recordset.
rst.open 'exec sp_SimpleProc @OrderID=1', conn

Użycie klasy Connection


Gdy Twoja aplikacja coraz bardziej zależy od napisanego kodu, powinieneś zacząć przyzwyczajać się do pisania kodu
ogólnego i nadającego się do powtórnego użycia. W tej książce postaram się pokazać Ci możliwie dużo przykładów
programowania klas. Tworzenie obiektu klasy Connection jest jednym z najważniejszych przykładów, które chciałbym Ci
pokazać. Jest to klasa do natychmiastowego użycia nie tylko w Accessie, ale także w każdym programie obsługującym
VBA, włączając inne aplikacje Office 2000 oraz Visual Basic 5 i 6.

Gdy programujesz w ADO, powinieneś przyzwyczaić się do korzystania z klasy Connection. Na podstawie tej ogólnej
klasy tworzy się obiekt połączenia ADO. Gdy cały kod odpowiedzialny za dostęp do danych opiera się na tej szczególnej
klasie tworzącej połączenie do bazy, musisz utrzymywać małe fragmenty kodu odpowiedzialne za informacje o połączeniu.

W tym rozdziale utworzysz prostą klasę DBConnection, która będzie miała jedną publiczną metodę, Connect. Connect
jest prostą funkcją VBA, która zwraca obiekt ADO Connection. Funkcja zamieszczona na wydruku 16.12 tworzy obiekt
ADO Connection i ustawia wartość zwracaną na utworzony obiekt (Klasa Connection jest bardzo prosta. Możesz
rozszerzyć ją tak, aby używała pliku UDL, jak jest opisane w rozdziale 7. „Zaawansowane ADO”).

Wydruk 16.12. Prosta klasa Connection


Function Connect() As ADODB.Connection
' Komponent do wielokrotnego użycia. Tworzy połączenie
' z bazą danych. Możesz użyć tego komponentu, aby
' zcentralizować miejsce, gdzie są ustawiane informacje o
' bazie danych

Dim conn As ADODB.Connection


Set conn = New ADODB.Connection

' Informacje o połączeniu się z bazą


With conn
.Provider = "SQLOLEDB"
.ConnectionString = "data source=(local); user id=sa;" & _
"initial catalog=airline"
.Open
End With
295 Rozdział 16. ♦ Tworzenie interfejsu użytkownika dla Microsoft SQL Server

Set Connect = conn


End Function

Użycie klasy Connection w aplikacji


Użycie klasy Connection w aplikacji jest proste. Gdziekolwiek chcesz podłączyć się do bazy danych, tworzysz obiekt
DBConnection, aby utworzył dla Ciebie obiekt ADO Connection, jak widać to na wydruku 16.13. Pozwoli to na ukrycie
specyficznego dla procesu połączenia kodu w ogólnej nadającej się do powtórnego wykorzystania klasie lub obiekcie COM
do późniejszego wykorzystania.

Wydruk 16.13. Użycie klasy Connection


Sub UseConnect()
' Używa komponentu Connection, aby podłączyć się do bazy

Dim conn As ADODB.Connection


Dim oConnect As DBConnection

Set oConnect = New DBConnection


Set rst = oConnect.Connect

End Sub
Rozdział 17.
Interfejs Accessa 2000
do Oracle'a
W tym rozdziale:
u Dostęp do danych Oracle'a przez Accessa
u Funkcje w Oracle'u i Accessie
u Poznajemy widoki i procedury przechowywane
u Tworzenie niezwiązanego interfejsu do Oracle'a

Na przekór dominacji Oracle'a w aplikacjach tworzonych w Accessie jest mało publikacji na temat ich współpracy. W
rozdziale tym chcę wypełnić tę lukę.

Mimo że nowe projekty ADP zapewniają możliwość tworzenia wyrafinowanych aplikacji klient-serwer, w wielu
przypadkach musisz użyć bogatego środowiska programowania zwykłej aplikacji Accessa. Na przykład w wypadku, gdy
tworzysz prototyp aplikacji lub chcesz skorzystać z możliwości zarządzania heterogenicznymi danymi.

Oracle jest wyjątkowo potężną i wyrafinowaną bazą danych, więc w tym rozdziale nie możemy przedstawić wszystkich
niuansów i jej złożoności. Mimo to, poprzez poznanie prostych technik i wytycznych, możesz wyzwolić jej siłę bez
specjalnych kłopotów.

Zasadniczo, dobre programowanie Access/Oracle wymaga użycia mechanizmów Oracle'a i pozwolenia mu na zarządzanie
danymi, ponieważ właśnie to robi świetnie. Może to brzmi dziwnie, ale w praktyce nie jest to tak proste do zrealizowania.
Wielu programistów Accessa zostało zobligowanych do użycia Oracle'a w swoich aplikacjach i często nie inwestują zbyt
wiele czasu w udoskonalanie struktury bazy danych, tak jak robią to przy projektowaniu dla Accessa. Często muszą
używać mniej optymalnych struktur danych lub hurtowni danych. Dodatkowo, wielu programistów Accessa uważa się za
zwolnionych z użycia w swoich aplikacjach czegokolwiek więcej z Oracle'a, niż ODBC i konto użytkownika. W rozdziale
tym prześledzimy sposoby ominięcia takich wyzwań, jak również użycia podstawowych narzędzi Oracle'a, które
niewielkim nakładem pracy mogą Ci służyć.

Dostęp do danych Oracle'a przez Accessa


Istnieje kilka sposobów dostępu do danych Oracle'a przez Accessa. W tym rozdziale skupimy się na dwóch: podstawowych
technikach ODBC bez programowania dla ODBC oraz programowaniu z użyciem ADO. W czasie powstawania aplikacji
możesz korzystać z obu sposobów, jednak w gotowej aplikacji powinieneś używać tylko jednego.

Dwie podstawowe techniki dostępu do danych są stosowane na trzy sposoby:


u Łączenie tabel (ODBC).
u Kwerendy przekazujące (SPT) (ODBC).
u Bezpośrednie połączenie poprzez ADO.
297 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

Tabele połączone
Ponieważ w Accessie bardzo prosto tworzy się tabele połączone pochodzące z wielu źródeł danych, większość danych
Oracle'a pochodzi z tych właśnie tabel. Tabele połączone używają ODBC, pomimo tego, że podstawowym modelem
dostępu do danych w Accessie 2000 jest ADO. Powoduje to konieczność instalowania na komputerze zarówno
sterowników ODBC, jak i ADO.

Aby utworzyć połączenie z tabelą Oracle'a, musisz posiadać:


u Zgodny z Oracle'em sterownik ODBC.
u Połączenie sieciowe z bazą Oracle poprzez SQLNet lub Net8 (Oracle używa własnego protokołu sieciowego). Bez
tych narzędzi nie będziesz w stanie połączyć się z bazą.
u Sterownik ODBC w Accessie.

Poprzez ODBC możesz: połączyć się do bazy, pracować z tabelami, widokami i procedurami oraz wysyłać do wykonania
wyrażenia SQL.

Tworzenie ciągu połączenia ODBC


Zarządca ODBC na komputerze klienta komunikuje się pomiędzy Twoim programem a odpowiednim dla Twojego
źródła danych sterownikiem ODBC. Aby podłączyć się do bazy Oracle, powinieneś najpierw utworzyć odpowiedni ciąg
połączenia ODBC. Ciąg ten składa się z części przedstawionych w tabeli 17.1.

Ciąg ODBC może wyglądać następująco:


ODBC;DSN=MSOracleDriver;UID=Scott;SERVER=empexample;;TABLE=SCOTT.DEPT

Każda część ciągu może być opuszczona, więc jeżeli ciąg nie będzie zawierał potrzebnych informacji, użytkownik będzie
musiał je podać.

Tabela 17.1.
Składniki ciągu połączeniowego ODBC

Składnik Opis
DSN Nazwa źródła danych
UID Nazwa użytkownika
PWD Hasło
Database Jeśli nazwa DSN nie jest nazwą bazy, należy tutaj wpisać nazwę bazy
APP Nazwa aplikacji używającej połączenia

Tworzenia nazwy źródła danych


Aby przygotować ODBC do pracy z Accessem, powinieneś utworzyć nazwę źródła danych. Jest to bardzo prosta operacja.
Poniższe punkty wskażą sposób utworzenia DSN dla Oracle'a.
82. Uruchom administrator ODBC z Panelu sterowania.
83. W programie administratora naciśnij przycisk Nowy, aby dodać źródło danych dla Oracle'a.
84. Wybierz Oracle ODBC Driver, Microsoft ODBC Driver dla Oracle'a lub inny sterownik ODBC dla Oracle'a.
Naciśnij Zakończ. W tym miejscu będziesz zapytany o informacje w okienku podobnym do okna z rysunku 17.1.
Wygląd tego okna zależy od wybranego sterownika i jego wersji.
Część V ♦ Access i architektura klient-serwer 298

Rysunek 17.1.
Wpisywanie
informacji o DSN

Po utworzeniu DSN można rozpocząć dołączanie tabel Oracle'a do twojej aplikacji.

Koszt połączenia z Oracle'em


Tworzenie połączenia z bazą danych Oracle zajmuje dużo więcej czasu i zasobów niż połączenie z bazą Jet. W czasie
programowania z użyciem ODBC, RDO, DAO, ODBC Direct lub ADO powinieneś spróbować trzymać cały czas otwarte
połączenie do bazy

i używać go w aplikacji. Access zajmie się tym, jeżeli połączysz tabelę z Oracle'em. Trzyma on wtedy otwarte połączenie,
a Ty możesz go użyć poprzez obiekt Table. Rysunek 17.2 przedstawia, jak można na podstawie tabeli połączonej
zbudować kwerendę.

Rysunek 17.2.
Buduj kwerendy
na tabelach
połączonych
identycznie jak na
tabelach lokalnych

SELECT SCOTT_EMP.ENAME, SCOTT_DEPT.DNAME


FROM SCOTT_DEPT INNER JOIN SCOTT_EMP ON SCOTT_DEPT.DEPTNO=
SCOTT_EMP.DEPTNO
WITH OWNERACCESS OPTION;

Lecz takie podejście jest kosztowne. Gdy uruchamiasz kwerendę na tabeli połączonej, Twoje zapytanie SQL jest zapisane
w Accessie, więc Oracle nie wie nic o nim. Sterownik ODBC i Jet muszą zanalizować wyrażenie. Sterownik ODBC
analizuje kwerendę i może wysłać przetworzony fragment Twojego zapytania do Oracle'a, zwykle przetwarzając jedną
tabelę. Zwykle kończy się to tym, że Oracle wysyła ogromne ilości danych przez sieć do komputera klienta, gdzie są one
przetwarzane przez Jet. Ponieważ Jet jest jedyną częścią tego łańcucha, która rozumie naszą kwerendę, całe przetwarzanie
odbywa się na komputerze klienta. Może być to niezbędne od czasu do czasu, ale nie jest to działanie prawdziwego
systemu klient-serwer.

Jeżeli chcesz przeglądać dane lub analizować strukturę tabel, a nie masz narzędzi Oracle'a, tworzenie tabel połączonych
jest dobrym sposobem. Łączenie jest również dopuszczalne, jeżeli chcesz dostać dane, które pozostaną w lokalnej tabeli,
lub chcesz zadać pytanie do danych pochodzących z wielu źródeł danych (kwerenda heterogeniczna). Jednak, jeżeli
zadajesz homogeniczne pytanie do danych Oracle'a, powinieneś pomyśleć o innym podejściu.

Kwerendy przekazujące (SPT)


Poprzez użycie tego samego połączenia, którego używasz do łączenia tabel, otrzymujesz dostęp do serwera Oracle i
przenosisz ciężar wykonania kwerendy na serwer – tam, gdzie powinna być wykonana. Oczywiście w SPT wszystkie
źródła danych, do których odwołujesz się w kwerendzie, muszą znajdować się w bazie Oracle oraz wyrażenia SQL muszą
być zapisane w dialekcie Oracle, jednak są to małe problemy, jeżeli skonfrontuje się je ze skróconym czasem odpowiedzi
oraz zmniejszonym ruchem w sieci. W kwerendach SPT jedyną informacją, jaką przesyłasz poprzez sieć, jest wyrażenie
SQL, a jedyną jaką otrzymujesz jest wynik.
299 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

Aby utworzyć SPT, wykonaj następujące czynności:


85. Utwórz nową kwerendę.
86. Z menu Kwerenda wybierz Tylko SQL.
87. Wybierz Przekazująca.
88. W widoku SQL edytora kwerend (dostępny tylko tryb projektowania) wybierz Widok i Właściwości.
89. Wpisz ciąg połączeniowy ODBC do właściwości Ciąg połączenia ODBC.
Ciąg ODBC powinien wyglądać podobnie do takiego:
ODBC;DSN=EmpExample;UID=SCOTT;PWD=tiger;DBQ=empexample;

Możesz skopiować ciąg z tabeli połączonej.

90. Wpisz wyrażenie SQL.

Przykładowe wyrażenie SQL wygląda następująco:


Select * from emp

W czasie wykonania, Access wysyła to wyrażenie SQL bezpośrednio do Oracle'a poprzez połączenie ODBC. Jet nie jest
zaangażowany w jego wykonanie. Oracle odbiera to wyrażenie i po wykonaniu odsyła wynik (jeśli istnieje) do klienta.

Niektóre sytuacje gdzie mogą być użyte SPT to:


u Wykonanie wyrażeń SQL zmieniających strukturę bazy.
u Uzyskanie wybranych wierszy i kolumn z tabel Oracle'a.
u Sprawdzenie ilości wierszy zmienionych wyrażeniem Update.
u Dostarczenie źródła rekordów dla prostego formularza związanego pokazującego małą ilość rekordów.
u Utworzenie, zmiana i wykonanie widoków i procedur przechowywanych w Oracle'u.

Powinieneś zawsze sprawdzić, czy zastosowanie kwerend SPT ulepszy Twoją aplikację.

Określanie właściwości kwerend przekazujących


Gdy tworzysz kwerendę przekazującą, musisz ustawić właściwość kwerendy, która określa, czy zwraca ona rekordy, czy
nie. Kwerendy, które wstawiają, zmieniają lub kasują rekordy, nie zwracają rekordów, natomiast kwerendy typu Select
zwykle to robią. Jeżeli nie ustawisz odpowiednio tej właściwości, dostaniesz komunikat błędu.

Składnia kwerend przekazujących


Musisz pisać wyrażenia SQL zgodnie ze składnią Oracle'a, która różni się znacznie od składni generowanej przez tabelkę
QBE. Access 2000 obsługuje dialekt SQL, który najbardziej odpowiada standardowi ANSI-92, lecz jeżeli używałeś SQL
Accessa począwszy od wersji 1.1, przegląd różnic pomoże Ci efektywnie używać bazy Oracle.

Oracle nie wymaga zakańczania wyrażenia średnikiem, gdy tworzymy kwerendę przekazywaną, mimo że jest on
wymagany w trakcie wykonywania zapytań z programu SQL Plus. Średnik na końcu wyrażenia SQL spowoduje błąd.

Nie można używać nawiasów kwadratowych do identyfikacji nazw tabel i kolumn. Ich użycie spowoduje błąd.

Mimo że Access zmienia kropkę z SCOTT.EMP na podkreślenie w SCOTT_EMP w trakcie łączenia tabeli, musisz
użyć separatora Oracle, którym jest kropka.

Wielkość liter
Wyrażenia SQL w Oracle'u mogą być pisane zarówno dużymi, jak i małymi literami oprócz porównywanych w frazie
Where wartości. Poniższe dwa wyrażenia są takie same:
Select eName, job FroM eMP
SELECT ENAME, JOB FROM EMP

Tylko pierwsze z dwóch poniższych wyrażeń zwróci prawidłową wartość:


Część V ♦ Access i architektura klient-serwer 300

Select ename, job from EMP where JOB='MANAGER'


Select ename, job from EMP where JOB='manager'

Wyrażenie Select
Słowo kluczowe Select działa tak samo jak w Accesie. Select wskazuje bazie Oracle, które pola (kolumny) zwrócić
jako wynik. Nazwy kolumn wymienione po słowie Select muszą istnieć w tabelach wymienionych w następnej klauzuli
From.
SELECT ename, job, hiredate ...

Tabele lub widoki użyte w kwerendzie są wymieniane w klauzuli From, identycznie jak w Accessie. Również identycznie
jak w Accessie kolejność tabel w liście nie wpływa na wynik zapytania.
Select ename, job, hiredate FROM emp

Klauzula WHERE
Klauzula Where sprawia większości programistom Accessa sporo problemów na początku pracy z bazą Oracle, ponieważ
skupia się tutaj większość różnic pomiędzy SQL Accessa i SQL Oracle. W Oracle'u klauzula Where nie tylko ogranicza
ilość rekordów zwracanych przez serwer, jak to jest w Accessie, ale także definiuje zależności pomiędzy tabelami i
widokami użytymi w zapytaniu.

W tych przykładach znajomych dla większości programistów Accessa klauzula Where ogranicza rekordy w wyniku:
Select * from Emp WHERE mng=7698
Select * from EMP WHERE HIREDATE between '1/1/1990' and '1/1/1995'
Select * from EMP WHERE ename like 'M%'

Definiowanie zależności
Gdy w kwerendzie występuje więcej niż jedna tabela, klauzula Where w Oracle'u definiuje zależności.
SELECT emp.ename, dept.dname
FROM emp, dept
WHERE (emp.deptno=dept.deptno) AND (emp.ename like 'M%')

Pokazane powyżej wyrażenie zwraca rekordy, które mają te same wartości po obu stronach relacji zdefiniowanej przez
pola podane w klauzuli Where (emp.deptno=dept. deptno). Aby zwrócić rekordy, które nie są reprezentowane z obu
stron relacji, musisz utworzyć połączenie typu outer join. W Oracle'u połączenie takie tworzy się poprzez wstawienie znaku
(+) po tej stronie relacji, która będzie zwracała wartości null, gdy nie ma odpowiadającej wartości. Dobrze jest zapamiętać,
że wstawia się znak (+) po tej stronie, która zawierać będzie dodatkowe puste pozycje. Wyrażenie poniżej zawiera
połączenie typu outer join z lewej strony relacji. Wyświetli ono wszystkich pracowników, którzy mają przypisaną lub nie
nazwę oddziału.
SELECT emp.ename, dept.dname
FROM emp, dept
WHERE emp.deptno(+)=dept.deptno

Relacje w Oracle'u mogą być zapisywane jako wyrażenia. Nie jest to możliwe w Accessie. Użycie wyrażeń w relacjach nie
jest częste. Może być to potężne narzędzie, gdy pracujemy na nieoptymalnych strukturach danych lub w danych występują
szczególne zależności, co zdarza się w hurtowniach danych. Wyrażenie SQL poniżej przedstawia sposób użycia wyrażenia
w relacji.
Select emp.ename, dept.dname
From emp, dept
Where (emp.deptno=dept.deptno+10)

Użycie znaków specjalnych


Access używa * i ? jako znaków specjalnych. Gwiazdka (*) zastępuje dowolną ilość znaków w tekście, natomiast znak
zapytania – jeden znak. W Oracle'u istnieją te same możliwości, ale używamy znaku % zamiast *, a _ zastępuje jeden znak.
Znaki te mogą być używane w następujący sposób:
Select * from emp where ename like 'M%'
Select * from emp where ename like 'J__S'

Użycie Null i Not Null


W Oracle'u testowanie wartości null odbywa się identycznie jak w Accessie.
301 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

SELECT * FROM emp WHERE comm IS NULL


SELECT * FROM emp WHERE comm IS NOT NULL

Tworzenie wyrażeń Insert


W Accessie kwerenda wstawiająca nowe wartości do tabeli generuje wyrażenie SQL, które wygląda następująco:
INSERT INTO SCOTT_EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
SELECT '9999' AS Expr1, 'JP' AS Expr2, 'SALESMAN' AS Expr3, _
7698 AS Expr4, #7/27/1997# AS Expr5, 2380 AS Expr6, 10 AS Expr7;

Jednak Access dopuszcza klauzulę Values tak samo jak Oracle (patrz poniżej), ale musisz ją wpisać samemu.

W Oracle'u możesz uprościć to wyrażenie:


INSERT INTO SCOTT_EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, _
COMM, DEPTNO)
VALUES ('9999', 'JP', 'SALESMAN', 7698, _
TO_DATE('7/27/1997', 'MM/DD/YYYY'), 2380, 0, 10)

Zwróć uwagę jak w Oracle'u używa się To_Date(), aby sprawdzić, czy wpisana data jest prawidłowa. Więcej o tej i
innych funkcjach Oracle'a napisałem w dalszej części rozdziału.

Tworzenie wyrażeń Update


Implementacja wyrażenia Update w SQL Oracle nie różni się wiele od tej z Accessa. Poniżej przedstawione jest wyrażenie
SQL, wygenerowane przez QBE Accessa, skojarzone z tabelą połączoną.
UPDATE SCOTT_EMP
SET SCOTT_EMP.SAL = [7000]
WHERE ((([SCOTT_EMP].[EMPNO])=9999));

Wersja dla Oracle'a jest prostsza od wersji Accessa o kilka nawiasów. Ponieważ ODBC wysyła ciąg ODBC bezpośrednio
do tabel użytkownika Scott, nie ma potrzeby kwalifikować nazw tabel nazwą użytkownika.
UPDATE emp
SET SAL = 7000
WHERE empno=9999

Użycie Group By/Having


QBE Accessa samo troszczy się o prawidłową składnię, gdy tworzysz kwerendę grupującą. W Oracle'u musisz sam się tym
zająć zająć. Tak jak w Accessie, Group By grupuje dane w wymienionych kolumnach. Wszystkie inne kolumny muszą
być przeglądane poprzez funkcje agregujące (np.: Sum(), Avg() i inne).
SELECT deptno, count(*)
FROM emp
WHERE deptno<>10
GROUP BY deptno
HAVING count(*)<6

Podczas wykonania powyższego wyrażenia Oracle pobierze wszystkie rekordy z wartością pola deptno różną od 10 i
grupuje je według pola wymienionego w operacji GROUP BY. Na koniec Oracle przeszukuje rezultat i odrzuca rekordy,
których liczba (count(*)) jest większa od 6. Jedyną różnicą pomiędzy tym wyrażeniem SQL a wyrażeniem w SQL
Accessa jest występowanie nawiasów.

Funkcje w Oracle'u i Accessie


W Accessie, przed wykonaniem kwerendy jest ona przeszukiwana pod kątem występowania funkcji zarówno VBA, jak i
utworzonych przez Ciebie. Analizator wyrażeń (ang. Jet Expression Service) dopuszcza stosowanie dowolnych funkcji w
wyrażeniach SQL. Nie możesz jednak stosować funkcji VBA oraz napisanych przez siebie, gdy używasz kwerend SPT.
Powód jest prosty, SPT nie używa w ogóle silnika Jet. Oracle odbiera SQL jako ciąg znaków i musi on być zrozumiały dla
Oracle'a. Mimo że jest możliwe utworzenie w Oracle'u podobnego zestawu funkcji jak w Accessie, wykracza to jednak
poza ramy tego rozdziału.

W dalszej części rozdziału zrobimy przegląd niektórych, najczęściej używanych funkcji Oracle'a, które możesz użyć w
kwerendach przekazujących.

Wiele z funkcji udostępnianych przez Oracle jest bardzo podobnych do funkcji operujących na ciągach w Accessie. Poniżej
przedstawię funkcje, które nie istnieją w Accessie, lub działają inaczej niż podobne do nich. Aby uzyskać pełną listę
funkcji, sięgnij do dokumentacji Oracle'a.
Część V ♦ Access i architektura klient-serwer 302

Ciągi
Większość typów danych, z którymi się spotykasz, to ciągi lub takie, które da się zamienić na ciągi. Zwykle będziesz chciał
przeszukiwać ciągi znaków, analizować je, zmieniać wielkość liter, łączyć lub inaczej mówiąc zmieniać je tak, aby
pasowały do twoich formularzy i raportów. W tej części opiszę niektóre z powszechnie używanych operacji na ciągach
znaków, które będziesz chciał wykonać w Oracle'u.

Łączenie
Oracle łączy ciągi znaków przy użyciu dwóch pionowych kresek (||) w odróżnieniu od Accessa, w którym używa się
znaku & lub +. Poniższe wyrażenie przedstawia w jaki sposób, łączyć ciągi.
SELECT ename || deptno
FROM emp

Initcap, Lower, Upper


Funkcja Initcap(string) zmienia na wileką pierwszą literę każdego wyrazu ciągu.

Podobnie Upper i Lower zmienia wszystkie litery ciągu na odpowiednio wielkie i małe.

Select INITCAP(ename)
FROM emp
Zwróci następujący wynik:
INITCAP(ENAME)
----------
Jp
Allen
Ward
Jones
Martin
Blake
Clark
Scott
King
Turner
Adams
James
Ford
Miller

SELECT UPPER(ENAME)
FROM emp
Zwróci następujący wynik:
UPPER(ENAME)
----------
JP
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER

SELECT LOWER(ename)
FROM emp
Zwróci następujący wynik:
LOWER(ENAME)
----------
jp
allen
ward
jones
martin
blake
clark
scott
king
turner
adams
303 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

james
ford
miller

Instr
Instr zwraca pozycję znaku, który podałeś jako argument i może być bardzo przydatna, jeżeli chcesz analizować ciągi,
poszukując przecinków lub spacji. Jeżeli poszukiwany znak nie występuje w ciągu, zwracana jest wartość 0. Funkcja
Instr jest wrażliwa na wielkość liter w odróżnieniu od Accessa.

Instr ma cztery parametry:

u String – wymagany. Ciąg znaków lub odwołanie do ciągu, który chcesz przeszukać.

u Set – wymagany. Znak lub ciąg znaków, które chcesz znaleźć.

u Start – nieobowiązkowy. Pozycja, na której powinno się rozpocząć szukanie. Domyślnie jest to pierwsza
pozycja.
u Occurrence – nieobowiązkowy. Jeżeli chcesz znaleźć drugie lub trzecie wystąpienie parametru Set, wpisz 2 lub
3.

Popatrz na wyrażenie SQL, w którym nie podamy wystąpienia ani pozycji startowej:
Select ename, instr(ename, 'A') from emp

Wynik:
ENAME INSTR(ENAME,'A')
---------- ----------------
JP 0
ALLEN 1
WARD 2
JONES 0
MARTIN 2
BLAKE 3
CLARK 3
SCOTT 0
KING 0
TURNER 0
ADAMS 1
JAMES 2
FORD 0
MILLER 0

Gdy funkcja zostanie wywołana z parametrem Occurence równym 2, znajdzie drugie wystąpienie szukanego znaku.
Select ename, instr(ename, 'A') from enp

ENAME INSTR(ENAME,'A')
---------- ----------------
JP 0
ALLEN 0
WARD 0
JONES 0
MARTIN 0
BLAKE 0
CLARK 0
SCOTT 0
KING 0
TURNER 0
ADAMS 3
JAMES 0
FORD 0
MILLER 0

LTrim/RTrim
Access ma trzy funkcje do wycinania znaków z ciągu: LTrim(), aby usunąć znaki z lewej strony, Rtrim, aby usunąć
znaki z prawej strony oraz Trim, aby usunąć znaki z obu stron. Oracle ma tylko Ltrim i Rtrim. Jednak funkcje obcinające
znaki w Accessie i Oracle'u różnią się w inny, bardzo ważny sposób.

W Accessie funkcje te obcinają tylko spacje, w Oracle'u mogą obcinać dowolny zbiór znaków.

Funkcje obcinające mają dwa argumenty:


u String – wymagany. Ciąg lub odwołanie do ciągu, na którym chcesz wykonać operacje.

u Set – nieobowiązkowy. Znaki, które chcesz usunąć.


Część V ♦ Access i architektura klient-serwer 304

Możesz użyć funkcji LTrim/RTrim, aby usunąć słowo 'THE' z początku tytułów poprzez wykonanie następującego
wyrażenia:
Select LTrim(Title, '"THE ') from Books

Należy pamiętać, że funkcje RTrim/LTrim są niewrażliwe na wielkość liter i ignorują kolejność podanych znaków do
usunięcia. Oznacza to, że tytuły książek zostaną zmienione w sposób pokazany w tabeli 17.2.

Tabela 17.2.
Przed i po obcięciu funkcją LTrim

Przed Po obcięciu
The Great Access Book Great Access Book
How to Develop in Access Ow to Develop in Access
The Ethical Developer ical Developer
Access 2000 Development Unleashed Access 2000 Development Unleashed

Funkcje LTrim/RTrim nie zwracają uwagi na kolejność liter w zbiorze liter do usunięcia ani na to, że powtarza ją się kilka
razy (tak jak: THE ETH... w The Ethical Developer). Aby uzyskać prawidłowe wyniki powinieneś prawdopodobnie użyć
kombinacji tej funkcji z Instr, Substr i Decode, aby dostać wyniki, jakich naprawdę potrzebujesz.

Soundex
Od roku 1988 Census Bureau używa algorytmu klasyfikacji nazwisk, które są podobnie wymawiane (w języku
angielskim). Algorytm ten nazywany jest Soundex. Działa on przez pobranie pierwszej litery i przypisanie liczby do każdej
następnej spółgłoski. Różne spółgłoski mają przyporządkowane te same wartości (na przykład [T] i [D] są tłumaczone na
3), oparte o ich brzmienie. Proces ten jest powtarzany aż do skompletowania 4. cyfrowego kodu. Słowa, które mają za mało
spółgłosek – są uzupełniane zerami tak, aby wygenerować czteroznakowy kod. Samogłoski są odrzucane, chyba że jest ona
pierwszym znakiem w słowie. Kody Soundex wyglądają następująco:
Select ename, soundex(ename) from emp
ENAME SOUNDEX(ENAME)
---------- --------------
JP J100
ALLEN A450
WARD W630
JONES J520
MARTIN M635
BLAKE B420
CLARK C462
SCOTT S300
KING K520
TURNER T656
ADAMS A352
JAMES J520
FORD F630
MILLER M460

Soundex może być użyteczny do wyszukiwania nazwisk w listach lub tytułach. Wyrażenie SQL takie jak poniżej:
Select ename from emp where soundex(ename) like soundex('muller')

powinno zwrócić nazwiska takie jak:


Mailer
Miller
Molar
Moller
Muler
Mulronsky

Funkcja Soundex nie interpretuje kontekstu znaków, więc niektóre wyniki mogą nie być intuicyjne na pierwszy rzut oka.
Słowa o różnej długości mogą sobie odpowiadać według tego algorytmu. Mimo tych niedogodności można go użyć do
przeszukiwania list wysyłkowych i książek telefonicznych.

Substr
Substr można porównać do funkcji Mid w Accessie. Oracle nie ma bezpośredniego odpowiednika funkcji Right() i
Left() znanych z Accessa. Tak jak funkcja Accessa Mid(), Substr() pobiera trzy argumenty:

u String – ciąg lub odwołanie do ciągu


305 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

u Start – podana jawnie lub obliczona pozycja początku podciągu

u End – podana jawnie lub obliczona wartość reprezentująca ilość znaków po prawej stronie pozycji Start

W sytuacjach, kiedy nazwisko klienta występuje w postaci:


MacIntyre, Alastair

możesz użyć funkcji Substr() w połączeniu z Instr(), aby rozdzielić nazwisko na osobne pola.
SUBSTR(CustomerName, INSTR(CustomerName, ', ')+2) = Alastair
SUBSTR(CustomerName, 1, INSTR(CustomerName, ', ')-1) = MacIntyre

W pierwszym wypadku Substr pobierze wszystkie znaki z ciągu, zaczynając od drugiego znaku po znaku „,” aż do końca
ciągu. Pozostawienie trzeciego argumentu pustego spowoduje, że funkcja przyjmie go równego długości całego ciągu. W
drugim przypadku funkcja zwróci wszystkie znaki od początku ciągu aż do znaku poprzedzającego przecinek.

Decode
Wielu programistów Accessa przyzwyczaiło się opierać na natychmiastowym porównaniu (IIf()) w swoich kwerendach.
Oracle nie dostarcza podobnie nazywającej się funkcji, można za to użyć podobnie działającej funkcji Decode.

Decode jest serią testów If/Then zakończonych przez Else. To oznacza, że jest to raczej konstrukcja typu Case Select
niż IIf().
DECODE( value, if1, then1, if2, then2, ..., else)

Ilość konstrukcji if/then jest prawie nieograniczona.

Poniższe wyrażenie SQL jest prostym przykładem użycia funkcji Decode do zamiany nazw miast na regiony, w których
leżą:
Select loc,
DECODE(loc, 'NEW YORK', 'MID-ATLANTIC', 'DALLAS', 'SOUTH', BOSTON', 'NEW ENGLAND', 'CHICAGO', 'MIDWEST',
'UNKNOWN') REGION
FROM dept

Wynik tej kwerendy przedstawia, w jaki sposób zostały pokazane regiony i w jaki sposób obsłużone zostało nieznane
miasto przez część Else funkcji Decode.
Select loc,
DECODE(loc, 'NEW YORK', 'MID-ATLANTIC', 'DALLAS', 'SOUTH', BOSTON', 'NEW ENGLAND', 'CHICAGO', 'MIDWEST',
'UNKNOWN') As REGION
FROM dept

LOC REGION
---------- ------------
NEW YORK MID-ATLANTIC
DALLAS SOUTH
CHICAGO MIDWEST
BOSTON NEW ENGLAND
SUMMIT UNKNOWN

Obliczenia w Oracle'u
Dopóki dobry projekt struktury bazy nie będzie przechowywać większości wyników obliczeń, nie będziesz mógł tworzyć
sensownych interfejsów lub raportów bez poznania funkcji matematycznych Oracle'a. Funkcje Oracle'a są bardzo podobne
do tych, które występowały w VBA lub Accessie. Rozdział ten wskaże kilka różnic pomiędzy funkcjami Oracle'a i
Accessa.

Ceil()
Ceil() nie ma odpowiednika w Accessie. Zwraca on najbliższą liczbę całkowitą większą lub równą wartości zadanej.
CEIL(34.2) = 35
CEIL( -2.4) = -2

Floor()
Floor() jest przeciwnością Ceil(), także nie mającą odpowiednika w Accessie. Funkcja zwraca najbliższą liczbę
całkowitą mniejszą lub równą wartości zadanej jako argument.
Floor(34.2) = 34
Floor( -2.4 ) = -3
Część V ♦ Access i architektura klient-serwer 306

Nvl()
Funkcja Nvl() jest funkcją podstawiania wartości i jest podobna do funkcji NZ() w VBA. Umożliwia ona
podstawienie zadanej wartości, gdy argument jest wartością null. Pomaga ona zapobiegać błędom matematycznym
spowodowanym przez podstawienie wartości null do obliczeń.

Posiada ona dwa parametry:


u Value – wymagana. Wartość lub odwołanie do wartości.

u Substitute – wymagana. Wartość zwracana przez funkcję, gdy Value będzie null.
NVL(wartość, podstawienie)
NVL(238, 15)=238
NVL(null, 15)=15

Round()
W Accessie przez długi czas brakowało funkcji Round(). W Accessie 2000 użytkownicy nareszcie mogą z niej skorzystać.
Funkcja ma dwa parametry:
u Value – wymagana. Wartość lub odwołanie do wartości do przetworzenia.

u Precision – nieobowiązkowa. Ilość miejsc po przecinku, do ilu będzie zaokrąglana liczba. Domyślnie przyjmowane
jest zero.

Sign()
Sign() działa dokładnie tak jak funkcja Accessa Sgn(). Zwraca ona 1 dla liczb dodatnich i -1 dla ujemnych.

Trunc()
Zamiast zaokrąglać liczbę w górę lub w dół, Trunc() po prostu obcina liczbę do żądanej długości. Funkcja posiada dwa
parametry:
u Value – wymagana. Wartość lub odwołanie do wartości do przetworzenia.

u Precision – nieobowiązkowa. Ilość miejsc po przecinku, do ilu będzie obcięta liczba. Domyślnie przyjmowane
jest zero.

Greatest/Least
Greatest i Least używane są, aby wybrać pomiędzy dwiema lub więcej wartościami. Mogą być one użyte do liczb,
ciągów lub dat. Gdy używane są do porównywania dat, jak w tym przykładzie poniżej, daty podawane w postaci tekstu
muszą być konwertowane przez funkcję To_Date(), w przeciwnym wypadku zostaną potraktowane jako ciąg znaków i
wynik funkcji nie będzie taki, jakiego się spodziewamy.

W przykładzie użyta jest funkcja Least, aby wybrać wcześniejszą z dat, tę zapisaną w polu Hiredate lub 1 stycznia 1985.

Funkcja Least wybierze wcześniejszą lub mniejszą wartość z podanych możliwości, podczas gdy Greatest wybierze
największą.
SELECT ENAME, LEAST(HIREDATE, TO_DATE('1-JAN-85')) FROM EMP
ENAME LEAST(HIREDATE)
---------- --------------
JP 01-JAN-85
ALLEN 20-FEB-81
WARD 22-FEB-81
JONES 02-APR-81
MARTIN 28-SEP-81
BLAKE 01-MAY-81
CLARK 09-JUN-91
SCOTT 01-JAN-85
KING 17-NOV-81
TURNER 08-SEP-81
ADAMS 01-JAN-85
JAMES 03-DEC-81
FORD 03-DEC-81
MILLER 23-JAN-82
307 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

Obliczenia na datach
Nie ma prawdopodobnie typu danych, który sprawia więcej kłopotu niż daty. Poniżej opiszemy kilka funkcji, które operują
na datach.

Arytmetyka
Date jest typem danych zarówno w Oracle'u jak i w Accessie. Tak jak w Accessie daty zapisują więcej informacji niż to
jest widoczne. W Oracle'u kolumna typu Date przechowuje rok, miesiąc, dzień, godzinę, minutę i sekundę. Oznacza to, że
możesz przeprowadzać obliczenia na datach. Jednak w odróżnieniu od liczb, gdy dodasz liczbę do daty, otrzymujesz nową
datę. Gdy odejmujesz jedną datę od drugiej, otrzymujesz liczbę oznaczającą czas pomiędzy tymi dwiema datami. W
zależności od formatowania czas ten może wyglądać dowolnie, od lat po sekundy. Jest również możliwe, że liczba ta nie
jest liczbą całkowitą – identycznie jak w Accessie.

Sysdate
Funkcja Sysdate() sięga do systemu operacyjnego i zwraca bieżącą datę i czas.
Select SYSDATE FROM sys.Dual

Wyrażenie to zwróci datę systemową, używając systemowej tabeli testowej.

Add_Months
Jeżeli pierwsza ocena pracownika powinna być po 6 miesiącach pracy, możesz użyć funkcji Add_Months, aby zaplanować
ocenę.

Add_Months posiada dwa parametry:

u Date – wymagana. Data lub odwołanie do prawidłowej daty.

u Count – wymagana. Ilość miesięcy, jaką należy dodać do Date.

Poniższe wyrażenie SQL przedstawia datę pierwszej oceny pracownika.


SELECT ename, hiredate, add_months(hiredate, 6) FROM emp
SELECT ENAME, LEAST(HIREDATE, TO_DATE('1-JAN-85')) FROM EMP
ENAME HIREDATE ADD_MONTH
---------- --------- ---------
JP 27-JUL-97 27-JAN-98
ALLEN 20-FEB-81 20-AUG-81
WARD 22-FEB-81 22-AUG-81
JONES 02-APR-81 02-OCT-81
MARTIN 28-SEP-81 28-MAR-82
BLAKE 01-MAY-81 01-NOV-81
CLARK 09-JUN-81 09-DEC-81
SCOTT 19-APR-87 19-OCT-87
KING 17-NOV-81 17-MAY-82
TURNER 08-SEP-81 08-MAR-82
ADAMS 23-MAY-87 23-NOV-87
JAMES 03-DEC-81 03-JUN-82
FORD 03-DEC-81 03-JUN-82
MILLER 23-JAN-82 23-JUL-82

Często, gdy planujemy zdarzenia, potrzebujemy określonego czasu realizacji zdarzenia, aby zdążyć wykonać zakładane
czynności. Można uzyskać datę rozpoczęcia realizacji poprzez wstawienie liczby ujemnej do drugiego argumentu funkcji
Add_Months().

Months_Between
Aby policzyć odstęp czasu pomiędzy dwiema datami, możesz odjąć jedną od drugiej. Miesiące jednak mają różną ilość dni
i aby podać ilość miesięcy pomiędzy datami, musiałbyś wykonać sporo obliczeń. Funkcja Months_Between() zwraca
różnicę w miesiącach pomiędzy datami, biorąc pod uwagę, które miesiące leżą pomiędzy nimi.

Poniższe wyrażenie zamienia miesiące na lata poprzez podzielenie ich przez 12. Użyjemy również zaokrąglenia, aby
otrzymać czytelny wynik.
SELECT ename, hiredate, ROUND(MONTHS_BETWEEN(SYSDATE, hiredate)/12,2) "YEARS SERVICE" FROM emp
ENAME HIREDATE YEARS SERVICE
---------- --------- -------------
JP 27-JUL-97 1.56
ALLEN 20-FEB-81 17.99
WARD 22-FEB-81 17.99
JONES 02-APR-81 17.88
Część V ♦ Access i architektura klient-serwer 308

MARTIN 28-SEP-81 17.39


BLAKE 01-MAY-81 17.8
CLARK 09-JUN-81 17.69
SCOTT 19-APR-87 11.83
KING 17-NOV-81 17.25
TURNER 08-SEP-81 17.44
ADAMS 23-MAY-87 11.74
JAMES 03-DEC-81 17.21
FORD 03-DEC-81 17.21
MILLER 23-JAN-82 17.07

Next_Day()
Jeżeli jakieś zdarzenie ma miejsce danego dnia tygodnia przed lub po podanej dacie (jak większość kalendarzowych świąt,
niektóre święta religijne i dni wypłaty), można policzyć daty, kiedy będzie ono wypadnie. Funkcja Next_Day() może
pomóc w takich obliczeniach.

Next_Day() posiada dwa parametry:

u Date – data lub odwołanie do prawidłowej daty

u Day – angielska nazwa dnia tygodnia ('Sunday', 'Monday', itd.)

Poniższe wyrażenie przedstawia pierwsze dni wypłaty pracowników, zakładając, że dostają pieniądze w każdy piątek.
SELECT ename, hiredate, next_day(hiredate, 'Friday') "PAYDAY!"
FROM emp
ENAME HIREDATE PAYDAY!
---------- --------- ---------
JP 27-JUL-97 01-AUG-97
ALLEN 20-FEB-81 27-FEB-81
WARD 22-FEB-81 27-FEB-81
JONES 02-APR-81 03-APR-81
MARTIN 28-SEP-81 02-OCT-81
BLAKE 01-MAY-81 08-MAY-81
CLARK 09-JUN-81 12-JUN-81
SCOTT 19-APR-87 24-APR-87
KING 17-NOV-81 20-NOV-81
TURNER 08-SEP-81 11-SEP-81
ADAMS 23-MAY-87 29-MAY-87
JAMES 03-DEC-81 04-DEC-81
FORD 03-DEC-81 04-DEC-81
MILLER 23-JAN-82 29-JAN-82

To_Date()
Funkcja To_Date() przeznaczona jest do zamiany daty zapisanej w postaci ciągu na wewnętrzny format daty
rozpoznawany przez Oracle. Często będziesz jej używał w wyrażeniach Insert i Update. Bez niej nie byłbyś często w
stanie przeprowadzić obliczeń na datach.

To_Date posiada dwa parametry:

u String – wymagany. Ciąg reprezentujący datę (np.: 'July 27, 1997'). Domyślnym formatem daty jest „DD-
MON-YYYY”.
u Format – nieobowiązkowy.
SELECT TO_DATE('27-jul-97', 'dd-mon-yyyy') "Data sformatowana" FROM sys.dual
Data sformatowana
-----------
27-JUL-1997

Problem roku 2000


Oracle nie przetwarza dat w sposób, w jaki robi to Access.

Poniższe dwa wyrażenia SQL przedstawiają jak Oracle przypisuje daty do bieżącego stulecia (stulecia daty uzyskanej przez
funkcję Sysdate()), gdy nie określimy sposobu konwersji.
SELECT MONTHS_BETWEEN('27-JUL-2001', '27-JUL-1997') FROM SYS.DUAL
MONTHS_BETWEEN('27-JUL-2001', '27-JUL-1997')
--------------------------------------------
48

SELECT MONTHS_BETWEEN('27-JUL-01', '27-JUL-97') FROM SYS.DUAL


MONTHS_BETWEEN('27-JUL-01', '27-JUL-97')
----------------------------------------
-1152
309 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

Podczas tworzenia aplikacji musisz brać to pod uwagę.

Pracując z datami, można użyć maski „RR”, aby konwertować zapisany dwucyfrowo rok na postać czterocyfrową według
następujących zasad: jeżeli rok zawiera się w przedziale 0–49, zostanie przypisany do XXI wieku, natomiast pomiędzy 50
a 99 do wieku XX.
SELECT TO_CHAR(TO_DATE('000727', 'RRMMDD'), 'DD-MON-YYYY') RRMMDD,
TO_CHAR(TO_DATE('000727', 'YYMMDD'), 'DD-MON-YYYY') YYMMDD
FROM SYS.DUAL
RRMMDD YYMMDD
----------- -----------
27-JUL-2000 27-JUL-1900

Poznajemy widoki
i procedury przechowywane
Przesyłanie wyrażeń SQL do wykonania przez Oracle jest świetnym sposobem na zwiększenie wydajności i zmniejszenie
ruchu w sieci, lecz przechowywanie wyrażeń SQL w aplikacji nie jest najlepszym możliwym rozwiązaniem. Aby
uruchomić całą siłę Oracle'a, skorzystać z pracy wykonanej w bazie danych, zmniejszyć koszty dodatkowych prac,
zabezpieczyć swoją pracę i utrzymywać spójność danych, powinieneś użyć widoków i procedur przechowywanych.

Widok w Oracle'u jest to po prostu zapytanie zapisane na serwerze. Tak jak kwerenda Select zapisana w Accessie, jest on
skompilowany i posiada plan wykonania. Oznacza to, że będzie działać szybciej niż pytanie przesłane do wykonania przez
SPT.

Jest wiele zalet stosowania widoków. Można je wywoływać poprzez nazwę, która jest o wiele krótsza niż średnie
wyrażenie SQL, przez co zmniejsza się obciążenie sieci. Ponieważ widok zapisany jest w bazie danych, posiada on dodatkowy
poziom bezpie-

czeństwa, co jest ważne w aplikacjach, które są słabo chronione. Ponieważ Twoja aplika-
cja prawdopodobnie nie jest jedyną, która korzysta z bazy danych, możesz skorzystać z gotowych widoków, co oszczędza czas i
zapewnia spójność danych w różnych aplikacjach.

Widoki można tworzyć za pomocą Accessa lub korzystając z narzędzi Oracle'a. Aby utworzyć widok lub przeprowadzić
inną zmianę struktury bazy danych, użytkownik, który pracuje musi mieć nadane prawo Resource. Sprawdź, czy
posiadasz wystarczające uprawnienia, lub zapytaj o to administratora bazy danych.

W tym rozdziale zajmujemy się dostępem do Oracle'a z Accessa, więc wszystko, co opiszę, można wykonać za pomocą
Accessa. Jeżeli jednak chciałbyś użyć SQL Plus lub innego narzędzia Oracle'a, sprawdź w dokumentacji jak ich używać.

Tworzenie widoków
Widok jest po prostu wyrażeniem SQL, które zwraca rekordy. Ponieważ widok jest częścią struktury bazy danych, może
być tworzony, zmieniany, używany lub usuwany za pomocą poleceń SQL.

Spójrzmy na proste wyrażenie SQL zapisane zgodnie ze składnią Oracle'a.


Select * from emp where sal>3000

Możesz utworzyć je w Accessie i uruchomić jako kwerendę przekazującą lub możesz utworzyć widok w Oracle'u i
wywołać ten widok.

Aby utworzyć widok z Accessa, utwórz kwerendę przekazującą, zawierającą wyrażenie definicji danych (DDL).
Wyrażenie takie rozpoczyna się słowami kluczowymi Create, Alter, Drop itd. Aby utworzyć widok, powinieneś użyć
następującej składni:
Create [or Replace]
View
[Nazwa widoku]
AS
[wyrażenie SQL zwracające rekordy]

Aby stworzyć widok z poprzedniego wyrażenia SQL, powinieneś użyć poniższego wyrażenia DDL uruchomionego przy
użyciu SPT:
Część V ♦ Access i architektura klient-serwer 310

Create or Replace View MyView As Select * from emp where sal>3000

Klauzula Or Replace powoduje, że nie zostanie wyświetlony błąd, gdy widok MyView już istnieje. Prawdopodobnie nie
będziesz chciał zawsze dołączać klauzuli Or Replace, ponieważ bardzo łatwo wtedy omyłkowo zmienić definicję już
istniejącego widoku.

Wykonanie tej kwerendy utworzy widok, który zwraca wszystkie kolumny z tabeli emp, których wartość pola sal jest
większa od 3000.

Aby sprawdzić, czy widok został prawidłowo utworzony, możesz podłączyć ją do Accessa, jak gdyby była to zwykła
tabela. Możesz również użyć go w dowolnym wyrażeniu SQL w kwerendzie przekazującej.
Select * from MyView

lub
Select MyView.ename, Dept.deptno from MyView, Dept
Where MyWiew.deptno=Dept.deptno

Połączenie z Oracle'em poprzez ADO


Tworzenie kwerend SPT jest świetną metodą komunikacji z Oracle'em, ponieważ przerzucają ciężar pracy na serwer zamiast
na Jet, który nie jest uruchamiany. Możesz skorzystać z wszystkich zalet kwerend SPT, łącząc się z Oracle'em poprzez ADO.
Podejście to pozwala efektywnie kontrolować poprawność danych, dynamicznie tworzyć wyrażenia SQL i wykonywać
procedury przechowywane.

Utworzenie połączenia z Oracle'em pociągało zwykle za sobą wiele skomplikowanych wywołań API z ODBC lub RDO,
który jest podobnym do DAO interfejsem ODBC. Teraz mamy ADO i OLEDB, co zapewnia szybki, jednolity i elastyczny
interfejs do różnych źródeł danych, włączając w to Oracle.

Szczegółowy opis ADO i OLEDB znajduje się w rozdziale 6. „Wprowadzenie do obiektów danych ActiveX” i oraz w
rozdziale 7. „Zaawansowane ADO”.

W tej części rozdziału prześledzimy sposoby użycia ADO i OLEDB, aby połączyć się z bazą danych Oracle i wykonać
wyrażenia SQL.

Gdy używamy kwerend SPT, Oracle analizuje wyrażenia SQL i tworzy wynik. Oracle nie ma planu wykonania takiego
zapytania, więc czas jego wykonania może nie być optymalny. Ponadto, gdy kilka aplikacji używa takiego samego
zapytania lub procedury, musisz je zaprojektować i wstawić do wielu aplikacji. Lepszym podejściem jest utworzenie
widoku lub procedury przechowywanej na serwerze. Może być on dzielony pomiędzy wiele aplikacji, zapewniając za
każdym razem ten sam wynik. Ponieważ zarówno zapytanie tworzące widok, jak i procedura ma utworzony plan
wykonania, więc będzie wykonana z maksymalną możliwą wydajnością.

Omawialiśmy już, w jaki sposób utworzyć widok i procedurę przechowywaną przez użycie kwerend SPT. Wyrażenie SQL
jest takie samo, ale użycie kodu ADO do zestawienia połączenia i utworzenia widoku lub procedury przechowywanej jest
nieco inne.

Przykłady w tym rozdziale są napisane w oparciu o dostawcę „Oracle Native OLEDB” z firmy Microsoft. Dostawca ten
łączy z Oracle Call Interface (OCI), jednak w chwili obecnej nie wszystko, co da się zrobić za pomocą OCI, można
wykonać, używając dostawcy OLEDB. Większość potrzebnych rzeczy da się wykonać, wykorzystując istniejący zestaw
funkcji.

Program z wydruku 17.1 tworzy widok w Oracle'u, a później otwiera go i wyświetla jego zawartość w oknie debuggera.

Wydruk 17.1. Tworzenie widoku w Oracle'u z Accessa


Function Create0racleView() As Boolean

Dim conn As New ADODB.Connection


Dim cmd As New ADODB.Command
On Error GoTo Create0racleView Err
With conn
.Provider = "MSDAORA"
.ConnectionString = "Data Source=empexample;
User ID=Scott;password=Tiger"
.Open
End With

cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
311 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

' Wyrażenie SQL Create or Replace oszczędza nam obsługi błędów


cmd.CommandText = "Create or Replace View MyView As _
Select * firom emp where SAL>2000"
cmd.Execute

Create0racleView_Exit:
conn.Close
Set conn = Nothing
Set cmd = Nothing
Exit Function

Create0racleView Err:
' Błąd
Create0racleView = False
' Sprawdź, który błąd wystąpił przeszukując tablicę błędów
With conn
For i = 0 To .Errors.Count - 1
errDesc = errDesc & .Errors(i).Description & Chr(13)
Next
End With
' Powiadom użytkownika
MsgBox "Wystąpił błąd: " & errDesc
Resume Create0racleView Exit
End Function

Parametry
W Accessie programista może tworzyć kwerendy sparametryzowane, mają one jednak tylko podstawowy plan wykonania i
wykonują się w oparciu o ten plan z różnymi wartościami parametrów. Niestety Oracle nie udostępnia parametrów widoku
poprzez dostawcę OLEDB. Alternatywą jest zmiana istniejącego widoku, tak jak pokazaliśmy powyżej. Można również
użyć obiektu polecenia z OLEDB, aby utworzyć i dostarczyć parametry do wyrażenia SQL.

Program na wydruku 17.2 przedstawia, w jaki sposób można to wykonać.

Wydruk 17.2. Użycie parametrów Oracle'a z VBA Accessa


Function OracleParams(SalAmnt As Long) As Boolean
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim rsfield as New Field
Dim cmd As New ADODB.Command
' Tworzenie połączenia
With conn
.Provider = "MSDAORA"
.ConnectionString = "Data Source=empexample;
User ID=Scott;password=Tiger"
.Open
End With
' Użyjemy kursorów po stronie serwera
With rs
.CursorLocation = adUseServer
End With
' Tworzenie obiektu polecenia
With cmd
cmd.ActiveConnection = conn
' Ustawienie CommandType, aby akceptował wyrażenia SQL
cmd.CommandType = adCmdText
' Ustawienie tekstu polecenia
cmd.CommandText = "Select * from emp where sal > ?"
' Tworzenie parametru i dołączenie go do zbioru
' parametrów polecenia
cmd.Parameters.Append
cmd.CreateParameter("SAL", adNumeric, adParamInput)
' Przypisanie wartości SalAmnt do pierwszego parametru
cmd(0) = SalAmnt
End With
' Wykonaj polecenie i przypisz wynik do obiektu ADO Recordset
Set rs = cmd.Execute
If conn.Errors.Count = 0 Then
OraclParams = True
End If
rs.MoveFirst
While Not rs.EOF
strfield = ""
For Each rsfield In rs.Fields
strfield = strfield & " " & rsfield
Next
Debug.Print strfield & Chr(9)
rs.MoveNext
Wend
End Function
Część V ♦ Access i architektura klient-serwer 312

Tworzenie procedur przechowywanych


Procedura przechowywana w Oracle'u jest podobna do modułu w Accessie. Wykonuje zbiór poleceń na serwerze.

Głównymi zaletami procedur przechowywanych są ich szybkość, niezawodność i bezpieczeństwo. Mogą one być użyte do
wymuszania reguł biznesowych, kontroli poprawności i zapewnienia transakcyjności. Najważniejszą wadą procedur jest
sposób ich tworzenia i uruchamiania. Oracle nie dostarcza środowiska programowania podobnego do środowiska Accessa,
przez to tworzenie i edycja procedur przechowywanych jest trudna. Oracle 8 dostarcza program zarządzania strukturą bazy,
który umożliwia tworzenie i kontrolę poprawności procedur, jednak wciąż nie jest to idealne rozwiązanie. Dodatkowo z
racji tego, że procedury są zależne od serwera bazy danych, gdy zmieniasz serwer, musisz również zmienić procedury
przechowywane.

Architektura wielowarstwowa została tak zaprojektowana, aby ograniczyć tę niedogodność. Nie ma żadnego powodu, aby
umieszczać całą skomplikowaną logikę aplikacji na serwerze (tak samo jak nie ma powodu, aby umieszczać ją na kliencie),
dzięki temu procedury przechowywane są dużo prostsze od innych obiektów zapewniających logikę biznesową i inne
operacje.

Poniżej utworzymy i uruchomimy prostą procedurę przechowywaną.

Aby tworzyć procedury w swojej przestrzeni tabel bazy danych, trzeba posiadać prawo systemowe Create Procedure, które
jest częścią roli Resource. Aby utworzyć procedurę w innej przestrzeni tabel, musisz posiadać prawo Create Any
Procedure. Porozmawiaj z administratorem bazy, jeżeli nie jesteś pewien, jakie posiadasz uprawnienia.

Procedura dzieli się na następujące części:


u Deklaracja parametrów.
u Rozpoczęcie przetwarzania.
u Zatwierdzenie zmian.
u Obsługa wyjątków.
u Odwołanie zmian.
u Obsługa błędów.

Procedura wstawiająca rekord do tabeli z dwoma polami przedstawiona jest na wydruku 17.3.

Wydruk 17.3. Procedura Oracle'a dodająca nowy rekord


(Ename CHAR, EJob CHAR) IS
BEGIN
INSERT INTO SCOTT.TESTTABLE
VALUES(Ename, EJob);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;

W tym przypadku procedura posiada dwa parametry, nazwisko i nazwę stanowiska.

Access może utworzyć procedurę poprzez kwerendę SPT w następujący sposób:


CREATE OR REPLACE PROCEDURE MyStoredProcedure
(Ename CHAR, EJob CHAR) IS
BEGIN
INSERT INTO SCOTT.TESTTABLE
VALUES(Ename, EJob);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;

Po utworzeniu procedury może być ona wywoływana poprzez kwerendę SPT lub VBA.
313 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

Uruchamianie procedury
Wywołanie procedury z kwerendy SPT jest nieco inne niż wywołanie widoku:
{call MyStoredProcedure }

Nawiasy klamrowe udają składnię, jakiej spodziewa się Oracle, używając Oracle call interface, używanego przez dostawcę
OLEDB.

Wykonywanie procedury z VBA poprzez dostawcę OLEDB dla Oracle'a wygląda nieco inaczej. Funkcja przedstawiona na
wydruku 17.4 korzysta z tego, że procedury ujawniają swoje parametry w sposób, który może być użyty w VBA. Podając
nazwę procedury przechowywanej, nazwę tabeli, do której chcesz wstawić rekord i wypełniając wymagane argumenty w
tablicy paramArray uruchamianej funkcji, możesz uruchomić większość procedur przechowywanych za pomocą funkcji
przedstawionej na wydruku 17.4.

Wydruk 17.4. Wykonanie procedury przechowywanej z parametrami za pomocą VBA w Accessie


Function RunOracleStoredProcedures(ProcName As String, _
DestTable as String, ParamArray ParamArgs() As Variant) As Boolean

Dim conn As New ADODB.Connection


Dim rs As New ADODB.Recordset
Dim i As Integer
Dim cmd As New ADODB.Command
Dim rsfield As Field
Dim strfield As String

With conn
.Provider = "MSDAORA"
.ConnectionString = "Data Source=empexample;_
User ID=Scott;password=Tiger"
.Open
End With
cmd.ActiveConnection = Conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = ProcName
For i = 0 To UBound(ParamArgs())
With cmd.Parameters(i)
.Type = adChar
.Direction = adParamInput
.Value = ParamArgs(i)
End With
Next

cmd.Execute

' A teraz wyświetlamy wynik w oknie uruchamiania


' Nie będziesz potrzebował tego fragmentu kodu
' w swoich aplikacjach

rs.Open "Select * from " & destTable, conn,_


adOpenForwardOnly, adLockReadOnly
rs.MoveFirst
While Not rs.EOF
strfield = ""
For Each rsfield In rs.Fields
strfield = strfield & " " & rsfield
Next
Debug.Print strfield & Chr(9)
rs.MoveNext
Wend

Set rs = Nothing
conn.Close
RunOracleStoredProcedures = True
End Function

Wykonywanie wielu prostych procedur przechowywanych umożliwia tworzenie złożonej logiki w znanym środowisku
VBA, korzystając z jego zaawansowanych możliwości uruchamiania kodu i obsługi błędów.

Tworzenie niezwiązanego interfejsu do Oracle'a


Mając na uwadze ograniczenia wydajności i duże obciążenie sieci, gdy używamy tabel połączonych, powinniśmy rozważyć
użycie niezwiązanego interfejsu użytkownika wszędzie tam, gdzie jest to możliwe. Utworzenie niezwiązanego interfejsu
pomaga zastosować w Twojej aplikacji architekturę wielowarstwową, co zwiększa jej skalowalność i ułatwia jej
konserwację. Umożliwi także łatwe łączenie różnych narzędzi programowania. Możesz użyć ADO, ADOX, DAO, RDO i
inne narzędzia tam, gdzie uważasz, że przyniosą korzyści. Niezwiązany interfejs ułatwia migrację do innego środowiska,
Część V ♦ Access i architektura klient-serwer 314

jak na przykład Visual Basic. Przez to, że jesteś pewny, że przetwarzanie odbywa się na serwerze, możesz również uzyskać
lepszą wydajność.

W przedstawionym tu ćwiczeniu utworzymy prosty niezwiązany interfejs dla Oracle'a, który wygląda i zachowuje się
identycznie jak formularz związany. Aby pokazać elastyczność ADO, użyjemy wyrażeń SQL oraz metod obiektu
Recordset.

Formularz będzie wyświetlał rekordy tabeli EMP. Użytkownik będzie mógł wstawiać i usuwać rekordy z bazy danych
Oracle. Można będzie zmieniać rekordy w tabeli bez konieczności każdorazowego zapisywania zmienionego rekordu.

Tworzenie niezwiązanego interfejsu


Na początek utwórz formularz taki, jak na rysunku 17.3.

Rysunek 17.3.
Formularz z danymi
w trybie
projektowania

Dla uproszczenia, nazwy obiektów ekranowych odpowiadają nazwom pól w tabeli EMP:
u Empno,

u Ename,

u Job,
u Mgr,

u Hiredate,

u Sal,
u Comm,

u Deptno.

Przyciski nawigacyjne i manipulacyjne będą nazywały się następująco:


u BtnGotoFirst,

u BtnGotoPrevious,
u BtnGotoNext,

u BtnGotoLast,
u BtnEdit,

u BtnNew,

u BtnDelete,
u BtnSave,

u BtnClose.

Tworzenie zmiennych globalnych


Podstawowe operacje można zrobić na kilka sposobów. Dla uproszczenia przyjmijmy, że obiekty Connection i
Recordset oraz zmienna, która informuje o zmianie danych, będą przechowywane przez trzy zmienne globalne
przechowywane w głównym module:
315 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

Global conn As ADODB.Connection


Global rs As ADODB.Recordset
Global EditRec As Boolean

Ładowanie danych i inicjalizacja formularza


Program przedstawiony na wydruku 17.5 wykonany zostanie jako obsługa komunikatu OnOpen. Procedura ta załaduje dane
i zainicjuje aplikację.

Wydruk 17.5. Utworzenie i otwarcie połączenia z Oracle'em oraz wypełnienie formularza


Private Sub Form Open(Cancel As Integer)
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
With conn
.Provider = "MSDAORA"
.ConnectionString = "Data Svurce-ernpexample;_
User ID=Scott;password=Tiger"
.Open
End With
rs.CursorLocation = adUseClient
rs.Open "Select * from emp", conn, adOpenStatic,_
adLockOptimistic, adAsyncFetch

FillForm

EditRec = True
End Sub

Oracle nie zwraca obiektów typu Recordset, ale dostawca OLEDB przechwytuje wynik wyrażenia SQL i zwraca go do
programu jako Recordset. Dostawca OLEDB przykrywa wywołania Oracle Call Interface tak, że dla aplikacji nie ma
różnicy pomiędzy Oracle'em a innymi źródłami danych. Używając globalnej zmiennej Recordset, można szybko i łatwo
wypełnić formularz danymi pochodzącymi z pierwszego rekordu. Następnie procedura ustawia zmienną EditRec na
true, co wskazuje, że dane na formularzu są gotowe do edycji. Zdarzenie OnOpen wywołuje funkcję FillForm, która
zamieszczona jest na wydruku 17.6.

Wydruk 17.6. Wypełnianie formularza danymi


Function FillForm() As Boolean

On Error GoTo FillForm Err


[Empno] = rs(0)
[ENAME] = rs(1)
[Job] = rs(2)
[MGR] = rs(3)
[HIREDATE] = rs(4)
[SAL] = rs(5)
[COMM] = rs(6)
[DEPTNO] = rs(7)

FillForm = True

FillForm_Exit:
Exit Function

FillForm_Err:
FillForm = False
Exit Function

End Function

Programowanie przycisków sterujących


Aby przeglądać cały wynik zapytania, należy oprogramować przyciski sterujące, tak jak jest to pokazane na wydrukach od
17.7 do 17.10.

Wydruk 17.7. Przejście do pierwszego rekordu


Private Sub btnGotoFirst_Click()

On Error Resume Next

rs.MoveFirst
If Not rs.BOF Then
FillForm
End If
CurrentContext Me
End Sub
Część V ♦ Access i architektura klient-serwer 316

Wydruk 17.8. Przejście do poprzedniego rekordu


Private Sub btnGotoPrevious_Click()

On Error Resume Next

rs.MovePrevious
If Not rs.BOF Then
FillForm
End If
CurrentContext Me
End Sub

Wydruk 17.9. Przejście do następnego rekordu


Private Sub btnGotoNext_Click()

On Error Resume Next

rs.MoveNext
If Not rs.BOF Then
FillForm
End If
CurrentContext Me
End Sub

Wydruk 17.10. Przejście do ostatniego rekordu


Private Sub btnGotoLast_Click()

On Error Resume Next

rs.MoveLast
If Not rs.BOF Then
FillForm
End If

On Error GoTo 0

CurrentContext Me
End Sub

Bieżący stan przycisków nawigacyjnych zależy od pozycji w zestawie rekordów wyniku. Funkcja CurrentContext, która
pobiera jako argument obiekt formularza, włącza oraz wyłącza przyciski nawigacyjne (wydruk 17.11).

Wydruk 17.11. Włączanie i wyłączanie przycisków nawigacyjnych


Sub CurrentContext(frm As Form)
Dim bFirstRec As Boolean
Dim bLastRec As Boolean

bFirstRec = (rs.AbsolutePosition = 1)
bLastRec = (rs.AbsolutePosition = rs.RecordCount)

With frm
If Not bFirstRec And Not bLastRec Then
!btnGotoFirst.Enabled = True
!btnGotoPrevious.Enabled = True
!btnGotoLast.Enabled = True
!btnGotoNext.Enabled = True
GoTo CurrentContext_Exit
End If
If bFirstRec And bLastRec Then
!btnEdit.SetFocus
!btnGotoFirst.Enabled = False
!btnGotoPrevious.Enabled = False
!btnGotoLast.Enabled = False
!btnGotoNext.Enabled = False
GoTo CurrentContext_Exit
End If

If bFirstRec Then
!btnGotoLast.Enabled = bFirstRec
!btnGotoNext.Enabled = bFirstRec
!btnGotoLast.SetFocus
!btnGotoFirst.Enabled = Not bFirstRec
!btnGotoPrevious.Enabled = Not bFirstRec
GoTo CurrentContext_Exit
End If

If bLastRec Then
!btnGotoFirst.Enabled = bLastRec
!btnGotoPrevious.Enabled = bLastRec
!btnGotoFirst.SetFocus
317 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

!btnGotoLast.Enabled = Not bLastRec


!btnGotoNext.Enabled = Not bLastRec
GoTo CurrentContext_Exit
End If
End With

End Sub

Zmiana danych Oracle'a przy użyciu formularza


Do tej pory możesz tylko oglądać dane, ale zmiany, jakie wprowadziłeś, nie zostaną zapisane w bazie. Funkcja z wydruku
17.12 wywołuje metodę Update obiektu OLEDB Recordset, aby wysłać zmiany do Oracle'a zaraz po tym, jak zmieniłeś
dane. Daje to możliwości takie same jak możliwości formularza związanego. Funkcja pokazana na wydruku 17.12 musi
być wywołana jako odpowiedź na zdarzenie AfterUpdate dla każdego pola tekstowego.

Wydruk 17.12. Funkcja UpdateField


Function UpdateField(FieldName As Variant, NewValue As Variant)_
As Boolean

If EditRec = False Or IsEmpty(EditRec) Then Exit Function

Dim rsOrigSource As String


Dim errDesc As String
Dim i As Integer

On Error GoTo UpdateField Err

' Zachowaj początkowe źródło recordset-u na wypadek błędu


rsOrigSource = rs.Source

' Próba zmiany pola przy użyciu metody update obiektu Recordset
rs.Update FieldName, NewValue

' Udało się


UpdateField = True

UpdateField_Exit:
Exit Function

UpdateField_Err:
' Błąd
UpdateField = False

' Sprawdź, jaki wystąpił błąd, przeszukując tablicę błędów


With conn
For i = 0 To .Errors.Count - 1
errDesc = errDesc & .Errors(i).Description & Chr(13)
Next
End With

' Informacja dla użytkownika


MsgBox "Wystąpił błąd: " & errDesc

' Musisz odwołać metodę Update metodą CancelUpdate


' gdyż nie będziesz mógł wykonać żadnej operacji na wyniku
rs.CancelUpdate

' Zamknięcie istniejącego wyniku


rs.Close

' Otwórz Recordset z zachowanym źródłem, przywracając


' mu stan początkowy
rs.Open rsOrigSource, conn, adOpenStatic, adLockOptimistic, _
adAsyncFetch

' Wywołaj FillForm


Forms![forml].FillForm

Resume UpdateField_Exit

End Function

Funkcja UpdateField może być wywoływana przez każde zdarzenie AfterUpdate, gdy zaznaczymy wszystkie pola
tekstowe na formatce i wstawimy wyrażenie pokazane na wydruku 17.13. Alternatywą do zapisywania zmian natychmiast
może być buforowanie zmian i zapisywanie ich po przejściu do innego rekordu. Możesz także użyć wywołania przez ADO
procedury przechowywanej i przekazać do niej nowe wartości.

Wydruk 17.13. Wyrażenie zapisujące zmiany po edycji zawartości pola


=UpdateField(screen.activecontrol.[Name],screen.activecontrol)
Część V ♦ Access i architektura klient-serwer 318

Teraz, gdy przechodzisz między rekordami i zmieniasz dane pracowników, zmiany zapisane będą w bazie po przejściu do
innego rekordu.

Wstawienie danych do Oracle'a przy użyciu formularza


Aby dodać nowy rekord, powinieneś wyczyścić wszystkie pola na formularzu i ustawić zmienną EditRec na false. Kod
programu z wydruku 17.14 powinien być wprowadzony jako obsługa zdarzenia OnClick przycisku btnNew.

Wydruk 17.14. Przygotowanie formularza do wpisania nowego rekordu


Private Sub btnNew Click()
ClearForm
EditRec = False
End Sub

Należy jeszcze napisać procedurę czyszczącą formularz. Dla naszych celów, może ona być zapisana w standardowym
module poza formularzem. Funkcja ta jest niezwykle prosta (wydruk 17.15).

Wydruk 17.15. Czyszczenie formularza


Sub ClearForm()
Me![Empno] = ""
Me![ENAME] = ""
Me![Job] = ""
Me!(MGR] = ""
Me![HIREDATE] = ""
Me![SAL] = ""
Me![COMM] = ""
Me![DEPTNO] = ""
End Sub

Zapisywanie danych do Oracle'a przy użyciu formularza


Gdy trzeba zapisać rekord, możesz wywołać poniższą procedurę za pomocą zdarzenia OnClick przycisku btnSave.
Sprawdzając stan zmiennej EditRec, wiemy, czy wprowadzasz nowy rekord i tworzymy odpowiednie wyrażenie SQL.
Zostanie ono wykonane poprzez obiekt Command. Technika ta pokazana jest na wydruku 17.16, jest standardowa dla
Oracle'a.

Wydruk 17.16. Zapis do Oracle'a poprzez SQL i ADO


Private Sub btnSave Click()

Dim cmd As New ADODB.Command


Dim strCmdtxt as string

' Jeżeli wstawiamy nowy rekord


If EditRec = False Then

' Po upewnieniu się, że obiekt Command jest prawidłowo ustawiony


' utworzymy i wykonamy wyrażenie SQL Insert
With cmd
.ActiveConnection = conn
.CommandType = adOmdText
with Me
strOmdtxt = strOmdtxt & "insert into emp values ("
strCmdtxt = strCmdtxt & "'![Empno] ',"
strOmdtxt = strCmdtxt & "'![ENAME] ',"
strCmdtxt = strCmdtxt & "'![Job] ',"
strCmdtxt = strCmdtxt & "'![MGR] ',"
strCmdtxt = strCmdtxt & "' to date('" &![HIREDATE] &
"','MM/DD/YY') ',"
strCmdtxt = strCmdtxt & "'![SAL] ',"
strCmdtxt = strCmdtxt & "'![COMM] ',"
end with
.Execute
End With
End If

' Zamknij, ustaw i otwórz jeszcze raz Recordset


With rs
.Close
.CursorLocation = adUseClient
.Open "Select * from emp", conn, adOpenStatic, adLockOptimistic,
adAsyncFetch
End With

' Wypełnij formularz


FillForm
319 Rozdział 17. ♦ Interfejs Access’a 2000 do Oracle’a

' Zmień tryb aplikacji na edycję danych


EditRec = True
End Sub

Usuwanie danych przy użyciu formularza


To samo podejście zastosowane jest przy usuwaniu danych. Procedura na wydruku 17.17 usuwa bieżący rekord z Oracle'a,
gdy wykonamy ją jako obsługę zdarzenia OnClick przycisku btnDelete.

Wydruk 17.17. Usunięcie bieżącego rekordu


Private Sub btnDelete Click()
Dim cmd As New ADODB.Command

' Jeżeli zmieniamy rekord


If EditRec = True Then

' Po upewnieniu się, że obiekt command jest prawidłowo ustawiony


' utworzymy i wykonamy wyrażenie SQL Delete
With cmd
.ActiveConnection = conn
.CommandType = adCmdText
.CommandText = "Delete from emp where empno= " & Me![Empno]
.Execute
End With
End If

' Zamknij, ustaw i otwórz jeszcze raz Recordset


With rs
.Close
.CursorLocation = adUseClient
.Open "Select * from emp", conn, adOpenStatic, adLockOptimistic,
adAsyncFetch
End With

' Wypełnij formularz


FillForm
End Sub

Aby przyciski nawigacyjne odzwierciedlały zawartość formularza w czasie przeglądania dostępnych rekordów, przypisz
kod zamieszczony na wydruku 17.18 do zdarzenia OnCurrent formularza.

Wydruk 17.18. Wypełnienie pól formularza danymi i sprawdzenie bieżącego kontekstu


Private Sub Form Current()
On Error Resume Next
Dim bFirstRec As Boolean
Dim bLastRec As Boolean

If Not rs.BOF Then


With Me
![Empno] = rs(0)
![ENAME] = rs(1)
![Job] = rs(2)
![MGR] = rs(3)
![HIREDATE] = rs(4)
![SAL] = rs(5)
![COMM] = rs(6)
![DEPTNO] = rs(7)
End With
End If

Current0ontext Me
End Sub

Zamykanie połączenia z Oracle'em


Gdy zamykamy formularz, należy zakończyć połączenie z Oracle'em i ustawić obiekty Connection i Recordset na
wartość nothing, ponieważ może zechcesz użyć tych obiektów w innych aplikacjach. Funkcja przedstawiona na wydruku
17.19 pomoże przeprowadzić prace porządkowe.

Wydruk 17.19. Porządki podczas zamykania formatki


Private Sub btnClose_Click()
On Error GoTo Err_btnClose_Click_Err

DoCmd.Close

Exit_btnClose_Click_Exit:
conn.Close
Set conn = Nothing
Część V ♦ Access i architektura klient-serwer 320

Set rs = Nothing
Exit Sub

Err_btnClose_Click_Err:
MsgBox err.Description
Resume Exit_btnClose_Click_Exit
End Sub

Poprzez wprowadzanie innych obiektów Recordset, trwałych obiektów Recordset oraz przez użycie uproszczeń
dostawcy OLEDB dla Oracle Call Interface możesz utworzyć cały niezwiązany interfejs użytkownika do Oracle'a,
korzystając z szybkości działania, skalowalności i odporności Oracle'a w Twojej aplikacji Accessa.
Część VI
Współoperatywność
W tej części:
u Użycie automatyzacji ActiveX.
u Integracja z Office 2000.
u Użycie Visual Basic z Accessem.
Rozdział 18.
Użycie automatyzacji ActiveX
W tym rozdziale:
u Co to jest automatyzacja ActiveX.
u Dlaczego używamy automatyzacji.
u Odróżnienie serwera automatyzacji od klienta automatyzacji.
u Określanie zasobów wymaganych przez automatyzację.
u Wielka trójka.
u Tworzenie i ustanowienie odwołania do innej aplikacji.
u Przypisywanie zmiennej obiektowej do aplikacji.
u Tworzenie egzemplarza aplikacji.
u Użycie metod i właściwości obiektów automatyzacji.
u Zwalnianie obiektu automatyzacji.
u Łączymy wszystko razem.
u Zamykanie aplikacji serwera automatyzacji.

W obecnych czasach, częściej niż do tej pory, żąda się od programistów szybkiego tworzenia skomplikowanych aplikacji,
które są zintegrowane z innymi programami.

Szczęśliwie, używając automatyzacji ActiveX (dawniej zwanej OLE Automation), aplikacje mogą współpracować ze sobą,
tworząc kompletne rozwiązania informatyczne. Może to poważnie skrócić czas tworzenia programów, ponieważ zamiast
tworzenia jakiejś funkcji programista może połączyć się z innym programem i użyć jego opcji.

W tym rozdziale opiszę zasady i techniki użycia automatyzacji ActiveX. W rozdziale 19. „Integracja z Office 2000” opiszę,
jak użyć automatyzacji ActiveX w celu zintegrowania Accessa 2000 z resztą pakietu Office.

Co to jest automatyzacja ActiveX


Technologia ActiveX jest bazowana na Component Object Model (COM) firmy Microsoft. Automatyzacja ActiveX pozwala
na współpracę programów ze sobą. Automatyzacja pozwala jednemu programowi na dostęp i manipulowanie obiektami
innego programu. Przykładem użycia automatyzacji jest drukowanie listów i raportów w Wordzie z Accessa.

Dlaczego używamy automatyzacji


Użycie automatyzacji jest efektywną metodą tworzenia i rozbudowy aplikacji. Automatyzacja może radykalnie skrócić
czas tworzenia aplikacji, ponieważ zamiast tworzyć i testować opcję od podstaw, możemy ją sobie „pożyczyć” z innej
aplikacji.
323 Rozdział 18. ♦ Użycie automatyzacji Active X

Nie ma powodów, abyś tworzył swój edytor tekstów lub arkusz kalkulacyjny do użycia w Accessie. Dużo prościej użyć
automatyzacji i niektórych technik opisanych w tym rozdziale, aby użyć w Twojej aplikacji Worda czy Excela. Umożliwia
to skupienie się na opcjach niedostarczonych przez inne programy, co będzie bardzo korzystne dla użytkowników.

Różnice między serwerem automatyzacji


a klientem automatyzacji
Gdy dwie aplikacje współpracują ze sobą, ważne jest, aby ustalić, która z nich udostępnia swoje obiekty, a która ich używa.
Serwer automatyzacji jest aplikacją, która udostępnia obiekty klasy Automation. Klient automatyzacji (nazywany czasami
kontrolerem automatyzacji) to aplikacja, która decyduje, które obiekty będą używane i w jaki sposób.

Na przykład, jeżeli przycisk w Accessie uruchamia drukowanie listu w Wordzie, serwerem automatyzacji jest Word,
natomiast klientem jest Access.

Określanie zasobów
wymaganych przez automatyzację
Ponieważ jedna aplikacja za pomocą automatyzacji kontroluje inną, zostaną otwarte co najmniej dwa programy. Zawsze,
gdy uruchamiamy kolejną aplikację, potrzebna jest dodatkowa ilość pamięci oraz mocy procesora. Jakie zasoby sprzętowe
są wymagane, aby sterować Wordem z Accessa, jest bardzo subiektywną decyzją. Minimalną akceptowalną wydajność
zapewnia procesor Pentium II z 24 MB pamięci RAM. Oczywiście szybszy procesor może istotnie poprawić wydajność,
jednak duża ilość pamięci RAM jest bardziej pożyteczna niż moc procesora. Jeżeli wydajność programów używających
automatyzacji jest niewystarczająca, najpierw dodaj pamięć, a dopiero później wymieniaj procesor na lepszy.

Wielka trójka
Mamy trzy etapy użycia automatyzacji:
91. Pobranie obiektu Automation. Utworzenie nowego albo odwołanie się do już istniejącego.

92. Użycie obiektu Automation w aplikacji.

93. Zwolnienie obiektu Automation.

Przykładowo, jeżeli chciałbyś wydrukować list lub raport w Wordzie z Accessa, pierwszym krokiem powinno być
utworzenie lub pobranie odwołania do aplikacji Word. Następnie używamy obiektów, właściwości i metod Worda (takich
jak otwarcie, edycja lub wydruk dokumentu). Po zakończeniu pracy należy zwolnić aplikację Word.

Tworzenie i ustanowienie odwołania do innej aplikacji


Aby użyć jakiejś aplikacji, niezbędne jest ustanowienie odwołania do tej aplikacji, poprzez utworzenie zmiennej
obiektowej i przypisanie jej egzemplarza aplikacji.

Ustanawianie odwołania do innej aplikacji


Za pomocą automatyzacji używasz i sterujesz pracą innych aplikacji spoza Accessa. Ilekroć używa się komponentu lub
aplikacji spoza Accessa, musisz ustanowić odwołanie do tej aplikacji. Aby to zrobić, otwórz edytor Visual Basica i wybierz
Tools, References. Na ekranie pojawi się okno dialogowe References, które zawiera listę bibliotek typów, programów,
bibliotek DLL i kontrolek ActiveX (rysunek 18.1). Ustaw odwołanie do aplikacji, której chcesz użyć w swoim programie.
Na przykład, aby odwołać się do Worda 2000, zaznacz pole wyboru obok Microsoft Word 9.0 Object Library.
Część VI ♦ Współoperatywność 324

Jeżeli nie możesz znaleźć potrzebnej Ci biblioteki na liście, naciśnij


przycisk Browse i odszukaj ją na dysku.

Po ustanowieniu odwołania do aplikacji możesz przeglądać jej obiekty, właściwości i metody, oraz używać ich.
Rysunek 18.1.
Okno dialogowe
odwołań

Przegląd obiektów, właściwości i metod


Przed omówieniem sposobów użycia obiektów innej aplikacji przypomnijmy kilka podstawowych pojęć. Bardzo ważne
jest, abyś rozumiał pojęcia: obiekt, właściwość i metoda. Bez tego nie ma sensu czytanie reszty tego rozdziału.

Obiekt jest elementem, który może być lub będzie użyty do programowania. W Accessie obiektami są formularze, pola
tekstowe, przyciski i tego typu elementy. Używając automatyzacji, inne aplikacje i ich obiekty mogą być programowane za
pomocą Accessa. Microsoft Office zawiera ponad 500 obiektów, które możesz używać w swoich aplikacjach. Przykładowo
Word udostępnia obiekt Document, a Excel obiekt Worksheet.

Właściwość jest charakterystyką obiektu. Właściwość może być rozumiana jako przymiotnik opisujący obiekt. W Accessie,
właściwościami pola tekstowego są: nazwa, widoczność, kolor i inne tego typu cechy. Analogicznie, gdy używamy
obiektów z innych aplikacji, mają one właściwości, które mogą być zmieniane poprzez automatyzację. Na przykład,
podobnie do formularzy Accessa, aplikacje Word i Excel mogą być ukrywane i pokazywane poprzez ustawienie
odpowiedniej właściwości. Większość właściwości może być zarówno odczytywana jak i zapisywana.

Metoda to działanie na obiekcie. Może być rozumiana jako czasownik w zdaniu. Przykładem metody Accessa jest Close,
natomiast przykładem metody Excela jest Quit, która zamyka Excela.

Poznajemy strukturę obiektów


Gdy korzystamy z innej aplikacji, dobrze jest najpierw zapoznać się ze strukturą obiektów tej aplikacji. Łatwo wtedy
sprawdzić, z których obiektów można skorzystać, aby wykonać określoną czynność. Model obiektów stanowi szablonową
reprezentację struktury aplikacji. Jest to szybka i prosta metoda sprawdzenia, jakie obiekty są dostępne w programie.
Modele różnych aplikacji można znaleźć w ich plikach pomocy. W rozdziale 19. przedstawię modele obiektów programów
Microsoft Office.

Użycie narzędzia Object Browser


Inną metodą szybkiego odszukania obiektów dostępnych w aplikacji jest użycie narzędzia Object Browser. Zaletami tego
sposobu jest dostęp do właściwości, metod i zdarzeń oraz to, że obiekty te są połączone z ich plikami pomocy. Object
Browser jest świetnym narzędziem do tego, aby szybko odszukać właściwy obiekt i poznać jego sposób działania.

Aby użyć Object Browser wybierz Object Browser z menu View w edytorze Visual Basica. Możesz również nacisnąć F2.
Object Browser pokazany jest na rysunku 18.2.
325 Rozdział 18. ♦ Użycie automatyzacji Active X

Rysunek 18.2.
Object Browser
pokazujący obiekty
Worda

Przy pierwszym otwarciu przeglądarki pole listy rozwijanej w lewym górnym rogu będzie ustawione na All Libraries. To
ustawienie powoduje, że są widoczne wszystkie obiekty aplikacji, do których ustawiliśmy odwołanie. Pierwszym krokiem
powinno być wybranie właściwej aplikacji na liście rozwijanej tak, aby widoczne były tylko jej obiekty. Przykładowo, gdy
wybierzemy Word, wyświetlone zostaną tylko obiekty Worda.

Druga lista służy do szukania. Przykładowo, jeżeli chcemy odnaleźć okno komunikatu, ustawiamy górną listę wyboru na
All Libraries, poniżej wpisujemy MsgBox i naciskamy na ikonę z lornetką (rysunek 18.3).

Lewy dolny panel zatytułowany jest Classes. W panelu tym wyświetlane są dostępne typy obiektów w wybranej
bibliotece. Gdy z listy zostanie wybrana klasa, na liście Member of zostaną wyświetlone właściwości, metody i zdarzenia.

Prawy dolny panel zatytułowany Members, przedstawia zawartość klasy wybranej po lewej stronie. Na przykład, jeżeli
wybrany zostanie obiekt Application, prawy panel będzie pokazywał wszystkie właściwości, metody, zdarzenia i stałe, które
zawiera obiekt zaznaczony na liście klas.
Rysunek 18.3.
Szukanie MsgBox
w Obiect Browser

Skąd Object Browser czerpie informacje o obiektach, właściwościach i metodach? Z większością aplikacji dostarczany jest
plik biblioteki typów, w którym zapisane są informacje o obiektach aplikacji, właściwościach, metodach i stałych. Object
Browser wyświetla informację z biblioteki typów. Biblioteki te zapisywane są zwykle w plikach z rozszerzeniem .TLB lub
.OLB.

Domyślnie elementy wyświetlane w panelach Classes i Members są upo-


rządkowane alfabetycznie. Dobrze jest nacisnąć prawy klawisz myszki na
panelach i wybrać Group Members. Spowoduje to pogrupowanie listy
według typów elementów. Elementy w każdej grupie uporządkowane będą
alfabetycznie.
Część VI ♦ Współoperatywność 326

Na samym dole okna wyświetlana jest składnia użycia wybranego elementu. Na przykład, po wybraniu obiektu Application z
Accessa i zaznaczeniu metody DLookup, w oknie na dole Object Browsera wyświetlona zostanie właściwa składnia. Po
dalsze informacje o wybranym elemencie można uzyskać, naciskając F1 i przeglądając pomoc podręczną.

Tworzenie zmiennej obiektowej


Zmienna jest fragmentem pamięci przeznaczonym do zapisywania i odczytywania informacji. Niewątpliwie masz już duże
doświadczenie w stosowaniu prostych zmiennych, takich jak liczby lub ciągi znaków. Poniższy przykład przedstawia
sposób deklaracji i użycia dwóch prostych zmiennych:
Dim strName as String
Dim I as integer

StrName = "Bob"
I = 10

W przykładzie tym zmienne zawierają zadeklarowany typ danych i dane tych typów mogą być przypisywane do zmiennej i
z niej odczytywane.

Zmienne obiektowe deklaruje się instrukcją Dim, identycznie jak zmienne proste.
Dim objWord.application
Dim objExcel.application

Zawsze kwalifikuj wszystkie obiekty użyte w automatyzacji. Zamiast


Dim objWord as Application

używaj
Dim objWord as Word.Application

Kilka programów, do których się odwołujesz, może posiadać obiekt


Application. Kwalifikacja nazwy obiektu zapewnia użycie właściwego
obiektu i prawidłowe działanie programu

Odwołanie do pracującej aplikacji


Po utworzeniu zmiennej obiektowej następnym krokiem jest odwołanie się do aplikacji, której chcesz użyć. Jednak pamiętaj, nie
wiesz czy aplikacja ta jest uruchomiona czy nie. Jeżeli chcesz użyć Worda, użytkownik być może ma go już otwartego. W tym
wypadku, możesz użyć do Twoich celów bieżącego egzemplarza Worda. W przeciwnym wypadku, gdy otworzysz kolejny
egzemplarz Worda, błyskawicznie zużyjesz zasoby w komputerze.

Aby sprawdzić, czy jest uruchomiony program, użyj funkcji GetObject. Funkcja ta zwróci odwołanie do aktualnie
uruchomionej aplikacji.
' Deklaracja zmiennej obiektowej objWord
Dim objWord as Word.Application

' Użycie funkcji GetObject do pobrania odwołania do


' aktualnie uruchomionej aplikacji
Set objWord = GetObject(, "Word.Application")

Przypisywanie zmiennej obiektowej


do aplikacji
Aby przypisać odwołanie do obiektu do zmiennej, używamy słowa kluczowego Set. Przykładowo:
Set objExcel = Excel.Application

Zmienne obiektowe przechowują wskaźnik do obiektu. Gdy zmienna obiektowa zostanie przypisana do aplikacji Excel,
zawiera ona wskaźnik do aplikacji, a nie przechowuje całej aplikacji Excel. Gdy obiekty są przekazywane z jednej
procedury do drugiej, są one zawsze przekazywane przez „referencję”, a nie przez „wartość”.
327 Rozdział 18. ♦ Użycie automatyzacji Active X

Tworzenie egzemplarza aplikacji


Jeżeli aplikacja nie pracuje lub chcesz utworzyć nowy egzemplarz obiektu, użyj słowa kluczowego New. Poniższy przykład
tworzy nowy egzemplarz aplikacji Word.
' Deklaracja zmiennej objWord
Dim objWord As Word.Application

' Tworzenie nowego egzemplarza aplikacji Word


Set objWord = New Word.Application

Zawsze pisz wyrażenia Dim i Set w osobnych wierszach programu. Nie


łącz ich razem w jednym wierszu w następujący sposób:
Dim objWord = New Word.application

Jeżeli użyjesz takiej deklaracji, program będzie wykonywał się wolniej, a


Ty nie będziesz wiedział, kiedy zostanie utworzony obiekt.

Jednoczesne użycie funkcji GetObject i New


Jeżeli aplikacja jest uruchomiona, użyj jej, nie otwieraj kolejnego egzemplarza. Jeżeli nie jest uruchomiona, uruchom ją.
Aby zrealizować taki scenariusz, użyj funkcji GetObject, aby sprawdzić, czy aplikacja pracuje, i słowa kluczowego
New, aby ją uruchomić w razie potrzeby.
' Jeżeli Word pracuje, użyj go. Jeżeli nie, uruchom go.

' Deklaracja zmiennej obiektowej objWord


Dim objWord As Word.Application

' Gdy Word nie jest uruchomiony, wystąpi błąd. Ignorujemy go.

On Error Resume Next

' Próba odwołania się do pracującego Worda.


Set objWord = GetObject(, "Word.Application")

' Jeżeli zmienna objWord ma wartość Nothing (nieutworzona


' zmienna obiektowa), Word nie jest uruchomiony

If objWord Is Nothing Then


' Utwórz egzemplarz aplikacji
Set objWord = New Word.Application

' Jeżeli objWord nadal zawiera "Nothing" MS Word 9.0


' nie jest zainstalowany.

If objWord Is Nothing Then


MsgBox "MS Word 2000 nie jest zainstalowany"
End If
End If
' On Error GoTo ErrorNandler (Tu wstaw obsługę błędów)

Słowo kluczowe New może być użyte, gdy tworzysz odwołanie do biblio-
teki typów aplikacji.

Użycie wczesnego i późnego łączenia typów


Zauważ, że zmienna obiektowa w wyrażeniu Dim i Set odwołuje się do Word.Application. Taka deklaracja nazywana
jest wczesnym łączeniem typów. W czasie kompilacji zmienna obiektowa jest wiązana z biblioteką typów Worda. Skutkuje
to szybszym wykonywaniem tak napisanego fragmentu kodu, ponieważ większość czynności została wykonana w trakcie
kompilacji, a nie w trakcie wykonania.

Jeżeli zmienna objWord zostanie zadeklarowana jako Object, łączenie z biblioteką typów Worda nastąpi w trakcie
wykonania programu, co znacznie spowolni program.

Przykład poniższy przedstawia oba podejścia:


' Użycie wczesnego łączenia typów. Program jest szybszy.
Dim objWord as Word.Application

' Późne łączenie typów, taki program wykonuje się wolniej.


Dim objWord as Object
Część VI ♦ Współoperatywność 328

W pliku Automation.mdb załączonym do rozdziału 19., znajdują się przy-


kłady testów wydajności, które pokazują znaczną różnicę szybkości między
wczesnym i późnym łączeniem typów.

Użycie funkcji CreateObject


Aby uzyskać najwydajniejszy kod Automation, deklarujemy zmienne obiektowe jako obiekty specyficznych typów
(wczesne łączenie), używamy funkcji GetObject, aby sprawdzić czy aplikacja jest uruchomiona i przy użyciu New
tworzymy egzemplarz aplikacji w razie potrzeby.

Niestety, w niektórych przypadkach nie można użyć wczesnego łączenia typów lub słowa kluczowego New. W takich
okolicznościach może być pomocna funkcja CreateObject.

Kiedy nie można uzyskać odwołania do aplikacji


Gdy używamy Automation z niektórych aplikacji (na szczęście nie z Accessa), nie można utworzyć odwołania do innej
aplikacji (nie da się uzyskać odwołania do okna dialogowego). Przykładem jest Outlook 97/98 i aplikacje dla Internetu. W
takich wypadkach zmuszony jesteś użyć późnego łączenia typów i użycia funkcji CreateObject. Przykład poniższy
zawiera kod Automation, który należy użyć w programie Outlook, aby automatyzować Word.

Możesz używać funkcji GetObject, aby sprawdzić, czy jest uruchomiony


Word. Funkcja CreateObject tworzy nowy egzemplarz aplikacji.

' Deklaracja objWord jako zmiennej obiektowej.


Dim objWord As Word.Application

' Gdy Word nie jest uruchomiony, wystąpi błąd. Ignorujemy go.

On Error Resume Next

' Próba odwołania się do pracującego Worda.


Set objWord = GetObject(, "Word.Application")

' Wystąpi błąd nr 429, jeżeli Word NIE pracuje


If Err.Number = 429 Then
Err.Number = 0

' Utwórz nowy egzemplarz aplikacji


Set objWord = Create0bject("Word.Application")

' Gdy znowu wystąpi błąd 429, MS Word 9.0 nie jest zainstalowany.
If Err.Number = 429 Then
MsgBox "MS Word 2000 nie jest zainstalowany"
End If
End If
' On Error GoTo ErrorHandler (Tu wstaw obsługę błędów)

Co wtedy, gdy użytkownik ma inną wersję aplikacji?


W niektórych firmach użytkownicy mogą mieć zainstalowane różne wersje aplikacji. Niektórzy mogą używać Word 95
inni Word 97, podczas gdy jeszcze inni używają Worda 2000. Niektórzy z nich mogą mieć nawet zainstalowanych kilka
wersji Worda!

Do funkcji CreateObject można przekazać w parametrze, którą wersję aplikacji ma ona utworzyć. Przykład poniżej
przedstawia użycie CreateObject w celu uruchomienia Worda 97.
' Deklaracja zmiennej obiektowej objWord
Dim objWord As Word.Application

' Tworzenie egzemplarza aplikacji Word 97


Set objWord = Create0bject("Word.Application.8")

Numer wersji Office 95 to 7.0, Office 97 to 8.0, a Office 2000 to 9.0.


Możesz także przesyłać numer wersji przy użyciu New.
329 Rozdział 18. ♦ Użycie automatyzacji Active X

Użycie metod i właściwości obiektów automatyzacji


Po utworzeniu egzemplarza obiektu aplikacji możesz używać go w swoich programach, korzystając z metod i właściwości
obiektu.

Ustawianie właściwości obiektu


Teraz możesz korzystać z innych aplikacji, używając ich możliwości w swojej aplikacji. Tak samo jak korzystasz z
właściwości obiektu z Accessa, możesz używać właściwości obiektów automatyzacji. Poniższy przykład używa
właściwości w Wordzie i Excelu:
' Ustawianie właściwości obiektów Automation
objWord.Visible = True
objExcel.Cells(1,1).Value = "Sprzedaż roczna"

Wykonywanie metod obiektów


Używając automatyzacji, można wykonywać metody obiektów. Przykład:
' Wykonywanie metod Add obiektów.
objWord.Documents.Add
objExcel.Workbooks.Add

Zwalnianie obiektów automatyzacji


Gdy zakończyłeś pracę na zmiennej obiektowej, należy ją zwolnić, przypisując jej wartość Nothing. Zasoby zajmowane
przez zmienną zostaną wtedy zwolnione. Właściwa składnia przedstawiona jest na przykładzie:
' Zwalnianie zmiennej obiektowej
Set objWord = Nothing

Gdy deklarujesz zmienną obiektową, od razu przejdź na dół procedury i


przypisz jej wartość Nothing. Zabezpieczy Cię to przed tym, że zapomnisz
zwolnić zmienną obiektową po napisaniu długiej procedury.

Łączymy wszystko razem


Przedyskutowaliśmy wszystkie kroki potrzebne do uruchomienia automatyzacji w aplikacji. Teraz spójrzmy na przykład
programu, który łączy te kroki ze sobą. Przykład ten drukuje dokument Worda za pomocą automatyzacji. Przykład zawiera
wszystkie kroki przedstawione do tej pory: tworzenie lub pobranie odwołania do Worda, użycie obiektów Worda (a
dokładniej metody PrintOut) oraz zwolnienie obiektu automatyzacji.
' Deklaracja zmiennej obiektowej objWord
Dim objWord As Word.Application

' Gdy Word nie jest uruchomiony, wystąpi błąd. Ignorujemy go.
On Error Resume Next

' Pobranie odwołania do obiektu aplikacji Word


Set objWord = GetObject(, "Word.Application")

' Jeżeli zmienna objWord ma wartość Nothing (nieutworzona


' zmienna obiektowa), Word nie jest uruchomiony
If objWord Is Nothing Then
' Create a new instance of the Word application.
Set objWord = New Word.Application

' Jeżeli objWord nadal zawiera "Nothing" MS Word 9.0


' nie jest zainstalowany.
If objWord Is Nothing Then
MsgBox "MS Word 2000 nie jest zainstalowany"
End If
End If

' On Error GoTo ErrorHandler (Tu wstaw obsługę błędów)

' Otwórz dokument Worda


Część VI ♦ Współoperatywność 330

objWord.Documents.Open ("C:\Automation\Northwind Magazine Ad.doc")

' Wydrukuj dokument Worda


objWord.PrintOut Background:=False

' Zamknij aplikację Word


objWord.Quit

' Zwolnij zmienną obiektową


Set objWord = Nothing

Jest to bardzo prosty przykład. Rozdział 19. zawiera bardziej skomplikowane


programy używające automatyzacji, a także plik Automation.MDB
zawierający tysiące wierszy kodu automatyzacji, który możesz użyć w
Twoich aplikacjach.

Zamykanie aplikacji
serwera automatyzacji
Podczas nauki tworzenia sesji automatyzacji mogłeś użyć uruchomionego wcześniej egzemplarza aplikacji lub uruchomić
nowy egzemplarz. Ważne jest, aby zamykać serwer automatyzacji pod odpowiednimi warunkami.

Jeżeli aplikacja działa, gdy uruchamiasz sesję automatyzacji i używasz tego egzemplarza aplikacji, nie zamykaj aplikacji
podczas kończenia sesji. Użytkownicy będą bardzo sfrustrowani, jeżeli ich aplikacja zostanie zakończona przez Twój
program.

Jeżeli utworzyłeś nowy egzemplarz aplikacji, powinieneś zamknąć go po zakończeniu pracy. Jeżeli tego nie zrobisz,
aplikacja pozostanie otwarta, nieużywana przez użytkownika, ale zajmująca cenne zasoby systemu.

Aby zakończyć aplikację, użyj właściwej metody dla aplikacji. Przykładowo, dla Excela wywołaj metodę Quit, tak jak
pokazane jest na przykładzie:
' Zamknij aplikację Excel poprzez wywołanie jej metody Quit.
objExcel.Quit

Użycie właściwości UserControl do sprawdzenia, w jaki sposób


została otwarta aplikacja
Właściwość UserControl umożliwia sprawdzenie, czy aplikacja lub dokument został utworzony lub otwarty przez
użytkownika, czy w sposób programowy. Jeżeli właściwość UserConrol (zmienna logiczna) zawiera wartość true,
aplikacja lub dokument został otwarty przez użytkownika. Jeżeli zawiera false, aplikacja lub dokument został otwarty
programowo.

Przykład poniższy otwiera Worda i sprawdza, w jaki sposób został otwarty, używając właściwości UserControl.
' Deklaracja zmiennej obiektowej objWord.
Dim objWord As Word.Application

' Otwarcie programowe Worda.


Set objWord = New Word.Application

' Sprawdzenie właściwości UserControl, aby stwierdzić, czy Word


' został otwarty programowo, czy przez użytkownika
If objWord.Application.UserControl Then
MsgBox "Word został otwarty przez użytkownika"
Else
MsgBox "Word został otwarty programowo".
End If

Set objWord = Nothing


331 Rozdział 18. ♦ Użycie automatyzacji Active X

Użycie WithEvents w celu udostępnienia zdarzeń serwera


automatyzacji
Użycie automatyzacji w sposób pokazany do tej pory można porównać do jednostronnej rozmowy telefonicznej. Access
kontrolował Worda i nakazywał wykonanie pewnych czynności. Przez użycie klauzuli WithEvents możesz utworzyć
dwukierunkową komunikację pomiędzy Accessem i Wordem. Access może zlecać do Worda drukowanie dokumentu lub
raportu, Word natomiast odpowiada Accessowi po wystąpieniu odpowiedniego zdarzenia.

Na początku należy sprawdzić, jakie zdarzenia są udostępniane przez aplikację. Najprostszą metodą dowiedzenia się tego,
jest użycie narzędzia Object Browser. Po wybraniu obiektu aplikacji możesz przeglądać udostępniane zdarzenia. Word 97
posiada tylko dwa zdarzenia udostępniane przez obiekt Application (DocumentChange i Quit). Word 2000 ma 12
zdarzeń udostępnianych przez obiekt Application. Są one pokazane na rysunku 18.4 w Object Browser. Gdy
przeglądamy zawartość obiektów, różne ikony wskazują właściwości (palec wskazujący kartkę papieru), metody (zielona
latająca gumka) i zdarzenia (błyskawica).
Rysunek 18.4.
Object Browser
pokazujący
zdarzenia
udostępnione
przez Microsoft
Word 2000

Microsoft Excel udostępnia więcej zdarzeń niż Word. Obiekt aplikacji Excel 2000 posiada 21 zdarzeń (rysunek 18.5).

Rysunek 18.5.
Object Browser
pokazujący
zdarzenia
udostępnione
przez Microsoft
Excel 2000

Uruchamiamy WithEvents
Normalnie, gdy używamy automatyzacji w procedurze, deklarujesz zmienną obiektową w następujący sposób:
Dim objWord as Word.application

Aby użyć WithEvents, usuń deklarację zmiennej z procedury i zamiast niej utwórz zmienną modułową. Słowo kluczowe
Dim powinieneś zmienić na Private lub Public. Należy również dodać klauzulę WithEvents, aby udostępnić zdarzenia
aplikacji.
Część VI ♦ Współoperatywność 332

' Deklaracja zmiennej modułu używająca klauzuli WithEvents


Private WithEvents objWord as Word.Application

Klauzula WithEvents może być używana tylko w modułach klasowych


(moduł formularza jest modułem klasowym). WithEvents nie może być
używane w zwykłych modułach.

Rysunek 18.6 przedstawia w jaki sposób zadeklarować zmienną modułową z użyciem klauzuli WithEvents.

Rysunek 18.6.
Deklaracja zmiennej
modułowej przy
użyciu klauzuli
WithEvents

Po zadeklarowaniu zmiennej modułowej przy użyciu klauzuli WithEvents sprawdź zawartość list wyboru na górze okna
modułu. W liście wyboru z lewej strony okna wybierz zadeklarowaną wcześniej zmienną, która reprezentuje serwer
automatyzacji. W prawej liście wyboru zobaczysz zdarzenia udostępniane przez aplikację. Po wybraniu zdarzenia w oknie
programowania pojawia się szkielet procedury, która jest wywoływana po zajściu zdarzenia. Możesz teraz wypełnić tę
procedurę kodem wykonywanym w odpowiedzi na zdarzenie. Na rysunku 18.7 pokazane są procedury używające udo-
stępnionych przez Worda zdarzeń DocumentChange i Quit.

Rysunek 18.7.
Procedury
używające
udostępnionych
zdarzeń programu
Microsoft Word

Techniki i wskazówki do automatyzacji


Od dawna automatyzacja nie ma dobrej opinii z powodu słabej wydajności. Używając rozsądnego sprzętu i właściwych
technik kodowania, automatyzacja może pracować wydajnie. Zapamiętaj poniższe porady, gdy będziesz programował
automatyzację.

Ustanowienie odwołania,
użycie wczesnego wiązania typów
i słowa kluczowego New
Aby rozpocząć sesję automatyzacji, ustaw odwołanie do aplikacji w oknie dialogowym odwołań. Używaj szczegółowych
klas w trakcie deklaracji zmiennych obiektowych oraz słowa kluczowego New, aby utworzyć egzemplarz obiektu aplikacji.

Wszystkie te zagadnienia były już wcześniej omawiane.


333 Rozdział 18. ♦ Użycie automatyzacji Active X

Użycie istniejącego egzemplarza aplikacji,


jeżeli jest ona uruchomiona
Nie otwieraj nowego egzemplarza aplikacji w każdej sesji automatyzacji. Jeżeli aplikacja jest uruchomiona, użyj
istniejącego egzemplarza w sesji automatyzacji.

Wyłącz odświeżanie ekranu


Podczas typowej sesji automatyzacji z użyciem Excela czy Worda następuje ogromna ilość odświeżeń ekranu. Zawsze,
gdy ważna jest dla nas wydajność, przełączaj ScreenUpdating na False. Wydajność się polepszy, gdyż nie będzie
konieczne odświeżanie ekranu.

Najlepszą techniką jest przełączenie ScreenUpdating na False, wykonanie pracy przez automatyzację i na koniec
przełączenie ScreenUpdating na True. Użytkownik zobaczy kompletny dokument, kiedy zostanie wykonany.

Poniższy przykład przedstawia tę technikę.


' Wyłącz odświeżanie ekranu
Application.ScreenUpdating = False

' Tutaj jest przetwarzanie przez automatyzację

' Włącz odświeżanie ekranu


Application.ScreenUpdating = False

Pewnego razu omyłkowo zainstalowałem użytkownikom aplikację z włą-


czonym odświeżaniem ekranu, co spowalniało aplikację. W następnej
wersji odświeżanie zostało wyłączone. Dostałem tak wiele skarg od użyt-
kowników, że dokonałem korekty i dałem im wersję znowu z włączonym
odświeżaniem ekranu. Użytkownicy wyjaśniali, że gdy był odświeżany
ekran, mieli możliwość przeczytania dokumentu, rozpoczęcia korekty lub
upewnienia się, że wybrali właściwy dokument do druku. Przez zmuszenie
użytkowników do czekania aż cały dokument będzie gotowy, tracili oni
trzy do pięciu sekund czasu poświęcanego na korektę. Uważali również, że
jest to coś ciekawego, oglądać jak dokument jest tworzony fragment po
fragmencie w „magiczny” sposób. Zatem należało tu rozpatrzyć „czas
przetwarzania” człowieka przy przeglądaniu dokumentu, a nie tylko czas
przetwarzania komputera.

Informacja o przetwarzaniu
Jeżeli sesja automatyzacji trwa przez dłuższy czas, na pewno musisz informować użytkownika o trwającym procesie.
Można użyć paska postępu, klepsydry jako kursora myszy lub innego graficznego wskaźnika. Jeżeli tego nie zrobisz,
użytkownik może pomyśleć, że komputer się zawiesił i wyłączyć go. Pamiętaj, że w pracy poprzez automatyzację
uruchomiona jest więcej niż jedna aplikacja, więc niszczące skutki takiego wyłączenia mogą być znaczne.

Jako programista wiesz, że wyświetlanie informacji w trakcie przetwarzania spowalnia sam proces przetwarzania.
Jednak ważniejszy jest nie całkowity czas, jaki zajmie ukończenie procesu, ale czas „widziany”. Użytkownicy uważają,
że przetwarzanie trwa krócej, gdy widoczne są wskaźniki zaawansowania procesu, choć naprawdę trwa to nieco dłużej.

Tworzyłem aplikację dla firmy lotniczej, która wymagała wykonania


skomplikowanego kodu automatyzacji Excela. W trakcie przetwarzania
mała ikona samolotu przesuwała się po ekranie. Użytkownicy byli bardziej
zainteresowani tym małym samolocikiem lecącym przez ich ekran niż
skomplikowanym programem wykonującym dla nich pracę.
Część VI ♦ Współoperatywność 334

Wykonywanie programu przez serwer automatyzacji


Program zawsze działa szybciej, jeżeli serwer automatyzacji wykonuje swój kod. Przykładowo, jeżeli Twoja aplikacja
Accessa używa Worda, na początku utwórz egzemplarz obiektu dokumentu Worda. Następnie umieść cały kod VBA, który
zajmuje się manipulowaniem Wordem (zmiany czcionek lub stylu tekstu, drukowanie dokumentu) w Wordzie.

Inaczej mówiąc, niech aplikacja uruchamia własny kod. Jeżeli używane są obiekty, właściwości i metody Worda, umieść je
w kodzie VBA w Wordzie. W przeciwnym wypadku komunikacja między procesami Accessa i Worda będzie nawiązywana
dla każdego wyrażenia w kodzie programu. Używając tej techniki, istotnie polepszysz wydajność.

Kod VBA w aplikacjach Word i Excel umieszczony jest w szablonach. Aby


ułatwić rozprowadzanie szablonów, umieść je w udostępnionym katalogu
na serwerze plików. W menu Narzędzia, Opcje, na zakładce Położenie
plików można ustawić położenie szablonów grupy roboczej na ten sieciowy
katalog. Gdy potrzebne są zmiany w kodzie lub dodajesz nowy szablon,
kopiujesz pliki tylko do jednego katalogu na serwerze.

Użycie konstrukcji With/End With


Są dwa powody, aby używać konstrukcji With/End With. Po pierwsze, kod działa szybciej, ponieważ odwołanie do
obiektu jest wykonywane tylko raz. Drugi powód to czytelność kodu. Pomyśl o każdej kropce jak o ograniczniku prędkości
na drodze. Im mniej kropek, tym lepiej! Porównaj dwa poniższe przykłady:

Przykład 1. Odwołanie do obiektu jest wykonywane w każdym wierszu kodu, co powoduje jego spowolnienie. Kod jest
trudniejszy do czytania.
objExcel.Range("F6").Select
objExcel.ActiveCell.FormulaRlC1 = "Sprzedaż roczna"
objExcel.Range("G6").Select
objExcel.ActiveCell.FormulaRlC1 = "Podsumowanie sprzedaży"
objExcel.Range("F7").Select

Przykład 2. Odwołanie do obiektu jest wykonywane tylko raz, co powoduje przyspieszenie kodu. Łatwiej się go czyta.
With objExcel
.Range("F6").Select
.ActiveCell.FormulaRlC1 = "Sprzedaż roczna"
.Range("G6").Select
.ActiveCell.FormulaRlC1 = "Podsumowanie sprzedaży"
.Range("F7").Select
End With

Zwalnianie zmiennych obiektowych


Tak jak wcześniej o tym mówiliśmy, zawsze zwalniaj zmienne obiektowe na końcu sesji automatyzacji przez przypisanie
im wartości Nothing, aby odzyskać zasoby.

Nie wyświetlaj okien dialogowych i komunikatów


Unikaj operacji, które zatrzymują sesję automatyzacji, takich jak okna dialogowe lub okna komunikatów. Jeżeli nastąpi
zatrzymanie, może nie być widoczne przez użytkownika, ponieważ inna aplikacja posiada w tym czasie fokus.

Używaj obsługi błędów


Automatyzacja komplikuje Twoje aplikacje. Zalety użycia właściwości innych aplikacji są ograniczane przez to, że więcej
rzeczy może źle zadziałać. Istotne jest, aby obsłużyć wszystkie błędy, które mogą zdarzyć się w trakcie sesji automatyzacji.
W aplikacjach Microsoft Office aplikacja serwera może zwracać informacje o błędach. Popatrz do rozdziału 13.
„Profesjonalna obsługa błędów”, aby znaleźć informacje na temat obsługi błędów.
Rozdział 19.
Integracja z Office 2000
W tym rozdziale:
u Powody integracji z Office 2000.
u Wybór właściwego narzędzia.
u Wszędzie VBA.
u Użycie rejestratora makr do pisania kodu.
u Użycie makr automatycznych.
u Microsoft Forms.
u Object Browser.
u Nazwy klas aplikacji Office.
u Przykład Automation.
u Automatyzacja Worda.
u Automatyzacja Excela.
u Automatyzacja PowerPoint.
u Automatyzacja Outlooka.
u Automatyzacja Graph.
u Automatyzacja MapPoint.
u Automatyzacja FrontPage.
u Automatyzacja Binder.
u Zabezpieczanie dokumentów, szablonów i kodu.

W poprzednim rozdziale zostały przedstawione zasady i techniki użycia automatyzacji. Teraz zastosujemy tę wiedzę,
używając wszystkich aplikacji w pakiecie Microsoft Office 2000.

W rozdziale tym zapoznamy się ze sposobami użycia w Accessie innych aplikacji firmy Microsoft, takich jak: Word,
Excel, PowerPoint, Outlook, Graph, MapPoint, FrontPage oraz Binder.

Zajrzyj do przykładów kodu dla tego rozdziału. Jest tam wiele wierszy
kodu automatyzacji dla programistów Access, Excel, PowerPoint, Outlook,
Graph, FrontPage i MapPoint (rysunek 19.1).
Część VI ♦ Współoperatywność 336

Rysunek 19.1.
Plik
Automation.MDB

Powody integracji z Office 2000


Office 2000 jest pełnym pakietem produktów będącym odpowiedzią na oczekiwania i potrzeby klientów. Produkty te
oferują ogromną ilość opcji, które zostały napisane i przetestowane przez Microsoft. Office 2000 udostępnia setki
obiektów, którymi programista może manipulować przy użyciu VBA. Żaden inny pakiet biurowy w chwili obecnej nie
zapewnia takiej siły i integracji, jaką oferuje Office 2000.

Aby utworzyć kompletną aplikację, możesz użyć wielu możliwości aplikacji Office 2000 opisanych poniżej.

Użycie Worda
Word jest doskonałym wyborem, aby tworzyć faktury, listy, notatki i raporty. Word jest wspaniałym edytorem raportów.

Jako programista, możesz tworzyć ozdobne dokumenty w Accessie lub Excelu, ale czemu ponosić taki wysiłek? Word ma
wszystkie style i możliwości formatowania, jakich kiedykolwiek będziesz potrzebował.

Użycie Excela
Jeżeli potrzebujesz przetwarzać liczby, Excel jest świetnym wyborem. Możesz tworzyć imponujące wykresy i diagramy na
spotkania służbowe, negocjacje z klientami, zebrania rady nadzorczej itp.

Użycie PowerPoint
Gdy przychodzi czas na pokaz, użyj PowerPoint. Robiące wrażenie, wysokiej jakości prezentacje mogą być utworzone
relatywnie łatwo. Utwórz efektywne demonstracje dla sprzedaży produktów, zebrań personelu lub dyrekcji, prezentacje dla
inwestorów itp.

Użycie Outlooka
Outlook dostarcza licznych funkcji, które możesz włączyć do Twojej aplikacji. Użyj poczty Outlooka do poczty
korporacyjnej, internetowej, automatycznej wysyłki zamówień do działów ekspedycji, automatycznego zamawiania
produktów w razie potrzeb, fakturowania klientów i innych funkcji.

Zamiast tworzyć kalendarz w swojej aplikacji, możesz podłączyć się do tej funkcji z Outlooka. Pracownicy mogą
prowadzić swoje kalendarze, jak również kalendarze biurowe.

Outlook zapewnia zarządzanie zadaniami, które mogą być użyte do stworzenia list zadań do wykonania przez
pracowników, listy zadań do wykonania przez oddział, specjalnych projektów, itd.
337 Rozdział 19. ♦ Integracja z Office 2000

Kontakty Outlooka umożliwiają utworzenie prywatnych list adresowych, jak również wspólnych dla biura. Oczywiście
bazę zarządzania kontaktami można utworzyć w Accessie, ale Outlook jest gotowy do użycia natychmiast.

Użycie Graph
Microsoft Graph jest użytecznym narzędziem do tworzenia wykresów w Accessie i innych aplikacjach Office.

Użycie MapPoint
MapPoint jest narzędziem do szukania i wyświetlania informacji na mapach. Za pomocą automatyzacji adres może być
odczytany z bazy danych, a następnie zostanie wyświetlona mapa przedstawiająca dokładne położenie adresu.

Użycie FrontPage
Sieć jest istotna w dzisiejszym świecie biznesu. Użyj FrontPage do tworzenia i modyfikacji stron WWW oraz do innych
zastosowań sieciowych.

Użycie Bindera
Office Binder dostarcza sposobu integracji dokumentów Office za pomocą zunifikowanego narzędzia. Za pomocą
automatyzacji dokumenty Worda, Excela i PowerPointa mogą być łączone w Binderze, więc użytkownicy będą mogli
pracować z wszystkimi dokumentami jednocześnie.

Wszystkie dokumenty mogą być zapisane w formacie Bindera, więc kiedykolwiek użytkownik będzie chciał pracować na
nich znowu, to otworzy Binder, gdzie wszystkie te dokumenty będą w wygodny sposób dostępne.

Wybór właściwego narzędzia


Pierwszym i prawdopodobnie najistotniejszym wyborem, jakiego dokonano programista, jest odpowiedź na pytanie „Jakiego
narzędzia powinienem użyć do stworzenia tej opcji?”.

Przeciwstaw się pokusom stworzenia wszystkiego w Accessie, ponieważ najlepiej znasz tę aplikację. VBA jest teraz
dostępny we wszystkich produktach Office. Teraz jest dużo łatwiej niż kiedyś przestawić się na Worda czy Excela i szybko
poczuć się komfortowo w czasie programowania.

Pomyśl o automatyzacji jak o zestawie usług, które możesz włączyć do swojej aplikacji:
u Access – usługi baz danych.
u Word – edycja tekstu i usługi małej poligrafii.
u Excel – obliczenia i usługi finansowe.
u PowerPoint – prezentacje
u Outlook – poczta, kalendarz, kontakty, zadania i inne usługi.
u Graph – wykresy i schematy.
u MapPoint – usługi związane z mapami.
u FrontPage – usługi tworzenia stron internetowych.
u Binder – usługi łączenia dokumentów.

Wszędzie VBA
Visual Basic for Applications (VBA) jest potężnym językiem programowania, który istnieje wewnątrz programów Office.
Ta unifikacja języka programowania pozwala programistom na łatwe łączenie aplikacji Office w zunifikowane rozwiązania
programowe.
Część VI ♦ Współoperatywność 338

Użycie rejestratora makr do pisania kodu


Rejestrator makr jest doskonałym generatorem kodu i może być użyty do błyskawicznego programowania w Wordzie,
Excelu i PowerPoincie. Aby uruchomić rejestrator makr w tych aplikacjach, wybierz Makro z menu Narzędzia, a następnie
Zarejestruj nowe makro (rysunek 19.2).

Rysunek 19.2.
Okno dialogowe
rejestratora makr

Po wywołaniu rejestratora makr, wpisz nazwę makra i naciśnij OK, aby rozpocząć proces rejestracji. Na ekranie widoczny
będzie mały pasek narzędzi zawierający dwa przyciski. Przesuwając kursor myszy nad tymi przyciskami, możesz zobaczyć, że
jest to zatrzymanie i pauzowanie rejestrowania. Dodatkowo, aby zasygnalizować, że działa rejestrator makr, przy kursorze
myszy widoczna jest mała kaseta magnetofonowa (rysunek 19.3).

Rysunek 19.3.
Dokument Worda
z pracującym
rejestratorem makr

W czasie pracy rejestratora wszystkie czynności, jakie wykonasz zostaną skonwertowane do kodu VBA. Możesz wpisywać
tekst do dokumentu, formatować go a nawet zapisywać i drukować. Gdy zakończysz czynności, które miały być
zarejestrowane, naciśnij przycisk Zatrzymaj rejestrowanie. Aby zobaczyć kod VBA, jaki został zapisany przez rejestrator,
wybierz Makro z menu Narzędzia i z następnego menu Makra. Wybierz zapisane przez siebie makro i naciśnij przycisk
Edytuj. Otworzy się edytor VBA, pokazując kod realizujący makro (rysunek 19.4).

Rysunek 19.4.
Kod VBA
wygenerowany przez
rejestrator makr
w edytorze VBA
339 Rozdział 19. ♦ Integracja z Office 2000

Rejestrator makr nie zawsze generuje optymalny kod, więc zawsze należy
go przejrzeć przed użyciem w aplikacji. Dodanie konstrukcji With/ End
With jest również dobrym pomysłem.

Użycie makr automatycznych


Word, Excel i PowerPoint zawierają mechanizm makr automatycznych. Mogą być one użyte do uruchamiania programu po
zajściu określonych zdarzeń. Przykładowo, w Wordzie istnieją następujące makra automatyczne:
u AutoExecute – jest wykonywane w czasie uruchamiania Worda;
u AutoNew – jest wykonywane podczas tworzenia nowego dokumentu;
u AutoOpen – jest wykonywane podczas otwierania dokumentu;
u AutoClose – jest wykonywane podczas zamykania dokumentu;
u AutoExit – jest wykonywane podczas zamykania Worda.

Aby użyć tych makr należy za pomocą VBA utworzyć w module funkcję o nazwie odpowiedniego makra automatycznego.
Przykładowo, aby utworzyć makro automatyczne AutoOpen, powinieneś utworzyć taką procedurę:
Private/Public Sub AutoOpen ()
' Kod wykonywany podczas otwierania dokumentu
End Sub

Microsoft Forms
Programy Office: Word, Excel i PowerPoint używają oddzielnego modułu formularzy Microsoft Forms. Niekiedy, gdy
używasz innych aplikacji, takie formularze mogą się przydać.

Doświadczeni programiści Accessa nie będą mieli trudności w użyciu Microsoft Forms. Tworzenie formularza, używając
Microsoft Forms, przebiega według następującego scenariusza. Z menu Insert wybierz User Form lub naciśnij Shift+F7.
Używając paska narzędzi, dodaj na formularz formanty. Napisz obsługę komunikatów formularza i formantów, używając
VBA. Do formularza takiego można również dodać formanty ActiveX.

Microsoft Forms są oddzielne od formularzy Accessa, Visual Basica


i Outlooka. Jest to osobny pakiet. Nie można konwertować formularzy
Accessa do Microsoft Forms i odwrotnie

Object Browser
Gdy pracujesz z różnymi aplikacjami omawianymi w tym rozdziale, nie zapominaj o użyciu narzędzia Object Browser.
W poprzednim rozdziale szczegółowo omówiłem, jak go używać.

Aby wywołać Object Browser, w oknie edytora VBA wybierz Object Browser z menu View lub naciśnij F2 (rysunek 19.5).
Część VI ♦ Współoperatywność 340

Rysunek 19.5.
Object Browser
wyświetlający
obiekty Worda

Nazwy klas aplikacji Office


Aby użyć innych aplikacji Office, musisz znać nazwy klas występujących w tych aplikacjach:

Aplikacja Nazwa klasy


Access Access.Application

Binder Office.Binder

Excel Excel.Application

Excel.Sheet

Excel.Chart

FrontPage FrontPage.Application

Graph Graph.Application

MapPoint MapPoint.Application

Outlook Outlook.Application

PowerPoint PowerPoint.Application

Word Word.Application

Word.Document

Przykład automatyzacji
Podstawy automatyzacji (przykładowo dla Worda: tworzenie lub pobieranie odwołania do Worda, użycie obiektów Worda,
zwalnianie obiektu) zostały przedstawione w poprzednim rozdziale.

Przykład poniższy drukujący informacje o Accessie w postaci dokumentu Worda ilustruje wszystkie wymienione kroki. Nie
zapomnij ustawić wcześniej odwołania do Worda.
Private Sub AccessApplicationReport()

Dim objWord As Word.Application

DoCmd.Hourglass True

' Przejdz do następnego wiersza w przypadku błędu


On Error Resume Next

' Próba pobrania odwołania do pracującego Worda


Set objWord = GetObject(, "Word.Application")

' Word nie działa


If objWord Is Nothing Then
' Utwórz nowy egzemplarz Worda
Set objWord = New Word.Application
341 Rozdział 19. ♦ Integracja z Office 2000

' Jeżeli objWord jest Nothing to znaczy, że nie da się


' uruchomić Worda
If objWord Is Nothing Then
MsgBox "MS Word 8.0 nie jest zainstalowany"
End If
End If

' On Error GoTo ErrorHandler (Tu wstaw obsługę błędów)


' Otwórz nowy dokument oparty na szablonie Normal.dot
objWord.Documents.Add

' Przełączenie się na Worda


objWord.Activate

' Pokazujemy Worda użytkownikowi


objWord.Visible = True

' Tworzenie nagłówka raportu


With objWord.Selection
.TypeText vbTab & vbTab & "Raport o aplikacji Accessa"
.StartOf Unit:=wdStory, Extend:=wdExtend
.Font.Bold = True
.Font.Size = 20
.EndKey Unit:=wdLine
.TypeParagraph
.TypeParagraph
.Font.Bold = False
.Font.Size = 16
End With

' Wstaw informacje o tej aplikacji Accessa do dokumentu Worda


With objWord.Selection
.TypeText "Obiekt aplikacji" & vbTab & "Wartość" & vbCrLf
.TypeText "Nazwa i ścieżka do bazy" & vbTab & _
Application.CurrentDb.Name & vbCrLf
.TypeText "Nazwa bieżącego formularza" & vbTab & _
Forms.Item(0).Name & vbCrLf
.TypeText "Nazwa bieżącego obiektu" & vbTab & _
Application.CurrentObjectName & vbCrLf
.TypeText "Nazwa bieżącego użytkownika" & vbTab & _
Application.CurrentUser & vbCrLf
.TypeText "Wersja Jet" & vbTab & _
Application.DBEngine.Version & vbCrLf
.TypeText "Kompilacja aplikacji" & vbTab & _
Application.IsCompiled & vbCrLf
.TypeText "Ilość odwołań" & vbTab & _
Application.References.Count & vbCrLf
.TypeText "Kursor myszy" & vbTab & _
Application.Screen.MousePointer & vbCrLf
.TypeText "User Control" & vbTab & Application.UserControl & _
vbCrLf
.TypeText "Widoczność aplikacji" & vbTab & Application.Visible & _
vbCrLf
.StartOf Unit:=wdStory
.MoveDown Unit:=wdLine, Count:=2
.StartOf Unit:=wdLine
.EndOf Unit:=wdStory, Extend:=wdExtend
.ConvertToTable Separator:=wdSeparateByTabs, NumColumns:=2, _
NumRows:=11, Format:=wdTableFormatColorful2, _
ApplyBorders:=True, ApplyShading _
:=True, ApplyFont:=True, ApplyColor:=True, _
ApplyHeadingRows:=True, ApplyLastRow:=False, _
ApplyFirstColumn:=False, ApplyLastColumn:=False, _
AutoFit:=True, AutoFitBehavior:=wdAutoFitFixed
.EndOf Unit:=wdStory
End With

' Wyłącz pokazywanie znaków końca akapitu


objWord.ActiveWindow.ActivePane.View.ShowAll = False

DoCmd.Hourglass False

' Zwolnij obiekt


Set objWord = Nothing

End Sub

Automatyzacja Worda
W tej części opiszę specyficzne zagadnienia i przykłady automatyzacji Worda.
Część VI ♦ Współoperatywność 342

Model obiektów Worda


Poprzedni przykład przedstawia program, zawierający wszystkie operacje potrzebne do automatyzacji. Skupię się teraz na
opisie obiektów, właściwości i metod dostępnych w Wordzie. Model obiektów jest w tym względzie bardzo pomocny.

Model obiektów jest szablonową reprezentacją obiektów aplikacji. Jest to szybka i łatwa metoda poznania obiektów, które
można użyć do programowania.

Spójrz do „Obiekty Microsoft Word” w pliku pomocy. Zamieszczony jest


tam diagram struktury obiektów w Wordzie.

Model Worda jest dosyć obszerny. Zawiera on ponad 180 obiektów dostępnych poprzez VBA. Często używane obiekty
Worda zebrane są w tabeli 19.1. Nazwy obiektów, które są kolekcjami mają końcówkę (s).

Tabela 19.1.
Obiekty Worda

Obiekt Worda Opis


Application Aplikacja Word. Zwykle nie potrzebujesz odwoływać się do tego obiektu
z Worda. Jeżeli używasz Worda z innej aplikacji, musisz użyć tego obiektu
AutoCaption(s) Automatycznie dodawane nagłówki
AutoCorrect Funkcja Autokorekta
Character Znaki w otwartym dokumencie
CommandBar(s) Poszczególne paski narzędzi dostępne są poprzez indeks lub nazwę
DefaultWebOptions Domyślne ustawienia dla publikowania lub zapisywania jako strona WWW
Dialog(s) Okna dialogowe
Dictionary(s) Słowniki w Wordzie
Document(s) Otwarte dokumenty. Można się do nich odwoływać przez indeks lub nazwę
Email Przesyłka e-mail dla dokumentu

Tabela 19.1.
Obiekty Worda (ciąg dalszy)

Obiekt Worda Opis


EmailSignature Informacja o podpisie przesyłki e-mail
Find Obiekt używany do przeszukiwania słów, zakresów itd.
Paragraphs Kolekcja akapitów.
Range Zdefiniowany punkt początkowy i końcowy akapitu. Dokument może zawierać
kilka zakresów
Replacement Obiekt określający warunki zastępowania
Selection Zaznaczony tekst. Może być tylko jeden zaznaczony fragment tekstu
w dokumencie
Table(s) Pojedyncza tabela
Template(s) Szablon dokumentu
WebOptions Ustawienia nadpisujące DefaultWebOptions
Window(s) Okna dokumentów. Poszczególne okna dostępne są przez indeks lub nazwę
Words Kolekcja słów

Użycie szablonów Worda


Jak mówiłem w poprzednim rozdziale, kod automatyzacji działa szybciej, gdy jest wykonywany przez serwer
automatyzacji. Inaczej mówiąc, gdy używamy obiektów Worda, kod VBA powinien być umieszczony w szablonie Worda
zamiast w Accessie.
343 Rozdział 19. ♦ Integracja z Office 2000

Aby utworzyć szablon Worda, otwórz nowy dokument Worda. Po wpisaniu potrzebnego kodu VBA wybierz Zapisz jako z
menu Plik, aby zapisać ten dokument jako szablon dokumentu (rozszerzenie .DOT).

Aby dodać kod do szablonu użyj Rejestratora Makr w sposób omówiony wcześniej. Uruchom Rejestrator, wykonaj
czynności które chcesz automatyzować a Rejestrator Makr utworzy dla Ciebie kod VBA.

Jak uruchomić kod VBA Worda z Accessa? Jest to bardzo proste. Należy użyć metody Run.
' Uruchom makro w Wordzie formatujące dokument
objWord.Run "FormatDocument"

Uruchamianie tego makra przez Worda jest dużo szybsze, ponieważ komunikacja między procesami musi zachodzić dla
każdej instrukcji automatyzacji. Dzięki umieszczeniu kodu w Wordzie, jest on uruchamiany przez jeden proces.

W pliku dołączonym do tego rozdziału znajdują się przykłady używające


tego samego kodu automatyzacji w Accessie i przedstawia szablon Worda.
Stoper pokazuje różnicę szybkości. Umieszczenie kodu w Wordzie
powoduje znaczną różnicę szybkości.

Mimo że program działa szybciej, gdy umieścimy go w szablonie Worda, czy nie będzie to sprawiało problemów
instalacyjnych? Nie, jeżeli zrobimy to odpowiednio. Szablony można zapisywać na każdej stacji roboczej lub jako
szablony grupy roboczej na serwerze. Zaletą zapisywania szablonów do katalogu szablonów grupy jest to, że gdy
zmienimy szablon, należy go skopiować tylko do współdzielonego katalogu na serwerze. Jednak, gdy używamy szablonów
grupy, następuje komunikacja przez sieć. Niektórzy programiści tworzą proste aplikacje, które kopiują szablony z serwera
do każdej stacji roboczej podczas startu aplikacji.

Aby zapewnić użytkownikom dostęp do szablonów grupy (na serwerze), wybierz Opcje z menu Narzędzia. Na zakładce
Położenie plików wpisz ścieżkę do katalogu szablonów grupy (patrz rysunek 19.6).

Rysunek 19.6.
Położenie plików
w opcjach Worda

Wstawianie danych do dokumentu Worda


Word jest wspaniałym edytorem raportów. Dane korporacyjne mogą być prezentowane w postaci dokumentów możliwych
do modyfikacji przez użytkowników. Poniższy przykład przedstawia gazety reklamowe (rysunek 19.7.).

Istnieją trzy sposoby, aby wysłać dane z bazy danych Accessa lub serwera SQL do dokumentu Worda: korespondencja
seryjna, zakładki oraz zastępowanie. Przykłady w tym rozdziale używają wszystkich tych sposobów.

Korespondencja seryjna
Użytkownicy często używają do tworzenia dokumentów korespondencji seryjnej. Można to także zrobić przy użyciu
automatyzacji.

Preferowaną metodą integracji z Wordem przy użyciu użycia automatyzacji jest korespondencja seryjna.
Część VI ♦ Współoperatywność 344

Rysunek 19.7.
Tworzenie raportów
w Wordzie

Aby stworzyć kod automatyzacji korespondencji seryjnej, uruchom rejestrator makr i wykonaj wszystkie kroki, które
wykonuje użytkownik w celu utworzenia takiego dokumentu. Wybierz Korespondencja seryjna z menu Narzędzia i
zrealizuj wszystkie kroki w pomocniku korespondencji seryjnej.

Gdy wybierasz źródło danych do połączenia z dokumentem, możesz wybrać tabelę Accessa lub kwerendę ze źródła
danych. Powinieneś wiedzieć, że jeżeli umieścisz dane w pliku RTF i użyjesz tak spreparowanego pliku jako źródło
danych, kod automatyzacji będzie działał wyraźnie szybciej.

Najważniejszą zaletą korespondencji seryjnej jest to, że użytkownicy mogą wstawiać pola danych do dokumentu. Pozwala
to użytkownikom na tworzenie swoich dokumentów, a także odciąża programistów od potrzeby tworzenia raportów.
Poprawnie zaprojektowane przez programistę szablony dokumentów zawierają odpowiednie pola danych, na podstawie
których użytkownicy mogą utworzyć swoje raporty (rysunek 19.8).

Rysunek 19.8.
Tworzenie raportów
przez użytkowników

Przykład procedury uruchamiającej korespondencję seryjną zaczerpnięty z pliku z przykładami do tego rozdziału:
Private Sub RunMailMerge()

With ActiveDocument.MailMerge
.MainDocumentType = wdFormLetters
ActiveDocument.MailMerge.OpenDataSource Name:= _
"C:\Automation\Automation.MDB", ConfirmConversions:=False, _
ReadOnly:=False, LinkToSource:=True, AddToRecentFiles:=False, _
PasswordDocument:="", PasswordTemplate:="", _
WritePasswordDocument:= ", WritePasswordTemplate:="", _
Revert:=False, Format:=wdOpenFormatAuto, _
Connection:="QUERY qryEmployeeLetters", SQLStatement:= _
"SELECT * FROM [qryEmployeeLetters]", SQLStatement1:=""
.Destination = wdSendToNewDocument
.Execute
End With

End Sub
345 Rozdział 19. ♦ Integracja z Office 2000

Zakładki
Inną metodą wstawiania danych do dokumentów Worda jest użycie zakładek. Zakładka w dokumencie jest oznaczeniem
miejsca, gdzie będą wstawione dane. W czasie wykonania programu wyszukiwane są kolejne zakładki i w te miejsca są
wstawiane dane.

Niedogodnością zakładek jest to, że programista sam musi wstawić zakładki do szablonu i napisać program (lub użyć
rejestratora makr) wyszukujący zakładki i wstawiający dane. Użytkownicy nie mogą tworzyć swoich dokumentów z
danymi, jak w przypadku użycia korespondencji seryjnej.

Inną niedogodnością tej metody jest to, że zakładki nie są widoczne w dokumencie, co utrudnia ich odszukanie i
identyfikację.

Aby zastosować tę metodę, utwórz szablon Worda i wpisz tekst. Następnie wstaw zakładki w miejsca, gdzie chcesz
wstawić dane, wybierając Zakładka z menu Wstaw. Wpisz nazwę zakładki i naciśnij przycisk Dodaj.

Użyj rejestratora makr do wygenerowania kodu VBA, przechodząc do zakładki i wpisując tekst. Przykład kodu
zamieszczony jest poniżej.
Selection.GoTo..... What:=wdGoToBookmark, Name:="MyBookmark"
Selection.TypeText "New Text"

Zastępowanie
Używając tej techniki, tekst jest wstawiany do dokumentu w oznaczone miejsca (np. {Nazwisko}). Program szuka
tych oznaczonych miejsc za pomocą funkcji Znajdź i zamienia je na odpowiednie dane. Inaczej mówiąc {Nazwisko}
zostanie odszukane i zamienione na „Kowalski”.

Zaletą tej metody w porównaniu z zakładkami jest to, że oznaczony tekst jest widoczny i czytelny w porównaniu z
zakładką. Jeszcze raz użyj rejestratora makr podczas wyszukiwania i zamiany, aby utworzyć kod VBA.
With Selection.Find
.ClearFormatting
.Text = "{Tekst do odszukania}"
.Replacement.Text = "Nowy tekst"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute Replace:=wdReplaceAll
End With

Przykłady kodu automatyzacji Worda


Poniższe przykłady przedstawiają programy używające specyficzne właściwości i metody obiektów Worda.

Formatowanie dokumentów
Word ma ogromne możliwości formatowania dokumentów. Do utworzenia i sformatowania dokumentu można użyć
następującego fragmentu programu w VBA:
' Formatowanie tekstu
With Selection.Font
.Size = 14
.Bold = True
End With

' Formatowanie akapitu


With Selection.ParagraphFormat
.LeftIndent = InchesToPoints(0)
.RightIndent = InchesToPoints(0)
.SpaceBefore = 0
.SpaceAfter = 0
.LineSpacingRule = wdLineSpaceSingle
.Alignment = wdAlignParagraphLeft
.KeepWithNext = False
.KeepTogether = False
.PageBreakBefore = False
.NoLineNumber = False
.Hyphenation = True
.FirstLineIndent = InchesToPoints(0)
.OutlineLevel = wd0utlineLevelBodyText
End With
Część VI ♦ Współoperatywność 346

' Ustawianie podwójnego odstępu między wierszami


Selection.ParagraphFormat.LineSpacingRule = wdLineSpaceDouble

' Wstawienie znaku końca strony


Selection.InsertBreak Type:=wdPageBreak

' Wstawienie znaku końca sekcji


Selection.InsertBreak Type:=wdSectionBreakNextPage

Użycie stylów dokumentu


Styl to zestaw instrukcji formatowania, który posiada swoją nazwę i może być przypisywany do tekstu. Style umożliwiają
formatowanie kilku bloków tekstu lub akapitów jedną instrukcją. Dodatkowo pomagają utrzymać spójność formatowania
dokumentu.
' Zastosowanie stylu Nagłówek 1
Selection.Style = ActiveDocument.Styles("Heading 1")

' Tworzenie nowego stylu


ActiveDocument.Styles.Add Name:="MyNewStyle", Type:=wdStyleTypeParagraph
With ActiveDocument.Styles("MyNewStyle")
.AutomaticallyUpdate = False
.BaseStyle = "Heading 5"
End With
With ActiveDocument.Styles("MyNewStyle").Font
.Name = "Times New Roman"
.Size = 12
.Bold = False
.Italic = False
.Underline = wdUnderlineSingle
.StrikeThrough = False
.DoubleStrikeThrough = False
.Outline = False
.Emboss = False
.Shadow = False
.Hidden = False
.SmallOaps = False
.AllCaps = False
.ColorIndex = wdAuto
.Engrave = False
.Superscript = False
.Subscript = False
.Scaling = 100
.Kerning = 0
.Animation = wdAnimationNone
End With

Autokorekta
Autokorekta poprawia niektóre błędnie napisane słowa (np. „barzdo” zostanie zamienione na „bardzo”). Możesz także użyć
autokorekty, aby zaoszczędzić pisania (np. zamienić „MS” na „Microsoft”).

Autotekst
Autotekst jest bazą danych przechowującą często używane fragmenty tekstu i obiekty graficzne, które mogą być w łatwy
sposób wstawiane do dokumentu. W przykładach do rozdziału zamieszczony jest program wstawiający tekst i zdjęcia do
dokumentu.
' Tworzenie pozycji w autotekście.
NormalTemplate.AutoTextEntries.Add Name:="Microsoft", _
Range:=Selection.Range

' Wstawianie do autotekstu.


NormalTemplate.AutoTextEntries("Microsoft").Insert _
Where:= Selection.Range

Autopodsumowanie
Autopodsumowanie analizuje każde zdanie dokumentu, aby wygenerować podsumowanie. Podsumowanie może być
wyświetlane na kilka sposobów: jako wyróżniony tekst w dokumencie, jako streszczenie na początku dokumentu, w nowym
dokumencie lub tylko samo podsumowanie. Autopodsumowanie może również tworzyć streszczenia stron WWW.
' Tworzy podsumowanie dokumentu jako nowy dokument.
ActiveDocument.AutoSummarize Length:=25, _
Mode:=wdSummaryModeCreateNew, UpdateProperties:=True
347 Rozdział 19. ♦ Integracja z Office 2000

Widoki dokumentu
Po utworzeniu dokumentu trzeba wyświetlić go we właściwej postaci: normalnej, układu dla sieci WWW, układu strony i
konspektu.
' Układ normalny
ActiveWindow.View.Type = wdNormalView

' Układ sieci WWW


ActiveWindow.View.Type = wdOnlineView

' Układ strony


ActiveWindow.View.Type = wdPageView

' Układ konspektu


ActiveWindow.ActivePane.View.Type =wd0utlineView

' Główny dokument


ActiveWindow.ActivePane.View.Type = wdMasterView

Spis treści
Dawniej tworzenie dokumentu było uciążliwym zadaniem. Teraz w Wordzie jest to zautomatyzowany proces. Aby
tworzenie spisu przebiegło sprawnie, należy używać stylów w dokumencie. Gdy zastosujesz style Nagłówek 1, Nagłówek 2
itd., Word w oparciu o te informacje automatycznie utworzy prawidłowy spis treści.
' Tworzenie spisu treści
With ActiveDocument
.TablesOfContents.Add Range:=Selection.Range, _
RightAlignPageNumbers:= _
True, UseHeadingStyles:=True, UpperHeadingLevel:=1, _
LowerHeadingLevel:=3, IncludePageNumbers:=True, _
AddedStyles:=""
.TablesOfContents(1).TabLeader = wdTabLeaderDots
End With

Przypisy
Przypisy pomagają czytelnikowi odnaleźć i ocenić informacje, które odnoszą się do treści zawartych w dokumencie.
' Tworzenie przypisu
ActiveDocument.Footnotes.Add Range:=Selection.Range, _
Reference:=Selection, Text:="My New Footnote"

Nagłówki
Nagłówki są umieszczone na górze każdej strony dokumentu.
' Tworzenie nagłówka
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.TypeText Text:="My Header"

Stopki
Stopki umieszczone są na dole każdej strony dokumentu.
' Tworzenie stopki
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
If Selection.HeaderFooter.IsHeader = True Then
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter
Else
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
End If
Selection.TypeText Text:="My Footer"

Hiperłącza
Hiperłącza umożliwiają użytkownikowi w łatwy sposób przeskakiwać do innych części dokumentu, otwierać inne
dokumenty, a nawet przeskakiwać do dokumentów umieszczonych w Internecie.
' Tworzenie hiperłącza do zakładki w dokumencie
ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, Address:= ", _
SubAddress:="MyBookmark"

' Tworzenie hiperłącza do innego dokumentu


ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, Address:= _
"C:\MyDoc.doc", SubAddress:=""

' Tworzenie hiperłącza do dokumentu w Internecie


ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, Address:= _
"http://www.microsoft.com/office/", SubAddress:=""
Część VI ♦ Współoperatywność 348

Tworzenie tabel
Tabele zawierają informacje zorganizowane w wiersze i kolumny. Word pozwala na łatwe tworzenie nawet
skomplikowanych tabel.
' Tworzenie tabeli
ActiveDocument.Tables.Add Range:=Selection.Range,
NumRows:=3, NumColumns:=3, Selection.Tables(1).AutoFormat, _
Format:=wdTableFormatClassic3, ApplyBorders:=True, _
ApplyShading:=True, ApplyFont:=True, ApplyColor:=True, _
ApplyHeadingRows:=True, ApplyLastRow:=False, _
ApplyFirstColumn:=True, ApplyLastColumn:=False, AutoFit:=False
' Wstawianie wierszy do tabeli
Selection.InsertRows 1

' Wstawianie kolumn do tabeli


Selection.InsertColumns

Ustawienia strony
Okno dialogowe ustawień strony pozwala na ustawienie marginesów, rozmiaru papieru, orientacji, źródła papieru oraz
układu. Wszystkie te ustawienia mogą być modyfikowane programowo.
' Ustawienie marginesów
With ActiveDocument.PageSetup
.TopMargin = InchesToPoints(0.5)
.BottomMargin = InchesToPoints(0.5)
.LeftMargin = InchesToPoints(0.5)
.RightMargin = InchesToPoints(0.5)
End With

' Ustawienie poziomej orientacji papieru.


ActiveDocument.PageSetup.Orientation = wdOrientLandscape

Podgląd wydruku
Aby wywołać podgląd wydruku, należy użyć poniższej instrukcji.
' Podgląd wydruku
ActiveDocument.PrintPreview

Drukowanie dokumentów, kopert i etykiet


Poniższy przykład przedstawia sposób, jak programowo wydrukować dokument, kopertę i etykietę:
' Drukowanie dokumentu
Application.PrintOut FileName:="", Range:=wdPrintAllDocument, _
Item:= wdPrintDocumentContent, Copies:=1, Pages:="", _
PageType:=wdPrintAllPages, Collate:=True, Background:=True,
PrintToFile:=False

' Drukownanie koperty


ActiveDocument.Envelope.PrintOut ExtractAddress:=False, _
OmitReturnAddress :=False, PrintBarCode:=False, _
PrintFIMA:=False, Height:=InchesToPoints(4.13), _
Width:=InchesToPoints(9.5), Address:="Tom Howe", _
AutoText:= "ToolsCreateLabelsl", ReturnAddress:=_
"1001 SW Fifth Avenue, Suite 1100",ReturnAutoText:= _
"ToolsCreateLabels2", AddressFromLeft:=wdAutoPosition, _
AddressFromTop:=wdAutoPosition, ReturnAddressFromLeft:=_
wdAutoPosition, ReturnAddressFromTop:=wdAutoPosition

' Drukowanie etykiety


Application.MailingLabel.DefaultPrintBarCode = False
Application.MailingLabel.PrintOut Name:="2160 Mini", _
Address:="Tom Howe"

Gdy codziennie drukowane są obszerne dokumenty i raporty, rozważ


użycie procedury uruchamiającej drukowanie w nocy, gdy drukarki są
wolne i ruch w sieci minimalny.

Pola
W Wordzie pola są używane do wstawiania do dokumentu różnych informacji, takich jak numery stron, daty i inne. Aby
wstawić pole do dokumentu, wybierz Pole z menu Wstaw. W czasie pracy z dokumentem można przełączyć się pomiędzy
tekstem i kodami pól przez naciśnięcie Alt+F9.
349 Rozdział 19. ♦ Integracja z Office 2000

Pola mogą być uaktualniane ręcznie przez naciśnięcie F9 lub automatycznie podczas drukowania dokumentu.

Niektóre często używane pola zamieszczone są w tabeli 19.2.

Tabela 19.2.
Pola Worda

Pole Worda Opis


Ask Prosi użytkownika o wprowadzenie tekstu skojarzonego z zakładką
CreateDate Data utworzenia dokumentu
Fill-in Prosi użytkownika o wprowadzenie tekstu do wstawienia do dokumentu

Tabela 19.2.
Pola Worda (ciąg dalszy)

Pole Worda Opis


Hyperlink Otwiera i przeskakuje do pliku
If Instrukcja warunkowa
MergeField Wstawia pole korespondencji seryjnej
Next Przejście do następnego rekordu korespondencji seryjnej
SectionPages Wstawia ilość stron w sekcji

W czasie pracy z polami przydatne są następujące skróty klawiszowe:

Skrót klawiszowy Opis


Alt+F9 Przełącza pomiędzy tekstem i kodami pól
Ctrl+F9 Wstawia znak pola
Ctrl+Shift+F9 Odłącza kody pól
Delete Usuwa pole
F9 Uaktualnia pola

Informacje o dokumencie
W czasie tworzenia i zapisywania dokumentu zapisywane są informacje pozwalające na późniejsze przeszukiwanie
dokumentów. Na rysunku 19.9. znajdują się informacje zawarte w oknie dialogowym Właściwości.

Rysunek 19.9.
Informacje
o dokumencie Worda

W dokumencie zapisywane są następujące informacje:


u Nazwa dokumentu;
u Rozmiar dokumentu;
u Data i czas utworzenia;
u Data i czas ostatniej modyfikacji;
Część VI ♦ Współoperatywność 350

u Nazwa bazowego szablonu;


u Słowa kluczowe identyfikujące dokument;
u Miejsce zapisu dokumentu;
u Nazwisko autora;
u Nazwisko kierownika;
u Firma;
u Kategoria;
u Komentarz;
u Statystyka dokumentu;
u Informacje o zawartości.

Można również utworzyć zestaw własnych właściwości bazujących na specyfice firmy. Popatrz na zakładkę
Niestandardowe okna Właściwości.

Inne możliwości Worda


Word posiada wiele funkcji małej poligrafii. Są to m.in.:
u Układ wielokolumnowy;
u Możliwość importu grafiki z innych aplikacji;
u Wbudowywanie czcionek True Type;
u Krawędzie i cieniowanie;
u Word Art.;
u Wiele narzędzi rysunkowych.

Automatyzacja Excela
W tej części opisane są specyficzne dla Excela zagadnienia oraz przykłady automatyzacji.

Model obiektów Excela


Excel zawiera ponad 140 obiektów dostępnych poprzez VBA.

Zajrzyj do „Obiekty Microsoft Excel” w pomocy do Excela. Zamieszczony


jest tam diagram obiektów Excela.

W tabeli 19.3 zestawione zostały często używane obiekty Excela. Obiekty, które mają także kolekcje zakończone są literą
(s).

Tabela 19.3.
Obiekty Excela

Obiekty Excela Description


Application Cała aplikacja Excel
Characters Znaki w obiekcie zawierającym znaki
Chart(s) Wykresy w skoroszycie
CubeField(s) Hierarchia lub pole wymiaru sześcianu OLAP
DefaultWebOptions Ustawienia dla publikacji i zapisywania jako strony WWW
Dialog(s) Wbudowane okna dialogowe
DocumentProperty(s) Wbudowane i zdefiniowane właściwości dokumentu
351 Rozdział 19. ♦ Integracja z Office 2000

Name(s) Nazwa dla obszaru komórek


PivotCache(s) Pamięć podręczna dla raportu z tabeli przestawnej
PivotTable(s) Raport z tabeli przestawnej
PublishObject(s) Obiekt w arkuszu, który będzie zapisywany na stronie WWW
Range Komórka, wiersz, kolumna lub obszar komórek zawierający ciągły blok
komórek lub trójwymiarowy obszar
Shape(s) Rysunek lub panel do rysowania
ShapeRange Podzbiór obiektów
Style(s) Opis stylu dla obszaru
WebOptions Ustawienia nadpisujące DefaultWebOptions
Workbook(s) Otwarty arkusz dostępny przez numer lub nazwę
Worksheet(s) Otwarty skoroszyt dostępny przez numer lub nazwę

Przykłady automatyzacji Excela


Przykłady poniższe przedstawiają automatyzację charakterystycznych właściwości i metod obiektów Excela.

Formatowanie dokumentów Excela


Excel posiada szerokie możliwości formatowania. Poniższe przykłady przedstawiają sposób w jaki należy formatować
nagłówki kolumn danych i w jaki sposób wywoływać metodę AutoFit:
' Formatowanie nagłówków kolumn
With objWorkSheet.
' Pogrubienie nagłówków kolumn
.Cells(1, 1).Font.Bold = True
.Cells(1, 2).Font.Bold = True
End With

' Formatowanie danych w arkuszu


With objWorkSheet.Columns

With .Item(2)
.NumberFormat = "0.00"
.AutoFit
End With

' Użycie metody AutoFit do formatowania danych


.Item(1).AutoFit

End With

Tworzenie wykresów
Użyj rejestratora makr, aby szybko utworzyć kod automatyzacji. Użyj kreatora wykresów do wybrania odpowiedniego
wykresu. Poniższy przykład tworzy różne typy wykresów.
' Tworzenie wykresu kołowego
objChart.ChartWizard Source:=objSheet.Cells(1, 1).CurrentRegion, _
Gallery:=xlPie, Format:=4, PlotBy:=xlColumns, _
CategoryLabels:=1, SeriesLabels:=1, HasLegend:=2, _
Title:="Sprzedaż (Wykres kołowy)"

' Tworzenie wykresu kolumnowego


With ObjChart.ActiveChart
.ChartType = xlColumnClustered
.SetSourceData Source:=_
Sheets("5 najlepszych produktów").Range("Al:B6"), _
PlotBy:=xl0olumns
End With

' Tworzenie wykresu pierścieniowego


With ObjChart.ActiveChart
.ChartType = xlDoughnut
.SetSourceData Source:=_
Sheets("5 najlepszych produktów").Range("Al:B6"), _
PlotBy:=xlColumns
.Location Where:=xlLocationAsNewSheet, Name:="Wykres pierścieniowy"
.HasLegend = True
.ChartTitle.Characters.Text = "Sprzedaż (wykres pierścieniowy"
End With

Program korzystający z automatyzacji może tworzyć w Excelu wykresy takie jak pokazany na rysunku 19.10.
Część VI ♦ Współoperatywność 352

Użycie właściwości Parent


Excel zawiera obiekt aplikacji oraz obiekt reprezentujący arkusz. Możesz dostać się do wszystkich obiektów Excela przez
właściwości tych obiektów wysokiego poziomu. Generalnie, kod automatyzacji rozpoczyna pracę od tych obiektów i
schodzi w dół hierarchii obiektów. W Excelu program może rozpocząć pracę od obiektu aplikacji, a następnie przenieść się
do obiektu zeszytu i dalej do arkuszy i komórek.

Gdy odwołujesz się do obiektu w hierarchii obiektów aplikacji, możesz przesuwać się w obu kierunkach.
Rysunek 19.10.
Tworzenie wykresów
w Excelu

Aby przesunąć się w górę hierarchii, używamy właściwości Parent. Przykładowo, gdy pracujesz z arkuszem, możesz
odwołać się do zeszytu, który zawiera ten arkusz poprzez właściwość Parent. Fragment programu ilustrujący tę technikę
zamieszczony jest poniżej.
Private Sub ParentPropertyDemo()
Dim objExcel As Excel.Application
Dim objWorkBook as Excel.WorkBook
' Utworzenie obiektu Excela
Set objExcel = New Excel.Application

' Otwarcie pliku Excela


' Upewnij się, że przykładowy plik znajduje się w podanym katalogu

objExcel.Workbooks.Open _
("C:\Automation\Sales by Country Data.xls")

' Ustaw zmienną objWork na aktywny zeszyt


Set objWorkBook = objExcel.ActiveWorkBook

' Pobierz nazwę zeszytu z objWorkBook ("Sales by Country")


MsgBox objWorkBook.Name
' Pobierz nazwę z obiektu aplikacji, używając właściwości Parent
' ("Microsoft Excel").
MsgBox objWorkBook.Parent.Name

' Maksymalizuj okno


objExcel.WindowState = xlMaximized
' Pokaż Excela użytkownikowi
objExcel.Visible = True
' Zakończ aplikację używając metody Quit
'objExcel.Quit
' Zwolnij obiekt aplikacji
Set objExcel = Nothing

End Sub

W przykładzie tym otwierany jest zeszyt Excela. Poprzez właściwość Parent obiektu reprezentującego zeszyt
odwołujemy się w górę hierarchii do obiektu aplikacji Excel.

Automatyzacja PowerPoint
W tej części opisane są specyficzne dla PowerPoint zagadnienia oraz przykłady automatyzacji.
353 Rozdział 19. ♦ Integracja z Office 2000

Model obiektów PowerPoint


PowerPoint zawiera ponad 85 obiektów dostępnych poprzez VBA.

Zajrzyj do „Obiekty Microsoft PowerPoint” w pomocy do PowerPoint.


Zamieszczony jest tam diagram obiektów PowerPoint.

W tabeli 19.4 zestawione zostały często używane obiekty PowerPoint. Obiekty, które mają także kolekcje, zakończone są
literą (s).

Tabela 19.4.
Obiekty PowerPoint

Obiekt PowerPoint Opis


ActionSetting(s) Ustawienia opisujące sposób reakcji rysunków lub obszaru tekstu
na manipulacje myszką w czasie pokazu
Animationsetting(s) Ustawienia animacji rysunków w czasie pokazu
Application Cała aplikacja PowerPoint
Cell Komórka w tabeli
CellRange Zbiór komórek we wierszu lub kolumnie tabeli
ColorScheme(s) Schemat kolorów dla slajdu.
Column(s) Kolumna tabeli
DefaultWebOptions Ustawienia dla publikacji i zapisywania jako strony WWW
DocumentWindow(s) Okno dokumentu
Pane(s) Fragment okna dokumentów
Presentation(s) Otwarta prezentacja dostępna przez numer lub nazwę
Row(s) Wiersz tabeli
Selection Zaznaczenie w dokumencie
ShapeRange Zbiór kształtów w dokumencie
SlideRange Zbiór slajdów
SlideShowwindow(s) Okno, w którym odbywa się pokaz
Table Tabela na slajdzie
TextRange Tekst dołączony do kształtu
WebOptions Ustawienia nadpisujące DefaultWebOptions

Przykłady automatyzacji PowerPoint


Poniższe przykłady przedstawiają przykłady użycia specyficznych właściwości i metod obiektów PowerPoint (rysunek
19.11)

Dodanie slajdu
Do dodania slajdu do prezentacji używana jest metoda Add.
' Dodaj slajd
Set ppPres = objPP.Presentations.Add
Część VI ♦ Współoperatywność 354

Rysunek 19.11.
Prezentacja
PowerPoint
stworzona
za pomocą
automatyzacji

Dodanie efektu przejścia


Poniższy fragment programu dodaje do slajdu efekt przejścia:
' Dodanie do slajdu efektu przejścia
objPresentation.Slides(5).SlideShowTransition.EntryEffect = _
ppEffectFade

Wstawianie danych i formatowanie slajdów


Program ten wstawia dane i formatuje slajd:
With objPresentation.Slides(5).Shapes(1)
.TextFrame.TextRange.Text = "Suma sprzedaży"
.Shapes(1).TextFrame.TextRange.Characters.Font.Size = 80
End With

With objPresentation.Shapes(2).TextFrame.TextRange
.Text = Chr$(CharCode:=13) + "Spotkanie Rady Nadzorczej" _
+ Chr$(CharCode:=13) + "Informacja o wartości sprzedaży"
.Characters.Font.Color.RGB = RGB(0, 0, 255)
.Characters.Font.Shadow = True
End With
With objPresentation.Shapes("Rectangle 3").TextFrame.TextRange, _
Characters(1, 53).Font
.Size = 36
.Color.Scheme0olor = ppFill
End With

Wstawienie rysunku do slajdu


Poniższy fragment dodaje do slajdu fotografię oraz formatuje slajd:
Dim strFileName as String
strFileName = ADOrs!Photos

objPresentation.Shapes.AddPicture(FileName:=strFileName, _
LinkToFile:=msoFalse, SaveWithDocument:=msoTrue, _
Left:=110, Top:=260, Width:=250, Height:=250).Select

Uruchamianie prezentacji
Aby uruchomić prezentację, wykonaj:
objPresentation.SlideShowSettings.Run

Automatyzacja Outlook
W tej części opisane są specyficzne dla Outlooka zagadnienia oraz przykłady automatyzacji.
355 Rozdział 19. ♦ Integracja z Office 2000

Model obiektów Outlook


Outlook zawiera ponad 55 obiektów dostępnych poprzez VBA.

Zajrzyj do „Obiekty Microsoft Outlook” w pomocy do Outlooka. Zamiesz-


czony jest tam diagram obiektów Outlooka.

W tabeli 19.5 zestawione zostały często używane obiekty Outlooka. Obiekty, które mają także kolekcje, zakończone są
literą (s).

Tabela 19.4.
Obiekty Outlook

Obiekt Outlook Opis


Action(s) Specjalizowana czynność na obiekcie
AddressEntries(s) Informacje o adresie przesyłki
Application Cała aplikacja Outlook
AppointmentItem Spotkanie w kalendarzu

Tabela 19.4.
Obiekty Outlook (ciąg dalszy)

Obiekt Outlook Opis


Attachment(s) Dołączony do przesyłki dokument
ContactItem Pojedynczy kontakt w folderze Kontakty
DistListItem Lista wysyłkowa w folderze Kontakty
DocumentItem Dokument w folderze Outlook
Explorer(s) Okno wyświetlające zawartość foldera
Folders Kolekcja obiektów MAPIFolder
Inspector(s) Okno wyświetlające element Outlook
Items Kolekcja elementów w MAPIFolder
JournalItem Pozycja w folderze dziennika
NameSpace Główny obiekt umożliwiający dostęp do danych
NoteItem Notatka w folderze notatek
Pages Kolekcja stron
PostItem List w folderze publicznym
PropertyPage(s) Strona właściwości definiowanych przez użytkownika
Recipient(s) Użytkownik lub zasób
SyncObject(s) Profil synchronizacji dla użytkownika
TaskItem Zadanie w folderze zadań

Przykłady automatyzacji Outlook


Poniższe przykłady przedstawiają przykłady użycia specyficznych właściwości i metod obiektów Outlooka.

Dodawanie i wyświetlanie folderów


Fragment programu, który dodaje folder oraz wyświetla folder Public.
' Dodaj folder do domyślnego foldery kalendarza
Set objSubFolder = objOutlook.GetNamespace("MAPI").GetDefaultFolder_
(olFolderCalendar).Folders.Add("New Calendar")
Część VI ♦ Współoperatywność 356

Dodawanie nowego zadania i wyświetlenie zadań


Poniższy kod dodaje nowe zadanie i wyświetla zadania:
Dim objOutlook As Outlook.Application
Dim objTaskFolder As Object
Dim objTaskItem As Object

Set objTaskItem = objOutlook.CreateItem(olTaskItem)


With objTaskItem
.Subject = "To jest temat zadania"
.Body = "To jest treść zadania"
' Możesz także dodać przypominanie, czas i datę
.Save
End With

' Przejście do foldera zadań


Set objTaskFolder = obj0utlook.GetNamespace("MAPI")._
GetDefaultFolder(13)

' Wyświetlenie zawartości foldera zadań


objTaskFolder.Display

Tworzenie wiadomości e-mail z załącznikiem


W łatwy sposób możesz wysłać wiadomość e-mail z aplikacji Accessa, automatyzując Outlooka (rysunek 19.12).

Rysunek 19.12.
Wysłanie
wiadomości e-mail
z załącznikiem
z Accessa

Program ten tworzy nową wiadomość e-mail i załącza arkusz Excela:


Dim objOutlook As Outlook.Application
Dim objRecipient As Recipient
Dim objAttachment As Attachment
Dim objMailItem As MailItem

' Tworzenie przesyłki e-mail


Set objMailltem = obj0utlook.CreateItem(olMailItem)

With objMailItem
' Tworzenie odbiorcy przesyłki
Set objRecipient = .Recipients.Add("Steven Johnson")
objRecipient.Type = olTo
' Ustawienie tematu, treści i ważności przesyłki
.Subject = "To jest mój raport sprzedaży do oceny"
.Body = "Jeżeli potrzebujesz innych informacji, _
proszę o kontakt." & vbOrLf & vbCrLf
.Importance = olImportanceHigh
' Dołączenie arkusza i wykresu w pliku Excela: "Sales by Country."
Set objAttachment = .Attachments.Add_
("C:\Automation\Sales by Country.xls")

' rozwinięcie nazw odbiorców


For Each objRecipient In .Recipients
objRecipient.Resolve
Next

' Wyświetlenie wiadomości


.Display
' Wysłanie wiadomości
.Send
End With
357 Rozdział 19. ♦ Integracja z Office 2000

Tworzenie elementów Outlooka


Poniższe instrukcje tworzą różne elementy Outlooka.

Element Outlook Instrukcja tworząca element


Spotkanie Set objItem = objOutlook.CreateItem(olAppointmentItem)

Kontakt Set objItem = objOutlook.CreateItem(olContactItem)

Dziennik Set objItem = objOutlook.CreateItem(olJournalItem)

Wiadomość e-mail Set objItem = objOutlook.CreateItem(olMailItem)

Notatka Set objItem = objOutlook.CreateItem(olNoteItem)

Wyświetlanie domyślnych folderów


W tabeli 19.6 zamieszczone są stałe używane w metodzie GetDefaultFolder do wyświetlenia domyślnych folderów
Outlooka.

Tabela 19.6.
Stałe folderów

Nazwa foldera Stała dla metody GetDefaultFolder


Kalendarz GetDefaultFolder(olFolderCalendar)

Kontakty GetDefaultFolder(olFolderContacts)

Skrzynka odbiorcza GetDefaultFolder(olFolderInbox)

Dziennik GetDefaultFolder(olFolderJournal)

Notatki GetDefaultFolder(olFolderNotes)

Zadania GetDefaultFolder(olFolderTasks)

Wyświetlenie foldera publicznego


Poniższy fragment programu wyświetla publiczny folder programu Outlook.
Dim objOutlook As Outlook.Application
Dim objNameSpace As Outlook.NameSpace
Dim objPublicFolders As Outlook.Folders
Dim objAllPublicFolders As Object
Dim objOffice0ontacts As Object

Set objNameSpace = obj0utlook.GetNamespace("MAPI")


Set objPublicFolders = objNameSpace.Folders("Public Folders")
Set objAllPublicFolders = objPublicFolders.Folders("Favorites")
Set objOffiEeContacts = objAllPublicFolders.Folders("Office Contacts")

' Wyświetlenie publicznego foldera "Office Contacts."


objOfficeContacts.DisplayThe

Szukanie elementu w Outlooku


Kod ten pokazuje jak znaleźć kontakt w Outlooku.
Set objItem = objContactItems.Find("[File As] = 'Zelko, John'")
objItem.Display

Filtrowanie elementów w Outlooku


Do filtrowania elementów Outlooka używana jest metoda Restrict. Poniższy program zwraca tylko te kontakty, które
mają imię „Steve”:
Set objFilter = objContactItems.Restrict("[First Name] = 'Steve' ")

W przykładach do tego rozdziału znajduje się kompletny program do in-


ternetowej poczty elektronicznej. Przesyłki mogą być wysyłane z Outlooka do
grup odbiorców zapisanych w bazie danych Accessa. W przykładach znajdują
się także program przesyłający listy z Worda do odbiorców z kontaktów
Część VI ♦ Współoperatywność 358

Outlooka.

Automatyzacja Graph
W tej części opisane są specyficzne dla Graph zagadnienia oraz przykłady automatyzacji.

Model obiektów Graph


Graph zawiera ponad 10 obiektów dostępnych poprzez VBA. Tabela 19.7 zawiera często używane obiekty. Obiekty, które
mają także kolekcje, zakończone są literą (s).

Tabela 19.7.
Obiekty Graph

Obiekt Graph Opis


Application Cała aplikacja Microsoft Graph
AutoCorrect Funkcja autokorekty w Graph
Axis(s) Oś
Chart Wykres

Tabela 19.7.
Obiekty Graph (ciąg dalszy)

Obiekt Graph Opis


ChartArea Obszar wykresu
ChartGroup(s) Jedna lub więcej serii punktów narysowanych na wykresie
Datasheet Arkusz danych
DataTable Tabela danych w wykresie
Legend Legenda na wykresie
PlotArea Obszar rysowania w wykresie
Series(s) Serie danych w wykresie

Tworzenie wykresu
Skomplikowane dokumenty często zawierają wykresy i diagramy. Word i inne produkty Office używają Microsoft Graph
do tworzenia i formatowania wykresów.

W Accessie jest bardzo łatwo utworzyć wykres na formularzu, używając kreatora. Często jednak możesz chcieć pokazać
różne typy wykresów dla różnych danych. Zamiast tworzyć sześć formularzy z różnymi wykresami, możesz manipulować
wykresem na formularzu za pomocą automatyzacji, aby pozwolić użytkownikowi na obejrzenie różnych prezentacji
graficznych jego danych (rysunek 19.13).
359 Rozdział 19. ♦ Integracja z Office 2000

Rysunek 19.13.
Pojedynczy
formularz może
pokazywać różne
typy wykresów

Przykłady automatyzacji Graph


Po utworzeniu formularza z wykresem użyj obiektu Chart i zmień właściwość ChartType, aby uzyskać różne typy
wykresu. Przykładowo, aby zmienić wykres kolumnowy na kołowy, użyj następującego programu:
' Przypisanie zmiennej do wykresu na ekranie
Set objChart = Me.objProductsSold.Object

' Zmień typ wykresu na kołowy


objChart.ChartType = xl3DPie

' Pokaż legendę


objChart.HasLegend = True

' Usuń zmienną obiektową


Set objChart = Nothing

Poprzez proste użycie właściwości i metod Microsoft Graph, możesz formatować i zmieniać wykres w zależności od potrzeb:
dodawać legendę, wskaźniki danych, etykietki, wzory tła itp.

Gdy automatyzujesz aplikację ze względu na jej możliwości rysowania


wykresów, możesz użyć Microsoft Excel lub Microsoft Graph. Powinieneś
użyć Excela, ze względu na bardziej rozwinięty model obiektów.

Automatyzacja MapPoint
W tej części opisane są specyficzne dla MapPoint zagadnienia oraz przykłady automatyzacji.

Model obiektów MapPoint


Obiekty MapPoint są dostępne poprzez VBA.

Zajrzyj do „Obiekty Microsoft MapPoint” w pomocy do MapPoint. Zamie-


szczony jest tam diagram obiektów MapPoint.

W tabeli 19.8 zestawione zostały często używane obiekty MapPoint.

Tabela 19.8.
Obiekty MapPoint

Obiekty MapPoint Opis


AppLication Cała aplikacja MapPoint
Location Lokalizacja
Część VI ♦ Współoperatywność 360

Map Mapa
PushPin Pineska

Przykłady automatyzacji MapPoint


Poniższy przykład automatyzacji MapPoint ma na celu wyświetlenia odpowiedniej mapy (popatrz na rysunek 19.14). Może
być on użyty do otwarcia mapy i pokazania położenia klienta.
' Ustaw odwołanie do MapPoint 1.0
Dim objMapPoint As MapPoint.Application
Dim objMap As MapPoint.Map

Set objMapPoint = New MapPoint.Application

' Otwórz mapę Portland w Oregonie


Set objMap = objMapPoint.OpenMap("C:\Maps\Portland, OR.ptm")

' Zwolnienie zmiennej obiektowej


Set objMap = Nothing
Set objMapPoint = Nothing

Rysunek 19.14.
Pokazanie mapy
w aplikacji Accessa
przy użyciu
MapPoint

Automatyzacja FrontPage
W tej części opisane są specyficzne dla FrontPage zagadnienia oraz przykłady automatyzacji.

Model obiektów FrontPage


Obiekty FrontPage są dostępne poprzez VBA.

Zajrzyj do „Obiekty Microsoft FrontPage” w pomocy do FrontPage. Za-


mieszczony jest tam diagram obiektów FrontPage.

W tabeli 19.9 zestawione zostały często używane obiekty FrontPage.

Tabela 19.9.
Obiekty FrontPage

Obiekt FrontPage Opis


Application Cała aplikacja FrontPage
HomeNavigationNode Węzeł nawigacji dla strony domowej
361 Rozdział 19. ♦ Integracja z Office 2000

Theme(s) Temat
Web(s) Sieć FrontPage
WebFile(s) Plik w opartej na FrontPage sieci
WebFolder(s) Folder w opartej na FrontPage sieci
WebWindow(s) Otwarte okno w opartej na FrontPage sieci

Przykłady automatyzacji FrontPage


Automatyzując FrontPage, możesz m.in.:
u Utworzyć nową sieć lub otworzyć już istniejącą;
u Tworzyć lub otwierać foldery sieci;
u Tworzyć, otwierać i modyfikować pliki w sieci;
u Stosować schematy.

Przykład poniższy automatyzuje FrontPage, aby utworzyć nową sieć, wstawić do niej nową stronę, wstawić dane Accessa
na stronę i zastosować schemat.
' Ustaw odwołania do ADO 2.1 oraz FrontPage 4.0 Web Objects.
Dim objFrontPage As FrontPage.WebWindow
Dim objWeb As Web
Dim objWebFile As WebFile
Dim objWebWindow As WebWindow
Dim strSQL As String
Dim ADOrs As ADODB.Recordset
Dim Conn As ADODB.Connection

Set objFrontPage = New FrontPage.WebWindow


Set objWeb = Webs.Open("C:\Automation\Web")

Set objWebFile = ActiveWeb.RootFolder.Files.Add _


("Podsumowanie sprzedazy.htm")
' Tworzenie połączenia ADO
Set Conn = New ADODB.Connection

' Tworzenie recordsetu ADO


Set ADOrs = New ADODB.Recordset

With Conn
.Provider = "Microsoft.JET.OLEDB.3.51"
.Open "C:\Automation\Automation.mdb"
End With

strSQL = "SELECT Categories.CategoryName AS Category,


Sum([Order Details].UnitPrice) AS Price FROM _
(Categories INNER JOIN Products ON Categories CategoryID = _
Products.CategoryID) INNER JOIN [Order Details]
ON Products.ProductID = [Order Details].ProductID _
GROUP BY Categories.CategoryName _
HAVING (((Sum([Order Details].UnitPrice))>0));"

' Otwarcie recordsetu ADO


ADOrs.Open strSOL, Conn

Set objWebWindow = Webs(0).WebWindows(0)

objWebWindow.Visible = True

' Aktywacja okna sieci


objWebWindow.Activate

' Otwórz stronę sieci


objWebFile.Open

' Wstaw nagłówek


objFrontPage.ActiveDocument.Body.insertAdjacentText "BeforeEnd", _
"Suma sprzedaży kategorii"

' Wstaw dane z bazy danych


Do Until ADOrs.EOF
objFrontPage.ActiveDocument.Body.insertRdjacentText _
"BeforeEnd", ADOrs!Category.Value & vbTab & vbTab &_
ADOrs!Price.Value
ADOrs.MoveNext
Loop

' Zmień schemat strony na "artsy"


objWebWindow.ActivePageWindow.ApplyTheme "artsy", _
fpThemePropertiesAll
Część VI ♦ Współoperatywność 362

' Zapisz stronę


objWebWindow.ActivePageWindow.Save

' Zamknij recordset.


ADOrs.Close

' Wyłącz klepsydrę


Screen.MousePointer = 0

' Zwolnij zmienne obiektowe


Set ADOrs = Nothing
Set objWeb = Nothing
Set objWebFile = Nothing
Set objWebWindow = Nothing
Set objFrontPage = Nothing

Automatyzacja Bindera
W tej części opisane są specyficzne dla Bindera zagadnienia oraz przykłady automatyzacji.

Model obiektów Bindera


Obiekty Bindera są dostępne poprzez VBA.

Zajrzyj do pomocy Bindera. Zamieszczony jest tam diagram obiektów


Bindera.

W tabeli 19.10 zestawione zostały często używane obiekty Bindera.

Tabela 19.10.
Obiekty Bindera

Obiekt Bindera Opis


Binder Aplikacja Microsoft Office Binder
DocumentProperty(s) Wbudowana lub zdefiniowana właściwość dokumentu
PageSetup Atrybuty ustawień strony
Section(s) Sekcja w Binderze

Przykłady automatyzacji Bindera


Zamieszczony tutaj kod tworzy nowy spinacz i dodaje do niego dokumenty:
Dim objBinder As Binder

Set objBinder = New Binder

With objBinder
' Dodaj dokument Worda do bindera
.Sections.Add FileName:="C:\Automation\Northwind Magazine Ad.doc"
.Sections(1).Name = "Ogłoszenie Northwind Magazine"
' Dodaj arkusz Excela do bindera
.Sections.Add FileName:="C:\Automation\Sales by Country Data.xls"
.Sections(1).Name = "Arkusz automatyzacji"
' Dodaj prezentację PowrePoint do bindera
.Sections.Add FileName:="C:\Automation\Board Of Director _
Meeting.ppt"
.Sections(1).Name = "Prezentacja na spotkanie Rady Nadzorczej"
End With

objBinder.Visible = True

' Zapisz binder


' objBinder.SaveAs "Automation.odb"

Set objBinder = Nothing

Program ten przy użyciu automatyzacji tworzy nowy binder z różnymi dokumentami Office (patrz rysunek 19.15).
363 Rozdział 19. ♦ Integracja z Office 2000

Rysunek 19.15.
Automatyzacja
Microsoft Binder

Zabezpieczanie dokumentów, szablonów i kodu programu


Dokumenty, formularze, szablony i moduły kodu mogą być zabezpieczone hasłem. Aby je zabezpieczyć, przejdź do okna
projektu w edytorze Visual Basic. Aby zabezpieczyć cały projekt, wywołaj właściwości projektu. Kliknij zakładkę
Protection i wprowadź hasło. W ten sam sposób można zabezpieczać hasłem formularze, szablony, dokumenty i moduły
kodu.
Rozdział 20.
Użycie Visual Basic z Accessem
W tym rozdziale:
u Tworzenie komponentów ActiveX.
u Tworzenie formantów ActiveX.

Access jest potężnym narzędziem programistycznym, ale jednak nie potrafi wszystkiego. Visual Basic to wspaniałe
uzupełnienie Accessa. Przy użyciu VB można tworzyć samodzielne komponenty ActiveX oraz formanty ActiveX.

W rozdziale tym zakładamy, że nie masz żadnego doświadczenia w programowaniu w Visual Basicu. Korzystając z
opisu, krok po kroku nauczysz się tworzenia formantów ActiveX, które będziesz mógł wykorzystać w swoich aplikacjach
w Accessie. Opiszemy także krok po kroku, jak tworzy się komponenty w Visual Basicu, które mogą być wykorzystane w
Accessie, Visual Basicu i innych aplikacjach Office.

Aby prześledzić przykłady zawarte w tym rozdziale, powinieneś mieć


dowolną wersję Visual Basic 6. Jeżeli nie masz Visual Basica, najtańszą
wersją jest Learning Edition.

Możesz zapytać, „Jaka jest różnica pomiędzy Visual Basic i Visual Basic for Appliccations (VBA)?” VBA jest językiem
programowania użytym w Visual Basicu, Accessie i innych aplikacjach Office. VBA w Office 2000 oraz Visual Basic 6 są
dokładnie takie same. Jednak Visual Basic 6 jest samodzielnym środowiskiem programistycznym, które będziesz używać
w tym rozdziale do tworzenia formantów ActiveX.

Tworzenie komponentów ActiveX


Za pomocą Visual Basica możesz tworzyć komponenty ActiveX i używać ich w aplikacjach Accessa. Przykładowym
komponentem, który utworzymy w tym rozdziale, będzie komponent umożliwiający odgrywanie plików dźwiękowych w
aplikacjach Accessa.

Komponenty ActiveX oraz kontrolki ActiveX omówione w tym rozdziale


zawarte są na płycie CD-ROM dołączonej do książki. Komponenty te
muszą zostać zarejestrowane w systemie. Aby to zrobić, otwórz plik
projektu i skompiluj go. W dalszej części rozdziału znajdziesz dodatkowe
informacje na temat rejestrowania komponentów.

Czym są komponenty ActiveX


Komponent ActiveX to kod w module klasowym skompilowany do postaci pliku wykonywalnego (EXE) lub biblioteki
dynamicznej (DLL). Korzyścią tworzenia komponentów ActiveX jest to, że można go stosować w każdej aplikacji
wspierającej COM. Dlatego, zamiast ograniczać się tylko do pojedynczej aplikacji Accessa, komponent może być użyty w
wielu aplikacjach Accessa, Visual Basica, Office i innych.
365 Rozdział 20. ♦ Użycie Visual Basic z Access’em

W rozdziale 11. „Tworzenie obiektów w modułach klasowych” tworzyłeś obiekt dźwiękowy przy użyciu modułu
klasowego cSound. W module klasowym plik dźwiękowy jest przekazywany do wywołania Windows API, aby odegrać
dźwięk. Kod w module klasowym zamieszczony jest na wydruku 20.1.

Wydruk 20.1. Moduł klasowy cSound


Option Explicit

' Wywołanie Windows API


Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal
uFlags As Long) As Long

Public Sub PlaySound(SoundFile As String)


' Odegraj plik dźwiękowy
sndPlaySound SoundFile, 1
End Sub

Problem z modułem klasowym polega na tym, że może być użyty tylko w aplikacji Accessa, w której istnieje ten moduł.
Jeżeli tworzymy nową aplikację, moduł musi zostać do niej zaimportowany. Jednak, jeżeli zmienisz w przyszłości kod
modułu, będziesz musiał wprowadzić ręcznie te poprawki w każdej aplikacji używającej tego modułu.

Poprzez utworzenie komponentu ActiveX dla obiektu dźwiękowego wszystkie aplikacje Accessa (jak również inne
aplikacje) mogą użyć komponentu ActiveX. Jeżeli musisz wprowadzić zmiany, wprowadzone zostaną w jednym miejscu.

Różnice między ActiveX EXE i ActiveX DLL


Gdy tworzysz komponent ActiveX w Visual Basicu, możesz utworzyć ActiveX EXE albo ActiveX DLL. Jaka jest różnica?

Komponent ActiveX w postaci pliku EXE posiada własną przestrzeń procesu oddzielną od wywołującej go aplikacji.
Wywołania z aplikacji są przesyłane pomiędzy procesami do komponentu. Jest to wolniejsze niż gdyby komponent
ActiveX był wykonywany w tym samym procesie. Zaletą ActiveX w postaci EXE jest to, że jeżeli załamie się,
wywołująca go aplikacja może dalej działać.

Komponent w postaci biblioteki DLL wykonywany jest w tej samej przestrzeni procesu co wywołująca go aplikacja.
Ponieważ nie zachodzi komunikacja międzyprocesowa, szybkość wykonania jest wyraźnie większa. Jeżeli jednak
komponent spowoduje błąd, zostanie zatrzymana cała aplikacja. Najczęściej jednak będziesz korzystać z komponentów w
bibliotekach dynamicznych.

ActiveX DLL jest wykonywany przez ten sam proces, co wywołująca go


aplikacja Accessa. Dlatego ActiveX DLL jest wyraźnie szybszy niż Ac-
tiveX EXE.

Tworzenie komponentu ActiveX


Aby utworzyć komponent ActiveX odgrywający dźwięki, uruchom Visual Basic. W oknie dialogowym New Project,
pokazanym na rysunku 20.1, wybierz ActiveX DLL.

Rysunek 20.1.
Wybór ActiveX DLL
w oknie New Project

Gdy projekt zostanie otwarty w IDE, zauważysz jeden moduł klasowy nazywany Class1. W oknie Project Properties
zmień nazwę modułu na cSound.
Część VI ♦ Współoperatywność 366

Otwórz w Accessie aplikację z rozdziału 11. „Tworzenie obiektów z modułów klas.mdb”. Otwórz moduł cSound i w trybie
projektowania skopiuj jego zawartość do schowka. Wróć do projektu w Visual Basicu i wklej całą zawartość do okna kodu
modułu cSound w sposób pokazany na rysunku 20.2.
Rysunek 20.2.
Kopia cSound
w oknie modułu
klasowego

W oknie Project Properties można znaleźć właściwość Instancing. Jej domyślną wartością jest MultiUse. Ponieważ
komponenty ActiveX zawierają moduły klasowe, można tworzyć wiele egzemplarzy danej klasy. Dzięki temu pojedynczy
moduł kodu może być użyty wiele razy. Jeżeli właściwość Instancing jest ustawiona na MultiUse, aplikacja Accessa
może tworzyć obiekty dźwiękowe przy użyciu tego komponentu. Jeżeli programy będą kilkakrotnie żądały utworzenia
obiektu, zostanie utworzony tylko jeden. Zmniejsza to zużycie pamięci, ale jeżeli wystąpi drugie żądanie dostępu do obie-
ktu, program zostanie wstrzymany aż do zakończenia obsługi wcześniejszego żądania. Najczęściej używana jest domyślna
wartość MultiUse.

Istnieje sześć ustawień właściwości Instancing. Ponieważ w tym roz-


dziale skupimy się na programowaniu dla potrzeb Accessa, nie będą one
szczegółowo opisane. Dodatkowe informacje znajdują się w pomocy do
Visual Basica.

Następnym krokiem jest modyfikacja właściwości projektu. Wybierz Project1 Properties z menu Project.

Na zakładce General w oknie Project Properties (rysunek 20.3) wprowadź nazwę projektu cSoundObject (nazwa projektu
nie może zawierać spacji). W polu Project Description wprowadź opis projektu np.: Obiekt cSound. W polu tym mogą
występować spacje i jest to nazwa, która pojawi się w oknie References podczas ustawiania odwołania do komponentu.

Na zakładce Make w oknie właściwości projektu, która pokazana jest na rysunku 20.4, można podać numer wersji. Dobrze
jest zaznaczyć pole wyboru Auto Increment, co spowoduje, że za każdą kompilacją komponentu zostanie wprowadzony nowy
numer wersji.
Rysunek 20.3.
Zakładka General
okna właściwości
projektu
367 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.4.
Zakładka Make
właściwości projektu

W części Version Information można wprowadzić nazwę, informacje o prawach autorskich, nazwę produktu i inne
informacje. Pozostałe ustawienia nie muszą być zmieniane w tym przykładzie.

Na zakładce Compile, która jest pokazana na rysunku 20.5, domyślnym ustawieniem jest Compile to Native Code. Zwykle
nie będziesz musiał zmieniać tego ustawienia. Jeżeli zmienisz na Compile to P-Code, program będzie wolniejszy, ale
komponent będzie mniejszy. Szczegółowy opis ustawień na zakładce Compile znajduje się w pomocy Visual Basica.

Rysunek 20.5.
Zakładka Compile
właściwości projektu

Na zakładce Component, która pokazana jest na rysunku 20.6, domyślnym ustawieniem jest Project Compatibility. Takiego
ustawienia powinieneś używać przy tworzeniu komponentów. Inne ustawienia, No Compatibility oraz Binary Compatibility,
omówione zostaną później w części „Dystrybucja komponentów ActiveX”.

Rysunek 20.6.
Zakładka
Component
właściwości projektu

W tym przykładzie nie będziemy zmieniać ustawień z zakładki Debugging. Kliknij przycisk OK, aby zamknąć okno
właściwości obiektu.

Aby zapisać projekt i wszystkie moduły klasowe, wybierz Save Project z menu File. Najlepiej zapisywać projekt (plik .vbp)
oraz moduł klasy (plik .cls) w tym samym katalogu (np. Obiekt Sound).

Kompilowanie biblioteki DLL


Po utworzeniu i zapisaniu projektu może zostać skompilowana biblioteka DLL zawierająca obiekt. Jest to bardzo łatwe.
Wybierz Make cSound Object DLL z menu File. Prawdopodobnie VB zaproponuje zapis pliku DLL w katalogu Visual
Basica. Zapisz plik DLL z obiektem cSound w tym samym katalogu co plik projektu.
Część VI ♦ Współoperatywność 368

Zapis pliku DLL w jednym katalogu razem z plikiem projektu ułatwia


późniejsze odszukanie plików.

Biblioteka DLL została utworzona i zarejestrowana w systemie. W Visual Basicu, gdy kompilujesz plik DLL, możesz od
razu rozpocząć korzysta z niego. W dalszej części rozdziału opisujemy, w jaki sposób rozprowadzać pliki DLL do innych
użytkowników.

Jeżeli zajrzysz do katalogu z zapisanym projektem (rysunek 20.7),


zauważysz wiele plików. Visual Basic zapisuje formularze, moduły i inne
obiekty w oddzielnych plikach. Inaczej postępuje Access, który umieszcza
wszystkie obiekty w jednym pliku MDB.
Rysunek 20.7.
Visual Basic
zapisuje obiekty
w oddzielnych
plikach

Przykład ten przedstawia sposób, jak utworzyć ActiveX DLL. Podobnie


tworzy się ActiveX EXE. Rozpocznij po prostu od wybrania ActiveX EXE
w oknie New Project.

Użycie komponentu ActiveX cSound


Po utworzeniu komponentu możesz użyć go w aplikacji Accessa. Aplikacja Accessa musi ustawić odwołanie do
komponentu, utworzyć egzemplarz obiektu i użyć go.

Poniżej przedstawimy sposób użycia komponentu. Utwórz pustą bazę Accessa o nazwie np.: Sound i zapisz ją. Następnie
utwórz pusty formularz i umieść na nim przycisk do testowania komponentu. Utwórz procedurę obsługi zdarzenia Click
przycisku. W oknie modułu ustaw odwołanie do komponentu ActiveX cSound. Uruchom okno References z menu Tools i
zaznacz pole wyboru obok Obiekt cSound. Obiekt cSound to nazwa wprowadzona wcześniej w polu Description w oknie
właściwości projektu. Zamknij okno References przez kliknięcie przycisku OK.

Ustawienie odwołania do obiektu cSound jest niezbędne, ponieważ jest to komponent oddzielny od aplikacji Accessa.
Zauważ, że używasz obiektu cSound bez tworzenia żadnego modułu w aplikacji Accessa.

Jako obsługę zdarzenia Click wpisz następującą procedurę:


Private Sub cmdSound_Click()

Dim objSound As cSound

Set objSound = New cSound

' Jeżeli używasz Windows NT, użyj ścieżki "C:\WINNT"


objSound.PlaySound "C:\Windows\Media\chimes.wav"

Set objSound = Nothing

End Sub

Czy zauważyłeś w trakcie wpisywania tekstu programu działanie IntelliSense dla Twojego obiektu (rysunek 20.8)? Jest to
wspaniała pomoc ułatwiająca i przyspieszająca wpisywanie kodu programu.
369 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.8.
IntelliSense
działające dla
obiektu cSound

Przy użyciu kilku wierszy kodu można pokazać, jak łatwo utworzyć obiekt dźwiękowy z komponentu ActiveX i używać
jego właściwości, metod i zdarzeń. Możesz także używać komponentu cSound w innych aplikacjach Accessa. Zmiany będą
ułatwione, ponieważ wszystkie aplikacje Accessa i inne używają tego samego komponentu. Jeżeli zdecydujesz się dodać
lub zmienić właściwość, metodę lub zdarzenie w komponencie, zrobisz to tylko w jednym miejscu, w samym
komponencie.

Użycie komponentu w innych aplikacjach


Oprócz Accessa możesz używać komponentu cSound w innych aplikacjach wspierających COM. Możesz użyć tego komponentu
w VB, Office, Outlook i programowaniu dla WWW.

Dystrybucja komponentów ActiveX


W trakcie dystrybucji komponentów do użytkowników musisz zająć się następującymi zagadnieniami:
u Instalowanie komponentu;
u Ustawienia rejestru komponentu;
u Zgodność komponentów.

Instalowanie komponentu
Najprostszą metodą instalacji komponentu na komputerze użytkownika jest użycie kreatora Package and Deployment
Wizard dostarczanego razem z Visual Basicem. Kreator ten tworzy program instalacyjny, który instaluje komponent i
wprowadza niezbędne wpisy do rejestru. Dostępne są także podobne programy innych firm.

Tworzenie programu instalacyjnego


przy użyciu Package and Deployment Wizard
Po uruchomieniu kreatora na jego pierwszej stronie znajduje się przycisk Browse. Po kliknięciu tego przycisku należy
odnaleźć plik projektu (np.: cSoundObject.vbp, tak jak na rysunku 20.9).

Rysunek 20.9.
Pierwszy ekran
kreatora Package
and Deployment

Na następnej stronie kreatora należy wybrać rodzaj skryptu pakowania (Packaging Script). W tym przykładzie wybierz
None (rysunek 20.10).
Część VI ♦ Współoperatywność 370

Rysunek 20.10.
Wybór skryptu
pakowania

Na kolejnej stronie kreatora należy podać typ pakietu (rysunek 20.11). Dostępne są trzy typy pakietów:
u Standardowy program instalacyjny (Standard Setup Package): tworzy zwykły program instalacyjny.
u Instalacja internetowa: tworzy program instalacji przez Internet.
u Pliki zależne: program instalacyjny zawiera tylko pliki zależne.

W tym przykładzie użyjemy standardowego pakietu instalacyjnego.

Na kolejnym ekranie podajemy katalog, w którym umieszczone zostaną pliki instalacyjne (rysunek 20.12). Jeżeli docelowy
katalog nie istnieje, zostanie automatycznie utworzony.
Rysunek 20.11.
Wybór typu pakietu
instalacyjnego

Rysunek 20.12.
Wybór katalogu
na pakiet
instalacyjny

Następny ekran zawiera listę plików, które zostaną umieszczone w pakiecie (rysunek 20.13). Kreator ten automatycznie
umieszcza na liście wszystkie potrzebne pliki. Zauważ, że na liście oprócz samego komponentu znajdują się również
biblioteki Visual Basica i inne pliki. Jeżeli chcesz dodać jeszcze inne pliki do pakietu, kliknij przycisk Add.
371 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.13.
Lista plików
w programie
instalacyjnym

Biblioteki Visual Basica muszą być zainstalowane na komputerze użyt-


kownika. Po jednokrotnym zainstalowaniu tych plików możesz nie
umieszczać ich już w programie instalacyjnym, co wyraźnie zmniejsza jego
objętość.

Na następnym ekranie ustawiamy parametry plików CAB. Pojedynczy plik CAB (plik jest skompresowany) może być
umieszczony na dysku CD-ROM lub w sieci, natomiast dla dyskietek należy utworzyć zwykle kilka plików.

Rysunek 20.14.
Ustawianie
parametrów
plików CAB

Na kolejnej stronie kreatora podajemy tytuł programu instalacyjnego (rysunek 20.15). Dobrze jest wpisać czytelną nazwę
programu, ponieważ właśnie ten napis zobaczy użytkownik po uruchomieniu programu instalacyjnego.

Rysunek 20.15.
Wpisywanie tytułu
instalacji

Na następnym ekranie wybieramy elementy, które umieszczone zostaną w menu Start (rysunek 20.16). Możesz utworzyć
grupę programów, w której będzie znajdowała się ikona instalowanego programu. Ponieważ zajmujemy się komponentem,
nie będzie potrzebna żadna grupa.
Część VI ♦ Współoperatywność 372

Rysunek 20.16.
Definiowanie
elementów menu
Start

Na kolejnym ekranie podajemy katalog, do którego będzie zainstalowany nasz komponent (rysunek 20.17). Zamiast
instalować komponent do katalogu Windows\System, umieść go w katalogu aplikacji, co ułatwi utrzymanie porządku.

Rysunek 20.17.
Definiowanie
katalogu docelowego

Na następnym ekranie zaznaczamy, czy nasz komponent będzie zainstalowany jako plik współdzielony, czy nie (rysunek
20.18). Plik współdzielony to taki, który jest używany przez więcej niż jedną aplikację.

Rysunek 20.18.
Definiowanie plików
współdzielonych

Na ostatniej stronie kreatora podajemy nazwę skryptu pakowania, który przechowuje wszystkie ustawione przed chwilą
ustawienia do późniejszego odtworzenia. Kliknij przycisk Finish, aby utworzyć pakiet.

Rysunek 20.19.
Wpisywanie nazwy
skryptu i tworzenie
pakietu

Po utworzeniu pliku (lub plików) CAB zostanie również utworzony raport z utworzenia pakietu zawierający dodatkowe
informacje. Jeżeli chcesz, możesz go zapisać do pliku.
373 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Wszystkie pliki instalacyjne znajdują się teraz w katalogu, który podałeś w trakcie pracy kreatora (rysunek 20.20). Pliki te
należy rozesłać do klientów, którzy zainstalują komponent na swoich komputerach tak jak wszystkie inne programy.
Dwukrotne kliknięcie ikony programu instalacyjnego (lub poprzez funkcję Dodaj/Usuń Programy w Panelu Sterowania)
uruchomi program instalacyjny, który zainstaluje komponent i inne potrzebne pliki (rysunek 20.21).

Rysunek 20.20.
Utworzone pliki
instalacyjne

Rysunek 20.21.
Uruchomiony
program
instalacyjny

Rozprowadzanie plików
przy użyciu kreatora Package and Deployment Wizard
Po utworzeniu plików instalacji musisz rozprowadzić je do użytkowników. Część Deploy kreatora Package and Deployment
Wizard zawiera procedurę ułatwiającą ten proces.

Uruchom kreator i na pierwszym ekranie kliknij przycisk Browse, aby odszukać plik projektu (np. cSoundObject.vbp, tak
jak na rysunku 20.22). Następnie kliknij przycisk Deploy.
Rysunek 20.22.
Kliknij przycisk
Deploy

Na następnym ekranie wybierz skrypt dystrybucji (rysunek 20.23).


Część VI ♦ Współoperatywność 374

Rysunek 20.23.
Wybór skryptu
dystrybucji

Na kolejnym ekranie wybierz pakiet, który chcesz rozprowadzać (rysunek 20.24).

Rysunek 20.24.
Wybór pakietu do
dystrybucji

Następny ekran zawiera listę dostępnych metod dystrybucji. Można umieścić pakiet w lokalnym lub sieciowym
katalogu albo wysłać na serwer WWW (rysunek 20.25). W tym przykładzie użyjemy katalogu na dysku.

Na kolejnym ekranie kreatora wybieramy katalog, do którego będą wysyłane pliki pakietu (rysunek 20.26). Może być to
katalog na serwerze sieciowym.
Rysunek 20.25.
Wybór metody
dystrybucji

Rysunek 20.26.
Wybór katalogu
docelowego

Na ostatnim ekranie można podać nazwę skryptu, do którego zostaną zapisane ustawienia (rysunek 20.27). Można go użyć
przy kolejnym użyciu tego kreatora. Aby zakończyć pracę kreatora i umieścić pliki w katalogu dystrybucji, kliknij Finish.
375 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.27.
Wpisywanie
nazwy skryptu
i rozprowadzanie
pakietu

Po wykonaniu dystrybucji tworzony jest raport, który można zapisać na dysku.

Wpisy w rejestrze
Aby komponent mógł działać, do rejestru muszą być wprowadzone odpowiednie informacje. Komponentowi musi zostać
przypisany globalny unikatowy identyfikator (GUID). Jest to identyfikator generowany w sposób losowy.

Gdy instalujemy aplikację przy użyciu programu instalacyjnego utworzonego za pomocą kreatora Package and
Deployment Wizard, niezbędne wpisy są tworzone automatycznie. Jeżeli nie został użyty kreator, musimy sami
zarejestrować komponent.

Jeżeli komponent jest w postaci pliku EXE, jest on automatycznie rejestrowany po uruchomieniu z wiersza poleceń
lub poprzez dwukrotne kliknięcie jego ikony w Explorerze.

Jeżeli komponent jest w postaci pliku DLL, do jego rejestracji należy użyć programu REGSVR32.EXE, który znajduje się w
katalogu Windows/System (WINNT/System32 w systemie Windows NT).

Aby zarejestrować komponent, wpisz poniższy wiersz w oknie Uruchom (rysunek 20.28):
REGSVR32.EXE "C:\Componnets\SoundObject.Dll"

Rysunek 20.28.
Ręczna rejestracja
ActiveX DLL przy
użyciu programu
REGSVR32

Można również wyrejestrowywać komponenty. Dla ActiveX EXE wykonaj ten program z wiersza poleceń dodając jako
parametr /UNREGSERVER. Dla ActiveX DLL do programu REGSVR32 dodaj parametr /U.

Jeżeli często rejestrujesz i wyrejestrowujesz komponenty przy użyciu


REGSVR32, dodaj REGSVR32 do katalogu SendTo w katalogu Windows.
Następnie możesz kliknąć prawym klawiszem myszy plik DLL i wybrać
REGSVR32 z menu kontekstowego.

Zgodność komponentów
Jak wcześniej wspominaliśmy, komponent musi zostać prawidłowo zarejestrowany. W rejestrze Windows tworzony jest
dla niego tzw. GUID. Co się stanie, gdy po zainstalowaniu komponentu zostanie on zmodyfikowany? Gdy instalujemy
zmodyfikowany komponent, czy musi on zostać powtórnie zarejestrowany pod innym identyfikatorem GUID?

Aby odpowiedzieć na te pytania, wróćmy do okna właściwości projektu na zakładkę Component. Na tej zakładce znajduje
się kilka opcji w części zatytułowanej Version Compatibility: No Compatibility, Project Compatibility oraz Binary
Compatibility.

W czasie gdy tworzymy komponent, powinna być wybrana opcja Project Compatibility. Uruchamia to funkcję
zarządzania kluczami w rejestrze za każdą kompilacją komponentu.

Gdy komponent trafi już do klientów, zmień ustawienie na Binary Compatibility (rysunek 20.29).
Część VI ♦ Współoperatywność 376

Rysunek 20.29.
Wybrana opcja
Binary Compatibility
oraz wpisana nazwa
wzorcowego
pliku DLL

W polu tekstowym poniżej tą opcją podajemy nazwę pliku DLL względem którego utrzymujemy zgodność. Za pomocą
klawisza „...” możemy odszukać na dysku wzorcowy plik DLL. Teraz, gdy utworzymy nowy plik DLL, będzie on zgodny z
plikiem wzorcowym.

Nawet, gdy włączysz opcję Binary Compatibility, jeżeli zmienisz interfejs


komponentu, wywołująca go aplikacja zawiedzie w czasie użycia kom-
ponentu. Przykładowo, gdy metoda komponentu cSound PlaySound
zostanie zmieniona na PlayMusic, komponent przestanie być zgodny z
poprzednimi wersjami. W takim przypadku zmień opcję zgodności na
No Compatibility i roześlij do użytkowników nowy komponent wraz z apli-
kacją Accessa.

Uważaj, aby nie usunąć wzorcowego pliku DLL, do którego odwołujesz się
w opcji Binary Compatibility. Nadaj mu specjalną nazwę i zapisz w bez-
piecznym miejscu. Przykładem nazwy może być Binary-cSoundObject.dll,
informująca o wykorzystaniu tego pliku jako wzorca w opcji zgodności
binarnej.

Kiedy używamy opcji No Compatibility? Załóżmy, że po rozesłaniu komponentu cSound zdecydowałeś się usunąć metodę
PlaySound, zastępując ją metodą o innej nazwie. Wszystkie aplikacje używające tego komponentu przestaną działać,
ponieważ polegają one na nazwie metody PlaySound. W takim przypadku wybierz opcję No Compatibility, dzięki czemu
zostanie utworzony nowy GUID. Najlepiej w takiej sytuacji utworzyć nowy pakiet instalacyjny i rozesłać go tak jak za
pierwszym razem.

Przed powtórnym zainstalowaniem komponentu najlepiej usunąć starą


wersję.

Komponent obsługi błędów


W rozdziale 13. „Profesjonalna obsługa błędów” omówiony został moduł klasowy obsługi błędów, który zawierał
następujące funkcje:
u Zapisywanie błędów w tabeli Accessa;
u Zapisywanie błędów w pliku tekstowym;
u Przesyłanie błędów jako e-mail;
u Zapisywanie błędów w kalendarzu Outlooka.

Do tego rozdziału dołączony został jeszcze obszerniejszy moduł obsługi błędów, który używa komponentu cError
(cErrorObject.dll). Na dysku znajduje się kompletny projekt ActiveX DLL, więc możesz go od razu użyć jako „globalny
moduł obsługi błędów”. Przy użyciu tego pliku DLL możesz użyć tego modułu w Accessie, VB, Office i innych
aplikacjach.
377 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Na dysku znajdują się aplikacje Accessa i Visual Basica, które używają


komponentu cError do obsługi błędów.

Dane modułu obsługi błędów


Moduł obsługi błędów zapisuje dane w bazie danych Accessa o nazwie Global Error Handler Data.mdb. Baza ta zawiera
dwie tabele. Informacje o błędach przechowywane są w tabeli tblErrorLog. Druga tabela, tblErrorOptions, zawiera
ustawienia sposobu pracy modułu. Formularz frmErrorOptions, przedstawiony na rysunku 20.30, zapewnia łatwy
dostęp do tych ustawień.

Rysunek 20.30.
Formularz ustawień
pracy modułu
obsługi błędów

Dodatkowo w bazie umieszczony jest raport błędów.

Komponent cError
Komponent obsługi błędów wykonuje dużo operacji. Zawiera on sześć modułów klasowych:
u cComputerName – pobiera nazwę komputera.
u cDBConnection – tworzy połączenie ADO.
u cError – przetwarza informacje o błędach.
u cSound – odgrywa pliki dźwiękowe.
u cSystemInformation – pobiera informacje o komputerze, takie jak: system operacyjny, procesor, ilość
zainstalowanej i wolnej pamięci.
u cUserName – pobiera nazwę użytkownika Windows.

Tworzenie formantów ActiveX


Visual Basic umożliwia tworzenie własnych formantów ActiveX, co daje ogromne możliwości rozszerzania aplikacji.

Rodzaje formantów ActiveX


W rozdziale 9. „Rozszerzanie formularzy za pomocą formantów ActiveX” opisane zostały 23 formanty wraz z przykładami
ich użycia.

Istnieją dwa rodzaje komponentów ActiveX: formanty interfejsu użytkownika i programowe. Formanty interfejsu
użytkownika to takie, którymi zajmowaliśmy się w rozdziale 9., jak TreeView czy ListView. Użytkownicy mogą nimi
manipulować. Formanty programowe są dostępne tylko dla programistów, użytkownicy nie mogą nimi manipulować.
Przykładem może być ImageList lub CommonDialog.
Część VI ♦ Współoperatywność 378

Atrybuty formantów ActiveX


Formanty ActiveX nie mogą istnieć niezależnie, muszą zostać utworzone w aplikacji bazowej, zwykle na formularzu.

Skompilowany formant ActiveX jest zapisany w pliku zwykle z rozszerzeniem OCX. Pojedynczy plik OCX może zawierać
kilka formantów. Przykładowo MSCOMCTL.OCX, dostarczany przez Microsoft, zawiera następujące formanty ActiveX:
ImageCombo, ImageList, ListView, ProgressBar, Slider, StatusBar, TabStrip, ToolBar oraz TreeView.

Formanty ActiveX są wewnątrzprocesowymi serwerami automatyzacji. Dlatego formant ActiveX, który utworzysz i
użyjesz w aplikacji Accessa, jest uruchamiany w jednym procesie razem z aplikacją Accessa, co daje doskonałą wydajność
programu.

Tworzenie programowych formantów ActiveX


W Accessie, gdy potrzebny jest stoper, programiści używają zdarzenia On Timer i właściwości Timer formularza. Jedynym
problemem tego podejścia jest to, że może być użyty tylko jeden stoper. Co zrobić, jeżeli potrzebujemy wielu niezależnych
stoperów?

Visual Basic zawiera wbudowany formant Timer, który nie jest dostępny z Accessa. Timer VB to formant programowy,
który może wykonywać procedurę co zadany okres czasu. Aby użyć formantu VB Timer, umieść ją na formularzu i ustaw
właściwość Interval na określony czas w milisekundach (1000 milisekund to 1 sekunda), tak jak pokazane jest na
rysunku 20.31. Procedura obsługi zdarzenia Timer wykonywana jest co podany okres czasu. Można umieścić wiele
stoperów na formularzu. Każdy z nich pracuje niezależnie.

Rysunek 20.31.
Ustawianie
właściwości Interval
formantu Timer

W tej części rozdziału utworzysz własny formant ActiveX Timer, który może zostać użyty w Accessie i innych
aplikacjach.

Projekt formantu i baza Accessa wykorzystująca formant Timer


zamieszczone są na dysku CD-ROM dołączonym do książki. Pa-
miętaj, że musisz zarejestrować (lub skompilować projekt) formant
ActiveX.

Utworzenie projektu dla formantu ActiveX


Aby utworzyć formant ActiveX po uruchomieniu Visual Basica, wybierz ActiveX Control w oknie New Project.
379 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.32.
Wybór formantu
ActiveX z okna
dialogowego
New Project

Tworzenie interfejsu
Po otwarciu projektu to co widzisz, wydaje się być formularzem. Nie jest to jednak formularz lecz obiekt UserControl.
Obiekt ten używany jest do tworzenia interfejsu formantu ActiveX. W oknie właściwości zmień nazwę z UserControl1.
na ctlTimer.

Formanty ActiveX mogą zawierać inne formanty. W naszym formancie ctlTimer użyjemy formantu PictureBox
pobranego z paska narzędzi (rysunek 20.33). Nazwij formant PictureBox picClock i ustaw jego właściwość Picture
na CirClock.bmp z podkatalogu Bitmaps\Gauge w katalogu, gdzie zainstalowałeś Visual Basic. Ten rysunek zegara będą
widzieli programiści, używając tego formantu.

Rysunek 20.33.
Wstawianie
formantu PictureBox
do UserControl

Następnie przenieś formant Visual Basica Timer z paska narzędzi do naszego formantu i nazwij go ctlVBTimer (rysunek
20.34). Zauważ, że w oknie właściwości formantu znajduje się właściwość Interval. Będziemy używać tej właściwości
w naszym formancie ActiveX.
Rysunek 20.34.
Wstawianie
formantu VB Timer
do UserControl

Teraz zmniejszymy nasz formant. Najpierw przesuń formant VB Timer dokładnie na formant PictureBox, a następnie
wybierz Send to Back z menu Format. Spowoduje to ukrycie formantu. Teraz zmniejsz rozmiar obiektu UserControl tak,
aby był widoczny tylko formant PictureBox (rysunek 20.35).
Część VI ♦ Współoperatywność 380

Rysunek 20.35.
Zmniejszanie
UserControl

Ponieważ tworzymy formant programowy, użytkownik nigdy go nie zobaczy. We właściwościach obiektu UserControl
ustaw właściwość InvisibleAtRuntime na True.

Ustawianie właściwości projektu


Wybierz Project1. Properties z menu Project. W oknie właściwości projektu wprowadź nazwę projektu (cTimerControl)
i opis (Formant cTimer) w sposób pokazany na rysunku 20.36. Zamknij okno przez kliknięcie przycisku OK.
Rysunek 20.36.
Wprowadzanie
nazwy i opisu
projektu

Zapisywanie projektu
Aby zapisać projekt, wybierz Save Project z menu File. Najlepiej zapisać plik projektu (plik .vbp) i formant (plik .ctl) w
tym samym katalogu, np. Formant Timer.

Dodawanie metod i zdarzeń


Kliknij obiekt UserControl (nie PictureBox) i przejrzyj listę właściwości. Zauważ, że nie ma tam właściwości
Interval. Musisz ją tam dodać. Również należy dodać zdarzenie Timer, aby było możliwe wpisywanie kodu procedury
uruchamianej po zajściu zdarzenia. Aby dodać właściwości, metody i zdarzenia, uruchom kreator ActiveX Control Interface
Wizard.

Użycie kreatora ActiveX Control Interface Wizard


Kreator ten uruchamiamy poprzez wybranie ActiveX Control Interface Wizard z menu Add-Ins. Jeżeli nie masz go w tym
menu, wybierz Add-In Manager, VB 6. ActiveX Control Interface Wizard i kliknij pole wyboru Load on Startup.

Pierwszy ekran kreatora jest ekranem informacyjnym (rysunek 20.37). Kliknij przycisk Next.
381 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.37.
Ekran informacyjny
kreatora ActiveX
Control Interface
Wizard

Po prawej stronie ekranu mamy listę standardowych właściwości, metod i zdarzeń (rysunek 20.38). Usuń wszystkie
pozycje z tej strony. Po lewej stronie okna wybierz właściwość Interval oraz zdarzenie Timer i przenieś je na prawą
stronę. Kliknij Next.

Rysunek 20.38.
Ekran kreatora
Selected Interface
Members

Na ekranie Create Custom Interface Members kliknij Next, ponieważ dodaliśmy już wszystkie interesujące nas elementy
(rysunek 20.39).

Rysunek 20.39.
Ekran kreatora
Create Custom
Interface Members

Na ekranie Set Mapping wybierz właściwość Interval oraz zdarzenie Timer i przypisz je do UserControl (rysunek
20.40). Aby przejść do kolejnego ekranu, kliknij przycisk Next.

Rysunek 20.40.
Ekran Set Mapping

Na ekranie Set Attributes wybierz właściwość Interval i upewnij się, że typ jest ustawiony na Long (rysunek 20.41),
następnie kliknij przycisk Next.
Część VI ♦ Współoperatywność 382

Rysunek 20.41.
Ekran Set Attributes

Na ekranie Finished kliknij przycisk Finish (rysunek 20.42). Kreator utworzy program dodający właściwość Interval
oraz zdarzenie Timer do formantu ActiveX. Można również zapisać raport na dysku.

Rysunek 20.42.
Ekran Finished

Otwórz okno kodu dla obiektu UserControl i obejrzyj program (rysunek 20.43). Kreator utworzył Property Get oraz
Property Let dla właściwości Interval. Zostało również wygenerowane zdarzenie Timer.

Dodajemy kod do formantu ActiveX


Kreator ActiveX Control Interface Wizard wykonał za Ciebie dużą część pracy, ale musisz dodać jeszcze kilka wierszy kodu,
aby dokończyć pracę nad formantem Timer.

Wywoływanie zdarzenia

Nasz formant ActiveX zawiera formant VB Timer, który posiada zdarzenie Timer. Nasz formant również posiada
zdarzenie Timer, które zostało dodane przez kreator ActiveX Control Interface Wizard. Musisz zsynchronizować te dwa
zdarzenia tak, aby po zajściu zdarzenia Timer z formantu Visual Basica uruchamiane było zdarzenie Timer naszego
formantu ActiveX.
Rysunek 20.43.
Kod wygenerowany
przez ActiveX
Control Interface
Wizard
383 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Aby to zrealizować, będziesz musiał wywołać zdarzenie (ang. raise)w UserControl. W oknie programowania wybierz
ctlVBTimer z listy obiektów po lewej stronie u góry okna. Następnie wybierz Timer z listy zdarzeń obok listy obiektów.
Utworzona zostanie procedura obsługi zdarzenia Timer (rysunek 20.44). Wprowadź kod pokazany na rysunku 20.44, który
wywoła zdarzenie Timer.

Rysunek 20.44.
Wywołanie
procedury
RaiseEvent

Jaki jest efekt tych operacji? Gdy uruchomiona zostanie obsługa zdarzenia z obiektu Timer Visual Basica, wywoła on
zdarzenie Timer formantu ActiveX. Uruchomi to procedurę obsługi zdarzenia utworzoną dla formantu ActiveX.

Użycie zdarzenia ReadProperties

Gdy programista umieszcza na formatce Twój formant Timer, ustawia właściwość Interval. Wartość właściwości
Interval musi być zsynchronizowana z właściwością obiektu VB Timer.

Formanty ActiveX zwykle są tworzone, gdy są dodawane do formularza przez programistów oraz gdy zawierający je
formularz jest otwierany. Odpowiednim miejscem do zsynchronizowania właściwości Interval jest zdarzenie
ReadProperties, ponieważ jest ono wywoływane w trakcie otwierania formularza zawierającego formant. Poniższy
fragment programu ustawia wartość właściwości Interval w obiekcie VB Timer na identyczną z tej samej właściwości
w Twoim formancie.
' Ustaw wartość właściwości Interval z obiektu VB Timer
' na taką samą jak w obiekcie Timer
UserControl.ctlVBTimer.Interval = Me.Interval

Upewnij się, że zapisałeś projekt.

Testowanie formantu ActiveX w Visual Basicu


Przed użyciem formantu w Accessie przetestujmy go w Visual Basicu.

Mając otwarty projekt formantu ActiveX, możesz dodać projekt dla standardowego pliku EXE i przetestować formant na
formularzu VB. Aby dodać nowy projekt, wybierz Add Project z menu File. W oknie New Project wybierz Standard EXE.
Zauważ, że oba projekty są wyświetlane w oknie Project Explorer (rysunek 20.45).

Rysunek 20.45.
Dodajemy projekt do
testowania formantu

Ponieważ mamy teraz dwa projekty, ustaw Startup Project na Standard EXE (Project1). W oknie Project Explorer kliknij
prawym klawiszem myszy Project1. i wybierz Set as Startup. Teraz, gdy będziesz uruchamiał projekt, uruchomiony
zostanie Project1. Następnie zamknij wszystkie otwarte okna projektu. W menu Windows wybierz kolejno otwarte okna
(oprócz Form1) i zamknij je.
Część VI ♦ Współoperatywność 384

W trybie projektowania formularza Form1. otwórz pasek narzędzi. Zauważ, że znajduje się tam nowy formant o nazwie
ctlTimer. Wstaw ten formant na formularz VB (rysunek 20.46).

Nowy formant Timer może być używany identycznie jak inne formanty (np.: TextBox). Można ustawiać jego właściwości z
okna właściwości oraz tworzyć procedury obsługi zdarzeń.
Rysunek 20.46.
Wstawianie
formantu Timer
na testowy formularz

W oknie właściwości ustaw właściwość Interval na 5000. Ponieważ jest to czas w milisekundach, Timer będzie
wywoływany co 5 sekund.

Następnie wybierz Code z menu View, aby otworzyć okno programowania. Wybierz ctlTimer1. z listy obiektów oraz
Timer z listy zdarzeń. W procedurze obsługi zdarzenia wprowadź proste okno komunikatu (rysunek 20.47).

Rysunek 20.47.
Procedura obsługi
zdarzenia Timer

Uruchom projekt, wybierając Start z menu Run (lub naciśnij F5). Co pięć sekund na ekranie pojawi się okno komunikatu
(rysunek 20.48). Zauważ, że komponent nie jest widoczny w czasie wykonywania programu.
385 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.48.
Okno komunikatu
otwiera się
co 5 sekund

Po przetestowaniu formantu w Visual Basicu użyjemy go w Accessie.

Użycie formantu Timer na formularzu Accessa


Przetestowanie formantu w Visual Basicu było bardzo proste. Aby użyć formantu w Accessie, należy skompilować
formant.

Otwórz projekt formantu ActiveX i wybierz Make cTimerControl z menu File. Zapisz plik OCX w tym samym katalogu co
projekt.

Formant ActiveX został skompilowany oraz zostały wprowadzone wpisy do rejestru.

Otwórz nowy formularz w trybie projektowania w bazie danych Accessa. Z menu Wstaw wybierz Formant ActiveX. Wybierz
formant Timer (cTimerControl) z listy, a następnie kliknij OK, aby zamknąć okno (rysunek 20.49).

Rysunek 20.49.
Wybór
cTimerControl
z okna Wstawianie
formantu ActiveX

Tak jak robiłeś to na formularzu VB, ustaw właściwość formantu Interval na 5000. oraz utwórz okno komunikatu w
obsłudze zdarzenia Timer.

Formant cTimerControl będzie teraz działać na formularzu Accessa.

Tworzenie wielu formantów Timer


Na początku tego rozdziału wspominaliśmy o możliwości wykorzystania zdarzenia OnTimer z formularza Accessa
jako stopera. Jednak w ten sposób możliwe jest uruchomienie tylko jednego stopera. Możesz wstawić do formularza kilka
formantów Timer i każdy z nich będzie pracować niezależnie (rysunek 20.50).

Rysunek 20.50.
Kilka formantów
Timer pracujących
jednocześnie
Część VI ♦ Współoperatywność 386

Rozprowadzanie formantu ActiveX Timer


Sposób rozprowadzania formantów ActiveX jest w zasadzie taki sam jak rozprowadzanie komponentów ActiveX.
Przeczytać możesz o tym wcześniej w części zatytułowanej „Dystrybucja komponentów ActiveX”.

Tworzenie okna właściwości


W rozdziale 9. opisywaliśmy, w jaki sposób utworzyć okno właściwości, aby łatwo można było ustawiać wartości
właściwości formantu ActiveX. Na rysunku 20.51. pokazane jest okno właściwości formantu ImageList.

Rysunek 20.51.
Okno właściwości
formantu ImageList

Można również utworzyć okno właściwości dla naszego komponentu Timer. W oknie projektu komponentu ActiveX
wybierz Add Property Page z menu Project. W oknie dialogowym Add Property Page wybierz kreator VB Property Page
Wizard. Kliknij przycisk Open w celu uruchomienia kreatora.

Na ekranie startowym kliknij przycisk Next.

Na ekranie Select the Property Pages kliknij przycisk Add i dodaj stronę General (rysunek 20.52).

Rysunek 20.52.
Kreator VB Property
Page Wizard: strona
Select the Property
Pages

Na ekranie Add Properties kliknij zakładkę General. Przesuń właściwość Interval z listy po lewej stronie okna do
listy po prawej (rysunek 20.53) a następnie kliknij Next.

Rysunek 20.53.
Kreator VB Property
Page Wizard: strona
Add Properties

Na ekranie Finished kliknij przycisk Finished. Kreator utworzy okno właściwości i dodatkowo może być utworzony raport.
Zauważ, że okno właściwości znajduje się w oknie Project Explorer (rysunek 20.54).
387 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.54.
Okno właściwości
w oknie Project
Explorer

Użycie okna właściwości


Aby użyć okno właściwości, zapisz i ponownie skompiluj projekt formantu ActiveX. Otwórz formularz Accessa w
trybie projektowania i dodaj formant Timer. Następnie kliknij prawym klawiszem myszy formularz i wybierz z menu
cTimerControl properties. Na stronie właściwości możesz wprowadzić wartość właściwości Interval (rysunek 20.55).
Rysunek 20.55.
Użycie okna
właściwości

Użycie formantu Timer w innych aplikacjach


Nasz formant nie jest ograniczony do stosowania tylko w VB i Accessie. Ten sam formant może być używany w Wordzie,
Excelu, Outlooku i innych aplikacjach.

Tworzenie formantów ActiveX interfejsu użytkownika


Większość formantów ActiveX posiada interfejs użytkownika wykorzystywany do manipulacji formantem. W tej części
utworzymy taki formant ActiveX. Przykładowy formant nazywa się cSlider i zawiera dwa formanty Slider i UpDown.
Gdy użytkownik zwiększa i zmniejsza wartość za pomocą formantu UpDown, Slider się przesuwa.

Projekt VB formantu ActiveX oraz baza danych Accessa, która używa


formantu cSlider, są dostępne na dysku CD-ROM dołączonym do książ-
ki. Pamiętaj, aby zarejestrować formant (lub skompilować projekt) przed
jego użyciem.

Tworzenie interfejsu użytkownika


Tak jak dla formantów programowych otwórz projekt formantu ActiveX. Dodaj formant Slider oraz UpDown do obiektu
UserControl w sposób pokazany na rysunku 20.56. Zauważ, że można w jednym formancie ActiveX umieścić wiele
innych formantów.

Nazwij następująco obiekty:


UserControl: cSlider
Slider control: ctlSlider
UpDown control: ctlUpDown

a następnie zmniejsz obiekt UserControl.


Część VI ♦ Współoperatywność 388

Rysunek 20.56.
Dodanie formantów
Slider oraz UpDown
do obiektu
UserControl

Kliknij prawym klawiszem myszy formant ctlUpDown i wybierz Properties z menu kontekstowego, co spowoduje
otwarcie okna właściwości. W oknie właściwości należy związać formant UpDown z Slider przy użyciu właściwości
Buddy. Od tej chwili formanty będą działać razem bez pisania ani jednego wiersza kodu.

Kliknij zakładkę Buddy w oknie właściwości. W polu tekstowym Buddy Control wprowadź ctlSlider. Spowoduje to
połączenie formantów ctlSlider i ctlUpDown. Wybierz Value z listy Buddy Property, co spowoduje, że zmiana wartości
ctlUpDown zmieni wartość ctlSlider. Zaznacz pole wyboru AutoBuddy i kliknij OK, aby zamknąć okno właściwości
(rysunek 20.57).

Rysunek 20.57.
Ustawienie
właściwości Buddy
w oknie właściwości

Ustawienie właściwości projektu


Wybierz Project1 Properties z menu Project. W oknie dialogowym Project Properties wprowadź nazwę projektu
(cSliderControl) oraz opis projektu (formant cSlider). Kliknięcie OK zamyka okno (rysunek 20.58).

Zapisywanie projektu
Zapisz projekt i obiekt UserControl, wybierając Save Project z menu File. Najlepiej zapisać projekt (plik .vbp) i obiekt
UserControl (plik .ctl) w tym samym katalogu.

Testowanie formantu na formularzu Visual Basica


Aby przetestować formant cSlider na formularzu Visual Basica, wykonaj te same czynności co przy testowaniu formantu
designtime.
Rysunek 20.58.
Wprowadzanie
nazwy i opisu
projektu w oknie
właściwości projektu

Użycie formantu cSlider na formularzu Accessa


Otwórz projekt formantu i wybierz Make cSliderControl.ocx z menu File. Zapisz plik OCX w tym samym katalogu co plik
projektu. Po tej operacji formant ActiveX jest gotowy do pracy, a w rejestrze są wszystkie odpowiednie wpisy.
389 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Otwórz formularz w trybie projektowania w bazie Accessa. Wybierz Formant ActiveX z menu Wstaw, a następnie
wybierz cSliderControl z listy. Kliknięcie OK zamyka okno dialogowe.

Formant cSlider działa teraz na formularzu Accessa (rysunek 20.59). Gdy zostanie kliknięty UpDown, zmieni się również
pozycja formantu Slider.

Rysunek 20.59.
Formant ActiveX na
formularzu Accessa

Dystrybucja formantu ActiveX cSlider


Rozprowadzanie formantów ActiveX nie różni się niczym od rozprowadzania komponentów ActiveX. Zajrzyj do części
„Dystrybucja komponentów ActiveX”.

Użycie formantu cSlider w innych aplikacjach


Twój formant cSlider nie jest ograniczony tylko do aplikacji VB i Accessa. Ten sam formant może być użyty Wordzie,
Excelu, Outlooku i innych aplikacjach.

Tworzenie instalacyjnego pakietu internetowego


Aby użyć formantu ActiveX cSlider na stronie WWW, użyj opcji Internet Package w kreatorze Package and
Deployment Wizard.

Uruchom kreator i wybierz plik projektu komponentu cSlider (plik .vbp). Kliknij przycisk Package, aby przejść do
następnego ekranu (rysunek 20.60). Wybierz Internet Package i kliknij przycisk Next.

Rysunek 20.60.
Wybór pakietu
internetowego

Wybierz skrypt pakowania (rysunek 20.61). Ponieważ pierwszy raz wykonujesz pakiet internetowy, wybierz None i kliknij
Next.

Rysunek 20.61.
Wybór skryptu
pakowania

Wybierz typ Internet Package i kliknij Next (rysunek 20.62).


Część VI ♦ Współoperatywność 390

Rysunek 20.62.
Wybór typu pakietu

Wybierz katalog, gdzie zapisywane będą pliki pakietu i kliknij Next (rysunek 20.63). Domyślnie tworzony jest katalog
pakietu jako podkatalog foldera z plikiem projektu.
Rysunek 20.63.
Wybór katalogu
pakietu

Ekran Included Files zawiera wszystkie pliki niezbędne do użycia formantu ActiveX. Dołączone są również biblioteki VB i
inne niezbędne pliki (rysunek 20.64). Kliknij przycisk Next.

Rysunek 20.64.
Pliki zawarte
w pakiecie
internetowym

Na ekranie File Source podaj położenie plików zawartych w pakiecie instalacyjnym (rysunek 20.65). Plik, w którym
znajduje się Twój formant ActiveX (plik OCX), znajdzie się w skompresowanym pliku cab. Domyślnym ustawieniem dla
bibliotek VB i innych plików Microsoftu jest witryna WWW firmy Microsoft. Możesz pozostawić domyślne ustawienie,
ponieważ w razie potrzeby użytkownicy załadują potrzebne pliki z serwera WWW Microsoftu.

Ustaw serwer WWW Microsoftu jako położenie bibliotek VB i innych pli-


ków Microsoftu. Microsoft zapewnia większą przepustowość łącz niż
większość firm, co zapewnia poprawne załadowanie aktualnych plików.

Na ekranie Safety wymieniony jest tylko formant cSlider. Wybierz Yes dla opcji Safe for Scripting oraz Yes dla Safe for
Initialization (rysunek 20.66). Jest to Twoja deklaracja, że komponent jest bezpieczny. Kliknij Next, aby przejść do
następnego ekranu.

Na ostatnim ekranie możesz podać nazwę skryptu, aby zapisać ustawienia wszystkich opcji w kreatorze. Używając
zapisanego skryptu, nie trzeba ponownie wybierać ustawień w kreatorze (rysunek 20.67). Kliknij Finish, aby wygenerować
pakiet.
391 Rozdział 20. ♦ Użycie Visual Basic z Access’em

Rysunek 20.65.
Wybór źródła plików

Rysunek 20.66.
Ustawianie ustawień
bezpieczeństwa

Rysunek 20.67.
Wybór nazwy dla
skryptu oraz
tworzenie pakietu

Po zakończeniu pracy kreator tworzy raport, który może zostać zapisany na dysku.

Użycie formantu cSlider na stronie WWW


Otwórz katalog, w którym zapisałeś pakiet internetowy. Zauważ, że został utworzony plik cSliderControl.htm (rysunek
20.68).

Dwukrotne kliknięcie pliku cSliderControl.htm otwiera stronę w przeglądarce internetowej. Formant cSlider działa w
przeglądarce identycznie jak w formularzach VB i Accessa.
Rysunek 20.68.
Pliki w katalogu
pakietu
internetowego
Część VI ♦ Współoperatywność 392

Nie wszystkie przeglądarki obsługują formanty ActiveX. Jednak Microsoft


Internet Explorer, jak widać na rysunku 20.69, obsługuje formanty
ActiveX.

Rysunek 20.69.
Formant cSlider na
stronie WWW

Aby zobaczyć kod HTML strony WWW, otwórz ją w Internet Explorerze i wybierz Źródło z menu Widok. Zauważ, że w
kodzie HTML znajduje się formant cSlider oraz jego classID (rysunek 20.70):
<OBJECT CLASSID="clsid:5220cb21-c88d-11cf-b347-00aa00a28331">
<PARAM NAME="LPKPath" VALUE="LPKfilename.LPK">
</OBJECT>
-->

<OBJECT ID="cSlider"
CLASSID="CLSID:A3251E4A-CCCF-11D2-A8AC-0010A4F61FE6"
CODEBASE="cSliderControl.CAB#version=1,0,0,0">
</OBJECT>

Jeżeli chcesz używać formantu cSlider na innej stronie WWW, skopiuj kod obiektu HTML z jednej strony do innej.
Rysunek 20.70.
Formant ActiveX
w kodzie HTML
Część VII
Zagadnienia wielodostępu
W tej części:
u Zagadnienia wielodostępu, serwer plików, blokowanie.
u Replikacja i JRO.
u Bezpieczeństwo.
Rozdział 21.
Zagadnienia wielodostępu, serwer
plików, blokowanie
W tym rozdziale:
u Konflikty.
u Konfiguracja.
u Blokady Accessa i Jet.
u Blokady Oracle / SQL Server.

Gdy baza danych Accessa opuszcza swoje środowisko programistyczne i zaczyna być używana przez ludzi, dla których
była utworzona, jest narażona na efekty uboczne wielodostępu. Najbardziej irytującym problemem powodowanym przez
wielodostęp są konflikty w dostępie do rekordów.

Konflikty
Ważne jest, aby pamiętać, że każda wieloużytkownikowa baza danych jest narażona na problemy powodowane przez
blokady i konflikty. Ukrywanie komunikatów o błędach lub nadzieja na to, że wszystko dobrze pójdzie, nie usunie
problemów. Mimo że zagadnienia wielodostępu wydają się skomplikowane, dokładne zrozumienie, w jaki sposób Jet
blokuje dane i zarządza wieloma użytkownikami, nie jest trudne. Pozostawienie nierozwiązanych zagadnień wielodostępu
tworzy zwykle dużo większe problemy nękające użytkowników, klientów i wpływające na naszą reputację. Nieprawidłowe
rozwiązanie problemów wielodostępu prowadzi do następujących problemów:
u Nowe rekordy nie są zapisywane – nie ma nic gorszego dla użytkownika wprowadzającego dane do aplikacji, jak
zniknięcie wprowadzonych danych. Fakt, że prawdopodobnie nie będzie mógł powtórzyć tego błędu, nie znaczy,
że problem nie istnieje, raczej mają rację mówiąc, że aplikacja jest niepewna.
u Zmiany nie zostają zapisane – klient może nawet nie zauważyć, że zmiany nie zostały zapisane. Jednak kiedyś w
przyszłości arkusz bilansu będzie nieprawidłowy lub nie będzie zgadzać się stan magazynu, albo zamówienie
ważnego klienta zostanie wysłane pod zły adres. Są to skomplikowane problemy i często nie są wykrywane na
czas.
u Użytkownicy mogą otrzymywać tajemnicze komunikaty, że system nie może zwrócić żądanych danych. Mimo że
jest to mniej dramatyczna sytuacja, nie należy rozczarowywać użytkowników, gdy system załamuje się przy
niewielkim obciążeniu.

W Accessie zagadnienia wielodostępu to nie tylko blokowanie i zdejmowanie blokad. Ponieważ aplikacja przechowywana
jest w pojedynczym pliku, a aplikacja ma formularz związany bezpośrednio z danymi, dyskusja na temat wielodostępu
musi zawierać zagadnienia dotyczące zarządzania plikami, konfiguracji, technik tworzenia interfejsu użytkownika oraz
właściwości kwerend i formularzy. Zwykle aplikacja Accessa wymaga kombinacji kilku taktyk, ponieważ napotkasz różne
problemy wielodostępu w kilku różnych miejscach aplikacji.
395 Rozdział 21. ♦ Zagadnienia wielodostępu, serwer plików, blokowanie

Konfiguracja
Aplikacja Accessa może być skonfigurowana na kilka sposobów, aby przystosować ją do obsługi wielu użytkowników.
Każdy z nich ma swoje wady i zalety. Podstawowe zalety i wady są opisane poniżej.
u Konfiguracja sieciowa. W takiej konfiguracji pojedynczy plik MDB umieszczony jest na serwerze sieciowym, a
użytkownicy uruchamiają aplikację z tego serwera. Zaletą takiej konfiguracji jest łatwość konserwacji, ponieważ
wystarczy zamienić jeden plik programu. Jednak wszystkie formularze, raporty, moduły, kwerendy oraz Access i
biblioteki DLL muszą być przesłane poprzez sieć, co powoduje duże obciążenie sieci prowadzące do obniżenie
wydajności aplikacji. W tej konfiguracji do manipulacji danymi prawdopodobnie używasz formularzy
związanych. Jak jest to przedstawione później, formularze związane powodują konflikty przy jednoczesnym
dostępie do danych.
u Oddzielenie danych od programu. Taka konfiguracja jest zwykle nazywana konfiguracją z użyciem zdalnej bazy
danych (zauważ, że określenie „zdalny” przechodzi transformację w czasach Internetu i niedługo może okazać się
archaiczne w tym kontekście), ponieważ dane są oddzielone od programu, ale silnik bazy danych pozostaje na
maszynie użytkownika. W odróżnieniu od konfiguracji klient – serwer silnik bazy danych Accessa pobiera dane,
blokuje je oraz zwalnia blokady w pliku MDB na serwerze. Zdolność do wielodostępu w takiej konfiguracji zależy
od zdolności silników bazy danych wszystkich użytkowników do współdziałania oraz od serwera plików, który
utrzymuje cały ruch w sieci. Jak do tej pory jest to zalecana metoda pisania aplikacji wielodostępnych w Accessie.
Główną zaletą tej metody jest dobra wydajność oraz, jeżeli jest odpowiednio zaimplementowana, kontrola nad
danymi. Ponieważ dane znajdują się na serwerze sieciowym, tylko one są przesyłane, więc obciążenie sieci jest
znacznie zmniejszone. Główną wadą takiego rozwiązania jest konieczność zainstalowania na każdym komputerze
klienta Accessa oraz aplikacji jako plik MDB lub MDE (skompilowana wersja formularzy, kwerend, raportów i
modułów aplikacji), co zwiększa nakłady na utrzymanie systemu.
u Replikacja. W konfiguracji z użyciem replikacji użytkownicy współdzielą dane, ale nie są one wspólne jak przy
użyciu konfiguracji sieciowej czy zdalnej bazy danych. Każdy użytkownik lub małe grupy użytkowników mają
prywatne kopie danych, które są aktualizowane między sobą przy użyciu mechanizmu replikacji Jet. Zaletą tego,
że użytkownicy mają swoje kopie danych, jest wyeliminowanie blokad, ale są one zastąpione problemami
replikacji, które są równie skomplikowane jak problem konfliktów. Inną zaletą jest umożliwienie użytkownikom
asynchronicznej replikacji danych, jeżeli odłączają się od sieci. Wadą tej metody jest to, że nawet w małych
grupach użytkowników używających wspólnych danych aplikacja musi radzić sobie zarówno z problemami
wielodostępu jak i replikacji. I na koniec, replikowane bazy danych są zwykle większe od tych, które nie używają
tej techniki.
u Konfiguracja klient-serwer. Access 2000 wreszcie umożliwia programistom tworzenie aplikacji klient-serwer przy
użyciu projektów dostępu do danych (ADP). W konfiguracji klient-serwer zarówno dane jak i silnik bazy danych
pozostają zdalne. Serwer Oracle, SQL Server lub inny centralnie zarządza danymi i blokadami oraz dba o
zapewnienie wielodostępu. Nie znaczy to, że nie musisz się tym przejmować, znaczy to, że musisz brać pod uwagę
inny zestaw założeń, możliwości i reguł. Najważniejszą zaletą takiej konfiguracji jest wydajność, stabilność i
możliwość obsłużenia dużej liczby użytkowników. Wadą jest koszt rozwiązania oraz zwiększony stopień
skomplikowania.

W tym rozdziale zajmiemy się zagadnieniami wspólnymi dla konfiguracji sieciowej, zdalnej bazy danych oraz klient-
serwer. Użycie replikacji przedstawione będzie w rozdziale 22. „Replikacja i JRO”.

W Accessie mamy możliwość wielu ustawień na poziomie bazy danych, na formularzach, kwerendach, zestawach
rekordów oraz na poziomie wykonania programu, które należy odpowiednio ustawić, aby aplikacja mogła niezawodnie
obsługiwać wielu użytkowników. Prawie wszystkie tematy przedstawiane w tym rozdziale znajdują się w różnych
miejscach aplikacji oraz techniki lub kombinacje technik różnią się od rodzaju aplikacji. Podstawą sukcesu w
wielodostępnej aplikacji jest planowanie, przewidywanie i testowanie.

Access i blokady Jet


Jet posiada schemat blokowania, który pozwala na efektywne obsługiwanie wielu użytkowników. Gdy Jet jest używany w
Accessie, w odróżnieniu od użycia go w VB lub innym środowisku programowania, istnieje kilka domyślnych ustawień,
które powinieneś rozpatrzyć. Ta część rozdziału zajmuje się tymi zagadnieniami.
Część VII ♦ Zagadnienia wielodostępu 396

Omówienie blokowania
Przed oddaniem wielodostępnej bazy danych musi być ona umieszczona w miejscu, do którego mają dostęp użytkownicy,
oraz baza musi zostać otwarta w trybie współdzielonym. Można to wykonać na kilka sposobów.

W oknie Opcje (Narzędzia, Opcje, Zaawansowane) znajduje się opcja Domyślny tryb otwarcia. Można ustawić tryb
wyłączny (tylko jeden użytkownik) lub tryb udostępniony.

Gdy wybrany jest tryb wyłączny, bazę danych może otworzyć tylko jeden użytkownik. Gdy baza danych dostanie otwarta
w tym trybie, Access zmienia nagłówek pliku LDB lub pliku blokad Accessa (więcej informacji o tym pliku w części
rozdziału: „Plik LDB”), aby zapobiec otwarciu bazy przez innego użytkownika. Oczywiście ta opcja nie może być
używana w aplikacjach wielodostępnych. Jednak czynności konserwacyjne, jak kompresowanie i naprawianie, muszą być
wykonywane przy bazie otwartej na wyłączność.

Ustawienie trybu udostępnionego pozwala na otwarcie bazy danych przez kilku użytkowników jednocześnie. Przy
otwieraniu bazy informacja o użytkownikach jest zapisywana w pliku LDB oraz przeprowadzana jest negocjacja
blokowania i zwalniania stron i rekordów.

Ustawienie tych opcji jest możliwe przy użyciu parametrów w wierszu poleceń przy uruchamianiu Accessa. W tabeli 21.1
opisane są niektóre parametry.

Tabela 21.1.
Parametry wiersza poleceń Accessa

Parametr Opis
/Excl Otwiera bazę na wyłączność. Może być użyte nawet z bazą ustawioną na tryb udostępniony
/Ro Tylko do odczytu. Baza jest dostępna dla wielu użytkowników, ale nie mogą być zapisane
zmiany. Nie są zakładane żadne blokady
Brak Jeżeli nie zostanie podany żaden parametr, baza otwierana jest w trybie ustawionym
w oknie opcji

Nie można pozwolić użytkownikom na otwarcie bazy na wyłączność, jeżeli


ma pracować na niej wielu użytkowników. Można się przed tym
zabezpieczyć, odbierając mu prawo Otwórz z wyłącznością z grupy użyt-
kowników. Szczegółowo zostało to opisane w rozdziale 23. „Bezpie-
czeństwo”.

Programista ma możliwość ustawienia w bazie domyślnego trybu blokowania rekordów. Możliwe są dwa tryby:
blokowanie rekordu i blokowanie strony.

Blokowanie stron kontra blokowanie rekordów


W przeszłości Access był szczególnie podatny na konflikty z powodu sposobu zapisu rekordów i ich blokowania.
Ponieważ Access posiadał rekordy o zmiennej wielkości, nie dało się łatwo zaimplementować blokowania rekordów.
Access zapisywał rekordy na stronach o wielkości 2KB (w silniku bazy danych Accessa 2000 – Jet 4.0 strony mają po
4KB). Gdy rekord był blokowany umyślnie bądź przypadkowo, blokowana była cała strona. Zablokowanie strony
blokowało również inne rekordy, które zapisane były na tej stronie. Mimo że ten sposób blokowania jest bardzo wydajny,
połączone jest to z częstymi konfliktami i ogranicza ilość użytkowników jednocześnie korzystających z bazy. Jest to
często krytykowane ograniczenie przy tworzeniu aplikacji w Accessie.

W Accessie 2000, Jet 4.0 daje programistom możliwość wyboru pomiędzy blokowaniem stron a blokowaniem rekordów.
Teraz użytkownik może zablokować tylko edytowany rekord bez niepotrzebnego blokowania innych rekordów. Ponieważ
rekord może zostać zablokowany tylko na chwilę (jak w przypadku wykonywania instrukcji SQL Delete, Update lub
Insert), szansa konfliktu dwóch użytkowników podczas edycji rekordu jest mniejsza, niż gdy zostanie zablokowanych
kilka rekordów podczas blokowania strony. Do tej pory szansa konfliktu była zwielokrotniana przez ilość rekordów na
stronie, co było trudne do określenia. Ilość rekordów na stronie zależy od rozmiaru rekordu oraz kiedy był wprowadzony, więc
trudno jest przewidzieć potencjalne konflikty.

Blokowanie rekordów jest domyślnym ustawieniem, jednak nie oznacza, że jest to zawsze najlepszy wybór. W sytuacjach,
gdy wydajność jest najważniejsza a potencjalne konflikty są rzadkie lub możliwe do zarządzania, nakład czasu na
blokowanie rekordów może okazać się zbyt duży. Rozważmy system obsługi bankowego kantoru wymiany walut, gdzie
397 Rozdział 21. ♦ Zagadnienia wielodostępu, serwer plików, blokowanie

rekordy są częściej wprowadzane niż poprawiane. Ponieważ taki system powinien działać szybko, z rzadkimi
przestojami powodowanymi przez konflikty. W przedstawianym przez nas przypadku blokowanie stron może być
odpowiednie.

W innym przypadku, gdzie współbieżność jest duża i jest niedopuszczalna edycja więcej niż jednego rekordu naraz,
blokowanie rekordów odpowiada tym warunkom. Jest to szczególnie ważne, gdy rekordy są często zmieniane. Wracając do
przykładu banku, baza danych obsługująca operacje na rachunkach klientów musi być cały czas dostępna. Powinna ona
zablokować rekord na wyłączność w trakcie jego edycji, ponieważ występuje ryzyko zapisania zmian zrobionych przez
innego użytkownika. Ponadto, gdy jest zmieniany rekord rachunku, nie może on blokować żadnych sąsiednich rachunków.
Blokowanie rekordów jest również odpowiednie w sytuacjach, gdy rekord musi być otwarty przez dłuższy okres czasu i
zabezpieczony przed zmianą przez innych użytkowników. Przykładem może być kontrola zgodności z przepisami informacji
o kliencie lub sprawdzenie zdolności kredytowej. Nie chcesz, aby rekord zmienił się, dopóki nie skończysz kontroli. Zwykle,
gdy użytkownik trzyma zablokowany rekord przez dłuższy czas, skutkuje to zablokowaniem kilku innych rekordów na czas
edycji. Dobra praktyka mówi, aby nie blokować rekordu na długi okres czasu chyba, że jest to absolutnie konieczne.

Od teraz programiści mają możliwość kontrolowania wielodostępu na poziomie stron lub rekordów. Taka kombinacja daje
dużą elastyczność.

Plik LDB
Plik blokad jest plikiem tymczasowym tworzonym przez Access w czasie otwierania bazy danych. Zawiera on informacje
o blokadach założonych w bazie danych oraz użytkownikach używających bazy. Gdy baza jest zamykana, plik zostaje
usunięty. Plik ten ma nazwę identyczną z nazwą obsługiwanej bazy danych i rozszerzenie LDB. Zawsze tworzony jest w
tym samym katalogu co baza danych.

Optymistyczne i pesymistyczne blokowanie rekordów


W aplikacjach wieloużytkownikowych jedynym bezpiecznym założeniem, jakie może zrobić programista, jest możliwość
wystąpienia konfliktów przy dostępie użytkowników do jednego rekordu. Jedynym sensowną rzeczą do zrobienia jest
zaplanowanie, w jaki sposób obsługiwać te sytuacje poprzez odpowiednie ustawienie opcji blokowania. Są to zasadniczo
dwie opcje: blokowanie optymistyczne i pesymistyczne.

Blokowanie optymistyczne
Jako domyślne w Accessie, blokowanie optymistyczne jest najłatwiejsze do implementacji i zwykle jest dobrym wyborem.
Gdy rekord jest optymistycznie zablokowany, zakłada się, że nie wystąpi konflikt i rekord jest blokowany tylko na czas
zapisu do bazy. Powoduje to, że dane są łatwo dostępne, ponieważ nikt nie blokuje na długo dostępu do danych. Podczas
gdy użytkownik wprowadza zmiany do rekordu, inni użytkownicy mogą również zmieniać ten rekord i pierwszy
użytkownik, który zapisze dane, zablokuje innych użytkowników. Mimo że optymistyczne blokowanie jest łatwe do
wykonania, zwykle powoduje kilka problemów. Ten typ blokowania wywołuje najstarsze zagadnienie wielodostępności –
czyje zmiany powinny zostać zapisane. Jeżeli Karol otworzy rekord i umieści na nim optymistyczną blokadę, nic nie
przeszkodzi Katarzynie otworzyć ten sam rekord, aby wprowadzić zmiany. Gdy Katarzyna zapisze swoje zmiany przed
Karolem, Karol zobaczy komunikat:
"Silnik bazy Microsoft Jet zatrzymał proces, ponieważ inny użytkownik próbuje zmienić te same dane w tym samym
czasie."

Wcześniejsze wersje Accessa przedstawiały okno dialogowe, które pozwalało użytkownikowi wybrać między nadpisaniem
zmian innego użytkownika, niezapisywaniem własnych zmian lub skopiowaniem danych do schowka. Okno konfliktu przy
zapisie nie przedstawiało odpowiednio dużo informacji, aby dokonać sensownego wyboru wśród prezentowanych opcji.
Nowe okno konfliktu przy zapisie prze to, że nie oferuje żadnego wyboru, jest jednoznaczne. W dalszej części rozdziału
przedstawimy konflikty przy zapisie i omówimy kilka sposobów na lepszą obsługę błędów.

Blokowanie pesymistyczne
Blokowanie pesymistyczne jest odwrotnością blokowania optymistycznego. Gdy rekord jest pesymistycznie zablokowany,
nikt z innych użytkowników nie może go otworzyć aż do jego zapisania. Wiele systemów baz danych używa tego sposobu
blokowania,

więc powinno być znane wielu programistom a użytkownicy zaznajomieni z jego konsekwencjami. Mimo że blokowanie
pesymistyczne eliminuje konflikty przy zapisie, nie jest pozbawione problemów.
Część VII ♦ Zagadnienia wielodostępu 398

Gdy zostanie uruchomione blokowanie pesymistyczne, spada dostępność i współbieżność dostępu do danych obniża się.
Jeżeli zostanie użyte blokowanie stron, problem zostanie powiększony, ponieważ zablokowane zostaną również wszystkie
rekordy na stronie. Jeżeli proces edycji danych jest czasochłonny, a pracuje równocześnie wielu użytkowników, blokady
pesymistyczne powinny być dokładnie przemyślane. Niektóre aplikacje, jak obsługa sprzedaży i magazynu,
prawdopodobnie skorzystają na zastosowaniu blokad pesymistycznych, ponieważ jest tu bardzo ważna kontrola
rekordów, jednak systemy kontroli czasu prawdopodobnie przez zastosowanie pesymistycznego blokowania zanotują
spadek wydajności. Wiele z tych ostrzeżeń dotyczy blokowania pesymistycznego w kontekście mechanizmu blokowania
stron Accessa. Teraz, gdy dostępne jest blokowanie rekordów, pesymistyczne blokowanie powinno być częściej
akceptowane i używane.

Blokowanie rekordów
Najważniejszą zaletą blokowania rekordów jest zwiększenie wielodostępu. Przez możliwość zablokowania tylko
zmienianego rekordu więcej użytkowników może dostać się do danych bez wystąpienia konfliktów przy blokowaniu lub
zapisie. Użycie blokowania rekordów pozwala programistom na użycie blokowania pesymistycznego w większej ilości
aplikacji. Użytkownicy zauważą, że zachowanie aplikacji jest bardziej im znane i bardziej intuicyjne. Użytkownik
oczekuje, że po prostu otworzy rekord, zmieni go i zmiany zostaną zapisane. W poprzednich wersjach Accessa
blokowanie stron powodowało, że pesymistyczne blokowanie było zbyt kosztowne w przypadku dużej ilości
użytkowników. Użytkownicy musieli się liczyć z tym, że ktoś inny zablokuje ich zmiany, a programiści będą obmyślać
sposoby na przewidywanie zachowań użytkowników (rozszerzanie rekordów, tabele tymczasowe itd.). Blokowanie
rekordów jest najważniejszym ulepszeniem Jet 4.0 i powinno spowodować utworzenie wielu popularnych i elastycznych
aplikacji.

Właściwość RecordLocks w interfejsie związanym


Gdy w Accessie otwierany jest związany formularz lub zestaw rekordów, możliwe jest nałożenie blokady na bazowy
zestaw rekordów. Oczywiście opcja ta działa tylko w przypadku rozwiązań z użyciem Jet, gdy używamy architektury
klient-serwer, Access zawsze przyjmuje opcję „Bez blokowania”.

Programista ma możliwość wyboru z:


u Bez blokowania – jest to odpowiednik blokowania optymistycznego.
u Edytowany rekord – jest to odpowiednik blokowania pesymistycznego.
u Wszystkie rekordy – blokuje wszystkie rekordy w zestawie. Należy ostrożnie używać go w aplikacjach
wielodostępnych.

Mimo że połączenie interfejsu użytkownika z danymi jest najprostszą


metodą udostępnienia użytkownikom danych, jednak robiąc to tracisz
możliwość kontroli. Na formularz podłączonym do pesymistycznie zablo-
kowanego rekordu użytkownik dostanie przekreślone O w pasku wyboru
rekordu, jednak nie wiadomo, kto zablokował rekord. Jeżeli pasek wyboru
rekordu jest niewidoczny, użytkownik usłyszy tylko sygnał dźwiękowy.

Metody blokowania silnika Jet


Blokady są normalną i niezbędną operacją w bazie danych, jednak aby upewnić się, że blokady są właściwego typu i czasu
trwania, powinieneś mieć możliwość dostania informacji o tym kiedy nastąpiła blokada. W tej części opisane zostało
rozpoznawanie typów blokad w aplikacji, aby sprawdzić, czy projekt aplikacji jest właściwy.

Określanie stanu blokad


Jak jest to opisane wcześniej, blokowanie rekordu lub strony jest wykonywane w różnych momentach w zależności, czy
jest to blokowanie optymistyczne, czy pesymistyczne. Także różne części aplikacji (lub różne aplikacje) mogą używać
różnych typów blokowania tych samych danych w tym samym czasie. Z tego powodu mogą wystąpić różne typy błędów.
Otrzymany błąd zależy od stanu blokady.

ADO dostarcza właściwości LockType w obiekcie recordset, która wskazuje na rodzaj blokady, jaka nałożona zostanie
na rekord w czasie jego edycji. Właściwość tę można zmieniać przed otwarciem zbioru rekordów, a po jego otwarciu
można ją tylko odczytywać.
399 Rozdział 21. ♦ Zagadnienia wielodostępu, serwer plików, blokowanie

W tabeli 21.2 opisane są stałe używane dla właściwości LockType w Mictosoft.Jet.OLEDB.4.0. Inni dostawcy OLEDB
dostarczają różnych opcji. Aby sprawdzić, która opcja jest dostępna, użyj metody .Supports z parametrem adUpdate lub
adUpdateBatch.

Tabela 21.2.
Stałe typów blokowania w Jet 4.0 udostępniane przez dostawcę Mictosoft.Jet.OLEDB.4.0

Stała Opis
AdLockReadOnly Domyślne ustawienie. Zbiór obiektów nie może być zmieniany, jest
otwierany tylko do odczytu i rekordy nie są blokowane
AdLockPessimistic Pesymistyczne blokowanie rekordów
AdLockOptimistic Optymistyczne blokowanie w czasie wywoływania zdarzenia Update
ADLockBatchOptimistic Optymistyczne blokowanie dla uaktualniania wsadowego

adLockPessimistic nie działa, gdy właściwość CursorLocation jest


ustawiona na adUseClient, jednak nie wystąpi żaden błąd. Jet podstawi
inny podobny typ blokowania. Dzieje się tak, ponieważ używając
adUseClient, serwer nie śledzi bieżącego rekordu, więc nie jest możliwe
pesymistyczne blokowanie.

Podzbiór ADOR (ADOR to podzbiór modelu obiektów ADO, który do-


starcza tylko obiektów Recordset i Field, które mogą być tworzone lub
przesyłane z serwera do klienta), dostarcza tylko typu blokowania
adLockOptimisticBatch.

Znajomość stanu blokady rekordu jest ważne w czasie tworzenia, testowania i utrzymywania aplikacji. Każdy proces, który
obsługuje dane, powinien być sprawdzony, czy spełnia założenia projektu. Wykonanie tego jest proste. Zatrzymaj
wykonanie programu i sprawdź wartość właściwości LockType w obiekcie recordset (rysunek 21.1).

Rysunek 21.1.
Właściwość
LockType obiektu
recordset
przedstawia rodzaj
blokady

Inna właściwość wskazuje na to, czy recordset był zmieniany. Właściwość EditMode zmienia się z początkowego
adEditNone na adEditInProgress w trakcie edycji rekordu oraz znów na adEditNone po udanym zapisaniu rekordu.

Inne wartości właściwości EditMode opisane są w tabeli 21.3.

Wartość właściwości EditMode wskazuje na stan bufora używanego do zmiany i tworzenia rekordów. Możesz użyć tej
wartości do sprawdzenia, czy potrzebujesz wywołać metodę Update lub CancelUpdate, gdy operacja została przerwana.

Tabela 21.3.
Wartości właściwości EditMode dla obiektu recordset ADO

Stała Opis
Część VII ♦ Zagadnienia wielodostępu 400

adEditNone Rekord nie był zmieniony


adEditInProgress Dane w rekordzie są zmienione, ale nie były zapisane
adEditAdd Występuje, gdy wywołana została metoda AddNew. Wskazuje na to, że w buforze
jest nowy rekord niezapisany do tabeli
adEditDelete Bieżący rekord został skasowany

Sprawdzanie blokad
Sposobem na sprawdzenie, jaka blokada została nałożona na rekord, jest odczytanie wartości właściwości LockType i
EditMode, ale większym problemem jest sprawdzenie, czy została nałożona blokada przez innego użytkownika na
potrzebne nam dane. Jedynym sposobem na zweryfikowanie blokad jest spowodowanie konfliktu.

Dostawca Jet OLEDB zwraca niektóre informacje o blokadach użytkownika w przypadku wystąpienia błędu. W przypadku
konfliktu należy sprawdzić wartość właściwości
Connection.Errors(index).SQLState

aby stwierdzić, jaki błąd wystąpił. W tabeli 21.4 wymienione zostały niektóre kody błędów powodowanych przez
konflikty, które można odczytać z właściwości SQLState.

Tabela 21.4.
Błędy blokowania dostarczone przez dostawcę Jet 4.0 OLEDB

Kod Komunikat
3006 Baza danych <nazwa> jest otwarta na wyłączność
3008 Tabela <nazwa> jest otwarta przez innego użytkownika lub otwarta jest przez interfejs
użytkownika i nie może być zmieniana przez program
3009 Próbujesz zablokować tabelę <nazwa> w czasie jej otwierania, ale nie może być zablokowana,
ponieważ jest używana. Poczekaj chwilę i ponów operację
3027 Nie można uaktualniać rekordu. Baza danych lub obiekt jest tylko do odczytu
3046 Nie można zapisać, zablokowane przez innego użytkownika
3158 Nie można zapisać rekordu, zablokowany przez innego użytkownika
3164 Pole nie może być zmienione, ponieważ inny użytkownik lub proces zablokował związany
rekord lub tabelę
3186 Nie można zapisać, zablokowane przez użytkownika <nazwa> na komputerze <komputer>
3187 Nie można odczytać, zablokowane przez użytkownika <nazwa> na komputerze <komputer>
3188 Nie można zapisać, zablokowane przez inną sesję na tym komputerze

Tabela 21.4.
Błędy blokowania dostarczone przez dostawcę Jet 4.0 OLEDB (ciąg dalszy)

Kod Komunikat
3189 Tabela <nazwa> jest zablokowana na wyłączność przez użytkownika <nazwa> na komputerze
<komputer>
3197 Silnik bazy Microsoft Jet zatrzymał proces, ponieważ inny użytkownik próbuje zmienić te same
dane w tym samym czasie
3202 Nie można zapisać, zablokowane przez innego użytkownika
3211 Silnik bazy danych nie może zablokować tabeli <nazwa>, ponieważ jest używana przez inną
osobę lub proces
3212 Nie można zapisać, zablokowane
3218 Nie można zapisać, zablokowane przez użytkownika <nazwa> na komputerze <komputer>
3260 Tabela <nazwa> Jest zablokowana na wyłączność przez użytkownika <nazwa> na komputerze
<komputer>
3261 Nie można zablokować tabeli <nazwa>, używana przez użytkownika <nazwa> na komputerze
<komputer>
401 Rozdział 21. ♦ Zagadnienia wielodostępu, serwer plików, blokowanie

Tablica błędów zawiera inne użyteczne informacje dotyczące błędu blokowania, informacje o blokadach innego
użytkownika. Właściwość NativeError oraz Number informuje o blokadzie wstrzymującej twoją operację. Kombinacje
wartości i ich znaczenie przedstawione są w tabeli 21.5.

Tabela 21.5.
Sposób, w jaki wartości NativeError i Number wskazują na typ blokady

Użytkownik Właściwość Wartość Typ blokady


Ty Connection.Errors(0).NativeError -533791822 Pesymistyczna
Ty Connection.Errors(0).Number -105514571 Optymistyczna
Inny Connection.Errors(0).NativeError -2147467259 Pesymistyczna
Inny Connection.Errors(0).Number -2147217887 Optymistyczna

W tej chwili możesz niewiele zrobić z tymi wartościami, może poza użyciem ich jako wartości opóźnienia następnej próby
zapisu. Zapamiętaj te właściwości, mogą być one przydatne w przyszłości.

Użycie blokowania stron


Access przez długi czas nie potrafił blokować rekordów (istniało pewne obejście problemu) i zamiast tego blokował całą
stronę, jak to zostało opisane wcześniej w tym rozdziale. Aby skorzystać ze wzrostu wydajności blokowania stron, wyłącz
domyślne blokowanie rekordów. Aby to zrobić wybierz Narzędzia→Opcje→Zaawansowane i wyłącz Otwórz z
blokowaniem na poziomie rekordu.

Obsługa błędów blokowania


Każdy system wieloużytkownikowy powinien uprzedzać komunikaty błędów. Różne systemy obsługują błędy w różny
sposób. Różne systemy dostarczają różnej informacji dla programistów i użytkowników w przypadku wystąpienia błędu
blokady. W tej części omówimy niektóre ustawienia blokowania i błędy blokowania, które możesz napotkać w trakcie
programowania w Accessie 2000. Przedstawione zostaną niektóre techniki obsługi błędów i unikania ich.

Ustawienia blokowania Accessa


Najlepszą metodą obsługi błędów wielodostępu jest unikanie ich. Access dostarcza kilka właściwości, które mogą zostać
ustawione, aby zmniejszyć częstotliwość konfliktów. Opcje te znajdują się na zakładce Zaawansowane okna dialogowego
Opcje. Jednak nie mogą same obsłużyć wszystkich błędów.
u Liczba ponownych prób aktualizacji. Tyle razy Access powtarza próby zapisu lub aktualizacji rekordu, gdy
wystąpiła blokada. Dopuszczalne wartości 1–10.
u Interwał odświeżania ODBC. Interwał odświeżania w sekundach w czasie używania bazy danych ODBC.
Dopuszczalne wartości 1–3600.
u Interwał odświeżania. Interwał odświeżania w sekundach w przypadku odświeżania rekordów w formularzu lub
arkuszu danych. Dopuszczalne wartości
1–32766.
u Interwał ponawiania prób aktualizacji. Czas w milisekundach między próbami zapisu zmienionego rekordu, gdy
wystąpiła blokada. Dopuszczalne wartości
1–32766.

Konflikty zapisu
Błąd konfliktu zapisu (błąd numer 3197 w tabeli 21.4) jest jednym z najbardziej zagmatwanych błędów w
wieloużytkownikowym środowisku Accessa. Użytkownik 1 otwiera rekord z optymistyczną blokadą i w trakcie, gdy edytuje
rekord Użytkownik 2 otwiera ten sam rekord, zmienia go i zapisuje. Gdy Użytkownik 1 kończy pracę i próbuje zapisać go,
wystąpi błąd. We wcześniejszych wersjach Accessa, wyświetlane było mylące okno dialogowe pytające użytkownika, czy
nadpisać zmiany innego użytkownika (mimo że nie wiadomo, jakie to zmiany), anulować własne zmiany (nigdy nie było to
popularne) lub skopiować dane do schowka.

Systemowa obsługa tego błędu została zmieniona. W Accessie 2000 błąd konfliktu przy zapisie powoduje anulowanie
zmian użytkownika. Mimo że brzmi to brutalnie, jednak lepiej, gdy zakłada się, że większość aplikacji wielodostępnych w
Accessie jest tworzona szybko przez ludzi, którzy mogą nie mieć dostatecznej wiedzy na temat zagadnień
wielodostępności. Poza tym użytkownik nie powinien odpowiadać na pytania, o których nawet nie pomyślał, że może
Część VII ♦ Zagadnienia wielodostępu 402

zostać zapytany. Jeżeli aplikacja zakłada inne traktowanie konfliktów zapisu, można napisać własny podprogram obsługi
błędów.

Zablokowany rekord
Gdy w czasie normalnego używania aplikacji Użytkownik 1 spróbuje zablokować rekord, który jest zmieniany przez
Użytkownika 2, Użytkownik 1 spowoduje błąd „Zablokowany rekord” (błąd numer 3260 w tabeli 21.4). Typowa procedura
obsługi błędów spróbuje kilka razy zablokować rekord przed wyświetleniem komunikatu o blokadzie. Jeżeli Użytkownik 2
zablokował rekord w sposób pesymistyczny, rekord zostanie zwolniony zaraz po zapisaniu do bazy danych. Jest to zwykle
krótki okres czasu.

Transakcje
Transakcje łączą oddzielne operacje tak, aby zostały wykonane jak jedna. Zbiór instrukcji może zostać wykonany w całości
prawidłowo (zostają potwierdzone – commit) lub w całości się nie udać (zostają wycofane – rollback). Gdy transakcja nie
uda się, zmiany zostają cofnięte do stanu sprzed rozpoczęcia transakcji. Zapewnia to, że gdy przedmiot zostanie
zarejestrowany na rachunku, zostanie zdjęty z magazynu. Gdy na jednym rachunku jest przychód, to na drugim rozchód i
gdy rekord jest zmieniany, tworzony jest zapis w dzienniku operacji. W wysoce zmiennym środowisku aplikacji
wielodostępnej użytkownik wykonujący te operacje może napotkać błąd zablokowanego rekordu w jednej części procesu,
co może spowodować błąd w bilansie na koncie, sztucznie wypełniony magazyn lub wykonane zmiany, ale nie w pełni
zarejestrowane. W skrócie, transakcje pomagają utrzymać integralność danych przy częstych i wielokrotnych blokadach
rekordów. Przetwarzanie transakcyjne powinno być użyte w aplikacjach wielodostępnych wszędzie tam, gdzie jest to
możliwe.

Jednak transakcje nie są bezwarunkowo dobrą rzeczą. Jedynym sposobem na zapewnienie wykonania wszystkich operacji
jest zgromadzenie razem wszystkich blokad. Transakcja zakłada wszystkie blokady, jakie nakłada aplikacja, ale nie
zwalnia ich aż do pomyślnego zakończenia całego procesu. Ponieważ wiele blokad może być nałożonych i będą aktywne
przez dłuższy okres czasu, niż gdyby były nakładane bez transakcji, wielodostępność aplikacji jest zmniejszona. Jednak
baza danych jest łatwo dostępna, ale z niską integralnością danych nie jest zbyt dużo warta, więc transakcje wydają się być
rozsądnym rozwiązaniem.

Transakcje są realizowane przez metody obiektu Connection w ADO. W tabeli 21.6 opisane są te trzy metody.

Tabela 21.6.
Definiowanie transakcji

Metoda Opis
BeginTrans Od tego wywołania instrukcje będą wykonywane jak jedna.
CommitTrans Kończy zestaw instrukcji i zatwierdza je do bazy danych.
RollbackTrans W wypadku błędu anuluje wszystkie instrukcje i przywraca bazę danych do postaci
sprzed BeginTrans.

Podstawowa postać przetwarzania transakcyjnego przedstawiona jest na wydruku 21.1.

Wydruk 21.1. Użycie transakcji w VBA


Function TestTrans() As Boolean
Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset
On error resume Err_TestTrans
Set conn=New ADODB.Connection
Conn.BeginTrans
' wykonanie instrukcji np. instrukcji SQL lub metod Edit, Update
' AddNew
' Jeżeli wszystko się udało zatwierdzamy transakcję
Conn.CommitTrans
Exit Function

Err_TestTrans:
' Coś poszło źle, anulujemy transakcję i przywracamy stan poprzedni
Conn.RollbackTrans
End Function

Transakcje można zagnieżdżać, więc zatwierdzanie jednej transakcji zależy od zatwierdzenia innej. Gdy zagnieżdżamy
transakcje, są one wykonywane od najniższego poziomu do najwyższego.
403 Rozdział 21. ♦ Zagadnienia wielodostępu, serwer plików, blokowanie

Blokady Oracle/SQL Server


Gdy oprzesz aplikację na serwerze SQL, np.: Oracle, Informix czy SQL Server, Access przestaje zarządzać blokadami.
Jednak założenia pozostają identyczne – kontrolować dostęp do rekordów w taki sposób, aby wielu użytkowników mogło
używać bazy w tym samym czasie. Serwery baz danych realizują to bardzo dobrze. Ponieważ dane są w tym samym
miejscu co silnik bazy danych, blokowanie rekordów i zarządzanie wielodostępem realizowane jest szybko, niezauważalnie
i stabilnie. Każdy z tych programów przechowuje informacje o blokadach w tabeli przechowywanej w pamięci i może
efektywnie wykonać nałożenie blokady, wykonanie operacji i zdjęcie blokady w przeciągu mikrosekund.

W przypadku użycia SQL Server używane są trzy typy blokad:


u Blokady współdzielone – używane są przy operacjach odczytu, pozwalają innym użytkownikom odczytać rekord
lub stronę, która zawiera rekord. Na rekord lub stronę może być nałożone wiele blokad współdzielonych
jednocześnie. Blokady te są zdejmowane zaraz po tym, jak dane przestają być potrzebne.
u Blokada na wyłączność – gdy wykonywane są instrukcje SQL Update, Delete lub Insert, na dane zakładana jest
blokada na wyłączność. Jeżeli została nałożona blokada na wyłączność, nie można wykonać żadnej innej operacji
nakładającej blokadę, dopóki serwer SQL zwolni blokadę po zatwierdzeniu danych.
u Blokada ruchoma – blokada ruchoma jest żądaniem blokady na wyłączność i jest nakładana po czterech
kolejnych nieudanych próbach zablokowania rekordu na wyłączność. Blokada ruchoma nakładana jest również,
gdy jednocześnie nałożonych jest zbyt wiele blokad współdzielonych. Gdy wystąpi taka sytuacja, serwer SQL nie
nałoży więcej blokad współdzielonych. Blokady ruchome zabezpieczają przed zmonopolizowaniem tabeli przez
blokady współdzielone (pochodzące z operacji odczytu) i niedopuszczeniem do operacji zapisu. Blokady ruchome
zabezpieczają przed sytuacją zwaną jako „zagłodzenie blokadami”.

Istnieją również inne strategie stosowane w SQL Server do zarządzania wielodostępnością. Między innymi: dynamiczne
blokowanie rekordów (SQL Server 7.0), unikanie, wykrywanie i korygowanie zakleszczeń, kontrola blokowania
optymistycznego i skalowalne narastanie blokad.

Dynamiczne blokowanie rekordów polega na tym, że zarządca blokad dostosowuje konfigurację blokad serwera do
wielkości używanej bazy danych. Powoduje to zmniejszenie zużycia zasobów oraz zmniejsza nakłady na ręczne zarządzanie
blokadami na serwerze.

Unikanie, wykrywanie i korygowanie zakleszczeń polega na tym, że SQL Server rozpoznaje sytuację, gdy dwa procesy
pozostają ze sobą w konflikcie. W takiej sytuacji jedna transakcja blokuje dane potrzebne w drugiej oraz druga blokuje dane
potrzebne w pierwszej transakcji. Pierwsza transakcja nie zwolni blokady, druga też tego nie zrobi. Bez interwencji silnika
bazy transakcje te pozostaną zakleszczone. SQL Server wykrywa taką sytuację, odwołuje jedną z transakcji, kończy drugą i
uruchamia pierwszą jeszcze raz, przełamując w ten sposób zakleszczenie. SQL Server aktywnie zapobiega zakleszczeniom,
ograniczając ilość blokad tabel.

SQL Server używa podejścia optymistycznego do zarządzania środowiskiem wielodostępnym. Przy użyciu tego podejścia
użytkownicy mogą używać kursorów po stronie serwera do przeglądania danych w przód i w tył bez użycia blokad.
Zamiast tego, SQL Server wykrywa zmiany rekordu i podejmuje stosowne działania (zwykle odrzuca zmiany, chyba że
dane zostały jawnie zablokowane).Podejście takie powoduje, że ogromne ilości danych są dostępne dla użytkowników bez
intensywnego zarządzania blokadami i związanych z tym narzutów.
Rozdział 22.
Replikacja i JRO
W tym rozdziale:
u Kiedy użyć replikacji.
u Kiedy nie używać replikacji.
u Przystosowanie bazy do replikacji.
u Replikacja przy użyciu aktówki.
u Użycie interfejsu użytkownika.
u Jet i model obiektowy replikacji.
u Opis metod i właściwości JRO.
u Obiekty repliki.
u Kolekcja Filters.

W czasach, gdy korporacje, coraz bardziej zależne od swoich danych, użytkownicy są coraz bardziej rozproszeni i żądają
od swoich sieci coraz więcej. W odpowiedzi na to, tworzone są zdecentralizowane i rozproszone systemy, aby dostarczyć
wszystkim informacji oraz rozładować obciążenie. Trend ten niesie z sobą nowe wyzwania. W jaki sposób korporacje mają
zapewnić wszystkim dostęp do danych? Jak zagwarantować, że użytkownicy podejmą decyzje w oparciu o aktualne dane?
Czy można zaufać danym? Jedną z technik spełniających te oczekiwania jest replikacja.

Rozdział ten zajmuje się tworzeniem i zarządzaniem replikami. Opisany został nowy model obiektowy Jet Replication
Model (JRO) używany do uruchomienia replikacji w aplikacjach i skorzystania z jej elastyczności. W silniku Jet
zrobiono zauważalne ulepszenia procesu replikacji. Między innymi: dwukierunkową synchronizację z SQL Server, lepsze
rozwiązywanie konfliktów, możliwość ustawiania priorytetów w schemacie bazy, rozdzielczość na poziomie kolumn oraz
zakresy widoczności. Te usprawnienia pozwalają na lepszą kontrolę przy definiowaniu topologii replikacji.

Kiedy użyć replikacji


Istnieje kilka czynników, które powinny być wzięte pod uwagę przy rozważaniu użycia replikacji. Nie jest niespodzianką,
że każdy potencjalny plus replikacji posiada także minus. Jednak istnieje kilka sytuacji, kiedy replikacja jest mądrym
wyborem.

Jeżeli wydajność aplikacji spada z powodu wielu konfliktów blokad, spowodowanych dużym ruchem w sieci lub częstym
generowaniem raportów, można zauważyć, że podział bazy danych na dwie lub więcej replik i podział użytkowników
pomiędzy nimi może usunąć problem blokad. Te dwa źródła danych wymienią się zmianami pomiędzy sobą.

Podobnie, jeżeli każdy użytkownik potrzebuje tylko podzbioru danych w swojej bazie, częściowa replikacja może być
odpowiednia, aby polepszyć wydajność, usunąć konflikty i zabezpieczyć ważne dane (przykładem może być aplikacja
zarządzania działem kadr, która rozdziela zarządzanie pracownikami do kierowników poszczególnych działów i pozwala
na dostęp do danych pracowników tylko własnego działu). Aby zwiększyć szybkość działania, aplikacja zarządzająca
czasem pracy może dostarczyć repliki z historią czasu pracy każdego użytkownika. Co więcej, system taki dla progra-
mistów może zostać odłączony od sieci i zapisywać pracę wieczorem, w weekend lub u klienta. Schemat synchronizacji
powinien rozwiązywać problemy napotkane w takiej aplikacji.
405 Rozdział 22. ♦ Replikacja i JRO

Gdy ograniczasz zbiór danych, jaki może zobaczyć użytkownik, tworzysz w schemacie replikacji partycje. Może być to
efektywną metodą zabezpieczenia rekordów przed zmianą przez nieuprawnione osoby. Istnieją trzy typy partycjonowania:
pionowe, poziome i połączone poziome i pionowe.

Gdy tworzy się partycję pionową, do osobnej bazy danych przeniesione zostaną tylko wybrane kolumny. Można to zrobić
poprzez replikację przy użyciu kwerendy lub widoku, który ogranicza dane tylko do tych, które mają być udostępniane.
Gdy replikujemy partycję pionową, musisz umieścić klucz główny w zapytaniu partycjonującym.

Gdy tworzy się partycję poziomą, ograniczasz ilość rekordów do replikacji. Można to zrobić poprzez filtr replikacji lub
poprzez kwerendę. Gdy replikujesz partycję poziomą, replikujesz całe rekordy.

Partycjonowanie poziome i pionowe może zostać połączone, ograniczając zarówno wiersze jak i kolumny.

Gdy aplikacja musi pracować bez przerwy, tworzenie kopii danych może spowodować niespodziewane przerwanie
aplikacji. Replikacja może regularnie kopiować dane do repliki, która może być bezpiecznie archiwowana.

Replikacja jest odpowiednim rozwiązaniem, gdy dane użytkownika są odporne na opóźnienia aktualizacji. Oznacza to, że
użytkownicy mogą tolerować posiadanie przez jakiś czas nieaktualnych danych. Gdy raporty są wykonywane raz na
godzinę lub raz dziennie, lub są oparte o dane do określonej godziny (np.: na koniec miesiąca, koniec roku podatkowego
lub na koniec poprzedniego dnia), replikacja jest do zaakceptowania.

Mimo że replikacja jest zwykle używana do rozprowadzania danych, może być użyta do rozprowadzania innych obiektów
Accessa. Kiedyś użyłem replikacji, aby uaktualnić aplikację w Argentynie zmianami, których dokonałem w Nowym Jorku.
Czasami replikacja może łagodzić niektóre problemy utrzymania aplikacji.

Kiedy nie używać replikacji


Jak wszystko inne, replikacja nie jest panaceum. Poniżej przedstawione zostały przypadki, kiedy nie powinieneś używać
replikacji.

Replikacja powoduje, że plik MDB jest dużo większy, ponieważ muszą zostać dodane dodatkowe obiekty, pola oraz dane
niezbędne do uruchomienia i zarządzania repliką. Jeżeli system, na którym pracuje aplikacja, posiada mało wolnych
zasobów, replikacja nie jest dobrym pomysłem.

Obciążone systemy, które przeprowadzają wiele transakcji, mogą powodować problemy z replikacją. Duża częstotliwość
transakcji i blokady zakładane w czasie tych transakcji zwykle prowadzą do konfliktów podczas synchronizacji danych.
Rozwiązywanie tych konfliktów może bardzo obniżyć wydajność systemu. Bez efektywnego rozwiązywania problemów
replikacja przyniesie aplikacji więcej kłopotów niż pożytku.

Kiedy aktualność danych jest bardzo ważna, replikacja jest nie do zaakceptowania, ponieważ zakłada, że użytkownicy oddają
aktualność danych w zamian za wydajność, współbieżność i mobilność.

Przystosowanie bazy do replikacji


Istnieje kilka sposobów na przystosowanie bazy danych do replikacji. W tym rozdziale opisane zostaną: aktówka,
interfejs użytkownika Accessa oraz Jet Replication Object (JRO).

Replikacja przy użyciu aktówki


Najprostszą metodą replikacji danych jest użycie aktówki. Mimo że technika ta pozwala tylko na synchronizowanie
komputera biurkowego z laptopem, jest dobrą metodą rozwiązania wielu problemów. Metoda ta działa także z innymi
plikami, nie tylko z bazą Accessa.

Można użyć replikacji przy użyciu aktówki dla siebie lub innych użytkowników, którzy chcą współdzielić pliki pomiędzy
komputerem biurkowym i laptopem.

Przed użyciem replikacji przy użyciu aktówki (lub każdej innej metody replikacji) upewnij się, że baza danych nie posiada
hasła. Następnie należy wykonać następujące kroki:
Część VII ♦ Zagadnienia wielodostępu 406

94. Otwórz Explorer.


95. Otwórz aktówkę.
96. Skopiuj bazę danych Accessa do okna aktówki i wykonaj czynności zalecone w oknach dialogowych kończących
się oknem z rysunku 22.1.

Rysunek 22.1.
Wybór bazy danych
jako repliki
w aktówce

97. W pierwszym oknie dialogowym kliknij przycisk Tak. Baza danych musi się zwiększyć, aby mogła być
replikowana.
98. Pozwól aktówce wykonać kopię bazy danych, jeżeli masz odpowiednią ilość miejsca na dysku.
99. Jeżeli chcesz zmieniać tylko dane w bazie danych, w kolejnym oknie wybierz opcję niedopuszczania zmian
struktury oryginalnej kopii bazy danych. Jeżeli spodziewasz się, że będziesz zmieniał projekt bazy, wybierz opcję
Kopia aktówki.
100. Jeżeli otworzysz jedną z kopii, zauważysz w tytule okna Wzorzec projektowania lub Replika.
101. Skopiuj aktówkę na wymienny nośnik danych i zabierz ze sobą. Jednak, gdy komputery są połączone, przeciągnij
aktówkę do innego komputera.
102. Gdy skończyłeś prace poza swoim komputerem, skopiuj zaktualizowany plik do komputera i po otwarciu aktówki
wybierz Aktówka, Aktualizuj zaznaczenie.

Aktówka stwierdza, jakie zmiany muszą być wykonane w każdym kierunku. Gdy sam używasz aktówki, jest prawie
niemożliwe, abyś napotkał na konflikty w danych. W dalszej części rozdziału rozpatrzymy bardziej rozbudowane,
drobiazgowe i potężne sposoby replikacji.

Nie można odwrócić konwersji bazy w replikę, jednak można przywrócić bazę danych do niereplikowalnej formy. Aby to
zrobić, wykonaj następujące kroki:
103. Z bazy danych, którą chcesz zmienić na formę niereplikowalną, wybierz Narzędzia, Opcje i zakładkę Widok.
Wyłącz Obiekty systemowe.
104. Utwórz nową bazę danych i otwórz ją.
105. Zaimportuj wszystkie obiekty z repliki do nowej bazy.
106. Upewnij się, że na zakładce Widok w oknie dialogowym Opcje, wybrane jest pole wyboru Obiekty systemowe.
107. Usuń kolumny s_GUID, s_Lineage, s_Generation i s_colLineage z wszystkich tabel.
108. Zapisz nową bazę.

Użycie interfejsu użytkownika


Interfejs użytkownika Accessa pozwala na większą elastyczność niż aktówka, lecz jest nieco bardziej skomplikowany.
Używając takiego podejścia, możesz uruchomić replikację pomiędzy różnymi użytkownikami w sieci, aby mogli
współdzielić dane i inne obiekty Accessa. Gdy używamy interfejsu Accessa, można także wybrać, które z obiektów mają
być replikowane i te, które nie będą replikowane. Podejście to pozwala na kontrolę, kiedy i z kim replikować.
109. Otwórz bazę na wyłączność, upewniając się, że nie ma założonego hasła.
110. Z menu Narzędzia wybierz Replikacja, Utwórz replikę (rysunek 22.2).
407 Rozdział 22. ♦ Replikacja i JRO

Rysunek 22.2.
Tworzenie repliki
przez interfejs
Accessa odbywa się
przez wybór z menu

111. Access zamknie bazę i otworzy ją ponownie. Następnie Access zapyta o możliwość utworzenia kopii bazy. Kopia
ma nazwę oryginalnej bazy danych i rozszerzenie BAK. Powinieneś pozwolić na utworzenie kopii.

Proces konwersji może potrwać kilka minut, w zależności od stopnia skomplikowania bazy i ilości danych. W czasie
procesu konwersji bazy do postaci repliki Access wykonuje następujące czynności:
u Tworzony jest nowy plik MDB i importowane są do niego wszystkie obiekty.
u Tworzy właściwość replicable dla każdego obiektu i ustawia jej wartość na T, więc zostanie on replikowany.
u Dodaje cztery pola o typach zamieszczonych w tabeli 22.1 do każdej tabeli w bazie danych.

Tabela 22.1.
Pola dodane do tabel w czasie ich przystosowania do replikacji

Nazwa pola Typ pola Opis


s_ColLineage OLE Object Śledzi zmiany w kolumnie lub polu
s_Generation Number Śledzi zmiany rekordu
s_Lineage OLE Object Śledzi inne zmiany
s_GUID AutoNumber Globalny unikatowy identyfikator rekordu

Pola te pozwalają na śledzenie przez Jet, zmian wprowadzonych do bazy danych i decydowanie o tym, co zrobić, gdy
wystąpi konflikt pomiędzy dwoma bazami. Nie możesz zmieniać zawartości, typu danych lub nazw tych pól, normalnie
nie są one widoczne w tabelach, chyba że zdecydujesz inaczej. Pola te zajmują trochę miejsca w bazie danych, w
zależności od ilości danych oraz ilości obiektów w bazie, rozmiar plików rośnie od 10 do 100 procent.

Jeżeli pole posiada typ Autonumerowanie, nie można oczekiwać, że replikacja będzie działać prawidłowo. Często stosuje
się pole typu Autonumerowanie, o wartościach 1, 2, 3... Jedynym sposobem uniknięcia konfliktów jest zmiana typu danych
przechowywanego w tym polu. Jeżeli pole ma typ Autonumerowanie z opcją Nowe wartości ustawioną na Przyrostowy, Jet
zmienia tę opcję na Losowy, aby zmniejszyć prawdopodobieństwo konfliktu. Jeżeli ta zmiana okaże się niewystarczająca,
można zmienić rozmiar takiego pola na ID Replikacji, co spowoduje nadanie każdego rekordu wartości GUID, który może
być używany jako identyfikator rekordu. Tworzenie liczb losowych lub ID Replikacji jest wolniejsze niż zwiększenie
wartości, ale czasami jest to konieczne i nieuniknione.

Do bazy danych zostaje również dodanych kilka tabel. Tabele te mają prefiks MSys i jako takie mogą zostać zmienione
przez Microsoft w kolejnych wersjach. Powinieneś poważnie się zastanowić przed napisaniem programu, który używa tych
tabel. Są one używane przez Jet i tak powinno pozostać. W tabeli 22.2 opisane jest przeznaczenie tych tabel.

Tabela 22.2.
Tabele dodane do bazy danych podczas przystosowania do replikacji

Nazwa tabeli Przeznaczenie


MSysConflicts Zapamiętuje nierozwiązane konflikty. Tabela jest pusta po rozwiązaniu wszystkich
konfliktów
Część VII ♦ Zagadnienia wielodostępu 408

MSysExchangeLog Zapamiętuje różne dane na temat każdej synchronizacji


MSysGenHistory Zapobiega wysłaniu niezmienionych rekordów w trakcie synchronizacji
MSysOthersHistory Zapisuje różne szczegóły działania z innych replik

Tabela 22.2.
Tabele dodane do bazy danych podczas przystosowania do replikacji (ciąg dalszy)

Nazwa tabeli Przeznaczenie


MSysRepInfo Informacje o zbiorze replik i wzorcu projektowania, razem z GUID
MSysReplicas GUID dla każdej repliki w zbiorze
MSysRepLock Zapisuje nieudane próby zablokowania rekordów w trakcie synchronizacji
MSysSchChange Zmiany schematu bazy danych wykonane we wzorcu projektowania. Są tu
przechowywane, dopóki są potrzebne
MSysSchedule Zapisy planowania tworzone przez Replication Manager
MSysSideTables Nazwy tabel i GUID dla potrzeb konfliktów
MSysTableGuids Nazwy replikowanych tabel wraz z GUID
MSysTombStone GUID tabel i rekordów dla usuniętych obiektów
MSysTranspAddress Identyfikuje replikę (repliki), z którą bieżąca replika jest synchronizowana

Tabele te są tylko do odczytu, a niektóre dane są przechowywane jako obiekty OLE, więc nie mogą być wyświetlane.

Dodatkowo do bazy danych dodanych zostaje kilka właściwości, aby można było sprawować kontrolę nad replikacją.
Właściwości te to: Replicable, ReplicableID oraz DesignMasterID.
u Replicable wskazuje silnikowi Jet, że baza może być replikowana.

u ReplicableID w sposób jednoznaczny identyfikuje bazę danych i wyróżnia ją spośród innych replik.

u DesignMasterID wskazuje na bazę, która zarządza zmianami w replikach.

Zmiany w projekcie można wprowadzać tylko do źródła projektowania. Powinna istnieć tylko jedna baza danych wskazana
jako źródło projektowania w schemacie replikacji lub zbiorze replik. Posiadanie więcej niż jednego źródła projektowania
prowadzi do uszkodzenia i utraty danych.

Niektóre obiekty są potrzebne tylko przez lokalną aplikację, więc powinieneś zauważyć, że szablony, większość tabel
systemowych i kreatorzy nie są replikowani. Jednak tabele systemowe biorące udział w śledzeniu procesu replikacji są
replikowane, a MsysAccessObjects oraz MsysCmdBars są również replikowane, co powoduje, że schemat bazy danych
oraz menu mogą być częścią schematu replikacji.

Replikacja ogranicza ilość zagnieżdżonych transakcji w bazie. Replika


obsługuje tylko sześć zagnieżdżonych transakcji.

Wybór między obiektami lokalnymi i replikowanymi


Gdy rezygnujesz z używania aktówki jako narzędzia replikacji i rozpoczynasz korzystanie z możliwości Accessa, jedną z
pierwszych rzeczy, nad którą powinieneś się zastanowić, jest wybór czy obiekt ma być lokalny, czy replikowany.
Kolejnymi są: wybór topologii replikacji oraz czy proces replikacji ma być kierowany, czy niekierowany, bezpośredni lub
pośredni.

Domyślnie Access zaznacza wszystkie obiekty do replikacji. Zwykle jednak aplikacja posiada obiekty, które nie muszą być
replikowane. Mogą to być tabele zawierające ustawienia lokalne, tabele tymczasowe lub proste kwerendy, które nie będą
zmieniane (przykładowo Select * from Customers Order by CompanyName). Możesz kontrolować, które obiekty
będą zmieniane w trakcie synchronizacji poprzez ustawienie właściwości Replicable. Jeżeli obiekt jest replikowany,
właściwość posiada zaznaczone pole wyboru w oknie właściwości obiektu, gdy jest lokalny – pole jest wyczyszczone i
obiekt nie będzie synchronizowany.

Aby zmienić obiekt na lokalny, należy wykonać poniższe kroki:


409 Rozdział 22. ♦ Replikacja i JRO

112. Wybierz obiekt.


113. Kliknij prawym klawiszem myszy i wybierz Właściwości z menu kontekstowego.
114. Wyczyść pole wyboru przy właściwości Replicable i kliknij OK.

Wzorzec projektowania, na którym obecnie pracujesz, jest specjalną bazą danych. Jest ona jedyna, na której możesz
dokonywać zmian i zmiany te zostaną przeniesione do replik. Zwykle wzorzec projektowania nie synchronizuje się z
replikami, ponieważ użytkownicy mogliby dostać niegotowy program. Dobrze jest izolować wzorzec od zbioru replik do
czasu, gdy chcesz rozesłać zmiany, jakie zrobiłeś w bazie danych.

Aby utworzyć topologię replikacji, powinieneś utworzyć odpowiednią ilość replik z właśnie stworzonej repliki. Nie
twórz kolejnych replik z oryginalnej bazy danych, ponieważ zostanie utworzonych wiele wzorców projektowania, co może
utrudnić życie.

Wszystkie repliki utworzone z tej repliki, lub z repliki tej repliki, będą członkami tego samego zbioru replik. Posiadają one
wspólny zestaw numerów GUID, co pozwala im na wymianę danych i informacji o schemacie bazy. Kolejność, w jakiej
tworzyłeś repliki, ma mały wpływ na kolejność replikacji. Każda replika może synchronizować się z każdym członkiem
zbioru, a Ty masz możliwość kontrolowania kolejności replikacji.

W czasie synchronizacji możesz wybrać replikę lub repliki, z którymi chcesz wymienić dane. Jak pokazane jest na rysunku
22.2, w Accessie można to zrobić poprzez menu Narzędzia, Replikacja, Synchronizuj. Domyślnym ustawieniem jest wybór
jednej repliki, z którą ma być wykonana synchronizacja, jednak masz do wyboru również inne opcje. Masz możliwość
wyboru replikacji w tle z każdą repliką, do której masz w danej chwili dostęp, lub z jedną repliką.

Planowanie topologii replikacji


Decyzja użycia replikacji i utworzenie replik to tylko część tego, co należy zrobić, aby wykorzystać możliwości replikacji
Accessa. Następnie musisz ustalić, kto będzie z kim synchronizował dane, kiedy będzie je synchronizował, jak zapewnić,
że replikacja będzie wykonana na czas oraz jak obsługiwać zawiłości takie jak zdalni użytkownicy i powolne połączenia.

Zagadnienia te powinny być rozważone w czasie projektowania topologii replikacji lub mapy replik. Mapa taka określa
miejsce, gdzie znajduje się replika, w jakiej relacji pozostają ze sobą repliki, w jaki sposób tworzona jest replika i kiedy
następuje. Topologia replikacji jest kluczowa dla wydajności i pewności działania. Powinieneś dokładnie przemyśleć różne
dostępne topologie i wybrać tę, która najbardziej odpowiada Twoim wymaganiom. Nie pozwól, by wyborem topologii
rządził przypadek.

Ilość kombinacji możliwych topologii jest niemal nieograniczona, gdy uwzględnisz możliwość synchronizacji w jednym
lub dwóch kierunkach. Możesz wymusić na jednej replice zbieranie wszystkich zmian z replik i nieprzekazywanie ich
dalej. Może być to użyteczne do efektywnego dostarczania wyników pracy dnia do komputera kierownika, a kierownik
raportuje i analizuje dane bez dokonywania żadnych zmian. Replikacja może następować według tradycyjnego modelu,
gdzie dwie bazy synchronizują ze sobą dane, aby obie zawierały wszystkie zmiany zrobione w obu bazach.

Rysunek 22.3 pokazuje kilka możliwych topologii replikacji. Zwróć uwagę na zależności i przepływ danych.

W sieci lokalnej (LAN), użytkownicy mogą utrzymywać przez większość czasu stałe połączenia z innymi użytkownikami.
W takim wypadku gwiazda, pętla, wielokrotne połączenia, magistrala oraz drzewo będą dobrze działać. Każda z tych
topologii ma swoje zalety i wady. Wybrana przez Ciebie topologia powinna być kombinacją tych bazowych typów. W
tabeli 22.3 zostały opisane niektóre wady i zalety podstawowych typów.

Tabela 22.3.
Wady i zalety różnych topologii

Topologia Zalety Wady Zalecane użycie


Wielokrotne Zapewnienie najbardziej Możliwe duże obciążenie sieci Gdy ważne są szybkie
połączenia aktualnych danych aktualizacje i jest
niewielu użytkowników
Gwiazda Małe obciążenie sieci Środek jest newralgicznym Niewielu użytkowników
punktem, obciążenie jest i powolna sieć
nierównomierne, wymagane są
wielokrotne synchronizacje,
aby rozesłać zmiany do
wszystkich użytkowników
Część VII ♦ Zagadnienia wielodostępu 410

Rysunek 22.3.
Podstawowe
topologie replikacji

Tabela 22.3.
Wady i zalety różnych topologii (ciąg dalszy)

Topologia Zalety Wady Zalecane użycie


Drzewo Małe obciążenie, dokładna Nieoczywiste opóźnienia, Gdy tylko niektórzy
kontrola nad zależnymi nierówne obciążenie, użytkownicy
replikami uszkodzenie niektórych węzłów uaktualniają dane,
jest poważniejsze niż innych drzewo jest bardzo
efektywne
Pętla Równe rozłożenie Nieodporna na uszkodzenia, Użyj w sytuacjach, gdy
obciążenia, małe obciążenie jeżeli replikacja nie może ważne jest równe
sieci odwrócić kierunku obciążenie
Magistrala Największe opóźnienie, Bardzo nieodporna na Proste tworzenie, dobre
równe rozłożenie uszkodzenia tylko dla replikacji
411 Rozdział 22. ♦ Replikacja i JRO

obciążenia, małe obciążenie uszkodzenia pojedynczego


sieci użytkownika

W sieciach rozległych, gdzie utrzymanie stałego połączenia nie jest możliwe lub jest ono zbyt wolne, topologie te mogą
być łączone poprzez przypisanie jednej z replik roli odległej repliki dla innej topologii lub podsieci. Jet może
synchronizować bazy poprzez Internet lub Intranet.

Niezależnie czy używasz interfejsu Accessa do implementacji replikacji, czy używasz JRO lub DAO, powinny zostać
rozważone wszystkie topologie przed wybraniem właściwego rozwiązania, bazowanego na ich wadach i zaletach oraz
potrzebach aplikacji.

Niezależnie od podejścia, jakiego używasz do implementacji replikacji, jesteś jedynym, kto może spowodować, że
replikacja będzie miała miejsce. W przypadku prostego schematu możesz użyć okna z menu Narzędzia, Replikacja,
Synchronizuj lub przez wywołanie synchronizacji poprzez zdarzenie w aplikacji. Zdarzenie może być wykonywane
podczas uruchamiania aplikacji, w regularnych odstępach czasu (można użyć stopera na niewidocznym formularzu) lub po
określonej liczbie wykonanych zmian.

W trakcie synchronizacji, musisz wybrać pomiędzy schematem sterowanym i niesterowanym. Jeżeli zdecydujesz się na
użycie schematu sterowanego, możesz także zdecydować, czy replikacja ma być bezpośrednia czy pośrednia. Twoje
rozwiązanie może używać różnych ustawień w różnych miejscach, lecz jest bardzo ważne, aby wiedzieć, co one znaczą.

Wybór schematu sterowanego


Schemat sterowany używa aplikacji Manager replikacji oraz Manager synchronizacji. Manager replikacji pozwala na
planowanie i kontrolę replikacji oraz rozwiązywanie powstałych konfliktów. Możliwość pracy w tle, przechowywanie
rekordów oraz synchronizacja co 15 minut powoduje, że warto jej używać. Mimo że istnieje możliwość skopiowania
takich funkcji we własnym programie JRO lub DAO, zwykle nie ma takiej potrzeby.

Synchronizacja bezpośrednia
Bezpośrednia synchronizacja zachodzi, kiedy obie bazy danych są jednocześnie otwarte i uaktualniane. Aby niezawodnie
wykonać bezpośrednią synchronizację, powinieneś mieć pewne i stałe połączenie pomiędzy replikami.

Synchronizacja pośrednia
Powinieneś używać synchronizacji pośredniej dla połączeń poprzez WAN lub dla wolnych połączeń. W czasie
synchronizacji pośredniej jedna baza jest otwierana, a pakiet zmian jest wysyłany do Managera synchronizacji. Gdy
wszystkie pakiety zmian zostaną dostarczone, pierwsza baza danych jest zamykana a druga jest otwierana i aktualizowana.
Taka operacja jest mniej podatna na przerwanie połączenia.

Wybór schematu niesterowanego


Schemat niesterowany nie polega na Managerze synchronizacji. Jeżeli masz bardzo poważne powody, jak na przykład
częstsza synchronizacja, niż pozwala na to manager lub niektóre typy synchronizacji zależnej od zdarzeń (np. gdy ilość
przedmiotów w magazynie przekroczy założony poziom), możesz sterować synchronizacją za pomocą własnego
programu.

Po tych wyjaśnieniach wybierz Narzędzia, Replikacja, Synchronizuj i kliknij przycisk OK, aby rozpocząć synchronizację
poprzez interfejs użytkownika Accessa.

Jet i model obiektowy replikacji


Najlepszą kontrolę nad procesem replikacji oraz rozwiązywaniem konfliktów zapewnia użycie obiektów z Jet Replication
Object (JRO). Przy użyciu tej metody jest możliwe prawie całkowite ukrycie przed użytkownikami procesu replikacji.
Jeżeli dokładnie zaplanuje się proces replikacji, JRO pozwoli na skorzystanie ze współdzielonych danych w sposób
bezbolesny i niewidoczny dla użytkowników aplikacji.

Gdy będziesz programował funkcje replikacji, możesz wybrać pomiędzy dwoma modelami obiektowymi, które mają różne
możliwości oraz inny interfejs. Można skorzystać z Data Access Objects (DAO) lub nowego Jet Replication Object. W
DAO możliwość replikacji danych jest wbudowana w obiekty razem z funkcjami manipulacji danych, bezpieczeństwa i
Część VII ♦ Zagadnienia wielodostępu 412

definiowania struktur danych. Jeżeli używasz do przetwarzania danych ADO (domyślne dla Accessa 2000), to nie ma
powodu ładować dużej biblioteki DAO (DAO360.dll ma wielkość 541 kB) duplikującej istniejące możliwości, jeżeli nie
potrzebujesz ich w całości. Zamiast tego użyj specjalizowanej i rozszerzonej biblioteki JRO (MSJRO.dll ma 97 kB). W
rozdziale tym przedstawimy sposób obsługi replikacji przy użyciu JRO.

Jet Replication Object jest interfejsem dla replikacji oraz podstawowej konserwacji w silniku bazy danych Jet. W
rozdziale tym przedstawimy tyko replikację pomiędzy bazami danych obsługiwanymi przez Jet, mimo że można używać
JRO do zaprogramowania replikacji pomiędzy SQL 7.0 i Jet 4.0. Tak jak ADO, ADOR i ADOX, JRO podąża za trendem
spłaszczania struktury modelu obiektowego. Model posiada tylko kilka warstw, więc metody i właściwości są łatwo
dostępne z poziomu obiektu.

Rysunek 22.4 ilustruje model JRO.

Rysunek 22.4.
Model JRO

Poznajemy JRO
JRO udostępnia zestaw metod i właściwości pozwalający kontrolować możliwości replikacji Accessa. W tej części
rozdziału objaśnione zostaną części modelu obiektowego. W tabelach 22.4 oraz 22.5 znajdują się właściwości i metody
obiektu Replica.

Tabela 22.4.
Właściwości JRO.Replica

Nazwa Składnik klasy Typ Uwagi


ActiveConnection JRO.Replica Object

ConflictFunction JRO.Replica String

ConflictTables JRO.Replica Recordset Tylko do odczytu


DesignMasterID JRO.Replica Variant

Priority JRO.Replica Long Tylko do odczytu


ReplicaID JRO.Replica Variant Tylko do odczytu
ReplicaType JRO.Replica RepIicaTypeEnum Tylko do odczytu
RetentionPeriod JRO.Replica Long

Visibility JRO.Replica VisibilityEnum Tylko do odczytu

Tabela 22.5.
Metody JRO.Replica

Metoda Składnia
CreateReplica Replica.CreateReplica(NazwaRepliki, Opis [,TypRepliki]
[,Widoczność] [,Priorytet] [,Aktualizacja])

Tabela 22.5.
Metody JRO.Replica (ciąg dalszy)

Metoda Składnia
GetObjectReplicability Set ReturnValue = Replica.GetObjectReplicability
(NazwaObiektu, TypObiektu)
MakeReplicable Replica.MakeReplicable([CiągPołączenia] [,Śledzenie
kolumn])
PopulatePartial Replica.PopulatePartial(PełnaReplika)
413 Rozdział 22. ♦ Replikacja i JRO

SetObjectReplicability Replica.SetObjectReplicability(NazwaObiektu,
TypObiektu, Replikowalność)
Synchronize Replica.Synchronize(Cel [,TypSynchronizacji]
(,TrybSynchronizacji])

Tabele 22.6 i 22.7 zawierają właściwości i metody kolekcji JRO.Filters.

Tabela 22.6.
Właściwości kolekcji JRO.Filters

Nazwa Składnik klasy Typ Uwagi


Count JRO.Filters Long Tylko do odczytu
Item JRO.Filters Filter Tylko do odczytu
Właściwość domyślna

Tabela 22.7.
Metody kolekcji JRO.Filters

Metoda Składnia
Append Filters.Append(NazwaTabeli [, TypFiltra], KryteriaFiltra)
Delete Filters.Delete(Indeks)
Refresh Filters.Refresh

Tabela 22.8 zawiera właściwości JRO.Filter.

Tabela 22.8.
Właściwości JRO.Filter

Nazwa Składnik klasy Typ Uwagi


FilterCriteria JRO.Filter String Tylko do odczytu
FilterType JRO.Filter Enum Tylko do odczytu
TableName JRO.Filter String Tylko do odczytu

Opis metod i właściwości JRO


Jet Replication Object zawiera do swojego użytku kilka metod i właściwości. Właściwości są używane do identyfikacji
bazy danych, umieszczenia jej w Twojej topologii replikacji oraz wyznaczają sposób obsługi konfliktów. Metody zajmują
się tworzeniem replik, synchronizacją między replikami oraz określają, które informacje są przesyłane pomiędzy
replikami. Obiekt JRO Replica zawiera również kolekcję filtrów, które ograniczają poprzez zdefiniowane warunki,
dane przesyłane pomiędzy replikami.

Właściwość ActiveConnection
ActiveConnection jest obiektem Connection, należącym do repliki. Właściwość ta może być poprawnym ciągiem
połączeniowym, jeżeli obiekt Connection jest niedostępny.

Tak jak w całym ADO, jeżeli właściwość ActiveConnection ma wartość Nothing, wszystkie zależne obiekty są
odłączone od źródła danych.

Właściwość ConflictFunction
Jako wartość właściwości ConflictFunction można przypisać nazwę własnej funkcji rozwiązywania konfliktów
synchronizacji. Można utworzyć własną funkcję rozwiązywania konfliktów, jeżeli domyślna działa w sposób, który Ci nie
odpowiada.
Część VII ♦ Zagadnienia wielodostępu 414

We wcześniejszych wersjach Jet występowały błędy replikacji (błędy powtórzenia klucza, naruszenie więzów
integralności, problemy kontroli poprawności itd.) oraz konflikty replikacji (dwoje użytkowników wprowadziło zmiany
pozostające w konflikcie) i każda z tych sytuacji obsługiwana była oddzielnie.

W Jet 4.0 błędy replikacji i konflikty replikacji są traktowane jednolicie. Pozwala to na łatwiejsze rozwiązywanie pro-
blemów replikacji.

W czasie tworzenia schematu replikacji powinieneś spodziewać się następujących typów konfliktów:
u Jednoczesne zmiany. Dwóch użytkowników zmieniało ten sam rekord w tym samym czasie. Jeden z
użytkowników straci swoje zmiany, a jego rekord przesłany zostanie do tabeli konfliktów.
u Błąd powtórzenia klucza. W czasie synchronizacji dwa rekordy mają taką samą wartość w polu klucza.
u Naruszenie poprawności wartości w tabeli. W czasie synchronizacji rekord narusza zasady poprawności danych
zapisane podczas tworzenia projektu tabeli (puste ciągi znaków, wartości poza zakresem itp.). Gdy wystąpi naru-
szenie reguł poprawności, rekord jest odrzucany.
u Naruszenie więzów integralności. Gdy usunięty zostanie rekord w replice, który jest jedną ze stron relacji jeden
do wielu, wszystkie rekordy bazujące na kluczu obcym zostaną w trakcie synchronizacji odrzucone. Gdy
zmieniamy klucz główny rekordu w replice, zmiana klucza spowoduje, że rekordy bazujące na poprzedniej
wartości klucza w innych replikach zostaną odrzucone. Rekordy repliki z kluczem obcym bazującym na
nieprawidłowej wartości klucza głównego również zostaną odrzucone.

W każdym z tych przypadków kreator rozwiązywania konfliktów pokaże użytkownikowi odrzucony rekord. Użytkownik
może zdecydować, czy powtórnie wykonać zmiany, anulować zmiany lub zmienić dane powodujące konflikt.

Access używa wbudowanej procedury rozwiązywania konfliktów. Kreator rozwiązywania konfliktów pokazuje
użytkownikowi każdy konflikt i musi on zadecydować, który rekord zawiera prawidłowe dane.

Aby uniknąć tego procesu, można użyć właściwości ConflictFunction. Pozwala ona na użycie własnej procedury
rozwiązywania konfliktów, które wystąpiły w czasie synchronizacji lub może wskazać replikę, której rekordy są zawsze
najważniejsze w wypadku wystąpienia konfliktu. Jako wartość właściwości ConflictFunction należy przypisać nazwę
funkcji, która ma być wywołana w wypadku konfliktu. Musi być to nazwa funkcji, nie można podać nazwy procedury.
Jeżeli właściwość ta nie jest ustawiona, Access wywoła wbudowaną funkcję rozwiązywania konfliktów.

Funkcja rozwiązywania konfliktów jest wywoływana po zakończeniu synchronizacji. Gdy tworzymy funkcję
rozwiązywania konfliktów, operujemy na zawartości tablicy konfliktów w Twojej replice, aby ocenić konflikt oraz zmienić
rekord lub zbiór rekordów przy użyciu zwykłych mechanizmów manipulacji danymi (DAO, ADO, RDO lub SQL).

Gdy wprowadzasz własną procedurę rozwiązywania konfliktów, zastępujesz nią wbudowany algorytm rozwiązywania
konfliktów. Powinieneś dokładnie rozważyć sytuacje, w których jest to potrzebne. Jedną z możliwych sytuacji, kiedy
możesz skorzystać z napisania własnej funkcji rozwiązywania konfliktów jest to gdy chcesz sprawdzić przynależność
użytkownika do grupy, aby zdecydować, czy jego zmiany mają pierwszeństwo przed zmianami innego użytkownika.
Podejście takie pozwala na pracę użytkownika na różnych replikach bez względu na priorytet danej repliki w topologii
replikacji.

Domyślnie Jet 4.0 rozwiązuje konflikty przy użyciu dwóch algorytmów bazujących na priorytetach oraz unika konfliktów
przez ich poszukiwanie tylko na poziomie kolumn.

W Jet 4.0 każdej replice jest przypisana wartość priorytetu. Ta liczba wyznacza miejsce repliki w topologii. Jeżeli dwie
repliki spowodowały konflikt, Jet rozwiązuje go, bazując na ich relacjach w topologii. Zmiany repliki o wyższym
priorytecie są ważniejsze. W wypadku remisu ważniejsza jest replika z mniejszą wartością ReplicaID (replika utworzona
wcześniej). Algorytm ten jest zbliżony do używanego w SQL Server 7.0.

Wartość priorytetu przyjmuje wartości od 0 do 100. W trakcie tworzenia repliki otrzymuje priorytet równy 90% wartości
źródła.

W Jet 4.0 konflikty powinny wystąpić rzadziej niż we wcześniejszych wersjach. We wcześniejszych wersjach występował
konflikt, gdy dwóch użytkowników zmienia to ten sam rekord, nawet, gdy zmienili dane w różnych polach. W Jet 4.0
dwóch użytkowników może zmienić różne pola tego samego rekordu i konflikt nie nastąpi. Śledzenie zmian na poziomie
kolumn radykalnie redukuje częstość konfliktów i odciąża użytkowników od rozwiązywania tych konfliktów.

Śledzenie zmian na poziomie kolumn jest domyślnie włączone w Jet 4.0. Jeżeli Twoja aplikacja potrzebuje śledzenia zmian
na poziomie rekordów, opcja musi być zmieniona przed przystosowaniem tabel do replikacji. Aby wybrać pomiędzy
śledzeniem zmian na poziomie kolumn i rekordów, użyj parametru columntracking metody replica.Ma-
415 Rozdział 22. ♦ Replikacja i JRO

keReplicable. Ustawienie tego argumentu na True włącza śledzenie zmian na poziomie kolumn, a False włącza
śledzenie zmian na poziomie rekordów. Poniższa metoda powinna przystosować bazę do replikacji ze śledzeniem zmian na
poziomie rekordów:
Replica.MakeReplicable CurrentProject.Connection, False

Właściwość ConflictTables
Właściwość ta wskazuje na obiekt RecordSet zawierający listę tabel i skojarzonych z nimi tabel konfliktów.

Wywołanie właściwości ConflictTables zwraca RecordSet zawierający dwie kolumny: TableName i związaną z nią
ConflictTableName. Dla każdej tabeli z konfliktami istnieje tabela przechowująca rekordy powodujące konflikty.
Właściwość ConflictTables można tylko odczytywać.

Otwierając tabelę o nazwie podanej w polu ConflictTableName właściwości ConflictTables, można obejrzeć rekord
stracony przy synchronizacji oraz obejrzeć jego pola specyficzne dla replikacji.

Na wydruku 22.1 pokazany jest przykład prostej funkcji rozwiązywania konfliktów. Używa on ADO, ADOX i JRO do
przetworzenia wszystkich konfliktów przy użyciu właściwości ConflictTables.

Wydruk 22.1. Proste rozwiązywanie konfliktów


Function CustomDataConflictResolver()
Dim jro As New jro.Replica
Dim cat As New ADOX.Catalog
Dim conflrs As New Recordset
Dim rs As New Recordset

On Error Goto CustomDataConflictResolver Error

Set jro.ActiveConnection = CurrentProject.Connection


Set cat.ActiveConnection = CurrentProject.Connection

' jro.ConflictTables zwraca Recordset z nazwami tabelami


' zawierających konflikty
Set conflrs = jro.ConflictTables

' Dla każdej związanej tablicy konfliktów rozpoznaj konflikt


' i rozwiąż go
While Not conflrs.EOF
' Otwórz tabelę aktualnego konfliktu i analizuj utracony rekord
rs.Open "Select * From " & conflrs.Fields(1), jro.ActiveConnection
While Not rs.EOF
' Oceń tutaj rekordy pozostające w konflikcie i
' użyj SQL lub ADO, aby zapisać właściwe zmiany
' Upewnij się, że zachowałeś rekordy, w których nie rozwiązałeś
' konfliktu
rs.MoveNext
Wend
' Zamknij recordset z utraconymi rekordami
rs.Close
' Pobierz nazwę następnej tabeli
conflrs.MoveNext
Wend
' Gdy tworzysz własną funkcję rozwiązywania konfliktów
' musisz usunąć zawartość tabeli konfliktów
While Not conflrs.EOF
cat.Tables.Delete (conflrs.Fields(1))
conflrs.MoveNext
Wend

CustomDataConflictResolver = True

CustomDataConflictResolver _Exit:
conflrs = Nothing
rs = Nothing
jro = Nothing
Exit Function

CustomDataConflictResolver Error:
' Obsługa błędów
CustomDataConflictResolver = False
Resume CustomDataConflictResolver _Exit

End Function

Sposób, w jaki rozwiążesz konflikty, należy całkowicie do ciebie. Możesz brać zawsze ostatni rekord, zawsze rekord z
określonej grupy lub określonego użytkownika, pobierać rekord w oparciu o największą lub najmniejszą wartość albo użyć
kombinacji wszystkich tych sposobów.
Część VII ♦ Zagadnienia wielodostępu 416

Właściwość DesignMasterID
Wartość DesignMasterID jest identyfikatorem GUID, który określa wzorzec projektowania w zbiorze replik. Właściwość ta
jest ustawiana w trakcie tworzenia wzorca projektowania.

Możesz zmienić replikę we wzorzec projektowania, gdy oryginalny wzorzec zostanie stracony, jednak replika nie może
zmienić innej repliki we wzorzec projektowania.

Ustawienie tej właściwości w replice, jeżeli w tym zbiorze replik istnieje


wzorzec projektowania, może podzielić zbiór na dwa niezgodne zbiory
replik. Jeżeli się to zdarzy, nie będziesz mógł wykonać synchronizacji z
wszystkimi dotychczasowymi użytkownikami. Ponieważ GUID wzorca
projektowania jest globalnie unikatowy, konwertuj replikę na

wzorzec projektowania tylko w nadzwyczajnych sytuacjach, kiedy wzorzec


projektowania został stracony lub uszkodzony i nie istnieje inny wzorzec
projektowania.

Obiekty repliki
Każda baza danych utworzona z wzorca projektowania lub innej repliki jest obiektem Replica dostępnym poprzez JRO.
Poniższe właściwości i metody pozwalają rozróżnić repliki i kontrolować ich zachowanie i współpracę z innymi replikami.

Właściwość ReplicaID
Właściwość ta w sposób jednoznaczny identyfikuje bazę danych repliki i zawiera GUID typu Variant. Wartość GUID
jest tworzona razem z repliką i jest możliwy tylko jej odczyt.

Właściwość ReplicaType
Właściwość ta wskazuje na typ repliki. Właściwość ta zawiera jedną ze stałych wymienionych w tabeli 22.9.

Tabela 22.9.
Wartości ReplicaType

Stała Wartość Opis


jrRepTypeNotReplicable 0 Domyślna. Baza danych nie jest replikowana
jrRepTypeDesignMaster 1 Replika jest wzorcem projektowania
jrRepTypeFull 2 Replika jest pełną repliką
jrRepTypePartial 3 Replika jest repliką częściową

Właściwość ReplicaType (tylko do odczytu) wskazuje na to, czy baza jest replikowana a jeżeli jest, w jaki sposób jest
replikowana. Jeżeli ReplicaType ma wartość jrRepTypeNotReplicable, baza nie była przygotowywana do replikacji.
Można użyć parametru ReplicaType metody CreateReplica, aby utworzyć pełną lub częściową replikę.

Właściwość RetentionPeriod
Właściwość ta wskazuje, ile dni (od 5 do 32000) przechowywać historię replikacji. Historia zawiera szczegóły o usuniętych
rekordach, zmianach projektu oraz inne specyficzne dla systemu informacje. Jeżeli baza danych została przygotowana do
replikacji poprzez ADO, RDO lub manager replikacji, domyślną wartością jest 60 dni. Jeżeli baza została przygotowana do
replikacji poprzez interfejs użytkownika Accessa, wartością domyślną jest 1000 dni.

Właściwość ta musi być ustawiana we wzorcu projektowania.


417 Rozdział 22. ♦ Replikacja i JRO

Właściwość Visibility
Właściwość Visibility wskazuje na to, czy replika jest globalna, lokalna lub anonimowa. Visibility zarządza
oddziaływaniem pomiędzy replikami i zawiera jedną ze stałych wymienionych w tabeli 22.10.

Tabela 22.10.
Możliwe wartości właściwości Visibility

Stała Wartość Opis


jrRepVisibilityGlobal 1 Domyślna. Replika globalna
jrRepVisibilityLocal 2 Replika lokalna
jrRepVisibilityAnon 4 Replika anonimowa

Z repliki globalnej można utworzyć replikę dowolnego typu. Wszystkie zmiany w globalnej replice są śledzone i mogą być
wymieniane z każdą globalną repliką w zbiorze. Globalna replika może również wymieniać zmiany z każdą lokalną lub
anonimową repliką, które przynależą do jednego węzła.

Lokalne i anonimowe repliki wymagają globalnej repliki, która będzie węzłem w ich topologii. Nie mogą synchronizować
się z innymi replikami w tym zbiorze replik. Wszystkie anonimowe i lokalne repliki mają priorytet 0, więc zawsze
przegrywają przy rozwiązywaniu konfliktów z węzłem.

Tylko replika będąca węzłem „wie” o istnieniu lokalnych replik i tylko ona może zaplanować replikację z lokalnych replik.

Repliki anonimowe mogą być używane w topologii internetowej, gdzie dane są silnie rozproszone, ponieważ nie są
utrzymywane informacje systemowe, przez co rozmiar repliki jest silnie zmniejszony. Żadna replika, nawet replika
będąca węzłem nie może nawiązać połączenia z repliką anonimową. Replika węzłowa nie może zaplanować replikacji z
repliką anonimową.

Visibility jest właściwością niezmienną i nie może być zmieniana po utworzeniu repliki przy użyciu metody
CreateReplica.

Metoda CreateReplica
Metoda ta tworzy nową replikę na podstawie bieżącej replikowalnej bazy danych.
Replica.CreateReplica(NazwaRepliki, Opis [,TypRepliki] [,Widoczność] [,Priorytet] [,Aktualizacja])

NazwaRepliki – ciąg przechowujący pełną ścieżkę dostępu do tworzonej repliki.


Opis – ciąg opisujący tworzoną replikę.
TypRepliki – parametr opcjonalny. Typ tworzonej repliki. Wartością domyślną jest jrRepTypeFull. Gdy
tworzona jest pełna replika, w trakcie synchronizacji wymieniane są wszystkie dane. W częściowej replice
wymieniane są tylko dane spełniające warunki filtra. Prawidłowe wartości stałych dla tego parametru opisane są w
tabeli 22.11.

Tabela 22.11.
Możliwe wartości parametru TypRepliki

Stała Wartość Opis


jrRepTypeNotReplicable 0 Domyślna. Baza danych nie jest replikowana
jrRepTypeDesignMaster 1 Replika jest wzorcem projektowania
jrRepTypeFull 2 Replika jest pełną repliką
jrRepTypePartial 3 Replika jest repliką częściową

Widoczność – parametr opcjonalny. Wartość tego parametru określa widoczność repliki. Wartością domyślną jest
jrRepVisibilityGlobal. Prawidłowe wartości stałych dla tego parametru opisane są w tabeli 22.12.

Tabela 22.12.
Możliwe wartości parametru Widoczność

Stała Wartość Opis


jrRepVisibilityGlobal 1 Domyślna. Replika globalna
Część VII ♦ Zagadnienia wielodostępu 418

jrRepVisibilityLocal 2 Replika lokalna


jrRepVisibilityAnon 4 Replika anonimowa

Priorytet – parametr opcjonalny. Jest to wartość typu Long, która wskazuje, która replika wygrywa w trakcie
rozwiązywania konfliktów. Domyślną wartością jest -1, co oznacza, że baza danych powinna ustalić właściwą
wartość. Gdy tworzysz globalne repliki, ich domyślny priorytet jest ustawiany na 90% wartości priorytetu repliki
źródłowej. Jeżeli jesteś administratorem bazy, możesz ustawić dowolną wartość od 0 do 100. Repliki lokalne i
anonimowe zawsze mają priorytet 0 i nie może być on zmieniany. Wartość ta jest wymuszana podczas tworzenia
repliki i próby jej zmiany są ignorowane.
Aktualizacja – parametr opcjonalny. Wartość parametru określa, czy możliwe są zmiany w replice. Domyślną
wartością jest jrRepUpdFull. Stała jrRepUpdReadOnly uniemożliwia użytkownikom wprowadzanie zmian do
replikowanych tabel. Jednak, gdy synchronizujesz nową replikę z inną ze zbioru replik, zmiany struktury i danych są
przenoszone do nowej repliki. W tabeli 22.13 wymienione są stałe dopuszczalne dla parametru Aktualizacja.

Tabela 22.13.
Możliwe wartości parametru

Stała Wartość Opis


jrRepUpdFull 0 Replika może być zmieniana
jrRepUpdReadOnly 2 Replika nie może być zmieniana

Replika dziedziczy dokładnie taką samą charakterystykę lub jest bardziej restrykcyjna od repliki, na podstawie której
została utworzona. Przykładowo, na podstawie globalnej repliki tylko do odczytu, można utworzyć lokalną lub anonimową
replikę tylko do odczytu lub lokalna replika może utworzyć inną lokalną replikę o tej samej charakterystyce.

Metoda GetObjectReplicability
Metoda ta wskazuje na to, czy obiekt w bazie jest lokalny czy replikowany. Składnia prawidłowego wywołania
GetObjectReplicability przedstawiona jest poniżej:
Set ReturnValue = Replica.GetObjectReplicability(NazwaObiektu, _
TypObiektu)

Metoda zwraca wartość logiczną wskazującą na to, czy obiekt może być replikowany. W bazach danych
nieprzystosowanych do replikacji funkcja zwraca dla wszystkich obiektów True, ponieważ każdy z tych obiektów może
zostać replikowany, mimo że nie został ustawiony żaden schemat replikacji. Jeżeli baza zostanie przekształcona do postaci
replikowalnej, metoda zwróci True. W bazach replikowalnych metoda ta zwróci False dla wszystkich nowych obiektów,
ponieważ domyślnie nie są one częścią schematu replikacji.

Parametry metody GetObjectReplicability przedstawione są poniżej.

NazwaObiektu – nazwa obiektu, z którego odczytywany jest stan replikacji.

TypObiektu – typ obiektu wyszczególnionego w pierwszym parametrze.

Metoda GetObjectReplicability wskazuje, czy obiekt jest lub może być replikowany.

Parametry NazwaObiektu i TypObiektu są ciągami zawierającymi nazwę obiektu (np. Klienci) i nazwę części okna bazy
danych (np. Tabele). Jeżeli obiekt o podanej nazwie i typie nie występuje w bazie, lub którykolwiek z ciągów będzie
dłuższy niż 64 znaki, wystąpi błąd.

Aby dowiedzieć się, w jaki sposób zmieniać stan replikacji obiektu, popatrz na opis metody SetObjectReplicability.

Jeżeli obiekt określony parametrami NazwaObiektu i TypObiektu nie istnieje, wystąpi błąd.

Metoda MakeReplicable
Metoda ta przystosowuje bazę danych do replikacji. Składnia jej jest przedstawiona poniżej.
Replica.MakeReplicable([CiągPołączenia] [,ŚledzenieKolumn])
419 Rozdział 22. ♦ Replikacja i JRO

CiągPołączenia – parametr opcjonalny. Ciąg zawierający nazwę i pełną ścieżkę dostępu do bazy danych. Wartość tego
parametru zastępuje właściwość ActiveConnection.

ŚledzenieKolumn – parametr opcjonalny. Wartość logiczna wskazująca na sposób śledzenia zmian, na poziomie kolumn
lub na poziomie rekordów. Wartością domyślną jest True. Śledzenie zmian na poziomie kolumn pozwala na połączenie
zmian w rekordzie, jeżeli dotyczyły różnych pól. Konflikt wystąpi, jeżeli różni użytkownicy zmienią to samo pole w
rekordzie. Jeżeli w bazie często zdarzają się nakładające się zmiany tego samego rekordu, ustawienie tego parametru może
spowodować polepszenie wydajności.

Jeżeli nie poda się parametru CiągPołączenia oraz nie ma ustawionej właściwości ActiveConnection, wystąpi błąd. Po
pomyślnym zakończeniu działania metody, zostaje ustawiona właściwość ActiveConnection.

Metoda PopulatePartial
Metoda ta służy do ładowania repliki częściowej.
Replica.PopulatePartial(PełnaReplika)

PełnaReplika – pełna ścieżka dostępu i nazwa bazy danych repliki, z którą będą wymieniane dane.

Gdy synchronizujesz replikę częściową z pełną repliką, możliwe jest pozostawienie osieroconych rekordów w replice
częściowej. Przykładowo, masz ustawiony filtr dla tabeli Klienci zawierający warunek Region ='NJ'. Jeżeli użytkownik
zmieni w replice częściowej pole Region z NJ na OR i uruchomi metodę Synchronize, zmiana zostanie przeniesiona do
pełnej repliki. Jednak rekord zawierający OR w polu Region pozostanie osierocony w replice częściowej, ponieważ nie
spełnia warunków filtra.

Aby uniknąć pozostawiania osieroconych rekordów w trakcie replikacji rekordów, należy użyć metody PopulatePartial.
Metoda ta czyści wszystkie rekordy z repliki częściowej i ponownie ładuje je, bazując na ustawionym filtrze. Metoda
PopulatePartial jest podobna do Synchronize, ale po synchronizacji wszystkich zmian z repliki częściowej do pełnej
repliki usuwa wszystkie rekordy z repliki częściowej i ponownie ładuje replikę częściową, bazując na bieżącym filtrze
repliki. Gwarantuje to, że zmiany poczynione w replice częściowej nie zostaną osierocone z powodu konfliktu filtra.

Zawsze używaj metody PopulatePartial, gdy tworzysz replikę częściową lub zmieniasz warunek filtra repliki. Jeżeli
aplikacja zmieniła warunek filtra, powinieneś wykonać następujące kroki:
115. Zsynchronizuj pełną replikę z replikami częściowymi, w których ma zostać zmieniony warunek filtra.
116. Użyj obiektu Filter, aby wprowadzić zmiany do warunku filtra repliki.

117. Wywołaj metodę PopulatePartial, aby usunąć wszystkie rekordy z repliki częściowej i przesłać wszystkie
rekordy spełniające warunek filtra z pełnej repliki do repliki częściowej.

Jeżeli zmieniony zostanie warunek filtra i zostanie wywołana metoda Synchronize bez wcześniejszego wywołania
PopulatePartial, mogą wystąpić błędy.

Metoda PopulatePartial może być wywołana tylko wtedy gdy replika częściowa zostanie otwarta na wyłączność. Co
więcej, nie można wywołać PopulatePartial z programu działającego w replice częściowej. Zamiast tego, należy
otworzyć na wyłączność replikę częściową z pełnej repliki lub innej bazy danych i wtedy wywołać metodę
PopulatePartial.

Mimo że PopulatePartial wykonuje jednokierunkową synchronizację


przed wyczyszczeniem i powtórnym ładowaniem repliki częściowej,
dobrym pomysłem jest wywołanie Synchronize przed PopulatePar-
tial. Gdy używa się połączenia bezpośredniego lub połączenia inter-
netowego, w razie wystąpienia błędu w trakcie metody Synchronize,
wystąpi błąd, który można przechwycić. Można na podstawie tego błędu
zdecydować, czy uruchamiać metodę PopulatePartial (która usuwa
wszystkie rekordy z repliki częściowej). W wypadku synchronizacji pośre-
dniej nie występuje przechwytywalny błąd, więcej informacji znajdziesz w
opisie metody Synchronize. Jeżeli wywołana zostanie metoda
PopulatePartial i wystąpi błąd w trakcie synchronizacji, rekordy w
częściowej replice pozostaną usunięte. Nie jest to satysfakcjonujący
rezultat.
Część VII ♦ Zagadnienia wielodostępu 420

Metoda SetObjectReplicability
Metoda ta decyduje, czy obiekt jest lokalny, czy replikowany. Ustawienie replikacji obiektu jest wykonywane przez
wywołanie metody w następujący sposób:
Replica.SetObjectReplicability(NazwaObiektu, TypObiektu, _
Replikowalność)

NazwaObiektu – nazwa obiektu, w którym będzie ustawiany status replikacji.


TypObiektu – typ obiektu, w którym będzie ustawiany status replikacji.
Replikowalność – wartość logiczna wskazująca na to, czy obiekt może być replikowany.

Metoda SetObjectReplicability powoduje, że obiekt jest replikowany lub pozostaje lokalny. Jeżeli baza danych nie
została jeszcze przystosowana do replikacji, ustawienie parametru Replikowalność na False powoduje, że obiekt
pozostanie lokalny po przystosowaniu bazy do replikacji. Obiekty w niereplikowalnych bazach danych są domyślnie
replikowalne. Jednak nowe obiekty tworzone w replikowalnych bazach danych nie są domyślnie replikowalne. Aby
zmienić nowy obiekt w replikowalnej bazie danych z lokalnego na replikowalny, należy ustawić parametr Replikowalność
na True.

Parametry NazwaObiektu i TypObiektu są ciągami zawierającymi nazwę obiektu (np. Klienci) i nazwę części okna bazy
danych (np. Tabele). Jeżeli obiekt o podanej nazwie i typie nie występuje w bazie lub którykolwiek z ciągów będzie
dłuższy niż 64 znaki, wystąpi błąd.

Metoda SetObjectReplicability jest ignorowana dla wszystkich obiektów Accessa następujących typów: Formularze,
Raporty, Strony, Makra i Moduły. Replikowalność tych obiektów jest kontrolowana poprzez tabelę MsysAccessObjects i
może być ustawiona przed przystosowaniem bazy danych do replikacji. Domyślnie obiekty te są replikowalne.

Informacje na temat sprawdzania replikowalności obiektów zawarte są przy opisie metody GetObjectReplicability.

Metoda Synchronize
Metoda ta powoduje synchronizację ze sobą dwóch replik zgodnie z ich właściwościami replikacji i parametrami
wywołania metody.
Replica.Synchronize(Cel [,TypSynchronizacji] (,TrybSynchronizacji])

Cel – ciąg zawierający nazwę i ścieżkę dostępu do repliki, z którą będzie się synchronizowała bieżąca replika,
nazwę synchronizatora, który zarządza docelową repliką, lub serwer internetowy zawierający docelową replikę.
TypSynchronizacji – parametr opcjonalny. Wartość wyliczeniowa określająca typ wykonywanej
synchronizacji. Domyślną wartością jest jrSyncTypeImpExp. Prawidłowe wartości parametru wymienione
zostały w tabeli 22.14.

Tabela 22.14.
Wartości parametru TypSynchronizacji

Stała Wartość Opis


jrSyncTypeExport 1 Wysyła zmiany z bieżącej repliki do docelowej
jrSyncTypeImport 2 Wysyła zmiany z repliki docelowej do bieżącej
jrSyncTypeImpExp 3 Wartość domyślna. Wysyła zmiany z bieżącej repliki do
docelowej i odwrotnie

TrybSynchronizacji – parametr opcjonalny. Wartość wyliczeniowa określająca tryb synchronizacji. Wartością


domyślną jest jrSyncModeIndirect. Właściwe wartości parametru przedstawione są w tabeli 22.15.

Tabela 22.15.
Wartości parametru TrybSynchronizacji

Stała Wartość Opis


jrSyncModeIndirect 1 Wartość domyślna. Synchronizacja pośrednia
jrSyncModeDirect 2 Synchronizacja bezpośrednia
jrSyncModeInternet 3 Pośrednia synchronizacja przez Internet
421 Rozdział 22. ♦ Replikacja i JRO

Replika podana jako wartość parametru Cel musi być częścią tego samego zbioru replik. Jeżeli obie repliki mają tę samą
wartość właściwości ReplicaID, lub obie są wzorcami projektowania dwóch różnych zbiorów replik, replikacja się nie
uda. Jest to wymuszone przez dostawcę.

Jeżeli synchronizacja jest pośrednia, wartością parametru Cel musi być nazwą synchronizatora. Jet w czasie replikacji
pozostawia zmiany w buforze. Synchronizator zarządzający docelową repliką pobiera te zmiany i nanosi je. Aby
synchronizacja pośrednia działała prawidłowo, Synchronizator musi być uruchomiony na komputerze lokalnym
i docelowym.

Gdy synchronizacja ma zachodzić przez Internet, wartość parametru Cel musi być w postaci adresu URL zamiast ścieżki w
sieci lokalnej. Jeżeli Cel jest w postaci adresu URL, a parametr TrybSynchronizacji nie jest jrSyncModeInternet,
wystąpi błąd.

Gdy tryb synchronizacji jest bezpośredni, obie repliki są jednocześnie otwierane i synchronizowane. Przy
synchronizowaniu przez sieć WAN lub odległą sieć, pewność i wydajność procesu można poprawić używając
synchronizacji pośredniej. Można również synchronizować dane z SQL Server i bazami danych Jet przez ustawienie
parametru Cel na ServerName.Database.Publication i tryb synchronizacji na inny niż bezpośredni.

Manager replikacji jest wymagany do zainstalowania i konfiguracji programów Synchronizer i Replman, za pomocą
których można monitorować stan synchronizacji pośrednich i internetowych. Są one dostępne w wersji Developer Edition
Office 2000. Więcej informacji na temat managera replikacji znajduje się w pomocy Accessa.

Kolekcja Filters
Kolekcja ta zawiera wszystkie obiekty Filter w replice. Każdy obiekt filtra pozwala na ograniczenie ilości
replikowanych rekordów.

Właściwości i metody kolekcji Filters wymienione są w tabeli 22.16.

Tabela 22.16.
Właściwości i metody kolecji Filters

Właściwość Opis
Właściwość Count Zwraca ilość filtrów w kolekcji
Metoda Item Umożliwia dostęp do kolumn w kolekcji
Metoda Append Dodaje nowy filtr do kolekcji
Metoda Delete Usuwa filtr z kolekcji
Metoda Refresh Uaktualnia obiekty w kolekcji, aby odzwierciedlić bieżące zmiany w projekcie bazy

Właściwość Count
Właściwość ta przechowuje ilość obiektów w kolekcji.

Możesz użyć właściwości Count, aby sprawdzić, ile obiektów znajduje się w kolekcji. Ponieważ numerowanie elementów
kolekcji zaczyna się od zera, powinieneś zawsze używać pętli rozpoczynających się od elementu zerowego i kończących
się na wartości właściwości Count – 1. Jeżeli używasz Microsoft Visual Basic i chcesz utworzyć pętlę przebiegającą przez
wszystkie elementy kolekcji, użyj konstrukcji For Each ... Next.

Jeżeli wartość właściwości Count wynosi 0, kolekcja nie zawiera obiektów.

Metoda Item
Metoda ta zwraca obiekt z kolekcji identyfikowanej przez nazwę lub numer. Wywołanie metody pokazane jest poniżej:
Set object = Collection.Item ( Indeks )

Zwraca odwołanie do obiektu.

Indeks – wartość typu Variant, która może być nazwą lub numerem obiektu w kolekcji.
Część VII ♦ Zagadnienia wielodostępu 422

Użyj metody Item, aby zwrócić określony obiekt w kolekcji. Jeżeli metoda nie może znaleźć obiektu odpowiadającego
podanej wartości indeksu, wystąpi błąd. Niektóre kolekcje nie umożliwiają nazywania obiektów, dla nich musisz używać
adresowania numerem.

Właściwość Item jest właściwością domyślną dla wszystkich kolekcji, więc poniższe instrukcje są równoważne:
Collection.Item( Indeks )
Collection( Indeks )

Metoda Append
Metoda ta dodaje nowy obiekt Filter do kolekcji obiektów Filters w replice częściowej. Składnia metody Append jest
następująca:
Filters.Append(NazwaTabeli [, TypFiltra], KryteriaFiltra)

NazwaTabeli – ciąg będący nazwą tabeli, na którą nakładany jest filtr.

TypFiltra – wartość wyliczeniowa wskazująca na wartość właściwości FilterType określająca, czy filtr bazuje na
tabeli, czy na relacji.

KryteriaFiltra – ciąg zawierający kryteria, które spełniać musi rekord, aby był replikowany z pełnej repliki. Ustawia
właściwość FilterCriteria.

Jeżeli replika nie jest repliką częściową, wystąpi błąd. Jeżeli filtr o takiej samej nazwie i typie już istnieje, również wystąpi
błąd.

Wystąpi błąd, gdy spróbujesz dodać drugi filtr typu jrFltrTypeTable do tej samej tabeli.

Metoda Delete
Metoda ta usuwa obiekt Filter z kolekcji Filters w replice.
Filters.Delete( Indeks )

Indeks – wartość typu Variant zawierająca nazwę lub numer obiektu Filter do skasowania.

Jeżeli są dwa filtry o takiej samej nazwie, skasowany zostanie pierwszy. Użycie numeru pozwala na jednoznaczną
identyfikację filtra w przypadku takich samych nazw filtrów.

Jeżeli filtr o podanej nazwie lub numerze nie istnieje w kolekcji, wystąpi błąd.

Metoda Refresh
Metoda ta uaktualnia obiekty w kolekcji, aby odzwierciedlały dostępne obiekty. Wywołanie metody Refresh jest proste.
Collection.Refresh

Obiekt Filter
Właściwość ta definiuje kryteria, jakie musi spełniać rekord, aby został replikowany z pełnej repliki.

Właściwość FilterCriteria
Umożliwia zapis i odczyt ciągu zawierającego kryteria. Dla filtrów opartych o tabelę ciąg powinien reprezentować klauzulę
Where kwerendy SQL bez słowa Where. Dla filtrów opartych o relację ciąg zawiera nazwę relacji. Po ustawieniu wartości
właściwość ta jest tylko do odczytu i może być zmieniana tylko przy użyciu metody Append.

Wartością domyślną jest pusty ciąg znaków.

Właściwość FilterType
Właściwość ta określa typ filtra.
423 Rozdział 22. ♦ Replikacja i JRO

Właściwość jest typu wyliczeniowego. Prawidłowymi wartościami są stałe zamieszczone w tabeli 22.17. Właściwość ta
jest tylko do odczytu i można ją zmieniać tylko za pomocą metody Append.

Tabela 22.17.
Wartości FilterType

Stała Opis
jrFltrTypeTable Wartość domyślna. Filtr jest oparty o tabelę
jrFltrTypeRelationship Filtr jest oparty o relację

Właściwość TableName
Właściwość ta przechowuje nazwę tabeli, na którą nakładany jest filtr.

Właściwość przechowuje ciąg określający nazwę tabeli. Dla filtrów opartych o relacje, jest to tabela będąca po stronie
relacji wiele. TableName jest tylko do odczytu i może być zmieniane przy użyciu metody Append.
Rozdział 23.
Bezpieczeństwo
W tym rozdziale:
u Elementy bezpieczeństwa.
u Tworzenie grupy roboczej.
u Użytkownicy i grupy.
u Tworzenie systemu bezpieczeństwa przy użyciu opcji startowych.
u Zagadnienia bezpieczeństwa przy użyciu replikacji.
u Ochrona dzielonych baz danych.
u Bezpieczeństwo systemu klient-serwer.
u Zabezpieczanie bazy danych krok po kroku.
u Częste błędy bezpieczeństwa.

Aplikacje, a w szczególności aplikacje wieloużytkownikowe, nie są dokończone, dopóki nie zostaną zabezpieczone. Bez
prawidłowo wykonanego systemu ochrony aplikacje są podatne na ataki złośliwych hackerów i niewinną ciekawość
niedoświadczonych użytkowników. Jednak pomimo olbrzymich możliwości systemu bezpieczeństwa Jet jest on zwykle w
bazach Accessa zaniedbywany lub niewłaściwie tworzony. Częściowo dlatego, że opracowanie właściwej struktury
bezpieczeństwa jest niełatwym zadaniem. Opisy sposobów tworzenia systemu bezpieczeństwa są mylące, a sposób, w jaki
Jet obsługuje system bezpieczeństwa, różni się od innych systemów baz danych.

Elementy bezpieczeństwa
W tym rozdziale skupimy się na modelu bezpieczeństwa opartym o grupę roboczą stosowanym w Jet. Wskażemy wiele
praktycznych zagadnieniach, które musisz rozważyć w trakcie zabezpieczania bazy danych. Pokażemy również techniki
ActiveX Data Object Extensions for Database Definition Language and Security (ADOX) do tworzenia funkcji
zabezpieczeń. ADOX korzysta z interfejsu programistycznego DAO dla definicji danych i zarządzania ochroną. ADOX
zapewnia prostszy model obiektowy, a gdy używamy dostawcy OLEDB, model nie zawiera różnic syntaktycznych.
Ponieważ ADOX obsługuje tylko źródła danych oraz obiekty oparte na danych, takich jak tabele, kwerendy, widoki i
procedury, omówione zostaną podstawy interfejsu i techniki DAO. Pozwoli to zastosować system bezpieczeństwa dla
formularzy, raportów i makr.

Istnieją dwie możliwości zabezpieczenia aplikacji Accessa 2000:


u Ustawienie hasła bazy danych.
u Utworzenie systemu bezpieczeństwa opartego o grupę roboczą.

Zabezpieczenie bazy danych hasłem


Ustawienie hasła bazy danych jest szybką i prostą metodą zabezpieczenia pliku MDB. Po jej zastosowaniu (menu
Narzędzia, Zabezpieczenia, Ustaw hasło bazy danych w bazie otwartej na wyłączność) wszystkim użytkownikom
zostanie przypisane to samo hasło. W czasie uruchamiania pliku MDB każdy użytkownik musi podać to hasło. Wszyscy
mają to samo hasło i przez to każdy, kto zna hasło, może dostać się do bazy. Łatwo zauważyć, że ten sposób jest dużym
425 Rozdział 23. ♦ Bezpieczeństwo

kompromisem, gdy wszyscy użytkownicy mają te same prawa i hasło. Użytkownicy są nieodróżnialni od siebie.
Dodatkowo, jeżeli hasło zostanie zapomniane, nie ma sposobu na jego odtworzenie. I na koniec, założenie hasła na bazę
danych wyklucza użycie replikacji. Samo hasło bazy danych nie jest najlepszą metodą na zabezpieczenie poważnej
aplikacji wieloużytkownikowej, jednak może być używane razem z grupą roboczą.

System bezpieczeństwa grupy roboczej jest bardziej skomplikowany od hasła bazy. W tym rozdziale skupimy się na tym
zagadnieniu.

System bezpieczeństwa grupy roboczej


Hasło bazy oparte jest o bazę danych (chroniona jest baza danych bez rozróżniania użytkowników), natomiast Access/Jet
jest zabezpieczany w oparciu o informacje podawane przy logowaniu do grupy roboczej. Jest to skomplikowany i
elastyczny system, gdzie identyfikacja użytkownika w grupie roboczej determinuje sposób pracy schematu bezpieczeństwa.
W tej strukturze bezpieczeństwa użytkownicy są jednoznacznie identyfikowani i mogą indywidualnie dostawać
uprawnienia do bazy i zawartych w niej obiektów. Można powiedzieć, że dyskusja o plikach grupy roboczej,
przestrzeniach roboczych i grupach, która zostanie zaraz przeprowadzona, jest w rzeczywistości dyskusją o organizacji,
rozszerzaniu i ułatwianiu podstawowych operacji tworzenia i przypisywania praw użytkownikom.

Taki system oparty o użytkowników nie jest administrowany przez Access ani Jet. Jest administrowany za pomocą pliku
grupy roboczej (system.mdw). Plik grupy roboczej zawiera informacje na temat uprawnień użytkowników i grup
użytkowników i jest używany przez Accessa do odczytywania tych uprawnień. W Accessie system zabezpieczeń jest
zawsze włączony, jednak nie jest on zwykle widoczny. Plik grupy roboczej jest zawsze używany, niezależnie od tego czy
efekty są widoczne. Z tego powodu bardzo ważne jest ustawienie odpowiedniej grupy roboczej przed rozpoczęciem prac
nad systemem bezpieczeństwa.

Stosowanie takiego modelu (z oddzielną administracją) powoduje, że grupy użytkowników mogą mieć różne aplikacje
zabezpieczane i administrowane przez jeden centralny plik bezpieczeństwa. Plik MDW używany przez bazę danych
definiuje grupę roboczą. Grupa robocza jest zbiorem użytkowników, ich grup i baz danych, których mogą używać. Jak
pokazane jest na rysunku 23.1, silnik bazy danych polega na jego przestrzeni roboczej, aby dostarczyć informacji na temat
użytkowników bazy danych.

Rysunek 23.1.
Zauważ, że w tym
schemacie nie ma
obiektów bazy
danych.

Mimo że użytkownik jest centrum systemu bezpieczeństwa, nie jest możliwe tworzenie użytkownika lub przeprowadzenie
znaczącej dyskusji o nim, bez umieszczania go w kontekście grupy. Grupa robocza musi istnieć, aby działał system
bezpieczeństwa. Możesz mieć wielu użytkowników lub tylko jednego, ale grupa musi być utworzona.

Plik grupy roboczej jest specjalną szyfrowaną bazą danych, która zawiera następujące informacje:
u nazwa użytkownika;
u hasło użytkownika;
u identyfikator użytkownika (PID);
u właściwości użytkownika (ustawienia paska narzędzi i niektóre wartości domyślne);
u ostatnie cztery bazy otwarte przez użytkownika (widoczne w menu Plik);
u nazwy grup;
u grupy (PID);
u członków grup (użytkownicy należący do grupy).
Część VII ♦ Zagadnienia wielodostępu 426

Tworzenie grupy roboczej


Zaraz po zainstalowaniu, Access jest podłączony do domyślnej grupy roboczej definiowanej przez plik system.mdw.
System.mdw jest utworzony jedynie dla wygody. Gdy jest on tworzony w trakcie instalacji, informacje krytyczne dla
działania systemu bezpieczeństwa są pozostawione poza nim, więc są one na stałe niechronione. Każdy, kto chce zobaczyć
plik pomocy Accessa, musi przebić się przez ochronę domyślnego system.mdw. Powinieneś pozostawić ten plik i w razie
potrzeby utworzyć nowy plik grupy roboczej.

Aby to wykonać, należy użyć programu wrkgadm.exe, który zwykle jest instalowany w ...\Microsoft
Office\Office\wrkgadm.exe.

Program ten pozwala na tworzenie nowych grup roboczych i przyłączanie się do już istniejących. Po utworzeniu grupy
wynikowy plik MDW powinien być umieszczony w sieci w katalogu dostępnym dla wszystkich spodziewanych
użytkowników. W czasie tworzenia pliku grupy roboczej nie musisz mieć szczegółowego planu struktury systemu
bezpieczeństwa, jednak dobrze jest utworzyć plik grupy roboczej w trakcie tworzenia aplikacji najszybciej jak to tylko
możliwe, aby uniknąć w przyszłości pomyłek.

W czasie pracy wrkgadm.exe musisz wybrać pomiędzy podłączeniem do istniejącej grupy lub tworzeniem nowej.

Po wybraniu tworzenia nowego pliku grupy roboczej musisz podać informacje na temat przynależności do grupy roboczej.
Jak widać na rysunku 23.2 w oknie są trzy pola. Administrator grupy roboczej wypełnia dwa z tych pól, odczytując je z
instalacji Office 2000 lub Accessa 2000. Możesz zmienić te dwa pola albo zostawić je bez zmian, jednak musisz
wprowadzić identyfikator grupy.

Rysunek 23.2.
Przed utworzeniem
grupy roboczej
zapisz te krytyczne
informacje

Rysunek 23.3.
Access automatyzuje
wprowadzanie
niektórych
informacji
w Administratorze
grupy, jednak nadal
możesz je zmienić

Identyfikator grupy dostarcza ziarna dla algorytmu szyfrowania pliku grupy roboczej. Jest to informacja, która nie jest
tworzona w trakcie instalacji. Administrator pozwala na pozostawienie tego pola pustego, ostrzegając wcześniej o tym
fakcie, jednak neguje to cel tworzenia grupy roboczej. Identyfikator grupy zawiera do 20 znaków i wielkość znaków jest
istotna. Ciąg, który wprowadziłeś zapewnia, że grupa robocza będzie unikatowa po utworzeniu binarnego identyfikatora
nazywanego Workgroup Security ID (SID). Jeżeli właściwie zabezpieczysz identyfikator grupy, nie może ona zostać prze-
jęta. System bezpieczeństwa tak silnie chroni ten ciąg, że masz jeszcze tylko jedną szansę na zobaczenie lub zmianę jego
wartości. Zapisz ten ciąg i przechowuj tak, aby osoby niepowołane nie miały do niego dostępu.

Zapisz wartość identyfikatora grupy i przechowuj w bezpiecznym miejscu.


Możesz jej potrzebować, aby powtórnie utworzyć grupę roboczą. Jet nigdy
nie udostępni tej wartości.

Następnym krokiem jest znalezienie odpowiedniego miejsca dla pliku grupy roboczej. Powinien być umieszczony w
katalogu, w którym wszyscy użytkownicy grupy mają prawo do zapisu i odczytu. Jednak, gdy użytkownicy nie zmieniają
się, można skopiować plik MDW do komputerów wszystkich użytkowników. Jeżeli plik zmieni się, operację należy
powtórzyć, co może spowodować, że większe nakłady na administrację przeważą zysk wydajności. Umieszczenie pliku
MDW na dysku sieciowym zwiększa szanse, że będzie on regularnie składowany, co ułatwia odzyskiwanie danych w wy-
padku awarii.
427 Rozdział 23. ♦ Bezpieczeństwo

Nie ulegaj pokusie nazwania pliku MDB tak samo jak aplikacji lub źródła
danych, jeżeli pliki te umieszczone są w tym samym katalogu. Plik MDW
tworzy plik LDB do przechowywania informacji o swoich blokadach, tak
samo jak źródło danych i aplikacja. Jeżeli pliki MDB i MDW mają tę samą
nazwę, to mimo że nie są ze sobą w konflikcie, to ich pliki LDB nie zgodzą
się ze sobą. Dobrym rozwiązaniem jest poprzedzenie nazwy pliku ciągiem
„SYS” lub „SYS_”.

Ostatnią szansą na zmianę lub obejrzenie informacji o grupie jest okno potwierdzenia danych o grupie roboczej. Upewnij
się, że prawidłowo zapisałeś wszystkie te informacje, a w szczególności identyfikator grupy, ponieważ może być on
potrzebny, aby odtworzyć plik MDW.

Jeżeli potwierdzisz informacje o grupie, administrator potwierdzi fakt utworzenia grupy roboczej i powróci do pierwszego
okna dialogowego. Zauważ, że podłączyłeś się do nowej grupy roboczej. Możesz teraz tworzyć bazy danych,
użytkowników i grupy, przypisywać użytkowników do grup oraz nadawać i odbierać prawa w tej grupie roboczej. Jeżeli
podłączysz się do innej grupy roboczej, możesz w niej pracować w obszarze przydzielonych uprawnień.

Aby nie zniszczyć żadnej istniejącej bazy danych, utwórz całkiem nową bazę danych, na której przetestujemy resztę cech
systemu bezpieczeństwa.

Jeżeli Access jest otwarty, zamknij go i uruchom ponownie. Spowoduje to uruchomienie Accessa w nowo utworzonej
grupie roboczej, chociaż nic na to nie wskazuje. Przed utworzeniem uprawnień jest bardzo ważne sprawdzenie, czy
dołączyłeś się do właściwej grupy roboczej.

Możesz ustawić przynależność bazy danych do grupy roboczej przez wpisanie odpowiednich parametrów wywołania bazy
danych:
Ścieżka do Access.exe Ścieżka do MDB /WRKGRP Ścieżka do pliku MDW
[/USER nazwa użytkownika /PWD hasło]

Parametry wywołania /WRKGRP, /USER, /PWD działają tylko dla baz


danych Accessa, nie dla projektów Accessa.

Użytkownicy i grupy
Użytkownicy są podstawą systemu bezpieczeństwa. Jet rozpoznaje użytkowników i wie, co każdy z nich może zrobić. Co
każdy z użytkowników może zrobić zależy od uprawnień nadanych bezpośrednio użytkownikowi lub które odziedziczył z
grup, do których należy. Uprawnienia użytkowników są sumą ich uprawnień pochodzących z grup (uprawnienia wynikowe)
oraz ich indywidualnych uprawnień (uprawnienia bezpośrednie). Użytkownik należy do co najmniej jednej grupy, grupy
Użytkownicy.

W trakcie logowania się do bazy danych Jet zawsze logujesz się jako użytkownik. Nie można zalogować się jako grupa.
System zabezpieczeń rozpoznaje, do jakich grup należysz i stosuje się do posiadanych przez Ciebie uprawnień.

Chociaż użytkownicy są podstawowym elementem systemu bezpieczeństwa, trudno jest dyskutować o nich bez brania pod
uwagę grup, ponieważ użytkownik zawsze należy do co najmniej jednej grupy, a grupy są stworzone do zarządzania
użytkownikami.

Rozważmy przypadek hipotetycznej grupy Urzędnik. Mimo że grupa może nie posiadać uprawnień do tworzenia i
modyfikacji obiektów, może być w niej jeden użytkownik, który jest wyznaczony do korygowania i tworzenia raportów.
Powinien on otrzymać bezpośrednie prawo do tworzenia i modyfikacji obiektów raportów, mimo że nikt w grupie Urzędnik
takiego prawa nie posiada. Mimo że to działa, powoduje kłopoty w administracji, ponieważ administrator zabezpieczeń
musi zajmować się indywidualnymi użytkownikami oraz grupami. Istnieje szansa, że jeżeli administrator zrobił jeden
wyjątek, zrobi i kolejny. Lepszym sposobem obsługi urzędnika tworzącego raporty jest przypisanie go do grupy, która
posiada uprawnienia do tworzenia i modyfikacji raportów. Tym sposobem administrator obsługuje funkcjonalne
możliwości pojedynczych użytkowników zamiast opracowywać ich indywidualne profile zabezpieczeń. Grupy nie mogą
należeć do grup.

Ponieważ raporty są tworzone przez kreatorów, a budowniczy zapytań


pomaga użytkownikom precyzyjnie definiować wymagane dane bez doda-
i bi któ t ń d b d h żli j t d i ki h
Część VII ♦ Zagadnienia wielodostępu 428

wania obiektów zapytań do bazy danych, możliwe jest danie szerokich


uprawnień do tworzenia raportów, nawet w zabezpieczonej bazie danych.
Zaoszczędzi to mnóstwo nudnej pracy przy ich tworzeniu.

Grupa Użytkownicy domyślnie posiada wszystkie uprawnienia, a każdy


użytkownik jest jej członkiem. Musisz usunąć wszystkie uprawnienia
z grupy Użytkownicy, aby prawidłowo zabezpieczyć bazę danych. Inaczej
każdy użytkownik bazy będzie dziedziczył prawa administratora.

Omówienie domyślnych ustawień użytkowników i grup


Przed rozpoczęciem pracy nad zabezpieczeniami należy zapoznać z domyślnymi ustawieniami. Jet rozpoczyna pracę z
dwiema grupami i jednym domyślnym użytkownikiem. Te dwie grupy to Administratorzy i Użytkownicy. Domyślnym
użytkownikiem jest Administrator. Administrator jest członkiem obu grup, a obie grupy posiadają wszystkie uprawnienia w
bazie danych.

Gdy tworzymy kolejnych użytkowników i grupy, nazwy grup i nazwy użytkowników nie mogą być takie same. Access
używa konwencji nazywania użytkowników w liczbie pojedynczej, a grup w liczbie mnogiej. Wydaje się być to dobrym
rozwiązaniem i należy stosować tę konwencję.

Najważniejszą grupą jest grupa Administratorzy, ponieważ ma ona specjalne uprawnienia, które nie mogą być nadawane
tworzonym przez Ciebie grupom. Aby tworzyć, zmieniać lub usuwać użytkowników, tworzyć lub usuwać grupy, zmieniać
przynależność do grupy lub wyczyścić hasło użytkownika, musisz być członkiem grupy Administratorzy. Użytkownik nie
będący członkiem tej grupy może oglądać dane o innych użytkownikach i sprawdzić, kto należy do grupy, ale nie może
zmienić żadnego z tych ustawień, nawet dla siebie. Może on tylko zmieniać swoje hasło. Oczywiście w bazie danych musi
być co najmniej jeden użytkownik należący do grupy Administratorzy.

Grupy nie są tylko zbiorem użytkowników. Mimo że nie mogą się logować do bazy i nie mogą posiadać własnego hasła ani
być właścicielem bazy danych, mogą jednak być właścicielami obiektów Accessa i posiadać różne uprawnienia. Ta
możliwość pozwala na ułatwienie administracji bazą danych i użytkownikami. Jako generalną zasadę powinieneś przyjąć,
że przypisujesz uprawnienia grupom, a następnie przypisujesz użytkowników do grup. Bardzo ułatwia to administrowanie
systemem zabezpieczeń.

Tworzenie użytkowników
Mimo że użytkownik może różnić się tylko szczegółami od innych użytkowników tej samej grupy, tworzenie
użytkowników jest niezbędne do prawidłowego funkcjonowania systemu bezpieczeństwa w bazie danych.

Aby utworzyć użytkownika, należy wykonać następujące kroki:


118. Z menu Narzędzia wybrać Zabezpieczenia, Konta użytkowników i grup.
119. Wybrać zakładkę Użytkownicy i kliknąć przycisk Nowa.
120. Wprowadź Nazwę i Identyfikator osobisty (PID), w sposób pokazany na rysunku 23.4. PID musi mieć od 4 do 20
znaków. Wielkość liter ma znaczenie. Służy on jako ziarno dla tworzenia identyfikatora zabezpieczeń (SID).
Musisz zapisać PID, ponieważ nie da się go później odczytać.

Rysunek 23.4.
Tworzenie nowego
użytkownika
i przypisywanie mu
identyfikatora PID
429 Rozdział 23. ♦ Bezpieczeństwo

Ustawianie i zmiana hasła użytkownika


Po utworzeniu użytkownika możesz przypisać mu hasło. Nie musisz tego robić, ale powinna być to standardowa procedura.

Kliknij zakładkę Zmienianie hasła logowania, aby zmienić lub ustawić hasło. Hasło powinno posiadać od 1 do 14 znaków i
nie jest obowiązkowe. Wielkość liter w haśle ma znaczenie. Ponieważ hasło jest przeznaczone do tego, aby sprawdzić, że
użytkownik jest tym, za kogo się przedstawia, każdy powinien mieć założone hasło. Nie można podejrzeć hasła po jego
ustawieniu, więc lepiej je zapisać. W najgorszym przypadku, jeżeli użytkownik zapomniał hasła, administrator może je
usunąć. Na rysunku 23.5 widać, w jaki sposób ukrywane jest hasło podczas jego zmiany.

Rysunek 23.5.
Zmiana hasła
użytkownika poprzez
okno Accessa

Zawodowa odpowiedzialność nie pozwala mi na podanie sposobów zła-


mania zabezpieczeń Accessa pozwalających na odtworzenie zapomnianego
hasła. Pamiętaj, aby używać hasła, którego nie zapomnisz, a nikt inny nie
będzie go znał. Gdy wybierzesz takie hasło dobrze je zapamiętaj lub zapisz
i przechowuj w bezpiecznym miejscu.

Tworzenie grup
Jak wspomnieliśmy wcześniej, grupy pozwalają na ułatwienie administracji przez ustawianie identycznego profilu
zabezpieczeń wszystkim członkom grupy.

Aby utworzyć grupę, wykonaj następujące czynności:


121. Z menu Narzędzia wybierz Zabezpieczenia, Konta użytkowników i grup.
122. Wybierz zakładkę Grupy i kliknij przycisk Nowa.
123. Wprowadź Nazwę i Identyfikator osobisty (PID). PID musi mieć od 4 do 20 znaków. Wielkość liter ma znaczenie.
Służy on jako ziarno dla tworzenia identyfikatora zabezpieczeń (SID). Musisz zapisać PID, ponieważ nie da się go
później odczytać (rysunek 23.6).

Rysunek 23.6.
Tworzenie grupy
przez nadanie jej
nazwy i PID przez
interfejs użytkownika

PID grupy jest ziarnem używanym do jednoznacznej identyfikacji grupy.


Jeżeli kiedykolwiek będziesz potrzebował odtworzyć grupę, musisz podać
ten sam PID. Zapisz go i przechowuj w bezpiecznym miejscu.
Część VII ♦ Zagadnienia wielodostępu 430

Przypisywanie użytkowników do grup


Użytkownicy i grupy są tak ściśle związani, że ich tworzenie i przypisywanie jest wykonywane w jednym miejscu. Użyj tej
samej zakładki okna Konta użytkowników i grup, gdzie tworzyłeś użytkownika, aby połączyć go z grupą.

Wykonaj następujące kroki:


124. U góry okna wybierz użytkownika.
125. Na dole okna dialogowego wybierz z listy Dostępne grupy grupę, do której chcesz przypisać użytkownika.
126. Dwukrotnie kliknij wybraną grupę lub użyj przycisku Dodaj, aby dodać użytkownika do grupy. Możesz również
usunąć użytkownika z grupy przez dwukrotne kliknięcie w liście Członek grupy lub używając przycisku Usuń. Nie
można usunąć użytkownika z grupy Użytkownicy.

Aby zobaczyć wszystkie przypisania w bazie, użyj przycisku Drukuj użytkowników i grupy.

Ponieważ system bezpieczeństwa jest zorientowany na użytkownika, można kontrolować skład grupy tylko z zakładki
Użytkownicy, a nie zakładki Grupy.

Rozróżnianie między domyślnymi


i specjalnymi grupami i użytkownikami
Po utworzeniu nowej bazy danych struktura bezpieczeństwa Accessa nie jest pozbawiona użytkowników i grup. Posiada
ona zestaw domyślnych użytkowników i grup. Ci użytkownicy i grupy muszą istnieć, aby system bezpieczeństwa działał
poprawnie. Dopóki Access nie wie, kto się loguje do bazy, wszyscy są identyfikowani jako użytkownik Administrator,
który jest członkiem domyślnych grup Użytkownicy i Administratorzy, do czasu utworzenia systemu bezpieczeństwa. Grupy te
nie powinny posiadać żadnego znaczenia w Twoim systemie bezpieczeństwa. W tej części opisane są te domyślne grupy.

Administratorzy – w odróżnieniu od zwykłych kont, grupa Administratorzy jest unikatowa w każdej grupie roboczej,
ponieważ jej SID jest generowany na podstawie SID grupy. Grupa Administratorzy musi zawsze posiadać co najmniej
jednego członka i Jet wymusza tę regułę. Mimo że członkostwo w grupie Administratorzy może być odebrane, grupa nadaje
specjalne niemożliwe do odebrania przywileje. Członek grupy Administratorzy może nadawać przywileje do każdego
obiektu w grupie roboczej. Przy użyciu DAO i ADOX możliwe jest zablokowanie tych przywilejów dla Administratorów do
obiektów bazy danych tak, aby specjalne przywileje posiadał tylko właściciel obiektów, jednak nie da się, ani używając
DAO ani ADOX, odebrać Administratorom prawa do administracji grupami i kontami użytkowników.

Administrator – jedyny domyślny użytkownik w Jet. Sam nie posiada żadnych specjalnych praw, jednak dziedziczy prawa z
grupy Administratorzy. Jeżeli nie zalogowałeś się do bazy za pomocą konta jakiegoś użytkownika, domyślnie jesteś
zalogowany jako Administrator. Jeżeli w grupie Administratorzy znajduje się jakiś inny użytkownik, możesz usunąć z niej
użytkownika Administrator. Jest to niezbędny krok do prawidłowego zabezpieczenia bazy danych i jest omówiony w tym
rozdziale w części „Zabezpieczanie bazy danych krok po kroku”.

Użytkownicy – po utworzeniu bazy grupa ta jest pusta i domyślnie posiada wszystkie prawa do bazy. Usunięcie wszystkich
praw z tej grupy jest niezbędnym krokiem do prawidłowego zabezpieczenia bazy danych i jest on omówiony w tym
rozdziale w części „Zabezpieczanie bazy danych krok po kroku”.

Właściciel – jest nim użytkownik, który utworzył obiekt, lub użytkownik, na którego zostało przeniesione posiadanie
obiektu. Właściciel obiektu jest najsilniejszym użytkownikiem i posiada do niego nieusuwalne prawa. Właścicielami
obiektów bazy danych muszą być użytkownicy, natomiast innych obiektów użytkownicy lub grupy.

Poznajemy uprawnienia
Tak jak trudno jest pisać o użytkownikach bez wspominania o grupach, równie trudno jest opisać uprawnienia bez
napisania o obiektach.

Po utworzeniu użytkowników i grup można rozpocząć tworzenie własnego systemu bezpieczeństwa. Uprawnienia
określają, co użytkownik lub grupa może, a czego nie może zrobić z tabelami bazy danych, kwerendami, formularzami,
raportami i makrami (moduły nie wchodzą już w skład systemu bezpieczeństwa). Typy uprawnień różnią się między
obiektami, a niektóre uprawnienia zależą od innych uprawnień. Przykładowo, jeżeli masz prawo do zmiany wyglądu
obiektu, musisz mieć możliwość otwarcia go (być może na wyłączność), odczytania i zapisu. Nie ma potrzeby
zapamiętywania niezależnych i zależnych zbiorów uprawnień. Interfejs Accessa będzie się troszczył o to za Ciebie, musisz
tylko wiedzieć, o co w tym chodzi. W tabeli 23.1 zestawione są obiekty, ich uprawnienia i ich konsekwencje.
431 Rozdział 23. ♦ Bezpieczeństwo

Uprawnienia nie są pamiętane w pliku MDW (w pliku MDW nie ma żadnej o nich informacji). Przechowywane są w
bazie danych, a tylko użytkownicy są autoryzowani za pomocą pliku MDW.

Tabela 23.1.
Uprawnienia i co one mogą dla Ciebie zrobić

Uprawnienie Opis Obiekt


Otwórz Otwieranie z zabronieniem innym dostępu do obiektu Baza danych
z wyłącznością
Otwórz/Uruchom Otwieranie w trybie pracy Baza danych
Czytanie projektu Otwieranie w trybie projektowania Wszystkie poza
modułami
Modyfikuj projekt Oglądanie, zmiana lub usuwanie obiektów struktury i ich Wszystkie
właściwości
Administruj Ustawianie hasła bazy danych, tworzenie wzorca Baza danych
(baza danych) replikacji, zmiana opcji startowych. Bez administracji
uprawnieniami
Administruj (inne) Pełne prawa, włączając administrowanie uprawnieniami Wszystkie poza bazą
danych
Odczytaj dane Tylko odczyt danych Tabele i zapytania
Aktualizuj dane Oglądanie i zmiana danych, bez dopisywania i kasowania Tabele i zapytania
Wstaw dane Oglądanie i dopisywanie danych, bez zmieniania Tabele i zapytania
i usuwania
Usuń dane Oglądanie i usuwanie danych, bez zmieniania i wstawiania Tabele i zapytania

Aby naprawić lub zmniejszać bazę danych, należy otworzyć ją na wyłączność. Tak samo należy otworzyć udostępnioną
użytkownikom wielodostępną bazę danych, jeżeli trzeba wprowadzić do niej zmiany.

Często pojawiają się problemy związane z zapytaniami. Można utworzyć dla użytkowników kwerendę, lecz nie chcesz, aby
mieli oni dostęp do tabel, na których ona bazuje. Włączenie opcji Uruchom uprawnienia właściciela daje dostęp na
poziomie rekordów i pól, ponieważ możesz ograniczyć użytkowników tylko do rekordów spełniających określone warunki
(na przykład: kody oddziałów, numery pracowników, bieżące daty, wartości pól itd.) oraz nie mogą oni zmieniać
utworzonych przez Ciebie zapytań.

Właściwości Uruchom uprawnienia znajduje się w oknie opcji dostępnym przez Narzędzia→ Opcje na zakładce
Tabele/Kwerendy. Wybranie Właściciela (rysunek 23.7) udostępnia wszystkie uprawnienia posiadane przez właściciela
kwerendy, na czas uruchomienia lub otwarcia kwerendy, jednak tylko właściciel może zmieniać zapytanie i tylko
właściciel może oddać posiadaną kwerendę innemu użytkownikowi. Wybranie Właściciela przesłania bieżące uprawnienia
użytkownika. Opcja ta może zostać uruchomiona z okna właściwości kwerendy oraz przez użycie klauzuli With
OwnerAccess w wyrażeniu SQL (więcej na ten temat w „Konsekwencje w czasie używania SQL”).

Rysunek 23.7.
Ustawienie
właściwości
Uruchom
uprawnienia
dla kwerendy
poprzez interfejs
użytkownika

Przez wszystkie lata tworzenia aplikacji baz danych nie spotkałem się z wieloma, o których można powiedzieć, że są
skończone. Jeżeli baza danych jest używana i użytkownicy ją lubią, jest zwykle rozszerzana. Aby obsłużyć ewentualne
nowe obiekty utworzone w przyszłości, Access dostarcza mechanizmu obsługi uprawnień obiektów, które jeszcze nie
zostały utworzone w trakcie tworzenia systemu bezpieczeństwa.
Część VII ♦ Zagadnienia wielodostępu 432

Wybranie <Nowe NazwaObiektu> w oknie dialogowym Uprawnienia użytkowników i grup nie zabezpiecza przed
tworzeniem nowych obiektów tylko definiuje, jakie będą uprawnienia nowo utworzonego obiektu. Nawet, gdy usunie się
wszystkie uprawnienia dla <Nowe NazwaObiektu>, użytkownicy będą mogli utworzyć nowe obiekty. Ponieważ
użytkownik tworzący obiekt jest jego właścicielem, może ustawić dowolne uprawnienia do obiektu. Jedyną metodą
zabronienia użytkownikom tworzenia obiektów jest interwencja w przypisywanie uprawnień przez ADO lub ADOX.

Właściciel obiektu jest najsilniejszym użytkownikiem obiektu i może zrobić z nim wszystko. Nie można praw związanych z
właściwością odebrać ani usunąć. Okno uprawnień może sugerować, że uprawnienia dla właściciela zostały odebrane, ale
w rzeczywistości tak nie jest. Jedynym sposobem na pozbawienie praw jest przeniesienie właściwości na innego
użytkownika.

Użytkownik, który utworzył bazę danych, jest jej właścicielem. Jego prawa do tworzenia obiektów w bazie danych nie można
odebrać, niezależnie co wskazuje okno nadawania uprawnień. Inni użytkownicy mogą tworzyć obiekty w bazie danych i stają
się ich właścicielami. Aby ułatwić administrację, należy prawo właściwości przenieść na grupę, tym sposobem każdy członek
grupy może administrować obiektem lub zbiorem obiektów.

Prawo właściwości obiektu może zostać przeniesione przez właściciela bazy danych lub właściciela obiektu. Aby zmienić
właściciela bazy danych, użytkownik musi posiadać prawa Czytanie projektu i Odczytaj dane w oryginalnej bazie danych.
Następnie należy utworzyć bazę danych w grupie roboczej, zaimportować wszystkie obiekty do nowej bazy, usunąć oryginalną
bazę oraz zmienić nazwę nowej bazy na taką jak usunięty oryginał.

Tworzenie systemu bezpieczeństwa przy użyciu opcji startowych


Oprócz rygorystycznego, prawidłowo zaprojektowanego systemu zabezpieczeń, powinieneś ustawić kilka opcji startowych,
aby poprawić bezpieczeństwo Accessa. Nie powinno być to mylone lub używane zamiast właściwego systemu
bezpieczeństwa, może jednak załatać jakąś nieprzewidzianą dziurę. To rozwiązanie może służyć jako tymczasowe
zabezpieczenie aplikacji.

W menu Autostart znajduje się kilka opcji:


127. Wyświetl okno bazy danych. W oknie bazy danych użytkownicy mogą zrobić najwięcej szkody. Poprzez ukrycie
tego okna po wczytaniu bazy danych, mniej doświadczeni (i zwykle najbardziej ciekawi) użytkownicy nie będą
mieli ochoty na zabawę tym oknem.
128. Pasek menu skrótów. Danie użytkownikowi dostępu do podstawowych możliwości Accessa może spowodować,
że mała wyrwa w systemie bezpieczeństwa powiększy się. Nie pozwalaj zamknąć formatki innym sposobem niż
ten, który przewidziałeś, lub zapisać dane bez sprawdzenia tożsamości i uprawnień bieżącego użytkownika.
Wyłączenie pełnego menu, domyślnych skrótów klawiszowych, pasków narzędzi oraz dostosowywania menu i
pasków narzędzi może zabezpieczyć przed włamaniem. Dokładnie przemyśl, które z opcji pozostaną aktywne.
129. Wyświetl kod po błędzie. Bez właściwego systemu bezpieczeństwa (i odpowiedniej obsługi błędów) użytkownicy mogą
otrzymać na ekran denerwujący i tajemniczy komunikat błędu lub, co gorsza, kod programu, co jest skrajnie
niewłaściwym i kłopotliwym zachowaniem aplikacji. Należy wyłączyć tę opcję.
130. Użyj specjalnych klawiszy programu Access. Naciśnięcie F11, Control-Break, Control-G może zrujnować aplikację.
Wyłącz tą opcję przed wysłaniem aplikacji do klientów.
131. Ikona aplikacji. Tutaj można wskazać inną ikonę, która zastąpi ikonę Accessa. Jeżeli tego nie zrobisz, niektórzy
użytkownicy mogą mieć kłopoty z odróżnieniem czy pracują w Accessie, czy w Twojej aplikacji. Można tutaj
podać nazwę pliku z ikoną (ICO) lub rysunkiem (BMP).

Zagadnienia bezpieczeństwa przy użyciu replikacji


Użycie replikacji w aplikacji powoduje wystąpienie problemów, które daje się jednak rozwiązać. Repliki mogą być
zabezpieczane na poziomie użytkowników. Wszystkie zmiany wprowadzane do uprawnień obiektów wzorca projektowania
zostaną w trakcie synchronizacji rozprowadzone do wszystkich replik, ponieważ uprawnienia te stanowią część samych
obiektów. Niestety plik grupy roboczej nie jest replikowany. Jeżeli użytkownicy nie mogą używać wspólnego pliku grupy
roboczej, co zdarza się w większości struktur replikacji, plik grupy roboczej musi być rozprowadzany, gdy utworzony zo-
stanie nowy obiekt lub gdy inne zmiany w strukturze zabezpieczeń tego wymagają.
433 Rozdział 23. ♦ Bezpieczeństwo

Innym problemem do rozpatrzenia jest skład grupy Administratorzy. Ponieważ członkowie tej grupy mogą dodawać i
usuwać użytkowników oraz usuwać hasła, ważne jest, aby ostrożnie dobierać administratorów i utrzymywać najmniejszą
możliwą ich liczbę.

Gdy używana jest replikacja, niedostępne jest zabezpieczenie bazy danych hasłem.

Ochrona podzielonych baz danych


Bazy danych Accessa zawsze mogą zostać podzielone. Po tej operacji dane umieszczone są w jednym pliku MDB,
natomiast część wykonywalna: formularze, raporty i moduły, w innym pliku. W jaki sposób zabezpieczyć taką aplikację.

Przy obsłudze tabel połączonych należy utworzyć dwa zbiory uprawnień: jeden dla źródłowej bazy danych, a drugi dla jej
klienta. Źródłem są tabele. W kliencie ustanowione są połączenia do tych tabel. Można ustawić uprawnienia do połączenia,
ale nie ma to większego sensu. Połączenie jest niczym więcej jak zbiorem właściwości.

Database=c:\Program Files\Microsoft Office\Office\Samples\Northwind.mdb

Wiedząc, że w tabeli połączonej przechowywanej na komputerze klienta nie ma żadnych danych, możesz nadać pełne
prawa do tabeli połączonej. Takie postępowanie pozwala użytkownikom na odtworzenie definicji tabeli w razie potrzeby.
Gdy połączenie nie jest chronione, należy zabezpieczyć źródłową bazę danych w normalny sposób. W ten sposób
nierozpoznani użytkownicy nie będą mogli dostać się do danych innymi sposobami.

Jeżeli będzie potrzeba odświeżenia połączeń do tabel źródłowych, możliwe są trzy sposoby:
u RefreshLink – wymagane prawo czytania danych w tabeli źródłowej.
u RefreshLink – wymagane prawo czytania projektu w tabeli źródłowej.
u Właściwość Connect – bez wymaganych praw w tabeli źródłowej.

Jeżeli z bazy źródłowej zostaną usunięte wszystkie uprawnienia, trzecia możliwość jest jedyną możliwą. Opcje te muszą
być uruchamiane poprzez DAO lub ADOX. Interfejs użytkownika nie pozwala na zarządzanie uprawnieniami połączenia,
chyba że masz uprawnienia do czytania danych w bazie źródłowej. Można wykonać to w następujący sposób:
Set tbldef = db.CreateTableDef(strTableName)
With tbldef
.SourceTableName=strTableName
.Connect = ";Database=" & strTableName
.Appedn tdf ' dołącz pojedynczą tabelę
End With

Innym sposobem poradzenia sobie z zagadnieniem połączeń jest całkowite usunięcie połączeń i dostęp do tabel źródłowych
poprzez obiekt zdalnej bazy danych i wyrażenia SQL. Można również skorzystać z możliwości Accessa 2000 do związania
formularza z odłączonym obiektem recordset. Na wydruku 23.1 znajduje się przykład tego podejścia.

Wydruk 23.1. Wiązanie formularza z odłączonym obiektem recordset


Dim wrk As Workspace
Dim db As Database
Dim rdb As Database
Dim rs As Recordset
Dim Connstr as String

Set wrk = DBEngine.Workspaces(0)


Set db = CurrentDb()

Connstr = "C:\program files\microsoft office\"


Connstr = Connstr & "office\samples\northwind.mdb"

Set rdb = wrk.OpenDatabase(Connstr, , , "admin")

Set rs = rdb.OpenRecordset("Select * from Customers") ...

Łączenie tabel nie wpływa na ADOX poza jednym ważnym szczegółem, ADOX „nie interesuje się” obiektami
umieszczonymi w bieżącej bazie danych (currentdb()), a więc nie zna uprawnień dotyczących połączenia. Przy
użyciu ADOX dane są otwierane bezpośrednio w źródłowej bazie danych. Program na wydruku 23.2 otwiera połączenie
ADO do źródła danych i ustawia uprawnienia dla użytkownika „JP”.

Wydruk 23.2. Otwarcie bazy danych przez ADOX i nadanie uprawnień


Dim cnn As New ADODB.Connection
Dim cat As New ADOX.Catalog
Część VII ♦ Zagadnienia wielodostępu 434

With cnn
.Provider = "Microsoft.Jet.OLEDB.4.O"
.ConnectionString = "data source=F:\NorthWind_Traders\& _
NorthWind.mdb;jet oledb:system database=" &
"F:\NorthWind_Traders\sysnwind.mdw; " &
"user id=Chuck;Password=opensesame"
.Open
End With

Set cat.ActiveConnection = cnn


cat.Users("JP").SetPermissions objName, adPermObjTable, _
adAccessGrant, adRightFull

Opcja With OwnerAccess


Jedną z możliwości jest usunięcie wszystkich uprawnień z tabel w bazie źródłowej. Można wtedy wykonywać kwerendy
oparte na połączonych tabelach, używając klauzuli With OwnerAccess na końcu wyrażenia SQL lub ustawiając tę
właściwość we właściwościach kwerendy. Tym sposobem kwerenda będzie mogła wykonać się i zwrócić wynik, jednak
użytkownik nie będzie mógł zmienić danych ani struktury tabeli.

Przykładowe wyrażenie SQL używające tej klauzuli wygląda następująco.


SELECT Customers.* FROM Customers
WITH OWNERACCESS OPTION

Aby utworzyć zapytania wykorzystujące opcję With OwnerAccess, wykonaj następujące czynności:
132. Usuń wszystkie uprawnienia z tabel dla grup, które będą używać kwerendy.
133. Przy użyciu użytkownika, który ma prawo odczytaj dane i aktualizuj dane w tej tabeli (lub tabelach) utwórz
zapytanie, wybierz kolumny i ustaw warunki, które określają oczekiwany wynik.
134. Zmień opcje uprawnień kwerendy na Właściciela. Pozwoli to na jej uruchomienie tak, jakby była uruchamiana
przez użytkownika, ale tylko właściciel może wprowadzić do niej zmiany.

Posiadanie zapytania, które może być zmieniane tylko przez właściciela, może przeszkadzać w złożonych aplikacjach, nad
którymi pracuje więcej programistów. Najlepiej ustawić grupę jako właściciela kwerendy, co pozwoli na modyfikowanie
jej przez wszystkich członków grupy, gdy zajdzie taka potrzeba. Powinieneś przestawić opcję uprawnień kwerendy na
Użytkownika przed przeniesieniem właściwości kwerendy na grupę.

Bezpieczeństwo systemu klient-serwer


W czasie pracy z danymi umieszczonymi na serwerze np.: SQL Server, Oracle lub Sybase, te same serwery zabezpieczają
dane, masz zwykle małą kontrolę nad tym systemem zabezpieczeń.

Jeżeli Twoja aplikacja jest oparta o dane z tabel na serwerze i chcesz ograniczyć możliwość zapisu i wstawiania danych do
tych tabel, możesz zrobić to poprzez uprawnienia Accessa, poprzez ADOX (użyj CurrentProject.Connection) lub
używając interfejsu użytkownika.

Zarządzanie użytkownikami
System zabezpieczeń Jet jest oparty o użytkowników, jednak nie oznacza to, że musisz obsługiwać wiele szczegółów na
jego temat. Zwykle wystarczy podać nazwę użytkownika, jego hasło i PID. Aby użytkownik mógł pracować, potrzebuje
uprawnień, a aby można było łatwo zarządzać użytkownikami, powinien należeć do przynajmniej jednej grupy. Poza tym
jest niewiele do zrobienia. Jeżeli wplączesz się w indywidualne ustawianie schematów zabezpieczeń dla poszczególnych
użytkowników, stworzysz sam sobie problemy administracyjne. Po przypisaniu nazwy, PID i hasła, powinieneś mody-
fikować tylko hasło. Unikaj nadawania praw do obiektu użytkownikom. Zamiast tego nadawaj prawa do obiektów grupom,
a następnie włącz użytkowników do tej grupy.

Na wydruku 23.3 znajduje się prosta funkcja, która ilustruje, w jaki sposób sprawdzić, czy użytkownik istnieje, utworzyć
go, usunąć, włączyć do grupy lub usunąć z grupy.

Wydruk 23.3. Przykład funkcji sprawdzającej istnienie użytkownika, jego usuwanie i tworzenie
Sub ADOXManageUser(strUserName, strPID, strPWD, _
435 Rozdział 23. ♦ Bezpieczeństwo

ParamArray JoinGroups() As Variant)

Dim cnn As New ADODB.Connection


Dim cat As New ADOX.Catalog
Dim Group As Variant

With cnn
.Provider = "Microsoft.Jet.OLEDB.4.O"
.ConnectionString = "data source=C:\Program Files\ & _
Microsoft Office\Office\Samples\Northwind.mdb; & _
jet oledb:system database=C:\Program Files\ & _
Microsoft Office\Office\Samples\sysnwind.mdw; &
user id=NWindAdmin;Password=opensesame"
.Open
End With

Set cat.Active0onnection = cnn

With cat
' Nie przewidujemy błędów
On Error ReSume Next

' Sprawdź czy nazwa istnieje


' Jeżeli tak, usuń użytkownika
' Usunięcie użytkownika usuwa go również z wszystkich grup
If strUserName = .Users(strUserName).Name Then
.Users.Delete strUserName
End If

' Utwórz nowego użytkownika


.Users.Append strUserName, strPWD
' Gdy użytkownik istnieje, można dodać go
' do podanych grup
For Each Group In JoinGroups()
.Groups(Group).Users.Append strUserName
Next

' Przed zakończeniem powinniśmy być zgodni z UI


' sprawdzam, czy użytkownik należy co najmniej do grupy
' Użytkownicy. Nie trzeba przeglądać wszystkich członków grupy
' wystarczy sprawdzić, czy nazwa występuje w kolekcji Users
If Not strUserName = .Groups("Users").Users(strUserName).Name Then
.Groups("Users").Users.Append strUserName
End If
End With
End Sub

Aby utworzyć lub zmienić użytkownika, funkcja wymaga jako argumentu nazwy użytkownika, jego PID i hasła oraz w
tablicy parametrów listy grup, do których użytkownik powinien należeć.

Funkcja sprawdza, czy nazwa użytkownika znajduje się w kolekcji Users. Jeżeli znajduje się tam, usuwa go i ponownie
tworzy z nowym identyfikatorem PID. Następnie przegląda przez przekazaną tablicę parametrów i przypisuje użytkownika
do grup. Aby być zgodnym z interfejsem użytkownika, funkcja sprawdza, czy użytkownik znajduje się co najmniej w
domyślnej grupie Użytkownicy. Jeżeli grupa ta nie została wymieniona w parametrze, użytkownik zostanie do niej
automatycznie przypisany.

Wyliczanie grup i użytkowników oraz wyświetlanie przynależności


Byłoby prawie niemożliwe administrowanie bazą danych, gdyby nie można było programowo uzyskać informacji, kto
może używać bazy i w jakim stopniu jej używa. VBA Accessa pozwala poprzez ADOX pobrać listę wszystkich
użytkowników z bazy danych, ich przynależność do grup oraz inne informacje. Przykład procedury wykonującej te
czynności znajduje się na wydruku 23.4.

Wydruk 23.4. Użycie ADOX do pobrania informacji o użytkownikach


Public Sub ADOXGroupsandUsers()

Dim cnn As New ADODB.Connection


Dim cat As New ADOX.Catalog
Dim i As Integer, k As Integer

With cnn
.Provider = "Microsoft.Jet.OLEDB.4.O"
.ConnectionString = "data source=h:\books and articles\ & _
unleashed\securityexample.mdb; & _
jet oledb:system database=h:\books and articles\ &
unleashed\sysnwind.mdw;user id=Admin;Password=letmein"
.Open
End With

Set cat.ActiveConnection = cnn


With cat
Debug.Print
Część VII ♦ Zagadnienia wielodostępu 436

' Pobranie i wypisanie listy grup


Debug.Print "Ilość grup = " & .Groups.Count
For i = 0 To .Groups.Count - 1
Debug.Print " " & .Groups(i).name
Next

Debug.Print

' Pobranie i wypisanie listy użytkowników


Debug.Print "Ilość użytkowników = " & .Users.Count
For i = 0 To .Users.Count - 1
' Nie pokazuj użytkowników 'Engine' i 'Creator'
If .Users(i).Groups.Count > 0 Then
Debug.Print " " & .Users(i).name
End If
Next

Debug.Print

'Wypisz zawartość kolekcji Groups z katalogu wraz z ich członkami


Debug.Print "Przynależność do grup"
For i = 0 To .Groups.Count - 1
Debug.Print " " & .Groups(i).name
For k = 0 To .Groups(i).Users.Count - 1
Debug.Print " " & .Groups(i).Users(k).name
Next
Next

Debug.Print

' Wypisz zawartość kolekcji Users z katalogu


' wraz z przynależnością do grup
Debug.Print "Przynależność użytkowników"
For i = 0 To .Users.Count - 1
' Nie pokazuj użytkowników 'Engine' i 'Creator'
If .Users(i).Groups.Count > 0 Then
Debug.Print " " & .Users(i).name
For k = 0 To .Users(i).Groups.Count - 1
Debug.Print " " & .Users(i).Groups(k).name
Next
End.If
Next
End With

End Sub

Identyfikacja bieżących użytkowników za pomocą ADOX


Często pojawiało się pytanie: „Kto jest teraz zalogowany” i do tej pory nie było eleganckiej metody sprawdzenia tego.
Teraz za pomocą ADOX można użyć wykazu, aby sprawdzić, kto używa bazy danych w każdym momencie. Przykład tego
znajduje się na wydruku 23.5.

Wydruk 23.5. ADOX pozwala na sprawdzenie, kto używa bazy danych


Sub UserRoster()
' Procedura używa rejestru użytkowników
' lub Jet 4.0, aby podłączyć się do bazy danych
' i sprawdzić, kto używa bazy danych
Dim conn As ADODB.Connection
Dim rst As ADODB.Recordset

On Error GoTo Proc_Err

Set conn = New ADODB.Connection

'Otwórz bazę źródłową


With conn
.Provider = "Microsoft.Jet.OLEDB.4.O"
.ConnectionString = "data source=h:\books and articles\ & _
unleashed\securityexample.mdb; & _
jet oledb:system database=h:\books and articles\ &
unleashed\sysnwind.mdw;user id=Admin;Password=letmein"
.Open
End With

' Otwórz recordset oparty na ilości użytkowników w bazie


Set rst = conn.OpenSchema(adSchemaProviderSpecific, ,
"{947bb102-5d43-11d1-bdbf-00c04fb92675}")

' Dla każdego użytkownika wypisz nazwę komputera i inne dane


Do Until rst.EOF
Debug.Print rst!COMPUTER_NAME
Debug.Print rst!LOGIN_NAME
Debug.Print rst!CONNECTED
437 Rozdział 23. ♦ Bezpieczeństwo

Debug.Print rst!SUSPECTED STATE

rst.MoveNext
Loop

Proc_Exit:
Exit Sub

Proc_Err:
MsgBox Err.Description
Resume Proc_Exit

End Sub

Wyszukiwanie użytkowników z pustym hasłem


Jedną z największych dziur w zabezpieczonej bazie danych jest użytkownik z pustym hasłem. Jet nie wymaga hasła, więc
musi ono zostać wymuszone poprzez własne funkcje tworzenia użytkownika lub ktoś musi dla każdego użytkownika
sprawdzić, czy można otworzyć bazę danych baz hasła. Funkcja na wydruku 23.6 przedstawia sposób, jak to zrobić przy
użyciu ADOX.

Wydruk 23.6. Wyszukiwanie pustych haseł


Public Sub ADOXPasswordCheck()
Dim strcnn1 As String
Dim strcnn2 A5 String
Dim cnn As New ADODB.Connection
Dim pwrdtestcnn As New ADODB.Connection
Dim cat As New ADOX.Catalog
Dim pwdCat As New ADOX.Catalog
Dim i As Integer, k As Integer

Strcnn1 = "data source=C:\Program Files\Microsoft Office\Office\"


Strcnn1 = strcnn1 & "Samples\NorthWind.mdb;"
Strcnn1 = strcnn1 & "jet oledb:system database="
Strcnn1 = strcnn1 & "C:\Program Files\Microsoft Office\Office\"
Strcnn1 = strcnn1 & "Samples\sysnwind.mdw; "
Strcnn1 = strcnn1 & "user id=NWindAdmin;Password=OpenSaysaMe"
With cnn
.Provider = "Microsoft.Jet.OLEDB.4.O"
.ConnectionString = strcnn1
.Open
End With

Set cat.ActiveConnection = cnn


With cat
For i = 0 To .Users.Count - 1
' Nie pokazuj użytkowników 'Engine' i 'Creator'
If .Users(i).Groups.Count > 0 Then
' Spróbuj otworzyć następne połączenie z nazwą użytkownika
' i pustym hasłem
With pwrdtestcnn
.Provider = cnn.Provider
strcnn2="data source=C:\Program Files\"
strcnn2= strcnn2 & "Microsoft Office\Office\Samples\"
strcnn2= strcnn2 & "NorthWind.mdb; "
strcnn2= strcnn2 & "jet oledb:system databa5e="
strcnn2= strcnn2 & "C:\Program Files\"
strcnn2= strcnn2 & "Microsoft Office\Office\"
strcnn2= strcnn2 & "Samples\sysnwind.mdw;
strcnn2= strcnn2 & "user id=NWindAdmin;Password= " "
.ConnectionString = strcnn2

' Zwykle dostaniemy błąd, a nie chcemy,


' żeby nas zatrzymał
On Error Resume Next
.Open
' Brak błędu oznacza, że udała się próba wejścia bez hasła
If Err = 0 Then
' użyj katalogu z bieżącego połączenia
Set cat.ActiveConnection = pwrdtestenn
Debug.Print cat.Users(i).name & " nie ma hasła"
' Zamknij to połączenie
pwrdtestcnn.Close
End If
End With
End If
Next
End With
End Sub
Część VII ♦ Zagadnienia wielodostępu 438

Ustawianie i usuwanie hasła


Ustawienie lub usunięcie hasła można wykonać przy użyciu interfejsu użytkownika lub poprzez ADOX. Poniższy wiersz
kodu zmienia hasło.
Cat.Users("Admin").changepassword "StareHasło", "NoweHasło"

Ustawienie obu argumentów metody changepassword na puste ciągi znaków usuwa hasło. Mimo że członek grupy
Administratorzy nie może zobaczyć hasła innego użytkownika, może on usunąć dowolne hasło.

Zarządzanie grupami
Aby łatwiej zarządzać użytkownikami, możesz przypisać uprawnienia i właściwość obiektu do grup zamiast do
użytkowników. Ogranicza to ilość różnych profili uprawnień.

Zarządzanie właściwością obiektów


Aby posiadać pełną kontrolę nad obiektami, powinieneś wiedzieć, w jaki sposób dostać się i zmodyfikować właściciela
obiektu. Na wydruku 23.7 przedstawione jest, jak dowiedzieć się, do której grupy należy obiekt i zmienić właściciela na
grupę, co ułatwi administrację.

Wydruk 23.7. Przypisywanie właściciela obiektu


Public Sub ADOXGroupOwnership(strObjectName As String, strGroupName As
String)

Dim cat As New ADOX.Catalog


Dim n As 5tring

' Tutaj pracujemy na komputerze klienta, ale jeżeli chcesz pracować z innym
' plikiem MDB, po prostu utwórz i otwórz połączenie do niego
Set cat.ActiveConnection = CurrentProject.Connection

With cat
Debug.Print .GetObjectOwner(strObjectName, adPermObjTable)
.SetObjectOwner strObjectName, adPermObjTable, strGroupName
.Tables.Refresh
Debug.Print .GetObjectOwner(strObjectName, adPermObjTable)
cat.Tables.Refresh
End With

End Sub

Zarządzanie wieloma aplikacjami


Przy użyciu ADOX Twoja aplikacja nie ładuje DDL lub zabezpieczeń, jeżeli tego nie potrzebuje, i ładuje, gdy tego
potrzebuje. ADOX znajduje się w niewielkiej bibliotece (msadox.dll) z jasnym i uniwersalnym interfejsem programowym.

Mimo że ADOX wciąż posiadał, w czasie pisania tej książki, kilka usterek, ale także posiada duży potencjał. Za jego
pomocą można administrować wszystkimi widocznymi grupami roboczymi z jednego miejsca. Nie wydaje się być to
niczym nowym, ale gdy rozważysz możliwość koordynowania zabezpieczeń Oracle i SQL Server oraz definicji danych w
Twojej lokalnej grupie roboczej, jest to imponujące. W chwili obecnej możesz wykonywać instrukcje DDL dla Oracle,
używając dostawcy MSDAORA i ADOX.

Gdy spotykasz się z implementacją systemu bezpieczeństwa oraz zagadnieniami definicji danych w wielu aplikacjach,
zwróć uwagę na ADOX i sprawdź, czy spełni wszystkie oczekiwania.

Właścicielem obiektów w bazie danych powinna być grupa. Strategia ta sprawdza się również w przypadku zarządzania
wieloma aplikacjami. ADOX pozwala na zarządzanie systemem bezpieczeństwa oraz wykonywanie poleceń DDL dla
wielu aplikacji z jednego miejsca, tym bardziej ważne jest przypisanie grupy jako właściciela wszystkich obiektów.
Ułatwia to również rozwój aplikacji. Jeżeli właścicielem obiektu jest pojedynczy użytkownik, tylko on może wprowadzić
do niego poprawki. W przypadku,

gdy właściciel nie jest osiągalny, proces rozwoju aplikacji poważnie zwalnia. Zamiast czekać na tę sytuację, lepiej
skorzystaj z grupy jako właściciela obiektów. Tym sposobem każdy członek grupy może wprowadzić niezbędne poprawki.
439 Rozdział 23. ♦ Bezpieczeństwo

Różne aplikacje mogą posiadać wspólną grupę roboczą (rysunek 23.1). Korzystaj z tej możliwości kiedykolwiek tylko
możesz. Istnieje duża szansa, że większość grup w różnych aplikacjach jest identyczna. Zmniejsza to ilość pracy dla
administratora.

Jeżeli jest to możliwe, staraj się, aby użytkownicy korzystali ze wspólnych plików, zamiast tworzyć schemat replikacji.
Mimo że replikacja jest świetnym narzędziem na współdzielenie danych i daje wiele możliwości dla aplikacji Accessa,
jednak pociąga ona zwykle duże koszty administracyjne.

Kluczem do zarządzania wieloma aplikacjami jest współdzielenie obiektów, użytkowników, grup, grup roboczych i
katalogów, gdziekolwiek jest to tylko możliwe. Zmniejszenie liczby zmiennych przy utrzymaniu tych aplikacji spowoduje,
że będą bardziej niezawodne i solidne.

Użycie SQL
Access 2000 dostarcza nowego sposobu obsługi podstawowych możliwości systemu zabezpieczeń w bazie danych oraz w
kliencie. Do dialektu SQL zostały dodane nowe słowa kluczowe, które pozwalają na tworzenie użytkowników i grup,
dodawanie użytkowników do grup, usuwanie użytkowników i grup, przypisywanie uprawnień oraz ich odbieranie.

Wyrażenia takie są wykonywane identycznie jak inne wyrażenia SQL, jednak zamiast zwrócić wynik lub zmienić definicję
bazy danych, wpływają na ustawienia zabezpieczeń wymienionych obiektów.

Create
Create User i Create Group wykonują dokładnie to, czego można się spodziewać. Do kolekcji użytkowników lub
grup w pliku systemowym bazy danych dodawany jest nowy użytkownik lub grupa. Jedyną różnicą pomiędzy tym sposobem
a użyciem ADOX jest brak identyfikatora PID. W wyrażeniu SQL nie można używać identyfikatora PID. Poniżej znajduje
się przykład tworzenia użytkownika i grupy za pomocą wyrażeń SQL.
CREATE USER użytkownik hasło [,użytkownik hasło, ...]
CREATE GROUP grupa hasło [,grupa hasło, ...]

Po utworzeniu użytkowników i grup można dodać użytkownika do grupy za pomocą wyrażenia Add User.

Add User
Add User wpływa również na kolekcję grup w pliku grupy roboczej. Gdziekolwiek występuje odwołanie do pliku grupy roboczej,
dotyczy bieżącej grupy. Za pomocą SQL nie można zmieniać innego pliku grupy roboczej niż ten, do którego jest zalogowany
użytkownik.
ADD USER użytkownik [, użytkownik, ...] TO grupa

Grant/Revoke
Po utworzeniu użytkowników i dodaniu ich do grup można nadać im uprawnienia. Wyrażenie Grant pozwala na nadanie
przywileju do obiektu użytkownikowi lub grupie.
GRANT {prawo [, prawo, ...]} ON
{TABLE tabela |
INDEX indeks |
QUERY kwerenda |
CONTAINER}
TO {użytkownik/grupa [,użytkownik/grupa, ...]}

Za pomocą tej metody możesz nadać mniej uprawnień niż za pomocą ADOX. Uprawnienia, które możesz nadać, są
następujące:
Select Selectsecurity Create
Delete Updatesecurity Selectschema
Insert Dbpassword Schema
Update Updateidentity Updateowner
Drop

Za pomocą SQL można nadawać uprawnienia do tabel, indeksów, kwerend i kontenerów.

Po nadaniu uprawnień można je odebrać za pomocą odwrotnego do Grant wyrażenia Revoke. Składnia i opcje są
identyczne jak dla wyrażenia Grant, a rezultat dokładnie odwrotny.
Część VII ♦ Zagadnienia wielodostępu 440

Drop
Po usunięciu uprawnień możesz usunąć użytkownika za pomocą wyrażenia Drop. Składnia i opcje są identyczne jak dla
wyrażenia Create poza słowem kluczowym Drop. Wynikiem wyrażenia jest usunięcie użytkownika lub grupy z pliku
grupy roboczej.

Zabezpieczanie bazy danych krok po kroku


Dobrze jest wiedzieć, że mimo oszałamiającej liczby opcji i nowych funkcji podstawowe czynności przy zabezpieczaniu
bazy danych Accessa nie zmieniły się.

Jeżeli podczas implementowania systemu bezpieczeństwa wykonasz możliwie dokładnie poniższe kroki, w pełni
wykorzystasz możliwości ochrony Accessa. Niedotrzymanie któregoś z punktów może spowodować obniżenie poziomu
bezpieczeństwa.
135. Utwórz nową grupę roboczą. Użyj programu wrkgadm.exe opisanego na początku tego rozdziału. Wybierz opcję
tworzenia nowego pliku grupy roboczej.
136. Otwórz Accessa, używając pliku grupy roboczej utworzonego specjalnie dla Twojej aplikacji.
137. Otwórz lub utwórz bazę danych, którą chcesz zabezpieczyć.
138. Utwórz nowego użytkownika i dodaj go do grupy Administratorzy.
139. Zmień hasło użytkownika Administrator.
140. Usuń wszystkie uprawnienia dla grupy Użytkownicy z wszystkich obiektów w bazie danych.
141. Zamknij bazę danych.
142. Otwórz Accessa, logując się jako nowy administrator.
143. Otwórz bazę danych, którą chcesz zabezpieczać.
144. Uruchom kreatora zabezpieczania na bazie danych. Zaoszczędzi Ci wiele żmudnej pracy, zmieniając właściciela
obiektów.
145. Usuń użytkownika Administrator z grupy Administratorzy.
146. Utwórz użytkowników i grupy potrzebne w aplikacji.
147. Przypisz użytkowników do odpowiednich grup.
148. Ustaw odpowiednie uprawnienia dla grup.
149. Dodawaj i usuwaj grupowe uprawnienia, tak jak tego potrzebujesz.

Częste błędy bezpieczeństwa


Jeden z częstych problemów występuje, gdy użytkownik logując się do jednej grupy roboczej może wejść do innej bazy
danych na użytkownika Administrator.

Zwykle dzieje się to, ponieważ system bezpieczeństwa został utworzony w domyślnym pliku system.mdw. Systemowy plik
MDW nie jest zabezpieczony i nigdy nie może być zabezpieczony, ponieważ przy jego tworzeniu nie został podany PID.
Ponieważ użytkownik Administrator jest uniwersalny, ktokolwiek może dostać się do takiego systemu. Jest również
możliwe, że użytkownik Administrator nie został usunięty z grupy Administratorzy. Ponieważ użytkownik Administrator nie
jest unikatowy dla wszystkich grup roboczych, każda z nich będzie widziała użytkownika Administrator jako swojego
Administratora. Jeżeli w Twojej grupie Administrator będzie członkiem grupy Administratorzy, użytkownicy z innych grup
roboczych będą mogli zalogować się do Twojej grupy z pełnymi prawami.

Aby rozwiązać ten problem, musisz zabezpieczyć bazę danych z użyciem nowego pliku grupy roboczej.

Czasami baza danych wydaje się zabezpieczona, wszyscy mogą się zalogować, ale nie działają uprawnienia.

Zwykle jest to spowodowane pozostawieniem uprawnień w grupie Użytkownicy. Po utworzeniu wszystkie grupy robocze dają
użytkownikom pełne prawa dostępu do wszystkich obiektów w bazie danych. Wszyscy użytkownicy są domyślnie w
441 Rozdział 23. ♦ Bezpieczeństwo

grupie Użytkownicy. Nawet gdy nie nadasz praw administratora, wszyscy użytkownicy z grupy Użytkownicy odziedziczą je
z grupy. Upewnij się, że usunąłeś wszystkie uprawnienia z grupy Użytkownicy.

Nic nie ogranicza Cię w tworzeniu tylu grup, ile potrzebujesz. Ponieważ grupa Użytkownicy jest bezużyteczna z powodu
braku uprawnień, a Administratorzy jest zbyt potężna, nie masz wyboru i musisz opracować swój schemat bezpieczeństwa i
utworzyć grupy w nim przewidziane.
Część VIII
Publikowanie w sieci
za pomocą Accessa 2000
W tej części:
u Konfiguracja serwera WWW dla publikowania w sieci WWW.
u Przenoszenie Accessa 2000 do sieci WWW.
u Użycie stron dostępu do danych.
u Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages.
Rozdział 24.
Konfiguracja serwera WWW dla
publikowania w sieci WWW
W tym rozdziale:
u Środowisko programistyczne a środowisko produkcyjne.
u Wybór platformy.
u Co to jest Option Pack.
u Uruchomienie serwera WWW.
u Zarządzanie i konfiguracja serwera WWW.
u Zabezpieczanie aplikacji WWW.
u Różnice pomiędzy witryną a katalogiem wirtualnym.

Większość programistów Accessa czuje się bardzo niepewnie, gdy ich szef lub klienci wspominają o publikowaniu w
sieci za pomocą Accessa 2000, ponieważ większość z nich jest ekspertami w zarządzaniu bazą danych oraz VBA,
natomiast niewiele wiedzą na temat uruchamiania i utrzymywania serwera WWW. W tym rozdziale wyjaśnimy, jak
skonfigurować komputer do programowania dla sieci WWW, jak uaktualniać serwer WWW i jak używać technologii
serwera WWW Microsoft. Nie znaczy to, że po zapoznaniu się z tym rozdziałem będziesz administratorem serwera
WWW, ale w razie potrzeby będziesz potrafił uruchomić serwer WWW.

Środowisko programistyczne a środowisko produkcyjne


Należy uściślić terminologię, której będziemy używać w tej części książki. Podczas tworzenia projektu wystąpią
prawdopodobnie dwa różne środowiska: środowisko programistyczne i środowisko produkcyjne. Środowisko
programistyczne jest miejscem, w którym tworzysz aplikację. Środowisko produkcyjne jest miejscem, gdzie Twoja apli-
kacja będzie umieszczona po jej ukończeniu. Jeżeli tworzysz strony na komputerze z Windows 95, a umieszczasz je na
komputerze z Windows NT Server w celu ich przetestowania i wykrycia błędów, komputer Windows 95 jest Twoją
maszyną programistyczną, natomiast Windows NT Server jest środowiskiem produkcyjnym.

W idealnym przypadku, Twoje środowisko programistyczne i produkcyjne powinny mieć identyczne konfiguracje
sprzętowe i programowe, ale powinny znajdować się na oddzielnych komputerach. Zwykle nie jest to osiągalne. Wielu
ludzi (włączając niektórych autorów tej książki) używa Windows 95/98 lub Windows NT Workstation jako ich środowisko
programistyczne, natomiast umieszczają pliki na komputerze Windows NT Server, który jest ich środowiskiem
produkcyjnym.

Wspaniałą możliwością technologii WWW Microsoft jest możliwość tworzenia i testowania aplikacji WWW Accessa 2000
na komputerze z Windows 95/98 i umieszczanie ich na Windows 2000/NT 4.0 bez żadnych zmian. Microsoft dostarcza
jednej technologii WWW, która działa na każdym ze wspomnianych systemów operacyjnych. Aby skorzystać tej
technologii, należy zainstalować serwer WWW na Twoich komputerach roboczym i produkcyjnym.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 444

Wybór platformy
Microsoft wypuścił trzy różne aplikacje serwera WWW, po jednej na każdy poziom platformy Windows. Pierwszy z nich,
Personal Web Server 4.0 (PWS4), działa na Windows 95/98 i dostarcza podstawowych funkcji serwera WWW. Kolejny,
Peer Web Services (znów PWS4), jest również serwerem o ograniczonych możliwościach prawie identycznych z wersją dla
Windows 95/98, ale zmodyfikowany do pracy w Windows NT 4.0 Workstation. Ostatni, Internet Information Server 4.0
(IIS4), może pracować na Windows NT 4.0. Wersje działające na Windows 95/98 mają tak podobne możliwości i
funkcje, że w dalszej części książki będę je nazywał PWS, bez rozróżniania tych dwóch produktów.

Wybranymi funkcjami tych dwóch produktów są:


u Możliwość udostępniania prostych stron WWW.
u Możliwość tworzenia aplikacji Active Server Pages.
u Możliwość tworzenia transakcyjnych aplikacji WWW za pośrednictwem Microsoft Trasaction Server.
u Obsługa połączeń ODBC.
u Możliwość użycia komponentów dostępu do danych: Microsoft Data Access Components (MDAC).
u Microsoft Message Queue (MSMQ).

W czasie instalacji Option Pack instalowane są komponenty Microsoft Data


Access Components w wersji 1.5. Zaleca się zainstalowanie najnowszej
wersji tych komponentów. W czasie pisania tej książki dostępną były
MDAC 2.1 instalowane razem z Accessem 2000.
Powinieneś również wiedzieć, że istnieje różnica pomiędzy wersjami
MSMQ, instalowanymi z Option Pack, w zależności od systemu operacyj-
nego. MSMQ instalowane na Windows NT Server jest w pełni fun-
kcjonalną usługą kolejki komunikatów, natomiast wersja dla Windows NT
Workstation i Windows 95/98 są po prostu klientami używającymi usługi
MSMQ na serwerze.

Mimo wielu podobieństw występują również różnice, w większości mające związek z wydajnością i skalowalnością.
Powinny być one brane pod uwagę przy wyborze docelowej platformy produkcyjnej.

Personal Web Server i Peer Web Services


Personal Web Server i Peer Web Services są wspaniałymi narzędziami do tworzenia aplikacji lokalnie na swoim
komputerze, bez potrzeby korzystania z NT Server. Pozwalają na tworzenie i testowanie aplikacji przed wypuszczeniem jej
do produkcyjnego serwera WWW. Jeżeli aplikacja działa prawidłowo na PWS, masz zapewnione, że będzie działała po
przeniesieniu jej na IIS4.

Ponieważ PWS nie został zaprojektowany do obsługi obszernych witryn WWW, brak w nim niektórych funkcji
zawartych w IIS4, takich jak Index Server, SMTP Server oraz Certificate Server. Istnieje również ograniczenie ilości
jednocześnie przyłączonych klientów, tylko jedno w przypadku Windows 95/98 i nie więcej jak 10 dla Windows NT
Workstation.

Internet Information Server


Internet Information Server 4.0 jest dużo wydajniejszym serwerem WWW niż Personal Web Server. Jest to zalecana
platforma dla wszystkich produkcyjnych serwerów WWW, ponieważ lepiej wytrzymuje duże obciążenie. Powinieneś
zauważyć lepsze osiągi IIS4 w porównaniu z PWS4. IIS4 nie posiada ograniczeń na ilość jednocześnie podłączonych
użytkowników. W zależności od projektu Twojej aplikacji może potencjalnie obsłużyć tysiące równoległych
użytkowników.

Instalacja obu produktów jest bardzo łatwa i dosyć podobna. Zaleca się instalowanie tylko tych usług, które będziemy
wykorzystywali. Załadowanie niepotrzebnych komponentów powoduje niepotrzebne obciążenie stacji roboczej lub
serwera.
445 Rozdział 24. ♦ Konfiguracja serwera WWW dla publikowania w sieci WWW

Teraz po zapoznaniu się z podstawowymi faktami na temat dostępnych serwerów WWW należy odpowiedzieć na pytanie,
którego należy użyć? Powinieneś w razie możliwości używać IIS4 i Windows NT 4 Server dla środowiska produkcyjnego.
Będziesz lepiej wyposażony do tworzenia aplikacji, mając jako swoje środowisko programistyczne maksymalnie podobne do
docelowego środowiska produkcyjnego. Zalecam więc IIS4 i NT Server jako środowisko programistyczne. Prawie każda
aplikacja Active Server Pages, jaką napiszesz, będzie działała na dowolnej platformie WWW: IIS4 lub PWS.

Aby zainstalować serwer Microsoft Web, należy zainstalować NT 4.0 Option Pack.

Pomiędzy ASP działającymi na IIS3 i IIS4 występują różnice. IIS3 używa


VBScript 2, natomiast IIS4 używa VBScript 3. Wszystkie wersje VBScript
są ze sobą zgodne w tył, natomiast każda nowa ma nowe funkcje. Musisz
być ostrożny, wymagając nowszych funkcji, chyba że jesteś pewien, że
Twój serwer WWW już je obsługuje.
Jeżeli masz zainstalowany Internet Explorer 5 na serwerze, posiadasz
VBScript 5, który zawiera wszystkie wcześniejsze funkcje oraz dodatkowe
zalety. Jeżeli nie masz zainstalowanego w Twoim systemie Internet Explorer
5, a chcesz skorzystać z zalet najnowszej maszyny skryptowej, możesz
załadować najnowszą wersję z www.miscrosoft.com/scripting/. Dwie nowe
funkcje wprowadzone w wersji 5 to Eval i Execute, pozwalające na
tworzenie kodu w czasie jego pracy. Wprowadzono kilka zmian
polepszających wydajność aplikacji używających VBScript (włączając w to
Active Server Pages).

Co to jest Option Pack


Jedynie standardowa instalacja Windows 2000 zawiera wszystkie niezbędne pliki do tworzenia aplikacji dla WWW,
natomiast usługi Web są bezpłatnym dodatkiem do NT 4.0 i Windows 95/98. Windows NT Option Pack jest pakietem,
który dostarcza funkcji niezbędnych do programowania dla WWW i publikowania w Sieci. Mimo że nazywa się „Windows
NT” Option Pack, ten sam pakiet instalacyjny może być użyty do zainstalowania Personal Web Server 4 i innych
rozszerzeń sieciowych do Windows 95/98.

W trakcie instalacji NT Server 4.0, masz możliwość zainstalowania Internet Information Server (wersja 2), jednak nie
zapewnia on wymaganych możliwości do tworzenia Active Server Pages, która jest kluczową technologią Microsoftu i
tematem rozdziału 27. „Publikacja w sieci WWW za pomocą Access 2000 i Active Server Pages”.

Teraz, gdy jesteśmy przy tym temacie, nie zalecamy instalowania IIS
podczas instalacji Windows NT Server lub odinstalowania go przed dalszą
pracą. Zawsze lepiej jest rozpocząć od czystej instalacji niż od aktualizacji.

Najnowsza wersja serwera WWW wchodzi w skład Option Pack, który można otrzymać
z wielu źródeł. Jeżeli prenumerujesz MSDN, jest on do Ciebie automatycznie rozsyłany.
Możesz również kupić płytę CD-ROM lub załadować go z serwera WWW Microsoftu.
Option Pack dostępny jest pod adresem:

http://www.microsoft.com/ntserver/nts/downloads/recommended/NT40ptPk/default.asp.

Option Pack może zostać zainstalowany i uruchomiony na Windows 95/98, Windows NT Workstation oraz Windows NT
Server 4.0. Przed zainstalowaniem Option Pack powinieneś zainstalować Microsoft Internet Explorer 4.0 lub nowszy.
Zalecamy zainstalowanie najnowszej wersji przeglądarki, która posiada większość łatek i poprawek (w chwili pisania
książki jest to Internet Explorer umieszczony na dysku z Office 2000). Dodatkowo, jeżeli instalujesz Option Pack na
komputerze z Windows NT 4.0, musisz mieć zainstalowany Service Pack 3.

Service Pack 4 jest najnowszym pakietem poprawek dla Windows NT


dostarczonym przez Microsoft, ale powinien być zainstalowany PO zain-
stalowaniu Option Pack.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 446

Jeżeli z jakiegoś powodu musisz przeinstalować Service Pack 3 po in-


stalacji Option Pack, nie nadpisuj żadnych nowszych plików zainstalowa-
nych przez Option Pack.

Przed instalacją Microsoft Option Pack powinieneś się upewnić, że twój komputer spełnia wymagania podane w tabeli
24.1.

Tabela 24.1.
Minimalne wymagania sprzętowe dla instalacji dla Windows NT Option Pack

Komponent sprzętu Wymagane Zalecane


Procesor 66 MHz 486 90 Mhz Pentium
RAM 32 MB 64 MB
Wolne miejsce na dysku 30 MB 100 MB
Monitor VGA Super VGA
CD-ROM (niewymagany) 3x 6x

Uruchomienie serwera WWW


Serwery WWW mogą być, w zależności od potrzeb Twojej aplikacji, proste lub skomplikowane. Powodem dużego
skomplikowania jest możliwość całkowitej kontroli, jaką możesz mieć przy użyciu serwerów WWW firmy Microsoft.

Instalacja
Przed zainstalowaniem Option Pack muszą być spełnione wymagania określone wcześniej, takie jak: instalacja Internet
Explorer 4.01 i Service Pack 3 (w przypadku NT).

W czasie instalacji NT Option Pack musisz spełnić kilka wymagań, aby móc tworzyć aplikacje przy użyciu Office 2000.
Instalacja wielu z proponowanych komponentów jest zbędna, jeżeli zaakceptujesz domyślne wartości. W tej części
rozdziału wymienimy dostępne opcje instalacji, opcje, których zainstalowanie jest niezbędne oraz komponenty, które
powinieneś zainstalować nawet, gdy tylko planujesz ich użycia.

NT Option Pack dla Windows 95/98


Komponenty dostępne w czasie instalacji NT Option Pack różnią się w zależności od platformy, na jaką instalujesz pakiet.

Dostępne komponenty instalacji


Poniżej wymienione zostały komponenty dostępne w czasie instalacji, gdy po uruchomieniu programu instalacyjnego
wybierzesz Custom Installation. Opcje wymagane przez konkretny system operacyjny zostały odpowiednio opisane.
Zaznaczone zostały również komponenty niezbędne do tworzenia aplikacji WWW przy użyciu Office 2000, Active Server
Pages oraz obiektów COM.
u Certificate Server (tylko NT Server). Pozwala na tworzenie i wysyłanie certyfikatów cyfrowych. Możliwości te
pozwalają na uruchomienie w aplikacjach dodatkowej warstwy zabezpieczeń. Można utworzyć osobisty
certyfikat bezpieczeństwa dla klienta, który ładuje ten certyfikat do komputera i instaluje w oprogramowaniu
klienta (w przeglądarce). W przyszłości możesz upewnić się, że klient jest tym, za kogo się podaje.
u Option Pack Common Program Files. Zawiera pliki wspólne dla większości komponentów. Są one wymagane, aby
tworzyć aplikacje dla WWW.
u FrontPage 98 Server Extensions. Umożliwia tworzenie witryn i wykonanie podstawowych czynności
administracyjnych za pomocą Microsoft FrontPage i Microsoft Visual InterDev. Nie musisz instalować tego
komponentu, chyba że chcesz używać FrontPage lub Visual InterDev do tworzenia aplikacji.
447 Rozdział 24. ♦ Konfiguracja serwera WWW dla publikowania w sieci WWW

Można używać ograniczonej ilości funkcji tworzenia aplikacji przy użyciu


FrontPage bez instalowania rozszerzeń FrontPage, ale nie będzie można
korzystać z wbudowanych kreatorów, robotów WWW i funkcji publikacji.
Ponieważ rozszerzenia te powodują pewien narzut na serwerze, wielu
programistów używa tych narzędzi do tworzenia szkieletu kodu, który jest
modyfikowany przez inne narzędzia i następnie przenoszony na serwer za
pomocą standardowego oprogramowania FTP.

u Internet Connection Services for RAS. Zarządza wieloma połączeniami wdzwanianymi oraz książkami
telefonicznymi. Pakiet ten nie jest wymagany.
u Microsoft Data Access Component 1.5. Instalowane są komponenty ActiveX Data Components 1.5 (ADO) oraz
komponenty Remote Data Services (RDS). W komputerze umieszczane są sterowniki i dostawcy, które
umożliwiają połączenie do baz danych. Jest to komponent niezbędny do tworzenia aplikacji WWW Office 2000. Po
zainstalowaniu tego komponentu powinno się zainstalować najnowszą wersję komponentów MDAC (wersja 2.1).
Od czasu wypuszczenia Option Pack pojawiło się kilka kolejnych wydań pozbawionych zauważonych błędów i
zawierających dodatkowe funkcje wymagane przy tworzeniu aplikacji Office 2000 (sieciowych i innych).
u Microsoft Message Queue (MSMQ). Pozwala aplikacjom na przesyłanie informacji o transakcjach do innych
komponentów bez potrzeby czekania na odpowiedź. Funkcja ta powinna być zbadana, jeżeli tworzysz aplikacje
transakcyjne, a interfejsy, których używasz, są czasami niepewne. Przykładowo, jeżeli używasz MSMQ i wystąpi
chwilowa przerwa w połączeniu sieciowym, MSMQ będzie próbował dokończyć transakcję. Gdy przerwa w sieci
zostanie usunięta, transakcja może zostać zatwierdzona. Nie jest to wymagana funkcja, chyba że masz specjalne
wymagania i planujesz użyć tej usługi w aplikacjach.
u Personal Web Server (tylko Windows 95/98 i Windows NT Workstation). Komponent ten zawiera właściwą część
usługi WWW. Jest on wymagany, jeżeli planujesz testować aplikacje na Twoim komputerze.
u Internet Information Server (tylko Windows NT Server). Pakiet zawiera:
u Usługę File Transfer Protocol (FTP);
u Usługę NNTP (do utrzymywania grup dyskusyjnych)
u Internet Service Manager (ISM). Jest to komponent wymagany do administracji i konfiguracji usługi WWW
poprzez Microsoft Management Console.
u Usługę Simple Mail Transfer Protocol (SMTP). Pozwala na generowanie przesyłek e-mail z aplikacji i
wysyłania ich do adresatów.
u World Wide Web Server (usługa HTTP). Jest niezbędna, jeżeli chcesz tworzyć, testować i udostępniać
aplikacje WWW na Twoim serwerze.
u Przykładowa witryna WWW. Jeżeli rozpoczynasz programowanie dla WWW, powinieneś zainstalować te
przykłady, aby zapoznać się z użytymi konwencjami programowania i użytymi technikami.
u ISM w wersji HTML (Internet Service Manager). Pozwala on na zdalną administrację serwerem WWW
poprzez interfejs HTML.
u Microsoft Transaction Server 2.0 (MTS). Instaluje administratora COM i DCOM. Jest wymagany przy
programowaniu dla WWW.
u Microsoft Index Server (tylko NT Server). Pozwala na przeszukiwanie tekstu dokumentów umieszczonych na
serwerze WWW. Jest to świetne narzędzie do wyszukiwania zawierające wiele zaawansowanych funkcji. Jeżeli go
zainstalujesz, upewnij się, że go używasz. Uruchomienie procesu indeksowania wszystkich Twoich stron WWW
może być bardzo kosztowne. Nie jest to konieczna dla nas opcja.
u Microsoft Script Debugger (tylko NT Server). Pozwala na uruchamianie skryptów ASP. Może być użyty do
ułatwienia uruchamiania skryptów ASP. Jest automatycznie uruchamiany w razie wystąpienia błędu. Ze względów
wydajności i bezpieczeństwa nie powinien być instalowany na produkcyjnym serwerze WWW. Nie jest konieczny
do programowania z Office 2000.
u Windows Scripting Host. Pozwala na pisanie i uruchamianie lokalnych plików skryptów, które mogą wykonywać
niektóre funkcje administracji systemem. Nie jest konieczny do programowania z Office 2000.
u Microsoft Management Console (tylko Windows NT). Główne narzędzie w Windows NT, służące do zarządzania i
konfiguracji wszystkich usług zainstalowanych przez Option Pack. Jest to wymagany komponent w przypadku
Windows NT Server. Nie jest wymagany w przypadku NT Workstation (można użyć Personal Web Manager), ale
jest rekomendowany.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 448

u Visual InterDev RAD Support. Pozwala aplikacjom Visual InterDev na zdalne rozpowszechnianie aplikacji na
Twój serwer. Nie jest to wymagana opcja przy programowaniu w Office 2000.

Instalowanie Visual InterDev RAD Support powoduje potencjalne osłabie-


nie systemu bezpieczeństwa twojego systemu, więc powinieneś być
ostrożny. Komponent ten pozwala na zdalne rozsyłanie aplikacji, nawet bez
Twojej wiedzy. Tak jak w przypadku platformy programistycznej możliwe
jest, że komponent zdalnie zainstalowany na Twoim komputerze będzie
miał niesprzyjające efekty w Twoim systemie.

Jak widać, w NT Option Pack umieszczono wiele składników. Każdy z tych składników dodaje kolejne możliwości, ale nie
są one wymagane do podstawowego programowania dla WWW i mogą wnosić niepotrzebny narzut w systemie, jeżeli
są zainstalowane bez powodu.

Aby ułatwić instalacje NT Option Pack, Microsoft dołączył do programu instalacyjnego trzy prekonfigurowane opcje
instalacji. Komponenty instalowane przez te opcje są przedstawione poniżej.

Opcje instalacji: minimalna, typowa i niestandardowa


Jeżeli wybierzesz instalację niestandardową (custom), będziesz mógł wybrać dowolne składniki z listy, którą
przedstawiliśmy powyżej. Nie jest to zwykle potrzebne lub wymagane, więc Microsoft dał możliwość skorzystania z
dwóch innych opcji.

Instalacja minimalna zawiera wszystko, co jest niezbędne do tworzenia podstawowych aplikacji WWW za pomocą Office
2000. Podczas instalacji w Twoim komputerze znajdą się następujące komponenty:
u Microsoft Data Access Components 1.5;
u Personal Web Server (tylko Windows 95/98 lub NT Workstation);
u Internet Information Server (tylko NT Server);
u Transaction Server;
u SMTP Service (tylko NT Server).

Instalacja typowa zawiera wszystkie komponenty wymienione powyżej oraz dodatkowo:


u FrontPage Server Extensions;
u Dokumentacja do Personal Web Server (tylko Windows 95/98 i NT Workstation);
u Dokumentacja do Internet Information Server (tylko NT Server);
u Dodatkowa dokumentacja do: Active Server Pages, usługi SMTP, ADO oraz Index Server (tylko NT Server);
u Microsoft Index Server (tylko NT Server);
u Microsoft Management Console (tylko NT Server);
u Index Server (tylko NT Server);
u Microsoft Script Debugger;
u Windows Scripting Host.

Aby wykonać pełną instalację dokumentacji do Active Server Pages dla


Personal Web Server, musisz uruchomić instalację niestandardową
i włączyć ten składnik instalacji. Z jakiegoś powodu Microsoft zdecydował
się nie włączać tego składnika do żadnej z dwóch przygotowanych opcji
instalacji.

Jeżeli potrzebujesz jakiegoś zaawansowanego komponentu, który nie instaluje się automatycznie, powinieneś uruchomić
instalację niestandardową.

Jeden z przedstawionych wcześniej komponentów, Microsoft Transaction Server, jest tak ważnym usprawnieniem i
integralną częścią strategii WWW firmy Microsoft, że zdecydowaliśmy się omówić go bardziej szczegółowo w następnej
części tego rozdziału.
449 Rozdział 24. ♦ Konfiguracja serwera WWW dla publikowania w sieci WWW

Microsoft Transaction Server 2.0


Microsoft Transaction Server (MTS) jest jednym z ważniejszych składników Option Pack i jest niezbędny do pracy wielu
innych usług, włączając w to IIS/PWS. MTS jest brokerem wywołań obiektów (object request broker) oraz brokerem
transakcji (transaction broker). Do tej pory krytyczne aplikacje musiały pracować na wielkich systemach zaopatrzonych w
specjalne oprogramowanie zapewniające wymaganą niezawodność.

MTS jest tak ważny dla pracy IIS, że Microsoft umieścił go jako część
Windows 2000 i zmienił jego nazwę na COM+.
MTS jest niezbędny do instalacji usług WWW Microsoftu, ponieważ nawet
gdy jawnie nie używałeś w aplikacji WWW tego składnika, MTS zarządza
wszystkimi aplikacjami ASP. Każda przetwarzana strona ASP jest
wykonywana przez MTS (zarządzający ASP.DLL). Jest to powód, dlaczego
IIS4 ma tak ogromną wydajność w porównaniu do IIS3.

Co to jest broker transakcji?


Dobre pytanie. Broker transakcji zarządza transakcjami, jednak to stwierdzenie również nie mówi zbyt wiele. Większość
systemów baz danych, jak Microsoft SQL Server, zapewnia zarządzanie transakcjami. Serwer bazy danych rozpoczyna
transakcję, a następnie wykonywane jest jedno lub więcej wyrażeń SQL na jednej lub więcej tabelach. Serwer bazy danych
nie zatwierdza zmian, dopóki nie dostanie polecenia mówiącego, że wszystko się udało. Pomaga to na zachowanie
integralności danych w bazie danych i spójności w aplikacji. Zapewnia to, że wyrażenie 1 zostanie wykonane tylko razem
z wyrażeniem 2 i 3. Jeżeli transakcja nie powiodła się, jest ona wycofywana, co oznacza, że wszystkie wyrażenia SQL są
anulowane i baza danych jest przywrócona do stanu sprzed transakcji.

MTS zapewnia dla obiektów COM to samo co serwer bazy dla wielu wyrażeń SQL. Dobrą praktyką jest podział aplikacji
na możliwie małe części i wyodrębnienie kodu, który może być wielokrotnie używany. Dla utworzenia naprawdę
skalowalnej aplikacji kod ten może być przeniesiony do COM i zarejestrowany w MTS. Po prawidłowej rejestracji MTS
określa które obiekty COM są niezbędne w transakcji i śledzi udane i nieudane wykonania każdego obiektu.

Access 2000 (i wszystkie poprzednie wersje) nie potrafi w pełni wy-


korzystać możliwości Microsoft Transaction Server. Mimo to możesz
tworzyć aplikacje z wykorzystaniem MTS, aby uzyskać szybkość działania,
skalowalność i łączenie połączeń, musisz użyć bardziej zaawansowanej
bazy danych, takiej jak Microsoft SQL Server, aby w pełni skorzystać z
wszystkich poziomów wsparcia transakcyjności.

Oprócz zarządzania transakcjami MTS zarządza tworzeniem i usuwaniem obiektów. Pozwala to na tworzenie obiektów
COM wtedy, gdy są potrzebne, zwiększając szybkość wykonywania aplikacji i zapobiegając zwiększaniu obciążenia
serwera.

MTS zarządza także łączeniem połączeń do bazy. Pozwala to użytkownikom na współdzielenie połączeń zamiast
indywidualnego połączenia dla każdego użytkownika. Bez łączenia połączeń 500 użytkowników wymaga 500 połączeń do
bazy danych. MTS pozwala na około 10-krotne zmniejszenie ilości połączeń. Jeżeli połączenie jest nieużywane, jest ono
pożyczane do wykorzystania przez innego użytkownika, a następnie oddawane do wspólnej puli dostępnych połączeń. Ilość
połączeń jest zwiększana, gdy wszystkie dostępne połączenia są zajęte. Jest to wspaniałe usprawnienie i daje niesamowity
wzrost wydajności aplikacji.

Na rynku znajduje się wiele dobrych książek, które szczegółowo opisują działanie, konfigurację i uwagi dotyczące
programowania dla Microsoft Transaction Server. Szczegółowe opisywanie tych tematów wykracza poza ramy tej książki.
Jeżeli masz zamiar tworzyć aplikacje oparte o transakcje lub aplikacje wymagające wbudowanej skalowalności,
powinieneś na pewno poznać MTS.

Teraz, gdy już wiesz co zainstalować, jak zainstalować i jakie podstawowe funkcje są dostępne, omówimy konfigurację
usług WWW.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 450

Zarządzanie i konfiguracja serwera WWW


Do konfiguracji serwisów WWW, w zależności od tego czy pracujesz na Windows 95/98, czy Windows NT (Server lub
Workstation), używa się dwóch różnych narzędzi. Powinieneś zapoznać się z interfejsem użytkownika narzędzia
właściwego dla Twojej platformy.

Personal Web Manager


Program pracujący na Windows 95/98 nazwany został Personal Web Manager i posiada bardzo prosty interfejs
użytkownika umożliwiający konfigurację serwera WWW. Dostępne jest pięć głównych opcji: Main, Publish, Web site, Tour
oraz Advanced. Wybór opcji z paska nawigacyjnego z lewej strony okna lub z menu View otwiera odpowiedni obszar w
głównej części okna.
u Ekran Main (rysunek 24.1) jest miejscem, w którym można uruchamiać i zatrzymywać lokalną usługę WWW. Na
tym ekranie wyświetlone są również podstawowe informacje na temat serwisu.
Oprócz uruchamiania i zatrzymywania serwisu można odczytać położenie głównej strony WWW (katalog domowy),
adres WWW strony głównej (ponad przyciskiem start / stop) i niektóre statystyki ruchu na Twoim serwerze (grupa
Monitoring).
Rysunek 24.1.
Strona Main
programu Personal
Web Manager jest
zwykle używana do
uruchamiania
i zatrzymywania
usługi WWW

Możesz uruchomić lub zatrzymać usługę WWW, klikając prawym klawi-


szem myszki ikonę PWS w zasobniku systemowym (dolny prawy róg
ekranu obok zegara) i wybierając żądaną opcję z menu.

u Kolejna strona jest interfejsem do kreatora publikacji. Zgodnie z dokumentacją Microsoftu, kreator ten
automatycznie skopiuje pliki do katalogu sieciowego i doda połączenie do tego katalogu z Twojej strony
domowej. Jednak kreator nie zawsze działa najlepiej i zwykle lepiej samemu zmodyfikować odpowiednie pliki.
u Po wybraniu Web Site można utworzyć domyślną stronę domową lub zmienić istniejącą. Jest to bardzo proste
narzędzie i można się bez niego obejść, szczególnie, gdy jesteś prawdziwym programistą WWW.
u Tour dostarcza podstawowych informacji, prawdopodobnie nic ponad to, co już wiesz. Jeżeli jesteś ciekawy,
przejrzyj dostępne ekrany informacyjne.
u Większość funkcji potrzebnych do programowania WWW zawarta jest w części Advanced, która pokazana jest na
rysunku 24.2. Za pomocą tej opcji można tworzyć katalogi wirtualne, ustawiać domyślne dokumenty i zarządzać
właściwościami katalogów.

Termin „katalog wirtualny” nie jest właściwie rozumiany przez niektórych


programistów. Jest on dokładnie wyjaśniony w części „Różnica pomiędzy
witryną a katalogiem wirtualnym” tego rozdziału.

Katalogi wirtualne zostaną później szczegółowo objaśnione, ale powinieneś zapamiętać, że posiadają one trzy poziomy
dostępu ustawiane podczas tworzenia katalogu: Read, Execute i Script (rysunek 24.3). Zawsze zaznaczaj poziom dostępu
Read, jeżeli tego nie zrobisz, nikt nie będzie mógł oglądać Twojej witryny. Jeżeli masz zamiar oglądać strony ASP bez
451 Rozdział 24. ♦ Konfiguracja serwera WWW dla publikowania w sieci WWW

tworzenia katalogu wirtualnego, powinieneś zaznaczyć pole wyboru umożliwiające wykonywanie skryptów (ASP są
skryptami VBScript wykonywanymi na serwerze).
Rysunek 24.2.
Będziesz używał
strony Advanced
programu Personal
Web Manager do
tworzenia
i zarządzania
katalogami
wirtualnymi

Rysunek 24.3.
Prawa dostępu dla
nowego katalogu
wirtualnego
w Personal Web
Manager

Jeżeli zaznaczysz opcję Execute dla katalogu wirtualnego, wszystkie pliki wykonywalne w nim umieszczone będą mogły być
wykonywane, włączając w to interpretery skryptów (jak np. Perl) i pliki binarne Windows (pliki EXE i DLL).

Program konfiguracji usług WWW w systemie Windows NT / Windows 2000 jest nazywany Microsoft Management
Console i jest nieco bardziej wymagający. Jeżeli programujesz na Windows 95/98 i masz osobę, która administruje
serwerem produkcyjnym na Windows NT, możesz opuścić ten fragment rozdziału.

Microsoft Management Console


Program Microsoft Management Console (MMC), pokazany na rysunku 24.4, jest głównym narzędziem do zarządzania
wszystkimi usługami, które są częścią Option Pack na Windows NT, oraz będzie dużą i ważną częścią Windows 2000
(następcy Windows NT). Dobrym pomysłem jest zapoznanie się z nim, jeżeli planujesz używać kolejnych wersji Microsoft
Windows NT.

Po otwarciu MMC można zauważyć, że lewy panel posiada dwie rozwijalne opcje. Prawy panel jest oknem szczegółów i
będzie zawierał informacje specyficzne dla opcji wybranych po lewej stronie. Pierwszą pozycją w liście w lewym panelu jest
Console Root, właściwie jest to sam MMC. Każda pozycja poniżej nazywana jest wtyczką i pozwala na wykonywanie
specyficznych operacji zwykle ograniczonych do jednej usługi. Windows 2000 będzie posiadało wiele dostępnych wtyczek
dla MMC.
Rysunek 24.4.
Microsoft
Management
Console (MMC) jest
głównym narzędziem
do administracji
usługami sieciowymi

Konfiguracja Internet Information Server


Pierwsza wtyczka (jedyna, którą opiszemy w tej książce) służy do zarządzania programem Internet Information Server.
Jeżeli rozwiniesz jeden poziom tej gałęzi, zobaczysz tam nawę NetBios Twojego komputera. Rozwinięcie jeszcze jednego
poziomu odkryje różne opcję zależne od zainstalowanych usług.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 452

Zwykle znajdują się tam:


u Default FTP Site;
u Default Web Site;
u Administration Web Site;
u Default SMTP Site.

Opisanie każdej z tych opcji wykracza poza ramy tej książki, ale zajmiemy się kilkoma opcjami dotyczącymi konfiguracji
serwera WWW (gałąź Administration Web Site), ponieważ wpłyną one na pracę i wydajność Twoich aplikacji WWW.

Wykonamy teraz kilka zmian w konfiguracji serwera.

Na początek wybierze nazwę lokalnego serwera i kliknij ją prawym klawiszem myszki. Tak jak w przypadku wielu
aplikacji Windows wyświetlone zostało menu z najczęściej używanymi opcjami (rysunek 24.5).

Wybierzemy Properties z menu. Spowoduje to wyświetlenie domyślnych opcji całego serwera. Można dostać się do tych
opcji przez wybranie właściwości poszczególnych witryn, ale wtedy trzeba wykonywać zmiany dla każdej witryny osobno.

Zmienimy teraz położenie plików śladu. Option Pack ustawia ich położenie w c:\winnt\ system32\logfiles\.Na pierwszy rzut
oka nie wzbudza podejrzeń, ale przecież pliki śladu mogą urosnąć do sporych rozmiarów na uczęszczanym serwerze. Może
to spowodować zatkanie dysku systemowego, czego należy unikać.
Rysunek 24.5.
Kliknięcie prawym
klawiszem na opcję
wyświetla menu
podręczne z listą
możliwych do
wykonania funkcji

Na dole zakładki Web Site wybierz Logging Properties. Następnie przejdź na zakładkę General i zmień położenie plików
śladu serwera WWW. Może być to katalog, który już istnieje w systemie. Może być to d:\logfiles\, jest poza partycją
systemową i jest łatwy do odszukania. Jeżeli wybierzesz zakładkę Extended Properties, możesz wybrać, które informacje
będą zapisywane do plików śladu, gdy klient zażąda strony.

Nie wybieraj wszystkiego. Każda rzecz, którą zapisujesz, powoduje do-


datkową aktywność dysków i obciążenie systemu. Dla najlepszej wydajności
wybierz tylko te informacje, których naprawdę potrzebujesz.

Kliknij kilka razy przycisk OK, aby wrócić do głównego okna właściwości WWW.

Teraz zajmiemy się zakładką Documents. Możesz podać na niej jeden lub więcej domyślnych dokumentów (rysunek 24.6).
IIS używa tej informacji do wybrania pliku, który będzie załadowany jako pierwszy. Jeżeli ktoś wpisze
www.NazwaWitryny.com bez podawania nazwy pliku, IIS rozpoczynając od góry listy szuka pliku o podanej nazwie,
dopóki go nie znajdzie lub nie dojdzie do końca listy. Jeżeli plik nie istnieje na serwerze lub nie ma co najmniej jednego
wpisu do listy domyślnych dokumentów, użytkownik dostanie komunikat błędu. Ponieważ moja firma, ORCS Web, Inc
utrzymuje wiele serwisów klientów, zawsze dodajemy plik index.html do każdego serwera WWW, taki jest standard przyjęty w
systemie UNIX i wielu użytkowników jest do tego przyzwyczajonych.
453 Rozdział 24. ♦ Konfiguracja serwera WWW dla publikowania w sieci WWW

Rysunek 24.6.
Czasami będziesz
chciał zmienić nazwę
domyślnego
dokumentu lub
dodać więcej
domyślnych
dokumentów do listy
dla konkretnej
witryny

Przejdźmy znów do okna właściwości WWW i omówimy teraz zakładkę Directory Security. MMC pozwala na zarządzanie
dodatkowymi ustawieniami zabezpieczeń, które działają razem z Windows NT File System (rysunek 24.7). Znajdują się tu
trzy grupy opcji, które udostępnia IIS.

Rysunek 24.7.
Bezpieczeństwo jest
prawie zawsze
problemem każdego
systemu
przyłączonego
do Internetu

u Anonymus Access and Authentication Control (Dostęp anonimowy i zarządzanie uwierzytelnianiem);


u Secure Comunications (Bezpieczny przesył danych);
u IP Address and Domain Name Restrictions (Ograniczenie adresów IP i nazw domen).

Wybierz Anonymus Access and Authentication Control. Masz do wyboru trzy opcje:
u Allow Anonymous Access (zezwolenie na dostęp anonimowy);
u Basic Authentication (podstawowe uwierzytelnianie, hasło przesyłane jest otwartym tekstem);
u Windows NT Challenge/Response (uwierzytelnianie próba/odpowiedź).

Jeżeli chcesz umożliwić anonimowy dostęp do Twoich stron, zaznacz pierwsze pole wyboru (Allow Anonymous Access).
Opcja ta powoduje, że IIS najpierw sprawdza, czy użytkownik IUSER (omówiony później w części „Co to jest IUSER ?”)
posiada prawo do dostępu do pliku lub strony. Jeżeli tak, przyjmuje, że klientem jest IUSER i przetwarza żądanie. Jeżeli
opcja ta nie jest aktywna lub użytkownik IUSER nie posiada prawa do żądanego pliku, proces autoryzacji jest ponawiany
dla pozostałych dwóch opcji.

Jeżeli włączona jest autoryzacja próba/odpowiedź i klientem jest Internet Explorer, nazwa użytkownika i hasło użyte do
zalogowania do klienta zostaną przesłane do serwera WWW i następuje próba autoryzacji. Przy użyciu tego sposobu
autoryzacji hasło jest przesyłane do serwera w bezpiecznej zaszyfrowanej postaci. Jeżeli użytkownik i hasło pasują do
konta na serwerze (lokalnego lub pochodzącego z domeny), użytkownik otrzymuje żądaną stronę lub nie, w zależności od
jego uprawnień. Jeżeli nie zostanie dopa-

sowane żadne konto użytkownika, żądanie dostępu zostanie odrzucone. Jeżeli klient nie używa przeglądarki Internet
Explorer, podczas uwierzytelniania hasło przesyłane będzie otwartym tekstem.

Aby autoryzować użytkowników, którzy nie używają przeglądarki Internet Explorer, IIS umożliwia uwierzytelnianie przy
użyciu nieszyfrowanego hasła. Metoda ta nie jest bezpieczna, ale jest wystarczająca, jeżeli musisz zabezpieczyć jakiś
fragment swojego serwera, a nie jesteś pewien, jakiej przeglądarki używają klienci. Uaktywnienie obu opcji jest zwykle
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 454

najlepszym wyborem. Na początku IIS spróbuje autoryzować się jako IUSER (jeżeli jest aktywny), a następnie spróbuje
autoryzacji Windows NT. Jeżeli nadal nie uzyska dostępu, spróbuje podstawowej autoryzacji.

Wybranie Secure Communication w oknie właściwości serwera WWW, gdy nie mamy jeszcze zainstalowanego klucza
bezpieczeństwa, powoduje otwarcie narzędzia Key Manager. Jeżeli zdecydujesz się na użycie Secure Socket Layer (SSL),
musisz od tego zacząć. W oknie tym można wygenerować żądanie wygenerowania klucza, które jest wysyłane do centrum
autoryzacji, np.: VeriSign. Po przetworzeniu żądania należy wprowadzić otrzymany certyfikat do Key Managera aby
zakończyć proces instalacji klucza.

Po zainstalowaniu klucza SSL przycisk zmienia się z Key Manager na Edit. Wybranie Edit pozwala na włączenie trybu
dostępu SSL do ochrony przesyłanych stron. URL umożliwiający dostęp do stron powinien być podawany wtedy w postaci
https:// zamiast http://.

Elektroniczny handel staje się coraz bardziej popularny. Aby bezpiecznie


przesyłać przez Internet poufne dane (jak numery kart kredytowych),
musisz użyć SSL.

Masz również możliwość ograniczenia dostępu do witryny, opierając się o adresy IP klientów. Nie jest to zbytnio
użyteczne, chyba że serwer jest używany w Intranecie. Większość adresów IP klientów w Internecie zmienia się, ponieważ
są one dynamicznie przydzielane przez ich ISP.

Jeżeli decydujesz się na ograniczenie dostępu oparte o adres IP, możesz podać listę klientów, którzy nie mają dostępu do
witryny, lub przeciwnie, podać listę klientów mających dostęp do witryny.

Powróćmy do okna właściwości serwera WWW na zakładkę Home Directory (rysunek 24.8). Tutaj wprowadzasz
ustawienia dotyczące Twojej aplikacji.

Pole tekstowe Local Path zawiera ścieżkę do katalogu zawierającego witrynę, której właściwości właśnie oglądamy.

Pola wyboru Access Permissions pozwalają zdecydować, czy serwer pozwala na odczyt, zapis, obie operacje lub odmawia
dostępu. Nie spotkałem się jeszcze z sytuacją, gdzie byłby potrzebny zapis, więc można zaznaczyć tylko pole Read.

Za pomocą pól Content Control można ustawiać cztery opcje:


Rysunek 24.8.
Zakładka Home
Directory pozwala
na zarządzanie
najniższą warstwą
ustawień witryny
WWW, takich jak
katalog na serwerze

u Log Access. Jeżeli pole to jest zaznaczone, włączasz zapisywanie informacji do plików śladu ustawionych na
zakładce Web Site. Wszystkie zgłoszenia HTTP będą powodowały pojawienie się wpisów w plikach śladu serwera
WWW.
u Directory Browsing Allowed. Jeżeli zaznaczymy tę opcję i nie będzie domyślnej strony domowej w przeglądarce
zostanie wyświetlona lista plików i katalogów.
u Index This Directory. Mówi usłudze Index Server, że należy śledzić i indeksować pliki zawarte, w tej witrynie dla
potrzeb przeszukiwania serwera.
u Front Page Web. Oznacza, że ta witryna jest witryną FrontPage lub Visual InterDev i obsługuje rozszerzenia
FrontPage Extensions.

W dolnej części tej zakładki znajdują się ustawienia aplikacji. Aplikacja w rozumieniu Microsoftu to niezależny zbiór stron
Active Server Pages, które współdziałają ze sobą w celu wykonania jakiejś operacji (to jest moja definicja, nie Microsoftu).
455 Rozdział 24. ♦ Konfiguracja serwera WWW dla publikowania w sieci WWW

Przed zmianami w tej części okna upewnij się, że uaktywnione jest prawo do wykonywania skryptów. Umożliwia ono
wykonywanie stron ASP na serwerze i wysyłanie wyników działania do przeglądarki. Widziałem u niektórych ludzi
włączone prawo do wykonywania programów (ponieważ było tak w IIS3), ale jest to absolutnie nieprawidłowe.
Dopuszczenie wykonywania programów jest niezbędne tylko dla katalogów zawierających CGI lub Perl, ale w innych
przypadkach nie powinno się włączać tego prawa. Umieszczenie pliku wykonywalnego w katalogu, w którym możliwe jest
uruchamianie, pozwala na uruchomienie tego programu na serwerze i spowodowanie nieprzewidzianych efektów.

Kliknij przycisk Configuration, aby uruchomić okno zawierające szczegóły wpływające na wydajność i możliwości stron
ASP.

Okno konfiguracji posiada trzy zakładki: App Mappings, App Options oraz App Debugging. Na zakładce App mapings
wymienia się wszystkie typy plików (rozszerzenia) i aplikacje, które są używane do przetwarzania tych plików. Musisz co
najmniej pozostwić

typy .asa i .asp uruchamiane przez ASP.DLL. Na liście znajduje się kilka innych typów plików, ale jeżeli jesteś pewien, że
ich nie używasz, możesz usunąć je z listy, poprawiając nieco wydajność serwera.

Na zakładce App Options można ustawić opcję pozwalającą na ustalanie sesji przez aplikację i określenie czasu, przez jaki
będzie ta sesja utrzymywana (rysunek 24.9). Bądź ostrożny przy modyfikacji tych ustawień, ponieważ mają one drastyczny
wpływ na działanie i wydajność serwera WWW. Większość programistów korzysta z korzyści ustanawiania sesji, jest to
jedna z najlepszych funkcji w ASP. Jeżeli jednak możesz uniknąć stosowania sesji, odczujesz ogromne przyśpieszenie
działania aplikacji.

Rysunek 24.9.
Ustawienia aplikacji
stają się ważne dla
pracy serwera,
gdy coraz lepiej
poznajesz
technologię WWW
firmy Microsoft

Na zakładce tej można również włączyć buforowanie (przyspiesza to działanie aplikacji), uaktywnić ścieżki względne
(pozwala to ASP na rozwijanie ścieżek względnych korzystając z katalogu rodzica) oraz podanie domyślnego języka
skryptów (zwykle jest to VBScript, ale może być JScript). Można również podać wartość limitu czasu dla skryptów.
Zwiększanie tej wartości pozwoli na wykonywanie dłuższych skryptów bez komunikatu błędu, ale niepotrzebnie blokuje
zasoby serwera. Lepiej pozostawić domyślne 60 sekund i podawać dłuższe limity czasu w stronach ASP w razie potrzeby
(<% Server.ScriptTimeout=180 %>).

Ostatnia zakładka, App Debugging, zawiera opcje pozwalające ustalić czy umożliwić debugowanie skryptu na serwerze,
kliencie, po obu stronach lub wyłączyć tę możliwość. Można również wprowadzić własny komunikat błędu wysyłany do
klienta, gdy strona ASP spowoduje błąd. Jest to dobra funkcja, ponieważ lepiej u klienta nie wyświetlać systemowego
komunikatu błędu. Jednak podczas uruchamiania aplikacji wyłącz tę funkcję, ponieważ nie będziesz wiedział, co poszło źle.

Zabezpieczanie aplikacji WWW


Jednym z problemów, z którymi stykają się użytkownicy po zainstalowaniu IIS lub PWS, jest bezpieczeństwo. Jest ono
szczególnie ważne, gdy pisze się aplikację obsługującą handel elektroniczny lub inną zawierającą ważne dane.

Istnieje kilka podstawowych czynności, które powinny być wykonane. Niektóre z nich opisane są później w „ASP/HTML
– położenie i uprawnienia” oraz „Bazy danych – położenie i uprawnienia”. Wymienione tam ustawienia zabezpieczeń są
wymagane dla zapewnienia podstawowego bezpieczeństwa wymaganego dla aplikacji WWW, jednak podane są
dodatkowe czynności, które mogą być podjęte, aby chronić ważne dane i zabezpieczać przed dostępem do witryny przez
niepożądanych ludzi.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 456

Wiele firm uruchamia ściany ognia (ang. firewall) pomiędzy ich serwerami
a Internetem. Takie zabezpieczenie pozwala na uruchomienie szcze-
gółowych zabezpieczeń na to, kto może dostać się do serwera oraz w jaki
sposób. Bardzo często ściany ognia blokują dostęp z zewnątrz do serwerów
dla wszystkich portów poza portem 80 (port HTTP). Pozwala to na
przepuszczenie wywołań HTTP do serwera i uruchomienie aplikacji
WWW, jednak nie pozwala na dostęp do innych nieautoryzowanych
portów.

Opcje, które do tej pory omawialiśmy, i wprowadzone zmiany dotyczą całego serwera. Oprócz zmieniania ustawień dla
całego serwera można ustawić niektóre opcje konfiguracji dla katalogu wirtualnego.

Różnice pomiędzy witryną a katalogiem wirtualnym


Witryna jest oddzielną jednostką na serwerze WWW identyfikowaną przez unikatową nazwę domeny. Internet Information
Server na Windows NT Server dobrze obsługuje wiele witryn na pojedynczym serwerze. Tylko sprzęt ogranicza ilość
witryn, które możesz uruchomić na pojedynczym serwerze.

Katalog wirtualny zawsze zawiera się w witrynie i jest przypisany tylko i wyłącznie do tej witryny. Katalog wirtualny
może mieć własne ustawienia dla WWW, które mogą być różne od ustawień dla reszty witryny, co umożliwia łatwe
zarządzanie zawartością witryny. Przykładowo, jeżeli chcesz uruchamiać CGI w witrynie (nie jest to zalecane ze względów
wydajności, ale możliwe), powinieneś umieścić wszystkie pliki CGI w jednym katalogu wirtualnym i nadać mu prawo
wykonywania programów.

Microsoft FrontPage i Visual InterDev w różny sposób traktują konfigu-


racje katalogów wirtualnych. Jeżeli używasz któregoś z tych narzędzi,
najlepiej pozwolić na stworzenie katalogu wirtualnego przez narzędzie. Po
utworzeniu katalogu przez program nie zmieniaj jego ustawień. Wielu
programistów „zepsuło” swoje witryny przez zmianę ustawień WWW lub
uprawnień plików na witrynach tworzonych przez FrontPage lub Visual
InterDev.

Prawdopodobnie jedną z najlepszych funkcji katalogu wirtualnego jest to, że może być umieszczony gdziekolwiek na
serwerze. Może być również umieszczony na dysku sieciowym mapowanym z innego serwera (wymaga to specjalnych
ustawień konfiguracji, które wykraczają poza ramy tej książki). Więc jeżeli witryna ma adres www.witryna.com, a katalog
wirtualny o nazwie „użytkownik1” umieszczony jest w d:\użytkownik1, będzie on dostępny jako
http://www.witryna.com/uzytkownik1/ nawet, gdy katalog ten jest fizycznie odizolowany od obszaru serwera.

Mimo że katalog wirtualny może znajdować się w dowolnym miejscu,


powinien być umieszczony w drzewie katalogów WWW. Struktura kata-
logów dla aplikacji WWW powinna zostać wcześniej przemyślana. Posia-
danie wielu katalogów wirtualnych rozsianych w różnych miejscach
serwera powoduje duże problemy w utrzymaniu.

Jednym z najbardziej użytecznych zastosowań katalogów wirtualnych jest kontrola dostępu do zawartości WWW. Załóżmy,
że mamy serwis WWW położony w d:\wwwroot\. Masz również dwóch współpracowników, którzy chcą mieć własne
fragmenty serwera, którymi będą zarządzać sami. Niezależnie od tego, czy będą mieli dostęp do swoich katalogów poprzez
dysk sieciowy, czy FTP, trudno jest zabezpieczyć się przed możliwością uzyskania przez nich dostępu do głównego
obszaru serwera, jeżeli tylko utworzysz katalogi d:\wwwroot\user1\ i d:\wwwroot\user2\.

Jednym ze sposobów poprawienia bezpieczeństwa i ograniczenia dostępu użytkowników tylko do ich plików, jest utworzenie
katalogów d:\wwwroot\user1\ i d:\wwwroot\user2\ i przypisanie katalogów wirtualnych do tych obszarów.

Kolejną świetną funkcją katalogów wirtualnych jest funkcja dostępna tylko na Windows NT, możliwość podania punktu
startowego dla aplikacji. Pozwala to na odizolowanie zmiennych sesji i aplikacji oraz całkowite odizolowanie od innych
aplikacji WWW nawet, gdy znajdują się na jednym serwerze.
457 Rozdział 24. ♦ Konfiguracja serwera WWW dla publikowania w sieci WWW

Mimo że możesz tworzyć aplikacje WWW na Windows 95/98, nie ma sposobu na tworzenie wielu aplikacji i korzystanie z
ich izolacji, tak jak można to zrobić na Windows NT. Na serwerze WWW pracującym w Windows 95/98 wszystkie strony
udostępniane przez PWS traktowane są jako jedna aplikacja WWW. Zmienne sesji tworzone w katalogu wirtualnym na
Windows 95/98 są dostępna dla wszystkich katalogów wirtualnych tej witryny. Jeżeli chcesz uruchamiać wiele aplikacji
WWW na jednym serwerze, jest to jeszcze jeden powód, aby użyć Windows NT.

Wywołując okno właściwości katalogu wirtualnego na Windows NT, można ustawić opcje w inny sposób niż dla reszty
witryny. Wszystkie opcje wymienione we wcześniejszej części rozdziału dostępne są również dla katalogu wirtualnego.
Powoduje to większą elastyczność i zarządzanie pojedynczymi aplikacjami WWW i pozwala na ustawianie
specyficznych opcji, które mogą być niezbędne w jednej aplikacji a niepotrzebne w innej.

Na zakładce Home Directory mamy możliwość utworzenia aplikacji w katalogu wirtualnym, którego właściwości właśnie
oglądamy. Po wskazaniu tego katalogu jako aplikacji będzie ona pracować niezależnie od reszty witryny. Znaczy to, że ta
aplikacja posiada własny plik global.asa oraz oddzielną konfigurację. Wszystkie sesje oraz zmienne globalne aplikacji
dostępne są tylko i wyłącznie w tej aplikacji. Próba dostępu do tych zmiennych spoza bieżącej aplikacji, nawet z tego
samego serwera, nie powiedzie się. Umożliwia to izolację i podwyższony poziom bezpieczeństwa.

Globalny plik global.asa powinien być umieszczony w katalogu będącym


punktem startowym aplikacji. Jeżeli zadeklarowałeś katalog wirtualny jako
aplikację, plik global.asa powinien znajdować się w fizycznym katalogu,
który zdefiniowałeś jako katalog startowy katalogu wirtualnego.

Jeżeli potrzebujesz jeszcze większej izolacji, możesz zażądać, aby aplikacja pracowała w oddzielnej przestrzeni pamięci.
Uaktywnienie tej funkcji wymaga od serwera WWW przełączania kontekstu i może mieć negatywny wpływ na wydajność
systemu. Korzyścią tego rozwiązania jest to, że aplikacja żądająca takiego traktowania jest izolowana i jej awaria nie
wpłynie na inne aplikacje pracujące na tym samym serwerze.

Czy teraz, gdy mamy zainstalowany serwer WWW i wiemy jak go skonfigurować, jest już wszystko gotowe? Nie do
końca. Jest jeszcze kilka punktów, o których musisz wiedzieć i brać pod uwagę podczas tworzenia i udostępniania aplikacji
WWW. Mimo że ustawiłeś podstawowe opcje w trakcie przygotowywania aplikacji, musisz zwrócić uwagę na środowisko
poza ustawieniami WWW. Jednym z ważniejszych zagadnień jest bezpieczeństwo oraz właściwe ustawienie aplikacji, aby
miała dostęp do odpowiednich plików i źródeł danych.

Co to jest IUSER ?
W trakcie instalacji IIS/PWS na Windows NT tworzone jest nowe konto użytkownika o nazwie
IUSER_<nazwa_komputera>, gdzie <nazwa_komputera> jest nazwą NetBios nadana serwerowi (w oknie właściwości
sieci).

Gdy ktoś chce obejrzeć stronę WWW, a na serwerze IIS uaktywniony jest anonimowy dostęp, IIS na początku sprawdza
prawo NTFS do odczytu pliku przez użytkownika IUSER. Jeżeli IUSER posiada wystarczające prawa do oglądania tej
strony, jest ona wysyłana do przeglądarki. Jeżeli IUSER nie ma odpowiednich praw do tego pliku lub IIS nie pozwala na
anonimowy dostęp, IIS spróbuje autoryzować użytkownika zgodnie z ustawieniami w MMC.

Typ systemu plików


Mimo że IIS posiada kilka zaszytych w sobie opcji zapewniających niewielki poziom bezpieczeństwa witryny, jest on
niewystarczający dla większości wypadków bez wsparcia ze strony zabezpieczeń Windows NT. Gorąco polecamy użycie
Windows NT File Sysem (NTFS) na partycji zawierającej pliki witryny WWW oraz bazę danych. Pozwala to na
uaktywnienie zabezpieczeń na poziomie dostępu do plików i katalogów, co jest jedyną drogą zabezpieczenia serwera
produkcyjnego.

NTFS jest dostępny tylko na Windows NT. Jeżeli tworzysz aplikację na


Windows 95/98, nie będziesz mógł utworzyć tak szczelnego systemu
bezpieczeństwa, jaki można utworzyć na Windows NT. Jest to jeszcze
jeden powód umieszczenia gotowej aplikacji na Windows NT.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 458

Struktura katalogów i wymagane uprawnienia


Standardowa konfiguracja komputera na serwer WWW posiada dwie partycje, jedna mała (około 1 GB) na system
operacyjny i druga na wszystkie związane z WWW pliki oraz pliki śladu. Rodzaj systemu plików użytego dla partycji
systemowej jest zależny od upodobań, ale prawie zawsze partycja zawierająca witrynę WWW posiada system plików
NTFS w celu zapewnienia odpowiedniego poziomu bezpieczeństwa.

W trakcie instalacji IIS wprowadza się ścieżkę do głównego katalogu WWW. Zakładając, że znajduje się ona na drugiej
partycji, domyślną ścieżką jest d:\inetpub\wwwroot\. Jest to obszar, do którego IIS będzie kierował wszystkie żądania
WWW, chyba że konfiguracja została zmodyfikowana. Gdy spojrzysz na właściwości tego katalogu przy użyciu MMC,
zauważysz, że wszystkie przydziały adresów IP są ustawione na „nieprzydzielone”, więc nawet, gdy posiadasz wiele
adresów IP na serwerze, wszystkie żądania kierowane będą do tego katalogu. Upraszczając, przyjmiemy, że na serwerze
znajduje się jedna witryna umieszczona w katalogu d:\inetpub\wwwroot.

ASP/HTML – położenie i uprawnienia


Zakładamy, że posiadasz ogólną wiedzę na temat uprawnień w NT i szybko prześledzimy wymagania dla IIS.

Aby obejrzeć dokument HTML, użytkownik IUSER musi mieć co najmniej prawo czytania pliku. Do obejrzenia
dokumentu Active Server Pages, użytkownik musi posiadać, co najmniej prawo uruchamiania tego pliku. Jeżeli przypisałeś
użytkownikowi prawo czytania tego pliku (rysunek 24.10), odpowiednim prawem NT, które należy przydzielić, jest prawo
Read & Execute (RX). Gdy mówimy o prawach Read & Execute, mamy na myśli najniższy poziom uprawnień NT, które
znajdują się w oknie specjalnych uprawnień pliku lub katalogu (rysunek 24.11). Mimo że pozwala to na dostęp zarówno do
stron HTML oraz ASP, nie jest to niezbędne ani najbardziej bezpieczne rozwiązanie, jeżeli bezpieczeństwo jest
priorytetem.
Rysunek 24.10.
NTFS na Windows
NT posiada niektóre
domyślne
ustawienia praw,
które w większości
przypadków
spełniają wymagania
bezpieczeństwa

Rysunek 24.11.
Jeżeli potrzebujesz
lepszej kontroli
uprawnień do pliku,
możesz zejść
do specyficznych
uprawnień używając
specjalnych
uprawnień do pliku
459 Rozdział 24. ♦ Konfiguracja serwera WWW dla publikowania w sieci WWW

Bazy danych – położenie i uprawnienia


Jeżeli używasz Active Server Pages, aby podłączyć się do bazy danych Accessa, baza danych nie musi znajdować się w
głównym katalogu witryny WWW. Ponieważ ścieżka jest podana w ciągu połączenia, możesz umieścić ją w dowolnym
miejscu. Ze względów bezpieczeństwa zaleca się umieścić bazę danych w katalogu, który jest odizolowany od plików
WWW. D:\databases\ jest świetnym rozwiązaniem. Uniemożliwia to złośliwym klientom wpisanie
http://www.witryna.com/baza/bazadanych.mdb i zapisanie pliku bazy danych na swoim komputerze.

Zabezpieczenie bazy danych może wydawać się pełne sztuczek, gdy nie zna się kilku szczegółów. Istnieją dwa sposoby
zabezpieczenia bazy danych, poprzez wbudowany w Access system zabezpieczeń lub poprzez ustawienie praw NTFS do
pliku.

Jeżeli posiadasz aplikację, która tylko odczytuje informacje i nigdy nie wprowadza informacji do bazy, sprawa jest prosta.
Nadaj użytkownikowi IUSER tylko prawo do czytania pliku bazy danych. Jeżeli teraz nie robisz nic poza czytaniem z bazy,
prawdopodobnie nie potrwa to długo. Jedną z największych korzyści aplikacji WWW jest dynamiczne wyświetlanie
informacji użytkownikom, jednak to tylko połowa sukcesu. Możliwość dopisywania danych do bazy przyniesie wiele
korzyści. Można zapisywać zwrotne informacje od użytkowników, informacje z listy dyskusyjnej, bieżące zamówienia i
inne dane. Pozwala to użytkownikom na lepszą interakcję z witryną i pomaga na lepsze obsłużenie klientów.

Załóżmy, że mamy bazę danych do zbierania zamówień przez sieć. Po ustawieniu uprawnień do zapisu i odczytu próba
zapisu do bazy kończy się niepowodzeniem. Gdy baza jest używana przez użytkownika, który ma prawo do zapisu, tworzy
on plik blokad. Ponieważ użytkownik IUSER posiada takie prawo, Access próbuje utworzyć plik i powoduje błąd
niedozwolonego dostępu. Aby nie występował ten błąd, użytkownik IUSER musi posiadać prawo do zmiany zawartości w
katalogu, w którym znajduje się baza danych. Prawo do zmian jest niezbędne, ponieważ plik blokad musi być uaktualniany
przy każdym wykonaniu polecenia SQL. Prawa do tworzenia i czytania nie wystarczą.

Jeżeli nie przeniosłeś bazy danych do osobnego katalogu, zaczyna to wyglądać źle. Jeżeli masz bazę danych w drzewie
katalogów witryny WWW, użytkownik IUSER musi posiadać prawa do czytania, zapisu i usuwania w katalogu bazy
danych, co jest BARDZO ZŁYM rozwiązaniem. We wczesnych etapach naszych eksperymentów z bazami danych,
aplikacjami WWW i wymaganiami bezpieczeństwa, jeden z autorów i ja zrobiliśmy tak, jak to opisałem wcześniej. Nie
czekaliśmy zbyt długo na hakera, który zauważył, że witryna jest dla niego szeroko otwarta i dokonał zmian w naszych
plikach.

Jeżeli używasz serwera SQL, system bezpieczeństwa jest zapewniany przez serwer bazy, co pozwala na uniknięcie
potencjalnych problemów przy zarządzaniu zabezpieczeniami na poziomie plików.
Rozdział 25.
Przenoszenie Accessa 2000
do sieci WWW
za pomocą komponentów sieciowych
Office
W tym rozdziale:
u Czym są komponenty sieciowe Office.
u Użycie formantu Office Arkusz.
u Użycie formantu Office Wykres.
u Użycie formantu Office Tabela przestawna.

Jak już wiesz, w obecnych czasach nie ignoruje się Internetu. Microsoft poszukiwał dla Office 2000 prostej metody przeniesienia
możliwie wiele z podstawowych możliwości Office 2000 do Internetu. Rezultatem prac są komponenty sieciowe Office 2000
oraz strony dostępu do danych (opisane w rozdziale 26., „Użycie stron dostępu do danych”). W tym rozdziale przedstawione
zostanie wprowadzenie do komponentów sieciowych Office.

Czym są komponenty sieciowe Office


Komponenty sieciowe Office są zbiorem formantów ActiveX opartych na technologii COM, dostarczających niektóre
podstawowe funkcje arkusza, wykresu i tabeli przestawnej, zawarte w Office, dla przeglądarki internetowej obsługującej
technologię ActiveX. W Office 2000 komponenty sieciowe składają się z:
u Formantu Office Arkusz;
u Formantu Office Wykres;
u Formantu Office Tabela przestawna.

Te trzy formanty graficzne (Spreadsheet, Chart oraz PivotTable) oraz formant DataSource są oparte o COM, więc
mogą być używane przez VBScript, JScript, VB, C++, Java oraz oczywiście VBA. To, że są one nazwane komponentami
sieciowymi, nie oznacza, że są dostępne tylko na stronach WWW. Mogą również spełniać ważną rolę w aplikacjach
Accessa. Rysunek 25.1 przedstawia prosty arkusz kalkulacyjny umieszczony na formularzu Accessa.
461 Rozdział 25. ♦ Przenoszenie Access’a 2000 do sieci WWW

Rysunek 25.1.
Komponent sieciowy
Office umieszczony
na formularzu
Accessa

Co potrafią komponenty sieciowe Office


Każdy komponent posiada inne funkcje, które można użyć w aplikacji. Formant Arkusz to mini Excel do wbudowania w
stronę WWW lub formularz. Posiada on większość podstawowych funkcji Excela, jak przeliczanie, filtrowanie czy
sortowanie. Możesz użyć formantu Arkusz jako niewidocznej maszyny liczącej w aplikacji Accessa, VB lub WWW.
Wykres umożliwia tworzenie dwuwymiarowych wykresów i posiada możliwość łączenia z innymi elementami HTML jak
formant Arkusz lub źródło danych. Wykres pozwala również na eksport rysunków GIF dla przeglądarek WWW, które nie
obsługują formantów ActiveX. Formant Tabela przestawna udostępnia funkcję tworzenia tabel przestawnych dostępną w
Excelu, poprzez formant ActiveX. Tabela przestawna tak jak Wykres potrafi również eksportować pliki GIF. Dostępny jest
również formant DataSource, który nie posiada postaci graficznej. DataSource działa analogicznie do formantu Data w
Visual Basicu. Łączy się on z bazą danych i pozwala innym formantom na dołączenie się do niego. Każdy z wymienionych
formantów zostanie bliżej omówiony w następnym rozdziale.

Wymagane licencje
na użycie komponentów sieciowych
W przeciwieństwie do formantów ActiveX, komponenty sieciowe wymagają zakupienia licencji Office 2000 dla każdego
komputera klienta. Użytkownicy nie muszą mieć zainstalowanego pakietu Office 2000, jednak muszą mieć na niego
licencję. Jeżeli pracujesz w dużej firmie i chcesz użyć komponentów sieciowych oraz stron ADP (opisane w następnym
rozdziale), możesz skorzystać z licencji typu site i rozprowadzać komponenty sieciowe jeszcze przed zainstalowaniem
Office 2000.

Użycie formantu Office Arkusz


Użycie formantu Arkusz jest podobne do użycia Excela. Można go stosować na dwa sposoby, w formie związanej i
niezwiązanej. Forma związana wymusza użycie formantu DataControl, który omówimy w następnym rozdziale. Tutaj
zajmiemy się użyciem formantu w postaci niezwiązanej.

Rozpoczynamy
Excel 2000 posiada funkcję radykalnie ułatwiającą użycie formantu Arkusz, jest to automatyczne przenoszenie arkusza
Excela do postaci strony WWW. W Excelu 2000 utwórz prosty arkusz. Następnie wybierz z głównego menu Plik, Zapisz
jako stronę sieci Web. Na ekranie pojawi się okno dialogowe pokazane na rysunku 25.2. Okno to pozwala na wybór
zakresu lub eksport całego arkusza. Jeżeli chcesz zapisać dane do interaktywnej strony WWW, musisz zdefiniować swoje
dane jako zakres w Excelu. Aby wyeksportować wybrany zakres do formantu Arkusz na stronie WWW, zaznacz pole wy-
boru Dodaj interakcję (rysunek 25.2).
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 462

Rysunek 25.2.
Okno Zapisz jako
stronę sieci Web

Po zapisaniu arkusza jako strony WWW przez Excela możesz otworzyć wynikową stronę w przeglądarce Internet Explorer
(rysunek 25.3).

Po otwarciu strony WWW możesz kliknąć prawym klawiszem myszy formant i otworzyć Przybornik właściwości (rysunek
25.4). Okno to utworzone w Dynamic HTML pozwala na formatowanie i zarządzanie układem formantu Więcej informacji na
temat użycia tego formantu w sieci WWW znajduje się w następnym rozdziale.
Rysunek 25.3.
Wynika zapisu
arkusza Excela 2000
jako strony WWW

Rysunek 25.4.
Okno przybornika
właściwości arkusza

Użycie formantu w Accessie


Aby wstawić formant Arkusz na formularz Accessa, z głównego menu wybierz Wstaw, Formant ActiveX. Otworzy się
okno dialogowe Wstawianie formantu ActiveX (rysunek 25.5). Przewiń listę dostępnych formantów do Arkusz pakietu
Microsoft Office 9.0 i kliknij OK. Spowoduje to wstawienie formantu do formularza w trybie projektowania (rysunek
25.6).

Po wstawieniu formantu na formularz należy napisać procedurę pobierającą dane do arkusza w trakcie ładowania
formularza. Wydruk 26.1 zawiera procedurę obsługi zdarzenia Load formatki. Procedura otwiera recordset ADO oparty
o kwerendę „Dziesięć najdroższych produktów” w bazie danych Northwind. Następnie przegląda wynik. Dla każdego
wiersza użyta jest domyślna właściwość ActiveCell w celu wstawienia danych z wyniku kwerendy do komórek
arkusza. W trakcie przesuwania się w wyniku należy zwiększać właściwość ActiveCell, aby wstawić dane do kolejnych
wierszy arkusza. Jak widać, jest to podobne do programowania w Excelu.

Po wstawieniu zmień nazwę formantu na Spreadsheet1 w oknie właściwości.


463 Rozdział 25. ♦ Przenoszenie Access’a 2000 do sieci WWW

Rysunek 25.5.
Okno dialogowe
Wstawianie
formantu ActiveX

Rysunek 25.6.
Formant Arkusz na
formularzu Accessa
w trybie edycji

Wydruk 25.1. Ładowanie danych do formantu Arkusz w trakcie pracy programu


Private Sub Form_Load()
'Ładuje do formantu ActiveX Arkusz
'dane pochodzące z kwerendy z Accessa

Dim rst As ADODB.Recordset


Dim intCount As Integer

On Error GoTo Proc_Err

Set rst = New ADODB.Recordset


rst.Open "[Ten Most Expensive Products]", CurrentProject.Connection

' Wpisywanie nagłówków


Spreadsheetl.ActiveCell(1, 1) = "Produkt"
Spreadsheetl.ActiveCell(1, 2) = "Cena"

' Inicjuj licznik pętli


intCount = 2

Do Until rst.EOF
' Wypełnij bieżącą komórkę zawartością rekordu
Spreadsheetl.ActiveCell(intCount, 1) = "" & _
rst!TenMostExpensiveProducts
Spreadsheetl.ActiveCell(intCount, 2) = "" & _
rst!UnitPrice
' Przejdź do kolejnego rekordu i zwiększ wartość licznika
rst.MoveNext
intCount = intCount + 1
Loop

rst.Close
Set rst = Nothing

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Użycie formantu Office Wykres


Mogłeś pomyśleć, że straciłeś zbyt dużo czasu, zajmując się programem Microsoft Graph. Formant Wykres jest prosty do
użycia i bardzo potężny. Jak inne formanty, może być użyty w trybie związanym i niezwiązanym. Teraz zajmiemy się
użyciem formantu w trybie niezwiązanym, natomiast tryb związany zostanie omówiony w następnym rozdziale.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 464

Dodatkowo w rozdziale 27. „Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages” przedstawimy, jak
używać tego komponentu do eksportowania rysunków GIF używanych w ASP.

Rozpoczynamy
Tak jak w przypadku formantu Arkusz rozpoczniemy od utworzenia prostego wykresu w Microsoft Excel 2000,
pokazanego na rysunku 25.7. Wybierz Plik, Zapisz jako stronę sieci Web, a następnie wybierz Zaznaczenie: Wykres oraz
zaznacz pole wyboru Dodaj interakcję. Wynik jest pokazany na rysunku 25.8. Można manipulować takim wykresem za
pomocą skryptów uruchamianych na komputerze klienta np.VBScript lub JScript. Aby używać formantu w skryptach,
musisz znać właściwości i metody, jakie udostępnia formant. Omówimy je w dalszej części rozdziału.

Rysunek 25.7.
Wykres w Microsoft
Excel 2000

Rysunek 25.8.
Formant Wykres
wyeksportowany
jako strona WWW

Użycie formantu w Accessie


Wstaw formant na formularz Accessa przy użyciu Wstaw, Formant ActiveX. Musisz wybrać z listy formantów ActiveX
„Wykres pakietu Microsoft Office 9.0”. Po utworzeniu formantu zmień jego nazwę na Chart1 w oknie właściwości. Gdy
używasz formantu Wykres w trybie niezwiązanym musisz pamiętać o dwóch ważnych sprawach. Po pierwsze, formant
Wykres może przechowywać wiele obiektów, więc każdy utworzony wykres będzie częścią kolekcji Charts. Po drugie,
możesz wypełnić tablice wartości dla serii wykresów i tablicę wartości dla danych serii wykresów.

Aby to przedstawić, stworzyłem prostą kwerendę przestawną w demonstracyjnej bazie danych Northwind, za pomocą
następującego wyrażenia SQL:
TRANSFORM Sum(CCur([Order Details].[UnitPrice]*
[Quantity]*(1-[Discount])/100)*100) AS ProductAmount
SELECT Year([OrderDate]) AS OrderYear
FROM Products INNER JOIN (Orders INNER JOIN
[Order Details] ON Orders.OrderID = [Order Details]
ON Products.ProductID = [Order Details].ProductID
WHERE (((Orders.OrderDate)
Between #1/1/1997# And #12/31/1997#))
GROUP BY Year([OrderDate])
PIVOT "Qtr " & DatePart("q",[OrderDate],1,0)
465 Rozdział 25. ♦ Przenoszenie Access’a 2000 do sieci WWW

In ("Qtr 1","Qtr 2","Qtr 3","Qtr 4");

Podane wyrażenie SQL dzieli całkowitą sprzedaż na kwartały i wylicza wynik pokazany na rysunku 25.9.

Rysunek 25.9.
Prosta kwerenda
przestawna
w Accessie 2000

Teraz skorzystamy z utworzonej kwerendy przestawnej, aby utworzyć niezwiązany wykres w procedurze obsługi zdarzenia
Open formularza. Utworzona została tablica aHeaders, wypełniona nazwami nagłówków dla serii (w tym przypadku
czterema kwartałami roku podatkowego). Następnie otwierany jest recordset ADO oparty o zapisaną kwerendę
przestawną nazwaną qryQuarterlySales i wypełniana jest tablica aValues wartościami pól z wyniku kwerendy. Cały
tekst procedury przedstawiony jest na wydruku 25.2.

Wydruk 25.2. Tworzenie niezwiązanego wykresu


Private Sub Form Open(Cancel As Integer)
'Ładuje do formantu ActiveX Wykres
'dane pochodzące z kwerendy z Accessa

Dim ChartSpace1, aHeaders(3), aValues(3)


Dim rst As ADODB.Recordset

On Error GoTo Proc_Err

Set rst = New ADODB.Recordset

' Tworzenie tablicy elementów dla wykresu


aHeaders(0) = "Q1"
aHeaders(1) = "Q2"
aHeaders(2) = "Q3"
aHeaders(3) = "Qq"

' Otwarcie recordsetu opartego o kwerendę XTAB


' i wypełniamy wartości dla słupków wykresu
rst.Open "qry0uarterlySales", CurrentProject.Connection
aValues(0) = rst![Otr 1]
aValues(1) = rst![Qtr 2]
aValues(2) = rst![Otr 3]
aValues(3) = rst![Otr 4]

Set ChartSpace1 = Me.Chart1

With ChartSpace1
.Border.Color = chColorAutomatic
' Można mieć więcej niż jeden wykres w
' obszarze wykresu, więc należy odwołać się do kolekcji
.Charts.Add
With .Charts(0)
.Type = chChartTypeColumnClustered
.SeriesCollection.Add
.SeriesCollection(0).Caption = "Sprzedaż w 1999"
' Wiązanie danych do wcześniej stworzonych tablic
.SeriesCollection(0).SetData _
chDimCategories, chDataLiteral, aHeaders
.SeriesCollection(0).SetData _
chDimValues, chDataLiteral, aValues
.HasLegend = True
End With

End With

rst.Close
Set rst = Nothing

Proc_Exit:
Exit Sub
Proc_Err:
MsgBox Err.Description
Resume Proc_Exit
End Sub

Użycie formantu Office Tabela przestawna


Tak jak w przypadku dwóch formantów przedstawionych w tym rozdziale, Tabela przestawna może być używana w trybie
związanym i niezwiązanym. Dalsza część rozdziału przedstawi sposób użycia formantu w trybie niezwiązanym, natomiast w
następnym rozdziale przedstawimy sposób wiązania formantu do danych na stronie dostępu do danych.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 466

Rozpoczynamy
Tabele przestawne są jedną z najpopularniejszych funkcji programu Microsoft Excel. Dają one możliwość tworzenia od
ręki raportów w Excelu. Wielu użytkowników staje się entuzjastami tabel przestawnych po nauczeniu ich tworzenia.
Możliwość tworzenia tabel przestawnych i użycia ich jako część witryny WWW lub formularza Accessa jest świetną
możliwością.

Zacznij od stworzenia tabeli przestawnej w Excelu 2000 w sposób pokazany na rysunku 25.10.

Rysunek 25.10.
Prosta tabela
przestawna
w Excelu 2000

Po utworzeniu tabeli przestawnej wybierz Plik, Zapisz jako stronę sieci Web, jednak zamiast kliknąć Zapisz w oknie
dialogowym kliknij Opublikuj. Uruchomiony zostanie zaawansowane okno dialogowe Publikowanie jako strony sieci Web
(rysunek 25.11).

Okno pokazane na rysunku 25.11 pozwala na wybranie do wyeksportowania elementów tabeli przestawnej i ustawienie
opcji widoku. Ustawiając opcje widoku, można wybrać opcję tabeli przestawnej. Excel utworzy stronę WWW pokazaną na
rysunku 25.12.
Rysunek 25.11.
Okno dialogowe
Publikowanie
jako strony
sieci Web

Rysunek 25.12.
Tabela przestawna
Excela
wyeksportowana
do przeglądarki
Internet Explorer
Rozdział 26.
Użycie stron dostępu do danych
W tym rozdziale:
u Tworzenie pierwszej strony dostępu do danych
u Tworzenie interaktywnych odnośników
u Łączenie komponentów sieciowych Office z DAP
u Skrypty w stronach dostępu do danych

Jak chyba zauważyłeś, obecnie nie ignoruje się Internetu. Tworząc Office 2000 przedstawiciele Microsoftu, poszukiwał
prostej metody przeniesienia maksymalnie dużo możliwości Office do Internetu. Wynikiem tych prac są strony dostępu do
danych (DAP – Data Access Pages) oraz komponenty sieciowe Microsoft Office 2000. Rozdział ten przedstawia możliwości
stron dostępu do danych na podstawie przykładowych stron DAP.

Prawdopodobnie zapoznałeś się już z Internetem lub firmowym Intranetem oraz utworzyłeś kilka prostych stron dla
użytkowników Twoich programów. Coraz częściej użytkownicy pytają Cię o możliwość oglądania wykresów, diagramów,
odnośników oraz utworzenia bardziej interaktywnych, dynamicznych stron WWW. Odpowiadasz, że jesteś specjalistą od baz
danych, a nie od programowania dla WWW oraz, że szybkie zrealizowanie tych pomysłów jest bardzo trudne. Projektanci
z Microsoftu uświadomili sobie, że użytkownicy chcą więcej możliwości w tworzeniu raportów w sieci i stworzyli
w Accessie 2000 mechanizm zwany stronami dostępu do danych.

Czym są strony dostępu do danych?


Prawdopodobnie zauważyłeś nową pozycję w oknie bazy danych nazwaną Strony. Jest to miejsce na nowe obiekty bazy danych
zwane stronami dostępu do danych (DAP). Rysunek 26.1 przedstawia okno bazy danych otwarte na pozycji Strony. DAP to pod-
zbiór raportów i formularzy Accessa zaprojektowanych do pracy w sieci, a dokładniej w Intranecie. Strony te są zapisane jako
Dynamic HTML i mogą być oglądane w Internet Explorer 5.0 lub późniejszych. Strona taka podłącza się do pracującej bazy
danych i daje możliwość wprowadzania do bazy danych z formularza lub tworzenia raportu z bazy danych.

Rysunek 26.1.
Nowa sekcja w oknie
bazy danych
zawierająca strony
dostępu do danych

Architektura oraz wymagania stron dostępu do danych


Strony dostępu do danych używają formantów ActiveX, dynamicznego HTML, ADO oraz skryptów wykonywanych po stronie
klienta. Używając skryptów wykonywanych po stronie klienta, musisz mieć zainstalowane na stacjach roboczych ADO i
dostawcę OLEDB dla Accessa i serwera SQL. Formaty ActiveX są obsługiwane tylko przez Internet Explorer 4.0 oraz 5.0,
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 468

więc jesteś ograniczony tylko do przeglądarek Microsoftu. Dodatkowo Microsoft wymaga licencji na Office 2000 do
używania stron dostępu do danych.

Jedyną gwarancją poprawnej instalacji formantów sieciowych, ADO 2.1 oraz właściwych sterowników i dostawców
OLEDB jest instalacja Office 2000.

Tworzenie Twojej pierwszej strony dostępu do danych


Rozpocznijmy tworzenie naszej pierwszej strony dostępu do danych. Przełącz okno bazy danych na Strony i wybierz Nowy.
Następnie wybierz Widok projektu. Na ekranie pojawi się pusta strona w widoku projektu (rysunek 26.2).

Zatytułuj stronę poprzez kliknięcie w górnej części strony i wpisanie „Kategorie”. Wywołaj listę pól, wybierając z menu
Widok, Lista pól. Lista pól pokazana jest na rysunku 26.3. Zawiera ona wszystkie tabele i kwerendy w bieżącej bazie
danych. Lista ta działa jak lista pól w typowym formularzu lub raporcie.

Po wyświetleniu listy pól przejdź do tabeli Categories i przeciągnij pola CategoryName oraz Description na stronę.
Rysunek 26.2.
Pusta strona dostępu
do danych w widoku
projektu

Rysunek 26.3.
Lista pól na stronie
dostępu do danych

Teraz, po dodaniu pól do strony, kliknij przycisk Zapisz z paska narzędzi, lub wybierz z menu Plik – Zapisz. Zauważ, że
jest wyświetlone okno dialogowe Zapisz jako stronę dostępu do danych (rysunek 26.4). Strony dostępu do danych nie są
zapisywane w pliku MDB jak inne obiekty bazy danych takie jak: tabele, kwerendy, formularze, raporty, makra i moduły.
Aby szybko sprawdzić położenie DAP, umieść kursor myszy nad nazwą DAP i poczekaj chwilę (rysunek 26.5).

Musisz pamiętać, że DAP nie są przechowywane w pliku MDB. Sprawia to


wiele kłopotów podczas rozprowadzania aplikacji. Musisz rozprowadzać
plik MDB wraz z wszystkimi utworzonymi stronami dostępu. Oprócz tego
musisz utrzymywać zgodność między ADP na dysku i informacją zapisaną
w bazie. Możesz jednak zmienić to ograniczenie w korzyść, jeżeli
umieścisz DAP na serwerze WWW. Dopóki użytkownicy mają dostęp do
serwera WWW poprzez Internet lub Intranet, możesz umieścić pliki DAP
na serwerze WWW.
469 Rozdział 26. ♦ Użycie stron dostępu do danych

Rysunek 26.4.
Zapisz jako stronę
dostępu do danych

Rysunek 26.5.
Podpowiedź
pokazująca ścieżkę
do strony dostępu
do danych

Zanim skupimy się na stronach dostępu do danych, przyjrzyjmy się funkcji Sortowanie i Grupowanie. Wybierz Widok,
Sortowanie i grupowanie z głównego menu. Wyświetlone zostanie okno dialogowe Sortowanie i grupowanie (rysunek
26.6).

Rysunek 26.6.
Okno dialogowe
Sortowanie
i grupowanie
w stronach dostępu
do danych

Większość z właściwości jest identyczna jak te używane w raportach, jednak są dwie, na które powinieneś zwrócić uwagę.
Pierwszą właściwością jest rozmiar strony danych. Określa ona ilość rekordów wyświetlanych na jednej stronie. Ustawimy
ten parametr na 1. Możesz eksperymentować tym parametrem, aby wyświetlić więcej rekordów. Drugą właściwością, z
którą powinieneś się zapoznać, jest: Sekcja nawigacji między rekordami. Ustawienie tej właściwości na Tak doda do strony
taką właśnie sekcję.

Po ustawieniu tych właściwości możemy zająć się formatowaniem strony. Aby formatować stronę dostępu do danych,
wybierz z menu Format, Motyw, co spowoduje wyświetlenie okna dialogowego Motyw (rysunek 26.7).
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 470

Rysunek 26.7.
Okno dialogowe
Motyw

Oglądanie strony dostępu do danych


Gotową stronę można oglądać na dwa sposoby: jako część aplikacji Accessa lub w przeglądarce WWW. Aby oglądać stronę
w Accessie, kliknij ikonę Widok strony lub wybierz z menu Widok, Widok strony, będąc w trybie projektowania. Jeżeli chcesz
wyświetlić stronę w aplikacji Accessa, użyj metody OpenDataAccessPage obiektu DoCmd:
DoCmd.OpenDataAccessPage "Kategorie", acDataAccessPageBrowse

Rysunek 26.8 przedstawia pokazuje stronę dostępu do danych w Accessie. Należy zauważyć, że można używać strony
dostępu do danych w aplikacji identycznie jak formularza czy raportu.

Można również oglądać stronę DAP w odpowiedniej przeglądarce WWW. Należy po prostu otworzyć odpowiedni plik
HTML z dysku lub serwera WWW. Rysunek 26.9 przedstawia stronę DAP otwartą w przeglądarce WWW.
Rysunek 26.8.
Strona dostępu do
danych wyświetlona
w Accessie
471 Rozdział 26. ♦ Użycie stron dostępu do danych

Rysunek 26.9.
Strona dostępu do
danych wyświetlona
w Internet
Explorerze

Zauważmy, że strony DAP wyglądają tak samo w przeglądarce jak i w Accessie. Nie tracimy żadnych możliwości.
przenosząc stronę z Accessa na stronę WWW. Oglądając stronę w przeglądarce, spróbujmy zmienić dane i przesunąć się
do kolejnego rekordu.

Można zauważyć, że dane pobierane są z bazy danych, a zmiany zostały do niej wprowadzone. Jeżeli utworzysz swoją
aplikację w oparciu o strony dostępu do danych zamiast w oparciu o formularze i raporty, możesz ją łatwo przenieść do
sieci WWW.

Tworzenie interaktywnych odnośników


Potężną opcją w stronach dostępu do danych jest możliwość tworzenia odnośników opartych o relacje jeden – do – wielu
zdefiniowane w bazie danych. Utworzymy teraz odnośnik, oparty o relację jeden do wielu z Categories do Products,
na naszej stronie Kategorie. Otwórz stronę i wyświetl w przedstawiony wcześniej sposób listę pól dostępnych w bazie
danych. Przenieś pola z tabeli Products: ProductName, UnitPrice oraz Discontinued na dół strony. Access utworzy
nową sekcję, która będzie sekcją odnośnika (rysunek 26.10).

Rysunek 26.10.
Podrzędna sekcja
odnośnika dla tabeli
Products w trybie
projektowania

Mimo że Microsoft wymaga przestrzegania standardów Windows w apli-


kacjach, które chcą używać logo Windows, jednak sam ich nie dotrzymuje.
Strony dostępu do danych nie posiadają funkcji Cofnij.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 472

W trybie projektowania pojawił się przycisk ze znakiem +. Wyświetla on dane odnoszące się do bieżącego rekordu. Można
umieścić go w dogodnym miejscu, np. na dole sekcji.

Wróćmy jeszcze raz do okna Grupowanie i sortowanie. Ustaw dla sekcji Categories rozmiar strony danych na 1, a dla
sekcji Products na Wszystko, oraz Sekcja nawigacji między rekordami dla Products na Nie.

W wyniku dostaniemy stronę, która przedstawia wszystkie produkty danej kategorii (rysunek 26.11).
Rysunek 26.11.
Sekcja odnośnika
dla produktów
na stronie dostępu
do danych

Łączenie komponentów sieciowych Office z DAP


Potężną opcją w stronach dostępu do danych jest możliwość umieszczania na nich komponentów sieciowych Office, które
są połączone dynamicznie z danymi. Rysunek 26.12 przedstawia stronę dostępu do danych utworzoną z użyciem
komponentów sieciowych Office.

Rysunek 26.12.
Strona dostępu
do danych
ze związanymi
komponentami
sieciowymi Office

Utwórzmy na początek prostą kwerendę krzyżową w przykładowej bazie danych Accessa NorthWind. Utworzymy
kwerendę krzyżową z wszystkimi kategoriami produktów i ich sprzedażą kwartalną w roku 1997. Zapis tej kwerendy w SQL
wygląda następująco:
TRANSFORM
Sum(CCur([Order Details].[UnitPrice]*[Quantity]*
(1-[Discount])/100)*100) AS ProductAmount
SELECT Categories.CategoryName
FROM (Categories INNER JOIN Products
ON Categories.CategoryID = Products.CategoryID)
INNER JOIN (Orders INNER JOIN [Order Details]
ON Orders.OrderID = [Order Details].OrderID)
ON Products.ProductID = [Order Details].ProductID
473 Rozdział 26. ♦ Użycie stron dostępu do danych

WHERE (((Orders.OrderDate) Between #1/1/1997# And #12/31/1997#))


GROUP BY Categories.CategoryName
PIVOT "Qtr " & DatePart("q",[OrderDate],1,0)
In ("Qtr 1","Qtr 2","Qtr 3","Qtr 4");

Zapisz tę kwerendę jako QuaterlyProducts i utwórz stronę dostępu do danych bazującą na tej kwerendzie.

Dodanie komponentu sieciowego Arkusz Excel


Aby dodać komponent Excel do strony dostępu do danych, kliknij ikonę podobną do ikony Excela na pasku narzędzi
(rysunek 26.13) i umieść komponent na stronie. Po umieszczeniu komponentu w odpowiednim miejscu należy związać
komórki arkusza z polami na stronie tak, aby arkusz zmieniał się, gdy użytkownik będzie przechodził między rekordami.
Musisz użyć modelu obiektowego DHTML, gdzie wszystkie obiekty są udostępnione poprzez obiekt document. Aby
odwołać się do pola o nazwie txtQ1, wprowadź do komórki:
=document.txtQ1.value

Dodaj komórkę dla każdego kwartału, sąsiednią komórkę zwiąż z formatem przechowującym daną.

Tabela 26.1.
Wartości komórek w arkuszu

Q1 =document.txtQ1.value

Q2 =document.txtQ2.value

Q3 =document.txtQ3.value

Q4 =document.txtQ4.value

Dodanie komponentu sieciowego Wykres


Po dodaniu do strony komponentu Arkusz Excel, dodajmy komponent Wykres wiążąc go z danymi w arkuszu. Gdy
będziemy przechodzić pomiędzy rekordami, będzie się zmieniać zawartość arkusza oraz uaktualniany będzie wykres.
Rysunek 26.13.
Pasek narzędzi
strony dostępu do
danych

Komponent Wykres dodajemy do strony poprzez kliknięcie ikony Wykres i narysowanie komponentu na stronie. Po tej
operacji zostanie uruchomiony kreator wykresów. Na pierwszej stronie kreatora wybieramy typ tworzonego wykresu.
Dostępne typy wykresów są podobne do wykresów 2D Excela. Po wybraniu typu wykresu należy wybrać przycisk
Następny. Na drugiej stronie kreatora (rysunek 26.14) wybieramy źródło danych dla wykresu, może być nim tabela lub
kwerenda albo arkusz kalkulacyjny istniejący na stronie. Wybierz arkusz kalkulacyjny i kliknij Następny. Na ostatniej
stronie ustalamy zakres na arkuszu zawierający wartości i etykiety. Wprowadzamy =A1:A4 jako etykiety oraz =B1:B4 jako
wartości.
Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 474

Rysunek 6.14.
Kreator wykresu
na stronie dostępu
do danych

Po zakończeniu pracy kreatora przełączamy się w tryb widoku strony i przeglądamy kolejne rekordy. Wykres powinien się
zmieniać po przejściu pomiędzy rekordami.

Skrypty w stronach dostępu do danych


Pisanie procedur kontrolujących strony dostępu do danych nie jest tak proste jak pisanie procedur dla formularzy i
raportów. Gdy chcesz napisać program zawarty w stronie DAP, musisz użyć skryptów, aby móc kontrolować zachowanie
się strony. Gdy tworzysz przycisk lub inny obiekt udostępniający zdarzenia, musisz napisać VBScript (lub JavaScript). W
Accessie nie ma edytora skryptów dla stron dostępu do danych, należy użyć Microsoft Script Editor (MSE), który
pokazany jest na rysunku 26.15.

Rysunek 26.15.
Microsoft Script
Editor (MSE)

Zamiast panelu nawigacji dostarczanego przez Accessa utworzymy nasz własny. Utwórz cztery przyciski i zatytułuj je:
Poprzedni, Następny, Pierwszy, Ostatni. Kliknij prawym przyciskiem myszy stronę i wybierz Microsoft Script Editor z menu
kontekstowego.

Po uruchomieniu MSE w oknie Script Outline przedstawione są wszystkie obiekty i zdarzenia dostępne na stronie. Wybierz
w oknie Script Outline przyciski umieszczone na stronie i kliknij dwukrotnie zdarzenie onClick. W oknie z kodem HTML
powinien pokazać się fragment kodu HTML:
<SCRIPT event=onclick for=Polecenie0 language=vbscript>
<!--

-->
475 Rozdział 26. ♦ Użycie stron dostępu do danych

</SCRIPT>

Istnieje kilka metod, aby napisać kod dla obiektu, jednak wyrażenie For wskazujące na używany obiekt jest domyślnym
sposobem. Wewnątrz bloku skryptu wprowadźmy poniższe wyrażenie:
MSODSC.CurrentSection.DataPage.MoveFirst

Każda strona dostępu zawiera obiekt DataSource o nazwie MSODSC, który z kolei zawiera obiekt DataPage.
Użyjemy metod MoveFirst, MoveLast, MoveNext i MovePrevious w odpowiednich przyciskach. Po oprogramowaniu
wszystkich czterech przycisków kod powinien wyglądać podobnie do zamieszczonego na wydruku 26.1.

Wydruk 26.1. Tworzenie własnych przycisków nawigacyjnych na stronie dostępu do danych


<SCRIPT event=onclick for=cmdFirst language=vbscript>
<!--
MSODSC.CurrentSection.DataPage.MoveFirst
-->
</SCRIPT>
<SCRIPT event=onclick for=cmdLast language=vbscript>
<!--
MSODSC.CurrentSection.DataPage.MoveLast
-->
</SCRIPT>
<SCRIPT event=onclick for=cmdNext language=vbscript>
<!--
MSODSC.CurrentSection.DataPage.MoveNext
-->
</SCRIPT>
<SCRIPT event=onclick for=cmdPrev language=vbscript>
<!--
MSODSC.CurrentSection.DataPage.MovePrevious
-->
</SCRIPT>

Zmiana źródła danych w trakcie działania strony


Dopóki strony dostępu do danych nie będą zapisywane we wnętrzu pliku MDB, dystrybucja ich będzie stanowić problem.
Najczęściej spotykanym problemem jest to, że strona odwołuje się do niewłaściwej bazy danych. Gdy umieścisz strony
DAP na serwerze WWW lub wyślesz pliki HTML do kogoś innego, strony odwoływać się będą do niewłaściwego pliku
MDB lub jakiś użytkownik może mieć pliki w innym miejscu niż inni użytkownicy.

W stronach DAP zarządzaniem połączeniami zajmuje się niewidoczny komponent sieciowy DataSource, za pomocą
którego można dowolnie programować połączenia. Komponent DataSource posiada właściwość ConnectionString,
którą można zmieniać programowo. Aby zmienić źródło danych, należy tylko zmienić właściwość ConnectionString
obiektu DataSource w następujący sposób:
MSODSC.ConnectionString = strConnect

Zakładamy, że komponent DataSource nazywa się MSODSC (taka jest jego domyślna nazwa) i strConnect jest
prawidłowym ciągiem połączeniowym OLEDB. Twój program powinien dostarczyć właściwy ciąg połączeniowy.

Możesz zapytać użytkownika o ścieżkę do pliku bazy danych za każdym uruchomieniem strony DAP. Aby to zrealizować,
użyj InputBox lub innego standardowego okna dialogowego wewnątrz programu klienta. Na wydruku 26.2 pokazany jest
sposób realizacji przełączenia źródła danych przy użyciu okna InputBox. Program prosi użytkownika o podanie ścieżki do
pliku bazy danych Accessa (rysunek 26.16), tworzy właściwy ciąg połączeniowy i przypisuje go do obiektu DataSource.
Możesz połączyć tę technikę z użyciem pliku UDL po stronie klienta, aby wyeliminować konieczność ręcznego
wpisywania danych.

Rysunek 26.16.
Wprowadzanie
danych o połączeniu

Wydruk 26.2. Ustawianie właściwego ciągu połączeniowego w stronie dostępu do danych


<SCRIPT language=vbscript>
<!--
'Przykład ten ustawia połączenie strony DAP do dowolnej
'bazy danych wprowadzonej przez użytkownika
Dim strConnect
Dim strPath

'Użytkownik wprowadza nazwę bazy przy użyciu InputBox


Część VIII ♦ Publikowanie w sieci za pomocą Access’a 2000 476

strPath=inputbox("Wprowadź ścieżkę do bazy NorthWind","Połączenie", _


"C:\Program Files\Microsoft Office\Office\Samples")

'Dla serwera SQL powinieneś zmienić na


'strConnect="Provider=SQLOLEDB.1"
strConnect="Provider=Microsoft.JET.OLEDB.4.0"
'Dodaj informacje o dostawcy do ścieżki
strConnect=strConnect & ";Data Source=" & strPath

'Ustawienie właściwości DataSource


'Domyślnie obiekt źródła danych nazywa się MSODSC
'Jeżeli zmieniłeś jego nazwę, musisz dokonać zmiany również tutaj

MSODSC.ConnectionString = strConnect

'Poinformuj użytkownika o zmianie połączenia


Msgbox "Połączenie zmienione na " & strPath,64

-->
</SCRIPT>
Rozdział 27.
Publikowanie w sieci
przy użyciu Accessa 2000
i Active Server Pages
W tym rozdziale:
u Użycie Active Server Pages.
u Architektura Active Server Pages.
u Rozpoczynamy pracę z Active Server Pages.
u Active Server Pages.
u Przykład: Tworzenie strony WWW dostępnej dla członków grupy.
u Publikacja w sieci z Accessa 2000 przy użyciu XML.
u Tworzenie wykresów przy użyciu formantu Wykres.

Jeżeli chcesz rozwinąć swoje statyczne strony WWW, publikować dane na bieżąco oraz tworzyć interakcyjne strony
WWW, powinieneś zapoznać się z Active Server Pages (ASP).

Statyczne strony WWW odchodzą w przeszłość. Aby zadowolić użytkowników, powinieneś dać im dostęp do możliwie
aktualnych danych. Używając ASP, można zagwarantować, że witryna WWW dostarcza najnowszych informacji. ASP
eliminuje wiele czynności potrzebnych do utrzymania witryny WWW. Przykładowo, jeżeli jesteś administratorem witryny,
która zawiera stronę z listą użytkowników, powinieneś oprzeć tę stronę na bazie danych. Dawniej musiałbyś ręcznie
zmieniać informacje o użytkownikach za każdym razem, gdy dane się zmieniły. Przy użyciu ASP możesz dać użytko-
wnikom możliwość zmiany tych danych poprzez przeznaczoną do tego stronę WWW. Strona z listą użytkowników
zostanie automatycznie uaktualniona, gdy ktoś wczyta ją do przeglądarki, ponieważ dane są przechowywane w bazie
danych Accessa 2000.

Użycie Active Server Pages


Strony Active Server Pages są najnowszą technologią oferowaną przez Microsoft dla dynamicznego udostępniania danych
w sieci WWW. ASP jest częścią Internet Information Server 3.0 i późniejszych, jest również dostępna w Personal Web
Server. Przy użyciu ASP można tworzyć strony WWW następnej generacji, które nie mają ograniczeń starszych
technologii jak Common Gateway Interface (CGI) i Internet Database Connector (IDC). Przy użyciu ASP można łatwo
tworzyć interaktywne witryny, które umożliwiają indywidualną obsługę klientów, wprowadzanie zamówień, koszyk zaku-
pów i wiele innych funkcji interaktywnych. Wygląd stron WWW może być dostosowywany przez użytkowników i
ustawienia te zostaną odtworzone podczas ich kolejnych wizyt.

Za pomocą ASP można tworzyć witryny interaktywne, które przechowują zmienne globalne ustawione przez użytkownika i
używane podczas wszystkich jego odwiedzin strony. Tradycyjne systemy klient-serwer mogły przechowywać stan sesji
pomiędzy kolejnymi stronami w zmiennych globalnych i klasach. Zarządzanie stanem sesji na stronach WWW nigdy nie
było takie łatwe. Przy użyciu ASP jest to bardzo łatwe zadanie. Przed ASP potrzebowałbyś skomplikowanych skryptów
478 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

CGI do zapamiętania, kto był na stronie i w jaki sposób przemieszczał się pomiędzy stronami. W ASP funkcjonalność ta
jest gotowa i nie wymaga pisania żadnego programu.

Tak jak jego poprzednik IDC/HTX, strony Active Server Pages są niezależne od przeglądarki oraz bardzo łatwe do
tworzenia i zmiany. ASP dostarcza ekstremalnej elastyczności w udostępnianiu danych z Accessa 2000 na witrynie WWW.
W tym rozdziale pokażemy, czym są strony ASP i jak je tworzyć.

Architektura Active Server Pages


Na pewno widziałeś w Internecie adres URL podobny do http://www.microsoft.com/default.asp. Plik z rozszerzeniem ASP
zawiera stronę Active Server Page. Strony ASP są dostępne tak jak strony HTML za pomocą protokołu HTTP. Ogromną
różnicą pomiędzy ASP i HTML jest sposób traktowania takiej strony przez serwer WWW. Strony ASP zawierają zarówno
HTML, jak i instrukcje dla serwera WWW. Instrukcje te są skryptami wykonywanymi na serwerze, które dynamicznie
tworzą kod HMTL w zależności od warunków, jakie podałeś lub od zawartości bazy danych. Serwer WWW przetwarza
instrukcje zawarte na stronie ASP i przesyła wynikowy kod HTML do przeglądarki użytkownika.

Strona ASP zawiera HTML lub HTML i skrypty dla serwera. Podczas przetwarzania pliku ASP serwer wykonuje skrypt na
serwerze i wysyła do przeglądarki czysty HTML. Ponieważ skrypt wykonywany jest na serwerze, pliki ASP są niezależne
od przeglądarki. Jeżeli strona nie zawiera skryptów, jest po prostu wysyłana do klienta. Możesz dla przykładu zmienić
rozszerzenie zwykłego pliku HTML na ASP. Tym sposobem utworzyłeś najprostszą stronę ASP. Gdy zażądasz tej strony,
serwer wyśle cały kod

HTML z pliku ASP. Jeżeli dodasz skrypt do tego pliku, przykładowo zmieniając kolor tła w zależności od dnia tygodnia,
skrypt ten zostanie wykonany na serwerze i otrzymasz tylko HTML z prawidłowym znacznikiem <Backcolor=”XXX”>.

Domyślnym językiem skryptów stron ASP jest VBScript i na nim skupimy się w drugiej części tego rozdziału. VBScript
jest podzbiorem Visual Basica i Visual Basica for Applications. Jeżeli znasz już VB i VBA, powinieneś czuć się jak w
domu, programując za pomocą VBScript. Jeżeli znasz JavaScript, również możesz go użyć, ASP pozwala na użycie
JavaScript. Jeżeli używasz innego języka skryptów jak Perl, możesz użyć go na stronach ASP pod warunkiem
zainstalowania wtyczki obsługującej ten język w serwerze WWW. Wtyczkę taką trzeba uzyskać od producenta języka.

Ponieważ skrypty wykonywane są na serwerze, a do przeglądarki jest przesyłany tylko wynikowy HTML, skomplikowany
kod i reguły biznesowe zawarte w skryptach są bezpieczne. Jeżeli użytkownik obejrzy kod źródłowy strony, zobaczy tylko kod
HTML wysłany do przeglądarki. Kod uruchamianego skryptu nie będzie widoczny w przeglądarce.

Active Server Pages kontra CGI


Strony Active Server Pages są integralną częścią systemu operacyjnego i nie wymagają kompilacji. Aplikacje CGI są
kompilowane na docelowym serwerze WWW i wykonywane jako osobny proces. Dla każdego aktywnego użytkownika
witryny uruchamiany jest osobny egzemplarz aplikacji CGI, co nie jest efektywne. Program CGI musi być skompilowany
za każdym razem, gdy go zmienimy, natomiast gdy zmienimy plik ASP, zostanie on skompilowany przy następnej próbie
dostępu do tego skryptu. Oznacza to, że w trakcie tworzenia aplikacji ASP po zapisaniu strony można ją natychmiast obej-
rzeć w przeglądarce.

W odróżnieniu do CGI, strony ASP wykonywane są w ramach jednego procesu, co powoduje drastyczną poprawę
wydajności. Ponieważ ASP jest wykonywane w ramach tego samego procesu, ładowany jest tylko jeden egzemplarz silnika
ASP dla wszystkich użytkowników aplikacji. Tworzy on wiele wątków obsługujących skrypty. ASP utrzymuje stan sesji
dla wszystkich użytkowników witryny. ASP można łatwo zintegrować z istniejącymi danymi, na przykład z bazą danych
Accessa 2000. Podczas, gdy trzeba włożyć nieco wysiłku w dostęp do danych ODBC ze skryptów CGI, dostęp poprzez
ODBC jest możliwy w Active Server Pages za pomocą ADO. Dodatkowo ADO używa dostawców OLEDB dla Jet, SQL
Server i Oracle w sposób przedstawiony w poprzednich rozdziałach, więc możesz używać również tych baz danych w
twoich skryptach.

Uruchomienie stron ASP


Przed konwersją wszystkich obiektów aplikacji należy się upewnić, czy są zainstalowane i działają strony Active Server
Pages, czy źródło ODBC lub dostawca OLEDB jest skonfigurowany dla bazy danych i czy skonfigurowany jest katalog
wirtualny z prawami do wykonywania skryptów aplikacji. Wszystkie te zagadnienia zostały opisane w rozdziale 24.
„Konfiguracja serwera WWW do publikowania w sieci WWW”.

478 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 479

Rozpoczynamy pracę
z Active Server Pages
Za pomocą Microsoft Access 2000 można wyeksportować każdy obiekt bazy danych jako stronę ASP. Gdy konwertujesz
obiekt bazy danych na Active Server Page, ASP będzie wyświetlało tabelę HTML z danymi w tym obiekcie. Użytkownicy
nie będą mogli zmieniać i kasować istniejących rekordów ani dopisywać nowych, chyba że dopiszesz odpowiedni fragment
programu. Funkcja eksportu jako ASP nie jest funkcją konwersji Accessa na ASP.

Aby skonwertować obiekt bazy danych do ASP przy użyciu interfejsu użytkownika Accessa, uruchom kreator, wybierając
z głównego menu Plik, Eksportuj. Wybierz typ pliku Active Server Pages. Następnie otwarte zostanie okno pokazane na
rysunku 27.1.

Rysunek 27.1.
Okno eksportu
do ASP

W oknie pokazanym na rysunku 27.1 należy podać nazwę źródła danych ODBC, hasło bazy danych, URL i limit czasu
sesji. Wprowadź dowolną nazwę źródła danych, nazwę użytkownika i hasło, ponieważ będziemy zmieniać wynikowy plik.
W polu URL wpisz URL serwera WWW, gdzie będzie umieszczony plik ASP (przykładowo www.mojserwer.com). Limit
czasu sesji jest czasem, jaki ASP będzie czekało przed zamknięciem połączenia, jeżeli nie będzie aktywności na stronie. Po
upływie tego czasu ASP usunie informacje o stanie sesji i zwolni zajętą pamięć. Domyślnie ASP przyjmuje 20 minut jako
limit czasu sesji.

Po wykonaniu eksportu w podanym katalogu znajdzie się plik ASP. Możesz zapisać stronę ASP w katalogu, który jest
katalogiem wirtualnym z prawem wykonywania skryptów w serwerze WWW. Sposób konfiguracji katalogu opisany jest w
rozdziale 24. Po zapisaniu pliku przez Accessa sprawdźmy, co zostało zrobione. Jako domyślnego dostawcę OLEDB do
eksportu ASP Access używa ODBC. Aby ominąć to ograniczenie, otwórz wygenerowaną stronę ASP w Notatniku. Treść
strony wygenerowanej przez kreatora zamieszczona jest na wydruku 27.1.

Wydruk 27.1. Wynik eksportu tabeli Klienci z bazy danych Northwind do ASP
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=windows-1250">
<TITLE>Klienci</TITLE>
</HEAD>
<BODY>
<%
If IsObject(Session("Northwind_conn")) Then
Set conn = Session("Northwind_conn")
Else
Set conn = Server.CreateObject("ADODB.Connection")
conn.open "Northwind","Admin",""
Set Session("Northwind_conn") = conn
End If
%>
<%
If IsObject(Session("Klienci_rs")) Then
Set rs = Session("Klienci_rs")
Else
sql = "SELECT * FROM [Klienci]"
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open sql, conn, 3, 3
If rs.eof Then
rs.AddNew
End If
Set Session("Klienci_rs") = rs
End If
%>
<TABLE BORDER=1 BGCOLOR=#ffffff CELLSPACING=0><FONT FACE="Arial"
ªCOLOR=#000000><CAPTION><B>Klienci</B></CAPTION></FONT>

<THEAD>
<TR>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>ID klienta</FONT></TH>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Nazwa firmy</FONT></TH>
480 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Przedstawiciel</FONT></TH>


<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Stanowisko</FONT></TH>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Adres</FONT></TH>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Miasto</FONT></TH>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Region</FONT></TH>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Kod pocztowy</FONT></TH>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Kraj</FONT></TH>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Telefon</FONT></TH>
<TH BGCOLOR=#c0c0c0 BORDERCOLOR=#000000 ><FONT SIZE=2 FACE="Arial" ªCOLOR=#000000>Faks</FONT></TH>

</TR>
</THEAD>
<TBODY>
<%
On Error Resume Next
rs.MoveFirst
do while Not rs.eof
%>
<TR VALIGN=TOP>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("IDklienta").Value)%><BR></FONT></ªTD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("NazwaFirmy").Value)%><BR></FONT><ª/TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("Przedstawiciel").Value)%><BR></FOªNT></TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("StanowiskoPrzedstawiciela").Valueª)%><BR></FONT></TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("Adres").Value)%><BR></FONT></TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("Miasto").Value)%><BR></FONT></TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("Region").Value)%><BR></FONT></TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("KodPocztowy").Value)%><BR></FONT>ª</TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("Kraj").Value)%><BR></FONT></TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("Telefon").Value)%><BR></FONT></TD>
<TD BORDERCOLOR=#c0c0c0 ><FONT SIZE=2 FACE="Arial"
ªCOLOR=#000000><%=Server.HTMLEncode(rs.Fields("Faks").Value)%><BR></FONT></TD>

</TR>
<%
rs.MoveNext
loop%>
</TBODY>
<TFOOT></TFOOT>
</TABLE>
</BODY>
</HTML>

Chcemy zmienić informację o połączeniu ADO w pliku ASP tak, aby używał on OLEDB. Należy zmienić tylko jeden wiersz
kodu zawierający ciąg połączeniowy. Kreator próbuje otworzyć połączenie ADO za pomocą nazwy DSN, którą podaliśmy w
oknie kreatora. Ponieważ podaliśmy wymyśloną nazwę DSN, należy zmienić połączenie, aby używało dostawcy OLEDB
dla Jet (dla Accessa) i wskazać plik MDB na serwerze. Należy użyć odpowiedniej składni przedstawionej w rozdziale 6.
„Wprowadzenie do obiektów danych ActiveX”. Należy zmienić wiersz z postaci:
conn.open "Northwind", "Admin", ""

na:
conn.open "Provider=Microsoft.Jet.OLEDB.4.0;data source="c:\northwind.mdb"

Zapisz plik w Notatniku i otwórz go w przeglądarce poprzez URL. Rysunek 27.2 przedstawia końcowy wynik konwersji do
Active Server Page. Musisz otworzyć ten plik ASP w przeglądarce, używając prawidłowego adresu URL. Przykładowo,
aby otworzyć plik ASP na twoim komputerze przy użyciu protokołu HTTP, należy użyć adresu podobnego do:
http://localhost/nazwa_katalogu_wirtualnego/plik.asp.

Konstrukcja kodu ASP


Jak można zauważyć, kreator eksportu tworzy bardzo prosty kod. Na początku otwierany jest obiekt połączenia ADO i na
bazie tego połączenia otwierany jest obiekt ADO recordset. W trakcie przesuwania się po wyniku dane kierowane są do
tabeli HTML. Dokładniej zostanie to opisane w dalszej części rozdziału.

480 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 481

Rysunek 27.2.
Tabela
skonwertowana
do postaci ASP

Ograniczenia eksportu stron ASP


Mimo że eksport z Accessa pozwala w łatwy sposób rozpocząć pracę z ASP, nie jest tak elastyczny jak mógłby być ani nie
utworzy dla Ciebie całej niestandardowej strony ASP. Eksport nie zapewnia żadnej interaktywności tworzonej strony, nie
pozwalając na zmiany rekordów czy ich usuwanie. Ponadto strona ASP wygenerowana przez eksport używa wolniejszego i
mniej efektywnego połączenia ODBC do podłączenia się do bazy danych.

Przy użyciu tej metody możesz utworzyć niektóre robocze strony ASP, ale jeżeli chcesz tworzyć sprawniejsze strony
ASP, które dają dodatkowe możliwości lub używają OLEDB, musisz nauczyć się podstaw ASP. Kolejna część rozdziału
zaznajomi Cię z podstawami ASP.

Active Server Pages


Aby tworzyć aplikacje ASP oparte o bazę danych Access 2000, musisz poznać podstawy ASP. Mimo że na temat ASP można
napisać oddzielną książkę, ta część rozdziału przedstawia podstawowe informacje pozwalające rozpocząć pracę. Materiał tu
przedstawiony pozwala na zbudowanie całkiem rozbudowanej aplikacji WWW. Omówione zostaną:
u Silnik ASP;
u Skrypty VBScript wykonywane na serwerze;
u Obiekty aplikacji i sesji;
u Obiekty żądań i odpowiedzi;
u Plik global.asa.

Silnik ASP
Active Server Pages to jeden z interfejsów Internet Server Application Programming Interface (ISAPI), które zostały dodane
do Internet Information Server (IIS) 3.0 i późniejszych. Gdy przeglądarka żąda pliku z serwera WWW, filtr ISAPI
sprawdza, czy żądanie to dotyczy strony ASP. Jeżeli przeglądarka żąda strony ASP, uruchamiany jest interpreter ASP.
Przetwarza on plik ASP i rozpoczynając od początku pliku, wykonuje skrypty. Wynikowy kod HTML wysyłany jest do
przeglądarki. Następna część rozdziału zawiera informacje o skryptach wykonywanych na serwerze.

Skrypty wykonywane na serwerze


Plik ASP zawiera skrypty wykonywane na serwerze oraz kod HTML. Skrypty domyślnie są zapisane w języku VBScript i
w tym rozdziale skupimy się na nim. Visual Basic Scripting Edition, znany pod nazwą VBScript, jest rozbudowanym
językiem skryptów wykonywanych zarówno na serwerze, jak i na maszynie klienta.
482 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

VBScript jest podzbiorem Visual Basica. VBScript posiada taką samą składnię i możliwości języka jak VBA. Jeżeli
używałeś VBA, nauczysz się VBScript bardzo szybko. VBScript nie posiada kilku ważnych funkcji VBA, jednak dzięki
temu jest bezpieczniejszy i mniejszy. Przykładowo usunięto obsługę plików, wywoływanie DLL i automatyzacji OLE.
Usunięto również wszystkie typy danych (Long, String itd.), a w zamian wszystkie zmienne są typu Variant. Tabela
27.1 zaczerpnięta z dokumentacji VBScript zawiera wszystkie właściwości VBA, które zostały usunięte z VBScript.

Tabela 27.1.
Wszystkie funkcje VBA niedostępne w VBScript

Kategoria Usunięta funkcja lub słowo kluczowe


Obsługa tablic Option Base
Deklaracja tablic o dolnej granicy <> 0
Kolekcje Add, Count, Item, Remove
Dostęp do kolekcji przy użyciu znaku ! (np.: Kolekcja!element)
Kompilacja warunkowa #Const
#If ... Then ... #Else

Przepływ sterowania DoEvents


GoSub ... Return, GoTo
On Error GoTo
On ... GoSub, On ... GoTo
Numery wierszy, etykiety wierszy
With ... End With

Konwersje CVar, CVDate, Str, Val

Typy danych Wszystkie wewnętrzne typy danych oprócz Variant


Type ... End Type

Data i czas Instrukcja Date, Instrukcja Time


Timer

Tabela 27.1.
Wszystkie funkcje VBA niedostępne w VBScript (ciąg dalszy)

Kategoria Usunięta funkcja lub słowo kluczowe


DDE LinkExecute, LinkPoke, LinkRequest, LinkSend

Uruchamianie Debug, PrintEnd, Stop

Deklaracje Declare (dla deklarowania bibliotek DLL)


New
Optional
ParamArray
Property Get, Property Let
Property Set
Static

Obsługa błędów Erl


Error
On Error ... Resume
Resume, Resume Next

Obsługa plików Tradycyjna obsługa plików


Funkcje finansowe Wszystkie funkcje finansowe
Manipulacja obiektami TypeOf

Obiekty Clipboard
Collection

Operatory Like

Opcje Deftype
Option Base
Option Compare
Option Private Module

Ciągi znaków Ciągi o stałej długości


LSet, Rset
Wyrażenie Mid
StrConv

Użycie obiektów Dostęp do kolekcji przy użyciu !

482 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 483

VBScript jest celowo niewielki, aby zapewnić bardzo szybką i efektywną kompilację. Innym powodem ograniczenia
funkcjonalności jest to, że VBScript może być uruchamiany zarówno na serwerze, jak i na komputerze klienta. Jeżeli
skrypt jest uruchamiany w przeglądarce na komputerze klienta, nie można dawać mu dostępu do systemu plików
komputera. Pozwoliłoby to złośliwym programistom na utworzenie skryptów formatujących dysk.

Tabela 27.2 pochodząca z dokumentacji VBScript zawiera listę dostępnych funkcji.

Można nauczyć się języka VBScript poprzez próby i eksperymenty z programem VBA, sprawdzając, czy działa on pod
VBScript. Dodatkowo Microsoft udostępnił dokumentację języka VBScript. Jest ona dostępna do załadowania z
www.microsoft.com/vbasic i jest bezpłatna. Po załadowaniu i zainstalowaniu dokumentacji na komputerze zostaje zainsta-
lowany pełny opis języka oraz przykładowe pliki (rysunek 27.3).

Tabela 27.2.
Funkcje dostępne w VBScript

Kategoria Słowo kluczowe


Obsługa tablic Array, Dim, Private, Public, ReDim
IsArray, Erase, LBound, Ubound

Przypisanie Set

Komentarze Komentarze przy użyciu ' lub Rem


Stałe, literały Empty, Nothing, Null, True, False

Przepływ sterowania Do...Loop, For...Next,


For Each...Next, If...Then...Else,
Select Case, While...Wend

Konwersje Abs, Asc, AscB, AscW, Chr, ChrB, ChrW,


Cbool, Cbyte, Ccur, Cdate, Cdbl, Cint, CLng, CSgn, CStr,
DateSerial, DateValue, Hex, Oct, Fix, Int, Sgn,
TimeSerial, TimeValue, Dates/Times, Date, Time,
DateAdd, DateDiff, DatePart, Day, Month,
Weekday, Year, Hour, Minute, Second, Now

Deklaracje Const, Dim, Private, Public, ReDim, Function, Sub

Formatowanie ciągów FormatCurrency, FormatDateTime,


FormatNumber, FormatPercent

Obsługa błędów On Err, Err

Wejście/wyjście InputBox, LoadPicture, MsgBox

Literały Empty, False, Nothing, Null, True

Matematyka Atn, Cos, Sin, Tan, Exp, Log, Sgr, Randomize, Rnd

Obiekty CreateObject, Dictionary, Err,


FileSystemObject, GetObject, TextStream

Operatory Dodawanie (+), Odejmowanie (-), Potęga (^),


Reszta z dzielenia (Mod), Mnożenie (*), Dzielenie (/),
Dzielenie całkowite (\), Negacja (-),
Łączenie ciągów (&), Równość (=), Nierówność (<>),
Mniejszy (<), Mniejszy lub równy (<=),
Większy (>), Większy lub równy (>=), Is, And, Or, Xor,
Eqw, Imp

Opcje Option Explict

Procedury Call, Function, Sub

Zaokrąglanie Abs, Int, Fix, Round, Sgn

Identyfikacja silnika skryptów ScriptEngine, ScriptEngineBuildVersion,


ScriptEngineMajorVersion, ScriptEngineMinorVersion

Tabela 27.2.
Funkcje dostępne w VBScript (ciąg dalszy)

Kategoria Słowo kluczowe


484 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

Ciągi Asc, AscB, AscW, Chr, ChrB, ChrW, Filter, Instr, InstrB,
InstrRev, Join, Len, LenB, Lcase, Ucase, Left, LeftB,
Mid, MidB, Right, RightB, Replace, Space, Split,
StrComp, String, StrReverse, LTrim, RTrim, Trim

Warianty IsArray, IsDate, IsEmpty, IsNull, IsNumeric, IsObiect,


Typename, VarType

Rysunek 27.3.
Dokumentacja do
VBScript

Użycie VBScript na stronach ASP


Przy użyciu VBScript można utworzyć świetnie wyglądające witryny, wykorzystując jego możliwość tworzenia skryptów
wykonywanych na komputerze klienta (a właściwie skrypty wykonywane są przez przeglądarkę). W tym rozdziale
skupimy się tylko na wykorzystaniu skryptów wykonywanych na serwerze, ponieważ tylko ten rodzaj skryptów
wykorzystywany jest przez ASP do generowania wynikowego kodu HTML. Poniżej wymienione zostało kilka funkcji,
które realizuje VBScript:
u Tworzenie zmiennych, przypisywanie do nich wartości, wykorzystywanie ich w warunkach logicznych lub
umieszczanie ich wartości w wynikowym kodzie HTML.
u Wykonywanie operacji na zmiennych przy użyciu If...Then, Select Case i innych operatorów.
u Tworzenie procedur wykonywanych na serwerze w celu wykonania logowania, kontroli dat i formatowania.
u Dynamiczne tworzenie skryptów VBScript w wynikowym kodzie HTML do wykonania w przeglądarce klienta.

Skrypty znajdują się w kodzie HTML pomiędzy znacznikami <%>. Możesz mieszać fragmenty HTML i skryptu.
Przykładowo, na wydruku 27.2 znajduje się skrypt ASP, który do zmiennej strName przypisuje nazwisko autora, a
następnie zamieszcza ten ciąg na stronie WWW.

Wydruk 27.2. Przykład pliku ASP używającego zmiennej


<HTML>
<HEAD><TITLE>Variables</TITLE></HEAD>
<BODY BGCOLOR=#FFFFFF>
<% strName="Stephen Forte" %>
Hello <%=strName%>
</BODY>
</HTML>

Gdy użytkownik zażąda pliku ASP, którego treść znajduje się na wydruku 27.2, serwer WWW wykona skrypt zawarty
pomiędzy ogranicznikami <%> i utworzy stronę WWW, która została pokazana na rysunku 27.3. Kod HTML będący
wynikiem działania skryptu przedstawiony jest na wydruku 27.3. Wydruk 27.3 zawiera źródło strony WWW z rysunku
27.4.

Wydruk 27.3. Źródło HTML strony WWW z rysunku 27.4


<HTML>
<HEAD><TITLE>Variables</TITLE></HEAD>
<BODY BGCOLOR=#FFFFFF>
Hello Stephen Forte
<BR>
</BODY>
</HTML>

484 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 485

Rysunek 27.4.
Strona WWW
utworzona
przez skrypt ASP
z wydruku 27.2

Porównaj plik ASP z wydruku 27.2 i plik HTML z wydruku 27.3 wygenerowany przez skrypt ASP. Zauważ, że kod
VBScript zawarty pomiędzy znacznikami <%> nie został umieszczony w wynikowym kodzie HTML. Fragment
<%=strName%> został zastąpiony w wynikowym kodzie przez wartość zmiennej. Fragmenty pomiędzy znacznikami <%>
są interpretowane i wykonywane przez serwer, a wyniki działania tego kodu są wysyłane do przeglądarki jako czysty kod
HTML.

W kolejnym przykładzie, zamieszczonym na wydruku 27.4, użyta zostanie pętla do zwiększania wartości zmiennej, która
jest używana w kodzie HTML.

Wydruk 27.4. Skrypt ASP wykonywany na serwerze


<HTML>
<HEAD>
<TITLE>Creating Hello World with Incremental Text Size Increase </TITLE>
</HEAD>
<BODY BGCOLOR=#FFFFFF>
<% for i = 3 to 7 %>
<FONT SIZE=<% = i %>>Hello World</FONT><BR>
<% next %>
<BR>
<BR>
</BODY>
</HTML>

Gdy użytkownik zażąda pliku ASP zamieszczonego na wydruku 27.4, VBScript pięć razy wykona pętlę, zwiększając za
każdym razem wielkość czcionki, co w wyniku da stronę HTML pokazaną na rysunku 27.5. Źródło wynikowej strony
zamieszczone jest na wydruku 27.5.

Rysunek 27.5.
Strona WWW
będąca wynikiem
wykonania skryptu
ASP z wydruku 27.4

Wydruk 27.5. Źródło strony WWW utworzonej przez skrypt ASP z wydruku 27.4
<HTML>
<HEAD>
<TITLE>Creating Hello World with Incremental Text Size Increase </TITLE>
</HEAD>
<BODY BGCOLOR=#FFFFFF>
<FONT SIZE=3>Hello WOrld</FONT><BR>
<FONT SIZE=4>Hello World</FONT><BR>
<FONT SIZE=5>Hello World</FONT><BR>
<FONT SIZE=6>Hello World</FONT><BR>
<FONT SIZE=7>Hello World</FONT><BR>
<BR>
<BR>
</BODY>
</HTML>

Jak zostało to pokazane na tych dwóch przykładach, strony ASP używają skryptów VBScript wykonywanych na serwerze
do generacji zwykłego kodu HTML. Aby zwiększyć możliwości stron WWW, należy skorzystać z niektórych
wbudowanych obiektów ASP, które teraz omówimy.
486 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

Obiekty aplikacji i sesji


Używając ASP, można skorzystać z kilku wbudowanych obiektów, które są dostępne dla aplikacji. W tej części opiszemy
sposób użycia każdego z tych obiektów w aplikacji ASP. Jest to jednak tylko wprowadzenie w temat użycia obiektów w
aplikacjach. Dokładnego opisu zagadnienia należy szukać w innych książkach serii „Księga eksperta”.

Użycie obiektu aplikacji


W czasie tworzenia stron ASP zakłada się, że każdy katalog wirtualny jest odrębną aplikacją. ASP odwołuje się do
każdej aplikacji jako obiektu. Obiekt Application używany jest do zarządzania wspólnymi danymi i jest dostępny dla
wszystkich użytkowników aplikacji. Obiekt Application tworzony jest z chwilą pierwszego dostępu do stron aplikacji
po uruchomieniu serwera WWW. Jest dostępny dla wszystkich użytkowników odwiedzających witrynę tak długo dostępny
aż do chwili, gdy we wszystkich sesjach upłynie limit czasu oczekiwania lub zostanie wyłączony serwer WWW.

Do obiektu Application można dynamicznie dołączać właściwości, które są traktowane jak zmienne globalne dostępne we
wszystkich plikach aplikacji i dla każdego użytkownika aplikacji. Składnia użycia właściwości obiektu Application jest
następująca:
<%Application("nazwa_właściwości")=wartość %>

Przykładowo, możemy sprawdzić, ilu użytkowników jednocześnie używa aplikacji. Możesz przygotować właściwość
VisitorNum w następujący sposób:
<%Application("VisitorNum")=0 %>

Następnie po zalogowaniu się użytkownika do naszego systemu należy zwiększyć wartość zmiennej globalnej o jeden i
wyświetlić liczbę aktualnie pracujących użytkowników. Aby liczba ta była zgodna ze stanem faktycznym, po wylogowaniu
użytkownika należy zmniejszyć licznik. Aby zwiększyć wartość właściwości, użyj następującego wiersza:
<%Application("VisitorNum")= Application("VisitorNum")+1 %>

Podczas wylogowywania użytkownika należy użyć:


<%Application("VisitorNum")= Application("VisitorNum")-1 %>

Aby wyświetlić liczbę jednocześnie zalogowanych użytkowników, użyj następującego wiersza:


Jednocześnie pracuje <%Application("VisitorNum")%> użytkowników

Podsumowując. Obiekt Application jest używany do przechowywania zmiennych globalnych, których można używać w
każdej stronie aplikacji i które są dostępne dla wszystkich użytkowników. Aby użyć indywidualnych zmiennych
globalnych dla poszczególnych użytkowników, należy skorzystać z obiektu Session, który jest opisany w kolejnej części
rozdziału.

Użycie obiektu sesji


Prawdopodobnie najważniejszym obiektem, o którym powinieneś się dowiedzieć, jest obiekt Session. ASP utrzymuje
automatycznie stan sesji i to właśnie obiekt Session przechowuje stan sesji dla bieżącego użytkownika. Jeżeli
jednocześnie strony używa 200 użytkowników, utworzonych jest 200 obiektów Session. Obiekt ten pozwala na tworzenie
własnych właściwości dostępnych globalnie dla użytkownika odwiedzającego witrynę. Przykładowo można pozwolić
użytkownikowi na podanie imienia i wybór ulubionego koloru. Przy użyciu właściwości obiektu Session można
wygenerować stronę WWW w podanym przez użytkownika kolorze i umieścić na niej imię użytkownika.

Obiekt sesji tworzony jest przy dostępie użytkownika do witryny WWW i usuwany jest po opuszczeniu witryny lub po
upłynięciu czasu nieaktywności sesji. Aby odwołać się do niestandardowych właściwości obiektu Session, należy użyć
składni identycznej jak przy odwołaniach do obiektu Application:
<%Session("nazwa_właściwości")=wartość %>

Po ustawieniu właściwości można odwoływać się do niej z wszystkich stron witryny.

Użycie obiektów żądań i odpowiedzi


Opisane w poprzedniej części obiekty Application i Session mają możliwość tworzenia niestandardowych właściwości
i utrzymują stan sesji. Kolejne dwa obiekty, Response i Redirect, posiadają metody pozwalające, poprzez skrypty
wykonywane na serwerze, na wykonywanie określonych akcji i dostęp do danych.

486 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 487

Obiekt Response
Aby obsłużyć komunikację pomiędzy przeglądarką i serwerem, należy użyć obiektu Response. Obiekt Response posiada
on osiem metod dostępnych dla programisty, jednak na potrzeby ASP i Accessa 2000 omówimy tylko metody Redirect i
Write.

Response.Redirect
Gdy chcesz wyświetlić jakąś stronę w przeglądarce, powinieneś w skrypcie ASP użyć metody Redirect obiektu Response.
Przykładowo, wyobraźmy sobie stronę WWW, na której znajduje się formularz, w którym użytkownik podaje nazwę
użytkownika. Jeżeli użytkownik ten istnieje w bazie danych, użytkownik zostaje przeniesiony na stronę główną, jeżeli nie istnieje,
na stronę rejestrowania nowego użytkownika. Można skorzystać z konstrukcji If...Then razem z metodą
Response.Redirect w następujący sposób:
<%If fLogin=True then
'Użytkownik zautoryzowany
Response.Redirect "welcome.html"
Else
'Nie ma takiego użytkownika
Response.Redirect "newmember.asp"
End if%>

Response.Write
W trakcie tworzenia skryptu ASP, który wypisuje tekst do wynikowego pliku HTML, można użyć metody Write obiektu
Response. Response.Write ma bardzo prostą składnię:
Response.Write("ciąg tekstu")

Przykładowo, można tworzyć różne komunikaty umieszczane na stronie w zależności od zdefiniowanego warunku. Możesz
spytać użytkownika o wiek, a następnie utworzyć w zależności od odpowiedzi odpowiednią stronę, używając metody
Write. Podany poniżej fragment skryptu demonstruje taką właśnie technikę.
<%If intAge < 21 Then
Response.Write("Prawo w Nowym Jorku")
Response.Write("zabrania sprzedawania alkoholu")
Response.Write("młodzieży do lat 21")
Else
Response.Redirect "buy.asp"
End If%>

Obiekt Request
Aby sprawdzić, co użytkownik wpisał do pola tekstowego na stronie WWW, powinieneś użyć obiektu Request. Obiekt
ten potrafi pobrać informację z wielu miejsc w przeglądarce, jednak skupimy się teraz tylko na pobieraniu wartości z
formularza zawartego na stronie WWW. Każdy formularz zawarty na stronie HTML składa się z elementów HTML, takich
jak pola tekstowe i listy wyboru. Jeżeli nadasz tym elementom nazwy i wywołasz plik ASP, można odczytać wartości z
tych elementów za pomocą następującego wywołania:
Request.Form("nazwa_elementu")

Możesz użyć obiektu Request.Form do odczytania informacji o użytkowniku i wstawić je do bazy danych Accessa 2000,
lub utworzyć odpowiednie wyrażenie SQL. Można również przypisać do zmiennej ciąg, który wpisał użytkownik przy
użyciu wyrażenia podobnego do następującego:
<% intAge=Request.Form("txtWiek")%>

Plik global.asa
Strony ASP używają specjalnego pliku o nazwie global.asa. Jest on umieszczony w katalogu, który jest korzeniem drzewa
katalogu wirtualnego i służy on do zarządzania zdarzeniami obiektów Application i Session. Plik ten jest również używany
do tworzenia zmiennych Application i Session. Obiekty Application i Session posiadają zdarzenia, które są
wykonywane na początku i na końcu istnienia obiektów. Są to:
u Application_OnStart;
u Application_OnEnd;
u Session_OnStart;
488 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

u Session_OnEnd.

Można użyć tych zdarzeń do tworzenia zmiennych, wstawiania lub szukania rekordów w bazie danych oraz upewnić się, że
użytkownik wlogował się. Plik global.asa nie działa jak domyślny dokument w katalogu wirtualnym. Pierwsze odwołanie
do niego następuje, gdy użytkownik po raz pierwszy uruchomił dowolną stronę z katalogu wirtualnego. Plik global.asa nie
tworzy kodu HTML jak pliki ASP, zamiast tego wykonywany jest kod obsługi odpowiednich zdarzeń obiektów
Application oraz Session. Wraz z rozwojem ASP Microsoft doda kolejne zdarzenia do ASP, które będą obsługiwane
przez kod zawarty w pliku global.asa.

Kod zamieszczony na wydruku 27.6 jest przykładowym plikiem global.asa ze zdefiniowaną obsługą zdarzeń OnStart dla
obiektów Application i Session. Dla obiektu Application ustawiana jest zmienna VisitorNum w celu zliczania
ilości jednocześnie wlogowanych użytkowników. W obsłudze zdarzenia OnStart obiektu Session zestawiane jest
połączenie do przykładowej bazy danych, aby każda strona mogła używać utworzonego tu obiektu Connection (więcej o
połączeniach do bazy znajduje się w rozdziale 6. „Wprowadzenie do obiektów danych ActiveX” i rozdziale 7. „Zaawan-
sowane ADO”). Oprócz połączenia do bazy tworzonych jest pięć zmiennych dostępnych dla całej sesji zainicjowanych
informacjami pochodzącymi z bazy danych.

Wydruk 27.6. Plik global.asa dla przykładowego katalogu wirtualnego


<SCRIPT LANGUAGE="VBScript" RUNAT="Server">
' Plik Global.asa dla www.orcs.com/access2000
' Zadanie: przygotowanie właściwości obiektów Application i Session
' Stephen Forte

</SCRIPT>
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
Sub Application_OnStart
' Przygotowanie zmiennych globalnych
Application("VisitorNum")=0
Application("Start")=Now
End Sub

Sub Session_OnStart
' Zestawienie połączenia z bazą danych
' Ustawiany jest również limit czasu oczekiwania itp.

Session("Start")=Now
Session("DataConn_ConnectionString") = _
"provider=Microsoft.Jet.OLEDB.4.O;" & _
"data source=C:/wwwroot/access2000/data/nyc.mdb"
Session("DataConn_ConnectionTimeout") = 15
Session("DataConn_CommandTimeout") = 30
Session("DataConn_RuntimeUserName") = ""
Session("DataOonn RuntimePassword") = ""
End Sub
</SCRIPT>

Przykłady użycia obiektów ASP


Na koniec przedstawimy przykład, w którym używane są obiekty ASP.

Przykładowa strona WWW używa zmiennych będących niestandardowymi właściwościami obiektów Application i
Session. W obiekcie Application utworzone zostały zmienne Start oraz VisitorNum. W trakcie obsługi zdarzenia
OnStart obiektu Application do zmiennej Start został przypisany bieżący czas. Jest on również przypisywany do
zmiennej Start z obiektu Session. Czas zapisany w obiekcie Session może nie być bieżącym czasem, ponieważ
zdarzenie OnStart obiektu Session jest wywoływane, gdy użytkownik odwoła się do dowolnej strony z katalogu
wirtualnego aplikacji. Wydruk 27.7 zawiera przykład użycia tych zmiennych na przykładowej stronie WWW.

Wydruk 27.7. Zmienne obiektów Application i Session


<hr>
<%Application("VisitorNum")=Application("VisitorNum")+1%>
<p align="left"><strong>
Zmienne obiektów Application i Session:</strong></p>
<p><strong>Aplikacja uruchomiona: <%=Application("Start")%> </strong></p>
<p><strong>Użytkownik odwiedzający aplikację:
<%=Application("VisitorNum")%> </strong></p>
<p><strong>Sesja uruchomiona: <%=Session("Start")%> </strong></p>
<hr>

488 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 489

Rysunek 27.6.
Obiekty ASP

Użycie ADO w aplikacjach ASP


Obiekt recordset udostępnia do potencjalnego użycia wiele właściwości i metod. W następnym przykładzie użyjemy
właściwości EOF (koniec pliku). EOF pozwala na uruchomienie pętli przeglądającej wszystkie rekordy wyniku od
pierwszego do ostatniego. Skrypt zamieszczony na wydruku 27.8 otwiera połączenie oraz po wykonaniu kwerendy w pętli
przebiega przez rekordy wyniku, wypisując je do wynikowego wyjścia HTML.

Wydruk 27.8. Użycie ADO na stronie ASP


<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>Rozdział 26.: Przykład użycia ADO</title>
</head>
<body>
<h2 align="center"> Lista klientów Northwind Traders </h2>
<p align="center"> Rozdział 26.: Przykład użycia ADO </p>
<hr>
<% ' Początek skryptu VBScript
Dim x
Dim dbconn
Dim rst
' Zestawienie połączenia
Set dbconn=server.createobject("adodb.connection")

' Inicjowanie połączenia z bazą danych


dbconn.open "provider=Microsoft.Jet.OLEDB.4.O;" & _
"data source=D:\wwwroot\db\ch27.mdb"

' Wykonanie zapytania


set rst=dbconn.execute ("Select * from Customers")

' Używane jako licznik


x=1
Do Until rst.eof
response.write x & ". " & rst("CompanyName")%>
<br>
<%rst.movenext
x=x+1
loop
dbconn.close
' Koniec skryptu%>
<hr>

</body>
</html>

Wykonanie skryptu 27.8 da w rezultacie stronę pokazaną na rysunku 27.7.


490 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

Rysunek 27.7.
Wynik wykonania
skryptu ASP
używającego ADO

Kombinacja ASP, VBScript oraz ADO pozwala na tworzenie złożonych stron WWW opartych o dane zapisane w bazie
danych Accessa 2000. W następnej części rozdziału przedstawię przykład zaczerpnięty z własnej praktyki.

Przykład: tworzenie strony WWW dostępnej dla członków grupy


Jeżeli chcesz stworzyć witrynę WWW dostępną dla określonej grupy użytkowników, chronioną przed niepowołanym
dostępem poprzez konieczność zalogowania się, Access 2000 oraz ASP są właściwym rozwiązaniem. Prowadzę lokalną
grupę użytkowników Accessa i Visual Basica w Nowym Jorku. Mamy własną witrynę WWW, która znajduje się pod
adresem www.nycaccessvb.com. Używa ona ASP do wyświetlania listy członków, listy spotkań i prowadzi bibliotekę
programów. Strony ASP mają połączenie do bazy danych zawierającej informacje o członkach. Dodatkowo członkowie
mogą po podaniu hasła uaktualniać informacje o sobie oraz przeglądać strony dostępne tylko dla nich, jak na przykład
forum o miejscach pracy.

Aplikacja ta pozwala ludziom, którzy podali właściwą nazwę użytkownika i hasło, na dostęp do systemu. Po zalogowaniu
użytkownika do zmiennej sesji przypisywany jest identyfikator użytkownika, uwalniając go od konieczności wprowadzania
własnych danych na kolejnych stronach witryny. Na koniec do bazy wpisywana jest bieżąca data jako data ostatniej wizyty.

Aplikacja uruchamia się, gdy użytkownik wczytuje stronę logowania klubu NYC Access VB. Strona ta przedstawiona jest
na rysunku 27.8.

Rysunek 27.8.
Okno logowania

Strona logowania jest zwykłą stroną HTML zawierającą formularz, który wywołuje plik ASP. Na wydruku 27.9
zamieszczony jest kod HTML użyty do utworzenia formularza.

Wydruk 27.9. Kod HTML do tworzenia kodu logowania


<form action="login.asp"
method="post" name="frmLogin">
<p align="right">ID <input type="text" size="15" name="txtID"></p>
<p align="right">Hasło<input type="password" size="15"
name="txtPass"></p>
<p align="right"><input type="submit" name="cmdOK"
490 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 491

value=" OK "> </p>


</form>

Po kliknięciu przez użytkownika przycisku OK uruchomiony zostanie plik login.asp. Skrypt ten sprawdza w bazie danych,
czy użytkownik znajduje się na liście członków. Baza zawiera tabelę z polami zawierającymi nazwę użytkownika, hasło,
datę ostatniego dostępu oraz inne pola. Na wydruku 27.10 zamieszczono treść pliku login.asp.

Wydruk 27.10. Plik ASP login.asp


<%@ LANGUAGE--"VBSCRIPT" %>

<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual InterDev 6.0">
<META HTTP-EQUIV="Content-Type" content="text/html;
charset=iso-8859-1">
<TITLE>Formularz logowania</TITLE>
</HEAD>
<BODY>
<BODY BGCOLOR=#FFFFFF>

<%
' Przeznaczenie: wszyscy użytkownicy muszą się zalogować
' Logowanie jest nieudane, jeżeli nie został wprowadzony prawidłowy
' identyfikator użytkownika lub hasło

' Zmienne
Dim rst
Dim strUserID
Dim strPass
Dim strSOL
Dim strConnect
Dim ado_OpenKeyset
Dim ado_LockOptimistic

' Argumenty dla obiektu recordset


ado_OpenKeyset=1
ado_LockOptimistic=3

' Przypisanie ciągu połączenia


strConnect="provider=Microsoft.Jet.OLEDB.4.O;" & _
"data source=D:\wwwroot\db\ch27.mdb"

' Pobranie danych z formularza do zmiennych


strPass=request.form("txtPass")
strUserID=request.form("txtID")

' Tworzenie wyrażenia SQL


strSOL="SELECT FName, LName, Email, lastLogin, pass, " & _
"Status FROM tblMembers WHERE (Email =' & " "' & strUserID & _
" "' & ")"

' Tworzenie obiektu rst


Set rst=server.createobject("ADODB.RECORDSET")

' Otwarcie obiektu rst


rst.open strSOL, _
strConnect, ado_OpenKeyset, ado_LockOptimistic

' Sprawdzenie, czy użytkownik podał identyfikator użytkownika i hasło


If strUserID="" or strPass="" then
Response.Write "Nie podałeś identyfikatora użytkownika " & _
"lub hasła. Proszę poprawić."
else
' jeżeli rst.eof (koniec pliku), to znaczy, że nie znaleziono
if rst.eof then
response.write "Nie ma takiego użytkownika w systemie !!!"
else
'Sprawdzenie, czy podano właściwe hasło
If rst("pass")= strPass Then
' Hasło prawidłowe
' Tworzymy stronę WWW
Response.Write "Witaj " & rst("FName") & _
" " & rst("LName")
Response.Write "<br>"
Response.Write "Ostatnio logowałeś się: " & rst("lastLogin")
Response.Write "<br><br>" & _
"<a href=" & chr(34) & "admin.htm" & chr(34) & _
">Aktualizacja" & "</a>danych konta "
Response.Write "<br> <a href=" & _
chr(34) & "job.htm" & chr(34) & _
">Forum o pracy </a> tylko dla członków"

' Ustaw czas ostatniego logowania


rst.update ("lastlogin"),Date()
' Ustawienie zmiennej sesji
Session("User") = strUserID
492 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

Else
' Nieprawidłowe hasło
response.write "Nazwa użytkownika: <strong>" & _
strUSerID & "</strong> jest OK, Złe hasło!!!"
end if
end if
end if
' Zamknięcie obiektu rst
rst.close
%>
</BODY>
</HTML>

Pierwszą czynnością wykonywaną przez skrypt zamieszczony na wydruku 27.10 jest przygotowanie zmiennych używane
w dalszej części skryptu. Następnie przy użyciu danych podanych przez użytkownika w formularzu tworzone jest
wyrażenie SQL. Do przechowywania nazwy użytkownika używana jest zmienna strUserId. Wyrażenie SQL, które
pobiera informacje o użytkowniku, wygląda następująco:
StrSQL="SELECT Fname, LName, Email, lastLogin, pass, " & _
"Status FROM tblMembers WHERE (Email=" & "'" & strUserId & "'" & ")"

Jak można zauważyć, kluczem głównym tabeli tblMembers jest pole Email. E-mail użytkownika jest również jego
identyfikatorem. Jeżeli użytkownik nie poda identyfikatora lub hasła, za pomocą metody Response.Write wyświetlane
jest ostrzeżenie pokazane na rysunku 27.9.

Rysunek 27.9.
Ostrzeżenie o braku
identyfikatora
użytkownika
lub hasła

Jeżeli użytkownik poda właściwą nawę użytkownika, skrypt sprawdza, czy podane jest właściwe hasło. Sprawdzenie to
przeprowadzane jest w wierszu:
If rst("pass")=strPass

Jeżeli hasło jest niewłaściwe, użytkownik jest o tym powiadamiany przy użyciu metody Response.Write (rysunek
27.10).

Jeżeli użytkownik wprowadzi właściwe hasło, w zmiennej sesji zapamiętywana jest nazwa użytkownika i uaktualniane jest
pole tabeli lastlogin. Poniższy fragment skryptu realizuje te czynności.
' Ustawienie daty ostatniej wizyty
rst.update("lastlogin"), Date()
' Ustawienie globalnej zmiennej sesji
Session("User") = strUserId
Rysunek 27.10.
Informacja
o błędnym haśle

Po autoryzacji użytkownika używamy metody Response.Write do utworzenia strony WWW tylko dla członków grupy.
Można również użyć metody Response.Redirect, aby skierować użytkownika na zupełnie inną stronę. Strona ta
pokazana jest na rysunku 27.11.

492 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 493

Rysunek 27.11.
Strona tylko dla
członków grupy

Po zalogowaniu użytkownika do systemu można dostarczyć do kolejnych stron wszystkie informacje o nim. Dodatkowo,
jedną z lepszych cech ASP jest możliwość edycji przez użytkownika informacji o sobie. W naszej sytuacji dajemy
użytkownikowi tylko możliwość zmiany hasła. Po zalogowaniu użytkownika do części witryny tylko dla członków
dostępna jest opcja zmiany własnych danych. Strona ta pokazana jest na rysunku 27.12.

Rysunek 27.12.
Strona zmiany hasła
przez członków
grupy

Jest to formularz HTML umożliwiający wprowadzenie i weryfikację hasła. Jej kod HTML przedstawiony jest na wydruku
27.11.

Wydruk 27.11. Formularz zmiany hasła


<form action= "changepass.asp" form method="POST" name="frmNew">
<p>Hasło<input type="password" size="20" name="txtPass"></p>
<p>Weryfikacja<input type="password" size="20" name="txtVer"></p>
<p><input type="submit" name="cmdOK" value="Wyślij"></p>
</form>

Formularz przedstawiony na wydruku 27.11 wywołuje plik changepass.asp, który uaktualnia hasło użytkownika i
potwierdza je. Wydruk 27.12 zawiera kod źródłowy pliku changepass.asp.

Wydruk 27.12. Plik changepass.asp


<%@ LANGUAGE="VBSCRIPT" %>
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual InterDev 1.0">
<META HTTP-EOUIV="Content-Type" content="text/html;
charset=iso-8859-1">
<TITLE>Zmiana hasła</TITLE>
</HEAD>
<BODY>

<%
' Przeznaczenie: sprawdzenie potwierdzenia hasła i zmiana bazy danych
' Jeżeli hasło nie jest identyczne w obu polach tekstowych, przerwij

' Deklaracje
Dim rst
Dim strPass
Dim strVerify
Dim strSOL
Dim strConnect
Dim ado_OpenKeyset
Dim ado_LockOptimistic

ado_OpenKeyset=1
ado_LockOptimistic=3

' Przypisanie ciągu połączenia


strConnect="provider=Microsoft.Jet.OLEDB.4.O;" & _
"data source=D:\wwwroot\db\ch27.mdb"
494 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

' Pobranie danych z formularza


strPass=request.form("txtPass")
strVerify=request.form("txtVerify")

' Sprawdzenie, czy zgadzają się wartości w polach


If strpass <> strVerify then
response.write "Nie zgadzają się wartości w " & _
" polach hasła ! <br>"
response.write "Proszę powtórzyć."
else
strSOL="SELECT pass, Status FROM tblMembers " & _
"WHERE (Email =" & "'" & Session("User") & "'" & ")"

' Utworzenie obiektu rst


Set rst=server.createobject("ADODB.RECORDSET")
rst.open strSOL, _
strConnect,ado_OpenKeyset,ado_LockOptimistic
If rst.eof then
response.write "Nie ma takiego użytkownika w systemie!!!"
else
rst.update ("pass"),strVerify
Response.Write "Hasło zostało zmienione, " & _
"proszę je zapamiętać !!"
end if
rst.close
end if%>
</BODY>
</HTML>

Kod z wydruku 27.12 nie różni się wiele od tego z wydruku 27.10. Na początku należy się upewnić, czy użytkownik wpisał
identyczne napisy do obu pól tekstowych i kontynuuje tylko w przypadku takiej zgodności. Następnie przy użyciu
zmiennej globalnej User tworzone jest wyrażenie SQL. Jest to przykład utrzymywania stanu sesji przez ASP. Nie ma
potrzeby pytać powtórnie użytkownika o jego identyfikator lub wywoływać skomplikowane i obciążające serwer programy
CGI-BIN, które potrafiłyby utrzymać stan sesji.

Po otwarciu obiektu recordset używamy metody Update w celu uaktualnienia hasła użytkownika w bazie danych na
serwerze WWW. Podczas następnego logowania użytkownika należy użyć nowego hasła. Rysunek 27.13 przedstawia
ekran potwierdzający zmianę hasła.

Rysunek 27.13.
Ekran
potwierdzający
zmianę hasła

Na tym zakończymy omawianie tego przykładu. Możesz odwiedzić witrynę http://www. nycaccessvb.com, aby przejrzeć
listę witryn WWW używających Accessa 97 lub 2000 jako silnika bazy danych.

Mam nadzieję, że ten przykład i cały rozdział pozwoli Ci rozpocząć tworzenie świetnych internetowych aplikacji Accessa
2000.

Publikacja w sieci z Accessa 2000 przy użyciu XML


Najprawdopodobniej natknąłeś się już na nowe słowo w technologii Internetu: XML lub Extensible Markup Language.
XML jest zorientowanym na dane standardem zapisu dokumentów i został zdefiniowany przez konsorcjum W3C.
Programiści internetowych baz danych powinni zainteresować się tym sposobem zapisu dokumentów. W tej części
rozdziału opiszemy dokumenty XML i użyjemy ich w aplikacji.

Podstawy XML
XML jest zbiorem reguł tworzenia opisowych znaczników identyfikujących dane, z których zbudowany jest dokument.
Mimo że XML jest podobny do HTML, to jest od niego o wiele bardziej rozbudowany. Za pomocą XML tworzy się
znaczniki, które używane w dokumencie dzielą go na logiczne fragmenty. Litera X w XML pochodzi od słowa Extensible
494 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 495

(rozszerzalny), ponieważ w przeciwieństwie do HTML, który ma ściśle zdefiniowany zbiór znaczników, zbiór znaczników
w XML jest nieomal nieograniczony. Znaczniki opisujące te dane tworzy się w momencie, gdy są one potrzebne. Ponieważ
programiści baz danych codziennie pracują z danymi, XML jest dla nich bardzo użyteczny.

Utwórzmy prosty dokument XML opisujący tabelę Klienci w bazie danych Northwind. Ponieważ XML oparty jest o zestaw
znaków Unicode, można do jego stworzenia użyć dowolnego edytora używającego ASCII lub Unicode. Aby rozpocząć
tworzenie dokumentu XML wpisz w edytorze poniższy wiersz:
<?xml version="1.0"?>

Jest to wiersz deklaracji sygnalizujący interpreterowi XML, że jest to dokument XML. Gdy Twoje dokumenty XML będą
bardziej skomplikowane, część deklaracji będzie bardziej złożona. Przykładowo można zadeklarować, jakie znaczniki są
dopuszczalne w dokumencie lub gdzie znajdują się deklaracje arkusza stylów. Na razie zajmiemy się tylko podstawami.

Po deklaracjach należy zdefiniować główny element. Jest on elementem, który będzie opisywany w dokumencie. W
dokumencie może występować tylko jeden taki element. Ponieważ opisujemy dane klientów, nasz element główny
nazywać się będzie <Customers>.

Następnie należy zdefiniować węzły potomne. Węzły potomne są elementami tworzącymi dane. Utworzymy węzeł
potomny do głównego, nazwanego <Customer>. Wewnątrz każdego węzła klienta mamy węzły potomne zawierające dane.
Te węzły mają nazwy zgodne z nazwami pól w tabeli Klienci z bazy danych Northwind. Przykład takiego pliku pokazany
jest na wydruku 27.13.

Wydruk 27.13. Prosty dokument XML, który opisuje klientów


<?xml version="1.0"?>
<Customers>
<Customer>
<CustomerID>ALFKI</CustomerID>
<CompanyName>Alfreds Futterkiste</CompanyName>
<ContactName>Maria Anders</ContactName>
<ContactTitle>Sales Representative</ContactTitle>
</Customer>
<Customer>
<CustomerID>ANATR</CustomerID>
<CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
<ContactName>Ana Trujillo</ContactName>
<ContactTitle>Owner</ContactTitle>
</Customer>
<Customer>
<CustomerID>ANTON</CustomerID>
<CompanyName>Antonio Moreno Taqueria</CompanyName>
<ContactName>Antonio Moreno</ContactName>
<ContactTitle>Owner</ContactTitle>
</Customer>
</Customers>

Teraz zapisz plik jako customers.xml.

Teraz możemy oddzielić dane od formatowania przy użyciu XML oraz Dynamic HTML. Wypełnimy tabelę HTML
danymi XML zapisanymi w pliku customers.xml. Możesz skorzystać z dostępnego w IE 4.0 i nowszych, łączenia danych z
pliku XML poprzez applet Javy. Wynik umieszczenia danych XML w tabeli HTML pokazany jest na rysunku 27.14. Aby
wczytać XML do strony WWW, utwórz prostą stronę zamieszczoną na wydruku 27.14.

Rysunek 27.14.
Dołączanie danych
XML do strony
HTML

Wydruk 27.14. Dołączanie danych XML w IE 4 i IE 5


<html>
<head>
<title>Dołączanie danych XML z pliku na dysku</title>
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
496 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

</head>
<! -Java Applet->
<APPLET code="com.ms.xml.dso.XMLDSO.class"
MAYSCRIPT id=xmldso WTDTH="100%" HEIGHT="20">
<PARAM NAME="URL" VALUE=" Customers.xml ">' +
</APPLET>
<p> Dołączanie danych XML z pliku na dysku </p>
<table id="table" border="2" width="100%"
datasrc="#xmldso" cellpadding="5">
<thead>
<tr>
<th>ID e/th>
<th>Name </th>
</head>
</tr>
<tr>
<td align="center" valign="top"><div datafld="Id Klienta"></td>
<td align="center" valign="top"><div datafld="Nazwa firmy"></td>
</tr>
</table>
</body>
</html>

Aby przetworzyć plik XML, należy użyć appletu Javy, który jest dostarczany razem z IE 4.0 (można również ściągnąć do
ze strony WWW Microsoftu). Dodaj fragment z APPLET z wydruku 27.14 do Twojego pliku HTML i ustaw właściwość
URL na ścieżkę lub URL do pliku XML. Następnie należy użyć prostego łączenia Dynamic HTML za pomocą znacznika
datasrc="#xmldso" w deklaracji tabeli, gdzie #xmldso jest nazwą obiektu z appletu Javy. Na koniec przypisz
właściwości datafld każdego pola tabeli nazwy węzłów potomnych z pliku XML. Gdy zmienisz zawartość pliku XML,
wynikowa strona również się zmieni.

Programowe tworzenie pliku XML


Ponieważ XML jest tak łatwy do tworzenia i używania w aplikacji, utwórzmy własną bibliotekę DLL ActiveX, która
utworzy kod XML. Za pomocą tej biblioteki można tworzyć na bieżąco pliki XML używane w witrynach WWW lub
aplikacjach.

Utwórzmy w VB 6.0 projekt ActiveX DLL o nazwie XML_TOOL z jednym modułem klasowym o nazwie Database.
Nasza klasa posiadała będzie tylko jedną metodę, CreateXML. Należy również ustawić w menu Tools, References
odwołanie do ADO 2.0. Metoda ta używa ADO do podłączenia się do bazy danych, otwarcia wyniku i zwrócenia danych
XML do klienta. Metoda ta wymaga trzech argumentów: nazwy głównego elementu, ciągu połączeniowego i wyrażenia
SQL, które należy wykonać. Metoda ta jest zamieszczona na wydruku 27.15.

Wydruk 27.15. Programowe tworzenie XML jako komponent VB


Public Function CreateXML _
(strEntity As String, strSOLStatement As String, _
strConnectionString As String) As String

' Funkcja tworzy XML z wyniku wykonania kwerendy.


' Używa Recordset ADO i zwraca wynik do aplikacji

Dim rst As ADODB.Recordset


Dim fld As ADODB.Field
Dim strReturn As String

On Error GoTo Proc_Err

Set rst = New ADODB.Recordset

' Otwarcie obiektu recordset opartego o wyrażenie SQL


' które jest przekazane do metody wraz z ciągiem połączeniowym

rst.Open strSQLStatement, StrConnectionString

' Rozpoczynamy tworząc nagłówek z numerem wersji


strReturn = "<?XML version= '1.0'?>"

If rst.EOF And rst.BOF Then


'Jeżeli nie ma danych tworzymy pusty element
strReturn = strReturn & vbNewLine & "<" & strEntity & "s/>"
Else
' Znacznik otwierający element
strReturn = strReturn & vbNewLine & "<" & strEntity & "s>"

'Pętla przebiegająca przez wynik zapytania i umieszczająca go w


' w pliku XML
Do Until rst.EOF
' Otwórz element
strReturn = strReturn & vbNewLine & "<" & strEntity & ">"

496 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 497

' Każde pole jest zapisywane do pliku


' Jeżeli chcesz mniej pól, wylicz je w wyrażeniu SQL

For Each fld In rst.Fields


strReturn = strReturn & vbNewLine & "<" & fld.Name & ">"
strReturn = strReturn & fld.Value
strReturn = strReturn & "</" & fld.Name & ">"
Next fld
' Zamknij element
strReturn = strReturn & vbNewLine & "</" & strEntity & ">"
' Przejście do następnego elementu
rst.MoveNext
Loop
' Znacznik kończący element
strReturn = strReturn & vbNewLine & "</" & strEntity & "s>"
End If

' Przepisz utworzony tekst do wyniku metody


CreateXML = strReturn

' Porządki
rst.Close
Set rst = Nothing

Proc_Exit:
Exit Function

Proc_Err:
' Prześlij błąd do aplikacji
Err.Raise Err, "XML DLL", Err.Description
Resume Proc_Exit

End Function

Teraz uruchomimy nasz komponent ActiveX. Po skompilowaniu DLL utwórz nową aplikację Visual Basica i ustaw
odwołanie do naszej biblioteki DLL. Program testujący metodę przedstawiony jest na wydruku 27.16. Trzeci parametr
wywołania (”Pubs”) jest nazwą DSN bazy danych na serwerze SQL.

Wydruk 27.16. Wywołanie komponentu utworzonego na wydruku 27.15


Private Sub cmdPrintXML Click()
Dim xml As XML_Tool.Database

Set xml = New XML Tool.Database


Debug.Print xml.CreateXML("Publishers", "Select * From Publishers",
"Pubs")
End Sub

Wynik działania programu jest następujący:


<?XML version= '1.0'?>
<Publishers>
<Publisher>
<pub_id>0736</pub id>
<pub_name>New Moon Books</pub name>
<city>Boston</city>
<state>MA</state>
<country>USA</country>
</Publisher>
<Publisher>
<pub_id>0877</pub_id>
<pub_name>Binnet & Hardley</pub_name>
<city>Washington</city>
<state>DC</state>
<country>USA</country>
</Publisher>
</Publishers>

Nasza aplikacja testująca drukuje kod XML w oknie uruchamiania, jednak można utworzyć plik XML przy użyciu
zwykłych operacji wejścia-wyjścia lub innej techniki. Użyjemy teraz komponentu na stronie ASP. W jednym z ostatnich
przykładów ładowaliśmy do strony HTML dane XML. Ten kod XML może być wbudowany w stronę WWW. Użyjmy
teraz naszego komponentu, aby dynamicznie utworzyć wbudowany w stronę kod XML, gdy użytkownik zażąda dostępu do
strony WWW. Za pomocą VBScript można załadować DLL ze strony WWW i dynamicznie utworzyć kod XML wyko-
rzystywany w aplikacji WWW. Poniższy kod tworzy taką samą jak poprzednio stronę WWW, jednak teraz jest dynamiczna i
tworzy XML na bieżąco.

Wydruk 27.17. Tworzenie XML w skrypcie ASP


<%
Dim xml
Dim strSOL
Dim strConnect
498 Część VIII ♦ Publikowanie w sieci za pomocą Accessa 2000

Dim strXML
Set xml = Server.Create0bject("XML Tool.Database")
strSQL="Select * from Customers "
strConnect="File Name=c:\jetweb.UDL;"
strXML= xml.CreateXML("Customer", cstr(strSOL), cstr(strConnect))
%>
<APPLET code="com.ms.xml.dso.XMLDSO.class"
MAYSCRIPT id=xmldso WIDTH="100%" HEIGHT="20">
<%=strXML%>
</APPLET>

Tworzenie wykresów przy użyciu formantu Wykres


Rozdział 25. zawiera wprowadzenie do komponentów sieciowych Office i wyjaśnia, jak używać ich w Accessie 2000 oraz
Visual Basicu. W rozdziale 26. objaśniliśmy sposób ich użycia na stronach dostępu do danych. Co zrobić, jeżeli
przeglądarka, której używasz, nie obsługuje formantów ActiveX? Formant Wykres pozwala na użycie rysunków GIF dla
przeglądarek nie obsługujących ActiveX.

Za pomocą prostej kwerendy przestawnej z bazy danych Northwind utworzymy niezwiązany formularz na stronie ASP.
Utworzymy plik global.asa, aby zarządzać plikami GIF (wydruk 27.18).

Wydruk 27.18. Tworzenie wykresu w pliku GIF na serwerze


<SCRIPT LANGUAGE="VBScript" RUNAT="Server">
Sub Session_OnStart
Session("nFiles") = 0
Set Session("FileSystem") = Create0bject("Scripting.FileSystemObject")
End Sub

Sub Session_OnEnd
Dim i

For i = 0 To Session("nFiles") - 1
Session("FileSystem").DeleteFile "D:\ntstuff\WebStuff\" &
Session("szFile" & i ), True
Next
End Sub
</SCRIPT>

W pliku ASP utworzymy tablicę aHeaders, w której umieszczamy nazwy nagłówków, w tym przykładzie cztery kwartały
roku podatkowego. Następnie po otwarciu wyniku ADO opartego na zapisanej kwerendzie krzyżowej o nazwie
qryQuarterlySales, wypełniamy tablicę aValues wartościami pól wyniku. Pełny kod przedstawiony jest na wydruku 27.19.

Wydruk 27.19. Praca z komponentem sieciowym Wykres z pakietu Office


<%@ language="vbscript" %>
<html>
<body>
<%
Dim ChartSpace1, c, aHeaders(3), aValues(3)
Dim rst

' Tworzenie tablicy nagłówków wykresu


aHeaders(0) = "01"
aHeaders(1) = "02"
aHeaders(2) = "03"
aHeaders(3) = "04"

' Otwarcie wyniku kwerendy krzyżowej z bazy Notrhwind


' i wpisanie jej wartości do słupków wykresu
Set rst=Server.Create0bject("ADODB.Recordset")
rst.Open "qry0uarterlySales", "File Name=" & Server.MapPath("Jet.UDL")

aValues(0) = rst![Otr 1]
aValues(1) = rst!(Otr 2]
aValues(2) = rst![Otr 3]
aValues(3) = rst![Otr 4]

' – Tworzenie niewidocznej wersji komponentu wykres


Set ChartSpace1 = Create0bject("OWC.Chart")
Set c = ChartSpacel.Constants

ChartSpacel.Border.Color = c.chColorNone
ChartSpacel.Charts.Add
ChartSpacel.Charts(0).Type = _
ChartSpacel.Constants.chChartTypeColumnClustered
ChartSpacel.Charts(0).SeriesColleCtion.Add
ChartSpacel.Charts(0).Series0ollection(0).Caption = "Sales"
ChartSpacel.Charts(0).Series0ollection(0).SetData _

498 D:\Kompakt !!!\Kompakt\Ksiazki 1 !\!done - Access 2000 - Księga eksperta\Access 2000 - Księga eksperta.doc
Rozdział 27. ♦ Publikowanie w sieci przy użyciu Accessa 2000 i Active Server Pages 499

c.chDimCategories, c.chDataLiteral, aHeaders


ChartSpacel.Charts(0).SeriesCollection(0).SetData _
c.chDimValues, c.chDataLiteral, aValues
ChartSpacel,Charts(0).HasLegend = True

'—- Pobranie nazwy tymczasowego pliku z global.asa


szFilename = Session("FileSystem").GetTempName & ".gif"

'—- Eksport pliku GIF z wykresu


ChartSpacel.ExportPicture "D:\ntstuff\WebStuff\" & _
szFilename, "gif", 600, 512

'—- Tworzenie łącza do pliku GIF


Response.Write "<img src= "' & szFilename
Session("szFile" & Session("nFiles")) = szFilename
Session("nFiles") = Session("nFiles") + 1
%>
</body>
</html>

You might also like