【问题标题】:vba find value then paste another into different cell in another columnvba找到值然后将另一个粘贴到另一列的不同单元格中
【发布时间】:2015-06-26 10:35:49
【问题描述】:

我目前正在运行一个宏,它在工作表 2 的 C 列中从“工作表 1”的 A 列中查找值,如果这些匹配,则应该将工作表 1 的 B 列中的值复制到表 2 中的相应行。

我的宏可以工作,但因为这是一个庞大的工作表,其中的循环花费了太多时间。这是因为工作表 1 大约有 300,000 行,并且每个实例中的值都是唯一的。在 Sheet 2 中大约有 50,000 行。它已经运行了一夜,到目前为止,工作表 1 中只达到了 60,000 行

我绝不是 VBA 专家,甚至不是中级专家,但从我所读到的内容来看,使用 Find 可能比查找匹配和循环更快?

这是我当前使用的宏

 Option Explicit

Sub lookupandcopy()
Application.Screenupdating = True

Dim j As Long, i As Long, lastRow1 As Long, lastRow2 As Long
Dim sh_1, sh_3 As Worksheet
Dim MyName As String

Set sh_1 = Sheets("sheet1") 
Set sh_3 = Sheets("sheet2")


lastRow1 = sh_1.UsedRange.Rows.Count 

For j = 2 To lastRow1
MyName = sh_1.Cells(j, 1).Value 


lastRow2 = sh_3.UsedRange.Rows.Count

For i = 2 To lastRow2
    If sh_3.Cells(i, 3).Value = MyName Then
        sh_3.Cells(i, 13).Value = sh_1.Cells(j, 2).Value 
    End If

    Next i

  Next j

Application.Screenupdating = True
End Sub

如果我遗漏了任何内容或任何其他需要的细节,请告诉我!

【问题讨论】:

  • 第 3 行应该是 Application.ScreenUpdating = False
  • 对不起,它在实际代码中是正确的,但它在另一台机器上运行,所以我不得不在这里重新输入。
  • 为什么用 sh_3 来指代 sheet2?一个关键问题是 sheet1 A 列中的值是否唯一。如果是——为什么不使用简单的 vlookup?
  • sh_3 用于避免我输入错误(像手指一样的大猩猩),Vlookup 会更快吗?我一直认为它对于大量数据来说太慢了,通常会尽量避免它
  • @Els 但为什么不为“sheet2”使用 sh_2?

标签: vba excel


【解决方案1】:

您似乎将 sheet1 中的 A 列和 B 列用作字典(并通过线性搜索访问值)。为什么不将值加载到具有 O(1) 搜索的字典对象中?确保您的项目包含对 Microsoft Scripting Runtime 的引用(如果您没有做过这些事情,则在 VBE 中使用工具 > 引用)然后尝试:

Sub lookupandcopy()
    Application.ScreenUpdating = False

    Dim AVals As New Dictionary
    Dim i As Long, j As Long, lastRow1 As Long, lastRow2 As Long
    Dim sh_1, sh_3 As Worksheet
    Dim MyName As String

    Set sh_1 = Sheets("sheet1")
    Set sh_3 = Sheets("sheet2")

    With sh_1
        lastRow1 = .Range("A:A").Rows.Count 'last row in spreadsheet
        lastRow1 = .Cells(lastRow1, 1).End(xlUp).Row 'last used row in column A
        'load the AVal dict
        For j = 2 To lastRow1
            MyName = .Cells(j, 1).Value
            If Len(MyName) > 0 Then AVals.Add MyName, .Cells(j, 2).Value
        Next j
    End With

    With sh_3
        lastRow2 = .Range("A:A").Rows.Count
        lastRow2 = .Cells(lastRow2, 3).End(xlUp).Row 'last used row in column 3
        For i = 2 To lastRow2
            MyName = .Cells(i, 3).Value
            If AVals.Exists(MyName) Then
                .Cells(i, 13).Value = AVals.Item(MyName)
            End If
         Next i
    End With
    Application.ScreenUpdating = True
End Sub

如果您在 A 列中有重复的值,那么您需要执行一些操作,例如将值发生的行索引的值集合存储为值,但设置这样一个字典的工作仍然比使用嵌套循环更好。

【讨论】:

  • B 列中的重复值会导致问题,我正在尝试运行您的代码,但它给了我以下错误“运行时错误 457”此键已与此集合的元素相关联'
  • 所以 - 您必须在 A 列中有重复的值。我将在今天晚些时候尝试修改我的代码以反映这一点。
  • @ELs 你的行 sh_3.Cells(i, 13).Value = sh_1.Cells(j, 2).Value 让我很困惑。如果相同的值 myName 可以在 A 列中多次出现,那么这会将 Cells(i,13) 的最终值设置为 B 列中的值,该值对应于 A 列中 myName 的最后一次出现。我不认为你想要这个——所以我怀疑你在 A 列中的值是不同的除了空白单元格。如果 usedrange (在工作表 1 的不同部分)低于 A 包含键的部分,那么您正在尝试处理 A 列中的更多内容,而不是您想要的。我稍微调整了代码。看看它现在是否有效。
  • 我已经添加了你的更新代码,它似乎工作得很好!
  • @ELs 当数据变得和你一样大时,从二次到线性时间算法可以产生巨大的差异。我的猜测是,它的运行速度比以前快 50,000 倍。字典是主要的救星,但两个 With 语句可能也有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多