Excel VBA 7.46字典+数字+窗体控件,跨工作表实现COUNTIF的功能

一起学习,一起进步~~

之前我们分享过一篇文章,就是通过字典+数组的方式来实现跨工作表求和的,在那一节的学习中,我们实现了count函数的跨工作表的一个求和的效果,后面有小伙伴表示,他碰到的场景不仅仅是求和,他希望能够得到了个类似countif函数的效果,跨工作表统计满足某条件的次数,这里我们划一下重点,次数,并不是总和,那么,我们要如何实现这样的功能呢?

代码区

我们还是使用相同的案列

我们当前依然需要针对这三个工作表的所有数据进行计算,我们现在希望通过类名,也就是姓名这一列来进行统计,语文成绩大于/等于/小于/介于

某一个值的次数,这个某小伙伴在课后提出来的要求,我们来实现他。

看看代码

因为今天我们要展示的场景比较的多,大于,小于,等于,还有介于,全部的代码展示出来太占篇幅了

我们就选择其中大于这个场景来展示代码,其他的场景也仅仅是修改下判断条件就可以了,大家可以自己按照需要编写代码

Sub dayu(s)Dim rng As Range, trng As Range, schrng As Range, zd As Object, str$Set zd = CreateObject("scripting.dictionary")Set trng = Application.InputBox("请选择表头区域", "表头区域的确定", , , , , , 8)TitleRow = trng.Rows.CountSet rng = Application.InputBox("请选择类别区域", "类别区域的确定", , , , , , 8)TargetCol = rng.ColumnSet schrng = Application.InputBox("请选择数据区域", "数据区域的确定", , , , , , 8)schrngCol = schrng.ColumnFor Each sth In Worksheets l = sth.Cells(Rows.Count, TargetCol).End(xlUp).Row For i = TitleRow + 1 To l str = sth.Cells(i, TargetCol) & "-" & Cells(i, TargetCol + 1) If zd.Exists(str) Then If sth.Cells(i, schrngCol) > Int(s) Then zd.Item(str) = zd.Item(str) + 1 End If Else If sth.Cells(i, schrngCol) > Int(s) Then zd.Add str, 1 Else zd.Add str, 0 End If End If Next iNext sthWorksheets.Add after:=Worksheets(Worksheets.Count)ActiveSheet.Name = "大于"CountNum = zd.CountActiveSheet.Range(Cells(1, 1), Cells(CountNum, 1)) = WorksheetFunction.Transpose(zd.keys())ActiveSheet.Range(Cells(1, 2), Cells(CountNum, 2)) = WorksheetFunction.Transpose(zd.Items())End Sub

仅仅针对大于条件的代码已经编写好了,我们先来看看代码的效果

当然本节提供的源码中已经涵盖了上面的4个场景的所有代码,并且为了提高通用性,我特意将这些条件放在一个窗体中来展示

对于窗体有兴趣大小伙伴们可以先研究下,我们后续还会单独针对窗体进行相关知识的分享

来看本节的代码执行效果

首先先会弹出一个窗体,让我们选择我们要执行的操作和相应的条件,假设这里我们选择要选择语文成绩大于110的情况

条件输入完毕之后,点击确定,开始进入对应的程序

这里我们先要依次选择对应的表头和类名所在的范围,然后我们来确定数据源的范围

这里的数据源就是指我们希望统计的学科所在的那一列,比方说我们想要统计语文成绩大于110的次数,那么我们就选择语文这一列

在选择范围的时候也要注意,这里一定要将表头那一列也选中

然后就可以等到程序运行的结果了

A22 的数据都是0?是我们统计错了吗?看下具体的数据,A22最高只有100,所以0是正确的的结果。

代码很好的执行了我们的需求

代码分析

实现了要求,那么我们就来啃一下今天的代码

Set zd = CreateObject("scripting.dictionary")

首先我们声明一个字典,这个字典就是来状态满足条件的格式的

然后我们要确定标头的区域

有了表头的区域之后,我们就需要得到表头总共有多少行,为什么要得到多少行呢?因为我们这里需要从表头的下一行开始进行遍历,

然后我们需要得到类别的区域

Set rng = Application.InputBox("请选择类别区域", "类别区域的确定", , , , , , 8)

不然我们怎么知道是按照什么来进行统计呢?

之后就是要得到数据区域

Set schrng = Application.InputBox("请选择数据区域", "数据区域的确定", , , , , , 8)

这个数据源就是我们要进行判断的那一列,比方说案例中我们判断的是语文成绩,所以这里我们就选择语文所在的列

For Each sth In Worksheets l = sth.Cells(Rows.Count, TargetCol).End(xlUp).Row For i = TitleRow + 1 To l str = sth.Cells(i, TargetCol) & "-" & Cells(i, TargetCol + 1) If zd.Exists(str) Then If sth.Cells(i, schrngCol) > Int(s) Then zd.Item(str) = zd.Item(str) + 1 End If Else If sth.Cells(i, schrngCol) > Int(s) Then zd.Add str, 1 Else zd.Add str, 0 End If End If Next iNext sth

这一段就是我们之前学习的利用字段来循环判断的过程中,不过这里我们要注意的时候,我们这里要字典只需要一个值就可以了,一个是字典名称,一个就是字典的值,这个值就是满足条件的格式

当条件不存在的时候,我们这里要细分一下,如果满足条件,就是

zd.Add str, 1

不满足条件的话,就是

zd.Add str, 0

为什么这样呢?我们来试想下,满足条件就是记录为1,代表他第一次是满足条件的,如果第一次都不满足条件,我们不能忽略,要等级为0,证明第一次判断的时候他也不满足条件,后续判断的时候要在0的基础上增加,我们不满足条件就直接忽略的话,最终的结果是没有这个值的,比方说上面案例中的A22

如果我们不登记的话,就会变成不存在这个数据,那么到底这几个数不存在还是结果为0 ?这就不得而知了,所以这里要注意

具体的循环比较的过程,相信大家有了前面的基础,这里就很简单理解了。窗体的构造我们后面在深入学习,这里就不做深究了。

================================

好了,明晚21:00,准时再见!

(0)

相关推荐