Open Office / Libre Office OLE / Datei speichern...

Für Dinge zum Forum, Kritik, Verbesserungsvorschläge, Umfragen und ähnliches.
Meridian
Beiträge: 42
Registriert: Di 22. Feb 2022, 12:19
OS, Lazarus, FPC: Window 11
CPU-Target: 64Bit
Wohnort: Cloppenburg

Open Office / Libre Office OLE / Datei speichern...

Beitrag von Meridian »

Hallo zusammen,
heute geht es darum, wie ich eine Open Office writer Datei unter einem bestimmten Namen als .odt Datei und anschließend als .pdf abspeichern kann.

Bisher habe ich folgendes geschafft...
Eine vorbereitete Vorlage - .ott - kann ich öffnen und Daten und Text hinzufügen. Jetzt würde ich die Datei Namens "unbenannt.odt" gerne im gewünschten Verzeichnis mit gewünschten Namen speichern. Anschließend auch noch als pdf-Datei.

Ich recht viel im Netzt gesucht, vieles konnte ich verwenden, aber das korrekte Speichern klapp noch nicht. :(

Hier mein Code, mit dem ich die Vorlage öffne. Wie bekomme ich sie gespeichert??

procedure TND_liste_Form.StarteLibreOffice;
var
S, F, Datei : String;
begin
// Pfad der exe ermitteln...
S := ExtractFilePath(Application.ExeName);
F := 'Bereitschaft.ott';
Datei := Utf8decode(S + F);

if Assigned(InitProc) then
TProcedure(InitProc);

try
Server := CreateOleObject(ServerName);
except
WriteLn('Unable to start LibreOffice/Open Office.');
Exit;
end;

Desktop := Server.CreateInstance('com.sun.star.frame.Desktop');

LoadParams := VarArrayCreate([0, -1], varVariant);

{Open existing} //you must use forward slashes, not backward!
OW := Desktop.LoadComponentFromURL('file:///'+ Datei, '_blank', 0, VarArrayCreate([0, - 1], varVariant));

end;


Vielen Dank für eure Unterstützung.

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

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Jorg3000 »

Tach!
Ich habe mal Tage damit verbracht, bis es richtig funktionierte, Microsoft Word per OLE zu steuern.
Aber mit der Erfahrung ist es mir gerade gelungen (nach nur 20 Fehlversuchen) mittels OLE und OpenOffice/LibreOffice ein .odt/.docx als .pdf zu speichern. :)

Code: Alles auswählen

unit OpenOfficeUnit;

{$mode objfpc}{$H+}

interface


function convertODTtoPDF(const SrcFilename, PdfFilename: String): Boolean;


implementation


uses
     SysUtils, Variants, ComObj;



