How to stop Excel from changing the Active Sheet after “Refresh all”? - excel

I have 3 queries (Power Query) in my Excel file that bring information from other different files in table format and in another worksheet I have a button that executes the ThisWorkbook.RefreshAll function.
Sub ButtonRefreshData()
ThisWorkbook.RefreshAll
End Sub
The problem is: Every time I update my queries, either through the button or Excel's own Refresh/Refresh all tool, my Active Worksheet is changed to the tables that I'm refreshing.
I also tried to set the sheet that I want as active after the refresh with something like ThisWorkbook.Sheets("MySheet").Activate, but no results.
How can I update my queries without changing my active sheet?
I'm currently using Excel 2016.
What I'm trying to do: I want the user to be able to update the data in the worksheet, but I don't want him to have direct access to the tables/data in the worksheets that will be hidden. The user must remain in the "main worksheet", which has the update button.

Activate the Previously Active Sheet
I couldn't reproduce your issue. I created two queries but both of them didn't change the ActiveSheet. Here are two ideas, the second being a bit too extreme i.e. it may hang or crash Excel. Your feedback is appreciated.
EDIT
Possibly get rid of all related to ash and just use the explicit Sheet1.Select after twRefresh.
Option Explicit
Sub Test1()
Application.ScreenUpdating = False
Dim ash As Object: Set ash = ActiveSheet
twRefresh
ash.Select
Application.ScreenUpdating = True
End Sub
Sub twRefresh
ThisWorkbook.RefreshAll
End Sub
Initial Ideas
Option Explicit
Sub Test1()
Application.ScreenUpdating = False
Dim ash As Object: Set ash = ActiveSheet
ThisWorkbook.RefreshAll
DoEvents
ash.Select
Application.ScreenUpdating = True
End Sub
Sub Test2()
On Error GoTo ClearError
Application.Visible = False
Dim ash As Object: Set ash = ActiveSheet
ThisWorkbook.RefreshAll
DoEvents
ash.Select
ProcExit:
Application.Visible = True
ClearError:
Debug.Print "Run-time error '" & Err.Number & "': " & Err.Description
Resume ProcExit
End Sub

Another user who had a similar problem reported that he was unable to resolve the issue and he attributed the cause to the version of Excel he was using, which turned out to be the same as mine.
In this sense, I assume that the cause is some bug in the version: Excel 2016 - 16.0.4266.1001
If you are having the same problem, please try to use newer versions.

Related

Updating data in a pivot table workbook from another workbook

