Lektionen/Automation

Excel aus Access steuern

Profi12 Min. Lesezeit

Access und Excel sind Geschwister im Office-Paket, und aus VBA heraus kannst du Excel komplett fernsteuern: Mappen erzeugen, Zellen füllen, formatieren, ganze Recordsets in Sekunden exportieren. Diese Technik heißt Automation — ein Programm steuert ein anderes über dessen Objektmodell.

Das ist mächtig, hat aber eine Falle: Wer Excel nicht sauber beendet, hinterlässt unsichtbare Geisterprozesse im Speicher. Diese Lektion zeigt beides — den vollen Zugriff und das saubere Aufräumen.

Die Grundidee der Automation

Excel stellt ein Objektmodell bereit: An der Spitze steht die Excel.Application, darunter Workbooks (Arbeitsmappen), darunter Worksheets (Tabellenblätter), darunter Range/Cells (Zellen). Von Access aus greifst du auf dieses Modell zu, als wärst du in Excels eigenem VBA.

Early Binding vs. Late Binding

Es gibt zwei Wege, an das Excel-Objekt zu kommen.

Late Binding — ohne Verweis, über CreateObject. Der Datentyp ist Object, die Bindung passiert erst zur Laufzeit:

Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")

Early Binding — mit gesetztem Verweis. Im VBE unter Extras → Verweise die Microsoft Excel xx.x Object Library aktivieren, dann typisiert deklarieren:

Dim xlApp As Excel.Application
Set xlApp = New Excel.Application
Late BindingEarly Binding
Verweis nötigneinja
IntelliSenseneinja
Konstanten wie xlUpselbst definiereneingebaut
Versionssicher beim Verteilenrobusterkann brechen

Empfehlung: Entwickle mit Early Binding (wegen IntelliSense und Konstanten) und stelle für die Auslieferung auf Late Binding um, wenn deine Nutzer unterschiedliche Excel-Versionen haben. Bei Late Binding musst du Konstanten wie xlUp (= -4162) selbst als Zahl schreiben.

Mappe öffnen und Zellen schreiben

Ein vollständiges Beispiel mit Late Binding. Beachte xlApp.Visible = True — damit siehst du Excel überhaupt; ohne läuft es unsichtbar im Hintergrund.

Public Sub ExcelBefuellen()
    Dim xlApp As Object
    Dim wb As Object
    Dim ws As Object

    Set xlApp = CreateObject("Excel.Application")
    xlApp.Visible = True                 ' Excel-Fenster anzeigen

    Set wb = xlApp.Workbooks.Add          ' neue leere Mappe
    Set ws = wb.Worksheets(1)             ' erstes Tabellenblatt

    ' Zellen schreiben
    ws.Range("A1").Value = "Artikel"
    ws.Range("B1").Value = "Preis"
    ws.Cells(2, 1).Value = "Schraube"     ' Zeile 2, Spalte 1
    ws.Cells(2, 2).Value = 0.05

    ' Zelle lesen
    Debug.Print ws.Range("B2").Value      ' 0,05

    ' Überschrift fett
    ws.Range("A1:B1").Font.Bold = True

    ' Speichern
    wb.SaveAs "C:\Export\Artikel.xlsx"
End Sub

Range("A1") adressierst du wie in Excel, Cells(Zeile, Spalte) mit Zahlen — das ist praktisch in Schleifen.

Ein ganzes Recordset in Excel kippen

Zeile für Zelle für Zelle zu schreiben ist langsam. Für Datenmengen gibt es CopyFromRecordset: eine einzige Zeile kopiert ein komplettes Recordset in einen Rutsch nach Excel.

Public Sub RecordsetNachExcel()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim xlApp As Object, wb As Object, ws As Object
    Dim i As Long

    Set db = CurrentDb
    Set rs = db.OpenRecordset( _
        "SELECT Kundenname, Ort, Umsatz FROM tblKunden", dbOpenSnapshot)

    Set xlApp = CreateObject("Excel.Application")
    Set wb = xlApp.Workbooks.Add
    Set ws = wb.Worksheets(1)

    ' Spaltenüberschriften aus den Feldnamen
    For i = 0 To rs.Fields.Count - 1
        ws.Cells(1, i + 1).Value = rs.Fields(i).Name
    Next i
    ws.Range("A1").Resize(1, rs.Fields.Count).Font.Bold = True

    ' Daten ab Zeile 2 in einem Rutsch
    ws.Range("A2").CopyFromRecordset rs

    ws.Columns.AutoFit
    xlApp.Visible = True

    ' Aufräumen
    rs.Close
    Set rs = Nothing
    Set db = Nothing
    Set ws = Nothing
    Set wb = Nothing
    Set xlApp = Nothing
