Reputation: 2300
I am trying to get a filtered range into an array, on my test data the array fArr has the proper dim and fLR is the proper count of the filter range
But filRange is always only the header range NOT the filtered range
How to get filRange to be the filtered range?
Or to the point how to get fArr to be an array of the filter data?
Thanks
Sub arrFilterdRng()
Dim fArr As Variant
Dim rRange As Range, filRange As Range, myCell As Range
Dim fLR As Long, rCtr As Long
'Remove any filters
ActiveSheet.AutoFilterMode = False
'~~> Set your range
Set rRange = Sheets("Z").UsedRange
With rRange
'~~> Set your criteria and filter
.AutoFilter Field:=3, Criteria1:="*"
Set filRange = .SpecialCells(xlCellTypeVisible).EntireRow
fLR = .Resize(, 1).SpecialCells(xlCellTypeVisible).Count
Debug.Print fLR
ReDim fArr(1 To fLR, 1 To .Columns.Count)
Debug.Print UBound(fArr, 1), UBound(fArr, 2)
rCtr = 0
For Each myCell In filRange.Columns(1)
rCtr = rCtr + 1
For cCtr = 1 To .Columns.Count
fArr(rCtr, cCtr) = myCell.Offset(0, cCtr - 1).value
Next cCtr
Next myCell
End With
'Remove any filters
ActiveSheet.AutoFilterMode = False
End Sub
My data looks like this (all text)
Upvotes: 1
Views: 7543
Reputation: 4977
My feeling is that the wildcard in your criteria is causing the trouble.
"*" only works for strings, so if your data are numbers (including dates) then they would be removed by the filter (ie they wouldn't be visible), so you would indeed only have the header in your range.
If you want numerical values, then one way of doing it would be to define a value, say:
.AutoFilter Field:=3, Criteria1:=">0"
or, if you want limits:
.AutoFilter Field:=3, Criteria1:=">0", Operator:=xlAnd, Criteria2:="<10"
If, on the other hand, you just want anything but blank cells, then the syntax should be:
.AutoFilter Field:=3, Criteria1:="<>"
You should also be aware that if the filtered range contains non-contiguous ranges, then each 'separate' range would be contained within the Areas
collection. This means something like filRange.Rows.Count
would only return the row count of the first area; and you can get real difficulties when you try to Offset
and/or Resize
the filtered range. It's also not possible to directly read non-contiguous ranges into an array using the .Value
property.
I'm not sure your code is the most efficient way of handling your task, but keeping the same structure it could look like this:
Dim rRange As Range, filRange As Range
Dim myArea As Range, myRow As Range, myCell As Range
Dim fArr() As Variant
Dim r As Long
With ThisWorkbook.Worksheets("Z")
.AutoFilterMode = False
Set rRange = .UsedRange
End With
With rRange
.AutoFilter Field:=3, Criteria1:=">0"
Set filRange = .SpecialCells(xlCellTypeVisible)
End With
With filRange
r = -1 'start at -1 to remove heading row
For Each myArea In filRange.Areas
r = r + myArea.Rows.Count
Next
ReDim fArr(1 To r, 1 To .Columns.Count)
End With
r = 1
For Each myArea In filRange.Areas
For Each myRow In myArea.Rows
If myRow.Row <> 1 Then
For Each myCell In myRow.Cells
fArr(r, myCell.Column) = myCell.Value
Next
r = r + 1
End If
Next
Next
Upvotes: 2
Reputation: 19319
Perhaps your data has more complexity, but you can simply assign the values of a range to an array with:
var = rng.SpecialCells(xlCellTypeVisible).Value
Thus no need to loop over the data.
Here's a working example with this simple grid of data:
This code:
Option Explicit
Sub arrFilterdRng()
Dim ws As Worksheet '<-- your worksheet
Dim rng As Range '<-- your range to filter
Dim var As Variant '<-- will hold array of visible data
Dim lng1 As Long, lng2 As Long
' get sheet; remove filters
Set ws = ThisWorkbook.Worksheets("Sheet2")
ws.AutoFilterMode = False
' get range; apply filter
Set rng = ws.UsedRange
rng.AutoFilter Field:=1, Criteria1:="x"
' assign visible range to array
var = rng.SpecialCells(xlCellTypeVisible).Value
' test array
For lng1 = LBound(var, 1) To UBound(var, 1)
For lng2 = LBound(var, 2) To UBound(var, 2)
Debug.Print var(lng1, lng2)
Next lng2
Next lng1
End Sub
Results in this on the sheet:
And the output to the Immediate window for the content of var
is:
a
b
c
x
2
3
x
5
6
Upvotes: 0