当另一个单元格的值发生变化时,单元格中的自动日期更新(由公式计算)

时间:2012-02-16 13:19:07

标签: excel vba date formula

我在C2中有一个公式,比如=A2+B2。每当C2改变值(实际值,而不是公式)时,我希望在D2中更新当前日期和时间。

我尝试了很多VBA代码和技巧,如果在C2中输入公式,它们都不起作用。但是如果我在C2中手动输入值,则会根据需要更新日期和时间。这当然是因为输入/更改了实际值 - 公式保持不变,可以这么说。

问题: 当C2中的公式结果发生变化时,是否可以创建更新D2的VBA代码(或其他内容)?

如果可能,我需要将其激活为单元格C2:C30(+ D2:D30表示日期+时间)

使用Excel 2010。

4 个答案:

答案 0 :(得分:10)

您可以通过用户定义函数(VBA宏函数)填充dependend单元格(D2),该函数将C2-Cell的值作为输入参数,将当前日期作为输出返回。

在D2中将C2作为UDF的输入参数告诉Excel每次C2更改时都需要重新评估D2(即如果为工作簿打开公式的自动计算)。

修改

以下是一些代码:

对于UDF:

    Public Function UDF_Date(ByVal data) As Date

        UDF_Date = Now()

    End Function

作为D2中的公式:

=UDF_Date(C2)

您必须为D2-Cell提供日期时间格式,否则它将显示日期值的数字表示。

如果将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
    

答案 1 :(得分:4)

以范围为条件插入日期。

这样做的好处是不更改日期,除非更改单元格的内容,并且它在C2:C2范围内,即使关闭并保存工作表,除非相邻单元格发生更改,否则不会重新计算

改编自this tip和@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

答案 2 :(得分:0)

Private Sub Worksheet_Change(ByVal Target As Range)

    If Target.Address = "$C$2" Then

        ActiveSheet.Range("D2").Value = Now()

    End If

End Sub

答案 3 :(得分:0)

最简单的方法是添加=IF(B3="","Not Allocated",Now())并将列的格式更改为所需的日期和时间格式。但是,如果编辑了B列,则需要更新的相应列的日期和时间将自动更新所有列,因为不检查旧值。但如果能够获得当前时间,这很容易使用。