🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA Chart in Excel — ein Diagramm im Code erstellen und warum es die falschen Daten zeichnet

|

VBA Chart in Excel — ein Diagramm im Code erstellen und warum es die falschen Daten zeichnet

TL;DR — Ein Diagramm speichert keine Daten — es speichert einen Verweis auf einen Range. Die .Values jeder Datenreihe sind eine Formel wie =Sheet1!$B$2:$B$13, das Diagramm ist also immer nur so korrekt wie dieser Verweis. Erstellen Sie ein eingebettetes Diagramm mit ws.ChartObjects.Add(left, top, width, height), holen Sie sein .Chart, setzen Sie .ChartType und binden Sie die Daten in einem Zug mit .SetSourceData Source:=Range(...). Die zwei Dinge, die beißen: Eingebettete Diagramme leben in ChartObjects (nicht in Charts, das sind Diagrammblätter), und ein erneuter Lauf des Makros stapelt Duplikate, wenn Sie nicht zuerst die alten löschen.

Dim co As ChartObject, ch As Chart

Set co = Worksheets("Report").ChartObjects.Add( _
    Left:=300, Top:=20, Width:=420, Height:=260)
Set ch = co.Chart                                   ' das ChartObject ist der Rahmen; .Chart ist das Diagramm
ch.ChartType = xlColumnClustered
ch.SetSourceData Source:=Worksheets("Data").Range("A1:B13")   ' den ganzen Bereich auf einmal binden
ch.HasTitle = True
ch.ChartTitle.Text = "Monthly Sales"

Diagramme in VBA sehen einfach aus — bis zum zweiten Lauf, wenn Sie zwei Diagramme vorfinden, oder bis zum ersten Lauf, wenn die Balken die falsche Spalte zeichnen. Beides entspringt demselben Missverständnis, und die Lösung für beides ist dieselbe Idee: Ein Diagramm enthält Ihre Daten nicht — es zeigt auf sie. Jede Datenreihe hält einen Verweis auf einen Bereich, geschrieben als Formel. Verschieben Sie die Daten, fügen Sie eine Zeile ein, bauen Sie die Quelle an anderer Stelle neu — und das Diagramm zeigt weiter dorthin, wohin es gewiesen wurde, und zeichnet getreulich die falschen Zellen. Sobald Sie „ein Diagramm ist eine Ansicht, an einen Range gebunden" festhalten, hört die API auf, fummelig zu sein, und die zwei klassischen Bugs werden offensichtlich.

Was Sie lernen

  • Das mentale Modell — ein Diagramm hält einen Verweis auf einen Range, keine Kopie der Daten
  • Die zwei Container: eingebettete ChartObjects gegenüber Diagrammblättern in Charts
  • Ein Diagramm erstellen und die Daten in einem Zug mit SetSourceData binden
  • Datenreihen von Hand mit SeriesCollection hinzufügen und steuern
  • Die Duplikat-Diagramm-Falle beim erneuten Lauf und wie man alte Diagramme entfernt
  • Die Quelle an eine Table binden, damit das Diagramm den Daten folgt

Das mentale Modell: ein Diagramm zeigt auf einen Range

Wenn Sie einen Bereich als Diagramm darstellen, kopiert Excel die Zahlen nicht in das Diagramm. Es speichert für jede Datenreihe eine Formel, die auf den Bereich verweist — genauso, wie eine Zellformel auf andere Zellen verweist. Sie können sie zurücklesen:

Debug.Print ch.SeriesCollection(1).Formula
' =SERIES("Sales",Data!$A$2:$A$13,Data!$B$2:$B$13,1)

Diese SERIES(...)-Formel ist die ganze Wahrheit über das Diagramm: ein Name, ein Verweis auf die X-Werte, ein Verweis auf die Y-Werte. Das Diagramm ist eine lebende Ansicht über diese Verweise. Deshalb ist „mein Diagramm zeigt die falschen Daten" so verbreitet — das Diagramm ist nicht falsch, sein Verweis zeigt auf Zellen, die nicht mehr das halten, was Sie denken. Und deshalb besteht die dauerhafte Lösung am Ende dieser Anleitung darin, den Verweis den Daten folgen zu lassen, statt ihn bei $B$2:$B$13 einzufrieren.

Die zwei Container: ChartObjects gegenüber Diagrammblättern

Excel hat zwei Heimstätten für Diagramme, und sie zu verwechseln ist das Erste, worüber ein Diagramm-Makro stolpert. Ein eingebettetes Diagramm schwebt auf einem Arbeitsblatt und lebt in der ChartObjects-Collection jenes Blatts; ein Diagrammblatt ist ein ganzer Tab, der nichts als ein Diagramm ist, und lebt in der Charts-Collection der Arbeitsmappe:

' Eingebettet: ein ChartObject ist der Rahmen/Container; sein .Chart ist das Diagramm selbst
Dim co As ChartObject
Set co = Worksheets("Report").ChartObjects.Add(300, 20, 420, 260)
co.Chart.ChartType = xlLine        ' Eigenschaften auf .Chart setzen, nicht auf co

