将ChangeEventHandler添加到现有的Excel工作表

时间:2014-06-30 19:18:24

标签: c# excel-vba visual-studio-2012 vba excel

我在C#中有一个简单的Windows窗体,我用它来打开一个excel工作簿并从其他工作簿上运行一个宏。代码是:

namespace my_tool
{

     public partial class Form1 : Form
     {
    //Excel event delegate variables:
    public Excel.DocEvents_ChangeEventHandler EventDel_CellsChange;
    public Excel.Worksheet xlSheet;
    public Excel.Application xlApp;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    public static void RunVBATest()
    {
        Microsoft.Office.Interop.Excel.Application oExcel = new Microsoft.Office.Interop.Excel.Application();
        oExcel.Visible = true;
        Excel.Workbooks oBooks = oExcel.Workbooks;
        Excel.Workbook oBook1 = null;
        Excel.Workbook oBook = null;
        oBook1 = oBooks.Open("C:\\Reports\\Macros\\excel-sql\\Excel_macro.xlsm");
        oBook = oBooks.Open("C:\\excelfile.xlsx");
        Excel.Worksheet sheet = (Excel.Worksheet)oBook.Sheets["Sheet1"];
        sheet.Select(Type.Missing);
        ((Microsoft.Office.Interop.Excel._Worksheet)sheet).Activate();

        // Run the macro.
        oExcel.Run("'Excel_macro.xlsm'!SQL_bai");

        // Quit Excel and clean up.
        //oBook.Saved = true;
        //oBook.Close(false);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
        //oBook = null;
        System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);
        //oBooks = null;
        //oExcel.Quit();
        System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
        //oExcel = null;
        //System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
    }

         private void button1_Click(object sender, EventArgs e)
    {
        RunVBATest();
    }

}
}

我想知道宏什么时候结束。从我搜索的内容中我发现,一种方法是在一个单元格中进行宏写入,并让应用程序检查该单元格是否为特定值。

要做到这一点,我需要添加一个事件处理程序,但我似乎无法使它与我的文件一起工作。我需要在单元格A1上的excelfile.xlsx选项卡中的Sheet1上的事件处理程序。

我找到了一个有效的例子但是当我尝试为我的文件修改它时它不起作用。 有效的代码如下:

//Excel Automation variables:
                 //Excel.Application xlApp;
                 Excel.Workbook xlBook;
                 Excel.Worksheet xlSheet1, xlSheet2, xlSheet3;
    //
                 //Excel event delegate variables:
                 Excel.AppEvents_WorkbookBeforeCloseEventHandler EventDel_BeforeBookClose;
                 Excel.DocEvents_ChangeEventHandler EventDel_CellsChange;
    //
                 private void StartExcelAndSinkEvents()
                 {
                     //Start Excel, and then create a new workbook.
                     xlApp = new Excel.Application();
                     xlBook = xlApp.Workbooks.Add(Missing.Value);
                     xlBook.Windows.get_Item(1).Caption = "XL Event Test";
                     xlSheet1 = (Excel.Worksheet)xlBook.Worksheets.get_Item(1);
                     xlSheet2 = (Excel.Worksheet)xlBook.Worksheets.get_Item(2);
                     xlSheet3 = (Excel.Worksheet)xlBook.Worksheets.get_Item(3);
                     ((Microsoft.Office.Interop.Excel._Worksheet)xlSheet1).Activate();

                     //Add an event handler for the WorkbookBeforeClose Event of the
                     //Application object.
                     EventDel_BeforeBookClose =
                        new Excel.AppEvents_WorkbookBeforeCloseEventHandler(BeforeBookClose);
                     xlApp.WorkbookBeforeClose += EventDel_BeforeBookClose;

                     //Add an event handler for the Change event of both worksheet objects.
                     EventDel_CellsChange = new Excel.DocEvents_ChangeEventHandler(CellsChange);

                     xlSheet1.Change += EventDel_CellsChange;
                     xlSheet2.Change += EventDel_CellsChange;
                     xlSheet3.Change += EventDel_CellsChange;

                     //Make Excel visible and give the user control.
                     xlApp.Visible = true;
                     xlApp.UserControl = true;
                 }

                 private void CellsChange(Excel.Range Target)
                 {
                     //This is called when any cell on a worksheet is changed.
                     Debug.WriteLine("Delegate: You Changed Cells " +
                        Target.get_Address(Missing.Value, Missing.Value,
                        Excel.XlReferenceStyle.xlA1, Missing.Value, Missing.Value) +
                        " on " + Target.Worksheet.Name);
                     MessageBox.Show(Target.get_Address(Missing.Value, Missing.Value,
                        Excel.XlReferenceStyle.xlA1, Missing.Value, Missing.Value));
                 }

                 private void BeforeBookClose(Excel.Workbook Wb, ref bool Cancel)
                 {
                     //This is called when you choose to close the workbook in Excel.
                     //The event handlers are removed, and then the workbook is closed 
                     //without saving the changes.
                     Wb.Saved = true;
                     Debug.WriteLine("Delegate: Closing the workbook and removing event handlers.");
                     xlSheet1.Change -= EventDel_CellsChange;
                     xlSheet2.Change -= EventDel_CellsChange;
                     xlSheet3.Change -= EventDel_CellsChange;
                     xlApp.WorkbookBeforeClose -= EventDel_BeforeBookClose;
                 }

         private void button2_Click(object sender, EventArgs e)
    {
        //StartExcelAndSinkEvents();
    }

此代码适用于新创建的工作簿。

当我尝试添加

EventDel_CellsChange = new Excel.DocEvents_ChangeEventHandler(CellsChange);

打开我的excelfile.xlsx后,我收到以下错误:

“非静态字段,方法或属性'my_tool.Form1.EventDel_CellsChange'”

需要对象引用

“非静态字段,方法或属性'my_tool.Form1.CellsChange(Microsoft.Office.Interop.Excel.Range)'”

需要对象引用

我做错了什么?

谢谢。

1 个答案:

答案 0 :(得分:1)

我设法让它发挥作用。我从静态方法调用非静态属性。

我已将“public static void RunVBATest()”替换为“public void RunVBATest()”,现在可以正常使用。

我多么愚蠢。也许我的回答会在同样的情况下帮助其他人。

谢谢。 Danut