November 25, 2020, 06:49:13

Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!


Word Automation: Daten von Access nach Word übertragen

Begonnen von herb54, November 09, 2020, 18:27:21

⏪ vorheriges - nächstes ⏩

herb54

Hallo,
in einem vorhergehenden Post hatte ich das Thema schon einmal angesprochen:
Ich möchte über eine Wordautomation die Inhalte von Textfeldern in eine Wordvorlage übertragen. Die Wordvorlage enthält Textmarken in die die Daten der Textfelder aus Access übertragen werden. Soweit klappt dies bis jetzt einwandfrei auf meinem eigenen PC. Ich habe das Programm nun auf einen Server gelegt und dort gestartet. Nachdem es nun eine gewisse Zeit fehlerfrei gelaufen ist, taucht nun ab und zu eine Fehlermeldung auf:
"Automatisierungsfehler Ein Aufruf im Messagefilter ist unzulässig."

Hier mal kurz der Programmcode (Vorgänge die ablaufen sind auskommentiert):

Private Sub A3D3_Click()
On Error GoTo Err_A3D3_Click
 Const Pfad As String = "C:\Eigene Dateien\"
' Pfadbeginn wo die neu erstellte Word Datei gespeichert wird
' ***********************************************************
Const wdDialogFileSaveAs = 84
' = Dialogfenster "Speichern" in Word
' ************************************

Dim appWord As Object, docWord As Object
' =  docWord = Wordvorlage,  appWord = neu erstellte Worddatei
' ******************************************************

Set appWord = CreateObject("word.application")
appWord.Visible = True
' =  Erstellen von appWord als Word-Dokument
' =  soll anschließend sichtbar sein
' ******************************************

Set docWord = appWord.Documents.Add("C:\Users\user\Documents\Formulare\Doc\A3D3.doc")
' = docWord = appWord = haben die gleichen Daten (und Pfadangabe zum Wordvorlagedokument)
'   damit die Originalvorlage docWord unverändert bleibt
'**********************************************************************************
'Falls der Datensatz noch nicht gespeichert wurde= Eigenschaft Me.Dirty = True
'Durch Me.Dirty = False wird der Datensatz quasi gespeichert
If Me.Dirty Then
MsgBox "Sie müssen den Datensatz erst speichern", vbInformation
Me.Dirty = False
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

'Eingaben erlauben
'******************************************
Me.AllowEdits = True
Me.AllowAdditions = True
Me.AllowDeletions = True

'Abfrage ob Eingaben vergessen wurden
' ******************************************
If Len(Trim(Me!Anrede & vbNullString)) = 0 Then
MsgBox ("Fehler: Anrede vergessen!!!")
Me!Anrede.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

If Len(Trim(Me!Vorname & vbNullString)) = 0 Then
MsgBox ("Fehler: Vorname vergessen!!!")
Me!Vorname.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

If Len(Trim(Me!Nachname & vbNullString)) = 0 Then
MsgBox ("Fehler: Vorname vergessen!!!")
Me!Nachname.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

If Len(Trim(Me!Strasse & vbNullString)) = 0 Then
MsgBox ("Fehler: Strasse vergessen!!!")
Me!Nachname.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

If Len(Trim(Me!PLZ & vbNullString)) = 0 Then
MsgBox ("Fehler: PLZ vergessen!!!")
Me!PLZ.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

If Len(Trim(Me!Ort & vbNullString)) = 0 Then
MsgBox ("Fehler: Ort vergessen!!!")
Me!Ort.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

If Len(Trim(Me!EinzelgesprächeA & vbNullString)) = 0 Then
MsgBox ("Fehler:" & vbCrLf & "Datum  Einzelgespräche Anfang vergessen!!!")
Me!EinzelgesprächeA.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

If Len(Trim(Me!EinzelgesprächeE & vbNullString)) = 0 Then
MsgBox ("Fehler:" & vbCrLf & "Datum  Einzelgespräche Ende vergessen!!!")
Me!EinzelgesprächeE.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

If Len(Trim(Me!AnzahlE & vbNullString)) = 0 Then
MsgBox ("Fehler:" & vbCrLf & "Anzahl Einzelgespräche  vergessen!!!")
Me!AnzahlE.SetFocus
appWord.Visible = False 'Worddokument schließen
Exit Sub
End If

'********************************************************************************
' Herr Frau = seines oder ihres
If Me!Anrede = "Herr" Then
Me!seines = "seines"
Else
Me!seines = "ihres"
End If

' ********************************************************************************
' = Routine zum Übertragen der Accesstextfelder in die Word Textmarken von docWord
' = in die Originalvorlage wird das Textfeld von Access geschrieben.
' = da ja docWord und appWord gleich sind wird auch in appWord dies geschrieben
With docWord
   .Bookmarks("Anrede").range = Me!Anrede
   .Bookmarks("Vorname").range = Me!Vorname
   .Bookmarks("Nachname").range = Me!Nachname
   .Bookmarks("Strasse").range = Me!Strasse
   .Bookmarks("PLZ").range = Me!PLZ
   .Bookmarks("Ort").range = Me!Ort
   .Bookmarks("seines").range = Me!seines
   .Bookmarks("EinzelgesprächeA").range = Me!EinzelgesprächeA
   .Bookmarks("EinzelgesprächeE").range = Me!EinzelgesprächeE
   .Bookmarks("AnzahlE").range = Me!AnzahlE
End With

' ********************************************************************************
' = Routine zum Abspeichern und öffnen des neuen Dokuments

appWord.ChangeFileOpenDirectory ("C:\Users\user\Documents\Formulare\Bescheinigungen")
With appWord.Dialogs(wdDialogFileSaveAs)
   .Name = Format(Date, "yyyy-mm-dd")
   .Show
   Set docWord = Nothing
   End With

' ********************************************************
   
  Application.Forms!frmDebitoren.Controls!Rechnung = False
     
Exit_A3D3_Click:
    Exit Sub

Err_A3D3_Click:
    MsgBox Err.Description
    Resume Exit_A3D3_Click
   
End Sub



Was ich nicht verstehe warum das Ganze fehlerfrei auf meinem PC läuft (Windows 10) und immer wieder mal eine Fehlermeldung verursacht wird auf dem Server (Windows 2012 R2)

Grüße
Herri

herb54

Hallo, was ich vergessen habe zu erwähnen: auf meinem PC ist Office 2013 (Access Version 15.0..) und auf dem Server Access 2003.
Gruß
Herri

DF6GL

Hallo,

auf den ersten Blick ist ersichtlich, dass die Word-Instanz nicht geschlossen wird und damit weiterhin existiert. Das führt zu mehreren Instanzen im Speicher, was die Fehlermeldung erklären könnte.

ZitatappWord.Visible = False 'Worddokument schließen

schließt nicht das Dokument, bzw. Word, es wird lediglich am Bildschirm unsichtbar...


Die ganzen IF-B(l)öcke sollten besser organisiert und auf "Exit Sub" verzichtet werden.  Ein(!) Ausgang aus der Sub sollte reichen, wobei dann an dieser Stelle "aufgeräumt" werden kann, soll heißen, das Dokument zu speichen/schliessen und die Word-Instanz schliessen (appWord.Quit). Weiterhin sollten die Objekt-Referenzen mit  Set docWord = Nothing und Set appWord = Nothing, zerstört werden.

herb54

Zitat von: DF6GL am November 10, 2020, 10:47:12Hallo,

auf den ersten Blick ist ersichtlich, dass die Word-Instanz nicht geschlossen wird und damit weiterhin existiert. Das führt zu mehreren Instanzen im Speicher, was die Fehlermeldung erklären könnte.

ZitatappWord.Visible = False 'Worddokument schließen

schließt nicht das Dokument, bzw. Word, es wird lediglich am Bildschirm unsichtbar...


Die ganzen IF-B(l)öcke sollten besser organisiert und auf "Exit Sub" verzichtet werden.  Ein(!) Ausgang aus der Sub sollte reichen, wobei dann an dieser Stelle "aufgeräumt" werden kann, soll heißen, das Dokument zu speichen/schliessen und die Word-Instanz schliessen (appWord.Quit). Weiterhin sollten die Objekt-Referenzen mit  Set docWord = Nothing und Set appWord = Nothing, zerstört werden.


Hallo Franz, vielen Dank! Werde ich machen. 
Grüße
Herri

herb54

So, ich habe jetzt mal eine Sprungmarke an das Ende (vor dem Fehlerhandler) gesetzt und diese Sprungmarke für die "Exit Sub" eingesetzt. Die Sprungmarke ist dann für das aufräumen zuständig:

If Len(Trim(Me!EinzelgesprächeA & vbNullString)) = 0 Then
MsgBox ("Fehler:" & vbCrLf & "Datum  Einzelgespräche Anfang vergessen!!!")
Me!EinzelgesprächeA.SetFocus
appWord.Visible = False 'Worddokument unsichtbar
GoTo Bereinigung
End If
.
.
.
.
With appWord.Dialogs(wdDialogFileSaveAs)
   .Name = Format(Date, "yyyy-mm-dd")
   .Show
   End With
' = Routine zum Abspeichern und öffnen des neuen Dokuments
' ********************************************************
  '**************Bereinigung******************************
Bereinigung:
Set docWord = Nothing
Set appWord = Nothing
Exit_A3D3_Click:
    Exit Sub

Err_A3D3_Click:
    MsgBox Err.Description
    Resume Exit_A3D3_Click
   
End Sub



Was mir noch nicht so richtig klar ist, was du mit "besser organisieren der If-Blöcke" meinst? Ich wüsste jetzt nicht wie man dies vereinfachen kann.
Noch eine Frage:

With appWord.Dialogs(wdDialogFileSaveAs)
   .Name = Format(Date, "yyyy-mm-dd")

hier wird ja mit dem aktuellen Datum abgespeichert. Ich könnte aber genauso gut z.B. mit dem Nachnamen abspeichern - also so:

With appWord.Dialogs(wdDialogFileSaveAs)
   .Name = Me!Nachname

Grüße
Herri

DF6GL

Hallo,

unabhängig davon, dass "GoTo Sprungmarke" recht verpönt ist, fehlt immer noch das Beenden der Word-Instanz(en)....

herb54

November 11, 2020, 17:17:08 #6 Letzte Bearbeitung: November 11, 2020, 17:27:50 von herb54
Hallo Franz,

mit appWord.Quit bekomme ich eine Fehlermeldung:

"Objekt unterstützt diese Eigenschaft der Methode nicht"

Ist es möglich, dass dies durch das Late Binding kommt?
Gruß
Herri

DF6GL

Hallo,

das hat mit Late Binding nichts zu tun..

Zeig mal den kompletten Code der Prozedur..

Vermutlich steht die Codezeile an einer falschen Stelle.

herb54

Hallo Franz,
hier der untere (letzte) Teil der Prozedur:
.
.
.
If Len(Trim(Me!AnzahlE & vbNullString)) = 0 Then
MsgBox ("Fehler:" & vbCrLf & "Anzahl Einzelgespräche  vergessen!!!")
Me!AnzahlE.SetFocus
appWord.Visible = False 'Worddokument unsichtbar
GoTo Bereinigung
End If
'********************************************************************************
' Herr Frau = seines oder ihres
If Me!Anrede = "Herr" Then
Me!seines = "seines"
Else
Me!seines = "ihres"
End If
' ********************************************************************************
' = Routine zum Übertragen der Accesstextfelder in die Word Textmarken von docWord
' = in die Originalvorlage wird das Textfeld von Access geschrieben.
' = da ja docWord und appWord gleich sind wird auch in appWord dies geschrieben
With docWord
   .Bookmarks("Anrede").range = Me!Anrede
   .Bookmarks("Vorname").range = Me!Vorname
   .Bookmarks("Nachname").range = Me!Nachname
   .Bookmarks("Strasse").range = Me!Strasse
   .Bookmarks("PLZ").range = Me!PLZ
   .Bookmarks("Ort").range = Me!Ort
   .Bookmarks("seines").range = Me!seines
   .Bookmarks("EinzelgesprächeA").range = Me!EinzelgesprächeA
   .Bookmarks("EinzelgesprächeE").range = Me!EinzelgesprächeE
   .Bookmarks("AnzahlE").range = Me!AnzahlE
End With
' ********************************************************************************
appWord.ChangeFileOpenDirectory ("C:\Users\user\Documents\Formulare\Bescheinigungen")
With appWord.Dialogs(wdDialogFileSaveAs)
.Name = Me!Nachname
   .Show
   End With
' = Routine zum Abspeichern und öffnen des neuen Dokuments
' ********************************************************
Bereinigung:
    appWord.Quit
    Set docWord = Nothing
    Set appWord = Nothing
     
Exit_A3D3_Click:
    Exit Sub

Err_A3D3_Click:
    MsgBox Err.Description
    Resume Exit_A3D3_Click
   
End Sub


Ich hatte auch schon gedacht, appWord.Quit an anderen Stellen zu platzieren hat aber nix gebracht.
Grüße
Herri

DF6GL

Hallo,

vermutlich fehlt das Schließen des Docs:

Bereinigung:
    docword.Close
    appWord.Quit

herb54

Hallo Franz, vielen Dank! Ich habe dies auch noch mit aufgenommen. Es funktioniert jetzt einwandfrei. Ich habe auch noch mal eine Reparatur von meinem Office vorgenommen. Das Einzige was jetzt noch unschön ist: Beim Abspeichern öffnet sich auf meinem eigenen PC Worddialog zum Abspeichern und legt sich vor das Accessprogramm. Auf dem Server bleibt das im Hintergrund. Hängt wahrscheinlich damit zusammen, dass es sich um ein älteres Office (2003) handelt. Gibt es da noch eine Möglichkeit, dass zu ändern dh. zu erzwingen, dass sich der Worddialog in den Vordergrund stellt?

Grüße
Herri

DF6GL

Hallo,


dann sag Word, dass es nicht speichern soll. Die Close-Methode hat einen "SaveChanges"-Parameter:

docword.Close False

herb54

Hallo Franz,
astrein - hat sofort geklappt! Vielen Dank für deine Hilfe!
Schon interessant: Du hattest mir vor Jahren im Spotlight-Forum schon viel geholfen
und jetzt auch hier.
Vielen lieben Dank auch an all die Anderen die hier immer wieder helfen wenn Not am Mann ist!

Grüße
Herri


DF6GL

Hi,

mhmm,ja, Spotlight.... Da schwelgt man ein bisschen in Nostalgie   :'(  ,

auch wenn ich mich jetzt nicht mehr so ganz genau (an Dich) erinnere...vielleicht hast Du jetzt aber auch einen anderen Nickname.