adding events on runtime for checkbox in userform in excel - vba

I have tried #DaveShaw code, for events on runtime for checkboxes, is click not an valid method for checkbox? It never get into the method checkBoxEvent_click
Dim CheckBoxArray() As New ClassEvents
for i=0 to 10
Set cTemp = MOM.Frame_MOM_MOM.Controls.Add("Forms.CheckBox.1")
With cTemp
.Top = HeaderOffset + RowOffset + i * 25 'your top pos
.Visible = True
.Left = 30 'your left pos
.Width = widthOfLabel 'your width
.Name = Replace(keyArrays(i, 1), " ", "_")
.Caption = keyArrays(i, 1) 'your caption ,
End With
ReDim Preserve CheckBoxArray(0 To i)
Set CheckBoxArray(i).checkBoxEvent = cTemp
next i
and my ClassEvents class looks like this:
Public WithEvents checkBoxEvent As MSForms.checkBox
Private Sub checkBoxEvent_click()
MsgBox "halla" 'checkBox.Caption
End Sub

you have to keep Dim CheckBoxArray() As New ClassEvents at the very top of your userfom code pane, thus outside any of its subs/functions
furthermore use Option Explicit statement too
it becomes
Option Explicit
Dim CheckBoxArray() As New ClassEvents '<--| keep this line at the very top of your userform code pane
Private Sub UserForm_Initialize()
Dim i As Long
Dim cTemp As MSForms.CheckBox '<-- with "Option Explicit" you have to declare all your variables
For i = 0 To 10
Set cTemp = MOM.Frame_MOM_MOM.Controls.Add("Forms.CheckBox.1")
With cTemp
.Top = HeaderOffset + RowOffset + i * 25 'your top pos
.Visible = True
.Left = 30 'your left pos
.Width = widthOfLabel 'your width
.Name = Replace(keyArrays(i, 1), " ", "_")
.Caption = keyArrays(i, 1) 'your caption ,
End With
ReDim Preserve CheckBoxArray(0 To i)
Set CheckBoxArray(i).checkBoxEvent = cTemp
Next i
End Sub
furthermore, since you already know the dimension of your array, Dim it at the beginning and don't ReDim it at every iteration:
Option Explicit
Dim CheckBoxArray(0 To 10) As New ClassEvents '<--| keep this line at the very top of your userform code pane
Private Sub UserForm_Initialize()
Dim i As Long
Dim cTemp As MSForms.CheckBox '<-- with "Option Explicit" you have to declare all your variables
For i = 0 To 10
Set cTemp = MOM.Frame_MOM_MOM.Controls.Add("Forms.CheckBox.1")
With cTemp
.Top = HeaderOffset + RowOffset + i * 25 'your top pos
.Visible = True
.Left = 30 'your left pos
.Width = widthOfLabel 'your width
.Name = Replace(keyArrays(i, 1), " ", "_")
.Caption = keyArrays(i, 1) 'your caption ,
End With
Set CheckBoxArray(i).checkBoxEvent = cTemp
Next i
End Sub

Related

Add code to dynamically added checkbox in form VBA

I wrote sub which add checkbox like below
Sub WstawCHB(i As Integer, ByVal ws As Worksheet)
Dim NewCheckBox As MSForms.CheckBox
Set NewCheckBox = ListaObecnosciForm.Controls.Add("Forms.Checkbox.1", "CB" & i, True)
With NewCheckBox
.Top = 20 * i
.Left = 20
.Width = 450
.Height = 24
.Caption = ws.Cells(2 + i, 27)
.Value = False
End With
End Sub
How to add some action to the checkbox in code. For example (.OnAction = "CheckBox1_Click")
Private Sub CheckBox1_Click()
MsgBox "Hello World!"
End Sub
Additional information: the Sub is calling in loop in code below, so I have to "inject" code for every created checkbox for each iteration of loop
Sub DodajCHB(ByVal LW As Integer, ByVal ws As Worksheet)
Dim i As Integer
i = 1
Do While i < LW
Call WstawCHB(i, ws)
i = i + 1
Loop
End Sub

How to dynamically create an element's position?

