【问题标题】:Filter out entire rows if group value is below 10如果组值低于 10,则过滤掉整行
【发布时间】:2019-11-29 18:10:09
【问题描述】:

如果值的总和超过特定数量,我会尝试从 VBA 中的电子表格中删除行。

例如,如果我有以下数据,A1中的名称和A2中的值:

我想在B行中删除A行中的值总和未达到10或以上的所有行,这将留下以下结果:

Thomas = 18 和 John = 15,所以 所有 行包含 Thomas 和 John。

所有其他行都将被删除。

请注意,我将始终知道数据在 A 行和 B 行中,但我不知道会有多少行并且需要在第一个空白单元格之前执行。

【问题讨论】:

  • 如果您需要帮助,请在问题中包含您正在使用的代码。请记住,Stack Overflow 不是免费的代码编写服务。
  • 嗨braX,我没有任何代码,因为我无法让它工作,我不希望为我编写代码,但有任何关于功能或想法的建议或指导即使有可能也会很好
  • 你有没有试过录制一个你想要的宏?如果您想学习,这是一个好的开始。
  • 在空白列中使用SUMIF公式识别不超过条件的名称,然后将其删除。
  • 我录制了一个宏来过滤小于 10 的值,但是当它涉及分组值时,我无法让它适用于单个行。

标签: excel vba filter


【解决方案1】:

成功了。你可以在这里看到:

Sub run()
    Dim rowIndex, countSameRow, sumSameRow As Integer
    sumSameRow = Cells(1, 2)
    rowIndex = 2
    countSameRow = 1
    While IsEmpty(Cells(rowIndex, 1)) = False
      If (Cells(rowIndex, 1) = Cells(rowIndex - 1, 1)) Then
          sumSameRow = sumSameRow + Cells(rowIndex, 2)
          countSameRow = countSameRow + 1
      Else
          If (sumSameRow < 10) Then
              Rows(rowIndex - 1 & ":" & rowIndex - countSameRow).Delete
              rowIndex = rowIndex - countSameRow
          End If
          countSameRow = 1
          sumSameRow = Cells(rowIndex, 2)
      End If
      If IsEmpty(Cells(rowIndex + 1, 1)) Then
          If (sumSameRow < 10) Then
              Rows(rowIndex & ":" & rowIndex - countSameRow + 1).Delete
          End If
      End If
      rowIndex = rowIndex + 1
    Wend
End Sub

【讨论】:

  • 只是一个小提示:Dim i, n, s As Integer 仅导致 s 变暗为 Integer 数据类型,其他将为 Variant。无论哪种方式,宁愿使用Long 而不是Integer 来防止溢出问题(这不会发生在这个特定的数据上)=)
  • 这很好用,代码也很简单,我可以在我的水平上学习,谢谢!我什至没有考虑使用循环方法,您能告诉我如何更改值以将不同的列引用到 A 和 B?
  • @user1747021 我不明白你的意思。举个例子
  • 目前名称必须在 A 列中,而值在 B 列中,如果它位于 D 和 K 列或任何其他组合中,我会更改哪些值?
  • @user1747021 看看Cells(1, 2),意思是Cells(Row1st, Column2nd)=>cells of row 1, column 2 (column B)。所以第 3 行 D 列的单元格将是 Cells(3, 4)
【解决方案2】:

完全同意您应该先编写自己的代码,但我忍不住为您编写了一些起始代码。看看以下是否符合您的目的:

Sub Test()

Dim lr As Long, x As Long
Dim arr As Variant, rng As Range
Dim dict1 As Object: Set dict1 = CreateObject("Scripting.Dictionary")
Dim dict2 As Object: Set dict2 = CreateObject("Scripting.Dictionary")

With Sheet1 'Change according to your sheets CodeName

    'Get all of your data form A:B in memory (array)
    lr = .Cells(.Rows.Count, 1).End(xlUp).Row
    arr = .Range("A1:B" & lr)

    'Step through the array and fill up our two dictionaries
    For x = LBound(arr) To UBound(arr)
        If dict1(arr(x, 1)) <> "" Then
            dict1(arr(x, 1)) = Join(Array(dict1(arr(x, 1)), x & ":" & x), ",")
        Else
            dict1(arr(x, 1)) = x & ":" & x
        End If
        dict2(arr(x, 1)) = dict2(arr(x, 1)) + arr(x, 2)
    Next x

    'Step through our second dictionary and check if value < 10
    For Each Key In dict2.keys
        If dict2(Key) < 10 Then
            If Not rng Is Nothing Then
                Set rng = Union(rng, .Range(dict1(Key)))
            Else
                Set rng = .Range(dict1(Key))
            End If
        End If
    Next Key

    'If any where below 10, this Range object has been filled, so delete it.
    If Not rng Is Nothing Then
        rng.Delete
    End If

End With

End Sub

【讨论】:

  • Scripting.Dictionary 不需要参考吗?
  • @Andreas,您的意思是图书馆参考资料吗?这是后期绑定,所以不需要。
  • 好吧,我的错!我只是认为字典需要参考。
  • @Andreas,好吧,早期绑定可能是一个很好的做法,因为智能感知会选择它(添加库),您可以轻松引用方法和属性。但是,将其传递给其他人可能会导致问题。因此,我真的不介意后期绑定自己。我猜是个人喜好=)
  • 抱歉回复晚了,这确实有效,错误与 Mac 相关,在 Windows 机器上完全没有问题。不幸的是,我只能选择一个答案作为正确答案,但这也是正确的
【解决方案3】:

这是另一种使用 Autofilter 和 SUMIF 删除行的方法。

这假设有一个标题行,如果没有,则先添加一行。
它在 C 列中添加一个 sumif 并过滤所有小于 10 的内容,然后将其删除。
然后再次删除 C 列。

Sub filter()

    Range("C1").Value = "Sum"
    Lastrow = Range("A" & Rows.Count).End(xlUp).Row
    Range("C2:C" & Lastrow).Formula = "=sumif(A:A,A2,B:B)"


    Range("A2").AutoFilter ' add a filter to table
    ActiveSheet.Range("$A$1:$C$" & Lastrow).AutoFilter Field:=3, Criteria1:="<10", Operator:=xlAnd ' filter all below 10

    ActiveSheet.Range("A2:C" & Lastrow).SpecialCells(xlCellTypeVisible).EntireRow.Delete ' delete them
    Range("A1").AutoFilter ' remove filter again
    Columns("C:C").EntireColumn.Delete ' remove column C
End Sub

【讨论】:

  • 投反对票的人能否评论一下你为什么投反对票的工作方法?
  • 我的回答也一样@Andreas
  • @JvdV 啊……就是其中之一……谢谢
  • 是的,我猜。这是反对这种行为的投票。我不介意投反对票,但我想知道为什么需要对答案投反对票的反馈。
猜你喜欢
  • 2023-02-09
  • 1970-01-01
  • 1970-01-01
  • 2022-06-11
  • 2022-01-11
  • 1970-01-01
  • 2018-02-09
  • 1970-01-01
  • 2021-11-23
相关资源
最近更新 更多