Delete Rows in specific columns based on values - excel

I got quite a specific task that im not getting quite right, wondering if anyone could help me out.
In my code, I have a big table that gets updated monthly amongst my team, what I want to do is find the column header titled "RD" and then delete all the rows within that column containing the value "Ad-Hoc" (apart from the column header)
Sub Delete_Rows_Based_On_Value()
Dim tbl As ListObject
Set tbl = ActiveSheet.ListObjects("Table_owssvr")
Dim I As Long, finalRow As Long, L As Long
For L = tbl.Columns.Count To 1 Step -1
If Cells(1, L) = "RD" Then
For I = finalRow To 2 Step -1
If Range(L, I).Value = "Ad-Hoc" Then
Range(L, I).EntireRow.Delete
End If
Next I
End If
Next L
End Sub
wonder if anyone could help me with this and whether im on the right track. thanks

Delete Rows in Table
This will delete table rows (not worksheet rows).
The Code
Option Explicit
Sub deleteRowsBasedOnValue()
With ThisWorkbook.Worksheets("Sheet1").ListObjects("Table_owssvr")
Dim cNum As Long: cNum = .ListColumns("RD").Index
Dim dRng As Range
Dim lr As ListRow
For Each lr In .ListRows
If lr.Range.Columns(cNum).Value = "Ad-Hoc" Then
buildRange dRng, lr.Range
End If
Next lr
End With
If Not dRng Is Nothing Then
dRng.Delete
End If
End Sub
Sub buildRange( _
ByRef BuiltRange As Range, _
AddRange As Range)
If BuiltRange Is Nothing Then
Set BuiltRange = AddRange
Else
Set BuiltRange = Union(BuiltRange, AddRange)
End If
End Sub

You're on the right track. You need to use tbl.ListColumns.Count listobjects don't have a columns property.
You need to assign finalRow a value, and you have your row and column swapped looking for "Ad-Hoc"
Dim tbl As ListObject
Set tbl = ActiveSheet.ListObjects("Table_owssvr")
Dim I As Long, finalRow As Long, L As Long
For L = tbl.ListColumns.Count To 1 Step -1 'tbl.columns will error
If Cells(1, L) = "RD" Then
finalRow = Cells(Rows.Count, L).End(xlUp).Row 'Get the last row in column L
For I = finalRow To 2 Step -1
If Cells(I, L).Value = "Ad-Hoc" Then 'L is the column it goes second
Cells(I, L).EntireRow.Delete
End If
Next I
End If
Next L
Using Autofilter
Sub delete_with_filter()
Dim tbl As ListObject
Dim delrange As Range
Set tbl = ActiveSheet.ListObjects("Table_owssvr")
With tbl
.Range.AutoFilter .ListColumns("RD").Index, "Ad-Hoc"
On Error GoTo errhandler
Set delrange = .DataBodyRange.SpecialCells(xlCellTypeVisible)
If Not delrange Is Nothing Then
Application.DisplayAlerts = False
delrange.Delete
Application.DisplayAlerts = True
End If
.Range.AutoFilter .ListColumns("RD").Index
End With
errhandler:
Select Case Err.Number
Case 1004
Debug.Print "Exiting Sub, No Cells Found"
tbl.Range.AutoFilter tbl.ListColumns("RD").Index
Exit Sub
End Select
End Sub

A lot answers, but I will throw this one in for short and quick. I tested and worked.
Sub DeleteTableRows()
Dim tbl As ListObject
Set tbl = ActiveSheet.ListObjects("Table_owssvr")
tbl.Range.AutoFilter Field:=tbl.ListColumns("RD").Index, Criteria1:="Ad-Hoc"
If tbl.Range.SpecialCells(xlCellTypeVisible).Count > tbl.ListColumns.Count Then
Application.DisplayAlerts = False
tbl.DataBodyRange.SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
End If
tbl.AutoFilter.ShowAllData
End Sub

Related

How to sort column2 only but separated by Space and Remove Duplicates

Thus anyone have idea on how to resolved this,
I have many Data to Sort, I want to Sort only Column 2 but separated by Space and also I want to delete duplicate values,
Is there any formula to fix this?
Please see Picture Below
I found this Answer on Google, And it Helps me to fix the Problem
Sub SortAndRemoveDuplicates()
Dim Rng As Range
Dim RngArea As Range
Dim sortRng As Range
Dim lr As Long
Dim i As Long
Dim startRow As Long
If Selection.Columns.Count > 1 Or Selection.Column <> 2 Then
MsgBox "Please select data in column B only and then try again...", vbExclamation
Exit Sub
End If
On Error Resume Next
Set Rng = Selection.SpecialCells(xlCellTypeConstants, 1)
On Error GoTo 0
If Rng Is Nothing Then Exit Sub
Application.ScreenUpdating = False
startRow = Selection.Cells(1).Row
lr = startRow + Selection.Rows.Count - 1
For Each RngArea In Rng.Areas
Set sortRng = RngArea.Resize(, 2)
sortRng.Sort key1:=sortRng.Cells(1), order1:=xlAscending, Header:=xlNo
Next RngArea
For i = lr To startRow Step -1
If Cells(i, 2) = Cells(i - 1, 2) Then
Rows(i).Delete
End If
Next i
Application.ScreenUpdating = True
End Sub

