Remove lines IF AND THEN ELSEIF - vba

Everyone!
I have a heavy file with different values in A and D columns.
Now I want this script to complete the following operation:
If value in column A is "Option One" and "K" in column D, then remove this entire line.
Additionally Remove entire raw if value in column A is "Option Two" and "M" in column D
The following code performs this operation for 70% and I can't find the issue.
It always leaves behind some rows and to completely remove unwanted entries, I have to run this code twice.
Will appreciate your help! Thank You!
Sub RemoveSomeLines()
Dim RemoveRow As Long
RemoveRow = Cells(Rows.Count, "A").End(xlUp).Row
For y = 1 To RemoveRow
If Cells(y, "A").Value = "Option One" And _
Cells(y, "D").Value = "K" Then
Cells(y, "A").EntireRow.Delete
ElseIf Cells(y, "A").Value = "Option Two" And _
Cells(y, "D").Value = "M" Then
Cells(y, "A").EntireRow.Delete
End If
Next y
End Sub

Try going backwards:
For y = RemoveRow To 1 Step -1
It is probably skipping rows because you are removing a row, moving the next row up, and then skipping the row that was moved up on the next loop because y increments by 1.
It looks like this:
Remove row 20.
Entire sheet shifts upward.
Row 21 is now row 20.
y increments on the next loop to become 21.
The new row 20 was actually skipped entirely.
Alternatively, I think it would work if you decremented y by 1 when you removed a row, but it's less code changes just to work backward instead of forward.

Related

How to delete a row that contains a certain code in the first column using excel VBA?

I run a report weekly and a step I must take is to delete a row that contains a certain phrase, in my case "CFS-GHOST-DJKT", in column A. Rows to read through start at 7 and have a variable end.
I have looked online and according to what I have found the following code should work but I get and error and it does not like the line With Cells(Lrow,"A")
I believe as far as the deleteing part goes it is ok the way it is written but the problem is the selection aspect.
Firstrow = 7
Lastrow = Cells(Rows.Count, "A").End(xlUp).Row
With Cells(Lrow, "A")
If Not IsError(.Value) Then
If .Value = "CFS-GHOST-DJKT" Then .EntireRow.Delete
End If
End With
You need to iterate from the last row to the first row when deleting else you will end up skipping rows.
Dim x As Long
For x = Cells(Rows.Count, "A").End(xlUp).Row To 7 Step -1
If Cells(x, "A") = "CFS-GHOST-DJKT" Then Rows(x).Delete
Next
as per you narrative ("I must ... delete a row") you seem to bother only one occurrence of the phrase "CFS-GHOST-DJKT"
in this case there's no need for iterating through cells but just try finding it and, if successful, delete its entire row
Dim f As Range
Set f = Range("A7", Cells(Rows.Count, "A").End(xlUp)).Find(what:="CFS-GHOST-DJKT", LookIn:=xlValues, lookat:=xlPart)
If Not f Is Nothing Then f.EntireRow.Delete

Return Column Header of Colored Cells

This process is being used for QC purposes. I have a spreadsheet that highlights certain cells that are wrong based off of their values and the validation rules we have in place. I was wonder if there was a way to return the column names of each cell that is colored into column A for each row? So for example if D2, F2, and G2 are wrong it would put all of those column headers in A2 to specify what exactly is wrong. I know it gets a bit more complicated trying to automate stuff with cell colors and I am not experienced in VBA which I'm assuming this will need. Is this possible to do, if so what would be the proper route to take? The data runs from column A to column BS, and the row numbers may differ, so if it could run up to row 1,000 that would be great. Attached is what the data looks like that I am working with.
The red means something is wrong in that row, and the orange cell is the color indicating that it is a wrong value
Yes, it is possible to do. Here is some snippets of code I pulled together to help get you started.
Lastrow = Cells(Rows.count, "A").End(xlUp).Row 'Get last row
With ActiveSheet
Lastcol = .Cells(1, .Columns.count).End(xlToLeft).Column 'Get last col
End With
For x = 1 To Lastcol 'Iterate Col
For i = 1 To Lastrow 'Iterate Row
'if red....
If Cells(i, x).Selection.Interior.Color = 255 then
'Move name to Cell A and append off of old name(s).
Cells(i, "A") = Cells(i, "A") & ", " & Cells(i, x)
End If
Next i 'next row
Next x 'next col

VBA Look for Duplicate, then assesses another cells value

