Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Word Automatisation Beschleunigen (https://www.delphipraxis.net/203682-word-automatisation-beschleunigen.html)

GoTo0815 12. Mär 2020 11:06

Word Automatisation Beschleunigen
 
Guten Tag!

Für einen Preislistengenerator verwende ich MS Word.
Für das allgemeine Design einer Seite in dieser Preisliste verwende ich ein einseitiges Worddokument (DOCX) als Vorlage(beispielsweise mit 6 Artikeln auf einer DIN A4 Seite).
Wenn die gesamte Preisliste nun 60 Artikel beinhalten soll, dann lade ich das o.g. Dokument editiere die Infos, Bilder und Tabellen per OLE und speichere das als PDF Dokument ab.
Dann schließe ich das Word Dokument und lade die Vorlage erneut. Das Ganze mache ich dann beispielsweise 10 Mal.
Das funktioniert soweit sehr gut und ist bereits lange verlässlich im Einsatz.

Das öffnen des Worddokuments (Vorlage) erfolgt über

Delphi-Quellcode:
   WordApp.Documents.Open(aFilename, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam);


Nun zum Problem:
Mittlerweile müssen hintereinander 100 - 150 verschiedene Preislisten mit jeweils mehr als 300 Artikeln erzeugt werden.
Das bedeutet im aktuellen Maximalfall, dass der o.g. Code 5000 - 7500 Mal ausgeführt wird.
Das laden der Vorlage dauert seine Zeit, was den gasamten Durchlauf auf mehrere Stunden ausweitet.
Ich habe bereits versucht, dass vor dem Start die Wordvorlage in ein virtuelles Laufwerk in den Arbeitspeicher geladen wird, um die Zugriffszeiten zu reduzieren, aber richtig Performance bringt das nicht.
Ein Worddokument ist eine ZIP Datei, bei der nur die Endung auf DOCX umbenannt wurde (übrigens sehr hilfreich, wenn man mal beispielsweise Bilder extrahieren möchte aus einem Dokument, einfach wieder in ZIP umbenennen...).
Somit dauert natürlich das Laden sehr lange.

Kurzum: Weiß jemand, wie ich es schaffen kann ohne jedesmal das Document zu laden?
Also einmal Laden, in eine Variable speichern und immer wieder ein neues Dokument aus dieser Variable erzeugen?
Ich finde dazu einfach nicht die passenden Ansätze im Netz. Ggf. suche ich auch falsch.
Würde mich über Ansätze oder Code sehr freuen.

Grüße
GoTo0815

Der schöne Günther 12. Mär 2020 11:53

AW: Word Automatisation Beschleunigen
 
Ich kenne mich mit der Automatisierung von Office nicht aus, aber nicht dass du nach jedem Dokument Word effektiv schließt und wieder neu startest? 🤔

GoTo0815 12. Mär 2020 11:59

AW: Word Automatisation Beschleunigen
 
... nein, die Word Instanz bleibt bis zum Ende geöffnet. Es wird immer nur wieder die selbe Worddatei geöffnet, editiert und dann gespeichert.

bcvs 12. Mär 2020 11:59

AW: Word Automatisation Beschleunigen
 
Ich habe mal eine Zeit lang Rechnungen auf diese Weise erzeugt. Dabei dauerte das Befüllen des Word-Dokumentes per OLE recht lange.

Jetzt lade ich das XML-Dokument aus der DOCX in ein TXMLDocument, schreibe meine Werte da an die richtigen Stellen rein und zippe das wieder zusammen zu einem DOCX. Vielleicht wäre das ja ein Ansatz für dich.

Edelfix 12. Mär 2020 12:03

AW: Word Automatisation Beschleunigen
 
Wir machen das ähnlich. Unsere Vorlagen haben die Endung .DOTX
Beim speichern auf das Format stellen.
Zum bearbeiten muss man die .DOTX Dateien im Windows Explorer mit rechter Maus Taste und dann „öffnen“ editieren.
Weiß nicht ob das ein Vorteil ist.

GoTo0815 12. Mär 2020 12:39

AW: Word Automatisation Beschleunigen
 
... würde es nur um einzelne Werte gehen, aber es werden ganze Preistabellen je Artikel eingefügt. Diese sind in der Anzahl der Reihen und Spalten unterschiedlich groß.
Ich würde erst einmal abwarten, ob jemand hier noch eine Idee hätte, ein Dokument nur einmal zu laden und es immer wieder neu aus einer Variable einem neuen Dokument zuzuweisen.
Der Aufwand der Umstellung wäre hier viel geringer. Sollte das dann keine Zeitersparnis bringen, würde ich andere Wege auch noch einmal anschauen.

Das Befüllen eines Dokuments geht übrigens deutlich zügiger, wenn man die Sichtbarkeit der MS Word App (Visible) auf False setzt.

hoika 12. Mär 2020 12:51

AW: Word Automatisation Beschleunigen
 
Hallo,
ich werfe mal WPTools in die Runde.
Die können mittlerweise auch DOCX.

Pfaffe 12. Mär 2020 12:56

AW: Word Automatisation Beschleunigen
 
Word.Visible:= false;
Nicht DOCX, sondern dotx als Vorlage verwenden.

Bei Excel: ExcelApplication1.Visible[FLCID]:= false;

KodeZwerg 12. Mär 2020 13:56

AW: Word Automatisation Beschleunigen
 
Ich weiß nicht ob es noch mehr Geschwindigkeit bringt, jedenfalls gäbe es da noch
Delphi-Quellcode:
WordApp.ScreenUpdating := False;

GoTo0815 12. Mär 2020 14:27

AW: Word Automatisation Beschleunigen
 
Pfaffe: Inwieweit hilft es eine DotX anstatt der DocX zu verwenden?
Muss diese dann in meinem Fall nicht auch tausende Male von der Festplatte geladen werden?
Die eigentliche Frage ist, wie verhindere ich das häufige Laden der Datei von der Festplatte.

p80286 12. Mär 2020 17:32

AW: Word Automatisation Beschleunigen
 
Eine Dot-Datei ist eine Vorlage, eine DOC das (mehr oder weniger) finale Dokument. Da einige Funktionalitäten eigentlich nur bei Vorlagen verfügbar sind, bin ich davon ausgegangen, daß DOC ein Schreibfehler war??
Die wichtigste Beschleunigung wurde schon genannt Visible=False.
Dann bringt die Arbeit mit Range statt Selection auch etwas.
Und vllt. können wir Dir weiter helfen wenn Du den Source postest.

Gruß
K-H

HolgerX 12. Mär 2020 18:13

AW: Word Automatisation Beschleunigen
 
Hmm..

Also um das leeren = Laden wird Du wohl nicht herum kommen.
Word unterstützt kein speichern/laden per Stream, somit kannst Du dir das originale Word-Dokument nicht vor dem Bearbeiten in nen Stream speichen und dann vor jeder Rechnung einfach wieder ins Word zurück schreiben.

Es scheint hier nur eine Möglichkeit über die Zwischenablage zu geben, was mir aber zu gefährlich wäre, wenn der User noch andere Copy/Paste Aktionen während deiner Erzeugung durchführen kann.

Eine Beschleunigung könnte somit (neben Visible:=False / ScreenUpdating := False) noch die Verwendung einer schnellen SSD zum Laden der Vorlage oder eine temporäre RAM-Disk, wenn es keine Hardware Option gibt.. ;)

