Where to save excel vba function to be able to access the function in other workbooks - vba

I've created a function and I would like to be able to open any excel file and use this function just by typing into a cell '=function'. Is this possible and how do I do this? Where do I save the function?

Save the workbook containing the function as an add-in (either .xlam or .xla depending on your Excel version). You can then install it via the Add-in manager and call it from any workbook.
Note: you don't technically have to save it as an add-in - you can use a regular workbook - but then you will have to prefix the function name with the name of the workbook whenever you call it (e.g. =Personal.xlsb!some_function), and you will have to remember to open the workbook each time (or put it in your XLSTART or other startup folder).

I'm going to provide an answer with the example of Workbook A as wbCompany and Workbook B as wbEmployee.
From what I understood is that you have a function in wbCompany.getEmployeeCount() and you want to use this function in wbEmployee.
Firstly, rename the VBA Projects of both files to prevent duplicate project name. So we will rename the VBA Projects as vbaPrjEmp and vbaPrjCmp for wbEmployee and wbCompany workbooks respectively.
Secondly, you need to add wbCompany as reference to wbEmployee.
In wbEmployee, open the Microsoft Visual Basic for Applications window.
Select Tools > References.
In the References dialog that appears, click on Browse.
In the Add Reference dialog that appears, select Microsoft Excel Files from the Files of type box, select the file that you want to call (in this case wbCompany), and click on Open.
Choose OK to close the References dialog.
Finally in wbEmployee you can now refer/call the function from wbCompany in the following manner:
Sub compareEmpCount()
msgbox vbaPrjCmp.ThisWorkbook.getEmployeeCount
End Sub

You can store it either in your Personal.xlsb workbook or in an Excel add-in (.xlam). Search for either of these two to get you on the right track.

Well, first of all, you have to enable macros in Excel.
After that, you can open Excel VBA editor with Alt+F11, and create your function there.
Finally, you can use your function in a cell with '=function'.
Anyway, you can try this link to help you with your first vba function: http://www.fontstuff.com/vba/vbatut01.htm
Note: I've already created some functions on Excel, and it always worked for me. But always remember: you must enable macros in Excel.
You can read about macros here: https://support.office.com/en-nz/article/Enable-or-disable-macros-in-Office-documents-7b4fdd2e-174f-47e2-9611-9efe4f860b12

Related

How to reference a workbook from another excel instance

I believe my problem is rather simple: I have a workbook and I'm using it to get some data from another software (SAP). When I export the data from the software, it automatically opens a .xlsx file, then what I'd need to do is copy some of the data from this file, paste on my original workbook, and then close the file. The section of my code which is giving me an error is this one:
fileName = "temp1.xlsx"
Set wbBasis = Workbooks(fileName)
This happens because the "temp1.xlsx" file that was opened by the SAP software is in another instance of excel, so my code isn't able to find it.
What I need to know is basically this. How to properly reference this "temp1.xlsx" workbook on my original code so that I'm able to edit it, copy stuff from it, close it, etc.
I've found some similar topics to my problem, like the two I'm listing down here, but couldn't adapt the solutions to my situation, and that's why I'm posting this new one.
Having multiple excel instances launched, how can I get the Application Object for all of them?
Finding a workbook in one of multiple Excel instances
Thank you in advance.
You don't need multiple instances of Excel, and you don't need the Excel file to be open in order to get information from it, either with VBA, or even with regular "linked formulas".
For example:
=SUM([C:\yourPath\Filename.xlsx]SheetName!A1:C25)
...returns the sum of cells A1:C25 on a worksheet named Sheetname in an Excel file located at C:\yourPath\Filename.xlsx.
Or you can import all the data directly with Get External Data.
See:
MSDN : Create an external reference (link) to a cell range in another workbook
MSDN : Connect to another workbook
...for more information and examples, search Google for "get data from another Excel workbook".

Excel VBA UDF autocorrects with wrong case

