如何关闭Word字段自动更新?解决VSTO插件插入图片性能问题
问题
我开发了一个简单的Word VSTO插件,功能是从磁盘选择单张或多张图片插入当前文档,功能正常。但每次插入图片时,Word都会更新文档中所有字段,当文档里有上百张图片时,这个操作耗时极长。我需要在插入图片期间关闭字段自动更新,完成后再重新开启。
我尝试了以下方法:
- 程序启动时添加代码:
Globals.ThisAddIn.Application.ActiveDocument.Fields.Locked = True
- 程序结束时添加代码:
Globals.ThisAddIn.Application.ActiveDocument.Fields.Locked = False Globals.ThisAddIn.Application.ActiveDocument.Fields.Update()
但每次插入图片时,Word仍会更新所有字段。有没有其他方法能实现需求?
编辑:插入图片的完整代码
Sub ImportPictures() Dim strPics As String = String.Empty Dim arrPics() As String Dim i As Long Dim vrtSelectedItem As Object = Nothing Dim tek As Microsoft.Office.Interop.Word.InlineShape = Nothing Dim picName As String = String.Empty Globals.ThisAddIn.Application.ActiveDocument.Fields.Locked = True '打开文件浏览器让用户选择图片 Try Using OpenFileDialog1 As New OpenFileDialog() OpenFileDialog1.InitialDirectory = "c:\\" OpenFileDialog1.Filter = "图片文件 (*.gif;*.jpg;*.jpeg;*.png;*.bmp)|*.gif;*.jpg;*.jpeg;*.png;*.bmp" OpenFileDialog1.FilterIndex = 1 OpenFileDialog1.RestoreDirectory = True OpenFileDialog1.Multiselect = True If OpenFileDialog1.ShowDialog() = DialogResult.OK Then For Each vrtSelectedItem In OpenFileDialog1.FileNames strPics = strPics & "|" & vrtSelectedItem Next vrtSelectedItem strPics = Mid(strPics, 2) arrPics = Split(strPics, "|") System.Array.Sort(arrPics) For i = 0 To UBound(arrPics) picName = Right(arrPics(i), Len(arrPics(i)) - InStrRev(arrPics(i), "\\")) tek.LockAspectRatio = True tek.ScaleHeight = 32.3 tek.Select() Globals.ThisAddIn.Application.ActiveDocument.Paragraphs.Format.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter Globals.ThisAddIn.Application.Selection.InsertCaption(Label:="Figure", Title:=": " & picName, Position:=word.WdCaptionPosition.wdCaptionPositionBelow) Globals.ThisAddIn.Application.Selection.Collapse(word.WdCollapseDirection.wdCollapseEnd) Globals.ThisAddIn.Application.Selection.TypeParagraph() Next i Else MsgBox("用户取消了选择。") End If End Using Globals.ThisAddIn.Application.ActiveDocument.Fields.Locked = False Globals.ThisAddIn.Application.ActiveDocument.Fields.Update() Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.SystemModal, "错误") End Try End Sub
解决方案
只锁定字段Fields.Locked不足以阻止Word的自动更新,尤其是插入题注(InsertCaption)这类操作会触发编号更新。可以通过以下组合方法解决:
1. 禁用Word全局自动更新选项
插入图片前修改应用程序级的自动更新设置,操作完成后恢复:
' 保存原有设置 Dim originalUpdateFields As Boolean = Globals.ThisAddIn.Application.Options.UpdateFieldsAtPrint Dim originalUpdateLinks As Boolean = Globals.ThisAddIn.Application.Options.UpdateLinksAtPrint ' 关闭自动更新 Globals.ThisAddIn.Application.Options.UpdateFieldsAtPrint = False Globals.ThisAddIn.Application.Options.UpdateLinksAtPrint = False
操作结束后恢复:
' 恢复原有设置 Globals.ThisAddIn.Application.Options.UpdateFieldsAtPrint = originalUpdateFields Globals.ThisAddIn.Application.Options.UpdateLinksAtPrint = originalUpdateLinks
2. 暂停屏幕更新减少开销
同时暂停Word的屏幕刷新,避免频繁界面重绘拖慢速度:
' 暂停屏幕更新 Globals.ThisAddIn.Application.ScreenUpdating = False
完成后恢复:
' 恢复屏幕更新 Globals.ThisAddIn.Application.ScreenUpdating = True
3. 修改题注插入逻辑
InsertCaption是触发字段更新的核心原因之一,可先插入纯文本临时题注,所有图片插入完成后再统一处理自动编号:
' 替换自动题注为纯文本,避免实时更新 Globals.ThisAddIn.Application.Selection.TypeText("Figure " & (i+1) & ": " & picName)
完整修改后的代码示例
Sub ImportPictures() Dim strPics As String = String.Empty Dim arrPics() As String Dim i As Long Dim vrtSelectedItem As Object = Nothing Dim tek As Microsoft.Office.Interop.Word.InlineShape = Nothing Dim picName As String = String.Empty ' 保存原有设置 Dim originalUpdateFields As Boolean = Globals.ThisAddIn.Application.Options.UpdateFieldsAtPrint Dim originalUpdateLinks As Boolean = Globals.ThisAddIn.Application.Options.UpdateLinksAtPrint Dim originalScreenUpdating As Boolean = Globals.ThisAddIn.Application.ScreenUpdating Try ' 关闭自动更新与屏幕刷新 Globals.ThisAddIn.Application.Options.UpdateFieldsAtPrint = False Globals.ThisAddIn.Application.Options.UpdateLinksAtPrint = False Globals.ThisAddIn.Application.ScreenUpdating = False Globals.ThisAddIn.Application.ActiveDocument.Fields.Locked = True '打开文件浏览器让用户选择图片 Using OpenFileDialog1 As New OpenFileDialog() OpenFileDialog1.InitialDirectory = "c:\\" OpenFileDialog1.Filter = "图片文件 (*.gif;*.jpg;*.jpeg;*.png;*.bmp)|*.gif;*.jpg;*.jpeg;*.png;*.bmp" OpenFileDialog1.FilterIndex = 1 OpenFileDialog1.RestoreDirectory = True OpenFileDialog1.Multiselect = True If OpenFileDialog1.ShowDialog() = DialogResult.OK Then For Each vrtSelectedItem In OpenFileDialog1.FileNames strPics = strPics & "|" & vrtSelectedItem Next vrtSelectedItem strPics = Mid(strPics, 2) arrPics = Split(strPics, "|") System.Array.Sort(arrPics) For i = 0 To UBound(arrPics) ' 补充原始代码缺失的插入图片步骤 tek = Globals.ThisAddIn.Application.Selection.InlineShapes.AddPicture( _ FileName:=arrPics(i), _ LinkToFile:=False, _ SaveWithDocument:=True) picName = Right(arrPics(i), Len(arrPics(i)) - InStrRev(arrPics(i), "\\")) tek.LockAspectRatio = True tek.ScaleHeight = 32.3 tek.Select() Globals.ThisAddIn.Application.ActiveDocument.Paragraphs.Format.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter ' 插入临时文本题注,避免触发自动更新 Globals.ThisAddIn.Application.Selection.Collapse(word.WdCollapseDirection.wdCollapseEnd) Globals.ThisAddIn.Application.Selection.TypeParagraph() Globals.ThisAddIn.Application.Selection.TypeText("Figure " & (i+1) & ": " & picName) Globals.ThisAddIn.Application.Selection.Collapse(word.WdCollapseDirection.wdCollapseEnd) Globals.ThisAddIn.Application.Selection.TypeParagraph() Next i Else MsgBox("用户取消了选择。") End If End Using Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.SystemModal, "错误") Finally ' 恢复所有原有设置 Globals.ThisAddIn.Application.ActiveDocument.Fields.Locked = False Globals.ThisAddIn.Application.Options.UpdateFieldsAtPrint = originalUpdateFields Globals.ThisAddIn.Application.Options.UpdateLinksAtPrint = originalUpdateLinks Globals.ThisAddIn.Application.ScreenUpdating = originalScreenUpdating ' 手动更新所有字段(按需启用) Globals.ThisAddIn.Application.ActiveDocument.Fields.Update() End Try End Sub
注:原始代码缺失插入图片的核心步骤AddPicture,修改后的代码已补充该逻辑,否则tek对象会为空导致运行报错。
内容的提问来源于stack exchange,提问作者Perry 59
相关产品推荐
相关产品推荐

