Screenshot of SourceReport Excel that need to be filtered.I need to develop a Excel VBA code to filter data on a worksheet, based on the filter conditions provided on the same worksheet.
Below is the code written for the same .. But this code filter the data from Row 1 instead of Row 4. Can you suggest an improvement?
Sub colFilter()
Dim ShtSource As Worksheet
Dim shtSrcHead As Range
Dim shtFilterData As Range
Dim filterStr As String
Set ShtSource = Sheets("SourceReport")
Dim lastCol As Long
Dim j As Long
Dim iCntr As Long
'get all of the filters of sheet , assuming in row 2
lastCol = ShtSource.Cells(1, Columns.Count).End(xlToLeft).Column
Set shtSrcHead = ShtSource.Range("A2", ShtSource.Cells(1, lastCol))
Set shtFilterData = ShtSource.Range("A4", ShtSource.Cells(1, lastCol))
j = 0
'actually loop through and find values
For Each srcHead In shtSrcHead
j = j + 1
If j = lastCol Then
j = 0
End If
If srcHead.Value = "INCLUDE" Or srcHead.Value = "EXCLUDE" Then
filterStr = srcHead.Offset(1, 0).Value
If srcHead.Value = "INCLUDE" Then
Debug.Print filterStr
Debug.Print j
shtFilterData.AutoFilter Field:=j, Criteria1:=filterStr
End If
If srcHead.Value = "EXCLUDE" Then
Debug.Print filterStr
Debug.Print j
shtFilterData.AutoFilter Field:=j, Criteria1:="<>" & filterStr
End If
End If
Next srcHead
MsgBox "Done!"
End Sub
As per below screenshot use the following sub to filter for multiple condition.
Sub MyFilter()
Dim include() As String
Dim exclude As String
Dim FiltRng As Range
Dim RngArea, RngArea2 As Range
'Set RngArea = Application.InputBox(prompt:="Select range include criteria.", Type:=8)
'Set RngArea2 = Application.InputBox(prompt:="Select range exclude criteria.", Type:=8)
'include = Split(RngArea, ",")
include = Split(Range("C2"), ",")
exclude = Range("B2")
Set FiltRng = Sheet1.Range("B4:C11")
FiltRng.AutoFilter Field:=2, Criteria1:=include, Operator:=xlFilterValues
FiltRng.AutoFilter Field:=1, Criteria1:="<>" & exclude
End Sub
Data position Screenshot
Adjust code for your data ranges.
Related
I need to find certain names on a worksheet, copy the entire row once it finds said name and paste it on another worksheet.
I wrote code that finds one of the names, then copies the row and pastes it to another sheet.
Sub Macro2()
Dim StatusCol As Range
Dim Status As Range
Dim PasteCell As Range
Set StatusCol = Sheet10.Range("A1:AV1569")
For Each Status In StatusCol
If Sheet11.Range("A2") = "" Then
Set PasteCell = Sheet11.Range("A2")
Else
Set PasteCell = Sheet11.Range("A1").End(xlDown).Offset(1, 0)
End If
If Status = "Jane Thompson" Then Status.Offset(0, -4).Resize(1, 5).Copy PasteCell
Next Status
End Sub
Instead of finding only one string, the "Jane Thompson" name, I want to loop through a list of names, find each, copy the entire row where they are located and paste the row into another sheet. I have all the names on another worksheet (about 80 different names)
I managed to find code that gives me the desired output:
Sub FruitBasket()
Dim rngCell As Range
Dim lngLstRow As Long
Dim strFruit() As String
Dim intFruitMax As Integer
intFruitMax = 3
ReDim strFruit(1 To intFruitMax)
strFruit(1) = "Fruit 2"
strFruit(2) = "Fruit 5"
strFruit(3) = "Fruit 18"
lngLstRow = ActiveSheet.UsedRange.Rows.Count
For Each rngCell In Range("A2:A" & lngLstRow)
For i = 1 To intFruitMax
If strFruit(i) = rngCell.Value Then
rngCell.EntireRow.Copy
Sheets("Inventory").Select
Range("A65536").End(xlUp).Offset(1, 0).Select
Selection.PasteSpecial xlPasteValues
Sheets("Fruit").Select
End If
Next i
Next
End Sub
But instead of 3 items in the array, I had to hard code 81 names. Is there any way to pull the items of an array from another sheet?
With the names in an array you can use Match rather than looping through them.
Option Explicit
Sub FruitBasket()
Dim ws As Worksheet, wsInv As Worksheet
Dim rngCell As Range, v As Variant, arNames
Dim lngLastRow As Long, lngInvRow As Long
With Sheets("Names")
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
arNames = .Range("A2:A" & lngLastRow)
End With
Set wsInv = Sheets("Inventory")
With wsInv
lngInvRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Application.ScreenUpdating = False
Set ws = ActiveSheet
With ws
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For Each rngCell In .Range("A2:A" & lngLastRow)
' check if value is in array
v = Application.Match(rngCell, arNames, 0)
If IsError(v) Then
' no match
Else
' match
rngCell.EntireRow.Copy
lngInvRow = lngInvRow + 1
wsInv.Cells(lngInvRow, "A").PasteSpecial xlPasteValues
End If
Next
End With
Application.CutCopyMode = False
Application.ScreenUpdating = True
MsgBox "Done"
End Sub
I am working on filtering a listbox based on the combobox selection.
Currently my codes look something like this.
Private Sub OEMNumberComboBox_Change()
Dim database(1 To 100, 1 To 7)
Dim i As Integer
Dim My_range As Integer
Dim colum As Byte
On Error Resume Next
Sheet7.Range("A1").AutoFilter field:=3, Criteria1:=Me.OEMNumberComboBox.Value
For i = 2 To Sheet7.Range("A100000").End(xlUp).Row
If Sheet7.Cells(i, 3) = Me.OEMNumberComboBox Then
My_range = My_range + 1
For colum = 1 To 7
database(My_range, colum) = Sheet7.Cells(i, colum)
Next colum
End If
Next i
ListBox1.List = database
End Sub
and the below during the intialisation
Sub Available_Stocks()
Application.ScreenUpdating = False
Dim invd_sh As Worksheet
Set invd_sh = ThisWorkbook.Sheets("Inventory")
Dim lr As Integer
lr = Application.WorksheetFunction.CountA(invd_sh.Range("A:A"))
If lr = 1 Then lr = 2
With Me.ListBox1
.ColumnCount = 9
.ColumnHeads = True
.ColumnWidths = "50,60,60,350,50,0,0,50,50"
.RowSource = "Inventory!A2:I" & lr
End With
End Sub
with the above codes it does filter the range but it is not reflected on the listbox and I am not sure what is wrong with the code.
It is exact copy of the online codes but i have made a slight modification (so that it is filtering column C).
user interface/objects
Update
Private Sub UserForm_Initialize()
'add column of data from spreadsheet to your userform ComboBox
OEMNumberComboBox.List = Sheets("Sheet1").Range("C1:C50").Value
End Sub
I have added the above code to populate the combobox but it sill shows one cell inside the listbox
For demonstration purpose, let's say your worksheet looks like the below and I want to populate all cells where the value of column C is 1
Logic:
Declare a Variant array.
Filter on column C with the relevant value from the combobox.
Loop through the Areas of the filtered range and populate the array.
Assign the array to the Listbox's .List.
Code:
Is this what you are tying? I have commented the code so that you should not have a problem understanding it. But if you do, then simply ask.
Option Explicit
Dim ws As Worksheet
Dim lrow As Long
Dim i As Long, j As Long
Private Sub UserForm_Initialize()
'~~> Set this to the relevant worksheet
Set ws = Sheet1
'~~> Set the listbox column count
ListBox1.ColumnCount = 8
Dim col As New Collection
Dim itm As Variant
With ws
'~~> Get last row in column C
lrow = .Range("C" & .Rows.Count).End(xlUp).Row
'~~> Create a unique list from column C values
On Error Resume Next
For i = 2 To lrow
col.Add .Range("C" & i).Value2, CStr(.Range("C" & i).Value2)
Next i
On Error GoTo 0
'~~> Add the item to combobox
For Each itm In col
OEMNumberComboBox.AddItem itm
Next itm
End With
End Sub
Private Sub CommandButton1_Click()
'~~> If nothing selected in the combobox then exit
If OEMNumberComboBox.ListIndex = -1 Then Exit Sub
'~~> Clear the listbox
ListBox1.Clear
Dim DataRange As Range, rngArea As Range
Dim DataSet As Variant
With ws
'~~> Remove any filters
.AutoFilterMode = False
'~~> Find last row in Col C
lrow = .Range("C" & .Rows.Count).End(xlUp).Row
'~~> Filter on the relevant column
With .Range("C1:C" & lrow)
.AutoFilter Field:=1, Criteria1:=OEMNumberComboBox.Value
On Error Resume Next
Set DataRange = .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow
On Error GoTo 0
End With
'~~> Check if the autofilter returned any results
If Not DataRange Is Nothing Then
'~~> Instead of using another object, I am reusing the object
Set DataRange = .Range("A2:G" & lrow).SpecialCells(xlCellTypeVisible)
'~~> Create the array
ReDim DataSet(1 To DataRange.Areas.Count + 1, 1 To 8)
j = 1
'~~> Loop through the area and store in the array
For Each rngArea In DataRange.Areas
For i = 1 To 8
DataSet(j, i) = rngArea.Cells(, i).Value2
Next i
j = j + 1
Next rngArea
'~~> Set the listbox list
ListBox1.List = DataSet
End If
'~~> Remove any filters
.AutoFilterMode = False
End With
End Sub
In Action:
I am trying to add data to a Listbox on a Userform, based on the value of the the Cell in column C of the range that is searched. If the cell in column C contains a certain string I would like it to be added to the Listbox.
The below code is as far as I have got but it is returning an empty Listbox with no error.
Private Sub OptionButton12_Click()
Dim I As Integer
Dim lastRow As Integer
Dim searchString As String
searchString = "LISTBOXENTRY"
With ThisWorkbook.Sheets("Sheet1")
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Plybooks.ListBox1.Clear
For I = 1 To lastRow
If Cells(I, 3).Value = searchString Then
Plybooks.ListBox1.AddItem Range("A" & I)
End If
Next I
End Sub
Try using the script below and please let me know if it works!
based on your script above, I assumed some of the dataframe dimensions. please let me know if it is not correct so I can tweak it.
I assumed you are working on first sheet (sheets(1)), and col C is the column you are using for the value check against the "searchString" variable. (if true, append the value in listbox1)
Thanks
Private Sub OptionButton12_Click()
Dim lastRow As Integer
Dim searchString As String
Dim wb As Workbook
Dim sRng As Range
Dim cel As Range
'assign current wb into wb workbook object
Set wb = ThisWorkbook
'assign str you want to search into variable
searchString = "LISTBOXENTRY"
'find last row number in colC (3) using crow function. (assuming you want to do a check on every cell listed in column C)
lastRow = crow(1, 3)
plybooks.listbox1.Clear
'assign range object using dataframe dimensions based on row 1 col C (lbound), to lastrow col3 (ubound)
With wb.Sheets(1)
Set sRng = .Range(.Cells(1, 3), .Cells(trow, 3))
End With
'loops through each cel
For Each cel In sRng
If cel.Value = searchString Then
'adds item into listbox1 if conditional statement is True
plybooks.listbox1.AddItem Item:=cel.Value
Else
End If
Next cel
End Sub
Private Function crow(s As Variant, c As Integer)
crow = Sheets(s).Cells(Rows.Count, c).End(xlUp).Row
End Function
Added cell values in ranges over multiple sheets if cell contains certain value, using the following:
Public Sub PlybookListbox()
'Clear fields before start
Plybooks.ListBox1.MultiSelect = 0
Plybooks.ListBox1.Clear
Plybooks.ListBox1.Value = ""
Plybooks.ListBox1.MultiSelect = 2
Dim AllAreas(2) As Range, Idx As Integer, MyCell As Range, TargetRange As Range
Dim lastrowFrontWing As Long
Dim lastrowNose As Long
Dim lastrowBargeboard As Long
lastrowFrontWing = Worksheets("Front Wing").Cells(Rows.Count, 2).End(xlUp).Row
lastrowNose = Worksheets("Nose").Cells(Rows.Count, 2).End(xlUp).Row
lastrowBargeboard = Worksheets("Bargeboard & SPV").Cells(Rows.Count, 2).End(xlUp).Row
Set AllAreas(0) = Worksheets("Front Wing").Range("c6:c" & lastrowFrontWing)
Set AllAreas(1) = Worksheets("Nose").Range("c6:c" & lastrowNose)
Set AllAreas(2) = Worksheets("Bargeboard & SPV").Range("c6:c" & lastrowBargeboard)
Plybooks.ListBox1.Clear
For Idx = 0 To 2
For Each MyCell In AllAreas(Idx).Cells
If InStr(1, MyCell.Value, "(FS)") > 0 Then
Plybooks.ListBox1.AddItem MyCell.Value
End If
Next MyCell
Next Idx
End Sub
I have 5 columns. If column 3 has no value, I want all other adjacent cells (column 1,2,4,5) to clear.
I got this from another site:
Sub ClearCust()
'Clears data in column if there is no Amt number next to it.
'Used in conjunction to fill blanks.
Dim j As Range
For Each j In Workbooks("OH Details_v1").Worksheets("Sheet1").Range("C2:D" & Worksheets("Sheet1").Range("a65536").End(xlUp).Row)
If j.Value = 0 Then
j.Offset(0, 1).ClearContents
End If
Next j
End Sub
But it only clears column C, D, E...
Something like this might be what you're looking for:
Sub ClearCust()
Dim wb As Workbook
Dim ws As Worksheet
Dim rLast As Range
'Set wb = Workbooks("OH Details_v1")
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet1")
Set rLast = ws.Range("A:E").Find("*", ws.Range("A1"), xlValues, , , xlPrevious)
If rLast Is Nothing Then Exit Sub 'No data
With ws.Range("C1:C" & rLast.Row)
.AutoFilter 1, "="
Intersect(.Parent.Range("A:E"), .Offset(1).EntireRow).ClearContents
.AutoFilter
End With
End Sub
EDIT:
To address your request of iterating over sets of columns to perform this same task, you can do something like this:
Sub ClearCust()
Dim wb As Workbook
Dim ws As Worksheet
Dim rLast As Range
Dim aClearAreas() As String
Dim i As Long
'Set wb = Workbooks("OH Details_v1")
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet1")
ReDim aClearAreas(1 To 3, 1 To 2)
'Define columns that will be cleared Define column within that range to evaluate for blanks
aClearAreas(1, 1) = "A:E": aClearAreas(1, 2) = "C"
aClearAreas(2, 1) = "F:J": aClearAreas(2, 2) = "H"
aClearAreas(3, 1) = "K:O": aClearAreas(3, 2) = "M"
'loop through your array that contains your clear area data
For i = LBound(aClearAreas, 1) To UBound(aClearAreas, 1)
'Get last populated row within the defined range
Set rLast = ws.Range(aClearAreas(i, 1)).Find("*", ws.Range(aClearAreas(i, 1)).Cells(1), xlValues, , , xlPrevious)
If Not rLast Is Nothing Then
'Filter on the column to be evaluated
With ws.Range(aClearAreas(i, 2) & "1:" & aClearAreas(i, 2) & rLast.Row)
.AutoFilter 1, "=" 'Filter for blanks
Intersect(.Parent.Range(aClearAreas(i, 1)), .Offset(1).EntireRow).ClearContents 'Clear cells only in the defined range
.AutoFilter 'Remove the filter
End With
End If
Next i
End Sub
Your explanation and title are two different subjects but based on your explanation-i understand you want to loop through column C and if a cell is empty, then you make other cells value to blank-i wrote below code. You may use. Tested
Sub test()
Dim ws As Worksheet
Set ws = ActiveSheet
With ws
lr = .Cells(Rows.Count, "C").End(xlUp).Row
For i = 2 To lr
If .Cells(i, "C") = "" Then
.Cells(i, "A") = ""
.Cells(i, "B") = ""
.Cells(i, "D") = ""
.Cells(i, "E") = ""
End If
Next i
End With
End Sub
How do you count the number of visible/not null rows (from row 3 onwards, checking if column A is empty) after an autofilter? Right now I am only getting 26...
Full code:
Sub GetPrimaryContacts()
Dim Col As New Collection
Dim itm
Dim i As Long
Dim CellVell As Variant
'Get last row value
LastRow = Cells.SpecialCells(xlCellTypeLastCell).Row
'Loop between all rows to get unique values
For i = 3 To LastRow
CellVal = Sheets("Master").Range("F" & i).Value
On Error Resume Next
Col.Add CellVal, Chr(34) & CellVal & Chr(34)
On Error GoTo 0
Next i
' Create workbooks - Token Not activated
Call TokenNotActivated
For Each itm In Col
ActiveSheet.Range("A2:Z2").Select
Selection.AutoFilter Field:=6, Criteria1:=itm
Call CountFilterAreaRows
Next
End Sub
Here's a function that will count the visible rows in an autofiltered range, even if there are none:
Function CountFilterAreaRows(ws As Excel.Worksheet) As Long
Dim FilterArea As Excel.Range
Dim RowsCount As Long
Set ws = ActiveSheet
For Each FilterArea In ws.AutoFilter.Range.SpecialCells(xlCellTypeVisible)
RowsCount = RowsCount + FilterArea.Rows.Count
Next FilterArea
'don't count the header
RowsCount = RowsCount - 1
CountFilterAreaRows = RowsCount
End Function
To call it as a function, see the edits above. Using your example you would could call it something like this (Untested):
Sub UseIt()
Dim ws As Excel.Worksheet
Dim itm
Dim col As Collection
'... your col logic
For Each itm In col
Set ws = ActiveSheet
ActiveSheet.Range("A2:Z2").AutoFilter Field:=6, Criteria1:=itm
Debug.Print CountFilterAreaRows(ws)
Next itm
End Sub
Note that you should avoid the use of Select.
I could be wrong, because I am guessing at what your code is actually doing, but see if this gets what you want done.
For Each itm In Col
RowCount = Sheets("Master").Rows(itm.Row).Count
MsgBox RowCount
Next
Say we have an AutoFilter with the first row containing headers and nothing below the filtered table:
Sub visiCount()
Dim r As Range, n as Long
n = Cells(Rows.Count, 1).End(xlUp).Row
Set r = Range("A1:A" & n).Cells.SpecialCells(xlCellTypeVisible)
MsgBox r.Count - 1
End Sub
EDIT ............started at A1 rather than A2