【问题标题】:clear cells while preserving Autofilter settings?在保留自动筛选设置的同时清除单元格?
【发布时间】:2011-12-08 07:17:19
【问题描述】:

我正在为基于 Access 数据库填充单元格的工作表编写脚本。我试图在不删除用户设置的任何自动过滤器的情况下清除工作表的内容,然后根据数据库重新加载数据。现在我正在使用:

Sub populateSheet()

Dim sht As Worksheet
Dim db As Database
Dim rs As Recordset


Set db = OpenDatabase("c:\myDB.mdb")
Set rs = db.OpenRecordset("myData")
Set sht = ThisWorkbook.Sheets("my output")
With sht
    .Cells.value=empty
    For c = 0 To rs.Fields.Count - 1
        .Cells(1, c + 1) = rs.Fields(c).name
    Next
    .Range("a2").CopyFromRecordset rs
End With

End Sub

sub buildTable()

dim ws as workspace
dim db as database
dim dbPath as string

set ws=dbengine.workspaces(0)
set db=ws.createdatabase("c:\myDB.mdb")
db.execute "create table myData (field1 text,field2 text)"
db.execute "insert into myData (field1,field2) values (""1"",""a"")"
db.execute "insert into myData (field1,field2) values (""2"",""b"")"
db.execute "insert into myData (field1,field2) values (""3"",""a"")"

db.close

end sub
sub test()
 buildTable
 populateSheet
end sub

当我运行.cells.clear 时,它会清除自动过滤器。有没有办法可以保留自动筛选设置,以便以相同的方式筛选新数据?或者也许记录它们并重新应用相同的设置?我尝试使用this solution,但无法让它检测到哪些列被过滤。

编辑:

我在上面的代码中应用了 Jean-FrançoisCorbett 的方法,但它有一个问题。用测试表试试这个:

1 a
2 b
3 a

运行populateSheet 后,自动筛选第二列以仅包含“a”,工作表显示:

1 a
3 a

然后再次运行populateSheet,工作表现在显示:

1 a
1 a

如果您删除自动过滤器,重新运行populateSheet,然后重新应用自动过滤器,您将获得正确的数据,但要获得正确的输出,这是一个非常繁琐的额外步骤。

编辑: 我添加了代码来创建一个数据库并创建一个可用于测试populateSheet 的表,并更改了populateSheet 中的一些参数以反映这个测试数据库。

【问题讨论】:

  • 你试过用 .ClearContents 代替 .Clear 吗?
  • @TimWilliams,这仍然会清除自动筛选。 sigil,您使用的是哪个 Excel 版本?

标签: vba excel autofilter


【解决方案1】:

如果您只想清除单元格中的值而不是其他任何内容,那么您可以这样做:

sht.Cells.Value = Empty

EDIT回应OP的编辑:

奇怪的是,上面的语句并没有清空任何被自动过滤器隐藏的行中的单元格!我认为使用CopyFromRecordset 导入数据时,自动过滤器隐藏的行也会导致意外行为。

该问题的解决方案当然是在清空所有单元格和导入数据之前,通过将自动过滤器设置为 (All) 来取消隐藏所有行,这在 VBA 中是这样完成的:

With Range("C1:D1") ' or wherever the filters are
    .AutoFilter Field:=1
    .AutoFilter Field:=2
    ' ... continue to set all fields to (All).
End With

【讨论】:

  • 嘿嘿。基本上,这会将值 Empty 的 Variant 写入范围内的所有单元格;在这种情况下,范围是整个工作表,从而使所有单元格Empty。我想我会试一试,果然,它奏效了。
  • :) 我的直觉是这种方法与清除过滤的内容相同。添加到魔术 VBA 包的另一个技巧 - 它不断增长
  • 太棒了!这是一个优雅的解决方案。
  • @Jean-FrançoisCorbett,很抱歉取消检查您的答案,但我发现您的方法存在问题。请参阅上面的编辑。
  • @sigil:见编辑。这几乎是一个单独的问题,可能应该作为一个单独的问题发布。
【解决方案2】:

好的,我有一个解决方案。基本上,我在变量数组中记录自动过滤条件,然后删除自动过滤设置,填充工作表(使用@Jean-FrançoisCorbett 对sht.Cells.Value = Empty 的建议),然后重新应用数组中的设置。代码如下:

Sub reapplyAutofilter()

Dim fltr As Filter
Dim columnCriteria1() As Variant
Dim columnCriteria2() As Variant
Dim columnOperators() As Variant

Dim filterCriteria() As Variant
Dim sht As Worksheet
Dim rangeAddr As String
Dim fieldCount As Long
Dim ctr As Long



Set sht = ThisWorkbook.Sheets("mySheet")

'don't analyze autofilter if it's not on
If Not sht.AutoFilterMode Then              
    populateSheet
    Exit Sub
End If


'put autofilter settings in arrays for criteria1, criteria2, and operator    
With sht.AutoFilter
    rangeAddr = .Range.Address                 
    fieldCount = .Filters.Count
    ReDim columnCriteria1(1 To fieldCount)
    ReDim columnCriteria2(1 To fieldCount)
    ReDim columnOperators(1 To fieldCount)
    For ctr = 1 To fieldCount
        With .Filters(ctr)
            If .On Then
                columnCriteria1(ctr) = .Criteria1
                columnOperators(ctr) = .Operator
                If (.Operator = xlOr) or (.Operator=xlAnd) Then
                    columnCriteria2(ctr) = .Criteria2
                Else
                    columnCriteria2(ctr) = Null
                End If
            Else
                columnCriteria1(ctr) = Null
            End If
        End With
    Next ctr
End With

'clear autofilter     
sht.AutoFilterMode = False

populateSheet


're-apply autofilter settings    
With sht.Range(rangeAddr)
    For ctr = 1 To fieldCount
        If Not IsNull(columnCriteria1(ctr)) Then
            If IsNull(columnCriteria2(ctr)) Then
                .AutoFilter Field:=ctr, Criteria1:=columnCriteria1(ctr), Operator:=xlFilterValues
            Else
                .AutoFilter Field:=ctr, Criteria1:=columnCriteria1(ctr), Criteria2:=columnCriteria2(ctr), Operator:=columnOperators(ctr)
            End If
        End If
    Next
End With


End Sub

我不确定这是否算作我解决了问题,因为我受到了 Jean-FrançoisCorbett 的代码的启发。我确实必须自己弄清楚如何捕获和重新应用自动过滤器设置。随意插话谁应该得到这个荣誉;否则,我会接受我自己的答案。

【讨论】:

    猜你喜欢
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多