I am trying to make a function that pass two range as a parameters, the code look something like this:
Function WhatEverFunction(range1 As Range, range2 As Range) As Integer
Dim column As ingeter
column = range1.Column
'make some stuff with the column
WhatEverFunction = range1.Value + range2.Value
End Function
This is how I execute the code and pass the parameters:
But this is the result:
Here are some of those corrections. Also, you are really just doing SUM so maybe consider the following:
Public Function WhatEverFunction(ByVal range1 As Range, ByVal range2 As Range) As Long
Dim myColumn As Long
myColumn = range1.column
'make some stuff with the column
WhatEverFunction = Application.WorksheetFunction.Sum(range1, range2)
End Function
Note #john Coleman's comment about what a udf cannot do. To be explicit, a UDF returns something to the cell it is placed in.
And your local settings might require WhatEverFunction = Application.WorksheetFunction.Sum(range1; range2)
Related
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.
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.
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 )
I'm writing some VBA functions in Excel that compute word values and cross sums of the input.
I'm passing the input as Public Function cross_sum(myRange As Range) As Integer to them so that they take cell references as input, e.g. =cross_sum(A1). Works fine.
However when I try to chain two functions like =cross_sum(word_value(A1)) I run into th VALUE error because word_value() returns an Integer value and not the Range cross_sum() is set to expect. However I did not find a way to cast an Integer (or String) into a Range.
As Excel's built-in functions support chaining as well as Range input I wonder how.
Unfortunately this is my first VBA project so I wonder if and how to cast or what type to choose to get this working both ways.
Any pointers appreciated!
TIA,
JBQ
You can pass Variant to a function and the function can determine the type of input:
Public Function Inputs(v As Variant) As String
If TypeName(v) = "Range" Then
MsgBox "you gave me a range"
Else
MsgBox "you gave me a string"
End If
Inputs = "done"
End Function
Sub MAIN()
Dim st As String
Dim rng As Range
st = "A1"
Set rng = Range(st)
x = Inputs(st)
x = Inputs(rng)
End Sub
Without your code, it is hard to know what you could change. That being said...
There is not a way to convert an integer to a range. You would have to create a function to do so if that is what you desired.
You could create a converter function, maybe titled IntegerToRange, that takes an integer and after some logic (maybe 1 = "A1", 2 = "A2" or something), will return a range. Your cell formula would then be =cross_sum(IntegerToRange(word_value(A1))
Alternatively, you could modify your word_value function to return a range instead of an integer. Your cell formula would then be =cross_sum(word_value(A1).
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