I have an Outlook userform to show selected emails.
Since listboxes cannot have text in the column-headers, I adapted the solution proposed here.
My Problem:
After intialization of the form, the header-box is at a wrong position and with a wrong size. Some checks show, that the correct values are allocated by the function createListboxHeader() - and without error. But checking the header-box's position and size after that function (back in initialization), the values are wrong - prove of what I see.
Sometimes it works correctly, but most of the times not.
Code:
Public Sub createListboxHeader(lstBody As ListBox, arrHeaders)
Dim lstHeader As ListBox
Dim i As Integer
'create new listbox for the header
Set lstHeader = Me.Controls.Add("Forms.ListBox.1","NameOnlyForTesting")
With lstBody
'ensure properties of body-listbox
.ColumnHeads = False
.ZOrder (1)
.SpecialEffect = fmSpecialEffectFlat
.BorderStyle = fmBorderStyleSingle
End With
With lstHeader
'properties of header-listbox
.BackColor = RGB(200, 200, 200)
.Enabled = False
.ZOrder (0)
.SpecialEffect = fmSpecialEffectFlat
.BorderStyle = fmBorderStyleSingle
'make column equal
.ColumnCount = lstBody.ColumnCount
.ColumnWidths = lstBody.ColumnWidths
'add header elements
.AddItem
For i = 0 To UBound(arrHeaders)
.List(0, i) = arrHeaders(i)
Next i
'positioning of header-listbox
.Height = 10
.Width = lstBody.Width
.Left = lstBody.Left
.Top = (lstBody.Top - lstHeader.Height) - 0
Debug.Print lstBody.Width, lstHeader.Height ' <-- show both '400'
End With
End Sub
Usage:
Private Sub UserForm_Initialize()
'find emails
Dim selEmails As Outlook.Selection
Set selEmails = getSelectedEmails() 'function not displayed here at StackOverflow
'show emails in List-Box
Call printSelectedEmailsInList(selEmails)
End Sub
Private Sub printSelectedEmailsInList(selectedEmails As Outlook.Selection)
Dim objEmail As Outlook.MailItem
Dim intCounter As Integer
Dim arrHeaders() As Variant
With Me.lstSelectedEmails
'configure listbox
.Clear
.ColumnCount = 5
.ColumnWidths = "70;100;100;200;100"
'configute header (AFTER body!)
arrHeaders = Array("Date", "From", "To", "Subject", "Folder")
Call createListboxHeader(Me.lstSelectedEmails, arrHeaders)
MsgBox Me.Controls("NameOnlyForTesting").Width '<-- shows'78' instead of '400'
'fill list with emails
intCounter = 0
For Each objEmail In selectedEmails
.AddItem
.List(intCounter, 0) = objEmail.SentOn
.List(intCounter, 1) = objEmail.SenderName
.List(intCounter, 2) = objEmail.To
.List(intCounter, 3) = objEmail.Subject
.List(intCounter, 4) = objEmail.Parent.Name
intCounter = intCounter + 1
Next
End With
End Sub
I solved my problem, by changing:
Private Sub UserForm_Initialize()
[...]
End Sub
to:
Private Sub UserForm_Activate()
[...]
End Sub

Excel VBA Runtime Error 9 but not when stepping through the code

