Meistens legst du Tabellen im Entwurf an — von Hand, in Ruhe. Manchmal aber muss
eine Struktur zur Laufzeit entstehen: eine Importtabelle, deren Spalten von einer
CSV abhängen, eine temporäre Arbeitstabelle oder ein Setup-Routine, die beim ersten
Start fehlende Tabellen ergänzt. Genau dafür gibt es das DAO-Objektmodell mit
TableDef, Field und Index.
Das Objektmodell: TableDef, Field, Index
Eine Tabelle ist in DAO ein TableDef. Es enthält eine Fields-Auflistung (die
Spalten) und eine Indexes-Auflistung (Schlüssel und Indizes). Der Ablauf ist
immer gleich: Objekt mit einer Create...-Methode erzeugen, konfigurieren, dann
mit Append in die passende Auflistung einhängen.
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Set db = CurrentDb
Set tdf = db.CreateTableDef("tblProjekt") ' noch nicht gespeichert
Wichtig: CreateTableDef erzeugt das Objekt nur im Speicher. Erst das Append in
db.TableDefs schreibt die Tabelle wirklich in die Datenbank.
Felder anlegen mit CreateField
Jede Spalte entsteht mit CreateField(Name, Typ, [Größe]). Der Typ ist eine
dbXxx-Konstante. Die gebräuchlichsten:
| Konstante | Access-Datentyp | Hinweis |
|---|---|---|
dbText | Kurzer Text | Größe = max. Zeichen (1–255) |
dbMemo | Langer Text | keine Größenangabe |
dbLong | Zahl (Long Integer) | typisch für IDs |
dbInteger | Zahl (Integer) | 16 Bit |
dbDouble | Zahl (Double) | Fließkomma |
dbCurrency | Währung | 4 Nachkommastellen |
dbDate | Datum/Uhrzeit | |
dbBoolean | Ja/Nein |
tdf.Fields.Append tdf.CreateField("ProjektID", dbLong)
tdf.Fields.Append tdf.CreateField("Titel", dbText, 100)
tdf.Fields.Append tdf.CreateField("Start", dbDate)
tdf.Fields.Append tdf.CreateField("Budget", dbCurrency)
tdf.Fields.Append tdf.CreateField("Aktiv", dbBoolean)
CreateField gibt ein Field-Objekt zurück, das du direkt an Fields.Append
weiterreichst. Die Size gibst du nur bei dbText an — bei Zahlentypen ergibt sie
sich aus der Konstante.
Weitere Feldeigenschaften setzen
Für Feinheiten wie „Ist Autowert" oder „Pflichtfeld" belegst du Eigenschaften am
Field-Objekt, bevor du es anhängst:
Dim fld As DAO.Field
Set fld = tdf.CreateField("ProjektID", dbLong)
fld.Attributes = dbAutoIncrField ' Autowert (fortlaufende Nummer)
tdf.Fields.Append fld
Set fld = tdf.CreateField("Titel", dbText, 100)
fld.Required = True ' Pflichtfeld (nicht Null)
fld.AllowZeroLength = False
tdf.Fields.Append fld
Achtung:
dbAutoIncrFieldfunktioniert nur mitdbLong. Andere Feldtypen als Autowert führen zu einem Laufzeitfehler beimAppend.
Tabelle speichern
Erst wenn alle Felder hängen, schreibst du das TableDef in die Datenbank:
db.TableDefs.Append tdf ' jetzt existiert die Tabelle
db.TableDefs.Refresh
Ab hier ist tblProjekt eine normale Access-Tabelle und taucht im Navigationsbereich
auf (evtl. musst du F5 drücken, damit die Anzeige aktualisiert wird).
Primärschlüssel und Indizes anlegen
Ein Primärschlüssel ist in DAO ein Index mit den Eigenschaften Primary = True
und Unique = True. Auch normale Indizes zur Beschleunigung von Abfragen legst du so
an. Der Index braucht mindestens ein Feld, das du über sein eigenes CreateField
anhängst:
Dim idx As DAO.Index
Set idx = tdf.CreateIndex("PrimaryKey")
idx.Primary = True
idx.Unique = True
idx.Fields.Append idx.CreateField("ProjektID")
tdf.Indexes.Append idx
Für einen einfachen (nicht eindeutigen) Suchindex auf Titel:
Set idx = tdf.CreateIndex("idxTitel")
idx.Fields.Append idx.CreateField("Titel")
tdf.Indexes.Append idx
Reihenfolge: Legst du den Index nach dem
TableDefs.Appendan, musst du dasTableDeffrisch ausdb.TableDefs("tblProjekt")holen und danachtdf.Indexes.Appendaufrufen. Sauberer ist es, Felder und Indizes vor dem erstenTableDefs.Appendfertig zu konfigurieren.
Ein vollständiges Beispiel
Public Sub TabelleErstellen()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim idx As DAO.Index
Set db = CurrentDb
' Falls schon vorhanden: erst weg
If TabelleExistiert("tblProjekt") Then
db.TableDefs.Delete "tblProjekt"
End If
Set tdf = db.CreateTableDef("tblProjekt")
Dim fld As DAO.Field
Set fld = tdf.CreateField("ProjektID", dbLong)
fld.Attributes = dbAutoIncrField
tdf.Fields.Append fld
tdf.Fields.Append tdf.CreateField("Titel", dbText, 100)
tdf.Fields.Append tdf.CreateField("Start", dbDate)
tdf.Fields.Append tdf.CreateField("Budget", dbCurrency)
Set idx = tdf.CreateIndex("PrimaryKey")
idx.Primary = True
idx.Fields.Append idx.CreateField("ProjektID")
tdf.Indexes.Append idx
db.TableDefs.Append tdf
db.TableDefs.Refresh
MsgBox "Tabelle tblProjekt wurde erstellt."
End Sub
Die Hilfsfunktion prüft, ob eine Tabelle existiert (sonst wirft der Zugriff einen Fehler):
Public Function TabelleExistiert(ByVal sName As String) As Boolean
Dim tdf As DAO.TableDef
On Error Resume Next
Set tdf = CurrentDb.TableDefs(sName)
TabelleExistiert = (Err.Number = 0)
On Error GoTo 0
End Function
Tabelle löschen
Zwei Wege — beide erledigen den Job, aber mit Unterschieden:
' DAO: entfernt nur die Tabellendefinition, still und leise
CurrentDb.TableDefs.Delete "tblTemp"
' DoCmd: entfernt jedes Objekt, funktioniert auch für Abfragen/Formulare
DoCmd.DeleteObject acTable, "tblTemp"
db.TableDefs.Delete ist die reine DAO-Variante ohne Rückfrage. DoCmd.DeleteObject
ist universeller (acQuery, acForm, …) und respektiert ggf. Warndialoge, wenn
DoCmd.SetWarnings aktiv ist.
Wann ist das sinnvoll?
- Dynamische Importe, deren Spalten erst zur Laufzeit feststehen.
- Temporäre Arbeitstabellen, die eine Routine anlegt, füllt und wieder löscht.
- Setup/Update-Code, der beim Programmstart fehlende Tabellen ergänzt.
Vorsicht mit Struktur-Änderungen: Tabellen per Code zu erstellen und zu löschen ist mächtig — und riskant. Ein
TableDefs.Deleteauf die falsche Tabelle ist nicht rückgängig zu machen. Ändere Strukturen nur mit Bedacht, nie auf Produktivdaten ohne Backup, und lösche niemals Tabellen anhand ungeprüfter Benutzereingaben. Wo eine feste Struktur genügt, entwirf die Tabelle von Hand.
Zusammengefasst
CurrentDb.CreateTableDeferzeugt eine Tabelle im Speicher; erstTableDefs.Appendspeichert sie dauerhaft.- Felder legst du mit
CreateField(Name, Typ, Größe)an —dbText,dbLong,dbDate,dbCurrencyusw. — und hängst sie mitFields.Appendein. - Primärschlüssel und Indizes sind
Index-Objekte (Primary/Unique) mit eigenen angehängten Feldern. - Löschen geht per
db.TableDefs.Delete(reines DAO) oderDoCmd.DeleteObject acTable(universell). - Sinnvoll bei dynamischen oder temporären Strukturen — Struktur-Änderungen aber immer mit Backup und Existenzprüfung absichern.