How do you take a vba addin and make an installer? - vba

I have written a vba module that installs an addin button to excel. I would like to deploy it on many computers as easy as possible. Currently, these are my steps.
Save the excel as *.xlsm
Open the doc on the computer that I want to install
Save the document as an extension (*.xlam) which places it in the addin folder
Go to options>Add-Ins>Manage /Go>
Click the check box for my add in
Is there a way to automate this process? Write something in vb?

You can build an exe or msi installer with a tool such as Advanced Installer (the free edition). One thing you can do is copy files to a specific location and if you put it in the XLSTART folder then that add-in will automatically load for the user when starting Excel. There's a complimentary folder within the Excel program files directory, usually something like this
C:\Program Files (x86)\Microsoft Office\Office15\XLSTART
which if you drop xlam files into that folder they'll load by default too. The user specific option is
C:\Users[UserName]\AppData\Roaming\Microsoft\Excel\XLSTART
there are PROS/CONS to both models. One is will all users have access or just the user that installs. The benefit of the user specific option is it requires limited rights for installation (no admin privileges)

As others have said, you can easily copy the files to the needed folder in each users Apps directory. They will then need to check the box in the Add-Ins menu, but at least the file will be there. I use this at work with some success by putting the Add-ins and .bat file on a shared drive that everybody has access to. You can then just provide a link to the .bat file which will copy the file from the shared drive to the person's computer in their Apps directory. Here's an example .bat that I use:
xcopy "\\server\share\folder\Addins\CRWScleanup.xlam" "%APPDATA%\Microsoft\AddIns\" /y
Initially I had the .bat files setup to detect and handle Win7 and WinXP because we have a mix at work, but then I realized that the folder location after %APPDATA% (which leads to a different place for XP vs Win7) is the same for each version of Windows. I.e. \Microsoft\AddIns\ %APPDATA% is a global Windows variable and its value will vary for each user (that is good).
It works brilliantly once the Add-In is installed because to update it all I have to do is put the new version on the shared drive and have the user click the link to the .bat while Excel is closed. The new version gets copied over and the user doesn't have to do anything.

With VBA you have to rely on Office files (Excel ones, in this case) and cannot move to executables/installation packages. You might create a program (or a macro) performing the steps you want in an automated way. But if what you want is relying on a standard installation package, which the user might execute (as usual, when installing a program), you would have to move to VB.NET.
VB.NET and VBA are not too different (well... actually, VB.NET includes many more things, but "understands" most of the VBA code) and VB.NET is quite programmer friendly; so a conversion from VBA to VB.NET wouldn't take you too long. In VB.NET you have different ways to interact with Excel; from your question, I understand that you want the Add-in alternative: it generates a custom "installation package" which, once clicked, will install the give Excel Add-in in the target computer. Relying on this option is easy: in your Visual Studio (you need a VS to work with VB.NET), open "New Project" and, within the Visual Basic Templates, select Office (, your version) and Excel Add-in.
NOTE: useful link provided my Mehow: it refers to an old VS (2008) but things haven't changed too much since then.
NOTE 2: the aforementioned suggestion is available in any fee-based VS version since the 2008 one. Not sure about the support in free versions (Express ones).

The easiest way would be to add some install code to the xlsm file on open.
This code could then do the following:
Turn off the install code by changing a variable on sheet (this will
stop the on open code running next time the file opens);
Save a copy of the file as an xlam to the add-in folder;
Activate the add-in;
Then close the xlsm file.
All you need to do is then email the xlsm file out and ask people to open it.
The code is quite simple, but I can show if you need.

I researched a lot of the methods described above and on other sites, but have managed to create my own install and uninstall using Excel add-ins (*.xlam) themselves. My add-ins now install themselves the first time and I have an uninstallation script as well. Works like a charm.
I used my own variation and derivations of Ivan's Solutions': https://grishagin.com/vba/2017/01/11/automatic-excel-addin-installation.html

Sub SaveAsAddIn()
'Alt+F8 SaveAsAddIn Run
Dim sName As String
Dim sFilename As String
Dim o As Object
On Error GoTo Finally
Try:
With Application.ThisWorkbook
sName = Split(.Name, ".")(0) 'name of ThisWorkbook without extension
sFilename = Application.UserLibraryPath & sName & ".xlam"
.Save
.Worksheets.Add After:=.Worksheets(.Worksheets.Count) 'add a blank sheet at the end
On Error Resume Next
Application.AddIns(sName).Installed = False 'uninstall the previous version of the AddIn
SetAttr sFilename, vbNormal
Kill sFilename
Application.DisplayAlerts = False
For Each o In .Sheets 'delete all sheets except the last one
o.Delete
Next
.SaveAs Filename:=sFilename, FileFormat:=xlOpenXMLAddIn 'save ThisWorkbook as AddIn
Application.AddIns(sName).Installed = True 'install ThisWorkbook as AddIn
.Close
Application.DisplayAlerts = True
End With
Finally:
End Sub

