Retrieve multiple values associated with single ID in excel - vba

I'm curious if there is a simpler solution out there with respect to retrieving values associated with a single ID in excel.
I have explored the INDEX solution to look up multiple values in a list but that is not really dynamic and gives you the result in a vertical order rather than the horizontal order that I required. (see Results desired below)
The sample function i used was this
"=IF(ISERROR(SMALL(IF(IF(ISERROR(SEARCH($A$9,$A$1:$A$7)),FALSE,TRUE),ROW($A$1:$A$7)),ROW($C$1:$C$7))),"",INDEX($A$1:$C$7,SMALL(IF(IF(ISERROR(SEARCH($A$9,$A$1:$A$7)),FALSE,TRUE),ROW($A$1:$A$7)),ROW($C$1:$C$7)),3))"
*Ignore the references for this example.
I have two sheets that I'm working on and basically need to retrieve the values associated with a single ID from "Numbers Sheet" and store them on "Master Sheet" See images below for clearer explanation. The formula needs to find the subsequent number associated with the ID and put it on the subsequent column as shown below.
*note: any user ID can request for any number of tickets so it can range from 1-100 (just showing 3 as an example)
Appreciate any guidance from the excel masters here. The only other solution I can think of is to use a vba code to retrieve each value and store it in an array and then retrieve the value from the array. Let me know your thoughts!
Thanks in advance!
Master Sheet:
Numbers Sheet:
Results desired:

Put the following formula in cell C2[1] of your Master Sheet
{=IFERROR(INDEX(Numbers!$A:$C,SMALL(IF(Numbers!$A$1:$A$1000=$A2,ROW(Numbers!$A$1:$A$1000)),INT((COLUMN(A:A)-1)/2)+1),MOD(COLUMN(A:A)-1,2)+2),"")}
[1] I'm assuming it is row 2 since you have unfortunately not shown the row numbers.
The formula is an array formula. Input it into the cell without the curly brackets and confirm it with [Ctrl] + [Shift] + [Enter]. The curly brackets then will appear automatically.
Then fill the formula to right and downwards as needed.

you can try this code
Sub main()
Dim IdRng As Range, cell As Range, filtCell As Range
Dim i As Long
With Worksheets("Master Sheet")
Set IdRng = .Range("A1", .Cells(.Rows.Count, 1).End(xlUp)).SpecialCells(XlCellType.xlCellTypeConstants)
End With
With Worksheets("Numbers")
With .Cells(1, 1).CurrentRegion
For Each cell In IdRng
.AutoFilter field:=1, Criteria1:=cell.value '<--| filter it on current department value
If Application.WorksheetFunction.Subtotal(103, .Cells.Resize(, 1)) > 1 Then
For Each filtCell In .Offset(1, 1).Resize(.Rows.Count - 1, 1).SpecialCells(XlCellType.xlCellTypeVisible)
cell.End(xlToRight).Offset(, 1).Resize(, 2).value = filtCell.Resize(, 2).value
Next filtCell
End If
Next cell
End With
.AutoFilterMode = False
End With
With Worksheets("Master Sheet").Cells(1, 1).CurrentRegion.Rows(1)
.Insert
With .Offset(-1)
.Font.Bold = True
.Resize(, 2) = Array("ID", "Name")
For i = 1 To .Columns.Count - 2 Step 2
.Offset(, 1 + i).Resize(, 2) = Array("Description " & (i + 1) / 2, "Number " & (i + 1) / 2)
Next i
End With
End With
End Sub

