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

Excel VBA のチャート — コードでチャートを作成する方法と、間違ったデータが描画される理由

|

Excel VBA のチャート — コードでチャートを作成する方法と、間違ったデータが描画される理由

TL;DR — チャートはデータを保存しません — Range への参照 を保存します。各系列の .Values=Sheet1!$B$2:$B$13 のような数式なので、チャートはその参照と同じだけしか正しくなりえません。埋め込み チャートは ws.ChartObjects.Add(left, top, width, height) で作り、その .Chart を取得し、.ChartType を設定し、.SetSourceData Source:=Range(...) で一度にデータを結び付けます。噛みついてくるのは 2 つ: 埋め込みチャートは ChartObjects に住みます(Charts ではありません。あちらはチャートシートです)。 そして、先に古いものを削除しない限り、マクロの再実行は重複したチャートを積み上げます。

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                                   ' ChartObject は枠、.Chart がチャート本体
ch.ChartType = xlColumnClustered
ch.SetSourceData Source:=Worksheets("Data").Range("A1:B13")   ' 範囲全体を一度に結び付ける
ch.HasTitle = True
ch.ChartTitle.Text = "Monthly Sales"

VBA でのチャート作りは簡単そうに見えます — 2 回目の実行でチャートが 2 つ見つかるまで、あるいは 1 回目の実行で棒が間違った列を描くまでは。どちらも同じ誤解から来ていて、どちらの直し方も同じ考えです。チャートはあなたのデータを含んでいるのではなく、それを指しているのです。 どの系列も、数式として書かれた範囲への 参照 を持っています。データを動かし、行を挿入し、別の場所で元データを作り直しても、チャートは命じられた場所を指し続け、間違ったセルを忠実に描きます。「チャートは Range に結び付いた 1 つのビューだ」と握った瞬間、API は面倒であることをやめ、2 つの古典的なバグは自明になります。

この記事で学べること

  • 考え方の軸 — チャートはデータのコピーではなく、Range への参照を持つ
  • 2 つの入れ物:埋め込みの ChartObjects と、Charts の中のチャートシート
  • SetSourceData で一度にチャートを作ってデータを結び付ける
  • SeriesCollection で手作業で系列を追加・制御する
  • 再実行での重複チャートの罠と、古いチャートの消し方
  • チャートがデータを追いかけるよう、元データを Table に結び付ける

考え方の軸:チャートは Range を指す

範囲をチャートにするとき、Excel は数値をチャートにコピーしません。系列ごとに、その範囲を参照する数式 を保存します — セルの数式が他のセルを参照するのとまったく同じです。それは読み戻せます。

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

この SERIES(...) 数式が、チャートについてのすべての真実です。名前、X 値への参照、Y 値への参照です。チャートは、それらの参照に対する 1 つのライブビューです。だからこそ「チャートが間違ったデータを表示する」がこれほどよくあるのです — チャートが間違っているのではなく、その参照が、あなたの思うものをもう持っていないセルを指しているのです。そしてこれが、本記事の最後で扱う恒久的な直し方が、$B$2:$B$13 で凍りつく代わりに参照にデータを追いかけさせることである理由です。

2 つの入れ物:ChartObjects とチャートシート

Excel にはチャートの住まいが 2 つあり、それらを取り違えることが、チャートのマクロを最初につまずかせます。埋め込み チャートはワークシート上に浮かび、そのシートの ChartObjects コレクションに住みます。チャートシート はチャートだけからなる 1 枚のタブで、ブックの Charts コレクションに住みます。

' 埋め込み:ChartObject は枠/入れ物、その .Chart がチャート本体
Dim co As ChartObject
Set co = Worksheets("Report").ChartObjects.Add(300, 20, 420, 260)
co.Chart.ChartType = xlLine        ' プロパティは co ではなく .Chart に設定する

' チャートシート:それ自体が 1 枚のタブ
Dim ch As Chart
Set ch = ThisWorkbook.Charts.Add

人に 1 時間を払わせる微妙な点はこれです。埋め込みチャートでは、ChartObjects.AddChartObject)を渡し、実際に書式を設定するチャートは co.Chart です。チャートが埋め込みなのに Charts(1) に手を伸ばすとエラーになります。Charts はチャートシートしか持たないからです。ほとんどのレポートはワークシート上にあるので、ChartObjects のほうをずっと多く使うことになります — 枠とチャートという 2 層の区別だけ、覚えておきましょう。

SetSourceData で一度にチャートを作ってデータを結び付ける

きれいなやり方はこうです。枠を追加し、.Chart を取得し、種類を設定し、SetSourceData で元データ全体を 1 回の呼び出しで結び付ける。

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 は、ブロック全体 — 見出し・分類項目・値 — を Excel に手渡し、系列を割り出させます。範囲を選んでチャートのボタンを押すのと、まさに同じです。これはほぼつねに望みどおりの動作で、系列を 1 つずつ組み立てるより行数もミスも少なくなります。範囲に見出し行と分類項目の列を含めれば、チャートは自分でラベルを付けます。.ChartType は前でも後でも設定できます — よく使う値は xlColumnClusteredxlLinexlPiexlXYScatter です。

SeriesCollection で手作業で系列を追加・制御する

精密な制御が要るとき — 一度に 1 系列、連続しない場所からの値、独自の名前 — は、SeriesCollection を通して系列を追加します。

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")

どの系列も、あの SERIES(...) 数式にそのまま対応する 3 つの部分を持ちます。.Name.XValues(分類項目のラベル)、.Values(数値)です。2 つ目の系列はもう一度 NewSeries で追加し、削除は ch.SeriesCollection(2).Delete です。.Values に範囲を設定することは、系列の数式に参照を書き込むことと同じです — これが間違ったデータのバグの背後にある仕組みであり、安定した元データに結び付けることが効いてくる理由です。

