VBA学习(73):Excel VBA 动态添加控件/学生成绩筛选

需求:筛选成绩与参考标准成绩相差在一定范围内的同学。比如标准成绩是100,成绩差是20,那么根据不同情况,成绩在100~120,或80~100,或80~120这些范围内的同学都应该被选到。

怎么来实现呢?

思考过程就不说了,直接动手吧:

1、插入一个Userform1,Name什么的就不改了

2、插入几个标签,一个命令按钮,LbSubject(科目)、LbStandard(标准)、LbDeviation(差值)、LbType(方式)、CmdConfirm(确定):

3、在Userform1的代码块顶端定义几个变量:

Dim dynamicLabel As Control
Dim arrA(), arrB(), arrC(), arrDetail()
Dim iRow As Integer
Dim iWidth As Integer

4、Userform1的Activate事件代码:

Private Sub UserForm_activate()
    arrC = Array("正差", "负差", "正负差", "总差")

    iWidth = 50
    h = 5
    With Me.LbSubject
        .Left = 1
        .Top = 1
        .Width = iWidth
    End With
    With Me.LbStandard
        .Left = Me.LbSubject.Left
        .Top = Me.LbSubject.Top + Me.LbSubject.Height + h
        .Width = Me.LbSubject.Width
    End With
    With Me.LbDeviation
        .Left = Me.LbStandard.Left
        .Top = Me.LbStandard.Top + Me.LbStandard.Height + h
        .Width = Me.LbStandard.Width
    End With
    With Me.LbType
        .Left = Me.LbDeviation.Left
        .Top = Me.LbDeviation.Top + Me.LbDeviation.Height + h
        .Width = Me.LbDeviation.Width
    End With
    Sheet1.Activate
    With ActiveSheet
        iRow = .UsedRange.Rows.Count
        .Range("R4:AA" & iRow).ClearContents
        iName = .Range("I2")
        arrDetail = .Range("A7:J" & iRow).Value
        arrA = .Range("K1:O2").Value
        arrB = .Range("K4:O4").Value
        For i = 1 To 5
            Set dynamicLabel = Me.Controls.Add("Forms.Label.1", "dycLb_Subject" & i)
            With dynamicLabel
                .Caption = arrA(1, i)
                .Top = Me.LbSubject.Top
                .Height = Me.LbSubject.Height
                .Width = iWidth
                .Left = Me.LbSubject.Left + Me.LbStandard.Width + .Width * (i - 1)
                .FontSize = 10
                .FontName = "微软雅黑"
                .ForeColor = RGB(50, 50, 255)
                .TextAlign = 2
            End With
            Set dynamicLabel = Me.Controls.Add("Forms.Label.1", "dycLb_Standard" & i)
            With dynamicLabel
                .Caption = arrA(2, i)
                .Top = Me.LbStandard.Top
                .Height = Me.LbStandard.Height
                .Width = iWidth
                .Left = Me.LbStandard.Left + Me.LbStandard.Width + .Width * (i - 1)
                .FontSize = 10
                .FontName = "微软雅黑"
                .ForeColor = RGB(128, 128, 128)
                .TextAlign = 2
            End With
            Set dynamicLabel = Me.Controls.Add("Forms.TextBox.1", "dycTxb_" & i)
            With dynamicLabel
                .Text = arrB(1, i)
                .Top = Me.LbDeviation.Top
                .Height = Me.LbDeviation.Height
                .Width = iWidth
                .Left = Me.LbDeviation.Left + Me.LbDeviation.Width + .Width * (i - 1)
                .FontSize = 10
                .FontName = "微软雅黑"
                .ForeColor = vbRed   ' RGB(50, 50, 255)
                .TextAlign = 2
                If i = 5 Then
                    .BackColor = RGB(255, 204, 0)
                End If
            End With
            If i < 5 Then
                Set dynamicLabel = Me.Controls.Add("Forms.OptionButton.1", "dycOp_" & i)
                With dynamicLabel
                    .Caption = arrC(i - 1)
                    .Top = Me.LbType.Top
                    .Height = Me.LbType.Height
                    .Width = iWidth
                    .Left = Me.LbType.Left + Me.LbType.Width + .Width * (i - 1)
                    .FontSize = 10
                    .FontName = "微软雅黑"
                    .ForeColor = vbRed   ' RGB(50, 50, 255)
                    .Value = True
                    .TextAlign = 2
                End With
             End If
        Next
    End With
    Me.Height = Me.LbType.Top + Me.LbType.Height + 40
    Me.Width = Controls("dycLb_Subject5").Left + Controls("dycLb_Subject5").Width + 20
    Me.CmdConfirm.Top = Me.LbType.Top
    Me.CmdConfirm.Left = Me.Width - Me.CmdConfirm.Width - 20
End Sub

代码分析:

(1)以LbSubject为基准,调整其他标签的位置

(2)激活Sheet1,读入数据

(3)从1-5循环,动态添加控件,科目标签(语文~总分)、标准标签(各科分数)、差值文本框、方式选项按钮,并设置控件的各种属性。

(4)最后,调整UserForm1的大小,Height根据LbType.Top来调整,Width根据dycLb_Subject5来调整。

5、在Sheet1表添加命令按钮CmdQuery2(查询2),并输入代码:

Private Sub CmdQuery2_Click()
    UserForm1.Show
End Sub

6、我们点击查询2:

这里,差值可以修改,总分差值是单独的数字,跟前面的各科差没有关系。方式,根据查询需要点选,默认是总差。

7、CmdConfirm(确定)按钮代码:

