How do I write a loop in VBA that will delete a row if a cell in a range and the cell next to it both equal a constant? - vba

[This is in Excel 2007]
In other words, the loop will cycle through all the active cells in a one-column range (rngAddressName) and, if the cell in the range AND the cell directly to the left of it contain the string "#N/A", then it will delete that row.
Unfortunately, nothing I have tried has had any actual effect. Here is my best go at it:
i = 1
For counter = 1 To rngSC2A.Rows.Count
Contents = rngSC2A.Cells(i).Value
If Contents = "#N/A" Then
If rngAddressName.Cells(i).CellOffset(0, -1).Value = "#N/A" Then
rngAddressName.Cells(i).EntireRow.Delete
Else
End If
Else
i = i + 1
End If
Next
But this doesn't seem to find any rows with the conditions satisfied (even though such rows exist in the worksheet).
I think it might have something to do with the fact that I am looking in the Cell.Value, but I am not sure.

You can autofilter your range, delete any rows that meet your criteria, then turn the autofilter off. This is a much more efficient approach than looping.
The example below works on columns A and B in Sheet1. Modify the variables to reference the range and sheet in your workbook.
Sub DeleteDoubleNA()
Dim ws As Worksheet
Dim rng As Range
Dim lastRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
lastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
Set rng = ws.Range("A1:B" & lastRow)
' filter and delete all but header row
With rng
.AutoFilter field:=1, Criteria1:="#N/A"
.AutoFilter field:=2, Criteria1:="#N/A"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
' turn off the filters
ws.AutoFilterMode = False
End Sub

This is a different take on on the excellent answer posted by #Jon Crowell.
If you use an Excel table, you can use the table's ListObject to get the data range which automatically excludes the header and footer rows.
This avoids the sometimes incorrect calculation search for a last row.
You also want to clear any pre-existing filters on the data so that you don't overlook any rows.
Dim myTable As Object
Set myTable = ActiveSheet.ListObjects(1) ' Works if worksheet contains only one table
' Clear pre-existing filters on the table
myTable.AutoFilter.ShowAllData
' Filter the table
With myTable.DataBodyRange
.AutoFilter field:=1, Criteria1:="#N/A"
.AutoFilter field:=2, Criteria1:="#N/A"
End With
' Delete visible cells in the filtered table
myTable.DataBodyRange.SpecialCells(xlCellTypeVisible).EntireRow.Delete
' Clear filters on the table
myTable.AutoFilter.ShowAllData
The (1) in ListObjects(1) is the first (in my case only) table in the worksheet. DataBodyRange refers to the data range of that table excluding header and footer rows.

Related

Get count of filtered rows and paste result in column

I have a worksheet with addresses and associated information including the state. I want to filter the worksheet by state and count the number of filtered rows, pasting that number of rows next to the state abbreviation in the adjoining column:
StateIN RCount
I can get the code to autofilter and list all the states used in the worksheet, but am having trouble figuring out how to tell Excel that I want it to give me the number of filtered rows (minus the header row) for each state listed. I have tried several things, but this is essentially the code I am using:
'filter and copy individual state data from vqueue worksheet to state worksheet
Application.ScreenUpdating = False
Dim x As Range
Dim rng As Range
Dim lastRow As Long
Dim sht As String
Dim LR As Long
LR = Range("A" & Rows.Count).End(xlUp).Row
'specify sheet name in which the data is stored
sht = "vqueue"
'change filter column in the following code
lastRow = Sheets(sht).Cells(Rows.Count, "J").End(xlUp).Row
Set rng = Sheets(sht).Range("A1:AC" & lastRow)
Sheets(sht).Range("J1:J" & lastRow).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("AD1"), Unique:=True
For Each x In Range([AD2], Cells(Rows.Count, "AD").End(xlUp))
With rng
.AutoFilter
.AutoFilter Field:=10, Criteria1:=x.Value
Range("AE" & x).Value = ws.AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Cells.Count
.SpecialCells(xlCellTypeVisible).Copy
Sheets.Add(After:=Sheets(Sheets.Count)).Name = x.Value
ActiveSheet.Paste
End With
Next x
I'm not entirely sure I even have it placed in the right location in the for/with loop. Currently, I am getting a 424 Object required error. Thanks in advance for any help!
Considering that you just need to count the number os records that match a certain criteria, I would suggest using just formulas to handle with this case instead of VBA. You could use either COUNTIF or COUNTIFS functions. If you are using the most recent versions of Excel, you also have a FILTER function that could be used to generate the list of states dynamically based on specified criteria, and then use one of the count functions to obtain the record count.

