I was trying to create an Excel button in a sheet from a C# code, using a C# event hander for the button, so I don't have to involve VBA and text scripts; and I found this great solution from @ Dummy yoyo that works but "only for a while".
The solution is simple: add a shape, get it as an ole object, get the ole as a button and add a click event:
int i = 1;
private void CreateButton()
{
Microsoft.Office.Interop.Excel.Worksheet sheet = #get a sheet from Excel
sheet.Shapes.AddOLEObject("Forms.CommandButton.1", Type.Missing, false, false, Type.Missing, Type.Missing, Type.Missing, 10, 10, 100, 30);
Microsoft.Office.Interop.Excel.OLEObject oleShape = sheet.OLEObjects(1);
Microsoft.Vbe.Interop.Forms.CommandButton button = oleShape.Object;
button.Caption = "Custom Buttom" + i;
button.Click += Button_Click;
i++; //for future use, see below
}
private void Button_Click()
{
MessageBox.Show("It works!");
}
Now, the first time I click the button on the sheet, it works! The second time "might" work. The more clicks the less chance of it working. Inevitably, the button "loses" the click event and just does nothing. I can't figure out why, what can be causing this.
I even tried to recreate the button every click with:
private void Button_Click()
{
MessageBox.Show("It Works!");
sheet.Shapes.Item(1).Delete();
CreateButton();
}
I can see the button is being recreated because of the i++ that shows in the button's caption. Even though, some clicks later, even the newly created button simply does nothing when clicked.
What can be going on? How can I solve this?
Edit:
A partial solution was found, as @Hans Passant suggested: if I keep the shape, the ole object and the button as static members outside the method, the garbage collector doesn't kill them. Nevertheless, I would like to save, close and reopen the sheet and still get the events.
Great solutions could be:
A few more details:
Globals.Factory, although I'd love to be able to get an instance of this factory and try Microsoft.Office.Tools.Worksheet methods to add controls.
Following way every time I click on this button not getting any issue.
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
int i = 1;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
//add data
xlWorkSheet.Cells[1, 1] = "";
xlWorkSheet.Cells[1, 2] = "Student1";
xlWorkSheet.Cells[1, 3] = "Student2";
xlWorkSheet.Cells[1, 4] = "Student3";
xlWorkSheet.Cells[2, 1] = "Term1";
xlWorkSheet.Cells[2, 2] = "80";
xlWorkSheet.Cells[2, 3] = "65";
xlWorkSheet.Cells[2, 4] = "45";
xlWorkSheet.Cells[3, 1] = "Term2";
xlWorkSheet.Cells[3, 2] = "78";
xlWorkSheet.Cells[3, 3] = "72";
xlWorkSheet.Cells[3, 4] = "60";
xlApp.Visible = true;
#region
xlWorkSheet.Shapes.AddOLEObject("Forms.CommandButton.1", Type.Missing, false, false, Type.Missing, Type.Missing, Type.Missing, 10, 10, 100, 30);
Microsoft.Office.Interop.Excel.OLEObject oleShape = xlWorkSheet.OLEObjects(1);
Microsoft.Vbe.Interop.Forms.CommandButton button = oleShape.Object;
button.Caption = "Custom Buttom" +i ;
button.Click += Button_Click;
i++;
#endregion
}
private void Button_Click()
{
MessageBox.Show("It works!");
}

but sometime button seems not clickable or not fire click even. see below screenshot.

Message show already, but we do not see it in top of the worksheet. too many time click on the button it may happened. so if you do not see the dialog just open it from taskbar.
Reopen: Controls that are added at run time are not persisted when the document or workbook is saved and closed. The exact behavior is different for host controls and Windows Forms controls. In both cases, you can add code to your solution to re-create the controls when the user reopens the document.
xlApp = new Excel.Application();
string workbookPath = @"c:/Book.xlsx";
xlWorkBook = xlApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlApp.Visible = true;
Microsoft.Office.Interop.Excel.OLEObject oleShape = xlWorkSheet.OLEObjects(1);
Microsoft.Vbe.Interop.Forms.CommandButton button = oleShape.Object;
button.Caption = "Custom Buttom" + i;
button.Click += Button_Click;
i++;
NB: Microsoft Excel 2013, project reference Microsoft office 15.0 object Library and VS 2022 work perfectly but Excel 2016 has this issue you are telling about. so I think this issue has come from
Microsoft Office specific version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With