Access

 MS Access & XML & Baza miejscowości i ulic TERYT.

Krajowy Rejestr Urzędowy Podziału Terytorialnego Kraju (TERYT)

Klasa clsTeryt. Przygotowanie tabel (relacji) na pobranie danych z Rejestru TERYT.

• Stan na dzień 03 marca 2018 roku

Główny Urząd Statystyczny (GUS) umożliwia pobranie z bazy Krajowego Rejestru Urzędowego Podziału Terytorialnego Kraju Pliki pełne rejestru TERYT. w formacie XML oraz CSV i kodowaniu UTF-8, poniższych katalogów:

  • TERC - system (zbiór) identyfikatorów i nazw jednostek podziału terytorialnego.
  • SIMC - system (zbiór) identyfikatorów (urzędowych) i nazw miejscowości.
  • ULIC - system (zbiór) identyfikatorów i nazwy ulic.
  • WMRODZ - zbiór (wykaz) symboli i nazw rodzajów miejscowości.

Potrzebne tabele MS Access

Na poprzednich stronach • Zbiór WMRODZ, • Zbiór TERC, • Zbiór SIMC, • Zbiór ULIC przedstawiłem sposób przetwarzania plików *.XML za pomocą biblioteki Microsoft XML,v6.0. Dla dwóch największych plików zawierających zbiór SIMC oraz zbiór ULIC biblioteka Microsoft XML,v6.0 niezbyt się sprawdziła ze względu na bardzo długi czas przetwarzania i zapisu danych do tabel. Dlatego w celu pobranie danych z tych plików zostały użyte wbudowane funkcje tekstowe VBA.

Według mojego projektu mającego na celu zapis wszystkich danych w „Relacyjnej bazie danych MS Access” dla każdego pliku trzeba utworzyć co najmniej jedną tabelę:

Plik WMRODZ.xml wymaga jednej tabeli:
• tblWMRodz,
Plik SIMC.xml wymaga czterech tabel:
• tblRodz_Gmi,
• tblWojewodztwa,
• tblPowiaty,
• tblTERC_Gminy,
Plik TERC.xml wymaga jednej tabeli:
• tblSIMC_Miejscowosci,
Plik ULIC.xml wymaga dwóch tabel:
• tblULIC_Nazwy,
• tblULIC_Ulice,

Wszystkie tabele powinny zawierać indeks podstawowy (Primry Key) i zostać połączone Relacjami wymuszającymi integralność danych. Wszystkie pola tabel, za wyjątkiem pola tNazwa_2 w tabeli tblULIC_Nazwy, są wymagane (muszą zawierać dane).
Najprościej jest dla każdej tabeli napisać procedurę, za pomocą której utworzymy tabelę, dodamy do niej pola, ustawimy wymagane właściwości pól tabeli. Mając utworzone tabele ustawiamy Relacje pomiędzy polami tabel i po robocie.

Słów kilka o module klasy

Zamiast wielokrotnie pisać taki sam, lub bardzo podobny kod dla 8-miu tabel, łatwiej i prościej będzie utworzyć moduł klasy (klasę) clsTeryt, zawierającą właściwości i metody za pomocą których w prosty sposób będziemy mogli wykonać wyżej opisane czynności.
Aby wstawić do naszego projektu moduł klasy należy w oknie edytora VBA wybrać z menu pozycję „Insert” i następnie kliknąć na podmenu „Class Module”.

Wstawianie modułu klasy z menu

lub po kliknięciu prawym przyciskiem myszy w oknie Eksplorator projektu „Project” wybrać z menu podręcznego pozycję „Insert”, a potem pozycję „Class Module”.

Wstawianie modułu klasy z menu podręcznego

Następnie w oknie właściwości nowo wstawionego modułu klasy „Properties Class1” nadajemy właściwości Name wartość clsTeryt. Od tej pory będziemy się mogli odwoływać do naszej klasy za pomocą jej nazwy clsTeryt.

Klasa clsTeryt