Alternativ kannst Du die Vorlage natürlich auch jedes Mal selber neu per Programm erstellen, ob das jedoch schneller geht...

Somit würde ansonsten nur die Verwendung einer Report-Komponente eine Alternative darstellen, dann müsste in dessem Designer nur das Word-Dokument nachgebildet werden.

EarlyBird 12. Mär 2020 19:59

AW: Word Automatisation Beschleunigen
 
ich werfe mal die verschiedenen dot.net Word API´s ins rennen.
Wir nutzen zur Zeit DevExpress Office File API.
Die Geschwindigkeit gegenüber der Word Automation ist "atemberaubend"
Das Handling ist meiner Meinung nach auch wesentlich einfacher.
Damit kann man eine Vorlage Laden und daraus beliebig viele neue Dokumente erzeugen.
Bei der Anzahl an Dokumenten die Ihr erstellen müsst ist das ja vielleicht eine Überlegung wert.
Und Pdf's kann man auch direkt damit erzeugen

GoTo0815 13. Mär 2020 09:03

AW: Word Automatisation Beschleunigen
 
Bereits alles umgesetzt:
SSD: Check
Ram Disk: Check
Visible:= False : Check
ScreenUpdating := False : Check

Vorlage selbst erstellen könnte klappen, ist für nen Test natürlich mächtig aufwändig :-)
Zwischenablage sehe ich ähnlich, obwohl, wenn der Rechner nur für diese Aufgabe verwendet wird, dann könnte das ggf. trotzdem ein Weg sein.