I initially asked a question below.
Basically I want VBA to look at Column L:L. If the cell=program, and the cell below does not equal lathe I want the row above to be deleted. If the cell doesn't equal program continue looking until the end of the data.
Realized I needed to look at the data different, as I was losing rows that I needed to stay.
New logic, which I think will still use some of the old program, but
it needed to be sorted using another column. I need the VBA to look at
column E:E. If the cell in the row below is a duplicate of the cell
above, then look at column L in that row to see if the cell says
Program. If so the cell below should be Lathe. If not lathe delete the
Program Row, If it is Lathe leave both rows. If the Cells in Column E
are not duplicates, continue looking. EX. If E5=E6, If not continue
looking. If yes Look at L5 to see if it say Program. If so look at L6
for Lathe. If not delete ROW5.
This I what I received that answered teh first question which I think will still get used
Dim rngCheck as Range
Dim rngCell as Range
Set rngCheck = Range("L1", "L" & Rows.Count - 1)
For each rngCell in rngCheck
If rngCell.value = "Program" And rngCell.offset(1,0).value <> "lathe" then
rngCell.offset(-1,0).EntireRow.Delete
End if
Next rngCell
This should do it
For i = ThisWorksheet.Cells.SpecialCells(xlCellTypeLastCell).Row to 2 step -1
' that row do you mean the duplicate or the original (I am using original)
If ThisWorksheet.Cells(i, 5) = ThisWorksheet.Cells(i-1, 5) and _
ThisWorksheet.Cells(i-1, 12) = "Program" and ThisWorksheet.Cells(i, 12) <> "Lathe"
ThisWorksheet.Rows(i-1).EntireRow.Delete
End If
Next i
When deleting it is best to iterate from last to first. If prevent you from skipping rows.
Sub RemoveRows()
Dim x As Long
With Worksheets("Sheet1")
For x = .Range("E" & .Rows.Count).End(xlUp).Row To 2 Step -1
If .Cells(x, "E").Value = .Cells(x - 1, "E").Value And Cells(x - 1, "L").Value = "Program" Then
.Rows(x).Delete
End If
Next
End With
End Sub

Deleting rows with duplicate info in columns

I'm writing a code that copies data from one sheet into another and I've got that function working fine. Now, I'm trying to code it to delete any rows that contain duplicate information based off that information's ID number in column F. Part of our process is to manually enter in column E when each row has been worked.
So my end goal is for the code to delete rows where column E is blank and column F is a duplicate. My code runs, but doesn't delete anything. I'm really hoping I'm just missing something ridiculously obvious.
For i = 1 To Range("f" & Rows.Count).End(xlUp).Row
If Cells(i, 5).Value = "" Then 'if column E is blank on row i
x = Cells(i, 6).Value
If Not IsError(Application.Match(x, "F:F", 0)) Then '& if that row is a duplicate
ActiveSheet.Range(x).EntireRow.Delete 'delete new duplicate row
End If
End If
Next i
Try it with,
For i = Range("f" & Rows.Count).End(xlUp).Row to 1 Step -1
If Cells(i, 5).Value = "" Then 'if column E is blank on row i
x = Cells(i, 6).Value
If Application.Countif(Columns(6), x) > 1 Then '& if that row is a duplicate
Rows(i).EntireRow.Delete 'delete new duplicate row
End If
End If
Next i
You were trying to delete the row number x, not i. Additionally, everything was going to be matched once.
So there are a couple of errors that need to be addressed in your code. First, if you are looping over a range and deleting rows, it's best to start from the bottom and work your way up. This prevents issues where your iterator is on a row, that row gets deleted, and the loop essentially skips the next row.
Next, you are looking for a Match in column F of x, which contains a value from Column F. So, it will always return a value (itself, at the very minimum). Maybe try using a COUNTIF and seeing if it's greater than 1 may be a better option?
Next, you populated the variable x with the value in Cells(i, 6), but then you try to use it as a range when deleting. Change your code to the following and see if it works:
For i = Range("f" & Rows.Count).End(xlUp).Row To 1 Step -1
If Cells(i, 5).Value = "" Then 'if column E is blank on row i
x = Cells(i, 6).Value
If Application.Countif(Columns(6), x) > 1 Then '& if that row is a duplicate
ActiveSheet.Rows(i).Delete 'delete new duplicate row
End If
End If
Next i
Why not use the .RemoveDuplicates method? It's faster than looping around. Here's a rough outline on its use:
With Range
.RemoveDuplicates Columns:=Array(6), Header:=xlYes
End With
Here's the msdn doc for the method, and another page with a more detailed implementation. They should clear up any questions you might have.

