Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Winword-OLE Search&Replace (https://www.delphipraxis.net/189782-winword-ole-search-replace.html)

hoika 20. Jul 2016 15:49

Winword-OLE Search&Replace
 
Hallo,
ich habe hier eine Docx-Datei mit einer Kopfzeile.
In der Zip-Datei (Docx=Zip, wie ihr ja wisst) steht die Kopfzeile in header2.xml.
Das Ersetzen klappt.
Jetzt habe ich eine weitere Docx-Datei, das steht die Kopfzeile in header3.xml.
Und genau hier klappt das Ersetzen nicht!

Es sieht so aus, als ob ich durch alle Kopfzeilen-Sektions muss.

Der Code ist nichts besonderes, kommt zum Teil von hier
http://www.delphipraxis.net/155216-w...nsertfile.html (#5)

Hm, und während des Schreibens hatte ich die Lösung ;)
Wenn ich in Word eine Kopfzeile einfüge, schreibt er "1. Kopfzeile".
Ich kann also nicht nur einen (eine ;) ) geben.

Deshalb noch mal die Frage:
Es sieht so aus, als ob ich durch alle Kopfzeilen-Sektions muss.

Ah ja, nicht über die SL_Search wundern, dass ist noch ein Anpassung zu
"ersetze Zeichen mit mehr als 255 Zeichen".

Delphi-Quellcode:
     
procedure DBInText_OLE_ReplaceString(const WordApp: OLEVariant;
  const SearchString, ReplaceString: String; const ZusatzLogInfo: String = '');

      WordApp.Selection.Find.ClearFormatting;
      WordApp.Selection.Find.Replacement.ClearFormatting;
      WordApp.Selection.Find.Text:= SL_Search[iString];
      WordApp.Selection.Find.Replacement.Text := SL_Replace[iString];
      WordApp.Selection.Find.Forward := True;
      WordApp.Selection.Find.Wrap := wdFindContinue;
      WordApp.Selection.Find.Format := False;
      WordApp.Selection.Find.MatchCase := False;
      WordApp.Selection.Find.MatchWholeWord := False;
      WordApp.Selection.Find.MatchWildcards := False;
      WordApp.Selection.Find.MatchSoundsLike := False;
      WordApp.Selection.Find.MatchAllWordForms := False;

      //WordApp.Selection.Find.Execute(Replace:= wdReplaceAll);
      iDummy := 0;
      if not WordApp.Selection.Find.Execute(Replace:= wdReplaceAll) then
      begin
        iDummy := 1;
      end;

// Aufruf
// 1. Kopfzeile
//               WordApp.ActiveWindow.ActivePane.View.SeekView:= wdSeekFirstPageHeader;
//               DBInText_OLE_ReplaceString(WordApp, SearchString, ReplaceString, '1. Kopfzeile');

               WordApp.ActiveWindow.ActivePane.View.SeekView:= wdSeekCurrentPageHeader;
               DBInText_OLE_ReplaceString(WordApp, SearchString, ReplaceString, 'Kopfzeile');

               WordApp.ActiveWindow.ActivePane.View.SeekView:= wdSeekMainDocument;
               DBInText_OLE_ReplaceString(WordApp, SearchString, ReplaceString, 'Hauptdokument');

               WordApp.ActiveWindow.ActivePane.View.SeekView:= wdSeekCurrentPageFooter;
               DBInText_OLE_ReplaceString(WordApp, SearchString, ReplaceString, 'Fusszeile');

hoika 20. Jul 2016 17:04

AW: Winword-OLE Search&Replace
 
Hallo,
google ...

http://stackoverflow.com/questions/9...ole-and-delphi

Ich glaube, das ist genau das was ich brauche.

p80286 21. Jul 2016 09:16

AW: Winword-OLE Search&Replace
 
Etwas chaotisch.
Zunächst solltest Du Dich entscheiden ob Du die .DOCX-Datei auseinander nehmen willst, oder ob Du die Änderungen mit Hilfe von OLE durchführen willst. Falls Du Dich für OLE entscheidest, das Worddokument besteht aus mehreren "Objektsamlungen" z.b. Shapes,Sections etc. innerhalb derer Du mit Hilfe von .Range und/oder .Selection eine Auswahl triffst, innerhalb der Du z.B. Suchen, Ersetzen oder Text eingeben kannst. (natürlich auch die Schriftart, fett, Unterstrichen usw.)

Du solltest dafür allerdings ein schlüssiges Konzept haben, da ja auch verschiedene Templates Einfluß auf das Dokument haben. Da könnten einige Änderungen durchaus kontraproduktiv sein.

