【问题标题】:Visual Basic, VBA array loopVisual Basic,VBA 数组循环
【发布时间】:2017-08-16 22:51:17
【问题描述】:

我使用http://www.homeandlearn.org/arrays_and_loops.html 来帮助我解决这个问题。

我有过滤到一个表的数据连接。不幸的是,当程序将文件导出到 Excel 时,其中一个来源会在错误的列(客户端列)中随机放置不正确的数据(通常是日期)。我想做的是类似于索引/匹配函数的东西。我想将这个主表 (A) 中的每个预订号与同一个工作簿中的另一个表 (B) 进行对比。如果另一张表 (B) 中的预订号与主表 (A) 中的预订号匹配,我希望将正确的客户值输入到主表 (A) 中。我对 VBA 还是很陌生,所以感谢您的帮助。我试图在这里和那里修改我的代码,但无济于事。另外,我最初是在没有真实数据的情况下将其作为练习来运行的,所以我没有弄乱我的原始文件。我试图添加适当的语法来引用其他工作表和诸如此类的东西,所以我想这也可能输入错误。这是我想出的最接近的原始代码:

Sub TransferData()
Dim MyArray(1 To 19) As Single

MyArray(1) = 81899
MyArray(2) = 87172
MyArray(3) = 87275
MyArray(4) = 87394
MyArray(5) = 87446
MyArray(6) = 87496
MyArray(7) = 87621
MyArray(8) = 87631
MyArray(9) = 87726
MyArray(10) = 87822
MyArray(11) = 87858
MyArray(12) = 88041
MyArray(13) = 88097
MyArray(14) = 88127
MyArray(15) = 88160
MyArray(16) = 88191
MyArray(17) = 88359
MyArray(18) = 88487
MyArray(19) = 88545

For i = 1 To 19
    If Worksheets("Sheet1").Range("B" & i).Value = MyArray(i) Then
       Worksheets("Sheet2").Range("P" & i).Value = _ 
       Worksheets("Sheet1").Range("E" & i).Value
    End If
Next i

End Sub

我不记得这个错误,因为代码与上面的不完全一样,但接近它。我相信它遇到的问题是,当 i 变量超过 19 时,系统找不到 > 19 的数组。我需要 VBA 来检查当前 3k+ 行数不断变化的 19 个数组。我试图添加另一个变量,如果我将变量分开,我可以让 VBA 针对所有行检查 19 个数组。这是我为此想出的代码....

Sub TransferData()
Dim MyArray(1 To 19) As Single

MyArray(1) = 81899
MyArray(2) = 87172
MyArray(3) = 87275
MyArray(4) = 87394
MyArray(5) = 87446
MyArray(6) = 87496
MyArray(7) = 87621
MyArray(8) = 87631
MyArray(9) = 87726
MyArray(10) = 87822
MyArray(11) = 87858
MyArray(12) = 88041
MyArray(13) = 88097
MyArray(14) = 88127
MyArray(15) = 88160
MyArray(16) = 88191
MyArray(17) = 88359
MyArray(18) = 88487
MyArray(19) = 88545

For i = 1 To 5000
For j = 1 To 19
If Worksheets("Sheet1").Range("B" & i).Value = MyArray(j) Then
    Worksheets("Sheet2").Range(i, 16).Value = Worksheets("Sheet1"). _ 
    Range(i,5).Value
    Next j
End If
Next i

End Sub

使用此代码,我得到编译错误:Next without For。在网上搜索时,我发现这可能是因为我有 2 个“For”,一个 if 语句,if 语句中的“next”语句,然后是循环外的另一个“next”语句。我在想必须这样做,以便 B 列中的每个单元格都针对所有数组可能性进行检查。

见下图。我需要将工作表中 P 列(实际帐单名称)的值:TMRtoSPIde 输入到工作表上的 D 列(帐单名称)中:当工作表中 K 列中的预留编号:TMRtoSPIde 与工作表中的预留匹配时:RawData:RawData。您会注意到工作表:RawData 在 Billing Name 列中有一个错误的 5 位序列日期。这些是我想要替换的。

