Opis problemu:
Każda baza MsAccess z czasem 'puchnie'. Jest to normalny efekt operacji tymczasowych, które w Accessie działają tak, że zajmują przestrzeń, a potem jej nie zwalniają. Nawet kasowanie rekordów (lub całych obiektów, jak np. tabele) nie zmniejsza romiaru bazy, tylko markuje je jako usunięte. Defragmentacja usuwa zalegające resztki i przywraca nominalny rozmiar pliku MDB.
Istnieje jednak pewien problem, który wprawdzie został usunięty w Accessie 2000, jednak ciągle dotyczy wcześniejszych wersji. Access 97 nie pozwala na defragmentację bieżącej bazy z poziomu kodu. To istotna wada, bo od czasu do czasu każdą bazę należy zdefragmentować. Można wprawdzie gdzieś na pulpicie zrobić dodatkową ikonkę, która po kliknięciu wywoła defragmentację bazy, ale... Po pierwsze nie jest to zawsze możliwe ani wygodne (np. gdy wysyłamy bazę w postaci pliku bez instalacji), a po drugie praktyka uczy, że jeśli nie można tej opcji zawrzeć w programie, to użytkownik nie będzie o niej pamiętał ani jej używał. Zwłaszcza, że dla niego efekt działania defragmentacji jest raczej mało zrozumiały, skoro po niej wszystko tak samo działa jak wcześniej.
Jednak każdy, kto pisze w Accessie wie, że defragmentacja redukuje rozmiar bazy, przyśpiesza jej działanie i zwiększa niezawodność aplikacji. A zatem jest użyteczna i warto ją stosować. Zostaje tylko pytanie, jak zdefragmentować bazę, którą właśnie używamy?
Rozwiązanie:
Mimo, że nie spotkałem się z idealną metodą defragmentacji bieżącej bazy w Accessie 97, to jednak jest kilka sposobów, które w lepszy lub gorszy sposób radzą sobie z tym problemem.call Shell("C:\defrag.bat", 0) DoCmd.QuitNie trudno się domyśleć, co taki plik BAT powinien zawierać, ale dla porządku przytoczmy jego przykładową zawartość:
C:\OFFICE\MSACCESS.EXE D:\Bazy\Baza.mdb /compact C:\OFFICE\MSACCESS.EXE D:\Bazy\Baza.mdbMożna także budować plik BAT dynamicznie, pozwoli to nam uniezależnić się od nazwy bazy i konfiguracji Accessa. Funkcja
SysCmd(acSysCmdAccessDir)
określa katalog, w którym znajduje się plik msaccess.exe,
a CurrentDb.Name
zwraca nazwę bieżącej bazy danych. Oto przykładowa procedura
defragmentacji bieżącej bazy oparta na dynamicznie budowanym pliku BAT:
Dim temp, NumPliku NumPliku = FreeFile Open "C:\defrag.bat" For Output As #NumPliku Print #NumPliku, """" & SysCmd(acSysCmdAccessDir) & "MSACCESS.EXE "" """ & CurrentDb.Name & """ /compact " Print #NumPliku, """" & SysCmd(acSysCmdAccessDir) & "MSACCESS.EXE "" """ & CurrentDb.Name & """" Close #NumPliku temp = Shell("C:\defrag.bat", 0) DoCmd.Quit
To prosty sposób, ale ma wadę: Niezbyt ładnie wygląda takie automatyczne zamykanie i otwieranie kolejnych instancji Accesa.
Metoda, wykorzystująca opcję defragmentacji, dostępną
z menu Accessa. Jak wiadomo opcja ta potrafi zdefragmentować bieżącą bazę,
ale tylko wtedy, jeśli zostanie wywołana bezpośrednio z menu, a nie z programu.
Spotkałem się z pomysłem, że można wysłać sekwencję klawiszy za pomocą
akcji SendKeys
, która będzie symulowała naciśnięcie odpowiedniej opcji
menu. Opcja raczej z dziedziny 'ratuj się kto może', ale przy pewnych założeniach
jest do przyjęcia. Osobiście jednak odradzam stosowanie SendKeys wszędzie
tam, gdzie można tego uniknąć ze względu nieprzewidywalność takich działań
przy różnych konfiguracjach Accessa.
Jest inny sposób wywołania tej opcji, bez SendKeys. Metoda polega na tym, że budujemy własny pasek narzędziowy i wyświetlamy go w taki sposób, żeby wyglądał trochę jak formularz z przyciskami poleceń. To moja ulubiona metoda defragmentacji bieżącej bazy. Przykład Defrag3.zip pokazuje jak prosto wykonać taką opcję w praktyce.
Krzysztof Pozorek