VBAによるピボットテーブルの作成
メニューを表示するにはスワイプしてください
ピボットテーブルは、フィールドを行、列、値にドラッグしてテーブルを要約する機能であり、これらのドラッグ&ドロップ操作にはすべて直接対応するVBAコードが存在します。つまり、新しいデータが到着するたびに、マクロによってピボットテーブルレポート全体をゼロから再構築することが可能です。
ピボットテーブルの作成
Sub BuildProfitPivot()
Dim wsData As Worksheet, wsPivot As Worksheet
Dim tbl As ListObject
Dim pc As PivotCache
Dim pt As PivotTable
Set wsData = ThisWorkbook.Worksheets("Reports")
Set tbl = wsData.ListObjects("tblReports")
' start clean: remove an existing Pivot sheet if this has run before
On Error Resume Next
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("Pivot").Delete
Application.DisplayAlerts = True
On Error GoTo 0
Set wsPivot = ThisWorkbook.Worksheets.Add
wsPivot.Name = "Pivot"
Set pc = ThisWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, SourceData:=tbl.Range)
Set pt = pc.CreatePivotTable( _
TableDestination:=wsPivot.Range("A3"), _
TableName:="ptProfitByRegion")
With pt
.PivotFields("Region").Orientation = xlRowField
.PivotFields("Month").Orientation = xlColumnField
.AddDataField .PivotFields("Profit"), "Sum of Profit", xlSum
End With
End Sub
DisplayAlertsと.Deleteの切り替え、DisplayAlerts = Falseの組み合わせは、「存在すれば削除」パターンの安全な実装方法:存在しないシートを削除しようとすると通常はエラーが発生しマクロが停止しますが、On Error Resume Next によりその特定のエラーを無視して処理を継続します。Error GoTo 0は、Excel の「このシートを本当に削除しますか?」という確認ポップアップを非表示にします。- 直後の
On Error Resume Nextで通常のエラー報告に戻します。On Error Resume Next をSubの残り全体で有効にしたままだと、後続の無関係なエラーもすべて黙って無視されてしまうため、これは避けるべき落とし穴です。 ThisWorkbook.PivotCaches.Createはテーブルデータのスナップショット(PivotCache)を作成します。これは PivotTable そのものではなく、すべての PivotTable が内部的に基づくオブジェクトです。pc.CreatePivotTableは、そのスナップショットを実際に表示可能な PivotTable に変換します。新しい Pivot シートの A3 セルから配置され、ptProfitByRegion という名前が付けられるため、後続のコード(たとえば RefreshTable など)で名前指定して再利用できます。PivotFields("Region").Orientation = xlRowFieldおよび直下の Month の行は、フィールドリストで Region を行、Month を列にドラッグする操作と同等のコードです。AddDataFieldは値エリアを埋める処理です。第2引数("Sum of Profit")は Excel が列見出しとして表示するラベルで、xlSum は合計値を集計する指定です(平均や件数ではなく)。
レポートの更新
一度 PivotTable を作成したら、新しいデータが追加されるたびに再作成するのではなく、リフレッシュ(更新)します。これにより高速化され、ユーザーが手動で調整したレイアウトも保持されます。
ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion").RefreshTable
この1行で、PivotCache が tblReports の最新状態を読み込み、PivotTable 内のすべての数値が更新されます。ただし、レイアウト(列幅、数値書式、フィールド配置など)はそのまま維持され、Pivot 作成後にユーザーが手動で調整した内容も残ります。これは BuildProfitPivot を再度呼び出して再構築する場合との大きな違いです。再構築するとシートが作り直され、手動調整がすべて消えてしまいます。
ピボットグラフの更新
PivotTable 上に作成した PivotChart は、PivotTable をリフレッシュするたびに自動的にデータが更新されます。そのため、レポート用マクロで PivotTable をリフレッシュするだけで、関連付けられたグラフも常に最新状態を保てます。
Dim pt As PivotTable
Set pt = ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion")
pt.RefreshTable
' any PivotChart based on pt updates automatically — no extra code needed
これは次のセクションで扱う通常のグラフと対照的です。通常のグラフは新しいデータを参照させるために SetSourceData の明示的な呼び出しが必要ですが、PivotChart は PivotTable に恒久的にリンクされており、自動的に追従します。ダッシュボードで常に最新の PivotTable 数値を反映したグラフを最小限のコードで実現したい場合、独立したグラフより PivotChart を使う方が一般的に適しています。
課題
BuildProfitPivotをそのまま実行し、「Pivot」シートが新規作成され、行に Region、列に Month が表示されることを確認してください。- 架空の6番目の地域用に
tblReportsに3月の新しい行を手動で追加し、RefreshTable の1行だけを実行してください。Pivot が再構築されることなく更新されることを確認します。 BuildProfitPivotを修正し、Profit の代わりに Sales を集計し、Region と Month を入れ替えて、Month を行、Region を列にしてください。
以下は、tblReports に 6 番目の地域を新しい 3 月の行として追加するコード例です。手入力ではなく、ListRows.Add を使用しています。
Sub AddSixthRegion()
Dim tbl As ListObject
Dim newRow As ListRow
Set tbl = ThisWorkbook.Worksheets("Reports").ListObjects("tblReports")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "March" ' Month
newRow.Range(1, 2).Value = "Southwest" ' Region
newRow.Range(1, 3).Value = 41500 ' Sales
newRow.Range(1, 4).Value = 28200 ' Expenses
newRow.Range(1, 5).Value = 13300 ' Profit
newRow.Range(1, 6).Value = 39000 ' Target
End Sub
このマクロを一度実行した後、前章の RefreshProfitPivot サブプロシージャを実行してください。ピボットテーブルに North、South、East、West、Central に加えて新しい行として "Southwest" が表示されるはずです。ピボット作成用マクロ自体には一切手を加えていません。
1. BuildProfitPivot をそのまま実行する場合
- 本章に記載された
Subをそのままコピーしてモジュールに貼り付け、一度実行します。 - Project Explorer またはシートタブを確認すると、"Pivot" という名前の新しいシートが作成されているはずです。行方向に Region、列方向に Month が並び、Profit が集計されています。
2. 6 番目の地域を追加し、リフレッシュのみ行う場合
- 新しい行をワークシートに直接入力します(コードは使いません)。
tblReportsの一番下に、架空の地域 "Southwest" の 3 月分の行を追加します。 BuildProfitPivotを再実行しないでください。これを実行すると Pivot シート全体が削除・再作成されてしまい、この演習の目的が失われます。- 代わりに、章で紹介した一行だけの
RefreshTableステートメントのみを実行します。既存のピボットテーブル名を参照する必要がありますが、これは章のリフレッシュ例と同じ方法です。
3. フィールドの入れ替えと集計値の変更
With ptブロック内の 3 行を変更します。どのフィールドをxlRowField、どれをxlColumnFieldにするか、AddDataFieldでどのフィールドを集計するかを指定します。- この修正版には異なる
Sub名と異なるTableNameを付けてください。同じ名前を使うとエラーになるか、最初のピボットテーブルが上書きされてしまいます。 AddDataFieldのラベル(第 2 引数、例:"Sum of Profit")は表示用テキストなので、実際に集計する内容に合わせて変更してください。
ポイント 2 — 6 番目の地域の行を手動で追加した後、次のコードのみを実行します。
Sub RefreshProfitPivot()
ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion").RefreshTable
End Sub
ポイント 3 — 別バージョンの修正版:
Sub BuildSalesPivotByMonth()
Dim wsData As Worksheet, wsPivot As Worksheet
Dim tbl As ListObject
Dim pc As PivotCache
Dim pt As PivotTable
Set wsData = ThisWorkbook.Worksheets("Reports")
Set tbl = wsData.ListObjects("tblReports")
On Error Resume Next
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("SalesPivot").Delete
Application.DisplayAlerts = True
On Error GoTo 0
Set wsPivot = ThisWorkbook.Worksheets.Add
wsPivot.Name = "SalesPivot"
Set pc = ThisWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, SourceData:=tbl.Range)
Set pt = pc.CreatePivotTable( _
TableDestination:=wsPivot.Range("A3"), _
TableName:="ptSalesByMonth")
With pt
.PivotFields("Month").Orientation = xlRowField
.PivotFields("Region").Orientation = xlColumnField
.AddDataField .PivotFields("Sales"), "Sum of Sales", xlSum
End With
End Sub
BuildSalesPivotByMonth を実行すると、新しい "SalesPivot" シートが作成され、行方向に Month、列方向に Region、集計値として Sales の合計が表示されます。これは元のレイアウトの鏡像となります。
フィードバックありがとうございます!
AIに質問する
AIに質問する
何でも質問するか、提案された質問の1つを試してチャットを始めてください
VBAによるピボットテーブルの作成
ピボットテーブルは、フィールドを行、列、値にドラッグしてテーブルを要約する機能であり、これらのドラッグ&ドロップ操作にはすべて直接対応するVBAコードが存在します。つまり、新しいデータが到着するたびに、マクロによってピボットテーブルレポート全体をゼロから再構築することが可能です。
ピボットテーブルの作成
Sub BuildProfitPivot()
Dim wsData As Worksheet, wsPivot As Worksheet
Dim tbl As ListObject
Dim pc As PivotCache
Dim pt As PivotTable
Set wsData = ThisWorkbook.Worksheets("Reports")
Set tbl = wsData.ListObjects("tblReports")
' start clean: remove an existing Pivot sheet if this has run before
On Error Resume Next
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("Pivot").Delete
Application.DisplayAlerts = True
On Error GoTo 0
Set wsPivot = ThisWorkbook.Worksheets.Add
wsPivot.Name = "Pivot"
Set pc = ThisWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, SourceData:=tbl.Range)
Set pt = pc.CreatePivotTable( _
TableDestination:=wsPivot.Range("A3"), _
TableName:="ptProfitByRegion")
With pt
.PivotFields("Region").Orientation = xlRowField
.PivotFields("Month").Orientation = xlColumnField
.AddDataField .PivotFields("Profit"), "Sum of Profit", xlSum
End With
End Sub
DisplayAlertsと.Deleteの切り替え、DisplayAlerts = Falseの組み合わせは、「存在すれば削除」パターンの安全な実装方法:存在しないシートを削除しようとすると通常はエラーが発生しマクロが停止しますが、On Error Resume Next によりその特定のエラーを無視して処理を継続します。Error GoTo 0は、Excel の「このシートを本当に削除しますか?」という確認ポップアップを非表示にします。- 直後の
On Error Resume Nextで通常のエラー報告に戻します。On Error Resume Next をSubの残り全体で有効にしたままだと、後続の無関係なエラーもすべて黙って無視されてしまうため、これは避けるべき落とし穴です。 ThisWorkbook.PivotCaches.Createはテーブルデータのスナップショット(PivotCache)を作成します。これは PivotTable そのものではなく、すべての PivotTable が内部的に基づくオブジェクトです。pc.CreatePivotTableは、そのスナップショットを実際に表示可能な PivotTable に変換します。新しい Pivot シートの A3 セルから配置され、ptProfitByRegion という名前が付けられるため、後続のコード(たとえば RefreshTable など)で名前指定して再利用できます。PivotFields("Region").Orientation = xlRowFieldおよび直下の Month の行は、フィールドリストで Region を行、Month を列にドラッグする操作と同等のコードです。AddDataFieldは値エリアを埋める処理です。第2引数("Sum of Profit")は Excel が列見出しとして表示するラベルで、xlSum は合計値を集計する指定です(平均や件数ではなく)。
レポートの更新
一度 PivotTable を作成したら、新しいデータが追加されるたびに再作成するのではなく、リフレッシュ(更新)します。これにより高速化され、ユーザーが手動で調整したレイアウトも保持されます。
ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion").RefreshTable
この1行で、PivotCache が tblReports の最新状態を読み込み、PivotTable 内のすべての数値が更新されます。ただし、レイアウト(列幅、数値書式、フィールド配置など)はそのまま維持され、Pivot 作成後にユーザーが手動で調整した内容も残ります。これは BuildProfitPivot を再度呼び出して再構築する場合との大きな違いです。再構築するとシートが作り直され、手動調整がすべて消えてしまいます。
ピボットグラフの更新
PivotTable 上に作成した PivotChart は、PivotTable をリフレッシュするたびに自動的にデータが更新されます。そのため、レポート用マクロで PivotTable をリフレッシュするだけで、関連付けられたグラフも常に最新状態を保てます。
Dim pt As PivotTable
Set pt = ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion")
pt.RefreshTable
' any PivotChart based on pt updates automatically — no extra code needed
これは次のセクションで扱う通常のグラフと対照的です。通常のグラフは新しいデータを参照させるために SetSourceData の明示的な呼び出しが必要ですが、PivotChart は PivotTable に恒久的にリンクされており、自動的に追従します。ダッシュボードで常に最新の PivotTable 数値を反映したグラフを最小限のコードで実現したい場合、独立したグラフより PivotChart を使う方が一般的に適しています。
課題
BuildProfitPivotをそのまま実行し、「Pivot」シートが新規作成され、行に Region、列に Month が表示されることを確認してください。- 架空の6番目の地域用に
tblReportsに3月の新しい行を手動で追加し、RefreshTable の1行だけを実行してください。Pivot が再構築されることなく更新されることを確認します。 BuildProfitPivotを修正し、Profit の代わりに Sales を集計し、Region と Month を入れ替えて、Month を行、Region を列にしてください。
以下は、tblReports に 6 番目の地域を新しい 3 月の行として追加するコード例です。手入力ではなく、ListRows.Add を使用しています。
Sub AddSixthRegion()
Dim tbl As ListObject
Dim newRow As ListRow
Set tbl = ThisWorkbook.Worksheets("Reports").ListObjects("tblReports")
Set newRow = tbl.ListRows.Add
newRow.Range(1, 1).Value = "March" ' Month
newRow.Range(1, 2).Value = "Southwest" ' Region
newRow.Range(1, 3).Value = 41500 ' Sales
newRow.Range(1, 4).Value = 28200 ' Expenses
newRow.Range(1, 5).Value = 13300 ' Profit
newRow.Range(1, 6).Value = 39000 ' Target
End Sub
このマクロを一度実行した後、前章の RefreshProfitPivot サブプロシージャを実行してください。ピボットテーブルに North、South、East、West、Central に加えて新しい行として "Southwest" が表示されるはずです。ピボット作成用マクロ自体には一切手を加えていません。
1. BuildProfitPivot をそのまま実行する場合
- 本章に記載された
Subをそのままコピーしてモジュールに貼り付け、一度実行します。 - Project Explorer またはシートタブを確認すると、"Pivot" という名前の新しいシートが作成されているはずです。行方向に Region、列方向に Month が並び、Profit が集計されています。
2. 6 番目の地域を追加し、リフレッシュのみ行う場合
- 新しい行をワークシートに直接入力します(コードは使いません)。
tblReportsの一番下に、架空の地域 "Southwest" の 3 月分の行を追加します。 BuildProfitPivotを再実行しないでください。これを実行すると Pivot シート全体が削除・再作成されてしまい、この演習の目的が失われます。- 代わりに、章で紹介した一行だけの
RefreshTableステートメントのみを実行します。既存のピボットテーブル名を参照する必要がありますが、これは章のリフレッシュ例と同じ方法です。
3. フィールドの入れ替えと集計値の変更
With ptブロック内の 3 行を変更します。どのフィールドをxlRowField、どれをxlColumnFieldにするか、AddDataFieldでどのフィールドを集計するかを指定します。- この修正版には異なる
Sub名と異なるTableNameを付けてください。同じ名前を使うとエラーになるか、最初のピボットテーブルが上書きされてしまいます。 AddDataFieldのラベル(第 2 引数、例:"Sum of Profit")は表示用テキストなので、実際に集計する内容に合わせて変更してください。
ポイント 2 — 6 番目の地域の行を手動で追加した後、次のコードのみを実行します。
Sub RefreshProfitPivot()
ThisWorkbook.Worksheets("Pivot").PivotTables("ptProfitByRegion").RefreshTable
End Sub
ポイント 3 — 別バージョンの修正版:
Sub BuildSalesPivotByMonth()
Dim wsData As Worksheet, wsPivot As Worksheet
Dim tbl As ListObject
Dim pc As PivotCache
Dim pt As PivotTable
Set wsData = ThisWorkbook.Worksheets("Reports")
Set tbl = wsData.ListObjects("tblReports")
On Error Resume Next
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("SalesPivot").Delete
Application.DisplayAlerts = True
On Error GoTo 0
Set wsPivot = ThisWorkbook.Worksheets.Add
wsPivot.Name = "SalesPivot"
Set pc = ThisWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, SourceData:=tbl.Range)
Set pt = pc.CreatePivotTable( _
TableDestination:=wsPivot.Range("A3"), _
TableName:="ptSalesByMonth")
With pt
.PivotFields("Month").Orientation = xlRowField
.PivotFields("Region").Orientation = xlColumnField
.AddDataField .PivotFields("Sales"), "Sum of Sales", xlSum
End With
End Sub
BuildSalesPivotByMonth を実行すると、新しい "SalesPivot" シートが作成され、行方向に Month、列方向に Region、集計値として Sales の合計が表示されます。これは元のレイアウトの鏡像となります。
フィードバックありがとうございます!