RTD.RefreshData crashes when invoked from modal form - excel

I have created a very simple modal form with two buttons: one just closes the form, and the other calls Application.RTD.RefreshData. In Excel 2003 this all works just fine, but in Excel 2010 the Application.RTD.RefreshData crashes with
Run-time error '1004': Application-defined or object-defined error
If I create the form as modeless everything works fine in both Excel 2003 and Excel 2010.
For what it's worth, this is all the code behind the form:
Private Sub RefreshDataButton_Click()
Application.RTD.RefreshData
End Sub
Private Sub CloseButton_Click()
Call Unload(Me)
End Sub
And I invoke the form using this code in my sheet:
Private Sub CommandButton1_Click()
Dim form As UserForm1
Set form = New UserForm1
form.Show vbModal
End Sub
I've scoured Google and SO for any information on this to no avail. Is it a known issue with Excel 2010, or am I really not allowed to call Application.RTD.RefreshData from a modal form?
EDIT: I should add that as far as I can tell there are no RTD servers in my Excel session.
EDIT2: Further investigation: the error does not occur in Excel 2003 or 2007; it does occur in 2010 and 2013.

In a normal RTD server, you use the excel callback to call UpdateNotify(), and then Excel will decide when to call RefreshData() based on the throttle settings and how "busy" it currently is. The definition of "busy" normally includes things like formula recalculations, saving the sheet, and having a modal dialog open.
Excel protects itself from external components when it considers itself busy by throwing an exception. This makes sense, as they don't want their application becoming unstable or locking up because of a greedy addin or macro. Essentially all calls you put in your code which access any part of the Excel object model (including your call to RefreshData()) can throw an exception if Excel decides it is "busy". I suspect that in later versions of Excel they have tightened their definition of "busy", which is why you are seeing this disparity with the modal dialog.

Related

How to make application level event handlers in VBA?

I have a VBA add-in that sits in a shared file drive that three users in my organization have added to their Excel. I thought the add-in would be handy because I could push changes to the code without updating the code in any individual Excel sheets. When I tried updating the code in the add-in, the add-in was read-only because other users had Excel open. I've been trying to figure out how to make the add-in read only whenever anyone else (meaning anyone other than me) opens an instance of Excel. I've added the below code to a class module in my add-in. I've tried debugging, but no part of the below code is executed when a user opens a new workbook. I'm totally stuck.
Private WithEvents App As Excel.Application
Private Sub Workbook_Open()
Set App = Application
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
If App.UserName <> "Andrew Lubrino" Then
SetAttr "C:\FilePath\Add-in.xlam", vbReadOnly
End If
End Sub
I've found a number of posts on this topic all with accepted code for seemingly the same problem, but the code simply doesn't work in my environment. Can anyone tell me what's going wrong?
edit:
I'm trying to make the add-in read only for all other users so that when I try to edit and make changes to the distributed code, I can save those changes. With the current set up, I can't save the code whenever any other user has Excel open. For the above code to work, you'd need the event to trigger for any workbook that another user opens

Read Excel VBA Macro Security Settings

I have created a macro-enabled Excel workbook that requires users to have "Trust access to the VBA project object model" enabled in the Excel Macro Security settings.
I forgot I had already done this, and my coworker got stuck on (not responding) when trying to run the macro.
This window can also be brought up with this code:
Application.CommandBars.ExecuteMso("MacroSecurity")
Can I programmatically determine the value of this checkbox with VBA? I'd like to be able to check whether a user has this feature enabled before allowing them to run the macro that could potentially hang up their machine.
Thanks, y'all
Private Function VBATrusted() As Boolean
On Error Resume Next
VBATrusted = (Application.VBE.CommandBars.Count) > 0
End Function

Excel Crashes Intermittently When Clicking Macro Button in Rapid Succession