I've encountered a strange thing: I've joined three workbooks: Personal Data Tracker, Global Tracker and the workbook with pivots and charts. The logic is as it follows: the user clicks on a button after the work is finished so the data is copied to the GL Tracker. Once the change event is triggered in the GL Tracker Table, the last workbook opens, the pivot is refreshed upon the open vent and the wb is closed.
Everything seems to be working fine, however when I run the macro live, at the very end I get an error message about
"Application-defined or object-defined error".
Only OK and Help button displayed, it doesn't make the VBE Open so I could debug it.
Would anyone know what it may be happening even if the whole chain works fine?
Thank you.
Code from the Personal Tracker:
Sub test()
Dim path As String
Dim wb As Workbook
path = ThisWorkbook.path & "\Dest.xlsm"
Application.ScreenUpdating = False
ThisWorkbook.Sheets("Total").Range("R1").Value = Date
Range("R1").Font.Color = VBA.ColorConstants.vbWhite
Worksheets("TOTAL").Range("B2:B13").Copy
On Error GoTo Handler
Workbooks.Open (path)
On Error GoTo 0
Set wb = Workbooks("Dest")
Worksheets("Sheet1").Range("B2").PasteSpecial Paste:=xlPasteValues
Exit Sub
Handler:
MsgBox "Someone else is saving their data at the moment." & vbNewLine & _
"Please try in a few seconds"
End Sub
Code from the GL Tracker:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim MRange As Range
Dim wbPivot As Workbook
Dim pt As PivotTable
Dim ws As Worksheet
Dim Name As String
Dim answer As VbMsgBoxResult
Set MRange = ThisWorkbook.Sheets(1).Range("Table1")
Name = Application.UserName
Application.ScreenUpdating = False
If Not Intersect(Target, MRange) Is Nothing Then
Application.EnableEvents = True
Set wbPivot = Workbooks.Open("C:\Users\jakub\Desktop\Excel - various\Pivot.xlsm")
End If
'refresh
For Each ws In wbPivot.Worksheets
For Each pt In ws.PivotTables
pt.PivotCache.Refresh
pt.Update
pt.RefreshTable
Next
Next
'saving
Application.ScreenUpdating = True
If Application.UserName <> "Jakub Tracz" Then
MsgBox "User not authorised. Workbook will be closed."
wbPivot.Close True
ThisWorkbook.Close True
Else
answer = MsgBox(Prompt:="Do you want to save and close the workbook?", _
Buttons:=vbYesNo + vbQuestion)
Select Case answer
Case vbYes
wbPivot.Close True
ThisWorkbook.Close True
Case vbNo
MsgBox "Welcome, " & Application.UserName
End Select
End If
End Sub
I'm going to give you a proof of concept code as an example for you to use. This will not exactly answer your question with code you can just copy/paste, but you will be able to use this to put it together the way you want it to work instead of me making assumptions about many things and restructuring it myself.
This simply demonstrates how to use a workbook object variable in one routine that can reference another workbook, and how to make changes to that 2nd workbook and save/close it.
Sub Tracker_Update()
Dim wbPivot as Workbook
' open the workbook
Set wbPivot = Workbooks.Open("C:\Users\jakub\Desktop\Excel - various\Test.xlsx")
' optionally make it hidden
wbPivot.Visible = False
With wbPivot
' pretend this code updates the pivot table
.Worksheets(1).Range("A1") = "hello world"
' Close and save it
.Close True
End With
' optionally clear the variable
' this is not really needed in VBA, but if you eventually
' start using VB.NET with Excel as a COM object,
' you will want to know how to do this part when you are done
Set wbPivot = Nothing
End Sub
I think you will like this approach in the end much better in the end anyway, as the code isn't scattered around so much in different places. Easier to debug later, and easier for someone else to understand what you are doing if and when you leave the company.

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 VBA: On Close Save Prompt after ActiveX Resize Despite Thisworkbook.Saved=True

