Search code examples
excelvbaworksheet-functionworksheet

Find all cells changed with paste or drag


SETUP:

Start with a sheet that has 3 columns. "ID", "MyNote", "MyDate" headers. This sheet may have thousands of rows of data.

I need to "flag" any row where the user has made a change to anything on the row. In other code the flagged rows will be in turn be used to update a table on my SQL server.

Typically there will only be a few rows the user would change/update in a session. So I don't want to process every row in the sheet, particularly the ones with no changes.

WHAT I HAVE WORKING NOW:

I have done this successfully by writing a "x" to an additional "flag" column any time the user makes a change. Then later I can process any rows that were flagged with a "x" . I did this using:

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

...  

PROBLEM:

That works great for individual cells being updated one at a time. The problem comes when a user either a) uses the drag and copy (drag the bottom right corner of a cell to replicate it where dragged), or b) with a paste from some other workbook, in either case more than one cell is changed at a time.

In those cases, the Worksheet_Change sees only the first cell and not any extra cells edited by dragging or pasting.

I tried to find other similar solutions for intercepting Copy/Paste, etc., but I can't see anyway to find that if a copy was made, which cells were affected.

NEED:

All I need to know is which row numbers were affected from a drag or a copy/paste. If I can accurately flag those rows as updated, I'm in business.

FOLLOW-UP

Using Tim's solution. Having trouble melding something back into it. Additionally I need to be able to check if a particular column was edited and if it was, clear a different column. For example, if Col 2 is edited, clear the contents of Col 3.

I tried adding the test inside the For loop, but my colno for rw.Col is coming out off.

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

Can you show me what I've done wrong?


Solution

  • For example (following on from Scott's comment):

    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