Private Sub CmdConfirm_Click()
    Dim iType As String
    Dim arrSelected()
    '确定哪个选项被选中,取其Caption
    For i = 1 To 4
        If Controls("dycOp_" & i).Value = True Then
            iType = Controls("dycOp_" & i).Caption
        End If
    Next
    Sheet1.Activate
    With ActiveSheet
        If iType = "正差" Then
            k = 0: m = 0
            For i = 1 To UBound(arrDetail, 1)
                For j = 1 To 4
                    '正差,我们定义为:该同学成绩比标准成绩高,,幅度不超过差值
                    If Round(arrDetail(i, j + 5) - arrA(2, j), 2) > Round(Controls("dycTxb_" & j), 2) _
                        Or Round(arrDetail(i, j + 5) - arrA(2, j), 2) < 0 Then
                    Exit For
                    End If
                    If j = 4 Then
                        'Stop
                        k = k + 1
                        ReDim Preserve arrSelected(9, m)
                        For p = 0 To 9
                            arrSelected(p, m) = arrDetail(i, p + 1)
                        Next
                        m = m + 1
                    End If
                Next
            Next
            If k > 0 Then
                .Cells(4, 18).Resize(UBound(arrSelected, 2) + 1, 10) = Application.WorksheetFunction.Transpose(arrSelected)
            End If
        ElseIf iType = "负差" Then
            k = 0: m = 0
            For i = 1 To UBound(arrDetail, 1)
                For j = 1 To 4
                    '负差,我们定义为:该同学成绩比标准成绩低,,幅度不超过差值
                    If Round(arrA(2, j) - arrDetail(i, j + 5), 2) > Round(Controls("dycTxb_" & j), 2) _
                        Or Round(arrA(2, j) - arrDetail(i, j + 5), 2) < 0 Then
                    Exit For
                    End If
                    If j = 4 Then
                        'Stop
                        k = k + 1
                        ReDim Preserve arrSelected(9, m)
                        For p = 0 To 9
                            arrSelected(p, m) = arrDetail(i, p + 1)
                        Next
                        m = m + 1
                    End If
                Next
            Next
            If k > 0 Then
                .Cells(4, 18).Resize(UBound(arrSelected, 2) + 1, 10) = Application.WorksheetFunction.Transpose(arrSelected)
            End If
        ElseIf iType = "正负差" Then
             k = 0: m = 0
            For i = 1 To UBound(arrDetail, 1)
                For j = 1 To 4
                    '正负差,我们定义为:该同学成绩比标准成高或低,幅度不超过差值
                    If Abs(Round(arrDetail(i, j + 5) - arrA(2, j), 2)) > Round(Controls("dycTxb_" & j), 2) Then
                        Exit For
                    End If
                    If j = 4 Then
                        'Stop
                        k = k + 1
                        ReDim Preserve arrSelected(9, m)
                        For p = 0 To 9
                            arrSelected(p, m) = arrDetail(i, p + 1)
                        Next
                        m = m + 1
                    End If
                Next
            Next
            If k > 0 Then
                .Cells(4, 18).Resize(UBound(arrSelected, 2) + 1, 10) = Application.WorksheetFunction.Transpose(arrSelected)
            End If
        ElseIf iType = "总差" Then
            k = 0: m = 0
            For i = 1 To UBound(arrDetail, 1)
                If Round(Abs(arrA(2, 5) - arrDetail(i, 10)), 2) <= Round(Controls("dycTxb_5")) Then
                    'For p = 1 To 10
                    '.Cells(4 + m, 17 + p) = arrDetail(i, p)
                    'Next
                    k = k + 1
                    ReDim Preserve arrSelected(9, m)
                    For p = 0 To 9
                        arrSelected(p, m) = arrDetail(i, p + 1)
                    Next
                    m = m + 1
                End If
            Next
            If k > 0 Then
                .Cells(4, 18).Resize(UBound(arrSelected, 2) + 1, 10) = Application.WorksheetFunction.Transpose(arrSelected)
            End If
        Else
            MsgBox "查询比较方式未选择!"
            Exit Sub
        End If
        For i = 1 To 5
            .Cells(4, 10 + i) = Controls("dycTxb_" & i)
        Next
    End With
    MsgBox "查询完成!共【" & k & "】记录!"
    Erase arrSelected
    Unload Me
End Sub

代码分析:

(1)首先通过循环,确定哪个选项被选中

(2)根据选项的Caption分别进行处理

(3)正差,我们定义为同学的成绩比标准高,但幅度不超过差值,即差值>同学-标准>0,在代码中,我们是排除不符合条件的记录;如果最终找到一条符合条件的记录,我们把它存到arrSelected()数组里,这里我们采用Redim preserve方法,动态扩展数组,不断地写入符合条件的记录,同时把记录数记入k,作为判断arrSelected是否有记录的依据,在程序结尾的MsgBox也引用到k。

(4)把arrSelected的记录写入到EXCEL表格,注意要作一个转置。

(5)其他方式选项类似。

(6)查询完成后,把差值再回写到Excel表中的对应单元格。因为我们可能进行了修改。这里差值的调整方式有2种,一种是在点查询2命令按钮前,在EXCEL表中的K4~O4单元格进行修改,另一种是在显示的用户窗体中修改。

(7)代码并不复杂,难点在于各种查询方式的条件判断比较费脑筋,纯粹是数学问题。

 感谢你们的阅读和喜欢,我收藏了很多技术干货,可以共享给喜欢我文章的朋友们,如果你肯花时间沉下心去学习,它们一定能帮到你,干货内容:

点击文末的名片可以抱走,或点此链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xwLink1996

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值