前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Excel实战技巧66:创建向导样式的数据输入窗体4

Excel实战技巧66:创建向导样式的数据输入窗体4

作者头像
fanjy
发布2019-12-10 16:24:27
1.3K0
发布2019-12-10 16:24:27
举报
文章被收录于专栏:完美Excel

学习Excel技术,关注微信公众号:

excelperfect

在开始阅读本文前,请先学习下列内容:

Excel实战技巧66:创建向导样式的数据输入窗体1

Excel实战技巧66:创建向导样式的数据输入窗体2

Excel实战技巧66:创建向导样式的数据输入窗体3

继续介绍组成示例应用程序的类模块代码。

管理列表

在HRWizard用户窗体中输入的一些数据是通过组合框控件显示给用户的。HRWizard工作簿文件包含一个名为ListMgr的工作表,其中包含每个列表的数据,这些数据存储在ListMgr工作表的命名区域。

cListManager类包含的函数可以从这些命名区域中获取数据填充组合框,同时也有一个将列表绑定到VBA Collection对象的方法。

插入一个新的类模块,将其命名为cListManager,在其中添加下面两个方法:

Public Sub BindListToRange(ListRangeName As String, TheCombo As MSForms.ComboBox)

TheCombo.RowSource = ListRangeName

End Sub

Public Sub BindListToCollection(TheCollection As Collection, TheCombo As MSForms.ComboBox)

Dim iNumItems As Integer

Dim i As Integer

iNumItems = TheCollection.Count

For i = 1 To iNumItems

TheCombo.AddItem TheCollection(i)

Next i

End Sub

BindListToRange方法接受命名区域名称字符串值和ComboBox对象,设置组合框的RowSource属性为命名区域。BindListToCollection方法简单地遍历集合并调用组合框的AddItem方法添加数据项。

数据类

数据类被命名为cHRData,这是一个专门为HRWizard应用程序设计的类。

插入一个新的类模块,将其命名为cHRData。在其中添加下面的模块级变量、一个属性和一个方法。

Private m_oWorksheet As Worksheet

Private m_lngNewRowNum As Long

Private m_oEmployee As cPerson

Private m_oXL As cExcelUtils

Public Property Get Worksheet() As Worksheet

Set Worksheet = m_oWorksheet

End Property

Public Property Set Worksheet(newWorksheet As Worksheet)

Set m_oWorksheet = newWorksheet

End Property

Public Function SaveEmployee(Employee As cPerson) As Boolean

Dim blnReturn As Boolean

If m_oWorksheet Is Nothing Then

GoTo Exit_Function

EndIf

m_lngNewRowNum =m_oXL.FindEmptyRow(m_oWorksheet)

Set m_oEmployee = Employee

SaveEmpData

SaveAddressData

SaveEquipmentData

SaveAccessData

Exit_Function:

SaveEmployee = blnReturn

Exit Function

End Function

添加下列类初始化和清理代码:

Private Sub Class_Initialize()

Set m_oXL = New cExcelUtils

End Sub

Private Sub Class_Terminate()

Set m_oXL = Nothing

End Sub

Worksheet属性让我们定义工作簿中存储数据的地方。当传递cPerson对象时SaveEmployee方法为我们做一些事情:

Public Function SaveEmployee(EmployeeAs cPerson) As Boolean

检查是否设置了Worksheet属性,以便知道在哪里保存数据:

If m_oWorksheet Is Nothing Then

GoTo Exit_Function

End If

使用cExcelUtils对象找到第一个空行:

m_lngNewRowNum =m_oXL.FindEmptyRow(m_oWorksheet)

(注:cExcelUtils对象是一个通用类,用来实现通用的功能。在上文表中未列出该类名,但在示例工作簿中含有该类模块)

接下来,将传递给该方法的cPerson对象赋值给私有的用于不同的保存函数的模块级cPerson对象:

Set m_oEmployee = Employee

