Word mutti-session handling within VBA

Q

QK

I have my VBA code fires up a word doc at run time, which does some search
and text gathering and populates into an Access table, then it QUIT (by
oWord.QUIT method).
At this stage if the user opens another word doc, play around and exit, the
"automated" word doc is prompted for "save/cancel" (I'm sure at this satge
the "text gathering and populates into an Access table" hasn't completed yet).
It ends up the populated info into the Access table is totally unexpected!
In VBA, how to manage multi-sessions of MS Words (let's say some fire up by
VBA,
some fire up by user interactively)?
Thanks
 
T

Tony Jollans

If you have a visible automation instance and you release control to the
user you must be aware that absolutely anything can happen. You should be
able to keep track of your own document(s) and can check for other open
documents in the instance and take whatever action you deem sensible but
there are worse things that can happen. The user could close your document,
or the Word instance, or resume your process whilst pausing a macro, or
anything else you can imagine.

Probably not the answer you want but if it really is necessary to let the
user loose there are no guarantees!
 
E

Ed

I have my VBA code fires up a word doc at run time, which does some search
and text gathering and populates into an Access table, then it QUIT (by
oWord.QUIT method).
At this stage if the user opens another word doc

Not quite sure I get this. This sounds like AFTER your macro has run to the
end and quit, and THEN the user opens up another Word doc, you get problems?

Or the other scenario is that the user opens another Word doc WHILE the
macro is still running. If you are using the code I gave you as it is with
no modifications, then your problem is right there! That code uses the
Selection object (because Range does not have the wdLine method, whilst
Selection does). It also does not set a document object to work on; in
other words, the code assumes the only document open will be the one you
want searched. If you open another document, you change your focus - AND
what the Selection object sees.
In VBA, how to manage multi-sessions of MS Words (let's say some fire up
by
VBA,
some fire up by user interactively)?

That depends on whether the code is opening the document, the code presents
the user with a dialog box to choose a document to open, or the user is
opening a document unrelated to the process.

Ed
 
Q

QK

You've found me again, even I made a typo mistake in "mutti" rather than
"multi"!

Ed said:
Not quite sure I get this. This sounds like AFTER your macro has run to the
end and quit, and THEN the user opens up another Word doc, you get problems?

QK: No, this is NOT the scenario.
The one below IS.
Or the other scenario is that the user opens another Word doc WHILE the
macro is still running. If you are using the code I gave you as it is with
no modifications, then your problem is right there! That code uses the
Selection object (because Range does not have the wdLine method, whilst
Selection does). It also does not set a document object to work on; in
other words, the code assumes the only document open will be the one you
want searched. If you open another document, you change your focus - AND
what the Selection object sees.
QK: Yes, I am using your code. Then how in VBA cope with this?
That depends on whether the code is opening the document, the code presents
the user with a dialog box to choose a document to open, or the user is
opening a document unrelated to the process.
QK: Windows is multi-tasking. On one hand the user runs an Access
appliaction, which fires up Word and does this "search and populates info..."
stuff. While it is running (take some time to finish), in stead of idling
here, the user opens another word doc to play with (totally unrelated to the
above process). This is quite common a Window task, i.e. multi-tasking!

Or should I just simply make the automated word doc INVISIBLE then the
problem resolved?
 
E

Ed

Hi again!
QK: Windows is multi-tasking. On one hand the user runs an Access
appliaction, which fires up Word and does this "search and populates
info..."
stuff. While it is running (take some time to finish), in stead of idling
here, the user opens another word doc to play with (totally unrelated to
the
above process). This is quite common a Window task, i.e. multi-tasking!

Ed: Multi-tasking isn't the issue. The issue is that you have a program
running that is working with the Selection object of the ActiveDocument. If
you open another document, *that* becomes the ActiveDocument, and the
program will then look for the Selection in *that* document and go from
there.
QK: Yes, I am using your code.

Ed: Aha! _There's_ the problem! 8>)
QK: Then how in VBA cope with this?

Ed: We need to switch to the Range object. If a document can be specified
and a Range object used, then the code will act only on that specific
document no matter what is opened. There may be a problem, though,
according to your original explanation:
QK: 4) Upon finding this specific text, i.e. "09 March 2006",
QK: 5) I'll move 3 lines under to get to the customer string line &
selected.

Ed: I used the Selection object because it has the wdLine method for
movement; the Range object does not. So we need to find a different way of
specifying the movements needed to get from the date to the customer name.

When you say "3 lines under", I'm wondering if these are just "lines", or if
each line is a separate paragraph, which would make the customer name "3
_paragraphs_ under". That we can work with, because the Range object does
have a wdParagraph method.

So if you turn on viewing non-printing characters (Tools >> Options >> View
tab, Formatting, All in Word XP), do you see:

date ¶





customer name ¶


If not, how is it laid out?

Ed
 
E

Ed

Hoping to avoid long time lags from time differences, I adjusted the code to
work with Ranges. NOTE: this code assumes the following:
(1) the customer name is actually three *paragraphs* below the date
(2) the customer name is the only text in that paragraph.
I based those assumptions on seeing many reports where the headers
containing the identifying data are only a couple of words on a single line
ending in a paragraph break. I know this can be a bad assumption, but there
it is in the interests of moving things along.

HTH
Ed

Sub XX_Test_FindAndPages2()