【问题讨论】:

  • 如果在Worksheets("Sheet1").Range("B2").Value 上找到预订号,则在Worksheets("Sheet2").Range("P2").Value = Worksheets("Sheet1").Range("E2").Value 上找到。奇怪的是,您在Worksheets("Sheet2") 上更新与Worksheets("Sheet1") 上的预订号相同的行我认为您还必须在Worksheets("Sheet2") 上找到预订号。
  • 你是绝对正确的。我一会儿要回到这里的绘图板。感谢您了解这个。
  • MyArray() 的目的是什么?这些是您想要限制代码使用的帐号子集吗?是否还有其他您不想使用的帐号?
  • 我将值存储在 MyArray 中,希望可以使用它来识别需要更新的行,因为我无法弄清楚如何进行 VBA 索引/匹配并让它粘贴这些值在我的桌子上。我拍了一些屏幕截图,希望能更容易理解。我将在上面编辑我的帖子。

标签: arrays excel vba loops


【解决方案1】:

字典和集合是匹配唯一值的理想选择。在此示例中,我使用 Scripting.Dictionary 来存储唯一 ID 和对找到它们的 EntireRow 的引用。

注意:Range().Range() 将返回一个相对于第一个范围对象的引用(例如,Range("A10").EntireRow.Range("ZZ1").Address 返回$ZZ$10)。

只存储所需的值会更简单,我只是想证明您可以将对象引用存储在字典中。请务必注意,您可以将对象存储为字典中的键和/或值。人们犯的一个常见错误是尝试将范围引用存储为键 dictionary.Add Cells(1,1), Cells(1,2) 会将对 Cells(1,1) 的引用存储为键,将 Cells(1,2) 的引用存储为它的值。这样做的问题是字典不知道如何比较单元格,您将无法根据关键关系查找您的值。 dictionary.Add Cells(1,1).Value, Cells(1,2) 是正确的语法。

Sub TransferData()
    Dim r As Range, Source As Range
    Dim d As Object
    Set d = CreateObject("Scripting.Dictionary")
    With Worksheets("TMRtoSPIde")
        For Each r In .Range("B2", .Range("B" & .Rows.Count).End(xlUp))
            If Not d.Exists(r.Value) Then d.Add r.Value, r.EntireRow
        Next
    End With

    With Worksheets("RawData")
        For Each r In .Range("B2", .Range("B" & .Rows.Count).End(xlUp))
            If d.Exists(r.Value) Then
                r.EntireRow.Range("K1").Value = d(r.Value).Range("P1").Value
            End If
        Next
    End With

End Sub

【讨论】:

  • 在阅读了您的回复后,由于您提到的整行内容并在代码中看到了这一点,我对其进行了一些修改。我担心我会转移左边的另一张我不需要的桌子。因此,我选择了带有绿色标题的正确表格,将其放在自己的工作表上,并相应地更改了编码以匹配它,瞧!非常感谢你的帮助。我从来没有听说过 VBA 的集合和字典,所以我会研究一下。我对 VBA 还是很陌生,很快就要上课了,所以感谢您让我领先一点,您的时间和解决方案!
【解决方案2】:

你的循环应该是这样的:

For i = 1 To 5000
    For j = 1 To 19
        If Worksheets("Sheet1").Cells(i, "B").Value = MyArray(j) Then
            Worksheets("Sheet2").Cells(i, "P").Value = Worksheets("Sheet1").Cells(i, "E").Value
            'Exit from the "For j" loop if we found a match
            Exit For
        End If
    Next j
Next i

【讨论】:

  • 感谢您对此进行调查。我会采纳 Thomas 的建议并尝试将其与您的建议联系起来,然后提供我的发现。
猜你喜欢
  • 2021-02-16
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-21
  • 2018-07-16
  • 1970-01-01
相关资源
最近更新 更多