2.10. Oddělení dat od jejich zpracování

V řadě aplikací je vhodné využít možnosti oddělení dat od jejich obsluhy. Především je to situace, kdy se s programem již pracuje a přitom pokračuje jeho vývoj. Je vhodné, aby nová verze obsluhy nemohla zasáhnout do již zapsaných dat.

Postup je velmi jednoduchý. Tabulky s daty umístíme do samostatného souboru. Do druhého souboru tyto tabulky připojíme (Attach), viz obr. 32 a doplníme jejich zpracováním.

Obr. 32. Tabulky umístěné v databázi a tabulky připojené vazbou

 

Připojení tabulek do hlavního souboru provedeme příkazem File-Attach Table... z hlavní nabídky. Zvolíme typ souboru Microsoft Access a najdeme požadovaný soubor s daty. Systém nabídne seznam tabulek, viz obr. 33, které postupně připojíme.

 

Obr. 33. Připojení tabulek z databáze s daty

 

Celý systém bude pracovat vcelku bez problémů. Ty nastanou v okamžiku, kdy bude soubor s daty přemístěn do jiného adresáře. Např. při instalaci systému bude zadána jiná cesta pro jeho uložení. Protože při připojení tabulek je uložena celá cesta ke zdrojové databázi, nebude připojení tabulek pracovat a systém zhavaruje. Existuje sice možnost opravit připojení tabulek pomocí doplňkového modulu (Add-ins) Attachment Manager, viz obr. 34, požadovat tento úkon po uživateli je však dosti odvážné. Zejména, pokud se data nacházejí v několika samostatných datových souborech. To je vhodné zejména, pokud se mezi tabulkami nachází data plněná uživatelem a data dodávaná od autora databáze (typicky různé číselníky, nabídky a katalogy).

Obr. 34. Oprava připojení tabulek z datového souboru pomocí přídavného modulu

Naštěstí existuje možnost provedení opravy připojení tabulek programově. Následující výpis modulu MODPripojeniTabulek obsahuje proceduru PripojeniTabulek(), která zkontroluje připojení tabulek a pokud není správné, pokusí se o jejich opravu. Pro co největší obecnost byl algoritmus rozdělen do několika částí:

  1. Zkontroluje se správnost připojení tabulek a uloží informace o nesprávně připojených tabulkách a požadovaných zdrojových souborech.
  2. U nenalezených zdrojových souborů se systém pokusí najít je na jiných místech, zejména na stejné cestě jako obslužný soubor a na jiných logických zařízeních (discích).
  3. Pokud soubory nebyly nalezeny, je uživateli nabídnuta možnost najít je ručně, a to i v případě, že byly z nějakého důvodu přejmenovány.
  4. Pokud byly všechny zdrojové soubory nalezeny, provede systém opravu připojení tabulek. Chyby mohou nastat především tehdy, když v zadaném souboru není nalezena požadovaná tabulka. Tuto kontrolu je samozřejmě možno do programu doplnit.
Výsledkem funkce je logická hodnota informující o tom, zda bylo připojení opraveno správně nebo ne. To umožňuje zapojit funkci např. do makra AutoExec a podle jejího výsledku buď otevřít obsluhu nebo ohlásit chybu a program opustit. Na závěr se ještě zastavme u důvodu, proč systém hledá zdrojové soubory na jiných zařízeních (discích). Důvodem je možnost umístit úlohu na síťový disk, který může využívat více uživatelů, ale ne všichni ho nutně musí mít připojen (mapován) pod stejným označením (F:, G:, atd.). Systém tedy umožňuje připojit data i když se disk, na kterém se nacházejí, jmenuje jinak než u předchozího uživatele. Samozřejmostí je skutečnost, že současně může úlohu používat více uživatelů, ale jen v případě, že mají tento disk označen stejným způsobem. Jinak si budou vzájemně měnit připojení tabulek. Řešením je oddělení datových souborů od obslužného souboru a jejich umístění na různé disky. V tomto případě je výhodné, když si obslužný soubor nainstaluje každý uživatel na vlastní disk, takže k němu nikdo jiný nebude mít přístup. Aplikace se tak blíží přístupu klient-server, který je v současné době velmi častý. Tvůrce programových modulů je potřeba upozornit, že tabulky připojené do obslužné databáze se chovají jako dotazy. V programu je nutno je otevírat s parametrem DB_OPEN_DYNASET nebo DB_OPEN_SNAPSHOT. Z toho vyplývá, že není možno používat pro vyhledávání indexy a metodu SEEK, která poskytuje nejrychlejší výsledky.

 

