Sanity Check

G

Greg Maxey

Hello,

I am working on a macro that I want to run from a menu command located on the "Table" menu. Like "Table Properties," I want this menu item dimmed if the selection is not in a table. I scratched around and found "WindowsChangeEvent" and cobbled together the following Class Module routine:

Option Explicit
Public WithEvents appWord As Word.Application
Private Sub appWord_WindowSelectionChange _
(ByVal oSel As Selection)
If oSel.Information(wdWithInTable) Then
CommandBars("Table").Controls("Table Data").Enabled = True
Else
CommandBars("Table").Controls("Table Data").Enabled = False
End If
End Sub

Seems to work like a charm. However, I am a little uneasy with the knowledge that every time I change the selection a macro is going to run. Hence the subject line. Is it sane to do what I have done. Is there a more appropriate method?

Thanks.
 
J

Jezebel

If you notice a performance hit, then no, it's insane. But you won't notice
anything, so yes it's fine.

You could improve performance a little --

1. Create a module-level variable for the control.
2. When you initialize the class, set the variable.
3. Simplify your code ...

' Module --------------------------
Private mMenuOption as Office.CommandBarControl
Private WithEvents appWord as Word.Application 'Is there some
reason you're making this public in your code?

Private Sub Class_Initialize()
set mMenuOption = CommandBars("Table").Controls("Table Data")
end sub

Private Sub appWord_WindowSelectionChange (ByVal oSel As Selection)
mMenuOption.enabled = oSel.Information(wdWithInTable)
end sub







Hello,

I am working on a macro that I want to run from a menu command located on
the "Table" menu. Like "Table Properties," I want this menu item dimmed if
the selection is not in a table. I scratched around and found
"WindowsChangeEvent" and cobbled together the following Class Module
routine:

Option Explicit
Public WithEvents appWord As Word.Application
Private Sub appWord_WindowSelectionChange _
(ByVal oSel As Selection)
If oSel.Information(wdWithInTable) Then
CommandBars("Table").Controls("Table Data").Enabled = True
Else
CommandBars("Table").Controls("Table Data").Enabled = False
End If
End Sub

Seems to work like a charm. However, I am a little uneasy with the
knowledge that every time I change the selection a macro is going to run.
Hence the subject line. Is it sane to do what I have done. Is there a more
appropriate method?

Thanks.
 
G

Greg Maxey

Jezebel,

OK, thanks. I will give that a try.

After posting the initial question, I noticed that if I quit and restarted
Word then the process didn't work until I re-initialized the class.

Dim X as New myClass1
Sub Register_Event_Handler()
Set X.appWord = Word.Application
End Sub

So do I put this reinitailization in an AutoExec macro, or someplace else?

Thanks
 
G

Greg Maxey

Jezebel,

The question you asked "is there some reason your are making this puplice in
your code."

Well, answer is that I don't know any better. This is what I have now in
the Class module:

Option Explicit
Private mMenuOption As Office.CommandBarControl
Public WithEvents appWord As Word.Application
Private Sub Class_Initialize()
Set mMenuOption = CommandBars("Table").Controls("Table Data")
End Sub
Private Sub appWord_WindowSelectionChange(ByVal oSel As Selection)
mMenuOption.Enabled = oSel.Information(wdWithInTable)
End Sub

As I mentioned in the last post, each time I start Word, I have to
initialize the class. To do that, currently have this code in another
module:

Dim myDynamicMenu as New myClass1
Sub Register_Event_Handler()
Set myDynamicMenu.appWord = Word.Application
End Sub

This only works if the the other piece is Public.

Please advise.

1. How do I keep it all Private?
2. Where do I put the code to automatically re-initialize the Class each
time Word starts.

Thanks
 
J

Jezebel

You've got two inititializations to deal with --

1. You need to inititialize your class object. Word's AutoExec is the
obvious place for this. Bear in mind that doing anything that resets VBA (ie
editing ANY code) will kill it. So in your AutoExec module --

Private mDynamicMenu as MyClass (Don't use 'As new'
declarations...)

Public Sub AutoExec()
Set mDynamicMenu = new MyClass
End sub


2. Within the class object, you need to inititialize the WordApp variable.
The class's Initialize event is the place for this --

Private WithEvents mWordApp as Word.Application
Private mMenuOption as Office.CommandBarControl

Private Sub Class_Initialize()
Set mWordApp = Word.Application
set mMenuOption = CommandBars("Table").Controls("Table Data")
End sub
 
G

Greg

Jezebel,

Thanks. I got close! I have managed to get the private declaration
part to work, however there is still a problem when I try to trigger
the Class initialization from AutoExec. If I let Word start first and
the run:

Sub Test()
Set myDynamicMenu = New MyClass
End Sub

Then everything works fine. If I move that line to an AutoExec macro,
there is an error generated one this line of the WindowSelectionChange
procedure:

mMenuOption.Enabled = oSel.Information(wdWithInTable)

At the first attempt to change the selection.

The error generated is:

Run time error '424' Object Required. Can't move the focus to the
control because it is invisible, not enabled, or of the type that does
not accept the focus.

It doesn't appear to be a timing issue as I have tried introducing a
delay in the AutoExec procedure. It seems that Word insists on being
completly opened before entertaining that line of code.

I took it out and replaced it with the full name of the control as
shown below and all seems to work as expected.

Private Sub mWordApp_WindowSelectionChange(ByVal oSel As Selection)
Dim bSavedState As Boolean
bSavedState = NormalTemplate.Saved
'mMenuOption.Enabled = oSel.Information(wdWithInTable)
CommandBars("Table").Controls("Table Data").Enabled =
oSel.Information(wdWithInTable)
NormalTemplate.Saved = bSavedState
End Sub

No big deal at this point, but if you know why that is happening, I
would be interested. Thanks.

If you want to see the purpose of this whole mash, see
http://gregmaxey.mvps.org/Table_Cell_Data.htm
wherein I will have to update the enhancements you have shown me today.

Thanks again.
 
J

Jezebel

The reason it's happening is that Auto_Exec runs when Word loads, before
*any* document is open: at which point there is no selection, so obviously
oSel is nothing. I suspect you might get the same error if you close all
documents without closing Word. Fortunately this error doesn't matter to
you, because if there's no document, the user can't display the Tables
context menu anyway. So the simplest (and best!) course of action is to
ignore the error --

On error resume next
mMenuOption.Enabled = oSel.Information(wdWithInTable)
on error goto 0
 
G

Greg Maxey

Jezebel,

Your explanation seems sound, but still no joy. I tried that and several
other error handling processes last night. The error handler works to avoid
the error message, but a new error is generated each time the
WindowsChangeEvent occurrs after the document is fully opened.

If after the document is open and I step through the code an I can see that
an error will be generated by mousing over mMenuOption.Enabled. I reports
<object required>

Other than being a longer line of code, is there anything else wrong or
inefficient with just using

CommandBars("Table").Controls("Table Data").Enabled

???

Thanks.
 

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