Poniżej przedstawiam spis metod jakie oferuje klasa clsTeryt, za pomocą których możemy utworzyć nową tabelę, dodać do niej nowe pola określonego typu i rozmiaru (dla pól tekstowych), utworzyć klucz podstawowy tabeli oraz utworzyć indeksy na wybranych polach. Pomiędzy tabelami możemy utworzyć Relacje wymuszające integralność referencyjną danych tj. „kaskadową aktualizację pól pokrewnych” oraz „kaskadowe usuwanie rekordów pokrewnych”.

Metody klasy clsTeryt

• Metoda

terytCreateTable(sTableName As String) As Boolean

tworzy nowy obiekt TableDef, (nową tabelę o nazwie sTableName). Należy zauważyć, że tabela ta nie jest jeszcze zapisana w bazie, więc nie może być widoczna w oknie bazy danych.

• Metoda 

terytCreateField( _
                          sFieldName As String, _
                          iType As Long, _
             Optional lSize As Integer = 0, _
             Optional fRequired As Boolean = True, _
             Optional fAllowZeroLength As Boolean = False) As Boolean

tworzy nowy obiekt Field określonego typu i rozmiaru (dla pola tekstowego), ustawia właściwość RequiredAllowZeroLength, następnie dołącza obiekt Field do kolekcji Fields obiektu TableDef (m_tdf). Innymi słowy, tworzy nowe pole sFieldName o określonym typie iType i rozmiarze lSize w tabeli i określa, czy pole to jest Wymagane (fRequired) tzn. użytkownik musi wpisać jakieś dane oraz czy dozwolony jest ciąg zerowej długości "" (fAllowZeroLength) tzn. użytkownik nie zna danych, ale wpisuje "" co oznacza, że pole zostało edytowane i nie zawiera wartości Null.

• Metoda 

terytAppendTable() As Boolean

dołącza obiekt TableDef (m_tdf) do kolekcji TableDefs obiektu Database (m_dbs). Tabela m_tdf o nazwie sTableName zostaje zapisana w bazie i jest widoczna w oknie bazy danych.

• Metoda 

terytCreateIndex( _
                          sFieldName As String, _
             Optional fPrimary As Boolean = False, _
             Optional fUnique As Boolean = False) As Boolean

tworzy nowy obiekt Index typu Podstawowy, Unikatowy (bez Duplikatów) lub Indeks (Duplikaty OK). Utworzony obiekt Index dołącza do kolekcji Indexes obiektu TableDef (m_tdf).

• Metoda 

terytCreateIndexMulti( _
                          sFieldName As String, _
             Optional sFieldName1 As String = "", _
             Optional sFieldName2 As String = "", _
             Optional fPrimary As Boolean = False, _
             Optional fUnique As Boolean = False) As Boolean

tworzy nowy, wielopolowy (maksymalnie 3 pola) obiekt Index typu Podstawowy, Unikatowy (bez Duplikatów) lub Indeks (Duplikaty OK). Utworzony obiekt Index dołącza do kolekcji Indexes obiektu TableDef (m_tdf).

• Metoda 

terytCreateRelation( _
                          sPrimaryTableName As String, _
                          sPrimaryFieldName As String, _
                          sForeignTableName As String, _
                          sForeignFieldName As String, _
             Optional fUpdateCascade As Boolean = False, _
             Optional fDeleteCascade As Boolean = False) As Boolean

tworzy obiekt Relation pomiędzy polem sPrimaryFieldName tabeli podstawowej sPrimaryTableName i polem sForeignFieldName tabeli obcej sForeignTableName zapewniając integralność referencyjną. Następnie tworzy obiekt Field kolekcji Fields należącej do nowego obiektu Relation i dołącza obiekt Field do kolekcji Fields obiektu Relation. Ustawia atrybuty, wymuszające integralność referencyjną UpdateCascade („kaskadowo aktualizuj pola pokrewne”) lub (i) RelationDeleteCascade („kaskadowo usuń rekordy pokrewne”) tak by zmiany, lub usuwanie rekordów z powiązanych pól zostały wykonane z zachowaniem reguł. Utworzony obiekt Relation dołączany jest do kolekcji Relations obiektu Database (m_dbs).

• Metoda 

terytDeleteAllRelations() As Boolean

