Excel VBA: Initialise public module-level variables when file is opened? - vba

I have a whole bunch of dates in three columns which are used by several macros. Currently each macro that uses these dates has to:
Declare the range
Have a for-loop through the range to get the date-cell and
Read the value of the cell into a variable of type date
This also includes checking the cell isn't empty, checking the date is valid.
Instead of this, I would like to have a macro that reads these dates into (VBA) arrays, which persist as long as the file is opened. I would also like to have this macro run when the file is opened, so that the dates are guaranteed to be initialised when any macro that uses them is run.
Any way to do these things?

Put your code in the Workbook_Open() event.
Alt-F11 to bring up the VBA Editor
Double-click the "ThisWorkbook" in the Project Explorer.
You'll see two drop-downs at the top of the code window. Pick "Workbook" from the first one and "Open" from the second to have a stub for your code created.

Related

How do I hotkey current sheet's VBA code?

I've had the issue of Worksheet_SelectionChange(ByVal Target As Range) triggering every time I click on something, which I don't want, as it means I have to wait every time I click in the actual sheet. I changed the code to Worksheet_Open, but that means I have to click the Run button whenever I want the code to run.
So I'm looking for a way of only running the current sheet's VBA code when I want to while I'm looking at the sheet (not while I'm in the VBA Editor). Ideally I'd be able to assign it to a hotkey using Application.OnKey, but I can't figure out how to refer to the sheet's code itself. The only solution I've found refers to an external macro, which isn't helpful, since I'm only wanting to use the code that's already in the sheet, as I'm using different macros for each sheet in the workbook.
Create a macro in a module for which you set the hot key, this macro will call the one you need:
CallByName ActiveSheet, ActiveSheet.Name & "Macro", VbMethod.
So you need to name the macros in the format of SheetNameMacro in each sheet.
More explanation: Trying to call a Sub with a String - VBA
Update
If your sheet names contains spaces then use this:
CallByName ActiveSheet, Replace(ActiveSheet.Name," ","_") & "Macro", VbMethod
and of course also replace spaces in your sheet (e.g. if your sheet called "list to delete" than macro name should be list_to_deleteMacro.

Is it possible to have a cell that has a formula and accepts entry at same time in excel?

Example:
A B
1 =vlookup(XX)
2
3
in cell A1 there is a Vlookup formula, Is it possible to enable user entry in this cell and override the formula then later restore the formula automatically when sheet is open again?
Even through VBA
Short, boring answer: nope.
A cell only ever has a keyed-in value, or a calculated formula. Can't have both.
Longer answer: maybe.
Shift everything 1 row down, and use row 1 to store your "original" formula - then hide that row (and pray the user isn't going to mess with it).
When the sheet is opened again sounds like you're confusing "workbook" and "worksheet" - you need to handle Workbook_Open if you want to run code when a workbook opens. Workbooks contain worksheets - it's the workbook that opens, not the sheets (sheets activate, but I doubt you would want to put that logic in there).
So, in the handler for Workbook_Open, write code that takes the formula in the hidden row and overwrites whatever is under it.
Another solution can be to hard-code the formula in the VBA code.
One possibility would be to store your Workbook as a template. Normally when a user opens the workbook by double-clicking, it will open whole new workbook based on the template, and they can modify it to their heart's content, save it, mail it to Grandma, etc.
The next person who comes along will double-click the template file and get the formula again, just as you designed it.
Short answer: Kind of, sort of
Long answer:
Save your workbook as a template. Every time someone will use it you'll see the orignal with formula, then if someone write over the formula, when using save your original will be kept intact.
What You need to do is:
press Alt + F11
select ThisWorkbook and paste this code:
Private Sub Workbook_Open()
Worksheets("Sheet1").Range("A11").Value = "asdf"
End Sub
Every time the workbook is opened, this script will run.
Instead of "Sheet1" you can write the name of the sheet you want to apply the script.
Inside the Range, You can define the cells you want to modify, You can use even multiple cells. Check this for more information about this.
After Value You can write what You want to be written inside the cell. You can write "=vlookup(XX)" and it will work.

How do I run VBA code on ListObject Change?

I know that I can write the following code in a sheets' VBA-object to run code on a worksheet change.
Private Sub Worksheet_Change(ByVal Target As Range)
End Sub
Is there anything similar that I can write to run code whenever I filter a certain ListObject?
Only in some cases. Say we include a new column in the table that we fill with the value 1. Elsewhere we insert an
=SUBTOTAL()
formula to sum that column. As the filter is operated the number of visible rows will vary. The SUBTOTAL() function will re-calculate.
At this point a Calculate Event macro would catch the re-calculation!
Try this...
I added a ListBox Form Control to my Excel sheet..
Next, I assign a macro to this object by Right Clicking and choosing "Assign Macro". (you may need to be in "Design Mode" to make this happen -- check the Developer Ribbon)
By default - the Macro Name is populated with a change event macro name. Click "New" to create the macro.
Your macro is added to a Module. Hope this helps!

Running Sheet-Specific Macro from Other Sheet

I have a Excel book that has multiple sheets, subs, and macros. In order to make it a bit more user friendly, I'd like to create a dashboard sheet where the user has to just click buttons to run everything. This is possible easily with the subs, but how can I call a macro from one sheet to another? I can't seem to find any Excel documentation on this.
Put the subs in a Module as opposed to in each sheet object.
To Create a Module right click on the book name in the VBA editor and then choose Insert -> Module. Any sub will then be accessible to any sheet (or object) within that book.
If you have a Sub in a worksheet code module, you can call it from a regular code module (or any other module) like:
Sheet1.MySub
...where Sheet1 is the codename of the sheet containing the code you want to run.

VBA Excel UDF retaining original value

I have a UDF non-volatile function in VBA, which requires a global variable (callback to VSTO) initialized.
This function resides in xla or xlam (same behaviour)
Is there a way to cancel calculation of the formula if the variable not yet available?
In Excel Automatic recalculation mode (I don't want to change that) Excel recalculates cells with my function every time I open a workbook, replacing value saved in a cell with error: "#ARG!".
I know how to return empty cell if my variable is not initialized, but is it possible to return original value? I checked with a debugger that it has been saved in the workbook. Trying to return Application.Caller.Value2 causes cyclic reference.
Also, the function isn't called (expected behaviour) if the VBA code is embedded in the workbook (xlsm), or if the workbook is in xls format. However, converting a workbook to xlsx causes the cells to be recalculated after workbook is opened as described.
You can do this in XLM or a C XLL by flagging the function as a macro function. In VBA the only easy way I know is an ugly hack : return Application.Caller.Text if the variable is not initialised.
This suffers from the major flaw that it gives you the formatted value of the cell rather than the actual value.
Otherwise you have to build a way of persisting the value of the cell in the closed-but-saved workbook: possible schemes include using Defined Names, Cell Comments, the registry, external files etc, but I don't think there is a clean VBA solution.
I eventually went with the xlsm approach.