欢迎转发和点一下“看”,文末留言互动!

置顶公众号或设为星标及时接收更新不迷路

朋友们好,这里是EXCEL应用之家,坚持分享EXCEL操作技巧。

今天来和大家分享一道按条件统计的题目。题目稍微有些难度,今天的推文中通过一条公式,三段代码来从不同角度解析这道题目。

原题是这样的:

有这样一组清单(我截取了一部分,如上图),记录了每个用户的登录时间。现在需要找出那些连续七天都有登录的用户名单。

提到连续问题,就要考虑使用FREQUENCY函数了。

01

FREQUENCY函数法

在单元格F3中输入下列公式,并向下填充。

=INDEX(A:A,SMALL(IF(FREQUENCY(ROW($1:$45),(B$3:B$46-B$2:B$45<>1)*ROW($1:$45))>=7,ROW(A$2:A$46)),ROW(A1)))

这个类型的题目我们在FREQUENCY函数的专题帖中有过相关讨论,这里就不再详细介绍了。

如有问题朋友们可以给我留言!

02

VBA循环法

完整代码如下:

Sub 连续7天()    Dim i%, j%, h%, m%, k%, arr As Variant, brr As Variant    arr = Range("A1").CurrentRegion.Offset(1)    ReDim brr(1 To 10, 1 To 1)    For i = 1 To UBound(arr) - 1        If arr(i, 1) <> arr(i + 1, 1) Then            k = k + 1            For j = h + 1 To i - 1                If CDate(arr(j + 1, 2)) - CDate(arr(j, 2)) = 1 Then                    m = m + 1                    If m + 1 >= 7 Then brr(k, 1) = arr(j, 1)                End If            Next        If m + 1 < 7 Then k = k - 1        h = i: m = 0        End If    Next    [E3].Resize(UBound(brr), 1) = brrEnd Sub

简单说一下这段代码。

判断一下前后两个相邻的单元格相减结果是否为1。如果是,就对变量m累积加1。当m+1的值大于等于7后(为什么要m+1?),对应的人名符合题目设定的条件,将其录入到数值brr中。

若m+1小于7,则表明在同一个人对应的区域中没有连续7天登录,这时对变量k要停留在当前的累计值不动,直到下一个符合条件的人名出现。原因是变量k控制着数组brr的行数。

在变量j循环时,通过变量h来控制不同用户的起始位置。

03

以前求最大的连续值我习惯用FREQUENCY函数,如今遇到了就写几行代码,真香!

VBA循环法

完整代码如下:

Sub 连续7天1()    Dim i%, m%, k%, arr As Variant, brr As Variant    arr = Range("A1").CurrentRegion.Offset(1)    ReDim brr(1 To 10, 1 To 1)    k = 1    For i = 1 To UBound(arr) - 1        If arr(i, 1) <> arr(i + 1, 1) Then k = k + 1        If arr(i, 1) = arr(i + 1, 1) Then            If CDate(arr(i + 1, 2)) - CDate(arr(i, 2)) = 1 Then                m = m + 1                If m + 1 >= 7 Then brr(k, 1) = arr(i, 1)            End If        Else            If m + 1 < 7 Then k = k - 1            m = 0        End If    Next    [E3].Resize(UBound(brr), 1) = brrEnd Sub

和上面一段代码相似。都是通过判断在同一个相同人名的区域内,是否连续7天登录,根据结果来录入数据。

04

VBA字典方法

完整代码如下:

Sub 连续7天2()    Dim i%, arr As Variant, mydic As Object, d    arr = Range("A2:B46")    Set mydic = CreateObject("scripting.dictionary")    For i = 1 To UBound(arr)        If Not mydic.exists(arr(i, 1)) Then            mydic(arr(i, 1)) = Array(arr(i, 2), 1)        Else            If CDate(arr(i, 2)) - CDate(mydic(arr(i, 1))(0)) = 1 Then                mydic(arr(i, 1)) = Array(arr(i, 2), mydic(arr(i, 1))(1) + 1)            Else                mydic(arr(i, 1)) = Array(arr(i, 2), 1)            End If        End If    Next    For Each d In mydic.keys        If mydic(d)(1) < 7 Then mydic.Remove (d)    Next    [E3].Resize(mydic.Count, 1) = Application.Transpose(mydic.keys)End Sub

这段代码使用了字典方法。同时,它也可以处理用户名为乱序排列的情况。

我就知道你“在看”

推荐阅读