usuwa wszystkie relacje w obiekcie Database m_dbs.

• Metoda

terytDeleteTable(sTableName As String) As Boolean

usuwa tabelę sTableName. Przed usunięciem tabeli sTableName sprawdza, czy usuwana tabela jest powiązana relacjami z innymi tabelami. Jeżeli tak, to usuwa wszystkie relacje, którymi powiązana jest tabela sTableName z innymi tabelami w obiekcie Database (m_dbs).

Właściwości klasy clsTeryt

• Właściwość

Property Get prpTableExists(sTableName As String) As Boolean

sprawdza w kolekcji TableDefs obiektu Database (m_dbs), czy tabela sTableName istnieje.

Kod klasy clsTeryt

Zastosowanie metod klasy clsTeryt

Wykorzystamy większość metod klasy clsTeryt by utworzyć wszystkie potrzebne tabele na przyjęcie danych z Plików pełnych rejestru TERYT. Po utworzeniu tabel za pomocą metody .terytCreateRelation(...) utworzone zostaną wszystkie potrzebne relacje pomiędzy utworzonymi tabelami.

02. Klasa clsTeryt. Tworzenie wszystkich tabel i relacji pomiędzy tabelami.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
Private Sub btnCreateTable_Click()
On Error GoTo Err_Handler
Dim cls As clsTeryt
 
Set cls = New clsTeryt
  With cls
    .terytDeleteTable "tblWMRodz"
      .terytCreateTable "tblWMRodz"
      .terytCreateField "ID_RM", dbText, 2
      .terytCreateField "tNazwa_RM", dbText, 100
      .terytCreateField "tStan_Na", dbText, 10
    .terytAppendTable
    ' utwórz Indeks Primary
    .terytCreateIndex "ID_RM", True
    '==================================================
    .terytDeleteTable "tblRodz_Gmi"
    .terytCreateTable "tblRodz_Gmi"
      .terytCreateField "ID_RG", dbText, 1
      .terytCreateField "tNazwa_RG", dbText, 100
      ' dodatkowe, skrótowe pole opisowe
      .terytCreateField "tSkrot_RG", dbText, 21
    .terytAppendTable
    ' utwórz Indeks Primary
    .terytCreateIndex "ID_RG", True
    '==================================================
    .terytDeleteTable "tblWojewodztwa"
    .terytCreateTable "tblWojewodztwa"
      .terytCreateField "ID_Woj", dbText, 2
      .terytCreateField "tWojewodztwo", dbText, 100
      .terytCreateField "tNazwa_Dod", dbText, 50
    .terytAppendTable
    ' utwórz Indeks Primary
    .terytCreateIndex "ID_Woj", True
    '==================================================
    .terytDeleteTable "tblPowiaty"
    .terytCreateTable "tblPowiaty"
      .terytCreateField "ID_Pow", dbText, 4
      .terytCreateField "Id_Woj", dbText, 2
      .terytCreateField "tPowiat", dbText, 100
      .terytCreateField "tNazwa_Dod", dbText, 50
    .terytAppendTable
    ' utwórz Indeks Primary
    .terytCreateIndex "ID_Pow", True
    ' utwórz Indeks (duplikaty OK)
    .terytCreateIndex "Id_Woj"
    '==================================================
    .terytDeleteTable "tblTERC_Gminy"
    .terytCreateTable "tblTERC_Gminy"
      .terytCreateField "ID_Gmi", dbText, 7
      .terytCreateField "Id_Pow", dbText, 4
      .terytCreateField "Id_RG", dbText, 1
      .terytCreateField "tNazwa", dbText, 100
      .terytCreateField "tNazwa_Dod", dbText, 50
      .terytCreateField "tStan_Na", dbText, 10
    .terytAppendTable
    ' utwórz Indeks Primary
    .terytCreateIndex "ID_Gmi", True
    ' utwórz Indeksy (duplikaty OK)
    .terytCreateIndex "Id_Pow"
    .terytCreateIndex "Id_RG"
    '==================================================
    .terytDeleteTable "tblSIMC_Miejscowosci"
    .terytCreateTable "tblSIMC_Miejscowosci"
      .terytCreateField "ID_Sym", dbText, 7
      .terytCreateField "Id_Gmi", dbText, 7
      .terytCreateField "Id_RM", dbText, 2
      .terytCreateField "tMZ", dbText, 1
      .terytCreateField "tNazwa", dbText, 100
      .terytCreateField "tSymPod", dbText, 7
      .terytCreateField "tStan_Na", dbText, 10
    .terytAppendTable
    ' utwórz Indeks Primary
    .terytCreateIndex "ID_Sym", True
    ' utwórz Indeksy (duplikaty OK)
    .terytCreateIndex "Id_Gmi"
    .terytCreateIndex "Id_RM"
    .terytCreateIndex "tNazwa"
    '==================================================
    .terytDeleteTable "tblULIC_Nazwy"
    .terytCreateTable "tblULIC_Nazwy"
      .terytCreateField "ID_SymUl", dbText, 5
      .terytCreateField "tCecha", dbText, 5
      .terytCreateField "tNazwa_1", dbText, 100
      .terytCreateField "tNazwa_2", dbText, 100, False
    .terytAppendTable
    ' utwórz Indeks Primary
    .terytCreateIndex "ID_SymUl", True
    ' utwórz Indeksy (duplikaty OK)
    .terytCreateIndex "tCecha"
    .terytCreateIndex "tNazwa_1"
    '==================================================
    .terytDeleteTable "tblULIC_Ulice"
    .terytCreateTable "tblULIC_Ulice"
      .terytCreateField "Id_Sym", dbText, 7
      .terytCreateField "Id_SymUl", dbText, 5
      .terytCreateField "tStan_Na", dbText, 10
    .terytAppendTable
    ' utwórz Indeksy (duplikaty OK)
    .terytCreateIndex "Id_Sym"
    .terytCreateIndex "Id_SymUl"
 
    ' utwórz dwupolowy Indeks Primary
    .terytCreateIndexMulti "Id_Sym", "Id_SymUl", "", True
 
    ' utwórz Relacje pomiędzy tabelami
    .terytCreateRelation "tblWojewodztwa", "ID_Woj", "tblPowiaty", "Id_Woj", True, True
    .terytCreateRelation "tblPowiaty", "ID_Pow", "tblTERC_Gminy", "Id_Pow", True, True
    .terytCreateRelation "tblTERC_Gminy", "ID_GMI", "tblSIMC_Miejscowosci", "Id_GMI", True, True
    .terytCreateRelation "tblWMRodz", "ID_RM", "tblSIMC_Miejscowosci", "Id_Rm", True, True
    .terytCreateRelation "tblRodz_Gmi", "ID_RG", "tblTERC_Gminy", "Id_RG", True, True
    .terytCreateRelation "tblSIMC_Miejscowosci", "ID_Sym", "tblULIC_Ulice", "Id_Sym", True, True
    .terytCreateRelation "tblULIC_Nazwy", "ID_SymUl", "tblULIC_Ulice", "Id_SymUl", True, True
  End With
 
' otwórz okno Relacje
DoCmd.RunCommand acCmdRelationships
' odśwież okno bazy
Application.RefreshDatabaseWindow
 
Exit_Here:
  ' zniszcz zmienne obiektowe
  Set cls = Nothing
  Exit Sub
Err_Handler:
  MsgBox "Błąd nr " & Err.Number & vbNewLine & _
          Err.Description
  Resume Exit_Here
End Sub
Relacje. Brak relacji
Widok okna „Relacje” po utworzeniu wszystkich tabel. Tabele połączone relacjami
Widok okna „Relacje” po utworzeniu wszystkich potrzebnych Relacji.

Poniżej znajduje się link do przykładowej bazy, w której przy wykorzystaniu metody klasy clsTeryt, utworzone zostaną wszystkie potrzebne tabele i relacje pomiędzy tabelami. Do tak przygotowanych tabel będzie możliwe pobranie wszystkich danych ze zbioru "TERCPlików pełnych rejestru TERYT.

Ale o tym na następnej stronie Zapis danych z plików pełnych rejestru TERYT.