.Net traue ich mich momentan nicht ran. Denke zwar, dass könnte die Lösung sein, aber ich habe mich da ehrlich gesagt noch nie mit beschäftig.

haentschman 13. Mär 2020 09:14

AW: Word Automatisation Beschleunigen
 
Moin...:P

Könntest du dir einen Umbau auf FastReport oder ähnliches vorstellen? Da hast du die Oberfläche (Word) außen vor. Du müßtest die Daten andersweitig "vorbereiten" ... Bilder in Datenbank/Ordner etc.

GoTo0815 13. Mär 2020 09:35

AW: Word Automatisation Beschleunigen
 
Moin auch !!! :-)

Ich habe schon sehr viel über andere Wege nachgedacht. Ein Grund um an Word festzuhalten ist, dass die Änderung der Vorlagen (beispielsweise das Layout) von jemandem ohne weitere Kenntnis in Word durchgeführt werden kann.
Ich empfinde die Ratschläge zu anderen Wegen auch wichtig und ggf. hilfreich, aber mit diesem Thread hier, verfolge ich den Ansatz die bestehende Word Automatisation zu beschleunigen.
Erst wenn hier alle Möglichkeiten erschöpft sind, würde ich ein Abbiegen auf einen anderen Weg in Betracht ziehen.

Ich habe halt immer noch die Hoffnung, dass hier irgendwer schreibt: "Da musst Du einfach VariableVomTypOleVariant := WordApp.Documents.ActiveDocument und dann ein WordApp.Documents.Add und dem dann die Varible zuweisen."

Uwe Raabe 13. Mär 2020 09:45

AW: Word Automatisation Beschleunigen
 
Als ich die Beschreibung deiner Vorgehensweise las, dachte ich gleich an die Mail-Merge Funktionalität in Word, bei der eine Vorlage mit Platzhaltern durch Einträge einer Datenquelle gefüllt und pro Datensatz ein separates Dokument gedruckt wird (gedruckt kann auch das Speichern als PDF bedeuten). Ich bin mir aber nicht sicher, ob das alle deine Anforderungen erfüllt.

GoTo0815 13. Mär 2020 10:09

AW: Word Automatisation Beschleunigen
 
Ja, die Serienbrieffunktion hatte ich auch bereits im Blick. Problematisch wird es halt mit dem Einfügen von unterschiedlich großen Preistabellen.
Sagen wir ein Artikel wäre Kies. Den es in 10 verschiedenen Körnungen gäbe und in Gebinden von 25kg bis hin zu mehreren Tonnen.
Der nächste Artikel wäre ein T-Shirt in 4 Größen und 3 Mengenstaffeln.
Will sagen die Tabellen haben unterschiedliche Mengen an Spalten und Reihen.
Vielleicht übersehe ich da auch etwas, aber ich konnte mir bisher keinen Weg vorstellen, das in einem Serienbrief abzubilden.
Schon auf der Seite der Quelldaten.. :-)

GoTo0815 13. Mär 2020 11:23

AW: Word Automatisation Beschleunigen
 
Habe mich jetzt mal ein wenig bei den VBAlern umgeschaut.
Und habe zumindest einen Lösungsansatz gefunden, dass Dokument einfach weiter zu verwenden.
Man merkt sich die Range der Textmarke füllt diese mit Inhalt. Dadurch werden laut Forumseintrag offene Textmarken zu geschlossenen.
Nach dem Speichern des befüllten Dokuments als PDF ersetze ich die gemerkten Ranges alle wieder durch gleichnamige Textmarken.
Ob das die gewünschte Performance bringt und das alles so klappt, werde ich testen, aber es ist zumindest ein Ansatz, mit dem ich auf Basis von "einer einzigen" geöffneten Vorlage arbeiten könnte.

