自动保存如何影响外接程序和宏

了解自动保存在 Excel、 PowerPoint 和 Word 中的工作方式,以及它会对外接程序或宏产生怎样的影响。

自动保存概述

当文件托管在云中 (即 OneDrive、OneDrive for Business 或 SharePoint Online)时,自动保存使用户所做的编辑能自动连续地得到保存。 当文件与其他人共享时,他们所做的更改会合并到该用户的文件版本中。 如果关闭了自动保存,则必须手动触发保存才能使用户所做的更改保留在云中,并使此用户能收到其他人所做的更改。

目前,Excel、Word 和 PowerPoint 提供 BeforeSave 事件,该事件允许开发人员在用户触发保存之后(但在保存发生之前)执行代码。 Excel 还提供了 AfterSave 事件,该事件可在保存完成后执行宏或外接程序代码。

启用自动保存后,这些事件会自动定期触发,无需用户交互。 因此,如果启用了自动保存,利用这些事件的外接程序和宏可能会遇到问题。

通常,如果用户选择禁用自动保存,则可避免这些问题。 你可以在可用的情况下使用 WordExcelPowerPoint 中的 AutoSaveOn 属性代表用户执行此操作(请参阅下面的示例)。 作为开发人员,你也可以执行一些步骤来减轻这些问题,以便外接程序和宏能顺畅工作,即使启用了自动保存。

示例

此示例关闭自动保存,并通知用户工作簿未自动保存。

Sub UseAutoSaveOn()
    ActiveWorkbook.AutoSaveOn = False
    MsgBox "This workbook is being saved automatically: " & ActiveWorkbook.AutoSaveOn
End Sub

保存事件和自动保存的潜在问题

你可能需要以处理以下一个或多个与保存事件和自动保存之间的交互相关的问题:

  1. BeforeSaveAfterSave 事件中的代码运行时间太长
  2. 保存事件的代码显示模式对话框
  3. 保存事件中的代码清除撤消堆栈(仅限 Excel)
  4. AfterSave 中的代码更新工作簿(仅限 Excel)
  5. BeforeSave 中的代码取消文件保存(通过将 Cancel 参数设置为 True)

问题 1:BeforeSave 或 AfterSave 事件中的代码运行时间太长

通常,当外接程序或宏代码正在运行时,Word、Excel 和 PowerPoint 无法响应用户交互。 因此,如果 BeforeSaveAfterSave 事件处理程序中的代码运行时间太长,则可能会显著降低用户体验。

如果禁用了自动保存,此代码只会在用户显式选择保存时运行,因此延迟不太明显,并且用户在准备保存之前可以避开该延迟。

如果启用了自动保存,此代码会自动定期运行,从而可能会打断用户,特别是在代码长时间运行的情况下。

示例应用场景

假设有一个外接程序,该外接程序允许基于 Excel 工作簿中的数据创建自定义地图。 此类外接程序可能有 BeforeSave 代码,该代码对用户创建的任何地图进行序列化,并将它们存储在工作簿的 CustomXML 部分中。 此过程可能需要一秒时间完成,并且 Excel 在此过程中可能会无响应。

如果关闭了自动保存,用户可选择何时想要保存,因此,即使外接程序轻微减慢了保存过程,用户也不会注意到。

如果启用了自动保存,即使用户正在执行其他操作(例如在单元格中键入数据),BeforeSave 代码也会自动定期运行,这可能会非常令人讨厌。

解决方法

外接程序应尝试避免在保存事件内执行长时间运行的操作。 在此示例中,开发人员可以选择在用户创建或修改自定义地图时将地图保存到文件,而不是等待保存事件。

问题 2:保存事件的代码显示模式对话框

如果启用自动保存,保存事件中运行的显示 UI(例如模式对话框)的代码可能会严重降低用户体验。 由于 BeforeSaveAfterSave 事件自动定期运行,因此这些对话框可能会中断用户的正常工作流。

示例应用场景

