Bellow is part of my codes and my coding is almost done, but now I found a big problem that it's necessary to be corrected.
I use this code on a sheet with over 10000 rows and my purpose is to update a column using Index & Match functions. What it's doing is that it replaces all cells of range in column J with corresponding values from another sheet. The big problem is that I don't want cells that have no matching item be replaced with #N/A and they keep their old values.
What should I do?
Dim SourceRange As Range
Dim fillRange As Range
'bellow formula in A1 notation:
'=INDEX('[myWB.xls]Sheet1'!$A:$B;
'IF(INDEX('[myWB.xls]Sheet1'!$A:$A;MATCH(C4;'[myWB.xls]Sheet1'!$A:$A))=C4;
' MATCH(C4;'[myWB.xls]Sheet1'!$A:$A);
' NA());
' 2)
ActiveCell.FormulaR1C1 = _
"=INDEX([myWB.xls]Sheet1!C1:C2,IF(INDEX([myWB.xls]Sheet1!C1,MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1))=R[-11]C[-12],MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1),NA()),2)"
' autofill formula in column
Set SourceRange = Cells(2, 10)
Set fillRange = Range(Cells(2, 10), Cells(10000, 10))
With SourceRange
.AutoFill Destination:=fillRange, Type:=xlCopy
End With
'replace formula with its value
With Range(Cells(2, 10), Cells(10000, 10))
.Value = .Value
End With
Update
This is my current code with some improvements. Thanks to Rob Anthony for his help.
Dim calc As XlCalculation
Dim f as String
With Workbooks(FinalWB.xls).Worksheets(1) 'Worksheet to be updated
calc = Application.Calculation
Application.Calculation = xlCalculationAutomatic 'Ensure automatic calculation is ON
Application.ScreenUpdating = False
Application.EnableEvents = False
'Copy Column J to Column Z
Range(.Cells(2, 26), .Cells(10000, 26)).Value = _ ' Col Z =
Range(.Cells(2, 10), .Cells(10000, 10)).Value ' Col J
f = "=if(ISERROR(INDEX([myWB.xls]Sheet1!C1:C2,IF(INDEX([myWB.xls]Sheet1!C1,MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1))=R[-11]C[-12],MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1),NA()),2)),RC[16],INDEX([myWB.xls]Sheet1!C1:C2,IF(INDEX([myWB.xls]Sheet1!C1,MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1))=R[-11]C[-12],MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1),NA()),2))"
With Range(.Cells(2, 10), .Cells(10000, 10))
.FormulaR1C1 = f 'fill formula without Autofill
.Value = .Value 'replace formula with its value
End With
'Delete Column Z
.Columns(26).EntireColumn.Delete
End With
Application.Calculation = calc
Application.ScreenUpdating = True
Application.EnableEvents = True
'This is above formula. now seems so easy to understand :)
' f =
' "=IF( 'if calculations result an error...
' ISERROR(
' INDEX([myWB.xls]Sheet1!C1:C2,
' IF(
' INDEX([myWB.xls]Sheet1!C1,
' MATCH(R[-11]C[-12],
' [myWB.xls]Sheet1!C1)
' )=R[-11]C[-12],
' MATCH(R[-11]C[-12],
' [myWB.xls]Sheet1!C1),
' NA()
' ),
' 2
' )
' ),
' RC[16], 'use previousely copied value of the cell...
' INDEX([myWB.xls]Sheet1!C1:C2, 'else use that calculations
' IF(
' INDEX([myWB.xls]Sheet1!C1,
' MATCH(R[-11]C[-12],
' [myWB.xls]Sheet1!C1)
' )=R[-11]C[-12],
' MATCH(R[-11]C[-12],
' [myWB.xls]Sheet1!C1),
' NA()
' ),
' 2
' )
' )
' "
The easiest way to solve this is to copy and paste Column J into a new column (say Z). Then, put this formula into Column J
=if(ISERROR(INDEX([myWB.xls]Sheet1!C1:C2,IF(INDEX([myWB.xls]Sheet1!C1,MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1))=R[-11]C[-12],MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1),NA()),2)),RC[16],INDEX([myWB.xls]Sheet1!C1:C2,IF(INDEX([myWB.xls]Sheet1!C1,MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1))=R[-11]C[-12],MATCH(R[-11]C[-12],[myWB.xls]Sheet1!C1),NA()),2))
I check to see whether the formula returns a valid value, if it does not, then I put in the value from Column Z (I have assumed that RC[16] is a valid reference for this, from your earlier comment), otherwise I put in the value as calculated.
Without seeing your spreadsheet, it is difficult to see exactly what you are trying to do. It might be possible to shorten this function.
Related
I have a file with more then 1 sheet, where in the Reports Sheet I want to filter by ASBN products and then delete them, because I already processed it in another sheet, so I need to delete the initial ones in order to paste back the processed one.
Idea is that this deleting code which is working, but is taking for at least 20 minutes, because I want to delete 123 572 rows, do you have any idea how could I make this work faster?
I also tried to clear contents first and then to delete empty rows, but it's the same.
Here you find the code:
Public Sub Remove_ABSN()
Dim area As String
Dim start As Long
area = "ABSN"
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.DisplayAlerts = False
Application.EnableEvents = False
start = Worksheets("Reports").Cells(Cells.Rows.Count, 1).End(xlUp).Row
Worksheets("Reports").Range("$A$2:$AN" & start).AutoFilter Field:=8, Criteria1:=area, Operator:=xlFilterValues
Worksheets("Reports").Range("$A$2:$AN$" & start).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Sheets("Reports").ShowAllData
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.DisplayAlerts = True
Application.EnableEvents = True
End Sub
I think AutoFilter will be the fastest way to do it. Here are two sample scripts to try. You can see for yourself which one is faster.
Public Sub UnionDeleteRowsFast()
' Careful...delete runs on Sheet1
Dim sh2 As Worksheet
Set sh2 = Sheets("Sheet1")
Dim lastrow As Long
Dim Rng As Range
lastrow = Cells(Rows.Count, "B").End(xlUp).Row
For i = lastrow To 2 Step -1
If Cells(i, 2).Value = "Delete" Then
If Rng Is Nothing Then
Set Rng = Range("B" & i)
Else
Set Rng = Union(Rng, Range("B" & i))
End If
End If
Next
If Not Rng Is Nothing Then Rng.EntireRow.Delete
End Sub
Sub AutoFilterDeleteRowsFast()
' Careful...delete runs on ActiveSheet
With ActiveSheet
.AutoFilterMode = False
With Range("B4", Range("B" & Rows.Count).End(xlUp))
.AutoFilter 1, "*Delete*"
On Error Resume Next
.Offset(1).SpecialCells(12).EntireRow.Delete
End With
.AutoFilterMode = False
End With
End Sub
There is a way that is much faster.
Suppose a table of 100,000 lines (A1:B100001) with headers in line 1. Then delete condition refers to just 1 column (B).
One needs a auxiliar column (A) just to count the lines in the original order. Here I use autofill function.
So one can sort the table and after restore the original order.
Below there is a complete example, that generates randomly numbers from 1 to 10 (it's slow!), and after quickly delete all lines with values 3
Sub EraseValue()
Application.ScreenUpdating = False
Dim i As Long
Dim T1 As Single ' milisecs after booting (Start)
Dim T2 As Single ' milisecs after booting (End)
Dim LIni As Variant ' Initial line to delete
Dim LEnd As Variant ' Final line to delete
Const Fin = 100000 ' Lines in the table
Const FinStr = "100001" ' Last line (string)
Randomize (GetTickCount()) ' Seed of random generation
For i = 1 To Fin
Cells(i + 1, "B") = Int(Rnd() * 10 + 1) ' Generates from 1 to 10
If i Mod 100 = 0 Then Application.StatusBar = i
DoEvents
Next i
Application.StatusBar = False
Dim Table As Range
Dim Colu As Range
T1 = GetTickCount() ' Initial time
Cells(2, "A") = 1 ' Starting value
Cells(3, "A") = 2 ' Step
' Fill from 1 to 100,000 step 1
Range("A2:A3").AutoFill Destination:=Range("A2:A" & FinStr)
' Order by condition column
Table.Sort Key1:=Cells(1, "B"), Header:=xlYes
'One needs delete lines with column B = 3
'LIni: Search key that not exceed value 2 in the column
' (2 is immediately previous value)
'LEnd: Search key that not exceed value 3 in the column
'LIni and LFim is relative to 2 so add 1 for skip the header
'Add more 1 to Lini in order to get the first value in the column >= key
'
LIni = Application.Match(2, Colu, 1) + 2
LEnd = Application.Match(3, Colu, 1) + 1
If IsError(LIni) Or IsError(LEnd) Or LEnd < LEnd Then
MsgBox ("There is no lines to delete")
End
End If
Range(Rows(LIni), Rows(LEnd)).Delete (xlUp) ' Delete lines
Table.Sort Key1:=Cells(1, "A"), Header:=xlYes ' Restore initial order
T2 = GetTickCount() ' Get the final time
MsgBox ("Elapsed milisecs: " + Format((T2 - T1), "0"))
End Sub
In my old computer, it take a little bit more that 0.5 secs with 100,000 lines.
If one has a condition that involves 2 columns or more, one need to create an another auxiliary column with a formula that concatenate these columns related do desired condition and run the match in this column. The formula needs to usage relative references. For instance (assuming that the data of column C are string and is already filled with a header).
Cells(1,4) = "NewCol" ' New column D
Dim NewCol As Range
Set NewCol = Range("D2:D" & FinStr)
' Two previous columns concatenated. In line 2
' the formula would be "=Format(B2,"0")+C2" (B2 is a number)
NewCol.FormulaR1C1 = "=Format(RC[-2],"0") & RC[-1]"
NewCol.Copy
NewCol.PasteSpecial(XlValues) ' Convert all formulas to values
Application.CutCopyMode=false
So one usages the column D instead column B
Can anyone help me adjust this code to fix my solution?
I have a button that adds x amount of new rows from A5 downwards. Columns A - Z.
I would like the new rows to be blank but still contain dropdowns and formula. New to VBA and struggling with this one.
I think I need to change the range and add xlPasteFormulas but unsure where and how for both. Any help hugely appreciated.
Option Explicit
Sub AddRows()
Dim x As Integer
x = InputBox("How many rows would you like to add?", "Insert Rows")
'Selecting range to insert new cells
Range(Cells(5, 1), Cells(x + 4, 1)).EntireRow.Insert
'Copys current cell A6 and past in the new cells
Cells(x + 5, 1).Copy Range(Cells(5, 1), Cells(x + 4, 1))
'if you want the cells to be blank but still have the drop down options
Range(Cells(5, 1), Cells(x + 4, 1)).ClearContents
End Sub
Please try the code below. It will copy everything from the BaseRow and then delete constant values in that range, leaving formats, including data validations, and formulas.
Sub AddRows()
Const BaseRow As Long = 11 ' modify to suit
Dim x As String ' InputBox returns text if 'Type' isn't specified
Dim Rng As Range
Dim R As Long
x = InputBox("How many rows would you like to add?", "Insert Rows")
If x = "" Then Exit Sub
R = BaseRow + CInt(x) - 1
Rows(BaseRow).Copy 'Copy BaseRow
'specify range to insert new cells
Set Rng = Range(Cells(BaseRow, 1), Cells(R, 1))
Rng.Insert Shift:=xlDown
' insert the new rows BEFORE BaseRow
' to insert below BaseRow use Rng.Offset(BaseRow - R)
Set Rng = Rng.Offset(BaseRow - R - 1).Resize(Rng.Rows.Count, ActiveSheet.UsedRange.Columns.Count)
Rng.Select
On Error Resume Next
Rng.SpecialCells(xlCellTypeConstants).ClearContents
Application.CutCopyMode = False '
End Sub
The code now has an emergency exit: If you don't enter anything in the InputBox the procedure terminates. Note that new rows are inserted above the BaseRow. After the insertion all new rows and the old row are identical. You can then choose to retain the constants in either the first or the last of these rows, effectively meaning, insert new, blank rows either above or below the BaseRow.
I am using autofilter to look up a criteria in column A in Sheet1 and return the corresponding value from column B in a table, however I want to be able to make it concatenate if column B contents are in two cells. Column A is blank under the identifier in cases like this.
Sub ReturnTIResults()
Dim r As Range
Application.ScreenUpdating = True
With Worksheets("Sheet1") ' reference results sheet
If IsEmpty(.Range("A1")) Then .Range("A1").Value = "dummy header"
' if A1 is empty, put a "dummy" header to make AutoFilter work properly
.AutoFilterMode = False
With .Range("B1", .Cells(.Rows.Count, 2).End(xlUp)).Offset(, -1) 'reference referenced sheet column A range from row 1 down to column B last not empty cell
.SpecialCells(xlCellTypeBlanks).Formula = "=R[-1]C" ' fill referenced range blank cells with the same value as the not empty cell above
.AutoFilter Field:=1, Criteria1:="=TI"
On Error Resume Next
Set r = .Resize(.Rows.Count - 1, 1).Offset(1,1).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not r Is Nothing Then r.Copy Worksheets("Search Results").Range("B7")
.Parent.AutoFilterMode = False
.SpecialCells(xlCellTypeFormulas).ClearContents ' clear cell with formulas
If .Range("A1").Value = "dummy header" Then
.Range("A1").ClearContents ' remove any "dummy" header
End With
End With
Application.ScreenUpdating = True
End Sub
Image
Untested, I basically just inserted some code within your If branch.
Few things to note:
Application.Transpose (used below to convert 2-d array to 1-d array) can only handle arrays of length ~65.5k. So if you have more filtered items than that, not all of them may get concatenated.
Cells have a character limit of ~32.8k I think. If the result of your concatenation violates this limit, you may get an error when trying to assign the result.
But other than that, should work fine. Also, both of your Application.ScreenUpdating assignments seem to be True. You might want to look into that.
Option Explicit
Sub ReturnTIResults()
Dim r As Range
Application.ScreenUpdating = True
With Worksheets("Sheet1") ' reference results sheet
If IsEmpty(.Range("A1")) Then .Range("A1").Value = "dummy header"
' if A1 is empty, put a "dummy" header to make AutoFilter work properly
.AutoFilterMode = False
With .Range("B1", .Cells(.Rows.Count, 2).End(xlUp)).Offset(, -1) 'reference referenced sheet column A range from row 1 down to column B last not empty cell
.SpecialCells(xlCellTypeBlanks).Formula = "=R[-1]C" ' fill referenced range blank cells with the same value as the not empty cell above
.AutoFilter Field:=1, Criteria1:="=TI"
On Error Resume Next
Set r = .Resize(.Rows.Count - 1, 1).Offset(1, 1).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not r Is Nothing Then
If r.Rows.Count > 1 Then
Dim toConcatenate As Variant
toConcatenate = Application.Transpose(r.Value2)
toConcatenate = VBA.Strings.Join(toConcatenate, ", ") ' <-- Change to whatever delimiter you want
Worksheets("Search Results").Range("B7").Value2 = toConcatenate
Else
Worksheets("Search Results").Range("B7").Value2 = r.Value2
End If
End If
.Parent.AutoFilterMode = False
.SpecialCells(xlCellTypeFormulas).ClearContents ' clear cell with formulas
If .Range("A1").Value = "dummy header" Then .Range("A1").ClearContents ' remove any "dummy" header
End With
End With
Application.ScreenUpdating = True
End Sub
On sheet one, I have descriptions in column A, and values in column B. On sheet two, I have formulas in columns A through F that I manually fill in with values from sheet one column B based on what the description in column A is. I want to highlight cells in sheet one column B if the cell in question has already been used in a formula on sheet two. Using conditional formatting if possible, using a macro otherwise.
I want to be able to quickly see if a cell in column B has already been added to a formula on another sheet so that I do not accidentally include the value twice.
Sheet One Sheet Two
A B C A B C
1 salt 3 1 =B1+B4
2 base 3 2
3 base 4 3
4 salt 1 4 =B2+B3
5 base 4 5
I expect to be able to automatically highlight a cell that is already in another function without having to manually do it to reduce the error chance. In the example above cells B1 through B4 would be highlighted since they have been used in a formula while B5 would remain normal since it has not been used yet
VBA Conditional Formatting feat. Array and Range Union
Features
Find Method (SO)
Cells Property
Parent Property
Formula Property
Resize Method
InStr Function
Replace Function
Union Method
The Code
Sub CompareColumnWithRange()
Const cStrTgtWs As Variant = 1 ' Target Worksheet Name/Index
Const cStrSrcWs As Variant = 2 ' Source Worksheet Name/Index
Const cLngTgtFirst As Long = 1 ' Target First Row
Const cLngSrcFirst As Long = 1 ' Source First Row
Const cStrTgtColumn As Variant = "B" ' Target Column Letter/Number
Const cStrSrcRange As String = "A:F" ' Source Columns Range
Const cColor As Long = 255 ' Formatting Color
Dim rngTgt As Range ' Target Range
Dim rngU As Range ' Target Union Range
Dim vntSrc As Variant ' Source Array
Dim i As Long ' Source Array Row Counter
Dim j As Integer ' Source Array Column Counter
Dim k As Long ' Target Range Row Counter
With Worksheets(cStrSrcWs).Range(cStrSrcRange)
' Check if sheet is empty (No data).
If .Find("*", .Cells(.Rows.Count, .Columns.Count), -4123, , 1) _
Is Nothing Then Exit Sub
' Paste Source Range's formulas into Source Array. Since the previous
' With statement refers to a range, the Parent property has to be used
' to 'aquire sheet level'.
vntSrc = .Parent.Range(.Parent.Cells(cLngSrcFirst, .Column), _
.Parent.Cells(.Cells.Find("*", , , , , 2).Row, _
.Columns.Count - .Column + 1)).Formula
End With
' ' Print contents of vntSrc to Immediate window.
' For i = 1 To UBound(vntSrc)
' For j = 1 To UBound(vntSrc, 2)
' Debug.Print vntSrc(i, j)
' Next
' Next
' Target Column vs Source Array
With Worksheets(cStrTgtWs)
' Determine the Target Range (1 column).
Set rngTgt = .Cells(cLngTgtFirst, cStrTgtColumn).Resize( _
.Cells(.Rows.Count, cStrTgtColumn).End(xlUp).Row - cLngTgtFirst + 1)
' Loop through Target Range (1 column)
For k = cLngTgtFirst To .Cells(.Rows.Count, cStrTgtColumn).End(xlUp).Row
' Loop through Source Array rows.
For i = 1 To UBound(vntSrc)
' Loop through Source Array columns.
For j = 1 To UBound(vntSrc, 2)
' Search for Target Range's cell address in current value
' of Source Array i.e. remove the $ signs in both, and add
' sheet name for Target Range.
If InStr(1, Replace(vntSrc(i, j), "$", ""), .Name & "!" _
& Replace(.Cells(k, cStrTgtColumn).Address, "$", "")) <> 0 Then
If Not rngU Is Nothing Then ' Add cells to existing range.
Set rngU = Union(rngU, .Cells(k, cStrTgtColumn))
Else ' Add cells to non-existing range. Runs only the first time.
Set rngU = .Cells(k, cStrTgtColumn)
End If
Exit For ' If a value has been found, stop searching for more.
End If
Next
Next
Next
End With
' Apply formatting to all 'collected' cells in Target Union Range in one go.
If Not rngU Is Nothing Then
rngU.Interior.Color = cColor
Set rngU = Nothing
End If
Set rngTgt = Nothing
End Sub
I have two workboks, one called slave and one called master.
Slave.xlsm
ID Case Size Names
1 1o Michael
2 4 Katie
3 3 Elliot
Master.xlsm
ID Case Size Names
1 1o
2 4
3 3
From Slave workbook, I am trying to copy the values from Name column where the ID and Case Size matches in Master.
I'm new to VBA and so have tried to compile my own code below with the help of some examples online. Here's what i've got so far:
Sub GetTheName()
Dim s As String, FileName As String
s = "C:\Users\******\Documents\*.xlsm"
FileName = Dir(s)
Do Until FileName = ""
If FileName Like "Slave*" Then MsgBox FileName
Dim w1 As Worksheet, w2 As Worksheet
Dim c As Range, FR As Long
Application.ScreenUpdating = False
Set w1 = Workbooks.Open(FileName).Sheets(1)
Set w2 = ThisWorkbook.Sheets(1)
For Each c In w1.Range("C10", w1.Range("C" & Rows.Count).End(xlUp))
FR = 0
On Error Resume Next
FR = Application.Match(c, w2.Columns("A"), 0)
On Error GoTo 0
If FR <> 0 Then w2.Range("R" & FR).Value = c.Offset(, 0)
Next c
Application.ScreenUpdating = True
FileName = Dir()
ActiveSheet.Range("A8").Value = Now()
Loop
End Sub
If i remove On Error Resume Next i get a type mismatch error on the below line:
FR = Application.Match(c, w2.Columns("R"), 0)
The code opens the workbok but does not copy anything across. I'm not sure why nothing is being copied. Please can someone show me where i am going wrong? Thanks
I have managed to get what you want... I'm not sure if you will be interested in my answer, but it does what you want...
First add a column where you concatenate A and B columns in the slave page
Find the matches with INDEX - MATCH method
I added the concatenate column on the D column... so the formula would be like this...
=INDEX(SLAVE!C2:C4;MATCH(CONCATENATE(MASTER!A2;MASTER!B2);SLAVE!D2:D4;0))
And this is the VBA code
Sub GetNames()
'
' GetNames Macro
'
'
LastRow = Sheets("SLAVE").Cells(Rows.Count, 1).End(xlUp).Row
Sheets("SLAVE").Activate
Sheets("SLAVE").Range("D2").FormulaR1C1 = "=CONCATENATE(RC[-3],RC[-2])"
Sheets("SLAVE").Range("D2").AutoFill Destination:=Range("D2:D" & LastRow & ""), Type:=xlFillDefault
LastRow = Sheets("MASTER").Cells(Rows.Count, 1).End(xlUp).Row
Sheets("MASTER").Activate
Sheets("MASTER").Range("C2").FormulaR1C1 = _
"=INDEX(SLAVE!RC:R[2]C,MATCH(CONCATENATE(MASTER!RC[-2],MASTER!RC[-1]),SLAVE!RC[1]:R[2]C[1],0))"
Sheets("MASTER").Range("C2").AutoFill Destination:=Range("C2:C" & LastRow & ""), Type:=xlFillDefault
End Sub
Based on the type mismatch in your comment, I will point you to here:
Application.Match gives type mismatch
It's likely you're not fining a match in the specified range.
you could use AutoFilter():
Option Explicit
Sub main()
Dim cell As Range, masterRng As Range
With Sheets("Master") '<--| reference your "Master" sheet
Set masterRng = .Range("A2", .Cells(.Rows.count, 1).End(xlUp)) '<--| reference its columns A cells from row 2 down to last not empty row
End With
With Sheets("Slave") '<--| reference your "Slave" sheet
With .Range("B1", .Cells(.Rows.count, 1).End(xlUp)) '<--| reference its columns A and B from row 1 (headers) down to column A last not empty row
For Each cell In masterRng '<--| loop through "Master" sheet column A ID Size"
.AutoFilter field:=1, Criteria1:=cell.Value '<--| filter it on its 2nd column (i.e. column B) with current cell offset 1 column value (i.e. current "Master" sheet "Case Size")
.AutoFilter field:=2, Criteria1:=cell.Offset(, 1).Value '<--| filter it on its 2nd column (i.e. column B) with current cell offset 1 column value (i.e. current "Master" sheet "Case Size")
If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 1 Then '<--| if any cell filtered other than headers
cell.Offset(, 2) = .Resize(.Rows.count - 1, 1).Offset(1, 2).SpecialCells(xlCellTypeVisible).Cells(1, 1) '<--|write first filtered 3rd column cell value in current cell offset 2 columns value (i.e. current "Master" sheet "Names")
End If
Next cell
End With
.AutoFilterMode = False
End With
End Sub