' Diagrammblatt: ein eigener Tab
Dim ch As Chart
Set ch = ThisWorkbook.Charts.Add

Die Feinheit, die Leute eine Stunde kostet: Bei einem eingebetteten Diagramm gibt Ihnen ChartObjects.Add den Rahmen (ein ChartObject), und das Diagramm, das Sie tatsächlich formatieren, ist co.Chart. Nach Charts(1) zu greifen, wenn Ihr Diagramm eingebettet ist, wirft einen Fehler, denn Charts hält nur Diagrammblätter. Die meisten Berichte leben auf einem Arbeitsblatt, Sie nutzen also ChartObjects weit häufiger — merken Sie sich nur die zweischichtige Rahmen-Diagramm-Trennung.

Ein Diagramm erstellen und die Daten in einem Zug binden

Das saubere Muster lautet: den Rahmen hinzufügen, .Chart greifen, den Typ setzen und die ganze Quelle mit SetSourceData in einem einzigen Aufruf binden:

Dim co As ChartObject, ch As Chart
Set co = Worksheets("Report").ChartObjects.Add(300, 20, 420, 260)
Set ch = co.Chart
ch.ChartType = xlColumnClustered
ch.SetSourceData Source:=Worksheets("Data").Range("A1:B13")

SetSourceData reicht Excel den ganzen Block — Überschriften, Kategorien und Werte — und lässt es die Datenreihen ermitteln, genau wie das Markieren des Bereichs und das Drücken der Diagramm-Schaltfläche. Das ist fast immer, was Sie wollen; es ist weniger Code und weniger Fehler als das Bauen der Datenreihen eine nach der anderen. Schließen Sie die Kopfzeile und die Kategoriespalte in den Bereich ein, und das Diagramm beschriftet sich selbst. Setzen Sie .ChartType davor oder danach — gängige Werte sind xlColumnClustered, xlLine, xlPie und xlXYScatter.

Datenreihen von Hand hinzufügen und steuern

Wenn Sie präzise Kontrolle brauchen — eine Datenreihe nach der anderen, Werte von einer nicht zusammenhängenden Stelle, ein eigener Name —, fügen Sie Datenreihen über SeriesCollection hinzu:

Dim s As Series
Set s = ch.SeriesCollection.NewSeries
s.Name = "2026"
s.XValues = Worksheets("Data").Range("A2:A13")
s.Values = Worksheets("Data").Range("B2:B13")

Jede Datenreihe hat drei Teile, die direkt auf jene SERIES(...)-Formel abbilden: .Name, .XValues (die Kategoriebeschriftungen) und .Values (die Zahlen). Fügen Sie eine zweite Datenreihe mit einem weiteren NewSeries hinzu; entfernen Sie eine mit ch.SeriesCollection(2).Delete. .Values auf einen Bereich zu setzen ist dasselbe wie den Verweis in die Datenreihenformel zu schreiben — was der Mechanismus hinter dem Falsche-Daten-Bug ist und der Grund, warum das Binden an eine stabile Quelle zählt.

Die Duplikat-Diagramm-Falle und das Entfernen alter Diagramme

Hier ist der Bug, der nach zwölf Läufen zwölf Diagramme erzeugt: ChartObjects.Add fügt immer ein neues hinzu. Es nutzt nie das Diagramm vom letzten Mal wieder, sodass ein unbeaufsichtigtes Makro still Kopien stapelt. Entfernen Sie die vorhandenen Diagramme des Blatts, bevor Sie bauen:

Dim co As ChartObject
For Each co In Worksheets("Report").ChartObjects
    co.Delete                          ' zuerst die Diagramme des letzten Laufs entfernen
Next co
' ...jetzt das frische Diagramm bauen

Durchlaufen Sie ChartObjects und Deleten Sie jedes, dann erstellen Sie Ihr Diagramm von einer sauberen Grundlage aus — dieselbe Collection-Disziplin, die Sie für jeden wiederholten Aufbau nutzen würden. Wollen Sie lieber ein bestimmtes Diagramm behalten und aktualisieren, benennen Sie es (co.Name = "chtSales"), schlagen Sie es im nächsten Lauf über diesen Namen nach und rufen Sie SetSourceData erneut auf, statt einen neuen Rahmen hinzuzufügen. So oder so, entscheiden Sie bewusst: frisch bauen oder an Ort und Stelle aktualisieren, niemals blind hinzufügen.

Die Quelle an eine Table binden, damit das Diagramm den Daten folgt

Nun die dauerhafte Lösung für den Falsche-Daten-Bug. Weil eine Datenreihe ein Verweis ist, friert ein an A1:B13 gebundenes Diagramm bei dreizehn Zeilen ein — fügen Sie einen Monat hinzu, und der neue Punkt liegt außerhalb des Diagramms. Binden Sie die Quelle stattdessen an eine Table, und der Verweis wächst mit den Daten:

' Die Quelle des Diagramms ist der Bereich einer Table -> neue Zeilen erscheinen automatisch
ch.SetSourceData Source:=Worksheets("Data").ListObjects("tblSales").Range

