очистить ячейки при сохранении настроек автофильтра? - PullRequest
1 голос
/ 29 ноября 2011

Я пишу скрипт для рабочего листа, ячейки которого заполняются на основе базы данных 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, он стирает автофильтр.Есть ли способ сохранить настройки автофильтра, чтобы новые данные были отфильтрованы таким же образом?Или, может быть, записать их и повторно применить те же настройки?Я пытался работать с этим решением , но у меня были проблемы с его определением, какие столбцы были отфильтрованы.

РЕДАКТИРОВАТЬ:

Я применил подход Жана-Франсуа Корбетта в приведенном выше коде, но у него есть проблема.Попробуйте сделать это с помощью тестовой таблицы:

1 a
2 b
3 a

После запуска populateSheet, а затем автофильтровать 2-й столбец, чтобы включить только «a», на рабочем листе отображается:

1 a
3 a

Затем выполнитеpopulateSheet снова, теперь лист показывает:

1 a
1 a

Если вы удалите автофильтр, повторно запустите populateSheet и повторно примените автофильтр, вы получите правильные данные, но это очень громоздкий дополнительный шагчтобы получить правильный вывод.

РЕДАКТИРОВАТЬ: я добавил код для создания базы данных и создать таблицу, которую вы можете использовать для проверки populateSheet, и изменил некоторые аргументы в populateSheet, чтобы отразить эту тестовую базу данных.

Ответы [ 2 ]

3 голосов
/ 29 ноября 2011

Если вы просто хотите очистить значения в ячейках и ничего больше, то вы можете сделать это:

sht.Cells.Value = Empty

РЕДАКТИРОВАТЬ Ответ на редактирование ОП:

Как ни странно, вышеприведенное утверждение не очищает ячейки в строках, которые были скрыты автофильтром!Я думаю, что скрытые автофильтром строки также вызывают неожиданное поведение при импорте данных с 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 голосов
/ 08 декабря 2011

Хорошо, у меня есть решение для этого. По сути, я записываю критерии автофильтрации в массиве вариантов, затем удаляю настройки автофильтра, заполняю лист (используя предложение @ 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

Я не уверен, считается ли это решением меня, потому что я был вдохновлен кодом Жана-Франсуа Корбетта. Мне пришлось самостоятельно выяснить, как перехватить и повторно применить настройки автофильтра. Не стесняйтесь сообщать о том, кто должен получить кредит на этом; в противном случае я приму свой ответ.

...