代码之家  ›  专栏  ›  技术社区  ›  to StackOverflow

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

  •  7
  • to StackOverflow  · 技术社区  · 17 年前

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

    我有以下问题:

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

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

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

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

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

    有人能为此提出VBA解决方案吗。可能是:

    • 抑制重新打开工作簿的提示。而是默默地使用已经打开的实例。

    • 不知何故,在原始实例关闭之前,让BeforeClose或其他事件处理程序在原始实例中运行,这样我就可以运行我的清理代码。

    更新:

    这是Excel 2003。

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

    然而,这并不能解决我的问题:如果我这样做,然后在资源管理器中双击工作簿,会自动重新打开工作簿,但仍然不会通过“BeforeClose”事件处理程序调用。

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

    • 是否有使用VBA检测和拦截以这种方式重新打开的工作簿?

    更新2

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

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

    3 回复  |  直到 8 年前
        1
  •  2
  •   BKimmel    17 年前

    伙计…这个 好像 这很容易,但很难。在我7年左右的Excel VBA工作经验中,我玩弄了能想到的每一个事件和应用程序/工作簿属性,但我根本想不出任何优雅的东西。..我认为简短的回答是,这个问题并没有一个简洁优雅的解决方案(如果有的话,我真的很想看看)。那是个坏消息。

    好消息是,我认为那里 解决问题的方法。..1稍微优雅一点,但需要你重新思考一些方法,而另一个方法虽然脏,但可能更简单一点。

    更优雅的方式 这将涉及重新思考和重构你的方法。..我认为我在工作中从未遇到过这个问题的原因是,在我的每种方法结束时,工作簿都处于“良好”状态。..或者换句话说,如果需要进行“清理”,则在每个方法结束时进行。如果这会对开销性能产生巨大影响,您可以考虑设置一个布尔标志,并限制它是否在其他每个方法的末尾运行。(即runCleanup=ReturnTrueIfCleanupIsNeeded()如果(runCleanup=true)则CleanupMethod()结束如果)

    更脏的路 将涉及通过以下方式将整个工作簿本身变成一种“特设互斥体”
    1) 复制整个( 原来的 )工作簿在WorkBookOpen活动中 又一个 ( 临时工 )工作簿和使用“另存为”方法 临时工 将其放置在单独的位置。
    2) 存储( 原来的 )路径。
    3) 向工作簿打开事件添加代码,以检查( 临时工 )A)立即关闭并激活 临时工 或B)用( 临时工 )然后使用SaveAs
    4) 在用户保存工作簿之前捕获事件并将其保存到 两者 这个 原来的 位置,以及 临时工 位置。
    5) 在WorkBookClose事件中,运行所需的任何清理并保存 临时工 回到原来的位置。

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

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

    谢谢你提出有趣的问题。

        2
  •  2
  •   Matthew Rathbone    17 年前

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

    使用以下代码创建一个名为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打开一个新工作簿时,您将捕获事件并运行安全方法。如果你愿意,你甚至可以阻止它重新打开工作簿。

        3
  •  2
  •   Vijay    8 年前

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

    这将重新打开一个没有警告的打开文件。。 但请注意,任何更改都将被丢弃!

    Application.DisplayAlerts = False
    Workbooks.Open (sPath)
    Application.DisplayAlerts = True
    

    来自 Excel Forum

    这个解决方案满足了我的需求

    推荐文章