Call built-in macro/function instead of my own

L

Larry Sulky

I need to intercept a few built-in macros, such as GrowFont. Based on
a boolean flag, I then want to execute Word's built-in GrowFont, as if
I'd never intercepted it. What's a nice, clean way to do that?

Sub GrowFont()
if flagNeverMind then ''' Oops! Let it go. Sorry I interfered.
''' Do the "real" GrowFont here, but how?
else
MsgBox "Not permitted at this time." , , "ERROR"
end if
End Sub

I'd rather not recreate the built-in macro within my own, but just
call it and gracefully step out of its way.

TIA--
--larry
 
T

That Guy

Well what you are explaining is a bit more involved than it has to be.

Check this article: http://msdn.microsoft.com/en-us/library/ff837542.aspx

It explains how to modify word commands. You can't intercept or handle
word commands but you can override them. Once you have the overridden
macro created just modify the command code to suit your needs.

So in this specific example you would have this:


Sub GrowFont()
'
' GrowFont Macro
' Increases the font size of the selection
'
If flagNeverMind Then ''' Oops! Let it go. Sorry I interfered.
Selection.Font.Grow
Else
MsgBox "Not permitted at this time.", , "ERROR"
End If

End Sub

Be sure to follow the article step by step because it is not intuitive
and almost seems deceivingly easy.
 
L

Larry Sulky

Well what you are explaining is a bit more involved than it has to be.

Check this article:  http://msdn.microsoft.com/en-us/library/ff837542.aspx

It explains how to modify word commands. You can't intercept or handle
word commands but you can override them. Once you have the overridden
macro created just modify the command code to suit your needs.

So in this specific example you would have this:

Sub GrowFont()
'
' GrowFont Macro
' Increases the font size of the selection
'
    If flagNeverMind Then ''' Oops! Let it go. Sorry I interfered.
        Selection.Font.Grow
    Else
        MsgBox "Not permitted at this time.", , "ERROR"
    End If

End Sub

Be sure to follow the article step by step because it is not intuitive
and almost seems deceivingly easy.

Thanks, Guy. I'm already doing that in several of my macros, but for
most of them I'd like to just trigger the built-in macro rather than
figuring out what the underlying code of the macro is and executing
that. In the example that you kindly filled out, you used
Selection.Font.Grow, which isn't hard to figure out. But I imagine
that some of them have more complex underlying code, which I would
have to deduce (and recording a macro doesn't always give useful
results). That's why I was wondering if there is a way just to call
the built-in macro of the same name... effectively to "un-override"
the macro.
---larry
 
L

Larry Sulky

Grrrk. I keep saying "built-in macro" when I mean "built-in command"