I've run into an interesting situation with Excel, and I was wondering if anyone of you knew an answer / solution.
Setup:
I have an empty excel worksheet with a ActiveX ToggleButton on it.
In a VBA code, I change the width of the button to 0, and then change the width to 100. (Why I do that is a different question, its part of a larger project, however, this causes the problem).
Then I set the save-status of the workbook to true, without actually saving the workbook.
Normally, if I now closed the workbook, it would just close, without asking me wether I want to save.
Now, due to the resizing, and even though the .Saved-Status is True, it asks me if I want to save when I close the workbook, and by clicking onto the close Icon of excel, the .Saved-Status is set to "False"
If you want to try for yourself, try the below steps.
Alternatively, I uploaded for convenience the same file here: (https://filebin.ca/3aLbbRxMTdUs/SavePromptUponResize.xlsm)
1) create a new workbook and add a new ACTIVEX toggle button.
2) in the VBA code of the workbook, add the below code
3) save the workbook, close it, and reopen it.
4) You should see a messagebox and after clicking, as second one
5) Now the status of the workbook is "saved"
6) Try to close the workbook -> you will be prompted if you want to save
7) If you check the .saved status now, it would say "false"
Looking forward to your insights!
Private Sub Workbook_Open()
MsgBox "Now a macro will run and resize twice the button you see." & vbCrLf & "Afterwards, the status of the workbook will be set to 'saved'." & vbCrLf & "However, upon closing, excel will still prompt to save."
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Sheets(1)
ws.Shapes("ToggleButton1").Width = 0
ws.Shapes("ToggleButton1").Width = 100
wb.Saved = True
MsgBox "Macro finished, save status is: " & wb.Saved
End Sub
Private Sub CheckSaveStatus()
MsgBox "Save status is: " & ActiveWorkbook.Saved
End Sub
The solution is as simple as this:
Private Sub Workbook_Open()
MsgBox "Now a macro will run and resize twice the button you see." & vbCrLf & "Afterwards, the status of the workbook will be set to 'saved'." & vbCrLf & "However, upon closing, excel will still prompt to save."
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Sheets(1)
Dim boolSaved As Boolean
boolSaved = wb.Saved
ws.Shapes("ToggleButton1").Width = 0
ws.Shapes("ToggleButton1").Width = 100
If boolSaved Then wb.Save
MsgBox "Macro finished, save status is: " & wb.Saved
End Sub
This technique can be used anywhere in your code where you need to do something that 'dirties' the workbook. The beauty of it is that it preserves the save prompt if the user has modified the workbook.
As to why it's happening, best guess is - a(nother) ActiveX bug in Excel.
Please try the below:
Option Explicit
Dim wb As Workbook
Dim ws As Worksheet
Dim i As Integer
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If i = 1 Then
wb.Saved = False
Else
wb.Saved = True
End If
End Sub
Private Sub Workbook_Open()
MsgBox "Now a macro will run and resize twice the button you see." & vbCrLf & "Afterwards, the status of the workbook will be set to 'saved'." & vbCrLf & "However, upon closing, excel will still prompt to save."
Set wb = ThisWorkbook
Set ws = wb.Sheets(1)
ws.Shapes("ToggleButton1").Width = 0
ws.Shapes("ToggleButton1").Width = 100
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
i = 1
End Sub
My experience has been that this Excel bug is triggered as a result of using VBA code to change the value of some properties of some ActiveX/OLE controls. I don't have a complete list of such properties but here's a few:
CommandButton:
Enabled property
Height property
TextBox:
ForeColor property
BackColor property
I use a generalized system (similar to Nikolaos Polygenis's solution), including extensive explanation due to this bug's subtlety, as follows:
In a standard module, define a project-global variable to indicate the no-save-needed condition:
'*************************************************************************************************************
'EXCEL OLE/ACTIVE-X SAVE-BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND
'
'(See the Workbook_BeforeClose event handler, in the ThisWorkbook module, for a complete explanation.)
'
Public SuppressWkBkSaveMsg As Boolean
'
'END SAVE-BUG WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND
'*************************************************************************************************************
In the ThisWorkbook module, place the following Workbook_BeforeClose event handler, with full explanation:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'*************************************************************************************************************
'EXCEL OLE/ACTIVE-X SAVE-BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND
'
'Excel has a very subtle bug in which, if you change the value of some properties of some ActiveX/OLE
'controls, the parent workbook's Saved property will not function correctly until the next actual workbook
'save event. That is, you can subsequently set the workbook's Saved property to True but Excel will still
'prompt the user about whether to save the workbook when closing it. In fact, if you check the value of the
'Saved property in a Workbook_BeforeClose event handler, it will be defined as False even though no changes
'have been made to the workbook after explicitly setting it to True!
'
'The most effective workaround is to defer the override of the workbook's Saved property until the Close event
'has been actually initiated: declare the project-global SuppressWkBkSaveMsg variable in a standard module,
'add this Workbook_BeforeClose event handler to the ThisWorkbook module, and then set SuppressWkBkSaveMsg to
'True whenever it's necessary to suppress Excel's user-inquiry about whether to save changes to the workbook
'before closing it.
'
If SuppressWkBkSaveMsg Then Me.Saved = True
'
'END SAVE-BUG WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND
'*************************************************************************************************************
End Sub
In any location in the code, in any module, whenever it's necessary to suppress Excel's user-inquiry about whether to save changes to the workbook before closing it, set SuppressWkBkSaveMsg to True:
'Do stuff that doesn't need to be saved, including modifications to OLE/ActiveX control-objects...
'
'*************************************************************************************************************
'EXCEL OLE/ACTIVE-X SAVE-BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND - BUG WORKAROUND
'
'(See the Workbook_BeforeClose event handler, in the ThisWorkbook module, for a complete explanation.)
'
SuppressWkBkSaveMsg = True
'
'END SAVE-BUG WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND - END WORKAROUND
'*************************************************************************************************************
'
'...

Excel Vba stops excution after deleting sheet

I am new to VBA. I have written a code to delete a particular sheet. After execution of that delete sheet macro, excel macro stopped execution. It didnt execute futher..
Here is my code..
Sub CopyAcross()
Dim sheetName As String
sheetName = "Master_Base"
If WorksheetExists(sheetName) Then
DeleteSheet (sheetName)
End If
MsgBox "Debug"
Workbooks("Master_Base.csv").Sheets("Master_Base").Copy Before:=Workbooks("Copy of test.xlsm").Worksheets("Sheet3")
End Sub
Sub DeleteSheet(strSheetName As String)
' deletes a sheet named strSheetName in the active workbook
Application.DisplayAlerts = False
Sheets(strSheetName).Delete
Application.DisplayAlerts = True
End Sub
Can any one help on this,
Thanks in advance.
I was experiencing the same issue, on a Windows 7 computer with Excel version 16.0.10730.20264 32-bit, the code ran fine without issue. However, on a Windows 10 computer with the same Excel install version, the macro would immediately stop execution following the Sheets.Delete line.
I found that this was only happening where I was attempting to manipulate a workbook that contained VBA code, that I had opened during the macro.
The issue is caused by the macro security settings on the computer. If you set Automation Security to Low before opening the workbook, you should no longer get the error:
Use the code:
Application.AutomationSecurity = msoAutomationSecurityLow
Since you are working with multiple workbooks, use objects. Else your code MAY work with the wrong workbook/worksheet
Try this (UNTESTED)
Sub CopyAcross()
Dim wbI As Workbook, wbO As Workbook
'~~> The workbook from where the code is running
Set wbO = ThisWorkbook
'~~> Here you open the csv
Set wbI = Workbooks.Open("E:\OPM\OPM Sheet\Master_Base.csv")
'~~> This will delete the sheet if it exists
'~~> no need to check if it exists
On Error Resume Next
Application.DisplayAlerts = False
wbO.Sheets("Master_Base").Delete
Application.DisplayAlerts = True
On Error GoTo 0
'~~> The csv will always have 1 sheet
'~~> so no need providing a name
wbI.Sheets(1).Copy Before:=wbO.Worksheets("Sheet3")
End Sub

How to replicate a sheet using VBA Macro (not copy) replicate

How would I replicate a sheet using VBA Macro but not use the VBA copy method?
So I want Sheet2 to look exactly like Sheet1 after.
I am new to VBA Macros so please guide me.
Here are couple of ways
WAY 1 Best way to do it
ThisWorkbook.Sheets("Sheet1").Copy _
After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
Way 2
Sub Sample()
Dim wsToCopy As Worksheet, wsNew As Worksheet
On Error GoTo Whoa:
Set wsToCopy = ThisWorkbook.Sheets("Sheet1")
Set wsNew = ThisWorkbook.Sheets.Add
wsNew.Name = "Copy of " & wsToCopy.Name
wsToCopy.Cells.Copy wsNew.Cells
Exit Sub
Whoa:
MsgBox Err.Description
End Sub
NOTE:
In case you are using Excel 2003, then WAY 2 might be the best way depending on the data. Please SEE THIS

Resources