Data:
This is only a sample from the data I am using.
Please find the output below. "Output via Code" is the one we are getting when we run the code. "Expected Output" is the one we are looking for.
Data+Output
The first code and its modified versions which I have pasted earlier seems to be giving the result but the only problem is, it is leaving one or two similar values without joining them.
Original Message:
I have framed a "If Statement". This statement compares two rows and displays a comment in one of the columns. While the statement works perfectly in excel, the code recorded in VBE for the same do not. Please help.
Statement:
=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))))))))
I tried recording a macro for this statement, but I get a error when I execute the recorded code in my macro.
I would like to convert this statement into macro and run it as loop till end of last row.
I would like to compare a particular cell in Row 1 and Row 2, then execute above statement. Then compare values of two different cells in Row 1 and Row 2, paste the outcome in anther cell. Once these tasks are performed, delete the second row and run the loop for similar cell values, join the first comments with second comment. If next row value is different then not to delete the row and run the loop and so on till end of all rows.
Also, the second "if statement" isn't doing the job it is suppose to do.
Second If Statement:
=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"))))))
VBE Code for If Statement 1:
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
Code 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
Code 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
Code 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
Converting Formula to Macro
I recreated a raw version of the last picture you added:
Using the heavily modified code below
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
Will yield the following result:
Which looks similar to what you were wanting. I made some edit to the formatting to make it easier to read. Let me know what you think and if this works for you :)
Original Answer Below (May be useful in seeing how to convert EXCEL Formula into VBA Code)
I'm not sure I understand the scope of your question but this is the direct conversion as best as I could make sense of it. Let me know if it functions how you imagine it should.
I recreated your sheet:
The first thing you want to do when doing a conversion like this is to break your formula up into a proper code format. I included Else and End if/conc lines to make your end parentheses easier to follow:
STATEMENT 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)
STATEMENT 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)
With this easy to read format, it's just a matter of using proper VBA vocabulary and a little clean up
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
When I run this code on the sheet, this is the resulting output:
It deleted the rows when D2:D3 are the same, and continues through the rest of the items in that range (which is dynamic). I didn't change the statements you wanted on the output. Let me know what you think.