一个在保存之前验证 Word 文档以确保公司品牌得以应用的外接程序可能会触发对话框,提醒用户发现的任何问题,并提供解决问题的方法。 由于 BeforeSave 事件现在会自动连续触发,因此该验证对话框可能会在用户执行其他操作时突然出现。

解决办法

请考虑删除需要在应用程序的其他区域显示 UI 的任何代码。 例如,用户可以选择“验证”按钮来触发验证过程,或者你可以仅在用户尝试更改现有数据时触发验证代码。

如果希望验证代码仅在第一次从新文档保存时触发,而不在后续自动保存时触发,请考虑在 BeforeSaveAfterSave 期间显示任何 UI 之前检查属性(例如 Excel 的 Workbook.Path)。 在 Excel 中,如果工作簿还没有保存位置,Workbook.Path 属性应该为空白。

问题 3:保存事件中的代码清除撤消堆栈(仅限 Excel)

通常,如果你在 Excel 中运行某些 VBA 语句,撤消堆栈将被清除。 例如,如果通过运行 ActiveCell.Value = "myValue" 来更改单元格值,则会清除撤消堆栈。 如果宏或外接程序的 BeforeSaveAfterSave 事件中存在此类代码,并且启用了自动保存,则该宏或外接程序的用户会经常无法按预期撤消正常用户操作。

示例应用场景

一个外接程序可能有会运行来响应 BeforeSave 事件的代码,该代码检查文档,并将值写入工作簿中的“日志”表。 如果启用了自动保存,这将会定期清除撤消堆栈,从而可能惹恼用户。

解决方法

请考虑删除在 BeforeSaveAfterSave 事件中写入工作簿的代码。 例如,可以对示例应用场景中描述的外接程序进行修改,以便将更改日志存储在单独的文件或数据库中。

问题 4:AfterSave 中的代码更新工作簿(仅限 Excel)

如果启用了自动保存,则只有在自上次触发以来工作簿中存在更改的情况下,BeforeSaveAfterSave 事件才会触发。 如果 AfterSave 事件中的代码更新了工作簿(也就是说,进行了其他更改),则该操作可能会再次为同一更改触发事件,然后再将事件排队,从而无限再次触发。 这可能会浪费系统资源并影响电池续航时间。

解决方法

应将 AfterSave 中会更新工作簿的代码完全转移到 BeforeSave 或另一个位置(请参阅问题 3)。 即使没有自动保存,目前这也不是一个好的做法,因为它会使工作簿保持永久的“更新”状态,从而导致在关闭时出现要求用户保存更改的提示,即使用户未进行任何其他更改。 

问题 5:BeforeSave 中的代码取消文件保存(通过将 Cancel 参数设置为 True)

目前,可以通过将 Cancel 设置为 True 在 BeforeSave 事件中取消保存:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) 
    Cancel = True
End Sub

如果启用了自动保存,应用程序(即 Excel、Word 或 PowerPoint)会连续自动触发保存,直至文件中没有其他未保存的更改为止。 用户对文件进行单次更改后,应用程序会尝试保存更改。

如果开发人员选择按上文所述方式取消保存,应用程序会不断确定存在未保存的更改,从而会导致(最终)再次尝试保存。 由于取消第一次保存的同一事件也会取消第二次保存尝试,因此该过程将在文件打开期间持续进行,从而可能会降低性能和缩短电池续航时间。

示例应用场景

一个外接程序可能完全重写了默认 Word 保存代码,以便将文件保存到公司数据库,而不是磁盘或 SharePoint 位置。 此类外接程序将首先取消尝试进行的保存,然后再尝试在另一个位置中保存。

解决方法

此类外接程序应确保通过将 AutoSaveOn 设置为 False 来禁用自动保存。 由于文件必须已保存在 OneDrive 或 SharePoint 位置中才能启用自动保存,因此在大多数这种应用场景中,自动保存应已经关闭或禁用。

另请参阅

支持和反馈

有关于 Office VBA 或本文档的疑问或反馈? 请参阅 Office VBA 支持和反馈,获取有关如何接收支持和提供反馈的指南。