代码之家  ›  专栏  ›  技术社区  ›  Ahmad

如何在正确关闭事件之前有效地使用工作簿?

  •  7
  • Ahmad  · 技术社区  · 14 年前

    每天,一个人需要检查特定的工作簿是否已正确更新彭博社和路透社的市场数据,即所有数据都已完成,并且“数字看起来是正确的”。在过去,人们没有检查“数字”,这导致不准确的上传到其他系统。

    其想法是,需要开发“某物”,以防止用户关闭/保存工作簿,除非他/她已检查更新是否正确/准确。这个 numbers look correct 动作纯粹是一种直观的练习,因此不会以任何方式进行编码。

    简单的解决方案是在关闭特定工作簿之前提示用户验证数据是否已被检查。

    使用VSTOSE for Excel2007,创建了一个外接程序,该外接程序钩住 WorkbookBeforeClose 在外接程序中初始化的事件 ThisAddIn_Startup

    private void wb_BeforeClose(Xl.Workbook wb, ref bool cancel)
    {
        //.... snip ...
    
        if (list.Contains(wb.Name))
        {
            DailogResult result = MessageBox.Show("some message", "sometitle", MessageBoxButtons.YesNo);
    
            if (result != DialogResult.Yes)
            {
                cancel = true; // i think this prevents the whole application from closing
            } 
        } 
    }
    

    我发现了以下内容 ThisApplication.WorkbookBeforeSave vs ThisWorkbook.Application.WorkbookBeforeSave 建议使用 ThisApplication.WorkbookBeforeClose 我认为这是我正在做的事情,因为这将跨越所有打开的文件。

    这种方法的问题是,假设我打开了几个文件,其中一些文件在我的 list ,该事件阻止Excel按顺序关闭所有文件。现在需要单独关闭每个文件。 编辑 :这种情况发生在 退出Excel 在“文件”菜单中使用。

    问题

    1. 我用的是 关闭前的工作簿 事件正确,这是否有效和高效地使用事件?
    2. 我应该使用应用程序级事件吗 或文档级事件 ?
    3. 上述行为是否正常? ?
    4. 在外接程序中使用工作簿事件时,欢迎使用任何其他建议

    更新[2010年3月30日]:

    我还尝试了以下方法,试图将 BeforeClose 按照上面链接的建议打开的每个工作簿的事件处理程序。

    private void ThisAddIn_Startup(...)
    {
        // snip
        Globals.ThisAddin.Application.WorkbookOpen += Application_Open; 
    }
    
    private void Application_Open(XL.Workbook wb)
    {
        wb.BeforeClose += Document_WorkbookBeforeClose; // method does the same as above
    }
    

    我在这种方法中发现的问题是,我试图关闭所有Excel文件(使用 退出Excel 选项)事件处理程序不执行。据我观察,当要检查的文档不是活动文档时,就会发生这种情况。

    与我最初的方法相比,这种方法似乎不稳定。有一件事我不确定或者不舒服,那就是每次打开文档时都要绑定事件。

    更新[2010年4月7日]:

    格伦提出的答案是有用的,但没有解决眼前的问题,因此我进一步澄清了最后一个问题。

    我也找到了这个博客 How to Get an Excel VSTO Workbook Closed Event 这与我的问题有些关联,因为它可以在我的解决方案的替代方法中使用,使用监视器类型的方法来处理工作簿(也可能使用新引入的 OnWorkbookClosed 事件)。

    更新[2010年4月8日]:

    似乎有些混乱,我不关心工作簿本身的任何验证,而是关心我使用的方法(即使用应用程序级别 关闭前的工作簿 事件)正确。 @Mathias下面的评论显示了对问题3部分的正确理解,不过我认为这是默认的Excel行为。解决这个问题的方法是创建一个只关闭特定文件的关闭函数。

    1. 上述行为是否正常? ? 是的,但为什么? 由于外接程序挂接到应用程序级事件,因此事件的检查和取消会阻止应用程序关闭任何其他工作簿。这里的钥匙是 ref bool cancel 论点( cancel=false 允许正常关闭工作簿(默认), cancel=true 阻止工作簿关闭)

    与2005年相比

    3 回复  |  直到 14 年前
        1
  •  7
  •   Todd Main    14 年前

    应用程序级别 WorkbookBeforeClose 是要使用的。问题是,当 关闭前的工作簿 被调用。如果不是这样,保存事件将启动,您实际上已经失去了 关闭前的工作簿 事件,因为它已经发生。下面是一些有助于处理此问题的VBA代码。

    Private Sub Workbook_BeforeClose(Cancel As Boolean)
        If Not Me.Saved Then
            NotSavedPrompt = Me.Name & " has not been saved. Would you like to save now?"
            SaveYesNo = MsgBox(NotSavedPrompt, vbQuestion + vbYesNoCancel)
            Select Case SaveYesNo
                Case vbYes
                    Me.Save
                Case vbNo
                    Me.Saved = True
                Case vbCancel
                    Cancel = True
                    Exit Sub
              End Select
        End If
        Call MyRoutine() //'this should be your sub that does what you want
    End Sub
    
        2
  •  3
  •   Glen Little    14 年前

    由于您在使用这种方法时遇到了问题,Excel可能不允许您执行所需的操作,因此您可以考虑使用另一种方法来解决整个问题。

    您能否在工作簿中构建一些东西,根据是否有人验证了数字,将其标记为“已验证/未验证”?根据实际使用工作簿的方式(与问题不清楚),显示未验证工作簿的方式可能有所不同…(视觉)将背景色设置为浅色红色,或(编程)将使用的命名范围更改为指向空白区域,以便其他加载项/宏找不到数据。

    要验证工作簿的用户需要单击一个按钮(在工作簿或工具栏中)以指示他们已经验证了该工作簿。然后,代码将撤消上述更改,并设置一个标志,指示工作簿已被验证。这可能在本书的某个隐藏单元格中,也可能在VBA模块的属性中。

    概括一下…打开时,检查标志。如果未设置,请将工作簿更改为“未验证”。如果已设置,则无需更改。当用户验证工作簿时,设置标志并将其永久保存。

    希望这有帮助!

        3
  •  1
  •   Ahmad    14 年前
    1. 在关闭事件之前,我是否正确使用了工作簿?这是否有效且高效地使用了事件?

      我找不到更好的活动。然而,我认为另一种方法是 Save&Close 使用WorkbookBeforeSave事件的函数

    2. 我应该使用应用程序级事件吗 或文档级事件 ?

      在写这个的时候,我会说是的。由于我无法使用现有工具创建文档级外接程序,因此这是可用的最佳解决方案。如果工具 有,我会修改 _AssemblyName _AssemblyLocation 相关文件的文档属性。但是,我会使用模板更改解决方案策略,然后根据需要保存文件。此外,在保存之前,还没有完全了解这一点,添加/删除正确的文档属性。文档级事件将非常适合使用上述方法。

    3. 上述行为是否正常?

      是的,但为什么?由于外接程序挂接到应用程序级事件,因此事件的检查和取消会阻止应用程序关闭任何其他工作簿。这里的键是ref bool cancel参数(cancel=false允许正常关闭工作簿(默认),cancel=true阻止工作簿关闭)。如果我错了,请告诉我。

    4. 在外接程序中使用工作簿事件时,欢迎使用任何其他建议

      请参阅以上答案,了解其他方法和不同事件的使用。