Passing a variable defined in a sub onto a function VBA - excel

I´m trying to use a sub to determine a dynamic range which serves as the input to a number of functions. The simplest version of what I´m trying to do looks like this
This approach gives me errors. Putting the subs and functions in different modules doesn´t help. What´s the mistake I´m making?
Global Info As Range
Sub InfoSetter()
Worksheets("Example").Activate
ActiveSheet.UsedRange.Select
Set Info = Selection
End Sub
Function Test() As Variant
Test = Info.Address
End Function

Try the below. This calls the sub from the function that sets the value of info. This means that your info will always be the current UsedRange when the function calculates. Also, using .Activate and .Select is generally considered bad practice. The below code does the same without using either.
Global Info As Range
Sub InfoSetter()
Set Info = Worksheets("Example").UsedRange
End Sub
Function Test() As Variant
Application.Volatile 'Added so function updates automatically when sheet calculates
Call InfoSetter
Test = Info.Address
End Function
Edit: Adding Application.Volatile at the beginning of your function will make it so this updates every time the worksheet calculates.

As per the comment from omegastripes, your error is likely to be because your range is empty. Given Test is a variant suggest you test for an empty range as below
Global Info As Range
Sub TryMe()
MsgBox Test
End Sub
your code
Sub InfoSetter()
Set Info = Worksheets("Example").UsedRange
End Sub
Function Test() As Variant
If Info Is Nothing Then
Test = "Ï'm empty"
Else
Test = Info.Address
End If
End Function

Related

Assigning excel function to a variable in Excel VBA

I am trying to assign am excel function to a VBA variable. I have tried a few different data types and none of them seem to work. I am trying to count the columns and rows in this table "tblAdsorpsionColumn" and I dont want to type out "Application.WorksheetFunction" every time I use an excel function in VBA. I know there other ways to do this but I want to use this way to learn how to use this functionality later. (what doesn't work: Worksheet,Double,String,Object)
Private Sub UserForm_Initialize()
Dim App As Object
Dim Table As Range
Set App = Application.WorksheetFunction
Set Table = ThisWorkbook.Worksheets("Sheet1").Range("tblAdsorpsionColumn")
lstTable.ColumnCount = App.Columns(Table)
End Sub
Say you use the SUM() worksheet function frequently in VBA and don't want to repeat typing Application.WorksheetFunction constantly. Just make a VBA wrapper like:
Option Explicit
Public Function summ(rng As Range) As Variant
With Application.WorksheetFunction
summ = .Sum(rng)
End With
End Function
You will get a very small performance hit using it, but it may be tolerable.
You can use a function to "shortcut" Application.WorksheetFunction :
Sub tester()
Debug.Print wsf.Average(Selection), wsf.Sum(Selection)
End Sub
Function wsf() As Object
Set wsf = Application.WorksheetFunction
End Function

From sub to Function

The objective is to count the number of comments in a range with a Function (not a sub).
I am trying to convert a Sub into a Function as I would like the range to vary and the user to enter as a formula
I have already searched the internet and got the right function. However for the sake of learning need to know why my Sub works and the Function does not
Function CommentsCounter(myRange3 As Range) As Long
'This one is mine - not working
CommentsCounter = myRange3.SpecialCells(xlCellTypeComments).Count
End Function
Sub working_just_fine()
'This one is working
Dim myRange4 As Range
Set myRange4 = Range("CO1:CO497")
Range("CO505").Value = myRange4.SpecialCells(xlCellTypeComments).Count
End Sub
Its giving the total number of cells and not the number of comments in the range
Interesting question, I tried some wonky stuff like declaring a public variable, then calling a Sub from the Function and putting the result of SpecialCells.Count into the public variable and accessing that from the Function. Surprisingly, calling the Sub from the Function led to a different result than calling the Sub separately. As a solution, this Function should do what you're trying to achieve, although it may be a bit slow on very large ranges, since it goes through every single cell in the range (I haven't done extensive testing on it yet):
Function CommentsCounter(myRange3 As Range) As Long
CommentsCounter = 0
For Each rngCell In myRange3
If Not rngCell.Comment Is Nothing Then CommentsCounter = CommentsCounter + 1
Next
End Function