Hier gefunden: http://www.office-loesung.de/ftopic42883_0_0_asc.php

Code:
Sub TBrange()
    Dim bRange As Range
    '
    If ActiveDocument.Bookmarks.Exists("F1") Then
        Set bRange = ActiveDocument.Bookmarks("F1").Range
        bRange.Text = "der Text"
    End If
    '
    ' Textmarke recykeln
    With ActiveDocument.Bookmarks
        .Add Range:=bRange, Name:="F1"
    End With
End Sub

TigerLilly 13. Mär 2020 13:36

AW: Word Automatisation Beschleunigen
 
Wenn die Vorlagen auch als RTF Dateien vorliegen können, dann ist das ev. eine Option:

https://www.128byte.ru/

p80286 13. Mär 2020 14:06

AW: Word Automatisation Beschleunigen
 
Zitat:

Zitat von GoTo0815 (Beitrag 1459659)
Ja, die Serienbrieffunktion hatte ich auch bereits im Blick. Problematisch wird es halt mit dem Einfügen von unterschiedlich großen Preistabellen.
Sagen wir ein Artikel wäre Kies. Den es in 10 verschiedenen Körnungen gäbe und in Gebinden von 25kg bis hin zu mehreren Tonnen.
Der nächste Artikel wäre ein T-Shirt in 4 Größen und 3 Mengenstaffeln.
Will sagen die Tabellen haben unterschiedliche Mengen an Spalten und Reihen.
Vielleicht übersehe ich da auch etwas, aber ich konnte mir bisher keinen Weg vorstellen, das in einem Serienbrief abzubilden.
Schon auf der Seite der Quelldaten.. :-)

Tja Deine Quelldaten kenne ich nicht.... der Rest sollte mit einem makro zu erledigen sein (insert table....)
Das ist ja der Vorteil daß es da Standdardaufrufe Beim erstellen eines Dokumentes aus einer Vorlage gibt.

Gruß
K-H

GoTo0815 14. Mär 2020 11:50

AW: Word Automatisation Beschleunigen
 
Tiger Lilly: Das werde ich mir mal anschauen.

jobo 14. Mär 2020 12:27

AW: Word Automatisation Beschleunigen
 
Zitat:

Zitat von GoTo0815 (Beitrag 1459663)
Code:
Sub TBrange()
    Dim bRange As Range
    '
    If ActiveDocument.Bookmarks.Exists("F1") Then
        Set bRange = ActiveDocument.Bookmarks("F1").Range
        bRange.Text = "der Text"
    End If
    '
    ' Textmarke recykeln
    With ActiveDocument.Bookmarks
        .Add Range:=bRange, Name:="F1"
    End With
End Sub

Wir haben das gleiche Prinzip in einem alten Delphiprojekt genutzt. Also Ranges über Bookmarks definiert und neu befüllt, gesetzt. Wenn ich mich richtig erinnere war es das beste/schnellste Ergebnis von verschiedenen Varianten / Versuchen (und damals nicht selbstverständlich, es war robust).
Das war allerdings ohne Exists Prüfung, sondern eine Iteration in einem gegebenen Dokument durch die Liste der definierten Bookmarks.
Auf die Art konnte man beliebig große Feldinhalte befüllen und das Ganze auch bei mehrseitigen Dokumenten so schnell, dass man mit einem System/Mitarbeiter mehrere Hochleistungsdrucker in Betrieb halten kann.
Man muss nur aufpassen, dass man sich bei der Arbeit mit den Dokumenten nicht unbemerkt die Bookmarks zerstört. Aber vielleicht kann man das mit neueren Wordversionen auch besser sehen und bedienen.
Drumrum war noch eine Gesamtseitenkontrolle, um Fehldrucke/Fehlbefüllung zu erkennen und einseitig/mehrseitiges vorbedrucktes Papier nicht falsch zu bedrucken.

