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

我有一个包含VBA应用程序的只读Excel工作簿。 应用程序保存需要保存在数据库中的任何数据,并且工作簿始终closures而不保存(通过在BeforeClose中设置ThisWorkbook.Saved = True)。

我有以下问题:

  • 用户双击Windows资源pipe理器中的工作簿,打开工作簿。

  • 用户在Windows资源pipe理器中的工作簿上再次双击。

  • Excel提示:“MyWorkbook.xls已经打开,重新打开会导致你所做的任何更改被丢弃,你想重新打开MyWorkbook.xls吗?

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

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

任何人都可以提出一个VBA的解决scheme。 这可能是:

  • 禁止提示重新打开工作簿。 而是静静地使用已经打开的实例。

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

更新:

这是Excel 2003。

我可以通过在Workbook_SheetChanged事件处理程序中设置“ThisWorkbook.Saved = True”来摆脱不需要的提示(VBA应用程序负责保存需要保存在数据库中的任何数据,所以我不在乎使用Excel保存更改)。

然而,这并没有解决我的问题:如果我这样做,然后在浏览器中双击工作簿静静地重新打开工作簿,但仍然没有调用“BeforeClose”事件处理程序。

所以要重述这个问题:

  • 反正用VBA来检测和拦截正在重新打开的工作簿吗?

更新2

接受BKimmel的答案 – 似乎没有VBA方法从工作簿中截取这个事件。

我要实现的解决scheme是将应用程序代码移动到XLA加载项中,该加载项在加载工作簿时自动加载(如果尚未加载)。 加载项可以处理Open和BeforeClose事件,并存储清理所需的信息。

男人…这似乎很容易,但它是一个艰难的。 我玩弄了每一个事件和应用程序/工作簿的财产,我可以想到在与Excel VBA工作7年的经验,我不能拿出任何优雅的东西…我认为简短的答案是这个问题并没有真正的简洁的解决scheme(如果有的话,我真的很想看到它)。 这是个坏消息。

好消息是,我认为有办法解决这个问题… 1是一个更高雅的方法,但是需要你重新思考你的一些方法,另外一个是肮脏的,但可能更简单一些。

更优雅的方式将涉及到重新思考和重构你的方法……我想我的工作从来没有遇到这个问题的原因是,在我的每个方法的结尾,工作簿被保持在“良好”状态或者换句话说,如果有“清理”的话,那么在每个方法的末尾都要完成。 如果在这里有巨大的开销性能,你可以考虑设置一个布尔标志,并限制它是否在每个其他方法的末尾运行。 (即runCleanup = ReturnTrueIfCleanupIsNeeded()If(runCleanup = true)Then CleanupMethod()End If)

更脏的方式将涉及使整个工作簿本身成为一种“特设互斥”
1)将WorkBookOpen事件中的整个( 原始 )Workbook复制到另一个temp )WorkBook中,并使用temp上的“SaveAs”方法将其放置在独立的位置。
2)存储( 原始 )path。
3)将代码添加到检查( temp )的WorkBook打开事件中,并且A)立即closures并激活temp或B)用( temp )覆盖自身,然后使用SaveAs
4)在用户保存工作簿并将其保存到原始位置和临时位置之前捕捉事件。
5)在WorkBookClose事件中,运行所需的任何清理并将temp保存回原始位置。

所有这一切的目的是为了避免当您打开工作簿两次时发生的“碰撞” – 实质上,当您第一次打开工作簿并将其保存在不同位置时,可能会创build一个临时工作簿(也许您甚至可以隐藏该文件?)确保当用户单击原始文件时,它不会与应用程序中已经处理的数据相冲突。 (当然,这有自己的问题/问题,如“如果我不知道用户有权访问什么path来保存临时文件”或“如果用户打开临时 XLS文件会怎么样…但是这就是为什么我把它叫做泥土路)“

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

感谢有趣的问题。

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

使用以下代码创build一个名为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 

然后在你的workbook_load事件上做类似的事情:

 Public controller as new ApplicationController Private Sub Workbook_Open() set controller.CApp = Excel.Application set controller.CurrentWB = ThisWorkbook End Sub 

现在,当excel打开一个新的工作簿,你将捕获事件并运行你的安全方法。 如果你愿意的话,你甚至可以阻止它重新打开工作簿。