Einzelnen Beitrag anzeigen

Killuah

Registriert seit: 18. Okt 2007
6 Beiträge
 
Delphi 2006 Architect
 
#1

Suchen & Ersetzen in einem OpenOffice-Dokument

  Alt 28. Aug 2009, 15:57
Hallo erstmal,

zur Zeit bin ich auf der Suche nach einer Möglichkeit in einem OpenOffice-Dokument(.odt / Writer) alle Variablen mit Inhalten zu ersetzen.
Syntax der Variable ist immer "[Bezeichnung]". Da ich schon einige verschiedene Möglichkeiten ausprobiert habe und nichts meinen Anforderungen ensprechen konnte bitte ich hier um etwas Hilfe.

Die wohl einfachste Methode wäre über den Search-/ ReplaceDescriptor von OpenOffice. Da ich hier jedoch den genauen Suchbegriff eingeben muss und ich in meinen Variablen auch If/Else-Anweisungen zulasse (eigener interner Parser der das Ganze verarbeitet) scheidet diese Möglichkeit leider aus.

Eine weitere Möglichkeit ist, über den SearchDescriptor eine Range zu erhalten, an dem die Variable beginnt und dort mit einem TextCursor zu arbeiten. Das funktioniert in reinem Text wirklich ausgezeichnet. Erst wenn man mit Tabellen oder Textfeldern arbeitet stößt man bei dieser Methode allein an seine Grenzen. So ist es leider nicht möglich in der Tabelle den TextCursor zu erstellen, da ich diesen nur auf einem XText-Objekt erstellen kann, und jede Tabelle ein eigenes XText behinhaltet, das ich hier nicht herausbekomme. (vielleicht weiß ja einer wie ich das rauskriege)

Eine weitere Möglichkeit ist, das ich alle XText-Objekte der Reihe nach durchgehe und schaue, ob die eckigen Klammern vorhanden sind. Jedoch tauchen auch hier Probleme bei den Tabellen auf. Wie man in der Datei im Anhang sieht, habe ich in einer Tabelle eine weitere Tabelle. Im Folgenden ersteinmal der bisherige QuellText:

Delphi-Quellcode:
type
  TOOTest = class(TForm)
    OpenDialog1: TOpenDialog;
    procedure FormCreate(Sender: TObject);
  public
    OOSrvMgr: Variant; // ServiceManager
    OOfficeApp: Variant; // XDesktop
    OODispHlp: Variant; // DispatchHelper
    OODokument: Variant;
    procedure ReplaceTables;
    procedure ReplaceText(XText: Variant);
    function GetCountInString(sAllText, sSearch: String): Integer;
  end;

