Lektionen/Datenzugriff

Tabellen & Felder per DAO erstellen

Profi10 Min. Lesezeit

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:

KonstanteAccess-DatentypHinweis
dbTextKurzer TextGröße = max. Zeichen (1–255)
dbMemoLanger Textkeine Größenangabe
dbLongZahl (Long Integer)typisch für IDs
dbIntegerZahl (Integer)16 Bit
dbDoubleZahl (Double)Fließkomma
dbCurrencyWährung4 Nachkommastellen
dbDateDatum/Uhrzeit
dbBooleanJa/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: dbAutoIncrField funktioniert nur mit dbLong. Andere Feldtypen als Autowert führen zu einem Laufzeitfehler beim Append.

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.Append an, musst du das TableDef frisch aus db.TableDefs("tblProjekt") holen und danach tdf.Indexes.Append aufrufen. Sauberer ist es, Felder und Indizes vor dem ersten TableDefs.Append fertig 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.Delete auf 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.CreateTableDef erzeugt eine Tabelle im Speicher; erst TableDefs.Append speichert sie dauerhaft.
  • Felder legst du mit CreateField(Name, Typ, Größe) an — dbText, dbLong, dbDate, dbCurrency usw. — und hängst sie mit Fields.Append ein.
  • Primärschlüssel und Indizes sind Index-Objekte (Primary/Unique) mit eigenen angehängten Feldern.
  • Löschen geht per db.TableDefs.Delete (reines DAO) oder DoCmd.DeleteObject acTable (universell).
  • Sinnvoll bei dynamischen oder temporären Strukturen — Struktur-Änderungen aber immer mit Backup und Existenzprüfung absichern.
Nächste Lektion
Unterformulare steuern