VBA point variable to range - vba

I want to point to a cell as a range in VBA. I've tried using:
Dim range
range = Sheet("sheet").Range("A1")
But this just returns the value in the range. What I actually want is the range object so I can manipulate it, e.g. by setting range.Value = "Hello"
Any ideas?

First, I strongly recommend you to make explicit declaration of variables in your code mandatory. Go to Tools - Options, in the Editor tab check "Require variable Declaration", or put Option Explicit in the first line of all your scripts.
Second, I think there is a small typo in your code, it should be Sheets.("sheet").
To answer your question, with range = Sheets("sheet").Range("A1") you are assigning a value variable, not an object. Therefore the default variable of the range object is implicitly assigned, which is value. In order to assign an object, use the Set keyword. My full example code looks like this:
Option Explicit
Public Sub Test()
Dim RangeObject As range
Set RangeObject = Sheets("Sheet1").range("A1")
RangeObject.Value = "MyTestString"
End Sub
This should put the text "MyTestString" in cell A1.
Edit: If you are using named ranges, try RangeObject.Value2 instead of RangeObject.Value. Named ranges do not have a Value property.

Related

VBA code help, issue with ranges [duplicate]

This is part of a larger code, but this snippet isn't working. I'm trying to just set two cells equal to each other, but it's not working. When I use the .Range("v1_copy"), the code runs, but when I name that range and place it as a variable (myCopyRange), the code doesn't run and I get the error: Compile error: Method or data member not found. Any help would be appreciated!
Sub copy_paste_test()
Dim myCopyRange As Range
Dim myPasteRange As Range
Dim myWS1 As Worksheet
Dim myWS2 As Worksheet
Set myWS1 = Sheets("Sheet1")
Set myWS2 = Sheets("Sheet2")
myCopyRange = Range("v1_copy")
myPasteRange = Range("v1_paste")
'myWS2.Range("v1_paste").Value = myWS1.Range("v1_copy").Value
' This line works, but the below line doesn't
myWS2.myPasteRange.Value = myWS1.myCopyRange.Value
' This should be the exact same, just substituting the variable, but doesn't work
End Sub
You're missing the Set keyword for your Range object reference assignments to myCopyRange and myPasteRange.
But for retrieving a named range, the best place to go if you want fully explicit code that does what it says and says what it does, is to dereference the Name from the appropriate Names collection.
If the names are workbook-scoped, qualify with a Workbook object - here a book object variable, but depending on needs ActiveWorkbook or ThisWorkbook work just as well:
Set myRange = book.Names("name").RefersToRange
If the names are worksheet-scoped, qualify with a Worksheet object - here a sheet object variable, but ActiveSheet works just as well:
Set myRange = sheet.Names("name").RefersToRange
That way the code won't break if the workbook is renamed, or if the user changes the "tab name" of the sheet. It won't break as long as the name exists in the queried Names collection.
'myWS2.Range("v1_paste").Value = myWS1.Range("v1_copy").Value
' This line works, but the below line doesn't
myWS2.myPasteRange.Value = myWS1.myCopyRange.Value
' This should be the exact same, just substituting the variable, but doesn't work
This should be the exact same - no. myWS1.myCopyRange is illegal: myWS1 is a Worksheet object: the Worksheet interface doesn't have a myCopyRange member, hence method or data member not found.
Since myCopyRange is a Range object, it knows about its Parent which is the Worksheet it belongs to: there's no need to qualify it... and there's no need to dereference it again either - this is enough:
myPasteRange.Value = myCopyRange.Value
Range will only apply to the currently active worksheet unless you add the Worksheet reference at the time of assignment (not at the time usage as you have done).
Since you are access a different worksheet, your second assignment will fail.
myCopyRange = myWS1.Range("v1_copy")
myPasteRange = myPasteRange = Range("v1_paste")
See the Range Object Documentation:
When it's used without an object qualifier (an object to the left of
the period), the Range property returns a range on the active sheet
... Use the Activate method to activate a worksheet before you use the
Range property without an explicit object qualifier
If you are trying to refer to NamedRanges and not a name held in a VBA variable, you need to change the way you are accessing the range.
Workbook-scope NamedRanges do not use worksheet reference - since they don't apply to a worksheet, they apply at the workbook level. If you need to add a qualifier, you add the workbook:
Range("MyBook.xls!MyRange")
If you are referring to Worksheet-scope NamedRange, you need a qualifier, but it goes inside the quotations:
Range("Sheet1!Sales")
Properly create ranges by using Set and don't refer to worksheets before them. Workbook-scoped ranges don't need to be tied to any worksheet.
Sub copy_paste_test()
Dim myCopyRange As Range
Dim myPasteRange As Range
Set myCopyRange = Range("v1_copy")
Set myPasteRange = Range("v1_paste")
Range("v1_paste").Value = Range("v1_copy").Value
'myPasteRange.Value = myCopyRange.Value
End Sub

VBA to Assign Named Range Reference

I am trying to assign a named range's reference from VBA. I generate a string that I want to be the named range's reference.
Ultimately my code is much more complicated than what I will show here but this boils out the gist of my problem. I can assign the reference no problem, however, when I look at the named range in the names manager I notice that all of my quotes have been doubled. For instance I have a named range called "exampleName" and so I run the following:
Sub Example()
Dim exampleStr As String
exampleStr = "EVALUATE("" = "" &ADDRESS(5,8))"
ThisWorkbook.Names("exampleName").RefersTo = exampleStr
End Sub
The code executes alright, but if I check under Name Manager I see:
As you can see, under Refers To I've 'earned' an extra set of quotes around the equals sign. For my actual sub this becomes problematic as I have to iterate, augmenting Refers To on each iteration. Each time I iterate, all of my quotes are replicated. Within only a few turns I have way more quotes than intended.
Any input on where I'm going wrong?