Gruß
K-H

Sherlock 21. Jul 2016 10:18

AW: Winword-OLE Search&Replace
 
Keine Ahnung warum in dem SO-Link keiner drauf kommt, aber Variant ist in OLE/COM die langsamste Möglichkeit. Lieber solltest Du das Word-Objekt über reguläre COM-Interfaces einbinden. Ich hatte früher (also vor 15 Jahren) mal eine Applikation die sehr viel in Word per Variant wurschtelte, die Performance war grottig, egal wie sehr ich dran rum schraubte. Erst ein bisschen später (nachdem ich das Projekt aufgab) kam mir durch "Eric Harmon COM-Automation in Delphi" insbesondere dieser Teil (vorletzter Absatz auf der Seite) die Erleuchtung. Variants sind nichts für Performance intensive Aufgaben. Ohnehin fährt man besser, wenn man gleich die Interfaces einbindet, der Code wird ja dadurch besser lesbar/wartbar.

Sherlock

hoika 21. Jul 2016 16:47

AW: Winword-OLE Search&Replace
 
Hallo,

die Variants haben den Vorteil, dass sie mit alle Word-Versionen funktionieren,
z.B. wurden in das Open neue Parameter eingeführt.
Da muss man je nach Word-Version was basteln.
Man hat dann also mehrere TLB's.

Ich nehme bei Docx die Datei bereits selber auseinander, um meine zu ersetzenden Kenner zu finden.
Ist ja ne simpel Zip-Datei.
Das OLE benutze ich dann "nur" zum eigentlichen Ersetzen.

Ich habe gestern abend mal angefangen mit,
mit meinem Link rumzuspielen.

Für einen Umstieg auf TWordApplication fehlt mir die Zeit.
Aber ich schaue den Harmon-Link mal an.

Danke

Heiko

Sherlock 22. Jul 2016 07:15

AW: Winword-OLE Search&Replace
 
Zunächst, bevor Du Zeit investierst: Harmon ist nur ein allgemeines COM-Buch für Delphi Entwickler.
Als nächstes sollten neue Versionen kein Problem sein, so lange die alten COM-Objekte weiter existieren, was IMHO bei Word eigentlich immer der Fall war (MS liebt die Abwärtskompatibilität). Neue Schnittstellen werden wie bei Windows selbst mit neuen Libs eingeführt, die alten bleiben bestehen.

Sherlock

bcvs 22. Jul 2016 07:40

AW: Winword-OLE Search&Replace
 
Zitat:

Zitat von hoika (Beitrag 1343162)
Ich nehme bei Docx die Datei bereits selber auseinander, um meine zu ersetzenden Kenner zu finden.
Ist ja ne simpel Zip-Datei.
Das OLE benutze ich dann "nur" zum eigentlichen Ersetzen.

Und warum ersetzt du deine Texte dann nicht direkt in der DOCX, wenn du sie eh schon auseinander nimmst?

hoika 22. Jul 2016 13:12

AW: Winword-OLE Search&Replace
 
Hallo,
das habe ich auch schon probiert.
Danach ist öfters die Datei defekt (sagt Word).

Ich glaube, dass liegt am Zippen nach dem Ersetzen.
Passiert aber nicht immer,
also lasse ich es lieber.

Sherlock 22. Jul 2016 14:13

AW: Winword-OLE Search&Replace
 
Nein, ich vermute mal eher, Du machst etwas falsch. Wenn nämlich Word sein eigenes Suchen&Ersetzen nicht ohne den von Dir beschriebenen Fehler erledigen könnte, dann wäre die Kacke mächtig am dampfen. HintergrundInformation: Wenn Du per COM/OLE eine Wordfunktion benutzt, ist das in aller Regel auch die Funktion die Word selbst verwendet.

Ich gehe mittlerweile davon aus, daß Du eine veraltete Schnittstelle verwendest, um auf das Word-Dokument zuzugreifen, dafür spricht, daß es mit docx nicht zurecht kommt, dafür aber mit dem von dir vorbereiteten/entpackten Dokument.

Sherlock

hoika 22. Jul 2016 14:52

AW: Winword-OLE Search&Replace
 
Hallo,
Moment! ;)

Klar kommt die alte Schnittstelle mit dem DOCX klar,
aber ich habe noch keine Funktion gefunden, die mir den Word-Text im Printformat,
also als reinen ASCI-Text zurückgibt.
Somit weiss ich nicht, welche Kenner das aktuelle Word-Dokument besitzt.
Kann ja sein, dass es nur 3 Kenner hat.
Dann muss ich nur 3 mal mein Replace machen.
Ich hatte mal was mit Paragraphs gelesen, das aber nicht hinbekommen.
Da Docx ja reine Text(Xml-)-Dateien sind, suche ich die Kenner einfach direkt per Delphi-Code.

