Warten bis Word fertig ist (A2002)

Hallo Forum,

Zu diesem Thema gibt es genügend Beiträge im WWW, nur solange es
einen Shell-Aufruf betrifft, nicht wenn aus Access ein Word-Objekt
zur Bearbeitung eines Dokumentes geöffnet wird.
Wie kann ich Access warten lassen bis ich Word schließe.

Ich vermute dass er dieses jetzt nicht immer macht, weil manchmal das
Word-Dokument nicht angezeigt wird. Mein Adressformular wird aber
geupdated, d.h. der Brief wird registriert und die Adresse
zugeordnet. Das sind Tätigkeiten die NACH dem ‚Wordaufruf‘ geschehen.

Dazu die wichtigsten Zeilen zum Aufruf:

Private Sub funktionskombiliste\_AfterUpdate()
Dim filename As String
Dim betreff As String


Select Case Me.funktionskombiliste.Column(0)

 
 Case 1: betreff = InputBox("Betreff eingeben", "Betreff")
 filename = newFilenameGen("Brief", betreff)
 Call einzelbrief\_tmpl("brief2.dot", Me.idx , betreff, filename, 1)

 ' Diese Funktion frischt mein Adressformular auf
 formrequery Me.Form, Me.idx 
.
.
.

Damit ihr mal prüfen könnt ob es an der Funktion liegt die das
Worddokument generiert hier noch das Wichtigste aus dieser:

Sub einzelbrief\_tmpl(tmpl, id, betreff, filename, case\_id As Integer)
Dim appWd As Word.Application
Dim WordDoc As Word.Document
Dim Nix

On Error Resume Next 'See if Word is running
'Set appWd = GetObject(, "Word.Application.9")
Set appWd = GetObject(, "Word.Application")

If Err.Number 0 Then 'Word Not running
 Err.Clear ' Clear Err object in case error occurred.
 'Create a new instance of Word

 'Set appWd = CreateObject("Word.Application.9")
 Set appWd = CreateObject("Word.Application")
 'Create an instance of Word
Else
 appWd.Activate
End If


On Error GoTo einzelbrief\_tmpl\_Error

 With appWd
 ' Vorlage als Dokument öffnen
 .Documents.Add Template:=CurrentProject.path & "\" & tmpl

 .ActiveDocument.Bookmarks("firma").Select
 .Selection.InsertAfter Nz(Forms("Adressen")![Firma])

 ...etc.

 ' Dokument sichern
 .ActiveDocument.SaveAs filename
 .ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument

 ' Sichtbar setzen
 .Visible = True

 'Maximieren
 .WindowState = wdWindowStateMaximize

 'zum txtanfang springen wenn vorhanden
 If .ActiveDocument.Bookmarks.Exists("txtanfang") Then
 .ActiveDocument.Bookmarks("txtanfang").Select
 End If
' .Quit
 End With

einzelbrief\_tmpl\_Exit:
 Exit Sub

einzelbrief\_tmpl\_Error:
 If Err.Number = 5941 Then
 Nix = MsgBox("Falsche WinWordVorlage (Textmarke fehlt)" & \_
 vbCrLf & "Vorlage war : " & tmpl, \_
 vbCritical, "WinWord Abbruch")
 appWd.Quit
 GoTo einzelbrief\_tmpl\_Exit
 End If
End Sub

Hab ich dort einen Fehler drin, oder kann ich Access warten lassen
bis ich mit dem WDoc fertig bin?

MfG
Marc

Vergessen: OS WinXP

Hallo, Marc!

Wie kann ich Access warten lassen bis ich Word schließe.

Ich verstehe ehrlich gesagt die Frage nicht. Du hast ja ein Word-Objekt. Mit dem machst Du einiges. Die gesamte Programmsteuerung liegt dabei eigentlich beim Access. Wenn Du von Access aus umfangreiche Sachen in Word machst, wird die nächste Programmzeile erst aufgerufen, wenn Word mit der vorangegangenen fertig ist.

Ich vermute dass er dieses jetzt nicht immer macht, weil
manchmal das
Word-Dokument nicht angezeigt wird. Mein Adressformular wird
aber
geupdated, d.h. der Brief wird registriert und die Adresse
zugeordnet. Das sind Tätigkeiten die NACH dem ‚Wordaufruf‘
geschehen.

Ggf. solltest Du nach dem „Sichtbarmachen“ von Word suchen. Vielleicht auch mal einfach den Programmablauf unterbrechen und manuell die Wordapplikation sichtbar machen und in den Vordergrund bringen, um zu sehen, ob alles einwandfrei läuft.

Case 1: betreff = InputBox(„Betreff eingeben“, „Betreff“)
filename = newFilenameGen(„Brief“, betreff)
Call einzelbrief_tmpl(„brief2.dot“, Me.idx ,
betreff, filename, 1)

Hier geht’s erst weiter, wenn der Einzelbrief erstellt wurde:

