Improve performance of Search Replace in Word document using OLE and Delphi

后端 未结 1 1294
梦谈多话
梦谈多话 2021-01-11 16:04

After some experiments I ended up with the following code to perform Search and Replace in MSWord. This code works perfectly also in header and footer, including the cases i

1条回答
  •  隐瞒了意图╮
    2021-01-11 17:07

    I didn't see such terrible performance when testing on my machine, but still, there are ways to improve performance.

    Biggest improvement is setting the aWordApp.ActiveWindow.Visible to False before calling MSWordSearchAndReplaceInAllDocumentParts.

    Second improvement is setting aWordApp.ScreenUpdating to False.

    When you are calling MSWordSearchAndReplaceInAllDocumentParts multiple times in a row, apply above settings once. Also, set ActiveWindow.ActivePane.View.Type to wdPrintView before calling MSWordSearchAndReplaceInAllDocumentParts multiple times.

    Edit:

    I got another improvement by changing the way you de find/replace: Instead of changing the SeekView, iterate through all the sections and get the range of the document, headers and footers yourself and do a Find/Replace over those ranges.

    procedure TForm1.MSWordSearchAndReplaceInAllDocumentParts(const aDoc: OleVariant);
    var
      i: Integer;
      lSection: OleVariant;
      lHeaders: OleVariant;
      lFooters: OleVariant;
      lSections: OleVariant;
    begin
      lSections := aDoc.Sections;
      for i := 1 to lSections.Count do
      begin
        lSection := lSections.Item(i);
        lHeaders := lSection.Headers;
        lFooters := lSection.Footers;
        if lSection.PageSetup.OddAndEvenPagesHeaderFooter then
        begin
          SearchAndReplaceInADocumentPart(lHeaders.Item(wdHeaderFooterEvenPages).Range);
          SearchAndReplaceInADocumentPart(lFooters.Item(wdHeaderFooterEvenPages).Range);
        end;
        if lSection.PageSetup.DifferentFirstPageHeaderFooter then
        begin
          SearchAndReplaceInADocumentPart(lHeaders.Item(wdHeaderFooterFirstPage).Range);
          SearchAndReplaceInADocumentPart(lFooters.Item(wdHeaderFooterFirstPage).Range);
        end;
        SearchAndReplaceInADocumentPart(lHeaders.Item(wdHeaderFooterPrimary).Range);
        SearchAndReplaceInADocumentPart(lFooters.Item(wdHeaderFooterPrimary).Range);
    
        SearchAndReplaceInADocumentPart(lSection.Range);
      end;
    end;
    
    procedure TForm1.SearchAndReplaceInADocumentPart(const aRange: OleVariant);
    begin
      aRange.Find.ClearFormatting;
      aRange.Find.Text := aSearchString;
      aRange.Find.Replacement.Text := aReplaceString;
      aRange.Find.Forward := True;
      aRange.Find.MatchAllWordForms := False;
      aRange.Find.MatchCase := True;
      aRange.Find.MatchWildcards := False;
      aRange.Find.MatchSoundsLike := False;
      aRange.Find.MatchWholeWord := False;
      aRange.Find.MatchFuzzy := False;
      aRange.Find.Wrap := wdFindContinue;
      aRange.Find.Format := False;
    
      { Perform the search}
      aRange.Find.Execute(Replace := wdReplaceAll);
    end;
    

    You will see even a bigger improvement if you open the document you want to modify while the application is invisible, or if you open the document with Visible := False; (setting the application visible again will also set the document visible).

    0 讨论(0)
提交回复
热议问题