c# combobox集合数据不显示_Excel实战技巧66:创建向导样式的数据输入窗体4

学习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属性

5942f9df70dbb5acdc476552ff128262.png

图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属性

f2dd3dbbefd2b50ff79c643461ff0200.png

图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所示。

4f5b6b3cd93376cbf47da166c07791fa.png

图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所示。

0881c3211ff95c14e19ca705077e09b4.png

图23

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

e5e2f4395eb3d41b832f108956cd60ee.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值