- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
经过一些实验,我最终得到了以下代码来在 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):
您能帮我找出问题所在吗?
最佳答案
在我的机器上测试时,我没有看到如此糟糕的性能,但是仍然有方法可以提高性能。
最大的改进是在调用 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/
我正在尝试使用 SAP ABAP OLE OBJECT 打开受密码保护的 excel 文件,如下所示: DATA: lt_excel_line(4096) OCCURS 10 WITH HEADER
我目前正在实现一个 IOleObject 接口(interface),以将我们软件的可视化数据嵌入到其他软件(如 PowerPoint)中。我们的软件创建测量数据的图形评估(图表等)。 目标是,最终用
我对此很陌生。我正在尝试将 355 行传输到目的地 我有 3 列要转移 Customer_Number、Crime_Type、Action_Date。 当我创建源表时都是nvarchar(50) 目标
我有一个包含 2 个组件的数据流任务: 属于 SELECT 查询的 OLEDB 数据源任务: SELECT ACCOUNTID FROM JOBS WHERE STATUS=3 OLE DB 命令任务
我有一个包含 2 个组件的数据流任务: 属于 SELECT 查询的 OLEDB 数据源任务: SELECT ACCOUNTID FROM JOBS WHERE STATUS=3 OLE DB 命令任务
我有一个自定义数据库,我想为其编写一个 OLE DB 提供程序,但我希望用 C# 来完成。 我找到了这两个站点,但所有示例都在 C 中。 http://msdn.microsoft.com/en-us
我正在运行以下代码 /*Fetchinch Last CustID from custMaster*/ int ID = 0; try { con.Open(); da = new
我使用 oledb 提供程序(SQLOLEDB 和 SQL Native OLEDB 提供程序)创建了一个示例应用程序。 案例 1:提供者 = SQLOLEDB hr = ::CoInitialize
我花了几个小时试图解决这个问题。对于给我带来问题的列,我在 sql server 中使用标量函数来获取名称。该功能是正确的并且工作正常。然后我使用一个存储过程与 ssis 一起使用。给我错误的列指出它
我的源是 TXT 平面文件源,目标是 OLE DB 类型。 (见图) 我发现了一个非常basic tutorial on Code Project创建一个包。我完成了这些步骤,但是在调试时出现了一个奇
我正在对SQL Server数据库使用OLE DB批量复制操作,但是在将数据加载到bit列时遇到了麻烦-它们总是填充有true! 我根据下面的代码段从simple reproduction progr
我目前生活在 90 年代,我收到了这段遗留代码。我对 COM/OLE/MFC/ATL 不了解,所以我问这个问题,希望当时有经验的人可以帮助我找出这个问题。 我拥有的是这个非常古老/遗留的 MFC/AT
我使用 WTL 创建了一个 Dialog,继承自 CDialogImpl 类,在主对话框中我创建了另一个对话框,并在第二个子对话框中创建了一个列表控件。我想向列表控件添加拖放功能,我在网上阅读了有关
我使用 WinAPI 函数在 C# 中创建 OLE 文件。 WinAPI 函数是: [DllImport("ole32.dll")] public static extern int O
我正在尝试调整图像大小以在我的 OLED 设备上显示。 我想要显示的图像是: 目前,我的 OLED 显示屏仅显示图像的一小部分: 基于How to resize image? ,我在脚本中添加了 ne
如何在 128x64 OLED 显示屏上滚动长文本 我正在使用 Adafruit_SSD1306 驱动程序 此代码仅显示“This”,因为文本太大而无法显示,但是当我滚动文本时,仅“This”滚动而不
我无法解决这些术语之间的差异。 是COM和ActiveX同义词吗? ActiveX对象仅仅是公开IDispatch的COM对象吗? 许多较旧的MSDN页面提到IDispatch时没有任何COM上下文。
我们在 Delphi 7 中使用一些 OLE 自动化来打开一个 word 文档,然后在加载后保存它,并将其加载到数据库中。 这工作正常,但部分要求是在 OLE 位发生时有一个进度条,如果 OLE 部分
在我当前使用的产品中,Excel 电子表格是使用 Delphi 的 OLE 生成的。电子表格包含许多日期,应用程序从系统设置加载短日期格式并将其应用到单元格。除非系统格式至少设置为俄语、巴什基尔语、鞑
这个 c++ question 的语法是什么?在德尔福? 使用 oleContainer 后,并尝试执行 SaveDocumentAs 但不起作用。我认为这可能是一个不错的选择。 更新:感谢您的翻译,
我是一名优秀的程序员,十分优秀!