MS Office Forum / Word / Programming / October 2006
Wait till intialization complete...
|
|
Thread rating:  |
Lüko Willms - 06 Oct 2006 21:30 GMT Is there a "wait" or "pause" function in VBA?
I have written a VBA-program for MS-Word which is started by the "New" event, i.e. when a new document is created based on a given template, in which my VBA program resides.
The new document is created by a database application (which is written in Delphi, by the way), which writes several hundred DocVariables into the Word document, which are then used in Fields, and in my VBA program.
The problem is now, that the "New" event is the moment when the document is created by that other application, and when my VBA program is triggered by that event, nearly all those DocVariables which my VBA program is to process are simply not yet in existence. They are still being Added. Takes its time.
How can I, resp. my VBA program, wait for the completion of this process? Is there a "wait" or "pause" function in VBA, by which my VBA program can be laid to rest for a specified span of time? Can I detect another application or task working on the "ActiveDocument" which my VBA program is associated with?
Any suggestion for me?
Yours, L.W. Germany
Helmut Weber - 07 Oct 2006 09:21 GMT Hi Lüko,
kind of a stab in the dark: Google here for gettickcount, sleep, ontime.
I'd check whether the number of docvariables is increasing between two points in time.
By the way, adding 300 docvariables to a doc, here and now, takes 10 Milliseconds:
Sub autonew() Dim lCnt As Long Dim lTm1 As Long lTm1 = GetTickCount For lCnt = 1 To 300 ActiveDocument.Variables.Add _ Name:=Format(lCnt, "000"), Value:=lCnt Next MsgBox GetTickCount - lTm1 ' 10 End Sub
 Signature Greetings from Bavaria, Germany
