简体   繁体   English

多次运行时如何阻止宏重复?

[英]How to stop a macro from repeating when run multiple times?

I have a macro that I hashed together with the immense help with other users on here. 我有一个宏,在这里我与其他用户一起获得了巨大的帮助。 I then edited it slightly to fit my needs. 然后,我对其进行了略微编辑以适应我的需求。

Right now, running the macro will have Excel look for any numerical value above 0 in column V of Sheet2. 现在,运行宏将使Excel在Sheet2的V列中查找大于0的任何数值。 If a value above 0 exists, copy cells S:V of that same row. 如果存在大于0的值,则复制同一行的单元格S:V。 Then Excel will look for the last row that has data in it in column T and move to the next row after. 然后,Excel将在T列中查找包含数据的最后一行,然后移至下一行。 Excel will then paste the data from cell S:V into this row. Excel然后将来自单元格S:V的数据粘贴到此行中。 Afterwards, it will go back to Sheet2 and continue to look in column V for the next value that exists and do it all over again until it reaches the end of the column. 然后,它将返回Sheet2并继续在V列中查找存在的下一个值,然后再次进行遍历,直到到达列末尾为止。

My issue is that when you run the macro twice, it will perform the actions as needed twice, resulting in duplicate values. 我的问题是,当您两次运行宏时,它将按需要执行两次操作,从而导致值重复。 I want Excel to perform the macro once and then if it is run again, have nothing happen. 我希望Excel执行一次宏,然后再次运行该宏,则什么也没有发生。 I'm trying to prevent human error in case someone accidentally runs the macro twice and doesn't notice it. 我正在尝试防止人为错误,以防有人不小心运行了两次宏而没有注意到它。 Is this possible? 这可能吗?

    Sub CopyPaste()

    Dim c As Range
    Dim IRow As Long, lastrow As Long
    Dim rSource As Range
    Dim wsI As Worksheet, wsO As Worksheet
    Dim endrow As Long


    On Error GoTo Whoa


    '~~> Sheet Where values needs to be checked
    Set wsI = ThisWorkbook.Sheets("Sheet2")
    '~~> Output sheet
    Set wsO = ThisWorkbook.Sheets("Sheet1")

    Application.ScreenUpdating = False

    'Look for last row with data in column T and move to next
    endrow = wsO.Cells(Rows.Count, "T").End(xlUp).Row + 1


    With wsI
        '~~> Find Last Row which has data in Col S to V
        If Application.WorksheetFunction.CountA(.Cells) <> 0 Then

            lastrow = .Columns("S:V").Find(What:="*", _
                          After:=.Range("S1"), _
                          Lookat:=xlPart, _
                          LookIn:=xlFormulas, _
                          SearchOrder:=xlByRows, _
                          SearchDirection:=xlPrevious, _
                          MatchCase:=False).Row
        Else
            lastrow = 1
        End If


        Set rSource = .Range("V1:V" & lastrow)


            If IsNumeric(c.Value) Then
                If c.Value > 0 Then
                    wsO.Cells(endrow + IRow, 20).Resize(1, 4).Value = _
                         .Range("S" & c.Row & ":V" & c.Row).Value
                    wsO.Cells(endrow + IRow, 25).Value = "ID#" & .Range("J" & c.Row).Value
                    IRow = IRow + 1
                End If
            End If

        Next
    End With

 LetsContinue:
    Application.ScreenUpdating = True
    Application.CutCopyMode = False
    Exit Sub
 Whoa:
    MsgBox Err.Description
    Resume LetsContinue
End Sub

Another solution to prevent human error (more like a band-aid solution): 防止人为错误的另一种解决方案(更像创可贴解决方案):

If MsgBox("Are you sure you want to run this macro? Running it a second time can result in duplicate values! Proceed?", vbYesNo + vbQuestion) = vbNo Then Exit Sub

Putting this at the start of your macro can warn the user against running it by accident. 将其放在宏的开头可以警告用户不要意外运行它。

As SJR mentioned why not clear the wsO before running the code again: 正如SJR所述,为什么在再次运行代码之前不清除wsO:

Sub CopyPaste()

Dim c As Range
Dim IRow As Long, lastrow As Long
Dim rSource As Range
Dim wsI As Worksheet, wsO As Worksheet
Dim endrow As Long


On Error GoTo Whoa


'~~> Sheet Where values needs to be checked
Set wsI = ThisWorkbook.Sheets("Sheet2")
'~~> Output sheet
Set wsO = ThisWorkbook.Sheets("Sheet1")

wsO.Rows("2:" & Rows.Count).ClearContents
'the above line will clear the sheet from Row 2 to the last (in case you have headers, if not then change 2 to 1

Application.ScreenUpdating = False

'Look for last row with data in column T and move to next
endrow = wsO.Cells(Rows.Count, "T").End(xlUp).Row + 1


With wsI
    '~~> Find Last Row which has data in Col S to V
    If Application.WorksheetFunction.CountA(.Cells) <> 0 Then

        lastrow = .Columns("S:V").Find(What:="*", _
                      After:=.Range("S1"), _
                      Lookat:=xlPart, _
                      LookIn:=xlFormulas, _
                      SearchOrder:=xlByRows, _
                      SearchDirection:=xlPrevious, _
                      MatchCase:=False).Row
    Else
        lastrow = 1
    End If


    Set rSource = .Range("V1:V" & lastrow)


        If IsNumeric(c.Value) Then
            If c.Value > 0 Then
                wsO.Cells(endrow + IRow, 20).Resize(1, 4).Value = _
                     .Range("S" & c.Row & ":V" & c.Row).Value
                wsO.Cells(endrow + IRow, 25).Value = "ID#" & .Range("J" & c.Row).Value
                IRow = IRow + 1
            End If
        End If


End With

LetsContinue:
    Application.ScreenUpdating = True
    Application.CutCopyMode = False
    Exit Sub
Whoa:
    MsgBox Err.Description
    Resume LetsContinue
End Sub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM