2011-11-29 26 views
1

我正在为其单元格基于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,但我无法检测哪些列被过滤。

编辑:

我申请让FrançoisCorbett的方法在上面的代码,但它有一个问题。用测试表试试这个:

1 a 
2 b 
3 a 

运行populateSheet后,再自动筛选第2列,只包括“A”,在工作表中显示:

1 a 
3 a 

然后现在再次运行populateSheet,板材显示:

1 a 
1 a 

如果删除自动筛选,重新运行populateSheet,并重新申请自动筛选,你会得到正确的数据,但是这是一个非常繁琐的额外步骤来获得正确的输出。

编辑: 我添加的代码创建一个数据库,让你可以用它来测试populateSheet表,并改变了一些参数在populateSheet以反映此测试数据库。

+0

而不是.Clear你试过.ClearContents? –

+0

@TimWilliams,这仍然会清除AutoFilter。 sigil,你在用什么Excel版本? – brettdj

回答

0

好的,我有一个解决方案。基本上,我将自动筛选条件记录在一系列变体中,然后删除自动筛选设置,填充工作表(使用@ 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的代码启发。我必须自己弄清楚如何捕获和重新应用Autofilter设置。请随时关注谁应该获得这个奖项的信誉;否则,我会接受我自己的答案。

3

如果你只是想清除的细胞,没有别的值,那么你可以这样做:

sht.Cells.Value = Empty 

编辑为了响应OP的编辑:

奇怪的是,声明上面不会清空由Autofilter隐藏的任何行中的单元格!我认为在使用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 
+0

+1有点惊讶这工作 - 但它的工作 – brettdj

+0

嘿嘿。基本上,这会向值范围内的所有单元格写入“空值”的变体;在这种情况下,范围是整个工作表,从而使所有单元格为“空”。我想我会试一试,果然,它的工作。 –

+0

:)我的直觉是这种方法会做同样的清除内容也擦拭过滤。魔术VBA包的另一个诀窍 - 它不断增长的 – brettdj