VBA is probably a better route for this and using .Find and .FindNext is the way I would go.
Attached is a generic FindAll function, so you could look for all the cells containing the ID in question then process the cells one at a time.
Function FindAll(What, _
Optional SearchWhat As Variant, _
Optional LookIn, _
Optional LookAt, _
Optional SearchOrder, _
Optional SearchDirection As XlSearchDirection = xlNext, _
Optional MatchCase As Boolean = False, _
Optional MatchByte, _
Optional SearchFormat) As Range
'LookIn can be xlValues or xlFormulas, _
LookAt can be xlWhole or xlPart, _
SearchOrder can be xlByRows or xlByColumns, _
SearchDirection can be xlNext, xlPrevious, _
MatchCase, MatchByte, and SearchFormat can be True or False. _
Before using SearchFormat = True, specify the appropriate settings for the Application.FindFormat _
object; e.g. Application.FindFormat.NumberFormat = "General;-General;""-"""
Dim SrcRange As Range
If IsMissing(SearchWhat) Then
Set SrcRange = ActiveSheet.UsedRange
ElseIf TypeOf SearchWhat Is Range Then
Set SrcRange = IIf(SearchWhat.Cells.Count = 1, SearchWhat.Parent.UsedRange, SearchWhat)
ElseIf TypeOf SearchWhat Is Worksheet Then
Set SrcRange = SearchWhat.UsedRange
Else: Set SrcRange = ActiveSheet.UsedRange
End If
If SrcRange Is Nothing Then Exit Function
'get the first matching cell in the range first
With SrcRange.Areas(SrcRange.Areas.Count)
Dim FirstCell As Range: Set FirstCell = .Cells(.Cells.Count)
End With
Dim CurrRange As Range: Set CurrRange = SrcRange.Find(What:=What, After:=FirstCell, LookIn:=LookIn, LookAt:=LookAt, _
SearchDirection:=SearchDirection, MatchCase:=MatchCase, MatchByte:=MatchByte, SearchFormat:=SearchFormat)
If Not CurrRange Is Nothing Then
Set FindAll = CurrRange
Do
Set CurrRange = SrcRange.Find(What:=What, After:=CurrRange, LookIn:=LookIn, LookAt:=LookAt, _
SearchDirection:=SearchDirection, MatchCase:=MatchCase, MatchByte:=MatchByte, SearchFormat:=SearchFormat)
If CurrRange Is Nothing Then Exit Do
If Application.Intersect(FindAll, CurrRange) Is Nothing Then
Set FindAll = Application.Union(FindAll, CurrRange)
Else: Exit Do
End If
Loop
End If
End Function

Related

VBA Script to remove all lines other then my filtered values