How to copy rows and paste them into a sheet given a cell value

I have data in a table, where I compare two columns J and T. The values which J and T can take include A2B, APL, BGF, CMA, among others (see code).
If these values are equal, copy row i into the sheet which has the name of the cells just checked.
If these values are not equal, copy row i into the sheets which have the name of the cells just checked.
Example: Compare J2 and T2,
Suppose J2=T2=BGF then copy row 2 and paste into sheet("BGF")
Next, compare J3 and T3
Suppose J3=BGF and T3=CMA, copy row 3 and paste into sheet(BGF) and sheet(CMA)
Next, compare J4 and T4
Suppose J4=Nothing and T4=CMA, copy row 4 and paste into sheet CMA
the only other combination is where Ji has a value and Ti is empty.
Problem: When running this code, If J3=BGF and T3= nothing (its empty), then the line is not copied to any sheet.
Here's the code
Sub Sortdata()
'step 1 clear all data
Sheets("A2B").Cells.ClearContents
Sheets("APL").Cells.ClearContents
Sheets("BGF").Cells.ClearContents
Sheets("CMA").Cells.ClearContents
Sheets("K Line").Cells.ClearContents
Sheets("MacAndrews").Cells.ClearContents
Sheets("Maersk").Cells.ClearContents
Sheets("OOCL").Cells.ClearContents
Sheets("OPDR").Cells.ClearContents
Sheets("Samskip").Cells.ClearContents
Sheets("Unifeeder").Cells.ClearContents
Dim i As Long
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim LastRow As Long
With Worksheets("All Data")
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = 2 To LastRow
If IsEmpty(.Range("J" & i)) Then
Set ws1 = Nothing
Else
Set ws1 = Worksheets(.Range("J" & i).Value)
End If
If IsEmpty(.Range("T" & i)) Then
Set ws2 = Nothing
Else
Set ws2 = Worksheets(.Range("T" & i).Value)
End If
If ws1 Is Nothing Then
If Not ws2 Is Nothing Then
CopyToWs ws2, .Rows(i)
End If
ElseIf ws2 Is Nothing Then
If Not ws1 Is Nothing Then
CopyToWs ws1, .Rows(i)
End If
Else
CopyToWs ws1, Rows(i)
If ws1.Name <> ws2.Name Then
CopyToWs ws2, .Rows(i)
End If
End If
Next
End With
End Sub
Sub CopyToWs(ws As Worksheet, rng As Range)
rng.Copy
ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(1, 0).EntireRow.PasteSpecial xlPasteValuesAndNumberFormats
End Sub
Please try this code. It takes a slightly different approach to what you tried but it gets the job done, I think.
Option Explicit
Sub Sortdata()
' Variatus #STO 20 Jan 2020
Const WsNames As String = "A2B,APL,BGF,CMA,K Line,MacAndrews," & _
"Maersk,OOCL,OPDR,Samskip,Unifeeder"
Dim WsS As Worksheet ' Source
Dim Ws As Worksheet
Dim Rng As Range
Dim Rt As Long ' target row
Dim LastRow As Long
Dim J As Long, T As Long
Dim Tmp As Variant, PrevTmp As Variant
Dim R As Long, C As Long
'step 1 clear all data
Tmp = Split(WsNames, ",")
For R = LBound(Tmp) To UBound(Tmp)
On Error Resume Next
Worksheets(Tmp(R)).Cells.ClearContents
Next R
Application.ScreenUpdating = False
Set WsS = Worksheets("All Data")
With WsS
J = .Columns("J").Column
T = .Columns("T").Column
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For R = 2 To LastRow
PrevTmp = ""
For C = J To T Step T - J
Tmp = .Cells(R, C).Value
If Len(Tmp) And Tmp <> PrevTmp Then
On Error Resume Next
Set Ws = Worksheets(Tmp)
If Err = 0 Then
Set Rng = .Range(.Cells(R, 1), .Cells(R, .Columns.Count).End(xlToLeft))
With Ws
Rt = Application.Max(.Cells(.Rows.Count, "A").End(xlUp).Row + 1, 2)
Rng.Copy Destination:=Ws.Cells(Rt, 1)
End With
End If
End If
PrevTmp = Tmp
Next C
If R Mod 25 = 0 Then Application.StatusBar = "Currently processing row " & R
Next R
End With
With Application
.ScreenUpdating = True
.StatusBar = "Done"
End With
End Sub
I think you will be able to find your way through it and make any required modifications. Let me know if you require any assistance.