function convertPath_FileURI(const Path: String): String;
begin
  Result := 'file:///' + StringReplace(Path, '\', '/', [rfReplaceAll]);
end;



function convertODTtoPDF(const SrcFilename, PdfFilename: String): Boolean;
var
   v, ServiceManager, Desktop, Document, Options: Variant;
begin
  Result:=false;
  if (SrcFilename='') or (PdfFilename='') then Exit;
  if not FileExists(SrcFilename) then Exit;

  VarClear(Document);
  try
   ServiceManager := CreateOleObject('com.sun.star.ServiceManager');
   Desktop := ServiceManager.createInstance('com.sun.star.frame.Desktop');

   Options := VarArrayCreate([0,2],varVariant);  // 2 = höchster Index  = 3 Elemente

   v := ServiceManager.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
   v.Name := 'Hidden';
   v.Value := true;
   Options[0] := v;

   v := ServiceManager.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
   v.Name := 'ReadOnly';
   v.Value := true;
   Options[1] := v;

   v := ServiceManager.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
   v.Name := 'AsTemplate';
   v.Value := false;
   Options[2] := v;

   v := convertPath_FileURI(SrcFilename);
   Document := Desktop.loadComponentFromURL( v, '_blank', 0, Options );

   if not VarIsClear(Document) then
     begin
      Options := VarArrayCreate([0,0],varVariant);  // zweite 0 = höchster Index  = 1 Element
      v := ServiceManager.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
      v.Name  := 'FilterName';
      v.Value := 'writer_pdf_Export';
      Options[0] := v;

      v := convertPath_FileURI(PdfFilename);
      Document.storeToURL( v, Options );
      Result:=true;
     end;

  except   // on E: Exception do Writeln(E.ClassName, ': ', E.Message);
    Result:=false;
  end;

  VarClear(Options);
  if not VarIsEmpty(Document) then begin Document.close(false); VarClear(Document); end;
  VarClear(Desktop);
  VarClear(ServiceManager);
end;


end. 
Dazu eine Test-Funktion ...

Code: Alles auswählen

procedure Test();
var Path, SrcFilename, DestFilename: String;
begin
  Path := ExtractFilePath(ParamStr(0));
  SrcFilename  := Path+'Test.odt';
  DestFilename := Path+'Test.pdf';

  if convertODTtoPDF(SrcFilename, DestFilename)
    then ShowMessage('geklappt')
    else ShowMessage('Fehler');
end;
Habe gerade erfolgreich getestet, dass es nicht nur mit .odt geht, sondern auch mit .docx und vermutlich allen Dateitypen, die von LibreOffice geöffnet werden können.
Ich hoffe, dass viele Leute das gut gebrauchen können.
Grüße, Jörg
Zuletzt geändert von Jorg3000 am Mi 30. Okt 2024, 21:00, insgesamt 1-mal geändert.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1639
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von fliegermichl »

Cool! Danke.
Ich hab kein Openoffice sondern Libreoffice und dein Programm hat ohne jeglichen Eingriff auf Anhieb funktioniert.

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

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Jorg3000 »

Nachtrag:
Eine kleine Schönheitskorrektur: aus dem Document.close(true) bitte ein Document.close(false) machen.
Ich hab's gerade oben im Sourcecode geändert.
Das true hätte ein Speichern bewirkt, falls das Dokument verändert worden wäre (allerdings wurde es sowieso nicht geändert).

Meridian
Beiträge: 42
Registriert: Di 22. Feb 2022, 12:19
OS, Lazarus, FPC: Window 11
CPU-Target: 64Bit
Wohnort: Cloppenburg

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Meridian »

Moin,
vielen dank für die klasse Hilfe und den Code.

Ich habe mich aber falsch ausgedrückt. 8) Sorry.

Ich möchte die aktuell im Writer geöffnete Datei nach der Ergänzung/Bearbeitung unter einem anderen Namen in einem anderen Zielverzeichnis speichern.
Ich suche nach "FileSave" und "FileSaveAs".

Ich öffne entweder eine echte "VorlagenDatei", mit der Endung .ott, die im Writer dann "Unbenannt 1" heißt und unter einem neuen Namen gespeichert werden muss.

Oder ich öffne eine "Vorlagendatei" mit der Endung .odt. Dann lautet die aktuelle Datei im Writer "Notfallbereitschaft.odt". Die unter einem anderen Namen gespeichert werden muss.

Das sieht dann z.B. so aus.

In Niedersachen ist heute Feiertag und ich wünschen einen Schönen
Dateianhänge
Datei ott.png
Datei ott.png (8.9 KiB) 2816 mal betrachtet
Datei odt.png
Datei odt.png (13.34 KiB) 2816 mal betrachtet

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

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Jorg3000 »

Moin!
Habe gerade keine Zeit, aber ich glaube es geht mit wenigen Änderungen.
Anstelle das Document zu laden, übernimmt man es einfach aus dem aktiven Frame.

Edit: mein Code-Schnipsel an dieser Stelle war nicht richtig (gelöscht). Siehe unten eine funktionierende Lösung.
Zuletzt geändert von Jorg3000 am Fr 1. Nov 2024, 04:05, insgesamt 1-mal geändert.

