Signed Excel VBA AddIn (*.xlam) not running properly despite installed certificate - excel

This is a tough one.
We developed an Excel VBA AddIn. That's an *.xlam file.
This AddIn is quite complex and transforms Excel into a software of it's own (well sort of - it still look pretty much like Excel).
Now we want to increase our security by only allowing signed macros within our company.
So we created a certificate, signed our VBA AddIn macro code and installed the certificate. Actually two certificates, one as a trusted root certificate and one in the list of trusted publishers.
And now we want to change the settings in the Excel trust center, so that only signed macros are allowed to run. And this works very well with all of our Excel macros - except with the AddIn.
Here comes the tricky part.
The AddIn itself starts and runs. The AddIn checks if a special type of excel file (with a certain custom property) is opened and starts an initialization process. The excel file itself doesn't contain any macros (it's an *.xlsx), but it contains numerous buttons (shape objects) and those are "connected" by the initialization procedure to other procedures (subs/ macros) from the AddIn.
MyWorksheet.Shapes("ShapeName").OnAction = "AddInModuleName.ProcedureName"
This code attaches the VBA subs from the AddIn to the shapes (buttons) in the (macro free) worksheet. So the worksheet becomes wired and functional.
This works very well when no limitations are put on the macros. But in this case with only signed macros allowed to run, the code is not excuted. The buttons are dead.
The code itself is just fine. I can trigger it e.g. with a keyboard shortcut. But the button refuses to run the code.
My explanation for this is:
By changing the ".OnAction" property of the shape, this itself is regarded as code - at least from a security point of view. So you could argue that I dynamically add "macros" (the OnAction property) to an excel file. And this code is not regarded to be signed. It doesn't inherit the safety level from the code it created.
Whatever the reason my be. My buttons are not working, despite the fact that the code is signed and trusted.
Any ideas for workarounds (despite the fact that I could probably use the Excel ribbon instead of a self made interface)?

I got it.
I post the answer, because this may be interesting to others too.
This is the premise:
We have an *.xlsx file, in other words an excel file with no macros.
We have a digitally signed and installed add-in (and alle certificates properly installed).
But all shape objects (buttons) in this file contain references to macros, in this case references to an add-in. This references are stored in the "OnAction" property of each shape.
When Excel starts, it runs the security check before any code is executed (makes sense). Now Excel finds those strings in the "OnAction" property of the shapes and says: "Hm - that's suspicious! I better block all shapes." It doesn't block the macro code in the add-in or so - just the shapes (the triggers) themselves. And it presents a macro warning (with default security setting). This happens - even when there is no macro available. If the OnAction properties contains any string, Excel will block it.
In the meanwhile my digitally signed Add-In runs just fine in the background provided that all certificates were installed. But none of the buttons is able to trigger any code (keyboard shortcuts work just fine).
So Excel has no problems with my add-in. It just doesn't want those OnAction properties to contain any strings. This is kinda strange. If Excel doesn't allow macros in the file. Why does it allow OnAction properties. Those should also not be saved in an *.xlsx file.
And this is the workaround:
I added a BeforeSave event in my add-in clearing all OnAction properties of all shapes in my workbook. And an AfterSave event which adds all those strings again.
So the saved file is cleaned from all suspious code.
Excel opens the file.
The file passes the security check.
And AFTER that my add-in code runs and wires all shapes (writes the macro calls in the OnAction properties of all shapes) and
whoosh - all Buttons are fully functional.
So Excel has no problem with the shapes (in an *.xlsx file) calling add-in macro code.
Andn it has no problems if this code is added during runtime.
It just doesn't like those "calls" to be there during the security check at start.
Feels almost like hacking....

Related

create and distribute Excel add in

I have created an extensive macro in excel, that I now want to distribute. I decided I want to do this by saving the macro as add in to a shared network, where all of my collegues have access to it. This way maintaining the macro will be way easier, as I am sure that there are plenty of updates, and bugfixing to come.
I have never created an add in before, so I read several online tutorials + stack overflow questions about it. Up until now I always saved my macros in personal.xlsb, likewise with the macro I now want to save as add in.
My first attempt was to simply save the workbook, where I run the macro, as .xlam, which did not work (I guess because the macro was not saved in that workbook, but in the personal.xlsb).
So I deleted the macro from the personal.xlsb, opened a new workbook, opened the VBA editor, created a new module in that workbook and inserted my code. I then saved the workbook as .xlam. I checked that in the VBA Editor the IsAddin is set to True.
From here it gets confusing somehow. When I open the .xlam file there are no worksheets in it, the add-in is loaded, but the macro does not show up in "Macros", even though the code shows up in the Editor.
When
However the .xlam is still empty when I open it - no code to be seen.
When I open another workbook and load the add-in, in the VBA editor the add-in does show up, and the module with the code of the macro is there as well. But when I click on "macro" it does not show up.
When I open a different Excel file, the add-in is loaded as well (in Excel-add-ins the box is ticked), the module does not show up, and in the VBA editor the .xlam also does not show up.
I have saved, closed, opened, and restarted several times. I have checked if the add-in is saved anywhere else - it was, but I deleted all .xlam files (as non of them worked anyway), and repeated my attempts stated above. When I load the .xlam from the shared network it seems to save itself into the addin folder of microsoft (I guess that is what it should do when it is loaded).
I would really appreciate if someone could help me with how to properly set this up.
I have:
a VBA code that runs fine, when I run it as macro.
I want
to save it to a shared network as add-in, and get it to run.
Edit1:
the add-in shows up in the active add-ins section in options:

