none
zugriff auf geöffnete word-dokumente RRS feed

  • Frage

  • hallo visual-basic-gemeinde,

    mit den beiden deklarationen

    Dim meinWord As Word.Application = GetObject(, "Word.Application")

    Dim meinDokument As Word.Document = meinWord.ActiveDocument

    kann ich bequem auf bereits geöffnete word-dokumente zugreifen.

    sind jedoch mehrere word-instanzen eingesetzt, so greift der aufruf von GetObject leider immer nur bei der zuerst eingesetzten instanz.

    gibt es nun ein verfahren, um alle word-instanzen zu erreichen?

    grüsse von peter


    • Bearbeitet SePe Samstag, 12. Mai 2012 09:02
    Samstag, 12. Mai 2012 08:58

Antworten

  • Hallo Peter,

    Du musst den Klassennamen weglassen, wenn Du auf die Art auf die Objekte zugreifen möchtest. Zudem bekommst Du eine Referenz auf das Dokument, nicht Word.Application:

    Dim doc As Word.Document = DirectCast(GetObject("D:\beispielDok.docx"), Word.Document)
    dim app As Word.Application = doc.Application

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de

    • Als Antwort markiert SePe Montag, 14. Mai 2012 07:12
    Samstag, 12. Mai 2012 17:08