最后,触发一些保存函数,每个数据对象一个:

SaveEmpData

SaveAddressData

SaveEquipmentData

SaveAccessData

Save方法简单地将存储在cPerson对象(及其内部的数据对象)中的数据转换到EmpData工作表中的单元格。在cHRData类模块中添加下列Save方法:

Private Sub SaveEmpData()

With m_oWorksheet

.Cells(m_lngNewRowNum, 1).Value =m_oEmployee.ID

.Cells(m_lngNewRowNum, 2).Value =m_oEmployee.FName

.Cells(m_lngNewRowNum, 3).Value =m_oEmployee.MidInit

.Cells(m_lngNewRowNum, 4).Value =m_oEmployee.LName

.Cells(m_lngNewRowNum, 5).Value =m_oEmployee.DOB

.Cells(m_lngNewRowNum, 6).Value =m_oEmployee.SSN

.Cells(m_lngNewRowNum, 7).Value =m_oEmployee.JobTitle

.Cells(m_lngNewRowNum, 8).Value =m_oEmployee.Department

.Cells(m_lngNewRowNum, 9).Value =m_oEmployee.Email

End With

End Sub

Private Sub SaveAddressData()

With m_oWorksheet

.Cells(m_lngNewRowNum, 10).Value =m_oEmployee.Address.StreetAddress

.Cells(m_lngNewRowNum, 11).Value =m_oEmployee.Address.StreetAddress2

.Cells(m_lngNewRowNum, 12).Value =m_oEmployee.Address.City

.Cells(m_lngNewRowNum, 13).Value =m_oEmployee.Address.State

.Cells(m_lngNewRowNum, 14).Value =m_oEmployee.Address.ZipCode

.Cells(m_lngNewRowNum, 15).Value =m_oEmployee.Address.PhoneNumber

.Cells(m_lngNewRowNum, 16).Value =m_oEmployee.Address.CellPhone

End With

End Sub

Private Sub SaveEquipmentData()

With m_oWorksheet

.Cells(m_lngNewRowNum, 17).Value =m_oEmployee.Equipment.PCType

.Cells(m_lngNewRowNum, 18).Value =m_oEmployee.Equipment.PhoneType

.Cells(m_lngNewRowNum, 19).Value =m_oEmployee.Equipment.Location

.Cells(m_lngNewRowNum, 20).Value =m_oEmployee.Equipment.FaxYN

End With

End Sub

Private Sub SaveAccessData()

With m_oWorksheet

.Cells(m_lngNewRowNum, 21).Value =m_oEmployee.Access.Building

.Cells(m_lngNewRowNum, 22).Value =m_oEmployee.Access.NetworkLevel

.Cells(m_lngNewRowNum, 23).Value =m_oEmployee.Access.RemoteYN

.Cells(m_lngNewRowNum, 24).Value =m_oEmployee.Access.ParkingSpot

End With

End Sub

注意,用于获取cPerson对象的内部的Address、Equipment、Access对象数据的语法:

m_oEmployee.Address.StreetAddress

m_oEmployee.Equipment.PCType

m_oEmployee.Access.Building

在一个对象里使用另一个对象可以灵活地分类对象中的信息。

管理向导

创建两个类来帮助管理向导应用程序。第一个非常简单,包含每步的配置数据,接着创建一个类,包含这些“向导步骤”对象的集合,管理向导过程的操作。

插入一个新的类模块,将其命名为cStep,添加下列代码:

Private m_iOrder As Integer

Private m_iPage As Integer

Private m_sCaption As String

Public Property Get Order() AsInteger

Order = m_iOrder

End Property

Public Property Let Order(newOrder As Integer)

m_iOrder = newOrder

End Property

Public Property Get Page() AsInteger

Page = m_iPage

End Property

Public Property Let Page(newPage As Integer)

m_iPage = newPage

End Property

Public Property Get Caption()As String