Meridian
Beiträge: 42
Registriert: Di 22. Feb 2022, 12:19
OS, Lazarus, FPC: Window 11
CPU-Target: 64Bit
Wohnort: Cloppenburg

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Meridian »

Danke Jörg,

ich bin dabei, habs aber noch nicht hinbekommen. Bin nur Hobby-Tüfftler, lerne aber gerne dazu.

Gruß Helmut

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

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Jorg3000 »

Hi!
Heute Mittag hatte ich die falsche OLE-Syntax rausgesucht.
Hier eine ganz neue Funktion, um das aktive Dokument als PDF zu speichern.

Code: Alles auswählen

function saveActiveDocumentAsPDF(const PdfFilename: String): Boolean;
var
   v, ServiceManager, Desktop, Document, Options: Variant;
begin
  Result:=false;
  if PdfFilename='' then Exit;

  try
   ServiceManager := CreateOleObject('com.sun.star.ServiceManager');
   Desktop  := ServiceManager.createInstance('com.sun.star.frame.Desktop');
   Document := Desktop.getCurrentComponent;

   if not (VarIsEmpty(Document) or VarIsClear(Document)) then
     begin
      Options := VarArrayCreate([0,0],varVariant);  // zweite 0 = höchster Index  = 1 Element
      v := ServiceManager.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
      v.Name  := 'FilterName';
      v.Value := 'writer_pdf_Export';
      Options[0] := v;

      v := convertPath_FileURI(PdfFilename);
      Document.storeToURL( v, Options );
      Result:=true;
     end;

  except
    Result:=false;
  end;

  VarClear(Options);
  VarClear(Document);
  VarClear(Desktop);
  VarClear(ServiceManager);
end;
Die Funktion convertPath_FileURI() bitte aus meiner Unit oben entnehmen.
Grüße, Jörg

Meridian
Beiträge: 42
Registriert: Di 22. Feb 2022, 12:19
OS, Lazarus, FPC: Window 11
CPU-Target: 64Bit
Wohnort: Cloppenburg

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Meridian »

Ich schon wieder,

vielen Dank.

Und wenn ich deine function saveActiveDocumentAsPDF(const PdfFilename: String): Boolean; als Neue zum Speichern in eine ODT Datei benötige. Also z.B.

function saveActiveDocumentAsODT(const odtFilename: String): Boolean; muss ich bestimmt in folgendem Teil Änderungen vornehmen oder?
...
v.Name := 'FilterName'; <-- ist das dann noch korrekt???
v.Value := 'writer_pdf_Export'; <-- und hier muss auch eine Änderung gemacht werden???
Options[0] := v;

v := convertPath_FileURI(odtFilename);


Ich habe heute wieder eine Menge dazu gelernt. Schönen Abend wünsche ich.

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

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Jorg3000 »

Um es als .odt zu speichern:
'FilterName' bleibt, aber anstelle von 'writer_pdf_Export' dann 'writer8' einsetzen.
Zuletzt geändert von Jorg3000 am Fr 1. Nov 2024, 04:06, insgesamt 1-mal geändert.

Meridian
Beiträge: 42
Registriert: Di 22. Feb 2022, 12:19
OS, Lazarus, FPC: Window 11
CPU-Target: 64Bit
Wohnort: Cloppenburg

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Meridian »

es funktioniert super, bin begeistert ...

Meridian
Beiträge: 42
Registriert: Di 22. Feb 2022, 12:19
OS, Lazarus, FPC: Window 11
CPU-Target: 64Bit
Wohnort: Cloppenburg

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Meridian »

Moin,

eine Sache würde ich gerne noch lösen... und hab es erfolglos probiert.

mit den beiden Funktionen
function saveActiveDocumentAsPDF(const PdfFilename: String): Boolean;
und
function saveActiveDocumentAsODT(const odtFilename: String): Boolean;
wird die aktuell im Writer geöffnete Datei im Zielverzeichnis gespeichert. Top.

