この記事でわかること
- VBAでピボットテーブルを自動更新できる(PivotTable.RefreshTable)
- ブック内の全ピボットテーブルを一括で更新できる
- データソース範囲の自動拡張+ブックを開いたときに自動更新する仕組みを作れる
どんな場面で使う?
- 月次報告のピボットテーブルを毎回手動で更新するのが面倒なとき
- ブック内に複数あるピボットテーブルをまとめて一括更新したいとき
- データ行が増えたときにソース範囲の拡張も自動化したいとき
- ブックを開くだけでピボットが最新状態になる仕組みを作りたいとき
完成イメージ(Before / After)

Before(手作業でピボットテーブルを更新):
| 操作 | 所要時間 |
|---|---|
| ピボットテーブルを右クリック →「更新」 | 約10秒 |
| シートが複数ある場合、1つずつ手作業で更新 | 1〜3分 |
| データ範囲が増えたら手動でソース変更 | 約2分 |
| 更新忘れで古いデータのまま報告 | 取り返しがつかない |
After(VBAで自動更新):
| 操作 | 所要時間 |
|---|---|
| マクロ実行で全ピボット一括更新 | 数秒 |
| データ範囲の拡張も自動 | 0秒 |
| ブックを開くだけで最新状態 | 0秒 |
自分も以前、月次報告用のブックに5つほどピボットテーブルがあって、毎回手作業で1つずつ右クリック→「更新」を繰り返していた。正直めんどくさかったし、1つ更新し忘れたまま上司に提出して「このデータ古くない?」と指摘されたこともある。VBAで全ピボットを一括更新するようにしてからは、更新忘れがゼロになった。この記事で、同じ手間を抱えている人がサクッと自動化できるようになればうれしい。
ピボットテーブルの更新忘れは事故のもと。VBAで自動化すれば確実に最新データで報告できる。
なお、ピボットテーブルの作成自体をVBAで自動化したい場合は ピボットテーブルをVBAで自動生成する方法 を参照。
更新忘れを防ぐ実務チェック

自分も以前、月次報告のピボットテーブルを手作業で更新していたとき、1つだけ更新し忘れそうになったことがある。怖いのは、ピボットテーブルは古い数字のままでも見た目はきれいな表として表示されることだ。気づかずに共有すると、報告書全体の信頼性が落ちてしまう。
そのため実務では、RefreshTable を実行するだけでなく、元データの範囲、テーブル形式になっているか、ピボット名が合っているか、全シートのピボットを拾えているかまで確認したい。さらに保存前に件数や更新日時を見られるようにしておくと、あとから「本当に更新されたか」を説明しやすい。
この記事のコードは、更新ボタンを押す作業を減らすだけでなく、更新漏れを起こしにくい運用に近づけるための土台として使える。
実行前の準備
バックアップを取る
ピボットテーブルの更新はデータの書き換えを伴う。 元データが壊れていると、ピボットの集計結果もおかしくなる。必ずファイルのコピーを別フォルダに保存してから実行する。
手順
ステップ1:コードを貼り付ける
下のコード(最小版)をVBEの標準モジュールに貼り付ける。
ステップ2:シート名・ピボットテーブル名を確認する
ピボットテーブルの名前は、ピボットテーブルをクリックしたときにリボンの「ピボットテーブル分析」タブの左上に表示される。コード内の "ピボットテーブル1" を自分のピボットテーブル名に書き換える。
ステップ3:マクロを実行する
Alt + F8 →「RefreshPivot」を選択 →「実行」。ピボットテーブルが最新データに更新される。
コード(最小版):特定のピボットテーブルを更新する
Sub RefreshPivot()
'--- 特定のピボットテーブルを更新する ---
'貼り付け場所:標準モジュール
'実行方法:Alt + F8 → RefreshPivot → 実行
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1") '★シート名を変更
ws.PivotTables("ピボットテーブル1").RefreshTable '★ピボットテーブル名を変更
MsgBox "ピボットテーブルを更新しました。", vbInformation
End Sub
ポイント:
RefreshTableメソッドが更新の本体。1行で完了する- シート名とピボットテーブル名は自分の環境に合わせて書き換える
コード(実務版):全ピボット一括更新+データソース自動拡張+ブック起動時に自動更新

