- 1.2k
- 8
- 15
'Returns last cell (max row & max col) using an array (fast)
Public Function GetMaxCellGetLastCell(Optional ByVal ws As Worksheet = Nothing) As Range
Dim usedRnguRng As Range, usedArrayuArr As Variant, r As Long, c As Long
Dim ubR As Long, ubC As Long, lRow As Long
If ws Is Nothing Then Set ws = Application.ThisWorkbook.ActiveSheet
Set usedRnguRng = ws.UsedRange
usedArrayuArr = usedRnguRng
If IsEmpty(usedArrayuArr) Then
Set GetMaxCellGetLastCell = ws.Cells(1, 1): Exit Function
End If
If Not IsArray(usedArrayuArr) Then
Set GetMaxCellGetLastCell = ws.Cells(usedRnguRng.Row, usedRnguRng.Column): Exit Function
End If
ubR = UBound(usedArrayuArr, 1): ubC = UBound(usedArrayuArr, 2)
For r = ubR To 1 Step -1 'finds'----------------------------------------------- last row
For c = ubC To 1 Step -1
If Not IsError(uArr(r, c)) Then
If Len(Trim$(usedArrayuArr(r, c))) > 0 Then
lRow = r: Exit For
ExitEnd ForIf
End If
Next
If lRow > 0 Then Exit For
Next
If lRow = 0 Then lRow = ubR
For c = ubC To 1 Step -1 'finds'----------------------------------------------- last col
For r = lRow To 1 Step -1
If Not IsError(uArr(r, c)) Then
If Len(Trim$(usedArrayuArr(r, c))) > 0 Then
Set GetMaxCellGetLastCell = ws.Cells(lRow + usedRnguRng.Row - 1, c + usedRnguRng.Column - 1)
Exit Function
End If
End If
Next
Next
End Function
'Returns last cell (max row & max col) using an array (fast)
Public Function GetMaxCell(Optional ByVal ws As Worksheet = Nothing) As Range
Dim usedRng As Range, usedArray As Variant, r As Long, c As Long
Dim ubR As Long, ubC As Long, lRow As Long
If ws Is Nothing Then Set ws = Application.ThisWorkbook.ActiveSheet
Set usedRng = ws.UsedRange
usedArray = usedRng
If IsEmpty(usedArray) Then
Set GetMaxCell = ws.Cells(1, 1): Exit Function
End If
If Not IsArray(usedArray) Then
Set GetMaxCell = ws.Cells(usedRng.Row, usedRng.Column): Exit Function
End If
ubR = UBound(usedArray, 1) ubC = UBound(usedArray, 2)
For r = ubR To 1 Step -1 'finds last row
For c = ubC To 1 Step -1
If Len(Trim$(usedArray(r, c))) > 0 Then
lRow = r
Exit For
End If
Next
If lRow > 0 Then Exit For
Next
If lRow = 0 Then lRow = ubR
For c = ubC To 1 Step -1 'finds last col
For r = lRow To 1 Step -1
If Len(Trim$(usedArray(r, c))) > 0 Then
Set GetMaxCell = ws.Cells(lRow + usedRng.Row - 1, c + usedRng.Column - 1)
Exit Function
End If
Next
Next
End Function
Public Function GetLastCell(Optional ByVal ws As Worksheet = Nothing) As Range
Dim uRng As Range, uArr As Variant, r As Long, c As Long
Dim ubR As Long, ubC As Long, lRow As Long
If ws Is Nothing Then Set ws = Application.ThisWorkbook.ActiveSheet
Set uRng = ws.UsedRange
uArr = uRng
If IsEmpty(uArr) Then
Set GetLastCell = ws.Cells(1, 1): Exit Function
End If
If Not IsArray(uArr) Then
Set GetLastCell = ws.Cells(uRng.Row, uRng.Column): Exit Function
End If
ubR = UBound(uArr, 1): ubC = UBound(uArr, 2)
For r = ubR To 1 Step -1 '----------------------------------------------- last row
For c = ubC To 1 Step -1
If Not IsError(uArr(r, c)) Then
If Len(Trim$(uArr(r, c))) > 0 Then
lRow = r: Exit For
End If
End If
Next
If lRow > 0 Then Exit For
Next
If lRow = 0 Then lRow = ubR
For c = ubC To 1 Step -1 '----------------------------------------------- last col
For r = lRow To 1 Step -1
If Not IsError(uArr(r, c)) Then
If Len(Trim$(uArr(r, c))) > 0 Then
Set GetLastCell = ws.Cells(lRow + uRng.Row - 1, c + uRng.Column - 1)
Exit Function
End If
End If
Next
Next
End Function
- 1.2k
- 8
- 15
Improved versionversions of GetMaxCell()
- thanks @Mat's Mug and @ZigD (SO) for suggestions:
It defaults to
ActiveSheet.UsedRange
if optional parameter is not sentIf the range is empty it returns
Cell( 1, 1 )
as default, instead ofNothing
- It requires an extra check for
Len( Cell( 1, 1 ).Value2 ) = 0
as a final confirmation
- It requires an extra check for
It returns reference to proper range and .Parent
If called without the optional parameter, will default to.ThisWorkbook.ActiveSheet
If the Else branch is entered the range is not empty
If the range is empty will returnsCell( 1, 1 )
as default, instead ofNothing
GetMaxCell (Array): Duration: 0.0000790063 seconds
GetMaxCell (Find): Duration: 0.0002903480 seconds
.Measured with MicroTimer
'Returns last cell (max row & max col) using an array (fast)
Public Function GetMaxCell(Optional ByRefByVal rngws As RangeWorksheet = Nothing) As Range
Dim usedRng As Range, usedArray As Variant, r As Long, c As Long
'ItDim returnsubR theAs Long, ubC As Long, lRow As Long
If ws Is Nothing Then Set ws = Application.ThisWorkbook.ActiveSheet
Set usedRng = ws.UsedRange
usedArray = usedRng
If IsEmpty(usedArray) Then
Set GetMaxCell = ws.Cells(1, 1): Exit Function
End If
If Not IsArray(usedArray) Then
Set GetMaxCell = ws.Cells(usedRng.Row, usedRng.Column): Exit Function
End If
ubR = UBound(usedArray, 1)
ubC = UBound(usedArray, 2)
For r = ubR To 1 Step -1 'finds last cellrow
of range with data For c = ubC To 1 Step -1
If Len(Trim$(usedArray(r, orc))) A1> if0 WorksheetThen
is empty lRow = r
Exit For
End If
Next
If lRow > 0 Then Exit For
Next
If lRow = 0 Then lRow = ubR
For c = ubC To 1 Step -1 'finds last col
For r = lRow To 1 Step -1
If Len(Trim$(usedArray(r, c))) > 0 Then
Set GetMaxCell = ws.Cells(lRow + usedRng.Row - 1, c + usedRng.Column - 1)
Exit Function
End If
Next
Next
End Function
'Returns last cell (max row & max col) using Find
Public Function GetMaxCell2(Optional ByRef rng As Range = Nothing) As Range
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ThisWorkbookActiveWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCellGetMaxCell2 = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
If Not lRow Is Nothing Then
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCellGetMaxCell2 = .Parent.Cells(lRow.Row, lCol.Column)
End If
End With
End If
End Function
Private Declare PtrSafe Function getFrequency Lib "Kernel32" Alias "QueryPerformanceFrequency" (cyFrequency As Currency) As Long
Private Declare PtrSafe Function getTickCount Lib "Kernel32" Alias "QueryPerformanceCounter" (cyTickCount As Currency) As Long
'https://msdn.microsoft.com/en-us/library/office/ff700515(v=office.14).aspx#Anchor_5
Function MicroTimer() As Double
Dim cyTicks1 As Currency
Static cyFrequency As Currency
MicroTimer = 0
If cyFrequency = 0 Then getFrequency cyFrequency 'Get frequency
getTickCount cyTicks1 'Get ticks
If cyFrequency Then MicroTimer = cyTicks1 / cyFrequency 'Returns Seconds
End Function
Improved version of GetMaxCell()
- thanks @Mat's Mug and @ZigD (SO) for suggestions:
It defaults to
ActiveSheet.UsedRange
if optional parameter is not sentIf the range is empty it returns
Cell( 1, 1 )
as default, instead ofNothing
- It requires an extra check for
Len( Cell( 1, 1 ).Value2 ) = 0
as a final confirmation
- It requires an extra check for
It returns reference to proper range and .Parent
If the Else branch is entered the range is not empty
Public Function GetMaxCell(Optional ByRef rng As Range = Nothing) As Range
'It returns the last cell of range with data, or A1 if Worksheet is empty
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ThisWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCell = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCell = .Parent.Cells(lRow.Row, lCol.Column)
End With
End If
End Function
Improved versions of GetMaxCell()
- The first function, using an array is much faster
- If called without the optional parameter, will default to
.ThisWorkbook.ActiveSheet
- If the range is empty will returns
Cell( 1, 1 )
as default, instead ofNothing
GetMaxCell (Array): Duration: 0.0000790063 seconds
GetMaxCell (Find): Duration: 0.0002903480 seconds
.Measured with MicroTimer
'Returns last cell (max row & max col) using an array (fast)
Public Function GetMaxCell(Optional ByVal ws As Worksheet = Nothing) As Range
Dim usedRng As Range, usedArray As Variant, r As Long, c As Long
Dim ubR As Long, ubC As Long, lRow As Long
If ws Is Nothing Then Set ws = Application.ThisWorkbook.ActiveSheet
Set usedRng = ws.UsedRange
usedArray = usedRng
If IsEmpty(usedArray) Then
Set GetMaxCell = ws.Cells(1, 1): Exit Function
End If
If Not IsArray(usedArray) Then
Set GetMaxCell = ws.Cells(usedRng.Row, usedRng.Column): Exit Function
End If
ubR = UBound(usedArray, 1)
ubC = UBound(usedArray, 2)
For r = ubR To 1 Step -1 'finds last row
For c = ubC To 1 Step -1
If Len(Trim$(usedArray(r, c))) > 0 Then
lRow = r
Exit For
End If
Next
If lRow > 0 Then Exit For
Next
If lRow = 0 Then lRow = ubR
For c = ubC To 1 Step -1 'finds last col
For r = lRow To 1 Step -1
If Len(Trim$(usedArray(r, c))) > 0 Then
Set GetMaxCell = ws.Cells(lRow + usedRng.Row - 1, c + usedRng.Column - 1)
Exit Function
End If
Next
Next
End Function
'Returns last cell (max row & max col) using Find
Public Function GetMaxCell2(Optional ByRef rng As Range = Nothing) As Range
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ActiveWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCell2 = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
If Not lRow Is Nothing Then
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCell2 = .Parent.Cells(lRow.Row, lCol.Column)
End If
End With
End If
End Function
Private Declare PtrSafe Function getFrequency Lib "Kernel32" Alias "QueryPerformanceFrequency" (cyFrequency As Currency) As Long
Private Declare PtrSafe Function getTickCount Lib "Kernel32" Alias "QueryPerformanceCounter" (cyTickCount As Currency) As Long
'https://msdn.microsoft.com/en-us/library/office/ff700515(v=office.14).aspx#Anchor_5
Function MicroTimer() As Double
Dim cyTicks1 As Currency
Static cyFrequency As Currency
MicroTimer = 0
If cyFrequency = 0 Then getFrequency cyFrequency 'Get frequency
getTickCount cyTicks1 'Get ticks
If cyFrequency Then MicroTimer = cyTicks1 / cyFrequency 'Returns Seconds
End Function
Improved version of GetMaxCell()
- thanks @Mat's Mug and @ZigD @ZigD (SO) for suggestions:
It defaults to
ActiveSheet.UsedRange
if optional parameter is not sentIf the range is empty it returns
Cell( 1, 1 )
as default, instead ofNothing
- It requires an extra check for
Len( Cell( 1, 1 ).Value2 ) = 0
as a final confirmation
- It requires an extra check for
It returns reference to proper range and .Parent
If the Else branch is entered the range is not empty
Public Function GetMaxCell(Optional ByRef rng As Range = Nothing) As Range
'It returns the last cell of range with data, or A1 if Worksheet is empty
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ThisWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCell = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCell = .Parent.Cells(lRow.Row, lCol.Column)
End With
End If
End Function
More info on Macro performance slow when page breaks are visible (Microsoft)
Improved version of GetMaxCell()
- thanks @Mat's Mug and @ZigD (SO) for suggestions:
It defaults to
ActiveSheet.UsedRange
if optional parameter is not sentIf the range is empty it returns
Cell( 1, 1 )
as default, instead ofNothing
- It requires an extra check for
Len( Cell( 1, 1 ).Value2 ) = 0
as a final confirmation
- It requires an extra check for
It returns reference to proper range and .Parent
If the Else branch is entered the range is not empty
Public Function GetMaxCell(Optional ByRef rng As Range = Nothing) As Range
'It returns the last cell of range with data, or A1 if Worksheet is empty
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ThisWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCell = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCell = .Parent.Cells(lRow.Row, lCol.Column)
End With
End If
End Function
More info on Macro performance slow when page breaks are visible (Microsoft)
Improved version of GetMaxCell()
- thanks @Mat's Mug and @ZigD (SO) for suggestions:
It defaults to
ActiveSheet.UsedRange
if optional parameter is not sentIf the range is empty it returns
Cell( 1, 1 )
as default, instead ofNothing
- It requires an extra check for
Len( Cell( 1, 1 ).Value2 ) = 0
as a final confirmation
- It requires an extra check for
It returns reference to proper range and .Parent
If the Else branch is entered the range is not empty
Public Function GetMaxCell(Optional ByRef rng As Range = Nothing) As Range
'It returns the last cell of range with data, or A1 if Worksheet is empty
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ThisWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCell = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCell = .Parent.Cells(lRow.Row, lCol.Column)
End With
End If
End Function
More info on Macro performance slow when page breaks are visible (Microsoft)
- 1.2k
- 8
- 15
- 1.2k
- 8
- 15