When named range is a static cell or a range I'd refer to it by its name and change cell property like so:
Worksheets("Manual_Input").Range("test_range").Interior.Color = vbYellow
Unfortunately, when named cell/range has formula in it, for example, =ROUND((Manual_Input!$F$17/1000),1)
I cannot seem to actually refer to $F$17 and change its properties. Running above statement returns 'Application-defined or object-defined error', although can be accessed by running:
ActiveWorkbook.Names("test_range")
which returns following:
=ROUND((Manual_Input!$F$17/1000),1)
I can even evaluate this named range by running:
Worksheets("Manual_Input").Evaluate("test_range")
which returns result of the formula
=ROUND((Manual_Input!$F$17/1000),1)
How do I get to the range F17 by its name in VBA?
Split(ActiveWorkbook.Names("test_range").RefersTo, "$")(1) & Split(Split(ActiveWorkbook.Names("test_range").RefersTo, "$")(2), ",")(0) should return the string you are looking for.
ActiveWorkbook.Names("test_range").RefersTo will return always in english the formula you applied to that range, as string. so you need extra function to split and get the text part you want.
In my case, i created a name like yours, referring to cell G9:
My code:
Sub TEST()
Dim vName As Name
Set vName = Application.ThisWorkbook.Names("test_range")
Debug.Print vName.RefersTo 'string with reference in english, not local
Debug.Print Split(vName.RefersTo, "$")(1) & Split(Split(vName.RefersTo, "$")(2), ",")(0) 'cell inside that string
Set vName = Nothing
End Sub
My output:
You'll need to use other functions like MID,LEFT,RIGHT, SPLIT to get exactly the text part you want to isolate.
I have that table in the sheet "Definições" and when searching for "Carregamento para" on the "Norma" column it jump the A2 cell for some reason... I mean the find does not mentioned the A2 cell it goes straight to A5.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
Set ws = Worksheets("Definições")
Dim tbl1 As ListObject
Set tbl1 = ws.ListObjects("Tabela1")
Dim cell1 As Range
Dim cell1a As Range
Set cell1a = tbl1.ListColumns("Norma").DataBodyRange
Set cell1 = tbl1.ListColumns("Norma").DataBodyRange.Find(What:="Carregamento para", After:=tbl1.DataBodyRange.Cells(cell1a.Row - 1, 1))
Debug.Print "DataBodyRange:" & tbl1.ListColumns("Norma").DataBodyRange.Address
Debug.Print "A2.Value:" & ws.Range("A2").Value
Debug.Print cell1.Address
Debug.Print cell1a.Address
End Sub
The Immediate window is returning this. Using header name "Norma" of the index 1 on the ListColumns it's the same result.
DataBodyRange:$A$2:$A$7
A2.Value:Carregamento para
$A$5
$A$2:$A$7
Any idea where the error is... Did try to search for something similar in google but nothing about this kind of error/bug ...
The Find method has a optional parameter After. From the documentation
After: The cell after which you want the search to begin. This corresponds to the position of the active cell when a search is done from the user interface.
Notice that After must be a single cell in the range. Remember that the search begins after this cell; the specified cell isn't searched until the method wraps back around to this cell.
If you do not specify this argument, the search starts after the cell in the upper-left corner of the range.
In order to start the search at the first cell of a range, specify After as the last cell in the range: in your case that would be (since you already have Set cell1a = tbl1.ListColumns("Norma").DataBodyRange lets use that)
After:=cell1a.Cells(cell1a.Cells.Count)
Note also the Remaks section of the help
The settings for LookIn, LookAt, SearchOrder, and MatchByte are saved each time you use this method. If you do not specify values for these arguments the next time you call the method, the saved values are used. Setting these arguments changes the settings in the Find dialog box, and changing the settings in the Find dialog box changes the saved values that are used if you omit the arguments. To avoid problems, set these arguments explicitly each time you use this method.
The following excel sub is a filter that is filtering out rows based on the rows in the criteria row.
The code works well when the ranges are set with absolute data. I want to change the code to take the range from references stored as cell values (an indirect reference) but I cannot find a way to adapt other code snippets I see to work and I wonder if anyone can help me. I am not a programmer.
The problem is that as new data is inserted from time to time the range reference will move and the start of the data an the associated filter is in cell (using RC notation 14,14) and the data in cell 13,12. While I know I can’t use the indirect function in vba I wondered if there is a way to dynamically assign a range to be able to use the Advance filter function.
I have the code to find the last column and row of the data block.
I have tried the following code (2 attempts) but it won’t let me use the object in this way
I have tried to crate the cell reference as a string then assign it using the range function. I then read an answer where someone had put the value of the cells directly into the range function and it has worked for them ( they were copying cells). The 2 attempt are broadly the same but in the second I am trying to be more specific.
The issue seems to be as soon as I change from an absolute reference "A50" in the range statement the range no longer works. I am unsure how to resolve this and perhaps it can't be
It may be helpful to know the that data being filtered is rows of name and telephone data along with a tally system to show attendance (one column per week for a year)
The cells with the dynamic data hold them in the form A1 not RC format
Sub UseAdvancedFilterInPlace()
'This version of the sub has absolute references and works perfectly
Dim rdData As Range
Dim rgcriteria As Range
Call TurnOffStuff
Set rgData = Sheet9.Range(“A50”).CurrentRegion
Set rgcriteria = Sheet9.Range(“A46”).CurrentRegion
rgData.AdvancedFilter xlFilterInPlace, rgcriteria
Call TurnOnStuff
End Sub
Sub UseAdvancedFilterInPlace()
'This version of the sub has dynamic references and fails
Dim rdData As Range
Dim rgcriteria As Range
Call TurnOffStuff
Dim Top_of_data As String
Dim Top_of_Criteria As String
Dim My_range As Range
‘Attempt 1
'Set rgData = Range(Sheet9.Cells(13, 12).Value).CurrentRegion
'Set rgcriteria = Range(Sheet9.Cells(14, 14).Value).CurrentRegion
'Attempt 2
Set rgData = Sheet9.Range(Sheet9.Range(Cells(13, 12)).Value).CurrentRegion
Set rgcriteria = Sheet9.Range(Sheet9.Range(Cells(14, 14)).Value).CurrentRegion
rgData.AdvancedFilter xlFilterInPlace, rgcriteria
Call TurnOnStuff
End Sub
The actual error message I get is an application-defined or object-defined error
This worked for me.
Set rdData = Sheet9.Range(Sheet9.Range("L13").Value).CurrentRegion
Set rgcriteria = Sheet9.Range(Sheet9.Range("N15").Value).CurrentRegion
given that Range("L13").Value is A50 and Range("N15").Value is A46.
extra: Use the statement Option Explicit in the first line of every module, out of every sub or function. This option throws an error on undeclared variables, and will help you avoid renameing mistakes on variables.
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!
I am trying to write a function and a procedure that calls on such a function to check if names of the items located in a large table of repetitive data appear on a different sheet that's basically sort of like an input sheet for a user or a set up sheet. Basically the code should catch misspellings and unmatched items in the table on Sheet2 vs. a range on Sheet1. Ideally I would want to add an ability for the code to stop on an unmatched item and maybe highlight it so that user could correct an error or research the issue further. Currently I've tried to write the first part of the code but something is not working. It always says item name doesn't exists no matter how i set up data in the table:
Option Explicit
Public Function ItemNameExists(Target As String) As Boolean
Dim lookUp As Excel.Range
Dim itemCell As Excel.Range
ItemNameExists = False
Set lookUp = Worksheets("Sheet2").Range("Table1[Items]")
For Each itemCell In lookUp
If (itemCell.Value = Target) Then
ItemNameExists = True
Exit Function
End If
Next
End Function
Sub CheckErrors()
Dim ItemName As Excel.Range
Dim Cell As Range
Set ItemName = Worksheets("Sheet1").Range("B3:B12")
For Each Cell In ItemName
If (Len(Cell.Value) > 0) Then
If (Not ItemNameExists(Cell.Value)) Then
MsgBox ("Item name doesn't exist on Sheet1")
Exit Sub
End If
End If
Next
End Sub
For searching a Range there is a specific method, Range.Find (official documentation here).
If no match is found, it returns Nothing.
As to your case, there are quite a few points where it may miss the target, so you would probably have to debug:
Make sure lookUp actually refers to the intended Range.
Make sure Target contains the intended text.
Try with itemCell.Text instead of itemCell.Value (if you still prefer not to use Range.Find).