When a VBA macro button (not AcitveX button) is clicked in rapid succession Excel "sometimes" crashes.
The VBA code makes heavy use of object modules, so I was thinking it was a garbage collection issue. I explicitly set the top level object to nothing before exiting the button click macro thinking it would force a garbage collection. That did not work.
It is super frustrating because it is intermittent. Maybe 1 out of 10 to 20 times.
The code shown is just the button click handler. There is about 10,000 lines of code called from this handler, which I did not show. The VBA code reads information from the sheet, does some calculations, updates an excel chart on the sheet, and writes some data back to the worksheet. I do the usual turning off events and screen updates.
I am just hoping someone else has come up against the rapid macro execution causing excel to crash. Again, the VBA code runs fine, it appears to be a higher level excel issue?
Public Sub Clicked_UpdateWall_C()
Dim Wall As New CWall_C
Dim ExecutionSuccess As Boolean
Dim errstr As String
ExecutionSuccess = CheckUnits(ActiveSheet.Name, errstr)
If ExecutionSuccess Then ExecutionSuccess = Wall.UpdateWall(ActiveSheet.Name, errstr)
Call CheckError(ExecutionSuccess, errstr)
' This is an attempt to force excel to do garbage collection
Set Wall = Nothing
End Sub
The error message is "Excel has stopped working" not a VBA runtime error. One can click the "restart excel" button in the error dialog, and excel restarts and generally most of the time one does not lose work.
Since it is intermittent, I cannot post the exact excel crash dialog box text.
When a VBA macro button (not AcitveX button) is clicked in rapid succession Excel "sometimes" crashes.
A shot in the dark. Try this. Put your code in lieu of '~~> Rest of your code. Now no matter how many times you click in succession, nothing will happen.
Option Explicit
Dim DoNotRunProc As Boolean
Public Sub Clicked_UpdateWall_C()
If DoNotRunProc = True Then Exit Sub
DoNotRunProc = True
On Error GoTo Whoa
'
'~~> Rest of your code
'
Whoa:
DoNotRunProc = False
End Sub
Note: If you have a separate error handler in your code then adjust the above code accordingly.
I was able to resolve the issue by doing two things:
Switched from a "Button Form Control" to an "Command Button ActiveX Control." My hunch was that the ActiveX control is more robust in terms of handling rapid clicks. Turned out to be true.
Added the DoEvents function to the end of the Command Button ActiveX Control event handler. This pretty much eliminated the issue 99.9% unless someone is just being ridiculous clicking the button. The hunch here is that it gave Excel time to handle any outstanding events that perhaps were not handled properly due to rapid button clicks.
Thanks to all of you who responded with positive comments and suggestions.

Workbook_Open() in Excel 2016 not firing

