Timestamping and copying a line to another sheet, if certain condition met

可紊 提交于 2020-01-16 18:19:10

问题


I need my audit list to (1) add a time stamp in the end of current line and then (2) copy the line to the other sheet, when there is a "N" or "n" marked in the specified column. The idea is to get a summary of copied non-conformities.

My trouble is that in the case of the code I use, it only deals with the first column correctly. It does nothing with others.

I use the code (below).

Sub Worksheet_Change(ByVal Target As Range)
    On Error GoTo ErrHandler
    Application.EnableEvents = False

    If Target.Column = 9 And UCase(Target) = "N" Then
        Set rChange = Intersect(Target, Range("I:I"))
        If Not rChange Is Nothing Then
            Application.EnableEvents = False
            For Each rCell In rChange
                If rCell > "" Then
                    With rCell.Offset(0, 2)
                        .Value = Now
                        .NumberFormat = "dd/mm/yyyy"
                    End With
                Else
                    rCell.Offset(0, 2).Clear
                End If
            Next
        End If

    If Target.Column = 9 And UCase(Target) = "N" Then
    Target.EntireRow.Copy Destination:=Sheet9.Range("A" & _
    Rows.Count).End(xlUp).Offset(1)

    If Target.Column = 8 And UCase(Target) = "N" Then
        Set rChange = Intersect(Target, Range("H:H"))
        If Not rChange Is Nothing Then
            Application.EnableEvents = False
            For Each rCell In rChange
                If rCell > "" Then
                    With rCell.Offset(0, 3)
                        .Value = Now
                        .NumberFormat = "dd/mm/yyyy"
                    End With
                Else
                    rCell.Offset(0, 3).Clear
                End If
            Next
        End If
    If Target.Column = 8 And UCase(Target) = "N" Then
    Target.EntireRow.Copy Destination:=Sheet9.Range("A" & _
    Rows.Count).End(xlUp).Offset(1)

    If Target.Column = 7 And UCase(Target) = "N" Then
        Set rChange = Intersect(Target, Range("G:G"))
        If Not rChange Is Nothing Then
            Application.EnableEvents = False
            For Each rCell In rChange
                If rCell > "" Then
                    With rCell.Offset(0, 4)
                        .Value = Now
                        .NumberFormat = "dd/mm/yyyy"
                    End With
                Else
                    rCell.Offset(0, 4).Clear
                End If
            Next
        End If
    If Target.Column = 7 And UCase(Target) = "N" Then
    Target.EntireRow.Copy Destination:=Sheet9.Range("A" & _
    Rows.Count).End(xlUp).Offset(1)


    If Target.Column = 6 And UCase(Target) = "N" Then
        Set rChange = Intersect(Target, Range("F:F"))
        If Not rChange Is Nothing Then
            Application.EnableEvents = False
            For Each rCell In rChange
                If rCell > "" Then
                    With rCell.Offset(0, 5)
                        .Value = Now
                        .NumberFormat = "dd/mm/yyyy"
                    End With
                Else
                    rCell.Offset(0, 5).Clear
                End If
            Next
        End If
    If Target.Column = 6 And UCase(Target) = "N" Then
    Target.EntireRow.Copy Destination:=Sheet9.Range("A" & _
    Rows.Count).End(xlUp).Offset(1)

    If Target.Column = 5 And UCase(Target) = "N" Then
        Set rChange = Intersect(Target, Range("E:E"))
        If Not rChange Is Nothing Then
            Application.EnableEvents = False
            For Each rCell In rChange
                If rCell > "" Then
                    With rCell.Offset(0, 6)
                        .Value = Now
                        .NumberFormat = "dd/mm/yyyy"
                    End With
                Else
                    rCell.Offset(0, 6).Clear
                End If
            Next
        End If
    If Target.Column = 5 And UCase(Target) = "N" Then

    Target.EntireRow.Copy Destination:=Sheet9.Range("A" & _
    Rows.Count).End(xlUp).Offset(1)

    If Target.Column = 4 And UCase(Target) = "N" Then
        Set rChange = Intersect(Target, Range("D:D"))
        If Not rChange Is Nothing Then
            Application.EnableEvents = False
            For Each rCell In rChange
                If rCell > "" Then
                    With rCell.Offset(0, 7)
                        .Value = Now
                        .NumberFormat = "dd/mm/yyyy"
                    End With
                Else
                    rCell.Offset(0, 7).Clear
                End If
            Next
        End If
    If Target.Column = 4 And UCase(Target) = "N" Then
    Target.EntireRow.Copy Destination:=Sheet9.Range("A" & _
    Rows.Count).End(xlUp).Offset(1)

    End If
    End If
    End If
    End If
    End If
    End If
    End If

    End If
    End If
    End If
    End If
    End If

    ErrHandler:
    Application.EnableEvents = True

