Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lernen Automatisierung von Diagrammen | Tabellen und Berichte Automatisieren
Excel VBA für Geschäftsautomatisierung

Automatisierung von Diagrammen

Swipe um das Menü anzuzeigen

Diagramme sind Formen, die auf einem Arbeitsblatt liegen, und wie alles andere in diesem Kapitel hat jede Eigenschaft, die man manuell im Formatierungsbereich einstellt, ein entsprechendes VBA-Pendant.

Abbildung 4.4

Diagramm erstellen

Sub BuildProfitChart()
    Dim ws As Worksheet
    Dim tbl As ListObject
    Dim chartObj As ChartObject
 
    Set ws = ThisWorkbook.Worksheets("Reports")
    Set tbl = ws.ListObjects("tblReports")
 
    Set chartObj = ws.Shapes.AddChart2(Style:=201, _
        XlChartType:=xlColumnClustered, _
        Left:=400, Top:=20, Width:=400, Height:=250).Chart.Parent
 
    With chartObj.Chart
        .SetSourceData Source:=tbl.ListColumns("Profit").Range
        .HasTitle = True
        .ChartTitle.Text = "Profit by Region"
    End With
End Sub
Zeilenweise Erklärung
expand arrow
  • AddChart2 erstellt die Diagrammform selbst — Style:=201 wählt einen integrierten visuellen Stil, XlChartType:=xlColumnClustered wählt ein Standard-Säulendiagramm, und Left/Top/Width/Height positionieren und dimensionieren es auf dem Arbeitsblatt in Punkt, derselben Einheit, die Excel intern für die Platzierung von Formen verwendet;
  • AddChart2 gibt tatsächlich ein Chart-Objekt zurück, nicht den ChartObject-Container darum herum — das .Chart.Parent am Ende dieser Zeile springt wieder zum Container zurück, als dessen Typ chartObj deklariert ist; diese Besonderheit ist leicht zu vergessen und sollte exakt so übernommen werden;
  • SetSourceData gibt der ansonsten leeren Diagrammform an, welche Daten dargestellt werden sollen — die Angabe von tbl.ListColumns("Profit").Range bedeutet, dass die Profit-Spalte über alle sichtbaren Zeilen der Tabelle dargestellt wird;
  • HasTitle = True muss gesetzt werden, bevor ChartTitle.Text zugewiesen wird — versucht man, den Titeltext bei einem Diagramm zu setzen, das noch keinen Titel hat, schlägt dies fehl.

Aktualisieren von Diagrammdaten

Wenn die zugrunde liegende Tabelle wächst, sollte das Diagramm mit SetSourceData auf den neuen Bereich verwiesen werden, anstatt es zu löschen und neu zu erstellen — so bleiben alle manuell vorgenommenen Formatierungen erhalten:

Dim cht As Chart
Set cht = ThisWorkbook.Worksheets("Reports").ChartObjects(1).Chart
cht.SetSourceData Source:=tbl.ListColumns("Profit").Range

ChartObjects(1) bezieht sich auf die erste Diagrammform auf dem Blatt nach Position — das ist in Ordnung, solange es nur ein Diagramm gibt, wird aber problematisch, sobald ein zweites Diagramm hinzugefügt wird, da "erstes" dann stillschweigend etwas anderes bedeuten kann. Ein Diagramm über einen explizit vergebenen Namen zu referenzieren (chartObj.Name = "ProfitChart", dann ChartObjects("ProfitChart"))) ist robuster, sobald ein Blatt mehr als ein Diagramm enthält.

Diagramme formatieren

With chartObj.Chart
    .ChartTitle.Font.Size = 14
    .ChartTitle.Font.Bold = True
    .SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(24, 106, 60)
    .Axes(xlValue).TickLabels.NumberFormat = "#,##0"
    .HasLegend = False
End With

SeriesCollection(1) ist die erste (und hier einzige) dargestellte Datenreihe — deren Format.Fill.ForeColor.RGB legt die Farbe der Balken fest, wobei dieselbe RGB(...) Funktion wie in den Formatierungsbeispielen aus Kapitel 1 verwendet wird. Axes(xlValue) bezieht sich speziell auf die Zahlenachse (im Gegensatz zu xlCategory, der Achse mit den Regionsnamen) — die Anwendung von NumberFormat steuert, wie die Zahlen entlang dieser Achse angezeigt werden, genau wie NumberFormat in einer Tabellenzelle. HasLegend = False entfernt die Legende vollständig, was immer sinnvoll ist, wenn ein Diagramm nur eine Datenreihe enthält, da eine Legende für eine einzige Farbe nur unnötige Unübersichtlichkeit schafft.

Aufgabe

  1. BuildProfitChart ausführen und bestätigen, dass ein Säulendiagramm erscheint, das den Profit für alle fünfzehn Zeilen (alle drei Monate, ungefiltert) anzeigt.
  2. Drei Zeilen hinzufügen, um die Balken des Diagramms dunkelgrün (RGB(24,106,60)) einzufärben und die Legende zu entfernen, wie oben gezeigt.
  3. tblReports auf nur Januar filtern und SetSourceData erneut auf tbl.ListColumns("Profit").Range anwenden — beobachten, ob das Diagramm den Filter berücksichtigt.
Hinweis
expand arrow

1. Ausführen von BuildProfitChart

  • Kopiere das Sub exakt wie im Kapitel gezeigt und führe es aus — für diesen Teil sind keine Änderungen nötig.
  • Es sollte ein Diagramm auf dem Blatt Reports erscheinen, das den Gewinn für jede aktuell sichtbare Zeile in der Tabelle darstellt.

2. Balken einfärben und Legende entfernen

  • Beide Eigenschaften gehören zum Diagrammobjekt, nicht zum Arbeitsblatt — chartObj.Chart ist der Einstiegspunkt, wie im Formatierungsbeispiel im Kapitel.
  • Die Balkenfarbe befindet sich bei SeriesCollection(1), da nur eine Datenreihe (Profit) dargestellt wird — .Format.Fill.ForeColor.RGB ist die spezifische Eigenschaft zum Setzen.
  • Das Entfernen der Legende ist eine einzelne boolesche Eigenschaft (HasLegend), getrennt von der Zeile für die Füllfarbe.

3. Filtern und SetSourceData erneut ausführen

  • Wende einen AutoFilter auf Month (Field:=1) an, eingeschränkt auf "January" — dieselbe Technik wie in Abschnitt 4.2.
  • Rufe dann erneut SetSourceData mit dem exakt gleichen Ausdruck tbl.ListColumns("Profit").Range aus BuildProfitChart auf — an dieser Zeile muss nichts geändert werden.
  • Beobachte genau, was danach mit dem Diagramm passiert: Schrumpft es auf nur die fünf Regionen des Januars oder zeigt es immer noch alle fünfzehn Zeilen, einschließlich der gerade durch AutoFilter ausgeblendeten? Diese Beobachtung ist der eigentliche Zweck dieser Aufgabe, nicht nur das Ausführen des Codes.
Lösung
expand arrow
Option Explicit

' Point 1 — run this exactly as shown in the chapter
Sub BuildProfitChart()
    Dim ws As Worksheet
    Dim tbl As ListObject
    Dim chartObj As ChartObject

    Set ws = ThisWorkbook.Worksheets("Reports")
    Set tbl = ws.ListObjects("tblReports")

    Set chartObj = ws.Shapes.AddChart2(Style:=201, _
        XlChartType:=xlColumnClustered, _
        Left:=400, Top:=20, Width:=400, Height:=250).Chart.Parent

    With chartObj.Chart
        .SetSourceData Source:=tbl.ListColumns("Profit").Range
        .HasTitle = True
        .ChartTitle.Text = "Profit by Region"
    End With
End Sub

' Point 2 — color the bars and remove the legend
Sub FormatProfitChart()
    Dim ws As Worksheet
    Dim chartObj As ChartObject

    Set ws = ThisWorkbook.Worksheets("Reports")
    Set chartObj = ws.ChartObjects(1)

    With chartObj.Chart
        .SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(24, 106, 60)
        .HasLegend = False
    End With
