После некоторых экспериментов я получил следующий код для выполнения поиска и замены в MSWord. Этот код отлично работает также в верхнем и нижнем колонтитулах, включая случаи, когда верхний и/или нижний колонтитулы различаются для первой страницы или нечетных/четных страниц.
Проблема в том, что мне нужно вызывать MSWordSearchAndReplaceInAllDocumentParts
для каждой заменяемой строки, и я получаю неприемлемую производительность (2 минуты для примерно 50 строк в 4-страничном документе). В идеале это должно быть "мгновенно", конечно.
Прежде чем обрабатывать верхние и нижние колонтитулы, я просто выполнял поиск и замену в основном документе (используя 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):
Можете ли вы помочь мне определить проблему?