Obr. 35. Umístění jednotlivých souborů v síťové aplikaci

Na obr. 35 je uveden příklad rozdělení jednotlivých souborů v síťové aplikaci. Na centrálním serveru jsou umístěny všechny datové soubory, ke kterým se připojují obslužné soubory umístěné na lokálních discích jednotlivých uživatelů. Rozdělení dat do více souborů umožňuje samostatnou distribuci částí dat s rozdílnou periodou aktualizace.

Pokud je to potřeba, je možno na lokálních počítačích umístit soubor s daty, která patří pouze jednotlivým uživatelům a nemají být přístupna ostatním uživatelům. Buď přímo do obslužného souboru nebo také do samostatného datového souboru.

Option Compare Database  'Usedatabase order for string comparisons
Option Explicit               'Declare all variables before the first usage

'*******************************************************************
' Systém pro automatickou opravu připojení tabulek z externích zdrojů
' Copyright (C) 1996 Ing. Radim Farana, CSc.
' *******************************************************************
 
' K provedení opravy připojení tabulek z externích zdrojů je potřeba
' připojit funkci PripojeniTabulek() do makropříkazu AutoExec.
' Pokud funkce vrátí hodnotu False, připojení nebylo úspěšné a nemá
' smysl pokračovat v práci se systémem.
' Funkce vyžaduje přítomnost funkce JmenoSOuboruAttach(Soubor),
' která se standardně nachází v modulu MODCestaKSouboru.
 
' Omezení systému
' -----------------
' Maximální počet externích tabulek = 100
' Maximální počet externích databází = 100
 
' Seznam procedur
' -----------------
'Private Function JmenoDB (Jmeno As String) As String
' ********************************************************
' Funkce vyzvedne z připojovacího řetězce název databáze
' ********************************************************
'Private Function OpravaConnect (Jmeno As String) As String
' ********************************************************
' Funkce vyzvedne z připojovacího řetězce název databáze
' ********************************************************
'Function PripojeniTabulek () As Variant
' *********************************************************
' Kontrola připojení tabulek z externích zdrojů
' Vrací logickou hodnotu informující, zda připojení proběhlo
' správně (True) nebo ne (False)
' Copyright (C) 1996 Ing. Radim Farana, CSc.
' *********************************************************
 
' Definice procedur
' -----------------
 
Private Function JmenoDB (Jmeno As String) As String
' ********************************************************
' Funkce vyzvedne z připojovacího řetězce název databáze
' ********************************************************
Dim S As String
Dim I As Integer
I = Len(Jmeno)
Do While I > 0
   S = Right(Left(Jmeno, I), 1)
   If S = "\" Or S = ":" Then
 JmenoDB = Right(Jmeno, Len(Jmeno) - I)
Exit Function
End If
I = I - 1
Loop
' Nepodařilo se najít začátek, nelze vrátit název databáze
JmenoDB = Jmeno
End Function
 
Private Function OpravaConnect (Jmeno As String) As String
' ********************************************************
' Funkce vyzvedne z připojovacího řetězce název databáze
' ********************************************************
Dim S As String
Dim I As Integer
I = Len(Jmeno)
Do While I > 0
  If Right(Left(Jmeno, I), 1) = "=" Then
  OpravaConnect = Right(Jmeno, Len(Jmeno) - I)
 Exit Function
End If
I = I - 1
Loop
' Nepodařilo se najít rovnítko, nelze vrátit název databáze
OpravaConnect = Jmeno
End Function
 
