Excel VBA中数组的查找模式

Excel VBA中数组的查找模式,excel,vba,Excel,Vba,我试图在VBA中找到数组的模式 假设存在电影标题的动态列表。A:A,还有一个和B:B一样长的列表,这是一个电影“类型”列表 我试图找到某一类型重复次数最多的标题 注意:A:A是一个动态列表,我不知道它的长度 --------------------------------- -Finding Nemo - Cartoon -Finding Nemo - Cartoon -Finding Nemo - Cartoon -Finding Nemo - Cartoon -Finding Ne

我试图在VBA中找到数组的模式

假设存在电影标题的动态列表。A:A,还有一个和B:B一样长的列表,这是一个电影“类型”列表

我试图找到某一类型重复次数最多的标题

注意:A:A是一个动态列表,我不知道它的长度

---------------------------------
-Finding Nemo  - Cartoon 
-Finding Nemo  - Cartoon
-Finding Nemo  - Cartoon
-Finding Nemo  - Cartoon
-Finding Nemo  - Cartoon
-Inception     - Action
-Inception     - Action
-Inception     - Action
-Dragon Ball   - Cartoon
-Dragon Ball   - Cartoon
-Dragon Ball   - Cartoon 
---------------------------------
以这张表为例,《海底总动员》是最常见的标题。但是现在我要写一个函数来返回那个结果吗

我假设的函数与此类似:

=movieMode(5)
其中5指定要返回的“top”结果数

这里的问题是,当A:A处于动态长度时,我不知道如何做到这一点。以及如何控制返回多少个结果。我应该设置一个过滤器,默认情况下只搜索“卡通”

请分享一些关于这方面的信息

更新

经过研究,我发现了这个公式