I have an Excel VBA addin that adds user defined functions (UDFs). These functions all work fine in terms of calculating their results.
I enter them into the Function Wizard using MacroOptions.
When using them in a worksheet, they autocorrect the function names for case. For example, if the function is named MyFunction, and the user enters it as myfunction, then when the formula is entered it autocorrects the function name's case to MyFunction. Just like with Excel's built-in worksheet functions, where if you enter e.g. median it will autocorrect it to MEDIAN.
However, there is one UDF for which that autocorrect is incorrect. I want it to be e.g. MyFunction, but even if the user enters it like that, it autocorrects to all lowercase, myfunction.
I have looked at every relevent line of code and can find no reason for that. The code is the same for all the other UDFs except of course for function name, function description, and the code and parameters in the function itself.
Any idea why that one UDF autocorrects the function name differently?
Here's an example of the MacroOptions line:
Application.MacroOptions "MyAddin.xla!MyFunction", "Description of MyFunction for the Excel's Function Wizard.", , , , , "Custom category in Function Wizard"
And the UDF itself looks like this:
Public Function MyFunction(param1 As Long, param2 As Long) As Long
'MyFunction's code here...
End Function
Again, the UDF calculates correctly. The issue is with the autocorrect on the function name.
I tried closing the addin, then creating a new UDF with the same function name as the affected function in the new, default Excel workbook. It worked correctly -- it autocorrected to the correct case. But when I closed it and went back to the addin, the problem returned.
UPDATE:
Here are the steps that worked for me to fix the problem (thanks, Charles Williams!):
Set the add-in workbook's IsAddin property to false. That turns it into a workbook, so you'll get a worksheet.
File > Save As, save as new xlsm workbook. Important: make sure there are no formulas in the worksheet with the affected function name; otherwise you'll be coming back to this step.
File > Options > Add-ins > Go, Uncheck the add-in so it doesn't load when Excel is started.
Exit and restart Excel.
Open the new xlsm workbook.
Enter a formula with the function name in correct case. It should NOT autocorrect to incorrect case.
Delete the formula.
Save the xlsm workbook.
Make a backup of the original add-in, as you're about to overwrite it.
Save the xlsm as a new xla add-in, overwriting the old one (I assume this works with xlam too but didn't try that).
File > Options > Add-ins > Go, recheck the add-in so it loads when Excel is started.
Restart Excel. Test for the problem; the problem should be fixed.
Excel insists on remembering the capitalization that was used the very first time the UDF is entered into a formula.
I have not found a sensible way of resetting this, apart from renaming the UDF.
If the XLAM's worksheets contain a formula referring to the UDF then that reference will lock in the capitalization. If the XLAM's worksheets do NOT contain a formula referring to the UDF then it will be set from the first workbook that uses it in an Excel session. If you have 2 saved workbooks with different capitalizations and they both get opened then the capitalization in the second gets overwritten with the capitalization from the first.
Inspired by other contributions (thanks!), here are the steps that worked for me:
Close the Excel session and open a new one.
Create a new workbook and write in it a formula including the correctly-capitalized UDF.
Discard the new workbook but keep the Excel session.
Open other workbooks with formulas including the UDF: the UDF will now be correctly capitalized.
You can close the Excel session without saving the workbooks.
In subsequent Excel sessions, the UDF will be correctly capitalized.

How to check if VBA module has been modified?

I have an Excel workbook that I would like to export the code for every time the workbook is closed but I would like to do so selectively so that each module will only get exported if it has been modified since the workbook was opened. I would like to be able to use the exported files to run a diff on the code and I'm assuming that re-exporting every time will cause the files to always be flagged as different. Here's an attempt at some pseudo-code to show what I mean:
for each module in Workbook
if module.isModified() then
module.export
end if
next module
VBComponent has a readonly property. Add reference to VBE and you should be able to access "changed" VBComponents
bool Saved
Saved Property - (Excel 2003 VBA Programmer's Reference Google Books)
I was just being lazy about it and hoping someone already new a method that I hadn't found. Sorry about that.
I found that I can use the following.
for each module in Workbook
if not module.saved then
module.export
end if
next module
Then, I'll just run the export function every time the workbook is saved.

Where Exactly To Store VBA

We receive Excel files daily from our field offices which I have to clean and re-format (about 110 columns and 500 rows-worth) using VBA.
I need to save my VBA as a macro so we can use it to clean up all the workbook we receive by running the macro and saving the edited sheet as a new worksheet by getting the name from UserForm Combobox items.
Where exactly should I store the VBA snippets? I mean when I open the Visual Basic panel, I have these three options:
Running The Code From Microsoft Excel Object :Sheets1(Sheet1)
Running the Code From An Inserted Module
Running the Code From User Form
If I am supposed to use options 1 or 2, how can I call the UserForm for saving the sheet?
I Recomend you to use modules (Option B)
Option C goes with option B, ill explain, you can create a sub in a module in option B, then you can do:
UserForm1.show
In Option B I would writte this code, but before trying this i recomend you to understand a bit more of vba
sub ClearWBs()
'opening workbook
Workbooks.Open Filename:="c:\book1.xls"
'your code
'your code
'below code for saving and closing the workbook
Workbooks("book1.xls").Activate
ActiveWorkbook.Save
ActiveWorkbook.Close
end sub
Use Module:
If your VBA code focusses on data summarization and manipulation I suggest you use a Module.(example is what you have described in your question).
Use Form:
If what you wan't to do requires a GUI(Graphical User Interface) then you'll have to resort to Form where you can design your GUI. (example is if you have many fields that the user needs to fill-up with distinct values in which you provide the choices)
Use Excel Object:
If what you wan't to do has something to do with events happening on Worksheet and/or Workbook, like for example whenever you add sheet the macro runs, or when you open or close the workbook the macro runs then you will have to write the macro in the Excel Object.
This is basically what i have in mind, hope this helps.
If you receive files that do not contain VBA and you need to apply the same code on those files all the time then I propose that you either save that code in your personal workbook.
You can see how to do that here: http://office.microsoft.com/en-ca/excel-help/copy-your-macros-to-a-personal-macro-workbook-HA102174076.aspx
This is nice because you can also tie it to keyboard shortcut or just have it always ready for you to use.
The disadvantage is that it will only be set up per user session per computer. What you can do is have that code all set up in a module and then import it into your personal workbook if you change session or if someone else has to do it.
Once it's done, you will not have to include the module in your files your receive again.

make excel files use a global workbook function with vba?

I am new to vba and I have problem understanding the workbooks in vba for excel files.
I have a macro called Addin.xla, this macro is used by 2000 files.
The problem that I have, is that the 2000 files have its own thisworkbook thats declares the function Workbook_BeforeClose. All the 2000 files have the exact same Workbook_BeforeClose.
What I want to do is to change the Workbook_BeforeClose function in all the 2000 files. Can I make the files use the Workbook_BeforeClose function in the Addin.xla file or must I change the same Workbook_BeforeClose function for all 2000 files?
If the later is the case, can someone show me how to write a macro that loops through all the files and updates this function automatic?
In the addin, handle the Application.WorkbookBeforeClose event.
But if you already have same code in 2000 files, you will have to remove it anyway. Otherwise it will run in addition to the handler you will define in the addin.
To auto remove:
Add a reference to Microsoft Visual Basic for Applications Extensibility X.X.
Then open each file in a loop and do
With currentWorkBook.VBProject.VBComponents("ThisWorkbook").CodeModule
.DeleteLines .ProcStartLine("Workbook_BeforeClose", vbext_pk_Proc), .ProcCountLines("Workbook_BeforeClose", vbext_pk_Proc)
End With
One solution would be to delegate the function to the addin:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
runCleanupCode
End Sub
where runCleanupCode is located in your addin. That means that if you want to make changes in the future, you only need to make them in the addin.
To change the code in all your sheets, you can follow this example.