Related

How do I save an Excel Add-In with VBA

I have an Excel Add-In which uses a worksheet in its workbook to save some preferences data (eg the last used value of a refEdit control on a userform).
I then save the add-in workbook using vba thisworkbook.save when preferences are changed in the userform.
I have found that this sometimes creates an xlsm file in myDocuments rather than saving the add-in in place (see also a copy of excel add-in is created in my documents after saving).
How can I save the add-in in place (in the add-ins folder) without creating a copy? Note activeworkbook.save wouldn't work as it saves the open workbook not the add-in.
I could alternatively create a temp file for the preferences but using the sheets in the add-in workbook seems a good place to store data.
As far as I know you can't have a file saved as an add-in and use the sheet on the file.
An add-in file is a VBA only file.
You say you want to save settings on the sheet. What about using the registry?
Saving data to the registry is very easy (actually easier than cells in my opinion).
To save a setting:
SaveSetting "MyAddIn", "Settings", "Username", "BOB"
The above line creates a value in the registry of windows with the value "BOB"
as "Username".
To get the setting from the registry you use:
Username = GetSetting("MyAddIn", "Settings", "Username")
You can read about the method here
The good thing about saving it on the registry opposed to a sheet is that you can't by accident delete or manipulate the data.
I found the answer: The user had two copies of Excel open (2016 and 2010). This resulted in the add-in file being locked by one of the two open copies of Excel meaning that the second copy opened the add-in as read-only and couldn't save the changes.
A rare bug and one I didn't foresee. I'm going to rewrite to save the preferences into an %appdata% file instead.
I'd advise people to avoid using thisworkbook.save with addins.
Thanks everyone for your help.

Using "GrantAccessToMultipleFiles" array feature in Word 2016 for Mac

I apologize in advanced if this is a basic question. I am new to this community and VBA. I'm using the following Macro in Word 2011 without issue:
ActiveDocument.Save
On Error Resume Next
Dim saveName As String
saveName = ActiveDocument.FullName
saveName = Left(saveName, Len(saveName) - 5) & ".pdf"
ActiveDocument.SaveAs fileName:=saveName, _
FileFormat:=wdFormatPDF
End Sub
I want to be able to use this in Word 2016 for Mac. I know there are sandboxing restrictions which is causing a permission dialog box to appear every time I want to run this macro. IF I understand correctly: once I give permission to a specific folder, that permission will be saved and I won't be prompted again when running macros that need access to that specific folder. So, for instance, I gave permission to my Dropbox folder. However, as part of my workflow, I am routinely creating new subfolders and each subfolder (under my Dropbox folder) apparently needs individual permission also.
I did some searching online and found that "GrantAccessToMultipleFiles" allows for an array to be created to give permission to files so that these dialog boxes do not keep coming up. My question then is: can I somehow give permission to my Dropbox folder and ANY subfolders that exist or are subsequently created?
I think you cant. As a workaround you can save the file to the UBF8T346G9.Office folder and move the file via applescript. Its a bit tricky but doable.

Excel Add-In Configure Variables and Save

I have been asked to create an Excel Add-in for people to load a series of xml documents into Excel spreadsheets from Excel. I will write an add-in and publish its location for people to download their own local copies for use. I would Ideally like to have some constants for the VBA configurable by each end user, to customize their experience and function.
I thought it would be nice to have one button to run the Add-in and another button called "Configure" or something, which would edit the values of some of the variables in the VBA, and save the new values so that next time the user open Excel, the Add-in remains configured for them. Is anything like this possible and do you have some suggestions about what path I should follow to get there?
Is there any way to get the variables to persist? I guess I would need to save the values somewhere on the local version of the Add-in, but if so, what is the best way to store a set of parameters?
Any general advice would be most welcome; I have not actually written the add-in yet, being still in the design stages.
I do not advise using cells to store settings as the user may F it up.
However VBA does support Registry edits.
SaveSetting "Macro name", "Settings", "Username", "John Doe"
The above code will save a setting or registry key called Username with the name John Doe in the appname called Macro name and the section Settings.
So in short you only need to change the last two strings when you save new settings. The first two should (to make it easy for you) be the same all the time.
The keys will be stored in : HCU\Software\VB and VBA Program Settings\Your app name\
To get the setting you use:
GetSetting("Macro name", "Settings", "Username")
Another solution is to use txt-file.
It's still better than cells but not as good as above mentioned registry.
settings = "Username=John Doe, Worktitle=Janitor"
MyFile = "C:\myapp\settings.txt"
fnum = FreeFile()
Open MyFile For Output As #fnum
Print #fnum, settings
Close #fnum
Now you have a txt file with the settings that you can read and parse.