=INDEX(A2:A177,MATCH(MAX(COUNTIF(A2:A177,A2:A177)),COUNTIF(A2:A177,A2:A177),0))
在两种情况下,返回出现次数最多的标题

  • 我使用Ctrl+Shift+Enter(似乎是在范围内循环?)
  • 在我指定的范围内没有空格
  • 我需要改进这个公式,使它取E:E,其中
    类型是卡通的,当A'x'不是空的时候。(当范围为空时,此公式似乎不起作用

    这是我第一天使用excel公式,我已经遇到了这个问题。哈哈

    进一步更新

    考虑到我上面给出的场景,我希望使用 =电影模式(2)

    结果应该是

    ----------------------------
    -Finding Nemo    - 5 
    -Dragon Ball     - 3
    ----------------------------
    
    我希望“卡通”过滤器默认设置在函数中。我不希望动作出现在任何点上,也不希望它成为变量

    但是,如果我使用

    -movieMode(1)
    
    预期的结果是

    -------------------
    -Finding Nemo  - 5
    -------------------
    
    使用此选项可返回仅包含不同值的数组。一旦获得该值,您就可以实现下面的逻辑(与您已有的公式类似)来生成结果。这些是工作表公式,但您应该能够在VBA中完成相同的任务。顺便说一句,是VBA的良好资源

    title genre       distinct  cpearsonVBA     count                tieBreak         rank            #_of_results   filter_array        result
    ----------------------------------------------------------------------------------------------------------------------------------------------------
    Finding Nemo      Cartoon   Finding Nemo    =COUNTIFS(A:A,C:C)   =ROW()^-9+D:D    =RANK(E:E,E:E)   2             =IF(F:F<=$G$2,1,0)  =IF(H:H,C:C,"")
    Finding Nemo      Cartoon   Inception       =COUNTIFS(A:A,C:C)   =ROW()^-9+D:D    =RANK(E:E,E:E)                 =IF(F:F<=$G$2,1,0)  =IF(H:H,C:C,"")
    Finding Nemo      Cartoon   Dragon Ball     =COUNTIFS(A:A,C:C)   =ROW()^-9+D:D    =RANK(E:E,E:E)                 =IF(F:F<=$G$2,1,0)  =IF(H:H,C:C,"")
    Finding Nemo      Cartoon              
    Finding Nemo      Cartoon              
    Inception         Action             
    Inception         Action             
    Inception         Action             
    Dragon Ball       Cartoon              
    Dragon Ball       Cartoon              
    Dragon Ball       Cartoon              
    
    title体裁不同cpearsonVBA计数分阶段排名#(共)个结果过滤器(共)个数组结果
    ----------------------------------------------------------------------------------------------------------------------------------------------------
    
    Finding Nemo卡通Finding Nemo=COUNTIFS(A:A,C:C)=ROW()^-9+D:D=RANK(E:E,E:E)2=IF(F:F这是一个使用脚本对象
    字典
    的解决方案,但在最后处理
    范围
    时效率不是很高。然而,我使用
    Application.screenUpdate=False
    来保持一些性能提升,并消除闪烁的屏幕更新……这是一个
    子部分,您也可以使用它作为函数,为
    Top N
    提供一个参数

    Option Explicit
    
    Sub getTopN()
    Dim ws As Worksheet
    Dim rng As Range
    Dim vArr As Variant, d As Object, aL As Object
    Dim i As Integer, j As Integer, lastRow As Long
    Dim topN As Integer
    
    Set d = CreateObject("Scripting.Dictionary")
    Set ws = Sheets(1)
    Set rng = ws.Range("A2")
    topN = ws.Range("B2").Value '-- for testing it's 2
    '-- get last used row dynamically
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    '--since data starting with row 2
    lastRow = lastRow - 1
    vArr = WorksheetFunction.Transpose(rng.Resize(lastRow).Value)
    
    For i = LBound(vArr) To UBound(vArr)
        If Not d.Exists(RTrim(vArr(i))) Then
            j = 1
            d.Add RTrim(vArr(i)), j
        Else
            d.Item(RTrim(vArr(i))) = d.Item(RTrim(vArr(i))) + 1
        End If
    Next i
    
    '-- screen updating false
    Application.ScreenUpdating = False
    
    '-- output items, keys in to sheet
    Set rng = ws.Range("C2")
    rng.Resize(UBound(d.keys) + 1) = Application.Transpose(d.keys)
    rng.Offset(0, 1).Resize(UBound(d.items) + 1) = Application.Transpose(d.items)
    
    '-- sort this new range , top N
    Set rng = rng.Resize(UBound(d.items) + 1, 2)
    rng.Sort key1:=Range("D2"), order1:=xlDescending, header:=xlNo
    '-- copy topN rows into a temp range
    ws.Range("E2").Resize(topN, 2) = rng.Resize(topN, 2).Value
    '-- clean up everything other than top N rows
    rng.ClearContents
    rng.Resize(topN, 2).Value = ws.Range("E2").Resize(topN, 2).Value
    ws.Range("C1").Value = "Top N Movies"
    ws.Range("E2").Resize(topN, 2).ClearContents
    '-- release memory
    Set d = Nothing
    
    Application.ScreenUpdating = True
    End Sub
    
    输出:


    参数值5是否意味着给我看5次的电影?否。这意味着我想要出现次数最多的前5部电影。在我给出的场景中,它不起作用,因为只有2个不同的卡通。你能给出示例输出和示例输入来解释测试用例吗?搜索是否必须限于卡通ons?如果是,您在函数参数中的具体位置是什么?@shahkalpesh我已经更新了这个问题。请参考,谢谢您的帮助。@HeHui因为您谈论的是数组,这是否意味着您更喜欢VBA解决方案?谢谢您的尝试,但您遗漏了我提出的一个非常核心的问题。主要问题是动态性。我不知道有多少不同类型的标题。因此我不可能使用你的解决方案,因为它只固定在3个不同的标题上。我的意思是,当我只有
    查找尼莫
    盗梦空间
    龙珠
    时,你的方法有效。如果我在中添加一个forth
    狮子王
    ,我将不得不重新调整我的模板,以阅读您生成的cpearsonVBA列表,这正是我试图避免的。我可以看到我的答案有多混乱,但这应该是可行的。您可以使用链接中的DistinctValues函数创建VBA数组,然后再从那里开始。这不是令人困惑的,但这不是我正在寻找的答案。我正在寻找一个可以我将动态检测所有标题,并生成我想要的最终结果。我不希望任何过程需要手动单击或生成第二个列表才能获得我的结果。我相信您的解决方案是有效的,因为有很多类似的解决方案与您的解决方案一样有效。啊……我假设您已经有了输入如果在VBA中执行此操作,则可以使用“范围”(“a1”).CurrentRegion.Resize(,1)选择a列中的所有数据正如我提到的,我实际上刚刚开始学习VBA。lol。我会尝试了解你在尝试什么,我会让你知道我是否在寻找它。什么是
    Sub
    ?我的意思是,我如何使用它?首先通过谷歌搜索理论和好奇心。然后,你可以问我们;-)没问题:)我注意到你把
    寻找尼莫
    卡通
    放在同一个单元格中。它们实际上属于两个不同的单元格。这会让问题更简单吗?如果你不把
    流派
    作为过滤标准来计算和列出
    前N名
    ,那么,电影名称和流派是否在同一单元格中并不重要。但如果这很重要的话,那么无论如何,把它们分成两个细胞。