Excel form listbox issue when using locked property - excel

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

Related

VBA Forms in custom addin

I am trying to create an excel addin which has a button when clicked will display a VBA form. Its quite simple one list box and one command button.
Below is the code in Command button
Private Sub CommandButton1_Click()
ThisWorkbook.IsAddin = False
On Error GoTo ErrHandler:
KeyAcc = WorksheetFunction.VLookup(ComboBox1.Value, Sheet1.Range("A:B"), 2, False)
MsgBox KeyAcc
ThisWorkbook.IsAddin = True
Unload Me
Exit Sub
ErrHandler:
MsgBox ComboBox1.Value & " Not found in the Database"
ThisWorkbook.IsAddin = True
Unload Me
ActiveWorkbook.Save = False
End Sub
Code in form load
Private Sub UserForm_Activate()
Application.ScreenUpdating = False
Dim cCount As Integer
ThisWorkbook.IsAddin = False
ThisWorkbook.Sheets("Sheet1").Select
For cCount = 1 To 320
UserForm1.ComboBox1.AddItem Range("A" & cCount).Value
Next
ThisWorkbook.IsAddin = True
ComboBox1.SetFocus
End Sub
The problem i face is whenever the user activates this button on the first book ie, after opening a new excel and performs the operation it works, once done when i try to close the blank workbook it asks do you want to Save your changes to the Addin
Is there any way to avoid this?
You don't need all that work just to load your combobox:
Private Sub UserForm_Activate()
Me.ComboBox1.List = ThisWorkbook.Sheets("Sheet1").Range("A1:A320").Value
ComboBox1.SetFocus
End Sub

Disable a command button if mandatory fields are empty

I am creating a form out of excel-ActiveX but I have no idea how I can make the command button disabled if all mandatory fields (textbox and combobox) are empty. I've attached the sample form for your reference.
sample LA Form
Use the *_Change event for each control (and optionally the UserForm_Activate event) to set the .Enabled property for the Control Button.
For example, on a simple UserForm with 1 ComboBox (ComboBox1), 2 TextBoxes (TextBox1 and TextBox2) and 1 CommandButton (CommandButton1), the following code will ensure that CommandButton1 is disabled unless there is data in each of the other 3 controls:
Option Explicit
Private Sub CheckMandatoryFields()
'Is a separate sub to make it easy to edit for all Controls at the same time
If Len(TextBox1.Value) > 0 And Len(TextBox2.Value) > 0 And Len(ComboBox1.Value) > 0 Then
CommandButton1.Enabled = True
Else
CommandButton1.Enabled = False
End If
End Sub
Private Sub CommandButton1_Click()
MsgBox "Button is enabled!"
End Sub
Private Sub ComboBox1_Change()
CheckMandatoryFields
End Sub
Private Sub TextBox1_Change()
CheckMandatoryFields
End Sub
Private Sub TextBox2_Change()
CheckMandatoryFields
End Sub
Private Sub UserForm_Activate()
CheckMandatoryFields
End Sub
If your Buttons and Controls are in a Worksheet, then you need to change UserForm_Activate to Worksheet_Activate. If they are in different worksheets, or some in a Worksheet and others in a UserForm, then you will need to Fully Qualify your references (e.g. Sheet1.Textbox1.Value)
If you are using Form Controls in a Worksheet instead of ActiveX controls, then you can't use the _Change events, and the way you Reference the objects is different:
Sheet1.Shapes("TextBox1").TextFrame2.TextRange.Text 'The value of TextBox1
Sheet1.Shapes("ComboBox1").ControlFormat.Value 'Which Number item in ComboBox1 is selected
Sheet1.Shapes("ComboBox1").ControlFormat.List(n) 'The value of the nth item in ComboBox1
A Form Control button does not have an Enabled property - however, if you have a "Do Nothing" macro, you can bodge it like so:
Sub DoNothing()
'As it says
End Sub
Sub MakeASound()
Beep
End Sub
Sub ToggleButton()
If Sheet1.Shapes("Button 1").OnAction = "Sheet1!DoNothing" Then 'Disable Button 1
Sheet1.Shapes("Button 1").OLEFormat.Object.Font.ColorIndex = 16 'Font colour = Grey
Sheet1.Shapes("Button 1").OnAction = "Sheet1!DoNothing"
Else 'Enable Button 1
Sheet1.Shapes("Button 1").OLEFormat.Object.Font.ColorIndex = 1 'Font colour = Black
Sheet1.Shapes("Button 1").OnAction = "Sheet1!MakeASound"
End If
End Sub

How to use VBA to read the values of a checkbox from an Excel userform

