VBA Word Hide/Show Button - vba

I have created a button in Word which can help me to save files much more easier. I have a question related to this button from the document. I have read that it is not possible to hide or show the button. So I though I will delete the button which worked, but once the project got a bit complicated.
Private Sub CommandButton1_Click()
CommandButton1.Select
Selection.Delete
UserForm1.Show
End Sub
My questions are:
Is it possible to use hide/show command for the CommandButtton1?
If 1 is not possible then is it possible to call from UserForm the function CommandButton1 and delete it from there if a certain value is true?

Unfortunately there is no way to hide/unhide buttons in Word, but deleting them instead is a good solution for this problem.
You can simply write a method and call that method from a UserForm.
Public Sub test()
CommandButton1.Select
Selection.Delete
End Sub
Now all you need to do is call the method :
call test
Edit:
Public Sub test()
CommandButton1.Select
Selection.Delete
'All the Other code
End Sub
Private Sub CommandButton1_Click()
call test
End Sub
Now you can just call the sub test to execute the same code as the CommandButton1 does.
Hope I could help.

Related

VBA - UserForm Button (Macro) to Continue running the sub

I have a sub called as sub1() which activates the userform1 through the command userform1.show()
This userform1 has a button called as continue. On clicking that button continue - A Macro called as Private Sub continuebutton() gets activated.
I want to program in such a way that it redirects to the line after userform1.show() in sub1().
Is it something that can be done?
Theoretically, what you want is possible, if you do it like this:
In the UserForm:
Private Sub btnContinue_Click()
flag = True
Debug.Print "I continue ..."
sub1
End Sub
In a module:
Public flag As Boolean
Public Sub sub1()
If flag Then
Debug.Print "sub 1 continues here..."
Else
flag = False
UserForm1.Show
Exit Sub
End If
End Sub
It will work exactly as intended, BUT it is not a good practice to work this way. (Some people may throw stones at you for using public variables at all in VBA.) Here are two articles, that give better ideas:
https://rubberduckvba.wordpress.com/2017/10/25/userform1-show/
Disclaimer - this one is mine:
http://www.vitoshacademy.com/vba-the-perfect-userform-in-vba/
On the form properties for userform1, set its "Modal" property to true.
When the form opens, it will have exclusive focus, and the code in sub1 will not continue running until after it closes. This may be the solution you need.
In the code below, the msgbox will only appear once userform1 closes:
sub sub1()
userform1.show()
msgbox "Now continuing with sub1"
end sub
No way as long as you show the form.
If you show the form modal, the calling routine continues if (and only if) the form is closed.
If you show the form non-modal, the code continues to run directly after the show - so it's already done.
So either you have to close the form when the user clicks the "continue..." button to let the calling macro continue or you have to split your code into two routines and call the second on button-click.
You can change your Sub1 as follows:
Sub sub1(Optional Continue As Boolean)
If Continue = True Then
DoSomeStuff
Exit Sub
End If
userform1.show
End sub
And then, you can call your sub1 using:
Private Sub continuebutton()
Call sub1(True)
End Sub
Hope it helps
If you don't want to go with the 'Modal Form' solution, you could add a subroutine to your main module, and call it when required. So, in userform1, you have:
sub sub1()
userform1.show()
end sub
public sub sub2()
msgbox "Now continuing..."
end sub
And then in userform1, set some code on its onClose event:
Private Sub continuebutton()
Call sub2()
end sub

Global reference to object on Click() sub (VBA)

I was wondering if there's a way to refer to the object of the "Click()" sub.
To make it clearer, let's say we have a button named foo1 and this button has a click sub "foo1_Click()". Does vba has a keyword to get the reference to foo1 that is global?
Something like:
Public Sub foo1_Click()
GlobalKeyword.Property
End Sub
P.s.: something like the word "this" from java refering to its own instance of class
Edit: In the example, the "GlobalKeyword" would refer to "foo1"
I think you're looking for the Application.Caller property found here.
In your case you would want to do something like....
Public Sub foo1_Click()
Dim button As Shape
Set button = ThisWorkbook.Sheets("sheetname").Shapes(Application.Caller)
End Sub
Of course after that you would want to do some error checking to make sure button is not nothing.
If you want to use the same code for a lot of buttons, then you may be better of using a separate subroutine.
Private Sub foo1_Click()
Call do_something
End Sub
Private Sub foo2_Click()
Call do_something
End Sub
Sub do_something() 'called by the foo _Click event
MsgBox Application.Caller
End Sub
This way, you it is easy to maintain the core functionality for all buttons simply by updating the do_something procedure.

Conditionally run VBA code