Program freezing and not working

I have written this VBA code that goes through a set of data and aligns specific rows of data together and deletes the rest. I have various columns labeled as below. Whenever "Billed" appears under the "M" column, my program records the order number associated with that row under "B". It then loops and while the order number under "B" is consistent, it moves the notes under "L" associated with "Completed" and copies it besides the column and the same under where "Billed" was found. In addition, when it also moves the date under column "D" for "Confirmed" associated with that same order number and again adds to the column beside the "Billed" row. The problem I am running into is that none of these rows appear in the same order and also there can be duplicates. If there's a duplicate like the one in second order number for "Confirmed" then the most recent one will be taken and copied over beside "Billed". Any help would be tremendously appreciated! Thanks a lot in advance. Here is an Example:-
B D L M
1.467334 4/22/2015 Confirmed
2.467334 4/17/2015 YES Tech swapped out the MGR 13, tested Completed
3.467334 4/20/2015 4/16 Maint. Billed Billed
4.537551 4/15/2015 Confirmed
5.537551 4/14/2015 YES Tech swapped out the MGR 13, tested Confirmed
6.537551 4/08/2015 4/16 Maint. Billed Billed
7.537551 4/14/2015 YES Tech swapped out equipment Completed
8.537551 4/08/2015 4/16 Maint. equip. Confirmed
Required Output:-
B D L M Q R
3.467334 4/20/2015 4/16 Maint. Billed Billed YES swapped out theMGR 13, tested 4/22/2015
6.537551 4/16/2015 4/16 Maint. Billed Billed YES Tech swapped out equipment 4/14/2015
Here is my code:
Sub Test()
Dim LR As Long
Dim Rng As Range
Dim i As Long
Dim r As Long
Dim com As Range
LR = Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To LR Step 1
''''This might be confusing but what I am doing here is copying the notes for the "Billed" row and moving to the right.
'This part works fine but the rest of the "Do While" loop doesn't.
If Cells(i, "M").Value = "Billed" Then
Cells(i, "Q").Value = Cells(i, 12).Value
Set com = Cells(i, "B")
Set num = Cells(i, "B").Row
Do While Cells(i, "B").Value = com
If Cells(i, "M") = "Completed" Then
Cells(num, "R").Value = Cells(i, 12).Value
End If
Loop
Do While Cells(i, "B").Value = com
If Cells(i, "M") = "Confirmed" Then
Cells(num, "S").Value = Cells(i, 4).Value
End If
Loop
End If
Next i
Your issue is here:
Do While Cells(i, "B").Value = com
If Cells(i, "M") = "Completed" Then
Cells(num, "R").Value = Cells(i, 12).Value
End If
Loop
Do While Cells(i, "B").Value = com will always be true, because neither i nor com are changing inside your loop. In some way shape or form, you need to adjust the value of one of those two variables within that loop. I believe that a simple i = i + 1 will do what you're after, like this:
Do While Cells(i, "B").Value = com
If Cells(i, "M") = "Completed" Then
Cells(num, "R").Value = Cells(i, 12).Value
End If
i = i + 1
Loop
Just realized that won't work, since i is the counter in your For...Next loop. Instead, try this:
r = i
Do While Cells(r, "B").Value = com
If Cells(r, "M") = "Completed" Then
Cells(num, "R").Value = Cells(r, 12).Value
End If
r = r + 1
Loop
You've declared r, but never used it, so I usurped it for this loop.
The same holds true for your next Do While...Loop block.
A couple of additional thoughts:
You're mixing reference between Cells(i, "M") and Cells(i, 12). While the compiler doesn't care and can easily interpret that, it's harder for us people types to figure out what column is being referenced - is M the 12th letter? No, it's the 13th, so that mean... oh, Column L!
Use consistent block indention - that also makes your code much easier to read and mentally parse. Again, the compiler doesn't care, but you, or the person maintaining the code after you, will appreciate it.
You mention that there's an issue with duplicate order numbers. I'm not seeing that unless the 1., 2., etc are indicating line numbers instead of decimal values. If this is the case, I'd suggest having your code sort the data in an order that makes sense for your purposes, then have your code written in that sorted order. That way, you can expressly handle the duplicate values - for example if OrderNum(row) = OrderNum(row-1) then and check the dates to pick up the newest one.