Function PripojeniTabulek () As Variant
' *********************************************************
' Kontrola připojení tabulek z externích zdrojů
' Vrací logickou hodnotu informující, zda připojení proběhlo
' správně (True) nebo ne (False)
' Copyright (C) 1996 Ing. Radim Farana, CSc.
' *********************************************************
Dim D As Database                                  ' Aktuální databáze
Dim TD As TableDef                               ' Aktuální definice tabulky
Dim I As Integer                                      ' Počítadlo
Dim P As Integer                                     ' Pomocné počítadlo
Dim PCesta As String                              ' Pomocná hledaná cesta
Dim S As String                                      ' Pomocný řetězec
Dim V As Variant                                   ' Pomocná proměnná
Dim OK As Variant                                 ' Hlášení o výsledku operace
Dim Jmeno As String                               ' Jméno hledaného souboru
Static TDFalse(1 To 100) As String         ' Názvy špatně připojených tabulek
Dim TDPoc As Integer                             ' Počítadlo názvů špatně připojených tabulek
Static DPuv(1 To 100) As String              ' Původní názvy zdrojových databází
Static DNov(1 To 100) As String              ' Nové názvy zdrojových databází
Dim DPoc As Integer                                ' Počítadlo převodu názvů databází
Const MaxPol = 100                                 ' Maximální počet uložených názvů
 
On Error GoTo ERR_P1
' Vynulování proměnných
For I = 1 To MaxPol
      TDFalse(I) = ""
      DPuv(I) = ""
      DNov(I) = ""
Next I
DPoc = 0
TDPoc = 0
PripojeniTabulek = False
 
' Kontrola připojení tabulek a nalezení chybných připojení
Set D = DBENGINE(0)(0)
For I = 0 To D.TableDefs.Count - 1
   Set TD = D.TableDefs(I)
   If TD.Connect <> "" Then
       ' Tabulka je připojena z externího zdroje
       S = TD.Connect
       S = OpravaConnect(S)
       V = Dir(S)
        If V = "" Then
           ' Původní zdroj nebyl nalezen
           If TDPoc < MaxPol Then
               TDPoc = TDPoc + 1
               TDFalse(TDPoc) = TD.Name
               V = 0
                OK = False
               Do While V < DPoc
                   V = V + 1
                   S = TD.Connect
                   If DPuv(V) = OpravaConnect(S) Then
                         OK = True
                   End If
               Loop
If Not OK Then
         If DPoc < MaxPol Then
             DPoc = DPoc + 1
             S = TD.Connect
             DPuv(DPoc) = OpravaConnect(S)
     Else
MsgBox Byla překročena velikost paměti pro nové připojení externích tabulek. Systém nelze provozovat.", 16, "Připojení 
tabulek"
                                         Exit Function
                                     End If
                                End If
                          Else
MsgBox Byla překročena velikost paměti pro nové připojení externích tabulek. Systém
nelze provozovat.", 16, "Připojení tabulek"
                                     Exit Function 
                                  End If
                            End If
                      End If
Next I
' Byly zkontrolovány připojené tabulky a nalezena chybná připojení
 
' Pokus o nalezení stejných databází na jiných cestách
If DPoc > 0 Then
      For I = 1 To DPoc
           If Len(DPuv(I)) < 4 Then
                ' soubor je moc krátký
             Else
                              P = 1
              Do While P > 0
                  Select Case P
         Case 1
' Kontrola původní cesty k připojení
PCesta = DPuv(I)
        Case 2
' Vyzkoušení aktuální cesty k databázi
             PCesta = Pracovni_Adresar() & "\" & JmenoDB(DPuv(I))
       Case 3
' Vyzkoušení jiných zařízení pro původní cestu
            PCesta = "C" & Right(DPuv(I), Len(DPuv(I)) - 1)
       Case 4
           PCesta = "D" & Right(DPuv(I), Len(DPuv(I)) - 1)
        Case 5
           PCesta = "E" & Right(DPuv(I), Len(DPuv(I)) - 1)
        Case 6
           PCesta = "F" & Right(DPuv(I), Len(DPuv(I)) - 1)
       Case 7
          PCesta = "G" & Right(DPuv(I), Len(DPuv(I)) - 1)