Excel 2016 - QAT and Macros

I built some macros and save the VBA project as .xlam (Excel Add In) file. The macros (Public Subs) are visible when I go to Excel > File > Options > Quick Access Toolbar(QAT) > Choose 'Macros' from the left drop-down menu. Then I can add the macros to the QAT so users can click the tools icon to run those macros.
I observed a VERY strange behavior. Here's what it was before, everything was normal.
Here's what it was after. Things start getting weird.
The only difference is I changed a Sub's argument type from a built-in variable type to a custom class type. But I haven't run the macro yet. I'm just entering the code. But Excel changed the display on two other macros I'm NOT editing (macro names are Check() and CheckAndFix()).
So the questions are:
1) Why Excel GUI displays different formats while I'm entering the code? And it seem to depends on the variable type I'm typing? I didn't know that IntelliSense had such an influence on the Excel user interface.
2) Why Excel changed the display of two other Subs that I didn't touch?
By the way, this behavior is reproducible even after computer reboot. i.e. I can change the argument type between String and cSettings and observed the macro list format changed accordingly.
Thank you!
I finally figure it out!
Whenever the code referencing an undefined data type, QAT customization won't work. The symptoms are:
1) You'll see the workbook name was prefixed to the macro name on the list. While in normal situation, you'll just see the macro name.
2) If you associate the macro to a QAT button. That button won't work. Whenever you click the button, it will say "Cannot run the macro'XXX'. The macro may not be available in this workbook or all macros may be disabled". This is misleading as the macro is there and all macro is allowed.
You may ask - "Why your code references some undefined data type?" It was because my code reference some additional data types (such as Dictionary) that requires additional library (such as "Microsoft Scripting Runtime). If the library reference was not manually configured, the data type will become 'undefined'.
I'm surprised that the program didn't throw compile error or runtime error. Instead, it gave the message "macro may not be available for this workbook".

Excel macro from Add-in not visible

I created some Excel macros with VBA, saved it as .xlam file. I copied the file to another computer (running Excel2013) and put it in the following folder:
%UserProfile%\AppData\Roaming\Microsoft\AddIns
I enabled the Add-In from Excel > File > Options > Add-ins. Now I want to add those macros to Quick Access Toolbar(QAT). In the QAT options, I choose "Macros" from drop-down menu. The macros didn't show up as I had expected. The list is blank.
My subs do not have parameters if that matters. I have searched the forum and Google with no luck. What else I can check? Thank you!
I experimented with one of my own add-ins. All the subs in a general module were visible; however, none of the functions were. (Even the functions with no parameters -- tested by changing Sub to Function temporarily. The switch resulted in that macro disappearing from the macro list.)
Since you don't mention if there was this issue on the first computer; I am assuming that you would see the same thing there, if you checked.
If you sometimes need a return value from those macros, could you create "calling" macros? Subs which call those functions? If you never need a return value, I would recommend just changing the designation from Function to Sub on the relevant macros.
You could also check out this answer on how to add a button to the excel ribbon via add-in code. This could be useful if you plan on moving the add-in between multiple computers.
Foolish me!
I saved the macro module into personal.xlsb. However, I was trying to export it by creating a blank spreadsheet (e.g. "Book1.xlsx") and save it as Excel Add-In (e.g. "Book1.xlam"). Of course the Book1.xlam won't contain any macro!
I apologize for newbie mistake.

How to keep reference to add-in UDF when workbook moved to different folder than add-in?

I wrote an Excel add-in that provides UDFs (user-defined worksheet functions).
All is well until one user sends his workbook using those functions to another user, or just tries to use the workbook on more than one computer, where the add-in has been installed to different paths.
Even if the only difference in the paths is the drive letter, when the workbook is opened on the other computer, the old full path appears on the formulas in front of all the UDFs, and the formulas return an error.
One way of dealing with that is doing a search & replace of all formulas in the workbook, replacing the path with an empty string. Then the formulas reset themselves for the add-in's path on the current computer. Sometimes I then have to go into the VBE and run a CalculateFullRebuild to get the formulas to work. Though it works, it's a lot to ask of the less technical users, and it's annoying to have to do it frequently for those users who move their workbooks around a lot.
Also -- do COM add-ins have this problem? My add-in is an xla. Though I'm curious about that, it's a moot point in this case since COM add-ins don't work on Macintosh Excel and I need this add-in to work cross-platform.
UPDATE:
As requested, here's a screenshot:
This screenshot shows what happens if Fred, who put the add-in in C:\Fred's Stuff\Fred's Excel Stuff\MyAddin.xla, sends his workbook to Martha, who put the same add-in in another path, such as C:\Martha's Files\Martha's Excel Files\MyAddin.xla, and Martha opens the file Fred sent.
If Martha deletes the path, leaving only "=MyUDF()" in the formula, Excel will find MyAddin.xla on Martha's computer in the path where Martha put it (assuming she had previously installed MyAddin.xla as an add-in in Excel), and resolve the formula correctly.
This is one of the many bugbears Excel developers need to face at one time or another, and there are a few work-arounds for it, but which one you choose will depend on your own circumstances:
http://www.jkp-ads.com/articles/FixLinks2UDF00.asp
In case the link dies, here is a summary of the three suggested methods:
Use fixed locations.
Instead of keeping your UDF code inside the addin, you create a facility that copies the UDF routine into each workbook that uses it.
Redirect the UDFs to the new location.

Excel programming methodologies

What are the differences in Excel programming between a UDF, Macro, Add-in, Automation Add-in, XLL, or VSTO.
Which one I should use and under which circumstances?
I'll try to group/oppose some of the elements you mention:
VSTO vs. VBA:
VBA (visual basic for applications) is the "classic" way to write Office automation. Excel has a development interface which you can fire from office to write macros and UDFs, and which hasn't changed for about 10 years. On the plus side, deployment is trivial, and VBA offers nice features like macro recording, which record your actions into code, and provide a good way to figure out the object model.
VSTO came about more recently, and allows you to automate office using .NET (uses COM). You can leverage all .NET and Visual Studio (ex: add WPF forms), which gives great flexibility but the deployment is more complex.
UDF vs. Macro vs. Add-In
User defined functions are custom-made methods which will stay attached to your workbook; once added gain the same status as the "built-in" Excel functions: you can call them from worksheets like =MyFunction()
Macros are procedures which will stay attached to your workbook. They can be called directly by the user, or attached to events (ex: when a worksheet is selected, do this).
Add-ins are not attached to a specific document, but to the application itself. Typically a macro or UDF is attached to the workbook: when you open the document, the code becomes available to you, and when you give the document, the code is copied as well. By contrast, Add-Ins are attached to the application: the moment you launch Excel, the add-in becomes available to you. Tools like the Solver are an Add-in. Note that Add-Ins can be written in either VBA or using VSTO (you can also write UDFs in .NET, but it's atypical).
When to use what
Add-In vs Macro/UDFs: write an add-in if your functionality should be accessible from any workbook.
VSTO or no VSTO: this is a matter of debate. Most people who are familiar with "classic" VBA automation don't like VSTO too much, because the learning curve is a bit steep. If you are used to working with .Net, this should not be a bit issue - but VSTO is somewhat quirky compared to "normal" .Net apps development.
Note also that if you use VSTO, your code can't be edited by the user. This is arguably desirable, but at the same time, Excel power-users usually know how to use VBA and macros, and expect to be able to tweak the code. That can lead to interesting discussions.
Personally, I typically use VSTO for add-ins, and I use it as soon as I see that lots of logic / procedural code is going into macros in VBA. What VSTO gives me is the ability to write testable code, in Visual Studio, and also high-performance code when heavy calculation is involved. The other reason to use VSTO is to leverage WPF to customize office.
Use VBA for Excel 2003 and earlier (though you could still use it in 2007 if you want).
VSTO is for Excel 2003 or 2007.
The old Excel 4.0 macro language should definitely not be used anymore, they keep disabling parts and the functionality is disappearing. We're having to rewrite all our spreadsheets to get the old macros out.
Macros are also another name for VBA code.
An Add-in is just another Excel workbook that has code in it (like VBA), so that you can use the code in different books, and keep the code directly out of the users book.
An UDF is just a function written in VBA that get's called as a worksheet function in a cell in a spreadsheet (it can also be stored in an Add-in).
Lance has good definitions to your questions. In terms of what to use when, VBA vs VSTO--if you are needing to use .net framework go with VSTO. For instance is I wanted to make a VB.net program interface with a spreadsheet learning VSTO would be the way to go (that and vba does not have an array.sort like vb.net which drives me crazy). However if you are making a nifty spreadsheet that will do some cool things for your end users (formulas, charts etc) just whip up some VBA code within the spreadsheet. It all depends on what you have to do. Best tool for the job.
A few more points from the VBA side of things:
Add-in - All of your non-trivial code should go in an add-in. A typical project for me consists of an add-in that contains all of the code, a data store (database, text file, Excel workbook) to hold the data, and one or more templates as presentation layer or user interface. You don't have to use an add-in; code will work just fine in modules within your templates. However, it's a good practice to keep your project layers separate. Code goes in an add-in, data goes in a data store, presentation pieces go in a workbook or workbooks. This way, you can change your code without affecting the other two layers. Or you can change a presentation template without affecting the existing data.
UDF - This is declared with the Function keyword. Use a function if you need to return a single value (or array or object instance etc). Custom worksheet functions are UDFs because they only return a value to a cell. They don't change any properties of the cell except the Value property. You can't apply borders or fonts, for example, via a function.
Macro - Also called a procedure, they are declared with the Sub keyword. Use a procedure if you need to do something other than return a value, such as if you need to manipulate parts of the Excel object model.

Resources