implementation

  procedure TOOTest.FormCreate(Sender: TObject);
  var
    sURLLocation: String;
  begin
  // Vorbereitung
    OOSrvMgr := CreateOleObject('com.sun.star.ServiceManager');
    OOfficeApp := OOSrvMgr.CreateInstance('com.sun.star.frame.Desktop');
    OODispHlp := OOSrvMgr.CreateInstance('com.sun.star.frame.DispatchHelper');
    if OpenDialog1.Execute then
      sURLLocation := ConvertToURL(OpenDialog1.FileName); // ConvertToURL ist aus den Examples von OOC
    OODokument := OOfficeApp.LoadComponentFromURL(sURLLocation, '_blank', 0, VarArrayCreate([0, -1], VarVariant));

    ReplaceTables;

    OODokument.Close(False);
    OOfficeApp := unassigned;
    OOSrvMgr := Null;
  end;

  procedure TOOTest.ReplaceTables;
  var
    XTextTables: Variant;
    XTable: Variant;
    XCell : Variant;
    iTable: Integer;
    Row, Column: Integer;
  begin
    XTextTables := OODokument.getTextTables;
  
    for iTable := XTextTables.getCount -1 downto 0 do
    begin
      XTable:= XTextTables.getByIndex(iTable);

      for Row := 0 to XTable.Rows.Count -1 do
      begin
        for Column := 0 to XTable.Columns.Count -1 do
        begin
          XCell := XTable.getCellByPosition(Column, Row);
          //ShowMessage('CellText = "'+XCell.getText.getString+'"');
          ReplaceText(XCell.getText);
        end;
      end;
    end;
  end;

  procedure TOOTest.ReplaceText(XText: Variant);
  var
    XTextCursor: Variant;
    // XTextCursor2: Variant;
    // XHlpCursor: Variant;
    bSelect: Boolean;
    sAllText: String;
    iAktPos: Integer;
  begin
    XTextCursor := XText.createTextCursor;
    XTextCursor.gotoStart(False);
  
    // XTextCursor2 := XText.createTextCursor;
    // XTextCursor2.gotoStart(False);
    // XHlpCursor := XText.createTextCursor;
    // XHlpCursor.gotoStart(False);

    sAllText := XText.getString;
  
    bSelect := False;
    while (Pos('[', sAllText) > 0) and (Pos(']', sAllText) > 0) do
    begin
      if sAllText[1] = '[then
      begin
        bSelect := True;
        XTextCursor.goRight(1, bSelect);
      end else if sAllText[1] = ']then
      begin
        XTextCursor.goRight(1, bSelect);
        if XTextCursor.getString <> 'then
          // überprüfen, ob die Anzahl an '[' und ']' identisch sind (für internen Parser (bzgl. If-Abfragen) wichtig)
          // GetCountInString(Text, SuchString: String): Integer;
          if GetCountInString(XTextCursor.getString, '[') = GetCountInString(XTextCursor.getString, ']') then
          begin
            XTextCursor.setString('');
            bSelect := False;
          end;
      end else
        XTextCursor.goRight(1, bSelect);

      // ToDo: geht so nicht, da der TextCursor ÜBER die Tabelle springt und
      // der sAllText die Inhalte enthält
      sAllText := Copy(sAllText, 2, Length(sAllText)-1);

      // ToDo: "sAllText := XTextCursor2.getText.getString;" gibt immer den kompletten Inhalt der Zelle zurück
      // XTextCursor2.goRight(1, False);
      // XTextCursor2.gotoEnd(True);
      // XHlpCursor.goRight(1, False);
      // sAllText := XTextCursor2.getText.getString;

      // Expand = True, damit die Seletierung wieder aufgehoben wird (?)
      // XTextCursor2.gotoRange(XHlpCursor, True);
    end;
  end;

end.
Nach dem Auswählen der Datei suche ich alle Tabellen und gehe diese der Reihe nach, beginnend mit der Letzten, einzeln durch.

Delphi-Quellcode:
Info: Warum mit der Letzten beginnen?

In OpenOffice sind die Tabellen im Dokument von Oben nach Unten einfach durchnummeriert.

Bsp:
[Dokument]
  [Tabelle1]
  [/Tabelle1]

  [Tabelle2]
    [Tabelle3]
    [/Tabelle3]
  [/Tabelle2]
[/Dokument]

Wenn ich in Tabelle2 bin und mir "sAllText" hole dann enthält dieser den kompletten Textinhalt von Tabelle3 - getrennt über einen Zeilenumbruch #13#10. Wenn ich also von hinten beginne habe ich in Tabelle3 keine '[' oder ']' mehr.
Dann wähle ich jede Zelle einzeln aus und ersetze mit "ReplaceText(XText: Variant)" die Variablen. Wie man anhand der beiden ToDo's in der Prozedur sehen kann stoße ich jedoch auf Probleme, wenn ich in einer Tabelle eine weitere habe.


Im Anhang einmal die Textdatei mit der ich teste und der Quellcode zum Debuggen. Ich selber Suche zur Zeit entweder in verschiedenen Foren, der API-Seite von OpenOffice oder in dem ObjektInspektor den man als Plugin in OpenOffice starten kann. Jedoch konnte bisher nichts weiterhelfen.


freundliche Grüße
Killuah
Angehängte Dateien
Dateityp: zip openoffice-suchenundersetzen_511.zip (199,2 KB, 12x aufgerufen)
  Mit Zitat antworten Zitat