Felix Riesterer: Word mittels PHP's COM-Schnittstelle öffnen

Liebe Mitlesende,

für ein ehrenamtliches Projekt benötige ich für die Migration Inhalte von Word-Dateien im HTML-Format. Dazu will ich die Word-Dateien mittels PHP nach HTML konvertieren. Um das zu erreichen haben meine Recherchen ergeben, dass ich aus PHP heraus Word öffnen lassen kann, um Word anzuweisen, dass es die aktuell geöffnete Datei im HTML-Format speichert.

Dieser Automatismus ist deswegen notwendig, da sich die Inhalte der Worddateien immer wieder ändern können, sodass eine einmalige Kovertierung nicht hilft.

Meine Versuche scheitern bereits daran, dass mein Script ohne jegliche Meldung sang- und klanglos abraucht, wenn ich auch nur irgendwie auf eine Methode des instanziierten COM-Objekts zugreifen möchte.

Beispiel:

// Verbindung zu MS Word aufbauen  
$word = new COM('word.application');  
// Fehlerfall abfangen? Keine Ahnung... "or die('Meldung')" ist keine Lösung  
  
$datei = 'w://w-00180.doc'; // Datei von Netzlaufwerk per PHP ermittelt  
  
// Debug-Ausgabe kommt in der Datei noch an:  
debug('Word scheint erreichbar: Version ', $word->Version);  
  
$word->Documents->Open($datei);  
  
// diese Debug-Ausgabe kommt nicht mehr an:  
debug('Word scheint noch immer erreichbar: Version ', $word->Version);  
  
// Mit dieser Zeile entkommentiert erhalte ich überhaupt keine Debug-Ausgaben  
//$word->Close();

Warum erhalte ich noch nichteinmal irgend eine Fehlermeldung in irgendeiner Log-Datei meines Indianers? Im Access-Log steht, dass die Anfrage mit einem 500er beantwortet wurde... mehr aber auch nicht.

Was kann ich tun? Mir fehlen die guten Suchwörter, denn mit "COM" und "PHP" finde ich hauptsächlich die PHP.net-Seiten, von denen ich meinen Code her habe.

Wenn ich auf dem Rechner manuell Word starte und die URL für die Datei eingebe, öffnet Word sie ohne jegliches Murren. An Zugriffsrechten (readonly) kann es also eigentlich nicht liegen... oder doch?

Wer weiß Rat?

Liebe Grüße,

Felix Riesterer.

