AUTOFILTERS in VBA - excel

I thought I was finally done with my workbook but alas there arose an issue when we put it into practice (much to my dismay).
In short;
I was using autofilter (not in vba) menus to filter the items in my warehouse, and the shelves they were on.
When I filtered out everything but the shelves i wanted to add inventory to, the values I added (through a VBA programmed button that basically copies everything in the "add to stock" (AKA "C4:C1000" row and adds it into the "currently in stock" row (AKA "D1:d1000")) got added to the wrong row.
My solution was to use the autofilters to find the correct shelf, write the amount added to the stock, and then press the button.
The VBA code of the button would (in my new plan) then do exactly as before, only this time it would first remove the filters, execute as before, and then re-apply filters.
I cannot - for the life of me - figure out how to turn the autofilters back on with VBA code though.
I have searched far and wide on the net, but the closest I can find to what I want is the following code:
Activesheet.range("a4").autofilter
That does nothing but stop my code from completing its execution mid-way.
Please help!
The full code for one of the pages is as follows:
Sub AddtoInnTotalandclear()
'The macro is used to move all amounts plottet into "INN" colum. Amounts are moved into "TOTAL AMOUNT IN STORAGE" while clearing the "INN" colum simultaneously
'Removes flickering from the screen (part 1 of 2)
Application.ScreenUpdating = False
'removes the protection on the worksheet (NB! you have to have the current password in the code line for this to work)
ActiveSheet.Unprotect Password:="kirk"
'Copies the values from the "inn" colum
Range("c4:c1000").Copy
'Adds the copied values to the values already in the "Total Amount" colum
Range("d4:d1000").PasteSpecial Operation:=xlPasteSpecialOperationAdd
'Clears the "inn" colum
Range("c4:c1000").ClearContents
'Disable marchiing atnsa around copied range
Application.CutCopyMode = False
Range("d4:d1000").Select
Selection.Locked = True
'Allows autofilter usage despite the document being locked
'&
'Re-Activates the password protection
With ActiveSheet
.Protect Password:="kirk", AllowFiltering:=True
.EnableSelection = xlNoRestrictions
End With
'Determines where you end up when you are finished
Worksheets("in").Range("c4").Select
'Removes flickering from the screen (part 2 of 2)
Application.ScreenUpdating = True
End Sub
---- I want to remove/disable autofilters when I press the button that activates this VBA code, then re-activate the autofilters once the entire procedure is done...
I need an EXCEL JEDI to give me some sound code advice here.. Please :)

Here is a demo example. Say we have data in cols A through D with the headers in row#1. If you run:
Sub qwerty()
Dim s As Worksheet
Set s = ActiveSheet
s.AutoFilterMode = False
s.Range("A:D").AutoFilter
End Sub
You will end up with filtering on cols A through D, but with no criteria on any of those columns applied.
EDIT#1:
If your header row is row #3 and we are filtering cols A through D, then:
Sub qwerty2()
Dim s As Worksheet, N As Long
Set s = ActiveSheet
N = Cells(Rows.Count, "A").End(xlUp).Row
s.AutoFilterMode = False
s.Range("A3:D" & N).AutoFilter
End Sub

Related

Excel 2017. 7 worksheets, 1 filter to change them all

