reference last column of worksheet - excel

All of the below methods have failed to reference the last column. What is a viable method?
For example 'Columns("1:" & llc.Address & "").Select through 'Columns("E:" & llc & "").Selectare trying to select sayColumns("E:N")`. But the last column is dynamic. In one instance it's column N, and in another application of the macro it's column AP.
Sub RestorePivtTable()
Set ws = ThisWorkbook.Sheets("sheet1")
llc = ws.Cells(2, ws.Columns.count).End(xlToLeft).Column
'Columns("1:" & llc.Address & "").Select
'Columns(1, llc).Select
'Range(Columns(1), Columns(llc)).Select
'Columns("E:" & Cells(3, llc).Address & "").Select
'Range("1:" & Cells(3, lc).Address & "").Select
'Range(Cells(1, 1).Address, Cells(3, llc).Address).Select
'Columns("E:" & llc & "").Select
Selection.ClearFormats
End Sub

If you are using your above method you will need to find the correct row to use. ie: you will need to know the row in which the data appears in the right-most column. If you want the last column out of anything, try:
ws.usedrange.columns
This just gives the number of columns in the used range of a sheet, which is defined as A1:[The bottom right cell which contains either values or formatting].
Note that this will not work if, say, you have formatting in E10, but you want to get column D, because D is the last column which has a value [ie: you want to exclude consideration of formatted cells].

I generally use this method, although you have to put checks in in case the sheet is empty (you can't return column 0).
Sub FindLastColumn()
Dim wrkSht As Worksheet
Set wrkSht = ThisWorkbook.Worksheets("Sheet1")
MsgBox wrkSht.Cells.Find(What:="*", After:=wrkSht.Cells(1, 1), SearchDirection:=xlPrevious).Column
End Sub

Basic example of how to find the last column in your sheet - I've included an If block in case the sheet is empty, but then I don't know why you would run this code on an empty sheet anyway...
Sub SO()
Dim lastCol As Integer
Dim lastCell As Excel.Range
'// Assuming the variable 'ws' has already been dimensioned and initialised
On Error Resume Next
Set lastCell = ws.Cells.Find(What:="*", After:=ws.Range("A1"), SearchDirection:=xlPrevious)
On Error GoTo 0
If lastCell Is Nothing Then
lastCol = 1
Else
lastCol = lastCell.Column
End If
MsgBox lastCol
End Sub
UsedRange can be unreliable in this instance, because it can still contain cells that were previously used but are now blank - and I'm guessing you're not interested in these cells. Using the Cells.Find() method means that you don't have to know which row will coincide with the last column (which is needed for Columns.Count.End(xlToLeft) method) so this is a bonus too when working with irregular data sets.

Trying to "read between the lines" of your code, I suspect that this is what you are after:
Public Sub RestorePivtTable()
Sheet1.Cells(2, Sheet1.Columns.Count).End(xlToLeft).EntireColumn.ClearFormats
End Sub
This will work as long as there are data in row 2.

Thanks everyone for your help. The below function and macro solved the issue of converting a column number reference into a letter reference:
Function GetColumnLetter(colNum As Long) As String
Dim vArr
vArr = Split(Cells(1, colNum).Address(True, False), "$")
GetColumnLetter = vArr(0)
End Function
Sub RestorePivtTable2()
Dim lc As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("PivtTable")
lc = ws.Cells(5, ws.Columns.count).End(xlToLeft).Column
myCol = GetColumnLetter(lc)
Columns("E:" & myCol & "").Select
Selection.ClearFormats
End Sub

Related

Using variable as column reference to autosum said column VBA

I'm really new to VBA and have been working section by section on a number of pieces of code to format a worksheet (I've been doing it piece by piece so that I understand how each works, and using a final macro to Call all the macros into one long process).
Issue is sometimes the worksheets I work with are not exported with columns in the same order from month to month (out of my control), thus to autosum a particular column I have to Find the column header, then autosum that column, but this makes the column letter(or number) completely variable. I know how to work with rows as variables, but I'm stuck on column. I've been scouring forums to try and find a concise explanation, but to no avail, yet.
This code DOES work for column Y specifically, but I'm trying to figure out how to get it to use a variable for the column.
For example, I'm using a separate Macro called "FindInvoiceColumn" to select the 1st cell in the column that contains the string "invoice_amount", then I'd like to use something like I wrote below to set "ColumnAddress" as the column value of that cell. As far as I know .Column returns the column number, which is fine, but I'm assuming I'd have to use with Cells() instead of Range(), I just don't know how to get here.
(Part of the code also shows Adding the word "Total" to the left of the cell containing the autosum value, and making both bold).
Here's what I have so far:
Dim Rng As Range
Dim c As Range
Set Rng = Range("Y" & rows.Count).End(xlUp).Offset(1, 0)
Set c = Range("Y1").End(xlDown).Offset(1, 0)
c.Formula = "=SUM(" & Rng.Address(False, False) & ")"
'Selects next empty row of column X to add "Total" label for sum of column Y'
Range("X" & Cells.rows.Count).End(xlUp).Offset(1, 0).Select
ActiveCell.FormulaR1C1 = "Total"
'Bolds Total and the Sum of invoices'
Range("X" & Cells.rows.Count).End(xlUp).Select
Selection.Font.Bold = True
Range("Y" & Cells.rows.Count).End(xlUp).Select
Selection.Font.Bold = True```
'The below is what I'd like to use to find the dynamic value of the column.'
'Finds cell in row 1 that contains column header "invoice_amount" and selects it'
Call FindInvoiceColumn
'Dim ColumnAddress As Integer
ColumnAddress = ActiveCell.Column
You can use .Address to get a column reference, such that:
Sub test()
Dim varCol As String
varCol = Columns(ActiveCell.Column).Address
Debug.Print varCol 'OUTPUTS $A:$A when I had cells(1,1) selected
End Sub
In the above example, I chose a single cell to A) find it's column reference, via .Column, and B) found the .address of said column.
You could also perform the sum on a defined range using .cells() notation, rather than .range() notation.
Sub test2()
Dim rng As Range
Set rng = Range(Cells(1, 1), Cells(2, 1))
Cells(3, 1).Formula = "=sum(" & rng.Address & ")"
End Sub
The above code ouputs:
Specific to using the .cells() notation, you can make your column reference a variable, e.g.:
dim r as long, c as long
r = 1
c = 4
debug.print cells(r,c).address `should output $D$1 (untested)
You can choose r or c to fit your needs.
And as always... avoid select/activate where possible!!!
Edit
Adding use of last row via code since comments are terrible:
dim col as long
col = 25 'Y
With sheets("name")
dim lastRow as long
lastRow = .cells(.rows.count,col).end(xlup).row
Dim rng As Range
Set rng = .Range(.Cells(1, 1), .Cells(lastRow, col))
end with
This is exactly why I mentioned the specifics abotu the notation after that section (use of r and c as variables).
I've used this code to set a column number if your header is in a variable position
Dim F As Object
ColumnAddress = 0
With ActiveSheet.Rows(1)
Set F = .Find(What:="invoice_amount", LookAt:=xlWhole)
If F Is Nothing Then
MsgBox "This is not a proper file"
' other code
Else
ColumnAddress = F.Column
End If
End With
You would then use Cells() in place of range to do further work with the result of ColumnAddress. Also, ColumnAddress should dim as Long, to be accurate.

Find a date in other sheet

I extract a date from sheet "A" to find in a sheet "B".
I have the same type of date in each sheet (type 7) and the date exists.
With the code below I have
Error 91 : Object variable or With undefined block variable
Sub SearchDate()
lastColTraining = ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Column
lastLetterTraining = Split(Cells(1, lastColTraining).Address, "$")(1)
Set allTraining = Range("K3:" & lastLetterTraining & "7")
For Each training In allTraining.Columns
trainingDate = training.Rows(4)
With Worksheets("B")
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
allDate = .Range("A2:A" & lastRow)
firstRowDate = allDate.Find(What:=trainingDate, After:=.Range("A" & lastRow)).Row
End With
Next training
End Sub
I scoured many forums and tried different solutions without finding an answer.
There are a few things going wrong here:
First: Declare your variables, it's even best to use Option Explicit on top of your module to actually make you not forget any. Otherwise VBA will try to make an educated guess which will be a Variant type of the date type.
Second I would try to avoid ActiveSheet but instead use a CodeName. For example Sheet1.Range("..."). This post on SO can clarify a thing or two on this matter.
Third, UsedRange is not the most reliable way to return a last used column. Instead I would go with something like:
With Sheet1 'The explicit sheet reference from the first point
lastColTraining = .Cells(1, .Columns.Count).End(xlToLeft).Column
End with
Fourth: You don't really need the column letter to refer to the column. There are other ways, for example using .Cells within a range. You could use:
With Sheet1 'The explicit sheet reference from the first point
lastColTraining = .Cells(1, .Columns.Count).End(xlToLeft).Column
Set allTraining = .Range(.Cells(3,11),.Cells(lastColTraining,11))`
End with
Fifth: If you have a Range object, you want to (most likely) Set it as a Range object. Otherwise (as per my first point) Excel will make an educated guess and in your case will return an array when you write: allDate = .Range("A2:A" & lastRow), instead use: Set allDate = .Range("A2:A" & lastRow)
Sixth: As per #SiddharthRout his comment, you'll recieve an error once your value isn't found. You can test that first trying to Set a FoundRange and check if it's not nothing.
Considering all the above, your code would run smoother using:
Option Explicit
Sub SearchDate()
Dim lastColTraining As Long, lastRow As Long, firstRowDate
Dim allTraining As Range, training As Range, allDate As Range, FoundCell As Range
Dim trainingDate As Variant
With Sheet1 'Change according to your sheets CodeName
lastColTraining = .Cells(1, .Columns.Count).End(xlToLeft).Column
Set allTraining = .Range(.Cells(3, 11), .Cells(7, lastColTraining))
For Each training In allTraining.Columns
trainingDate = training.Rows(4)
With Worksheets("B")
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set allDate = .Range("A2:A" & lastRow)
Set FoundCell = allDate.Find(What:=trainingDate, AFter:=.Range("A" & lastRow))
If Not FoundCell Is Nothing Then firstRowDate = FoundCell.Row
End With
Next training
End With
End Sub
I'm just not sure what you want with trainingDate = training.Rows(4). If you just interested in the 7th row of each column, then refer to that Range instead. Neither am I sure what your goal is with the code, but hopefully you can get it to work now.

Find last row in range

I'm having a little trouble with finding the last row.
What I am trying to do is find the last row in column "A", then use that to find the last row within a range.
Example of Data:
1) LR_wbSelect = wbshtSelect.cells(Rows.count, "A").End(xlUp).Row - 22
2) LR_wbSelectNew = wbshtSelect.cells(LR_wbSelect, "A").End(xlUp).Row
I am using the last row in column "A" as the data from row 29 down will always be the same length, the rows used in column "B" from row 29 can be a varying number of rows.
So I am trying to use LR_wbSelect in column "A" to get my starting last Row, then within LR_wbSelectNew using it as the starting point to look up from.
This works when the column I set to "A", LR_wbSelectNew gives me the row of "17", but when I change the column in LR_wbSelectNew to "B" it doesn't give the correct last row of "18".
I can change the column to "C, D, E, F" and the code works fine, but the only column that I can use is "B" because it will always have data in it, where the rest of that row could have a blank cell.
After doing some testing on the sheet, by pressing CRTL & Up from the lastring point of LR_wbSelect column "B" ignores the data in the rows and go to the row where it find data. I can't see a reason why Excel doesn't think there is data in these cells?
There are mulitple results and methods when searching for the LastRow (in Column B).
When using Cells(.Rows.Count, "B").End(xlUp).Row you will get the last row with data in Column B (it ignores rows with spaces, and goes all the way down).
When using:
With wbshtSelect.Range("B10").CurrentRegion
LR_wbSelectNew = .Rows(.Rows.Count).Row
End With
You are searching for the last row with data in Column B of the CurrentRegion, that starts from cell B10, untill the first line without data (it stops on the first row with empty row).
Full Code:
Sub GetLastRow()
Dim wbshtSelect As Worksheet
Dim LR_wbSelectNew As Long
' modify "Sheet2" to your sheet's name
Set wbshtSelect = Sheets("Sheet2")
' find last row with data in Column B
With wbshtSelect
LR_wbSelectNew = .Cells(.Rows.Count, "B").End(xlUp).Row
End With
' for debug only
Debug.Print LR_wbSelectNew ' >>result 31
' find last row with data in Column B at current regioun starting at cell B10
With wbshtSelect.Range("B10").CurrentRegion
LR_wbSelectNew = .Rows(.Rows.Count).Row
End With
' for debug only
Debug.Print LR_wbSelectNew ' >> result 18
End Sub
Edit1: code searches for last row for cells with values (it ignores blank cells with formulas inside).
Sub GetLastRow()
Dim wbshtSelect As Worksheet
Dim LR_wbSelectNew As Long
' modify "Sheet2" to your sheet's name
Set wbshtSelect = Sheets("Sheet2")
' find last row with data in Column B at current regioun starting at cell B10
With wbshtSelect.Range("B10").CurrentRegion
LR_wbSelectNew = .Rows(.Rows.Count).Row
End With
Dim Rng As Range
Set Rng = wbshtSelect.Range("B10:B" & LR_wbSelectNew)
' find last row inside the range, ignore values inside formulas
LR_wbSelectNew = Rng.Find(What:="*", _
After:=Range("B10"), _
LookAt:=xlPart, _
LookIn:=xlValues, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
' for debug
Debug.Print LR_wbSelectNew ' << result 18 (with formulas in the range)
End Sub
Hope this piece of code helps !
Sub LastRowInOneColumn()
'Find the last used row in a Column: column A in this example
Dim LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
MsgBox LastRow
End Sub
I came here looking for a way to find the last row in a non-contiguous range. Most responses here only check one column at a time so I created a few different functions to solve this problem. I will admit, though, that my .Find() implementation is essentially the same as Shai Rado's answer.
Implementation 1 - Uses Range().Find() in reverse order
Function LastRowInRange_Find(ByVal rng As Range) As Long
'searches range from bottom up stopping when it finds anything (*)
Dim rngFind As Range
Set rngFind = rng.Find( What:="*", _
After:=rng.Parent.Cells(rng.row, rng.Column), _
LookAt:=xlWhole, _
LookIn:=xlValues, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious)
If Not rngFind Is Nothing Then
LastRowInRange_Find = rngFind.row
Else
LastRowInRange_Find = rng.row
End If
End Function
Implementation 2 - Uses Range().End(xlUp) on each column
Function LastRowInRange_xlUp(ByVal rng As Range) As Long
Dim lastRowCurrent As Long
Dim lastRowBest As Long
'loop through columns in range
Dim i As Long
For i = rng.Column To rng.Column + rng.Columns.count - 1
If rng.Rows.count < Rows.count Then
lastRowCurrent = Cells(rng.row + rng.Rows.count, i).End(xlUp).row
Else
lastRowCurrent = Cells(rng.Rows.count, i).End(xlUp).row
End If
If lastRowCurrent > lastRowBest Then
lastRowBest = lastRowCurrent
End If
Next i
If lastRowBest < rng.row Then
LastRowInRange_xlUp = rng.row
Else
LastRowInRange_xlUp = lastRowBest
End If
End Function
Implementation 3 - Loops through an Array in reverse order
Function LastRowInRange_Array(ByVal rng As Range) As Long
'store range's data as an array
Dim rngValues As Variant
rngValues = rng.Value2
Dim lastRow As Long
Dim i As Long
Dim j As Long
'loop through range from left to right and from bottom upwards
For i = LBound(rngValues, 2) To UBound(rngValues, 2) 'columns
For j = UBound(rngValues, 1) To LBound(rngValues, 1) Step -1 'rows
'if cell is not empty
If Len(Trim(rngValues(j, i))) > 0 Then
If j > lastRow Then lastRow = j
Exit For
End If
Next j
Next i
If lastRow = 0 Then
LastRowInRange_Array = rng.row
Else
LastRowInRange_Array = lastRow + rng.row - 1
End If
End Function
I have not tested which of these implementations works fastest on large sets of data, but I would imagine that the winner would be _Array since it is not looping through each cell on the sheet individually but instead loops through the data stored in memory. However, I have included all 3 for variety :)
How to use
To use these functions, you drop them into your code sheet/module, specify a range as their parameter, and then they will return the "lowest" filled row within that range.
Here's how you can use any of them to solve the initial problem that was asked:
Sub answer()
Dim testRange As Range
Set testRange = Range("A1:F28")
MsgBox LastRowInRange_Find(testRange)
MsgBox LastRowInRange_xlUp(testRange)
MsgBox LastRowInRange_Array(testRange)
End Sub
Each of these will return 18.
If your wbshtSelect is defined as worksheet and you have used set to define the specific worksheet, you can use this.
Dim LastRow As Long
wbshtSelect.UsedRange ' Refresh UsedRange
LastRow = wbshtSelect.UsedRange.Rows(wbshtSelect.UsedRange.Rows.Count).Row
Otherwise take a look here http://www.ozgrid.com/VBA/ExcelRanges.htm
LR_wbSelectNew = wbshtSelect.cells(LR_wbSelect, "B").End(xlUp).Row
Why are you using "LR_wbSelect" as the row counter? If you want to know the last row of column 'B', you should use Rows.count
Rows.count --> Returns maximum number of rows (which is 1048576 for Excel 2007 and up)
End(xlUp) --> Moves the pointer upward to the last used row
So,
cells(Rows.count, "A").End(xlUp).Row --> This moves the pointer to the last row if the column 'A' (as if you are pressing Crtl+Up keys when A1048576 cell is selected)
So, use Rows.count to select the last row for column 'B' as well. If you have some specific requirement related to LR_wbSelect, please mention it.
Alternatively, if you want to know the last row used in a sheet, you may use the below:
mySheet.Cells.SpecialCells(xlCellTypeLastCell).Row
LR_wbSelect = ThisWorkbook.Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
Simple function that return last row no. in specific sheet.
It takes the last address in UsedRange and retrieve last row number.
Feel to free change the code and use standard range insead of UsedRange.
Function FindLastRow(wsToCheck As Worksheet) As Long
Dim str As String
str = wsToCheck.UsedRange.AddressLocal()
FindLastRow = Right(str, InStr(1, StrReverse(str), "$") - 1)
End Function
Range().End will bring you to the end of a code block. If the starting cell is empty, it brings you the the first used cell or the last cell. It the cells is not empty it brings you to the last used cell. For this reason, you need to test whether or not the cell in column B is to determine whether to use LR_wbSelectNew as the last row.
With wbshtSelect
LR_wbSelect = .Cells(Rows.Count, "A").End(xlUp).Row - 22
If .Cells(LR_wbSelect, "B") <> "" Then
LR_wbSelectNew = LR_wbSelect
Else
LR_wbSelectNew = .Cells(LR_wbSelect, "B").End(xlUp).Row
End If
End With
This code defines a Target range that extends from A1 to the last row in column a - 22 and extends 10 columns.
Dim Target As Range
With wbshtSelect
Set Target = .Range("A1", .Cells(Rows.Count, "A").End(xlUp).Offset(-22)).Resize(, 10)
End With
'This is sure method to find or catch last row in any column even 'if some cell are blank in-between. (Excel-2007)`
'This works even if sheet is not active
'mycol is the column you want to get last row number
for n=1048575 to 1 step -1
myval=cells(n,mycol)
if myval<>"" then
mylastrow=n 'this is last row in the column
exit for
end if
next
ret=msgbox("Last row in column-" & mycol & "is=" & mylastrow)
Dim rng As Range
Dim FirstRow, LastRow As long
Set rng = Selection
With rng
FirstRow = ActiveCell.Row
LastRow = .Rows(.Rows.Count).Row
End With
Shai Rado's first solution is a great one, but for some it might need a bit more elaboration:
Dim rngCurr, lastRow
rngCurr = wbshtSelect.Range("B10").CurrentRegion
lastRow = rngCurr.Rows(rngCurr.Rows.Count).Row
If you want to know the last used row in the entire worksheet:
Dim rngCurr, lastRow
rngCurr = Range("A1").CurrentRegion
lastRow = rngCurr.Rows(rngCurr.Rows.Count).Row
Backing off from the range to the worksheet will get you the whole sheet extents of the range used on the sheet (which may be smaller than you expect if the sheet doesn't have data in the top rows; but it does include internal blanks)
TheRange.Worksheet.UsedRange.Rows.Count
If there is no data in the top rows, the following will get you the first row which you need to add to the above to get the highest row number
TheRange.End(xlDown).Row
So
Dim TheRange as Range
Dim MaxRow as Long
MaxRow = TheRange.Worksheet.UsedRange.Rows.Count + TheRange.End(xlDown).Row
Will get the highest row number with data (but not the whole sheet)
Before getting into complex coding why not build something on the below principle:
MaxRow = Application.Evaluate("MIN(ROW(A10:C29)) + ROWS(A10:C29) - 1")

Last row in column VBA

I wrote a short VBA code to automate stuff.
A short snippet is as follows:
Sub TEST()
Rows("1:2").Select
Selection.Delete Shift:=xlUp
Range("A1").Select
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$1:$O$148"), , xlYes).Name = _
"Table2"
End Sub
However, every Excel file differs with regards to the number of rows. Now when I recorded this macro it just takes the range of $A$1:$O$148. How can I adjust this part so that it automatically recognizes the last row and/or range?
I already tried:
.Range("A1").SpecialCells(xlCellTypeLastCell).Row
Instead of:
Range("$A$1:$O$148")
Thanks in advance!
Generally, you can find the last row / column and therefore the complete used range by using:
ActiveWorkbook.Worksheets("NAME").Range("A" & Rows.Count).End(xlUp).row
for the last row and
ActiveWorkbook.Worksheets("NAME").Cells(1, Columns.Count).End(xlToLeft).Column
for the last column.
I would advice against using UsedRange because if you have blanks in between, it will lead to mistakes.
This is the way I do it and I'm guessing this is a duplicate, but you can mimic hitting End-Up from a row well below your used range with
finalRow = Range("A65000").End(xlup).Row
then you can do
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$1:$O$" & finalRow & ""), , xlYes).Name = _
"Table2"
You can use the UsedRange property of your worksheet-object.
You can get the indexes of your last used row and column using
ActiveSheet.UsedRange.Columns.Count
ActiveSheet.UsedRange.Rows.Count
So you would basically use this like
With m_Sheet
' Use this range
.Range(.UsedRange.Rows.Count, .UsedRange.Columns.Count)
End With
I used the shortcut Ctrl+Arrow Down, which resulted in following VBA (after recording the macro):
Selection.End(xlDown).Select
This will do the trick:
Dim rSource As Range
With Worksheets("Sheet1")
Set rSource = .Range("A1", .Columns("A:O").Find(What:="*", After:=.Range("A1"), SearchDirection:=xlPrevious))
End With
This would help if you don't know much of the vba library or syntax like me.
Dim lastline as long
Dim lastColumnline as long
dim usedcells as long
dim i as long
dim YOURCOLUMN as long
dim count as long
Set ws = Worksheet("blablabla")
lastline = ws.UsedRange.SpecialCells(xlCellTypeLastCell).Row
usedcells = Application.WorksheetFunction.CountA(ws.Columns(YOURCOLUMN))
for i = 1 to lastline
if ws.cells(i,YOURCOLUMN) <> vbnullstring then
count = count + 1
if count = usedcells then
lastColumnline = i
'i is the lastColumnline
end if
end if
next i
This is how I locate last row:
Function lastRow(Optional strSheet As String, Optional column_to_check As Long = 1) As Long
Dim shSheet As Worksheet
If strSheet = vbNullString Then
Set shSheet = ActiveSheet
Else
Set shSheet = Worksheets(strSheet)
End If
lastRow = shSheet.Cells(shSheet.Rows.Count, column_to_check).End(xlUp).Row
End Function
The column is optional, if no value is given, it is column A.
My GitHub repository with LastThings is here.

Excel VBA to delete rows -- how to make this quicker?

I am current using the below code snippet i found on stackxchg to delete rows that whereby there is no numeric value in column A. This works however it is gruesomely slow for a sheet with 5000 rows. Is there any way I can get this thing to go faster? The concept is, I have some rows that will kick out dates only if a criteria is met, and a chart will be generated using the dates in this column. I would like the chart range reference to change with the rows, but this is tough since there are formulas in the rows all the way down (and for a chart to look good the rows need to be completely empty). My workaround was to find a macro which could delete these rows (but it's going too slow using this code). Any help would be appreciated.
Sub Sample()
Dim LR3 As Long, i3 As Long
With Sheets("Basket Performance")
LR3 = .Range("A" & .Rows.Count).End(xlUp).Row
For i3 = LR3 To 2 Step -1
If Not IsNumeric(.Range("A" & i3).Value) Or _
.Range("A" & i3).Value = "" Then .Rows(i3).Delete
Next i3
End With
End Sub
You can do a single delete at the end of your loop:
Sub Sample()
Dim LR3 As Long, i3 As Long, rng As Range
With Sheets("Basket Performance")
LR3 = .Range("A" & .Rows.Count).End(xlUp).Row
For i3 = LR3 To 2 Step -1
If Not IsNumeric(.Range("A" & i3).Value) Or _
.Range("A" & i3).Value = "" Then
If rng Is Nothing Then
Set rng = .Cells(i3, 1)
Else
Set rng = application.union(rng, .Cells(i3, 1))
End If
End If '<<EDIT
Next i3
End With
If Not rng Is Nothing then rng.Entirerow.Delete
End Sub
you can try this
Option Explicit
Sub delrow()
With ThisWorkbook.Worksheets("Basket Performance")
.Columns("A").Insert '<== insert a "helper" column for counting and sorting purposes. it'll be removed by the end of the macro
.Columns("B").SpecialCells(xlCellTypeConstants, xlNumbers).Offset(, -1).FormulaR1C1 = "=COUNT(R1C[1]:RC[1])"
.Cells.Sort key1:=.Columns("A"), order1:=xlAscending, Orientation:=xlTopToBottom, Header:=xlNo
.Columns("A").Cells.SpecialCells(xlCellTypeBlanks).EntireRow.Delete '<== maybe you don't need to delete but just define the chart range reference from row 1 down to the last row in column A with a number
.Columns("A").Delete '<== remove the "helper" column
End With
End Sub
you may want to consider not deleting "non numeric" rows once sorted out, and just defining the chart range reference from row 1 down to the last row in column A with a number instead

Resources