I am currently in the process of creating a VBA Script where i extract a list of raw data and filter out values Apple, Banana, and Oranges. I then delete all the other rows if it is not the values mentioned above.
So for example i have apple, banana, orange, grape, mandarin, avocado, coconut, lemon, watermelon.
I only want to keep apple, banana and orange in the end. If it has any of the other fruits i want that whole row of information removed.
Sub RMWO_Clean()
Dim ws As Worksheet
Dim rng As Range
Dim lastRow As Long
Set ws = ActiveWorkbook.Sheets("Sheet1")
lastRow = ws.Range("Q" & ws.Rows.Count).End(xlUp).Row
Set rng = ws.Range("Q1:Q" & lastRow)
Columns("AF:AF").Select
Selection.TextToColumns Destination:=Range("AA1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=False, FieldInfo _
:=Array(1, 1), TrailingMinusNumbers:=True
With rng
.AutoFilter Field:=1,Criteria1:="<>*Apple*", Operator:=xlAnd, Criteria2:="<>*Banana*"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
ws.AutoFilterMode = False
End Sub
I know that you cannot use
Criteria3:=xx
I have also tried
Criteria1:=Array("<>Apple", "<>Banana", "<>Orange")
But this seems to only leave orange behind.
Are you able to let me know what i am doing wrong?
Criteria1:=Array("<>Apple", "<>Banana", "<>Orange") needs Operator:=xlFilterValues operator, and yet won't work with those "<>"
so you can fool it by thinking the other way around:
filter "good" records
delete all records that are not good
like follows:
With rng
.AutoFilter Field:=1, Criteria1:=Array("Apple", "Banana", "Orange"), Operator:=xlFilterValues
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0) ' reference 'records' only (skip headers)
Select Case Application.Subtotal(103, .Cells) ' count number of filtered cells
Case 0 'if no cells to save
.EntireRow.Delete ' delete all rows
Case Is < .Count 'if there's at least one row to delete
Set saveRng = .SpecialCells(xlCellTypeVisible) ' store cells to save
.Parent.AutoFilterMode = False 'remove filter
saveRng.EntireRow.Hidden = True 'hide cells to save
.SpecialCells(xlCellTypeVisible).EntireRow.Delete 'delete visible cells
saveRng.EntireRow.Hidden = False 'bring cells to save visible back
End Select
End With
.Parent.AutoFilterMode = False
End With
Starting with:
I run:
Dim myRange As Range
Set myRange = ActiveSheet.Range("$A$1:$A$4")
myRange.AutoFilter Field:=1, _
Criteria1:="<>*Banana*", Operator:=xlAnd, Criteria2:="<>*apple*"
...and I get:
...and then I run:
myRange.AutoFilter Field:=1
...and I get:
I can delete the non-filtered rows with:
Rows("2:7").Delete Shift:=xlUp
Putting it all together, you could do something like:
Sub DeleteRowsExceptApplesAndBananas()
Const startCell = "A1"
Dim rgFilter As Range
'get range to filter
With Sheets("Sheet1")
Set rgFilter = Range(.Range(startCell), .Range(startCell).End(xlDown))
'set filter
rgFilter.AutoFilter 1, "<>*Banana*", xlAnd, "<>*apple*"
'delete rows beginning one below startCell's row
Range(.Range(startCell).Offset(1).Row & ":" & _
.Range(startCell).End(xlDown).Row).Delete (xlUp)
'un-filter
rgFilter.AutoFilter 1
End With
End Sub
It doesn't seem to me that Range.AutoFilter will do what you want it to here, precisely because you can only use two criteria for it.
I'd personally prefer to solve this problem with a loop operation, like so:
Option Compare Text
Sub Macro1()
Dim ws As Worksheet
Dim rng As Range
Dim col As String
Dim i As Integer
Set ws = ActiveWorkbook.Sheets("Sheet1")
col = "A"
i = 1
Set rng = ws.Range(col & i)
Do
Select Case rng.FormulaR1C1
Case "apple", "orange", "banana"
i = i + 1
Case Else
rng.Delete xlShiftUp
End Select
Set rng = ws.Range(col & i)
Loop Until rng.FormulaR1C1 = ""
End Sub
The code above assumes that you've already done all the preprocessing you've needed to do to extract your list of fruits, and that that list begins in cell A1 of Sheet1, although you can of course modify that code to put the list anywhere you'd like.
Version 1 bellow uses a "reverse" AutoFilter
Version 2, moves all rows to keep to a new sheet, and deletes the old (very fast for a lot of rows)
.
Version 1
Option Explicit
Public Sub DeleteRowsForCriteria()
Const FILTER_COL = "Q"
Const To_KEP = "apple banana orange"
Dim ws As Worksheet, lr As Long
Set ws = Sheet1 'Or: Set ws = ThisWorkbook.Worksheets("Sheet1")
lr = ws.Cells(ws.Rows.Count, FILTER_COL).End(xlUp).Row
Application.ScreenUpdating = False
ws.Range("AF1:AF" & lr).TextToColumns Destination:=ws.Range("AA1"), _
TextQualifier:=xlDoubleQuote, _
FieldInfo:=Array(1, 1), _
TrailingMinusNumbers:=True
Dim filterCol As Range, toKep As Variant, keep As Range
Set filterCol = ws.Range("Q1:Q" & lr)
toKep = Split(To_KEP)
With filterCol 'Reverse Filter - show all rows to keep ("apple banana orange")
.AutoFilter Field:=1, Criteria1:=toKep, Operator:=xlFilterValues
If .SpecialCells(xlCellTypeVisible).Count > 1 Then
Set keep = .SpecialCells(xlCellTypeVisible).EntireRow
End If
.AutoFilter 'Unhide all rows
keep.Rows.Hidden = True 'Hide all rows to keep ("apple banana orange")
.SpecialCells(xlCellTypeVisible).EntireRow.Delete 'Delete unwanted (now visible)
End With
keep.Rows.Hidden = False 'Unhide rows to keep ("apple banana orange")
Application.ScreenUpdating = True
End Sub
.
Version 2
Public Sub DeleteRowsForCriteriaFast()
Const FILTER_COL = "Q"
Const To_KEP = "apple banana orange"
Dim ws1 As Worksheet, ws2 As Worksheet, lr As Long, wsName As String, keep As Range
Set ws1 = Sheet1 'Or: Set ws = ThisWorkbook.Worksheets("Sheet1")
lr = ws1.Cells(ws1.Rows.Count, FILTER_COL).End(xlUp).Row
Application.ScreenUpdating = False
ws1.Range("AF1:AF" & lr).TextToColumns Destination:=ws1.Range("AA1"), _
TextQualifier:=xlDoubleQuote, _
FieldInfo:=Array(1, 1), _
TrailingMinusNumbers:=True
Dim filterCol As Range, toKep As Variant
Set filterCol = ws1.Range("Q1:Q" & lr)
toKep = Split(To_KEP)
Application.DisplayAlerts = False
Set ws2 = ThisWorkbook.Worksheets.Add(After:=ws1)
wsName = ws1.Name
With filterCol
.AutoFilter Field:=1, Criteria1:=toKep, Operator:=xlFilterValues
If .SpecialCells(xlCellTypeVisible).Count > 1 Then
.EntireRow.Copy
ws2.Cells.PasteSpecial xlPasteColumnWidths
ws2.Cells.PasteSpecial xlPasteAll 'Paste data on new sheet
ws1.Delete: ws2.Name = wsName: ws2.Cells(1).Select
End If
End With
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.CutCopyMode = False
End Sub
.
TextToColumns default parameters
DataType:=xlDelimited
ConsecutiveDelimiter:=False
Tab:=False
Semicolon:=False
Comma:=False
Space:=False
Other:=False

