I am new to VBA and I have written the below code that is supposed to compare dates in two columns, and take which ever date is greater and display it on a Worksheet called PPDCI. If there is no dates, or dates are equal then it will display that record on another worksheet called "Error" and "REVIEW PPD DATA".
The program seems to work fine for the first two IF conditions for variables PPD_1_Date and PPD_2_Date that output data to the PPDCI worksheet, however the results on the Error tab are not what I am expecting. It seems to be including blank rows (rows that I believe are on the PPDCI tab with data), rows that only contain the cell with "REVIEW PPD DATA" (ID, Name information missing), and rows that just have data in columns A - C (sourced from the "Data" worksheets columns F - H).
I tried changing the code (commented out below) to include a condition for if the two date fields are empty then GoTo EmptyRange, just prior to iterating the Next i. This producted a runtime error though, even though it works on several other functions in my module
Function PPDdate()
Dim PPD_1_Date As Date
Dim PPD_2_Date As Date
Dim i As Long, j As Long, k As Long
j = Worksheets("PPDCI").Range("A" & Rows.Count).End(xlUp).Row + 1
k = Worksheets("Error").Range("A" & Rows.Count).End(xlUp).Row + 1
For i = 2 To lstrow
PPD_1_Date = Worksheets("Data").Range("AW" & i)
PPD_2_Date = Worksheets("Data").Range("BA" & i)
If PPD_1_Date > PPD_2_Date Then
Worksheets("PPDCI").Range("A" & j & ":C" & j).Value =
Worksheets("Data").Range("F" & i & ":H" & i).Value
Worksheets("PPDCI").Range("F" & j).Value = PPD_1_Date
j = j + 1
Else
If PPD_1_Date < PPD_2_Date Then
Worksheets("PPDCI").Range("A" & j & ":C" & j).Value =
Worksheets("Data").Range("F" & i & ":H" & i).Value
Worksheets("PPDCI").Range("F" & j).Value = PPD_2_Date
Worksheets("PPDCI").Range("G" & j).Value = "ELSE IF CONDITION"
j = j + 1
Else
'If IsEmpty(Worksheets("Data").Range(PPD_1_Date & i).Value) = True And
IsEmpty(Worksheets("Data").Range(PPD_2_Date & i).Value) = True Then
'GoTo EmptyRange
'Else
Worksheets("Error").Range("A" & k & ":C" & k).Value =
Worksheets("Data").Range("F" & i & ":H" & i).Value
Worksheets("Error").Range("F" & j).Value = "REVIEW PPD DATA"
k = k + 1
'End If
End If
End If
EmptyRange:
'k = k + 1
Next i
End Function
I would expect all the rows that qualify for the final Else statement to be grouped together and not missing any of the cells. Should I be incrementing k (k = k+1) somewhere else in the code? Any feedback is appreciated!
Related
I have id numbers on column A starts from A3 To A25. I want to check each of the column A value with the F G H I columns values. In F G H I columns where data starts from 29th-row, how do check with A column value with multiple columns values at a time?
lastrow = Range("A" & Rows.Count).End(xlUp).Row
lastrow1 = Range("F" & Rows.Count).End(xlUp).Row
For i = 3 To lastrow
For j = 30 To lastrow1
If Range("F" & j).Value = Range("A" & i).Value Or Range("G" & j).Value = Range("A" & i).Value Or Range("H" & j).Value = Range("A" & i).Value Or Range("I" & j).Value = Range("A" & i).Value Then
End if
Next j
Next i
use below code. i have tested on your query
Please test it if any problem, feel free to contact.
Function allvlookup(rng As Range, rng1 As Range)
Dim rng_r As Range
Dim str As String
For Each rng_r In rng1
If rng = rng_r Then
result = rng_r.Value
End If
Next rng_r
allvlookup = result
End Function
I am having two sht, sht1 as BW and sht2 as result.
I want to Count the number of 1's in column T and U of sht1, according to the week in column AX and print the Counted values in the result sheet, looking into the same week.
I took the advice of an expert in the Forum and completed till this.
I want an if condition, in such a way that, if the column AA is empty, then i should not Count the 1's in column T and U, it should be skipped.
I introduced this code of line in my existing code after j=2; and got an error
error Label not defined`,
If ws.Range("AA" & i) = "" Then
GoTo nextrow
could someone help, how i should execute this condition ?
here is my code;
Sub results()
Dim i As Integer, j As Integer, cntT As Integer, cntu As Integer, ws As Worksheet
Set ws = Sheets("Result")
Sheets("BW").Select
For i = 2 To WorksheetFunction.CountA(ws.Columns(1))
cntT = 0
cntu = 0
If ws.Range("A" & i) = Val(Format(Now, "ww")) Then Exit For
Next i
For j = 2 To WorksheetFunction.CountA(Columns(50))
If ws.Range("A" & i) = Range("AX" & j) And Range("T" & j) = 1 Then cntT = cntT + 1
If ws.Range("A" & i) = Range("AX" & j) And Range("U" & j) = 1 Then cntu = cntu + 1
Next j
If cntT <> 0 Then ws.Range("B" & i) = cntT
If cntu <> 0 Then ws.Range("C" & i) = cntu
If cntT + cntu <> 0 Then
ws.Range("D" & i) = cntT + cntu
ws.Range("E" & i) = cntT / (cntT + cntu)
ws.Range("F" & i) = cntu / (cntT + cntu)
End If
ws.Range("E" & i & ":F" & i).NumberFormat = "0%"
End Sub
The GoTo nextrow is looking for a line label titled nextrow. That's how the GoTo command is built and operates. For what you are trying to accomplish, try this instead:
If ws.Range("AA" & i) <> "" Then
If ws.Range("A" & i) = Range("AX" & j) And Range("T" & j) = 1 Then cntT = cntT + 1
If ws.Range("A" & i) = Range("AX" & j) And Range("U" & j) = 1 Then cntu = cntu + 1
End If
This way it says, if the column is NOT blank, then do stuff, otherwise go to next j
If you want to use the GoTo Command in the future you can use line numbers (like GoTo 0 which should take you back to the beginning of the code) or you can create a line label by placing nextrow: on an empty line. Then when you call GoTo nextrow it will go to that line, and proceed from there.
I am working on this code that compares column A ( code source) and column B( code roc) and for each code source in column A it has his code regate in column C and address in column D so if A=B copy them back in E and F with their code regate in column G and their address in column H .
this the code I am using it blocks until I shut down excel and it doesn't give me the exact results if anyone can help me thank you
here is a picture of the result that i need from A and B , C and D
Sub copy_lignes()
Dim DerLigA, DerLigB As Long, i, j As Long
DerLigA = Sheets("sheet3").Range("A" & Rows.Count).End(xlUp).Row
DerLigB = Sheets("sheet3").Range("B" & Rows.Count).End(xlUp).Row
For i = 2 To DerLigA
For j = 2 To DerLigB
If Sheets("sheet3").Range("A" & i) = Sheets("sheet3").Range("B" & j) Then
Sheets("sheet3").Range("A" & i).Copy Destination:=Sheets("sheet3").Range("E" & i)
Sheets("sheet3").Range("B" & i).Copy Destination:=Sheets("sheet3").Range("F" & i)
Sheets("sheet3").Range("C" & i).Copy Destination:=Sheets("sheet3").Range("G" & i)
Sheets("sheet3").Range("D" & i).Copy Destination:=Sheets("sheet3").Range("H" & i)
End If
Next j
Next i
End Sub
Try the code below, maybe this is what you meant in your post:
Sub copy_lignes()
Dim DerLigA, DerLigB As Long, i, j As Long
Dim PasteRow As Long
' optimize speed performance
Application.ScreenUpdating = False
With Sheets("Sheet3")
DerLigA = .Cells(.Rows.Count, "A").End(xlUp).Row
DerLigB = .Cells(.Rows.Count, "B").End(xlUp).Row
PasteRow = 2
For i = 2 To DerLigA
For j = 2 To DerLigB
If .Range("A" & i) = .Range("B" & j) Then
.Range("A" & i).Copy Destination:=.Range("E" & PasteRow)
.Range("B" & j & ":D" & j).Copy Destination:=.Range("F" & PasteRow)
PasteRow = PasteRow + 1
End If
Next j
Next i
End With
' restore settings
Application.ScreenUpdating = True
End Sub
It might be that you just need to tab in a few lines, so it should look like this:
Sub copy_lignes()
Dim DerLigA As Long
Dim DerLigB As Long
Dim i As Integer
Dim j As Integer
i = 2
j = 2
DerLigA = Sheets("sheet3").Range("A" & Rows.Count).End(xlUp).Row
DerLigB = Sheets("sheet3").Range("B" & Rows.Count).End(xlUp).Row
For i To DerLigA
For j To DerLigB
If Sheets("sheet3").Range("A" & i) = Sheets("sheet3").Range("B" & j) Then
Sheets("sheet3").Range("A" & i).Copy Destination:=Sheets("sheet3").Range("E" & i)
Sheets("sheet3").Range("B" & i).Copy Destination:=Sheets("sheet3").Range("F" & i)
Sheets("sheet3").Range("C" & i).Copy Destination:=Sheets("sheet3").Range("G" & i)
Sheets("sheet3").Range("D" & i).Copy Destination:=Sheets("sheet3").Range("H" & i)
End If
Next j
Next i
End Sub
I'm trying to create a macro that will group data by month: for example, if there are 3 entries for February for client A, then it will consolidate the three entries into one and sum the amounts.
I have:
A: Client name
B: Invoice number
C: Billing month
D: Currency
E: Charge amount
F: Invoice step
What I am trying to do, is group the following into a single row, with the invoice amounts added up, and replace the three rows with just the one row. These entries are for a single client (so the grouping depends on the value in column A).
EG. Client A has three entries for Jan, Client B has one, Client C has one. Then for February Client A has one, Client B has one and Client C has two.
Any macro suggestions I've seen on here haven't been helpful to me, I keep getting errors coming up so I don't know what the problem is. This is the one I tried:
Sub Group()
Dim e As Range, a as Range
Set e = Range("C6")
Set c = e.Offset(, 2)
Do
If Evaluate("=month(" & e.Address & ")") <> Evaluate("=month(" & e(2).Address & ")") Then
e(2).Resize(2, 3).Insert
e(2).Offset(, 2) = "=sum(" & Range(a, c.Offset(, 2)).Address & ")"
e(2).Offset(, 2).Font.Bold = 1
Set e = e.End(4)
Set c = e.Offset(, 2)
Else
Set e = e(2)
End If
Loop Until e.End(4).Row = Rows.Count
e(2).Offset(, 2) = "=sum(" & Range(c, e.Offset(, 2)).Address & ")"
e(2).Offset(, 2).Font.Bold = 1
End Sub
EDIT: Subtotals and pivot tables would not work - the raw data is pasted in (thousands of lines of entry, for 40+ clients and some have many invoices each month), the raw data is sorted using a macro, which is then pasted into other sheets. Pasting from the pivot would be more difficult.
I follow your image to write the code:
After the code:
Here is the code:
Sub TEST()
Dim lastrow As Long
lastrow = Range("A" & Rows.Count).End(xlUp).Row
For i = 6 To lastrow
lastrow = Range("A" & Rows.Count).End(xlUp).Row
For j = i + 1 To lastrow
If Range("A" & j) = Range("A" & i) And Range("C" & j) = Range("C" & i) Then
Range("B" & i) = Range("B" & i) & "," & " " & Range("B" & j)
Range("E" & i) = Range("E" & i).Value + Range("E" & j).Value
Rows(j).EntireRow.Delete
End If
Next j
Next i
End Sub
I have some code which is designed to scan Columns F & G for occurrences of words found in an array, the array containing text found in Column J. If it finds occurrences in either Column F or Column G, it will copy and paste the terms into the corresponding columns.
Column J contains free text from a field in SAP. The field is free text so it could be "Kerry John Pub Expenses" or "CATS O/H Kerry John", or even "CATS John Kerry O/H". There is no data entry standard for this field; this is what makes this task difficult .
Column F and Column G contains first names and last names. The code makes an assumption, if it finds an entry in column F or G that matches an entry in the txt array, it will copy and paste that entry.
During testing, the code proved not sufficient to match the outcomes which I was looking for, and the solution to this problem would be to match text in Columns F and G concurrently for two matching words rather than doing them in separate intervals.
I would like some suggestions as to how this code could be re-written to achieve this result.
Example of successful code run
Here we have 4 rows of data, John Citizen is located in Row 3, therefore the blank cells in Columns F and G, Row 2 can be populated with his first and last name.
The problem
Because I have two rows that contain Kerry Citizen and John Kerry, the row is populated with Kerry Kerry as a result, where the entry should be "John" in Column F and "Kerry" in Column G
Code starts here
Sub arraycolumnmatch()
Dim txtArray As Variant, T As Variant
Dim I As Long, J As Long
For I = 2 To Range("E50000").End(xlUp).row
typ = Range("F" & I).Value
If typ = "" Then
txt = Range("J" & I).Value
txtArray = Split(txt, " ")
For Each T In txtArray
For J = 2 To Range("F50000").End(xlUp).row
If Range("F" & J).Value = T Then
match_txt = T
Range("F" & I).Value = match_txt
End If
Next J
Next T
For Each T In txtArray
For J = 2 To Range("G50000").End(xlUp).row
If Range("G" & J).Value = T Then
match_txt = T
Range("G" & I).Value = match_txt
End If
Next J
Next T
End If
Next I
End Sub
You can simplify your code greatly, and make it work, like this:
typ = Range("F" & I).Value
If typ = "" Then
txt = Range("J" & I).Value
matchFound = False
For J = 2 To Range("G50000").End(xlUp).Row
If InStr(txt, Range("F" & J).Value) <> 0 _
And InStr(txt, Range("G" & J).Value) _
And Not (IsEmpty(Range("F" & J).Value)) _
And Not (IsEmpty(Range("G" & J).Value)) Then
'Both names match. Copy them.
Range("F" & I).Value = Range("F" & J).Value
Range("G" & I).Value = Range("G" & J).Value
matchFound = True
Exit For ' look no further.
End If
Next J
If Not matchFound Then MsgBox "No match found for: " & txt
End If
Tested, works for me.
The Code below runs for every first name on the list but only adds the name if both names match.
Sub arraycolumnmatch()
Dim txtArray As Variant, t As Variant
Dim I As Long, J As Long
For I = 2 To Range("G50000").End(xlUp).Row
typ = Range("F" & I).Value
If typ = "" And Not Range("J" & I).Value = Empty Then
txt = Range("J" & I).Value
txtArray = Split(txt, " ")
For Each word In txtArray
If Not word = "" Then
Set findtext = Range("F:F").Find _
(what:=(word), LookIn:=xlValues)
stoploop = False
loopcnt = 0
Do While Not findtext Is Nothing And stoploop = False And loopcnt < 21
loopcnt = loopcnt + 1
If InStr(txt, Range("F" & findtext.Row).Value) <> 0 _
And InStr(txt, Range("G" & findtext.Row).Value) Then
'Both names match. Copy them.
Range("F" & I).Value = Range("F" & findtext.Row).Value
Range("G" & I).Value = Range("G" & findtext.Row).Value
stoploop = True
Exit For ' look no further.
Else
Set findtext = Range("F" & findtext.Row & ":F" & 50000).Find _
(what:=(word), LookIn:=xlValues)
End If
Loop
End If
Next word
If Not stoploop Then MsgBox "No match found for: " & txt
End If
Next I
End Sub
Edit: Did an integration of #Jean InStr and a Find in Range which would allow for less loop time and a double match find.
I have had to stick with my original syntax, answer is below. Not the most efficient way of reaching the result, but it works
Sub arraycolumnmatch()
Dim txtArray As Variant, T As Variant
Dim I As Long, J As Long
For I = 2 To Range("E50000").End(xlUp).row
typ = Range("F" & I).Value
If typ = "" Then
txt = Range("J" & I).Value
txtArray = Split(txt, " ")
For Each T In txtArray
For J = 2 To Range("G50000").End(xlUp).row
If Range("G" & J).Value = T Then
match_txt = T
Range("G" & I).Value = match_txt
Exit For
End If
Next J
Next T
For Each T In txtArray
For J = 2 To Range("F50000").End(xlUp).row
If Range("F" & J).Value = T Then
match_txt = T
If Not Range("G" & I).Value = T Then
Range("F" & I).Value = match_txt
Exit For
End If
End If
Next J
Next T
End If
Next I