excel: advanced filter with protected sheet - vba

I have this sheet where I use Advanced Filter to search for informations inside another sheet in my workbook.
In addition, I want to protect sheet because I have some formulas on cells that people shouldn't be able to change but I also have cells that the user should come with some information then I've already unlocked these cells as you can see below:
The problem is when I try to run my Advanced Filter when I click my "Filter" button. I get an error message that says:
Advanced Filter can't run in Protected Sheet.
So I associated this code to my "Filter" button:
Private Sub Filtrar_Click()
Dim wks As Worksheet
For Each wks In ActiveWorkbook.Worksheets
wks.Unprotect "Password"
Call LimparAntes
wks.Protect "Password", UserInterfaceOnly:=True
Next
End Sub
The LimparAntes sub is the routine that calls Advanced Filter, but I still get the same mistake so I'm in doubt. The code is below:
Sub LimparAntes()
'
' LimparAntes Macro
'
'
Dim Lastrow As Long
Lastrow = Sheets("AUX").Range("A" & rows.Count).End(xlUp).Row
Sheets("AUX").Range("A1:K" & Lastrow).AdvancedFilter Action:=xlFilterCopy, _
CriteriaRange:=Sheets("CONSULTA").Range("D34:I35"), CopyToRange:=Sheets("CONSULTA").Range("B40:K40"), Unique:= _
False
Sheets("CONSULTA").Range("F37").Select
End Sub
Is that the correct way to do that? I've made a lot of research but I couldn't find anyone with the same problem with Advanced Filter as I so I don't even know if it's possible to achieve what I want.

Is this all of the code?
Just from looking at the code without executing it, the first steps should be to unlock/unprotect ALL sheets by doing:
Dim wks As Worksheet
For Each wks In ActiveWorkbook.Worksheets
wks.Unprotect "Password"
Next
Then upon completion, you should run LimparAntes(). That will then copy/filter the data you need. And then finally you should lock the sheets.
Private Sub Filtrar_Click()
Dim wks As Worksheet
For Each wks In ActiveWorkbook.Worksheets
wks.Unprotect "Password" 'Unprotect all sheets first
Next
Call LimparAntes 'Call filter sub
For Each wks In ActiveWorkbook.Worksheets
wks.Protect "Password", UserInterfaceOnly:=True 'Re-Protect all sheets
Next
End Sub
Try this and see if it removes the error. If not, I have read that setting the autofilter property to True prior to locking the sheet may be beneficial.

Related

Copy/Paste Macro Pasting Randomly

I am having an issue copying and pasting a drop-down data validation menu from one sheet into all selected sheets. The drop-down menu seems to paste randomly instead of pasting into sheet "B22" of the selected sheets.
Sub TEST()
Dim sht As Worksheet
Sheets("Sheet2").Range("B22").Copy
'Sheets selection should be done before running macro
Selection.Range("B22").PasteSpecial xlPasteValidation
Application.CutCopyMode = False
End Sub
Any suggestions on how to tackle this? I am having some difficulty finding the error in my code.
In case you want to work with the workbook and avoid using copy/paste..
Option Explicit
Sub Test()
Dim excel_sheet As Worksheet
Dim sht As Worksheet
Dim drop_down_value As Range
Set sht = ThisWorkbook.Sheets("Sheet2")
Set drop_down_value = sht.Range("B22")
'Sheets selection should be done before running macro
For Each excel_sheet In ThisWorkbook.Windows(1).SelectedSheets
excel_sheet.Range("B22").Value = drop_down_value.Value
Next
End Sub
Try the following, you need to loop through all selected Sheets instead of using Selection.Range:
Sub TEST()
Dim sht As Worksheet
Sheets("Sheet2").Range("B22").Copy
'Sheets selection should be done before running macro
For Each sht In ActiveWindow.SelectedSheets
sht.Range("B22").PasteSpecial xlPasteValidation
Application.CutCopyMode = True
Next
End Sub

VBA Hide all sheets that aren't being used in workbook

I have many sheets in a workbook. I have a main sheet/"form" called "JE" and on that sheet there are buttons and macros that lead to other sheets in the workbook. But, the intention is for other users, not myself, to use the workbook. So, I would only like the sheet that is being used to be visible at any given time. At no time do I want more than 1 sheet to be visible by the user. The user can navigate the workbook mainly thru clicking buttons and certain cells in select sheets that will allow them to navigate throughout the entire workbook. I have tried this by adding code into 'ThisWorkbook' module but it doesn't seem to working as I'd like. When I navigate to one sheet and back to another, some sheets remain visible when I'd like them to be hidden so I'm unsure of what other modifications I can make to code below to get my desired result. If anyone can offer up any modifications or changes I can make to accomplish this, I'd really appreciate it.
UPDATE:
I have added this code to my 'ThisWorkbook' Object:
Option Explicit
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim MySh As Worksheet
For Each MySh In ThisWorkbook.Worksheets
If MySh.Name <> Sh.Name Then MySh.Visible = 0
Next MySh
End Sub
but, when I go to double-click values that usually populate cells in my main sheet ("JE") I get a run-time 1004 error. The values still populate the main sheet but it no longer navigates back to the main sheet as I'd like.
If anyone knows of a solution or a mod I can make, I'd really appreciate it.
The code is nice. Simply put it in the Workbook part of the VBA project:
Option Explicit
Private Sub Workbook_Open()
Dim MySh As Worksheet
For Each MySh In ThisWorkbook.Worksheets
If MySh.Name = ActiveSheet.Name Then MySh.Visible = xlSheetHidden
Next MySh
End Sub
The ThisWorkbook part is here:
In general, I use always something similar, when I am starting an Excel application. I define two Arrays with Visible and Invisible Worksheets and I iterate over them, making them either visible or not visible. Like this:
Option Explicit
Public Sub HideNeeded()
Dim varSheet As Variant
Dim arrVisibleSheets As Variant
Dim arrHiddenSheets As Variant
arrVisibleSheets = Array(Sheet1)
arrHiddenSheets = Array(Sheet2, Sheet3)
For Each varSheet In arrVisibleSheets
varSheet.Visible = xlSheetVisible
Next varSheet
For Each varSheet In arrHiddenSheets
varSheet.Visible = xlSheetVeryHidden
Next varSheet
End Sub
xlSheetVeryHidden makes it possible to unhide it only from the VB Editor. Otherwise you need xlSheetHidden.
It should be Workbook_SheetActivate:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim MySh As Worksheet
For Each MySh In ThisWorkbook.Worksheets
If MySh.Name <> Sh.Name Then MySh.Visible = 0 'zero - false, 1 - true, 2 - very hidden
Next MySh
End Sub
Sub HideInactive()
Set theActiveSheet = ActiveSheet
For Each Sheet In ThisWorkbook.Worksheets
If Sheet.Index <> theActiveSheet.Index Then Sheet.Visible = False
Next
End Sub
I 've test the code. Thank you for reading.

Making VBA apply to renamed tabs & all tabs in a workbook

I don't know very much at all about VBA, but I found the below code on a website and am using it in a workbook.
Private Sub Workbook_Open()
With Worksheets("WFD")
.EnableOutlining = True
.Protect Password:="XXXX", _
Contents:=True, UserInterfaceOnly:=True
End With
End Sub
How should I amend this so that if the Sheet name is changed from "WFD" to something else, the code still works? Also I would like it to apply to all sheets in the workbook.
Thanks very much
If you want this code for each worksheet use code below:
Private Sub Workbook_Open()
Dim ws As Worksheet
For Each ws In Worksheets
With ws
.EnableOutlining = True
.Protect Password:="XXXX", _
Contents:=True, UserInterfaceOnly:=True
End With
Next
End Sub
You should use the Sheet Object Codename.
This is found in the VB Editor beside the sheet objects in the VB project.
By default they are Sheet1, Sheet2 etc. You can easily change them by clicking and typing a new name etc.
You could of course leave them as default codeName if you like...
This is NOT the same as the worksheet name, which is changed by users on the Sheet tabs in Excel interface.
Private Sub Workbook_Open()
With WFD 'where WFD is the CODENAME of the Sheet Object!
.EnableOutlining = True
.Protect Password:="XXXX", _
Contents:=True, UserInterfaceOnly:=True
End With
End Sub
You could write Worksheets(1) or Worksheets(5), depending on the number of the Worksheet. However, if you start adding and deleting Worksheets, it whould not work (e.g., it would be working on some other worksheet). To see the associated number to the worksheet, run this and check the immediate window:
Option Explicit
Public Sub TestMe()
Dim ws As Worksheet
Dim cnt As Long
For cnt = 1 To ThisWorkbook.Worksheets.Count
Debug.Print cnt; "-> "; Worksheets(cnt).name
Next cnt
End Sub
However, if you have only one Worksheet, Worksheets(1) would always work.

Hide excel worksheet via VBA

I have a workbook that has a number of worksheets each one with a colaborator name on it (Windows login username).
I've tried via VBA to loop through all Worksheets to match the actual Windows Logged On username with the matching Worksheet, and after the match is done, only that Worksheet is kept visible (with all the others being hiden).
I've managed to do this partially but i can only do it untill it finds the matching worksheet. For example, if the matching username is the third worksheet (in a total of ten for example) the code stops there. I want it to run through all worksheets and only then hide the non matching Worksheets.
First i have the following module:
Sub WorksheetFilter()
Dim Username As String
Dim Worksheetname As String
Worksheetname = ActiveWorkbook.ActiveSheet.Name
Username = Environ("Username")
If Worksheetname <> Username Then
ActiveSheet.Visible = False
End If
End Sub
Then, i call the previous module on the Workbook_Open() event:
Option Explicit
Dim WS As Worksheet
Private Sub Workbook_Open()
For Each WS In ActiveWorkbook.Worksheets
WorksheetFilter
Next
End Sub
Any hints on how this can be achieved?
Thanks,
VĂ­tor
Use the code below, and put it in the Workbook module under the Workbook_Open event.
Just loop through all sheets and compare each one with the username.
Option Explicit
Public Sht As Worksheet
Private Sub Workbook_Open()
For Each Sht In ThisWorkbook.Sheets
If Sht.Name = Environ("Username") Then
Sht.Visible = xlSheetVisible
Else
Sht.Visible = xlSheetHidden
' option 2: use very hidden, only able to unhide through code (unable to unhide using right-click)
'Sht.Visible = xlSheetVeryHidden
End If
Next Sht
End Sub
Please see below: chopped your code around a bit. You do not need to defien the worksheets name. This is for the module level, you can call it in the workbook open event as per usual
Option Explicit
Dim ws As Worksheet
Dim Username As String
Sub WorksheetFilter()
Username = Environ("Username")
For Each ws In ActiveWorkbook.Worksheets
If ws.Name <> Username Then
ws.Visible = False
Else
ws.Visible = True
End If
Next ws
End Sub
Please let me know how this works for you! :)

Create an IF statement to check and remove the advanced filter [duplicate]

It seems older macros are not working. I have proper securtiy set to run VBA macros but when I have tried a few methods for clearing ALL filters on a worksheet, I get a compile error.
Here is what I have tried:
Sub AutoFilter_Remove()
'This macro removes any filtering in order to display all of the data but it does not remove the filter arrows
ActiveSheet.ShowAllData
End Sub
I have buttons on the sheets to clear all filters for ease of use for users since the sheets has a lot of columns that have filters on them.
Try this:
If ActiveSheet.AutoFilterMode Then ActiveSheet.ShowAllData
ShowAllData will throw an error if a filter isn't currently applied. This will work:
Sub ResetFilters()
On Error Resume Next
ActiveSheet.ShowAllData
End Sub
If the sheet already has a filter on it then:
Sub Macro1()
Cells.AutoFilter
End Sub
will remove it.
For tables try this to check if it's on and turn off:
If wrkSheetCodeName.ListObjects("TableName").ShowAutoFilter Then
wrkSheetCodeName.ListObjects("TableName").Range.AutoFilter
End if
To Turn back on:
wrkSheetCodeName.ListObjects("TableName").Range.AutoFilter
this works nice.!
If ActiveSheet.AutoFilterMode Then Cells.AutoFilter
That is brilliant, the only answer I found that met my particular need, thanks SO much for putting it up!
I made just a minor addition to it so that the screen didn't flash and it removes and subsequently reapplies the password on each sheet as it cycles through [I have the same password for all sheets in the workbook]. In the spirit of your submission, I add this to assist anyone else....
Sub ClearFilters()
Application.ScreenUpdating = False
On Error Resume Next
For Each wrksheet In ActiveWorkbook.Worksheets
'Change the password to whatever is required
wrksheet.Unprotect Password:="Albuterol1"
wrksheet.ShowAllData 'This works for filtered data not in a table
For Each lstobj In wrksheet.ListObjects
If lstobj.ShowAutoFilter Then
lstobj.Range.AutoFilter 'Clear filters from a table
lstobj.Range.AutoFilter 'Add the filters back to the table
End If
'Change the password to whatever is required
wrksheet.Protect Password:="Albuterol1", _
DrawingObjects:=True, _
Contents:=True, _
Scenarios:=True, _
AllowFiltering:=True
Next 'Check next worksheet in the workbook
Next
Application.ScreenUpdating = True
End Sub
I know this is a relatively old post and don't really like being a necromancer... But since I had the same issue and tried a few of the options in this thread without success I combined some of the answers to get a working macro..
Hopefully this helps someone out there :)
Sub ResetFilters()
On Error Resume Next
For Each wrksheet In ActiveWorkbook.Worksheets
wrksheet.ShowAllData 'This works for filtered data not in a table
For Each lstobj In wrksheet.ListObjects
If lstobj.ShowAutoFilter Then
lstobj.Range.AutoFilter 'Clear filters from a table
lstobj.Range.AutoFilter 'Add the filters back to the table
End If
Next 'Check next worksheet in the workbook
Next
End Sub
There are two types of filters in Excel:
Auto Filter
Advanced Filter
The Auto Filter feature lets you filter from the excel interface using those tiny dropdown buttons. And the Advanced filter feature lets you filter using a criteria range.
The ShowAll method removes the filters, as in, shows all the rows, but does not get rid of those Drop Down buttons. You have to set the AutoFilterMode property of the worksheet to FALSE to remove those buttons.
Here is a Sub that I use frequently to remove filters:
Sub RemoveFilters(ByRef WhichSheet As Worksheet)
If WhichSheet.FilterMode Then WhichSheet.ShowAllData
If WhichSheet.AutoFilterMode Then WhichSheet.AutoFilterMode = False
End Sub
This shows all the data, and removes the dropdown buttons. It comes in handy while stacking (copying and pasting) data from multiple sheets or workbooks. Hope this helps.
I found this workaround to work pretty effectively. It basically removes autofilter from the table and then re-applies it, thus removing any previous filters. From my experience this is not prone to the error handling required with the other methods mentioned here.
Set myTable = YOUR_SHEET.ListObjects("YourTableName")
myTable.ShowAutoFilter = False
myTable.ShowAutoFilter = True
This will work too:
If ActiveSheet.FilterMode Then cells.AutoFilter
I usually use this code
Sub AutoFilter_Remove()
Sheet1.AutoFilterMode = False 'Change Sheet1 to the relevant sheet
'Alternatively: Worksheets("[Your Sheet Name]").AutoFilterMode = False
End Sub
This will first check if AutoFilterMode is set (filtering is possible), then check if FilterMode is on (you are filtering on something) then turn off filtering.
Regarding Errors, i.e. protection - se other answers
Context added (my script is looping over sheets, which are then saved as CSV, hence the need to remove filters - but keep AutoFilterMode on, if set:
For Each WS In ActiveWorkbook.Worksheets
Select Case WS.Name
Case "01", "02", "03", "04", "05"
With WS
If WS.AutoFilterMode Then
If WS.FilterMode Then WS.ShowAllData
End If
' Processing data
End With
Case Else
' Nothing to see here
End Select
Next
Try something like this:
Sub ClearDataFilters()
'Clears filters on the activesheet. Will not clear filters if the sheet is protected.
On Error GoTo Protection
If ActiveWorkbook.ActiveSheet.FilterMode Or _
ActiveWorkbook.ActiveSheet.AutoFilterMode Then _
ActiveWorkbook.ActiveSheet.ShowAllData
Exit Sub
Protection:
If Err.Number = 1004 And Err.Description = _
"ShowAllData method of Worksheet class failed" Then
MsgBox "Unable to Clear Filters. This could be due to protection on the sheet.", _
vbInformation
End If
End Sub
.FilterMode returns true if the worksheet is in filter mode. (See this for more information.)
See this for more information on .AutoFilter.
And finally, this will provide more information about the .ShowAllData method.
Here's the one-liner I use. It checks for an auto-filter and if found, removes it.
Unlike some answers, this code won't create an auto-filter if used on a worksheet that is not auto-filtered in the first place.
If Cells.AutoFilter Then Cells.AutoFilter
All you need is:
ActiveSheet.AutoFilter.ShowAllData
Why? Like the worksheet, AutoFilter also has a ShowAllData method, but it doesn't throw an error even when auto filter is enabled without an active filter.
This works best for me.
I usually use the following before I save and close the files.
Sub remove_filters
ActiveSheet.AutofilterMode = False
End Sub
Simply activate the filter headers and run showalldata, works 100%. Something like:
Range("A1:Z1").Activate
ActiveSheet.ShowAllData
Range("R1:Y1").Activate
ActiveSheet.ShowAllData
If you have the field headers in A1:Z1 and R1:Y1 respectively.
Im using .filtermode if filter is on it returns true
Dim returnValue As Boolean
returnValue = worksheet1.FilterMode
if returnValue Then
worksheet1.ShowAllData
End If
Try this:
Sub ResetFilters()
Dim ws As Worksheet
Dim wb As Workbook
Dim listObj As ListObject
For Each ws In ActiveWorkbook.Worksheets
For Each listObj In ws.ListObjects
If listObj.ShowHeaders Then
listObj.AutoFilter.ShowAllData
listObj.Sort.SortFields.Clear
End If
Next listObj
Next ws
End Sub
This Code clears all filters and removes sorting.
Source: Removing Filters for Each Table in a Workbook, VBA
Here is some code for fixing filters. For example, if you turn on filters in your sheet, then you add a column, then you want the new column to also be covered by a filter.
Private Sub AddOrFixFilters()
ActiveSheet.UsedRange.Select
' turn off filters if on, which forces a reset in case some columns weren't covered by the filter
If ActiveSheet.AutoFilterMode Then
Selection.AutoFilter
End If
' turn filters back on, auto-calculating the new columns to filter
Selection.AutoFilter
End Sub
This thread is ancient, but I wasn't happy with any of the given answers, and ended up writing my own. I'm sharing it now:
We start with:
Sub ResetWSFilters(ws as worksheet)
If ws.FilterMode Then
ws.ShowAllData
Else
End If
'This gets rid of "normal" filters - but tables will remain filtered
For Each listObj In ws.ListObjects
If listObj.ShowHeaders Then
listObj.AutoFilter.ShowAllData
listObj.Sort.SortFields.Clear
End If
Next listObj
'And this gets rid of table filters
End Sub
We can feed a specific worksheet to this macro which will unfilter just that one worksheet. Useful if you need to make sure just one worksheet is clear. However, I usually want to do the entire workbook
Sub ResetAllWBFilters(wb as workbook)
Dim ws As Worksheet
Dim wb As Workbook
Dim listObj As ListObject
For Each ws In wb.Worksheets
If ws.FilterMode Then
ws.ShowAllData
Else
End If
'This removes "normal" filters in the workbook - however, it doesn't remove table filters
For Each listObj In ws.ListObjects
If listObj.ShowHeaders Then
listObj.AutoFilter.ShowAllData
listObj.Sort.SortFields.Clear
End If
Next listObj
Next
'And this removes table filters. You need both aspects to make it work.
End Sub
You can use this, by, for example, opening a workbook you need to deal with and resetting their filters before doing anything with it:
Sub ExampleOpen()
Set TestingWorkBook = Workbooks.Open("C:\Intel\......") 'The .open is assuming you need to open the workbook in question - different procedure if it's already open
Call ResetAllWBFilters(TestingWorkBook)
End Sub
The one I use the most: Resetting all filters in the workbook that the module is stored in:
Sub ResetFilters()
Dim ws As Worksheet
Dim wb As Workbook
Dim listObj As ListObject
Set wb = ThisWorkbook
'Set wb = ActiveWorkbook
'This is if you place the macro in your personal wb to be able to reset the filters on any wb you're currently working on. Remove the set wb = thisworkbook if that's what you need
For Each ws In wb.Worksheets
If ws.FilterMode Then
ws.ShowAllData
Else
End If
'This removes "normal" filters in the workbook - however, it doesn't remove table filters
For Each listObj In ws.ListObjects
If listObj.ShowHeaders Then
listObj.AutoFilter.ShowAllData
listObj.Sort.SortFields.Clear
End If
Next listObj
Next
'And this removes table filters. You need both aspects to make it work.
End Sub
This will clear only if you have filter and does not cause any error when there arent any filter.
If ActiveSheet.AutoFilterMode Then ActiveSheet.Columns("A").AutoFilter
I am using this approach for a multi table and range sheet as a unique way.
Sub RemoveFilters(Ws As Worksheet)
Dim LO As ListObject
On Error Resume Next
Ws.ShowAllData
For Each LO In Ws.ListObjects
LO.ShowAutoFilter = True
LO.AutoFilter.ShowAllData
Next
Ws.ShowAllData
End Sub
Wow. Logging in afterwards deleted all but a portion of the first line. My mistake. However, this will be terse.
For both tests
Enter text in A1 and A5 of Sheet1
Filter for blanks only.
Run either test
Enter text in A5
Try to filter!
Sub SubsequentFilterFails()
With Sheet1 'assumes code name is still Sheet1
.ShowAllData 'assumes a filter has been applied
.Range(.Cells(2, 1), .Cells(7, 1)).EntireRow.Delete
End With
End Sub
Sub SubsequentFilterWorks()
With Sheet1
.Cells.AutoFilter
.Range(.Cells(2, 1), .Cells(7, 1)).EntireRow.Delete
.Cells.AutoFilter
End With
End Sub
Thus, when filters are being cleared in order to clean the worksheet .Cells.AutoFilter will be used.
Loop AutoFilter columns, if column is activated(on) then reset a column filter, you may insert a new criteria after a loop. This code does not remove AutoFilter banner.
Dim iCol as Long
Dim ws as Worksheet
...
For iCol = 1 To ws.AutoFilter.Filters.count
If ws.AutoFilter.Filters(iCol).On Then ws.AutoFilter.Range.AutoFilter Field:=iCol
Next
...
ws.AutoFilter.Range.AutoFilter Field:=4, Criteria1:="AABBCC"
I found this answer in a Microsoft webpage
It uses the AutoFilterMode as a boolean .
If Worksheets("Sheet1").AutoFilterMode Then Selection.AutoFilter
You must select range of the table first before using ActiveSheet.ShowAllData