Search all columns of a spreadsheet for a unique value

I am struggling with a starting point for my next question. Essentially, I need to be able to search an entire spreadsheet for a unique 13 digit number (which would be unknown so I can't reference it beforehand), find all the references to that number, copy the rows into a new work sheet and then look for the next 13 digit number until all of the different 13 digit references have been copied into new sheets. Now this number may be in column A/B but it also may not, we aren't given the data in set template which is why it needs to search the whole spreadsheet. Can anyone give me an idea as to where to start? I have the basis of a subroutine if I know the numbers beforehand but in this instance, we don't know these numbers just that they are in there. Please help?! This is a VBA solution that I need.
Sample Data
Now the unique number may not always be in Column B which is why the macro needs to be able to identify which column the 13 digit number is in before copying all the rows which relate to it. I hope that makes more sense.
Here is a generic FindAll function which can serve as a start. You will need to specify a region (eg. .UsedRange) to search and what you are searching for and it will return a range of all the cells that match.
Function FindAll(What, _
Optional SearchWhat As Variant, _
Optional LookIn, _
Optional LookAt, _
Optional SearchOrder, _
Optional SearchDirection As XlSearchDirection = xlNext, _
Optional MatchCase As Boolean = False, _
Optional MatchByte, _
Optional SearchFormat) As Range
'LookIn can be xlValues or xlFormulas, _
LookAt can be xlWhole or xlPart, _
SearchOrder can be xlByRows or xlByColumns, _
SearchDirection can be xlNext, xlPrevious, _
MatchCase, MatchByte, and SearchFormat can be True or False. _
Before using SearchFormat = True, specify the appropriate settings for the Application.FindFormat _
object; e.g. Application.FindFormat.NumberFormat = "General;-General;""-"""
Dim SrcRange As Range
If IsMissing(SearchWhat) Then
Set SrcRange = ActiveSheet.UsedRange
ElseIf TypeOf SearchWhat Is Range Then
Set SrcRange = IIf(SearchWhat.Cells.Count = 1, SearchWhat.Parent.UsedRange, SearchWhat)
ElseIf TypeOf SearchWhat Is Worksheet Then
Set SrcRange = SearchWhat.UsedRange
Else: SrcRange = ActiveSheet.UsedRange
End If
If SrcRange Is Nothing Then Exit Function
'get the first matching cell in the range first
With SrcRange.Areas(SrcRange.Areas.Count)
Dim FirstCell As Range: Set FirstCell = .Cells(.Cells.Count)
End With
Dim CurrRange As Range: Set CurrRange = SrcRange.Find(What:=What, After:=FirstCell, LookIn:=LookIn, LookAt:=LookAt, _
SearchDirection:=SearchDirection, MatchCase:=MatchCase, MatchByte:=MatchByte, SearchFormat:=SearchFormat)
If Not CurrRange Is Nothing Then
Set FindAll = CurrRange
Do
Set CurrRange = SrcRange.Find(What:=What, After:=CurrRange, LookIn:=LookIn, LookAt:=LookAt, _
SearchDirection:=SearchDirection, MatchCase:=MatchCase, MatchByte:=MatchByte, SearchFormat:=SearchFormat)
If CurrRange Is Nothing Then Exit Do
If Application.Intersect(FindAll, CurrRange) Is Nothing Then
Set FindAll = Application.Union(FindAll, CurrRange)
Else: Exit Do
End If
Loop
End If
End Function

Search again if not found

So I have a part in my macro that I want to add what I assume needs to be an "Else" portion, but I am not that good with macros and am asking for help.
Range("Z1").Copy
Dim FindString As String
Dim Rng As Range
FindString = Sheets("Pull").Range("Y1").Value
If Trim(FindString) <> "" Then
With Sheets("HourTracker").Range("A:A")
Set Rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Application.Goto Rng, True
Else
MsgBox "Nothing found"
End If
End With
ActiveCell.Offset(0, 1).Activate
Selection.PasteSpecial xlPasteValues
Application.DisplayAlerts = True
End If
End Sub
So what I want this to do, is instead of "MsgBox "Nothing Found"", I want it to essentially perform the same thing as above, but copy cell Z2, and search for the value of Y2 in the same sheet "HourTracker" then paste the value. I have no idea on how to accomplish this, and all my attempts have failed. Any help would be much appreciated. Let me know if you need more clarification, thank you in advance!!!
Sounds to me like you're looking for a loop.
Sub findStuff()
Application.DisplayAlerts = False
' The item you want to paste
Dim PasteString As String
' The item you're looking for
Dim FindString As String
' The range that may containing FindString
Dim Rng As Range
' The variable used to loop through your range
Dim iCounter as Long
' loop through the first cell in column Y to the last used cell
For iCounter = 1 To Sheets("Pull").Cells(Rows.Count, 25).End(xlUp).Row
' PasteString = the current cell in column Z
PasteString = Sheets("Pull").Cells(iCounter, 26).Value
' FindString = the current cell in column Y
FindString = Sheets("Pull").Cells(iCounter, 25).Value
If Trim(FindString) <> "" Then
With Sheets("HourTracker").Range("A:A")
' Find the cell containing FindString
Set Rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
' There's no need to activate/ select the cell.
' You can directly set the value with .Value
Rng.Offset(0, 1).Value = PasteString
Else
' Do nothing
End If
End With
Else
' Do nothing
End If
Next
Application.DisplayAlerts = True
End Sub
Every time the compiler hits Next it will start again at For but raise the value of iCounter by 1. We can use Cells to accomplish this since Cells takes the row and column arguments as numbers, not strings (like Range). The syntax is simply Cells(Row #, Column #). Therefore, every time the For . . . Next loops around again, iCounter will go up by one and you'll search in the next row.
Instead of using .Paste, you can set the value of a cell directly with .Value. Pasting is pretty slow and using .Value is much faster.
Cells().End(xlUp).Row is a method used to find the last used cell in a range. See Error in finding last used cell in VBA for a much better explanation than I can give here.

How to apply another filter, if one filter is already applied in VBA

I was trying to write a code. I 've applied a filter and then I need to apply one more filter after few lines. But the second filter is not getting applied. Here is my code-
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
Sub occ_const_ashish()
Dim wb As Worksheet
Dim bldscrng As Range
Dim wb1 As String
Dim i As String, j As String
Dim arr() As Variant
Dim arrTemp() As Variant
Set wb = Sheets(ActiveSheet.Name)
wb1 = ActiveSheet.Name
wb.Activate
LC = Sheets(wb1).Cells(1, Columns.Count).End(xlToLeft).Column
' Sets the search range as A1 to the last column with a header on the Run sheet
Set sRange = Sheets(wb1).Range("A1", Cells(1, LC))
' With the search range
With sRange
' Set Rng as the cell where "Country" is found
Set cntryrng = .Find(What:="CNTRYCODE", After:=.Cells(1), _
LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not cntryrng Is Nothing Then
' Define LastRow as the last row of data under the Due Date header
LR = Sheets(wb1).Cells(Rows.Count, cntryrng.Column).End(xlUp).Row
' Copy from the Due Date header down to the last row of that column and paste to A1 of Paste Report Here sheet
'Set rngSourceRange1 = Sheets(wb1).Range(cntryrng(2), Cells(LR, cntryrng.Column))
Set rngSourceRange1 = Sheets(wb1).Range(cntryrng(2), Cells(LR, cntryrng.Column))
For Each cell In rngSourceRange1
i = cell.Value
rw = cell.Row
'MsgBox i
With ThisWorkbook.Sheets("Construction")
arr = Application.Transpose(.Range(.Cells(2, 1), .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, 1)).Value2)
End With
'arr1 = Application.Transpose(Sheets(wb1).Range(Sheets(wb1).Cells(2, 5), Sheets(wb1).Cells(Sheets(wb1).Cells(Sheets(wb1).Rows.Count, 5).End(xlUp).Row, 5)).Value2)
If IsInArray(i, arr) Then
'arrayTemp = Filter(arr1, i)
'MsgBox Join(arrayTemp, ",")
With ThisWorkbook.Sheets("Construction")
.AutoFilterMode = False
.Range("A1:E1").AutoFilter
.Range("A1:E1").AutoFilter Field:=1, Criteria1:=i
End With
With sRange
' Set Rng as the cell where "Country" is found
Set bldscrng = .Find(What:="BLDGSCHEME", After:=.Cells(1), _
LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
col1 = bldscrng.Cells(1, 1).Column
j = Cells(rw, col1).Value
If j = "" Then
Cells(rw, LC + 1).Value = "BLDSCHEME is BLANK"
'MsgBox "bldscheme is blank"
Else
'MsgBox j
With ThisWorkbook.Sheets("Construction")
arr1 = Application.Transpose(.Range(.Cells(2, 3), .Cells(.Cells(.Rows.Count, 3).End(xlUp).Row, 3)).Value2)
End With
If IsInArray(j, arr1) Then
'MsgBox "scheme found"
With ThisWorkbook.Sheets("Construction")
If ActiveSheet.AutoFilterMode = False Then Range("A1:E1").AutoFilter
.Range("A1:E1").AutoFilter
.Range("A1:E1").AutoFilter Field:=1, Criteria1:=i
.Range("A1:E1").AutoFilter Field:=3, Criteria1:=j
End With
Else
'MsgBox "scheme not found"
Cells(rw, LC + 1).Value = "BLDSCHEME is INVALID"
End If
End If
End With
Else
MsgBox "Country not found"
End If
Next cell
End If
End With
End Sub
The problem is here:
If ActiveSheet.AutoFilterMode = False Then ...
Here you check if the AutoFilterMode is false while you have applied a filter in the previous lines. So it goes to the Else part and shows: MsgBox "scheme not found".
Modify this part of the code as below to comprehend what I mean:
With ThisWorkbook.Sheets("Construction")
.AutoFilterMode = False
Debug.Print .AutoFilterMode 'before applying autofilter
.Range("A1:E1").AutoFilter
Debug.Print .AutoFilterMode 'after applying autofilter
.Range("A1:E1").AutoFilter Field:=1, Criteria1:=i
End With
Also, when you want to use this much if-statements try to make the indentation clear and have some comments (maybe numbering) to make your code legible. Moreover, you can consider using Select Case.

Apply advanced filter after autofilter

I want to do two successive filtering; the first on dates which I use auto-filter and on the produced result I want to do advance-filter (because I have OR in mind).
So what I did first was to set a range variable to the unfiltered range.
Set rng = Range(ws.Cells(1, 1), ws.Cells(rowNos, colNos))
Then using auto-filter I filter for given dates.
rng.AutoFilter Field:=1, Criteria1:=">" & lDate
Since now some rows will be hidden, and I want to apply advanced filter, I made use of specialcells
rng.SpecialCells(xlCellTypeVisible).AdvancedFilter Action:=xlFilterCopy, _
CriteriaRange:=crt, CopyToRange:=thisWB.Worksheets("Sheet3").Range("A1"), _
Unique:=False
However I got an error in the last step "the command requires at least two rowa of data . . " I made sure that there were at least 100 rows which fit the criteria meaning that the error is not because of a lack of rows.
Please help me get the problem. Also if there's another way I can accomplish the task I'll be happy to change my codes. What I'm trying to do is for specific dates filter a table and then filter again for values on two columns (as is normally done with advanced filters).
It seems like .AdvancedFilter does not work on non-continuous ranges. The code below is a bit kludge-y, but worked for a little example I pulled together where I want to return observations that are > April 1st, 2014 where Foo = Yes and Bar = 7. My data sheet contains exactly one row that matches all those criteria.
Option Explicit
Sub FilterTwice()
Dim DataSheet As Worksheet, TargetSheet As Worksheet, _
ControlSheet As Worksheet, TempSheet As Worksheet
Dim DataRng As Range, ControlRng As Range, _
TempRng As Range
Dim lDate As Date
Dim LastRow As Long, LastCol As Long
'assign sheets for easy reference
Set DataSheet = ThisWorkbook.Worksheets("Sheet1")
Set ControlSheet = ThisWorkbook.Worksheets("Sheet2")
Set TargetSheet = ThisWorkbook.Worksheets("Sheet3")
'clear any previously-set filters
Call ClearAllFilters(DataSheet)
'assign data range
LastRow = DataSheet.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
LastCol = DataSheet.Cells.Find("*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Set DataRng = Range(DataSheet.Cells(1, 1), DataSheet.Cells(LastRow, LastCol))
'assign a control (or critieria) range for the advanced filter
Set ControlRng = Range(ControlSheet.Cells(1, 1), ControlSheet.Cells(2, 2))
'apply date filter
lDate = "4/1/2014"
With DataRng
.AutoFilter Field:=1, Criteria1:=">" & lDate
End With
'add a temporary sheet and copy the visible cells to create a continuous range
Set TempSheet = Worksheets.Add
DataRng.SpecialCells(xlCellTypeVisible).Copy
TempSheet.Range("A1").PasteSpecial Paste:=xlPasteAll
'assign temp range
LastRow = TempSheet.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
LastCol = TempSheet.Cells.Find("*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Set TempRng = Range(TempSheet.Cells(1, 1), TempSheet.Cells(LastRow, LastCol))
'apply advanced filter to temp range and get obs where foo = yes and bar = 7
With TempRng
.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=ControlRng, _
CopyToRange:=TargetSheet.Range("A1"), Unique:=False
End With
'remove the temp sheet and clear filters on the data sheet
Application.DisplayAlerts = False
TempSheet.Delete
Application.DisplayAlerts = True
DataSheet.AutoFilterMode = False
End Sub
Sub ClearAllFilters(cafSheet As Worksheet)
With cafSheet
.AutoFilterMode = False
If .FilterMode = True Then
.ShowAllData
End If
End With
End Sub