How to convert a String to a Range Object - vba

Is there anyway to convert a string value to a Range object ? I'm having a function which takes a Range object as a argument and need to pass a single string parameter to it
Thank You

A string with a cell address? if so:
Dim r As Range: Set r = Range("B3")
MsgBox r.ColumnWidth

I don't like this one bit, but if you can't change the function that requires a range, you could create a function that converts a string to a range. You'd want to be sure that the only thing the first function cares about is the Value or Text properties.
Function FuncThatTakesRange(rng As Range)
FuncThatTakesRange = rng.Value
End Function
Function ConvertStringToRange(sInput As String) As Range
Dim ws As Worksheet
Set ws = Workbooks.Add.Sheets(1)
ws.Range("A1").Value = sInput
Set ConvertStringToRange = ws.Range("A1")
Application.OnTime Now + TimeSerial(0, 0, 1), "'CloseWB """ & ws.Parent.Name & """'"
End Function
Sub CloseWb(sWb As String)
On Error Resume Next
Workbooks(sWb).Close False
End Sub
Use in the Immediate Window like
?functhattakesrange(convertstringtorange("Myvalue"))

Here is my solution that involves no need for a new function.
1.Make dynamic string variable first
2.Then finalize it by creating a range object out of this string via a range method: Set dynamicrange= range (dynamicstring)
You can manipulate dynamicstring as you want to, I just kept it simple so that you can see that you can make range out of a string variable.
Sub test()
Dim dynamicrangecopystring As String
Dim dynamicrangecopy As range
dynamicrangecopystring = "B12:Q12"
Set dynamicrangecopy = range(dynamicrangecopystring)
End Sub

Why not change the function argument to a variant and then in the function determine Using VarType etc) if you have been passed a Range and use error handling to check for a string which can be converted to a range or a string that cannot be converted to a range ?

This simple function will convert string arguments into a range object, usable in other excel functions.
Function TXT2RNG(text) As Variant
Set TXT2RNG = Range(text)
End Function

Let's say Sheet1!A1 has the text value "Sheet1!B1" and Sheet1!B1 has the value "1234". The following code will use the range address stored as text in A1 as an input and copy the range B1 to A2:
Sub Tester()
Sheet1.Range(Range("A1")).Copy
Sheet1.Range("A2").PasteSpecial xlPasteAll
End Sub

Related

Passing 2 range variables to a Sub - Object required/ByRef argument Type mismatch error

I am trying to copy range from 1 worksheet with conditional formatting rules and paste in another workbook using the exact formatting but deleting the conditional rules.
I am passing 2 range objects to my sub and when calling the macro I am getting the error. Please help me.
Sub Create()
Dim rgFrom, rgTo As Range
oldBook = ActiveWorkbook.Name
Workbooks.Add
Set rgFrom = Workbooks("Daily Flow Template.xlsm").Worksheets("DailyFlow").Range("A1:BZ110")
Set rgTo = ActiveWorkbook.Worksheets("Sheet1").Range("A1:BZ110")
PasteFormattedRange (rgFrom), rgTo ----- Error Object Required
End Sub
Sub PasteFormattedRange(ByRef rgFrom As Range, ByRef rgTo As Range)
Dim S As String
Dim rgStart As Range
Dim i As Long, CF_Format As Long
Dim SaveDisplayAlerts As Boolean, SaveScreenUpdating As Boolean
Dim HTMLInClipBoard As Boolean
Dim Handle As Long, Ptr As Long, FileName As String
Set rgStart = Selection
rgFrom.Copy
'Enumerate the clipboard formats
If OpenClipboard(0) Then
CF_Format = EnumClipboardFormats(0&)
Do While CF_Format <> 0
S = String(255, vbNullChar)
i = GetClipboardFormatName(CF_Format, S, 255)
S = Left(S, i)
HTMLInClipBoard = InStr(1, S, "HTML Format", vbTextCompare) > 0
If HTMLInClipBoard Then
Application.CutCopyMode = False
Application.Goto rgTo
ActiveSheet.PasteSpecial Format:="HTML"
Application.Goto rgStart
Exit Do
End If
CF_Format = EnumClipboardFormats(CF_Format)
Loop
CloseClipboard
End If
End Sub
ByRef argument type mismatch
This answer from "ByRef argument type mismatch in Excel VBA" might help explain this error a bit clearer than I can.
The basic gist of it is:
Unless you need to, pass arguments ByVal instead of ByRef.
If you use ByRef make sure to declare your statements explicitly rather than delcaring with the default data type (Variant) that way you will be passing a Range where a Range is expected.
This answer on my question on CodeReview also touches on passing arguments ByVal opposed to ByRef.
Object required (Error 424)
If you are not returning a value, you don't need to include parentheses ( ) - You can read about it on Using parentheses in code(VBA).
The below edit to your problem line will execute without the Object Required error:
PasteFormattedRange rgFrom, rgTo
When using parentheses for a Sub, Function or any other Method or Property, you would need to encapsulate all arguments within the parentheses rather than just one if the parentheses are actually required.
If you are assigning a value, you would need the parentheses, like so:
Sub Foo()
x = MyFunction(Argument1, Argument2)
End Sub
If you are not assigning a value, you don't include the parentheses, like so:
Sub Foo()
MySub Argument1, Argument2
End Sub

VBA: Using a range returned from a function

I'm trying to use WorksheetFunction.Match in VBA, but I'm having issues in populating the lookup_array parameter. For the lookup_array, I'm using the output of another function -GetSubRange() as Range - that returns a range.
I've verified that my WorksheetFunction.Match() syntax works, and that my GetSubRange() function also works - when coded differently, I can get the address, select it, etc.
The result is that the function returns a #VALUE! error, which I've concluded is that the lookup_array parameter isn't referencing the range input properly.
Any ideas?
Here's what I'm trying to do:
Function GetValue(rng As Range, colName As String, key As String) As String
Dim rngSubRange As Range
Set rngSubRange = GetSubRange(rng, colName)
GetValue = WorksheetFunction.Match(key, rngSubRange, 0)
End Function
Function GetSubRange(rng As Range, colName As String) As Range
Dim rngHeader As Range
Dim colNum As Integer
Set rngHeader = ThisWorkbook.Names(rng.Name.Name &"_Header").RefersToRange
colNum = Application.Match(colName, rngHeader, 0)
Set GetSubRange = rng.Columns(colNum)
End Function
The error was in the algorithm: I was searching in the wrong subrange. rngSubRange was getting the range of the value column, but the key was in another column. I had to create to subranges: one for the key column and one for the value column.

How to pass a table name to a function in Excel

I have various settings tables in Excel, each with two column headings Parameter and Value.
I want to pass a specific table's name to a function getParameter that looks up a specific parameter's name in that table, returns the associated parameter's value, and performs all error handling, e.g. with the following code segment:
Function getParameter(....
...
Dim paramterValue as Variant
With Application
parameterValue = .Index([tableName[Value], .Match("parameterName", [tableName[Parameter], 0))
If Not IsError(parameterValue) then
...
Else
...
End If
End With
End Function
How do I define the appropriate function arguments and call the function?
Tables are in VBA selectable as ListObject Object. But those objects are on worksheet scope only. So we must know the worksheet on which the table is placed on to get it using wrksht.ListObjects(tableName).
To be more flexible, we could using Evaluate to evaluate the structured references:
Public Function getParameter(tableName As String, parameterName As Variant) as Variant
Dim parameterValue As Variant
Dim oRangeTValues As Range
Dim oRangeTParameters As Range
Set oRangeTValues = Evaluate("" & tableName & "[Value]")
Set oRangeTParameters = Evaluate("" & tableName & "[Parameter]")
With Application
parameterValue = .Index(oRangeTValues, .Match(parameterName, oRangeTParameters, 0))
If Not IsError(parameterValue) Then
getParameter = parameterValue
Else
getParameter = CStr(parameterValue)
End If
End With
End Function
This will be usable on all worksheets since the table names are on workbook scope in reality.
This is supposed to be used as User Defined Function using a cell formula like =getParameter("TableName","Parameter").
I'll try like this, identifying the sheet and the ListObject corresponding to your TableName :
Function getParameter(ByVal tableName As String, ByVal parameterName As String) As Variant
Dim parameterValue As Variant
Dim RgVal As Range
Dim wS As Worksheet
Dim LOTable As ListObject
Application.Volatile
Set wS = Evaluate(tableName).Parent
Set LOTable = wS.ListObjects(tableName)
Set RgVal = LOTable.DataBodyRange
With Application.WorksheetFunction
parameterValue = .Index(RgVal.Columns(2), .Match(parameterName, RgVal.Columns(1), 0))
End With 'Application.WorksheetFunction
If Not IsError(parameterValue) Then
getParameter = parameterValue
Else
'...
DoEvents
getParameter = CStr(parameterValue)
End If
End Function
Call in VBA :
Sub test_GetParameter()
Debug.Print getParameter("Table1", "testParam")
End Sub
Call in Excel :
= getParameter("Table1", "testParam")
#R3uk Axel Richter's code is sufficient, but yours also works.

Pass name created in Name Manager Excel to Function VBA

I created a name in Name Manager. How to pass the name "MyRange1" parameter for my function in VBA code?
In Excel:
=MyFunction(MyRange1)
MyFunction is:
Public Function MyFunction(nameDefined As Variant) As String
'How get value of nameDefined ??
End Function
There are two ways to pass a Named Range:
as a String
as a Range Object
so a UDF() in a worksheet cell would have either:
=myudf("Name1")
or
=myudf(Name1)
Naturally, the UDF() would have to be coded to expect one or the other,
Note that there could be volatility problems with using only a String.
EDIT#1:
Here is an example of passing a Range rather than a String. Say we create MyRange1 like:
and the UDF() is like:
Public Function MyFunction(rng As Range) As String
Dim r As Range
For Each r In rng
MyFunction = MyFunction & "..." & r.Text
Next r
End Function
Then we can use it in a worksheet cell like:
=MyFunction(MyRange1)
Once the UDF() has the range, it can get the list of items contained therein.
To figure out similar questions, you can put a Breakpoint in the code and analyse the Locals window:
From the Locals window you can notice that you can access "Str2" with nameDefined(2,1)
( or in your version of Excel it might be nameDefined(2) for horizontal array )
You can also check the run-time type with some of the VBA functions:
t = VBA.TypeName(nameDefined) ' t = "Variant()"
v = VBA.VarType(nameDefined) ' v = vbArray + vbVariant ( = 8204 )
b = VBA.IsArray(nameDefined) ' b = True ( also True for range with more than one cell )

vba - properly passing range value to a function

in my application i call a function and pass 4 values to calculate a cell adress:
nettowertadresse = searchAdress(Dateiname, CurrentSheet, "Nettowert", Range("A1:C60"))
function:
Function searchAdress(inputworkbook As String, inputsheet As String, inputsearchtext As String, inputrange As Range) As Range
With Workbooks(inputworkbook).Sheets(inputsheet).Range(inputrange)
Set searchAdress = .Find(inputsearchtext, LookIn:=xlValues)
End With
End Function
now the problem is that i get error 1004 "application defined or object defined error" and i think that maybe the range is not properly passed because the debugger shows no value for the variable "inputrange" when jumping to the function. please give some advice on how to make this function work. thanks.
Your function, searchAddress, declares inputrange as Range. This means that the object inside your function is a Range object.
So you should not be using it as .Range(inputrange). Instead try using this code, which treats it correctly as a Range object:
Function searchAdress(inputworkbook As String, inputsheet As String, inputsearchtext As String, inputrange As Range) As Range
With Workbooks(inputworkbook).Sheets(inputsheet)
Set searchAdress = inputrange.Find(inputsearchtext, LookIn:=xlValues)
End With
End Function
Also note that there is another bug in your code that calls this function. You need to use the keyword Set when assigning the return value to your nettowertadresse variable:
Set nettowertadresse = searchAdress(Dateiname, CurrentSheet, "Nettowert", Range("A1:BA2"))
Otherwise you will experience Run-time error '91', which you mention in your follow-up question.
you add a Range to a rangeobject in your function, your function looks like this then:
With Workbooks(inputworkbook).Sheets(inputsheet).Range(Range("A1:C60"))
Set searchAdress = .Find(inputsearchtext, LookIn:=xlValues)
End With
You should change this:
Function searchAdress(inputworkbook As String, inputsheet As String, inputsearchtext As String, inputrange As String) As Range
With Workbooks(inputworkbook).Sheets(inputsheet).Range(inputrange)
Set searchAdress = .Find(inputsearchtext, LookIn:=xlValues)
End With
End Function
And then pass this to the function:
nettowertadresse = searchAdress(Dateiname, CurrentSheet, "Nettowert", "A1:C60")