brenns
asked on
SetFocus for built-in Outlook mail form with VBA
As part of a Send and File mail message routine I've implemented using a custom toolbar button in Outlook XP, I attempt to invoke the ActiveInspector.CommandBar s("Tools") .Controls( "Spelling. ..").Execu te method before performing an ActiveInspector.CurrentIte m.Send method. Unfortunately, the Tools/Spelling menu item is inactive (and thus fails when called by VBA code) if the focus of the built-in Outlook mail form is not on the Subject or Body form controls (i.e. if it's instead in the From, To, CC fields). So, prior to invoking the "Spelling..." menu item, I first need to set the focus of the form to the Subject or Body form control.
This sounds simple enough, but it is not. Let me tell you a few things that DO NOT work:
1) ActiveInspector.CurrentIte m.Body.Set Focus - this does NOT work because the MailItem.Body property is NOT the same as the body form control, and SetFocus will not work
2) ActiveInspector.ModifiedFo rmPages("M essage").C ontrols("M essage").S etFocus - this does NOT work because the ModifiedFormPages collection is empty when you are using the default/built-in Outlook forms. This option would work if I was using custom forms, but I am not.
3) Prompting the user to place the cursor in the Subject/Body fields if it's not there - this will NOT work as a solution because the customer wants a TRUE solution (nice try though)
So, here's the question, for which an answer would be enormously appreciated
1) How can I set the focus of the default/built-in (NOT custom) Outlook mail message form to the Subject or Body fields using Outlook VBA from the VbaProject.OTM project?
Thanks!
-------------------------- ---------- ---------- ---------
P.S. The reason I'm attempting to use the menus to invoke the spell checker is that I could not figure out a way to invoke it any other way. There does not appear (in the research I've done at least) to be a way perform the .CheckSpelling method in Outlook like you can in Word or Excel. If you can tell me how to invoke the spell checker without the menu, which bypasses the SetFocus problem I face, you get the points, a blue ribbon, and a free pizza.
This sounds simple enough, but it is not. Let me tell you a few things that DO NOT work:
1) ActiveInspector.CurrentIte
2) ActiveInspector.ModifiedFo
3) Prompting the user to place the cursor in the Subject/Body fields if it's not there - this will NOT work as a solution because the customer wants a TRUE solution (nice try though)
So, here's the question, for which an answer would be enormously appreciated
1) How can I set the focus of the default/built-in (NOT custom) Outlook mail message form to the Subject or Body fields using Outlook VBA from the VbaProject.OTM project?
Thanks!
--------------------------
P.S. The reason I'm attempting to use the menus to invoke the spell checker is that I could not figure out a way to invoke it any other way. There does not appear (in the research I've done at least) to be a way perform the .CheckSpelling method in Outlook like you can in Word or Excel. If you can tell me how to invoke the spell checker without the menu, which bypasses the SetFocus problem I face, you get the points, a blue ribbon, and a free pizza.
ASKER
vinnyd79, thanks, but that's the same solution that I described in my first follow-up comment. Although that solution works, it wont work in this instance because:
a) too slow
b) confusing for the end user
c) ugly
But, as we both know, it does work, so thanks for the comment, even though I had anticipated that response.
a) too slow
b) confusing for the end user
c) ugly
But, as we both know, it does work, so thanks for the comment, even though I had anticipated that response.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Scott,
Good thought, and yes I have tried that. The problem is that SendKeys appears (and I could be wrong here) to just be sending keystrokes into never-never-land. It's as if the code needs to first activate the form somehow before SendKeys knows where to place the keystrokes. I've tried having SendKeys send vbTab and just plain old text. If I place my cursor in the "To" field before executing the SendKeys code, I can't get ANY text to be placed in that field, much less tabs. The problem might stem from the fact that the code for the "Send and File" button is completely independent of the built-in form, but I don't really know. I just know it doesn't appear to work.
Although I (me, personally) can't get this to work, it's possible that it's a workable solution. It's still not as good as simply invoking a checkspelling or manually setting the form's focus, but it's more doable than the external Word spell check.
On a related note, I've also tried to use something like Selection.TypeText vbTab (which is how Word records a Tab press in a Macro) to no avail.
If you have some ideas how I can pursue this Scott, I'd be happy to give them a shot.
Good thought, and yes I have tried that. The problem is that SendKeys appears (and I could be wrong here) to just be sending keystrokes into never-never-land. It's as if the code needs to first activate the form somehow before SendKeys knows where to place the keystrokes. I've tried having SendKeys send vbTab and just plain old text. If I place my cursor in the "To" field before executing the SendKeys code, I can't get ANY text to be placed in that field, much less tabs. The problem might stem from the fact that the code for the "Send and File" button is completely independent of the built-in form, but I don't really know. I just know it doesn't appear to work.
Although I (me, personally) can't get this to work, it's possible that it's a workable solution. It's still not as good as simply invoking a checkspelling or manually setting the form's focus, but it's more doable than the external Word spell check.
On a related note, I've also tried to use something like Selection.TypeText vbTab (which is how Word records a Tab press in a Macro) to no avail.
If you have some ideas how I can pursue this Scott, I'd be happy to give them a shot.
ASKER
Scott,
Let me add something about SendKeys that I didn't mention before. If I "manually" execute a macro (using Tools/Macro/Macros... and then selecting my public sub) that houses the line "SendKeys vbTab", I can shift the focus of the form to the next field. So I know, in theory, SendKeys does work in my scenario.
Hold the presses!
I did in fact figure out how to get the SendKeys procedure to work from my code. I'm such a dumb-ACK sometimes. If I do a "SendKeys vbTab, 1" and wait for the procedures to process the keypress before continuing (which is what the boolean wait is for in SendKeys string[, wait]), it actually performs the tab press.
Unfortunately, even after the tab keypress moves the cursor into the message body field, the Tools menu is not being updated. Take a look at my loop below. I tried adding in a DoEvents hoping that would allow the menu to update, but that doesn't work. I have to manually break out of the loop with the loopcount variable because the commandbar execute keeps failing (which adds a bunch of tab to the message body). After falling out of the loop, the final commandbar execute fails.
On Error Resume Next
loopcount = 0
Do
Err.Clear
SendKeys vbTab, True
ActiveInspector.CommandBar s("Tools") .Controls( "Spelling. ..").Execu te
loopcount = loopcount + 1
DoEvents
Loop Until Err.Number = 0 Or loopcount > 50
On Error GoTo 0
ActiveInspector.CommandBar s("Tools") .Controls( "Spelling. ..").Execu te
However, if after I run the code and it fails, I then manually select Tools/Spelling... or simply click my button again, it works. We're getting close here.
Let me add something about SendKeys that I didn't mention before. If I "manually" execute a macro (using Tools/Macro/Macros... and then selecting my public sub) that houses the line "SendKeys vbTab", I can shift the focus of the form to the next field. So I know, in theory, SendKeys does work in my scenario.
Hold the presses!
I did in fact figure out how to get the SendKeys procedure to work from my code. I'm such a dumb-ACK sometimes. If I do a "SendKeys vbTab, 1" and wait for the procedures to process the keypress before continuing (which is what the boolean wait is for in SendKeys string[, wait]), it actually performs the tab press.
Unfortunately, even after the tab keypress moves the cursor into the message body field, the Tools menu is not being updated. Take a look at my loop below. I tried adding in a DoEvents hoping that would allow the menu to update, but that doesn't work. I have to manually break out of the loop with the loopcount variable because the commandbar execute keeps failing (which adds a bunch of tab to the message body). After falling out of the loop, the final commandbar execute fails.
On Error Resume Next
loopcount = 0
Do
Err.Clear
SendKeys vbTab, True
ActiveInspector.CommandBar
loopcount = loopcount + 1
DoEvents
Loop Until Err.Number = 0 Or loopcount > 50
On Error GoTo 0
ActiveInspector.CommandBar
However, if after I run the code and it fails, I then manually select Tools/Spelling... or simply click my button again, it works. We're getting close here.
ASKER
Something new to report. ActiveInspector.CommandBar s("Tools") .Reset does the trick. The following code now actually works for my testing.
On Error Resume Next
loopcount = 0
Do
Err.Clear
SendKeys vbTab, True
ActiveInspector.CommandBar s("Tools") .Reset
ActiveInspector.CommandBar s("Tools") .Controls( "Spelling. ..").Execu te
loopcount = loopcount + 1
Loop Until Err.Number = 0 Or loopcount > 50
This isn't the prettiest code, but it does actually work. I've been trying to create a situation in which it doesn't work (i.e. setting focus on buttons first), but I can't. So, Scott, unless someone can tell me how to actually invoke the checkspelling method within Outlook in the next day or so, this solution is "good enough". And since your thought actually prompted me to take another look at why SendKeys was failing for me, the thanks will go to you.
On Error Resume Next
loopcount = 0
Do
Err.Clear
SendKeys vbTab, True
ActiveInspector.CommandBar
ActiveInspector.CommandBar
loopcount = loopcount + 1
Loop Until Err.Number = 0 Or loopcount > 50
This isn't the prettiest code, but it does actually work. I've been trying to create a situation in which it doesn't work (i.e. setting focus on buttons first), but I can't. So, Scott, unless someone can tell me how to actually invoke the checkspelling method within Outlook in the next day or so, this solution is "good enough". And since your thought actually prompted me to take another look at why SendKeys was failing for me, the thanks will go to you.
Glad it worked. I don't do any outlook atomation myself, so I'm not intimate with It's behavior. That's why I gave you the "old school" suggestion.
scott
scott
Brenn,
The solution is fairly simple.
On Error Resume Next
loopcount = 0
Do
Err.Clear
SendKeys vbTab, True
ActiveInspector.CommandBar s("Tools") .Reset
ActiveInspector.CommandBar s("Tools") .Controls( "Spelling. ..").Execu te
loopcount = loopcount + 1
Loop Until Err.Number = 0 Or loopcount > 50
I'll take the 500pts now.
The solution is fairly simple.
On Error Resume Next
loopcount = 0
Do
Err.Clear
SendKeys vbTab, True
ActiveInspector.CommandBar
ActiveInspector.CommandBar
loopcount = loopcount + 1
Loop Until Err.Number = 0 Or loopcount > 50
I'll take the 500pts now.
nice try dj
ASKER
Well, since we didn't get an honest to goodness .CheckSpelling solution, and Scott forced me to go back and look at my SendKeys attempt, thanks go to Scott.
thanks brenns!
Brenn,
I thought we were buddies? :-)
I thought we were buddies? :-)
ASKER