备忘一些教训
- TextBox1 不在窗体里报错,把窗体代码拷贝到模块时,别忘了去掉窗体相关的对象
- 不应该在initial做歌词初始化,form_initialize() 应该尽量的快,不做不必要的事
1 控件的分类(也许这个分类不对,暂时理解到这)
- 表单控件
- 传统表单控件
- ActiveX控件(activeX并不能直接用到窗体,和窗体的事件也略有不同,比如getfoucs,窗体里是enter等)
- 窗体控件
- 窗体控件(但是感觉和 activeX控件很像),只能往窗体上添加的这类控件
2 窗体和控件的属性,应该在属性窗口设置,还是代码控制?
我发现窗体和控件的很多属性,既可以在VBE的属性窗口设置,也可以在VBA代码里设置,我总结了下差别如下
2.1 属性窗口设置的属性
- 属性窗口设置的属性
- 可以说是静态的,部分属性修改后,比如caption属性,直接就在VBE界面中可以看到
- 有些属性修改后,是需要运行后才能看到效果的
2.2 VBA代码设置的属性
- VBA里基本可以设置绝大多数的属性(应该比 VBE属性窗口可以设置的属性要多)
- 可以说相对静态的 VBE界面的属性设置窗口,VBA的设置都是运行后才生效的(也可以说是动态的)
- VBA代码设置的属性,在VBE界面上,还没运行时看不出来。
- 一旦窗体运行,VBA代码会覆盖 属性窗口的设置,我觉得优先级更高。
2.3 这两者如何使用
- 静态的属性设置,可能会在代码没运行起来的时候,比如VBE窗口,或代码卡住没跑起来的时候显示出来
- 所以需要注意,UI静态设置上的属性,可能会在少数情况被用户看到。
- 理论上,我觉得所有属性都只在 VBA代码里设置会比较好。
3 form 窗体
3.1 窗体和窗体控件的通用属性
通用属性
- xxx.enabled=true
- xxx.visible=true
- xxx.picture 相关几个
- xxx.mouseicon 相关几个
- xxx.backcolor xxx.backstyle 相关几个
- xxx.boldercolor xxx.bloderstyle 相关几个
- xxx.font xxx.forecolor 相关几个
- xxx.height xxx.width xxx.left xxx.top 相关几个
- xxx.controltipText
- xxx.textalign
有一定特殊性的属性的
- defalut
- rowsource
- rowsouretype
3.1.1 设置窗体的显示位置
- 可以在 窗体名.show的 过程中
- 可以在 窗体_initialize() 事件中
- 但是,必须先设置 Me.StartUpPosition = 0,否则设置窗体的位置无效
Private Sub UserForm_Initialize()
Me.StartUpPosition = 0
Me.Top = 0
Me.Left = 0
end sub
但是很奇怪,不设置的时候, me.top=0 ?
- 没有设置位置,默认窗体居中的时候
- debug.print me.top =0
- debug.print me.left=0
3.1.2 form的隐藏 form.hide 方法 (控件只能设置属性 object.visible=false)
- form.hide
- form如果hide还可以访问,比如me.hide 或访问其控件,但是unload 就不在内存中了。
- 控件没有hide方法
- 只能设置 visible属性 object.visible=false
3.2 这次的form表单效果(未完成)
- 包括label,滚动label
- 包括音乐播放器
- 包括listbox
- 包括控制listbox的commandbutton
- 还有几个控制EXCEL表的增加,查询,删除,也就是增删改查的commandbutton
3.3 form 设置
3.3.1 form作为窗体具有唯一性和特殊性,是其他控件parent
- 很多控件都得在form设置,而不能在控件本身中设置
- form_initialize() 事件是很重要的,主要就是各种初始化
- 设置 form的外观,和其他控件的初始外观
- 设置一些控件的数据源,如listbox的数据内容
- 控制一些控件的可用,可见等 enabled, visible
Private Sub UserForm_Initialize()
'窗体自身初始化显示
窗体3.Caption = "本窗体对应的工作表range是 " & ActiveWorkbook.Name & "的sheet: " & Sheet3.Name
'label的初始化
Label1.BackStyle = 0
Label1.Caption = "请输入您想查找的新海诚电影名"
Label1.ForeColor = RGB(255, 255, 255)
Label2.Caption = Worksheets("窗体3对应").Range("a1")
Label3.Caption = Worksheets("窗体3对应").Range("C1")
'listbox的初始化
'ListBox1.RowSource = "窗体3对应!A1:A10" '这样设置会导致additem removeitem报错
'ListBox2.RowSource = "窗体3对应!c1:c10"
For i = 2 To Worksheets("窗体3对应").Range("a65536").End(xlUp).Row '这样写会很卡Range("a:a").Rows.Count
ListBox1.AddItem Range("a" & i)
Next
For i = 2 To Worksheets("窗体3对应").Range("c65536").End(xlUp).Row
ListBox2.AddItem Range("c" & i)
Next
'Frame1.BackStyle = 0
'farme1 难道不能设置背景透明?
End Sub
3.3.2 form设置背景图
- 设置picture可以用 VBE 属性窗口功能
- 也可以使用VBA语法
- object.picture=loadpicture("绝对路径")
Private Sub WindowsMediaPlayer1_Click(ByVal nButton As Integer, ByVal nShiftState As Integer, ByVal fX As Long, ByVal fY As Long)
WindowsMediaPlayer1.URL = "C:\Users\Administrator\Desktop\rain.mp3"
WindowsMediaPlayer1.Controls.Play
窗体3.Picture = LoadPicture("C:\Users\Administrator\Desktop\timg2.jpg")
End Sub
1 label 标签控件
1.1 label的基础功能
- label的主要属性就是caption
- label.name 我觉得主要还是标识作用
Private Sub Label1_Click()
'label的很多通用属性
Label1.Visible = True
Label1.enanbled = True
'label1的文本属性
debug.print label1.caption
'label1没有如下这些属性
'Label1.Value = 1
'Label1.Text = 111
'Label1.Default = 222
End Sub
1.2 label的高级功能
- 如何实现,label可以按时替换文本?
- 如何实现, label可以实现滚动文本显示?
Private Sub Label4_Click()
For i = 1 To 26 '我希望是循环播放字幕,这样不行, 还想实现字幕左右移动。。。
Label4.Caption = Range("f" & Application.Match(i, Range("e1:e100"), 0)).Value
Debug.Print Label4.Caption
' Application.Wait Now + TimeValue("00:00:03") '整个程序会卡停
Sleep 3000
DoEvents
Next
延时代码的问题(还没解决)
- 如果是使用
- Application.wait now+timevalue(00:00:03)
- 等待时会整个卡住
- 如果是使用sleep
- sleep
- sleep代码,必须要加载一个特定库才可以使用
- 另外 sleep需要配合 doevents用
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
sleep 2000
1.3 label的滚动显示功能
- 还不会。。。
2 textbox 文本框控件
2.1 文本框的基本属性
- 文本框没有 caption
- 文本框中的内容是text属性,textbox1.text 属性
- text()属性也可以用value() 或者缺省
- textbox1.text 这个属性,在VBE属性窗口或 窗体_initialize的文本
- 的可以 当成 初始文本(提示玩家输入等效果)
- 这三者的区别,一般情况下,输入的内容都是 string类型
- textbox1.text (会智能识别,如果是数字等会为double等类型,其他一般为string)
- textbox1.value (会智能识别,如果是数字等会为double等类型,其他一般为string)
- textbox (所有内容即使1 也会当文本,全部都按string返回)
Private Sub CommandButton3_Click()
'增加记录按钮,输入
Range("B15") = TextBox1.Text
Range("B16") = TextBox1.Value
Range("B17") = TextBox1
Debug.Print TypeName(Range("B15"))
Debug.Print TypeName(Range("B16"))
Debug.Print TypeName(Range("B17"))
Debug.Print TypeName(Range("B15").Value)
Debug.Print TypeName(Range("B16").Value)
Debug.Print TypeName(Range("B17").Value)
End Sub
2.2 文本框的设置-----对文本的各种控制
- textbox1.multiline=true '可以换行
- textbox1.maxlength=20 '最大字数
Private Sub UserForm_Initialize()
'窗体自身初始化显示
窗体3.Caption = "本窗体对应的工作表range是 " & ActiveWorkbook.Name & "的sheet: " & Sheet3.Name
'label的初始化
Label1.BackStyle = 0
Label1.Caption = "请输入您想查找的新海诚电影名"
Label1.ForeColor = RGB(255, 255, 255)
Label2.Caption = Worksheets("窗体3对应").Range("a1")
Label3.Caption = Worksheets("窗体3对应").Range("C1")
'listbox的初始化
'ListBox1.RowSource = "窗体3对应!A1:A10" '这样设置会导致additem removeitem报错
'ListBox2.RowSource = "窗体3对应!c1:c10"
For i = 2 To Worksheets("窗体3对应").Range("a65536").End(xlUp).Row '这样写会很卡Range("a:a").Rows.Count
ListBox1.AddItem Range("a" & i)
Next
For i = 2 To Worksheets("窗体3对应").Range("c65536").End(xlUp).Row
ListBox2.AddItem Range("c" & i)
Next
'Frame1.BackStyle = 0
'farme1 难道不能设置背景透明?
TextBox1.MultiLine = True '可以换行
TextBox1.MaxLength = 20 '最大字数
End Sub
2.3 密码设置
- textbox1.passwordchar="#"
- 或者设置为其他符号 "*"
- 一个特殊性
- 有冲突的地方
- 如果设置了 passwordchar 属性,自动换行属性就失效了。。可能是系统默认passwordchar 只能一行?
TextBox1.MultiLine = True '可以换行
TextBox1.MaxLength = 20 '最大字数
'TextBox1.PasswordChar = "#"
2.3 文本框 和 commandbutton 和 表格互动
- textbox 和commandbutton 按钮
- 实现了,查找,增加,删除,三种功能按钮,也就是增删改查等功能
- 可以在窗体上对,EXCEL的range操作
Private Sub CommandButton3_Click()
'增加记录按钮,输入
Dim a As Object
b = TextBox1.Value
Set a = Range("a1:" & "a" & Range("a65536").End(xlUp).Row).Find(b)
If a Is Nothing Then
Range("a" & 1 + Range("a65536").End(xlUp).Row).Value = b
Else
MsgBox "您输入的内容重复了"
'goto '这里加goto语句意义不大,用户用inputbox输入,又不是inputbox
End If
TextBox1.Value = ""
End Sub
Private Sub CommandButton4_Click()
'查找按钮
Dim a As Range
Dim b
b = TextBox1.Value
Set a = Range("a1:a" & Range("a65536").End(xlUp).Row).Find(b)
If a Is Nothing Then
MsgBox "你要查找的内容并不存在"
Else
MsgBox "你要查找的内容,已经存在"
End If
End Sub
Private Sub CommandButton5_Click()
'删除按钮
Dim a As Range
Dim b
b = TextBox1.Value
Set a = Range("a1:a" & Range("a65536").End(xlUp).Row).Find(b)
If a Is Nothing Then
MsgBox "你要删除的内容并不存在"
Else
c = MsgBox("您确定要删除吗?", vbOKCancel) '最好二次确认后确定,查返回值
If c = vbOK Then
a = ""
MsgBox "你要删除的内容,已经删除"
End If
End If
TextBox1.Value = ""
End Sub
3 commandbutton
3.1 按钮图标
- picture
- pictureposition '有各种图标和文字的排列方式
4 listbox
- listbox可以设置,多选
4.1 listbox的属性
- controlsource 当前显示的内容
- rowsource 这样会导致不能加减元素,如 additem 和 removeitem
- columnSource 设置多列的方法,如何指定多列内容 ?
4.2 listbox和commandbutton 联动
- 实现两个listbox 互相可以增减内容
4.2.1 数据源
4.2.2 实现代码
Private Sub UserForm_Initialize()
'窗体自身初始化显示
窗体3.Caption = "本窗体对应的工作表range是 " & ActiveWorkbook.Name & "的sheet: " & Sheet3.Name
'label的初始化
Label1.BackStyle = 0
Label1.Caption = "请输入您想查找的新海诚电影名"
Label1.ForeColor = RGB(255, 255, 255)
Label2.Caption = Worksheets("窗体3对应").Range("a1")
Label3.Caption = Worksheets("窗体3对应").Range("C1")
'listbox的初始化
'ListBox1.RowSource = "窗体3对应!A1:A10" '这样设置会导致additem removeitem报错
'ListBox2.RowSource = "窗体3对应!c1:c10"
For i = 2 To Worksheets("窗体3对应").Range("a65536").End(xlUp).Row '这样写会很卡Range("a:a").Rows.Count
ListBox1.AddItem Range("a" & i)
Next
For i = 2 To Worksheets("窗体3对应").Range("c65536").End(xlUp).Row
ListBox2.AddItem Range("c" & i)
Next
End Sub
4.2.3删除和增加用的代码不对等 (listbox不能指定 rowresource等,两者冲突)
- 增加内容
- ListBox2.AddItem ListBox1.Text
- 删除内容
- ListBox1.RemoveItem ListBox1.ListIndex
- listbox不能指定 rowresource等,两者冲突
- 因为 listbox指定rowResource等,相当于固定了数据来源(适合数据源不变的listbox)
- 如果listbox的数据会变化,最好按 additem的方式添加和删除
Private Sub CommandButton1_Click()
'向右箭头
ListBox2.AddItem ListBox1.Text
ListBox1.RemoveItem ListBox1.ListIndex
End Sub
Private Sub CommandButton2_Click()
'向左箭头
ListBox1.AddItem ListBox2.Text
ListBox2.RemoveItem ListBox2.ListIndex
End Sub
4.3 listbox 指定 rowSource的方式,居然是 ="sheet1!A1:A9"
- 特别注意点1
- rowSource指定后,不可以在additem removeitem
- 所以我在这个例子里,用的是 循环 additem的方式
- 特别注意点2
- rowsource的指定是表格写法 rowsource="sheet1!A1:A9"
- 而不是VBA的写法 rowsource= worksheets().range()
4.4 listbox 如何指定多列内容 ?
- 没有columnSource 属性
- 只有columncount属性
- 可以在rowsource指定一个区域
- 设置列宽度,sheListBox1.ColumnWidths = "50;100;50" '实测用两种分隔都可以 "50,100,50"
Private Sub UserForm_Initialize()
ListBox1.RowSource = "sheet3!a2:c10"
ListBox1.ColumnCount = 3
ListBox1.ColumnWidths = "50;80;50" '实测用两种分隔都可以 "50,100,50"
ListBox1.ColumnHeads = True ’设置了heads好像会自动往上找1行
End Sub
5 combobox
5.1 基本功能 combobox1
- combobox1 功能,确实是 textbox 和 listbox 的结合
- 可以在combobox1里输入,如果设置了 matchRequired 属性,会要求输入的内容,必须是combobox1里 rowsource的内容
- 而且,如果输入的是 rowsource的内容,还会在下拉框里自动选择对应的内容。
- 属性 matchRequired=true '必须否则 属性值无效
-
方法 combobox1.dropdown '设置在鼠标移动过去的时候,自动打开下拉框
Private Sub ComboBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
ComboBox1.DropDown
End Sub
Private Sub UserForm_Initialize()
'combobox1的初始化
ComboBox1.RowSource = "窗体3对应!c1:c110"
ComboBox1.ControlSource = "窗体3对应!d1"
ComboBox1.MatchRequired = True '必须是rowsource内容啊
ComboBox1.MatchEntry = 1 '好像无论设置0,1 都不限制输入内容??
End Sub
6 optionbutton
6.1 optionbutton 基础功能
- 好像如果没有其他框架
- 一个窗体内的多个option 自动被认为是一组,不需要写 option 按钮本身的逻辑,如果有frame内的认为是一组。
- 不需要在optionbutton1_change() 里 写 optionbutton2.value=false optionbutton3.value=false ?
6.2 optionbutton_change() 使用
- optionbutton.value =true /false 这个只判断bool
- optionbutton.caption = 标题 这个可以显示optionbutton 的标题
optionbutton_change() 这样使用的局限性
- 每次optionbutton 的值变动,都会 触发2次事件
- 一次是选中时其值改变,一次是离开时(选择了其他option)又触发
Private Sub OptionButton1_Change()
Debug.Print OptionButton1.Caption
End Sub
Private Sub OptionButton2_Change()
Debug.Print OptionButton2.Caption
End Sub
Private Sub OptionButton3_Change()
Debug.Print OptionButton3.Caption
End Sub
6.3 optionbutton 和 commandbutton的联动
- 这种方式,每次只会输出一次值
- 但是操作上,比较反人类,很麻烦,不符合 optionbutton 简洁的方式
6.4 optionbutton_click()
- 这样尝试的话,用 optionbutton_click() 还挺好的
Private Sub OptionButton1_Click()
Debug.Print OptionButton1.Caption
End Sub
Private Sub OptionButton2_Click()
Debug.Print OptionButton2.Caption
End Sub
Private Sub OptionButton3_Click()
Debug.Print OptionButton3.Caption
End Sub
6.5 optionbutton 和分组frame
- 现在对optionbutton的总结是
- 如果没有分组,那默认整个form里的 optionbutton 都算一组
- 如有有分组fram,那默认一个frame下的 optionbutton 为一组
7 checkbox
7.1 checkbox基本功能
- 本身每个 checkbox 都是单独的控制自身 状态,value
- chekbox1.value
- checkbox1.caption
7.2 checkbox 和frame 联动的意义,是不是不大?
- 本身每个 checkbox 都是单独的控制自身 状态,value 和 caption
- 分组除了用户看起来更清晰,代码上没有特别的用处了吧?
7.3 checkbox 和 commandbutton的联动 (感觉对用户太麻烦)
8 picture 控件
8.1 语法
- image.picture=loadpicture("c... .jpg")
- 其实 form.picture=loadpicture() 也是类似的语法
8.2 picture 和listbox的联动
Private Sub UserForm_Initialize()
ListBox3.AddItem "timg1"
ListBox3.AddItem "timg2"
End Sub
Private Sub ListBox3_Change()
Image1.Picture = LoadPicture(ThisWorkbook.Path & "\" & ListBox3.Value & ".jpg")
End Sub
9 音乐控件
9.1 窗体的默认控件里没有 音乐控件,需要添加 mediaplayer
- 工具栏上邮件:添加
- 找到 microsoft mediaplayer
9.2 音乐控件的播放
- 播放音乐的属性
- 播放器.url
- 播放器.controls.play
- WindowsMediaPlayer1.URL = "C:\Users\Administrator\Desktop\rain.mp3"
- WindowsMediaPlayer1.Controls.Play
Private Sub WindowsMediaPlayer1_Click(ByVal nButton As Integer, ByVal nShiftState As Integer, ByVal fX As Long, ByVal fY As Long)
WindowsMediaPlayer1.URL = "C:\Users\Administrator\Desktop\rain.mp3"
WindowsMediaPlayer1.Controls.Play
End Sub
10 spinbutton
10.1 spinbutton 和 文本框 或单元格联动的两种方式
- 做了2种 spinbutton 和2个textbox 的联动
- form_initialize() 上做了初始化
- 第一种是直接等于spinbutton.value
- 左边的texbox2, 设置的是 textbox2.value=spinbutton.value
- 第二种是,用spinUp 和spinDown 去控制 textbox.value
- 右边的textbox3 设置的是 spinUp() +1 spinDown() -1 但这样 textbox3的范围就不会固定在 spinbutton的min-max之间。
Private Sub SpinButton1_Change()
TextBox2.Value = SpinButton1.Value
End Sub
Private Sub SpinButton1_SpinDown()
TextBox3.Value = TextBox3.Value - 1
End Sub
Private Sub SpinButton1_SpinUp()
TextBox3.Value = TextBox3.Value + 1
End Sub
Private Sub UserForm_Initialize()
'spinbutton相关的初始化
SpinButton1.Max = 10
SpinButton1.Min = 1
TextBox2.Value = 1
TextBox3.Value = 1
'下面这部分代码,和本部分内容无关----------------------------------------
'窗体自身初始化显示
窗体3.Caption = "本窗体对应的工作表range是 " & ActiveWorkbook.Name & "的sheet: " & Sheet3.Name
'label的初始化
Label1.BackStyle = 0
Label1.Caption = "请输入您想查找的新海诚电影名"
Label1.ForeColor = RGB(0, 0, 0)
Label2.Caption = Worksheets("窗体3对应").Range("a1")
Label3.Caption = Worksheets("窗体3对应").Range("C1")
'listbox的初始化
'ListBox1.RowSource = "窗体3对应!A1:A10" '这样设置会导致additem removeitem报错
'ListBox2.RowSource = "窗体3对应!c1:c10"
For i = 2 To Worksheets("窗体3对应").Range("a65536").End(xlUp).Row '这样写会很卡Range("a:a").Rows.Count
ListBox1.AddItem Range("a" & i)
Next
For i = 2 To Worksheets("窗体3对应").Range("c65536").End(xlUp).Row
ListBox2.AddItem Range("c" & i)
Next
'Frame1.BackStyle = 0
'farme1 难道不能设置背景透明?
TextBox1.MultiLine = True '可以换行
TextBox1.MaxLength = 20 '最大字数
'TextBox1.PasswordChar = "#"
End Sub