Announcement

Collapse
No announcement yet.

workbook.container

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • workbook.container

    Ich habe ein in Word eingebettetes Excel-Objekt und möchte Word über Änderungen des Inhalts, wenn dieses zum Editieren geöffnet ist, informieren. Dafür benötige ich den Link auf das entsprechende Word-Container-Objekt.

    In Excel ist das Property "workbook.container" vorhanden. Beim geöffneten eingebetteten Objekt führt der Zugriff zu einem Fehler, ist so also nutzlos. Angeblich (nach längerer Netzsuche) funktioniert es, wenn der Aufruf aus dem IE erfolgt, was ich jedoch nicht getestet habe.

    Gibt es eine andere Möglichkeit der Beschaffung des OLE Container-Objekts, z.B. eine externe Funktion aus der OLE32.DLL, die dieses Container-Property kapseln sollte?

  • #2
    So, ein Stückchen weiter bin ich schon. Ob es funktioniert weiß ich nicht.

    Der offizielle Weg geht über: IOleClientSite::GetContainer

    Eine VB-Umsetzung ist hier. Wie ich es in VBA umgesetzt bekomme, ist mir aber noch nicht klar.

    Comment


    • #3
      Wie wurde Excel eingebettet - als Variant - Variable mit CreateObject() oder als New Excel.Application?

      Im zweiten Fall, ist unter Extras->Verweise auch die richtige Office XX Object Library eingebunden?

      Nach meiner Erfahung geht mit Variant=CreateObject("Excel.Application") auch extern alles, wass direkt in einem Excel - Makro funktioniert.

      Viel Erfolg
      Tino
      Ich habs gleich!
      ... sagte der Programmierer.

      Comment


      • #4
        Eingebettet wird das Objekt mit
        Code:
        with .InlineShapes.AddOLEObject _
        (FileName:="xxx.xlt", DisplayAsIcon:=True, IconLabel:="xxx")
        Beim Ende der Bearbeitung des geöffneten Excel-Objekts wird das Makro "Workbook_BeforeClose" direkt von und in Excel ausgeführt. Dieses informiert Word darüber, dass das Objekt geschlossen wird (und das eingebettete Objekt ggf. neue Daten enthält, die nun von Word abgeholt und angezeigt werden) .

        Für den Aufruf des Word-Makros benötige ich eben die Referenz auf das Word-Container-Dokument, um dort das Makro zu referenzieren.

        Die Verwendung von "ThisWorkbook.Container" führt aber eben zu einem "Anwendungs- oder objektdefinierter Fehler".

        Mein Workaround ist derzeit so:
        • Abfangen des Doppelklicks und den rechten Mausklick bei einer Selection auf dem eingebetteten Objekt in Word
        • "manuelles" öffnen des Excel-Workbook mit
          Code:
          Selection.InlineShapes(1).OLEFormat.DoVerb wdOLEVerbOpen
        • Starten eines Makros in Excel, dem ich "ThisDocument" als Parameter übergebe.
          Code:
          Set oExcel = Selection.InlineShapes(1).OLEFormat.Object
          oExcel.Application.Run "InitExcelFromWord", ThisDocument

        Nun hat Excel das Container-Dokument und kann hier mein Word-Makro starten, was auch perfekt funktioniert.

        Nachteil ist, dass ich vom Abfangen der Maus-Klicks abhänge. Das Popup-Menu beim rechten Mausklick geht mir verloren und den Aufruf des Objekts per MenuItem Bearbeiten --> Objekt bekomme ich auch nicht mit.

        Comment


        • #5
          Mein Workaround ist grundsätzlich so geblieben. Nur fange ich nicht mehr die Maus-Klicks ab, sondern übergeb den Container in einer Timer-Routine:
          Code:
          On Error Resume Next
          ...
          Set oExcel = InlineShapes(i).OLEFormat.Object
          If Not oExcel Is Nothing Then
              oExcel.Application.Run "SetContainer", ActiveDocument
              Set oExcel = Nothing
          End If
          Wichtig ist die If-Abfrage. Ansonsten pumpt sich Word mit Speicher voll bis nichts mehr geht und den es irgendwie nicht mehr frei gibt.

          Comment


          • #6
            Lösung: AccessibleObjectFromWindow

            Also, das mit der Timer-Routine ist nicht so richtig funktionsfähig. Es passiert zwar das gewünschte, jedoch läuft irgendwie der Garbage-Collector nicht optimal, d.h. wenn das eingebettete Objekt geöffnet ist, und der Zugriff aufs Object bzw. allgemein Objekte wiederholend stattfindet, kommen COM, .net und sonstiges sich ins Gehege und Word kommt nach einiger Zeit an irgendwelche Speichergrenzen. Die Anzeige geht in die Normal-Ansicht und die MsgBoxen fallen auf eine "Standard"-Anzeige zurück. Also, alles nicht praktikabel...

            Weitergesucht und und die Lösung gefunden:
            Die Lösung heißt "AccessibleObjectFromWindow" aus der OLEACC.DLL. Mit dem Handle des Dokumentenfensters bekommt man dessen Objekt, was mit ganz normalem VBA (indirekt per IDispose) alle Zugriffe ermöglicht und somit per .Parent den Zugriff auf das Document-Object ermöglicht.

            Für den Funktionsaufruf braucht man jetzt nur noch das Handle des entsprechenden Client-Fensters was das geöffnete OLE-Objekt einbettet. Das gibt es per "EnumChildWindows". Hier sucht man mit "GetClassName" ein Fenster der Klasse "OpusApp" (das ist das Word-Programm) und von diesem wieder per "EnumChildWindows" das Dokumentfenster der Klasse "_WwG". Davon gibt es komischerweise zwei, jedoch gibt "AccessibleObjectFromWindow" nur bei einem kein Fehlercode und das gewünschte Windows-Object zurück.

            Da ja gerne mehrere Dokumentenfenster geöffnet sind, muss nun noch das richtige herausgefunden werden. Dies erfolgt am einfachsten, in dem man in den ermittelten Dokument-Objekten jenes ermittelt, was genau (eindeutig) das geöffnete, eingebettete OLE-Objekt referenziert. Auf diese Weise funktioniert es ganz sicher, ohne die Fensternamen zur Suche kompliziert, risikoreich und ggf. sprachabhängig zusammenbasteln zu müssen

            Comment

            Working...
            X