【问题标题】:Compare 2 sets of data and paste any missing values on another sheet比较 2 组数据并将任何缺失值粘贴到另一张纸上
【发布时间】:2017-11-14 18:06:43
【问题描述】:

所以我有一个包含 1000 多行的主工作表和另一个“应该”具有相同数据的工作表。但是,实际上有时主服务器中缺少一些,有时查询运行中缺少一些。
为简单起见,假设唯一 ID 在 B 列中。这是我的代码,但它非常慢,而且只进行单向比较。

我的理想代码应该是运行得更流畅一些,并为我提供主数据和查询中缺失的数据。

我提问的方式有问题吗,请告诉我。

Sub FindMissing()

    Dim lastRowE As Integer
    Dim lastRowF As Integer
    Dim lastRowM As Integer
    Dim foundTrue As Boolean


    lastRowE = Sheets("Master").Cells(Sheets("Master").Rows.Count, "B").End(xlUp).Row
    lastRowF = Sheets("Qry").Cells(Sheets("Qry").Rows.Count, "B").End(xlUp).Row
    lastRowM = Sheets("Mismatch").Cells(Sheets("Mismatch").Rows.Count, "B").End(xlUp).Row



    For i = 1 To lastRowE
        foundTrue = False
        For j = 1 To lastRowF
            If Sheets("Master").Cells(i, 2).Value = Sheets("Qry").Cells(j, 2).Value Then
                foundTrue = True
                Exit For
            End If
        Next j
        If Not foundTrue Then
            Sheets("Master").Rows(i).Copy Destination:= _
            Sheets("Mismatch").Rows(lastRowM + 1)
            lastRowM = lastRowM + 1
        End If
    Next i

End Sub

【问题讨论】:

  • 两件事可以帮助您加快代码速度;首先在代码的开头添加Application.ScreenUpdating = False,然后在最后一个For 循环的末尾重新应用Application.ScreenUpdating = True。最后,不要使用.Copy,而是尝试使用Range("A1").Value = Range("B1").Value仅提取从位置到目的地的值
  • 您为什么使用Sheets("E Dump").Rows.Count 来帮助定位主工作表上的最后一行?
  • 哎呀,试图简化遗漏的工作表名称
  • @Maldred 神圣的蝙蝠侠,application.screenupdate 太棒了。速度提高了 10 倍。我在第二部分仍然遇到问题
  • 永远不要将任何东西声明为 Integer,始终声明为 Long。 Integer 的限制为 32767,并且无论如何都会转换为 Long。将 i 和 j 声明为 Long,现在它们是未声明的,因此它们默认具有 Variant 类型。如果数据量很大,它会影响速度,但如果整数适用于这个数据集,应该不会有任何明显的改进。

标签: vba excel


【解决方案1】:

不要遍历工作表上的单元格。将所有值收集到变量数组中并在内存中处理。

Option Explicit

Sub YouSuckAtVBA()

    Dim i As Long, mm As Long
    Dim valsM As Variant, valsQ As Variant, valsMM As Variant

    With Worksheets("Master")
        valsM = .Range(.Cells(1, "B"), .Cells(.Rows.Count, "B").End(xlUp)).Value2
    End With

    With Worksheets("Qry")
        valsQ = .Range(.Cells(1, "B"), .Cells(.Rows.Count, "B").End(xlUp)).Value2
    End With

    ReDim valsMM(1 To (UBound(valsM, 1) + UBound(valsQ, 1)), 1 To 2)
    mm = 1
    valsMM(mm, 1) = "value"
    valsMM(mm, 2) = "missing from"

    For i = LBound(valsM, 1) To UBound(valsM, 1)
        If IsError(Application.Match(valsM(i, 1), valsQ, 0)) Then
            mm = mm + 1
            valsMM(mm, 1) = valsM(i, 1)
            valsMM(mm, 2) = "qry"
        End If
    Next i

    For i = LBound(valsQ, 1) To UBound(valsQ, 1)
        If IsError(Application.Match(valsQ(i, 1), valsM, 0)) Then
            mm = mm + 1
            valsMM(mm, 1) = valsQ(i, 1)
            valsMM(mm, 2) = "master"
        End If
    Next i

    valsMM = helperResizeArray(valsMM, mm)

    With Worksheets("Mismatch")
        With .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0)
            .Resize(UBound(valsMM, 1), UBound(valsMM, 2)) = valsMM
        End With
    End With

End Sub

Function helperResizeArray(vals As Variant, x As Long)
    Dim arr As Variant, i As Long

    ReDim arr(1 To x, 1 To 2)

    For i = LBound(arr, 1) To UBound(arr, 1)
        arr(i, 1) = vals(i, 1)
        arr(i, 2) = vals(i, 2)
    Next i

    helperResizeArray = arr
End Function

您无法调整二维数组的第一个等级,因此我添加了一个辅助函数,该函数将在将结果放回不匹配工作表之前调整其大小。

【讨论】:

  • 吉普车爬行者。这太神奇了,也有点令人沮丧。我应该是这里工作的大师,每次我来到这个网站时,我都觉得自己像一只孔雀鱼。非常感谢吉普。另一个不相关的问题,你们如何发展自己的技能?我基本上已经最大限度地学习了 VBA 课程,他们甚至没有触及任何接近这一点的东西。对想要了解更多信息的人有什么建议吗?
  • 好吧,您可以在 SO excel-vba 论坛上花费数千小时。 vba 速度慢的声誉很大程度上是由于大多数人编写的代码效率低下。
猜你喜欢
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
  • 2020-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多