Here's another example that may help clarify. When a certain
condition, flagNeverMind, is false, then my code disables the
Formatting toolbar. That way, the user can't change the font used for
a run of text (among many other things she also can't do). But she can
still press Ctrl+Shift+F and get to the Font built-in command, and use
the cursor keys to select a font sight-unseen (even though the toolbar
is disabled). I doubt she would want to do this but not only do I not
want her to, I don't want her to get confused about what's happened if
she did it by accident.

So I create a macro named Font to override the built-in command Font.
That macro has to check flagNeverMind and if it's true, it has to do
the best it can to execute the originally intended action, which is to
give focus to the font selection window in the Formatting toolbar. How
do I do that? Wouldn't being able to just execute "BuiltIn.Font" be a
nice way? Is there another way?

Sub Font()
If flagNeverMind Then ' The Formatting toolbar must already be
enabled, since the flag is true.
MsgBox "Action 'Font' should be available to you but I don't
know " & _
"how to trigger the original built-in command, or
how to give " & _
"focus to the right part of the toolbar.", ,
"DEBUG"
Else
MsgBox "Action 'Font' is not available now.", , "ERROR"
End If
End Sub
 
L

Larry Sulky

Following my long-established precedent of answering my own questions:

Sub Font()
If flagNeverMind Then

Application.CommandBars("Formatting").Controls("Font:").SetFocus
Else
MsgBox "Action 'Font' is not available now.", , "ERROR"
End If
End Sub

The trick was to find out which control is called by the built-in
command, based on a good guess (note that it has a colon in the name,
which seems to be a convention for controls that have submenus), and
then simply use the SetFocus method. I used this code to get a list of
all the controls:

Sub ShowAllToolbarControls()
Dim myCommandBar As CommandBar
For Each myCommandBar In CommandBars
Dim myNames As String
myNames = myCommandBar.index & " " & myCommandBar.name & " ("
& myCommandBar.Controls.count & ") :: "
Dim ctl As Variant
For Each ctl In myCommandBar.Controls
myNames = myNames & ctl.Caption & ", "
Next ctl
Debug.Print myNames
Next myCommandBar
End Sub
 
T

That Guy

One thing you are assuming is that I had some kind of intuition when I
answered your question.

The one thing you have missed is that when you choose to create a new
macro built on top of one of the word macros it will start you off
with whatever they have already.

I have tried your new example and it would appear that not every
command can be exposed in this way. So I guess it is a bit of a crap
shoot.

It seems like you have it figured out. I hope the tip in the article
is help full all the same and I am glad you have found a solution.
 
A

AnthonyHall

Well what you are explaining is a bit more involved than it has to be.

Check this article:  http://msdn.microsoft.com/en-us/library/ff837542.aspx

It explains how to modify word commands. You can't intercept or handle
word commands but you can override them. Once you have the overridden
macro created just modify the command code to suit your needs.

So in this specific example you would have this:

Sub GrowFont()
'
' GrowFont Macro
' Increases the font size of the selection
'
    If flagNeverMind Then ''' Oops! Let it go. Sorry I interfered.
        Selection.Font.Grow
    Else
        MsgBox "Not permitted at this time.", , "ERROR"
    End If

End Sub

Be sure to follow the article step by step because it is not intuitive
and almost seems deceivingly easy.

It does indeed almost seem deceivingly easy. And that's right, because
it is deceiving: it doesn't actually work.For example, I tried the
method described in the Microsoft article with the various
FileSaveAs... commands such as FileSaveOdt. I didn't change the
created macro at all. Nevertheless, the behaviour was quite different.
Whereas the built in behaviour is to prompt for the new file name and
location, the behaviour of the created macro is simply to save the
file as an odt file under its existing name, no questions asked. This
is clearly useless.

It is indeed an extraordinary feature of VBA that it doesn't allow you
to intercept commands and then invoke the built in command. There is
exactly the same problem if you try to intercept keystrokes: what I
often want to do is examine the state of the document and in 99% of
cases do whatever Word would have done with the keystroke in the first
place. But there is no way of achieving this as far as I can see.
 
T

That Guy

There really is no way to do it with word and VBA because as far as I
know there is no way to hook into the applications events themselves,
other than a very few that are exposed in the application object and
to implement that takes a little jumping through hoops.

I think word 2007 has more features and I know there is a VB.NET
extension library for authoring tools for word 2007. Other than that
you can dive into writing a custom solution in VB.NET that would allow
you to control what is going to the word application object. Wrapping
word with VB6 and VB.NET is quite easy and the application interfaces
are very robust.

If all you have someone doing is typing up documents that don't need a
lot of fancy formatting and frills, then creating an implementation
like this would be somewhat easy. Check out codeproject.com I know
they have a whole bunch of good examples.

best of luck.
 
L

Larry Sulky

There really is no way to do it with word and VBA because as far as I
know there is no way to hook into the applications events themselves,
other than a very few that are exposed in the application object and
to implement that takes a little jumping through hoops.

I think word 2007 has more features and I know there is a VB.NET
extension library for authoring tools for word 2007. Other than that
you can dive into writing a custom solution in VB.NET that would allow
you to control what is going to the word application object. Wrapping
word with VB6 and VB.NET is quite easy and the application interfaces
are very robust.

If all you have someone doing is typing up documents that don't need a
lot of fancy formatting and frills, then creating an implementation
like this would be somewhat easy. Check out codeproject.com I know
they have a whole bunch of good examples.

best of luck.

Yes, I've found what both of you have found: it's a crap shoot, it's
under-supported, and it's weirdly implemented. It would all be SOOOOO
much easier if I could just say, "Please do the built-in function".

For example, I'm intercepting the Bold command. So I have to have a
macro that can either apply Bold local formatting, or, in some cases,
apply a BOLD style. HOWEVER, I've just realised that I also have to
have my macro be aware of when it's being called from within the
Format dialogue, or even from the Style dialogue, at which point it
has to do something else again. And I need to do this for every
command I need to intercept. So I have to figure out how to know where
a command/macro is being called from. *sigh*
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top