I have 7 worksheets which do exactly what I want. I am now being asked for a filter to show specific years. Done. However to look at a year of trend data, I have to manually filter each sheet.
I wouldn't mind going the extra mile, and if it's possible, have a filter in one of these sheets that organises the year in all the other sheets.
I have=YEAR(O9:O29148) on my largest sheet. A8:O8 and everything above is exactly the same on each sheet, every sheet has the same type of data in the same column. The only thing that does change is the unique data itself.
What I want is to have a Year filter (2000-2018) on my dashboard, which will then filter all the worksheets to show the same year, or all data if required.
Is this even possible?
(I do not understand VBA code, but I am capable of inserting it into VBA editor and then running said macro).
Any help would be greatly appreciated, thank you!
Not really knowing a lot about the way your data is set up, I build the following, with this code on the worksheet_change event of the dashboard sheet, where I have E6 controlling the year. I have 3 other sheets with data in column A with year numbers, you can use this as a base. You will need to experiment with your column, on the filter, number most likely.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim wsWorksheet As Excel.Worksheet
If Target.Cells(1, 1).Address(False, False) = "E6" and Target.Cells.Count=1 Then
For Each wsWorksheet In ThisWorkbook.Worksheets
With wsWorksheet
If .Name <> Target.Worksheet.Name Then
If .UsedRange.AutoFilter Then
.UsedRange.AutoFilter 1, Target.Value
End If
End If
End With
Next wsWorksheet
End If
End Sub
Public Sub Filter_Sheets()
Dim i As Long
Dim comboBox As ControlFormat
With ThisWorkbook
Set comboBox = .Worksheets(9).Shapes("Drop Down 229").ControlFormat
For i = 1 To Worksheets.Count
.Worksheets(i).UsedRange.AutoFilter Field:=15, Criteria1:=comboBox.List(comboBox.ListIndex)
Next
End With
End Sub
This is the best fit I have managed to discover. I still get an error (AutoFilter method of Range class failed). However this does work. I am now using a combobox to change the auto filter on all 7 sheets as needed. In order to go back to select all, having "<>" in a cell the dropdown references, works to select all the data again.

Formula to hide rows based on the value of a cell

I have a worksheet that contains the names of all managers and their employees, ideally the way this sheet needs to work is that there is a drop down in the top left and when a manager selects their name, all rows that don't have their name against, are hidden, so only their team is shown.
I know auto filtering and having them choose their name would be the easiest way and is a good option to fall back on, but I'm hoping there is a way to do this with VBA or a formula to just hide rows when its not their team when they select their name in the drop down. As i'm trying to create something that's quite slick and looks nice
I did try to do something around having a helper cell to display true and false if the names matched, but came a bit stuck at this point. Tried using the code below, but it doesn't seem to actually be doing anything. Column with TRUE/FALSE is in Col A
Sub TEST()
Dim cell As Range
Application.ScreenUpdating = False
Application.EnableEvents = False
For Each cell In Range("A4:A34")
If cell.Value = "FALSE" Then
cell.EntireRow.Hidden = True
Else
cell.EntireRow.Hidden = False
End If
Next
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Any ideas on how to do this without just using autofilter would be great
Given the following assumptions:
Drop down with Manager name is in cell A1
Column listing manager name for each row is in column A
Data set starts in row 5
Column A is contiguous with no blank spaces
Place the following code into the Worksheet module of the data sheet and change assumptions to fit your data set.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$A$1" and Target.Cells.Count = 1 Then
Application.ScreenUpdating = False
Range("A5:A1000").EntireRow.Hidden = False
Dim mgrList as Range
Set mgrList = Range(Range("A5"),Range("A5").End(xlDown))
Dim mgrCheck as Range
For each mgrCheck in mgrList
mgrCheck.EntireRow.Hidden = mgrCheck <> Target
Next
End If
End Sub
Use an if then else statement with a call that shows/hides the rows that you'd like to show.
If Range("A1").Value = "John Snow" Then
Call Show_John_Snow
Else
If Range("A1").Value = "Daenerys Targaryen" Then
Call Show_Daenerys
Else....
'subroutine
Show_John_Snow
Rows("17:20").EntireRow.Hidden = True 'hide others
Rows("21:53").EntireRow.Hidden = False 'show John Snow
Rows("54:75").EntireRow.Hidden = True 'hide others
I have this data, in which I have Headers at A3:D3, data starting from row 4 to 99.
I tried applying Autofilter, check if this one works for you.
Sub test()
Range("A3:D3").Select
Selection.AutoFilter
ActiveSheet.Range("A3:D99").AutoFilter Field:=2, Criteria1:="0"
ActiveSheet.Range("A3:D99").AutoFilter Field:=2, Criteria1:="1"
End Sub
Here, I selected option named "0" from drop-down filter from Field-2, that is Range A4, and as you told, other cells automatically gets hidden, and the cells corresponding to that criteria only gets visible.
Also I tried with other option "1".
This seems a very difficult or involved way to do this, I have to show students their results without them seeing other students results.
So, one sheet has all the data and on a "front" sheet I call the relevant data for the particular student using index() and match(). Each student has an ID number which is entered, then for confirmation the name is returned then the relevant grades.

