【VBA】グラフのデータ範囲を自動更新する方法(コピペOK)
この記事でできること
VBAで Excelグラフのデータ範囲を自動更新 できるようになります。
データが追加されるたびにグラフの範囲を手動で変更している方、この記事のコードをコピペすれば 最終行を自動検出してグラフの範囲を一発で更新 できます。所要時間は5分です。
自分も月次報告のグラフを毎回手で範囲変更していて、正直めんどくさかった。しかも範囲を間違えてグラフが歯抜けになってるのに気づかず提出したこともある。VBAで自動化してからは、データを追加するだけでグラフが勝手に更新されるので、確認作業すら不要になった。同じ苦労をしている方がこの記事でサクッと解決できればうれしい。
どんな場面で使う?
- 月次・週次レポート — 毎月データ行が追加される売上表やKPIダッシュボードで、グラフの範囲を手動で伸ばす手間をゼロにしたい
- 在庫推移・生産実績の管理 — 日々の記録がどんどん増える台帳で、常に最新データまでグラフに反映させたい
- 複数グラフのダッシュボード — 1シートに5個以上のグラフを貼っていて、全部まとめて一発で更新したい
- 共有ブックの自動化 — ブックを開いた瞬間にグラフが最新状態になっていてほしい(Workbook_Openとの組み合わせ)
- テーブル形式のデータ管理 — ListObject(テーブル)を使っているが、グラフだけテーブル拡張に追従しない場合の対策
前提条件
| 項目 | 内容 |
|---|---|
| Excel | 2016以降 / Microsoft 365 |
| OS | Windows 10 / 11 |
| 保存形式 | .xlsm(マクロ有効ブック) |
| 貼り付け場所 | 標準モジュール(基本コード・実務版) / ThisWorkbook(自動更新版) |
| 実行方法 | マクロ実行 / ブックを開いたとき自動実行 |
バックアップ推奨: 実行前にブックのコピーを保存してください。グラフの参照範囲を変更する操作は元に戻す(Ctrl+Z)が効きません。
—
完成イメージ(Before / After)
Before: データを5行追加したのに、グラフは古い範囲のまま。手動でデータ範囲を変更する必要がある。
After: マクロを実行(またはブックを開く)だけで、グラフのデータ範囲が最終行まで自動的に拡張される。
—
手順
- 開発タブ を表示する(表示されていない場合は「ファイル → オプション → リボンのユーザー設定」で「開発」にチェック)
- Alt + F11 でVBE(コードを書く画面)を開く
- 「挿入」→「標準モジュール」 をクリック
- 下のコードをコピーして貼り付ける
- シートに戻り、Alt + F8 でマクロを選んで実行する
- グラフのデータ範囲が最終行まで更新されていることを確認する
VBEの開き方やマクロの実行方法が分からない場合は、VBAマクロにショートカットキーを割り当てて素早く実行する方法 も参考にしてください。
—
基本コード(最終行取得 → グラフの範囲更新)
Sub UpdateChartRange()
Dim ws As Worksheet
Dim cht As ChartObject
Dim lastRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
'--- 最終行を取得(A列基準)
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
'--- シート上の1番目のグラフを取得
Set cht = ws.ChartObjects(1)
'--- データ範囲を更新(A1からD列の最終行まで)
cht.Chart.SetSourceData Source:=ws.Range("A1:D" & lastRow)
MsgBox "グラフの範囲を A1:D" & lastRow & " に更新しました。"
End Sub
ポイント:
SetSourceDataがグラフのデータ範囲を丸ごと変更するメソッド。個別の系列ではなく、グラフ全体のソースを一括で差し替えるため、系列が複数あっても1行で更新できるEnd(xlUp)でA列の最終行を取得し、範囲を動的に構築する。この書き方なら、データが10行でも1,000行でも同じコードで対応できる- シート名(
"Sheet1")と列範囲("A1:D")は自分のブックに合わせて変更する。たとえばA列〜F列までデータがあるなら"A1:F"に書き換える
なぜ SetSourceData を使うのかというと、グラフのデータ範囲を「右クリック → データの選択 → 範囲を手入力」で変えるのと同じ操作をコード1行で実現できるからだ。手動だとグラフの数だけ繰り返す必要があるが、VBAなら一瞬で終わる。
最終行の取得方法をもっと詳しく知りたい方は データの最終行・最終列を正確に取得する方法 を参照してください。
—
実務版コード
実務版1: シート上の全グラフを一括更新
グラフが複数あるシートで、すべてのグラフを一括更新します。
Sub UpdateAllChartsOnSheet()
Dim ws As Worksheet
Dim cht As ChartObject
Dim lastRow As Long
Dim dataRange As Range
Dim updatedCount As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
'--- 最終行を取得(A列基準)
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
'--- データがなければ終了
If lastRow < 2 Then
MsgBox "データがありません。", vbExclamation
Exit Sub
End If
'--- 全グラフをループして一括更新
For Each cht In ws.ChartObjects
'--- 各グラフのデータ範囲を更新
On Error Resume Next
cht.Chart.SetSourceData Source:=ws.Range("A1:D" & lastRow)
If Err.Number = 0 Then
updatedCount = updatedCount + 1
Else
Debug.Print "更新失敗: " & cht.Name & " - " & Err.Description
Err.Clear
End If
On Error GoTo 0
Next cht
MsgBox updatedCount & " 個のグラフを更新しました(範囲: A1:D" & lastRow & ")"
End Sub
自分はこれを覚えてから、ダッシュボードシートに貼った5つのグラフを1回のマクロ実行で全部更新できるようになった。月次報告の準備が10分は短くなった。
コード解説:
このコードのキモは For Each cht In ws.ChartObjects のループだ。シート上に埋め込まれたグラフオブジェクトをすべて巡回し、1つずつ SetSourceData で範囲を更新している。On Error Resume Next でエラーを吸収しているのは、グラフによってはデータ構造が異なり更新に失敗する場合があるため。失敗したグラフはイミディエイトウィンドウ(Debug.Print)に名前が出力されるので、あとから個別に原因を調べられる。updatedCount で成功件数をカウントしておくことで、全部更新できたかどうかをMsgBoxで確認できる仕組みになっている。
実務版2: ブックを開いたとき自動更新(Workbook_Openイベント)
ブックを開くだけでグラフが自動更新される設定です。
貼り付け場所が違います: このコードは ThisWorkbook モジュールに貼り付けてください。標準モジュールでは動きません。
手順: VBEの左側ツリーで「ThisWorkbook」をダブルクリック → 以下のコードを貼り付け
Private Sub Workbook_Open()
Dim ws As Worksheet
Dim cht As ChartObject
Dim lastRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
'--- 最終行を取得
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
'--- データがなければ何もしない
If lastRow < 2 Then Exit Sub
'--- 全グラフのデータ範囲を更新
For Each cht In ws.ChartObjects
On Error Resume Next
cht.Chart.SetSourceData Source:=ws.Range("A1:D" & lastRow)
On Error GoTo 0
Next cht
End Sub
コード解説:
Workbook_Open はExcelがブックを開いた瞬間に自動実行されるイベントプロシージャだ。通常のSubプロシージャと違い、ユーザーがマクロを手動で実行する必要がない。このコードでは If lastRow < 2 Then Exit Sub で安全弁を設けており、データが空(ヘッダー行しかない)の場合はグラフ更新をスキップする。こうしておくと、新規ブックや空シートで余計なエラーが出ない。
イベント処理の詳細は ブックを開いたとき・保存時に自動実行するイベント処理の方法 で解説しています。
実務版3: テーブル(ListObject)参照版
データをテーブル形式で管理している場合はこちら。テーブルなら自動拡張されるため、最終行の取得が不要になります。
Sub UpdateChartFromTable()
Dim ws As Worksheet
Dim tbl As ListObject
Dim cht As ChartObject
Dim dataRange As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
'--- テーブルを取得(シート上の1番目のテーブル)
If ws.ListObjects.Count = 0 Then
MsgBox "テーブルが見つかりません。", vbExclamation
Exit Sub
End If
Set tbl = ws.ListObjects(1)
'--- テーブル全体(見出し+データ)を範囲として取得
Set dataRange = tbl.Range
'--- グラフのデータ範囲を更新
Set cht = ws.ChartObjects(1)
cht.Chart.SetSourceData Source:=dataRange
MsgBox "グラフの範囲をテーブル「" & tbl.Name & "」に更新しました。"
End Sub
コード解説:
テーブル(ListObject)を使う最大のメリットは、データを追加すると自動的にテーブル範囲が拡張される点だ。つまり最終行を End(xlUp) で取得する必要がなくなる。tbl.Range はヘッダー行を含むテーブル全体を返すので、グラフの SetSourceData にそのまま渡せる。データ行だけが欲しい場合は tbl.DataBodyRange を使えばよい。テーブルを使っていないブックではこの方法は使えないが、テーブル管理に切り替えれば最終行のズレに悩まされることがなくなるので、長期運用するブックにはおすすめの構成だ。
テーブル操作の基本は テーブル形式のデータをVBAで操作する方法 を参照してください。
---
落とし穴
| # | 症状 | 原因 | 対策 |
|---|---|---|---|
| 1 | 「実行時エラー '9': インデックスが有効範囲にありません」 | シート名が間違っている("Sheet1" がブックに存在しない) |
Sheets("Sheet1") のシート名を実際のシート名に修正する |
| 2 | グラフが更新されない(範囲が変わらない) | SetSourceData の列範囲がグラフのデータ構造と合っていない |
グラフを右クリック →「データの選択」で現在の範囲を確認し、列範囲を合わせる |
| 3 | 「実行時エラー '1004'」が出る | グラフシート(埋め込みでなく独立シートのグラフ)に ChartObjects を使っている |
グラフシートの場合は ThisWorkbook.Charts("Chart1").SetSourceData を使う |
| 4 | 最終行がずれる(空白行の下にデータがある) | End(xlUp) は連続データの末尾を取得するため、途中に空白行があるとそこで止まる |
空白行を削除するか、UsedRange や Find で最終行を取得する。詳しくは データの最終行・最終列を正確に取得する方法 を参照 |
| 5 | Workbook_Openが動かない | マクロが無効になっている / セキュリティ設定でブロックされている | 「ファイル → オプション → トラストセンター → マクロの設定」で「通知を表示してすべてのマクロを無効にする」を選び、ブックを開いたときに「コンテンツの有効化」をクリックする |
| 6 | 複数系列のグラフで一部の系列だけ更新したい | SetSourceData はグラフ全体の範囲を変更するため、個別の系列は変更できない |
系列ごとに更新する場合は cht.Chart.SeriesCollection(1).Values = ws.Range("B2:B" & lastRow) のように SeriesCollection を使う |
自分も最初、シート名のスペルミスで30分溶かした。エラーが出たらまずシート名を確認するクセをつけると無駄な時間が減る。
VBAでグラフのデータ範囲が変更できないときの対処法
「SetSourceDataを実行してもグラフの範囲が変わらない」という場合、原因は列範囲がグラフのデータ構造と合っていないことが多い。たとえばグラフがA列〜C列のデータで作られているのに、SetSourceData Source:=ws.Range("A1:D" & lastRow) とD列まで指定すると、余分な系列が追加されるか無視される。対策として、まずグラフを右クリック→「データの選択」で現在の範囲を確認し、コードの列範囲をそれに合わせる。自分もこれで「更新したのに見た目が変わらない」と悩んだことがある。
VBAでSetSourceDataがエラーになるときの対処法
「SetSourceDataで実行時エラー1004が出る」という場合、原因はグラフがシートに埋め込まれたChartObjectではなく、独立したグラフシートであることが多い。グラフシートの場合は ws.ChartObjects(1) ではアクセスできず、ThisWorkbook.Charts("Chart1").SetSourceData のように Charts コレクションから直接アクセスする必要がある。また、Source に渡す範囲がデータのないシートを参照している場合もエラーになるので、シート名とデータ範囲の両方を確認すること。
VBAでWorkbook_Openでグラフの自動更新が動かないときの対処法
「ブックを開いたのにグラフが更新されない」という場合、原因はマクロのセキュリティ設定でVBAが無効になっていることが多い。Excelのデフォルト設定では、ブックを開いたときに「コンテンツの有効化」ボタンをクリックしないとマクロが実行されない。「ファイル→オプション→トラストセンター→マクロの設定」で「通知を表示してすべてのマクロを無効にする」を選び、ブックを開いたときに必ず「コンテンツの有効化」をクリックする運用を徹底する。信頼できるフォルダにファイルを置くと、毎回クリックする手間を省ける。
---
FAQ
Q1. グラフが埋め込みではなくグラフシート(独立シート)の場合は?
グラフシートの場合は ChartObjects ではなく、Charts コレクションからアクセスします。
ThisWorkbook.Charts("Chart1").SetSourceData _
Source:=ThisWorkbook.Sheets("Sheet1").Range("A1:D" & lastRow)
Q2. 特定のグラフだけ更新するには?
ChartObjects をインデックスまたは名前で指定します。グラフ名はグラフをクリックしたときに数式バーの左側に表示されます。
ws.ChartObjects("Chart 1").Chart.SetSourceData Source:=ws.Range("A1:D" & lastRow)
Q3. データが列方向に増える場合(行ではなく列が追加される)は?
最終列を取得して範囲を構築します。
Dim lastCol As Long
lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
cht.Chart.SetSourceData Source:=ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))
Q4. グラフの種類(棒グラフ→折れ線グラフなど)も同時に変更できる?
はい。ChartType プロパティで変更できます。
cht.Chart.ChartType = xlLine '折れ線グラフに変更
グラフの作成方法については データ範囲からグラフを自動作成する方法 で詳しく解説しています。
Q5. Worksheet_Changeイベントでデータ入力のたびにグラフを更新できる?
できます。ただし、パフォーマンスの観点からデータ量が多い場合は Workbook_Open での更新をおすすめします。セル変更イベントの書き方は セルの値が変わったら自動実行するイベント処理の方法 を参照してください。
---
まとめ
この記事では、VBAで グラフのデータ範囲を自動更新する方法 を解説しました。
- 基本:
Chart.SetSourceDataとEnd(xlUp)で最終行まで範囲を更新 - 一括更新:
For Each ChartObjectで全グラフを一発更新 - 自動更新:
Workbook_Openイベントでブックを開くたびに自動更新 - テーブル版:
ListObject.Rangeでテーブルの自動拡張を活用
データが増えるたびに手でグラフの範囲を変えるストレスから解放されます。グラフの自動更新は一度設定してしまえば、あとは意識する必要がない。自分の経験では、この仕組みを入れたブックは「データを貼って開くだけ」の状態になり、報告書の準備時間が体感で半分以下になった。まずは基本コードで1つのグラフを更新するところから始めて、慣れたらWorkbook_Openで自動化するのが失敗の少ない進め方だ。
---
次にやりたくなること
- グラフ自体をVBAで作りたい → データ範囲からグラフを自動作成する方法 でグラフの種類・書式設定まで自動化できます
- テーブル形式でデータを管理したい → テーブル形式のデータをVBAで操作する方法 でテーブルの追加・フィルタ・集計をVBAで操作できます
- 最終行の取得方法をもっと正確にしたい → データの最終行・最終列を正確に取得する方法 で5つの取得方法と使い分けを解説しています
- データの追加自体も自動化したい → セルの値を別シートに転記する方法 でデータの転記処理と組み合わせると、入力からグラフ更新まで全自動にできます
- 処理にかかった時間を計測したい → 処理時間を計測してボトルネックを見つける方法 で、グラフ更新処理のパフォーマンスを数値で把握できます
---
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "VBAでグラフシート(独立シート)のデータ範囲を更新するには?",
"acceptedAnswer": {
"@type": "Answer",
"text": "グラフシートの場合はChartObjectsではなく、ThisWorkbook.Charts(\"Chart1\").SetSourceData Source:=範囲 のようにChartsコレクションからアクセスします。"
}
},
{
"@type": "Question",
"name": "VBAで特定のグラフだけデータ範囲を更新するには?",
"acceptedAnswer": {
"@type": "Answer",
"text": "ChartObjectsをインデックスまたは名前で指定します。例: ws.ChartObjects(\"Chart 1\").Chart.SetSourceData Source:=範囲。グラフ名はグラフをクリックしたときに数式バーの左側に表示されます。"
}
},
{
"@type": "Question",
"name": "VBAでデータが列方向に増える場合のグラフ更新方法は?",
"acceptedAnswer": {
"@type": "Answer",
"text": "最終列をCells(1, Columns.Count).End(xlToLeft).Columnで取得し、ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))のように範囲を構築してSetSourceDataに渡します。"
}
},
{
"@type": "Question",
"name": "VBAでグラフの種類も同時に変更できる?",
"acceptedAnswer": {
"@type": "Answer",
"text": "はい。Chart.ChartTypeプロパティで変更できます。例: cht.Chart.ChartType = xlLine で折れ線グラフに変更できます。"
}
},
{
"@type": "Question",
"name": "Worksheet_Changeイベントでデータ入力のたびにグラフを更新できる?",
"acceptedAnswer": {
"@type": "Answer",
"text": "可能ですが、データ量が多い場合はパフォーマンスが低下する可能性があります。Workbook_Openイベントでの更新がおすすめです。"
}
}
]
}


コメント