Last Row in Range - excel

Having an issue finding information and/or solutions that produce the desired result, so here it goes.
Right now, and potentially at production time, i will have a "template" named-range on a worksheet. On first use this NamedRange is only rngNamed1 but after the first use there could be more Named Ranges similar to this one, say up to rngNamed30.
Lets say on the 2nd run after building up to rngNamed30, that i need to add 3 more of the NamedRange, which results in rngNamed33.
What i need to do is basically find the last row & column of the last Named Range, so i know where to start the copying of data to and declare the next Named Range.
What i have tried so far:
Dim rng As range
Set rng = range("rngNamed1")
'Set rng = rng.Find("*", rng.Cells(1, 1), xlFormulas, xlPart, xlByRows, xlPrevious, False)
Debug.Print rng.Find("*", rng.Cells(1, 1), , , , xlPrevious).Address
The problem with most of the solutions out there is they are based on finding the last cell WITH DATA. I just need to know the Last Cell of the Range, irregardless of whether it contains data or not.

You can do this easily using the Row and Rows.Count of the range:
Sub NextRowAfterRange()
Dim ws As Worksheet
Dim rangeNom As String
Dim nextRow As Long
' Enter desired name here
rangeNom = "rngName1"
Set ws = ActiveSheet
nextRow = ws.Range(rangeNom).Row + ws.Range(rangeNom).Rows.Count
MsgBox nextRow
End Sub

Related

Copy Values instead of formulas in an offset copy