Delete entire row if cell contains the string X

I am trying to come up with a way to delete all rows (and shift cells up, if possible) where the website column cell contains the word none. The table contains 5000+ records and this would save me a great amount of time.
I appreciate any suggestions.
This is not necessarily a VBA task - This specific task is easiest sollowed with Auto filter.
1.Insert Auto filter (In Excel 2010 click on home-> (Editing) Sort & Filter -> Filter)
2. Filter on the 'Websites' column
3. Mark the 'none' and delete them
4. Clear filter
Ok I know this for VBA but if you need to do this for a once off bulk delete you can use the following Excel functionality: http://blog.contextures.com/archives/2010/06/21/fast-way-to-find-and-delete-excel-rows/ Hope this helps anyone
Example looking for the string "paper":
In the Find and Replace dialog box, type "paper" in the Find What box.
Click Find All, to see a list of cells with "paper"
Select an item in the list, and press Ctrl+A, to select the entire list, and to select all the "paper" cells on the worksheet.
On the Ribbon's Home tab, click Delete, and then click Delete Sheet Rows.
In the "Developer Tab" go to "Visual Basic" and create a Module. Copy paste the following. Remember changing the code, depending on what you want. Then run the module.
Sub sbDelete_Rows_IF_Cell_Contains_String_Text_Value()
Dim lRow As Long
Dim iCntr As Long
lRow = 390
For iCntr = lRow To 1 Step -1
If Cells(iCntr, 5).Value = "none" Then
Rows(iCntr).Delete
End If
Next
End Sub
lRow : Put the number of the rows that the current file has.
The number "5" in the "If" is for the fifth (E) column
I'd like to add to #MBK's answer. Although I found #MBK's answer to be very helpful in solving a similar problem, it'd be better if #MBK included a screenshot of how to filter a particular column.
This was alluded to in another comment, but you could try something like this.
Sub FilterAndDelete()
Application.DisplayAlerts = False
With Sheet1 'Change this to your sheet name
.AutoFilterMode = False
.Range("A3:K3").AutoFilter
.Range("A3:K3").AutoFilter Field:=5, Criteria1:="none"
.UsedRange.Offset(1, 0).Resize(ActiveSheet.UsedRange.Rows.Count - 1).Rows.Delete
End With
Application.DisplayAlerts = True
End Sub
I haven't tested this and it is from memory, so it may require some tweaking but it should get the job done without looping through thousands of rows. You'll need to remove the 11-Jul so that UsedRange is correct or change the offset to 2 rows instead of 1 in the .Offset(1,0).
Generally, before I do .Delete I will run the macro with .Select instead of the Delete that way I can be sure the correct range will be deleted, that may be worth doing to check to ensure the appropriate range is being deleted.
Try this ...
Dim r as Range
Dim x as Integer
For x = 5000 to 4 step -1 '---> or change as you want //Thanx 4 KazJaw
set r = range("E" & format(x))
if ucase(r.Value) = "NONE" then
Rows(x).EntireRow.Delete
end if
Next
Delete rows 1 and 2 so that your headings are on row 1
Put this in a macro (IT WILL CHECK THROUGH ROW 75000, YOU CAN LOWER THE NUMBER IF YOU WOULD LIKE
Columns("E:E").Select
Selection.AutoFilter
ActiveSheet.Range("$E$1:$E$75000").AutoFilter Field:=1, Criteria1:="none"
Range("E2:E75000").SpecialCells(xlCellTypeVisible).Select
Selection.EntireRow.Delete
ActiveSheet.Cells.EntireRow.Hidden = False
ActiveSheet.Range("$E$1:$E$75000").AutoFilter Field:=1
Columns("E:E").Select
Selection.AutoFilter
Range("E2").Select
Range("A1").Select

Macro for Excel: If Column B has "X", then copy entire row and paste in Worksheet named "Column B"

I have limited experienced of writing macros, and I'm looking to update a current spreadsheet used at work. Currently we copy the entire Master worksheet and paste it into other worksheets before sorting for the "X" in certain columns to delete other rows on the master worksheet.
What I am looking to do is search the Master Sheet, and if Column B has an "X" then copy the entire row and paste it into a worksheet named "Column B". Then, once Column B was completed and pasted, it would look at Column D. If Column D had an "X", it would copy the entire row and paste it in worksheet tab named "Column D".
Thanks in advance!
Approach
I should have included this in the first version of my answer.
My solution depends on AutoFilter. I first offer a play solution that demonstrates this approach by:
making rows not containing X in column B invisible
making rows not containing X in column D invisible
clearing the AutoFilter
If this approach appeals, I refer you to my answer to another question which creates a menu so the user can select which filter they want.
If this approach does not appeal, I offer a second solution which involves copying the visible rows left by each filter to other worksheets.
Introduction
You say "I have limited experienced of writing macros" which I take to mean you have some experience. I hope I have the level of explanations correct. Come back with questions if necessary.
I assume your workbook is on a server. I assume someone has write access to update the master worksheet while others open read-only copies so they can look at the subsets of interest to them. If my assumptions are about right, take a copy of the workbook for you to play with. Don't worry about others updating the master version of the workbook, we will copy the final version of the code from your play version when we have finished.
Step 1
Copy the first block of code to a module within the play version. Near the bottom you will find Const WShtMastName As String = "SubSheetSrc". Replace SubSheetSrc by the name of your master worksheet.
Note: the macros within this block are named CtrlCreateSubSheetB and CreateSubSheetB because they are play versions. The real versions are named CtrlCreateSubSheet and CreateSubSheet.
Run macro CtrlCreateSubSheetB. You will see the Master worksheet but only those rows with an "X" in column B. Click on the message box.You will see the Master worksheet but only those rows with an "X" in column D. Click on the message box and the filter will disappear. Switch to the VB Editor if you are not already there. In the Immediate Window (Click Ctrl+G if it is not visible) and you will see something like:
Rows with X in column 2: $A$1:$G$2,$A$4:$G$5,$A$8:$G$9,$A$11:$G$12,$A$14:$G$14, ...
Rows with X in column 4: $A$1:$G$1,$A$3:$G$3,$A$5:$G$5,$A$7:$G$7,$A$10:$G$10, ...
Now work down macros CtrlCreateSubSheetB and CreateSubSheetB. You must understand how these macro have created the effects you saw. If necessary use VB Help, the Debugger and F8 to step down the macros to identify what each statement is doing. I believe I have given you enough information but come back with questions if necessary.
' Option Explicit means I have to declare every variable. It stops
' spelling mistakes being taken as declarations of new variables.
Option Explicit
' Specify a subroutine with two parameters
Sub CreateSubSheetB(ByVal WShtSrcName As String, ByVal ColSrc As Long)
' This macro applies an AutoFilter based on column ColSrc
' to the worksheet named WShtSrcName
Dim RngVis As Range
With Sheets(WShtSrcName)
If .AutoFilterMode Then
' AutoFilter is on. Cancel current selection before applying
' new one because criteria are additive.
.AutoFilterMode = False
End If
' Make all rows which do not have an X in column ColSrc invisible
.Cells.AutoFilter Field:=ColSrc, Criteria1:="X"
' Set the range RngVis to the union of all visible rows
Set RngVis = .AutoFilter.Range.SpecialCells(xlCellTypeVisible)
End With
' Output a string to the Immediate window.
Debug.Print "Rows with X in column " & ColSrc & ": " & RngVis.Address
End Sub
' A macro to call CreateSubSheetB for different columns
Sub CtrlCreateSubSheetB()
Const WShtMastName As String = "SubSheetSrc"
Dim WShtOrigName As String
' Save the active worksheet
WShtOrigName = ActiveSheet.Name
' Make the master sheet active if it is not already active so
' you can see the different filtered as they are created.
If WShtOrigName <> WShtMastName Then
Sheets(WShtMastName).Activate
End If
' Call CreateSubSheet for column 2 (=B) then column 4 (=D)
Call CreateSubSheetB(WShtMastName, 2)
Call MsgBox("Click to continue", vbOKOnly)
Call CreateSubSheetB(WShtMastName, 4)
Call MsgBox("Click to continue", vbOKOnly)
With Sheets(WShtMastName)
If .AutoFilterMode Then
.AutoFilterMode = False
End If
End With
' Restore the original worksheet if necessary
If WShtOrigName <> WShtMastName Then
Sheets(WShtOrigName).Activate
End If
End Sub
Step 2
If my assumptions about how you use the workbook are correct you may not need much more. If John and Mary each open a read-open copy of the master workbook then John could use the B filter while Mary uses the D filter. If this sounds interesting, look at my answer to copy row data from one sheet to one or more sheets based on values in other cells.
Step 3
If you do not like the idea of just using filters and still want to create copies of the B data and the D data, you will need the code below.
The macros within this block are named CtrlCreateSubSheet and CreateSubSheet but are not much different from the B versions above.
In CtrlCreateSubSheet you will need to replace "SubSheetSrc", "SubSheetB" and "SubSheetD" with your names for these worksheets. Add further calls of CreateSubSheet for any further control columns.
Note: these version delete the original contents of the destination sheets although this is not what you have asked for. I have deleted the original contents because (1) what you have adding new rows is more complicated and (2) I do not believe you are correct. If there is some significance to what you requested then come back and I will update the code.
Option Explicit
Sub CtrlCreateSubSheet()
Const WShtMastName As String = "SubSheetSrc"
' Call CreateSubSheet for column 2 (=B) then column 4 (=D)
Application.ScreenUpdating = False
Call CreateSubSheet(WShtMastName, 2, "SubSheetB")
Call CreateSubSheet(WShtMastName, 4, "SubSheetD")
With Sheets(WShtMastName)
If .AutoFilterMode Then
.AutoFilterMode = False
End If
End With
Application.ScreenUpdating = True
End Sub
Sub CreateSubSheet(ByVal WShtSrcName As String, ByVal ColSrc As Long, _
ByVal WShtDestName As String)
' This macro applies an AutoFilter based on column ColSrc to the worksheet
' named WShtSrcName. It then copies the visible rows to the worksheet
' named WShtDestName
Dim RngVis As Range
Dim WShtOrigName As String
With Sheets(WShtSrcName)
If .AutoFilterMode Then
' AutoFilter is on. Cancel current selection before applying
' new one because criteria are additive.
.AutoFilterMode = False
End If
' Make all rows which do not have an X in column ColSrc invisible
.Cells.AutoFilter Field:=ColSrc, Criteria1:="X"
' Set the range RngVis to the union of all visible cells
Set RngVis = .AutoFilter.Range.SpecialCells(xlCellTypeVisible)
End With
If RngVis Is Nothing Then
' There are no visible rows. Since the header row will be visible even if
' there are no Xs in column ColSrc, I do not believe this block can
' be reached but better to be safe than sorry.
Call MsgBox("There are no rows with an X in column " & ColSrc, vbOKOnly)
Exit Sub
End If
' Copy visible rows to worksheet named WShtDestName
With Sheets(WShtDestName)
' First clear current contents of worksheet named WShtDestName
.Cells.EntireRow.Delete
' Copy column widths to destination sheets
Sheets(WShtSrcName).Rows(1).Copy
.Rows(1).PasteSpecial Paste:=xlPasteColumnWidths
' I do not recall using SpecialPaste column widths before and it did not
' work as I expected. Hunting around the internet I found a link to a
' Microsoft page which gives a workaround. This workaround worked in
' that it copied the column widths but it left row 1 selected. I have
' added the following code partly because I like using FreezePanes and
' partly to unselect row 1.
WShtOrigName = ActiveSheet.Name
If WShtOrigName <> WShtDestName Then
.Activate
End If
.Range("A2").Select
ActiveWindow.FreezePanes = True
If WShtOrigName <> WShtDestName Then
Sheets(WShtOrigName).Activate
End If
' Copy all the visible rows in the Master sheet to the destination sheet.
RngVis.Copy Destination:=.Range("A1")
End With
End Sub
Step 4
Once you have deleveloped the macros to your satisfaction, you will need to copy the module containing the macros from your play version to the master version. You can export the module and then import it but I think the following is easier:
Have both the play and master versions of the workbook open.
Create an empty module in the master version to hold the macros.
Select the macros in the play version, copy them to the scratchpad and then paste them to the empty module in the master version.
You will need to teach whoever is responsible for updating the master version to run the macros whenever a significant update is complete. You could use a shortcut key or add the macro to the toolbar to make the macro easy to use.
Summary
Hope all that makes sense. Do ask questions if necessary.
More simply:
Sub Columns()
If WorkSheets("Sheet1").Range("B1") = x Then
WorkSheets("Column B").Range("B2") = WorkSheets("Sheet1").Range("B2:B" & Rows.Count).End(xlup).Row
End if
If WorkSheets("Sheet1").Range("D1") = x Then
WorkSheets("Column D").Range("D2") = WorkSheets("Sheet1").Range("D2:D" & Rows.Count).End(xlup).Row
End if
End Sub

Moving Rows to another sheet in a workbook

I need Help!
I am not well versed in VBA or Macros but i cannot find any other way to accomplish what i need to do without using it.
I have a sheet which i will be using to track Purchase orders, and what i need to do is; when i have a row in sheet 1 (Purchase Orders) which has been recieved i.e. the date of receipt has been recorded in column H i need for the entire row to be cut and pasted into sheet 2 (Received orders).
The header takes up the first 7 rows the rows, so i need the macro to look at rows 8-54. Once the received items are removed from sheet 1, i need the row to also be deleted or preferably for the list to be sorted by column A moving the now empty row which has been cut from open for a future entry.
Any help would be greatly appreciated.
The "Record Macro" feature should be enough to do the task you describe.. In Excel 2007, go to the Developer tab in the Ribbon, and select "Record Macro", and perform exactly the steps you are describing. It will record the equivalent VBA code, which you can then execute - or tweak/modify.
I tested this out, here's one way to do it:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim receivedDate As Range, nextOpen As Range, isect As Range
Set receivedDate = Sheet1.Range("H8:H54")
Set isect = Application.Intersect(Target, receivedDate)
If Not (isect Is Nothing) And IsDate(Target) = True Then
Set nextOpen = Sheet2.Range("A1").End(xlDown).Offset(1, 0)
Target.EntireRow.Copy Destination:=nextOpen.EntireRow
Target.EntireRow.Delete
End If
Application.EnableEvents = True
End Sub
This would be pasted into the Sheet1 code. Any time a cell is changed on sheet1, the code checks to see if it's in the critical range that you specified. (H8:H54) If it is, it then checks to see if it's a date. If it is, it then copies the entire row, puts it in the next open row on Sheet2, and deletes the original row. The cells below it will get shifted up so there are no gaps.
Since the code functions on a cell changing event, it disables "Application.EnableEvents" in order to avoid a loop of changing a cell to call an event which changes a cell to call an event... etc.

Resources