End Select
V = Dir(PCesta)
              If V = "" Then
                    ' Pokus nebyl úspěšný
                    P = P + 1
                        If P > 7 Then
                        P = 0
                        PCesta = ""
                       End If
                   Else
                        ' Pokus byl úspěšný
                        P = 0
                        DNov(I) = PCesta
                   End If
                Loop
                If PCesta = "" Then
                     ' Soubor nebyl nalezen
               Else
                     ' Soubor byl nalezen pod jiným názvem jednotky
                End If
           End If
        Next I
 End If
 
' Hledání automaticky nepřipojených tabulek ručně
I = 0
           Do While I < DPoc
            I = I + 1
                    If DNov(I) = "" Then
                    ' Databázi je potřeba hledat
If 6 = MsgBox("Systém potřebuje data z databáze '" & DPuv(I) & "',
ale nenašel ji, chcete ji najít ručně? (Pokud bude nabízený soubor prázdný, stiskněte tlačítko OK a pak najděte
požadovaný soubor.)", 4 + 32, "Připojení
tabulek") Then
              S = JmenoSouboruAttach(JmenoDB(DPuv(I)))
          If S = "" Then
' Databáze nebyla zadána
MsgBox "Hledaná databáze nebyla zadána. Systém nemůže dále 
pracovat.", 16,  "Připojení tabulek"
        Exit Function
           Else
                V = Dir(S)
                If V = "" Then
                 ' Hledaná databáze neexistuje
MsgBox "Zadaná databáze " & S & "nebyla nalezena. 
Systémnemůže dále pracovat.", 16, "Připojení tabulek"
                          Exit Function
                    Else
                        ' Hledaná databáze je v pořádku
                        DNov(I) = S
                   End If
             End If
         Else
MsgBox "Za těchto okolností není možno spustit systém.Práce 
končí.", 64, "Připojení tabulek"
              Exit Function
           End If
       End If
Loop
 
' Nové připojení tabulek
On Error Resume Next
For I = 1 To TDPoc
Set TD = D.TableDefs(TDFalse(I))
S = TD.Connect
S = OpravaConnect(S)
P = 0
V = ""
Do Until P = DPoc
              P = P + 1
                          If S = DPuv(P) Then
                             V = DNov(P)
                          End If
Loop
TD.Connect = ";DATABASE=" & V
Err = 0
TD.RefreshLink
If Err <> 0 Then
        ' Spojení se nepodařilo realizovat
            Select Case Err
                  Case 3011
MsgBox "Byla nalezena požadovaná databáze '" & V & "', ale 
chybí v ní tabulka '" & TD.SourceTableName & "'.
Systém nebude pracovat.", 16, "Připojení zdrojových
tabulek"
                   Case 3024
MsgBox "Je požadována
databáze '" & V & "', ale nebyla nalezena .
Systém nebude pracovat.", 16, "Připojení zdrojových
tabulek"
                 Case 3051
MsgBox "Byla nalezena
požadovaná databáze '" & V & "', ale  
je nastavena jen pro čtení. Systém nebude pracovat.", 16, "Připojení 
zdrojových tabulek"
          Case 3027
MsgBox "V systému je potřeba připojit zdrojové databáze, ale hlavní databáze je
jen pro čtení. Systém nebude pracovat.", 16, "Připojení zdrojových tabulek"
          Case Else
MsgBox "V systému je potřeba připojit zdrojovou databázi '" & V &
"', s tabulkou '" & TD.SourceTableName &"', ale nepodařilo se to. 
Systém nebude pracovat.", 16, "Připojení zdrojových tabulek"
        End Select 
        Exit Function
    End If
Next I
PřipojeniTabulek = True
Exit Function
 
'*******************************
' Obsluha chyby
'*******************************
ERR_P1:
      V = ""
      Resume Next
End Function