Excel 용 타임 스탬프 수식 만들기


1

아이디어는 간단합니다, 나는 뭔가를 할 수있는 기능을 원합니다. =MOD_DATE_OF(A1:A4) 그러한 범위에있는 셀이 수정되면 해당 수식을 할당 한 셀에 현재 날짜가 표시됩니다.

나는 웹과 심지어 비슷한 질문을 발견했다. 이리 , 그러나 그들 중 누구도 .

내가 가진 가장 가까운 곳은 어딘가에이 코드였습니다 (미안하지만 소스 코드를 잃어 버렸습니다) :

Private Sub Worksheet_Change(ByVal Target As Excel.Range)
    If Target.Column = 1 Then
        Target.Offset(0, 1).Value = Date
    End If
End Sub

하지만 아직 함수가 아닙니다 ..

Office 2010의 Excel을 사용하고 있습니다.

감사

답변:


4

다음은 다양한 범위의 변경 날짜를 모니터링 할 수있는 본격적인 솔루션입니다. 이 함수는 VBA에서 배열을 사용하기위한 칩 피어슨 도구 에서 기능을 스택 오버플로 사용자 Thomas에 의해 답변.

기본 개념은 모니터링 된 모든 범위 (과거 또는 현재)의 주소가 가장 최근의 업데이트 날짜와 함께 저장되는 전역 배열이 함수와 Worksheet_Change Sub가 상호 작용할 수있게한다는 것입니다. Worksheet_Change Sub 모든 저장된 범위에 대해 변경된 범위를 검사하여이 배열을 업데이트합니다. 이 함수는 배열에서 모니터 된 범위를 찾고 저장된 변경 날짜를 반환합니다. 그렇지 않으면 오늘 날짜가 반환되고 배열에 추가됩니다.

또한 통합 문서를 닫고 타임 스탬프 배열을 할당 해제 할 때 타임 스탬프가 손실되지 않도록하려면 배열을 Workbook_Close 이벤트의 시트에 기록한 다음 Workbook_Open 이벤트의 배열에 다시 작성해야합니다.

모듈에서 다음 코드를 붙여 넣습니다.

Public funcInstances() As Variant

Public Function MOD_DATE_OF(monitor As Range)
Application.Volatile True
Dim i As Long
Dim tmpArray() As Variant

If Not IsDimensioned(funcInstances) Then
    ReDim funcInstances(1 To 1, 1 To 2) As Variant
    funcInstances(1, 1) = monitor.Address
    funcInstances(1, 2) = Date
Else
    For i = 1 To UBound(funcInstances, 1)
        If funcInstances(i, 1) = monitor.Address Then
            MOD_DATE_OF = Format(funcInstances(i, 2), "yyyy-mm-dd")
            Exit Function
        End If
    Next i
    tmpArray = ExpandArray(funcInstances, 1, 1, "")
    Erase funcInstances
    funcInstances = tmpArray
    funcInstances(UBound(funcInstances, 1), 1) = monitor.Address
    funcInstances(UBound(funcInstances, 1), 2) = Date
End If
MOD_DATE_OF = Format(funcInstances(UBound(funcInstances, 1), 2), "yyyy-mm-dd")
End Function

'ExpandArray() is the work of Chip Pearson.  Code copied from http://www.cpearson.com/excel/vbaarrays.htm
Function ExpandArray(Arr As Variant, WhichDim As Long, AdditionalElements As Long, _
        FillValue As Variant) As Variant
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ExpandArray
' This expands a two-dimensional array in either dimension. It returns the result
' array if successful, or NULL if an error occurred. The original array is never
' changed.
' Parameters:
' --------------------
' Arr                   is the array to be expanded.
'
' WhichDim              is either 1 for additional rows or 2 for
'                       additional columns.
'
' AdditionalElements    is the number of additional rows or columns
'                       to create.
'
' FillValue             is the value to which the new array elements should be
'                       initialized.
'
' You can nest calls to Expand array to expand both the number of rows and
' columns. E.g.,
'
' C = ExpandArray(ExpandArray(Arr:=A, WhichDim:=1, AdditionalElements:=3, FillValue:="R"), _
'    WhichDim:=2, AdditionalElements:=4, FillValue:="C")
' This first adds three rows at the bottom of the array, and then adds four
' columns on the right of the array.
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim Result As Variant
Dim RowNdx As Long
Dim ColNdx As Long
Dim ResultRowNdx As Long
Dim ResultColNdx As Long
Dim NumRows As Long
Dim NumCols As Long
Dim NewUBound As Long

Const ROWS_ As Long = 1
Const COLS_ As Long = 2


''''''''''''''''''''''''''''
' Ensure Arr is an array.
''''''''''''''''''''''''''''
If IsArray(Arr) = False Then
    ExpandArray = Null
    Exit Function
End If

'''''''''''''''''''''''''''''''''
' Ensure the dimension is 1 or 2.
'''''''''''''''''''''''''''''''''
Select Case WhichDim
    Case 1, 2
    Case Else
        ExpandArray = Null
        Exit Function
End Select

''''''''''''''''''''''''''''''''''''
' Ensure AdditionalElements is > 0.
' If AdditionalElements  < 0, return NULL.
' If AdditionalElements  = 0, return Arr.
''''''''''''''''''''''''''''''''''''
If AdditionalElements < 0 Then
    ExpandArray = Null
    Exit Function
End If
If AdditionalElements = 0 Then
    ExpandArray = Arr
    Exit Function
End If

NumRows = UBound(Arr, 1) - LBound(Arr, 1) + 1
NumCols = UBound(Arr, 2) - LBound(Arr, 2) + 1

