使用VBA循环的多个IF语句

时间:2016-10-18 17:35:54

标签: excel vba excel-vba excel-formula

数据:

这只是我正在使用的数据的样本。

请查看下面的输出。 "通过代码输出"是我们运行代码时得到的。 "预期产出"是我们正在寻找的那个。

Data+Output

我之前粘贴的第一个代码及其修改版本似乎是在给出结果,但唯一的问题是,它会留下一个或两个相似的值而不加入它们。

原始讯息:

我已经制作了一个" If Statement"。此语句比较两行并在其中一列中显示注释。虽然该语句在excel中完美运行,但VBE中记录的代码却没有。请帮忙。

声明:

=IF(D2=D3,(IF(G2+H2+G3+H3=0,CONCATENATE("Batch ","'",C2,"'"," has no earnings/hours"),(CONCATENATE(IF(G2=0,"",CONCATENATE("paying ","'",F2,"'"," earnings ",G2)),IF(H2=0,"",IF(H2<>0,IF(G2=0,CONCATENATE("paying ","'",F2,"'"," hours ",H2),CONCATENATE(" and hours ",H2)))),IF(G3=0,"",CONCATENATE(" , paying ","'",F3,"'"," earnings ",G3)),IF(H3=0,"",IF(H3<>0,IF(G3=0,CONCATENATE(" , paying ","'",F3,"'"," hours ",H3),CONCATENATE(" and hours ",H3)))))))),IF(D2<>D3,IF(G2+H2=0,CONCATENATE("Batch ","'",C2,"'"," has no earnings/hours"),CONCATENATE("Batch ","'",C2,"'",CONCATENATE(IF(G2=0,"",CONCATENATE(" paying ","'",F2,"'"," earnings ",G2)),IF(H2=0,"",IF(G2=0,CONCATENATE(" paying ","'",F2,"'"," hours ",H2),CONCATENATE(" and hours ",H2))))))))
  1. 我尝试为此语句录制一个宏,但是当我在宏中执行录制的代码时出现错误。
  2. 我想将此语句转换为宏并将其作为循环运行直到最后一行结束。
  3. 我想比较第1行和第2行中的特定单元格,然后执行上面的语句。然后比较第1行和第2行中两个不同单元格的值,将结果粘贴到另一个单元格中。执行这些任务后,删除第二行并运行类似单元格值的循环,将第一个注释与第二个注释连接起来。如果下一行值不同,则不删除该行并运行循环,依此类推,直到所有行结束。
  4. 此外,第二个&#34; if语句&#34;没有做它应该做的工作。
  5. 第二句如果声明:

    =IF(D2<>D3,I2,IF(D2=D3,IF(AND(I2="Y",I3="Y"),"Y",lf(AND(I2="Y",I3="N"),"Y",IF(AND(I2="N",I3="Y"),"Y",IF(AND(I2="N",I3="N"),"N"))))))
    

    If语句1的VBE代码:

    ActiveCell.FormulaR1C1 = _
        "=IF(RC[-6]=R[1]C[-6],(IF(RC[-3]+RC[-2]+R[1]C[-3]+R[1]C[-2]=0,CONCATENATE(""Batch "",""'"",RC[-7],""'"","" has no earnings/hours""),(CONCATENATE(IF(RC[-3]=0,"""",CONCATENATE(""paying "",""'"",RC[-4],""'"","" earnings "",RC[-3])),IF(RC[-2]=0,"""",IF(RC[-2]<>0,IF(RC[-3]=0,CONCATENATE("" paying "",""'"",RC[-4],""'"",""hours"", RC[-2]),CONCATENATE("" and hours "",RC[-2]))" & _
        "1]C[-3]=0,"""",CONCATENATE("" , paying "",""'"",R[1]C[-4],""'"","" earnings "",R[1]C[-3])),(IF(R[1]C[-2]=0,"""",IF(R[1]C[-2]<>0,IF(R[1]C[-3]=0,CONCATENATE("" paying "","""",R[1]C[-4],""'"","" hours "",R[1]C[-2]),CONCATENATE("" and hours "",R[1]C[-2]))))))))),IF(RC[-6]<>R[1]C[-6],IF(RC[-3]+RC[-2]=0,CONCATENATE(""Batch "",""'"",RC[-7],""'"","" has no earnings/hours"")" & _
        "CONCATENATE(""Batch "",""'"",RC[-7],""'"",CONCATENATE(IF(RC[-3]=0,"""",CONCATENATE("" paying "",""'"",RC[-4],""'"",""earnings "",RC[-3])),IF(RC[-2]=0,"""",IF(RC[-3]=0,CONCATENATE("" paying "",""'"",RC[-4],""'"","" hours "",RC[-2]),CONCATENATE("" and hours "",RC[-2]))))))))"
    

    Final Output

    代码1:

    Sub CompareAndCompare()
    Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet4")
    Dim A As Range, B As Range, C As Range, D As Range, E As Range, F As Range
    Dim compRange As Range: Set compRange = ws.Range("D2", ws.Cells(ws.Rows.Count, "D").End(xlUp))
    Dim state1 As String
    
    For Each A In compRange    'A = D2 on first iteration of the loop
        Set B = A.Offset(1)    'B = D3
        Set C = A.Offset(0, 3) 'C = G2
        Set D = A.Offset(0, 4) 'D = H2
        Set E = A.Offset(1, 3) 'E = G3
        Set F = A.Offset(1, 4) 'F = H3
        Set G = A.Offset(0, 5) 'G = I2
        Set H = A.Offset(1, 5) 'H = I3
        state1 = ""
    
        If A.Value = B.Value Then
            If G.Value = "N" And H.Value = "N" Then 'Statement 2
                ws.Range("K" & A.Row).Value = "N"
            Else
                If G.Value = "" And H.Value = "Y" Then
                ws.Range("K" & A.Row).Value = "Y"
            Else
                 If G.Value = "Y" And H.Value = "" Then
                ws.Range("K" & A.Row).Value = "Y"
            Else
                If G.Value = "N" And H.Value = "" Then
                ws.Range("K" & A.Row).Value = "N"
            Else
                If G.Value = "" And H.Value = "N" Then
                ws.Range("K" & A.Row).Value = "N"
            Else
                If G.Value = "" And H.Value = "" Then
                ws.Range("K" & A.Row).Value = ""
            Else: ws.Range("K" & A.Row).Value = "Y"
            End If
           End If
          End If
         End If
        End If
      End If
            If C.Value + D.Value + E.Value + F.Value = 0 Then
                state1 = "'" & ws.Range("F" & A.Row).Value & "', " & "'" & ws.Range("F" & A.Offset(1).Row).Value & "' has no earnings/hours"
            Else
                If C.Value <> 0 Then _
                    state1 = state1 & "paying '" & ws.Range("F" & A.Row).Value & "' earnings " & C.Value
    
                If D.Value <> 0 Then
                    If C.Value = 0 Then
                        state1 = state1 & "paying '" & ws.Range("F" & A.Row).Value & "' earnings " & D.Value
                    Else
                        state1 = state1 & " and hours " & D.Value
                    End If
                End If
    
                If E.Value <> 0 Then _
                    state1 = state1 & " paying '" & ws.Range("F" & A.Offset(1).Row).Value & "' earnings " & E.Value
    
                If F.Value <> 0 Then
                    If E.Value = 0 Then
                        state1 = state1 & " paying '" & ws.Range("F" & A.Offset(1).Row).Value & "' hours " & F.Value
                    Else
                        state1 = state1 & " and hours " & F.Value
                    End If
                End If
            End If
            B.EntireRow.Delete
        Else 'D2 <> D3
            ws.Range("K" & A.Row).Value = G.Value 'Statement 2
    
            If C.Value + D.Value = 0 Then
                state1 = "'" & ws.Range("F" & A.Row).Value & "' has no earnings/hours"
            Else
                'state1 = "'" & ws.Range("F" & A.Row).Value & "'"
                If C.Value <> 0 Then _
                    state1 = " paying '" & ws.Range("F" & A.Row) & "' earnings " & C.Value
    
                If D.Value <> 0 Then
                    If C.Value = 0 Then
                        state1 = " paying '" & ws.Range("F" & A.Row) & "' hours " & D.Value
                    Else
                        state1 = " and hours " & D.Value
                    End If
                End If
            End If
        End If
        ws.Range("J" & A.Row).Value = state1
    Next A
    End Sub
    

    代码2:

    Sub CompareAndCompare1()
    Dim ws As Worksheet:  Set ws = ThisWorkbook.Sheets("Sheet4")
    Dim A As Range, B As Range
    Dim compRange As Range: Set compRange = ws.Range("D2", ws.Cells(ws.Rows.Count, "D").End(xlUp))
    Dim state1 As String
    For Each A In compRange    'A = D2 on first iteration of the loop
        Set B = A.Offset(1)    'B = D3
         Set C = A.Offset(0, 7) 'C =K2
        Set D = A.Offset(1, 7) 'D = K3
        state1 = ""
     If A.Value = B.Value Then
             If C.Value = "N" And D.Value = "N" Then    'Statement 2
                ws.Range("L" & A.Row).Value = "N"
            Else
                If C.Value = "" And D.Value = "Y" Then
                ws.Range("L" & A.Row).Value = "Y"
            Else
                 If C.Value = "Y" And D.Value = "" Then
                ws.Range("L" & A.Row).Value = "Y"
            Else
                If C.Value = "N" And D.Value = "" Then
                ws.Range("L" & A.Row).Value = "N"
            Else
                If C.Value = "" And D.Value = "N" Then
                ws.Range("L" & A.Row).Value = "N"
            Else
                If C.Value = "" And D.Value = "" Then
                ws.Range("L" & A.Row).Value = ""
            Else: ws.Range("L" & A.Row).Value = "Y"
            End If
          End If
         End If
        End If
       End If
       End If
      state1 = "Batch " & ws.Range("C" & A.Row).Value & ": " & ws.Range("J" &  A.Row).Value & ", " & ws.Range("J" & A.Offset(1).Row).Value
     B.EntireRow.Delete 
     Else 'D2<>D3
     ws.Range("L" & A.Row).Value = C.Value
     state1 = "Batch " & ws.Range("C" & A.Row).Value & ": " & ws.Range("J" & A.Row).Value
     End If
     ws.Range("M" & A.Row).Value = state1
      Next A
      End Sub
    

    代码3:

    Sub CompareAndCompare2()
    Dim ws As Worksheet:  Set ws = ThisWorkbook.Sheets("Sheet4")
    Dim A As Range, B As Range
    Dim compRange As Range: Set compRange = ws.Range("A2", ws.Cells(ws.Rows.Count, "A").End(xlUp))
    Dim state1 As String
     For Each A In compRange    'A = A2 on first iteration of the loop
        Set B = A.Offset(1)    'B = A3
         Set C = A.Offset(0, 11) 'C =L2
        Set D = A.Offset(1, 11) 'D = L3
        state1 = ""
    If A.Value = B.Value Then
            If C.Value = "N" And D.Value = "N" Then    'Statement 2
                ws.Range("N" & A.Row).Value = "N"
                Else: ws.Range("N" & A.Row).Value = "Y"
            End If
            state1 = "For file# " & ws.Range("A" & A.Row).Value & ", " &    ws.Range("M" & A.Row).Value & ", " & ws.Range("M" & A.Offset(1).Row).Value
    B.EntireRow.Delete
    Else 'A2<>A3
    ws.Range("N" & A.Row).Value = C.Value
    state1 = "For file# " & ws.Range("A" & A.Row).Value & ", " & ws.Range("M" & A.Row).Value
    End If
    ws.Range("O" & A.Row).Value = state1
    Next A
    End Sub
    

1 个答案:

答案 0 :(得分:1)

将公式转换为宏

我重新创建了您添加的最后一张图片的原始版本:

enter image description here

使用下面经过大量修改的代码

Sub CompareAndCompare()
    Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets(1)
    Dim A As Range, B As Range, C As Range, D As Range, E As Range, F As Range, finalR As Range
    Dim compRange As Range: Set compRange = ws.Range("D2", ws.Cells(ws.Rows.Count, "D").End(xlUp))
    Dim state1 As String, stateTypeA As String, yn As String, myCell As Variant
    Dim myRow As Long, STATEMENT As String, tempString() As String
    Dim passOne As Boolean, firstTime As Boolean: firstTime = True
    Dim st1 As String, st2 As String, output1 As Range, output2 As Range
    Dim idNo As Range, batchNo1 As Range, batchNo2 As Range

    For myRow = 2 To compRange.Count + 1 'This loop puts statements in "J"
        stateType = ""
StartOver:
        Set A = ws.Range("D" & myRow)        'A = D2
        Set C = ws.Range("G" & myRow)        'C = G2
        Set D = ws.Range("H" & myRow)        'D = H2
        Set output1 = ws.Range("J" & myRow)

        If A.Value = "" Then Exit For

        STATEMENT = ""
        If C.Value = 0 Then STATEMENT = STATEMENT & "1"
        If D.Value = 0 Then STATEMENT = STATEMENT & "2"
        If C.Value <> 0 Then STATEMENT = STATEMENT & "3"
        If D.Value <> 0 Then STATEMENT = STATEMENT & "4"
        stateType = "(" & ws.Range("F" & myRow).Value & ") "

        Select Case STATEMENT
            Case "12" 'C = 0, D = 0
                state1 = "*"

            Case "34" 'C <> 0, D <> 0
                state1 = stateType & "has earnings of " & C.Value & " and " & D.Value & " hours"

            Case "14" 'C = 0, D <> 0
                state1 = stateType & "has " & D.Value & " hours"

            Case "23" 'D = 0, C <> 0
                state1 = stateType & "has earnings of " & C.Value
            Case Else: MsgBox STATEMENT 'If a case isn't defined, show STATEMENT so code can be added
        End Select
            output1.Value = state1
    Next myRow
'//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    For myRow = 2 To compRange.Count + 1 'This Loop concatenates "J" when same "D"
Reiterate:
        Set A = ws.Range("D" & myRow) 'A = D2 on first iteration of the loop
        Set B = A.Offset(1)           'B = D3

        If A.Value = "" Then Exit For

        If A.Value = B.Value Then


CheckForMore:
            Set G = A.Offset(0, 5)        'G = I2
            Set H = A.Offset(1, 5)        'H = I3

            If (G.Value = "N" And H.Value = "N") Or ((G.Value = "" Or H.Value = "") And (G.Value = "N" Or H.Value = "N")) Then 'Statement 2
                yn = "N"
            Else: yn = "Y"
            End If

            ws.Range("K" & myRow).Value = yn
            Set B = A.Offset(1)
            st1 = "(" & ws.Range("F" & myRow).Value & ")"
            st2 = "(" & ws.Range("F" & myRow + 1).Value & ")"
            Set output1 = ws.Range("J" & myRow)
            Set output2 = ws.Range("J" & myRow + 1)

            If firstTime = True Then
                If output1.Value = "*" Then
                    firstTime = False
                    stateType = st1
                End If
            End If

            If output2.Value = "*" And A.Value = B.Value Then
                If stateType = "" Then
                    stateType = st2
                Else: stateType = stateType & ", " & st2
                End If
                B.EntireRow.Delete
                GoTo CheckForMore

            ElseIf output1.Value = "*" And firstTime = False And A.Value = B.Value Then
                output1.Value = "* have no earnings/hours, " & output2.Value
                B.EntireRow.Delete
                GoTo Reiterate

            ElseIf output1.Value <> "*" And firstTime = False And A.Value = B.Value Then
                output1.Value = output1.Value & ", " & output2.Value
                B.EntireRow.Delete
                GoTo Reiterate

            ElseIf output1.Value <> "*" And stateType <> "" And A.Value = B.Value Then
                output1.Value = output1.Value & ", * have no earnings/hours, " & output2.Value
                B.EntireRow.Delete
                GoTo Reiterate '''''''''''''''''''''''

            ElseIf output1.Value = "*" And A.Value <> B.Value Then
                output1.Value = "* have no earnings/hours "

            ElseIf output1.Value <> "*" And stateType <> "" Then
                output1.Value = output1.Value & ", * have no earnings/hours "
            End If

            output1.Value = Replace(output1.Value, "*", stateType)
            firstTime = True
            stateType = ""
        Else
            output1.Value = Replace(output1.Value, "*", stateType)
            firstTime = True
            stateType = ""
        End If
    Next myRow

    Set finalR = ws.Range("A2", ws.Cells(ws.Rows.Count, "A").End(xlUp))
    passOne = False
'/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    For Each myCell In finalR 'This loop finalizes and removes duplicates
        myRow = myCell.Row
finalAgain:
        Set output1 = ws.Range("J" & myRow)
        Set output2 = ws.Range("J" & myRow + 1)
        Set idNo = ws.Range("A" & myRow)
        Set batchNo1 = ws.Range("C" & myRow)
        Set batchNo2 = ws.Range("C" & myRow + 1)

        If myCell.Value = myCell.Offset(1).Value Then
            If passOne = False Then
                output1.Value = "FOR " & idNo.Value & ", FROM BATCH " & batchNo1.Value & ": " & output1.Value _
                    & Chr(10) & "FROM BATCH " & batchNo2.Value & ": " & output2.Value
            Else: output1.Value = output1.Value & Chr(10) & "FROM BATCH " & batchNo2.Value & ": " & output2.Value
            End If
            myCell.Offset(1).EntireRow.Delete
            passOne = True
            GoTo finalAgain
        Else: If passOne = False Then output1.Value = "FOR " & idNo.Value & ", FROM BATCH " & batchNo1.Value & ": " & output1.Value
        End If
        passOne = False
    Next myCell
End Sub

将产生以下结果:

enter image description here

看起来与您想要的相似。我对格式进行了一些编辑,以便于阅读。让我知道您的想法以及这是否适合您:)

下面的原始答案(可能有助于了解如何将EXCEL公式转换为VBA代码)

我不确定我理解你问题的范围,但这是直接转换,因为我可以理解它。如果它符合您的想象,请告诉我。

我重新创建了您的工作表:

enter image description here

进行此类转换时,您要做的第一件事就是将公式分解为正确的代码格式。我添加了ElseEnd if/conc行,以便让您的结束括号更容易理解:

声明1

----------------------------STATEMENT 1-----------------------------
IF(D2=D3,
    (IF(G2+H2+G3+H3=0,
        CONCATENATE("Batch ","'",C2,"'"," has no earnings/hours"),
    Else
        (CONCATENATE(
            IF(G2=0,
                "",
            Else
                CONCATENATE("paying ","'",F2,"'"," earnings ",G2)
            end if),
            IF(H2=0,
                "",
            Else
                IF(H2<>0,
                    IF(G2=0,
                        CONCATENATE("paying ","'",F2,"'"," hours ",H2),
                    Else
                        CONCATENATE(" and hours ",H2)
                    end if)
                end if)
            end if),
            IF(G3=0,
                "",
            Else
                CONCATENATE(" , paying ","'",F3,"'"," earnings ",G3)
            end if),
            IF(H3=0,
                "",
            Else
                IF(H3<>0,
                    IF(G3=0,
                        CONCATENATE(" , paying ","'",F3,"'"," hours ",H3),
                    Else
                        CONCATENATE(" and hours ",H3)
                    end if)
                end if)
            end if)
        end concatenate))
    end if))
    IF(D2<>D3,
        IF(G2+H2=0,
            CONCATENATE("Batch ","'",C2,"'"," has no earnings/hours"),
        Else
            CONCATENATE("Batch ","'",C2,"'",
                CONCATENATE(
                    IF(G2=0,
                        "",
                    Else
                        CONCATENATE(" paying ","'",F2,"'"," earnings ",G2)
                    end if),
                    IF(H2=0,
                        "",
                    Else
                        IF(G2=0,
                            CONCATENATE(" paying ","'",F2,"'"," hours ",H2),
                        Else
                            CONCATENATE(" and hours ",H2)
                        end if)
                    end if)
                end concatenate)
            end concatenate)
        end if)
    end if)
end if)

声明2

----------------------------STATEMENT 2-----------------------------
=IF(D2<>D3,
    I2,
Else
    IF(D2=D3,
        IF(AND(I2="Y",I3="Y"),
            "Y",
        Else
            IF(AND(I2="Y",I3="N"),
                "Y",
            Else
                IF(AND(I2="N",I3="Y"),
                    "Y",
                Else
                    IF(AND(I2="N",I3="N"),
                        "N"
                    end if)
                end if)
            end if)
        end if)
    end if)
end if)

使用这种易于阅读的格式,只需要使用正确的VBA词汇并进行一些清理

Sub CompareAndCompare()
    Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets(1)
    Dim A As Range, B As Range, C As Range, D As Range, E As Range, F As Range
    Dim compRange As Range: Set compRange = ws.Range("D2", ws.Cells(ws.Rows.Count, "D").End(xlUp))
    Dim state1 As String

    For Each A In compRange    'A = D2 on first iteration of the loop
        Set B = A.Offset(1)    'B = D3
        Set C = A.Offset(0, 3) 'C = G2
        Set D = A.Offset(0, 4) 'D = H2
        Set E = A.Offset(1, 3) 'E = G3
        Set F = A.Offset(1, 4) 'F = H3
        Set G = A.Offset(0, 5) 'G = I2
        Set H = A.Offset(1, 5) 'H = I3
        state1 = ""

        If A.Value = B.Value Then
            If G.Value = "N" And H.Value = "N" Then 'Statement 2
                ws.Range("K" & A.Row).Value = "N"
            Else: ws.Range("K" & A.Row).Value = "Y"
            End If

            If C.Value + D.Value + E.Value + F.Value = 0 Then
                state1 = "Batch '" & ws.Range("C" & A.Row).Value & "' has no earnings/hours"
            Else
                If C.Value <> 0 Then _
                    state1 = state1 & "paying '" & ws.Range("F" & A.Row).Value & "' earnings " & C.Value

                If D.Value <> 0 Then
                    If C.Value = 0 Then
                        state1 = state1 & "paying '" & ws.Range("F" & A.Row).Value & "' earnings " & D.Value
                    Else
                        state1 = state1 & " and hours " & D.Value
                    End If
                End If

                If E.Value <> 0 Then _
                    state1 = state1 & " , paying '" & ws.Range("F" & A.Offset(1).Row).Value & "' earnings " & E.Value

                If F.Value <> 0 Then
                    If E.Value = 0 Then
                        state1 = state1 & " , paying '" & ws.Range("F" & A.Offset(1).Row).Value & "' hours " & F.Value
                    Else
                        state1 = state1 & " and hours " & F.Value
                    End If
                End If
            End If
            B.EntireRow.Delete
        Else 'D2 <> D3
            ws.Range("K" & A.Row).Value = G.Value 'Statement 2

            If C.Value + D.Value = 0 Then
                state1 = "Batch '" & ws.Range("C" & A.Row).Value & "' has no earnings/hours"
            Else
                state1 = "Batch '" & ws.Range("C" & A.Row).Value & "'"
                If C.Value <> 0 Then _
                    state1 = state1 & " paying '" & ws.Range("F" & A.Row) & "' earnings " & C.Value

                If D.Value <> 0 Then
                    If C.Value = 0 Then
                        state1 = state1 & " paying '" & ws.Range("F" & A.Row) & "' hours " & D.Value
                    Else
                        state1 = state1 & " and hours " & D.Value
                    End If
                End If
            End If
        End If
        ws.Range("J" & A.Row).Value = state1
    Next A
End Sub

当我在工作表上运行此代码时,这是结果输出:

enter image description here

当D2:D3相同时,它删除了行,并继续通过该范围内的其余项目(这是动态的)。我没有在输出中更改您想要的语句。让我知道你的想法。