I am trying to select a range until the last used row in the sheet. I currently have the following:
Sub Select_Active_Down()
Dim lr As Long
lr = ActiveSheet.UsedRange.Rows.Count
If Cells(ActiveCell.Row, ActiveCell.Column) = Cells(lr, ActiveCell.Column) Then
MsgBox "There isn't any data to select."
Else
Range(Cells(ActiveCell.Row, ActiveCell.Column), Cells(lr, ActiveCell.Column)).Select
Cells(lr, ActiveCell.Column).Activate
End If
End Sub
The issue is that I need to select multiple columns, and this will only select the first column of the active range. How can I modify this to select multiple columns rather than just the first?
What about selection the entire region? This can be done as follows in VBA:
Selection.CurrentRegion.Select
There also is the possibility to select the entire array. For that, just press Ctrl+G, choose Special and see over there.
I would do this slightly different. I would use .Find to find the last row and the last column (using the same logic shown in the link) to construct my range rather than using Selection | Select | ActiveCell | UsedRange | ActiveSheet.
Is this what you are trying?
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim LastRow As Long
Dim LastColumn As Long
Dim rng As Range
'~~> Change it to the relevant sheet
Set ws = Sheet1
With ws
'~~> Check if there is data
If Application.WorksheetFunction.CountA(.Cells) = 0 Then
MsgBox "No Data Found"
Exit Sub
End If
'~~> Find last row
LastRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Find last column
LastColumn = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
'~~> Construct your range
Set rng = .Range(.Cells(1, 1), .Cells(LastRow, LastColumn))
'~~> Work with the range
With rng
MsgBox .Address
'
'~~> Do what you want with the range here
'
End With
End With
End Sub
Related
I have an Excel spreadsheet with the tabs "Analysis" and "Database". I want to create a button in Analysis that when clicked will convert the Database tab into a table. The Database isn't static and different users are always adding data.
I have the code below but it fails at the ".parent..." line of code.
Sub Convert_Table()
With ThisWorkbook.Sheets("Database").Range("a1")
.Parent.ListObjects.Add(xlSrcRange, ThisWorkbook.Sheets("Database").Range(.End(xlDown), .End(xlToRight)), , xlYes).Name = "Table1"
End With
End Sub
ThisWorkbook.Sheets("Database").Range("a1").Parent is the Sheets("Database"). Simplify your code.
I would do this slightly different.
I will find the last row and last column to make my range and then create the table. xlDown and xlToRight are not reliable if there are blank cells in between.
Is this what you are trying (UNTESTED)? I have commented the code but if you still have a problem understanding it, simply post a comment below.
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Dim rng As Range
Dim tbl As ListObject
'~~> This is your worksheet
Set ws = ThisWorkbook.Sheets("Database")
With ws
'~~> Unlist the previously created table
For Each tbl In .ListObjects
tbl.Unlist
Next tbl
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
'~~> Find last row
lastRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Find last column
lastCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
'~~> Set your rnage
Set rng = .Range(.Cells(1, 1), .Cells(lastRow, lastCol))
'~~> Create the table
.ListObjects.Add(xlSrcRange, rng, , xlYes).Name = "Table1"
End If
End With
End Sub
I need more experienced persons advice on some situation which I am facing. I have a test sample data in the following table.
hello good day today
hello good day today
hello good day today
hello good day today
hello good day today
hello good day today
hello good day today
today
today
I have used 4 ways to determine range as per following code and also the last cell by FIND method.
Sub test()
Dim ws As Worksheet
Dim myRange As Range
Dim myRange1 As Range
Dim myRange2 As Range
Dim rLastCell As Range
Set ws = ThisWorkbook.ActiveSheet
With ws
Set myRange = .Range(.Cells(1, 1), .Range("A1").SpecialCells(xlCellTypeLastCell))
Debug.Print ws.Name, myRange.Address
'set range with used area
Set myRange1 = ws.UsedRange
Debug.Print ws.Name, myRange1.Address
'set range with currentegion
Set myRange2 = .Range("A1").CurrentRegion
Debug.Print ws.Name, myRange2.Address
' finding lastcell and then set range
Set rLastCell = ActiveSheet.Cells.Find(What:="*", After:=.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
Debug.Print rLastCell.Address
End With
End Sub
Results of Debug.Print are
Book1 $A$1:$D$11
Book1 $A$1:$D$11
Book1 $A$1:$D$6
$D$11
My specific query is that by UsedRange, SpecialCells(xlCellTypeLastCell) and FIND method I get the same results. Though use of these or other approaches depend on the situation at hand but considering this particular data situation, Is over-riding preference for a particular method is warranted.
EDIT:
Based on comments of #VBasic2008 and an excellent article referred by # QHarr , I am inclined to adopt for range determination in general situations following methodology. I would like to find Last Row and Last Column of the range utilizing the Last function suggested in Ron de Bruin Aricle . Range will be set based on Anchor Cell and Last Row and Last Column Values.Code followed by me as follows.
Sub Range_Detrmine()
Dim ws As Worksheet
Dim LastRow As Long
Dim LastCol As Long
Dim rng As Range
Dim Frng As Range
Set ws = ThisWorkbook.ActiveSheet
With ws
' Use all cells on the sheet
Set rng = .Cells
' Find the last row
LastRow = Last(1, rng)
LastCol = Last(2, rng)
Set Frng = .Range(.Cells(1, 1), .Cells(LastRow, LastCol))
Debug.Print LastRow & ":"; LastCol
Debug.Print ws.Name, Frng.Address
End With
End Sub
Function Last(choice As Long, rng As Range)
'Ron de Bruin, 5 May 2008
' 1 = last row
' 2 = last column
' 3 = last cell
Dim lrw As Long
Dim lcol As Long
Select Case choice
Case 1:
On Error Resume Next
Last = rng.Find(What:="*", _
After:=rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
Case 2:
On Error Resume Next
Last = rng.Find(What:="*", _
After:=rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
Case 3:
On Error Resume Next
lrw = rng.Find(What:="*", _
After:=rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
On Error Resume Next
lcol = rng.Find(What:="*", _
After:=rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
On Error Resume Next
Last = rng.Parent.Cells(lrw, lcol).Address(False, False)
If Err.Number > 0 Then
Last = rng.Cells(1).Address(False, False)
Err.Clear
End If
On Error GoTo 0
End Select
End Function
I tested the above code for some example situations as per snapshots appended. I tested the correctness of range determined before deleting formatted row and after deleting the formatted row.Also in case of filter applied it is giving correct range even though filter check-marks are visible in Header Row in Column H
Debug.Print LastRow & ":"; LastCol
Debug.Print ws.Name, Frng.Address
Results before and after range modification are :
17: 8
Sheet1 $A$1:$H$17
14: 7
Sheet2 $A$1:$G$14
I would like to know if there are some caveats to this approach.
I have run a macro to paste, edit, alter and split data using a specified data set.
On a new data set (more data) I ran into a problem with my data range.
ActiveSheet.Range("$A$1:$T$299").AutoFilter Field:=6, Criteria1:= _
"=Site Reference A", Operator:=xlOr, Criteria2:= _
"=Site Reference A Total"
Range("A1:T299").Select
Range("F160").Activate
Selection.SpecialCells(xlCellTypeVisible).Select
Selection.Copy
My data range is $A$1:$T$299. How would I make this dynamic?
Example -
Data set A has 200 columns.
Data set B has 230 columns.
A little long, but this full code is the safer way to find the last row and last column in a sheet.
Dim Sht As Worksheet
Dim FiltRng As Range
Dim LastCol As Long
Dim LastRow As Long
Set Sht = ActiveSheet '<-- better not rely on ActiveSheet
LastRow = FindLastRow(Sht)
LastCol = FindLastCol(Sht)
With Sht
Set FiltRng = .Range(.Cells(1, 1), .Cells(LastRow, LastCol)) ' <-- set the filtered range dynamically
End With
With Sht
FiltRng.AutoFilter Field:=6, Criteria1:= _
"=Site Reference A", Operator:=xlOr, Criteria2:= _
"=Site Reference A Total"
' rest of your code goes here
End With
'==========================================================
Function FindLastCol(Sht As Worksheet) As Long
' This Function finds the last col in a worksheet, and returns the column number
Dim LastCell As Range
With Sht
Set LastCell = .Cells.Find(What:="*", After:=.Cells(1), Lookat:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False)
If Not LastCell Is Nothing Then
FindLastCol = LastCell.Column
Else
MsgBox "Error! worksheet is empty", vbCritical
End
End If
End With
End Function
'==========================================================
Function FindLastRow(Sht As Worksheet) As Long
' This Function finds the last row in a worksheet, and returns the row number
Dim LastCell As Range
With Sht
Set LastCell = .Cells.Find(What:="*", After:=.Cells(1), Lookat:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
If Not LastCell Is Nothing Then
FindLastRow = LastCell.Row
Else
MsgBox "Error! worksheet is empty", vbCritical
End
End If
End With
End Function
If there is no other data in column A, you can use a dynamic named range. Just use the following formula as the range for your named range and then reference the named range in your code. Keep in mind that this only works if there is no other data in column A.
=OFFSET($A$1,0,0,COUNTA($A:$A),1)
My first post here.....
I was able to search and find this code from Siddharth Rout which is the basis for what I want to do....append multiple sheets of data to a single data sheet. However I'm having trouble modifying it to fit my case. What I have below doesn't currently work......
Problem 1) How can I use Select Case InStr with multiple sheets (3) that do not have a common name such as "Legende" as the original poster had in her case.
Problem 2) In my case each sheet will have different columns that I need copied to the Tab_Appended sheet, Sheet1 will have x rows and I want column B, D, M, AR, etc and Sheet2 will have XXXX rows and I want to copy column B, D, N, AS, AT, etc for 15 sheets.
Credit to Siddharth Rout for this original code:
Sub SummurizeSheets()
Dim wsOutput As Worksheet
Dim ws As Worksheet
Dim wsOLr As Long, wsLr As Long
Application.ScreenUpdating = False
'~~> Set this to the sheet where the output will be dumped
Set wsOutput = Sheets("Tab_Appended")
With wsOutput
'~~> Get Last Row in "Tab_Appended" in Col A/M and Add 1 to it
wsOLr = .Range("A:M").Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row + 1
'~~> Loop through sheet
For Each ws In Worksheets
'~~> Check if the sheet name has Legende
'Select Case InStr(1, ws.Name, "Legende", vbTextCompare)
Select Case InStr(1, ws.Name, "Test2", vbTextCompare) + _
InStr(1, strData, "Test", vbTextCompare) + _
InStr(1, strData, "Sheet2", vbTextCompare)
'~~> If not then
Case 0
With ws
'~~> Get Last Row in the sheet
wsLr = .Range("A:M").Find(What:="*", After:=.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row
'~~> Copy the relevant range
.Range("A2:M" & wsLr).Copy wsOutput.Range("A" & wsOLr)
'~~> Get Last Row AGAIN in "Tab_Appended" in Col A/B and Add 1 to it
wsOLr = wsOutput.Range("A:M").Find(What:="*", After:=wsOutput.Range("A1"), _
Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False).Row + 1
End With
End Select
Next
End With
Application.ScreenUpdating = True
End Sub
Thanks,
Don
I need to find out the column that is the last column in a range that is defined with:
Set RngSource = ActiveWorkbook.ActiveSheet.UsedRange
First things first
Never use UsedRange to set your range. I have explained it HERE as to why you shouldn't use UsedRange
Set RngSource = ActiveWorkbook.ActiveSheet.UsedRange
Find the Last Column that has data and the Last Row which has data and then set your range. So your question of finding the last column from the range will not arise. Here is an example
Sub Sample()
Dim ws As Worksheet
Dim rng As Range
Dim lRow As Long, lCol As Long
'~~> Set your worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
'~~> Find Last Row
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Find Last Column
lCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Else
lRow = 1: lCol = 1
End If
'~~> Set your range
Set rng = .Range(.Cells(1, 1), .Cells(lRow, lCol))
Debug.Print rng.Address
End With
End Sub
Use End(xlToRight) with an activecell.