重複チャートの罠と、古いチャートの消去

12 回実行すると 12 個のチャートを生むバグがこれです。ChartObjects.Addつねに新しいものを 1 つ追加します。前回のチャートを再利用することは決してないので、無人のマクロは黙ってコピーを積み上げます。作る前に、シートの既存のチャートを消しましょう。

Dim co As ChartObject
For Each co In Worksheets("Report").ChartObjects
    co.Delete                          ' 先に前回のチャートを削除する
Next co
' ...これで新しいチャートを作る

ChartObjects をループして 1 つずつ Delete し、きれいな状態からチャートを作ります — 繰り返しの作成すべてに使うのと同じ コレクション の規律です。特定の 1 つのチャートを残して更新したいなら、名前を付け(co.Name = "chtSales")、次の実行でその名前で引き、新しい枠を追加する代わりに SetSourceData をもう一度呼びます。どちらにせよ、意図して決めましょう。新しく作るのか、その場で更新するのか — 何も考えずに追加してはいけません。

チャートがデータを追いかけるよう、元データを Table に結び付ける

さて、間違ったデータのバグへの恒久的な直し方です。系列は参照なので、A1:B13 に結び付いたチャートは 13 行で凍りつきます — 月を 1 つ追加すると、新しい点はチャートの外です。代わりに元データを Table に結び付ければ、参照はデータとともに伸びます。

' チャートの元データは Table の範囲 -> 新しい行が自動的に現れる
ch.SetSourceData Source:=Worksheets("Data").ListObjects("tblSales").Range

元データが ListObject のとき、行を追加すると Table が伸び、Table は系列が参照する範囲を伸ばし、チャートは新しい点とともに描き直されます — コードも、SetSourceData のやり直しも要りません。これは ピボット を最新に保つのと同じ一手であり、Table がまず作る価値のある土台である理由です。ピボットとチャートを一度そこに向ければ、両方が自己更新します。チャートを画像として渡すには、co.Chart.Export "C:\Reports\sales.png" がディスクに直接 PNG を書き出します。

ExcelMaster の活用

完成したレポートまで届いてしまうチャートのミスは、静かなものです。誰も削除しなかった 2 つ目のチャート、前四半期の範囲をまだ指している系列、SetSourceData がずれたブロックを受け取ったせいで間違った列を描く棒。どれもきれいに描画されます — ただ、間違った絵を見せるだけです。

ExcelMaster は、その 3 つすべてに痛い目を見た人のようにチャートを作ります。「月次の売上を地域別にチャートにして」と頼めば、描く前に古い ChartObjects を消し、新しい行が自ら現れるよう元データを Table に結び付け、系列を手配線する代わりに SetSourceData でブロック全体を使い、枠とチャートの区別につまずくのではなく co.Chart を通して書式を設定します。あなたはほしい絵を説明するだけ。データが伸びてもチャートが真実を語り続けるよう参照を配線するのは、それがやります。

よくある質問

VBA でチャートを作成するには?

埋め込みチャートを ChartObjects.Add で追加し、その種類とデータを .Chart を通して設定します。Set co = ws.ChartObjects.Add(300, 20, 420, 260)Set ch = co.Chartch.ChartType = xlColumnClusteredch.SetSourceData Source:=Range("A1:B13") です。ChartObject が枠で、その .Chart が書式を設定するチャートです。SetSourceData は範囲全体を 1 回の呼び出しで結び付けます。

VBA のチャートが間違ったデータを描画するのはなぜ?

チャートは範囲のコピーではなく、範囲への参照を持つからです — 各系列の .Values=Sheet1!$B$2:$B$13 のような数式です。データが動いたり、行が挿入されたり、元データが別の場所で作り直されたりすると、参照はまだ古いセルを指し、チャートはそれを描きます。SetSourceData で結び付け直すか、参照がデータを追いかけるよう元データを Table に向けましょう。

VBA の ChartObjects と Charts の違いは?

ChartObjects は、シート上に浮かぶ 埋め込み チャートの、ワークシートのコレクションです。各 ChartObject は枠で、その .Chart が実際のチャートです。Chartsチャートシート の、ブックのコレクションです — チャートだけからなるタブです。チャートが埋め込みなのに Charts(1) に手を伸ばすとエラーになります。代わりに ws.ChartObjects(1).Chart を使いましょう。

VBA でチャートに系列を追加するには?

SeriesCollection.NewSeries を使い、その各部を設定します。Set s = ch.SeriesCollection.NewSeriess.Name = "2026"s.XValues = Range("A2:A13")s.Values = Range("B2:B13") です。さらに追加するにはもう一度 NewSeries、削除は ch.SeriesCollection(2).Delete です。単純なチャートなら、範囲全体への SetSourceData のほうが、手作業で系列を追加するより簡単です。

VBA で重複したチャートが作られるのを止めるには?

ChartObjects.Add はつねに新しいチャートを追加するので、マクロを再実行するとコピーが積み上がります。作る前に、既存のものを削除します。For Each co In ws.ChartObjects: co.Delete: Next co です。特定のチャートを残して更新したいなら、名前を付け(co.Name = "chtSales")、次の実行でその名前で見つけ、新しい枠を追加する代わりに SetSourceData をもう一度呼びます。

検証環境

検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-02.

関連ガイド: VBA Pivot Table · VBA Table · VBA Range · VBA Collection · VBA Worksheet