到目前为止,我们已经完成了最艰难的工作。接下来,我们来编写用户窗体代码,将已完成的对象放进HRWizard用户窗体里并使这些对象工作。
编写HRWizard用户窗体代码
打开HRWizard用户窗体代码窗口,添加下列模块级的变量声明:
Dim m_oEmployee As cPerson
Dim m_oLM As cListManager
Dim m_oWizard As cStepManager
Dim m_colSteps As Collection
虽然我们创建了9个分开的类模块来运行我们的应用程序,但是许多类都是通过在声明部分列出来内部使用。使用cPeason类收集新员工的数据,使用cListManager类来填充HRWizard用户窗体中不同的组合框,使用cStepManager类决定何时且按什么顺序显示哪个界面,并控制导航命令按钮的可用性。最后,使用标准的VBA Collection对象,用于存储cStepManager对象的PageSettings集合。
初始化应用程序
在HRWizard用户窗体的Initialize事件中,将初始化自定义的对象并添加代码来设置向导、列表和显示用户窗体。
在UserForm_Initialize事件中添加下列代码:
Private Sub UserForm_Initialize()
Set m_oEmployee = New cPerson
Set m_oLM = New cListManager
Set m_oWizard = New cStepManager
InitWizard
InitLists
InitForm
End Sub
下面,创建三个Init函数,分别设置向导、列表管理器和用户窗体对象。
初始化向导
在用户窗体代码窗口添加新的过程,将其命名为InitWizard,并添加下列代码:
Private Sub InitWizard()
With m_oWizard
Set .Worksheet =Sheets("UFormConfig")
.NumberOfSettings = 3
Set m_colSteps =.PageSettings
Set .PreviousButton =Me.cmdPrevious
Set .NextButton =Me.cmdNext
.CurrentPage =MultiPage1.Value + 1
End With
End Sub
上述代码完成下列工作:
1.告诉cStepManager对象在哪里找到配置数据
Set .Worksheet = Sheets("UFormConfig")
2.告诉cStepManager对象获取数据的列数
.NumberOfSettings = 3
3.放置页设置到集合里
Set m_colSteps = .PageSettings
4.设置导航按钮
Set .PreviousButton = Me.cmdPrevious
Set .NextButton = Me.cmdNext
5.设置当前页
.CurrentPage = MultiPage1.Value + 1
因为多页控件的Page集合基于0,所以使用多页控件的Value属性加1来设置CurrentPage属性。
在初始化用户窗体之前,必须设置cStepManager对象,因为该用户窗体使用PageSettings集合来设置它自已。
初始化组合框
下一步是将组合框绑定到它们各自的列表。该列表被存储在ListMgr工作表中。
在用户窗体代码窗口添加新的过程InitLists,输入下列代码:
Private Sub InitLists()
With m_oLM
.BindListToRange "Departments", Me.cboDept
.BindListToRange "Locations", Me.cboLocation
.BindListToRange "NetworkLvl", Me.cboNetworkLvl
.BindListToRange "ParkingSpot", Me.cboParkingSpot
.BindListToRange "YN", Me.cboRemoteAccess
End With
End Sub
同样,上述代码也非常简单,它们为应用程序中的每个列表调用cListManager对象的BindListToRange方法,给组合框添加数据项。
初始化用户窗体
在设置应用程序中的最后一步是初始化用户窗体自身。添加一个名为InitForm的新过程,并输入下列代码:
Private Sub InitForm()
Dim iFirstPage As Integer
Dim i As Integer
Dim iPageCount As Integer
iFirstPage =m_colSteps("1").Order - 1
Me.MultiPage1.Value =iFirstPage
Me.MultiPage1.Pages((m_colSteps("1").Page) - 1).Caption =m_colSteps("1").Caption
m_oWizard.HandleControls
iPageCount =MultiPage1.Pages.Count
For i = 1 To iPageCount -1
MultiPage1.Pages(i).Visible = False
Next
End Sub
这里,设置多页控件的Value属性为PageSetting集合(m_colSteps)的项目(其键值为1),并设置其标题:
iFirstPage = m_colSteps("1").Order - 1
Me.MultiPage1.Value = iFirstPage
Me.MultiPage1.Pages((m_colSteps("1").Page) - 1).Caption =m_colSteps("1").Caption
注意,我们传递Order属性的值作为键值,这使得它非常容易去判断要移动至哪页。当设置多页控件的Value属性时,正使用相对应的值激活该页。在这里,该值为1。
然后调用m_oWizard对象的HandleControls方法初始化导航按钮为正确的设置:
m_oWizard.HandleControls
接下来,隐藏除第一页外的所有页:
iPageCount = MultiPage1.Pages.Count
For i = 1 To iPageCount - 1
MultiPage1.Pages(i).Visible = False
Next
注意,多页控件的Page集合是基于0的,因此通过以1开始循环计数器,保持该页面可见。此时,可以运行该用户窗体。
1.在VBE中,双击工程资源管理器窗口的用户窗体。
2.单击标准工具栏中的“运行子过程/用户窗体”按钮或者按F5键,如下图24所示。
图24
注意,下图25在选项卡中出现的标题,并且前一步按钮被禁用。
图25
再看看Department组合框,已经绑定了Departments命名区域到该组合框,如下图26所示。
图26
3、通过单击右上方的X按钮,停止用户窗体的运行。
给用户窗体添加导航
导航按钮要在向导应用程序中完成移动步骤的任务,但它们也需要具备放置每个界面中的数据到其在用户窗体的cPerson对象里的位置的能力。
在cmdNext_Click中添加下列代码:
Private Sub cmdNext_Click()
Dim iNext As Integer
StoreData
iNext =m_oWizard.NextPage
Me.MultiPage1.Value =m_colSteps(CStr(iNext)).Order - 1
Me.MultiPage1.Pages((m_colSteps(CStr(iNext)).Page)- 1).Caption = m_colSteps(CStr(iNext)).Caption
ShowNextPage"up"
End Sub
在向导中移到下一步之前首先需要做的是保留在当前用户窗体中输入的值。StoreData方法决定用户处于哪一步并基于该位置调用正确的存储方法,代码如下所示:
Private Sub StoreData()
Select Casem_oWizard.CurrentPage
Case 1
StorePerson
Case 2
StoreAddress
Case 3
StoreEquipment
Case 4
StoreAccess
End Select
End Sub
上述代码中的存储方法的代码如下:
Private Sub StorePerson()
With m_oEmployee
.FName = Me.txtFname.Value
.MidInit =Me.txtMidInit.Value
.LName =Me.txtLname.Value
IfLen(Me.txtDOB.Value & "") > 0 Then
.DOB =Me.txtDOB.Value
End If
.SSN =Me.txtSSN.Value
.Department = Me.cboDept.Text
.JobTitle =Me.txtJobTitle.Value
.Email =Me.txtEmail.Value
End With
End Sub
Private Sub StoreAddress()
With m_oEmployee.Address
.StreetAddress =Me.txtStreetAddr.Value
.StreetAddress2 =Me.txtStreetAddr2.Value
.City =Me.txtCity.Value
.State =Me.txtState.Value
.ZipCode =Me.txtZip.Value
.PhoneNumber =Me.txtPhone.Value
.CellPhone =Me.txtCell.Value
End With
End Sub
Private Sub StoreEquipment()
Dim opt As MSForms.OptionButton
Withm_oEmployee.Equipment
For Each opt In Me.fraPCType.Controls
If opt.Value =True Then
.PCType =opt.Caption
Exit For
End If
Next
For Each opt In Me.fraPhoneType.Controls
If opt.Value =True Then
.PhoneType =opt.Caption
Exit For
End If
Next
.Location =Me.cboLocation.Text
If Me.chkFaxYN = TrueThen
.FaxYN ="Y"
Else
.FaxYN ="N"
End If
End With
End Sub
Private Sub StoreAccess()
Dim opt As MSForms.OptionButton
With m_oEmployee.Access
If Len(Me.cboNetworkLvl.Text & "") > 0 Then
.NetworkLevel =CInt(Me.cboNetworkLvl.Text)
End If
.ParkingSpot =Me.cboParkingSpot.Text
.RemoteYN = Me.cboRemoteAccess.Text
For Each opt In Me.fraBuilding.Controls
If opt.Value =True Then
.Building =opt.Caption
Exit For
End If
Next
End With
End Sub
这段代码简单地从界面中接收数据,并将其放置在cPerson里的相应的对象中。
接下来,确定下一页。(记住,多页集合是基于0的,因此从Order属性中减1以获得下一页的值)
iNext = m_oWizard.NextPage
Me.MultiPage1.Value = m_colSteps(CStr(iNext)).Order - 1
Me.MultiPage1.Pages((m_colSteps(CStr(iNext)).Page) - 1).Caption =m_colSteps(CStr(iNext)).Caption
然后,调用ShowNextPage方法,告诉它我们想移动的方式:
ShowNextPage "up"
ShowNextPage方法的代码如下:
Private Sub ShowNextPage(Direction As String)
Dim iCurrPage As Integer
Dim iUpDown As Integer
iCurrPage =MultiPage1.Value
If LCase(Direction) ="up" Then
iUpDown = 1
Else
iUpDown = -1
End If
MultiPage1.Pages(iCurrPage + iUpDown).Visible = True
MultiPage1.Pages(iCurrPage).Visible = False
End Sub
这个方法查找CurrentPage属性的值,基于传递给该方法的Direction参数加或减1。
cmdPrevious按钮的Click事件看起来非常相似:
Private Sub cmdPrevious_Click()
Dim iPrevious As Integer
StoreData
iPrevious =m_oWizard.PreviousPage
Me.MultiPage1.Value =m_colSteps(CStr(iPrevious)).Order - 1
Me.MultiPage1.Pages((m_colSteps(CStr(iPrevious)).Page) - 1).Caption =m_colSteps(CStr(iPrevious)).Caption
ShowNextPage"down"
End Sub
唯一的差别是传递关键字down到ShowNextPage方法以便向用户移动到合适的方向。
下面,添加最后一个事件处理来帮助我们使用导航。无论何时改变多页控件中的页面,控件的Change事件被触发。我们使用事件去捕捉当前页面的值,并将其存储在m_oWizard对象的CurrentPage属性中。
添加下面的代码到MultiPage1控件的Change事件:
Private Sub MultiPage1_Change()
m_oWizard.CurrentPage =MultiPage1.Value + 1
End Sub
现在,让我们来试试导航的工作。
1.在设计视图下打开用户窗体,单击标准工具栏中的“运行子程序/用户窗体”按钮或按F5键。
2.启动用户窗体后,单击下一步按钮移动到向导中的第二步(已在配置工作表中定义),应该是Address界面。注意到两个导航按钮现在都能用了,如下图27所示。
图27
3.单击前一步按钮导航回到Personal界面,此时前一步按钮不再是活动的了。
4.单击下一步按钮直至最后一个界面(已在配置工作表中定义),应该是Access界面,此时下一步按钮不再能够使用,如下图28所示。
图28
5.通过单击右上方的X按钮,停止用户窗体的运行。
保存员工记录
至此,我们已经做了大量的工作,从自定义对象获得了一些完美干净的功能提供给用户窗体。唯一没有做的就是将数据保存到EmpData工作表。
一般来说,可以创建一个子过程,将其命名如SaveData(),将从cmdSave_Click事件中调用该程序,但是cHRData类已经具有了SaveEmployee方法。我们可以直接从cmdSave_Click中调用而不需要再创建保存函数。
在cmdSave_Click事件中插入下列代码:
Private Sub cmdSave_Click()
Dim oHRData As cHRData
Set oHRData = New cHRData
Set oHRData.Worksheet =Sheets("EmpData")
oHRData.SaveEmployee m_oEmployee
Set oHRData = Nothing
End Sub
在设置Worksheet属性之后,以便于cHRData对象知道在哪里保存数据,调用SaveEmployee方法,传递m_oEmployee对象,那里包含要保存的所有数据。
清理
我们几乎已经获得了一个完整的应用程序。下面让我们添加Cancel按钮的代码并在用户窗体的Terminate事件中放置清理代码。
在cmdCancel按钮的Click事件中添加下面的代码行:
Private Sub cmdCancel_Click()
Unload Me
End Sub
这行代码简单地卸载用户窗体而不保存任何数据。
现在我们清除HRWizard用户窗体使用的对象。在UserForm_Terminate事件处理中添加下列代码:
Private Sub UserForm_Terminate()
Set m_oEmployee = Nothing
Set m_oLM = Nothing
Set m_oWizard = Nothing
End Sub
下面再添加一个简单的函数用来打开向导窗体。在VBE中,添加一个标准模块,在其中添加下列代码:
Sub StartWizard()
HRWizard.Show
End Sub