自分はこの実務版を使うようになってから、月次報告の準備が劇的に楽になった。データを貼り付けてブックを開き直すだけで、全ピボットが最新状態になっている。同僚にも共有したら「これブック開くだけで更新されるの?」と驚かれた。
実務版コード1:全ピボット一括更新+データソース自動拡張(標準モジュール)
Sub RefreshAllPivots()
'--- ブック内の全ピボットテーブルを一括更新する ---
'貼り付け場所:標準モジュール
'実行方法:Alt + F8 → RefreshAllPivots → 実行
Dim ws As Worksheet
Dim pt As PivotTable
Dim pc As PivotCache
Dim srcWs As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Dim srcRange As Range
Dim updatedCount As Long
Application.ScreenUpdating = False '画面更新を停止して高速化
'--- ここが追加:データソース範囲の自動拡張 ---
'ピボットの元データがあるシートの範囲を自動検出して更新する
For Each pc In ThisWorkbook.PivotCaches
On Error Resume Next
Set srcWs = Nothing
'元データのシートを取得(エラーが出る場合はスキップ)
Dim srcAddr As String
srcAddr = pc.SourceData
'SourceDataがシート参照の場合のみ処理
If InStr(srcAddr, "!") > 0 Then
Dim sheetName As String
sheetName = Left(srcAddr, InStr(srcAddr, "!") - 1)
sheetName = Replace(sheetName, "'", "") '囲みの'を除去
Set srcWs = Nothing
Set srcWs = ThisWorkbook.Worksheets(sheetName)
If Not srcWs Is Nothing Then
'最終行・最終列を取得してソース範囲を自動拡張
lastRow = srcWs.Cells(srcWs.Rows.Count, 1).End(xlUp).Row
lastCol = srcWs.Cells(1, srcWs.Columns.Count).End(xlToLeft).Column
If lastRow >= 2 And lastCol >= 1 Then
Set srcRange = srcWs.Range(srcWs.Cells(1, 1), srcWs.Cells(lastRow, lastCol))
pc.SourceData = "'" & srcWs.Name & "'!" & srcRange.Address(ReferenceStyle:=xlR1C1)
End If
End If
End If
On Error GoTo 0
Next pc
'--- ここまで追加 ---
'全シートの全ピボットテーブルを更新
updatedCount = 0
For Each ws In ThisWorkbook.Worksheets
For Each pt In ws.PivotTables
On Error Resume Next
pt.RefreshTable
If Err.Number = 0 Then
updatedCount = updatedCount + 1
Else
Debug.Print "更新失敗: " & ws.Name & " - " & pt.Name & " (Error: " & Err.Description & ")"
Err.Clear
End If
On Error GoTo 0
Next pt
Next ws
Application.ScreenUpdating = True '画面更新を再開
MsgBox updatedCount & " 個のピボットテーブルを更新しました。", vbInformation
End Sub
実務版コード2:ブックを開いたときに自動更新(ThisWorkbook モジュール)

'--- ブックを開いたときにピボットテーブルを自動更新する ---
'貼り付け場所:ThisWorkbook モジュール(標準モジュールではない!)
'VBEの左側ツリーで「ThisWorkbook」をダブルクリックして開く
Private Sub Workbook_Open()
Dim ws As Worksheet
Dim pt As PivotTable
Application.ScreenUpdating = False
For Each ws In ThisWorkbook.Worksheets
For Each pt In ws.PivotTables
On Error Resume Next
pt.RefreshTable
On Error GoTo 0
Next pt
Next ws
Application.ScreenUpdating = True
End Sub
実務版のポイント:
RefreshAllPivotsはデータソース範囲を自動拡張してから更新するので、行が増えても安心Workbook_Openイベントでブックを開くだけで自動更新される- エラー処理付きなので、1つのピボットが壊れていても他のピボットは更新される
- 画面更新・再計算を止めてマクロを高速化する方法 の ScreenUpdating を組み合わせて高速化している
ThisWorkbook モジュールへの貼り付け方:
VBEの左側「プロジェクトエクスプローラー」で
ThisWorkbookをダブルクリック → 表示されたコード画面に貼り付ける。標準モジュールに貼り付けても動かないので注意。イベント処理の詳細は ブックを開いたとき・保存時に自動実行するイベント処理の方法 を参照。
落とし穴
自分も最初、ピボットテーブルの更新マクロを書いたとき「これだけ?簡単じゃん」と思っていたのに、実務で使い始めたら予想外のトラブルに何度もハマった。特に3番目のソース範囲ずれは、上司に報告した集計表の合計値がおかしくて冷や汗をかいた。
| # | 症状 | 原因 | 対策 |
|---|---|---|---|
| 1 | 「実行時エラー ‘1004’」が出る | ピボットテーブル名が間違っている、またはシート名が違う | ピボットテーブルをクリックして「ピボットテーブル分析」タブで正しい名前を確認する |
| 2 | 更新したのにデータが古いまま | ピボットキャッシュが更新されていない。複数のピボットが同じキャッシュを共有している場合がある | PivotCache.Refresh を使うか、ThisWorkbook.RefreshAll で全キャッシュを更新する |
| 3 | 新しく追加した行がピボットに反映されない | データソース範囲が固定されていて、追加行が範囲外になっている | 実務版コードのようにソース範囲を自動拡張するか、元データを テーブル形式 にしておく |
| 4 | Workbook_Openが動かない | マクロのセキュリティ設定で「マクロを無効にする」が選択されている | 「ファイル」→「オプション」→「トラストセンター」→「マクロの設定」で「警告を表示してすべてのマクロを無効にする」を選び、開くときに「コンテンツの有効化」をクリックする |
| 5 | 更新が異常に遅い | データソースが大量(10万行超)で、画面更新が走っている | Application.ScreenUpdating = False を設定する。実務版コードには組み込み済み |
| 6 | 外部データソースのピボットで認証エラーが出る | 外部DB接続のピボットは接続情報が必要 | 本記事のコードはExcelシート上のデータがソースの場合を想定。外部接続の場合は PivotCache.Connection の設定が別途必要 |
VBAでピボットテーブルの更新がエラーになるときの対処法
「RefreshTableを実行するとエラーが出る」という場合、原因はデータソースの範囲が無効になっていることが多い。データの行数が変わった場合、ソース範囲が古いまま。PivotCacheのSourceDataを最新の最終行に合わせて更新してからRefreshする。
VBAでピボットテーブルのソース範囲が自動拡張されないときの対処法
「データを追加したのにピボットに反映されない」という場合、原因はソース範囲が固定されていること。ChangePivotCacheでSourceDataを動的に設定するか、テーブル形式(ListObject)をソースにすれば自動でデータ範囲が拡張される。
実務でピボット更新を自動化する前の確認
ピボットテーブルの更新自動化で一番怖いのは、更新ボタンを押したのに元データの範囲が古いまま、という状態です。見た目は更新されたように見えても、新しく追加された行がデータソースに含まれていなければ、集計結果は正しくありません。そのため、更新処理と一緒に、元データの範囲が最新行まで広がっているかを確認します。
業務では、月次レポートや売上一覧のように、毎回行数が増える表でピボットを使うことが多いです。この場合は、元データをテーブル化しておくか、最終行を取得してデータ範囲を更新する方針にしておくと安定します。更新忘れだけでなく、範囲漏れを防ぐことまで含めて自動化と考えるのがポイントです。
| 確認項目 | 起きやすい問題 | 対策 |
|---|---|---|
| 元データ範囲 | 新しい行が集計されない | テーブル化または範囲更新 |
| 空白行 | 最終行判定がずれる | 基準列を決める |
| ピボット名 | 名前変更でエラー | 事前に名前を確認する |
| 更新タイミング | 開いた直後に古い結果を見る | Workbook_Openで更新するか決める |
更新前に元データ件数を確認する例
Dim lastRow As Long
lastRow = Worksheets("データ").Cells(Rows.Count, "A").End(xlUp).Row
If lastRow < 2 Then
MsgBox "更新するデータがありません"
Exit Sub
End If
ピボット更新の前にデータ件数を確認しておくと、空の表を更新してしまうミスを防げます。自動更新は便利ですが、元データがない状態や、貼り付け途中の状態で動くと混乱します。ボタン実行にするのか、ブックを開いたタイミングで実行するのかも、使う人の作業手順に合わせて決めておくと安全です。
FAQ
Q1. RefreshTableとRefreshAllの違いは?
PivotTable.RefreshTable は個別のピボットテーブルを更新する。ThisWorkbook.RefreshAll はピボットテーブルだけでなく、クエリテーブルや外部データ接続もすべて更新する。ピボットだけ更新したい場合は RefreshTable を使う。外部接続も含めて全部更新したい場合は RefreshAll が手軽。
Q2. ピボットテーブルの名前がわからない場合はどうする?
ピボットテーブルのセルをクリックすると、リボンの「ピボットテーブル分析」タブの左上に名前が表示される。VBAで一覧を取得したい場合は、イミディエイトウィンドウで For Each pt In ActiveSheet.PivotTables: Debug.Print pt.Name: Next を実行すると全ピボット名が出力される。
Q3. 元データをテーブル形式にしておけばソース範囲の自動拡張は不要?
その通り。元データを Ctrl + T でテーブル化しておけば、行を追加してもピボットのソース範囲が自動で追従する。テーブル操作の詳細は テーブル形式のデータをVBAで操作する方法 を参照。自分も最初はRange指定で苦労していたが、テーブル形式に変えてからは範囲ずれの問題がなくなった。
Q4. 特定のシートのピボットだけ更新したい場合は?
最小版コードのように、シート名を指定して For Each pt In ws.PivotTables でループすればよい。実務版コードの「全シートループ」部分を特定シートに限定するだけで対応できる。
Q5. セルの値が変わったときに自動でピボットを更新できる?
できる。Worksheet_Change イベント内で RefreshTable を呼び出せばよい。ただし、ピボットの元データがあるシートで Worksheet_Change を使うと、更新のたびにイベントが発火してループする可能性がある。Application.EnableEvents = False で制御が必要。詳細は セルの値が変わったら自動実行する方法 を参照。
まとめ
この記事では、VBAでピボットテーブルを自動更新する方法を解説した。
- 基本:
PivotTable.RefreshTableで特定のピボットを更新 - 実務版: 全ブック内の全ピボットを一括更新+データソース範囲の自動拡張
- 自動化:
Workbook_Openイベントでブックを開くだけで最新状態にする
ピボットテーブルの更新忘れは報告ミスに直結する。VBAで自動化しておけば、常に最新データで集計できる。
元データのソース範囲ずれが心配な場合は、データを テーブル形式 にしておくのが最も確実な方法。
次にやりたくなること
- グラフのデータ範囲を自動更新する方法: ピボットや集計表に連動するグラフも最新化したい場合
- ピボットテーブルをVBAで自動生成する方法: ピボットテーブルの作成自体もVBAで自動化したい場合
- データをテーブル形式にしてVBAで扱いやすくする方法: ピボットの元データ範囲を安定させたい場合
- 画面更新・再計算を止めてマクロを高速化する方法: 大量のピボット更新を高速化したい場合
- セルの値が変わったら自動実行する方法: 元データが変わったタイミングで処理を走らせたい場合
- Workbook_Openで開くたびに自動更新したい場合: まずこの記事の「ThisWorkbook モジュール」に貼り付けるコードで動作確認する


コメント