End Sub

回答1:


Your problem is easy to identify if you indent correctly.

First two other issues:

  1. Pleae do not include On Error GoTo ErrHandler at the top of your routine. This just means you ignore any errors. You should be trying to identify statements that can give errors and to fix the problems that cause those errors.
  2. Target does not have to be a single cell as your code assumes. For example, the user could have copied or cleared a range.

Below is an indented version of the start of your routine with the Then and Else bodies removed so you can see the problem.

Sub Worksheet_Change(ByVal Target As Range)

  If Target.Column = 9 And UCase(Target) = "N" Then
    If Not rChange Is Nothing Then
    End If

    ' We are already within If Target.Column = 9 And UCase(Target) = "N"
    ' So this If adds nothing
    If Target.Column = 9 And UCase(Target) = "N" Then

      ' We are within If Target.Column = 9 And UCase(Target) = "N"
      ' So the Then block of this If will never be executed 
      If Target.Column = 8 And UCase(Target) = "N" Then
        If Not rChange Is Nothing Then
        End If

      If Target.Column = 8 And UCase(Target) = "N" Then

        If Target.Column = 7 And UCase(Target) = "N" Then

You need to use the If .. ElseIf ... ElseIf ... Else ... End If construct

Sub Worksheet_Change(ByVal Target As Range)
  Application.EnableEvents = False

  If UCase(Target) = "N" Then

    If Target.Column = 9 Then
      If Not rChange Is Nothing Then
      End If

      ' Delete because unnecessary
      'If Target.Column = 9 Then

    ElseIf Target.Column = 8 Then
      If Not rChange Is Nothing Then
      End If

      ' Delete because unnecessary
      'If Target.Column = 8 Then

    ElseIf Target.Column = 7 Then
      If Not rChange Is Nothing Then
      End If

      ' Delete because unnecessary
      'If Target.Column = 7 Then

    ElseIf Target.Column = 6 Then

    : : : :

    End If

  End If

If I understand your code, most of the duplication is unnecessary. Try the changes I have suggested. If they work, I will show you how to tidy your code more extensively.




回答2:


It seems that you want to see if an N has been typed or pasted into column D:I with slightly varying actions resulting from the location of Target. Many of the actions are the same; essentially they timestamp in column K and copy across to Sheet9. An If/ElseIf/ElseIf/End If would work for this by dealing with each individually but you should be able to stack all of the same actions together.

Sub Worksheet_Change(ByVal Target As Range)

    If Not Intersect(Target, Range("D:I")) Is Nothing Then
        On Error GoTo ErrHandler
        Application.EnableEvents = False
        Dim rChange As Range
        For Each rChange In Intersect(Target, Range("D:I"))
            If UCase(rChange.Value2) = "N" Then
                Cells(rChange.Row, "K") = Now
                Cells(rChange.Row, "K").NumberFormat = "dd/mm/yyyy"
                Cells(rChange.Row, "A").EntireRow.Copy _
                  Destination:=Sheet9.Cells(Rows.Count, "A").End(xlUp).Offset(1)
            ElseIf Not CBool(Len(rChange.Value)) Then
                Cells(rChange.Row, "K").ClearContents
            End If
        Next rChange
    End If

ErrHandler:
    Application.EnableEvents = True

End Sub

If an N is typed or pasted in D:I, a timestamp is put into column K and the row is copied to Sheet9. If the value is deleted from D:I, the timestamp is removed and no copy operation is made. By making the offset always point to column K, you do not require individual routines for each column.



来源:https://stackoverflow.com/questions/29701395/timestamping-and-copying-a-line-to-another-sheet-if-certain-condition-met

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!