После некоторых экспериментов я получил следующий код для выполнения поиска и замены в MSWord. Этот код отлично работает также в верхнем и нижнем колонтитулах, включая случаи, когда верхний и нижний колонтитулы отличаются для первой страницы или нечетных/четных страниц.
Проблема заключается в том, что мне нужно вызвать MSWordSearchAndReplaceInAllDocumentParts
для каждой строки, которую я заменяю, и я получаю неприемлемую производительность (2 минуты для примерно 50 строк в 4-страничном слове doc). В идеале это должно быть "мгновенно", конечно.
Перед обработкой верхних и нижних колонтитулов я просто выполнял поиск и замену в основном документе (используя wdSeekMainDocument). В этом случае перфмант был приемлемым (хотя и довольно медленным). Я просто удивляюсь, почему это так медленно: время переключения переключается? Обычно верхние и нижние колонтитулы содержат несколько слов, поэтому я ожидал, что все "Поиск и замена" в верхних и нижних колонтитулах не ухудшают общую производительность. Но это не то, что я наблюдал.
Это код, внизу я поставил результаты профилировщика:
// global variable (just for convenience of posting to Stack Overflow)
var
aWordApp: OLEVariant; // global
// This is the function that is executed once per every string I replace
function MSWordSearchAndReplaceInAllDocumentParts;
begin
try
iseekValue := aWordApp.ActiveWindow.ActivePane.View.SeekView;
iViewType := aWordApp.ActiveWindow.ActivePane.View.Type;
if iViewType <> wdPrintView then
aWordApp.ActiveWindow.ActivePane.View.Type := wdPrintView;
if aWordApp.ActiveDocument.PageSetup.OddAndEvenPagesHeaderFooter then
begin
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekEvenPagesFooter;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekEvenPagesHeader;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
end;
if aWordApp.ActiveDocument.PageSetup.DifferentFirstPageHeaderFooter then
begin
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekFirstPageFooter;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekFirstPageHeader;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
end;
//Replace in Main Docpart
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekMainDocument;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
//Replace in Header
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekCurrentPageHeader;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
//Replace in Footer
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekCurrentPageFooter;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
//Replace in Header
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekPrimaryHeader;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
//Replace in Footer
Try
aWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekPrimaryFooter;
SearchAndReplaceInADocumentPart;
Except
// do nothing ..it was not able to set above view
end;
finally
aWordApp.ActiveWindow.ActivePane.View.SeekView := iseekValue;
if iViewType <> wdPrintView then
aWordApp.ActiveWindow.ActivePane.View.Type := iViewType;
end;
end;
// This is the function that performs Search And Replace in the selected View
// it is called once per view
function SearchAndReplaceInADocumentPart;
begin
aWordApp.Selection.Find.ClearFormatting;
aWordApp.Selection.Find.Text := aSearchString;
aWordApp.Selection.Find.Replacement.Text := aReplaceString;
aWordApp.Selection.Find.Forward := True;
aWordApp.Selection.Find.MatchAllWordForms := False;
aWordApp.Selection.Find.MatchCase := True;
aWordApp.Selection.Find.MatchWildcards := False;
aWordApp.Selection.Find.MatchSoundsLike := False;
aWordApp.Selection.Find.MatchWholeWord := False;
aWordApp.Selection.Find.MatchFuzzy := False;
aWordApp.Selection.Find.Wrap := wdFindContinue;
aWordApp.Selection.Find.Format := False;
{ Perform the search}
aWordApp.Selection.Find.Execute(Replace := wdReplaceAll);
end;
Здесь я вставлю профилирующие результаты (у меня есть aqtime pro):
Не могли бы вы помочь мне в выявлении проблемы?