Cannot execute code at UserInterFaceOnly set to True - excel

I have this code:
Private Sub Workbook_Open()
Dim wSheet As Worksheet
For Each wSheet In Worksheets
wSheet.Protect Password:="Wordpass", _
UserInterFaceOnly:=True
Next wSheet
End Sub
It protects all worksheet in the workbook but allows macro to run.
However, this code:
wb.RefreshAll 'I've declared and set wb accordingly.
doesn't execute at all even though UserIntergFaceOnly is set to True.

The userinterfaceonly flag certainly doesn't work the way I would expect. Generally speaking, I set it, but I often find that I have to bracket things with unprotect and protect. Whenever I get an error, or failure to do something, its the first thing I try.
I apologise for lack of specifics and I will post back later after surveying my code. To be honest, I'm usually so busy with trial and error due to lack of documentation for VBA that I haven't had time to document this type of behaviour yet. But I will in the near future.
But meanwhile, I also try to make sure object reference are a qualified as possible so, in your case for example, I would try:
Thisworkbook.Refreshall
Or
Application.Thisworkbook.Refreshall
Or maybe even
application.workbooks(application.thisworkbook.name)
Failing that, bracket with unprotect/protect contents:=True, userinterfaceonly:=True

Try this
Private Sub Workbook_Open()
Dim wSheet As Worksheet
Dim pt As PivotTable
For Each wSheet In Worksheets
wSheet.Protect Password:="Wordpass", _
UserInterFaceOnly:=True
Next wSheet
End Sub
'~~> Change "Sheet1" to the relevant sheet which has the pivot
Sub UpdatePivot()
With ThisWorkbook.Sheets("Sheet1")
For Each pt In .PivotTables
pt.RefreshTable
DoEvents
Next pt
End With
End Sub

Related

How to run multiple VBA procedures on multiple sheets at once, except for one sheet

I'm trying to run the same set of procedures on all worksheets at once except for the a sheet titled "summary". This is what I've tried, and I keep getting different types of errors. The procedure I'm calling is a procedure that calls other procedures, maybe that is the issue?
Option Explicit
Sub runAll()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "summary" Then
Call Formatting
End If
Next ws
End Sub
Contained in the Formatting sub are more calls.
Sub oracleCogsUniversal()
Call Formatting
Call DeleteDetails
Call addSummary
Call pasteID
Call moveUp
Call formatFile
End Sub
You'll need to debug this. First thing I would do is this:
Option Explicit
Sub runAll()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Debug.print ws.name
Next ws
End Sub
to make sure your sheet names are as you expect. Open the Immediate Window and see what is output. Chances are the name is not "summary" as you expect. If it is not, change your <> "summary" statement to the correct name. Once that is worked out, in your "Formatting" function, remark everything out and reenable each line, or section, one at a time until you find the error.
The only way to get to the bottom of this is to debug it systematically.
In runAll you only call Formatting - did you mean to call oracleCogsUniversal? You don't pass anything to those sub-procedures, so I'm guessing there's no way for them to know which sheet they're supposed to be operating on?
You should be passing ws to oracleCogsUniversal, and that in turn should maybe be passing that worksheet reference on to anything else it calls, so the called code can work on a specific worksheet.
Option Explicit
Sub runAll()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "summary" Then
oracleCogsUniversal ws '<< pass along the `ws` reference; use of Call is deprecated
End If
Next ws
End Sub
Sub oracleCogsUniversal(ws As Worksheet) '<< get `ws` from `runAll`
Formatting ws '<< pass ws to called Sub
DeleteDetails ws
addSummary ws
pasteID ws
moveUp ws
formatFile ws
End Sub
Sub Formatting(ws As Worksheet)
ws.Rows(1).Font.Bold = True 'work directly on `ws`
End Sub

Protecting Sheets stops Macro from working