End Sub

' Point 3 — filter to January, then re-point the chart at the same range
Sub FilterJanuaryAndRefreshChart()
    Dim ws As Worksheet
    Dim tbl As ListObject
    Dim chartObj As ChartObject

    Set ws = ThisWorkbook.Worksheets("Reports")
    Set tbl = ws.ListObjects("tblReports")
    Set chartObj = ws.ChartObjects(1)

    tbl.Range.AutoFilter Field:=1, Criteria1:="January"

    chartObj.Chart.SetSourceData Source:=tbl.ListColumns("Profit").Range
End Sub

Führe diese in der Reihenfolge aus: BuildProfitChart, dann FormatProfitChart, dann FilterJanuaryAndRefreshChart. Speziell bei Punkt 3 — achte darauf, was tatsächlich passiert. Excel-Diagramme berücksichtigen in der Regel einen aktiven AutoFilter und blenden die Balken der herausgefilterten Zeilen automatisch aus, auch ohne dass SetSourceData erneut ausgeführt wird. Das erneute Ausführen bestätigt hier hauptsächlich, dass das Diagramm weiterhin korrekt auf die gesamte Spalte verweist — der Filter selbst sorgt für das Ausblenden, nicht der Aufruf von SetSourceData. Es lohnt sich, den Unterschied mit aktiviertem und deaktiviertem Filter selbst zu testen.

Note
Hinweis

Das mehrfache Ausführen von BuildProfitChart erstellt jedes Mal ein neues Diagramm, ohne das alte zu löschen — so werden mehrere Diagramme übereinander gestapelt. ChartObjects(1) bezieht sich immer auf das erste erstellte Diagramm, das nun möglicherweise unter einer neueren Kopie verborgen ist. Deshalb können Formatierungsänderungen erfolgreich ausgeführt werden, aber scheinbar keine sichtbare Wirkung haben.

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 4. Kapitel 4

Fragen Sie AI

expand

Fragen Sie AI

ChatGPT

Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen

Automatisierung von Diagrammen

Diagramme sind Formen, die auf einem Arbeitsblatt liegen, und wie alles andere in diesem Kapitel hat jede Eigenschaft, die man manuell im Formatierungsbereich einstellt, ein entsprechendes VBA-Pendant.

Abbildung 4.4

Diagramm erstellen

Sub BuildProfitChart()
    Dim ws As Worksheet
    Dim tbl As ListObject
    Dim chartObj As ChartObject
 
    Set ws = ThisWorkbook.Worksheets("Reports")
    Set tbl = ws.ListObjects("tblReports")
 
    Set chartObj = ws.Shapes.AddChart2(Style:=201, _
        XlChartType:=xlColumnClustered, _
        Left:=400, Top:=20, Width:=400, Height:=250).Chart.Parent
 
    With chartObj.Chart
        .SetSourceData Source:=tbl.ListColumns("Profit").Range
        .HasTitle = True
        .ChartTitle.Text = "Profit by Region"
    End With
End Sub
Zeilenweise Erklärung
expand arrow
  • AddChart2 erstellt die Diagrammform selbst — Style:=201 wählt einen integrierten visuellen Stil, XlChartType:=xlColumnClustered wählt ein Standard-Säulendiagramm, und Left/Top/Width/Height positionieren und dimensionieren es auf dem Arbeitsblatt in Punkt, derselben Einheit, die Excel intern für die Platzierung von Formen verwendet;
  • AddChart2 gibt tatsächlich ein Chart-Objekt zurück, nicht den ChartObject-Container darum herum — das .Chart.Parent am Ende dieser Zeile springt wieder zum Container zurück, als dessen Typ chartObj deklariert ist; diese Besonderheit ist leicht zu vergessen und sollte exakt so übernommen werden;
  • SetSourceData gibt der ansonsten leeren Diagrammform an, welche Daten dargestellt werden sollen — die Angabe von tbl.ListColumns("Profit").Range bedeutet, dass die Profit-Spalte über alle sichtbaren Zeilen der Tabelle dargestellt wird;
  • HasTitle = True muss gesetzt werden, bevor ChartTitle.Text zugewiesen wird — versucht man, den Titeltext bei einem Diagramm zu setzen, das noch keinen Titel hat, schlägt dies fehl.