Alle Antworten

  • Hallo Peter,

    wenn Du den Dateinamen des geöffneten Dokuments kennst, kannst Du bei GetObject auch diesen Dokumentnamen angeben und Dir dessen Instanz zurückgeben lassen. Ist der Name nicht bekannt, musst Du Dich selber durch die Running Object Table (ROT) arbeiten und die passende Instanz heraussuchen. Ein Codesnippet zum Durchlaufen der ROT findest Du u.a. hier:

    Laufende COM-Objekte abfragen
    http://dotnet-snippets.de/dns/laufende-com-objekte-abfragen-SID526.aspx


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de

    Samstag, 12. Mai 2012 12:32
  • hallo thorsten;

    mit der angabe des dateinamens habe ich mich eben auch schon versucht, aber da verstehe ich offenbar etwas falsch,

    denn sowohl bei

    meinWord =

    CType(GetObject("Dokument1", "Word.Application"), Word.Application)

    als auch beispielsweise bei

    meinWord =

    CType(GetObject("D:\beispielDok.docx", "Word.Application"), Word.Application)

    erhalte ich die ex.message:

    "der Datei- oder Klassenname wurde während des Automatisierungsvorgangs nicht gefunden"

    grüsse, peter

    Samstag, 12. Mai 2012 16:45
  • Hallo Peter,

    Du musst den Klassennamen weglassen, wenn Du auf die Art auf die Objekte zugreifen möchtest. Zudem bekommst Du eine Referenz auf das Dokument, nicht Word.Application:

    Dim doc As Word.Document = DirectCast(GetObject("D:\beispielDok.docx"), Word.Document)
    dim app As Word.Application = doc.Application

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de

    • Als Antwort markiert SePe Montag, 14. Mai 2012 07:12
    Samstag, 12. Mai 2012 17:08
  • hallo thorsten,

    ja, so funktioniert's!

    ich habe da beim pröbeln ziemlich falsch herumprogrammiert!

    vielen dank und gruss, peter

    Samstag, 12. Mai 2012 18:56
  • hallo thorsten,

    dein link zu Laufende COM-Objekte abfragen macht mir noch bauchschmerzen, weil ich einerseits mit der funktion GetRunningCOMObjectNames() alle namen der COMobjekte erhalte, mir aber dabei kein filter zur verfügung steht, um die wordObjekte herauszufiltern, und anderseits mit der funktion GetRunningCOMObjectByName(objectDisplayName As String) unter objectDisplayName der dokumentpfad bekannt sein müsste.

    jedenfalls mit meinem beschränkten wissen stosse ich da an meine grenzen.

    inzwischen habe ich folgenden code zusammengebaut, doch mit eher ungutem gefühl, weil ich da um sieben ecken herumprogrammiere:

    Option Explicit On
    Option Strict On
    
    Imports System.Runtime.InteropServices
    Imports System.Runtime.InteropServices.ComTypes
    '
    Imports Microsoft.Office.Interop
    
    Module alleWordFenster
    
        <DllImport("ole32.dll")> _
        Private Function GetRunningObjectTable(reserved As UInteger, ByRef pprot As IRunningObjectTable) As Integer
        End Function
        <DllImport("ole32.dll")> _
        Private Function CreateBindCtx(reserved As UInteger, ByRef pctx As IBindCtx) As Integer
        End Function
    
        Public Sub wordFensterListe()
            Dim msgText As String = ""
            Dim fenstertitelListe As List(Of String) = listeAllerFenstertitel()
            Dim hptPfadListe As List(Of String) = New List(Of String)
            '
            For Each objektName As String In holeNamenAllerLaufendenCOMobjekte()
                For Each fenstertitel As String In fenstertitelListe
                    If objektName.EndsWith(fenstertitel) Then
                        If Not hptPfadListe.Contains(objektName) Then
                            hptPfadListe.Add(objektName)
                        End If
                    End If
                Next fenstertitel
            Next
            fenstertitelListe.Clear()
            '
            Dim meinDokument As New Word.Document
            Dim listeAllerWordInstanzen As List(Of Word.Application) = New List(Of Word.Application)
            '
            For Each pfad As String In hptPfadListe
                meinDokument = DirectCast(GetObject(pfad), Word.Document)
                listeAllerWordInstanzen.Add(meinDokument.Application)
            Next pfad
            hptPfadListe.Clear()
            '
            Dim z As Integer = 0
            For Each instanz As Word.Application In listeAllerWordInstanzen
                For Each dok As Word.Document In instanz.Documents
                    msgText &= dok.FullName & vbCr
                    z += 1
                Next dok
            Next instanz
            '
            MsgBox(msgText, _
                   CType(MsgBoxStyle.Information + MsgBoxStyle.OkOnly, MsgBoxStyle), _
                   z.ToString & " wordDokumente")
        End Sub
    
        Private Function listeAllerFenstertitel() As List(Of String)
            Dim liste As List(Of String) = New List(Of String)()
            Dim prozessListe As Process() = Process.GetProcesses
            '
            For Each prozess As Process In prozessListe
                If LCase(prozess.ProcessName) = "winword" Then
                    If (prozess.MainWindowTitle IsNot Nothing) AndAlso (Not prozess.MainWindowTitle = "") Then
                        liste.Add(Replace(prozess.MainWindowTitle, " - Microsoft Word", ""))
                    End If
                End If
            Next
            '
            Return liste
        End Function
    
        Private Function holeNamenAllerLaufendenCOMobjekte() As List(Of String)
            Dim liste As List(Of String) = New List(Of String)()
            '
            Dim laufendeObjekteTafel As IRunningObjectTable = Nothing
            If (Not GetRunningObjectTable(0, laufendeObjekteTafel) = 0) OrElse (laufendeObjekteTafel Is Nothing) Then
                MsgBox("kein zugriff auf die tafel der laufenden COMobjekte", _
                       CType(MsgBoxStyle.Information + MsgBoxStyle.OkOnly, MsgBoxStyle), _
                       "fehlermeldung")
                Return liste
            End If
            '
            Dim monikerListe As IEnumMoniker = Nothing
            laufendeObjekteTafel.EnumRunning(monikerListe)
            monikerListe.Reset()
            '
            Dim monikerArray As IMoniker() = New IMoniker(0) {}
            '
            While monikerListe.[Next](1, monikerArray, IntPtr.Zero) = 0
                Dim bindInfo As IBindCtx = Nothing
                Dim anzeigenamen As String = ""
                '
                CreateBindCtx(0, bindInfo)
                monikerArray(0).GetDisplayName(bindInfo, Nothing, anzeigenamen)
                Marshal.ReleaseComObject(bindInfo)
                '
                liste.Add(anzeigenamen)
            End While
            '
            If laufendeObjekteTafel IsNot Nothing Then
                Marshal.ReleaseComObject(laufendeObjekteTafel)
            End If
            If monikerListe IsNot Nothing Then
                Marshal.ReleaseComObject(monikerListe)
            End If
            '
            Return liste
        End Function
    
    End Module
    
    

    in Function listeAllerFenstertitel() erhalte ich mithilfe Process.GetProcesses die MainWindowTitle aller wordinstanzen und in Function holeNamenAllerLaufendenCOMobjekte() hole ich die namen aller COMobjekte ab. darunter sind die pfade der geöffneten word-dokumente aufgeführt. in Sub wordFensterListe vergleiche ich beide listen und übernehme nur die entsprechenden pfade der MainWindowTitle. durch diese bekomme ich zugang zu allen word-instanzen, über die ich dann genauso wie auf die documents-auflistung zugreifen könnte.

    das alles wird dir bestimmt sehr unprofessionell vorkommen und ist es ja auch, aber mir kommt die programmierei bei der verwaltung meiner schreibarbeiten doch sehr entgegen.

    gruss, peter

    Sonntag, 13. Mai 2012 14:36