如何停止Excel提示重新打开工作簿?

如何停止Excel提示重新打开工作簿?,excel,vba,Excel,Vba,我有一个包含VBA应用程序的只读Excel工作簿。应用程序会将需要保存的任何数据保存到数据库中,并且工作簿总是在不保存的情况下关闭(通过在BeforeClose中设置ThisWorkbook.saved=True) 我有以下问题: 用户在Windows资源管理器中双击工作簿,工作簿将打开 用户在Windows资源管理器中再次双击工作簿 Excel提示:“MyWorkbook.xls已打开。重新打开将导致放弃您所做的任何更改。是否要重新打开MyWorkbook.xls?” 如果用户单击“是”,工

我有一个包含VBA应用程序的只读Excel工作簿。应用程序会将需要保存的任何数据保存到数据库中,并且工作簿总是在不保存的情况下关闭(通过在BeforeClose中设置ThisWorkbook.saved=True)

我有以下问题:

  • 用户在Windows资源管理器中双击工作簿,工作簿将打开

  • 用户在Windows资源管理器中再次双击工作簿

  • Excel提示:“MyWorkbook.xls已打开。重新打开将导致放弃您所做的任何更改。是否要重新打开MyWorkbook.xls?”

  • 如果用户单击“是”,工作簿将重新打开,而不执行已打开实例的BeforeClose事件处理程序

这在我的应用程序中是一个问题,因为这意味着BeforeClose事件处理程序中的某些重要清理代码无法执行

有谁能为这个问题提出VBA解决方案吗。这可能是:

  • 取消显示重新打开工作簿的提示。而是静默地使用已经打开的实例

  • 在原始实例关闭之前,以某种方式让BeforeClose或其他事件处理程序在其中运行,以便我可以运行清理代码

更新:

这是Excel2003

我可以通过在Workbook\u SheetChanged事件处理程序中设置“ThisWorkbook.Saved=True”来消除不必要的提示(VBA应用程序负责保存需要保存在数据库中的任何数据,因此我不关心Excel保存更改)

但是,这并不能解决我的问题:如果我这样做了,那么在资源管理器中双击工作簿将以静默方式重新打开工作簿,但仍然可以这样做,而无需通过“BeforeClose”事件处理程序调用

因此,重新表述这个问题:

  • 是否使用VBA检测并拦截以这种方式重新打开的工作簿
更新2

接受BKimmel的回答-似乎没有VBA方法从工作簿中截获此事件


< >我将实施的解决方案是将应用程序代码移动到XLA外接程序中,加载工作簿时,该代码将自动加载(如果尚未加载)。外接程序可以处理“打开”和“关闭前”事件,并存储进行清理所需的信息。

当工作簿重新打开时,您可以使用一些特殊的应用程序事件来处理,并手动触发工作簿关闭代码:

使用以下代码创建名为ApplicationController的类模块:

Public WithEvents CApp As Application
Public CurrentWB as Workbook

Private Sub CApp_WorkbookOpen(ByVal wb As Excel.Workbook)


Dim sPathName As String
sPathName = wb.Name
if sPathName = CurrentWB.Name then CallSomeMethod()

End Sub
然后在工作簿加载事件上执行以下操作:

Public controller as new ApplicationController
Private Sub Workbook_Open()
set controller.CApp = Excel.Application
set controller.CurrentWB = ThisWorkbook
End Sub
现在,当excel打开新工作簿时,您将捕获事件并运行安全方法。如果你愿意,你甚至可以阻止它重新打开工作簿。

伙计……这看起来很容易,但很难。我玩弄了7年左右使用Excel VBA的经验中所能想到的每一个事件和应用程序/工作簿属性,但我想不出任何优雅的东西。。。我认为简单的答案是,对于这个问题,并没有一个简单而优雅的解决方案(如果有,我真的很想看到)。这是个坏消息。

好消息是,我认为有一些方法可以解决这个问题……1有点优雅,但需要你重新思考一些方法,而另一个方法不好,但可能更简单。


更优雅的方法是重新思考和重构您的方法……我认为我在工作中从未遇到过这个问题的原因是,在我的每个方法结束时,工作簿都处于“良好”状态。。。或者换句话说,如果有“清理”要做,那么它是在每个方法的末尾完成的。如果在这个过程中出现了巨大的开销性能,您可以考虑设置布尔标志并限制它是否在每个其他方法的末尾运行。(即runCleanup=ReturnTrueIfCleanupIsNeeded()如果(runCleanup=true)那么CleanupMethod()结束如果)

更脏的方法是通过
1)将工作簿打开事件中的整个(原始)工作簿复制到另一个(temp)中,将整个工作簿本身变成一种“特殊互斥对象”使用temp上的“另存为”方法将其放置在单独的位置
2)存储(原始)路径
3)向工作簿打开事件添加代码,检查(temp)和A)立即关闭并激活temp或B)用(temp覆盖自身然后使用SaveAs
4)在用户保存工作簿之前捕获事件,并在WorkBookClose事件中将其保存到原始位置和临时位置,运行所需的任何清理操作,并将temp保存回其原始位置。

所有这一切的目的是避免两次打开工作簿时发生的“冲突”——基本上是,在第一次打开时创建temp工作簿并将其保存到其他位置(也许你甚至可以隐藏文件?)你要确保当用户单击原始文件时,它不会与他们在应用程序中已经使用的数据发生冲突。(当然,这也有自己的问题,比如“如果我不知道用户有权保存临时文件的路径怎么办”或“如果用户打开temp XLS文件会怎么样……但这就是为什么我称之为dirt way的原因)“

我知道这很重要,特别是如果您不习惯使用VBA;如果您希望我发布一些代码来帮助您完成这些步骤,请留下评论,我会的。

谢谢您提出的有趣问题。

您也可以通过以下方式抑制提示:

这将重新打开一个o
Application.DisplayAlerts = False
Workbooks.Open (sPath)
Application.DisplayAlerts = True