VBA 动态添加组合框不触发变化事件
VBA Dynamically added combo box does not trigger change event
我有一个代码可以在 运行 时在用户表单中添加一个组合框。组合框包含文件夹中的图像名称列表。当用户 select 图片命名时,它会将图片设置为用户表单的背景图片。
但是动态组合框只更改背景图像一次,即下面代码中的 UserForm_Initialize
事件,而我在设计中添加的组合框完美运行,即只要组合框值更改,就会更改用户表单的背景。
UserForm1
Private Sub UserForm_Initialize()
'AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage Me
With CreateObject("Scripting.FileSystemObject")
For Each fl In .GetFolder(ThisWorkbook.Path & "\Images\BackgroundImages\").Files
cmbBackgroundImg.AddItem fl.Name
Next fl
End With
cmbBackgroundImgName = RegKeyRead("HKCU\Software\ExcelAssistant\BackGroundImageName")
If cmbBackgroundImgName <> "" Then
If CreateObject("Scripting.FileSystemObject").FileExists(ThisWorkbook.Path & "\Images\BackgroundImages\" & cmbBackgroundImgName) = True Then
cmbBackgroundImg.Text = cmbBackgroundImgName
RegKeySave "HKCU\Software\BPOUtility\BackGroundImageName", cmbBackgroundImg.Text
End If
End If
End Sub
Private Sub cmbBackgroundImg_Change()
On Error Resume Next
If cmbBackgroundImg.Text = "" Then
Me.Picture = Nothing
Else
Me.Picture = LoadPicture(ThisWorkbook.Path & "\Images\BackgroundImages\" & cmbBackgroundImg.Text)
Me.PictureSizeMode = fmPictureSizeModeStretch
RegKeySave "HKCU\Software\ExcelAssistant\BackGroundImageName", cmbBackgroundImg.Text
End If
End Sub
模块 1
Public Function AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage(frm As MSForms.UserForm)
Dim CmbBox As MSForms.Control, EventHandlerCollection As New Collection, _
cmbeventhandler As CtrlEvents
Set CmbBox = frm.Controls.Add("Forms.ComboBox.1", "cmbBackgroundImage")
Set cmbeventhandler = New CtrlEvents
cmbeventhandler.AssignComboBox CmbBox
EventHandlerCollection.Add cmbeventhandler
With CreateObject("Scripting.FileSystemObject")
For Each fl In .GetFolder(ThisWorkbook.Path & "\Images\BackgroundImages\").Files
CmbBox.AddItem fl.Name
Next fl
cmbBackgroundImgName = "asoggetti-cfKC0UOZHJo-unsplash.bmp"
If cmbBackgroundImgName <> "" Then
If .FileExists(ThisWorkbook.Path & "\Images\BackgroundImages\" & cmbBackgroundImgName) = True Then
CmbBox.Text = cmbBackgroundImgName
End If
End If
End With
End Function
Public Function GetUserFormOfControl(Obj As Object) As UserForm
Dim ParentType As String, TempObj As Object
Set TempObj = Obj
Do Until ParentType = "UserForm"
If Not TypeOf TempObj Is MSForms.Control Then
ParentType = "UserForm"
Set GetUserFormOfControl = TempObj
Else
Set TempObj = TempObj.Parent
CtrlName = TempObj.Name
End If
Loop
End Function
Public Function RegKeyRead(i_RegKey As String) As String
On Error Resume Next
RegKeyRead = CreateObject("WScript.Shell").regread(i_RegKey)
End Function
Public Function RegKeySave(i_RegKey As String, i_Value As String, Optional i_Type As String = "REG_SZ")
CreateObject("WScript.Shell").RegWrite i_RegKey, i_Value, i_Type
End Function
CtrlEvents Class
Public WithEvents m_combobox As MSForms.ComboBox
Private Sub m_combobox_Change()
If m_combobox.Name = "cmbBackgroundImage" Then
If m_combobox.Text = "" Then
GetUserFormOfControl(m_combobox).Picture = Nothing
Else
With GetUserFormOfControl(m_combobox)
.Picture = LoadPicture(ThisWorkbook.Path & "\Images\BackgroundImages\" & m_combobox.Text)
.PictureSizeMode = fmPictureSizeModeStretch
End With
End If
End If
End Sub
Public Sub AssignComboBox(c As MSForms.ComboBox)
Set m_combobox = c
End Sub
因此,通过行 AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage Me
添加到用户表单的组合框未能按预期工作。应该怎么解决?
EventHandlerCollection
超出范围并在 AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage
退出后立即销毁,因此它无法处理任何事件。
您需要将该集合设置为全局变量,以便它在填充它的子程序退出后保留在范围内。
Dim EventHandlerCollection As Collection 'global so stays in scope
Public Function AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage( _
frm As MSForms.UserForm)
Dim CmbBox As MSForms.Control, cmbeventhandler As CtrlEvents
Set EventHandlerCollection = New Collection
Set CmbBox = frm.Controls.Add("Forms.ComboBox.1", "cmbBackgroundImage")
Set cmbeventhandler = New CtrlEvents
cmbeventhandler.AssignComboBox CmbBox
EventHandlerCollection.Add cmbeventhandler
我有一个代码可以在 运行 时在用户表单中添加一个组合框。组合框包含文件夹中的图像名称列表。当用户 select 图片命名时,它会将图片设置为用户表单的背景图片。
但是动态组合框只更改背景图像一次,即下面代码中的 UserForm_Initialize
事件,而我在设计中添加的组合框完美运行,即只要组合框值更改,就会更改用户表单的背景。
UserForm1
Private Sub UserForm_Initialize()
'AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage Me
With CreateObject("Scripting.FileSystemObject")
For Each fl In .GetFolder(ThisWorkbook.Path & "\Images\BackgroundImages\").Files
cmbBackgroundImg.AddItem fl.Name
Next fl
End With
cmbBackgroundImgName = RegKeyRead("HKCU\Software\ExcelAssistant\BackGroundImageName")
If cmbBackgroundImgName <> "" Then
If CreateObject("Scripting.FileSystemObject").FileExists(ThisWorkbook.Path & "\Images\BackgroundImages\" & cmbBackgroundImgName) = True Then
cmbBackgroundImg.Text = cmbBackgroundImgName
RegKeySave "HKCU\Software\BPOUtility\BackGroundImageName", cmbBackgroundImg.Text
End If
End If
End Sub
Private Sub cmbBackgroundImg_Change()
On Error Resume Next
If cmbBackgroundImg.Text = "" Then
Me.Picture = Nothing
Else
Me.Picture = LoadPicture(ThisWorkbook.Path & "\Images\BackgroundImages\" & cmbBackgroundImg.Text)
Me.PictureSizeMode = fmPictureSizeModeStretch
RegKeySave "HKCU\Software\ExcelAssistant\BackGroundImageName", cmbBackgroundImg.Text
End If
End Sub
模块 1
Public Function AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage(frm As MSForms.UserForm)
Dim CmbBox As MSForms.Control, EventHandlerCollection As New Collection, _
cmbeventhandler As CtrlEvents
Set CmbBox = frm.Controls.Add("Forms.ComboBox.1", "cmbBackgroundImage")
Set cmbeventhandler = New CtrlEvents
cmbeventhandler.AssignComboBox CmbBox
EventHandlerCollection.Add cmbeventhandler
With CreateObject("Scripting.FileSystemObject")
For Each fl In .GetFolder(ThisWorkbook.Path & "\Images\BackgroundImages\").Files
CmbBox.AddItem fl.Name
Next fl
cmbBackgroundImgName = "asoggetti-cfKC0UOZHJo-unsplash.bmp"
If cmbBackgroundImgName <> "" Then
If .FileExists(ThisWorkbook.Path & "\Images\BackgroundImages\" & cmbBackgroundImgName) = True Then
CmbBox.Text = cmbBackgroundImgName
End If
End If
End With
End Function
Public Function GetUserFormOfControl(Obj As Object) As UserForm
Dim ParentType As String, TempObj As Object
Set TempObj = Obj
Do Until ParentType = "UserForm"
If Not TypeOf TempObj Is MSForms.Control Then
ParentType = "UserForm"
Set GetUserFormOfControl = TempObj
Else
Set TempObj = TempObj.Parent
CtrlName = TempObj.Name
End If
Loop
End Function
Public Function RegKeyRead(i_RegKey As String) As String
On Error Resume Next
RegKeyRead = CreateObject("WScript.Shell").regread(i_RegKey)
End Function
Public Function RegKeySave(i_RegKey As String, i_Value As String, Optional i_Type As String = "REG_SZ")
CreateObject("WScript.Shell").RegWrite i_RegKey, i_Value, i_Type
End Function
CtrlEvents Class
Public WithEvents m_combobox As MSForms.ComboBox
Private Sub m_combobox_Change()
If m_combobox.Name = "cmbBackgroundImage" Then
If m_combobox.Text = "" Then
GetUserFormOfControl(m_combobox).Picture = Nothing
Else
With GetUserFormOfControl(m_combobox)
.Picture = LoadPicture(ThisWorkbook.Path & "\Images\BackgroundImages\" & m_combobox.Text)
.PictureSizeMode = fmPictureSizeModeStretch
End With
End If
End If
End Sub
Public Sub AssignComboBox(c As MSForms.ComboBox)
Set m_combobox = c
End Sub
因此,通过行 AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage Me
添加到用户表单的组合框未能按预期工作。应该怎么解决?
EventHandlerCollection
超出范围并在 AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage
退出后立即销毁,因此它无法处理任何事件。
您需要将该集合设置为全局变量,以便它在填充它的子程序退出后保留在范围内。
Dim EventHandlerCollection As Collection 'global so stays in scope
Public Function AddBackgroundChangeComboBoxAndSetPreferredBackgroundImage( _
frm As MSForms.UserForm)
Dim CmbBox As MSForms.Control, cmbeventhandler As CtrlEvents
Set EventHandlerCollection = New Collection
Set CmbBox = frm.Controls.Add("Forms.ComboBox.1", "cmbBackgroundImage")
Set cmbeventhandler = New CtrlEvents
cmbeventhandler.AssignComboBox CmbBox
EventHandlerCollection.Add cmbeventhandler