Find LastColumn: 2 methods tried, each gives different column as last - excel

This is my method #1. The correct result should yield Row 1 and Column 384. This method gives the correct result But it is highly inefficient with Activate/Select, etc.
Workbooks.Open Filename:=sDest, UpdateLinks:=0
Windows(sDestFile).Activate
Sheets(sDestTab).Select
'Find LastColumn
Dim colLast As Integer
With ActiveSheet
colLast = Cells(rowTop, Columns.Count).End(xlToLeft).Column
End With
Then I created Method #2. This method is less of an eyesore, but it consistently gives me Row 1 and Column 386 as the answer (instead of Column 384). I cannot for the life of me figure out why a change in code would shift my LastColumn by 2.
Workbooks.Open Filename:=sDest, UpdateLinks:=0
'Find Last Column
Dim colLast As Integer
colLast = Workbooks(sDestFile).Worksheets(sDestTab).Cells(rowTop, Columns.Count).End(xlToLeft).Column

Use .Find. Try this
Dim lastcol As Long
With Workbooks(sDestFile).Worksheets(sDestTab)
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastcol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Else
lastcol = 1
End If
End With
MsgBox lastcol
If you want to find the last column in Row 1 then try this
Dim wb As Workbook
Dim colLast As Long
Set wb = Workbooks.Open(Filename:=sDest, UpdateLinks:=0)
With wb.Sheets(sDestTab)
colLast = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With

when I want to find the last row or column containing the value:
Option Explicit
Public Function Row_Last(ws As Worksheet) As Long
On Error Resume Next
Row_Last = _
ws.Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
If Row_Last = 0 Then Row_Last = 1
End Function
Public Function Col_Last(ws As Worksheet) As Long
On Error Resume Next
Col_Last = _
ws.Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
If Col_Last = 0 Then Col_Last = 1
End Function

Related

Range Selection Method Dilemma

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.

VBA Excel detect always hidden rows and columns in With x End With loop?

How to detect always in With xx end Withalso hidden columns and rows? My code's current variables values are changing depending on that are the columns and rows hidden or not. That prevents my code working on properly.
With myMatrixSheet
lastRow = .Range("B" & .Rows.Count).End(xlUp).row
lastColumn = .Cells(7,.UsedRange.Columns.Count).End(xlToLeft).column + 1
End With
My solved and final code look likes below
With myMatrixSheet
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).row
Else
lastRow = 1
End If
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastColumn = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).column
Else
lastColumn = 1
End If
End With
I find FIND the easiest way (other methods are available):
Sub Test()
Dim LastRow As Long
Dim LastColumn As Long
With Sheet1
LastRow = .Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Row
LastColumn = .Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Column
End With
If LastRow = 0 Then LastRow = 1
If LastColumn = 0 Then LastColumn = 1
'--OR USE SEPARATE FUNCTION--
Dim rLastCell As Range
Set rLastCell = LastCell(Sheet1)
Debug.Print rLastCell.Row & " : " & rLastCell.Column
End Sub
Public Function LastCell(wrkSht As Worksheet) As Range
Dim lLastCol As Long, lLastRow As Long
On Error Resume Next
With wrkSht
lLastCol = .Cells.Find("*", , , , xlByColumns, xlPrevious).Column
lLastRow = .Cells.Find("*", , , , xlByRows, xlPrevious).Row
If lLastCol = 0 Then lLastCol = 1
If lLastRow = 0 Then lLastRow = 1
Set LastCell = .Cells(lLastRow, lLastCol)
End With
On Error GoTo 0
End Function
The FIND solution will be covered in the link provided by #Vityata.
To get the last of the rows/columns also when they are hidden:
Activesheet.cells.SpecialCells(xlCellTypeLastCell).Row
Activesheet.cells.SpecialCells(xlCellTypeLastCell).Column
If you need the specific column, use it like this:
Public Function GetLastRow(lngCol As Long) As Long
GetLastRow = ActiveSheet.Columns(3).Find(What:="*", SearchDirection:=xlPrevious).Row
End Function
In general, this is probably the best article for last rows and columns:
https://www.rondebruin.nl/win/s9/win005.htm

Excel File Size

I have an Excel Sheet with about 76.000 rows and 50 Columns. All is just plain text. The saved Excel file is about 16Mb. Is this realistic as the file size seems a bit big too me.
Best
syrvn
I think that 16Mb is could be too much for your file.
Sometimes big excel sheet (expecially if there are pivot tables inside them) have oversize weight if saved with old Excel versions...like Excel 2003, or if they are being saved with different versions multiple times...for Example Excel 2003, then Excel 2010, then again Excel 2003, ...
The best way is to copy all your table into another brand new file and save it, this will have smaller size than the first because you left all unuseful data into the old one.
Another way is to run the Excel Diet macro that you can find here.
Option Explicit
Sub ExcelDiet()
Dim j As Long
Dim k As Long
Dim LastRow As Long
Dim LastCol As Long
Dim ColFormula As Range
Dim RowFormula As Range
Dim ColValue As Range
Dim RowValue As Range
Dim Shp As Shape
Dim ws As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error Resume Next
For Each ws In Worksheets
With ws
'Find the last used cell with a formula and value
'Search by Columns and Rows
On Error Resume Next
Set ColFormula = .Cells.Find(What:="*", After:=Range("A1"), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious)
Set ColValue = .Cells.Find(What:="*", After:=Range("A1"), LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious)
Set RowFormula = .Cells.Find(What:="*", After:=Range("A1"), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
Set RowValue = .Cells.Find(What:="*", After:=Range("A1"), LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
On Error GoTo 0
'Determine the last column
If ColFormula Is Nothing Then
LastCol = 0
Else
LastCol = ColFormula.Column
End If
If Not ColValue Is Nothing Then
LastCol = Application.WorksheetFunction.Max(LastCol, ColValue.Column)
End If
'Determine the last row
If RowFormula Is Nothing Then
LastRow = 0
Else
LastRow = RowFormula.Row
End If
If Not RowValue Is Nothing Then
LastRow = Application.WorksheetFunction.Max(LastRow, RowValue.Row)
End If
'Determine if any shapes are beyond the last row and last column
For Each Shp In .Shapes
j = 0
k = 0
On Error Resume Next
j = Shp.TopLeftCell.Row
k = Shp.TopLeftCell.Column
On Error GoTo 0
If j > 0 And k > 0 Then
Do Until .Cells(j, k).Top > Shp.Top + Shp.Height
j = j + 1
Loop
If j > LastRow Then
LastRow = j
End If
Do Until .Cells(j, k).Left > Shp.Left + Shp.Width
k = k + 1
Loop
If k > LastCol Then
LastCol = k
End If
End If
Next
.Range(.Cells(1, LastCol + 1), .Cells(.Rows.Count, .Columns.Count)).EntireColumn.Delete
.Range("A" & LastRow + 1 & ":A" & .Rows.Count).EntireRow.Delete
End With
Next
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

Null rows is also read when reading data from excel sheet dynamically

endofrow = excelWorksheet.get_Range("X3", "Y3").get_End(XlDirection.xlDown).Row.ToString();
//endofrow value must be 5 but it comes as 8 and null rows appear
this function must read only 2 rows as only two rows of data are present ,but it reads extra rows and null rows are appearing during insertion.
I use this code to return last row. hope this might help you
Sub GetLastRow()
Dim ws As Worksheet
Dim lRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lRow = 1
End If
End With
MsgBox "The last row in Sheet1 which has data is " & lRow
End Sub
you can change it according to your need.

Find last column assigned in Range

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.

Resources