Copying several filtered columns' worth of non blank cells to second sheet

I have a table that I need to autofilter itself according to criteria in column "AS", then copy multiple discrete columns' worth of resulting non-blank cells to specific cells in the next sheet.
What is the most efficient way of doing this? I'm aware that I may have to copy/paste specialvalues instead of direct reference
I'm not entirely sure what you're asking. But, imagine Column A is filled with names of fruits and Column B is filled with numbers. The following code filters Column A with the criteria "Apples" and copies the corresponding numbers to a new worksheet. This might start you off on the right track.
Sub selectApples()
' Find last row in column A
Dim LastRow As Integer
LastRow = Cells(Rows.Count, 1).End(xlUp).Row
' Select data in column A and filter
Range("A1:A" & LastRow).Select
Selection.AutoFilter Field:=1, Criteria1:="Apples"
'Find new last row
Dim newLastRow As Integer
newLastRow = Cells(Rows.Count, 1).End(xlUp).Row
'Copy and paste special into new worksheet
Range("B2:B" & newLastRow).Select
Selection.Copy
Sheets.Add After:=ActiveSheet
Selection.PasteSpecial Paste:=xlPasteValues
End Sub

Selecting range without knowing number of rows or columns having data in Excel/VBA

I am looking for code for two different types of selection. One code would select in an L shape all of the rows in one column and all of the columns in one row. In the example of having data in the range A1:A10, and data in row 10 only from col A - K. The selection would look like an L. How can you do this without knowing how many rows or columns have data in them?
The second code would have the same data, but need to select the whole range A1:K10 in that example, but the code would need to select whatever range had the data.
i found the answer. i have to do a union. here is the code with the union at the end.
Sub mywork()
Dim ws As Worksheet
Dim lRow As Long, lCol As Long
Dim rng As Range
'~~> Set this to the relevant worksheet
Set ws = [Sheet1]
With ws
'~~> Get the last row and last column
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
lCol = .Cells(lRow, .Columns.Count).End(xlToLeft).Column
'~~> Set the range
Set rng = .Range(.Cells(lRow, 1), .Cells(lRow, lCol))
End With
Set rng = Application.Union(Range("A1:A" & lRow), rng)
rng.Select
End Sub
activesheet.usedrange.address should tell you the used range.
In your case something like this should work: [sheet1].usedrange.select (Replaces all the code in the module)
The benefit here is the fact that you are not hard coding "A1:A" against the last identified cell, works well if you have blank rows at the top.

Filter a column and select the last used row

I want to filter a particular column in Excel sheet and then select the range of it until the last used row.
For getting a particular column I am using
ActiveSheet.Range("$A$1:$D30").AutoFilter Field:=3 , Criteria1:= "1"
And for finding the last row I am using
Cells(ActiveSheet.Rows.Count,1).End(xlUp).Row
I am not able to combine both together. If I run both the commands together, I am getting the entire results instead of filtered results.
I know it may be a simple one, But I am not able to do it. Can anybody help me in doing it?
My requirement is that the first the column should be filtered and then the range of until the last unused row should be selected. So that I can do some commands using the selection.
Try this:
With Range("A1:D" & Range("a1048576").End(xlUp).Row)
.AutoFilter Field:=3, Criteria1:="1"
.Resize(, 1).Offset(1).SpecialCells(xlCellTypeVisible).Select
End With
Use the SpecialCells Method with the xlCellTypeVisible argument. I also qualified the worksheet to work with, since it's way more stable than using ActiveSheet (should always be avoided, unless absolutely necessary.)
Dim ws as Worksheet
Set ws = Sheets("mySheet") 'change to the sheet name you need
Dim lRow as Long
lRow = ws.Cells(ws.Rows.Count,1).End(xlUp).Row
ws.Range("$A$1:$D" & lRow).AutoFilter Field:=3 , Criteria1:= "1"
Dim rRng as Range, cel as Range
Set rRng = ws.Range("A2:A" & lRow).SpecialCells(xlCellTypeVisible) 'assumes header row in column 1
'Updated code based on your comments.
For each cel in rRng
objRecipients.Add cel
Next
ws.AutoFilterMode = False

