I am trying to find a way of compiling the code in VBA on workbook open. I can do this manually by opening the VBA environment, going into Debug and "Compile VBAProject" but was wondering if there is a way to do this through the code every time the workbook opens.
The purpose of this is to load the code into the computers memory to prevent a compile error due to use of some Active X Objects. As mentioned, I can do this manually and it solves the problem however, as there are many users that use this and the workbook is password protected, not all will have access to the debug option.
I think you might try to do this by automating the VBE (Visual Basic Editor).
REQUIREMENT:
you need to go to Excel / File / Options / Trust Center / Trust Center settings and check the option Trust access to the VBA project object model (for security reasons this is deactivated by default, and if you don't check it the below code will raise the run-time error 1004 programmatic access to visual basic project is not trusted). Clearly, you only need to do this once (in each computer you want to execute the automated compilation, of course).
CODING:
Your command bar instruction (i.e. "Compile VBA Project") is inside the VBE object of the Excel Application, specifically in the command bars:
Dim objVBECommandBar As Object
Set objVBECommandBar = Application.VBE.CommandBars
The object will now contain the entire command bar of the Visual Basic Editor.
In particular, you look for the ID button "578", which is in fact the "Compile VBA Project" (you can put a watcher on the variable and browse all is inside into the local window, you might want to search for other commands). Hence, to summarize:
Set compileMe = objVBECommandBar.FindControl(Type:=msoControlButton, ID:=578)
compileMe.Execute
This will allow the compilation of the project. As you were asking, you just put this into the This Workbook open event:
Private Sub ThisWorkbook_Open()
Set compileMe = objVBECommandBar.FindControl(Type:=msoControlButton, ID:=578)
compileMe.Execute 'the project should hence be compiled
End Sub
Related
Since upgrading to Excel 365, my company has been having all sorts of trouble with VBA-supported Excel workbooks crashing or not functioning properly. The issues have popped up in various workbooks and various departments, including seemingly simple VBA workbooks. I've discovered a fix (see below) but it's not sustainable.
The Issues
The various issues we have experienced are listed below. Note, these issues only occur when you open a file in Excel 365 desktop. The same files, when opened in the Excel 365 browser app or in Excel 2016 will work fine. Also, all these issues happen at random. A user may have been working in a file for weeks and then the next time they open the file they get one of these errors.
"Can't find project or library" errors even when we are using the standard set of libraries and basic VBA. Then when you open the VBA Editor window, all the VBA screens are essentially frozen up and the library list is inaccessible.
Excel hard crashes or locks up when opening these files and enabling VBA. Note, the crash only occurs when the VBA is enabled. If you open a file without enabling VBA, it will work fine (though obviously you can't use any of the code).
The file opens seemingly fine, but the VBA doesn't work and once again, everything is locked up when you access the VBA editor window.
"unhandled win32 exception occurred" error
when executing a command, getting an error 32809 which seems to indicate the compiled VBA has been corrupted
The Fix
Opening the VBA Editor window, then selecting Debug -> Compile VBAProject seemingly fixes the issue. I've yet to experience any of the above issues where the file had been manually compiled this way. The problem with this is that every time you add code to a file or any time you add a new tab to a file, you have to go in and perform this manual compile again.
Yes, apparently adding a single tab in a file changes the workbook structure enough that it is necessary to compile again. The Compiled VBAProject selection will be greyed out. But adding a tab (or adding new VBA) will un-grey it and require another manual compile or the problems start occurring again.
This fix also works to repair files where the above issues are occurring. To fix those files, you can:
Make sure "Disable Trusted Documents" and "Disable VBA macros with notification" are toggled on in your security settings so that VBA doesn't automatically run when you open a file.
Open the file with the errors but do not enable the VBA.
Go to the VBA Editor window, select Debug -> Compile VBAProject.
Save the file, close it, reopen it, enable the VBA, and everything works fine again.
But again, this isn't sustainable because all my users will have to remember to go compile VBA any time they add a new tab to a workbook.
Help?
Has anyone found a more sustainable fix to this issue? Is there a bug with the Excel 365 Desktop automatic compiler that Microsoft is working on?
I think I perhaps found an answer in this thread:
https://social.msdn.microsoft.com/Forums/en-US/814ac2ce-ab45-45dc-8c6a-8ef0775d189a/excel-64bit-crashes-when-activating-macros-but-excel-32bit-does-not?forum=exceldev&prof=required
Per that thread – “the cause is that Excel does not correctly save the compile state of the VBA code and 64 bit Excel cannot recover from that issue when opening the afflicted Excel file (32 bit usually can). A fix was released for only Excel 2016 and not for other versions". That would indeed confirm that it is a bug within Excel and explains why we only see the issue with 365 64 bit Excel.
That also explains why my manual compile fix works. Based on the article I found, there is a more sustainable fix. You can change Excel’s registry and force VBA to compile accurately.
To implement the permanent fix:
Open the start menu and type “reg” and select the “Registry Editor”
Navigate to: Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Excel\options
On the Edit menu, point to New, and then click DWORD Value.
Type ForceVBALoadFromSource, and then press Enter.
In the Details pane, right-click ForceVBALoadFromSource, and then click Modify.
In the Value data box, type 1, and then click OK.
I have surfing the net for months already and haven't really found a solution to the following task I would like to perform. Here is a deal.
I am writing a bunch of code in VBA, which basically creates a new worksheet in a workbook with a specific type of calculators (there are many) for job purposes. One sheet - one type of calculator/analysis.
What I want to accomplish is, that due to increasing amount of code - I would like to put everything on to the ribbon, so I can access a macro through that. However, the job is based on to the case-to-case analysis basis, so the each new project requires a new Excel workbook to be created, where I can choose the calculator I want and do the job.
In addition to that, it requires to be launched on all computers with Excel in the network, with ability for me to be able to modify/add a code to the macro, so that all PC's can stay up-to-date simultaneously.
To wrap-up shortly:
There is a bunch of VBA macros (which I'm constantly updating/adding);
I need to access those macros through the Ribbon in any new workbook (not the one macro are located) on a number of computers in the network;
There is a need to provide instant updates of the code for Ribbon and macro users.
SO, is there any solution, like - I create 2 files (one with Ribbon configuration, another with calculators) and drop them into the server folder? Each user access them once during the installation (basically locating the folder, where the addins are located), and if I need to modify something - I do it with those two files in the server folder and that's it.
If it's not real or pretty hard (for non-programmer) to instantly update all the users, the manual update can work out, but the minimum of being able to access the ribbon in each new workbook is a must.
Thank you in advance for help.
Thanks to all of you folks, who contributed on the question. Want to summarize the experience and provide the way I managed to go with it.
1) Get your VBA code
Let's have a code like this. It can be whatever you feel like. To do so, open VBA in the Developers tab or by pressing Alt+F11. Create a new Module, by right clicking on VBAProject > Insert > Module, name it sayMsg in the Properties window and enter the following code:
Sub saySomething()
MsgBox "What's up?"
End Sub
As I said above - this module can contain anything, usually the functional part of your code, which is going to be called out in another module later.
Let's create a new module the same way we created the first one and name it sayRibbon. This separate module contains a call function or so called "button", which runs our subroutine from sayMsg module. Copy > Paste the code below:
Private Sub sayButtons(Control As IRibbonControl)
Select Case Control.ID
Case Is = "saySomething_Btn"
Call saySomething
Case Else
End Select
End Sub
Basically, what we have here is a Case named saySomething_Btn, which is the "button" itself, with its defined call function.
Now save it as Excel Add-in file .xlam and close the program.
Notice: when you choose .xlam from a drop down menu, you will automatically be located in default Microsoft > AddIns folder. In order to save it on your Desktop, first of all choose the file type, and then relocate the folder.
2) XML map by Office RibbonX Editor
The utility above provides you with the option to create a custom tab in the Excel ribbon. Follow the link for download. All installation and use instructions are also available by that link.
After you finish with an install, open OfficeRibbonXEditor.exe file.
File > Open your .xlam file. Now it appeared in the list below.
Right click > Insert Office 2010+ CustomUI Part (or Insert Office 2007 CustomUI Part - depends on the Office version you are running).
Copy > Paste the code below:
Code
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" xmlns:Q="sayRibbon">
<ribbon startFromScratch="false">
<tabs>
<tab idQ = "Q:rxTabUI" label="Say Something" insertAfterMso="TabView">
<group idQ="Q:rxGrpUI" label="Say">
<button id="saySomething_Btn" label="Say Something" onAction="sayButtons" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Press Validate, in case of issues - the error message will appear (Debug if needed, but you shouldn't in this case).
Now Save and Close the Ribbon Editor. You can only save, when .xlam is not opened by Excel.
3) Access the .xlam Add-In in any WorkBook
The main purpose of such approach was to provide an easy access to the VBA code from any Workbook in Excel and from any machine in the corporate network without actually installing it separately on each individual computer.
It doesn't really matter - do you want to get access only on your PC or local network, the installation process is the same.
Place .xlam file to any location of your choice (local folder or server).
Go to Excel > File > Options > Add-Ins.
Press Go... button below, Browse for the .xlam location and press OK.
Ensure the Add-In is marked in a list. Press OK.
Notice: I would recommend to encrypt your VBA for security reasons, in case if you want to be the one, who actually can edit the code - to eliminate any issues, which may arise if VBA code isn't encrypted.
I have checked the performance on my corporate network, the results are quite satisfying. All the changes you perform in the code are instantly updated among all users after they restart their Excel application.
Don't forget to release the change notes and to keep at least couple of older versions available for people, in case of need or emergency.
As long as the project will evolve, maybe more complex approaches could be used, however due to boundaries I am currently facing, this approach provides the best performance at the moment.
Every once in a while, I will find that somehow the Application.EnableEvents property gets set to false, requiring me to manually set it back to true in the VBE's Immediate window. The mystery to me is that it is set to false without a VBA error being thrown. Had an error been thrown, I wouldn't have questioned it as much.
Can any of you help me out with possible causes to this? For now, I have no leads.
Contextual information:
I have not been able to reproduce the error
Nowhere in my code am I changing Application.EnableEvents
All of my code relies exclusively on events, I don't have any UDFs that I call within worksheet cells
From what I remember, the VBE was open every time, so I was probably actively developing at the time of the failure.
Thanks,
Add a watch on Application.EnableEvents, ensure it is global so set Procedure to (All Procedures) and Module (All Modules) . Change the Watch Type to Break When Value Changes
Make sure your code is unlocked. Then run your applciation, the code should should stop on each line when the value changes. This way, you can double check your code acts as intended.
Incidentally, you an use the RAII design pattern to manage these Application settings. The code here uses a RAII design pattern to manage the status bar Essentially the RAII pattern uses a class and utilizes the destructor to reset a setting.
This setting should never change on its own. I would check to see if you have another workbook open that is modifying the setting.
To do this Open the VBA editor (Alt-F11) and see what workbooks are open by looking at the project explorer on the left hand side. Look inside each project for code that is disabling the events.
Also, when you do a search on your project and any other open project, make sure to choose "Current Project" in the find window and search on "EnableEvents" The current project is not selected by default and you may be missing some code in your search you didn't know about like the workbook startup event.
I have an Excel spreadsheet with VBA programming, form activex controls, form controls. The spreadsheet has worked normally, until last week. I think the problem started when the automatic installation of windows uptade took place, however it might be only coincidence, since I am not positive if this is the cause. Now, the spreadsheet opens and immediately a small window appears that indicates :
“Visual Basic for Applications - Permisson Denied to use object (OK,
Help)”. Selecting help, minimum information and it is irrelevant.
Selecting OK, another window pops out “Visual Basic for Applications -
Unexpected error 419 (OK, Help)”
I cannot even save the sheet to another name. The VBA code cannot run. If I open any new spreadsheet, Excel functions normally, also with its VBA. Just before having this problem, every time that I opened the spreadsheet a window appeared, indicating that Excel blocked the functionalities of the ActiveX controls and asking that if I would allow the use of ActiveX. Today, I enabled all macros and also all activex controls. My previous backups of this spreadsheet have also the same problem. None works. I went to VBA Edit-->References and compared the Libraries I had and the Libraries that are there on the spreadsheet. It seems that no library is missing. How to solve that?
The permissions have changed on your workstation and/or network. Specifically, the folders that hold the DLL files that contain the objects referenced in the VBA. As an example (and I don't know if this is exactly the case, but an illustration), if your code is referencing the Microsoft Scripting Runtime (many VBA projects do), your code needs permissions to access C:\Windows\SysWOW64\scrrun.dll. (I found this by calling up the VBA editor, selecting Tools-->References, then selecting Microsoft Scripting Runtime and reading the bottom of the dialog window for the location.)
This is the location of the DLL on my workstation. Yours might be different or it might have moved during a systems update or the permissions to access that folder may have changed. You'll have to check the locations of all the references in your VBA project to determine this. Sometimes the libraries referenced are located on network drives, which can complicate matters if the network permissions change.
I decided to try to export all the forms (*.frm; *.frx). Everything went fine until I came across to a specific form that had a shockwaveflash object. At this point the message "Permission denied to use object". Bingo!
I then tracked the location on my workstation of such shockwave object reference and applied full administrator control. However, I still could not use shockwave objects. I then uninstalled flash and downloaded the lates shockwaveflash plugin from Adobe. When I open Excel->Developer->Insert->ActiveX Controls->More Controls -> ShockwaveFlashObject and then insert the object in a sheet, the message: "MS Excel - Cannot insert object" appears. I have manually deleted the "*.exd” from C:\Users\[User ID]\AppData\Local\Temp\Excel8.0. Also deleted from C:\Users\[User ID]\AppData\Local\Temp\VBE\, but the problem was still there: "Microsoft Excel - Cannot insert object".
To solve the issue I finally accessed the VBA editor and deleted the userform that had the ShockwaveFlashObject in it. All went back to normal afterwards.
I have a roughly 100MB-large Excel file that I am opening with this code that runs when a UserForm button is pressed:
Public Sub SelectButton_Click()
fNameAndPath = Application.GetOpenFilename(Title:="Please Select a Report")
If fNameAndPath = False Then Exit Sub
End Sub
Because this file is so big, it takes a while to validate before opening, and this validation makes up about half the time my entire macro takes to complete (I'm working in Excel 2013 and this file is not opening from a network or shared drive). If I open the file manually, then I get the option to skip validation after three seconds of validating. The problem with this is that it opens the file in Protected View, where I can't work with it.
Using VBA, is there a way to "force skip" this time consuming validation while simultaneously avoiding Protected View?
When Excel is completely closed, this warning/guideline appears in the bottom left of the opening splash screen:
When Excel is already open, this warning/guideline appears in the bottom right:
So far there are two solutions that I've found to be useful for solving this problem, thanks to the comments above:
1. Disabling Office Validation for Excel files in the Registry settings for Windows:
I prefer to use early binding, so I would suggest in the VBA editor window, opening the Tools window, selecting 'References...', and then checking the box next to 'Windows Script Host Object Model', and clicking OK. This will enable IntelliSense as you are writing your VBA:
Dim wsh As New WshShell
wsh.RegWrite "HKCU\Software\Microsoft\Office\15.0\Excel\Security\FileValidate\DisableEditFromPV", 0, "REG_DWORD"
Set wsh = Nothing
This will work for Excel 2013. If you have a different version of Office or Excel, you will use something other than 15.0 in your file path.
However, this method has the glaring problem of removing validation of any Excel file on your computer, even those that might have malicious code in them or that might run from dangerous locations, such as your Temp or Downloads folder.
Additionally, writing to the Windows Registry might be disallowed depending on your current environment or permissions. For that reason, I recommend a different solution:
2. Setting the location of the Excel file to be a Trusted Location in Microsoft Excel:
It's possible to set a new Trusted Location in the Registry via VBA, but since this method is intended for use by those who can't access the registry, we won't get into that.
To add the file's location (let's say it's the "Excel Files" folder in C:\) as a Trusted Location, first click the File tab and then click Options at the bottom of the File Menu:
In the Excel Options window that opens up, click on Trust Center at the bottom of the side menu and then click the Trust Center Settings button that appears on the right:
Finally, click the Add new location... option and enter C:\Excel Files\ (or whatever your folder location is; you can even browse to it), and then click OK. You can also check the option to include subfolders if you want.