Running functions from Excel Add-Ins in vba, is there an easier way than using Run "mySub"?

I'm trying to create my first Excel Add-In for Excel 2010. Most of it is working, it's running from the ribbon buttons, but I'm having trouble addressing the Add-In's subroutines from my workbook's VBA code.
According to this answer on SO, it should be possible to simply use the syntax:
mySub
or
Call mySub
But this causes the error "Sub or Function not defined". I've only managed to run them this way:
Run "mySub"
or
Application.Run("myAddIn.xlam!mySub")
Is there a way to include the Add-In so I can address it the easy way?
The Add-In is already checked in the Tools->Add-Ins list, and has a unique name (CalcFunctions) which is different from its file name (CalculationFunctions.xlam). The Add-In file is on a different disk and I'm working on a server, but I don't expect that that matters.
(Posted on behalf of the OP).
Turns out I'm just dumb. I only set a reference to the Add-In in the regular Excel window. I assumed that was what people meant by Tools->References->Add-Ins (I use Excel in Dutch and there's no "Tools" menu). Anyway, the solution was setting a reference in that menu in the VBA editor window.
Here's how to add a reference in VBA:
ThisWorkbook.VBProject.References.AddFromFile refPath
With refPath being the full path to the file.
To be able to add references you need to have permission to edit the VBA project. You can enable this in excel settings->trust center->macro settings. If you're on a company pc it's likely the administrator has to set these settings for you.

XLAM / XLA Addins: is there a better way?

This post is about installing XLAM's without creating links. (Everyone hates links). Consider the trivial addin:
Public Function UDF_HELLO(x)
UDF_HELLO = "Hello " & x
End Function
Put this code and nothing else into a Module and save as "Hello.xlam" on the Desktop (and NOT in the default excel addins folder). Next, while HELLO.XLAM is still open, create a new XLSX workbook with the formula
=UDF_Hello("world")
in cell A1, which simply displays "Hello world" in that cell. Save the workbook and exit Excel. Now, if you reopen the workbook without the XLAM, Excel will complain about "links to other sources ...". Whether you click "Update" or "Don't Update", Excel will mangle the formula in cell A1 like this:
='C:\Documents and Settings\tpascale\Desktop\Hello.xlam'!UDF_Hello("world")
Very often this "forced-linkage" is NOT desirable. In my computing environment there is a lot of ad-hoc analysis and it makes no sense to impose an install regimen on every XLAM we throw together to solve the problem of the day. I just want to hand out XLAM files to users and let those users open them when they need them, WITHOUT having to worry about the slightest mis-step causing their formulas to get mangled.
QUESTION:
Is there a way to instruct Excel to NEVER construct external links for UDFs, and simply to use UDFs if they're loaded and return #VALUEs otherwise ?
I don't know of a way around this with .xla/.xlam add-ins.
But this issue does not occur with .xll add-ins.
These can be created in C using the Excel 2010 SDK, or in managed languages like VB.NET or C# using the free Excel-DNA library.
(Disclaimer: I'm the developer of Excel-DNA. This issue is one of the reasons I went with the .xll interface for making managed UDF add-ins.)
You can have them open the .xla file and have an Auto_Open procedure install the add-in.
http://www.vbaexpress.com/kb/getarticle.php?kb_id=693
After excel closes you can have the add-in uninstall itself.
oAddIn.Installed = False
You can give your add-in a setting for the user to not uninstall after every use by using a worksheet named something then have cell A1 equal to true or false.
I haven't tested this but hopefully it works for you.
This should work to resolve your issue though it does not instruct Excel regarding external links. I have tested it myself by creating the XLAM, saving it to my desktop, installing it in the Excel add-ins and then using it on a new workbook.
Steps:
Once you have saved the add-in, close it.
Go to Excel Options-->Add-Ins
In the Manage drop-down select Excel Add-ins and press 'Go'
In the 'Add-Ins'dialogue that appears click 'Browse' and navigate to
the add-in you just created. Select it and hit 'Ok'
If prompted to save the add-in in the add-ins folder, select 'No'.
Selecting 'Yes' may cause an error if the add-in file suffix does
not match the version of Excel being used.
Your add-in should appear in the 'Add-Ins available' scrollbox,
check its box and hit 'Ok'
Your add-in should now be active whenever you open Excel.
Test this by opening a new workbook and try using your UDF.
Best,
I usually solve this problem by:
Saving an XLA/XLAM file (outside Personal folder, of course)
Connect to it in Tools - Addins
Write pseudo macros in your current Excel file that links to those macros / functions in the XLA/XLAM file.
See the detailed instructions in my reply here.