добавить ChangeEventHandler в существующую таблицу Excel

#c# #excel #visual-studio-2012 #vba

#c# #excel #visual-studio-2012 #vba

Вопрос:

У меня есть простая форма Windows на C #, и я использую ее, чтобы открыть одну книгу 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();
    }

}
}
  

Я хочу знать, когда завершится макрос. Из того, что я искал, я обнаружил, что один из способов сделать это — заставить макрос записывать в ячейку и заставить приложение проверять эту ячейку на определенное значение.

Для этого мне нужно добавить обработчик событий, но, похоже, я не могу заставить его работать с моими файлами. Мне нужен обработчик событий на листе 1 в excelfile.xlsx вкладка в ячейке A1.

Я нашел пример, который работает, но когда я пытаюсь изменить его для своих файлов, он не работает. Работающий код выглядит следующим образом:

 //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.Офис.Взаимодействие.Excel.Диапазон) ‘»

Что я делаю не так?

Спасибо.

Ответ №1:

Мне удалось заставить его работать. Я вызывал нестатическое свойство из статического метода.

Я заменил «public static void RunVBATest ()» на «public void RunVBATest ()», и теперь он работает.

Как глупо с моей стороны. Возможно, мой ответ поможет другим в той же ситуации.

Спасибо. Данут