’ Diese Funktion frischt mein Adressformular auf
formrequery Me.Form, Me.idx

Und das läuft ja auch korrekt, oder?

Sub einzelbrief_tmpl(tmpl, id, betreff, filename, case_id As
Integer)
Dim appWd As Word.Application
Dim WordDoc As Word.Document

Ähem: Hier würde ich u. U. aufpassen: Ich würde mit einem globalen Word-Objekt arbeiten. Theoretisch ist es nämlich nur in dieser Funktion gültig. Dann sollte es nach Verlassen der Funktion auch wieder entfernt werden. Doch ganz ehrlich gesagt traue ich der GarbageCollection in Access überhaupt nicht. (Und den anderen vom MS verbrochenen übrigens auch nicht.) Und insofern weiß ich nicht, was passiert, wenn die Funktion verlassen wird: Läuft Word noch oder nicht?

appWd.Activate

und

’ Sichtbar setzen
.Visible = True

ist eigentlich nur während Entwicklung zu Debug-Zwecken sinnvoll; danach kannst Du es zugunsten von Performancegewinnen unsichtbar laufen lassen.

’ .Quit

Und mit diesem Quit sollte eigentlich Word wieder korrekt geschlossen werden. Ggf. noch mit Set appWd = Nothing den Verweis entfernen. Erst, wenn Word zu ist, geht’s mit der nächsten Zeile weiter.

Hab ich dort einen Fehler drin, oder kann ich Access warten
lassen bis ich mit dem WDoc fertig bin?

Wie gesagt: Eigentlich tut Access das. Was genau meinst Du? Wenn Du Word beenden willst, beendet es mit appWd.Quit und Set appWd = Nothing. Ich vermute, wg. der auskommentierten .Quit läuft es weiter…

Ahhh, Moment: Ich glaube, ich weiß langsam, was Du willst: Willst Du manuell im Word-Dokument was ändern und im Access auf die „Beendigung“ warten? Das wird lustiger, ist aber machbar. Meld’ Dich nochmal, wenn’s das ist…

Gruß, Manfred

Hallo Manfred,

vielen Dank für die prompte Antwort.

Ahhh, Moment: Ich glaube, ich weiß langsam, was Du willst:
Willst Du manuell im Word-Dokument was ändern und im Access
auf die „Beendigung“ warten? Das wird lustiger, ist aber
machbar. Meld’ Dich nochmal, wenn’s das ist…

Der Kandidat hat 100 Punkte !! :wink:

Ja genau, ich bin im Adressenformular in Access. An diese ‚Adresse‘
kann ich Briefe und Faxe senden. Suche mir aus was, gebe den Betreff
in ein Dialog ein und öffne dann Word welches ein .dot als Dokument
bekommt. Jetzt fangen die Probleme schon an: Nicht immer wird das
WordDoc gezeigt! Mal klappt es, mal nicht…
Wenn es denn mal klappt, sind die Adressdaten alle im WordDoc.
Wie du im Quelcode sehen kannst, wird das Doc unter einen Namen (filename) gespeichert. Dann angezeigt damit der Text eingegeben werden kann. Beim manuellem Schließen und speichern ist diese Aktion beendet. Dann erst sollte das Formular aufgefrischt werden und entsprechend den neuen Brieflink anzeigen. Klappte am Morgen noch ganz gut, jetzt immer weniger, obwohle ich kaum was geändert habe.

Wenn’s nicht klappt, öffnet sich das Doc nicht, das Access-Formular wird aufgefrischt und das Doc ‚hängt‘ irgendwo unsichtbar rum(?)
Wenn ich ein anderen Brief öffne, oder manchmal klappt es auch wenn ich ein anderen neuen Brief anlege, DANN kommt das alte UND das neue Doc zuvorschein! (Alle Daten sind auch drinne)

Ich habe die Probleme sowohl in XP alsauch in W2K, beide mit A2002 und W2002.

Beim suchen bin ich auf ein Programm gestoßen welche genau diese vorgehensweise anbietet. Das Programm läuft einwandfrei. Der Quellcode in meinem Programm kopiert, und bei mir läuft’s jetzt nur ab und an.

Es ist sicherlich ein PIBKAC-Problem!
(problem identified between keybord and chair)

Falls dir was dazu einfällt… ich würde mich echt freuen!

Gruß
Marc

Hallo, Marc!

Ahhh, Moment: Ich glaube, ich weiß langsam, was Du willst:
Willst Du manuell im Word-Dokument was ändern und im Access
auf die „Beendigung“ warten? Das wird lustiger, ist aber
machbar. Meld’ Dich nochmal, wenn’s das ist…

Ja genau, ich bin im Adressenformular in Access. An diese
‚Adresse‘
kann ich Briefe und Faxe senden. Suche mir aus was, gebe den
Betreff
in ein Dialog ein und öffne dann Word welches ein .dot als
Dokument
bekommt. Jetzt fangen die Probleme schon an: Nicht immer wird
das
WordDoc gezeigt! Mal klappt es, mal nicht…