Weist du, wie ich den lesbaren Text einer Worddatei mit Word selber ermittle,
also ohne die Formatierungen und den ganzen Schickschnack?

Wie gesagt:
Es sind 2 Methoden:
1. Ermittle alle Kenner des Dokumentes.
2. Ersetze genau diese Kenner durch die entsprechenden Werte.

PS2:
Ich glaube, das war bei Open-Office, der ganz penibel mit seinen Dateien war.
Ausgepackt, etwas im Text (nicht dem Xml-Strukturen) geändert,
wieder zusammengepackt -> Puff, OO sagt, Datei ungültig.

Heiko

p80286 22. Jul 2016 22:15

AW: Winword-OLE Search&Replace
 
Zitat:

Zitat von hoika (Beitrag 1343194)
Klar kommt die alte Schnittstelle mit dem DOCX klar,
aber ich habe noch keine Funktion gefunden, die mir den Word-Text im Printformat,
also als reinen ASCI-Text zurückgibt.

Speicher es als Text, aber ich vermute, das willst Du nicht.

Eine andere Möglichkeit wäre das kopieren des ganzen Text (Details weiß ich jetzt gerade nicht "wholeStory" könnte Dein Stichwort sein) und dann liest Du das Clipboard aus.

Zitat:

Zitat von hoika (Beitrag 1343194)
Somit weiss ich nicht, welche Kenner das aktuelle Word-Dokument besitzt.
Kann ja sein, dass es nur 3 Kenner hat.
Dann muss ich nur 3 mal mein Replace machen.

Was verstehst Du unter "Kenner"?


Zitat:

Zitat von hoika (Beitrag 1343194)
Ich hatte mal was mit Paragraphs gelesen, das aber nicht hinbekommen.

Ein entspricht ziemlich genau einem Delphi-String, platt gesagt das was zwischen zwei CRLF steht. Je nach Seitenbreite und Länge erhält man dann einen mehrzeiligen Abschnitt.

Du bist Dir aber darüber im klaren, daß ein Word-Dokument nicht einfach nur aus Text besteht, sondern z.B in Sections unterteilt ist?

Gruß
K-H

Sherlock 25. Jul 2016 06:46

AW: Winword-OLE Search&Replace
 
OK, alles gut dann.
Meinst Du mit "Kennern" Textmarken? Die werden im englischen Bookmarks genannt und sind als solche im Selection Objekt zu finden (https://msdn.microsoft.com/en-us/lib.../ff193356.aspx).

Mein Ausflug in die Word-COM-Programmierung handelte vom Suchen&Ersetzen solcher Textmarken. Wie gesagt wegen mangelhafter Performance (es ging um 300-400 Textmarken pro Dokument) wurde das zu Gunsten von Crystal Reports samt Word Export aufgegeben. Aber eventuell kann ich noch ein bis zwei Tipps zusammenkratzen. Quellcode liegt mir leider nicht mehr vor.

Sherlock

hoika 25. Jul 2016 07:56

AW: Winword-OLE Search&Replace
 
Hallo,
nein, ist schon gut. Klappt ja ganz gut.
Vielleicht kaufe ich ja wirklich mal ne Komponente (Scallabium?),
oder schau mir mal TWordApplication an.

Bei 300-400 Kennern würde ich auch krachen gehn ;)

Mit Kenner meine ich eine eigene Kreation, wie z.B. #Name#,
der soll dann durch den richtigen Namen ersetzt werden.


Einfach so auf was anderes Umsteigen geht nicht,
hängen ja ne Menge Kunden dran, die sich eigene Reports mit Word oder Open-Office gebastelt haben.


< Du bist Dir aber darüber im klaren, daß ein Word-Dokument nicht einfach nur aus Text besteht,
sondern z.B in Sections unterteilt ist? >
Ja, ist bekannt, benutzt aber von unseren Kunden keiner.
Wir haben vorgefertigte Reports (mit einer Sektion), die werden abgeändert.
Ich habe aber mal testweise eine Word-Datei mit 2 Sektions erzeugt,
und schon wurde bei der 2. Sektion nichts ersetzt ...
Muss ich noch ändern.

Sherlock 25. Jul 2016 08:46

AW: Winword-OLE Search&Replace
 