I am having trouble figuring out how to have my offset copy and paste code, copy values rather than formulas.
I have the following code which works perfectly but putting the copied cells in the next blank column, but I need the values, not formulas pasted in.
Sub Burndown_Snapshot()
'Copies the Overall Status Summary Data from the Dashboard and adds to the next empty column of the Historic Status table
'Triggered by the 'Burndown Snapshot' button on the dashboard
Dim column_number As Integer
column_number = Sheets("Historic Status").Cells.Find(What:="*", After:=Range("IV65536"), SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column + 1
Sheets("Dashboard").Range("C3:C7").Copy Destination:=Sheets("Historic Status").Cells(1, column_number)
End Sub
I figure i need a .PasteValues in there somewhere but im not sure where
Thanks
Copy Column Range
Set lCell = dws.Cells.Find("*", , xlFormulas, , xlByColumns, xlPrevious)
dws.Cells means all worksheet cells e.g. A1:XFD1048576, or A1:IV65536 for version prior to Office 2007.
The 2nd (omitted) argument (of the Find method) is After whose default parameter is Cells(1) or Cells("A1") i.e. the first cell of whichever range (dws.Cells) you apply the method to.
Combined with the xlPrevious parameter of the SearchDirection argument, it looks first in the last cell (e.g. XFD1048576).
By choosing the xlByColumns parameter of the SearchOrder argument, the next cell looked in will be XFD1048575 etc.
The xlFormulas parameter of the LookIn argument makes sure that the first non-empty cell is found (not ="" or "'", just empty (blank includes all three)).
The parameter of the 4th, the LookAt argument, is irrelevant and therefore omitted.
Set dCell = dws.Cells(1, lCell.Column + 1)
After the cell is found (Not lCell Is Nothing), we reference the cell (dCell)in the first row (1 before the comma) in lCell's column adjacent to the right (lCell.Column + 1)
Set drg = dCell.Resize(srg.Rows.Count, srg.Columns.Count)
The destination range has to be the same size as the source range to copy by assignment.
In this particular case, you can safely omit , srg.Columns.Count since there is only one column Set drg = dCell.Resize(srg.Rows.Count) (the default parameter of both arguments of the Resize method is 1.
Now you can copy values by assignment: drg.Value = srg.Value.
Sub Burndown_Snapshot()
'Copies the Overall Status Summary Data from the Dashboard and adds to the next empty column of the Historic Status table
'Triggered by the 'Burndown Snapshot' button on the dashboard
Dim sws As Worksheet: Set sws = ThisWorkbook.Worksheets("Dashboard")
Dim srg As Range: Set srg = sws.Range("C3:C7")
Dim dws As Worksheet: Set dws = ThisWorkbook.Worksheets("Historic Status")
Dim lCell As Range
Set lCell = dws.Cells.Find("*", , xlFormulas, , xlByColumns, xlPrevious)
If lCell Is Nothing Then Exit Sub ' no data in range
Dim dCell As Range: Set dCell = dws.Cells(1, lCell.Column + 1)
Dim drg As Range: Set drg = dCell.Resize(srg.Rows.Count, srg.Columns.Count)
drg.Value = srg.Value
End Sub
So I updated my code to include an extra copy paste function to give me the result I want, which also works, but requires a defined cut and paste range (which in most cases should be workable)
Sub Burndown_Snapshot2()
'Copies the Overall Status Summary Data from the Dashboard and adds to the next empty column of the Historic Status table
'Triggered by the 'Burndown Snapshot' button on the dashboard
Application.ScreenUpdating = False
Dim column_number As Integer
Dim rng As Range
column_number = Sheets("Historic Status").Cells.Find(What:="*", After:=Range("IV65536"), SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column + 1
Sheets("Dashboard").Range("C3:C7").Copy Destination:=Sheets("Historic Status").Cells(1, column_number)
For Each rng In Sheets("Historic Status").Range("B1:ZZ5")
If rng.Value <> "" Then
rng.Value = rng.Value
End If
Next rng
Application.ScreenUpdating = False
End Sub
However #VBasic2008s answer is much cleaner and doesn't have an arbitrary end point

VBA Extract Unique Values with Advance Filter From One Worksheet to Another

So I have this Workbook contains several worksheets.
In Sheet22 is a database and I need to extract unique values from one of its columns, which is Column "BC" (or Col 55).
here is to illustrate the unique values that I want to extract:
I need to extract the unique values to another worksheet (Sheet 32) starts from Range A1. But before that, I need to clear the target range first if it is not empty, then after that, paste the unique values.
so this is the codes I used, (fyi I'm, still new to VBA, so I found this code to be the closest to what I have in mind and modified it):
Option Explicit
Sub uniqueValuesFromRangeCustomer()
Dim rngCollectFrom As Range, targetRange As Range
Dim lastRow As Long
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Sheet22")
'Set the target range where the unique values will be copied to
Set targetRange = Sheets("Sheet32").Range("A1")
'Clear the target range if it is not empty
If targetRange <> vbNullString Then
'Find last row in target range column
lastRow = Sheets("Sheet32").Columns(targetRange.Column).Find("*", , , , xlByRows, xlPrevious).Row
'Delete target range
Sheets("Sheet32").Range(targetRange, Cells(lastRow, targetRange.Column)).Delete xlUp
'Reset target range (since it gets deleted)
Set targetRange = Sheets("Sheet32").Range("A1")
End If
'Define the range the unique values will be extracted from
'Find last row
lastRow = Sheets("Sheet22").Columns(55).Find("*", , , , xlByRows, xlPrevious).Row
'Set the source range
Set rngCollectFrom = Sheets("Sheet22").Range(Cells(2, 55), Cells(lastRow, 55))
'Use Advanced Filter
rngCollectFrom.AdvancedFilter Action:=xlFilterCopy, copytorange:=targetRange, unique:=True
When I run the code, I got error message: "Subscript out of range", and when I debug, it highlights the code:
Set sh: ThisWorkbook.Sheets("Sheet22")
I still don't understand how to modify this code to works, please someone if can help me with this problem.
Thanks before!

VBA to delete specific rows by row number

If anyone is willing to help me, I'd be most grateful.
Basically I would like to perform the same task as what was featured in this thread...
Excel Marcro - delete a row based on row number
I have a list of 3500+ lines and need to occasionally delete about 25-30 (non-consecutive) rows based on row number (the row #s will vary every time). I'd like to list the row numbers (to be deleted) on Sheet2 (in Column A) and have the code automatically read the row numbers on Sheet2 and delete those rows from Sheet1. I tried the code provided in the thread and I get a "run-time error 424" Object required. If I mouse over the error it tells me "SourceWks = Nothing" and "Sheet2 = Empty". I do have data contained in the sheet(s). I'm sure I'm just missing something simple.
I'll paste the code I'm using below (again it is from the original thread which was reported by the user to work just fine)...
Dim deleteRows As Range
Dim data() As Variant
Dim i As Double
Dim SourceWks As Worksheet, deleteWks As Worksheet
Set SourceWks = Sheet2
Set deleteWks = Sheet1
With SourceWks
data = .Range(.Cells(1, 1), .Cells(1, 1).End(xlDown))
End With
Set deleteRows = deleteWks.Rows(data(1, 1))
For i = 2 To UBound(data, 1)
Set deleteRows = Union(deleteRows, deleteWks.Rows(data(i, 1)))
Next i
deleteRows.Delete Shift:=xlUp
I've tried it both ways...keeping Sheet1 named "Sheet1" and Sheet2 named "Sheet2" and I've also tried changing the sheets to be named to: "deleteWKS" and "SourceWks" all with the same results.
If anyone can please let me know what I'm doing incorrectly, I'd be most appreciative.
Consider:
Sub rowKiller()
Dim SourceWks As Worksheet, deleteWks As Worksheet
Dim rng As Range, i As Long
Set SourceWks = Sheet2
Set deleteWks = Sheet1
Set rng = SourceWks.Columns(1).SpecialCells(2)
rng.Sort Key1:=rng(1), Order1:=xlDescending, Header:=xlNo, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
For Each r In rng
i = r.Value
deleteWks.Rows(i).EntireRow.Delete
Next r
End Sub
NOTES:
The reason we sort the row list descending because we want to delete the rows in Sheet1 from the bottom upwards.

For Each In: Is it possible to run through a single-column range and paste multiple columns, starting with that first FOR cell?

I've been having trouble trying to optimize a certain part of my code. I am performing a Monte Carlo simulation and I want to copy the values of a range a repeated number of times. To do this, I've used a For Each In structure. Below is a minimal example.
sub example()
Dim live As Excel.Range 'the range to be copied in each For Each In
Dim acell as Excel.Range 'For range
Set live = Range("C5:P5")
For Each acell in Range("B9:B90")
acell.value=live.value
Next acell
End Sub
The problem is that live spans multiple columns, while acell is just one cell; what ends up happening is just the first column is copied, the rest are blank. I have also used For Each acell in XYZ.rows where XYZ is a previously defined range of multiple columns and rows. However, this is considerably slower.
Is it possible to run through a single-column range and paste multiple columns, starting with that first cell?
Is this what you are looking for?
Sub example()
Dim live As Excel.Range 'the range to be copied in each For Each In
Dim acell As Excel.Range 'For range
Set live = Range("C5:P5")
live.Copy
Range("B9").PasteSpecial xlPasteValues, , , True
End Sub
You're almost there; you're just missing a tiny change in your code. You have to Resize the target range. Instead of
bcell.value=live.value ' bcell (presumably a typo) is only 1 column wide
use
acell.Resize(1, live.Columns.Count).Value = live.Value
It might be best to read C5:P5 in as an array:
Sub CopyLoop()
Dim copyRng(), targetRng As Range, cl As Range
copyRng = Range("C5:P5") 'Read in as array
Set targetRng = Range("B9:B90")
For Each cl In targetRng
Range("B" & cl.Row & ":O" & cl.Row) = copyRng
Next cl
End Sub

Select all data in sheet

I am writing a macro that opens a New Workbook and copies all data to a different Workbook.
The data always starts on C12 but we dont always know how many rows of data there are
The following code is giving an error:
Workbooks("Somesheet.xls").Activate
Sheets("Sheet1").Activate
With Range("C12").Select
End (xlDown)
End With
How do I select all rows from C12?
dim rng as range
with Workbooks("Somesheet.xls").Sheets("Sheet1").range("C12")
set rng = range(.cells(0,0), .end(xldown))
end with
You could also use
set rng = Workbooks("Somesheet.xls").range("C12").CurrentRegion
I use Find to detect the true last used cell as UsedRange can be unreliable with over- estimating the extent of the true used range unless it is forced to recalc in the code before being used. UsedRange can also be problematic unless it start from A1 (I had this issue with Rachel's code when testing data only in C12:C40, the answer provided was G34:G60)
From your question sample code it appears you only wanted column C data from C12 down (which is what this code does). It can readily be extended accross the true used range of columns, or as entire rows if needed
Sub GetData()
Dim wb As Workbook
Dim ws As Worksheet
Dim rng1 As Range
Dim rng2 As Range
Set wb = Workbooks("SomeSheet.xlsm")
Set ws = wb.Sheets("Sheet1")
Set rng1 = ws.Columns("C").Find("*", ws.[c1], xlFormulas, , , xlPrevious)
If rng1.Row > 12 Then
Set rng2 = ws.Range(ws.[c12], rng1)
MsgBox "Your range is " & rng2.Address(0, 0)
Else
MsgBox "Last row in " & ws.Name & " was only " & rng1.Row
End If
End Sub
In order to select all data from cell C12 down, use the UsedRange property to find the absolute last row used. Other methods will stop before the true end of the sheet if there is a blank cell in Column C. This snippet sets a Range variable that spans from C12 to the last used cell in the sheet:
Dim rng As Range
Dim lRowLast As Long, lColLast As Long
With ActiveWorkbook.Worksheets("Sheet1")
lRowLast = .UsedRange.Row + .UsedRange.Rows.Count - 1
lColLast = .UsedRange.Column + .UsedRange.Columns.Count - 1
Set rng = .Range(.Range("C12"), .Cells(lRowLast, lColLast))
End With
Note: use .Row + .Rows.Count - 1 to handle cases where the used range starts after the first row.
Edit: Updated example to fix the bug that #brettdj pointed out.

Resources