Könnte mit besagtem Problem zusammenhängen, dass nach Beendigung besagter Funktion das Wordobjekt gelöscht wird und eben mal mehr, mal weniger zuverlässig aus dem Speicher entfernt wird. Daher: Globals Word-Objekt.

Wenn es denn mal klappt, sind die Adressdaten alle im WordDoc.
Wie du im Quelcode sehen kannst, wird das Doc unter einen
Namen (filename) gespeichert. Dann angezeigt damit der Text
eingegeben werden kann. Beim manuellem Schließen und speichern
ist diese Aktion beendet.

Wie definierst Du diess Ende genau? Muss der Anwender (und tut er das auch) Word beenden? Oder muss die Datei geschlossen werden? Oder reicht es auch, wenn er Access wieder aktiviert? Dies sind alles gewisse Probleme, mit denen Du Dich wirst rumschlagen müssen. Oder Du musst eben die Anwender ziemlich genau darauf trimmen, was Du programmtechnisch haben willst.

Dann erst sollte das Formular
aufgefrischt werden und entsprechend den neuen Brieflink
anzeigen. Klappte am Morgen noch ganz gut, jetzt immer
weniger, obwohle ich kaum was geändert habe.

Das veränderliche Verhalten mag komisch sein. Zur Lösung: Um das Warten auf das Ende nachzubilden, würde ich ein kleines Formular anzeigen mit einer Abbrechen-Schaltfläche, damit sich im Access auch noch weitermachen lässt, obwohl der Anwender irgendwas komisches macht. Mit dieser Abbrechen-Schaltfläche wird eine globale Abbruch-Variable gesetzt.

Diese überprüfst Du in einer Schleife (das „warten“), außerdem versuchst Du in der Schleife, irgendwas banales von der Word-Applikation (z. B. Caption) auszulesen. Das gibt einen Fehler, sobald Word nicht mehr läuft. Diesen fängst Du ab, beendest die Schleife und machst weiter wie gewünscht.

Also als Beispiel: Du definierst eine globale Variable

gbAbbruch as boolean

In Deinem „Abbruch“-Formular gibt’s die Schaltfläche „Abbrechen“, bei deren Klick Du nichts anderes machst als

gbAbbruch = True

.

Dann baust Du folgendes in die Word-Steuerung ein:

 gbAbbruch = False ' erst mal rücksetzen
 '... diverse Sachen in Word vorbelegen
 'jetzt warten:
 do while not gbAbbruch
 strTest = appWd.Caption
 DoEvents ' damit ggf. auf den Klick auf das Abbrechen reagiert wird!
 loop
 ...
Fehlerabfangroutine:
 select case err
 case 0
 case 

Die Variable gbAbbruch kann also durch zwei Aktionen gesetzt werden: Entweder Klick auf die Schaltfläche oder aber das Schließen von Word (und damit der Versuch, ein nicht mehr gültiges/existierendes Objekt auszulesen) über die Fehlerabfangroutine.

Und erst jetzt weiter machen mit Formular refreshen usw. 

Code ist nicht getestet (weiß auch nicht, ob das Word-Objekt überhaupt eine Eigenschaft Caption hat), aber zumindest mal als Abriss, wie es funktionieren könnte.



> Wenn's nicht klappt, öffnet sich das Doc nicht, das  
> Access-Formular wird aufgefrischt und das Doc 'hängt' irgendwo  
> unsichtbar rum(?)  
> Wenn ich ein anderen Brief öffne, oder manchmal klappt es auch  
> wenn ich ein anderen neuen Brief anlege, DANN kommt das alte  
> UND das neue Doc zuvorschein! (Alle Daten sind auch drinne)


Schau mal rein, ob Du die Applikation oder den Prozess noch irgendwo am rennen hast. Dies deutet auf die unsaubere GarbageCollection hin, von der ich sprach, wenn Du das Word-Objekt nur in Deiner Funktion definiert hast, die aber ggf. verlässt. Ich vermute, das nicht reproduzierbare Verhalten hinsichtlich Sichtbarkeit oder nicht hängt damit und unterschiedlichen Laufzeiten zusammen. Mal bist Du aus der Routine raus, bevor das Dokument angezeigt wird; dann wird Word vielleicht nicht beendet, ist aber unsichtbar im Hintergrund (und nur über die Prozesse beim Taskmanager sichtbar), mal wird das Dokument noch rechtzeitig angezeigt, bevor Du die Routine verlässt.

Hoffe, Du kommst halbwegs klar...

Gruß, Manfred

ERLEDIGT ! Es war ein PIBKAC
Das kommt davon wenn man(n) Code von Anderen kopiert.
Als ich endlich mal darauf kam, die Fehlerroutine nicht nur für 1 Problem sich zu melden, sondern für alle…
Tja…

Vielen Dank

Marc