提高宏观效率

Improve Macro Efficiency

宏改进| 您好,这是我第一次 post 访问此站点,我喜欢这里的社区 我是宏的新手,但我已尽力创建一个功能宏,我想听听专业人士的意见,我可以改进我的宏,主要是它的效率。我试图用这个宏执行的任务是根据我的 MainB 工作簿中的单元格打开工作簿,然后比较这两个工作簿中的 3 个字符串,如果它们匹配,将它们复制并粘贴到原始文件,关闭前一个并继续。 我现在遇到的错误是在宏遇到不存在的文件位置后,它关闭了主工作簿并且不再继续。如果它有任何机会继续那么它会给我一条错误消息,它不应该因为我已经指定了要做什么 'OnError'.

 Sub DoCopyandRepeat()

Dim MainB As Workbook
Dim CopyB As Workbook
Dim wsM As Worksheet
Dim wsC As Worksheet
Dim A, B, C, D, E, F, G, H As Variant
Dim X As Integer

Set MainB = ThisWorkbook

Set wsM = MainB.Worksheets("Sheet1")

AfterError:

For X = 3 To 10 Step 1

If Cells(X, 23).Value = "" Then
Workbooks.Open Filename:="C:\Users\XY\OneDrive - XX\Desktop\Macro book"

Set MainB = ThisWorkbook
Set wsM = MainB.Worksheets("Sheet1")
MainB.Activate

Workbooks.Open Filename:="C:\Users\XY\OneDrive - XX\Desktop\Folder1\Folder2\" & Worksheets("Sheet1").Cells(X, 5) & "\Folder3\" & Worksheets("Sheet1").Cells(X, 12) & "\" & Worksheets("Sheet1").Cells(X, 14)
    On Error GoTo Reset:

    End If
    
Set CopyB = ActiveWorkbook
Set wsC = CopyB.ActiveSheet

wsC.Range("E4").Copy
wsM.Activate
Range("AE2").PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, True, False

wsC.Range("C4").Copy
wsM.Activate
Range("AF2").PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, True, False

wsC.Range("E6").Copy
wsM.Activate
Range("AG2").PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, True, False

wsC.Range("E5").Copy
wsM.Activate
Range("AH2").PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, True, False
    
A = Range("AE2")
B = Cells(X, 15)
ActiveSheet.Range("AE3") = StrComp(A, B, vbTextCompare)

C = Range("AF2")
D = Cells(X, 12)
ActiveSheet.Range("AF3") = StrComp(C, D, vbTextCompare)

E = Range("AG2")
F = Cells(X, 18)
ActiveSheet.Range("AG3") = StrComp(E, F, vbTextCompare)

G = Range("AH2")
H = Cells(X, 15)
ActiveSheet.Range("AG3") = StrComp(E, F, vbTextCompare)

If Cells(3, 31) = 0 And Cells(3, 32) = 0 And Cells(3, 33) = 0 Then
    CopyB.Activate
    Range("G4:G10").Copy
    MainB.Activate
    Cells(X, 23).PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, Transpose:=True
    CopyB.Close
    
ElseIf Cells(3, 32) = 0 And Cells(3, 33) = 0 And Cells(3, 34) = 0 Then

    CopyB.Activate
    Range("G6:G10").Copy
    MainB.Activate

    CopyB.Activate
    Range("G5").Copy
    MainB.Activate
    Cells(X, 23).PasteSpecial xlPasteValues, xlPasteSpecialOperationNone
    
    CopyB.Activate
    Range("G4").Copy
    MainB.Activate
    Cells(X, 24).PasteSpecial xlPasteValues, xlPasteSpecialOperationNone
    CopyB.Close
    
Else
    Cells(X, 23) = "failure"

CopyB.Close

End If

ActiveWorkbook.Save
Application.Wait (Now + TimeValue("0:00:05"))

Reset:

Next X
Resume AfterError

End Sub

On Error 问题

您的 On Error GoTo 行应该 在您要处理的代码 之前。

如果您在 VBE 中使用 F8 单步执行代码,例如,如果您要打开的工作簿不存在,则代码在 On Error 处理程序,因此您在屏幕上收到错误消息。

为避免错误出现在屏幕上并使您的代码按预期执行,请这样尝试;

...
Set MainB = ThisWorkbook
Set wsM = MainB.Worksheets("Sheet1")
MainB.Activate

On Error GoTo Reset

Workbooks.Open Filename:="C:\Users\XY\OneDrive - XX\Desktop\Folder1\Folder2\" & Worksheets("Sheet1").Cells(X, 5) & "\Folder3\" & Worksheets("Sheet1").Cells(X, 12) & "\" & Worksheets("Sheet1").Cells(X, 14)

End If
...

这样,如果您单步执行代码,您会看到 On Error 代码在 Workbooks.Open 行之前的行执行,因此如果抛出错误,代码现在知道 转到 Reset

作为一个简单的例子,下面的子程序有一个错误处理程序并尝试除以零(你不能这样做!)。

Sub foo()

Debug.Print 1 / 0
On Error GoTo Safety:

Exit Sub
Safety:
Debug.Print "Safety!"
End Sub

这个例子抛出一个错误;

Run time error '11' Division by zero

现在,如果我们将错误处理程序移动到 1/0 行上方,

Sub foo()

On Error GoTo Safety:

Debug.Print 1 / 0

Exit Sub
Safety:
Debug.Print "Safety!"
End Sub

此示例将 Safety! 输出到 VBE 中的 Immediate window。


至于 审查 您的代码以进行改进等,这个问题更适合另一个 Stack Exchange 站点:Code Review.

提高效率

Option Explicit

Sub DoCopyandRepeat()
     
    Dim dwb As Workbook: Set dwb = ThisWorkbook
    Dim dws As Worksheet: Set dws = dwb.Worksheets("Sheet1")
    
    Dim swb As Workbook
    Dim i As Long
    
    For i = 3 To 10
    
        ' Attempt to open the Source Workbook.
        Set swb = Nothing
        If dws.Cells(i, 23).Value = "" Then ' Unclear, edit appropriately.
            Set swb = Workbooks.Open( _
                Filename:="C:\Users\XY\OneDrive - XX\Desktop\Macro book")
        Else
            On Error Resume Next
            Set swb = Workbooks.Open( _
                Filename:="C:\Users\XY\OneDrive - XX\Desktop\Folder1\Folder2\" _
                & dws.Cells(i, 5).Value & "\Folder3\" _
                & dws.Cells(i, 12).Value & "\" _
                & dws.Cells(i, 14).Value)
            On Error GoTo 0
        End If
        
        If Not swb Is Nothing Then ' if file was opened
        
            Dim sws As Worksheet: Set sws = swb.ActiveSheet
            
            With dws
                
                .Range("AE2").Value = sws.Range("E4").Value
                .Range("AF2").Value = sws.Range("C4").Value
                .Range("AG2").Value = sws.Range("E6").Value
                .Range("AH2").Value = sws.Range("E5").Value
                    
                .Range("AE3").Value = StrComp(.Range("AE2").Value, _
                    .Cells(i, 15).Value, vbTextCompare)
                .Range("AF3").Value = StrComp(.Range("AF2").Value, _
                    .Cells(i, 12).Value, vbTextCompare)
                .Range("AG3").Value = StrComp(.Range("AG2").Value, _
                    .Cells(i, 18).Value, vbTextCompare)
                .Range("AH3") = StrComp(.Range("AH2").Value, _
                    .Cells(i, 15).Value, vbTextCompare) ' suspicious
             
                If .Cells(3, 31).Value = 0 And .Cells(3, 32).Value = 0 _
                        And .Cells(3, 33).Value = 0 Then
                    swb.Range("G4:G10").Copy
                    .Cells(i, 23).PasteSpecial xlPasteValues, _
                        xlPasteSpecialOperationNone, Transpose:=True
                ElseIf .Cells(3, 32).Value = 0 And .Cells(3, 33).Value = 0 _
                        And .Cells(3, 34).Value = 0 Then
                    swb.Range("G6:G10").Copy
                    '.Cells... ' Missing Paste???
                    .Cells(i, 23).Value = swb.Range("G5").Value
                    .Cells(i, 24).Value = swb.Range("G4").Value
                Else
                    .Cells(i, 23).Value = "failure"
                End If
                
                swb.Close SaveChanges:=False
            
            End With
            
            dwb.Save
            Application.Wait (Now + TimeValue("0:00:05")) ' ???
        
        'Else
            
            ' File was not opened: do nothing.
        
        End If
    
    Next i

