セルが変更されたら自動的に履歴を記録する方法
Excelでは、通常はセルの値を変更すると元の値が失われてしまいます。しかし、VBAを使用することで、セルの変更前・変更後の値を「いつ・誰が・どのセルを」変更したのか自動で別シートに記録・保存することが可能です。売上データや共有タスク表の変更追跡、トラブル発生時の監査ログとして非常に役立ちます。
VBAの設定手順
- 履歴を記録したいExcelシートを開いた状態で、キーボードの Alt + F11 を押し、VBAエディターを開きます。
- 画面左側の「Microsoft Excel Objects」内にある、対象のシート名(例:
Sheet1)をダブルクリックしてコードウィンドウを開きます。 - 右側の白い画面に、以下のVBAコードをそのまま貼り付けます。
- エディターを閉じ、Excelシート側でセルを変更すると、「変更履歴」シートが自動生成され、履歴が1行ずつ蓄積されます。
セルの変更履歴を自動で記録するVBAコード
※このマクロは、対象のシートモジュール(Sheet1など)に直接貼り付けてください。標準モジュールでは動作しません。
Dim OldValues As Object ' 変更前の値を一時保持する辞書オブジェクト
' 1. セルを選択したとき、変更前の値を辞書に記憶するイベント
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cell As Range
' 辞書が未作成の場合のみ生成
If OldValues Is Nothing Then
Set OldValues = CreateObject("Scripting.Dictionary")
End If
' 選択されたセルのアドレスと値をペアで記憶
For Each cell In Target
If Not IsEmpty(cell.Value) Then
OldValues(cell.Address) = cell.Value
Else
OldValues(cell.Address) = "(空白)"
End If
Next cell
End Sub
' 2. セルの値が書き換わったとき、変更履歴シートにログを書き出すイベント
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
Dim lastRow As Long
Dim cell As Range
Dim oldValue As String
' 変更履歴シートの有無を確認し、なければ新規作成
On Error Resume Next
Set ws = ThisWorkbook.Sheets("変更履歴")
On Error GoTo 0
If ws Is Nothing Then
Set ws = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = "変更履歴"
' 見出しを設定
ws.Range("A1:F1").Value = Array("No.", "変更日時", "変更者", "セルアドレス", "変更前の値", "変更後の値")
End If
' 【超重要】履歴書き込みによる不要なイベント連鎖(無限ループ)を防ぐ
Application.EnableEvents = False
On Error GoTo ErrorHandler
' 変更されたセルを1つずつループ処理(複数セルの同時変更・コピペにも対応)
For Each cell In Target
' 変更前の値を取得(辞書になければ空白だったとみなす)
If Not OldValues Is Nothing Then
If OldValues.Exists(cell.Address) Then
oldValue = OldValues(cell.Address)
Else
oldValue = "(空白)"
End If
Else
oldValue = "(不明)"
End If
' 履歴シートの最終行の下にデータを書き出す
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1
ws.Cells(lastRow, 1).Value = lastRow - 1
ws.Cells(lastRow, 2).Value = Now
ws.Cells(lastRow, 3).Value = Application.UserName
ws.Cells(lastRow, 4).Value = cell.Parent.Name & "!" & cell.Address(False, False)
ws.Cells(lastRow, 5).Value = oldValue
ws.Cells(lastRow, 6).Value = cell.Value
Next cell
ErrorHandler:
' 【超重要】イベント機能を必ず有効に戻す
Application.EnableEvents = True
End Sub
コードの重要ポイント解説
- Application.EnableEvents = False / True:この記述が最も重要です。VBA自身が「変更履歴」シートに値を書き込む行為も「セルの変更」にあたるため、これがないと再び自分自身のプログラムが呼び出され、Excelがハングアップ(強制終了)する無限ループに陥ります。それを防ぐために一時的にイベントを停止させています。
- Worksheet_SelectionChange:ユーザーがセルをクリック(選択)した瞬間の値を内部の「辞書(Dictionary)」にストックしておき、その後に値が書き換わった際に「変更前」のデータとして取り出せるようにしています。
- cell.Parent.Name & "!" & cell.Address:複数シートで運用する場合に備え、どのシートのどのセルが変更されたのかがひと目で分かる形式(例: Sheet1!A1)で記録します。
動作・出力イメージ
セルが書き換えられると、「変更履歴」シートに以下のように時系列でデータが追加されていきます。
| No. | 変更日時 | 変更者 | セルアドレス | 変更前の値 | 変更後の値 |
|---|---|---|---|---|---|
| 1 | 2026/06/24 12:00:15 | 山田 太郎 | Sheet1!A1 | 150,000 | 180,000 |
| 2 | 2026/06/24 12:05:42 | 鈴木 一郎 | Sheet1!B5 | (空白) | 対応中 |
まとめと運用の注意点
- VBAのイベント機能を活用すれば、事前のシート準備なしで、セルの「変更前」と「変更後」のログを全自動で取得できます。
- ブックの保存形式に注意: この機能を維持するため、Excelファイルを保存する際は必ず「Excel マクロ有効ブック(.xlsm)」の形式を選択して保存してください。通常の .xlsx で保存するとマクロコードが消去されてしまいます。