Excel VBAでセル入力時だけタイムスタンプを記録する方法|SelectionChangeではなくChangeイベントを使う

Visual Basic

Excel VBAで作業ログを残したい場合、セルを選択しただけで記録されてしまうケースがあります。これはイベントの種類が目的と合っていないことが原因です。セルの入力や変更を検知して、日時・ユーザー名・パソコン名・セル位置・入力内容などを記録したい場合は、SelectionChangeイベントではなくWorksheet_Changeイベントを使用します。この記事では、セル入力時だけログを保存するVBAの考え方と修正方法を解説します。

セルを選択しただけでログが残る原因

セル選択時にログが記録される原因は、使用しているイベントがWorksheet_SelectionChangeになっているためです。

Worksheet_SelectionChangeイベントは、その名前の通り「セルの選択位置が変更された瞬間」に実行されるイベントです。そのため、B2からC2へ移動しただけでもマクロが動作し、セルの内容を入力していなくてもログが保存されます。

今回のように「文字を入力したタイミングで記録したい」という目的の場合、選択ではなくセルの内容が変更されたことを検知する必要があります。

セル入力を検知するにはWorksheet_Changeイベントを使う

セルの値が変更された時に実行されるイベントがWorksheet_Changeです。入力後にEnterキーを押して確定したタイミングなどで、このイベントが発生します。

例えば、B2:U100の範囲に文字が入力された場合だけログを残したい場合は、以下のように変更します。

Worksheet_SelectionChangeをWorksheet_Changeへ変更するだけでも、動作は大きく改善されます。

セル入力時だけログを保存するVBAサンプル

以下のコードでは、B2:U100の範囲が変更された場合に、日時・ユーザー名・コンピュータ名・セル番号・入力内容をLogging_Dataシートへ記録します。

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim wsLog As Worksheet
    Dim nextRow As Long

    If Intersect(Target, Range("B2:U100")) Is Nothing Then
        Exit Sub
    End If

    Application.EnableEvents = False

    Set wsLog = Worksheets("Logging_Data")

    nextRow = wsLog.Cells(wsLog.Rows.Count, "A").End(xlUp).Row + 1

    wsLog.Cells(nextRow, 1).Value = Now
    wsLog.Cells(nextRow, 2).Value = Environ("UserName")
    wsLog.Cells(nextRow, 3).Value = Environ("COMPUTERNAME")
    wsLog.Cells(nextRow, 4).Value = Target.Address(RowAbsolute:=False, ColumnAbsolute:=False)
    wsLog.Cells(nextRow, 5).Value = Target.Value

    Application.EnableEvents = True

End Sub

このコードを対象となるワークシートのコード画面に貼り付けることで、そのシート内での入力変更だけを監視できます。

Application.EnableEventsを使う理由と注意点

コード内にあるApplication.EnableEvents = Falseは、イベントの連続実行を防ぐために使用しています。

例えば、ログを書き込む処理によって別のセルが変更された場合、Worksheet_Changeが再度実行される可能性があります。それを防ぐため、一時的にイベントを停止しています。

ただし、途中でエラーが発生するとイベントがFalseのまま残り、以降マクロが動かなくなる場合があります。そのため、実際の運用ではエラー処理を追加するとより安全です。

複数セルへの貼り付け時に注意するポイント

Worksheet_Changeでは、1つのセル入力だけではなく、複数セルへのコピーや貼り付けでもイベントが発生します。

例えば、B2:B10へ一括貼り付けした場合、Targetには複数セルが含まれます。その場合、Target.Addressでは範囲全体が記録され、Target.Valueでは配列として扱われることがあります。

1セルずつ確実にログを残したい場合は、For Eachを使って変更されたセルを順番に処理する方法が適しています。

入力内容だけでなく変更前の値も記録したい場合

Worksheet_Changeイベントで取得できるのは、基本的に変更後の値です。変更前の値まで記録したい場合は、別途Worksheet_SelectionChangeやWorksheet_BeforeDoubleClickなどを組み合わせて、変更前データを保持する仕組みが必要になります。

例えば、誰がいつどのデータを修正したかを管理する業務システムのようなログを作る場合は、単純な入力記録よりも少し高度な設計が必要になります。

一方で、「いつ誰がどのセルへ何を入力したか」を確認する程度であれば、Worksheet_Changeだけでも十分対応できます。

まとめ|セル入力ログはSelectionChangeではなくChangeイベントで作成する

セルを選択しただけでログが残る問題は、Worksheet_SelectionChangeを使用していることが原因です。このイベントはセル移動を検知するため、入力の有無に関係なく実行されます。

セルへ文字を入力した時だけログを残したい場合は、Worksheet_Changeイベントを利用します。日時、ユーザー名、コンピュータ名、セル番号、入力内容などを記録する仕組みも簡単に作成できます。

Excelで作業履歴を管理する場合は、目的に合ったイベントを選ぶことが重要です。入力操作を記録したい場合はChangeイベント、選択操作を取得したい場合はSelectionChangeイベントというように使い分けることで、希望する動作を実現できます。

コメント

タイトルとURLをコピーしました