Why is Range.Find() method so confusing? - excel

This code gives me a 424 error "Object Required".
Dim playerLocation As Range
Set playerLocation = Sheets("World Map").UsedRange.Find("&").Address
And this works fine
Set playerLocation = Sheets("World Map").UsedRange.Find("&")
But when i put them into the immediate window:
?Sheets("World Map").UsedRange.Find("&").Address
$T$18
?Sheets("World Map").UsedRange.Find("&")
&
Is it just me or this completely backwords? Doesn't a Range variable take a range object? But it creates an error when i explicitly give it the Address of a cell. I'm so confused.

From Microsoft, Range.Find method:
Return value:
A Range object that represents the first cell where that information is found.
However, the Range.Address property:
Returns a String value that represents the range reference in the language of the macro.
Perhaps one way of thinking about it, is that by using .Address explicitly, you're asking for a String. You're not asking for an Object (which Range) is. If you were, you'd correctly declare your object and just leave off .Address.
And of course, you can always get the Address property from a Range Variable...Dim findRng as Range // Set findRng = Worksheets(1).Cells.Find("something") // debug.print findRng.Address.
You can also access all other Range properties now, so when I personally need to use Find, I tend to set that as a Range, so I don't have to "work backwards" later if I want to, say bold the cell, etc.

Related

Clean up Named Range Addresses with Errors (e.g. #REF!)

I set up a named range, let's call him RngIn.
He has 3 cells, and his address refers to A1:A3
Next, I delete Row 2.
My RngIn now shows #REF! error (correctly) in its RefersTo property:
"=A1,Sheet1!#REF!,A2"
This means I cannot manipulate the rest of that named range using VBA, because of the Method 'Range' of Global Object error.
The range is created during a process, and if a user subsequently needs to delete one row for whatever reason, my future code will fail because it needs to know where the rest of the named range data is...
I have tried many ways to access the remaining address information for this range, in VBA, but failed so far, e.g.
Dim RngAddress As String
Dim RngIn As Range
Set RngIn = Range("A1:A3")
RngAddress = RngIn.Address
RngAddress = RngIn.RefersToRange.Address
RngAddress = RngIn.RefersTo
RngAddress = Replace(RngIn.Address, "Sheet1!#REF!", "")
What I ideally want to see in a text string as the result for RngIn is:
"=A1,A2"
Because A2 is now the location of the data which was originally in A3.
Not sure I understand this well: your example code does not use Defined Names (aka Named Ranges).
lets suppose you create a Name called RangeIn that refers to A1,A3,A5 and you then delete Row 3.
The RefersTo for RangeIn is now =Sheet1!$A$1,Sheet1!#REF!,Sheet1!$A$4
This code removes the Sheet1!#REF!, to leave the Name RangeIn referring to =Sheet1!$A$1,Sheet1!$A$4
Option Explicit
Option Compare Text
Sub ChangeRef()
Dim strAd As String
strAd = ThisWorkbook.Names("RangeIn").RefersTo
strAd = Replace(strAd, "Sheet1!#REF!,", "")
ThisWorkbook.Names("RangeIn").RefersTo = strAd
End Sub
In cases like this, I set the start and end points of my named ranges to be the cell above and the cell below the range where the user can delete, and then use the OFFSET or INDEX function to resize that range to exclude my bookmarks. Or I use Excel Tables, which can handle row deletions without returning #REF errors.

Excel: VBA referencing named range based on string variable

How do I reference/select a named range based on a string variable with the text being the name ranged name?
Example:
'Target is range variable which is set to cell that is double clicked.
'For this example lets say the cell value is "A1A"
Dim binName As String
binName = "B1" & Target(1).Value
MsgBox(binName) 'This displays "B1A1A" which is the name of the named range
Range(binName).Select 'I want to select the range with the name B1A1A
This gives me
Run-time error '1004':
Method 'Range' of object'_Worksheet' failed
on the last line of the above code.
I understand that Range() is looking for an object, but I dont know how to refer call a range name from a string variable.
Thank in advanced for any help.
Resolution Edit:
Per Davids recommendation below, I changed
Range(binName).Select
to
Application.Goto ThisWorkbook.Worksheets("B1").Range(binName) 'where "B1" is the worksheet name
It's possible to have a Workbook scoped range that is still explicitly assigned to a single worksheet, which I gather is what you want (Name refers to some range on some other worksheet, etc.).
If you're doing this as UI, rather than Select try using the following:
Application.GoTo Range(binName)
Or:
Application.GoTo [binName]
Tested, and seems to work even when a range is explicitly on another worksheet, Application.GoTo takes care of toggling to that sheet and selecting that range.
Application.Evaluate(binName).Select
Application Evaluate will evaluate a string and resolve the reference. It accepts strings as arguments, and doesnt need to resolve to a range (for example, Application.Evaluate("10") would result in a return of 10).
For more information, check out the MSDN documentation: https://msdn.microsoft.com/en-us/vba/excel-vba/articles/application-evaluate-method-excel.
EDIT: Worth noting, this isnt properly error handled, so it could potentially return a Nothing reference, or an error, if the input string is not a valid named range.
Additionally, ThisWorkbook.Sheets("SomeRangeName").Select should work (and does work) just fine. It is more likely that there is something wrong with the name of your range.

Use Named Range in UDF

I'm trying to create a UDF that will use a named range. My named range ("best_Grade") is a single cell, with a value. (The named range is scoped to the Workbook).
In a workbook module, when I try to create the variable using a named range, I get
Run-time error '1004': Method of 'Range' of object '_Global' failed
Neither line works:
Dim namedRng As Range
Dim locDataWS As Worksheet
Set locDataWS = Sheets("Approval matrix 16")
Set namedRng = Range("best_Grade") ' errors
Set namedRng = locDataWS.Range("best_Grade") ' When I take above line out, this line errors too
and I've tried:
Dim wb As Workbook
Set wb = ActiveWorkbook
Set namedRng = wb.Names("best_Grade").RefersToRange
How come it's erroring out? This page says it should be working, no? Do I have to put this UDF on the actual sheet object, and not in a workbook module?
Edit: Note: the named range is not set to a cell, but a SumIf formula (best_Grade = SumIf(A2:A10,"x",...)` which may be causing the error?
Edit2: Yeah, that's why I think. I created a named range for a random cell, and was able to use Range("a_grade").Value and it returned the expected value. Since my best_Grade range is a formula, I think that's why it's erroring out. However, I don't know why, as I'd think a named range is a named range, no matter what it's made up of...
Edit n+1: Note there are two "answers" to this. If I wanted to continue using a named range as a Range variable, see my answer below. However, what I really wanted to do was what #MacroMarc posted, so I chose that as the "Answer".
You need to use the Names collection instead:
Sub t5()
' named range "Test" is `=Sum($A$1:$A$4)`
Dim rng As Double
rng = Evaluate(Names("Test").Value)
Debug.Print rng
End Sub
There are various properties that Name objects have to return string representations.
Sub t5()
' named range "Test" is `=Sum($A$1:$A$4)`
Set wb = ActiveWorkbook
Dim rng As String
rng = wb.Names("Test").RefersTo
Debug.Print rng
rng = Application.Evaluate(wb.Names("Test").RefersTo)
Debug.Print rng
End Sub
After some testing I found the above worked...and kind of interesting. I got the lead from Macro Man's comment as well at Chip Pearson post.
The key is the defined names returns a string ="your result" so you can either evaluate it to get the answer, or you can do some string manipulation to pull off the quotes and equal sign. You really were close with your RefersToRange choice.
See Vegard's comment under your own posted answer.
The reason it wasn't working is because my named range best_Grades was not a cell reference, but a formula instead. Thus, when using Range("best_Grades").Value, it was erroring out. (best_Grades = SumIf(A2:A10,"x", B2:B10, ...)
Not sure why, since I'd think a named range is a named range, regardless of what makes that up...but I suppose not.
For now, my solution is just to create another named range, based on an actual cell value, and then use that. (theBest_Grades = A2). Then, I can call simply Range("theBest_Grades").Value without any issues.
I'll leave this open for a few days, in case someone has an idea of how I can keep my formula named range, and use that in VBA.
Edit: This was basically how I originally had the worksheet/named range:
with the named range being given as:
But, as I said, you can't use that type of named range in VBA (at least not that I have found).
So, to solve it, I just used that SumIf in the cell, and gave that cell the named range:
And now I can use Range("findWindow_Example").Value without issue.
Edit n+1:
I tried doing a simple test with a Double, same thing though, it errors out:
Sub t5()
' named range "Test" is `=Sum($A$1:$A$4)`
Dim rng As Double
rng = Range("Test") 'Run time error 1004
Debug.Print rng
End Sub
One thing I haven't seen mentioned here is that a ground rule for UDF's is broken here IMHO:
ALL information a UDF needs should be passed to the UDF through its arguments.
If you adhere to that rule, using any range name becomes simple, since the value of the range name will automagically be transferred to the argument.
The correct way to solve the problem has been found by more than one answerer, but as I said in the comments (and subsequently, thought might be of interest to others), the reason for the error wasn't specified yet.
The named range you defined does not return a range object. This means that this code:
Dim namedRng As Range
Set namedRng = Range("best_Grade")
couldn't possibly work (primarily because the named range returns a numerical value. If it returned a string address representation, it might have worked with some syntax improvements).
To illustrate this from the compiler's point of view, look at the print-outs in the immediate window here (the first line in particular):
If we assume the initial code to be pseudo-code, what was being asked of the compiler was to construct a range out of the formula (not its' result either!).
So if we swap Set namedRng = Range("best_Grade") for Set namedRng = Range(Names("namedRange")) the result might presumably (but not necessarily -- see end of post!) look like:
Set rng = Range("=SUMIF('Ark1'!$B$1:$B$5, "x", 'Ark1'!$A$1:$A$5)")
And of course, this would not work. But throwing namedRange into an Evaluate would, as the other answers demonstrate, be perfectly legal!
Interestingly, if we do ? Evaluate(Names("namedRange")) (omitting the .Value), we get an Error 2015, despite being able to ask the compiler ? Names("namedRange") and get a string in return!

Get range identifier from range object excel vba

I have some VBA code that works on named ranges that are set up externally. How can I get the actual cell reference from this range? For example
Dim rangeID As String
rangeID = ActiveSheet.Range("MyNamedRange").UnknownFunction
Sets rangeID to "CG13" if the named range "MyNamedRange" refers to CG13
ActiveSheet.Range("MyNamedRange") already is the "actual cell reference." It references the cell object. You should directly use that object reference anywhere you need a cell in your code.
The textual representation of the address of that cell is ActiveSheet.Range("MyNamedRange").Address. You can provide parameters to get the address in the form you want (e.g. to get "CG13" you call Address(False, False, xlA1)).

Excel macro input type not returning correct value

I'm trying to delete all cells that have the same interior color in an Excel 2010 worksheet using the following code:
Dim myRange As Range
Set myRange = Application.InputBox("Select a cell to remove based on background fill color.", Type:=8)
Range("C3").Interior.Color = Range(myRange).Interior.Color
But when I run the code, I get the following error:
Method 'Range' of object '_Global' failed.
I've figured out that even though I'm asking for the cell reference as a range object (Type:=8), myRange is being set to the value of the cell. For example, the value in A2 is "Test." myRange should come back asA2, but it's coming back as "Test." Any idea why that would be?
Just do:
Range("C3").Interior.Color = myRange.Interior.Color
You have already dimensioned myRange as a Range variable, so you don't need to qualify it as Range(myRange). If you do that, it is trying to evaluate the myRange.Value, and that's why you're getting the error.
Cheers.
Your problem is with Range(myRange). The Range object can be used in one of two ways; either a string (i.e. Range("A1:B2")) or two other Range objects, representing the top left and bottom right of a rectangle (i.e. Range(Cells(1,1),Cells(2,2))). You are providing it with a single Range object.
I suspect you meant to do this:
Dim myRange As Range
Set myRange = Application.InputBox("Select a cell to remove based on background fill color.", Type:=8)
Range("C3").Interior.Color = myRange.Interior.Color

Resources