i have a macro (Makro1) that is assigned to a button in a custom toolbar (Custom1) with caption "Schutzstatus". i want the toolbar only to be loaded with this very xls-file.
can someone help me out with the code?
i managed to customize the tooltip:
Application.CommandBars("Custom1").Controls(1).TooltipText = "Abfrage des Schutzstatus der Arten im Zwischenspeicher"
but i fail in creating the whole thing by vba..
thanks in advance,
kay
You don't actually need to (re)create the whole toolbar on loading your XLS, but you need to display/hide it during certain navigations
1 create the toolbar
2 attach it to your XLS (view / toolbars / customize .... / attach)
3 create event procedures to show/hide your toolbar; unless you want to have a specific behaviour for different sheets, the following should be enough to care for all navigation:
Private Sub Workbook_Activate()
' show toolbar
Application.CommandBars("CoolBar").Visible = True
Application.CommandBars("CoolBar").Controls(1).TooltipText = "C'mon squeeze me"
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
' drop toolbar
Application.CommandBars("CoolBar").Delete
End Sub
Private Sub Workbook_Deactivate()
' see if we have a toolbar (it might have been already deleted by "Workbook_BeforeClose"
' if yes - hide it
Dim Idx As Integer
For Idx = 1 To Application.CommandBars.Count
If Application.CommandBars(Idx).Name = "CoolBar" Then
Application.CommandBars("CoolBar").Visible = False
End If
Next Idx
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
' display toolbar
Application.CommandBars("CoolBar").Visible = True
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
Application.CommandBars("CoolBar").Visible = False
End Sub
Place all in the "ThisWorkbook" object - so they fire on all sheets.
4 After saving the toolbar with the XLS and testing, close the XLS - the toolbar will be still present in your application object - and delete the toolbar from there. Don't panic, it's coming back when you re-open your XLS file.
Hope this helps
Tschüss MikeD
Actually the answer was close but didn't work for me. That .Delete does delete the command bar completely as confirmed by Kay in his last comment. You basically had to recreate but bar and button again when the workbook is opened. Below is the improved code:
Private Sub Workbook_Activate()
' show toolbar
Dim SortBar As CommandBar
Dim BarControl As CommandBarControl
Set SortBar = FindCommandBar("SortBar")
If SortBar Is Nothing Then
Set SortBar = Application.CommandBars.Add("SortBar")
Set BarControl = SortBar.Controls.Add
BarControl.OnAction = "Your_Macro_Name"
BarControl.Caption = "Text for your button"
BarControl.Style = msoButtonCaption
End If
SortBar.Visible = True
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
' drop toolbar
Application.CommandBars("SortBar").Delete
End Sub
Private Sub Workbook_Deactivate()
' see if we have a toolbar (it might have been already deleted by "Workbook_BeforeClose"
' if yes - hide it
Dim SortBar As CommandBar
Set SortBar = FindCommandBar("SortBar")
If Not SortBar Is Nothing Then
SortBar.Visible = False
End If
End Sub
Private Function FindCommandBar(Name As String) As CommandBar
Dim Idx As Integer
For Idx = 1 To Application.CommandBars.Count
Set FindCommandBar = Application.CommandBars(Idx)
If FindCommandBar.Name = Name Then
Exit Function
End If
Next Idx
Set FindCommandBar = Nothing
End Function
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
' display toolbar
Application.CommandBars("SortBar").Visible = True
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
Application.CommandBars("SortBar").Visible = False
End Sub
Related
I have created a multipage user form which dynamically populates with a set of identical frames and each of them has 2 option buttons based on previous user selections. I am trying to check if at least one of the option buttons is selected within each frame but don't seem to access the option buttons in code even through I know what their names will be. I will then be transferring the selection to a worksheet so need to be able to see what they have selected. Any help would be appreciated, I use VBA for excel infrequently so its always a struggle to be honest.
I'm getting closer, I've used this code of another post and changed it slightly while I trial what I am doing. Getting there slowly. :)
I'm not sure what some of the Class modules part is doing but its working.
Forms: Userform1
Option Explicit
Friend Sub OptionButtonSngClick(o As MSForms.OptionButton)
Dim cControlCheck As MSForms.Control
Dim cControlCheck1 As MSForms.Control
Dim cControlFrame As MSForms.Control
Dim strName As String
If Left(o.Name, 2) = "qN" Then
o.BackColor = RGB(256, 0, 0)
ElseIf Left(o.Name, 2) = "qY" Then
o.BackColor = RGB(0, 256, 0)
End If
For Each cControlCheck In UserForm1.Controls
If TypeName(cControlCheck) = "Frame" Then
For Each cControlCheck1 In Me.Controls(cControlCheck.Name).Controls
If TypeName(cControlCheck1) = "OptionButton" Then
If cControlCheck1 = False Then
cControlCheck1.BackColor = RGB(240, 240, 240)
End If
End If
Next
End If
Next
End Sub
Friend Sub cmdCheck_Click()
Dim cControlCheck2 As MSForms.Control
Dim cControlCheck3 As MSForms.Control
Dim cCollection As Collection
Set cCollection = New Collection
For Each cControlCheck2 In UserForm1.Controls
If TypeName(cControlCheck2) = "Frame" Then
For Each cControlCheck3 In Me.Controls(cControlCheck2.Name).Controls
If TypeName(cControlCheck3) = "OptionButton" Then
cCollection.Add cControlCheck3
End If
Next
End If
Next
If cCollection(1).Value = False And cCollection(2).Value = False Then
MsgBox ("Make a selection")
End If
End Sub
Class Module: OPtionButtonEvents
Option Explicit
Private WithEvents ob As MSForms.OptionButton
Private CallBackParent As UserForm1
Private CallBackParent1 As UserForm1
Private Sub ob_Change()
End Sub
Private Sub ob_Click()
Call CallBackParent.OptionButtonSngClick(ob)
End Sub
Private Sub ob_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Call CallBackParent.OptionButtonDblClick(ob)
End Sub
Friend Sub WatchControl(oControl As MSForms.OptionButton, oParent As UserForm1)
Set ob = oControl
Set CallBackParent = oParent
End Sub
i really need some help, im new to VBA programming and just learn all by myself.
Thx for all Help.
What is my problem ?
I have more than 1 Userforms in my Tool and every Userform contains alot of Buttons some Buttons the same on other Userforms and some different.
if i click a button in a Userform, the class cant give my userform.name as a variable to the next module.
in the Code "Class" sUserform is alltime "nothing"
My Code
Userform
Option Explicit
Private myBtn As clsCMD
Private Sub UserForm_Activate()
modUI.ufGETICON Me
End Sub
Private Sub UserForm_Initialize()
modMSG.ufINFO
modAUTOOPEN.Workbook_Open Me
Dim ctrl As Control
For Each ctrl In frmMain.Controls
If TypeOf ctrl Is MSForms.CommandButton Then
Set myBtn = New clsCMD
Set myBtn.Button = ctrl
End If
Next
End Sub
Class
Option Explicit
Public WithEvents Button As MSForms.CommandButton
Private Sub Class_Initialize()
Static collButton As New Collection
collButton.Add Me
End Sub
Private Sub Button_Click()
Dim sButton As String
sButton = Button.Name
CMDTEST *sUserform*, Button
End Sub
Private Sub CMDTEST(*sUserform As Object*, sButton As Object)
If sButton.Name = "cmd_Admin" Then
modCMD.cmd_Admin
End If
If sButton.Name = "cmd_OItem" Then
modCMD.cmd_OItem sUserform
End If
End Sub
Modul
Option Explicit
Public sUserform As Object
Public Sub cmd_Admin()
Dim sAnswer As String
sAnswer = InputBox("Passwort f?r den Zugang zum Adminbereich eingeben:", "Zugang Adminbereich")
If sAnswer = sPASS Then
Unload frmMain
frmMain.Hide
ElseIf sAnswer = "" Then
Exit Sub
Else
MsgBox "Inkorrektes Passwort eingegeben", vbInformation + vbOKOnly, "Passwortabfrage negativ"
End If
Application.Visible = True
End Sub
Public Sub cmd_OItem(sUseform As Object)
sUserform.Hide
frmOnIt.Show
End Sub
It's difficult to give you a precise answer without seeing how you want to apply this code across your Userforms.
If, for example, you're running the loops on each Userform, then couldn't you just add a Userform property to your class and pass in the appropriate Userform?
For Each ctrl In frmMain.Controls
If TypeOf ctrl Is MSForms.CommandButton Then
Set myBtn = New clsCMD
With myBtn
Set .Owner = frmMain
Set .Button = ctrl
End With
End If
Next
Otherwise, I guess you'd just have to run up the control ladder until you find a Userform:
Private Function GetUserFormName(ctrl As Object) As String
Do
Set ctrl = ctrl.Parent
Loop Until TypeOf ctrl.Parent Is MSForms.UserForm And Not TypeOf ctrl.Parent Is MSForms.Frame
GetUserFormName = ctrl.Parent.Name
End Function
So your routine would contain code something like:
Private Sub CMDTEST(sButton As Object)
Dim n As String
n = GetUserFormName(sButton)
End Sub
I solved the problem now and I'd like to hear your feedback if it's a good way or not. Maybe there are some improvements to do?
You have to know this project is huge and i have more than 20 Userforms and over all Userforms more than 300 buttons.
Most of these buttons are like a Menu (laststep, nextstep, finish, cancel, OItem, Test, and some more). These are all doing the same every time,
and then i have some special buttons they are only 1-5 times on all userforms but these buttons should also doing the same on their Userforms (like refresh, change picture from Item, change something else etc.)
I tested this code on a VBA Project on 3 Userforms
Code starting everytime from modAUTOOPEN, Auto_Open
Userforms are:
ALL Userforms have the same code at this time for this test.
frmMain (starting site)
frmOnIt
frmTeM
.
Option Explicit
Private myBtn As clsCMD
Private myBtnColl As Collection
Private Sub UserForm_Activate()
modUI.ufGETICON Me
End Sub
Private Sub UserForm_Initialize()
modMSG.ufINFO
modAUTOOPEN.Workbook_Open Me
Dim ctrl As Control
Set myBtnColl = New Collection
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.CommandButton Then
Set myBtn = New clsCMD
Set myBtn.UserForm = Me
Set myBtn.button = ctrl
myBtnColl.Add myBtn
End If
Next
End Sub
Modules are:
modARCHIV
(not relevant, just old material - maybe its useful in the future)
modAUTOOPEN
(standard stuff)
.
Option Explicit
Public sUSER As String
Public Const sPASS As String = "12345"
Public Sub Workbook_Open(sUSerform As Object)
modUI.ufPOSITION1 sUSerform
End Sub
Public Sub Auto_Open()
' User basierend auf Exceluser ausw?hlen
sUSER = Application.Username
modData.defDEFAULTS
modData.defWORKSHEETS
Load frmMain
frmMain.Show
End Sub
modCHECKS
(not relevant atm, checking which users are using the tool etc.)
modCMD
(where I program all my CMDs for every UF)
.
Option Explicit
Public Sub cmd_Admin()
Dim sAnswer As String
sAnswer = InputBox("Passwort f?r den Zugang zum Adminbereich eingeben:", "Zugang Adminbereich")
If sAnswer = sPASS Then
Unload frmMain
frmMain.Hide
ElseIf sAnswer = "" Then
Exit Sub
Else
MsgBox "Inkorrektes Passwort eingegeben", vbInformation + vbOKOnly, "Passwortabfrage negativ"
End If
Application.Visible = True
End Sub
Public Sub cmd_OItem(sUfName As Object)
Application.ScreenUpdating = False
sUfName.Hide
frmOnIt.Show
End Sub
Public Sub cmd_Test(sUfName As Object)
Application.ScreenUpdating = False
sUfName.Hide
frmTeM.Show
End Sub
modDATA
(standard stuff)
modFUNC
(not relevant atm, for new functions)
modLOAD
(not relevant atm, load all datas to specific UF)
modMSG
(programming and updating all infoboxes on alle UF)
modSAVE
(not relevant atm, save all data from UF to WS or in new WB)
modUI
(checking how many screens and where to open, adding minimize button and windowstaskbar button, etc.)
ClassModules are:
clsCMD (should the connection betweend buttons on UF and modCMD)
.
Option Explicit
Public WithEvents button As MSForms.CommandButton
Private c_Userform As Object
Public Property Set UserForm(ByVal UfName As Object)
Set c_Userform = UfName
End Property
Private Sub Button_click()
CMDTEST UfName, button
End Sub
Public Sub CMDTEST(UfName As Object, button As Object)
Dim sButton As String
Dim sUfName As String
sButton = button.Name
sUfName = c_Userform.Name
If button.Name = "cmd_Admin" Then
modCMD.cmd_Admin
End If
If button.Name = "cmd_OItem" Then
modCMD.cmd_OItem c_Userform
End If
If button.Name = "cmd_Test" Then
modCMD.cmd_Test c_Userform
End If
'If Button.Name = "cmd_Auftragstool" Then
' modCMD.cmd_Auftragstool c_Userform
'End If
'If Button.Name = "cmd_Beenden" Then
' modCMD.cmd_Beenden c_Userform
'End If
End Sub
I have a UserForm that prompts the user to both to select a file (Application.FileDialog(.soFileDialogOpen)) and to click a couple of options (various checkboxes). Both of these are required, so I want the OK button to only be enabled if a file has been selected and at least one checkbox has been clicked. I have a sub (CheckAndEnable) that runs both after a file is selected and after any checkbox is clicked (I am using a class to handle this).
Here is a very simplified version of the userform code. The userform has a button called buttonOK, a button that selects a file buttonSelectFile, and a variable number of checkboxes.
Option Explicit
Dim colChkboxes As Collection
Dim intchoice As Integer, AtLeastOneChecked As Boolean, strPath As String
Private Sub buttonOK_Click()
Hide
End Sub
Private Sub buttonSelectFile_Click()
Dim intchoice As Integer
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
intchoice = Application.FileDialog(msoFileDialogOpen).Show
If intchoice <> 0 Then
strPath = Application.FileDialog(msoFileDialogOpen).SelectedItems(1)
labelPath.Caption = strPath
End If
CheckAndEnable
End Sub
Public Sub CheckAndEnable()
Dim ctrl As Control
' checks all checkboxes to determine if at least one is checked
AtLeastOneChecked = False
For Each ctrl In Me.Controls
If TypeName(ctrl) = "CheckBox" Then
If ctrl.Value = True Then
AtLeastOneChecked = True
Exit For
End If
End If
Next ctrl
' enable the OK button if file selected and at least one checkbox clicked
If (AtLeastOneChecked = True) And (Not IsEmpty(strPath)) And (strPath <> "") Then
buttonOK.Enabled = True
Else
buttonOK.Enabled = False
End If
End Sub
Private Sub UserForm_Initialize()
buttonOK.Enabled = False
' declare vars
Dim ctrl As Control
Dim obj As clsCheckBox
Set colChkboxes = New Collection
' set each checkbox to CheckBox Class that handles if checkbox is
clicked.
For Each ctrl In Me.Controls
If TypeName(ctrl) = "CheckBox" Then
Set obj = New clsCheckBox
obj.AssignClicks ctrl
colChkboxes.Add obj
End If
Next ctrl
End Sub
I also have a Class Module clsCheckBox with the following code, which calls CheckAndEnable whenever a checkbox is clicked.
Private WithEvents chkbox As MSForms.CheckBox
Public Sub AssignClicks(ctrl As Control)
Set chkbox = ctrl
End Sub
Private Sub chkbox_Change()
Call MyUserform.CheckAndEnable
End Sub
When I run the UserForm directly, everything works beautifully. The problem is that when I call the userform in a module (this userform is part of a series of userforms in a larger script), the CheckAndEnable script runs when checkboxes are clicked but doesn't enable the OK button as it is supposed to. I have researched this extensively but haven't been able to find anything. Any help would be appreciated!
When you call MyUserform.CheckAndEnable in the chkbox_Change() sub of clsCheckBox, it runs the CheckAndEnable script for the default instance of the UserForm. Since the module showing the userform was creating a non-default instance of the form, the CheckAndEnable script was failing because it had no knowledge of what checkboxes/variables/etc had been changed in the non-default version.
Thanks to Mathieu Guindon for the solution. See UserForm1.Show for more details.
Let me preface my question with the fact that I am self taught, so please provide as much detail as possible and bear with me if I need you to explain differently or multiple times.
I created a notation/email generating tool for my team using Microsoft Visual Basic 7.0. The only complaint that I received on it was that many of them are not used to hot keys so they depend on using the mouse but right click didn't work. I was able to find code that creates a pop-up for copy and paste when they use right click, and it works great on the few textboxes that are on the main form itself, however it does not work on the majority of the textboxes as they are in a Multipage.
Does anyone know how to alter the below code to work for textboxes on a Multipage? Also, before it is suggested, I did toy with the idea of moving everything out of the Multipage, however that format is the easiest as there are multiple stages and types of notes/emails that they would need to send at any time, so having tabs available for them to simply click is the most user friendly that I was able to create and that they all agreed on.
Thank you all so much in advance!
Code in the form:
Dim cBar As clsBar
Private Sub UserForm_Initialize()
On Error GoTo Whoa
Application.EnableEvents = False
Set cBar = New clsBar
cBar.Initialize Me
Letscontinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
Code in a Class Module:
Option Explicit
'Popup objects
Private cmdBar As CommandBar
Private WithEvents cmdCopyButton As CommandBarButton
Private WithEvents cmdPasteButton As CommandBarButton
'Useform to use
Private fmUserform As Object
'Control array of textbox
Private colControls As Collection
'Textbox Control
Private WithEvents tbControl As MSForms.TextBox
'Adds all the textbox in the userform to use the popup bar
Sub Initialize(ByVal UF As Object)
Dim Ctl As MSForms.Control
Dim cBar As clsBar
For Each Ctl In UF.Controls
If TypeName(Ctl) = "TextBox" Then
'Check if we have initialized the control array
If colControls Is Nothing Then
Set colControls = New Collection
Set fmUserform = UF
'Create the popup
CreateBar
End If
'Create a new instance of this class for each textbox
Set cBar = New clsBar
cBar.AssignControl Ctl, cmdBar
'Add it to the control array
colControls.Add cBar
End If
Next Ctl
End Sub
Private Sub Class_Terminate()
'Delete the commandbar when the class is destroyed
On Error Resume Next
cmdBar.Delete
End Sub
'Click event of the copy button
Private Sub cmdCopyButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
fmUserform.ActiveControl.Copy
CancelDefault = True
End Sub
'Click event of the paste button
Private Sub cmdPasteButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
fmUserform.ActiveControl.Paste
CancelDefault = True
End Sub
'Right click event of each textbox
Private Sub tbControl_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If Button = 2 And Shift = 0 Then
'Display the popup
cmdBar.ShowPopup
End If
End Sub
Private Sub CreateBar()
Set cmdBar = Application.CommandBars.Add(, msoBarPopup, False, True)
'We’ll use the builtin Copy and Paste controls
Set cmdCopyButton = cmdBar.Controls.Add(ID:=19)
Set cmdPasteButton = cmdBar.Controls.Add(ID:=22)
End Sub
'Assigns the Textbox and the CommandBar to this instance of the class
Sub AssignControl(TB As MSForms.TextBox, Bar As CommandBar)
Set tbControl = TB
Set cmdBar = Bar
End Sub
Get ActiveControl name on a Multipage control
It's necessary to know the multipage's selected Page via a helper function (ActiveControlName) using SelectedItem property and getting the control (its name) from there. Change your button click events as follows:
Relevant button click events in class module clsBar
'Click event of the copy button
Private Sub cmdCopyButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
Dim sACN As String
sACN = ActiveControlName(fmUserform) ' find control's name
' Debug.Print sACN & ".Copy"
fmUserform.Controls(sACN).Copy ' << instead of fmUserform.ActiveControl.Copy
CancelDefault = True
End Sub
'Click event of the paste button
Private Sub cmdPasteButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
Dim sACN As String
sACN = ActiveControlName(fmUserform)
' Debug.Print sACN & ".Paste"
fmUserform.Controls(sACN).Paste ' << instead of fmUserform.ActiveControl.Paste
CancelDefault = True
End Sub
Helper function called by above click events
Function ActiveControlName(form As UserForm) As String
'cf Site: https://stackoverflow.com/questions/47745663/get-activecontrol-inside-multipage
'Purpose: get ActiveControl
Dim MyMultiPage As MSForms.MultiPage, myPage As MSForms.Page
If form.ActiveControl Is Nothing Then
' do nothing
ElseIf TypeName(form.ActiveControl) = "MultiPage" Then
Set MyMultiPage = form.ActiveControl
Set myPage = MyMultiPage.SelectedItem
ActiveControlName = myPage.ActiveControl.Name
Else
ActiveControlName = form.ActiveControl.Name
End If
End Function
Side note
Suggest to check for the length of selected text strings in case of empty strings to prevent from unwanted results.
I'm having an issue with the way a listbox behaves on an Excel form. Steps to reproduce the issue:
Create a user form with one listbox control
Use following code with this user form:
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Me.ListBox1.Locked = True
Me.ListBox1.Locked = False
End Sub
Private Sub UserForm_Initialize()
Dim i As Integer
For i = 1 To 10
Me.ListBox1.AddItem i
Next i
End Sub
When the form is first shown, I am able to navigate the list box normally, using arrow keys and page keys. However, after the double-click event is triggered, all keyboard navigation has no effect, including tabbing to other controls (if they're on the form). Clicking on the listbox does seem to work, and the focus outline is shown correctly, but there's something wrong with the way the focus is handled after the listbox is locked and then unlocked. What is going on?
Using Office 2013 32-bit edition.
I managed to replicate this issue, and setting the focus somewhere else before locking and unlocking the listbox worked for me:
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Me.TextBox1.SetFocus 'or some other control.
Me.ListBox1.Locked = True
Me.ListBox1.Locked = False
Me.ListBox1.SetFocus
End Sub
2 solutions I tested that allows you to use Arrow Keys to navigate.
Given that there isn't a single click event handler, try call the Single Click Event after the DblClick (works all the time):
Private Sub ListBox1_Click()
Debug.Print "ListBox1_Click()"
End Sub
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "ListBox1_DblClick()"
With Me.ListBox1
.Locked = True
.Locked = False
End With
ListBox1_Click
End Sub
Private Sub UserForm_Initialize()
Dim i As Integer
For i = 1 To 10
Me.ListBox1.AddItem i
Next i
End Sub
Setting the Cancel = False at the end of DblClick. (Sometimes does not work!)
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "ListBox1_DblClick()"
With Me.ListBox1
.Locked = True
.Locked = False
End With
Cancel = False
End Sub
Private Sub UserForm_Initialize()
Dim i As Integer
For i = 1 To 10
Me.ListBox1.AddItem i
Next i
End Sub
Changing the zoom in the sheet that has the listbox worked for me.
Private Sub Worksheet_Activate()
Dim temp As Double
Application.ScreenUpdating = False
'Change worksheet zoom setting for the active window
temp = ActiveWindow.Zoom
ActiveWindow.Zoom = temp + 10
ActiveWindow.Zoom = temp
Application.ScreenUpdating = True
End Sub