End Sub

CopyFromRecordset schreibt nur die Daten, keine Überschriften — die setzt du wie oben selbst aus rs.Fields.

Sauber beenden — der Geisterprozess

Das ist der wichtigste Teil. Wenn du Excel unsichtbar startest und die Objektvariable einfach aus dem Gültigkeitsbereich fallen lässt, bleibt EXCEL.EXE oft im Task-Manager hängen — ein Geisterprozess. Er belegt Speicher und blockiert später die Datei.

Die Regel: erst Quit, dann jede Objektvariable auf Nothing setzen — von innen nach außen.

Public Sub ExcelSauberBeenden()
    Dim xlApp As Object, wb As Object, ws As Object

    Set xlApp = CreateObject("Excel.Application")
    Set wb = xlApp.Workbooks.Add
    Set ws = wb.Worksheets(1)

    ws.Range("A1").Value = "Fertig"
    wb.SaveAs "C:\Export\Test.xlsx"

    ' In umgekehrter Reihenfolge abbauen
    wb.Close SaveChanges:=False
    xlApp.Quit                 ' Excel beenden

    Set ws = Nothing
    Set wb = Nothing
    Set xlApp = Nothing        ' Referenz freigeben -> Prozess verschwindet
End Sub

Falle: Sogenannte „unqualifizierte" Zugriffe wie Cells(1, 1) statt ws.Cells(1, 1) erzeugen versteckte Referenzen auf die Application und verhindern das Beenden. Qualifiziere jeden Zugriff mit ws., wb. oder xlApp., sonst hilft auch Quit nichts.

Robuster mit Fehlerbehandlung

Damit kein Geisterprozess zurückbleibt, wenn zwischendrin etwas schiefgeht, gehört das Aufräumen in einen Fehlerbehandler:

Public Sub ExcelMitFehlerschutz()
    Dim xlApp As Object, wb As Object

    On Error GoTo Aufraeumen
    Set xlApp = CreateObject("Excel.Application")
    Set wb = xlApp.Workbooks.Add

    wb.Worksheets(1).Range("A1").Value = "Hallo"
    wb.SaveAs "C:\Export\Robust.xlsx"

Aufraeumen:
    If Err.Number <> 0 Then MsgBox "Fehler: " & Err.Description
    On Error Resume Next
    If Not wb Is Nothing Then wb.Close SaveChanges:=False
    If Not xlApp Is Nothing Then xlApp.Quit
    Set wb = Nothing
    Set xlApp = Nothing
End Sub

Die einfache Alternative: TransferSpreadsheet

Wenn du nur Daten aus einer Tabelle oder Abfrage nach Excel exportieren willst, ohne zu formatieren, brauchst du gar keine Automation. DoCmd.TransferSpreadsheet erledigt das in einer Zeile:

DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, _
    "tblKunden", "C:\Export\Kunden.xlsx", True

Der letzte Parameter True schreibt die Feldnamen als Überschriftszeile. Nimm TransferSpreadsheet für schnelle Datendumps und die volle Automation nur, wenn du Formatierung, Formeln oder mehrere Blätter brauchst.

Zusammengefasst

  • Automation steuert Excel über sein Objektmodell: Application → Workbook → Worksheet → Range.
  • Early Binding (Verweis) gibt IntelliSense; Late Binding (CreateObject) ist versionssicherer.
  • CopyFromRecordset kippt ein ganzes Recordset in einem Rutsch nach Excel.
  • Immer Quit und danach alle Objekte auf Nothing setzen — sonst bleibt ein Geisterprozess; jeden Zugriff qualifizieren.
  • Für einfache Exporte reicht DoCmd.TransferSpreadsheet ganz ohne Automation.
Nächste Lektion
Arrays: statisch & dynamisch