Using Range(Cell1 value, Cell2 value) - VBA - excel

I'm trying to define a range by the contents of two different cells, each containing the indirect cell addresses. I'm not sure whether it's possible, but here's an example:
Cell X100 contains value $A$1
Cell Y200 contains values $C$5
Is there any way I can use Range() and cells X100 and Y200 to arrive at Range("$A$1:$C$5")?
I've tried using Cells.Address but I can't figure out the right format for the application. Any help is appreciated!
Thanks
Edit
Thank you Tom! I have another question for you. The X100 cell is actually variable in my case, and I was using the following formula to find it:
Cells.Find("ID").Offset(1,0).Address
Is there any way to incorporate this sort of formula into the Range application? Or would it be easier to define a static cell in the spreadsheet containing this formula?
Thanks a bunch
Edit 2
Here you are! I'm dimming r and x as ranges and setting them as follows:
r = Cells.Find("ID").Offset(1,0).Address
x = Cells.Find("Description of initiative").offset(1,0).end(xldown).Offset(0,cells.Find("ID").Column-cells.Find("Description of initiative").Column).address
They're convoluted I know, but I printed them out and they are returning the right cells in the $A$1 format.
Hope this clarifies! Really appreciate your help.

Do you mean
Range(Range("X100").Value2 & ":" & Range("Y200").Value2)

Rather than working with addresses, work with Range objects.
Not sure I fully understand your setup, but something like this is maybe what you're looking for.
Sub Test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim startCell As Range
Set startCell = ws.Cells.Find(What:="ID") '<--- you should specify the other parameters of Find
Dim endCell As Range
Set endCell = ws.Cells.Find(What:="Description of initiative") '<--- again, specify parameters of Find
If startCell Is Nothing Then Exit Sub '<--- Find was unsuccessful
If endCell Is Nothing Then Exit Sub '<--- Find was unsuccessful
Set startCell = startCell.Offset(1, 0)
Dim columnOffset As Long
columnOffset = startCell.Column - endCell.Column
Set endCell = endCell.Offset(1).End(xlDown)
Set endCell = endCell.Offset(, columnOffset) '<--- there's a simpler way to do this, this just gets you back to startCell.Column, but preserving your logic
Dim myRange As Range
Set myRange = ws.Range(startCell, endCell)
End Sub
Here's the simpler way to get endCell instead of the offset.
Sub Test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim startCell As Range
Set startCell = ws.Cells.Find(What:="ID") '<--- you should specify the other parameters of Find
Dim endCell As Range
Set endCell = ws.Cells.Find(What:="Description of initiative") '<--- again, specify parameters of Find
If startCell Is Nothing Then Exit Sub '<--- Find was unsuccessful
If endCell Is Nothing Then Exit Sub '<--- Find was unsuccessful
Set startCell = startCell.Offset(1, 0)
Dim lastRow As Long
lastRow = endCell.Offset(1).End(xlDown).Row
Set endCell = ws.Cells(lastRow, startCell.Column)
Dim myRange As Range
Set myRange = ws.Range(startCell, endCell)
End Sub

Related

Excel VBA - Find a new Range based on the difference between two existing Ranges