Dim objDoc As Document ' working document
Dim rngDoc As Range ' range to be checked
Dim rngInfo As Range ' range with info
Dim strCheck As String ' date to look for
Dim strCust As String ' customer name
Dim lngPages As Long ' number of pages
Dim lngCust As Long ' count of customers
Dim aryCust() ' array of customer names
Dim aryPgs() ' array of no. of pages
Dim x As Long, y As Long ' page number holders
Dim a As Long, b As Long ' number holders
Dim bolEndOfDoc As Boolean ' True if no match found

Set objDoc = ActiveDocument
Set rngDoc = objDoc.Content
Set rngInfo = objDoc.Content

lngCust = 0
a = ActiveDocument.BuiltInDocumentProperties(wdPropertyPages)
strCheck = InputBox("What date are you searching for?")
If strCheck = "" Then GoTo EndMe
Selection.HomeKey wdStory

Do
' The Find operation resets the Range object
' to just the Found text. This code allows a search
' of rngDoc for rngInfo without losing rngDoc
rngInfo.SetRange _
Start:=rngDoc.Start, _
End:=rngDoc.End

bolEndOfDoc = True ' sets False if match is found
With rngInfo.Find
.ClearFormatting
If .Execute(FindText:=strCheck, MatchWholeWord:=False, _
Forward:=True, Wrap:=wdFindStop) = True Then
' found a match
bolEndOfDoc = False
' select customer name
lngCust = lngCust + 1
' the following code assumes the 3rd paragraph below
' the found date is one and only one line, and the
' only text on that line is the customer name
rngInfo.Collapse wdCollapseStart
rngInfo.MoveStart Unit:=wdParagraph, Count:=3
rngInfo.MoveEnd Unit:=wdParagraph, Count:=1

strCust = rngInfo.Text
' write into array
ReDim Preserve aryCust(lngCust)
aryCust(lngCust) = strCust
' get page number
y = x

x = rngInfo.Information(wdActiveEndPageNumber)
' If this is the first find, then loop again
' else subtract page numbers and add to array
If lngCust <> 1 Then
ReDim Preserve aryPgs(lngCust - 1)
aryPgs(lngCust - 1) = x - y
End If
rngInfo.Collapse wdCollapseEnd
' Reset rngDoc
rngDoc.SetRange _
Start:=rngInfo.Start, _
End:=rngDoc.End

End If
End With
Loop While bolEndOfDoc = False

' write last page quantity to array
ReDim Preserve aryPgs(lngCust)
aryPgs(lngCust) = a - x

' Show values
For b = 1 To lngCust
MsgBox "Customer No. " & b & _
", " & aryCust(b) & _
", had " & aryPgs(b) & _
" pages of information."
Next b

Set objDoc = Nothing

EndMe:
End Sub
 
Q

QK

QK,

Ed, the legend.
I haven't tried your code yet but I will tomorrow.
Your assumptions (1) and (2) below are CORRECT.
Another weird thing on Word is that in VBA I tried to set the
top and left margins document-wide (i.e. apply to whole document).
I've got one doc comes back with run time error: value out of range.
It appears that there is a built-in large value (9999999) "inherit" to the
doc and cannot take my assignment!
But all other docs are OK. One of the Qord MVP sais this is the Word doc
issue. I didn't find any UNUSUAL for that particular doc with others.
Any idea?
Thanks from the southern hemi-sphere.
QK
 
Q

QK

Ed my mentor,

I did tr your Sub XX_Test_FindAndPages(2).
This doesn't work, complaining "argument is NOT optional" at compile time!
rngInfo.SetRange _
Start:=rngDoc.Start, _
End:=rngDoc.End

Here is how my word doc is created/opened in the VBA code:

Dim Oword As Word.Application
Dim ODoc As Word.Document
Dim ORng As Word.Range

Set Oword = CreateObject("Word.Application")
Set ODoc = Oword.Documents.Open("C:\TEST.doc")
Oword.Visible = True

QK
 
E

Ed

Do you really have it titled:
"Sub XX_Test_FindAndPages(2)"?
If so, change it to:
"Sub XX_Test_FindAndPages2()"
Anything in the parenthesis is an expected argument.

Also, are you calling my code as a separate macro from within your code? Or
did you integrate your code and mine? One issue that usually gets me is
when I mix two macros and forget to make sure all my variable names match.
If you put
Set Oword = CreateObject("Word.Application")
Set ODoc = Oword.Documents.Open("C:\TEST.doc")
Oword.Visible = True and then try to
you will get an error, because you have not set objDoc.

One thing to try when stepping through a code is to look at the Local
Variables window (View >> Locals Window). It will show you when a variable
has been set and what it's value or "attachment" is.

Ed
 
Q

QK

Ed,

Sorry about the mislead here:
What VBA complains at compile time is this statement:
rngInfo.SetRange _
Start:=rngDoc.Start, _
End:=rngDoc.End
Complaining "argument is NOT optional" at compile time!
You may want to try your code and see how it goes?
Cheers
QK
 
E

Ed

It runs just fine on my Word XP. Maybe you have a different version that is
giving problems.

A couple of thoughts:
(1) The SetRange method *RE*defines a range. It will not define it for the
first time. Step through watching the Locals window and make sure rngInfo
gets properly set before it hits this line.
(2) rngDoc must also be set when the macro reaches this statement.
Otherwise, there is no Start or End of the rngDoc range. Again, watch the
Locals as you step through to see if this range is being set.

Why don't you post back your completed code, or at least the front end to
this point? Also post the results of the Locals - are all the ranges and
objects being set? If not, who's missing in action?

Ed
 

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