What would the reason be for a VBA user form with an EventHandler class to throw a Run-time error '9': Subscript out of range
BUT
If I F8 and step into the UserForm code I can step right through the entire code without it crashing
Just for simplicity here is my event handler class LabelEventHandler
Private WithEvents Innerlabel As MSForms.Label
Private InnerRow As Integer
Private InnerSheet As Worksheet
Public Property Set Label(ByVal InLabel As MSForms.Label)
Set Innerlabel = InLabel
End Property
Public Property Let Row(ByVal InRow As Integer)
InnerRow = InRow
End Property
Public Property Set Sheet(ByVal InSheet As Worksheet)
Set InnerSheet = InSheet
End Property
Private Sub InnerLabel_Click()
Dim Frame As MSForms.Frame
Dim ChildLabel As MSForms.Label
Set Frame = Innerlabel.Parent
For Each ChildLabel In Frame.Controls
Select Case ChildLabel.Name
Case "FullName"
InnerSheet.Cells(InnerRow, 4).Value = ChildLabel.Caption
Case "Email"
InnerSheet.Cells(InnerRow, 5).Value = ChildLabel.Caption
Case "Phone"
InnerSheet.Cells(InnerRow, 6).Value = ChildLabel.Caption
End Select
Next
End Sub
and here is the UserForm code
Private Sheet As Worksheet
Private LabelClickArray() As New LabelEventHandler
Public Sub AddUser(FullName As String, Email As String, Phone As String)
Dim FullNameLabel As MSForms.Label
Dim EmailLabel As MSForms.Label
Dim PhoneLabel As MSForms.Label
Dim UserFrame As Frame
Dim Top
Top = FindBottomUserRow()
Set UserFrame = Me.Controls.Add("Forms.Frame.1")
With UserFrame
.Top = Top
.Left = 5
.Width = 660
.Height = 20
.Font.Name = "Verdana"
.Font.Size = 12
.Font.Weight = 400
.Caption = ""
.BorderStyle = fmBorderStyleNone
End With
Set FullNameLabel = UserFrame.Controls.Add("Forms.Label.1")
Set EmailLabel = UserFrame.Controls.Add("Forms.Label.1")
Set PhoneLabel = UserFrame.Controls.Add("Forms.Label.1")
With FullNameLabel
.Top = 0
.Left = 0
.Width = 200
.Height = 15
.Name = "FullName"
.Caption = FullName
End With
With EmailLabel
.Top = 0
.Left = 205
.Width = 300
.Height = 15
.Name = "Email"
.Caption = Email
End With
With PhoneLabel
.Top = 0
.Left = 510
.Width = 150
.Height = 15
.Name = "Phone"
.Caption = Phone
End With
ReDim Preserve LabelClickArray(UBound(LabelClickArray) + 3)
Set LabelClickArray(UBound(LabelClickArray) - 2).Label = FullNameLabel
Set LabelClickArray(UBound(LabelClickArray) - 1).Label = EmailLabel
Set LabelClickArray(UBound(LabelClickArray)).Label = PhoneLabel
Set LabelClickArray(UBound(LabelClickArray) - 2).Sheet = Sheet
Set LabelClickArray(UBound(LabelClickArray) - 1).Sheet = Sheet
Set LabelClickArray(UBound(LabelClickArray)).Sheet = Sheet
LabelClickArray(UBound(LabelClickArray) - 2).Row = ActiveCell.Row
LabelClickArray(UBound(LabelClickArray) - 1).Row = ActiveCell.Row
LabelClickArray(UBound(LabelClickArray)).Row = ActiveCell.Row
End Sub
Function FindBottomUserRow()
Dim Frame As Control
Dim Top
Top = 30
For Each Frame In Me.Controls
If (TypeName(Frame) = "Frame" And Frame.Top > Top) Then Top = Frame.Top
Next
If (Top > 30) Then Top = Top + 20
FindBottomUserRow = Top
End Function
Private Sub UserForm_Initialize()
Set Sheet = ActiveSheet
Me.AddUser "Ryan", "ryan#r.com", "2625"
Me.AddUser "Jeff", "j#k.com", "123-4567"
End Sub
The error
Your error happens at the ReDim Preserve command, because you never initialized the array. You cannot execute a UBound-function to a non-initialized array (if you try, you get the Runtime error 9). If you cannot be sure at runtime if your array in already initialized, change your code to:
If IsArrayAllocated(LabelClickArray) Then
ReDim Preserve LabelClickArray(UBound(LabelClickArray) + 3)
Else
ReDim LabelClickArray(3)
End If
The function IsArrayAllocated looks like this:
Function IsArrayAllocated(arr As Variant) As Boolean
On Error Resume Next
IsArrayAllocated = IsArray(arr) _
And Not IsError(LBound(arr, 1)) _
And LBound(arr, 1) <= UBound(arr, 1)
End Function
(Code copied from cpearson)

VBA excel 2007, ComboBox "Permission Denied"

I'm a beginner with VBA, I'm developing a macro on excel 2007 and I'm having some problems with the ComboBox. Anywhere I try to add items i always get the error 70 "Permission Denied". What is my mistake?
Below you can find my simple code
Private Sub CommandButton2_Click()
Dim pic As IPictureDisp
Set pic = UserForm1.Image1.Picture
'stdole.SavePicture pic, "ciao"
Call SavePicture(pic, "ciao.jpg")
End Sub
Private Sub CommandButton3_Click()
Dim MyChart As Chart
Dim ChartData As Range
Dim ChartName As String
ChartName = "ANCONA"
Set ChartData = ActiveSheet.Range("A1:A9")
Application.ScreenUpdating = True
'UserForm1.Image4.Picture = LoadPicture("C:\Users\rfori\Desktop\PROGETTO
MARTINA\parto_trig.jpg")
'
Set MyChart = ActiveSheet.Shapes.AddChart(xlXYScatterLines).Chart
With MyChart.SeriesCollection.NewSeries
.Name = ChartName
.Values = ChartData
.XValues = ActiveSheet.Range("B1:B9")
End With
Dim imageName As String
imageName = "prova.jpg"
MyChart.Export Filename:=imageName, FilterName:="jpg"
Application.ScreenUpdating = True
UserForm1.Image1.Picture = LoadPicture("prova.jpg")
'MyChart.SeriesCollection(1).Name = ChartName
'MyChart.SetSourceData Source:=ChartData
End Sub
Private Sub UserForm_Activate()
ComboBox1.AddItem "ciao"
End Sub
Private Sub UserForm_Initialize()
ComboBox1.AddItem "ciao"
With Me
.StartUpPosition = 1
.Width = MultiPage1.Width
.Height = MultiPage1.Height
.Left = Application.Left - (Application.Width * 0.85) \ 2
.Top = Application.Top - (Application.Height * 0.85) \ 2
End With
myarray1 = Array("Ancona", "Milano", "Palermo")
For x = 0 To 2
'ComboBox1.AddItem myarray1(x)
Next x
End Sub
Sub window_sizer()
With ActiveWindow
.WindowState = xlNormal`enter code here`
.Height = 75
.Width = 125
.ScrollColumn = 1
.ScrollRow = 1
End Sub
Thank you in advance
had the same problem before as described in Combobox additem permission denied error no.70
.
Make sure that the property ListFillRange is empty.

Create event handlers for multiple dynamic controls

I have a userform that creates two dynamic control buttons but I am having difficulty accessing the .name property of the dynamic control, which means I can't create the event handler correctly. Due to this problem I am unable to create event handlers. Below shows the code that creates the dynamic controls and also the code that I have written for the event handlers (which isn't functioning correctly)
Option Explicit
Public WithEvents cButton As MSForms.CommandButton
Private Sub TextBox1_Change()
If TextBox1 <> vbNullString Then
For i = 1 To TextBox1.Value
Set cButton = Me.Controls.Add("Forms.CommandButton.1")
With cButton
.Name = "CommandButton" & i
.Left = 150
.Top = buttonStartPosition
.Width = 300
.Height = 140
End With
Next i
End If
End sub
Private Sub cButton_Click()
If cButton.Name = "CommandButton1" Then
MsgBox "Button1"
ElseIf cButton.Name = "CommandButton2" Then
MsgBox "Button2"
End If
End Sub
Once this code is executed and the two buttons are on the screen, I press the first button (button1) and nothing happens but when I press the second button (button2) I receive the message "Button2". So how come I can't access the first button?
#user3538102 .. To your comment regarding Textbox's. Below is example is an example. I added Combo box select either CommandButton or TextBox and generate events. The code works but could be better.
I added combo box to select to dynamically generate object type.
In UserForm Activate event - Add combo drop down list
Private Sub UserForm_Activate()
ComboBox1.AddItem "CommandButton"
ComboBox1.AddItem "TextBox"
ComboBox1.ListIndex = 0
End Sub
In Class1 Class Module ..
Modified UserForm code ..
Option Explicit
Dim cObjs() As New Class1
Private Sub TextBox1_Change()
Dim i As Integer
Dim buttonStartPosition As Integer
Dim cObj As Object
buttonStartPosition = 30
If TextBox1 <> vbNullString Then
For i = 1 To TextBox1.Value
If ComboBox1.Value = "CommandButton" Then
Set cObj = Me.Controls.Add("Forms.CommandButton.1")
Else
Set cObj = Me.Controls.Add("Forms.TextBox.1")
End If
With cObj
.Name = ComboBox1.Value & i
.Left = 15
.Top = buttonStartPosition
.Width = 30
.Height = 14
End With
ReDim Preserve cObjs(1 To i)
If ComboBox1.Value = "CommandButton" Then
Set cObjs(i).ButtonGroup = cObj
Else
Set cObjs(i).TextGroup = cObj
End If
buttonStartPosition = buttonStartPosition + 14
Next i
End If
End Sub
I got the events for multiple buttons to work with help from .. JWalk Excel Tips
Below is the modification based on your code and the link provided.
Create a Class module called "Class1"
Add modified code to UserForm1..
Option Explicit
Dim Buttons() As New Class1
Private Sub TextBox1_Change()
Dim i As Integer
Dim buttonStartPosition As Integer
Dim cButton As CommandButton
buttonStartPosition = 30
If TextBox1 <> vbNullString Then
For i = 1 To TextBox1.Value
Set cButton = Me.Controls.Add("Forms.CommandButton.1")
With cButton
.Name = "CommandButton" & i
.Left = 15
.Top = buttonStartPosition
.Width = 30
.Height = 14
End With
ReDim Preserve Buttons(1 To i)
Set Buttons(i).ButtonGroup = cButton
buttonStartPosition = buttonStartPosition + 14
Next i
End If
End Sub