简体   繁体   中英

add ChangeEventHandler to existing excel sheet

I have a simple Windows Form in C# and i use it to open one excel workbook and run a macro on it from other workbook. The code is:

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();
    }

}
}

I want to know when the macro finishes. From what I searched I found that one way to do it is to make the macro write in an cell and to have the application check that cell for a particular value.

To do this I need to add an event handler but i cannot seem to make it work with my files. I need the event handler on Sheet1 in the excelfile.xlsx tab on cell A1.

I found an example that works but when I try to modify it for my files it does not work. The code that works is the following:

//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();
    }

This code works for a newly created workbook.

When I try and add

EventDel_CellsChange = new Excel.DocEvents_ChangeEventHandler(CellsChange);

after I open my excelfile.xlsx I get following error:

"An object reference is required for the non-static field, method, or property 'my_tool.Form1.EventDel_CellsChange'"

and

"An object reference is required for the non-static field, method, or property 'my_tool.Form1.CellsChange(Microsoft.Office.Interop.Excel.Range)'"

What am i doing wrong?

Thank you.

I managed to make it work. I was calling a non-static property from a static method.

I have replaced "public static void RunVBATest()" with "public void RunVBATest()" and it works now.

How stupid of me. Maybe my answer will help others in the same situation.

Thank you. Danut

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM