I have a problem using my autofilter. I need to filter sever values at a time.
I have the list of values on first sheet (column I2:I50) and on the second sheet I would need to filter all these values from database.
My code so far is:
Dim OZ As Variant
OZ = Array("100001", "100015")
Sheets("Sheet2").Select
Range("A1:M1").AutoFilter Field:=3, Criteria1:=OZ, _
Operator:=xlFilterValues
This works perfectly so far. Now I am strugeling to setup the macro in a way, so the array refers to the Range of Sheet1 and I2:I50. Values in this range are variables calculated by functions.
Can you please help me with that?.
Thanks
This For would set your OZ variable with all the 49 values from Sheet1
'You need 49 values I2:I50
Dim OZ(49) As Variant
For i = 0 To 48
'1st data row starts at I2, hence + 2
OZ(i) = "=" & Worksheets("Sheet1").Range("I" & i + 2).Value
Next i
Worksheets("Sheet2").Range("A1:M1").AutoFilter Field:=3, Criteria1:=OZ, Operator:=xlFilterValues
you could use Join() and Split() functions to return a Variant array compatible for Criteria1
Dim OZ As Variant
OZ = Split(Join(Application.Transpose(Worksheets("Sheet1").Range("I2:I50").Value), "|"), "|")
Worksheets("Sheet2").Select
Range("A1:M1").AutoFilter Field:=3, _
Criteria1:=OZ, _
Operator:=xlFilterValues
but you should avoid the Select/Selection/Activate/ActiveXXX pattern and use explicitly fully qualified range references
Worksheets("Sheet2").Range("A1:M1").AutoFilter Field:=3, _
Criteria1:=Split(Join(Application.Transpose(Worksheets("Sheet1").Range("I2:I50").Value), "|"), "|"), _
Operator:=xlFilterValues
i think that advanced filter will do the job.
Sub ExampleCopy()
Sheets("Table").Range("A1:B7").AdvancedFilter Action:=xlFilterCopy, _
CriteriaRange:=Sheets("Cryteria").Range("A1:15"), _
CopyToRange:=Sheets("Result").Range("A1"), _
Unique:=False
Sheets("Result").Select
End Sub
'OR
Sub ExampleInPlace()
Sheets("Table").Range("A1:A11").AdvancedFilter Action:=xlFilterInPlace _
, CriteriaRange:=Sheets("Cryteria").Range("A1:A6"), Unique:=False
End Sub
The first one will copy result to a custom location. In this case to Sheet "Result" cell A1.
The second one will filter in place so in sheet "Table"
Bear in mind that in order for this to work your cryteria column header has to be the same as the data table column.
You can aslo try recording this macro using "advanced" from ribbon tab "DATA" section "Sort&filter".
Good luck.
The range can be evaluated to an array:
[Sheet2!A1:M1].AutoFilter 3, [transpose(text(Sheet1!I2:I50, "#"))], xlFilterValues
Related
I'm trying to use the AutoFilter function in VBA.
I have cells in this column filled with values that start with a value that I want to filter on like "pathogenic", "polymorfism", "VUS",... but ends with some more text that I don't want to use in the filter.
e.g.
variant
class
V600E
pathogenic variant - BRAF
V590A
VUS - D1234567
G12D
pathogenic variant - KRAS
G15A
polymorfism
A56D
polymorfism - KFP
E4654M
presumably pathogenic variant
In this case I want to filter all rows where the class starts with "pathogenic variant","VUS" and "presumably pathogenic variant", in the example row 1-3 and row 6.
I found a way to use the autofilter for 2 values:
ActiveSheet.Range("$A$2:$BB$550").AutoFilter _
Field:=17, _
Criteria1:=("=patho*"), _
Operator:=xlOr, _
Criteria2:=("=VUS*"), _
Operator:=xlFilterValues
I can't use more then 2 criteria. When I use the following code the filtering doesn't work.
ActiveSheet.Range("$A$2:$BB$550").AutoFilter _
Field:=17, _
Criteria1:=Array("=patho*", "=VUS*", "=presumably patho*"), _
Operator:=xlFilterValues
You can use Advanced Filter.
Columns A and B: Your range
Column D: Criteria
Column F and G: Extract
You you want to Filter in Place instead of using Copy uncomment the last line.
Sub AdvFilter()
Dim yourRange As Range
Dim criteriaRange As Range
Dim extractRange As Range
Set yourRange = Range("A1:B25")
Set criteriaRange = Range("D1:D4")
Set extractRange = Range("F1:G1")
' Advanced filter: Copy
yourRange.AdvancedFilter Action:=xlFilterCopy, criteriaRange:=criteriaRange, CopyToRange:=extractRange, Unique:=False
' Advanced filter: Filter in Place
'yourRange.AdvancedFilter Action:=xlFilterInPlace, criteriaRange:=criteriaRange, CopyToRange:=extractRange, Unique:=False
End Sub
I have following code in which I have tried to applied 3 filters, now what I want is, to apply this filter criteria based on named range
I have stored relevant value in specific cell and given names to that range
for first criteria i.e. >=200 named range is VOLUME
for second criteria i.e. >=0.07 named range is MOVE
for third criteria i.e. >=400 named range is STRENTH
So what are the changes that I need to make in following code?
Sub FILTER2()
'FILTER CRITERIA
ActiveSheet.Range("$A$2:$AC$500").AutoFilter Field:=6, Criteria1:=">=200", _
Operator:=xlAnd
ActiveSheet.Range("$A$2:$AC$500").AutoFilter Field:=21, Criteria1:=">=0.07" _
, Operator:=xlAnd
ActiveSheet.Range("$A$2:$AC$500").AutoFilter Field:=28, Criteria1:=">=400" _
, Operator:=xlAnd
Range("A1").Select
End Sub
As per my comment, you might want to consider a With statement, better not to refer to ActiveSheet
Sub FILTER2()
With Sheet1 'Change according to your sheets CodeName
.Range("$A$2:$AC$500").AutoFilter 6, ">=" & .Range("VOLUME")
.Range("$A$2:$AC$500").AutoFilter 21, ">=" & .Range("MOVE")
.Range("$A$2:$AC$500").AutoFilter 28, ">=" & .Range("STRENTH")
End With
End Sub
you can try defining a variable to contain the value of your named range.
Named Range in your sheet as "Volume" then i can store that value in var namedRange1.
example below:
Sub FILTER2()
namedRange1 = range("Volume")
'FILTER CRITERIA
ActiveSheet.range("$A$2:$AC$500").AutoFilter Field:=6, Criteria1:=">=" & namedRange1, _
Operator:=xlAnd
....same with the other lines, just define new variable to contain new named range
I have Excel file that I want to filter about one column and on another column add specific value
Sub Macro1()
'
' Macro1
'
'
Range("Table1[type phone]").Select
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:= _
"=*samsung*", Operator:=xlAnd
Range("Table1[company]").Select
'Here I want to add the specific value "Samsung"'
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:= _
"=*iphone*", Operator:=xlAnd
Range("Table1[company]").Select
'Here I want to add the specific value "Apple"'
End Sub
Also how can I filter about one column Blanks cells and on another column add specific value "other"?
[
What conditions can be written if, for example, the Samsung Devices table is missing?
Because if I run the code it crashes in the line it is looking for Samsung.
How can I do it?
Thank You for helping!
To change the value of only cells that are visible (aka those that are show in the filter) you can use SpecialCells(xlCellTypeVisible)
So for your example the code that would go in the first break would be
"Range("B2:B18").SpecialCells(xlCellTypeVisible).Value= "Samsung"
and the second break
"Range("B2:B18").SpecialCells(xlCellTypeVisible).Value= "Apple"
You need to change "18" to whatever the last row is. (Or you can define a variable called LastRow and then call that instead of hard-coding the number which means it will dynamically change based on how many rows there are.)
With LastRow
Sub Macro1()
Dim LastRow As Long
LastRow = ActiveSheet.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
Range("Table1[type phone]").Select
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:= _
"=*samsung*", Operator:=xlAnd
Range("Table1[company]").Select
Range("B2:B" & LastRow).SpecialCells(xlCellTypeVisible).Value= "Samsung"
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:= _
"=*iphone*", Operator:=xlAnd
Range("Table1[company]").Select
Range("B2:B" & LastRow).SpecialCells(xlCellTypeVisible).Value= "Apple"
End Sub
We created a new variable called LastRow and defined it as long (A type of number). Then we defined LastRow according to a formula I use from this site:
https://www.thespreadsheetguru.com/blog/2014/7/7/5-different-ways-to-find-the-last-row-or-last-column-using-vba
Finally we replace Range("B2:B18") with Range("B2:B" & LastRow) which dynamically replaces the 18 with the number LastRow.
I have a large data sheet that I want to search in VBA based on 3 sets of criteria. Each row entry can be assumed to be unique. The format of the sheet/data itself cannot be changed due to requirements. (I've seen several posts on related questions but haven't found a working solution for this yet.)
At first I used the classic VBA find method in a loop:
Set foundItem = itemRange.Find(What:=itemName, Lookin:=xlValues, lookat:=xlWhole, SearchOrder:=xlByRows)
If Not foundItem Is Nothing Then
firstMatchAddr = foundItem.Address
Do
' *Check the other fields in this row for a match and exit if found*
Set foundItem = itemRange.FindNext(foundItem)
Loop While foundItem.Address <> firstMatchAddr And Not foundItem Is Nothing
End If
But because this needs to be called a number of times on large sets of data, the speed of this was no good.
I did some searching and found that I could use the match method with index. So I unsuccessfully tried many variations of that such as:
result = Evaluate("=MATCH(1, (""" & criteria1Name & """=A2:A" & lastRow & ")*(""" & criteria2Name & """=B2:B" & lastRow & ")*(""" & criteria3Name & """=C2:C" & lastRow & "), 0)")
And
result = Application.WorksheetFunction.Index(resultRange, Application.WorksheetFunction.Match((criteria1Name = criteria1Range)*(criteria2Name = criteria2Range)*(criteria3Name = criteria3Range))
And
result = Application.WorksheetFunction.Index(resultRange, Application.WorksheetFunction.Match((criteria1Range=criteria1Name )*(criteria2Range=criteria2Name )*(criteria3Range=criteria3Name ))
Then I tried using AutoFilter to sort:
.Range(.Cells(1,1), .Cells(lastRow, lastCol)).AutoFilter Field:=1, Criteria1:="=" & criteria1Name
.Range(.Cells(1,1), .Cells(lastRow, lastCol)).AutoFilter Field:=2, Criteria1:="=" & criteria2Name
.Range(.Cells(1,1), .Cells(lastRow, lastCol)).AutoFilter Field:=3, Criteria1:="=" & criteria3Name
But because one of the sorting columns contains dates, I had issues getting AutoFilter to work properly.
My question is, how can I search through columns in Excel VBA based on multiple criteria, without looping, returning either the row number or the value in the cell of that row that I am interested in?
You could use an Advanced Filter. Put the column headers in a separate part of the sheet (or a different sheet altogether). Under those column headers, put the criteria you're looking for in each column. Then name that range (including the headers) something like "Criteria". Then the macro becomes:
Sub Macro1()
Sheets("Sheet1").Range("A1").CurrentRegion.AdvancedFilter xlFilterInPlace, Range("Criteria")
End Sub
As a follow up to my comment below, to have the VBA create the criteria range behind the scenes:
Sub Macro1()
'Code up here that defines the criteria
Application.ScreenUpdating = False
Application.DisplayAlerts = False
With Sheets.Add
'Create the advanced filter criteria range
.Range("A1") = "HeaderA"
.Range("B1") = "HeaderB"
.Range("C1") = "HeaderC"
.Range("A2") = criteria1Name
.Range("B2") = criteria2Name
.Range("C2") = criteria3Name
'Alternately, to save space:
'.Range("A1:C1").Value = Array("HeaderA", "HeaderB", "HeaderC")
'.Range("A2:C2").Value = Array(criteria1Name, criteria2Name, criteria3Name)
'Then perform the advanced filter
Sheets("Sheet1").Range("A1").CurrentRegion.AdvancedFilter xlFilterInPlace, .Range("A1:C2")
'Remove behind the scenes sheet now that the filter is completed
.Delete
End With
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
You can use EVALUATE for multiple criteria like so to return the row numbers of mathcing values. This uses the same approach as Is it possible to fill an array with row numbers which match a certain criteria without looping?
It searches 50000 rows to match
the first four letters in column A matches fred
the date in B to be greater than 1/1/2001
apple in column 5
Any rows matching these criteria are retuned as row numbers in x
(rows 1 and 5 in picture below)
code
Sub GetEm2()
x = Filter(Application.Transpose(Application.Evaluate("=IF((LEFT(A1:A10000,4)=""fred"")*(B1:B10000>date(2001,1,1))*(C1:C10000=""apple""),ROW(A1:A10000),""x"")")), "x", False)
End Sub
Application.Transpose is limited to 65536 cells, so a longer range needs to be "chunked" into pieces.
I have a big database-like sheet, first row contains headers. I would like a subset of rows of this table based on column values. Two issues:
1) VBA-wise I would like to loop through the columns, when the values for all necessary columns all match, copy the entire row into a new sheet.
2) The subset of rows is based on a list. I just read I can use Autofilter with an array. Is it possible to input this array from a column instead of manually entering it in the VBA code? The list I'm using consists of 200 different strings and will be updated periodically.
Where CritList is the list of strings. I still need to figure out how, but now I leave the office, so more tomorrow.
EDIT1 Thanks to #DougGlancy; the autofiltering works now. Here is his beautiful code (I only added the array-filter).
EDIT2 Included a more elaborate array-filter, where NameList is the list I would like to filter for. Now it all works!
Sub FilterAndCopy()
Dim LastRow As Long
Dim vName As Variant
Dim rngName As Range
Set rngName = Sheets("Sheet3").Range("NameList")
vName = rngName.Value
Sheets("Sheet2").UsedRange.Offset(0).ClearContents
With Worksheets("Sheet1")
.Range("A:E").AutoFilter
'Array filter from NameList
.Range("A:J").AutoFilter Field:=3, Criteria1:=Application.Transpose(vName), _
Operator:=xlFilterValues
.Range("A:E").AutoFilter field:=2, Criteria1:="=String1" _
, Operator:=xlOr, Criteria2:="=string2"
.Range("A:E").AutoFilter field:=3, Criteria1:=">0", _
.Range("A:E").AutoFilter field:=5, Criteria1:="Number"
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
.Range("A1:A" & LastRow).SpecialCells(xlCellTypeVisible).EntireRow.Copy _
Destination:=Sheets("Sheet2").Range("A1")
End With
End Sub
Here's a different approach. The heart of it was created by turning on the Macro Recorder and filtering the columns per your specifications. Then there's a bit of code to copy the results. It will run faster than looping through each row and column:
Sub FilterAndCopy()
Dim LastRow As Long
Sheets("Sheet2").UsedRange.Offset(0).ClearContents
With Worksheets("Sheet1")
.Range("$A:$E").AutoFilter
.Range("$A:$E").AutoFilter field:=1, Criteria1:="#N/A"
.Range("$A:$E").AutoFilter field:=2, Criteria1:="=String1", Operator:=xlOr, Criteria2:="=string2"
.Range("$A:$E").AutoFilter field:=3, Criteria1:=">0"
.Range("$A:$E").AutoFilter field:=5, Criteria1:="Number"
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
.Range("A1:A" & LastRow).SpecialCells(xlCellTypeVisible).EntireRow.Copy _
Destination:=Sheets("Sheet2").Range("A1")
End With
End Sub
As a side note, your code has more loops and counter variables than necessary. You wouldn't need to loop through the columns, just through the rows. You'd then check the various cells of interest in that row, much like you did.