Helmut Weber, MVP WordVBA
Win XP, Office 2003 "red.sys" & Chr$(64) & "t-online.de"
Lüko Willms - 07 Oct 2006 13:54 GMT Am Sat, 7 Oct 2006 08:21:34 UTC, schrieb Helmut Weber <nbhymsjxdgcn@mailinator.com> auf microsoft.public.word.vba.general :
> I'd check whether the number of docvariables > is increasing between two points in time. I had that idea, too.
Currently, I think that the proper way would be to use the Task object, resp. the Tasks collection of the Application MS-Word. MAybe also the Parent property of the Document object. Don't know yet, but that is the direction which I am currently researching.
Maybe some real expert is able to help me...
Yours, L.W.
Tony Jollans - 08 Oct 2006 16:14 GMT Helmut was trying to help; the suggestion that he is no expert is (a) untrue and (b) rude.
Before you go down a blind alley can I ask a basic question?
You create a document You write some docvars to it. You then want to run a macro.
Why don't you simply do that, all under control from the same place (your delphi app)?
Trying to run one element of your process asynchronously when it is dependent on another element introduces an unnecessary complexity - especially, as you have found out, when there aren't any easy-to-use facilities to help you control the process.
-- Enjoy, Tony
> Am Sat, 7 Oct 2006 08:21:34 UTC, schrieb Helmut Weber > <nbhymsjxdgcn@mailinator.com> auf microsoft.public.word.vba.general : [quoted text clipped - 13 lines] > Yours, > L.W. Lüko Willms - 08 Oct 2006 16:50 GMT Am Sun, 8 Oct 2006 15:14:48 UTC, schrieb "Tony Jollans" <my forename at my surname dot com> auf microsoft.public.word.vba.general :
> You create a document > You write some docvars to it. No, that is a foreign application which does it.
> You then want to run a macro. Which is fired by the "Document New" event.
> Why don't you simply do that, all under control from the same place (your > delphi app)? I write the VBA program, but I have no control over the data base.
The database application exports data to a newly created MS-Word document in form of Document Variables, and then leaves it alone. Until now this information has been used only in Fields, but I now started to add some VBA programming.
My VBA program is fired by the Document_New event, but at that moment in time, the database is not yet done with its work on the document. My VBA program is to use information from these Document Variables, which are not yet present.
I am just looking for ways to wait without waisting processor time, i.e. yielding time to the OS instead of stealing CPU cycles from the database application, which makes the actual waiting time longer. But until now I can't find a way to do that with VBA (I am using Office 2000 for development here, and Office 2003 at the actual production site). I also do rather not want to bother the users with MsgBoxes which they might have to acknowledge repeatedly.
Yours, L.W.
Tony Jollans - 08 Oct 2006 19:26 GMT Well, first thing is that I don't think you can do it in Document_New at all. The document is not considered open, or available for the Delphi app to add variables to, until the event code has finished. This means you will have to start a separate macro using Application.OnTime. In that macro you will have to check whether the variables have been added or not and, not continue until they have, perhaps with a DoEvents loop ...
Document_New ...
' Do whatever you have to do Application.Ontime Now + TimeValue("00:00:01"), "NextMacro"
NextMacro ...
While <Document>.Variables.Count < 300 DoEvents Wend ' Now you can do your stuff
Instead of DoEvents you could use another OnTime and exit. You may need to experiment with the timings to get the best result.
Of course, if the delphi app is changed to add 400 variables you will start failing so it would be better having a more definite trigger.
-- Enjoy, Tony
> Am Sun, 8 Oct 2006 15:14:48 UTC, schrieb "Tony Jollans" <my forename > at my surname dot com> auf microsoft.public.word.vba.general : [quoted text clipped - 33 lines] > Yours, > L.W. Lüko Willms - 08 Oct 2006 21:42 GMT Am Sun, 8 Oct 2006 18:26:20 UTC, schrieb "Tony Jollans" <my forename at my surname dot com> auf microsoft.public.word.vba.general :
thanks for your thoughts
> Well, first thing is that I don't think you can do it in Document_New at > all. The document is not considered open, or available for the Delphi app to > add variables to, until the event code has finished. This means you will > have to start a separate macro using Application.OnTime. I had a look at this in the online help, but had and have my doubts, one reason being the time granularity which seemed to be somewhat to coarse, but I may have been in error on that matter.
If really the "document_new" event is not yet over in that moment, the document will not yet have the name which is being assigned to it by the database application, and do I not have to specify that name in the OnTime call? Will the target macro really catch the new document which had just been created, or some other? I am not sure.
Otherwise, your suggestion may hit the mark. Anyway, I will have to consult with the developers of the database application, what they have to say about my project.
> Of course, if the delphi app is changed to add 400 variables you will start > failing so it would be better having a more definite trigger. I had a look at various documents, and found that the number of DocVariables can easily reach 850 or more...
But the very first one is named "DATA_DONE", and it always had the value of "1". I guess that it has initially the value "0", and is changed to "1" when the data is actually done. I have a procedure which loops thru the document variable collection, checks for the existence of this variable and its value (when available -- I hope that the second condition after a AND operator is not checked by VBA...). But, as I said, I would like to simply yield the time to the OS and other applications by some kind of WAIT function.
Yours, L.W.
Tony Jollans - 08 Oct 2006 22:36 GMT > the document will not yet have the name which is being assigned to it > by the database application, and do I not have to specify that name in > the OnTime call? Your macro is not in the document - by definition; it is in the template on which the document is based. You shouldn't, however, need to explicitly name it in the OnTome anyway.
> But the very first one is named "DATA_DONE", and it always had the > value of "1". I guess that it has initially the value "0", and is [quoted text clipped - 3 lines] > that the second condition after a AND operator is not checked by > VBA...). The actual data are for you and the delphi app to agree; I can't help on that score, but you don't want to be checking up to 800 variables just to find the one you want. Address it by name and trap the error if it doesn't exist.
> But, as I said, I would like to simply yield the time to the > OS and other applications by some kind of WAIT function. That (yielding to the OS for all queued activity to run) is what DoEvents does. There is no VBA Wait - although it can be done with API calls or mimiced using OnTime.
-- Enjoy, Tony
Lüko Willms - 09 Oct 2006 07:35 GMT Am Sun, 8 Oct 2006 21:36:34 UTC, schrieb "Tony Jollans" <my forename at my surname dot com> auf microsoft.public.word.vba.general :
> but you don't want to be checking up to 800 variables just to > find the one you want. Address it by name and trap the error if it doesn't > exist. maybe. I have some reticence to use this Basic-ish "on error resume next" thing. And I'm not sure about the scope of that statement.
> > But, as I said, I would like to simply yield the time to the > > OS and other applications by some kind of WAIT function. > > That (yielding to the OS for all queued activity to run) is what DoEvents > does. There is no VBA Wait - although it can be done with API calls or > mimiced using OnTime. Thanks. I think I now understand better the "DoEvents". Better than a "wait" with a fixed time. I have put that in the loops and will test it out this afternoon (if not other, more urgent tasks keep me away).
I still wonder what I can do with the "tasks" collection, "ActiveDocument.Creator" and so on.
MfG, L.W.
Tony Jollans - 09 Oct 2006 08:35 GMT > I have some reticence to use this Basic-ish "on error resume > next" thing. And I'm not sure about the scope of that statement. I'm not wonderfully impressed with it myself but it's what we've got so we have to work with it. You control the scope yourself - but do read up on it to make sure it doesn't bite you. In this case a fairly basic ...
myvar = 0 On error resume next myvar = activedocument.variables("whatever") On error goto 0 If myvar = 1 then etc
... is probably along the lines of what you want
> I still wonder what I can do with the "tasks" collection, > "ActiveDocument.Creator" and so on. I wonder many things but sometimes I just have to get on with the job at hand :-)
-- Enjoy, Tony
Karl E. Peterson - 11 Oct 2006 18:52 GMT > But the very first one is named "DATA_DONE", and it always had the > value of "1". I guess that it has initially the value "0", and is [quoted text clipped - 4 lines] > VBA...). But, as I said, I would like to simply yield the time to the > OS and other applications by some kind of WAIT function. DoEvents does indeed yield to the system, but it can give the appearance of 100% cpu utilization as the system will continue to feed timeslices to the yielding app just as before. I have re-read this thread, and wonder whether you actually considered a timer-based polling for the other app's completion? That would seem to avoid the need for your user to tell you when it's finished. Checking every 100ms or so wouldn't put any strain on the cpu, but would appear "instantaneous" to the user.
 Signature Working without a .NET? http://classicvb.org/
