From the Excel Window, I can assign a shortcut key to my macro by:
going to the Developer tab
touching the Macros button
touching Options... in the resulting Dialog Box
Can I assign this from within the VBE Window, using the VBE menu bar instead??
The Application.OnKey approach keeps the shortcut separate from the procedure (which makes maintenance difficult), and you might end up with conflicts - particularly if you've assigned keys using the Macros dialog and the Application.OnKey property. And, of course, you need the SetShortCutKeys code to run on workbook_open, which might not always run.
Fortunately, it is possible to assign the shortcut key in VBA, and within the procedure itself, but you'll need to export the module, edit the text file, and then reimport. Unfortunately, while VBA does maintain the code, the shortcut keys only seem to work in Excel. Perhaps it's a feature of VBA that the host application can optionally support.
Let's say you have the following VBA in a standard module:
Option Explicit
Public Sub Bar()
MsgBox "Bar"
End Sub
If you use the Macros dialog in Excel, and choose a shortcut key for the Bar macro to Ctrl+Shift+T, and then Export the module to a text file, you'll find the module source is:
Attribute VB_Name = "Module1"
Option Explicit
Sub Bar()
Attribute Bar.VB_ProcData.VB_Invoke_Func = "T\n14"
MsgBox "Bar"
End Sub
Notice the Attribute Bar.VB_ProcData.VB_Invoke_Func = "T\n14" attribute, which wasn't visible in the VBIDE, but is persisted by VBA in the underlying source. The T in T\n14 is a case-sensitive key (which implies a Shift), and I think the \n14 must refer to the Ctrl key. By following the VB Attribute naming pattern and syntax, and including similar lines in your other procedures, you can assign shortcut keys in other procedures using the text editor, and then, when you're done, you can import the modified module back into the VBA project.
Note that once you import the modified module, you'll no longer be able to see the attribute lines, and you'll need to take care not to change the name or number of parameters in the procedure, as the VBIDE might delete the underlying attribute without warning you.
Alternatively, if you want to do it using VBA you can do something like:
Sub SetShortcutKeys()
With Application
.OnKey Key:="^+K", Procedure:="YourMacroGoesHere"
End With
End Sub
Related
In my modules, I want to use my controls from my form. For example: I want to set focus on a textbox after a certain Sub.
My current solution is to make a subroutine to set all controls in a public variable (see below).
My questions:
What is the best practice? How do people usually do this?
When should I call my subroutine? (is it the first call in the FORM_LOAD sub?)
Public TBnr As TextBox
Public Sub controlsInitieren()
Set TBnr = Forms("frm_TreeView_Example").pstNr
End Sub
Well, as a general rule, while many platforms seperate out the UI part and the code part? Well, Access is quite much a different approach - it is standard fair to place the required code inside of the form "class" (all forms in Access are a "class", and you can even have muliple instances of the SAME form open more then one time).
So, in general, your code should be in the forms code (class) module.
However, you could and call a external routine.
So in the form, you could call your above routine like this:
Call MySetFocus(me, "NameOfControlToSetFocusTo")
And your sub would look like this:
Sub MySetFocus(f as form, sCtrl as string)
f(sCtrl).SetFocus
End Sub
However, as noted, the amount of code above is more code then simply in the forms code module going:
me.ControlName.SetFocus
However, while the above is a less then ideal example, passing the form "instance" (me) to a external sub or function allows you to referance any property or method or feature that exists in the form in an external routine.
So in place of say
me("LastName") = "Zoo"
In the above sample routine, you would and could go;
f("LastName") = "Zoo"
So any place you would and could use "me" in the form, you can use the form instance you passed from the form. As noted, it is a good idea to use "me", since as I noted, Access does allow multiple copies of the form to be opened at the same time - and thus your code can't distinguish between what form instance you are using unless you pass the current "in context" form. So like in JavaScript, using "this" ?
In access that current instance of the class object is "me", and you are free to pass that instance to any sub or function you want as per above.
The best practice is to use only procedures inside the form code. In such a case you refer to a text box control in this way: Me.Textbox1.SetFocus. If you want to set some controls properties during the form loading, you can do that in the frm_TreeView_Example_Initialize event;
They usually do it in the way I described at item 1;
If you want to use such a strange/unusual way you can do it calling the subroutine whenever you want. But, in order to set a specific property value of the form frm_TreeView_Example controls you can simply use frm_TreeView_Example.TextBox1.SetFocus. You can use this way of setting in a module procedure, even before the form has been shown. You can simply show it in that procedure code using at the end: frm_TreeView_Example.Show;
I have an Excel project with a lot of macros.
What I want is assign macros to buttons in the ribbons.
For that I created macros like:
Sub R10_parallel_device()
help.helpON ("parallel_device ")
Call sub_novelty_claims("parallel_device")
End Sub
So the three conditions are met:
a) the macro SUB R10_parallel_device() do not accept parameters
b) it is not private
c) It is not hide
when I go to the list of macros I see all the list of macros named Rnn but all THE BUTTONS ARE GREY OUT EXCEPTFOR CREATE.
Now if I click in that sub for instance SUB R10_parallel_device() I can not edit it and if I click "create" excel sends me to a new created module where
Sub R10_parallel_device()
End Sub
appears.
&
When I go to file/options/ribbon if I want to add that macro to a button it is listed and it is possible to assigne the macro to a button but it would not run, giving the error that such a macro is not found.
NOTE: I checked which macro are listed thisworkbook/all/ etc.
note2: this did not help me. this neither
thx
Confirmed it's the macro names - go to Developer -> View Code (or type Alt + f11), then select the module with your code in it and rename them. For whatever reason it's that R# syntax:
I know how to use variables in Word 2010 using VBA. However, they are all reset when the document in closed and reopened.
How do I store a variable permanently in a Word document?
This can be used:
Sub Test()
ActiveDocument.Variables.Add Name:="PermanentVar", Value:=100
'ActiveDocument.Variables("PermanentVar").Delete
End Sub
Check if it is retained:
Private Sub Document_Open()
Msgbox ActiveDocument.Variables("PermanentVar")
End Sub
Ref MS kb Link
Ref SO link
Use a custom document property instead. These are stored on the Word document permanently, and can be edited and retrieved using VBA.
To create a custom property, go to File > Properties > Advanced Properties (this will be in a slightly different place in older version of Word but will still be there somewhere...).
Go to the Custom tab from the advanced properties, and fill in the name of your custom document property, the field type (you can select text, date, number or a Yes/No flag, which should cover off most options), and a starting value - you have you include a starting value or the Add button will be greyed out. Click Add.
You now have a custom property in your document, and you can use VBA to manipulate and reference it.
To change the value of your property, use the following code:
Application.ActiveDocument.CustomDocumentProperties.Item(1).Value = "Your new value..."
Item(1) is set because this is reference the first custom document property in your document. If you have more than one custom property, you'll need to change the number to reference the correct property, or write some VBA that will reference the property by name.
To pass the property to a variable, use the following code:
strYourVariable = Application.ActiveDocument.CustomDocumentProperties.Item(1).Value
I've seen lots of code for how to ActivateTab OnLoad but can't get it to work dynamically... on the click of a worksheet button for example.
There is a button on Sheet1 pointing at startHereConfigure
<customUI onLoad="RibbonOnLoad"
xmlns="http://schemas.microsoft.com/office/2009/07/customui">
Public Rib As IRibbonUI
Sub RibbonOnLoad(ribbon As IRibbonUI)
Set Rib = ribbon
End Sub
Sub startHereConfigure()
Rib.ActivateTab "Configure"
End Sub
I want to be able to call startHereConfigure (and other similar subs) to bring to the fore a particular Tab - how do I do this?
Add this line to the custom XML file:
<customUI onLoad="RibbonOnLoad" xmlns="http://schemas.microsoft.com/office/2009/07/customui">
Where "RibbonOnLoad" is the name of the function to be called upon starting Outlook.
Add this funciotn into a standard module:
Public Rib As IRibbonUI
Sub RibbonOnLoad(ribbon As IRibbonUI)
Set Rib = ribbon
Rib.ActivateTab "Configure" ' Name of the tab to activate
End Sub
Jorge's answer is the normal way.
I introduce 2 other work-arounds here.
One is moving your custom tab control before the Home Tab
by adding 'insertBeforeMso' in your customui(14).XML.
<tab id="id1" label="Tab1" insertBeforeMso="TabHome">
Your 'Tab1' is the first one, so it is activated first when opening your office file.
The other one is using SendKey method which is a little tricky.
After adding onLoad macro in customui XML,
you can add following lines in a module in VBE.
Sub onLoad(control As IRibbonUI)
'control.ActivateTab "Tab1"
Application.SendKeys "%Y%" 'Alt + Y + Alt key
End Sub
Here 'Y' key is your custom tab shortcut key and 'Alt' key is sent again after 'Y' key in order to prevent the Alt shortcut keys from appearing on ribbon menus.
Samuel Liew: I thought the way I answered was implicit enough.
The following is the same expanded to be more explicit:
Sean: Unclear from the above if you got an answer or you solved it yourself.
As, I can't see an answer and your last comment suggests you went off with false information.
Certainly your code should work in 2010 office systems.
I'm doing just that and activating a range of different tabs, based on targeted worksheet 'types' becoming active. And the tab activation code is just part of a general workbook events handling sub (i.e. called by application event handlers).
And that has been operational since prior to you asking this question.
So the response from Siddharth Rout above about not being able to do this is invalid.
I'm assuming your Tab id is defined in the xml to match the id in your code above per:
<tab id="Configure" label="YOUR LABEL" >
I'm also assuming the rest of your xml is correct, and you can see the tab, just not be able to activate it.
If all that's the case, as to 'How to': You should just need to call that sub.
In my case I do that on Workbook or Worksheet activated (on open or change of window). But any call mechanic (such as your in-sheet control) should work just as well.
As an aside, I'd recommend using more obviously unique codes for ribbon control ids
e.g. Using some leading chars from the overall function and the control type like 'xyzTab_Configure'.
Just means if/when you add more, you have a explicit way to know which is which, and avoid any clashes.
That all covered: I have however run into an issue with office 2019.
See: vba IRibbonUI.ActivateTab not working in Office 2019
So first, when one clicks on the "View Macro" button, this pops up:
What I want to know is, is there some code that I can run on workbook open (and then "unrun" on workbook close) that grays out that run button (like the others underneath it are) ONLY until the password is entered in the VBA project (using Alt+F11 to open the editor)?
I don't want the users to be able to run any of these subs manually.
If you declare the sub so that it needs input, even optional input it will not show in the list either.
sub Test(optional a as string)
Declare the subs as private and they won't show up in the Alt+F8 dialog box.
Declare them as public (the default) and they will.
You can use vba to edit the vba code of another module.
Is it possible in Excel VBA to change the source code of Module in another Module
You can change one line or search through the lines and comment/uncomment whole blocks of code. Capturing the event when vba is unlocked may be the hard part. You may have to run a sub that does this after unlocking vba.
I think you have the wrong approach to this and it would be better to structure your code more properly.
The first two on that sheet are called from other macros that are run with buttons on my main worksheet.
OK. So attach these to a form control/button, and use Bigtree's suggestion to include an optional argument in these subs. They will not display in the Macros menu. YOU can run them at least three different ways:
either from the VBE by finding the procedure and pressing F5, or
by entering the name of the procedure in the Immediate window in the VBE, or
by pressing the buttons you have provided.
The middle two are called when the sheet opens and closes
Sounds like this should be a private subroutine (or, use the method above from Bigtree) and CALL these from the one or more of the appropriate event handlers (at the worksheet level perhaps: Worksheet_Activate, Worksheet_Deactivate; or at the workbook level SheetActivate and SheetDeactivate depending on your needs)
You can always run the procedure manually from the Immediate window in VBE, or by manually invoking the event procedure, etc.
and the last two I manually call when I want to edit my main sheet
Again, call from the Immediate window or manually from the VBE. You only have 6 subroutines here, it can't be that difficult to locate the ones you frequently need. Put them in a new module and organize your modules so you know where these are.
Alternatively, put some boolean in the subroutine like:
Sub SheetLock()
If Not Environ("username") = "YOUR_USERNAME" Then Exit Sub
'other code to do stuff is below...
End Sub
UPDATE FROM COMMENTS
The Immediate Window is like a console/command line, it is where the result of your Debug.Print statements would appear, etc. It is very handy for debugging and evaluating expressions.
There are several ways you could invoke the subroutine depending on whether it is public/private, including
Application.Run "MacroName" or simply MacroName if public
Application.Run "ModuleName.MacroName" or Call ModuleName.MacroName if private
I did not want to use a private sub,
I used the shape name to determine if from a button
On Error GoTo noshapeselected
shapeis = ActiveSheet.Shapes(Application.Caller).Name
' I manually set the shape name in the page layout tab selection pane
' below I test for the desired button
If shapeis = "your button name" then
goto oktogo
else
goto noshapeselected
endif
noshapeselected:
msgbox ("must run from a button")
goto theendsub
oktogo: 'continue if desired shape was selected
theendsub: 'a button was not pushed
For those macros without buttons, but called by another macro,
set a variable to 'OK' to run a macro, then the called macro tests for 'OK' ('OK' means initiated by another macro 'NOK' means not initiated by another macro)