Wir hatten bewußt auf die Eigenkreationen verzichtet, weil die immer wieder mal zerschossen werden könnten. Textmarken muß man hingegen sehr bewußt... kaputtieren. ;) Außerdem können Textmarken von Word besser gesucht werden, weil sie als eigene Objekte geführt sind. Aber wenn die Kiste schon steht, will ich da nicht mehr rein reden :)

Sherlock

p80286 25. Jul 2016 10:49

AW: Winword-OLE Search&Replace
 
ich hab da ein Makro ausgegraben, daß mir ein wenig die Struktur eines Worddokumentes analysiert:
Code:
Sub Makro2()
'
' Dokument Inhalt
'
'
With ActiveDocument
  MsgBox ("im Dokument enthaltene Shapes:" + Str(.Shapes.Count))
  For a = 1 To .Shapes.Count
   MsgBox (a + .Shapes(a).Name)
  Next
 
  MsgBox ("im Dokument enthaltene InlineShapes:" + Str(.InlineShapes.Count))
 
 
  MsgBox ("im Dokument enthaltene Sections:" + Str(.Sections.Count))
  For a = 1 To .Sections.Count
    MsgBox ("Anzahl Header" + Str(.Sections(a).Headers.Count) + " in Section" + Str(a) + Chr(13) + Chr(10) + _
            "Anzahl Footer" + Str(.Sections(a).Footers.Count) + " in Section" + Str(a))
    For b = 1 To .Sections(a).Headers.Count
      MsgBox ("Header " + Str(b) + " Anzahl Shapes " + Str(.Sections(a).Headers(b).Shapes.Count))
    Next
     
  Next
  MsgBox ("im Dokument enthaltene bookmarks: " + Str(.Bookmarks.Count))
    For a = 1 To .Bookmarks.Count
      MsgBox (Str(a) + "Bookmark Name:" + .Bookmarks(a).Name + Chr(13) + Chr(10) + _
                "Bookmark Länge:" + Str(.Bookmarks(a).Range.StoryLength))
               
               
  Next
 
 ' MsgBox ("im Dokument enthaltene FooterHeader:" + Str(.Shapes.Count))
End With 'ActiveDocument
End Sub
vielleicht hilft Dir das weiter

Gruß
K-H

da stimmt was nicht mit den codeTags??

Pardon, da war noch eine Macke drin.

Sub Makro2()
'
' Dokument Inhalt
'
'
With ActiveDocument
MsgBox ("im Dokument enthaltene Shapes:" + Str(.Shapes.Count))
For a = 1 To .Shapes.Count
MsgBox (Str(a) + .Shapes(a).Name)
Next

MsgBox ("im Dokument enthaltene InlineShapes:" + Str(.InlineShapes.Count))

MsgBox ("im Dokument enthaltene Sections:" + Str(.Sections.Count))
For a = 1 To .Sections.Count
MsgBox ("Anzahl Header" + Str(.Sections(a).Headers.Count) + " in Section" + Str(a) + Chr(13) + Chr(10) + _
"Anzahl Footer" + Str(.Sections(a).Footers.Count) + " in Section" + Str(a))
For b = 1 To .Sections(a).Headers.Count
MsgBox ("Header " + Str(b) + " Anzahl Shapes " + Str(.Sections(a).Headers(b).Shapes.Count))
Next

Next

MsgBox ("im Dokument enthaltene bookmarks: " + Str(.Bookmarks.Count))

For a = 1 To .Bookmarks.Count
MsgBox (Str(a) + "Bookmark Name:" + .Bookmarks(a).Name + Chr(13) + Chr(10) + _
"Bookmark Länge:" + Str(.Bookmarks(a).Range.StoryLength))
Next


' MsgBox ("im Dokument enthaltene FooterHeader:" + Str(.Shapes.Count))
End With 'ActiveDocument
End Sub

Sherlock 25. Jul 2016 10:51

AW: Winword-OLE Search&Replace
 
Ist das lossy zipped? :D

Die Forensoftware scheint Word-Macros auszublenden ;)

Ah, so geht es wohl besser.

Sherlock

p80286 25. Jul 2016 11:04

AW: Winword-OLE Search&Replace
 
Zitat:

Zitat von Sherlock (Beitrag 1343282)
Die Forensoftware scheint Word-Macros auszublenden ;)

Verdenken kann ich es Ihr nicht. Mir graust es jedesmal wenn ich solche Konstrukte sehe, aber wenn's geht *schulterzuck*

Gruß
K-H

hoika 25. Jul 2016 13:02

AW: Winword-OLE Search&Replace
 
Hallo,
danke schön.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:38 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz