gpt4 book ai didi

delphi - 使用 OLE 和 Delphi 提高 Word 文档中搜索替换的性能

转载 作者:行者123 更新时间:2023-12-03 14:40:26 24 4
gpt4 key购买 nike

经过一些实验,我最终得到了以下代码来在 MSWord 中执行搜索和替换。此代码在页眉和页脚中也能完美运行,包括首页或奇数/偶数页的页眉和/或页脚不同的情况。

问题是,我需要为替换的每个字符串调用 MSWordSearchAndReplaceInAllDocumentParts,并且性能令人无法接受(4 页文档单词中的大约 50 个字符串需要 2 分钟)。理想情况下,它当然应该是“瞬时”的。

在处理页眉和页脚之前,我只是在主文档中进行搜索和替换(使用 wdSeekMainDocument)。在这种情况下,性能是可以接受的(即使很慢)。我只是想知道为什么这么慢:切换 View 需要时间吗?通常,页眉或页脚包含很少的单词,因此我预计页眉和页脚中的所有搜索和替换不会使整体性能变得如此糟糕。但这不是我观察到的。

这是代码,在底部我放置了探查器结果:

// 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): enter image description here

您能帮我找出问题所在吗?

最佳答案

在我的机器上测试时,我没有看到如此糟糕的性能,但是仍然有方法可以提高性能。

最大的改进是在调用 MSWordSearchAndReplaceInAllDocumentParts 之前将 aWordApp.ActiveWindow.Visible 设置为 False

第二个改进是将 aWordApp.ScreenUpdating 设置为 False

当您连续多次调用 MSWordSearchAndReplaceInAllDocumentParts 时,请应用一次上述设置。另外,在多次调用 MSWordSearchAndReplaceInAllDocumentParts 之前,请将 ActiveWindow.ActivePane.View.Type 设置为 wdPrintView

编辑:

通过更改查找/替换的方式,我得到了另一项改进:无需更改 SeekView,而是迭代所有部分并自己获取文档、页眉和页脚的范围,然后在这些范围内执行查找/替换。

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;

如果在应用程序不可见时打开要修改的文档,或者使用 Visible := False; 打开文档,您将看到更大的改进。 (再次将应用程序设置为可见也会将文档设置为可见)。

关于delphi - 使用 OLE 和 Delphi 提高 Word 文档中搜索替换的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9520261/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com