I know there are lots of questions on this, which I have read - but none seem to give me the code I need to make this work.
I have a number of buttons that I have placed in the Ribbon of my excel sheet. These are attached to macros that copy sheets onto another sheet, as an example
The macro is ran by pressing the button:
Sub btnSheet1_onAction(control As IRibbonControl)
mFunction.CopySheet1toSheet2
End Sub
The macro is contained in my mFunction module as :
Public Sub CopySheet1toSheet2()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
ws.Cells.Copy Destination:=ThisWorkbook.Sheets(2).Cells
End Sub
Now.... I need to protect items/cells in sheet 1 and 2. When I protect the sheets the macros make excel crash - no runtime errors or anything.
I have inserted the following code into the 'ThisWorkbook'
Private Sub Workbook_Open()
Sheets(1).Protect Password:="secret", UserInterFaceOnly:=True
Sheets(2).Protect Password:="secret", UserInterFaceOnly:=True
End Sub
But it still doesn't work - I have also tried with the following code in the mFunction module
Public Sub CopySheet1toSheet2()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
ws.Unprotect Password = "secret"
ws.Cells.Copy Destination:=ThisWorkbook.Sheets(2).Cells
ws.Protect Password = "secret"
End Sub
But that doesn't seem to work either - I am guessing it might be something to do with the fact that the macro is copying the sheet into another sheet that is locked also?
I should also note that there are other sheets in the workbook that are protected, but that do not have macros attached to them, so they stay protected, could this be causing an issue?
Some help would be greatly appreciated!!
UserInterFaceOnly
When you save a Workbook with sheets that have been protected using UserInterFaceOnly, this property is removed on the file that is saved. So on reopening the file the sheets will remain protected but can not be changed programmatically either.
So, regarding this piece of code, which on first glance appears to do exactly what you need:
Private Sub Workbook_Open()
Sheets(1).Protect Password:="secret", UserInterFaceOnly:=True
Sheets(2).Protect Password:="secret", UserInterFaceOnly:=True
End Sub
.. if you save and reopen your file, when your above Workbook_Open() runs it will fail to set the protection as there is already protection in place.
The workaround is to include lines for each sheet that remove any protection in place first. Then you can set it again correctly - like so:
Private Sub Workbook_Open()
Sheets(1).Unprotect Password:="secret"
Sheets(2).Unprotect Password:="secret"
Sheets(1).Protect Password:="secret", UserInterFaceOnly:=True
Sheets(2).Protect Password:="secret", UserInterFaceOnly:=True
End Sub
This should then allow your copy code to run without issue as I can't see much wrong with that part at all.
Incidentally, if your passwords are the same, you could tidy it up slightly with:
Private Sub Workbook_Open()
Dim sh As Worksheet
For Each sh In Array(Sheets(1), Sheets(2))
sh.Unprotect Password:="secret"
sh.Protect Password:="secret", UserInterFaceOnly:=True
Next
End Sub
Okay - so I have used this as a work around, but if anyone can give a more eloquent solution that would be great:
Dim ws As Worksheet
Set ws1 = ThisWorkbook.Worksheets(1)
Set ws2 = ThisWorkbook.Worksheets(2)
ws1.Unprotect ("2402")
ws2.Unprotect ("2402")
ws1.Cells.Copy Destination:=ws2.Cells
ws1.Protect ("2402")
ws2.Protect ("2402")

Excel: EnableOutlining seems to default to False on opening workbook

Like many other people, I want to be able to enable grouping and ungrouping with the little +/- buttons on a protected worksheet. Everyone seems to have succeeded with the same sort of code that protects the worksheet, enables outlining and then unprotects it again, which is great and it works except if I save the sheet and then re-open it again EnableOutlining is always set as False, and if the sheet is protected I cannot use the +/- buttons. Is there something else I am supposed to do to save this setting permanently, and not just for the duration of the session?
Here's the code I have been using:
Private Sub Workbook_Open()
MsgBox ActiveSheet.EnableOutlining
End Sub
Sub EnableOutliningWithProtection_AllSheets()
'PURPOSE: Allow Outline functionality during Protection in all Sheets
'SOURCE: www.TheSpreadsheetGuru.com/the-code-vault
'(Except edited by me to include the Errorcatch)
Dim sht As Worksheet
On Error GoTo Errorcatch
'Loop through each Worksheet in ActiveWorkbook
For Each sht In ActiveWorkbook.Worksheets
'Password Protect Current Sheet
sht.Protect Password:="", UserInterfaceOnly:=True
'Enable Group Collapse/Expand Capabilities
sht.EnableOutlining = True
'Unprotect Sheet
sht.Unprotect ""
Next sht
Exit Sub
Errorcatch:
MsgBox Err.Description
End Sub
(I've got the Workbook_Open() bit to check if EnableOutlining was still True)
I've seen the 'protect UserInterfaceOnly and EnableOutlining' question, but I didn't think the results applied as the code was written for C#, and I'm not looking at protecting UserInterfaceOnly.
You can't save it permanently. You have to use the Open event to reset it when the workbook is opened.
Private Sub Workbook_Open()
EnableOutliningWithProtection_AllSheets
End Sub

Excel 2013 VBA Clear All Filters macro

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

Excel VBA setting multiple sheets as a variable

I have a workbook that is used for project payback over a number of years. I have set up some code in ThisWorkbook to lock the results worksheets, but allow users to open or close column groups (to allow them to hide or unhide the month columns of each year). My current code, which works nicely, looks like this:
Sheet10.Protect Password:="password", UserInterfaceOnly:=True
Sheet10.EnableOutlining = True
Sheet11.Protect Password:="password", UserInterfaceOnly:=True
Sheet11.EnableOutlining = True
and so on for 4 more sheets (and it works).
What I would like to do is, define a variable that stores the sheet identifiers and run a For Each / Next loop on the real code.
But I cannot get a variable declaration to work that doesn't throw some compile or runtime error.
My favourite construction is
Dim wSheet as Worksheet
wSheet = Array(Sheet10, Sheet11, Sheet14)
For Each wSheet in Workbook
wSheet.Protect Password:="password", UserInterfaceOnly:=True
wSheet.EnableOutlining = True
Next wSheet
But it fails on my setting wSheet... I have tried several variants but it nearly always fails on that second line (doesn't matter whether I use sheet index, sheet name etc). Any thoughts?
The problem in your code is the declaration in the first line:
Dim wSheet as Worksheet
either make it an array declaration:
Dim wSheet() as Worksheet
or make it a variant like this:
Dim wSheet as Variant
or this:
Dim wSheet
I couldn't get the first posted answer to work. Here's what worked for me, taken from an answer to this question posted by user #Dee:
Sub Test()
Dim sheetsArray As Sheets
Set sheetsArray = ActiveWorkbook.Sheets(Array("Sheet1", "Sheet2", "Sheet3"))
Dim sheetObject As Worksheet
' change value of range 'a1' on each sheet from sheetsArray
For Each sheetObject In sheetsArray
'Do something
Next sheetObject
End Sub

Resources