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
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).