--
ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
  1. *Grrr*... error_reporting(E_ALL) und schon kommt was: "Datei konnte nicht gefunden werden".

    Jetzt brat mir einer aber einen Storch! Folgende Schreibweisen erzeugen immer wieder diese Fehlermeldung:
     w://w-00180.doc
     w:/w-00180.doc
     w:\w-00180.doc
     w:\w-00180.doc

    Die Datei heißt wirklich 'w-00180.doc' und liegt auf Laufwerk 'w:'. Wie sonst soll ich sie denn bitteschön referenzieren, wenn obige Schreibweisen nicht helfen?

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Moin Moin!

      *Grrr*... error_reporting(E_ALL) und schon kommt was: "Datei konnte nicht gefunden werden".

      Woher kommt die Meldung? Word oder PHP?

      Jetzt brat mir einer aber einen Storch! Folgende Schreibweisen erzeugen immer wieder diese Fehlermeldung:
      w://w-00180.doc
      w:/w-00180.doc
      w:\w-00180.doc
      w:\w-00180.doc

      Die Datei heißt wirklich 'w-00180.doc' und liegt auf Laufwerk 'w:'. Wie sonst soll ich sie denn bitteschön referenzieren, wenn obige Schreibweisen nicht helfen?

      Die Windows-API verträgt Forward Slashes, Word vermutlich nicht. Bleiben also Backslashes. PHP verwurstet innerhalb von Strings einen für sich selbst, Du mußt also jeden Backslash, der in der OLE-Schnittstelle ankommen soll, in PHP-Strings doppelt schreiben.

      Mit etwas "Glück" verwurstet Word den String auch nochmal, so dass Du nochmal Backslashes verdoppeln mußt.

      Vielleicht erforschst Du die OLE-API erst einmal mit VB oder irgendetwas anderem aus der MS-Ecke? Oder Du suchst Dir einen Word-Leser, der ohne Word auskommt.

      Bei DocX hätte sich natürlich angeboten, das DocX stumpf mit ZIP zu entpacken und das enthaltene XML mit üblichen Tools zu verwursten.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
      1. Lieber Alexander (HH),

        Die Windows-API verträgt Forward Slashes, Word vermutlich nicht.

        s.o.

        Bei DocX hätte sich natürlich angeboten, das DocX stumpf mit ZIP zu entpacken und das enthaltene XML mit üblichen Tools zu verwursten.

        Die Dateien sind nicht docX sondern doc. Leider.

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
    2. Hey Felix,

      ich weiß leider nicht mehr genau, wo mir das letztens untergekommen ist und auch nicht, warum dies der Fall ist. Aber: Mir hat es letztens geholfen, das Trennzeichen zu verdreifachen, also '///' oder '\'.

      Vielleicht hilft Dir das als Ansatz, auch wenn ich keine Erklärung dafür habe.

      Gruß, Dennis

      1. Lieber Der-Dennis,

        das Trennzeichen zu verdreifachen, also '///' oder '\'.

        in PHP(5) unter Windows ist es anscheinend egal ob man \ oder / benutzt. Bei \ muss man aufpassen, da man eventuell Zeichen maskiert, obwohl man das so nicht gemeint hat. Gerade Dein Beispiel '\' sieht problematisch aus. Um ein lokales Laufwerk anzusprechen hatte 'D:/verzeichnis/datei.end' bei mir in beiden Kontexten (PHP und com(word.application)) Erfolg.

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
        1. Hi!

          Bei \ muss man aufpassen, da man eventuell Zeichen maskiert, obwohl man das so nicht gemeint hat.

          Der Kontextwechsel mal wieder, tritt selbst bei String-Literalen auf.

          Gerade Dein Beispiel '\' sieht problematisch aus.

          Eine ungerade Anzahl kann nicht gut sein, wenn man Backslashes mit einem ebensolchen maskieren muss. Der dritte ist bereits ein weiteres Maskierzeichen. Wenn das problemlos durchgeht, dann nur deswegen, weil PHP nicht alle Kombinationen aus Backslash und weiterem Zeichen als Sequenz kennt und dann Backslash und folgendes Zeichen getrennt betrachtet. Man fällt erst dann auf die Nase, wenn man bei einer Änderung nun eins der Zeichen n, r, t, v oder f nach dem \ notiert.

          Lo!

          1. Hey Felix, hey dedlfix,

            mir ist bewusst, dass ungerade Wiederholungen der Zeichen nicht Sinn der Sache sind und unter Umständen noch größere Probleme verursachen können.

            Ein Kollege, der an einem ähnlichem Problem arbeitete (Verbindung PHP - andere Anwendung), fragte mich allerdings wie gesagt vor einiger Zeit, ob ich einen Fehler in seinem Skript erkennen könne. Er hätte einen einfachen Slash (oder Backslash, weiß es nicht mehr genau) versucht ebenso wie die Verdoppelung und Vervierfachung. Konnte ich nicht, sagte aber "pragmatisch", "wie sieht's mit dreimal aus?". Und es funktionierte.

            Warum auch immer dies der Fall ist, scheint es eine PHP-Funktion oder eine sonstige API einer anderen Anwendung zu geben, die diese Verdreifachung erwartet. Ich frage bei nächster Gelegenheit nach, worum es dabei ging und melde mich dann bei Euch. Wenn ich mich recht entsinne, hat er das anschließend auch anders gelöst. Auch dies werde ich Euch mitteilen.

            Ihr habt aber wie gesagt recht, dass ungerade Wiederholungen im Normalfall sinnlos sind - darauf hätte ich eingehen sollen.

            @Felix: Viel Erfolg weiterhin und ich freue mich, dass Du den Fehler finden konntest.

            Gruß, Dennis

            1. Hey Felix, hey dedlfix,

              mir hat das gerade keine Ruhe gelassen und ich habe meinen Kollegen angerufen. Zuerst einmal: Ich nehme alles zurück und behaupte das Gegenteil. Wenn man keine Ahnung hat...

              Aber, falls es Euch interessiert: Es ging um eine Verbindung zwischen Matlab und PHP. Und dazwischen gab's noch eine selbstgemachte Schnittstelle, geschrieben in C++. PHP sollte an der besagten Stelle einen Dateinamen entgegen nehmen und an die C++-Schnittstelle weitergeben. Diese Schnittstelle hat an der entsprechenden Stelle den Dateinamen zerlegt und Teile davon in einen regulären Ausdruck übernommen - und irgendwo da hat es in diesem speziellen Fall zufällig funktioniert, wenn der Wert im eigentlichen Dateipfad verdreifacht wurde.

              Das ist die Kurzform von dem, was ich meine gerade einigermaßen verstanden zu haben. Durch den Hinweis mit dem Verdreifachen sei man aber darauf gekommen, dass die Schnittstelle überhaupt nicht funktioniert und grundlegend überarbeitet werden musste, sowohl was die Logik als auch die Ausführung angeht.

              So, ich hoffe, ich habe zumindest ein kleines bisschen Klarheit geschaffen, was mich zu dem völlig falschen Hinweis verleitet hat.

              Gruß, Dennis

              1. Hallo Dennis

                • und irgendwo da hat es in diesem speziellen Fall zufällig funktioniert, wenn der Wert im eigentlichen Dateipfad verdreifacht wurde.

                Windows interpretiert \\ grosszügig als ///. Das ist eine spezielle Form eines Kommentars. So markierte Kommentare werden an den Interpreter weitergereicht und dienen etwa zur Generierung einer XML-Datei, mit der ein Einsprunpunkt festgelegt und eine Applikation gestartet werdeb kann. (Ganz ohne Zufall.)

                Mit den besten Grüssen
                Richard

    3. Hallo,

        
      <?php  
      // Verbindung zu MS Word aufbauen  
      $word = new COM('word.application');  
      // Fehlerfall abfangen? Keine Ahnung... "or die('Meldung')" ist keine Lösung  
        
      $datei = 'd://test.doc'; // Datei von Netzlaufwerk per PHP ermittelt  
        
        
      $word->Documents->Open($datei);  
      
      

      *Grrr*... error_reporting(E_

      funzt bei mir ...; habe dazu eine test.doc unter d: eingerichtet...;

      Gruß

      jobo

      1. Hello,

        Und funktioniert es mit

        $datei = 'd:/test.doc'; // Datei von Netzlaufwerk per PHP ermittelt

        auch?

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hallo,

          Und funktioniert es mit

          $datei = 'd:/test.doc'; // Datei von Netzlaufwerk per PHP ermittelt

          auch?

          ja.

          Gruß

          jobo

    4. Yerf!

      Als was läuft PHP (im IIS?) und wo genau liegen die Dateien (Netzwerk?)

      Netzwerkdienste haben so die Eigenschaft nicht auf von einem Benutzer verbunbdenes Netzlaufwerk zugreiufen zu können. Teste also notfalls erst mal von einem lokalen Laufwerk aus.

      Gruß,

      Harlequin

      --
      RIP --- XHTML 2
      nur die Besten sterben jung
      1. Moin Moin!

        Als was läuft PHP (im IIS?) und wo genau liegen die Dateien (Netzwerk?)

        Netzwerkdienste haben so die Eigenschaft nicht auf von einem Benutzer verbunbdenes Netzlaufwerk zugreiufen zu können. Teste also notfalls erst mal von einem lokalen Laufwerk aus.

        Erschwerend kommt dazu, dass ab XP / Server 2003 Laufwerksbuchstaben PRO USER vergeben werden, während sie bei allen älteren Windows-Version global waren.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
      2. Lieber Harlequin,

        es ist eine XAMP-Installation unter WinXP. Die Daten liegen auf einem anderen XP-Rechner im Netzwerk in einem freigegebenen Verzeichnis.

        Netzwerkdienste haben so die Eigenschaft nicht auf von einem Benutzer verbunbdenes Netzlaufwerk zugreiufen zu können. Teste also notfalls erst mal von einem lokalen Laufwerk aus.

        Das hat mich auf die Lösung gebracht. Danke dafür!

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
  2. Moin Moin!

    Dieser Automatismus ist deswegen notwendig, da sich die Inhalte der Worddateien immer wieder ändern können, sodass eine einmalige Kovertierung nicht hilft.

    Es wird Zeit, die Texter von Word auf ein CMS umzuschulen!

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
    1. Lieber Alexander (HH),

      Es wird Zeit, die Texter von Word auf ein CMS umzuschulen!

      dazu muss es zuerst existieren. Aber genau da arbeite ich ja dran. *g* Anstatt Word gibt's dann den TinyMCE. Der verkraftet auch Copy&Paste aus Word sehr gut.

      Liebe Grüße,

      Felix Riesterer.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
  3. Hi Felix,

    ich weiß nicht, ob mein Hinweis dir weiterhelfen kann, da ich mich mit API-Geschichten nicht auskenne und nicht einschätzen kann inwiefern es Parallelen gibt. Ich kenne aber die Syntax um Word per VBA zu steuern. Und dort gestaltet sich der Befehl wie folgt:

    Document.Open Filename:="w:\test.doc"

    Gruß Fabulit

  4. Hi,

    woher weiss denn PHP was W:\ bedeutet? PHP wird sicherlich nicht unter deinem Benutzerkonto ausgeführt. Vielleicht solltest du mal einen UNC Pfad angeben, statt eine Laufwerksbezeichnung?

    Gruss, Frank

    1. Moin Moin!

      woher weiss denn PHP was W:\ bedeutet? PHP wird sicherlich nicht unter deinem Benutzerkonto ausgeführt.

      Wenn es im Kontext eines Webservers läuft, vermutlich nicht. Dann greifen auch noch andere Beschränkungen (z.B. ist es Diensten in aller Regel nicht gestattet, mit einem "fremden" Desktop zu interagieren, und einen eigenen haben sie nicht).

      Von der Kommandozeile bzw. über "Scheduled Tasks" gestartet könnte PHP durchaus unter Felix' Account laufen.

      Vielleicht solltest du mal einen UNC Pfad angeben, statt eine Laufwerksbezeichnung?

      Könnte helfen, wenn die Rechte großzügig genug vergeben wurden.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
      1. möchte nur noch betonen:

        Account != Profil unter Windows. Dem Account seinem Profil kann ein Laufwerksmapping eines Netzwerkordners zugehörig sein (welches beim Anmeldevorgang verbunden wird).

        Cheers, Frank

        1. Lieber Frank (no reg),

          möchte nur noch betonen:

          Account != Profil unter Windows.

          das hat mich auf die Lösung gebracht. Danke dafür.

          Liebe Grüße,

          Felix Riesterer.

          --
          ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
          1. Moin, freut mich, geholfen zu haben.

            Lieber Frank (no reg),

            Abgesehen von dem (no reg) ... So spricht eigentlich generell meine ganze weibliche Bekanntschaft an?! ;-)

            Cheers, Frank

      2. Lieber Alexander (HH),

        Von der Kommandozeile bzw. über "Scheduled Tasks" gestartet könnte PHP durchaus unter Felix' Account laufen.

        zu diesem Problem kommen wir auch noch, wenn über den Taskplaner eine entsprechende "Seite" des Webservers automatisiert aufgerufen werden soll, damit der dann eine Website synchronisiert.

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
  5. Liebe Helfer und Tipps-Geber,

    das "Problem" war tatsächlich, dass der Apache zwar unter dem angemeldeten Benutzerkonto lief (das ist bei XAMP so wenn der Apache nicht als Dienst läuft O_o) und deshalb das gemountete Netzlaufwerk zur Verfügung hatte, das über ihn gestartete Word aber nicht. Somit hatte Word kein Netzlaufwerk und konnte die Dateien nicht finden.

    Das hat eine ganze Weile gedauert, bis da der Groschen gefallen war. Mir blieb keine andere Möglichkeit, als die Word-Dateien mittels PHP in ein lokales Verzeichnis zu kopieren, um sie dann von dort aus mit Word zu konvertieren.

    Es handelt sich um eine Übergangslösung, um von einem MS Access basierten Verwaltungssystem auf ein PHP/MySQL-basiertes umzusteigen. Die Konvertierung ist also nur für die Phase des Parallelbetriebs vor dem eigentlichen Umsteigen notwendig und somit ein tatsächlich nur vorübergehendes Provisorium (im Gegensatz zu den Provisorien, die für die Ewigkeit gemacht sind).

    Vielen Dank an alle, die mir Tipps gegeben haben.

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)