[gelöst] MS Word OLE .docx SaveAs .rtf/.pdf/.html

Antworten
Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 169
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

[gelöst] MS Word OLE .docx SaveAs .rtf/.pdf/.html

Beitrag von Jorg3000 »

Hi!
Kennt sich jemand mit OLE bezüglich Microsoft Word aus?
Ich versuche eine .DOCX per OLE als .RTF speichern zu lassen. Das Laden funktioniert, das Speichern aber nicht.
Ich verwende Lazarus v2.0.10 auf Windows 10 64bit mit Office 2021.
Der Fehler tritt immer bei Doc.SaveAs2() auf, egal welche Parameter ich bisher übergeben habe.
Danke und Grüße, Jörg

Code: Alles auswählen

uses ... Variants, ComObj;

function WordDoc_SaveAs(const aSrcFilename, aDestFilename: String): Boolean;
var 
    WordApp, Doc: Variant;  // OleVariant?
begin
  Result:=false;
  if (aSrcFilename='') or (aDestFilename='') then Exit;
  if not FileExists(aSrcFilename)
    then begin ShowMessage('File not found'#13+aSrcFilename); Exit; end;

  WordApp:=Unassigned;  // Check for Unassigned with VarIsEmpty(). Check for an Undefined value with VarIsClear(). Check for a Null value with VarIsNull().
  Doc:=Unassigned;
  Result:=true;

  try
    WordApp:=CreateOleObject('Word.Application');
   except
    Result:=false;
    ShowMessage('Could not find or start MS Word'); 
  end;

  if Result then
   try
     Doc:=WordApp.Documents.Open(aSrcFilename,false{noConfirm},true{ReadOnly},false{notRecentFiles});
    except
     Result:=false;
     Doc:=Unassigned;  
     ShowMessage('Could not open file'#13+aSrcFilename);
   end;

  if Result and FileExists(aDestFilename) then Result:=DeleteFile(aDestFilename);

  if Result then
   try
     Doc.SaveAs2(aDestFilename,6);  // https://docs.microsoft.com/de-de/office/vba/api/word.saveas2
     // Doc.SaveAs2(FileName:=aDestFilename, FileFormat:=6);
    except
     Result:=false;
     ShowMessage('Could not save file'#13+aDestFilename);
   end;

  if not VarIsEmpty(Doc) then
   try
     Doc.Close(0);  // 0 = don't SaveChanges
    except
     ShowMessage('Error at Doc.Close');
   end;
  Doc:=Unassigned;

  if not VarIsEmpty(WordApp) then
   try
     WordApp.Quit;  // doesn't close other Word windows opened by user
    except
     ShowMessage('Error at WordApp.Quit');
   end;
  WordApp:=Unassigned;

  if Result then ShowMessage('YEAH! :)');
end;


procedure TForm1.Button1Click(Sender: TObject);
var Path: String;
begin
  Path:=ExtractFilePath(ParamStr(0));
  WordDoc_SaveAs(Path+'Test1.docx', Path+'Test2.rtf');
end; 
Zuletzt geändert von Jorg3000 am Mo 12. Sep 2022, 07:20, insgesamt 3-mal geändert.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Word OLE .docx to .rtf

Beitrag von theo »

Ich habe kein MS Office, aber falls dir das hilft: Mit LibreOffice geht es ganz einfach auf der Kommandozeile, auch hier mit Linux.
soffice --headless --convert-to rtf *.docx --outdir OutputDirectory/

Jens
Beiträge: 3
Registriert: So 11. Sep 2022, 17:14

Re: Word OLE .docx to .rtf

Beitrag von Jens »

möglicherweise mag Word nicht, dass Du ein RTF mit der .docx-Erweiterung abspeichern willst. Ersetze doch mal

Code: Alles auswählen

WordDoc_SaveAs(Path+'Test1.docx', Path+'Test2.docx');
durch

Code: Alles auswählen

WordDoc_SaveAs(Path+'Test1.docx', Path+'Test2.rtf');

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 169
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Word OLE .docx to .rtf

Beitrag von Jorg3000 »

Oh, der Dateiname Test2.docx hieß nur durch hin- und herprobieren versehentlich nicht mehr Test2.rtf.
Habe es oben im Beispiel wieder korrigiert. Ändert aber nichts daran, dass SaveAs2 sich weiterhin weigert.
Laut Fehlermeldung liegt es wohl an der Parameterübergabe. Aber ich komme trotzdem nicht weiter.

Und ich bin ja auch Fan von LibreOffice, aber das nützt mir in diesem Fall nichts, weil fast alle meiner Firmenkunden nur Microsoft-Office einsetzen.

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: Word OLE .docx to .rtf

Beitrag von wp_xyz »

Wenn man das SaveAs2 nur mit 1 Parameter aufruft, dann funktioniert es - nur entsteht dann halt keine rtf-Datei. Bei mir kommt die Fehlermeldung "Der Remoteprozeduraufruf ist fehlgeschlagen", aber hier ist überhaupt nichts "remote"... Sehr seltsam. Andererseits finde ich im Internet viele (ältere) Beispiele, in denen das SaveAs2 genauso wie von dir angewendet vorkommt. Könnte es sein, dass die Methode in aktuelleren Office-Versionen (ich habe 2016) geändert wurde?

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 169
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Word OLE .docx to .rtf

Beitrag von Jorg3000 »

wp_xyz hat geschrieben:
So 11. Sep 2022, 18:37
Wenn man das SaveAs2 nur mit 1 Parameter aufruft, dann funktioniert es
Danke fürs Ausprobieren!
Das ist auch meine Erfahrung. Mit nur einem Parameter klappt der SaveAs2-Aufruf.
Habe aber im Netz einige Beispiele mit mehreren Parametern gefunden, die entweder wie in meinem Code gestrickt sind (und dann angeblich so funktionieren) oder eine total veraltete Syntax verwendeten.

Laut der aktuellen Microsoft-Dokumentation https://docs.microsoft.com/de-de/office ... rd.saveas2
sind natürlich mehrere Parameter möglich. Aber schon sobald ich die Syntax Doc.SaveAs2(FileName:=aDestFilename) nehme, geht's nicht mehr.

Habe auch schon versucht aDestFilename als WideString (weil wohl extra OLE-kompatibel) oder als OLEVariant zu definieren, aber damit bisher auch ohne Erfolg.

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 169
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Word OLE .docx to .rtf

Beitrag von Jorg3000 »

Ich hatte gerade noch die verrückte Idee, ein Array of (Ole)Variant zu übergeben ...

Code: Alles auswählen

 var Parameters: OleVariant;
 Parameters := VarArrayOf( [aDestFilename, 6] );  // Parameters:=VarArrayOf( [ OleVariant(WideString(aDestFilename)), OleVariant(6) ] );
 Doc.SaveAs2(Parameters);
Zu meiner Überraschung wurde schon mein erster Versuch kompiliert, aber natürlich funktioniert SaveAs2 damit auch nicht. :lol:

Jens
Beiträge: 3
Registriert: So 11. Sep 2022, 17:14

Re: Word OLE .docx to .rtf

Beitrag von Jens »

Hier viewtopic.php?p=71501#p71501 hatte jemand Probleme mit Speichern/Überschreiben, evtl. hilft das

Code: Alles auswählen

Documents.Add
anstelle von

Code: Alles auswählen

Documents.Open

Jens
Beiträge: 3
Registriert: So 11. Sep 2022, 17:14

Re: Word OLE .docx to .rtf

Beitrag von Jens »

in https://stackoverflow.com/questions/840 ... and-as-pdf wird das Format auch als OleVariant angegeben:

Code: Alles auswählen

var
  FileName,
  FileFormat : OleVariant;
begin
  FileName := AFileName;
  FileFormat := wdFormatPDF;
  ADocument.SaveAs(FileName, FileFormat, EmptyParam, EmptyParam, EmptyParam,
                     EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
                     EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
                     EmptyParam);
end;

wp_xyz
Beiträge: 4885
Registriert: Fr 8. Apr 2011, 09:01

Re: Word OLE .docx to .rtf

Beitrag von wp_xyz »

Hey, gut beobachtet. Genau so funktioniert es!

Code: Alles auswählen

function WordDoc_SaveAs(const aSrcFilename, aDestFilename: String): Boolean;
var
    WordApp, Doc, Format: OleVariant;
begin
     ...
     Format := 6;
     Doc.SaveAs2(aDestFilename, Format); 
     ...  
Ich habe den Wiki-Artikel über Word-Automation entsprechend ergänzt: https://wiki.freepascal.org/WordAutomat ... _speichern

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 169
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Word OLE .docx to .rtf

Beitrag von Jorg3000 »

Moin!
Yeaaah, es läuft! Ein großes Dankeschön für eure Bemühungen! :)

Ich hatte die Parameter zuvor schon mal als OleVariant ausprobiert, aber zunächst erfolglos.
Bei mir funktioniert es nur in Kombination mit Documents.Add anstelle von Documents.Open!

So sehen die funktionierenden Änderungen bei mir jetzt aus ...

Code: Alles auswählen

 Doc:=WordApp.Documents.Add(aSrcFilename);
 ...
 Doc.SaveAs( OleVariant(aDestFilename), OleVariant(6) );
PS: Mir fällt nachträglich auf, dass ich zwischenzeitlich testhalber von SaveAs2 auf SaveAs gewechselt war. Hm egal, funktioniert.

Hier noch weitere interessante Format-Möglichkeiten https://docs.microsoft.com/de-de/office ... saveformat
wdFormatText = 2 = Microsoft Windows text form
wdFormatRTF = 6 = Rich text format (RTF)
wdFormatHTML = 8 = Standard HTML format.
wdFormatPDF = 17 = PDF format

Besten Dank und schöne Grüße, Jörg

Antworten