calling a sub function with a button in vba - vba

I have 10 Sub function macros in "This workbook". Instead of running each macros, everytime i wanted an userform with button, and when I click , it should execute all the Sub function in "This workbook".
I created another function like calling, and I used the following code,
Sub calling()
Call lookup
Call RangeTest
Call datecompare
Call AutoPivot
Call Autochart
Call pivot
Call chart
Call pivot1
End Sub
so, whenever I go for macros, I select Sub calling() and it executes the 10 Sub functions. I would like to have it through a button click. Could anyone suggest how I can do this ?

You should simply add a button from the developper ribbon and assign it to calling().
However, make sure all your macros are in the same module or else you'll have to specify it. If you still get an error it would be interesting to see on what line the error is coming from.
Thank you

I'm assuming the confusion arises because you are trying to use an ActiveX button. If you were using a Form Button, the macro name would appear in the "Assign Macro" popup box. But the ActiveX version doesn't provide the dialog, and because the button exists on the page, doesn't easily see the macros from "This Workbook".
Here's what worked for me.
Within Sheet3:
Private Sub CommandButton1_Click()
Application.Run ("'ThisWorkbook.calling'")
End Sub

Related

Access Embedded Macro and Event Procedure

I am trying to make basic msaccess form. And I created this save button through command button wizard. (Record Operations/ Save Record)
As you can see this save button's On_Click event =>>Embedded Macro.
I wanna write some additional code after insertion has occured.
Private Sub Command28_Click()
MsgBox "Done!"
End Sub
My question is: If On_Click=Macro; button save function works but msgbox code doesnt work. If On_Click=Procedure "Done!" message appears but save function doesnt work. How to work both of them (save function and message; in other words embedded macro and VBA code)

Is there a way to hide macros in Excel?

I just finished some VBA and I was wondering if there is a way to hide certain macros on Excel.
I need the user to run a certain macro and only that one, but it shows all the sub macros in Excel. I want to hide the unnecessary macros from the user so that way the user doesn't accidentally click on the wrong one.
You can also do this by placing the macros you want to hide in a separate module and using Option Private Module at the top of the module before the code. The macros will still be available to your project but will not appear in the Macros seen by the user when he clicks the Macros button.
You can either create a button in the ribbon to run the macro, or you can add "Private" before each "Sub" in the VBA editor that you don't want the user to easily access.
To subjectively 'hide' certain sub procedures (i.e. 'macros') from the (Alt+F8) Developer, Macros dialog use an optional non-variant parameter that means nothing.
Sub meh(Optional w As Worksheet)
Debug.Print "hello world"
End Sub
The meh macro will not show up in the list of macros to run. If you dim the parameter as variant it will show in the list. This is likely due to a optional variant parameter being able to use the IsMissing function. It will also not be able to be run from the VBE with F5 or stepped through with F8.
The test sub procedure will run the code correctly.
Sub test()
meh
End Sub
Sub meh(Optional w As Worksheet)
Debug.Print "hello world"
End Sub

Application.Quit in UserForm attempts to run rest of macro before exiting

