记录宏所做更改

时间:2016-03-26 21:44:08

标签: arrays excel vba excel-vba

某些背景:

我有一个Excel加载项,执行17个子例程,并想知道什么是最简单,最有效,最快捷的方法

  1. 记录宏
  2. 所做的具体更改
  3. 显示所有更改的列表(在新电子表格中)以及更改(或标记/突出显示)每个单元格的原因
  4. 将每个错误的单元格地址作为可点击链接提供,该链接将用户带到另一个工作表中的特定单元格(在同一工作簿中)
  5. 到目前为止我收集了什么:

    我已经了解了一些如何实现这一目标的方法,最明显的是来自hereherehere,最重要的是here。这些建议方法,如

    • 在遍历所有潜艇之前将UsedRange转储到数组中,然后在所有潜艇完成后将UsedRange转储到第二个阵列中。比较两个数组并找到不同的方式。
    • 利用worksheet_change事件记录更改。
    • Marktastic site的最后一个链接提供了最有说服力的方法,结合了前两种方法。但是,即使他每次worksheet_change事件触发时都会检查数组的方法需要.06秒,这似乎会增加很多开销。

    我面临的一些特殊问题包括:

    • 处理大型文件(15000多行,150列)
    • 我的一些潜艇进行了不需要注意的更改,例如只重新排列某些单元格中的值,否则不会更改它们
    • 我的宏可以快速工作(<1分钟)并完成扫描我们的大文件,所以我想这会消除使用Worksheet_Change事件并在每次错误后立即写入单独的工作表因此得到了解决。即使像马克所暗示的那样使用两种方法似乎也会造成太多滞后时间。
    • 比较两个数组似乎对于我正在使用的文件来说也很慢,因为它意味着迭代15000(行)x 150(列)= 2,250,000个单元格
    • 由于我通过宏进行所有更改,worksheet_change事件不会触发。

    所以,这基本上消除了我遇到的所有选项。我能想到的唯一另一个选择是只有一个数组,在代码执行时用它来记录单元格/位置以及位置中的错误,然后在子程序完成后将整个数组转储到新工作表中。这真的是我最好的选择吗?

    所以,鉴于上述所有事实和研究

    现在,我的问题是:

    • 在我的情况下记录更改并显示宏完成后对文件进行了哪些(必须注意的)更改的最有效方法是什么?无论我是否列出,请随意分享您认为最适合这种情况的方法。
    • 您能否提供一个如何实施建议方法的简单示例代码?

1 个答案:

答案 0 :(得分:0)

这是我决定使用的内容。使用这种方法,每当我想记录一个变化并传递我需要记录的必要变量时,我就调用一个sub。在这种情况下,CellReasonStatus。然后,已调用的子项将其存储在公共Array的末尾,在本例中为ChangeLog。在我完成记录所需的所有更改后,我调用PrintLog子将更改列表吐出到新工作表上,我重命名更改日志。我添加的一个简洁的补充是我在将值存储在数组中时生成的预制HYPERLINK公式。将数组粘贴到工作表后,单元格引用已经是可单击的链接,将用户带到另一个工作表上的地址。

Public ChangeLog() As String

Sub Test()
    Log ActiveSheet.Range("A2"), "Test1", "Changed"
    Log ActiveSheet.Range("B2"), "Test2", "Needs Attention"
    Log ActiveSheet.Range("C2"), "Test3", "Changed"
    PrintLog
End Sub

Sub Log(Cell As Range, Reason As String, Optional Status As String)
    On Error Resume Next
    If (Not Not ChangeLog) = 0 Then
        ReDim ChangeLog(0 To 2, 0 To 1)
        ChangeLog(0, 0) = "Cells": ChangeLog(1, 0) = "Changes Made": ChangeLog(2, 0) = "Status"
        ChangeLog(0, 1) = "=Hyperlink(" & """#'" & ActiveSheet.Name & "'!" & Cell.Address(False, False) & """,""" & Cell.Address(False, False) & """)"
        ChangeLog(1, 1) = Reason
        ChangeLog(2, 1) = Status
    Else
        ReDim Preserve ChangeLog(0 To 2, 0 To UBound(ChangeLog, 2) + 1)
        ChangeLog(0, UBound(ChangeLog, 2)) = "=Hyperlink(" & """#'" & ActiveSheet.Name & "'!" & Cell.Address(False, False) & """,""" & Cell.Address(False, False) & """)"
        ChangeLog(1, UBound(ChangeLog, 2)) = Reason
        ChangeLog(2, UBound(ChangeLog, 2)) = Status
    End If
    On Error GoTo 0
End Sub

Sub PrintLog()
    Dim currentSheet As Integer: currentSheet = ActiveSheet.Index
    For s = 1 To ActiveWorkbook.Worksheets.Count
        If Worksheets(s).Name = "Change Log" Then
            Application.DisplayAlerts = False
            Worksheets(s).Delete
            Application.DisplayAlerts = True
            Exit For
        End If
    Next
    Dim WS As Worksheet: Set WS = Sheets.Add(After:=Worksheets(ActiveSheet.Index))
    WS.Name = "Change Log"
    WS.Tab.Color = vbYellow
    WS.Range("A1").Resize(UBound(ChangeLog, 2) + 1, 3) = WorksheetFunction.Transpose(ChangeLog)
    Erase ChangeLog
    Worksheets(currentSheet).Activate
End Sub

更改日志表预览:
Change Log