C2に数式があります。たとえば、=A2+B2
です。 C2が値(式ではなく実際の値)を変更するたびに、D2で現在の日付と時刻を更新します。
私はたくさんのVBAコードとトリックを試しましたが、C2に数式が入力された場合、どれも機能しません。しかし、C2に手動で値を入力すると、日時は必要に応じて更新されます。もちろん、これは実際の値が入力/変更されるためです。つまり、公式は同じままです。
質問: C2の数式の結果が変化したときにD2を更新するVBAコード(または何か他のもの)を作成することは可能ですか?
可能であれば、これをセルC2:C30でアクティブにする必要があります(日付+時間の場合は+ D2:D30)
Excel 2010を使用します。
C2セルの値を入力パラメーターとして受け取り、現在の日付を出力として返すユーザー定義関数(VBAマクロ関数)によって、依存セル(D2)を埋めることができます。
D2のUDFの入力パラメーターとしてC2を使用すると、C2が変更されるたびに(つまり、ブックで数式の自動計算がオンになっている場合)、D2を再評価する必要があることがExcelに通知されます。
編集:
ここにいくつかのコードがあります:
UDFの場合:
Public Function UDF_Date(ByVal data) As Date
UDF_Date = Now()
End Function
D2の式として:
=UDF_Date(C2)
D2セルに日時形式を指定する必要があります。そうしないと、日付値の数値表現が表示されます。
また、C2の参照をD2の式と相対的に保つ場合は、式をドラッグすることで目的の範囲に拡張できます。
注: Excelがブックを再計算するたびにD2の日付が現在の値にリセットされるため、これはまだ理想的な解決策ではない可能性があります。 D2にC2が最後に変更されたときのみを反映させるには、C2の過去の値を追跡する必要があります。これは、たとえば、入力パラメーターの値の横のアドレスも提供し、非表示のシートに入力パラメーターを格納し、UDFが呼び出されるたびに以前の値と比較することにより、UDFに実装できます。
補遺:
次に、セル値の変更を追跡し、最後の変更が検出された日時を返すUDFの実装例を示します。使用する場合は、次のことに注意してください。
UDFの使用方法は、上記と同じです。
UDFは、単一セルの入力範囲に対してのみ機能します。
セルの値は、セルの最後の値と、ブックのドキュメントプロパティで変更が検出された日時を格納することによって追跡されます。数式が大きなデータセットで使用される場合、ファイルのサイズは大幅に増加する可能性があります。数式によって追跡されるすべてのセルについて、ストレージ要件が増加します(セルの最後の値+最終変更日)。また、Excelは、非常に大量のドキュメントプロパティとコードを処理すると、特定の時点でブレーキがかかる場合があります。
ワークシートの名前が変更されると、そこに含まれるセルのすべての追跡情報が失われます。
コードは、文字列への変換が非決定的であるセル値を停止する可能性があります。
以下のコードはテストされていませんであり、概念実証としてのみ見なされます。 自己責任で使用してください。
Public Function UDF_Date(ByVal inData As Range) As Date
Dim wb As Workbook
Dim dProps As DocumentProperties
Dim pValue As DocumentProperty
Dim pDate As DocumentProperty
Dim sName As String
Dim sNameDate As String
Dim bDate As Boolean
Dim bValue As Boolean
Dim bChanged As Boolean
bDate = True
bValue = True
bChanged = False
Dim sVal As String
Dim dDate As Date
sName = inData.Address & "_" & inData.Worksheet.Name
sNameDate = sName & "_dat"
sVal = CStr(inData.Value)
dDate = Now()
Set wb = inData.Worksheet.Parent
Set dProps = wb.CustomDocumentProperties
On Error Resume Next
Set pValue = dProps.Item(sName)
If Err.Number <> 0 Then
bValue = False
Err.Clear
End If
On Error GoTo 0
If Not bValue Then
bChanged = True
Set pValue = dProps.Add(sName, False, msoPropertyTypeString, sVal)
Else
bChanged = pValue.Value <> sVal
If bChanged Then
pValue.Value = sVal
End If
End If
On Error Resume Next
Set pDate = dProps.Item(sNameDate)
If Err.Number <> 0 Then
bDate = False
Err.Clear
End If
On Error GoTo 0
If Not bDate Then
Set pDate = dProps.Add(sNameDate, False, msoPropertyTypeDate, dDate)
End If
If bChanged Then
pDate.Value = dDate
Else
dDate = pDate.Value
End If
UDF_Date = dDate
End Function
範囲を条件として日付の挿入を行います。
これには、セルの内容が変更されない限り日付が変更されないという利点があります。また、C2:C2の範囲内であれば、シートを閉じて保存しても、隣接するセルが変更されない限り再計算されません。
このヒント と@Paul Sからの回答
Private Sub Worksheet_Change(ByVal Target As Range)
Dim R1 As Range
Dim R2 As Range
Dim InRange As Boolean
Set R1 = Range(Target.Address)
Set R2 = Range("C2:C20")
Set InterSectRange = Application.Intersect(R1, R2)
InRange = Not InterSectRange Is Nothing
Set InterSectRange = Nothing
If InRange = True Then
R1.Offset(0, 1).Value = Now()
End If
Set R1 = Nothing
Set R2 = Nothing
End Sub
最も簡単な方法は、=IF(B3="","Not Allocated",Now())
を追加して、列の形式を必要な日付と時刻の形式に変更することです。ただし、ここでB列を編集すると、古い値をチェックしないため、更新が必要な各列の日付と時刻がすべての列に対して自動的に更新されます。しかし、現在の時刻を取得するのに問題がなければ、これは簡単に使用できます。
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$C$2" Then
ActiveSheet.Range("D2").Value = Now()
End If
End Sub