Caption = m_sCaption

End Property

Public Property Let Caption(newCaptionAs String)

m_sCaption = newCaption

End Property

HRWizard.xlms工作簿包含一个名为UFormConfig的隐藏的工作表,该工作表包含向导中每个步骤的信息。在这里,可以修改步骤的顺序或者插入一个新步骤。

下表列出了cStep类的属性及其描述。

表:cStep属性

图20

下面,设置一个类来管理向导中的步骤。在这个类中,将创建cStep对象的集合,用于追踪我们在处理过程中的哪一步以及共有多少步。

插入一个新的类模块,将其命名为cStepManager,添加下列模块级的变量声明:

Dim m_oStep As cStep

Dim m_iNumSettings As Integer

Dim m_iNumSteps As Integer

Dim m_iCurrentPage As Integer

Dim m_iPreviousPage As Integer

Dim m_iNextPage As Integer

Dim WithEvents m_oPreviousButton As MSForms.CommandButton

Dim WithEvents m_oNextButton As MSForms.CommandButton

Dim m_oWorksheet As Worksheet

通过接下来的一些Integer变量,cStep对象m_oStep用于填充向导步骤的集合。告诉有多少步骤,每步有多少属性,基于用户在向导的位置追踪当前、下一个、前一个步骤。

接下来,有两个设置为MSForms.CommandButton对象类型的变量,它们被声明为WithEvents。我们让cStepManager类维护这些按钮的状态。WithEvents声明来捕获它们的Click事件,并在类里面执行操作。使用Click事件基于用户在向导中的位置决定是否启用按钮。

在cStepManager中添加下面的代码:

Public Property Get NumberOfSettings() As Integer

NumberOfSettings = m_iNumSettings

End Property

Public Property Let NumberOfSettings(newNum As Integer)

m_iNumSettings = newNum

End Property

'worksheet属性:获取/设置包含步骤信息的工作表

Public Property Get Worksheet() As Worksheet

Set Worksheet = m_oWorksheet

End Property

Public Property Set Worksheet(newWorksheet As Worksheet)

Set m_oWorksheet = newWorksheet

End Property

Public Property Get CurrentPage() As Integer

CurrentPage = m_iCurrentPage

End Property

Public Property Let CurrentPage(newPage As Integer)

m_iCurrentPage = newPage

End Property

Public Property Get PreviousPage() As Integer

PreviousPage = m_iCurrentPage - 1

End Property

Public Property Get NextPage()As Integer

NextPage = m_iCurrentPage + 1

End Property

Public Property Set PreviousButton(newPreviousBtn As MSForms.CommandButton)

Set m_oPreviousButton = newPreviousBtn

End Property

Public Property Set NextButton(newNextBtn As MSForms.CommandButton)

Set m_oNextButton = newNextBtn

End Property

下表列出了cStepManager类的属性及其描述。

表:cStepManager属性

图21

下面,需要在该类中添加更多的属性。

下面的只读属性PageSettings包含cStep对象的集合,包含向导的每一步的信息。

PageSettings属性存储该集合,使用HRWizard用户窗体后台的客户端代码返回一个Collection对象。

PageSettings属性的代码如下:

Public Property Get PageSettings() As Collection

Dim colReturn As Collection

Dim numrows As Integer

Dim row As Integer

Dim col As Integer

Dim sKey As String

Set colReturn = New Collection

numrows = m_oWorksheet.Cells(Rows.Count,1).End(xlUp).row

For row = 2 To numrows

Set m_oStep = New cStep

For col = 1 To m_iNumSettings

Select Case col

Case 1

m_oStep.Order =m_oWorksheet.Cells(row, col).Value

sKey = CStr(m_oStep.Order)

Case 2

m_oStep.Page =m_oWorksheet.Cells(row, col).Value

Case 3

m_oStep.Caption =m_oWorksheet.Cells(row, col).Value

