Selecting range without knowing number of rows or columns having data in Excel/VBA - 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.

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.

Formatting as a table dynamically Excel VBA

I would like to format a certain range in a worksheet as a table in Excel. The formatting will always start in row 10.
In order to do so, I have written the following code:
Set rng = Range(Range("B10"), Range("B10").End(xlUp).SpecialCells(xlLastCell))
Set table = Sheets("Results").ListObjects.Add(xlSrcRange, rng, , xlYes)
table.TableStyle = "TableStyleMedium13"
As of now, the formatting is done from row 10 until the end of the worksheet - even in empty rows. However, I would like the table to be formatted only up until the last row of data and for it to do this dynamically given the fact that the amount of data will vary. How can I do this?
The code below will format all cells from "B10" until last row with data in Column B (it will also format blank rows in the middle, in case you have gaps).
Dim LastRow As Long
With Sheets("Results")
' find last row with data in Column B
LastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
' set Rng from B10 untill last row with data in Column B
Set Rng = Range("B10:B" & LastRow)
Set Table = .ListObjects.Add(xlSrcRange, Rng, , xlYes)
Table.TableStyle = "TableStyleMedium13"
End With
Range("B" & Rows.Count).End(xlUp)
This should work - will simply identify last populated row.

Excel VBA - Delete Rows Based on Criteria

I have a report that I pull everyday that is placed in a very awekward format. It's contains a variable row count by 4 columns organized into unofficial tables based on the Name of each employee.
What I have is an employee name in column B preceded 2 blank rows above and followed by 1 blank row of data below.
What I want to accomplish is loop through the data, identify cells in column B <> blank, delete the entire 2 rows below that cell, and delete the entire 1 row above that cell.
Below is what I have so far. not much:
Sub test()
Dim currentSht As Worksheet
Dim startCell As Range
Dim lastRow As Long
Dim lastCol As Long
Dim i as integer
Set currentSht = ActiveWorkbook.Sheets(1)
Set startCell = currentSht.Range("A1")
lastRow = startCell.SpecialCells(xlCellTypeLastCell).Row
lastCol = startCell.SpecialCells(xlCellTypeLastCell).Column
For i = lastRow To 1
If Cells(i, "B").Value <> "" Then
End Sub
without making major changes to your code, try this:
For i = lastRow To 1 Step - 1
If Cells(i, "B").Value <> "" Then
Range(Cells(i, "B").Offset(1), Cells(i, "B").Offset(2)).EntireRow.Delete 'delete two below
Cells(i, "B").Offset(-1).EntireRow.Delete ' delete one above
You already get to your non-blank cell (ie Cells(i,"b")). To reference a range in relation to a cell you already have, use OFFSET.
So, and in this order, you select a range of cells from one below your cell Offset(1) to two cells below Offset(2)'. Change this range toENTIREROW` for those cells, and delete.
Then you select the cell above Offset(-1), select the ENTIREROW and delete.
as per your question narrative you'd possibly need to delete all rows that has a blank cell in column "B"
should that be the issue than you could (disclaimer: test it on a copy sheet!) simply go like follows:
Sub test()
With ActiveWorkbook.Sheets(1)
.Range("A1", .Cells(.Rows.Count, "A").End(xlUp)).Offset(, 1).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End With
End Sub

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 loop a dynamic range and copy select information within that range to another sheet

I have already created a VBA script that is about 160 lines long, which produces the report that you see below.
Without using cell references (because the date ranges will change each time I run this) I now need to take the users ID, name, total hours, total break, overtime 1, and overtime 2 and copy this data into sheet 2.
Any suggestions as to how I can structure a VBA script to search row B until a blank is found, when a blank is found, copy the values from column J, K, L, M on that row, and on the row above copy value C - now paste these values on sheet 2. - Continue this process until you find two consecutive blanks or the end of the data...
Even if you can suggest a different way to tackle this problem than the logic I have assumed above it would be greatly appreciated. I can share the whole code if you are interested and show you the data I began with.
Thank you in advance,
J
As discussed, here's my approach. All the details are in the code's comments so make sure you read them.
Sub GetUserNameTotals()
Dim ShTarget As Worksheet: Set ShTarget = ThisWorkbook.Sheets("Sheet1")
Dim ShPaste As Worksheet: Set ShPaste = ThisWorkbook.Sheets("Sheet2")
Dim RngTarget As Range: Set RngTarget = ShTarget.UsedRange
Dim RngTargetVisible As Range, CellRef As Range, ColRef As Range, RngNames As Range
Dim ColIDIndex As Long: ColIDIndex = Application.Match("ID", RngTarget.Rows(1), 0)
Dim LRow As Long: LRow = RngTarget.SpecialCells(xlCellTypeLastCell).Row
'Turn off AutoFilter to avoid errors.
ShTarget.AutoFilterMode = False
'Logic: Apply filter on the UserName column, selecting blanks. We then get two essential ranges.
'RngTargetVisible is the visible range of stats. ColRef is the visible first column of stats.
With RngTarget
.AutoFilter Field:=ColIDIndex, Criteria1:="=", Operator:=xlFilterValues, VisibleDropDown:=True
Set RngTargetVisible = .Range("J2:M" & LRow).SpecialCells(xlCellTypeVisible)
Set ColRef = .Range("J2:J" & LRow).SpecialCells(xlCellTypeVisible)
End With
'Logic: For each cell in the first column of stats, let's get its offset one cell above
'and 7 cells to the left. This method is not necessary. Simply assigning ColRef to Column C's
'visible cells and changing below to CellRef.Offset(-1,0) is alright. I chose this way so it's
'easier to visualize the approach. RngNames is a consolidation of the cells with ranges, which we'll
'copy first before the stats.
For Each CellRef In ColRef
If RngNames Is Nothing Then
Set RngNames = CellRef.Offset(-1, -7)
Else
Set RngNames = Union(RngNames, CellRef.Offset(-1, -7))
End If
Next CellRef
'Copy the names first, then RngTargetVisible, which are the total stats. Copying headers is up
'to you. Of course, modify as necessary.
RngNames.Copy ShPaste.Range("A1")
RngTargetVisible.Copy ShPaste.Range("B1")
End Sub
Screenshots:
Set-up:
Result:
Demo video here:
Using Filters and Visible Cells
Let us know if this helps.