【发布时间】:2020-05-30 17:14:36
【问题描述】:
背景:
我多次申请AutoFilter 并且从未真正问过自己为什么它有时会以这种方式工作。处理过滤数据的结果有时会让人感到困惑,尤其是当SpecialCells 发挥作用时。
让我详细说明以下场景:
测试数据:
| Header1 | Header2 |
|---------|---------|
| 50 | |
| 10 | |
| 30 | |
| 40 | |
| 20 | |
代码 1 - 普通 AutoFilter:
With Sheets("Sheet1").Range("A1:B6")
.AutoFilter 1, ">50"
.Columns(2).Value = "Check"
.AutoFilter
End With
这会起作用(即使不使用SpecialCells(12)),但会填充B1。
代码 2 - 使用 .Offset:
为了防止上述行为,我们可以像这样实现Offset:
With Sheets("Sheet1").Range("A1:B6")
.AutoFilter 1, ">50"
.Columns(2).Offset(1).Value = "Check"
.AutoFilter
End With
但是,现在这将填充我们数据下方的行,单元格B7。
代码 3 - 使用 .Resize:
为了防止.Offset 填充B7,我们现在必须包含.Resize:
With Sheets("Sheet1").Range("A1:B6")
.AutoFilter 1, ">50"
.Columns(2).Offset(1).Resize(5, 1).Value = "Check"
.AutoFilter
End With
尽管现在我们都阻止了B1 和B7 被填充,但B2:B6 被填充了,AutoFilter 机制似乎“损坏”了。我试图用下面的截图来展示它。中间一个是在">30" 上过滤时,右边是在">50" 上过滤时。在我看来,这与引用范围现在由零个可见单元格组成的事实有关。
代码 4 - 使用 .SpecialCells:
我在这里做的正常事情是首先Count可见单元格(包括范围内的标题以防止error 1004)。
With Sheets("Sheet1").Range("A1:B6")
.AutoFilter 1, ">50"
If .SpecialCells(12).Count > 2 Then .Columns(2).Offset(1).Resize(5, 1).Value = "Check"
.AutoFilter
End With
问题:
如你所见,我从.Columns(2).Value = "Check"一直到If .SpecialCells(12).Count > 2 Then .Columns(2).Offset(1).Resize(5, 1).Value = "Check",只是为了防止B1被覆盖。
显然,AutoFilter 机制在第一种情况下确实可以很好地检测可见行本身,但为了防止标题被覆盖,我必须实现:
我是不是把事情复杂化了,会有更短的路线吗?此外,为什么一旦没有单元格可见,就会填充整个范围的不可见单元格。当实际上过滤了一些数据时,它会很好地工作。这是什么机制(见代码3)?
我想出的不太优雅(IMO)的选项是重写B1:
With Sheets("Sheet1").Range("A1:B6")
.AutoFilter 1, ">50"
Var = .Cells(1, 2): .Columns(2).Value = "Check": .Cells(1, 2) = Var
.AutoFilter
End With
【问题讨论】:
-
您是否尝试在第 2 列中的每个可见单元格中添加检查?
-
@TinMan,对于这个确实可以做的练习。但其背后的问题是在 AutoFilter 之后找到最好的方法,并考虑到根据我上面的说明可能存在不可见的单元格。
-
你是对的。我会使用
SpecialCells(),因为更改列标题会修改相关公式。 -
不确定这是否有帮助,但我发现这篇非常有用的帖子回复:getting visible cell row count
-
感谢@Zac 的指点,我会通读一遍。
标签: excel vba autofilter