#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 ()», и теперь он работает.
Как глупо с моей стороны. Возможно, мой ответ поможет другим в той же ситуации.
Спасибо. Данут