Project Outline: The project I'm working on consists of a file with 2 sheets. The first sheet is a Dashboard of Reports with inputs about who worked it, what department it was for, and the timeframe of each report. This information is then transferred to a second sheet via a Button.
Right now the button copies the data from Dashboard to Data, adding the new information, starting in the first blank row (counted up from the bottom) of Column B. It then requests a Date input for that data from the user.
What I want to happen next:
I need to find the Range based on where the last input from Column A is, to where the last input of Column B is.
Example: Say there is Data from A1:A345. Say there is also Data from B1:B764. I need the VBA script to pull the range A346:A764 so I can then tell it to apply the Date from the input box in Column A for that range. (The dates may be historical and/or out of order so the input from the user is important. )
I'm currently using :
sh2.Cells(Rows.Count, 1).End(xlUp) - to Find the range of Column A
sh2.Cells(Rows.Count, 2).End(xlUp) - to Find the range of Column B
I'm having trouble figuring out a way to compare on range to the other in order to return the correct range for the data.
I've attempted using:
DO UNTIL (Excel crashed, it seems to loop continuously and I'm having trouble finding a way to get it to recognize when to stop)
DO UNTIL Attempt
`sh2.Cells(Rows.Count, 1).End(xlUp)(2).Select
Do Until IsEmpty(ActiveCell.Offset(, 1))
sh2.Cells(Rows.Count, 1).End(xlUp)(2).Value = myDate
Loop`
LOOP UNTIL (Excel crashed, same as above)
FOR EACH with IF NOT (I can't quite figure out how to compare the ranges to return a usable value)
FOR EACH Attempt
`Dim AColLR As Long
Dim BColLR As Long
Dim rngA As Range
Dim rngB As Range
Dim rngC As Range
Dim cell As Range
AColLR = sh2.Cells(Rows.Count, 1).End(xlUp).Row
BColLR = sh2.Cells(Rows.Count, 2).End(xlUp).Row
'Set rngB = sh2.Range("B2:B" & BColLR)
Set rngC = sh2.Range(BColLR - AColLR)
For Each cell In rngC
If Not IsEmpty(cell.Value) Then
cell.Offset(, -1).Value = myDate
End If
Next cell`
FUNCTION (I wasn't able to figure out how to call the function in the Sub, also Function might be broken?)
FUNCTION Attempt
`Function SetDifference(rngA As Range, rngB As Range) As Range
Dim sh1 As Worksheet, sh2 As Worksheet
Set sh1 = Sheets("Dashboard")
Set sh2 = Sheets("Data")
AColLR = sh2.Cells(Rows.Count, 1).End(xlUp).Row
BColLR = sh2.Cells(Rows.Count, 2).End(xlUp).Row
rngA = sh2.Range("A2:A" & AColLR)
rngB = sh2.Range("B2:B" & BColLR)
On Error Resume Next
If Intersect(rngA, rngB) Is Nothing Then
'if there is no common area then we will set both areas as result
Set SetDifference = Nothing
'alternatively
'set SetDifference = Nothing
Exit Function
End If
On Error GoTo 0
Dim aCell As Range
For Each aCell In rngA
Dim Result As Range
If Application.Intersect(aCell, rngB) Is
Nothing Then
If Result Is Nothing Then
Set Result = aCell
Else
Set Result = Union(Result, aCell)
End If
End If
Next aCell
Set SetDifference = Result
End Function`
I'm not sure which method is actually the correct one to use for this type of referencing.
Any assistance would be most appreciated!!
Something like this should work:
Dim cA As Range, cB As Range, ws As Worksheet, rng As Range
Set ws = ActiveSheet 'or some specific sheet
With ws
Set cA = .Cells(.Rows.Count, "A").End(xlUp).Offset(1)
Set cB = .Cells(.Rows.Count, "B").End(xlUp).Offset(0, -1)
Set rng = .Range(cA, cB)
End With
rng.Value = "dateHere"

define dynamic range in vba

I have the following problem:
I am trying to set the range client equal to a dynamically changing range.
In column AI, starting from cell 131, I have a list of clients, which varies in length depending on the years I download data for. I would like to set the range named client equal to this variable range. My code so far is:
Sub range()
Dim client As range
Dim lastrow As Long
Dim startingcell As Long
Set startingcell = range("AI131")
lastrow = Cells(Row.Count, startingcell.Column).End(xlUp).Row
Set client = range(startingcell, Cells(lastrow, startingcells.Column))
End Sub
It is not working though, any suggestions?
Thank you
Looks like you've an error with dimensioning and use of variables not being correct.
This will utilize only As Range which should help resolve the issue:
Dim startcell As Range, endcell As Range, client As Range
Set startcell = Cells(131, "AI")
Set endcell = Cells(Rows.Count, "AI").End(xlUp)
Set client = Range(startcell, endcell)

Selecting range inside For each loop works fine and but if outside the loop, gives error

When I select a range inside a for loop, it works fine:
For Each d1 In Range(Range("B2"), Range("B2").End(xlDown))
To improve the performance of the code, I tried selecting range outside the For Each loop as follows. But it gives me error.
Dim StartCell As Variant
Dim EndCell As Variant
StartCell = Range("B2")
EndCell = Range("B2").End(xlDown)
For Each d1 In Range(StartCell, EndCell)
----
----
Can anyone help in resolving the error?
Your two variables are actually ranges so you need to use the Set statement when assigning such (object) variables. Btw your code will fail if you have nothing underneath B2.
Dim StartCell As Range
Dim EndCell As Range
Set StartCell = Range("B2")
Set EndCell = Range("B2").End(xlDown)
For Each d1 In Range(StartCell, EndCell)

Range.Find function in Excel VBA not able to find row

My VBA subroutine can't seem to find a row with a matching date.
My Objective:
To find the row number of the first row in Sheet1 with a date equal to the oldest date in Sheet2
My process is:
Find the row in Sheet2 with the oldest date
Find the first row in Sheet1 with the
same date and return the row number of that row.
What Happens
When I run my sub I get is Run-time error '91' - Object variable or With block variable not set.
If I try "Msgbox FindRow Is Nothing" I get the true response.
This makes no sense, since in this system Sheet1 E6 has the same value as Sheet2 E8
MY DATA:
Sheet1 (E2 - E8):
09/10/2013
09/10/2013
14/11/2013
14/11/2013
17/11/2013
17/11/2013
20/11/2013
Sheet2 (E2 - E8):
01/12/2013
01/12/2013
27/11/2013
27/11/2013
24/11/2013
24/11/2013
20/11/2013
17/11/2013
My code so far:
Private Sub transferPostings()
Dim EarliesNewDate As Variant
Dim FirsCandidateOverlappingRow, rowCountHist, onlyNewRowsCount As Integer
Dim wsHist, wsNew As Worksheet
Dim possibleDuplicates, onlyNew, FindRow As Range
Set wsHist = Worksheets("Sheet1")
Set wsNew = Worksheets("Sheet2")
wsNew.Range("E1").End(xlDown).NumberFormat = "General"
Range(wsHist.Range("E2"), wsHist.Range("E2").End(xlDown)).NumberFormat = "General"
EarliesNewDate = wsNew.Range("E1").End(xlDown).Value
Set FindRow = Range(wsHist.Range("E2"), wsHist.Range("E2").End(xlDown)).Find(EarliesNewDate)
wsNew.Range("E1").End(xlDown).NumberFormat = "dd/mm/yyyy"
Range(wsHist.Range("E2"), wsHist.Range("E2").End(xlDown)).NumberFormat = "dd/mm/yyyy"
MsgBox FindRow.Row
End Sub
Any help with this problem is much appreciated.
Your .Find command is not supplying any parameters. This means that it is using the parameters that were last used (or the defaults if it wasn't used in this session). At a minimum, you should be using LookIn:=xlValues and you should probably be specifying LookAt:=xlWhole.
Sub transferPostings()
Dim EarliesNewDate As Variant
Dim FirsCandidateOverlappingRow, rowCountHist, onlyNewRowsCount As Integer
Dim wsHist As Worksheet, wsNew As Worksheet
Dim possibleDuplicates, onlyNew, FindRow As Range
Set wsHist = Worksheets("Sheet1")
Set wsNew = Worksheets("Sheet2")
wsNew.Range("E1").End(xlDown).NumberFormat = "General"
Range(wsHist.Range("E2"), wsHist.Range("E2").End(xlDown)).NumberFormat = "General"
EarliesNewDate = wsNew.Range("E1").End(xlDown).Value
Set FindRow = wsHist.Range(wsHist.Range("E2"), wsHist.Range("E2").End(xlDown)).Find(What:=EarliesNewDate, LookIn:=xlValues, LookAt:=xlWhole)
wsNew.Range("E1").End(xlDown).NumberFormat = "dd/mm/yyyy"
Range(wsHist.Range("E2"), wsHist.Range("E2").End(xlDown)).NumberFormat = "dd/mm/yyyy"
MsgBox FindRow.Row
End Sub
You didn't mention that the dates in Sheet1!E:E were the results of formulas. I strongly suspect they are and that would have been worth mentioning.
BTW, when declared as Dim wsHist, wsNew As Worksheet, wsHist is a variant not a worksheet. It doesn't matter in this case but you should be aware of how variables are declared for future practise. see Declaring Variables or Declaring Variables for more details.

VBA - How to set the start and end row when setting a range by column numbers

Suppose I set a range of multiple distinct columns by column number like this:
Set rngData = shtData.Range(Columns(1), Columns(2), Columns(5))
But I only want the range to start at for example row 5 and end at row 10.
Can I specify this in the Set rngData statement? Appreciate any help
EDIT.
Thanks to KazJaw this is the solution that worked for me:
Dim shtData, rngData
Set shtData = Worksheets("Data")
Set rngData = Union(shtData.Columns(1), shtData.Columns(2), shtData.Columns(5))
Set rngData = Intersect(rngData, shtData.Rows("5:10"))
There are few possible ways but I'm not sure which would be best for you. My first and possibly simplest proposal is the following:
Set rngData = shtData.Range(Columns(1), Columns(2), Columns(5))
set rngData = Intersect(rngData, shtData.Rows("5:10"))
But, your current range will not work anyway. You could use something like this instead:
Set rngData = shtData.Range("A:B, E:E")
or if you need to keep numeric index of columns than you could go this way (complete code):
Set rngData = Union(shtData.Columns(1), shtData.Columns(2), shtData.Columns(5))
set rngData = Intersect(rngData, shtData.Rows("5:10"))
Edit- to extend and explain: See below subroutine and comments inside
Sub Test_Selection()
'Variant A- select range from column 1 to 5
ActiveSheet.Range(Columns(1), Columns(5)).Select
'Variant B- select range of columns: 1, 2 and 5
With ActiveSheet
Union(.Columns(1), .Columns(2), .Columns(5)).Select
End With
'This will not work
ActiveSheet.Range(Columns(1), Columns(2), Columns(5)).Select
End Sub
So, variant B above is able to select not continuous range like this:
And final explanation about Intesect, for all who are interested. This procedure would give result as presented in the picture below:
Sub Final_Combination()
Dim shtData As Worksheet
Set shtData = ActiveSheet
Dim rngData As Range
Set rngData = Union(shtData.Columns(1), shtData.Columns(2), shtData.Columns(5))
Set rngData = Intersect(rngData, shtData.Rows("5:10"))
'or simply combined in one line of code
Set rngData = Intersect(Union(shtData.Columns(1), _
shtData.Columns(2), _
shtData.Columns(5)), _
Rows("5:10"))
rngData.Select
End Sub

Resources