简体   繁体   English

检查不同工作表中的列相同的工作簿 vba

[英]Check columns in difference sheets same workbook vba

I just started playing with vba working to find a way to check two excel sheets.I went trough all the answers i could find here about comparing sheets in excel with vba and finally found this answer VBA - Compare Tables on 2 Sheets with Differences from R.Katnaan that gave the best result. I just started playing with vba working to find a way to check two excel sheets.I went trough all the answers i could find here about comparing sheets in excel with vba and finally found this answer VBA - Compare Tables on 2 Sheets with Differences from R .Katnaan给出了最好的结果。 So i am trying to adjust and implement it on my situation.所以我正在尝试根据我的情况进行调整和实施。 The sheets are target and counting with an output sheet for the result.工作表是目标并使用 output 工作表作为结果计数。 The sheets are dynamically changed of my choosing based on reference in the output sheet where the user decides the files to be checked though a dropdown list.这些工作表是根据 output 工作表中的参考动态更改我选择的,用户通过下拉列表决定要检查的文件。 The code always checks the column b with starting row 3 on both sheets target and counting.该代码始终检查工作表目标和计数上从第 3 行开始的 b 列。

The code is working but for large sheets ( more than 100 rows ) it takes to much time.该代码正在运行,但对于大型工作表(超过 100 行),它需要很长时间。 example for a sheet with 3500 rows it took 3 minutes 45 seconds to bring the result and there are mistakes on it ( results missing).例如,对于具有 3500 行的工作表,需要 3 分 45 秒才能得出结果,并且上面有错误(结果丢失)。 i would guess is the do while function but i am not sure.is there a way to optimize the code?我猜是 function 但我不确定。有没有办法优化代码? Thank you in advance for your time.提前感谢您的宝贵时间。

Public Sub Compare_sheets()

    Dim targetSheet, countingSheet, outputSheet As Worksheet
    Dim startrow, outputRow, temptargetRow, tempcountingRow, countingRowCount, targetRowCount, totalRowCount, finishedcountingIndex As Integer
    Dim finishedcounting() As String
    Dim isExist As Boolean
    
    
    'Do in background
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    
    'Set sheets
    Set targetSheet = Sheets(Sheets("Compare Sheets").Range("C3").Value)
    Set countingSheet = Sheets(Sheets("Compare Sheets").Range("C4").Value)
    Set outputSheet = Sheets("Compare Sheets")

    'Set start row of each sheet for data
    startrow = 3
    outputRow = 2

    'Get row count from counting sheet and targetsheet
    countingRowCount = countingSheet.Range("b" & startrow).End(xlDown).Row
    targetRowCount = targetSheet.Range("b" & startrow).End(xlDown).Row
    
    'Check which is bigger
    If countingRowCount < targetRowCount Then
        totalRowCount = targetRowCount
    Else
        totalRowCount = countingRowCount
    End If
    'Set index
    finishedcountingIndex = 0

    'Re-define array
    ReDim finishedcounting(0 To totalRowCount - 1)

    'Set the start row
    temptargetRow = startrow

    'Here I looped with OR state, you can modify it to AND start if you want
    Do

        'Reset exist flag
        isExist = False

        'loop all row in counting sheet
        For tempcountingRow = 1 To totalRowCount Step 1

            'If row is not finished for checking.
            If UBound(Filter(finishedcounting, tempcountingRow)) < 0 Then

                'If all cell are equal
                If targetSheet.Range("b" & temptargetRow) = countingSheet.Range("b" & tempcountingRow) Then

                    'Set true to exist flag
                    isExist = True

                    'Store finished row
                    finishedcounting(finishedcountingIndex) = tempcountingRow

                    finishedcountingIndex = finishedcountingIndex + 1

                    'exit looping
                    Exit For

                End If

            End If

        Next tempcountingRow

        'Show result
        outputSheet.Range("g" & outputRow) = targetSheet.Range("b" & temptargetRow)
        outputSheet.Range("h" & outputRow) = targetSheet.Range("c" & temptargetRow)
        outputSheet.Range("i" & outputRow) = targetSheet.Range("d" & temptargetRow)

        If isExist Then
            outputSheet.Range("f" & outputRow) = "FOUND"
        Else
            outputSheet.Range("f" & outputRow) = "MISSING"
        End If

        'increase output row
        outputRow = outputRow + 1

        'go next row
        temptargetRow = temptargetRow + 1

    Loop While targetSheet.Range("B" & temptargetRow) <> vbNullString ' Or targetSheet.Range("B" & temptargetRow) <> "" Or targetSheet.Range("C" & temptargetRow) <> ""

    'loop all row in counting sheet
    For tempcountingRow = 1 To totalRowCount Step 1

        'If row is not finished for checking.
        If UBound(Filter(finishedcounting, tempcountingRow)) < 0 Then

            'Show result
            outputSheet.Range("g" & outputRow) = countingSheet.Range("b" & tempcountingRow)
            outputSheet.Range("j" & outputRow) = countingSheet.Range("c" & tempcountingRow)
            'outputSheet.Range("C" & outputRow) = countingSheet.Range("C" & tempcountingRow)
            outputSheet.Range("f" & outputRow) = "ADDITIONAL"

            'increase output row
            outputRow = outputRow + 1

        End If

    Next tempcountingRow
    
    'Update
    Application.ScreenUpdating = True
    Application.EnableEvents = True