I have created a userform that contains two checkboxes. I would like to be able to do different things depending on whether each box is checked or unchecked. However, it seems like no matter what I do, it will always tell me the original value of the checkboxes (false and false). Here is the code attached to clicking CommandButton1:
Private Sub CommandButton1_Click()
ReadData
End Sub
And here ReadData:
Sub ReadData()
Dim myForm As UserForm
Set myForm = UserForms.Add("ComplaintEntryForm")
Debug.Print (myForm!CheckBox1.Name)
Debug.Print (myForm!CheckBox1.Value)
Debug.Print (myForm!CheckBox2.Name)
Debug.Print (myForm!CheckBox2.Value)
End Sub
No matter how the boxes are checked, the immediate window always shows this:
VBA.UserForms.Add("ComplaintEntryForm").Show
CheckBox1
False
CheckBox2
False
I have a screenshot of the whole operation but it won't let me upload it because I'm a new user.
Try this method to load and show the form (this goes in a normal module):
Sub main()
Dim myForm As ComplaintEntryForm
Set myForm = New ComplaintEntryForm
myForm.Show
Set myForm = Nothing
End Sub
In the UserForm's own module, add the following:
Private Sub CheckBox1_Change()
readData
End Sub
Private Sub CheckBox2_Change()
readData
End Sub
Private Sub UserForm_Initialize()
Me.CheckBox1.Value = True
Me.CheckBox2.Value = False
End Sub
Private Sub readData()
Debug.Print Me.CheckBox1.Name
Debug.Print Me.CheckBox1.Value
Debug.Print Me.CheckBox2.Name
Debug.Print Me.CheckBox2.Value
End Sub
I've initialized the two checkboxes to specific values in the Initialize event. This means we are certain about the state the form will start in

Excel Userform Textbox Behavior

I have a textbox on a userform. It is the only textbox on the form. There are three labels and two buttons in addition to this textbox. Basically, I want the focus to remain on this textbox under all scenarios, other than the moment that one of the buttons would be clicked, but then I want the focus to come right back to the text box. Both buttons have "TakeFocusOnClick" and "TabStop" set to False. I was having problems with getting the focus set to the textbox, which is why I changed these two settings.
Once I changed these settings, the Enter key in the textbox stopped having any effect. I have events written for _AfterUpdate and _KeyPress for the textbox, but they don't fire. As you can see in the code, I have commented out the lines to set the focus to this textbox. Since it is now the only object that can take focus, these lines are not needed (theoretically). When I allowed the other objects to take focus, these lines weren't having any effect (focus was switching to the buttons despite these SetFocus lines).
Here is the code. It is very simple, except that the Enter key isn't triggering the event. Can anyone see why? Thanks.
Private Sub btnDone_Click()
Application.Calculation = xlCalculationAutomatic
formMath.Hide
'Clear statistics
Range("attempts").Value = 0
Range("correct").Value = 0
Sheet5.Range("A2:W500").ClearContents
End Sub
Private Sub btnSubmit_Click()
recordAnswer
'formMath.txtAnswer.SetFocus
End Sub
Private Sub txtAnswer_AfterUpdate()
recordAnswer
'formMath.txtAnswer.SetFocus
End Sub
Private Sub txtAnswer_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii = 13 Then
recordAnswer
End If
End Sub
Private Sub UserForm_Initialize()
'Initialize manual calculation
Application.Calculation = xlCalculationManual
Application.Calculate
'Initialize statistics
Range("attempts").Value = 0
Range("correct").Value = 0
Sheet5.Range("A2:W500").ClearContents
'Initialize first problem
newProblem
End Sub
Sub recordAnswer()
'Update statistics
Dim attempts, correct As Integer
attempts = Range("attempts").Value
correct = Range("correct").Value
Range("results").Offset(attempts, 0).Value = attempts + 1
Range("results").Offset(attempts, 1).Value = lblTopNum.Caption
Range("results").Offset(attempts, 2).Value = lblBotNum.Caption
Range("results").Offset(attempts, 3).Value = lblBop.Caption
Range("results").Offset(attempts, 4).Value = Range("Answer").Value
Range("results").Offset(attempts, 5).Value = txtAnswer.Text
If (Range("Answer").Value = txtAnswer.Text) Then
Range("results").Offset(attempts, 6).Value = 1
Else
Range("results").Offset(attempts, 6).Value = 0
End If
'Update attempts and success
Range("attempts").Value = attempts + 1
Range("correct").Value = correct + 1
newProblem
End Sub
Sub newProblem()
Application.Calculate
formMath.lblTopNum.Caption = Range("TopNum").Value
formMath.lblBotNum.Caption = Range("BotNum").Value
formMath.lblBop.Caption = Range("ProbType").Value
formMath.txtAnswer.Value = ""
'formMath.txtAnswer.SetFocus
End Sub
To start off
You can either in the design mode, set the TabIndex property of the Textbox to 0 or you can set the focus on the textbox in the UserForm_Initialize()
Private Sub UserForm_Initialize()
TextBox1.SetFocus
End Sub
Similarly after any operation that you perform, simply call the TextBox1.SetFocus to revert to the textbox.
Option Explicit
Private Sub UserForm_Initialize()
TextBox1.SetFocus
End Sub
Private Sub CommandButton1_Click()
MsgBox "Hello from Button 1"
TextBox1.SetFocus
End Sub
Private Sub CommandButton2_Click()
MsgBox "Hello from Button 2"
TextBox1.SetFocus
End Sub
Let me know if this is not what you want?
I found a way to accomplish this. In the code above I took out the _KeyPress and _AfterUpdate events and replaced them with:
Private Sub txtAnswer_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case 13: recordAnswer
End Select
End Sub
Not sure why the other methods didn't work, but this does.
Also not sure why simply setting the focus directly didn't work. I suspect that the focus was being set, but then something else was happening subsequently that was changing the focus off of the textbox. Just a guess.
Thanks for the help. I appreciate it.

show custom toolbar only with certain xls-file

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

Resources