GoTo0815 16. Mär 2020 20:33

AW: Word Automatisation Beschleunigen
 
Ich versuche das gerade umzusetzen. Bei einfachen Textersetzungen klappt das auch gut, aber wenn die Textmarke mit einer Tabelle gefüllt ist, dann habe ich Probleme, dass immer mehr Tabellen in einer Textmarke entstehen und nicht wie gewünscht nur eine neue Tabelle in der Textmarke.


Delphi-Quellcode:
  var ovBookmark, ovBRange : OleVariant;
      iRows, iCols : Integer;

  ovBookmark := 'NameDerTextmarke';
  ovBRange := WordApp.ActiveDocument.Bookmarks.Item(ovBookmark).Range;
  WordTable := WordApp.ActiveDocument.Tables.Add(ovBRange, iRows, iCols);
  // Dann wird die Tabelle mit Inhalt gefüllt.
  // ....
  // Später dann noch
  // Hier hatte ich auch schon versucht noch einmal nach dem Befüllen der Tabelle noch einmal ovBRange neu zu setzen.
  // Wenn ich ovBRange := WordApp.ActiveDocument.Bookmarks.Item(ovBookmark).Range; setze ändert das das Problem nicht. Es werden immer mehr Tabellen im Inneren der Bookmark.
  // Wenn ich ovBRange := WordTable.Range; setze, dann erhalte ich beim erneuten erstellen einer Tabelle die Meldung: "Der Bereich kann nicht gelöscht werden".
  WordApp.ActiveDocument.Bookmarks.Add(ovBookmark, ovBRange);
Also der erste Durchgang mit der frischen Vorlage funktioniert. Die Tabelle kann einwandfrei eingesetzt werden. Nur ab dem zweiten Durchgang werden es immer mehr Tabellen innerhalb einer Bookmark und es wird immer langsamer. Was klar ist.

jobo 17. Mär 2020 11:29

AW: Word Automatisation Beschleunigen
 
Ich krieg leichtes Hirnsausen mit Blick auf VB, aber ich glaube Du musst die Table der Range zuweisen und nicht eine Table mit Hilfe der Range anlegen.

GoTo0815 17. Mär 2020 11:45

AW: Word Automatisation Beschleunigen
 
Das kann ich gut verstehen.
Ich habe jetzt den Weg gewählt die Tabellen zu löschen, bevor ich neue einfüge.
Dazu merke ich mir die Bookmarks in denen eine Tabelle erstellt wird in einer StringList.

Delphi-Quellcode:

if aListOfBookmarksWithTables.Count > 0 then
begin
  for iCounter2 := aListOfBookmarksWithTables.Count-1 downto 0 do
  begin
    WordTable:= WordApp.ActiveDocument.Bookmarks.Item(aListOfBookmarksWithTables[iCounter2]).Range.Tables.Item(1);
    WordTable.Delete;
    aListOfBookmarksWithTables.Delete(iCounter2);
  end;
end;
Scheint zumindest zu funktionieren.

Jumpy 17. Mär 2020 21:03

AW: Word Automatisation Beschleunigen
 
Wenn in dem Dokument im Leerzustand keine Tabellen sind, könntest du doch einfach pauschal alle Tabellen im Dokument löschen und musst das nicht so kompliziert mit Merkliste machen, oder?

GoTo0815 19. Mär 2020 09:32

AW: Word Automatisation Beschleunigen
 
Danke Jumpy,
Man muss dem User der die Vorlage gestaltet auch die Möglichkeit geben Tabellen anderweitig zu ergänzen, ohne dass das System dann diese auch löscht. Ergo komme ich am Merken der mit temporären Tabellen befüllten Bookmarks nicht vorbei.
Z.B. werden für die Positionierung der Elemente (Bilder, Beschreibung, Preistabelle) auch Tabellen in unserer aktuellen Vorlage verwendet, daher konnte ich den Weg nicht gehen.

Wir haben das ganze jetzt so im Betrieb und es funktioniert. Allerdings nicht wesentlich schneller als vorher mit dem Neuöffnen der Vorlagen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:58 Uhr.

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