Excel 2016 (or 365) does not seem to fire the Workbook_Open() sub reliably or more precisely, not at all!
The simple event sub
Private Sub Workbook_Open()
MsgBox "Work book is open"
End Sub
does not seem to work. However, if a workbook is already open and then the workbook containing the above Sub is then opened, it does run as expected.
I notice that unlike Excel 2010, 2016 (365) opens each workbook in its own window, not a workbook window in the Excel application window. Is this a bug in 2016 and is there a workaround?
I have produced a work around for my own applications and that is call the activation of a worksheet and call my initialization routines from there. But a bit "rough" and it would be good to have the Workbook_Open() sub working correctly.
It is a simple single Sub in the ThisWorkbook module. Macros are enabled. In Excel 2010 it works perfectly, as do two other macros in other workbooks for which I have written macros. It is just this one thing with Excel 2016. Given that the Workbook_Open() sub is the gateway to a workbook it seems a little strange that we have to go to a workaround to make it function.
Try encapsulating the call with a new instance of Excel. Example below:
Sub OpenInNewExcel()
Dim Background_Excel As Excel.Application
Dim pathName As String
Dim fileName As String
Let pathName = "Enter your path here" 'include "\" at the end
Let fileName = "Enter your file name here"
Background_Excel.Workbooks.Open fileName:=pathName & fileName
Background_Excel.Parent.Quit ' This is how you close the file completely using VBA otherwise the file will close and the Excel Shell will remain.
End Sub
Also make sure that enable macros is turned on in the Options-Trust Center.
You have to add the file/folder location of your workbook as a "Trusted Location".
You can see more info about that in Designate trusted locations for files in Office 2016.
I have same problem then I found solution after google it:
https://www.myonlinetraininghub.com/excel-forum/vba-macros/excel-2016-workbook_open-event-doesnt-trigger
Then I also use "Private Sub Workbook_Open()" and "Public Sub Auto_Open()" open in excel 2016 that work fine:
Private Sub Workbook_Open()
CustomStartUp
End Sub
Public Sub Auto_Open()
CustomStartUp
End Sub
Private Sub CustomStartUp()
MsgBox "Work book is open"
End Sub
I've had this problem (I'm using Microsoft 365), and I found this thread.
It happens for me sometimes when I have another workbook already open, then, on trying to open my macro-enabled workbook, before any sheet is displayed I get the Microsoft warning message about macros. Then, although I click its 'Enable' button, the Workbook opens, macros do get enabled, but Workbook_Open doesn't run.
I've never known the problem to occur if no other workbook is open. (Of course, the user might still get the yellow-backed messages at the top of the workbook, asking them to click the Enable Editing and/or Enable Macros buttons.)
Note that my Workbook_Open just calls another 'workbook-opening' sub in a module to do all the opening processing.
My solution: When my workbook-opening sub is called, it sets a global variable to True to indicate it has run.
I've made it obvious to the user that the problem has occurred, by means of a 'Welcome' sheet with all its cells locked, so the user can do nothing; at this point all other sheets are very hidden. The workbook-opening sub, when it runs, deactivates this sheet and makes it very hidden, so the user never normally sees it, and makes the other sheets visible. But if this screen remains, it instructs the user to select the other workbook, then select this one again. My Workbook_Activate code then runs, and because the global variable isn't True, it calls the workbook-opening sub. If this global variable is True, it does nothing.
To make this work, the Workbook_Close sub makes the other sheets very hidden and the Welcome sheet visible, ready for the next time the Workbook is opened.
Hey presto, the problem is solved.
The Welcome sheet actually has a dual purpose, in that if either of the yellow-backed warning messages are displayed, it will remain and force the user, with suitable instructions, to click Enable Editing and/or Enable macros. If the users aren't au fait with macro-enabled Excel, they will just ignore these and try to carry on regardless.
All this is much easier to implement than to explain. I hope it's clear.
And I hope this might be of help to someone.
I had this issue with one of my files as well. I managed to fix this issue by running Workbook_Open manually in the VBA editor once open and saving the file in another location. The file in the new location should have no issue with auto-running Workbook_Open. If this doesn't work, copy the original file to a new location before manually running & saving.
If the newly saved file does not run Workbook_Open, repair your version of Office.

Userform in Excel 2013 disappears while switching an active workbook behind

I have faced one problem in Excel 2013. In my project, I have a userform that contains a listbox which lists names of all opened excel books.
When a user clicks on a particular name in the list, the appropriate book is activated. So the userform is always on top and while the user is clicking on the names in the list, he can see all opened workbooks getting activated one by one behind the active userform.
This is the way it used to work in Excel 2010.
Now, after upgrade from 2010 to 2013, if a user clicks on a name in the list, selected workbook gets activated but the userform disappears.
What exactly has been broken in Excel 2013 and what is the way to bypass this problem?
Yes, the default behavior has changed. In Pre Excel 2013, The different workbooks are shown within one main Excel window if opened in the same instance. But in Excel 2013, they are shown in their own window. And because of this a modeless userform will only be visible on top of the workbook that was active when the userform was loaded.
And I don't think this has a fix yet. It is by design and may not be fixed.
#Siddharth, based on what you said, I think I have a solution. When you open a form, it will only show up on top of the ActiveWorkbook. As long as all the code is in the same code thread (not sure if terminology is right) , you're stuck with the same workbook; But if you use the Application.Run or Application.Ontime commands it seems to start it's own code thread, which is independent enough to work. Just Activate the workbook/sheet first, and then Unload the form and remote call the macro that showed the form in the first place.
Unfortunately, you need to use Unload instead of Hide, because of the aforementioned issue; which means you need to save any/all options selected.
Private Sub lstFiles_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
ThisWorkbook.Application.Workbooks(lstFiles.Text).Activate
Unload Me
Application.Run "USER_Macro1"
'Application.OnTime Now(), "USER_Macro1"
End Sub
 
Private Sub USER_Macro1(Optional Control) ' As IRibbonControl)
ModelessForm.Show vbModeless
End Sub
I tested it in Excel 2013 and so far it even seems to work regardless of the Screenupdating = false issue seen elsewhere.

Resources