#excel #vba #autofilter
Вопрос:
Я использую автофильтр для уменьшения диапазона данных на основе определенных критериев. Как только фильтр будет применен, у меня может быть что угодно от 100 до 1000 строк. Я знаю, что до запуска фильтра я захочу скопировать определенное количество строк из этого отфильтрованного списка — часто это небольшое число, например, 3, 4 или 5. Я сохраняю это число в переменной под названием SELECTIONS. Чего я изо всех сил пытаюсь добиться, так это скопировать это количество строк из отфильтрованных данных. Я пробовал различные подходы, но ни один из них, похоже, не позволяет мне копировать нужные строки.
Вот мой код ниже:
'Define how many selections are required Dim selections As Integer selections = Sheets("MO Systems").Range("Q2").Value Dim LastRow, SelectRow As Long 'Defines sheet and row where we will paste data SelectRow = Sheets("Selections").Range("A165536").End(xlUp).Row 1 'Remove any autofilter than had previously been applied Sheets("Overs Assessment").Select If (ActiveSheet.AutoFilterMode And ActiveSheet.FilterMode) Or ActiveSheet.FilterMode Then ActiveSheet.ShowAllData End If 'Apply Filters 'Filter 1 Sheets("Overs Assessment").Range("$A$1:$FW$50881").AutoFilter Field:=3, Criteria1:="gt;1.0" 'Filter 2 Sheets("Overs Assessment").Range("$A$1:$FW$50881").AutoFilter Field:=50, Criteria1:="gt;=3.9", Operator:=xlAnd, Criteria2:="lt;=7" 'Filter 3 Sheets("Overs Assessment").Range("$A$1:$FW$50881").AutoFilter Field:=37, Criteria1:="gt;1.79", Operator:=xlAnd 'Filter 4 Sheets("Overs Assessment").Range("$A$1:$FW$50881").AutoFilter Field:=58, Criteria1:="gt;=4.54", Operator:=xlAnd, Criteria2:="lt;=11.99" 'Date Filter Sheets("Overs Assessment").Range("$A$1:$FW$50881").AutoFilter Field:=1, Criteria1:=Sheets("MO Systems").Range("F2").Value 'If there is only one selection, I can copy the lastrow and this is simple If selections = 1 Then LastRow = Sheets("Overs Assessment").Cells(1, 1).SpecialCells(xlCellTypeVisible).End(xlDown).Row Sheets("Overs Assessment").Range("A" amp; LastRow amp; ":E" amp; LastRow).Copy Sheets("Selections").Range("A" amp; SelectRow).PasteSpecial xlValues Else 'If selections gt; 1, this is where I cannot seem to find a solution to copy the relevant cells. End If
Комментарии:
1. Возможно, было бы проще скопировать всю партию, а затем удалить ненужные фрагменты. В противном случае вам придется создать диапазон, так как отфильтрованные ячейки, вероятно, не являются смежными.
Ответ №1:
Выполните итерацию в обратном направлении по областям и строкам несмежного отфильтрованного диапазона и заполните массив номерами строк.
Option Explicit Sub CopyEnd() 'Define how many selections are required Dim selections As Integer Dim wsSrc As Worksheet, wsDest As Worksheet Dim rngFilter As Range, rngCopy Dim LastRow As Long, destRow As Long selections = Sheets("MO Systems").Range("Q2").Value 'Defines sheet and row where we will paste data Set wsDest = Sheets("Selections") With wsDest destRow = .Cells(.Rows.Count, 1).End(xlUp).Row 1 End With Set wsSrc = Sheets("Overs Assessment") With wsSrc ' set filter range LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row Set rngFilter = .Range("A1:V" amp; LastRow) 'Remove any autofilter than had previously been applied If (.AutoFilterMode And .FilterMode) Or .FilterMode Then .ShowAllData End If 'Apply Filters With rngFilter 'Filter 1,3,3,4,Date .AutoFilter .AutoFilter Field:=3, Criteria1:="gt;1.0" .AutoFilter Field:=50, Criteria1:="gt;=3.9", Operator:=xlAnd, Criteria2:="lt;=7" .AutoFilter Field:=37, Criteria1:="gt;1.79" .AutoFilter Field:=58, Criteria1:="gt;=4.54", Operator:=xlAnd, Criteria2:="lt;=11.99" .AutoFilter Field:=1, Criteria1:=Sheets("MO Systems").Range("F2").Value ' rng to copy Set rngCopy = .SpecialCells(xlCellTypeVisible) MsgBox "Filter Range is " amp; rngCopy.Address '.AutoFilter ' remove filters End With ' fill array with row numbers of last n rows Dim i As Long, k As Long, n As Long, a, r, ar n = selections ReDim ar(1 To n) For a = rngCopy.Areas.Count To 1 Step -1 If i = n Then Exit For For r = rngCopy.Areas(a).Rows.Count To 1 Step -1 If a gt; 1 Or r gt; 1 Then ' exclude header i = i 1 ar(i) = rngCopy.Areas(a).Rows(r).Row End If If i = n Then Exit For Next Next ' copy rows MsgBox i amp; " rows " amp; Join(ar, ":") For k = i To 1 Step -1 wsDest.Cells(destRow, 1).Resize(, 5).Value2 = .Cells(ar(k), 1).Resize(, 5).Value2 destRow = destRow 1 Next End With MsgBox "Done" End Sub
Ответ №2:
Один из способов… (отрегулируйте диапазоны и листы в соответствии с требованиями)
Sub test() Dim selections As Long Dim cntRows As Long, i As Long, iRow As Long, iArea As Long Dim rngFilter As Range Dim rngSource As Range Dim rngDest As Range Dim rArea As Range selections = 10 Set rngFilter = Worksheets("Sheet1").Range("A2:B11") ' ("A2:FW50881") Set rngSource = rngFilter.SpecialCells(xlCellTypeVisible) ' probably a multi area range For Each rArea In rngSource.Areas cntRows = cntRows rArea.Rows.Count ' count filtered rows Next If cntRows lt; selections Then selections = cntRows ' Set rngDest = Worksheets("Sheet2").Range("A1:B" amp; selections) i = selections For iArea = rngSource.Areas.Count To 1 Step -1 Set rArea = rngSource.Areas(iArea) For iRow = rArea.Rows.Count To 1 Step -1 rngDest.Rows(i).Value = rArea.Rows(iRow).Value ' if need row formats copy/paste i = i - 1 If i = 0 Then Exit For Next If i = 0 Then Exit For Next End Sub
Если смежные строки, скорее всего, находятся в отфильтрованном диапазоне, быстрее копируйте соответствующие области, однако немного больше занимайтесь домашним хозяйством.
Комментарии:
1. Не видел, что уже был ответ, когда я написал!
Ответ №3:
Еще один подход: добавьте все видимые ячейки в ColA в коллекцию, а затем используйте эту коллекцию для выбора строк для копирования.
Sub Tester() Dim wsOvers As Worksheet, c As Range Dim selections As Long 'lt;lt;lt;lt; always prefer Long to Integer Dim LastRow As Long, PasteCell As Range, rngVis As Range, n As Long Dim col As New Collection, i As Long selections = Sheets("MO Systems").Range("Q2").Value Set PasteCell = Sheets("Selections").Cells(Rows.Count, "A").End(xlUp).Offset(1, 0) Set wsOvers = Sheets("Overs Assessment") With wsOvers If (.AutoFilterMode And .FilterMode) Or .FilterMode Then .ShowAllData With .Range("$A$1:$FW$50881") .AutoFilter Field:=3, Criteria1:="gt;1.0" .AutoFilter Field:=50, Criteria1:="gt;=3.9", Operator:=xlAnd, Criteria2:="lt;=7" .AutoFilter Field:=37, Criteria1:="gt;1.79", Operator:=xlAnd .AutoFilter Field:=58, Criteria1:="gt;=4.54", Operator:=xlAnd, Criteria2:="lt;=11.99" .AutoFilter Field:=1, Criteria1:=Sheets("MO Systems").Range("F2").Value Set rngVis = .SpecialCells(xlCellTypeVisible) End With End With n = 0 For Each c In rngVis.Columns(1).Cells 'loop over all visible cells in ColA n = n 1 ' and add them to a collection If n gt; 1 Then col.Add c '...skipping the header Next c 'now copy the selected last # of rows For n = 1 To selections i = col.Count - (n - 1) 'collection index If i lt; 1 Then Exit For 'not enough items in the collection PasteCell.Resize(1, 5).Value = col(i).Resize(1, 5).Value Set PasteCell = PasteCell.Offset(1) 'next row down Next n End Sub