How to delete rows that contains value "Invoiced" in whole worksheet

I have a lot of Excels from different modules with different column layouts (purchase orders, Sales orders, Production orders, etc.).
I want to delete every row that contains value "Invoiced".
I was able to create simple code where only one column ("J") is checked, but I need whole worksheet to be checked.
Private Sub BoomShakalaka_Click()
Application.ScreenUpdating = False
ow = Cells(Rows.Count, "J").End(xlUp).Row
For r = ow To 1 Step -1
If Cells(r, "J") = "Invoiced" Then Rows(r).Delete
Next
Application.ScreenUpdating = True
End Sub
I expect that after I run this function, it will check the whole workbook and delete every row which contains the value "Invoiced".
I want to add here my idea of using arrays instead, so you only access the worksheet when you read the data, and then when you delete the rows.
Option Explicit
Sub deleteInvoiced()
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
Dim wb As Workbook: Set wb = ActiveWorkbook 'or ThisWorkbook, or the name of the workbook where data is
Dim ws As Worksheet
Dim R As Long, C As Long, X As Long
Dim lRow As Long, lCol As Long
Dim arrData
For Each ws In wb.Worksheets
lRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).row 'Get the last row in the current sheet
lCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column 'Get the last column in the current sheet
arrData = ws.Range(ws.Cells(1, 1), ws.Cells(lRow, lCol))
For R = UBound(arrData) To LBound(arrData) Step -1
For C = UBound(arrData, 2) To LBound(arrData, 2) Step -1
If arrData(R, C) = "Invoiced" Or arrData(R, C) = "Delivered" Then
'Now delete the rows
ws.Cells(R, C).EntireRow.Delete
Exit For 'Exit here in case multiple "Invoice" or "Delivered" in the same row (WHY?!!). Thanks #Brian.
End If
Next C
Next R
Next ws
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
End Sub
PS: There is no error handling, but i leave that to you.
Loop through every cell within every row within activesheet.usedrange:
Private Sub BoomShakalaka_Click()
For r = ActiveSheet.UsedRange.Rows.Count To 1 Step -1
For Each c In ActiveSheet.UsedRange.Rows(r).Cells
If c.Value = "Invoiced" Then
c.EntireRow.Delete
Exit For
End If
Next c
Next r
End Sub
Alternatively, you could do it by using find. This will be faster than my other answer if there is a lot of data:
sub BoomShakalaka_Click()
screenupdating = false
On Error GoTo exitSub
ActiveSheet.UsedRange.SpecialCells(xlLastCell).select
do while true
Cells.Find(What:="Invoiced", After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False _
, SearchFormat:=False).Activate
Selection.EntireRow.Delete
Loop
exitSub:
screenupdating = True
Exit Sub
end sub
Here's another interesting way. It assumes your data starts in cell A1 and is contiguous.
Option Explicit
Public Sub TestDeleteInvoiced()
Dim wb As Workbook
Dim ws As Worksheet
Dim arr As Variant
Dim arr1() As Variant
Dim row As Long
Dim col As Long
Dim i As Long
Set wb = ActiveWorkbook
i = 1
ReDim arr1(1 To 14)
For Each ws In wb.Worksheets
arr = ws.Range("A1").CurrentRegion
For row = UBound(arr, 1) To LBound(arr, 1) Step -1
For col = UBound(arr, 2) To LBound(arr, 2) Step -1
If arr(row, col) = "Invoiced" Then
arr1(i) = row & ":" & row
i = i + 1
'This If statement ensures that the Join function is less than 255 characters.
If i = 15 Then
ws.Range(Join(arr1, ", ")).EntireRow.Delete
ReDim arr1(1 To 14)
i = 1
End If
Exit For
End If
Next col
Next row
ReDim Preserve arr1(1 To i - 1)
ws.Range(Join(arr1, ", ")).EntireRow.Delete
Next ws
End Sub
Note: Deleting a range of non-contiguous rows cannot exceed a 255 character parameter. Link

Fastest way to (auto)filter multiple criterias in Excel and delete non-matching rows?