End Sub

谢谢大家的意见我能够将代码从 160 行减少到 90 行并实现更高的功能,同时还需要更少的变量。这是我最终 result.Also 实现的 dir 函数,因此它在文件夹中搜索特定文件。我仍然相信它可以做得更好,但它足以完成当前的任务。

Sub CopyPaste()

Dim MainB As Workbook
Dim CopyB As Workbook
Dim wsM As Worksheet
Dim wsC As Worksheet
Dim X As Integer
Dim Folder As String
Dim XFile As String
Dim temp As Variant
Set MainB = ThisWorkbook
Set wsM = MainB.Worksheets("DATA")

AfterError:

For X = 3 To 204 Step 1

 If wsM.Cells(X, 16).Value = "" Then
    Folder = "C:\Users\USERXY\FolderLevel1\FolderLevel2\FolderLevel3\XX" & Worksheets("DATA").Cells(X, 1)
    XFile = Dir(Folder & "*short*")
    Workbooks.Open (Folder & XFile)
    On Error GoTo Reset:
    ElseIf Cells(X, 16).Value <> "" Then GoTo ErrorContinue:
    
End If
        
Set CopyB = ActiveWorkbook
Set wsC = CopyB.ActiveSheet
    
    wsC.Range("G4:G10").Copy
    wsM.Cells(X, 16).PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, 
    Transpose:=True
                        
        wsM.Range("AE3").Value = StrComp(wsC.Range("E4").Value, _
           wsM.Cells(X, 9).Value, vbTextCompare)
        wsM.Range("AF3").Value = StrComp(wsC.Range("C4").Value, _
           wsM.Cells(X, 8).Value, vbTextCompare)
        wsM.Range("AG3").Value = StrComp(wsC.Range("E6").Value, _
           wsM.Cells(X, 11).Value, vbTextCompare)
        wsM.Range("AH3") = StrComp(wsC.Range("E5").Value, _
           wsM.Cells(X, 9).Value, vbTextCompare)       
        wsM.Range("AI3") = StrComp(wsC.Range("E5").Value, _
           wsM.Cells(X, 10).Value, vbTextCompare)
        wsM.Range("AJ3") = StrComp(wsC.Range("E4").Value, _
           wsM.Cells(X, 10).Value, vbTextCompare)
           
           
    If wsM.Range("AE3").Value <> 0 And wsM.Range("AH3") = 0 Then
        
        wsM.Cells(X, 16) = wsC.Range("G5")
        wsM.Cells(X, 17) = wsC.Range("G4")
        wsM.Range("AE3").Value = StrComp(wsC.Range("E5").Value, _
        wsM.Cells(X, 9).Value, vbTextCompare) 'Recheck Switch
    End If
    
    If wsM.Range("AF3").Value <> 0 Then
        wsM.Cells(X, 28) = "Type 0 Miss match"
    Else: wsM.Cells(X, 28) = "Fit"
    End If
    
    If wsM.Range("AE3").Value <> 0 Then
        wsM.Cells(X, 29) = "Type 1 Miss match"
    Else: wsM.Cells(X, 29) = "Fit"
    End If
    
    If wsM.Range("AG3").Value <> 0 Then
        wsM.Cells(X, 30) = " Type 2 Miss match"
    Else: wsM.Cells(X, 30) = "Fit"
    End If
 
    If wsM.Range("AI3").Value = 0 Or wsM.Range("AJ3").Value = 0 Then
        wsM.Cells(X, 27) = "Fit"
    Else: wsM.Cells(X, 27) = " Mismatch or Missing"
    End If
    
CopyB.Close

Application.Wait (Now + TimeValue("0:00:05"))
ErrorContinue:
Next X
Exit Sub
Reset:
Cells(X, 16) = "File Location Unavailable"
Resume ErrorContinue:
End Sub