End Select

Next col

colReturn.Add m_oStep, sKey

Next row

m_iNumSteps = colReturn.Count

Set PageSettings = colReturn

End Property

我们首先做的是获取工作表中已使用的区域的行数:

numrows =m_oWorksheet.Cells(Rows.Count, 1).End(xlUp).row

注意,虽然Excel的Worksheet对象有Rows.Count方法,但是在这里不能使用(m_oWorksheet.Rows.Count)。这将返回工作表中的总行数,这样不仅提供不正确的值,而且也会使Integer变量溢出。

接下来,循环填充cStep对象集合,代码如下:

For row = 2 To numrows

Set m_oStep = New cStep

For col = 1 To m_iNumSettings

Select Case col

Case 1

m_oStep.Order =m_oWorksheet.Cells(row, col).Value

sKey = CStr(m_oStep.Order)

Case 2

m_oStep.Page =m_oWorksheet.Cells(row, col).Value

Case 3

m_oStep.Caption =m_oWorksheet.Cells(row, col).Value

End Select

Next col

colReturn.Add m_oStep, sKey

Next row

上述代码中,首先做的是实例化一个新的cStep对象,然后移到内部循环遍历配置工作表中的列,将它们赋给内部的cStep对象的相应属性。这段代码运行前,已经通过NumberOfSettings属性设置m_iNumSettings值。

然后,将cStep对象添加到内部的集合colReturn中,在该集合中传递Order值作为主键。

注意,在外部循环中的第一行代码,Set m_oStep=New cStep,是重要的。如果忽略该代码,那么集合中将以四个相同的cStep对象结束(全部都包含从工作表中读取的最后一个配置项中的数据)。这是因为m_oStep对象引用仍然是当前引用,所以每次调用时都会修改任何已存在的实例。通过使用New关键字,创建新的、单独的对象实例。

最后,设置内部的m_iNumSteps变量,用来追踪前一个和下一个可用的命令按钮,并且最终返回集合:

m_iNumSteps = colReturn.Count

Set PageSettings = colReturn

现在,将注意力转向PreviousButton属性和NextButton属性。记得这些属性的内置变量被声明为WithEvents。当声明一个对象时使用WithEvents时,可以通过VBE代码窗口的对象框访问该对象的事件代码,如下图22所示。

图22

从对象框中选择m_oNextButton和m_oPreviousButton,在类模块中插入事件处理代码块,并在其中添加代码如下:

Private Sub m_oNextButton_Click()

m_oNextButton.Enabled = Me.NextPage<> m_iNumSteps + 1

m_oPreviousButton.Enabled = Me.PreviousPage<> 0

End Sub

Private Sub m_oPreviousButton_Click()

m_oPreviousButton.Enabled = Me.PreviousPage<> 0

m_oNextButton.Enabled = Me.NextPage<> m_iNumSteps + 1

End Sub

这段代码基于cStepManager类的NextPage或PreviousPage属性控制每个按钮是否启用。当该类首次在客户端代码中被创建时,再添加一个方法初始化按钮:

Public Sub HandleControls()

m_oPreviousButton.Enabled = Me.PreviousPage<> 0

m_oNextButton.Enabled = Me.NextPage<> m_iNumSteps + 1

End Sub

到现在为止,我们已经创建了相当数量的代码,全都存储在跨越许多类模块的对象中。通过划分功能,使维护代码的工作非常容易。如果需要绑定列表到目前还没有处理的数据源,只需在cListManager类中添加一个新方法。如果需要在数据处理过程中添加一个用户界面,则在多页控件中设计一个新页面,创建一个新类去存储用户信息,并在配置表中添加一行。

在添加完所有的类模块并编写好代码后,工程资源管理器中的类模块文件夹应该如下图23所示。

图23

至此,该应用程序的类模块代码编写完毕,可以开始着手编写用户窗体代码了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 完美Excel 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档