Aktualisieren von Diagrammdaten

Wenn die zugrunde liegende Tabelle wächst, sollte das Diagramm mit SetSourceData auf den neuen Bereich verwiesen werden, anstatt es zu löschen und neu zu erstellen — so bleiben alle manuell vorgenommenen Formatierungen erhalten:

Dim cht As Chart
Set cht = ThisWorkbook.Worksheets("Reports").ChartObjects(1).Chart
cht.SetSourceData Source:=tbl.ListColumns("Profit").Range

ChartObjects(1) bezieht sich auf die erste Diagrammform auf dem Blatt nach Position — das ist in Ordnung, solange es nur ein Diagramm gibt, wird aber problematisch, sobald ein zweites Diagramm hinzugefügt wird, da "erstes" dann stillschweigend etwas anderes bedeuten kann. Ein Diagramm über einen explizit vergebenen Namen zu referenzieren (chartObj.Name = "ProfitChart", dann ChartObjects("ProfitChart"))) ist robuster, sobald ein Blatt mehr als ein Diagramm enthält.

Diagramme formatieren

With chartObj.Chart
    .ChartTitle.Font.Size = 14
    .ChartTitle.Font.Bold = True
    .SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(24, 106, 60)
    .Axes(xlValue).TickLabels.NumberFormat = "#,##0"
    .HasLegend = False
End With

SeriesCollection(1) ist die erste (und hier einzige) dargestellte Datenreihe — deren Format.Fill.ForeColor.RGB legt die Farbe der Balken fest, wobei dieselbe RGB(...) Funktion wie in den Formatierungsbeispielen aus Kapitel 1 verwendet wird. Axes(xlValue) bezieht sich speziell auf die Zahlenachse (im Gegensatz zu xlCategory, der Achse mit den Regionsnamen) — die Anwendung von NumberFormat steuert, wie die Zahlen entlang dieser Achse angezeigt werden, genau wie NumberFormat in einer Tabellenzelle. HasLegend = False entfernt die Legende vollständig, was immer sinnvoll ist, wenn ein Diagramm nur eine Datenreihe enthält, da eine Legende für eine einzige Farbe nur unnötige Unübersichtlichkeit schafft.

Aufgabe

  1. BuildProfitChart ausführen und bestätigen, dass ein Säulendiagramm erscheint, das den Profit für alle fünfzehn Zeilen (alle drei Monate, ungefiltert) anzeigt.
  2. Drei Zeilen hinzufügen, um die Balken des Diagramms dunkelgrün (RGB(24,106,60)) einzufärben und die Legende zu entfernen, wie oben gezeigt.
  3. tblReports auf nur Januar filtern und SetSourceData erneut auf tbl.ListColumns("Profit").Range anwenden — beobachten, ob das Diagramm den Filter berücksichtigt.
Hinweis
expand arrow

1. Ausführen von BuildProfitChart

  • Kopiere das Sub exakt wie im Kapitel gezeigt und führe es aus — für diesen Teil sind keine Änderungen nötig.
  • Es sollte ein Diagramm auf dem Blatt Reports erscheinen, das den Gewinn für jede aktuell sichtbare Zeile in der Tabelle darstellt.

2. Balken einfärben und Legende entfernen

  • Beide Eigenschaften gehören zum Diagrammobjekt, nicht zum Arbeitsblatt — chartObj.Chart ist der Einstiegspunkt, wie im Formatierungsbeispiel im Kapitel.
  • Die Balkenfarbe befindet sich bei SeriesCollection(1), da nur eine Datenreihe (Profit) dargestellt wird — .Format.Fill.ForeColor.RGB ist die spezifische Eigenschaft zum Setzen.
  • Das Entfernen der Legende ist eine einzelne boolesche Eigenschaft (HasLegend), getrennt von der Zeile für die Füllfarbe.

