Wie löse ich das Problem mit Excel VBA?
Hi,
ich habe eigentlich einen Code der funktionieren sollte und möchte über eine Excel VBA Prozedur ein Word Dokument öffnen, welches dann über Excel zum Teil ausgefüllt wird.
Es kommt nun leider fast immer vor, dass sich das Word-Dokument 2x öffnet (1 Leerdokument. Muss dazu sagen, dass sich der Standard-Vorlagenordner auf einem Netzlaufwerk befindet.
Ich habe eine Pause von 1 Sekunde eingebaut, nachdem ich nach diesem Fehler im Netz gesucht habe, leider tritt das Problem weiterhin sehr häufig auf.
Vielleicht kann ja jemand helfen?
Danke im Voraus.
Sub create()
Dim WordApp As Object
Set WordApp = CreateObject("Word.Application")
Call Sleep(1000)
With WordApp
.Visible = True
.Documents.Open ("Q:\Dokument.docx")
End With
End Sub
2 Antworten
Wenn eine Word Datei (oder eine andere Office Datei) geöffnet wird legt das System eine versteckte Datei an die so ähnlich heißt.
Du kannst Prüfen, ob eine solche Datei vorhanden ist.
Es ist immer eine Tilde + $+ Underscore als Präfix vorm Dateinamen.
Öffne mal eine solche Datei mit dem TextEditor.
Du wirst sehen, dass dein User-Name auftaucht. Immer an der gleichen Stelle.
Ich habe in meinen Projekten auf Vorhandensein diese Datei geprüft, wenn ja, geöffnet und den UserNamen extrahiert und somit den aktuellen User warnen können,
damit es keine doppelten Zugriffe gibt.

Ggf ist während dem Testen eine Word Objekt vorhanden geblieben.
Ggf über den Task Manger (STRG+ALT+ENTF) dies prüfen und erst alle WORD Objekte beenden.
Auch dein Code muss am Ende das Objekt Set WordApp = nothing
vorhanden sein.
Also ich habe inzwischen festgestellt, dass es tatsächlich so war, dass noch ein Objekt offen war. Der Code funktioniert nun soweit. Ich hätte aber gerne eine Prüfung, ob die Vorlage bereits geöffnet ist und eine Msg-Box, die sich in diesem Fall öffnet, damit man diese erst schließt und ggf. speichert.
Dann soll die Msg-Box bestätigt werden und die Vorlage öffnet sich.
Ist so etwas möglich?
Dies ist auch möglich.
Hier musst du aber auf Windows zugreifen und durch eine Liste aller laufenden Prozesse iterieren um den richtigen zu beenden.
Beispiel Code gibt es im Web.
Recherchiere VBA Prozesse beenden. (ggf auch in englischer Sprache)
Wenn dies nicht zum Ziel führt kann ich auch meinen Code posten. (Den ich aber auch aus dem Web hatte)
Wenn ich das richtig verstehe, würde dann der Prozess Word beendet? Oder tatsächlich nur das entsprechende Dokument?
Im ersten Fall wäre das nicht zielführend, da ggf. andere Word-Dokumente geöffnet sein könnten, auf die sich der Code nicht bezieht.
Ich sehe schon, es wird wieder kompliziert. Wollte prüfen ob das Dokument bereits geöffnet ist und eine Msg Box ausgeben, dass das Dokument erst (ggf.) gespeichert und dann geschlossen werden muss. und wenn das Dokument beendet wurde, soll der Code weiterlaufen.
Ich habe nun einiges gesichtet aber nichts davon verstehe ich.
Ich dachte dann, ich mache einen Code wenn ein Fehler ist:
On Error GoTo errorhandler
errorhandler:
MsgBox "Dokument ist bereits geöffnet!" & Chr(10) & "Bitte Dokument ggf. speicherung und schließen." & Chr(10) & "Abschließend mit OK fortsetzen.", vbOKCancel, vbExclamation
If vbOK Then
Set doc = WordApp.Documents.Open("Q:\\Test.docx")
...weiteren Code ausführen
Else
Exit Sub
...
Aber er öffnet ja nun schon das Dokument und prüft nicht erst. Und auch so funktioniert der Code nicht.
Im ErrorHandler 'nur' auf den Fehler hinweisen und was der Nutzer nun zu tun hat.
NICHT im ErrorHandler dann gemäß User Reaktion weiteren Code ausführen.
Den User mit seinen Korrekturen die Dinge von vorne beginnen lassen.
Denn im weiteren Code könnten wieder Fehler auftreten. ErrorHandler Kaskaden unbedingt vermeiden.
Oh, danke für die Info. Ich hatte vorhin einen Code gefunden, der dem ersten Test nach vielversprechend aussah und mein Problem lösen konnte. Nur dummerweise habe ich nun das geänderte Dokument geschlossen und überschrieben und jetzt finde ich es wieder nicht. *nervt*
Nachtrag, ich habe den Code gefunden und angepasst, aber er funktioniert nicht:
Function IsFileOpen(filename As String)
Dim filenum As Integer, errnum As Integer
On Error Resume Next
filenum = FreeFile()
Open filename For Input Lock Read As #filenum
Close filenum
errnum = Err
On Error GoTo 0
Select Case errnum
Case 0
IsFileOpen = False
Case 70
IsFileOpen = True
Case Else
Error errnum
End Select
End Function
Public Function LastUser(strPath As String) As String
Dim strXl As String
Dim strFlag1 As String, strflag2 As String
Dim i As Integer, j As Integer
Dim hdlFile As Long
Dim lNameLen As Byte
strFlag1 = Chr(0) & Chr(0)
strflag2 = Chr(32) & Chr(32)
hdlFile = FreeFile
Open strPath For Binary As #hdlFile
strXl = Space(LOF(hdlFile))
Get 1, , strXl
Close #hdlFile
j = InStr(1, strXl, strflag2)
#If Not VBA6 Then
'// Xl97
For i = j - 1 To 1 Step -1
If Mid(strXl, i, 1) = Chr(0) Then Exit For
Next
i = i + 1
#Else
'// Xl2000+
i = InStrRev(strXl, strFlag1, j) + Len(strFlag1)
#End If
'// IFM
lNameLen = Asc(Mid(strXl, i - 3, 1))
LastUser = Mid(strXl, i, lNameLen)
End Function
Zwar erkennt er in meiner Prozedur, dass das Dokument geöffnet ist (in dem Fall von mir). Jedoch hängt er sich in der Function "LastUser" hier auf:
Open strPath For Binary As #hdlFile
Ich erhalte Laufzeitfehler 52. Über Google finde ich raus, dass es sich ggf. um einen falschen Eintrag in der system.cfg handet. Da gehe ich aber nicht ran.
Jetzt bin ich noch immer keinen Schritt weiter :-(.
Jetzt habe ich noch einen Code gefunden, der aber scheinbar nur prüft, ob Word geöffnet ist und nicht explizit das Dokument:
Sub test()
Dim wordApp As Word.Application
Dim doc As Word.Document
Dim FileName As String
Dim myObject As Object
FileName = "\\gsdg_*.docx"
On Error Resume Next
Set myObject = GetObject(, "Word.Application")
If Err.Number <> 0 Then
'If myObject Is Nothing Then
Set wordApp = CreateObject("Word.Application")
wordApp.Documents.Open FileName
wordApp.Visible = True
wordApp.Activate
wordApp.WindowState = 1
Else
For Each doc In wordApp
If StrComp(doc.FullName, FileName, vbTextCompare) = 0 Then
MsgBox "Dokument ist bereits geöffnet!"
End If
Next doc
End If
End Sub
Außerdem fehlt dann noch die Prüfung, welcher User das Dokument geöffnet hat (Rückmeldung über MsgBox). Also so einfach ist das Ganze (für mich) nicht...
Den User abfragen geht mit Application.GetUser (oder so ähnlich)
Also, es gibt die Liste der Offenen Applicationen.
Jede einzelne Applikation bietet dann ein Interface der zugehörigen offenen Dateien.
Hier ein Beispiel alle offenen Excel Datei zu checken. (Analog auch für Word, PowerPoint, etc)
Dim myWb as Workbook
For each myWB in Workbooks
next
Bei mir funktioniert der Code oben nicht, er erkennt nur, dass Word geöffnet ist, bezieht sich aber nicht auf das Dokument. Ich verstehe es einfach nicht.
Die Word Applikation ist ein "erstes" Objekt. Das geöffnete Document ist ein zweites Object.Du hast eine Mischung aus "Early-" und "Late Binding" programmiert.Nur eines von beidem machen.Im Zweifel zu Beginn nur heraus finden dass Word Offen ist und den Nutzer anweisen dies zu schliessen und ggf Änderungen zu speichern.Dann dein Makro erneut laufen lassen und Word als einziger in den Fingern zu haben.Offenbar willst du den "letzten" User der das Dokument verändert hat ermitteln ?VBA User ermitteln der das Dokument geöffnet hat (herber.de)Der letzte user der etwas modifizerit hat ist ein Attribut in Word. .BuiltInDocumentProperties("Author")
Achso ist das. Also ich möchte prüfen, dass mein Word-Dokument, also die Vorlage, bereits geöffnet ist. Wenn das der Fall ist, soll eine Meldung erscheinen, dass das Dokument bereits geöffnet ist und wer das geöffnet hat.
Dann kann der andere Benutzer informiert werden, das Dokument bitte zu schließen und ggf. zu speichern.
Ohne diese Abfrage öffnet VBA ja auch ein Debuggen-Fenster und das möchte ich nicht haben. Ich denke, dass ich mit dieser Mitteilung diesen Fehler ordentlich auffange und den Benutzer zum Handeln bewege.
Vielleicht kann ich das auch so regeln:
Dokument-Vorlage geöffnet? Ja, Info mit Username
Msg-Box Weiter -> neue Prüfung oder Abbrechen. Dann muss eben wieder mit dem CommandButton gestartet werden, sobald man Rückmeldung hat.
Wie ich das nun verstehe, muss ich eine Prüfung einbauen, die jedes geöffnete Word-Dokument auf den Namen hin überprüft. Wenn dieser nicht gefunden wird, wird die Vorlage geöffnet und die Einträge aus Excel werden in Word übernommen.
Sowas habe ich schon versucht, aber irgendwie nicht richtig hinbekommen.
Ich habe es nun mit der Funktion verstanden und hätte vorher mal drauf kommen sollen, den Code mal schrittweise auszuführen:
Dann im Code:
Die Userform anstatt einer Messagebox, da diese viel flexibler ist. Dort gibt es nun einen Button "Erneut versuchen" und Abbrechen. Erneut versuchen wiederholt die Sub, Abbrechen beendet.
Jetzt muss ich es nur noch schaffen, dass im Label der UserForm2 der Benutzer eingetragen wird, der das Dokument geöffnet hat.