VBA EXCEL: Apply sub to another worksheet from module

Trying to get a sub from a module to run within another worksheet. In a sense to stop using redundant ranges and keep it streamlined.
i.e.
-Module object-
Public sub method1()
{
Range("B4:B23") = ""
Range("C4:C23") = ""
'Empties these ranges...
}
-worksheet(s)-
sub project)
{
with sheet1 (or on any sheet 2,3,4,5... etc.)
Call module1.method1
'but this method only works on the module object, not in the context of the 'specified worksheet where it is needed
End with
Ideally to clear the data in ranges by using method1 in ANY worksheet. Every reference I tried just runs the module1 method without any effect or makes a useless reference to the method or worksheet. Just trying to save on code space by not writing direct references to every sheet which is formatted identical.
You can do this with a sub (ClearCells) that accepts a variable number of arguments via the ParamArray keyword. Then you can simply call the ClearCells sub and pass it the worksheet objects you want to clear the same ranges in, as in the DoClear sub. You can add more ranges as needed to the Union function in the GetRanges function.
Sub DoClear()
ClearCells Sheet1, Sheet3
End Sub
Sub ClearCells(ParamArray wkshts() As Variant)
Dim vWs As Variant
Dim ws As Worksheet
For Each vWs In wkshts
Set ws = vWs
GetRanges(ws).Clear
Next vWs
End Sub
Function GetRanges(ws As Worksheet) As Range
With ws
Set GetRanges = Union(.Range("B4:B23"), _
.Range("C4:C23"))
End With
End Function
Or assuming you are calling the method from the sheet you want to clear, you can just use ActiveSheet:
Public Sub Method1()
ActiveSheet.Range("B4:B23").Clear
ActiveSheet.Range("C4:C23").Clear
End Sub

Pass .Range as a parameter VBA

Hi Please help me with the below,
Sub movedata()
Call select_data(.Range("B6:B12"))
End Sub
Function select_data(C As Range)
Worksheets("sheet1").Range("I6:I16") = Worksheets("Sheet1").Range(C).Value
End Function
I can't see where I am going wrong,
Thanks,
C already is a Range object so there's no need to pass it to the Range() function (which expects a string anyway) to create it.
Change:
Worksheets("sheet1").Range("I6:I16") = Worksheets("Sheet1").Range(C).Value
To:
Worksheets("sheet1").Range("I6:I16") = C
You are confusing the range as a Range object with its Address property.
Method 1:
Sub movedata()
Call select_data(Range("B6:B12").address)
End Sub
Function select_data(C As string)
with Worksheets("sheet1")
.Range("I6:I16") = .Range(C).Value
end with
End Function
Method 2:
Sub movedata()
Call select_data(Worksheets("sheet1").Range("B6:B12"))
End Sub
Function select_data(C As range)
C.parent.Range("I6").resize(C.rows.count, C.columns.count) = C.Value
End Function
fwiw, there is going to be some difficulties stuffing B6:B12's values into I6:I16's cells. There seem to be 4 missing values.

How do I pass a Range object for use in another function?

I have a button someone can click. This button will create a range and pass it to another function that changes the value of that range.
Sub CommandButton21_Click()
Dim example As Range
Set example = Range("A1")
test (example)
End Sub
This function does not work. For some reason the range cannot be used by the other function.
Function test(x As Range)
x.Value = "changed"
End Function
Any help? The error says "Object required". I have tried to pass stuff like [A1] or making it a variant with no luck.
You can't "Call" a function, you Call a sub.....try this:
Sub CommandButton21_Click()
Dim example As Range
Set example = Range("A1")
MsgBox test(example)
End Sub
Function test(r As Range) As String
r.Value = "Changed"
test = "O.K."
End Function
Use Call:
Call test(example)
If you will not return any value, use Sub rather than Function.

Resources