My question is: using VBA in Excel 2013 how can I gracefully close an entire instance of Excel when the user decides they don't want to fill out a UserForm and clicks quit or cancel?
Currently, if the user clicks quit or cancel, I check to see if my instance is the only one open. If it is not, I can use ThisWorkbook.Close and I think I will be okay. However, if it is, I do not want the application to still be present, so I used Application.Quit. This, though, tries to finish running the macro, throws errors (originally "type mismatch" because I unload the form), and only closes after I click "Debug" or "End" (which it does so fast for either I cannot actually debug). I'm ignoring the first case for now and just trying to exit the entire application. It's a very long macro with a lot of subroutines and functions, so for debugging and posting here, I have shortened it. The type mismatch error no longer occurs, but I believe that was a consequence of the actual error: code running after the command to close the application is called.
First, here's the code that starts everything:
Private Sub CommandButton1_Click()
Call form_variables
frm_REQUEST.Show
Call a_REQUEST_main
End Sub
The subroutine
form_variables
is a subroutine that creates public variables so I can store the data from the UserForm.
frm_REQUEST.Show
initializes (including calling a function that finds another workbook, extracts a list, does some formatting, closes the workbook and enters the list into the userforms drop down box) and shows the form, and finally
a_REQUEST_main
uses the public variables (where UserForm data is stored) and does its thing (but shouldn't do anything if the UserForm is closed).
The code that is executed when .Show is called is:
Private Sub UserForm_Initialize()
' Get job numbers from other workbook
Dim job_selection_list As Variant
job_selection_list = get_job_list()
With frm_REQUEST.Job_Number_ComboBox
.List = job_selection_list
End With
' set focus on Job Numbers
JN_combobox.SetFocus
End Sub
Private Sub cancel_button_Click()
Set job_selection_list = Nothing
Unload Me
Application.Quit
End Sub
Private Sub submit_button_Click()
' Values from userform saved as global (?) variables so other subroutines can access.
End Sub
I stepped through the program and saw that, once Application.Quit is called in the UserForm, the macro, in the main subroutine, steps to
Call a_REQUEST_main
but it should really just close everything out. I tried doing "save" commands, and changing the order of things, and read about objects needing to be set to nothing (hence the setting of the job_selection_list which is created when the drop down list is initialized), but I cannot seem to get this to work, or find anything online. Can anyone provide some guidance or let me know of a better way to close an excel instance? Help me Stack-Overflow Kenobi, you're my only hope!
Thanks.
Just add a variable to account for when the user closes the form
in the form
'hold flag if users cancels form
Public btnCancel As Boolean
Private Sub CommandButton1_Click()
Unload Me
btnCancel = True
End Sub
'set the flag each time the form active
Private Sub UserForm_Activate()
btnCancel = False
End Sub
then in your code
Call form_variables
frm_REQUEST.Show
If frm_REQUEST.btnCancel Then
Application.Quit
Else
Call a_REQUEST_main
End If
Put Application.Quit in the form's Terminate event handler instead of in the button's Click event handler.
The reason is that clearly the procedure will keep running even if the form has unloaded. So use the events to your advantage.
Putting it in the Click event will unload the form, but the procedure will keep running which of course may raise errors or other undesired effects.
Note: You may be prompted to save/discard changes (if any) to the workbook.

Modeless form that still pauses code execution

Is there anyway to have a userform that acts modeless, while still pausing code execution like a modal form?
I'd like the userform to show, but still allow interaction with the parent program. Modal forms block interaction with the parent program. A modeless form would work, but I would like the code execution to pause while the form is up.
I've worked around this by creating an infinite loop that checks if the form is visible, but that seems a bit hacky.
Public Sub GetFormInfoAndDoStuff
ufForm.show vbModeless
Do while ufForm.Visible
DoEvents
Loop
' Do other stuff dependent on form
End Sub
EDITED to clarify that code after .show exists which must execute after the user form is done
You should be able display the form as vbModeless and only execute code when specifically requested, i.e., from a CommandButton or other control.
You then leave the form visible/shown until it is specifically closed, via the "X" button or via another control which calls the UserForm_Terminate event.
In order to achieve this, you may need to move some of your executable code in to another subroutine and/or module, and call this subroutine for example from a CommandButton_Click event.
You already have a subroutine somewhere that contains a line like:
Sub ShowTheForm()
UserForm1.Show vbModeless
End Sub
So the form is displayed properly to allow user-input to the parent application.
You don't really need to put any other code in the above module. We will put the other code in other modules/subs, and then call it from user controls like command buttons.
Example:
Take all of your executable code, and put it in another subroutine (and if it suits your organizational preference, another module), like:
Sub MyMacro(msg$)
MsgBox msg
End Sub
On the UserForm, add a command button and assign it the following code:
Sub CommandButton1_Click()
MyMacro "hello"
End Sub
Now, the form will display until the user clicks the "X" button. Code will only run when called from the command button.
EDIT FOR CLARIFICATION
You don't need to "pause" the execution using this method. Execution ends once the form is displayed modelessly, and the form persists. The object has some events which you may use to trigger further execution of code.
Here's what I do.
This example is for a form I called "Find Header". The code tries to find several column headers, but the markers for a few of them may be missing (and the header text may have been overwritten with something random), so I may need to pause and ask the user to locate (click on) some of the headers for me:
First, put this declaration in a standard module:
Public bDlgFindHeaderIsShowingModeless As Boolean
Then, put this in the event procedure for any button or other control that dismisses the modeless dialog, such as the Click events for the form's OK and Cancel buttons:
bDlgFindHeaderIsShowingModeless = False
Then, put this wherever in your code you want to show the modeless form while paused for user interactivity:
bDlgFindHeaderIsShowingModeless = True 'init
frmFindHeader.Show vbModeless
Do
If Not bDlgFindHeaderIsShowingModeless Then Exit Do
DoEvents
Loop
Yes, it churns the CPU, so you might not want to do it if you're on a single-core processor and there are critically important background processes running. But it works; the user is able to easily and smoothly interact with Excel while the modeless form displays. The user doesn't feel like they are fighting an endless loop.
The Best method would be to use two different subs. I was able to solve this problem without splitting my sub as follows:
Public Mode as Boolean
Sub Stuff()
If Mode Then
Goto Continue
End If
'Code before Userform
Mode = True
Userform.Show vbModeless
Exit Sub
Continue:
Mode = False
'Rest of your code
End Sub
I made "Mode" a global variable because I use this userform for multiple subs. If you are using a single sub you can use it locally. I also made "Mode" false when opening this workbook by going under "ThisWorkbook" Tab and adding the following code:
Private Sub Workbook_Open()
Mode = False
End Sub
This again will only be needed if you use your userform for more than one sub.
Last add this code under your Userform code when your proceed button is pressed.
Private Sub Confirm_Click()
Userform.hide
if Mode Then
Call Stuff
End If
End Sub
If you are only are using the one sub method skip the if statement and just call the sub.

VBA cannot find my macro when it has parameters

I am trying to write a macro that will be attached to a series of buttons in an Office 2010 backstage tab. Depending on the button clicked the Macro should be called with different parameters.
The issue I am having is that if the Macro is defined as having parameters then VBA will display the "Macros" dialog box, with no Macros listed. Removing the parameters from the declaration will allow the macro to run, but it needs the Macros to make sense.
The VBA being used is below:
Sub NewDocs(docType As String, docTemplate As String)
Dim sMyShellCommand As String
sMyShellCommand = "C:\NewDocs.exe " & docType & docTemplate
WordBasic.Shell (sMyShellCommand)
End Sub
Any ideas
If I've got your question right....
Because there is no place in the Macros dialog box for entering parameters, the macros with parameters are simply not shown.
If you want to make them visible in the dialog box, you can enumerate those functions you need (and I hope it is not a big number).
For example,
Sub NewDocs1
Dim docType As String
Dim docTemplate As String
docType = "the type you want"
docTemplate = "the template you want"
NewDocs docType, docTemplate
End Sub
In addition, as you said in the question, you wanted the macro to run when buttons were pressed. Then there is no need to make the macro visible in the dialog box (which saves your labor). Simply associate it with the button with correct parameters.
You can pass arguments from the Macro dialog. For example, if you have this macro
Sub myMacro(n As Long)
MsgBox n
End Sub
To run it, enter
mymacro 1000
... and press the Run button.
You can't call functions or subs with parameters from UI components, just subs without parameters. The best solution is to create a parameter free sub for each button you need to associate with, and call the parameterized sub or function from inside each sub