【问题标题】:Find all cells changed with paste or drag查找所有通过粘贴或拖动更改的单元格
【发布时间】:2021-04-28 18:28:39
【问题描述】:

设置:

从包含 3 列的工作表开始。 “ID”、“MyNote”、“MyDate”标题。此工作表可能有数千行数据。

我需要“标记”用户对行中的任何内容进行更改的任何行。在其他代码中,标记的行将依次用于更新我的 SQL 服务器上的表。

通常只有几行用户会在会话中更改/更新。所以我不想处理工作表中的每一行,尤其是那些没有变化的。

我现在的工作:

每当用户进行更改时,我通过将“x”写入额外的“标志”列成功地做到了这一点。然后稍后我可以处理任何带有 "x" 标记的行。我是这样做的:

Private Sub Worksheet_Change(ByVal Target As Range)
...
' Flag any lines with a change
    If Not Intersect(Target, Me.Range(TestForChangeColRange)) Is Nothing Then
        Application.EnableEvents = False
          ' Set the "Pending Write" Flag
          Target.Worksheet.Range(PendingWriteCol & Target.Row).Value = "x"
        Application.EnableEvents = True

...  

问题:

这对于一次更新一个单元格非常有用。当用户a)使用拖动和复制(拖动单元格的右下角以在拖动的位置复制它)或b)使用来自其他工作簿的粘贴时出现问题,在任何一种情况下都更改了多个单元格一次。

在这些情况下,Worksheet_Change 只看到第一个单元格,而不是通过拖动或粘贴编辑的任何额外单元格。

我试图找到其他类似的解决方案来拦截复制/粘贴等,但无论如何我都看不到如果复制了,哪些单元格受到了影响。

需要:

我只需要知道哪些行号受到了拖动或复制/粘贴的影响。如果我能准确地将这些行标记为已更新,我就成功了。

跟进

使用蒂姆的解决方案。难以将某些东西重新融入其中。 此外,我需要能够检查是否编辑了特定列,如果是,则清除不同的列。例如,如果编辑了 Col 2,则清除 Col 3 的内容。

我尝试在 For 循环中添加测试,但我的 rw.Col 的 colno 出来了。

If Not rng Is Nothing Then
    'expand the range so we can flag by row, and not cell-by-cell
    Set rng = Application.Intersect(rng.EntireRow, rngTbl)
    For Each rw In rng.Rows 'loop over affected rows
        Me.Cells(rw.Row, PendingWriteCol).Value = "x"

        If rw.Column = RequestTypeCol Then
          Me.Cells(rw.Row, LastColToClear).ClearContents
        End If

    Next rw
End If

你能告诉我我做错了什么吗?

【问题讨论】:

  • 你需要循环由:Intersect(Target, Me.Range(TestForChangeColRange))返回的范围,然后逐行做代码。
  • 斯科特,谢谢。这有点过头了,你能举个例子吗?或者指出我可以看到的地方?我试图将其分配给一个变量并在调试器中查看结果。我看不到如何从中提取行号。我看到一个我认为的数组,其中包含拖动单元格的值,但我不知道如何判断该拖动发生了哪些行或多少行。

标签: excel vba worksheet-function worksheet


【解决方案1】:

例如(根据 Scott 的评论):

Private Sub Worksheet_Change(ByVal Target As Range)
    Const PendingWriteCol As Long = 4
    Const TestForChangeColRange = "A:C"
    
    Dim rw As Range, rng As Range, rngTbl As Range
    
    Set rngTbl = Me.Range(TestForChangeColRange)
    Set rng = Application.Intersect(Target, rngTbl) 'any monitored cells affected?
    If Not rng Is Nothing Then
        'expand the range so we can flag by row, and not cell-by-cell
        Set rng = Application.Intersect(rng.EntireRow, rngTbl)
        For Each rw In rng.Rows 'loop over affected rows
            Me.Cells(rw.Row, PendingWriteCol).Value = "x"
        Next rw
    End If
End Sub

【讨论】:

  • 亲爱的,谢谢!我确实在处理循环周围添加了 Application.EnableEvents = False/True,因此它不会从正在写入的“x”重新触发工作表更改事件。非常感谢让我克服困难。
  • 我把它省略了,因为“x”写在监控范围之外:它会重新触发处理程序,但它只是退出而不会导致无限循环。如果您添加EnableEvents = False,那么您还应该添加一个错误处理程序以确保在运行时错误的情况下它不会被关闭
  • 蒂姆,我有一个后续问题。我在原始问题中发布了它。还需要知道是否正在对特定列进行操作。
  • 你需要删除第二个相交,然后逐个循环遍历 rng 单元
  • 罗杰,谢谢。我刚刚发现我可以以相同的方式对列进行后续循环。不像我想的那么优雅,但实际上是一样的。
猜你喜欢
  • 1970-01-01
  • 2021-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-15
  • 2016-04-13
相关资源
最近更新 更多