If WhichDim = ROWS_ Then
    '''''''''''''''
    ' Redim Result.
    '''''''''''''''
    ReDim Result(LBound(Arr, 1) To UBound(Arr, 1) + AdditionalElements, LBound(Arr, 2) To UBound(Arr, 2))
    ''''''''''''''''''''''''''''''
    ' Transfer Arr array to Result
    ''''''''''''''''''''''''''''''
    For RowNdx = LBound(Arr, 1) To UBound(Arr, 1)
        For ColNdx = LBound(Arr, 2) To UBound(Arr, 2)
            Result(RowNdx, ColNdx) = Arr(RowNdx, ColNdx)
        Next ColNdx
    Next RowNdx
    '''''''''''''''''''''''''''''''
    ' Fill the rest of the result
    ' array with FillValue.
    '''''''''''''''''''''''''''''''
    For RowNdx = UBound(Arr, 1) + 1 To UBound(Result, 1)
        For ColNdx = LBound(Arr, 2) To UBound(Arr, 2)
            Result(RowNdx, ColNdx) = FillValue
        Next ColNdx
    Next RowNdx
Else
    '''''''''''''''
    ' Redim Result.
    '''''''''''''''
    ReDim Result(LBound(Arr, 1) To UBound(Arr, 1), UBound(Arr, 2) + AdditionalElements)
    ''''''''''''''''''''''''''''''
    ' Transfer Arr array to Result
    ''''''''''''''''''''''''''''''
    For RowNdx = LBound(Arr, 1) To UBound(Arr, 1)
        For ColNdx = LBound(Arr, 2) To UBound(Arr, 2)
            Result(RowNdx, ColNdx) = Arr(RowNdx, ColNdx)
        Next ColNdx
    Next RowNdx
    '''''''''''''''''''''''''''''''
    ' Fill the rest of the result
    ' array with FillValue.
    '''''''''''''''''''''''''''''''
    For RowNdx = LBound(Arr, 1) To UBound(Arr, 1)
        For ColNdx = UBound(Arr, 2) + 1 To UBound(Result, 2)
            Result(RowNdx, ColNdx) = FillValue
        Next ColNdx
    Next RowNdx

End If
''''''''''''''''''''
' Return the result.
''''''''''''''''''''
ExpandArray = Result

End Function

'IsDimensioned() is the work of StackOverflow user @Thomas.  Code copied from https://stackoverflow.com/a/5480690/657668
Public Function IsDimensioned(vValue As Variant) As Boolean
    On Error Resume Next
    If Not IsArray(vValue) Then Exit Function
    Dim i As Integer
    i = UBound(vValue)
    IsDimensioned = Err.Number = 0
End Function

적절한 워크 시트 모듈에서 다음 코드를 붙여 넣습니다.

Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim j As Long
If IsDimensioned(funcInstances) Then
    For j = 1 To UBound(funcInstances, 1)
        If Not Intersect(Target, Range(funcInstances(j, 1))) Is Nothing Then
            funcInstances(j, 2) = Date
        End If
    Next j
    Me.Calculate
End If
Application.EnableEvents = True
End Sub

마지막으로 ThisWorkbook 모듈에서 다음 코드를 붙여 넣습니다.

Private Sub Workbook_BeforeClose(Cancel As Boolean)
If IsDimensioned(funcInstances) Then
    Application.ScreenUpdating = False
    'Store array on a new temporary and hidden worksheet.
    Dim tmpS As Worksheet, tmpR As Range
    Set tmpS = Worksheets.Add
    tmpS.Name = "TEMP Record of Timestamps"
    tmpS.Visible = xlSheetHidden
    Set tmpR = tmpS.Range("A1:B1").Resize(UBound(funcInstances, 1), 2)
    tmpR.Value = funcInstances
    ThisWorkbook.Save
    Application.ScreenUpdating = True
End If
End Sub

Private Sub Workbook_Open()
Dim ws As Worksheet, tstamps As Range
Dim wsfound As Boolean
wsfound = False
Application.ScreenUpdating = False
For Each ws In ThisWorkbook.Worksheets
    If ws.Name = "TEMP Record of Timestamps" Then
        wsfound = True
        Exit For
    End If
Next ws
If wsfound Then
    Set tstamps = ws.UsedRange
    funcInstances = tstamps.Value
    Application.DisplayAlerts = False
    ws.Delete
    Application.DisplayAlerts = True
End If
Application.ScreenUpdating = True
End Sub

이 페이지를 가로 지르는 사람을위한 참고 사항 : 많은 의견은 이전의 불완전한 해결책에 관한 것이므로 혼동하지 마십시오.


1
이 작동합니다. 시간을 기록해야하는 경우, Now를 사용할 때 Long이 문제가되므로 modDate를 Variant로 설정하면 시간을 표시 할 수 있습니다.
datatoo

그것은 당신이 말한 것처럼 하나의 인스턴스에 대해 작동합니다. 기능으로 생각한 것이 정확히 같았 기 때문에 여러 지점을 따로 모니터링 할 수있었습니다. 그 기능을 추가 할 수있는 기회가 있습니까? :) 감사.
flpgdt

@ flpgdt 하, 물론 당신이 원하는거야! 테스트 할 생각이 있지만 잠시 시간이 걸릴 수 있습니다. 나에게 너무 많은 시간을 소비한다면 잠시 후에 기본 아이디어를 게시 할 수 있습니다.
Excellll

@Excellll 감사합니다. 시간이 들었을 때 나 스스로 해결할 것이지만 만족할만한 해결책을 얻는 데 오랜 시간이 걸릴 것입니다.
flpgdt

@flpgdt 전체 솔루션을 추가했습니다. 그것은 약간의 작업을했지만, 그것이 완벽하다고 생각합니다. 그것이 당신을 위해 작동하는지 알려주세요.
Excellll
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.