Ist die Quelle ein ListObject, dehnt das Hinzufügen einer Zeile die Table aus, die Table dehnt den Bereich aus, auf den die Datenreihe verweist, und das Diagramm zeichnet mit dem neuen Punkt neu — kein Code, kein erneutes SetSourceData. Das ist derselbe Zug, der eine Pivot aktuell hält, und der Grund, warum eine Table das Fundament ist, das man zuerst bauen sollte: Richten Sie Ihre Pivots und Diagramme einmal darauf, und beide aktualisieren sich selbst. Um ein Diagramm als Bild weiterzugeben, schreibt co.Chart.Export "C:\Reports\sales.png" ein PNG direkt auf die Festplatte.

Wie ExcelMaster hilft

Die Diagramm-Fehler, die einen fertigen Bericht erreichen, sind still: das zweite Diagramm, das niemand löschte, die Datenreihe, die noch auf den Bereich des letzten Quartals zeigt, die Balken, die die falsche Spalte zeichnen, weil SetSourceData einen Block bekam, der sich verschoben hatte. Jeder rendert sauber — er zeigt nur das falsche Bild.

ExcelMaster baut Diagramme wie jemand, der von allen dreien schon einmal verbrannt wurde. Bitten Sie es, „den Monatsumsatz nach Region als Diagramm darzustellen", und es entfernt die alten ChartObjects, bevor es zeichnet, bindet die Quelle an eine Table, damit neue Zeilen von allein erscheinen, nutzt SetSourceData für den ganzen Block, statt Datenreihen von Hand zu verdrahten, und formatiert über co.Chart, statt über die Rahmen-Diagramm-Trennung zu stolpern. Sie beschreiben das gewünschte Bild; es verdrahtet den Verweis so, dass das Diagramm die Wahrheit weiter erzählt, während die Daten wachsen.

Häufig gestellte Fragen

Wie erstelle ich in VBA ein Diagramm?

Fügen Sie mit ChartObjects.Add ein eingebettetes Diagramm hinzu, setzen Sie dann Typ und Daten über .Chart: Set co = ws.ChartObjects.Add(300, 20, 420, 260), Set ch = co.Chart, ch.ChartType = xlColumnClustered, ch.SetSourceData Source:=Range("A1:B13"). Das ChartObject ist der Rahmen und sein .Chart das Diagramm, das Sie formatieren. SetSourceData bindet den ganzen Bereich in einem Aufruf.

Warum zeichnet mein VBA-Diagramm die falschen Daten?

Weil ein Diagramm einen Verweis auf einen Bereich hält, keine Kopie davon — die .Values jeder Datenreihe sind eine Formel wie =Sheet1!$B$2:$B$13. Bewegen sich die Daten, werden Zeilen eingefügt oder die Quelle anderswo neu gebaut, zeigt der Verweis noch auf die alten Zellen, und das Diagramm zeichnet sie. Binden Sie mit SetSourceData neu, oder richten Sie die Quelle auf eine Table, damit der Verweis den Daten folgt.

Was ist der Unterschied zwischen ChartObjects und Charts in VBA?

ChartObjects ist die Collection der eingebetteten Diagramme eines Arbeitsblatts, die auf dem Blatt schweben; jedes ChartObject ist ein Rahmen, dessen .Chart das eigentliche Diagramm ist. Charts ist die Collection der Diagrammblätter der Arbeitsmappe — Tabs, die nichts als ein Diagramm sind. Nach Charts(1) zu greifen, wenn Ihr Diagramm eingebettet ist, wirft einen Fehler; nutzen Sie stattdessen ws.ChartObjects(1).Chart.

Wie füge ich in VBA eine Datenreihe zu einem Diagramm hinzu?

Nutzen Sie SeriesCollection.NewSeries, setzen Sie dann ihre Teile: Set s = ch.SeriesCollection.NewSeries, s.Name = "2026", s.XValues = Range("A2:A13"), s.Values = Range("B2:B13"). Fügen Sie weitere mit einem weiteren NewSeries hinzu; entfernen Sie eine mit ch.SeriesCollection(2).Delete. Für ein einfaches Diagramm ist SetSourceData auf dem ganzen Bereich leichter als das Hinzufügen von Datenreihen von Hand.

Wie verhindere ich, dass VBA doppelte Diagramme erstellt?

ChartObjects.Add fügt immer ein neues Diagramm hinzu, sodass ein erneuter Lauf eines Makros Kopien stapelt. Löschen Sie vor dem Bauen die vorhandenen: For Each co In ws.ChartObjects: co.Delete: Next co. Wollen Sie ein bestimmtes Diagramm behalten und aktualisieren, benennen Sie es (co.Name = "chtSales"), finden Sie es im nächsten Lauf über diesen Namen und rufen Sie SetSourceData erneut auf, statt einen neuen Rahmen hinzuzufügen.

Getestet in

Getestet in: Excel 365 (Windows 11), VBA 7.1 — zuletzt geprüft am 02.09.2026.

Verwandte Anleitungen: VBA Pivot Table · VBA Table · VBA Range · VBA Collection · VBA Worksheet