Fujitsu-Siemens
 
M A G A Z I N
 
SOFTWARE 
  Radenko S. Mikanović

MS Access - links

Kada dođete u situaciju da, posle male ispravke na Access aplikaciji morate da izgubite ceo dan (na putu do sedišta firme za koju ste radili program i nazad), ozbiljno razmislite o načinu na koji ste osmislili bazu i aplikaciju. Ako ste to sve stavili na jednu "gomilu" (u jedan fajl), posle čitanja ovog teksta to više nikada nećete uraditi.


Svak za sebe, svi za korisnika


bazi pripadaju samo tabele

Koncepcija odvajanja Access aplikacije od baze podataka zasniva se na tome da bazi pripadaju samo tabele, dok aplikaciju čine svi drugi Access objekti: Queries, Modules, Forms i Reports (Macros smo prevazišli, a Pages ne daju efekte koje bismo očekivali), što znači da morate imati najmanje 2 fajla (bazu-MDB i aplikaciju MDE). Složićete se da ovo i nije nešto komplikovano, a efekti se ogledaju u sledećem:
* povezivanje više aplikacija na istu bazu neće predstavljati problem, za razliku od nekih ideja o otvaranju iste aplikacije (MDE fajl) od strane više korisnika
* fleksibilno povezivanje kod slučaja više baza (poslovni periodi), prenosa i izmena na aplikaciji (izmene na aplikaciji i slanje update-a elektronskom poštom (ili FTP-om) ne utiče bazu podataka
* izbor baze na koju će se korisnik povezati, a prema njenom sinonimu (npr: 2001, 2002, 2003,...)
* korisnik aplikacije ne može da utiče na dizajn baze, a ne mora ni da zna ništa o njenoj lokaciji (slučaj korporativnog LAN-a)
* napredni korisnici mogu imaju svoje baze podataka na priručnim medijima (HDD MobileRack, floppy disk, ZIP drive, Flash drive i slično), što u današnje vreme mnogi koristiti već zahtevaju.


Obožavam Funkciju


Funkcija je objekat tipa procedure, ali daleko naprednija od svog prvog konkurenta Sub-procedure

Između navedenog problema i fleksibilnog rešenja ima mnogo puteva i puteljaka, a ja vam predlažem da pođete mojim, sigurnim i utabanim putem. Na tom putu, iskoristiću vaše vreme na par minuta, da bih vam skrenuo pažnju na jedan od najjednostavnijih objekata, koje možete da kreirate i kontrolišete i sa manjim iskustvom, ali efekte ćete sagledati tek 2-3 godine rada. Činjenica je da objektna orijentacija (OO) u programiranju daje nesagledive prednosti, ali neiskusan programer će do OO teško da dopre bez dobrog poznavanja mogućnosti tako jednostavnih objekata kao što su funkcije. Funkcija je objekat tipa procedure, ali daleko naprednija od svog prvog konkurenta Sub-procedure, što ću pokušati da odbranim u par redova:
* prvo, procedura Function vraća vrednost, što se može koristi i u cilju ispitivanja korektno odrađenog zadatka
* drugo, procedura Function se može koristiti u događaju (Event) grafičkog objekta, što predstavlja prvi korak u smanjenju obima kooda i centralizovanju događaja, pa npr. svojstvo Click tastera "cmdOpen" može da ima vrednost '=OpenForm("Options")' i unosi se preko Property prozora
* Pogled na moje aplikacije, rađene u proteklih 10 godina, govori da - ja sve više koristim funkcije, a Sub procedure samo u malom broju događajima objekata gde se ne zahteva naprednija tehnika.
Navešću prost primer - funkciju OpenForm za otvaranje forme:
Public Function OpenForm(myForm As String, _
Optional myCriteria As String = "", _
Optional dMOD As Integer = 1, _
Optional wMOD As Integer = 0, _
Optional MyArgs As String = "")
'Copyright©1998, Mikac@InfoSKY.net
On Error GoTo Err_OpenForm
'Normal - myMode=0; Design - myMode=1; Preview - myMode=2; FormDS - myMode=3
' dMOD
' acFormAdd = 0; acFormEdit = 1; acFormReadOnly = 2; acFormDS = 3;
' acFormPropertySettings = -1
' wMOD
' acHidden=1; acIcon=2; acNormal=0; acWindowNormal=0; acDialog 3

DoCmd.OpenForm myForm, 0, , myCriteria, dMOD, wMOD, MyArgs
OpenForm = True
Exit_OpenForm:
Exit Function

Err_OpenForm:
If Err.Number = 3075 Then
myCriteria = ""
Resume
End If
Resume Exit_OpenForm
End Function

Dakle, gde god mi u aplikaciji zatreba otvaranje neke postojeće forme, koristim ovu funkciju, pa ako nešto ne radi kako treba - zna se gde treba ispravljati. I sami možete razviti sličnu funkciju za otvaranje objekata tipaReports.


Univerzalne funkcije za link(ovanje) tabela


Evo nas opet na glavnoj temi, koju ćemo rešiti kroz tri funkcije: jednu za povezivanje i dve za prekid veza, aplikacije sa Access bazom po Jet konceptu, gde verzija JetEngine nije od značaja (Access 2.0 = Jet 2.0, Access95 = Jet 3.0, Access 97 = Jet 3.5, Access2000/XP = Jet 3.6), jer Access koristi driver za pristup bazama svih verzija: Microsoft Jet 4.0 Database Engine Driver. Tabela se linkuje samo u cilju uticaja na podatke, ali ne i dizajna i/ili formatizovanja, pa su, u pristupu ovim tabelama, na raspolaganju samo komande za tu namenu.
Funkcija Link2DB, koja je u nastavku prikazana, služi za povezivanje (Link) aplikacije na sve tabele (izuzem sistemskih) određene baze podataka, tj. svim tabelama za editovanje podataka. U osnovi, koristi se ideja da se u aplikaciji kreira tabela sa linkom na izvor podataka (tabelu u drugoj bazi). Ako tabela sa tim imenom već postoji u aplikaciji - biće obrisana, pa treba voditi računa o imenovanju tabela koje u aplikaciji eventualno moraju da se koriste (tabele za podešavanje opcija i slično), ali i kod povezivanja na baze koje mogu imati istoimene tabele.
Argumenti funkcije Link2DB:
dbFN - database file name (npr: c:\my documents\data.mdb")
dbPASS - pristupni password baze podataka, a ako baza nema password treba poslati prazan string ""
Sinonim - je drugo, javno ime, baze (npr: podaci o klijentima), za poruku korisniku u slučaju greške pri povezivanju
Vis - logička vrednost True/False kojom se određuje vidljivost "progress bar"-a za vreme povezivanja sa bazom
Public Function Link2DB(dbFN As String, _
dbPASS As String, _
Optional Sinonim As String, _
Optional Vis As Boolean = False) As Boolean
'Copyright©1998, Mikac@InfoSKY.net
Dim wsp As Workspace
Dim dbs As Database, dbsAnother As Database
Dim tdf As TableDef, dbt As TableDef
Dim i As Integer, n As Integer

Set dbs = CurrentDb()
Set wsp = CreateWorkspace(0, "admin", "", dbUseJet)

Dim MyConnect As String
On Local Error GoTo Link2DBErr
Set dbsAnother = wsp.OpenDatabase(dbFN, False, False, _
"MS Access;PWD=" & dbPASS & ";DATABASE=" & dbFN)
i = 0
n = dbs.TableDefs.Count
For Each tdf In dbsAnother.TableDefs
i = i + 1
y = SysCmd(acSysCmdInitMeter, "Link to DB:", n)
If Left(tdf.Name, 4) <> "MSys" Then
If Vis Then y = SysCmd(acSysCmdUpdateMeter, 100 * i / n)

On Local Error Resume Next
dbs.TableDefs.Delete tdf.Name

On Local Error GoTo Link2DBErr
Set dbt = dbs.CreateTableDef(tdf.Name)

dbt.Connect = "MS Access;PWD=" & dbPASS & ";DATABASE=" & dbFN
dbt.SourceTableName = tdf.Name

dbs.TableDefs.Append dbt
End If
Next
Link2DB = True

Link2DBexit:
wsp.Close
y = SysCmd(acSysCmdClearStatus)
Set dbs = Nothing
Set dbsAnother = Nothing
Exit Function

Link2DBErr:
Select Case Err.Number
Case 3031 'pass
MsgBox "Nekorektan Password za povezivanje na: '" & Sinonim & "'", vbCritical, "Opss..."
Case 3024, 3044 'file
MsgBox "Ne postoji fajl za povezivanje sa: '" & Sinonim & "'", vbCritical, "Opss..."
Case 3045 'open in exclusive mode
MsgBox "Baza za povezivanje '" & Sinonim & "' otvorena u Exclusive modu." & _
vbCrLf & "Promenite mod pristupa ili zatvorite odnosnu bazu.", vbCritical, "Opss..."
Case Else
MsgBox Error
End Select

Link2DB = False
Resume Link2DBexit
End Function

Funkcija DisconnectDB neophodna je za prekid uspostavljenih linkova sa bazom podataka, a treba je koristiti kada korisnik aplikacije prekida linkove prema jednoj konkretnoj bazi podataka
Public Function DisconnectDB(dbFN As String, _
Optional Sinonim As String = "", _
Optional Vis As Boolean = False) As Boolean
'Copyright©1998, Mikac@InfoSKY.net
Dim dbs As Database
Dim tdf As TableDef, dbt As TableDef
Dim i As Integer, n As Integer
Set dbs = CurrentDb
n = dbs.TableDefs.Count
y = SysCmd(acSysCmdInitMeter, "Link to DB:", n)
For i = n - 1 To 0 Step -1
Set tdf = dbs.TableDefs(i)
If InStr(LCase(tdf.Connect), LCase("DATABASE=" & dbFN)) > 0 Then
If Vis Then y = SysCmd(acSysCmdUpdateMeter, 100 * i / n)
On Local Error GoTo DisconnctDBErr
dbs.TableDefs.Delete tdf.Name
End If
Next

DisconnctDBexit:
y = SysCmd(acSysCmdClearStatus)
dbs.TableDefs.Refresh
Set dbs = Nothing

DisconnectDB = True
Exit Function

DisconnctDBErr:
MsgBox "Greška (" & Err.Number & ") pri raskidu sa sa: '" & Sinonim & "'" & vbCrLf & "Tabela: " & Chr(34) & tdf.Name & Chr(34) & ", nije na raspolaganju!", vbCritical, "Opss..."
MsgBox Error
DisconnectDB = False
Resume DisconnctDBexit
End Function
Sledeća, i poslednja, funkcija je BreakAllLinks, a predstavlja najbrži način raskidanja svih linkova koji su u aplikaciji uvedeni za vreme rada korisnika. Dobro će poslužiti kada korisnik izlazi iz aplikacije u kojoj ste koristili linkove na više baza podataka. Zaostali linkovi iz aplikacije na tabele baze podataka su osetljiva mesta za "razbijanje" lokacije i pristupnih šifara baza podataka, kao i otkrivanje primenjene koncepcije.
Public Function BreakAllLinks(dbs As Database, _
Optional Vis As Boolean = False) As Boolean
'Copyright©1998, Mikac@InfoSKY.net
Dim tdf As TableDef, dbt As TableDef
Dim n As Long
n = dbs.TableDefs.Count
y = SysCmd(acSysCmdInitMeter, "Link to DB:", n)
For i = n - 1 To 0 Step -1
Set tdf = dbs.TableDefs(i)
If tdf.Connect <> "" Then
If Vis Then y = SysCmd(acSysCmdUpdateMeter, 100 * i / n)
On Local Error GoTo BreakAllLinksErr
dbs.TableDefs.Delete tdf.Name
End If
Next

BreakAllLinksExit:
y = SysCmd(acSysCmdClearStatus)
dbs.TableDefs.Refresh
Set dbs = Nothing
DoCmd.Close acForm, "_progress_"
BreakAllLinks = True
Exit Function

BreakAllLinksErr:
Resume BreakAllLinksExit
End Function


Rezime


Pokazao sam vam kako aplikacija može da se poveže sa izvorom podataka (bazom), što predstavlja tek početak rada na ideji linkovanja. U cilju jednostavnosti prikazao sam samo Jet pristup, ostavljajući ODBC pristup za kasnije. Linkovanje Access aplikacija sa Access bazom nije moguće preko ODBC-a, ali iz VisualBasic aplikacija se čak i preporučuje. ODBC omogućava široki spektar drivera za pristup različitim formatima izvora podataka, od najjednostavnijih takstualnih (*.txt, *.csv), preko prevaziđenih XBase izvora (*.dbf, *.db), pa do SQL Servera (Microsoft, InterBase, mySQL). Još nešto o čemu treba razmišljati je povezivanje na tabele baza u kojima je aktiviran sigurnosni sistem korisnika i dozvola. Pristup je nešto složeniji, ali tema "sigurnosni sistem JetEngine" traži daleko više prostora.
Iako to može da zvuči suviše kompleksno, Access omogućava i linkovanje aplikacija, gde se iz radne aplikacije poziva funkcija, procedura ili klasa iz neke druge. Primenjujući povezivanje aplikacija po AddIns ili References metodi, funkcije dobijaju još više na značaju, ali je daleko važnije savladati filozofiju objektno orijentisanog programiranja i iskoristiti veliku filozofiju u za male i praktične primere od značaja za korisnika aplikacije. O tome u nekom sledećem članku.

Verzija za štampu

 

VRH STRANE

(c) 2003 OMEGA - sva prava zadržana