Is it possible to have multipe buttons, lets say 'Button 1' and 'Button 2' run the same VBA code but yield a different result based on the button that was pressed?
For instance when I press button 1 I want it to go to a website, load data and put it on to Sheet 1. But when I press button 2, it goes to the same site and loads it to Sheet 2.
I know I can have multiple instances of the same VBA code (with different names) however I am hoping to simplify the code and prevent it from being overly complicated.
If you are using a Forms button you can assign the same macro and use Application.Caller to return the name/id of the calling button.
Sub Test()
MsgBox Application.Caller & " was pressed"
End Sub
Create one sub to do the work and pass the sheetname as an argument to that sub. I did it with a string variable, but you can do it with a worksheet variable as well.
Sub Button1_Click()
LoadWebsiteToSheet "Sheet1"
End Sub
Sub Button2_Click()
LoadWebsiteToSheet "Sheet2"
End Sub
Sub LoadWebsiteToSheet(sName as String)
'... code to load website to Worksheets(sName)
End Sub
I was leaning more towards brettdj's solution as well
If you assign the same macro to many buttons, you will get different results based on the button name.
You could name the button to the sheet you wanted. Practice with this. Add several buttons and assign this code to them. Click each button to see what happens.
Sub GetButtonName()
Dim Btn As String
Btn = ActiveSheet.Shapes(Application.Caller).Name
MsgBox Btn
End Sub

What's the best practice for getting a value from a combobox on a userform?

There's a lot of information and a lot that you can do with userforms but I can't really find a standard way to use them. Let's say I have a userform with a standard dropdown list that asks someone to choose a fruit. In the userform code I will put the below code after adding a combo box called fruitcombo:
Private Sub UserForm_Initialize()
userform1.fruitcombo.AddItem "Peach"
userform1.fruitcombo.AddItem "Pear"
userform1.fruitcombo.AddItem "Grape"
End Sub
I will also add a commandbutton which will be labeled "Submit" and in that event:
Private Sub Submit_Click()
Me.Hide
End Sub
That's where it starts to get hazy. What's the best way to capture the answer that was selected? One way I can think would be to make a global variable called fruitanswer and then instead of the Me.Hide we can skip straight to Unload Me
Ex:
Private Sub Submit_Click()
fruitanswer = fruitcombo.value
Unload Me
End Sub
Or we can have fruitanswer as a private variable in the module where the userform is called and then unload it in there. There are also multiple ways to initialize the userform. I'm also wondering the best way to initialize it. The Show method will automatically initialize it, but the Hide method WON'T automatically de-initialize it. For that, the Unload statement is necessary. So does anyone initialize it before calling the Show method using the Load statement?
Ex:
Load userform1 'Any point to including this?
userform1.show
'user chooses a fruit and clicks submit button
'userform is hidden by commandbutton but not unloaded yet
fruitanswer = fruitcombo.value
Unload userform1
Out of these options, which is the best method? Is there anything to make it more efficient?
You can wrap the whole thing in a single function call:
strFruit = UserForm1.GetFruit()
Then, in your UserForm, have it do the work of displaying and unloading itself like so:
Private bOK As Boolean
Public Function GetFruit() As String
bOK = False
Me.Show vbModal
If bOK Then GetFruit = ComboBox1.Text
Unload Me
End Function
Private Sub cmdOK_Click()
bOK = True
Me.Hide
End Sub
Private Sub cmdCancel_Click()
Me.Hide
End Sub
This assumes you have buttons named cmdOK and cmdCancel and a combobox named ComboBox1.
Since Show() is being called modally, the code after it won't execute until the form is closed or hidden. When either button is clicked (or the form is closed by other means) then the code continues, the selected text is returned (if OK was clicked), and the form unloads itself.
The beauty of doing it this way is that your calling code doesn't need to worry about instantiating and destroying the form each time it's called. It's just a single statement to load the form and get the return value.
Of course, you'll need to add the code to populate the combobox with whatever items you wish to display.

How do i perform the desired operation If one of the command button is OK and the other is CANCEL

Can anyone tell me How do i do certain task based on the command button options.
I have a Userform where user submits his data and it has 2 command buttons one is OK and the other is CANCEL. I have to exit when user clicks CANCEL and continue the Process when user clicks ok
file_name=userform1.textbox1.value
This is how we can get the data of the text box into our functions but what is the way to know which command button key is pressed ? Becuase if i press OK or CANCEL the operation is still being performed. I have tried like these
value=userform1.commandbutton1.value
value2=userform1.commandbutton2.value
not working. I even tried these
commandbutton1_click() \\ this is the OK command button
call main
end sub
commandbutton2_click() \\ this is the CANCEL command button
end sub
I have tried To call the main sub_routine from the OK sub routine But it says main routine not found becuase I have written these codes in the thisworkbook.and the commandbutton1_click routine is inside the Userform1 module
SO how do i make it work? I hope you understood where I'm Stucking up.Thank you in advance
Private Sub CommandButton1_Click() 'should be called cmdOk
main
End Sub
Private Sub CommandButton2_Click() 'should be called something like cmdCancel
Unload Me
End Sub
Private Sub main()
'DO PROCESSING
End Sub
Do you call main on Form_Load() or Form_Activate() or anything like this? When clicking Cancel, the above unloads the form. When clicking Ok, it starts the processing. There is not more to it.
If you want to keep the main method outside of your userform, you can try something like this, based on the example given by #cularis
' This way you can keep your code in ThisWorkbook
' I would recommend creating a new module.
' You can name your module whatever you'd like.
Private Sub CommandButton1_Click()
ThisWorkbook.main
End Sub
Private Sub CommandButton2_Click()
Unload Me
End Sub