Filter a column and select the last used row - vba

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

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.

Create Range excluding column in middle

I have the problem of needing to exclude a column in the middle of my excel worksheet. Is there a way of creating a range that excludes a column not on the edges of the data. The range is dynamic ranging from A1:AA#. The column "F" needs to be excluded from this range. This range needs to be stored for use in a pivotTable.
Range("A1:E4,G1:J4").Select
This is how the excel macro recorder creates a range with a gap, but I cannot find a way to modify this so the last cell is dynamic.
Thanks.
Just as you should avoid using the .Select Method, you should also avoid using the .UsedRange when possible (See here).
You can try something like this. It is not as clean, but may prove to be less bug prone.
Dim LRow As Long
LRow = Range("A" & Rows.Count).End(xlUp).Row
Dim MyRange1 As Range, MyRange2 As Range, BigRange As Range
Set MyRange1 = Range("A1:E" & LRow)
Set MyRange2 = Range("G1:J" & LRow)
Set BigRange = Application.Union(MyRange1, MyRange2)
BigRange.Select
You can then refer to your BigRange directly moving forward.
If you have only one set of data in your sheet, you could try something like that :
Intersect(ActiveSheet.UsedRange, Range("A:E,G:AA")).Select
This will select everything that contains data up to column AA on the sheet except for column F.
Whenever possible , you should avoid using .select .activate but you only provide one line of your code so I can't help you much on that part except redirect you to this.
you could use
Dim rng As Range
Set rng = Intersect(Range("A:E,G:AA"), Rows(1).Resize(Cells(Rows.Count, 1).End(xlUp).Row))
where the column index in Cells(Rows.Count, 1) lets you choose what column size your range after

excel: usedrange with columns of table

Is there any way to use UsedRange to select from first to last column from a table?
Here is the original code:
Worksheets("Sheet1").UsedRange.Columns("E").Cells
But it gets from first row to last maximum of Excel and I don't want this. So I tried to do something like this:
Dim LastRow As Integer
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
With ws.UsedRange.Columns("E2:E & LastRow").Cells
Although this doesn't seem to work here, so I was in doubt if there is a correct way to do this or the UsedRange it's not the best for that.
In addition, after this I want to use THIS code provided by Jeeped, but I need to know if it's possible to solve this problem first.
You could use the range directly,
with ws
with .range(.cells(1, "E"), .cells(.rows.count, "E").end(xlup))
'do something with the cells in column E
end with
end with
You could use .UsedRange with Intersect
with Intersect(ws.UsedRange, ws.columns("E"))
'do something with the cells in column E
end with
Try this, but never use .Select.
With ws
.Range("E2:E" & LastRow).Select
End with

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.

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?

[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.