TL;DR — Ein Diagramm speichert keine Daten — es speichert einen Verweis auf einen Range. Die
.Valuesjeder 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 mitws.ChartObjects.Add(left, top, width, height), holen Sie sein.Chart, setzen Sie.ChartTypeund binden Sie die Daten in einem Zug mit.SetSourceData Source:=Range(...). Die zwei Dinge, die beißen: Eingebettete Diagramme leben inChartObjects(nicht inCharts, 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
ChartObjectsgegenüber Diagrammblättern inCharts - Ein Diagramm erstellen und die Daten in einem Zug mit
SetSourceDatabinden - Datenreihen von Hand mit
SeriesCollectionhinzufü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