3. Filtern und SetSourceData erneut ausführen

  • Wende einen AutoFilter auf Month (Field:=1) an, eingeschränkt auf "January" — dieselbe Technik wie in Abschnitt 4.2.
  • Rufe dann erneut SetSourceData mit dem exakt gleichen Ausdruck tbl.ListColumns("Profit").Range aus BuildProfitChart auf — an dieser Zeile muss nichts geändert werden.
  • Beobachte genau, was danach mit dem Diagramm passiert: Schrumpft es auf nur die fünf Regionen des Januars oder zeigt es immer noch alle fünfzehn Zeilen, einschließlich der gerade durch AutoFilter ausgeblendeten? Diese Beobachtung ist der eigentliche Zweck dieser Aufgabe, nicht nur das Ausführen des Codes.
Lösung
expand arrow
Option Explicit

' Point 1 — run this exactly as shown in the chapter
Sub BuildProfitChart()
    Dim ws As Worksheet
    Dim tbl As ListObject
    Dim chartObj As ChartObject

    Set ws = ThisWorkbook.Worksheets("Reports")
    Set tbl = ws.ListObjects("tblReports")

    Set chartObj = ws.Shapes.AddChart2(Style:=201, _
        XlChartType:=xlColumnClustered, _
        Left:=400, Top:=20, Width:=400, Height:=250).Chart.Parent

    With chartObj.Chart
        .SetSourceData Source:=tbl.ListColumns("Profit").Range
        .HasTitle = True
        .ChartTitle.Text = "Profit by Region"
    End With
End Sub

' Point 2 — color the bars and remove the legend
Sub FormatProfitChart()
    Dim ws As Worksheet
    Dim chartObj As ChartObject

    Set ws = ThisWorkbook.Worksheets("Reports")
    Set chartObj = ws.ChartObjects(1)

    With chartObj.Chart
        .SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(24, 106, 60)
        .HasLegend = False
    End With
End Sub

' Point 3 — filter to January, then re-point the chart at the same range
Sub FilterJanuaryAndRefreshChart()
    Dim ws As Worksheet
    Dim tbl As ListObject
    Dim chartObj As ChartObject

    Set ws = ThisWorkbook.Worksheets("Reports")
    Set tbl = ws.ListObjects("tblReports")
    Set chartObj = ws.ChartObjects(1)

    tbl.Range.AutoFilter Field:=1, Criteria1:="January"

    chartObj.Chart.SetSourceData Source:=tbl.ListColumns("Profit").Range
End Sub

Führe diese in der Reihenfolge aus: BuildProfitChart, dann FormatProfitChart, dann FilterJanuaryAndRefreshChart. Speziell bei Punkt 3 — achte darauf, was tatsächlich passiert. Excel-Diagramme berücksichtigen in der Regel einen aktiven AutoFilter und blenden die Balken der herausgefilterten Zeilen automatisch aus, auch ohne dass SetSourceData erneut ausgeführt wird. Das erneute Ausführen bestätigt hier hauptsächlich, dass das Diagramm weiterhin korrekt auf die gesamte Spalte verweist — der Filter selbst sorgt für das Ausblenden, nicht der Aufruf von SetSourceData. Es lohnt sich, den Unterschied mit aktiviertem und deaktiviertem Filter selbst zu testen.

Note
Hinweis

Das mehrfache Ausführen von BuildProfitChart erstellt jedes Mal ein neues Diagramm, ohne das alte zu löschen — so werden mehrere Diagramme übereinander gestapelt. ChartObjects(1) bezieht sich immer auf das erste erstellte Diagramm, das nun möglicherweise unter einer neueren Kopie verborgen ist. Deshalb können Formatierungsänderungen erfolgreich ausgeführt werden, aber scheinbar keine sichtbare Wirkung haben.

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 4. Kapitel 4
some-alt