How to delete row based on cell value

I have a worksheet, I need to delete rows based on cell value ..
Cells to check are in Column A ..
If cell contains "-" .. Delete Row
I can't find a way to do this .. I open a workbook, copy all contents to another workbook, then delete entire rows and columns, but there are specific rows that has to be removed based on cell value.
Need Help Here.
UPDATE
Sample of Data I have
The easiest way to do this would be to use a filter.
You can either filter for any cells in column A that don't have a "-" and copy / paste, or (my more preferred method) filter for all cells that do have a "-" and then select all and delete - Once you remove the filter, you're left with what you need.
Hope this helps.
The screenshot was very helpful - the following code will do the job (assuming data is located in column A starting A1):
Sub RemoveRows()
Dim i As Long
i = 1
Do While i <= ThisWorkbook.ActiveSheet.Range("A1").CurrentRegion.Rows.Count
If InStr(1, ThisWorkbook.ActiveSheet.Cells(i, 1).Text, "-", vbTextCompare) > 0 Then
ThisWorkbook.ActiveSheet.Cells(i, 1).EntireRow.Delete
Else
i = i + 1
End If
Loop
End Sub
Sample file is shared: https://www.dropbox.com/s/2vhq6vw7ov7ssya/RemoweDashRows.xlsm
You could copy down a formula like the following in a new column...
=IF(ISNUMBER(FIND("-",A1)),1,0)
... then sort on that column, highlight all the rows where the value is 1 and delete them.
if you want to delete rows based on some specific cell value.
let suppose we have a file containing 10000 rows, and a fields having value of NULL.
and based on that null value want to delete all those rows and records.
here are some simple tip.
First open up Find Replace dialog, and on Replace tab, make all those cell containing NULL values with Blank.
then press F5 and select the Blank option, now right click on the active sheet, and select delete, then option for Entire row.
it will delete all those rows based on cell value of containing word NULL.
If you're file isn't too big you can always sort by the column that has the - and once they're all together just highlight and delete. Then re-sort back to what you want.
You can loop through each the cells in your range and use the InStr function to check if a cell contains a string, in your case; a hyphen.
Sub DeleteRowsWithHyphen()
Dim rng As Range
For Each rng In Range("A2:A10") 'Range of values to loop through
If InStr(1, rng.Value, "-") > 0 Then 'InStr returns an integer of the position, if above 0 - It contains the string
rng.Delete
End If
Next rng
End Sub
This is the autofilter macro you could base a function off of:
Selection.AutoFilter
ActiveSheet.Range("$A$1:$A$10").AutoFilter Field:=1, Criteria1:="=*-*", Operator:=xlAnd
Selection.AutoFilter
I use this autofilter function to delete matching rows:
Public Sub FindDelete(sCol As String, vSearch As Variant)
'Simple find and Delete
Dim lLastRow As Integer
Dim rng As Range
Dim rngDelete As Range
Range(sCol & 1).Select
[2:2].Insert
Range(sCol & 2) = "temp"
With ActiveSheet
.usedrange
lLastRow = .Cells.SpecialCells(xlCellTypeLastCell).Row
Set rng = Range(sCol & 2, Cells(lLastRow, sCol))
rng.AutoFilter Field:=1, Criteria1:=vSearch, Operator:=xlAnd
Set rngDelete = rng.SpecialCells(xlCellTypeVisible)
rng.AutoFilter
rngDelete.EntireRow.Delete
.usedrange
End With
End Sub
call it like:
call FindDelete "A", "=*-*"
It's saved me a lot of work. Good luck!