简体   繁体   English

VBA代码中的多个IF语句,用于根据另一列从多个列中提取不同的单元格值。

[英]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 注意值得改变的是

  1. Declaring worksheet variables ( ws1 & ws2 ) to reduce the number of times you have to type/read the string Worksheets("Sheet#") 声明工作表变量( ws1ws2 )以减少键入/读取字符串Worksheets("Sheet#")
  2. Switched from ElseIf method to use Select Case ElseIf方法切换到使用Select Case
  3. Corrected some unqualified objects on your last row calculation 更正了上一行计算中的一些不合格对象
  4. Added 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 硬编码

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.

相关问题 根据另一个工作表的单元格输出隐藏/取消隐藏另一个工作表中的多行的 VBA 代码 - VBA code to hide/unhide multiple rows in another worksheet based on cell output from another worksheet 数组中多个 if 语句的 VBA 代码 - VBA code for multiple if statements within an Array 根据不同工作表下一列中的多个单元格值删除行 - Delete Rows based on multiple cell values in a column under a different sheet 调整VBA代码以根据多行中的值隐藏列 - Adapting VBA Code to Hide Columns based off values from multiple rows VBA - 如果单元格值...然后多个 THEN 语句 - VBA - If cell value ... then multiple THEN statements 使用VBA自动筛选具有不同工作表中的值的多列 - Using VBA to autofilter Multiple columns, with values from different sheet VBA - 根据多个列中的值隐藏行 - VBA - Hide rows based on values in multiple Columns Excel公式/ VBA代码:水平查找值并拉整列(多个值) - Excel Formula/ VBA code : To lookup value horizontally and pull the entire column ( multiple values) VBA 将值粘贴到多列中的代码 - VBA Code to paste values in multiple columns 如何使用 vba 代码在一个单元格中获取多个查找值,用于静态 LookupValue、LookupRange、ColumnNumber、来自不同工作表的分隔符 - how to get multiple lookup values in one cell using vba code for static LookupValue, LookupRange , ColumnNumber, delimiter from different sheets
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM