【问题标题】:Compare two column in differents worksheets比较不同工作表中的两列
【发布时间】:2018-06-16 13:00:44
【问题描述】:

我创建了一个宏来比较不同工作表中的两列,并用绿色突出显示匹配的单元格

但问题是两列都超过了 9000 行,所以如果我使用这个

for i =1 to lastrow 

它将占用超过 5 分钟的匹配值并给出结果

 Dim i As Variant, j As Integer, k As Integer


'lastRow = Sheets(1).Range("A1").End(xlDown).Row

'lastrow1 = Sheets(2).Range("A1").End(xlDown).Row
lastRow = Sheets(1).Cells(Rows.Count, "A").End(xlUp).Row
lastRow1 = Sheets(2).Cells(Rows.Count, "A").End(xlUp).Row
     For i = 8 To 9252
If Sheets(1).Cells(i, 1).Value <> "" Then

   For j = 1 To 9252
        If Sheets(1).Cells(i, 4).Value = Sheets(2).Cells(j, 1).Value Then
            Sheets(1).Cells(i, 4).Interior.ColorIndex = 4

        End If
        Next j
 Else
    i = i + 1
    End If
    Next i

我想要的是找到一个解决方案来使用 Lastrow 比较两列并找到一个没有延迟的有效解决方案

有人对此有所了解吗?

最好的问候 马球

【问题讨论】:

  • 您在备用工作表上获得多个匹配值的频率是多少?
  • 您是否尝试过条件格式而不是 VBA?
  • @Jeeped 仅 4 或 5 次
  • @johnColeman 在这种情况下我需要使用 VBA 代码来适应以后的很多事情和修改
  • 如果 Sheet1 中的单元格为空白,为什么要推进计数器 (i = i + 1)? For ... Next 会解决这个问题。

标签: excel vba


【解决方案1】:

您只想在 Sheet2 上查找 Sheet1 中的值; Sheet2 上是否有多个匹配值无关紧要。 Application.Match 将比遍历所有行更快地找到相同的值。

dim i as long, f as variant

with workSheets(1)
    for i=8 to .Cells(.Rows.Count, "A").End(xlUp).Row
        f = application.match(.cells(i, "A").value2, workSheets(2).columns("A"), 0)
        if not iserror(f) then
            .cells(i, "A").Interior.ColorIndex = 4
        end if
    next i
end with

使用您原来的双循环,即使在 Sheet2 的第 10 行中找到了 Sheet1 的值,您仍然通过循环进行比较,直到第 9252 行。Sheet1 中的单元格只能着色一次。

【讨论】:

  • 只是为了澄清,正如我在这里看到的“i”从 8 开始并且 J 不存在 ???因为在第二张纸中,值位于不同的行并从不同的行开始
  • Sheet1 从第 8 行开始;检查 Sheet2 上的整个 A 列。您自己的代码在第一行开始了 Sheet2 的 A 列循环。
  • 如果我想修改工作表 2 的行,我该如何管理?? ?提前谢谢你
  • workSheets(2).columns("A")更改为workSheets(2).range("a1:a9252")并调整行号。但是,除非您担心匹配高于或低于指定范围的内容,否则任何优势都是微不足道的。
  • @Jeeped 我喜欢你的极简代码!只是一个小的更正,.cells(i, "A").Interior.ColorIndex = 4 应该是.cells(i, "D").Interior.ColorIndex = 4,尽管我相信 OP 很快就会注意到。
【解决方案2】:

一种方法是使用字典作为集合数据结构来保存工作表 2 中的值,然后在工作表 1 中使用该字典。这会将您的二次算法更改为线性算法:

