[英]Multiple IF statements within VBA code to pull in different cell values from multiple columns based on another column.
Apologies if this has been asked before, but I couldn't find a solution that matched the code I already have, which nearly works except for the conditions I'm adding in. 如果以前曾经问过这个问题,我会道歉,但我找不到与我已经拥有的代码相匹配的解决方案,除了我正在添加的条件之外,它几乎可以工作。
Explanation: 说明:
I have multiple Record #s in Sheet1. 我在Sheet1中有多个Record#。 I need to find a match for the same in Sheet2 and when located, I need it to return values that are all found in Column 8 and 15, based on the value (and subsequently row #) in Column 7.
我需要在Sheet2中找到相同的匹配项,当找到它时,我需要它返回第8列和第15列中的值,这些值基于第7列中的值(以及随后的行#)。
For ex: 例如:
Sheet1:
Column 1
123
999
989
Sheet2:
Column1 Column7 Column8 Column 15
321 PRA PRAABC Completed
123 IRA IRABCD Cancelled
000 TPSD TPSDRST Completed
989 APSD APSDABC In Prog
So the results would be: 结果将是:
123 IRABCD Cancelled 123 IRABCD取消
989 APSDABC In Prog 989 APSDABC In Prog
My code below: 我的代码如下:
Sub CopyBasedonSheet1()
Dim i As Long
Dim j As Long
Sheet1LastRow = Worksheets("Sheet1").Range("O" & Rows.Count).End(xlUp).Row
Sheet2LastRow = Worksheets("Sheet2").Range("B" & Rows.Count).End(xlUp).Row
For j = 1 To Sheet1LastRow
For i = 1 To Sheet2LastRow
If Worksheets("Sheet1").Cells(j, 15).Value = Worksheets("Sheet2").Cells(i, 2).Value Then 'if Engagement # from sheet1 matches sheet2
If Worksheets("Sheet2").Cells(i, 7) = "IRA" Then
Worksheets("Sheet1").Cells(j, 23).Value = Worksheets("Sheet2").Cells(i, 8).Value
Worksheets("Sheet1").Cells(j, 24).Value = Worksheets("Sheet2").Cells(i, 15).Value
If Worksheets("Sheet2").Cells(i, 7) = "TPSD" Then
Worksheets("Sheet1").Cells(j, 25).Value = Worksheets("Sheet2").Cells(i, 8).Value
Worksheets("Sheet1").Cells(j, 26).Value = Worksheets("Sheet2").Cells(i, 15).Value
ElseIf Worksheets("Sheet2").Cells(i, 7) = "CA" Then
Worksheets("Sheet1").Cells(j, 27).Value = Worksheets("Sheet2").Cells(i, 8).Value
Worksheets("Sheet1").Cells(j, 28).Value = Worksheets("Sheet2").Cells(i, 15).Value
Else
End If
Next i
Next j
End Sub
I receive a "Next without For"
error on Next i
我在
Next i
上收到"Next without For"
错误
This is what a simplified version of your code may look like. 这就是代码的简化版本。 Note worthy changes are
注意值得改变的是
ws1
& ws2
) to reduce the number of times you have to type/read the string Worksheets("Sheet#")
ws1
和ws2
)以减少键入/读取字符串Worksheets("Sheet#")
ElseIf
method to use Select Case
ElseIf
方法切换到使用Select Case
Option Explicit
for clarity Option Explicit
When it comes to efficiency, you would probably be better off looping through an array rather a range like this. 在效率方面,你可能最好在循环数组而不是像这样的范围。 Either way, it's a good idea to toggle of
Screen Updating
to speed things along. 无论哪种方式,切换
Screen Updating
以加快速度都是一个好主意。
Option Explicit
Sub CopyBasedonSheet1()
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
Dim i As Long, j As Long
Dim LRow1 As Long, LRow2 As Long
LRow1 = ws1.Range("O" & ws1.Rows.Count).End(xlUp).Row
LRow2 = ws2.Range("B" & ws2.Rows.Count).End(xlUp).Row
For j = 1 To LRow1
For i = 1 To LRow2
If ws1.Cells(j, 15).Value = ws2.Cells(i, 2).Value Then
Select Case ws2.Cells(i, 7)
Case "IRA"
ws1.Cells(j, 23).Value = ws2.Cells(i, 8).Value
ws1.Cells(j, 24).Value = ws2.Cells(i, 15).Value
Case "TPSD"
ws1.Cells(j, 25).Value = ws2.Cells(i, 8).Value
ws1.Cells(j, 26).Value = ws2.Cells(i, 15).Value
Case "CA"
ws1.Cells(j, 27).Value = ws2.Cells(i, 8).Value
ws1.Cells(j, 28).Value = ws2.Cells(i, 15).Value
End Select
End If
Next i
Next j
End Sub
There are two missing End If
s in the code. 代码中有两个缺少
End If
。 To avoid this problem, add the End If
s as your go and fill in the If
block content after. 要避免此问题,请将
End If
添加为go,并填写If
块内容。
If Worksheets("Sheet1").Cells(j, 15).Value = Worksheets("Sheet2").Cells(i, 2).Value Then End If
Using a code formatter to auto indent your code will help catch such errors. 使用代码格式化程序自动缩进代码将有助于捕获此类错误。 Check out RubberDuck .
查看RubberDuck 。
Sub CopyBasedonSheet1()
Dim i As Long
Dim j As Long
Sheet1LastRow = Worksheets("Sheet1").Range("O" & Rows.Count).End(xlUp).row
Sheet2LastRow = Worksheets("Sheet2").Range("B" & Rows.Count).End(xlUp).row
For j = 1 To Sheet1LastRow
For i = 1 To Sheet2LastRow
If Worksheets("Sheet1").Cells(j, 15).Value = Worksheets("Sheet2").Cells(i, 2).Value Then 'if Engagement # from sheet1 matches sheet2
If Worksheets("Sheet2").Cells(i, 7) = "IRA" Then
Worksheets("Sheet1").Cells(j, 23).Value = Worksheets("Sheet2").Cells(i, 8).Value
Worksheets("Sheet1").Cells(j, 24).Value = Worksheets("Sheet2").Cells(i, 15).Value
If Worksheets("Sheet2").Cells(i, 7) = "TPSD" Then
Worksheets("Sheet1").Cells(j, 25).Value = Worksheets("Sheet2").Cells(i, 8).Value
Worksheets("Sheet1").Cells(j, 26).Value = Worksheets("Sheet2").Cells(i, 15).Value
ElseIf Worksheets("Sheet2").Cells(i, 7) = "CA" Then
Worksheets("Sheet1").Cells(j, 27).Value = Worksheets("Sheet2").Cells(i, 8).Value
Worksheets("Sheet1").Cells(j, 28).Value = Worksheets("Sheet2").Cells(i, 15).Value
Else
End If
End If
End If
Next i
Next j
End Sub
Using a Scripting.Dictionary
to match unique values is vastly faster then using nested loops. 使用
Scripting.Dictionary
匹配唯一值比使用嵌套循环快得多。 Watch: Excel VBA Introduction Part 39 - Dictionaries . 观看: Excel VBA简介第39部分 - 词典 。
Sub RefactoredCopyBasedonSheet1()
Dim dic As Object, key As Variant, row As Range
Dim r As Long
Set dic = CreateObject("Scripting.Dictionary")
With Worksheets("Sheet2")
For r = 1 To .Range("B" & Rows.Count).End(xlUp).row
key = .Cells(r, "B").Value
Set dic(key) = .Rows(r)
Next
End With
With Worksheets("Sheet1")
For r = 1 To .Range("O" & Rows.Count).End(xlUp).row
key = .Cells(r, "O").Value
If dic.Exists(key) Then
Set row = dic(key)
Select Case row.Cells(1, 7)
Case "IRA"
.Cells(j, 23).Value = row.Cells(1, 8).Value
.Cells(j, 24).Value = row.Cells(1, 15).Value
Case "TPSD"
.Cells(j, 25).Value = row.Cells(1, 8).Value
.Cells(j, 26).Value = row.Cells(1, 15).Value
Case "CA"
.Cells(j, 27).Value = row.Cells(1, 8).Value
.Cells(j, 28).Value = row.Cells(1, 15).Value
End Select
End If
Next
End With
End Sub
Hard Coded? 硬编码? It means code names of the sheets are used so you just write eg Sheet1.Name, Sheet2.Rows.Count etc. You can find the code name in the VBE (F11).
这意味着使用工作表的代码名称,因此您只需编写例如Sheet1.Name,Sheet2.Rows.Count等。您可以在VBE(F11)中找到代码名称。 When you click on a sheet, the properties window shows in the first row the (name) property, where you can also change it.
单击工作表时,属性窗口会在第一行显示(名称)属性,您也可以在其中更改它。 But the interesting part is you can rename your sheets via sheet tab as you wish and the code will still work.
但有趣的是,您可以根据需要通过工作表选项卡重命名工作表,代码仍然有效。
You should always use Option Explicit before any code in a module, because it will indicate if there is an error in the code. 您应该始终在模块中的任何代码之前使用Option Explicit ,因为它将指示代码中是否存在错误。
Use constants at the beginning of a procedure (Sub or Function) for Numbers and Strings, so you will easily find them and if you want to change them, you will only have to do it once . 在数字和字符串的过程 (Sub或Function)开头使用常量 ,这样您就可以轻松找到它们,如果要更改它们,您只需要执行一次 。 Imagine you don't won't the data from column 15 anymore but data from column 12. You would have to change it many times in your code but by using constants you change it only once .
想象一下,您不会再使用第15列中的数据,而是来自第12列的数据。您必须在代码中多次更改它,但使用常量只需更改一次 。
Since I don't know what's in the columns, I've used some generic variable names, but you should always use more descriptive ones like intSource, lngData, objWbSource, objWsTarget, rngValues, intCount etc. 由于我不知道列中的内容,我使用了一些通用变量名,但是你应该总是使用更具描述性的名称,如intSource,lngData,objWbSource,objWsTarget,rngValues,intCount等。
Use the With ... End With statement especially for worksheets, not only to not have to type their name many times, but to make the code more readable for others or for yourself after eg months or years. 使用With ... End With语句尤其适用于工作表,不仅不必多次键入其名称,而且可以使代码在其他人或自己(例如数月或数年)之后更具可读性 。
Another way (using the Find Method) of determining the last used row was used in this code, the only difference being to the preferred way of eg .Cells(Rows.Count, 1).End(xlUp).Row, that it won't skip the last row if you have data in it. 在此代码中使用另一种方法(使用Find方法)确定最后使用的行 ,唯一的区别是例如.Cells(Rows.Count,1).End(xlUp).Row的首选方式,它赢了如果你有数据,请跳过最后一行。
Option Explicit
Sub CopyBasedonSheet1()
' Columns in Sheet1
Const cInt1_1 As Integer = 15 ' O
Const cInt1_2 As Integer = 23 ' W
Const cInt1_3 As Integer = 24 ' X
Const cInt1_4 As Integer = 25 ' Y
Const cInt1_5 As Integer = 26 ' Z
Const cInt1_6 As Integer = 27 ' AA
Const cInt1_7 As Integer = 28 ' AB
' Columns in Sheet2
Const cInt2_1 As Integer = 2 ' B
Const cInt2_2 As Integer = 7 ' G
Const cInt2_3 As Integer = 8 ' H
Const cInt2_4 As Integer = 15 ' O
Const cStrSearch1 As String = "IRA"
Const cStrSearch2 As String = "TPSD"
Const cStrSearch3 As String = "CA"
Dim lngLR1 As Long ' Sheet1 Last Used Row
Dim lngLR2 As Long ' Sheet2 Last Used Row
Dim lng1 As Long ' Sheet1 Row Counter
Dim lng2 As Long ' Sheet2 Row Counter
' Sheet2
With Sheet2
' Last Row Sheet2
lngLR2 = .Range(.Cells(1, cInt2_1), .Cells(Rows.Count, cInt2_1)) _
.Find(What:="*", After:=.Cells(1, cInt2_1), _
LookIn:=xlFormulas, Lookat:=xlWhole, _
SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Row
End With
' Sheet1
With Sheet1
' Last Row Sheet1
lngLR1 = .Range(.Cells(1, cInt1_1), .Cells(Rows.Count, cInt1_1)) _
.Find(What:="*", After:=.Cells(1, cInt1_1), _
LookIn:=xlFormulas, Lookat:=xlWhole, _
SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Row
For lng1 = 1 To lngLR1
For lng2 = 1 To lngLR2
' Check if Engagement # from Sheet1 matches Sheet2
If .Cells(lng1, cInt1_1).Value = Sheet2.Cells(lng2, cInt2_1).Value _
Then
Select Case Sheet2.Cells(lng2, cInt2_2).Value
Case cStrSearch1
.Cells(lng1, cInt1_2).Value = Sheet2.Cells(lng2, cInt2_3).Value
.Cells(lng1, cInt1_3).Value = Sheet2.Cells(lng2, cInt2_4).Value
Case cStrSearch2
.Cells(lng1, cInt1_4).Value = Sheet2.Cells(lng2, cInt2_3).Value
.Cells(lng1, cInt1_5).Value = Sheet2.Cells(lng2, cInt2_4).Value
Case cStrSearch3
.Cells(lng1, cInt1_6).Value = Sheet2.Cells(lng2, cInt2_3).Value
.Cells(lng1, cInt1_7).Value = Sheet2.Cells(lng2, cInt2_4).Value
Case Else
End Select
Else
End If
Next
Next
End With
End Sub
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.