在Excel事件BeforeSave上显示Form2

时间:2018-05-21 09:53:59

标签: vb.net winforms excel-interop

在Visual Studio 2017中,我创建了一个带有Form1的Windows窗体应用程序,用户在其中选择一个打开的Excel工作簿来收听其BeforeSave事件。

保存该工作簿后,程序会检测到该工作簿,然后从工作表中选择一些特定数据并打开Form2该数据。

我遇到的问题是,当我在Form2事件上加载BeforeSave时,其控件(如标签,按钮,文本框等)无法正确显示。它们看起来像带有背景颜色的盒子。

此处我的代码缩小并更改为重要的部分:

' Reference:
' Microsoft Excel 15.0 Object Library
Imports Microsoft.Office.Interop
Public Class Form1
    Private xlApp As Excel.Application
    Public Shared WithEvents xlBook As Excel.Workbook
    Private Shared Sub Workbook_BeforeSave(SaveAsUI As Boolean, ByRef Cancel As Boolean) Handles xlBook.BeforeSave
        Form2.Show()
        'Form1.Close()
    End Sub
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Try
            xlApp = Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
            xlBook = xlApp.Workbooks(1)
        Catch
            MsgBox("Excel isn't opened.")
            Close()
        End Try
    End Sub
End Class

修改:使用Application.Run(Form2)有效(不知道原因),但我也无法使用Form1关闭Form1.Close()

1 个答案:

答案 0 :(得分:1)

BeforeSave事件与其他Interop.Excel事件一样,是在另一个线程上引发的。因此,您无法直接从中访问GUI线程。为了访问GUI线程(例如,访问表单控件,在主线程上创建表单等),您需要使用委托调用Invoke方法。

用以下内容替换Form2.Show()可以解决问题:

Invoke(Sub() Form2.Show())

但是,您应该创建要加载的表单的 new 实例。因此,您应该使用以下内容代替上一行:

Private Sub Workbook_BeforeSave(SaveAsUI As Boolean,
                                ByRef Cancel As Boolean) Handles xlBook.BeforeSave
    Invoke(Sub()
               Dim frm As New Form2
               frm.Show()
           End Sub)
End Sub

要了解有关WinForms线程安全调用的更多信息,请查看参考文献中的第一篇文章。

参考文献: