I have an UserForm in Excel VBA with different Objects like CheckBox, RadioButtons, TextEdit Box etc. Each Object has different event functions, but i want to call the some event functions in user defined sub function like UserForm_Init() function in order to re-utilize the same code written in them.
Example:
Private Sub CheckBox1_Click() [Later changed to public also]
If CheckBox1.Value Then
--- Code
End If
End Sub
Private Sub CheckBox2_Click()
If CheckBox2.Value Then
--- Code
End If
End Sub
Private Sub RadioButton1_Click()
If RadioButton1.Value Then
--- Code
End If
End Sub
' User Defined Function
Sub UserForm_Init()
CheckBox1_Click()
CheckBox2_Click()
RadioButton1_Click()
End Sub
But when i am trying to compile it is showing compile error, how can i execute these object event functions within user-defined sub function.
I know I can write individual functions within Event functions and call these individual functions for user-defined sub function. But in this case, it will be too-difficult to re-change entire code. I have only option of calling these event-functions in an sub-function for execution.
How can i perform these actions, call event functions with in the user defined sub function [UserForm_Init()]?
VBA doesn't use curly braces. This code won't compile with those. VBA requires Sub and End Sub to define the procedures.
Sub CheckBox1_Click()
if CheckBox1.Value Then
--- Code
end if
End Sub
Sub CheckBox2_Click()
if CheckBox2.Value Then
--- Code
end if
End Sub
Sub RadioButton1_Click()
if RadioButton1.Value Then
--- Code
End If
End Sub
Sub UserForm_Init()
CheckBox1_Click()
CheckBox2_Click()
RadioButton1_Click()
End Sub
NOTE: If your custom function UserForm_Init is not in the Form's code module, you'll need to qualify the procedure names, e.g.:
Sub UserForm_Init()
UserForm1.CheckBox1_Click()
UserForm1.CheckBox2_Click()
UserForm1.RadioButton1_Click()
End Sub
Additional complexity may arise based on your implementation, but I hope this will get you started.
You're missing parts of code in your example; it's hard to determine what you're trying to do without a clear picture. It is possible to call an event procedure from another, it's a bad idea for a number of reasons.
Instead of calling a private procedure like you're trying to, sort of like this:
Private Sub myEvent()
'event code here
End Sub
Sub mySub()
myEvent()
End Sub
...you're better off to move the code that you need to be shared to a shared module, kind of like this:
Public Sub mySubInSharedModule()
'event code here
End Sub
Private Sub myEvent()
Call mySubInSharedModule()
End Sub
Public Sub mySub()
Call mySubInSharedModule()
End Sub
There are numerous articles explaining this further, on this site and others. To get you started, see this search as well as this Stack Overflow question.
Related
My problem is so simple that it's ridiculous...
If I create a Module like:
Sub Check_TextBox(ByVal CheckThisBox As TextBox)
'With anything. Even if I leave this blank..
End sub
And try to call it on a UserForm like:
Private Sub CommandButton1_Click()
Call Check_TextBox(Me.TextBox1)
End Sub
It simply gives me "Incompatible Types Error"... I have no clue about what's going on. "TextBox1" IS a TextBox and I declare it as one on the Sub.
Need to be a bit more explicit about the parameter type:
Sub Check_TextBox(CheckThisBox As msforms.TextBox)
Debug.Print CheckThisBox.Text
End Sub
I have a rather large VBA project and now I need to know what sub is calling the function.
example:
sub first()
RunSomeCode
end sub
sub second()
RunSomeCode
end sub
Function RunSomeCode()
' here I need to know if the calling sub is first() or second()
end function
The only way I know of is to pass a string with the functioncall in first and second sub with the calling sub name.
But this function is called from everywhere and I wanted to know if there is a simpler way to do it.
I need to get a string of what sub called the RunSomeCode, to just get it in debugging is not enough.
Ctrl+L is the shortcut for the Call Stack in VBA. You may see the stack. As you see in the screenshot below, the function was called from the Sub Second:
Assuming you only need it in First and Second then probably this could help
Option Explicit
Sub first()
RunSomeCode "First"
End Sub
Sub second()
RunSomeCode "Second"
End Sub
Sub third()
RunSomeCode
End Sub
Function RunSomeCode(Optional Caller As String)
' here I need to know if the calling sub is first() or second()
If Len(Caller) > 0 Then
Debug.Print Caller
End If
End Function
I have two modules, Module1 and Module2.
In Module1:
Private Function myCheck() As Boolean
if [Operation] = [Something] then
myCheck = True
Else
myCheck = False
End if
End Sub
In Module2, I would like to run myCheck sub in Module 1 then do another operation:
Private Sub Execute()
[Operation 1]
If myCheck = True Then
[Operation 2]
Else
[Operation 3]
End If
End Sub
It does not work. If I place Private Function myCheck within the same module then it works. Is there a special method to call a sub or function from another module?
Use Option Private Module For Module1, then in Module 2:
for a Sub; qualify what you're calling with the Module it's in, like so:
Module1.myCheck()
for a Private Sub; use Application.Run and qualify what you're calling with the Module it's in, like so:
Application.Run ("Module1.myCheck")
Using Private Module hides it's contained sub/s in the Developer > Macros list.
Further Reading :-)
Read through the comments in the code below to see what does and doesn't work.
To confirm the behaviours yourself:
Create a new Excel, open Developer > Visual Basic, insert 3 Modules.
Copy the below code blocks into the relevant modules.
'In Module1
Option Explicit
Sub ScopeTrials()
'NOTES:
' Only NormalSubIn_NormalModule shows in Developer > Macros.
' As the default without a keyword is Public I have called
' these "Normal". I.e. you can use Public or Nothing wherever
' Normal is.
' A line commented out shows what doesn't work.
NormalSubIn_NormalModule
Call NormalSubIn_NormalModule
Application.Run ("NormalSubIn_NormalModule") 'Not recommended!
NormalSubIn_PrivateModule
Call NormalSubIn_PrivateModule
Application.Run ("NormalSubIn_PrivateModule") 'Not recommended!
'PrivateSubIn_NormalModule
'Call PrivateSubIn_NormalModule
'Module2.PrivateSubIn_NormalModule
'Call Module2.PrivateSubIn_NormalModule
Application.Run ("PrivateSubIn_NormalModule") 'Fails with duplicates! See Explanation
Application.Run ("Module2.PrivateSubIn_NormalModule")
'PrivateSubIn_PrivateModule
'Call PrivateSubIn_PrivateModule
'Module3.PrivateSubIn_PrivateModule
'Call Module3.PrivateSubIn_PrivateModule
Application.Run ("PrivateSubIn_PrivateModule") 'Fails with duplicates! See Explanation
Application.Run ("Module3.PrivateSubIn_PrivateModule")
'Explanation: if there is an identical sub in another Private Module, then this fails
'with Runtime Error 1004 (Macro not available or Macros Disabled), which is Misleading
'as the duplication and/or nonspecified module is the problem.
'I.e. always specify module!
'Also, this only fails when the line is actually run. I.e. Compile check doesn't find this
'when starting to Run the code.
End Sub
'In Module2
Option Explicit
Sub NormalSubIn_NormalModule() 'only THIS sub shows in Developer > Macros
MsgBox "NormalSubIn_NormalModule"
End Sub
Private Sub PrivateSubIn_NormalModule()
MsgBox "PrivateSubIn_NormalModule"
End Sub
'In Module3
Option Explicit
Option Private Module
Sub NormalSubIn_PrivateModule()
MsgBox "NormalSubIn_PrivateModule"
End Sub
Private Sub PrivateSubIn_PrivateModule()
MsgBox "PrivateSubIn_PrivateModule"
End Sub
You can use Application.Run to do this:
Application.Run "Module1.myCheck"
The macro will stay "invisible" for the users if they display the Macros Dialog Box (Alt+F8), since it's still private.
Edit #1
A second option is to introduce a dummy variable as an optional parameter in the Sub, like this:
Public Sub notVisible(Optional dummyVal As Byte)
MsgBox "Im not visible because I take a parameter, but I can be called normally."
End Sub
This too, will hide the macro in the Macros Dialog Box (Alt+F8), but it can now be invoked the usual way.
If I want to write a Sub that positions a UserForm relative to the Application object that displays it, How would I go about doing it?
I want to write a sub that goes like this:
Sub PositionForm(WhichForm as Object)
WhichForm.Left = <WhichForm Application Object>.Left
End Sub
I understand that there are many workarounds to this. I am interested in knowing whether there is a way to getting that reference.
in Excel the following works:
Sub PositionForm(WhichForm As Object)
WhichForm.Left = Application.Left
End Sub
to be called from any UserForm code as:
Private Sub CommandButton2_Click()
... any code
PositionForm Me
... any code
End Sub
My VBA code is too large and I'm trying to make smaller SUBS so the error won't come up, but then the error "Ambigoius name" pops up. I've tried to rename my subs...
Ex.
Private Sub worksheet_calculate()
Range("I9").Interior.Color=Range("AK9").Display.Format.Interior.Color
end sub
Private Sub worksheet_calculate2()
Range("J9").Interior.Color=Range("AQ9").Display.Format.Interior.Color
end sub
...when I rename the other subs as shown in the example it doesn't do anything, only the original work properly. How do I rename them so they can work properly?
In my understanding, worksheet_calculate is the predefined name of the subroutine, triggered by the event when the worksheet is recalculated.
You can define and call other private subs from it.
like
Private Sub worksheet_calculate()
rem sub body
CalculateSub1 pars 'variant one
Call CalculateSub1(pars) 'variant two
rem sub body
End Sub
Sub CalculateSub1(pars)
Rem Sub body
End Sub
Just insert the below line of codes at the end of your main sub which is "worksheet_calculate"
Call worksheet_calculate2
Call worksheet_calculate3
Call worksheet_calculate4
Call worksheet_calculate4
.
.
.
Call worksheet_calculaten