Aber das aktuell geöffnete Dokument im Writer hat noch immer den Namen "Unbenannt 1". Wie bekomme ich den aktuellen Namen identisch geändert?

Thanks...
Dateianhänge
Datei ott.png
Datei ott.png (8.9 KiB) 2665 mal betrachtet

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

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Jorg3000 »

Hello again!

In den bisherigen Funktionen wurde durch .storeToURL() ein Export ausgelöst, weshalb der Dateiname nicht als Dokumententitel übernommen wurde.
Für das normale Speichern gibt es .store() und .storeAsURL() ... ein kleiner Unterschied "As" und "To".

Hier eine neue Funktion, die herkömmlich speichert ...

Code: Alles auswählen

function saveActiveDocument(const Filename: String=''; wantClose: Boolean=false): Boolean;   // old: saveActiveDocumentAsPDF()
var
   ServiceManager, Desktop, Document, Options, fn: Variant;
begin
  Result:=false;
  try
   ServiceManager := CreateOleObject('com.sun.star.ServiceManager');
   Desktop  := ServiceManager.createInstance('com.sun.star.frame.Desktop');
   Document := Desktop.getCurrentComponent;

   if not (VarIsEmpty(Document) or VarIsClear(Document)) then
     begin
       if Filename='' then Document.store()
         else begin
               Options := VarArrayCreate([0, -1], varVariant);  // keine Optionen nötig (leeres Array)
               fn := convertPath_FileURI(Filename);
               Document.storeAsURL( fn, Options );
              end;
       Result:=true;
     end;

  except   // on E: Exception do Writeln(E.ClassName, ': ', E.Message);
    Result:=false;
  end;

  VarClear(Options);
  if wantClose and not VarIsEmpty(Document) then Document.close(false);
  VarClear(Document);
  VarClear(Desktop);
  VarClear(ServiceManager);
end;
Der Dateiname wird als Titel übernommen.
Wenn die Datei bereits gespeichert wurde, darf ein leerer Dateiname übergeben werden, um den bisherigen Namen zu behalten.
Grüße, Jörg

Meridian
Beiträge: 42
Registriert: Di 22. Feb 2022, 12:19
OS, Lazarus, FPC: Window 11
CPU-Target: 64Bit
Wohnort: Cloppenburg

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Meridian »

Moin,

danke noch einmal für die tolle Hilfe bezüglich meiner Fragen zum Thema LibreOffice-Steuerung.
Ich habe etwas mehr Erfahrung was die MS Word- und Excel-Steuerung mit Lazarus angeht, aber nicht zu LibreOffice.

Wer hat Tipps für mich, wie und wo ich mir mehr Wissen über diese Themen aneignen kann?
Würde gerne auch zusätzlich etwas zur LibreOffice Draw-Steuerung lernen.

Vielen Dank

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

Re: Open Office / Libre Office OLE / Datei speichern...

Beitrag von Jorg3000 »

Meridian hat geschrieben: Mi 6. Nov 2024, 13:45wo ich mir mehr Wissen über diese Themen aneignen kann?
Das ist gar nicht so einfach, denn bei der Websuche findet man recht wenig.
Das liegt daran, dass mal von OLE, mal vom COM Interface, mal vom UNO Interface die Rede ist, außerdem entweder OpenOffice oder LibreOffice genannt wird. Und das Thema scheint überhaupt wenig nachgefragt zu sein (weniger als Word/Excel OLE), d.h. ich habe in Foren nur wenige Code-Beispiele gefunden.
Ich empfehle dir ein Sprachmodell zu befragen. Eventuell dabei Pascal verheimlichen und die OLE-Syntax aus der Programmiersprache herauslesen, die einem das LLM von sich aus anbietet.
Letztlich bleibt es wahrscheinlich trotzdem viel Versuch und Irrtum, bis man aus den Schnipseln etwas lauffähiges zusammengebastelt hat.
Viel Glück und Erfolg!

Antworten