End Sub 

Use a Dictionary Object .使用字典 Object

Option Explicit
Public Sub Compare_sheets2()

    Const ROW_START = 3
    Const COL_KEY = "B"

    Dim t0 As Single: t0 = Timer
    Dim wsTarget As Worksheet, wsCount As Worksheet, wsOutput As Worksheet
    Dim lastrow As Long, i As Long, rowOut As Long
    
    Dim dict As Object, key, ar
    Set dict = CreateObject("Scripting.Dictionary")
    
    Set wsOutput = Sheets("Compare Sheets")
    With wsOutput
        Set wsTarget = Sheets(.Range("C3").Value2)
        Set wsCount = Sheets(.Range("C4").Value2)
    End With
    
    With wsCount
        lastrow = .Cells(.Rows.Count, COL_KEY).End(xlUp).Row
        ar = .Range("B1:B" & lastrow).Value2
        For i = ROW_START To lastrow
            key = Trim(ar(i, 1))
            If dict.exists(key) Then
                MsgBox "Duplicate key '" & key & "'", vbExclamation, wsCount.Name & " Row " & i
            Else
                dict.Add key, i
            End If
        Next
    End With
    
    rowOut = 2
    With wsTarget
        lastrow = .Cells(.Rows.Count, COL_KEY).End(xlUp).Row
        ' FOUND or MISSING
        For i = ROW_START To lastrow
            key = Trim(.Cells(i, COL_KEY))
            
            ' check if col B value exists on wsCount
            If dict.exists(key) Then
                wsOutput.Cells(rowOut, "F") = "FOUND"
                dict(key) = 0 ' mark as found
            Else
                wsOutput.Cells(rowOut, "F") = "MISSING"
            End If
            wsOutput.Cells(rowOut, "G").Resize(, 3) = .Cells(i, COL_KEY).Resize(, 3).Value2
            rowOut = rowOut + 1
        Next
    
        ' ADDITIONAL
        For Each key In dict.keys
           i = dict(key)  ' row on wsCount
           If i > 0 Then
               wsOutput.Cells(rowOut, "F") = "ADDITIONAL"
               wsOutput.Cells(rowOut, "G") = key
               wsOutput.Cells(rowOut, "J") = wsCount.Cells(i, "C").Value2
               rowOut = rowOut + 1
           End If
        Next
    End With
     
    MsgBox lastrow - ROW_START + 1 & " rows scanned on " & wsTarget.Name, _
            vbInformation, Format(Timer - t0, "0.0 secs")
    
End Sub

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

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