Call module with multiple inputs - vba

I've tried finding a solution to this problem but have been unable to.
In generic form:
Module1
Sub Source()
Call Module2.Run
End Sub
Module2
Sub Run()
Value = 10
Some code which uses Value as input
End Sub
What I want to be able to do is to be able to define multiple Values in Module1 and then run Module2.Run() with each value.
Module1
Sub Source()
Value = 10, 20, 30
Call Module2.Run (10)
Call Module2.Run (20)
Call Module2.Run (30)
End Sub
Module2
Sub Run()
Value = Input from Module1.Source()
Some code which uses Value as input
End Sub
Or something along these lines. Any input would be greatly appreciated.

You can pass parameters through arguments like so
Sub Sub1 ()
Dim myVal as Long
myVal = 1000
Sub2 (myVal) 'The "Call" is not necessary
End Sub
Sub Sub2 (myVal as Long) 'This sub requires an input to run (myVal)
MsgBox myVal
End Sub

You can create an array, fill it and pass as an argument.
Avoid using names like Source and Run which are already used by Excel;.
Option Explicit
Sub Sour()
Dim arr_1d() As Variant
arr_1d = Array("val1", "val2", "val3")
Dest arr_1d
End Sub
Sub Dest(arr_1d() As Variant)
Dim y As Long
For y = LBound(arr_1d) To UBound(arr_1d)
Debug.Print arr_1d(y)
Next
End Sub

Related

How do I exit sub where function is used?

Was wondering if it was possible to exit sub using a function :
For example
Public Function test()
Exit Sub 'does not work
End Function
Sub MySub()
test() 'Here we should Exit MySub()
End Sub
But this Trigger an error. Is there a way to do this ?
NOTE I don't want to exit the function but I would like to exit the Sub or Stop the code execution directly into my function.
That is not possible. However, if your intent is to have test decide whether or not to abort MySub, then just return a boolean from test and act on it in MySub:
Sub MySub()
If test() Then
Exit Sub
End If
End Sub
From MSDN:
Exit Function Immediately exits the Function procedure in which it
appears.
You should use Exit Function and not Exit Sub inside test()
Update:
If you wish to exit the calling sub MySub, you should return some value from the test function. For Example:
Public Function test()
test = False
End Function
Sub MySub()
If test() = False Then
Exit Sub
End If
End Sub
Try this approach, please. Your function must return something in order to exit the sub. Your sub is not automatically exited if the function is. You must set a condition inside the sub to exit it in case of a specific function return:
Public Function test(a As Long, b As Long) As Boolean
If a + b > 10 Then
test = True
Else
Exit Function ' even if it is not necessary
End If
End Function
Sub MySub()
If Not test(5, 7) Then Exit Sub
'do whatever...
End Sub

How can I declare one variable with assigned value that can use for all module in vba?

My question is how my variable and assigned value can be use for all module, for example like:
this is declare global module:
sub global()
public A as integer
A=3
end sub
this is first module(for sheet1):
sub first()
if Sheet1.Cells(1, "A") > 100 then
Sheet3.Cells(A, "A") = Sheet1.Cells(1, "B").Value
A=A+1
eng sub
this is second module(for sheet2):
sub second()
if Sheet2.Cells(1, "A") > 100 then
Sheet3.Cells(A, "A") = Sheet2.Cells(1, "B").Value
A=A+1
end sub
*i had separate the modules file for every single sheet such as sheet1 with module1 and sheet2 with module2.
so I expect that when A sum inside the first or second module will return to global() A value.
example of my contain file
Based on comments to Vityata's answer, and edits to the Question:
Module1
Option Explicit
Public A as Long
'Long and Integer use the same amount of Memory in VBA,
' so there is no reason not to use Long
Sub getglobal()
A=3
End Sub
Module2
Option Explicit
Sub first()
If Sheet1.Cells(1, "A") > 100 Then
Sheet3.Cells(A, "A") = Sheet1.Cells(1, "B").Value
End If
Module1.A=Module1.A+1
End Sub
Module3
Option Explicit
Sub second()
If Sheet2.Cells(1, "A") > 100 Then
Sheet3.Cells(A, "A") = Sheet2.Cells(1, "B").Value
End If
Module1.A=Module1.A+1
End Sub
What you need is achieved with declaring the variable like this Public A As Integer outside a sub or a function, in a module.
Public A As Integer
Sub SetGlobal()
A = 3
End Sub
And then somewhere else:
Sub first()
A = A + 3
MsgBox A
End Sub
In general, you cannot name a Sub Global, because it is a name, used by the VBE.
If you want to have a minumum value of the public variable, then you may consider creating a class, which has a condition in the Get-property. If the minimum value is 3, then the class should look like this:
Option Explicit
Private m_lA As Long
Public Property Get A() As Long
A = m_lA
If A < 3 Then A = 3
End Property
Public Property Let A(ByVal lNewValue As Long)
m_lA = lNewValue
End Property
And you can call it from the modules like this:
Option Explicit
Public myVar As New publicA
Public Sub TestMe()
Debug.Print myVar.A
myVar.A = myVar.A * 30
Debug.Print myVar.A
End Sub

VBA value persistence

I have a bunch of globally defined variables in my VBA (macro) script. I set values to these in a procedure in my current module. Is there any way to get these values in another procedure present in another module.
As far as variable declaration goes.
Within a sub - this is only accessible to the sub itself:
Sub LocalScope()
Dim stringVariable as string
stringVariable = "abc"
debug.print stringVariable
End Sub
Dim at the top of the module - this is accessible to any subs within the module:
Dim stringVariable as string
Sub ModuleScope()
stringVariable = "abc"
End Sub
Sub PrintString()
debug.print stringVariable
End Sub
Public at the top of the module - this is accessible to subs in all modules:
Public stringVariable as string
Sub ModuleScope()
stringVariable = "abc"
End Sub
Sub PrintString()
debug.print stringVariable
End Sub

Populate Various Comboboxes by Function Call

Morning !
I'm trying to make my code more generic by using Functions to populate various ComboBoxes, however, I'm with troubles to do this...
In UserForm:
Private Sub UserForm_Initialize()
Call Lista_Vendedores
ComboBox1.List = Lista_Vendedores
End Sub
In Module:
Public Function Lista_Vendedores() As Variant
Dim Lista As New Collection
Dim Cont_Vendedores As Integer
Cont_Vendedores = Plan1.Cells(1, 8).Value
Sheets("Plan1").Select
For i = 3 To Cont
Lista (Row.Cells(i, 8))
MsgBox Lista
Next i
Set Lista_Vendedores = Lista
Set Lista = Nothing
End Function
When I try to run the code, nothing happens, however, none error is shown.
Your code can be simplified a lot. It doesn't need to be in a function, just give it a range as per the example below:
Userform:
Private Sub UserForm_Initialize()
ComboBox1.List = ThisWorkbook.Worksheets("Sheet1").Range("A1:A8")
End Sub
Module:
Public Sub ShowUserform()
UserForm1.Show
End Sub
You are making lots of mistakes in your code, and while CallumDA33 solution is better, I think you should take a look at this:
First, you are not calling your function correctly. The sub should be:
Private Sub UserForm_Initialize()
ComboBox1.List = Lista_Vendedores
End Sub
The Call line is not necessary. (and the keyword Call itself is almost never required). I really don't get where your syntax is coming from.
In the Lista_Vendedores function, you are not using correctly the Lista Collection.
Cont is undefined. You should always use Option Explicit at the start of your modules.
You are not affecting any value to the collection.
You should also avoid using Select as much as possible.
The List property expect an variant array, not a collection, so the function should return a variant array, not an variant containing a single (empty) collection object, so I also changed the type for Lista.
Follows corrected but untested code:
Public Function Lista_Vendedores() As Variant()
Dim Lista As Variant()
Dim Cont_Vendedores As Integer
With Sheets("Plan1")
Cont_Vendedores = .Cells(1, 8).Value
Redim Lista(0 to Cont_Vendedores-3)
For i = 3 To Cont_Vendedores
Lista(i-3) = .Cells(i,8)
Next i
End With
Lista_Vendedores = Lista
End Function
Edit: corrected typo

VBA variables defined one sub and called in another in multiple subs

I want to call a sub that I've written in another sub, and add a couple new things to it, but use the variables that I've defined in the first sub don't show up in the second, even though the first macro is called within the sub.
For example, I've defined the variables as Public outside of the subs, but the values I define in the first sub, and then call in second sub gets lost. In the code below, running the macro "test" works, but "test1" gives me a "Run-time error '1004'".
Public row1 As Integer
Public col1 As Integer
Sub test()
row1 = 2
col1 = 2
ActiveSheet.Cells(row1, col1).Select
End Sub
Sub test1()
Call test
ActiveSheet.Cells(row1, col1).Resize(6, 5).Select
End Sub
Any guidance on how to get row1 and col1 to work in the test1 sub would be great. Is there a better way to achieve what I'm trying to do?
An alternative option is to pass variables from sub to use a Public Function like this:
Sub MainSubHere()
'Some random code
Dim AddMe1 As Long, AddMe2 As Long, MySum As Long
AddMe1 = 2
AddMe2 = 2
MySum = AddMeSub(AddMe1, AddMe2)
Msgbox MySum
End Sub
Public Function AddMeSub(AddMe1 As Long, AddMe2 As Long) As Long
AddMeSub = AddMe1 + AddMe2
End Sub
You can try, but there's other stuff to improve here, such as using Select rathering then just going to the action statement. I left out that sub out since it served no purpose.
Dim row1 As Integer, col1 As Integer
Private Sub DefineVars()
Set row1 = 2
Set col1 = 2
End Sub
Sub test()
Call DefineVars
ActiveSheet.Cells(row1, col1).Resize(6, 5).Select
End Sub