(VBA) when to use .cell(1,1) or .cell(1,1).value reference

In my macros when I'm referencing to a value found in a cell, I've been inconsistently using either .cell(r,c) or .cell(r,c).value.
dim c as variant
c = sheet1.cell(1,1) 'or sheet1.cell(1,1).value
Are both references correct or is there a preferred way?
.Value is the default property of the range object. Therefore, when you assign something like this:
myVar = myRange
it is equivalent to myVar = myRange.Value, because you are assigning a variable not an Object.
However, if you use Set, like this:
Set myObj = myRange
You would be assigning an object reference. The keyword Set tells VBA that you are assigning an object reference. The absence of Set makes VBA conclude that you implicitly want to get the .value, the default property of the range.
It is a good programming practice to use .value explicitly, for two reasons:
1- It makes code more readable, because the reader does not have to guess what is going on implicitly
2- With the advent of VB.net, the keyword Set has disappeared; the syntax for assigning an object or a normal variable becomes the same. For this reason, the default property idiom has disappeared with VB.net. Therefore, good practice is to use .value in VBA as well, because it makes an eventual porting of your code to VB.net much easier.
I always use .Value2 to get the value of a cell (or an array of vables from a range). If I don't use .Value2 it means I want a reference to the Range objects and not the value. For example
Dim r as Range
Set r = Range("A1")
Dim x as Double, i as Integer
x = r.Offset(1,0).Value2
Dim vals() as Variant
vals = r.Offset(1,0).Resize(10,1).Value2
For i=1 to 10
vals(i,1) = CDbl(i)/10
Next i
r.Offset(1,0).Resize(10,1).Value2 = vals
In addition I dont use the Cell() method because the location of cells may change in the future. I use named ranges with the .Offset() and .Resize() methods to set the range of cells I want read or write values to. So in the above code I would never use Range("A1") but something like Range("my_table") with a named range "my_table" defined on the top left cell of where I interact with.
There is a little known shortcut to get the value of a cell with the [] notation
Dim x as Double
x = [A2]
// This is the same as x = Range("A2").Value2

How do I use RefersToRange?

Can anyone tell me how to use RefersToRange in vba? and what and when is the need of it.
Please provide with simple example first.
Thanks in advance.
In Excel, there is the concept of a named range, that is a range of cells which has a name attached to it. This is represented by the Name object.
The RefersToRange method:
Returns the Range object referred to by a Name object.
For example, let's say I want to read the values only in the print area of the current worksheet. I need the Name object in order to access the print area, but I can't do anything useful with it; if I want to do something useful I have to access the range of cells referred to by that name:
Dim n As Name
Set n = ActiveWorkbook.Names("Print_Area")
Dim rng As Range
Set rng = n.RefersToRange
Dim values() As Variant
values = rng 'I can't read values with a Name object, but I can with a Range object
One thing I have discovered is that sometimes referring to a named range in this fashion:
ThisWorkbook.Range("DownloadPictures").Value = "yes"
results in:
Run-time error '1004':
Method 'Range' of object '_Worksheet' failed
But referring to the named range in this fashion:
ThisWorkbook.Names("DownloadPictures").RefersToRange = "yes"
works fine. My particular circumstance is that the named range ("DownloadPictures") is scoped to the entire workbook, which has several worksheets. I am referring to the name in one of the worksheet's Worksheet_Calculate subroutines. I don't understand why the first method causes an error and the second does not but apparently this is one reason to use the RefersToRange property.
RefersToRange is, one of many ways, to 'point' a range. For example,
ThisWorkbook.Names("DownloadPictures").RefersToRange = "yes"
the above code, points to the range, which can be a cell, named "DownloadPictures" and sets it value to "yes". As a matter of fact, I'd rather use,
ThisWorkbook.range("DownloadPictures").Value = "yes"
The 'Name' in MS Excel is similar to the Variant variable type, but unlike the variables you 'Dim' in the VB code, the 'Name' only be used (or you can consider it is only be used) in the Workbook. The 'Name' and variables are not interfered with each other.
If you open the 'Name Manager', the concept becomes easier to understand. The Name can be created to refer to a cell, a range of cell (a range), some value (so called constant), or a formula.
Each Name object represents a defined name for a range of cells. Names can be either built-in names—such as Database, Print_Area, and Auto_Open—or custom names. ---MSDN
As a Name can refer to range, constant or a formula .RefersToRange specifically refer to a range. And return false if not so.

VBA User Form Range to Variable- Syntax Issue

I've created a VBA Userform in Excel, where the user selects several ranges. Within the user form, I have input validation through a series of If then MsgBox statements.
As part of this, I need to take the inputted range and use it as a variable.
Assuming that the range is Me.ActDurations, I tried to use this:
dim ActDur as range
set ActDur = Me.ActDurations
I've also tried:
set ActDur = Me.ActDurations.Value
And that doesn't work either. What is the proper syntax for this? Using the first type gives me a type mismatch error.
The .Value property of RefEdit returns a string. To use it as a range, you should use the string as a range name. Sample code below.
Dim address as String
Dim targetRange As Range
address = RefEdit1.Value 'String returned by the selected range using RefEdit.
Set targetRange = Range(address)
'Do some code here.
Modify as necessary for your code. ;)