Lüko Willms - 12 Oct 2006 08:03 GMT Am Wed, 11 Oct 2006 17:52:43 UTC, schrieb "Karl E. Peterson" <karl@mvps.org> auf microsoft.public.word.vba.general :
> I have re-read this thread, and wonder whether > you actually considered a timer-based polling for the other app's > completion? How would I find that out? The application will run all day, as the main database application for that site. I would have to find out when they have finished working on my document. What would I have to look at?
Yours, L.W.
Karl E. Peterson - 12 Oct 2006 19:59 GMT >> I have re-read this thread, and wonder whether >> you actually considered a timer-based polling for the other app's [quoted text clipped - 4 lines] > they have finished working on my document. What would I have to look > at? This is what I *specifically* replied to:
Karl E. Peterson wrote:
> Lüko Willms wrote: >> But the very first one is named "DATA_DONE", and it always had the [quoted text clipped - 5 lines] >> VBA...). But, as I said, I would like to simply yield the time to the >> OS and other applications by some kind of WAIT function. I chose that passage carefully, as it sounded as if this was the answer to the question you now ask. Did I misunderstand? I would test that "DATA_DONE" variable on each timer tick, until it's flagged.
Also, with regard to this:
>> I hope that the second condition after a AND operator is not checked by >> VBA... It is. VB(A) doesn't short-circuit logical expressions.
 Signature Working without a .NET? http://classicvb.org/
Lüko Willms - 13 Oct 2006 07:18 GMT Am Thu, 12 Oct 2006 18:59:27 UTC, schrieb "Karl E. Peterson" <karl@mvps.org> auf microsoft.public.word.vba.general :
> I would test that > "DATA_DONE" variable on each timer tick, until it's flagged. I tried; the problem is that the Delphi-Application and my "Document_New" event-procedure apparently block each other.
I'm currently changing it to a MACROBUTTON filed on the top of the letter which the user should click to do the initialization work from my VBA program. Unfortunately, it doesn't work yet...
I also have suggested to the developers of that Delphi application that they make an configurable option available to RUN a macro supplied in the document template.
Yours, L.W.
Lüko Willms - 11 Oct 2006 10:44 GMT Am Sun, 8 Oct 2006 15:14:48 UTC, schrieb "Tony Jollans" <my forename at my surname dot com> auf microsoft.public.word.vba.general :
> Before you go down a blind alley can I ask a basic question? > [quoted text clipped - 4 lines] > Why don't you simply do that, all under control from the same place (your > delphi app)? As I said in my previous anwer to this question, it is not my Delphi application.
But, having explored all the other possibilities, and now looked into how the developers of this application do it (Delphi 5 with OLE-Automation), I came to the conclusion, that the above would be the best way to go.
Because:
> Trying to run one element of your process asynchronously when it is > dependent on another element introduces an unnecessary complexity - > especially, as you have found out, when there aren't any easy-to-use > facilities to help you control the process. That is the bitter truth. I even looked into the Application events, like Application.WindowActivate, but that would, if successfully implemented (VBA unter Office 2000 rejected an unknown user object type), do that event for _any_ window activated in MS-Word, not only those based on my template - right?
So I will contact the developers of that Delphi5 application, and suggest to them to implement as a configuration option for the Word interface (one can configure which group of DocVariables is created) to run a user-written macro, which then should have a fixed name, e.g. "ThisDelphiApp_UserStartMacro" or something similar.
In the mean time I will rewrite my VBA program to be activated by some user input...
Yours,
|
|
|