Sub ColorMatches()
    Dim i As Long
    Dim lastRow As Long
    Dim R As Range, cl As Range
    Dim D As Object
    Dim vals As Variant

    'load dictionary from sheet 2
    Set D = CreateObject("Scripting.Dictionary")
    lastRow = Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row
    vals = Sheets(2).Range("A8:A" & lastRow).Value
    For i = LBound(vals) To UBound(vals)
        If Not D.exists(vals(i, 1)) Then D.Add vals(i, 1), 0
    Next i

    'use dictionary in sheet 1
    lastRow = Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row
    Set R = Sheets(1).Range("A1:A" & lastRow)
    For Each cl In R.Cells
        If D.exists(cl.Value) Then cl.Interior.ColorIndex = 4
    Next cl

End Sub

作为一个很小但可能很重要的一点:请注意,我使用 Long 表示 i 而不是 Integer 表示行索引(就像您在代码中所做的那样)。现代版本的 Excel 的行数超过了 Integer 变量所能表示的行数,而且 16 位整数很可能使用 32 位存储,因此使用 Integer 只是冒着溢出而没有相应收益的风险。

【讨论】:

    【解决方案3】:

    我相信这应该可以解决问题。我不是专家,但通过艰难的方式学到了一个简单的教训:您与工作表的互动越少,它的工作速度就越快!

    Option Explicit                                                             'Is worth using this option, so you remember declaring your variables
    
    Sub SO()
    
    Dim i As Long, j As Long, k As Long
    Dim arrRange1 As Variant, arrRange2 As Variant, arrColor As Variant         'Declare arrays
    ReDim arrColor(0)                                                           'Initial redim
    
    Dim lastRow As Long                                                         'Only need to use one variable for this, and reassign as needed through the code
    Dim sh1 As Worksheet: Set sh1 = ThisWorkbook.Sheets("RandomSheetName 1")    'Declare sheet 1
    Dim sh2 As Worksheet: Set sh2 = ThisWorkbook.Sheets("RandomSheetName 2")    'Declare sheet 2
    
        With sh1
            lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row                    'Get last row from sheet 1 in column "A"
            arrRange1 = .Range(.Cells(8, 4), .Cells(lastRow, 4))                'Get all values from column "D", starting at row 8
        End With
        With sh2
            lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row                    'Get last row from sheet 2 in column "A"
            arrRange2 = .Range(.Cells(1, 1), .Cells(lastRow, 1))                'Get all values from column "A", starting at row 1
        End With
    
        For i = LBound(arrRange1) To UBound(arrRange1)                          'Loop through first sheet values
            If arrRange1(i, 1) <> "" Then                                       'If not empty, then...
                For j = LBound(arrRange2) To UBound(arrRange2)                  'Loop through second sheet values
                    If arrRange1(i, 1) = arrRange2(j, 1) Then                   'If match, then...
                        ReDim Preserve arrColor(k)                              'Redim (preserve) the colours array
                        arrColor(k) = i + 7                                     'Add the value of i in the colours array (note +7, since yours sheet1 values start at row 8, feel free to amend)
                        k = k + 1                                               'Increase the counter for the colours array
                        Exit For                                                'As per idea from the accepted response, no point to check the whole sheet2 range if duplicate found already
                    End If
                Next j
            End If
        Next i
    
        Application.ScreenUpdating = False                                      'It always helps to turn off the screenupdating when working with the sheets
        For i = LBound(arrColor) To UBound(arrColor)                            'Loop through the colours array
            If arrColor(0) = "" Then Exit For                                   'If the first element is empty, means no matches... exit here.
            sh1.Cells(arrColor(i), 4).Interior.ColorIndex = 4                   'Colour the cell as needed using the value we previously stored
        Next i
        Application.ScreenUpdating = True                                       'And lets not forget to turn it on again
    
    End Sub
    

    PS:请注意,Rows.Count 的计数来自ActiveSheet,而不是来自Sheet1Sheet2。您需要充分参考,即:Sheets(1).Rows.Count

    所以这个:

    lastRow = Sheets(1).Cells(Rows.Count, "A").End(xlUp).Row
    

    应该是

    lastRow = Sheets(1).Cells(Sheets(1).Rows.Count, "A").End(xlUp).Row
    

    With Sheets(1)
        lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
    End With
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多