I have the following code that I am using as a workaround instead of filtering the data as I have multiple criterias. I read somewhere that it is only possible to filter 2 criterias at a time?
The thing is that I have 5 - AB, DZ, RE, Z3, ZP - everything else should be deleted. So I am using the code below, which works fine, but having to deal with +30000 rows everytime I run the macro, it is extremely slow.
Is there anyway you can do this faster? I was thinking of just filtering each criteria at a time (creating 5 of the first of the below codes). But if there is anyway to do it faster, I would appreciate some help.
THE CODE I USE THAT IS SLOW:
' Step 13 - Filter and Delete All Except
' AB, DZ, RE, Z3, ZP in Column 6 - Type
Sub FilterDeleteType()
Dim rTable As Range, r As Range
Dim rDelete As Range
Set rDelete = Nothing
Dim v As Variant
Worksheets("Overdue Items").Activate
For Each r In Columns(6).Cells
v = r.Value
If v <> "Type" And v <> "AB" And v <> "DZ" And v <> "RE" And v <> "Z3" And v <> "ZP" Then
If rDelete Is Nothing Then
Set rDelete = r
Else
Set rDelete = Union(r, rDelete)
End If
End If
Next
If Not rDelete Is Nothing Then rDelete.EntireRow.Delete
End Sub
You can just look in hidden rows and check that column -
Sub test()
Dim lastrow As Integer
lastrow = Cells(Rows.Count, "A").End(xlUp).Row
Dim lastcol As Integer
lastcol = Cells(1, Columns.Count).End(xlToLeft).Column
'do your autofilter here
For i = 1 To lastrow
If Rows(i).Hidden = True Then
Range(Cells(i, 1), Cells(i, 5)).ClearContents
Range(Cells(i, 7), Cells(i, lastcol)).ClearContents
If Cells(i, 6) <> "AB" Or "DZ" Or "RE" Or "Z3" Or "ZP" Then
Cells(i, 6).ClearContents
End If
End If
Next
End Sub
So I managed to do exactly what my previous code was doing, just significantly faster. With the help from this post https://stackoverflow.com/a/22275522
What the code is doing is that it filter the values that I want (using an array), and then it will delete the hidden rows, meaning the rows that has NOT been filtered.
Sub FilterType()
Dim LRow As Long
Dim delRange As Range
Dim oRow As Range, rng As Range
Dim myRows As Range
Const Opt1 As String = "AB"
Const Opt2 As String = "DZ"
Const Opt3 As String = "RE"
Const Opt4 As String = "Z3"
Const Opt5 As String = "ZP"
On Error GoTo ErrHandler:
Sheets(1).Activate
With ThisWorkbook.Sheets(1)
'~~> Remove any filters
.AutoFilterMode = False
LRow = .Range("F" & .Rows.Count).End(xlUp).Row
With .Range("F1:F" & LRow)
.AutoFilter Field:=1, Criteria1:=Array(Opt1, Opt2, Opt3, Opt4, Opt5), Operator:=xlFilterValues
End With
With Sheets(1)
Set myRows = Intersect(.Range("F:F").EntireRow, .UsedRange)
If myRows Is Nothing Then Exit Sub
End With
For Each oRow In myRows.Columns(6).Cells
If oRow.EntireRow.Hidden Then
If rng Is Nothing Then
Set rng = oRow
Else
Set rng = Union(rng, oRow)
End If
End If
Next
ErrHandler:
'~~> Remove any filters
.AutoFilterMode = False
End With
If Not rng Is Nothing Then rng.EntireRow.Delete
End Sub

Chart Data Error

If my chart data only equals to one column it gives an error.
Sub RemoveHiddenColumns()
Dim myChart As Chart
Set myChart = Chart4
myChart.Activate 'first activate the chart
Dim i As Integer
For i = 1 To ActiveChart.SeriesCollection.Count 'loop through each series
Dim strText As String, strCol As String, strSht As String, intCol As Integer
strText = Split(ActiveChart.SeriesCollection(i).Formula, ",")(2) 'extract sheet name and column of series
strSht = Split(strText, "!")(0)
strCol = Split(strText, "!")(1) 'get column range of series
Dim wks As Worksheet
Set wks = Sheet2
If wks.Range(strCol).EntireColumn.Hidden = True Then 'if the column is hidden
ActiveChart.SeriesCollection(i).Delete 'remove the series
End If
Next
End Sub
This code successfully removes hidden ROWS from a table. I know that you want to remove columns, but I'm not sure entirely what you're going for so I didn't try and adapt it. You should be able to do that fairly easily.
Sub RhidRow2(ByVal count4 As Long)
Dim count1 As Long 'counters to be used
Dim ws As Worksheet
Dim rngVis As Range
Dim rngDel As Range
Set ws = ActiveSheet
On Error Resume Next
Set rngVis = ws.Range("A2:A" & count4).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rngVis Is Nothing Then
ws.Range("Z1").Value = 1
Else
For count1 = count4 To 2 Step -1
If ws.Rows(count1).Hidden = True Then
If rngDel Is Nothing Then
Set rngDel = ws.Rows(count1)
Else
Set rngDel = Union(rngDel, ws.Rows(count1))
End If
End If
Next count1
If Not rngDel Is Nothing Then
Application.DisplayAlerts = False
Intersect(rngDel, rngDel.ListObject.DataBodyRange).Delete 'if row is hidden, delete
Application.DisplayAlerts = True
End If
End If
End Sub

Resources