Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Word Zugriff per Ole -- zunehmend langsamer (https://www.delphipraxis.net/90839-word-zugriff-per-ole-zunehmend-langsamer.html)

stifflersmom 24. Apr 2007 17:24


Word Zugriff per Ole -- zunehmend langsamer
 
Hallo,

ich habe mir gerade als aktuelles projekt vorgenommen,
eine lokale Datenbank zu erstellen, die sämtliche in einem
(natürlich auch mehrere) Worddokument vorkommenen Wörter aufnimmt,
damit man anschließend über eine Wortsuche schneller die betreffenden
Dokumente aufgelistet bekommt, als es z.B. die bordeigene Suche von
Windows schafft.
Nun aber zu meinem "Problem":
Ich verbinde mich mit einem Worddokument und gehe dann alle
Wörter in dem Dokument durch um diese dann später mal zu verarbeiten,
allerdings ist es so, dass die Verarbeitungsgeschwindigkeit der
Wörter zunehemnd abnimmt, je weiter sich die Routine dem Dokumentende
nähert.
Hier mal mein bisheriger "Versuchscode":
Delphi-Quellcode:
procedure TForm1.bt_OpenWordDocClick(Sender: TObject);
Var
V             :OleVariant;
Docs, ItemIndex: OleVariant;
ConFirmConversions,
OpenReadOnly  :OleVariant;
LinesCount    : Integer;
Zl            : TStringList;

begin
If OpenDialog1.execute Then
 Begin
 Screen.Cursor      := crHourGlass;
 Zl                 := TStringList.Create;
 
 If CheckBox2.Checked Then
 Zl.Sorted          := True;
 
 If Not CheckBox1.Checked Then
 Zl.Duplicates      := dupIgnore;
 
 Memo1.Lines.Clear;
 EditDocFile.Text   := OpenDialog1.FileName;
 ProgressBar1.Visible:= True;
 
  try
    ItemIndex := 1;
    try
      Wordapplication.Visible := False;
      Wordapplication.Connect;
    except
      MessageDlg('Word ist nicht auf diesem Rechner installiert', mtError, [mbOk], 0);
      Abort;
    end;

      Docs             := (EditDocFile.Text);
      ConFirmConversions:= False;
      OpenReadOnly     := True;

      WordApplication.Documents.Open(Docs,ConFirmConversions,OpenReadOnly,EmptyParam,
      EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,
      EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam);

      WordDocument.ConnectTo(WordApplication.Documents.Item(ItemIndex));
      ProgressBar1.Max := WordDocument.Words.Count;

    // Alle Wörter durchgehen  
    For LinesCount := 1 To WordDocument.Words.Count Do
     Begin
     ProgressBar1.Position := LinesCount;
     V:=WordDocument.Words.Item(LinesCount).Text;
     V:= trim(V);
     If Length(V) > 1 Then
     Zl.Add(V);
     End;
  except
    on E: Exception do
    begin
      ShowMessage(E.Message);
      WordApplication.Disconnect;
    end;
   
  end;
   ProgressBar1.Visible := False;
//   WordApplication.Disconnect;
   Memo1.Lines.Assign(Zl);
   Zl.Free;
   Screen.Cursor:= crDefault;
 end;
end;
Jetzt also die Gretchenfrage, ist mein Vorhaben so überhaupt sinnvoll realisierbar,
oder ist der Zugriff per Ole 'n schlechter Ansatz?
Ich bin für alle Vorschläge offen.

Moin

Bernhard Geyer 24. Apr 2007 20:14

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Wie viel Worde sind denn Aufgenommen?
Ich tipp viel mehr darauf das die Option dupIgnore die Stringlist bei >> 1000 Einträgen sehr langsam macht. AFAIK ist da nicht gerade der schnellste Algorithmus implementiert.

CCRDude 24. Apr 2007 20:31

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Wenns eine Stringliste sein muss - THashedStringList aus der unit IniFiles dürfte etwas zügiger funktionieren. Allerdings ist eine Stringlist an sich keine besonders performante Lösung... denk vielleicht alternativ mal lieber über einen Baum nach.

stifflersmom 25. Apr 2007 06:57

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Zitat:

Zitat von Bernhard Geyer
Wie viel Worde sind denn Aufgenommen?
Ich tipp viel mehr darauf das die Option dupIgnore die Stringlist bei >> 1000 Einträgen sehr langsam macht.

Nö, ob mit oder ohne, das ist spürbar kein Unterschied

Zitat:

Zitat von Bernhard Geyer
AFAIK ist da nicht gerade der schnellste Algorithmus implementiert.

Wie gesagt, ich bin für alle Hinweise offen, (wink mit dem Zaunpfahl)

Moin

stifflersmom 25. Apr 2007 06:59

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Zitat:

Zitat von CCRDude
Wenns eine Stringliste sein muss - THashedStringList aus der unit IniFiles dürfte etwas zügiger funktionieren. Allerdings ist eine Stringlist an sich keine besonders performante Lösung... denk vielleicht alternativ mal lieber über einen Baum nach.

Stringlist war erst mal nur der erste Versuchsansatz, die übernommenen Wörter irgendwo hinzuschieben, obwohl die Option mit den Duplikaten schon recht bequem ist.
Hmmm, Baum, da bin ich leicht überfordert, hättest Du mal einen Ansatz bzw. ein wenig Code für mich?

Moin

Jens Schumann 25. Apr 2007 07:19

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Hallo,
wenn mich meine Erinnerung nicht täuscht werden hier min 1 oder 2 Interfaces (bei jedem Aufruf innerhalb
der Schleife) angefordert.
Delphi-Quellcode:
WordDocument.Words.Item(LinesCount).Text;
Versuch mal das Interface auf WordDocument.Words oder wenn es geht auf WordDocument.Words.Item vor
dem Aufruf der Schleife zu holen. So dass innerhalb der Schleife nur noch
Delphi-Quellcode:
    For LinesCount := 1 To WordDocument.Words.Count Do
     Begin
     ProgressBar1.Position := LinesCount;
     V:=Item(LinesCount).Text;
steht


Vor einigen Jahren habe ich malen gelesen, dass das wiederholte Anfordern von Interfaces Resourcen verbraucht.

stifflersmom 25. Apr 2007 08:13

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Hmmm, finde ich nicht wirklich performanter
Delphi-Quellcode:
    // Alle Wörter durchgehen  
    MyWords := WordDocument.Words;
    For LinesCount := 1 To MyWords.Count Do
     Begin
     ProgressBar1.Position := LinesCount;
     V:=MyWords.Item(LinesCount).Text;
     V:= trim(V);
     If Length(V) > 1 Then
     Zl.Add(V);

Bernhard Geyer 25. Apr 2007 08:20

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Kannst du ein paar € ausgeben? Falls ja: Mit AutomatedQA hätte man das Problem in 1-2 Minuten gefunden indem man einfach ein Line-Profiling auf diese Funktion durchführt.

stifflersmom 25. Apr 2007 11:06

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Ich lade gerade mal eine Trial-Version herunter, vielleicht kann ich mit der ja genaueres erfahren.

Moin

stifflersmom 25. Apr 2007 11:07

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Zitat:

Zitat von CCRDude
Wenns eine Stringliste sein muss - THashedStringList aus der unit IniFiles dürfte etwas zügiger funktionieren. Allerdings ist eine Stringlist an sich keine besonders performante Lösung... denk vielleicht alternativ mal lieber über einen Baum nach.

Nö, bringt (leider) nicht wirklich was.
Ich weis auch momentan noch nicht, ob nicht die Übergabegeschwindigkeit von Word der wahre Pferdefuß ist.

Moin

Bernhard Geyer 25. Apr 2007 11:28

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Zitat:

Zitat von stifflersmom
Ich weis auch momentan noch nicht, ob nicht die Übergabegeschwindigkeit von Word der wahre Pferdefuß ist.

Hier bringt es was statt späte Bindung mit OleVariant frühe Bindung über die Typbibliothek zu verwenden. Auch war es bei älteren Windows-Versionen so das späte Bindung nur eine bestimmte Anzahl von Aufrufen verkraftet hat.

stifflersmom 25. Apr 2007 12:18

Re: Word Zugriff per Ole -- zunehmend langsamer
 
Zitat:

Hier bringt es was statt späte Bindung mit OleVariant frühe Bindung über die Typbibliothek zu verwenden. Auch war es bei älteren Windows-Versionen so das späte Bindung nur eine bestimmte Anzahl von Aufrufen verkraftet hat.
ok, das werde ich mal ausprobieren, mal sehen, ob ich das auf die Schnelle umgesetzt bekomme.

Moin

stifflersmom 25. Apr 2007 14:42

Re: Word Zugriff per Ole -- zunehmend langsamer
 
So, nun bin ich's leid.
Der "wortweise" Zugriff ist irgendwie nicht der richtige Weg.
Jetzt gehe ich einfach die Holzhammermethode:
Word aufrufen
Dokument als tmp. Textdatei speichern
Word-Dokument schließen

Anschließend die tmp. Textdatei laden und irgendwie verarbeiten.
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
StartDir := extractFilePath(ParamStr(0));
mV := CreateOleObject('Word.Application');
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
mV.Quit;

procedure TForm1.SpeedButton2Click(Sender: TObject);
var
  ZL,Zl2 : TStringList;
  I : Integer;
begin
   If OpenDialog1.Execute Then
    Begin
    ZL := TStringList.Create;
    Zl.Sorted := CheckBox2.Checked;
    If Not CheckBox1.Checked Then
    Zl.Duplicates      := dupIgnore;

    Zl2 := TStringList.Create;
    Zl2.Sorted := Zl.Sorted;
    Zl2.Duplicates := Zl.Duplicates;
     
     mV.Visible := False;                          // Das klappt nicht wirklich!
     mV.Documents.open (FileName:=OpenDialog1.FileName, ConfirmConversions:=False, Format:=wdOpenFormatAuto) ;
     mV.ActiveDocument.SaveAs (FileName:=StartDir+'TMPFB.TXT', FileFormat:=wdFormatText, AddToRecentFiles:=True) ;
     mV.Documents.Close;
     
     Memo1.Lines.LoadFromFile(StartDir+'TMPFB.TXT');       // Ab hier ist erst mal alles richtige Baustelle...
     Zl.DelimitedText:=Memo1.Lines.Text;
     DeleteFile(StartDir+'TMPFB.TXT');
     For I :=0 To zl.Count-1 Do
      Zl2.Add(Trim(Zl[i]));
     Memo1.Lines.Assign(ZL2);
     Zl.Free;
     Zl2.Free;
     End;
end;
Übrigens, hat jemand 'n Tipp für mich,
dass wenn ich mit einem Word-Dokument verbinde,
Word NICHT im Hintergrund angezeigt wird?

Moin


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:59 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