简体   繁体   English

Excel OLEObject按钮点击几次后失去点击事件

[英]Excel OLEObject button loses click event after clicking a few times

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;我试图从 C# 代码在工作表中创建一个Excel 按钮,使用按钮的C# 事件处理程序,所以我不必涉及 VBA 和文本脚本; and I found this great solution from @ Dummy yoyo that works but "only for a while".我从@Dummy yoyo找到了这个很好的解决方案,它有效但“只持续了一段时间”。

The solution is simple: add a shape, get it as an ole object, get the ole as a button and add a click event:解决方案很简单:添加一个形状,将其作为 ole object 获取,将 ole 作为按钮获取并添加点击事件:

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!");
}

The problem:问题:

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.由于按钮标题中显示的i++ ,我可以看到正在重新创建按钮。 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.正如@Hans Passant所建议的那样,找到了部分解决方案:如果我将形状、ole object 和按钮作为 static 成员保留在方法之外,垃圾收集器不会杀死它们。 Nevertheless, I would like to save, close and reopen the sheet and still get the events.尽管如此,我还是想保存、关闭并重新打开工作表并仍然获得事件。

Great solutions could be:伟大的解决方案可能是:

  • Identifying why it happens and solving it确定它发生的原因并解决它
  • Suggesting another way of creating the button using a c# click handler建议使用c# 单击处理程序创建按钮的另一种方法
  • Making it possible to save this sheet, close and reopen it with the events still attached.可以保存此工作表,关闭并重新打开它,同时仍附加事件。

A few more details:更多细节:

  • I am creating a new Excel application from C# code and taking the first sheet of the first workbook.我正在从 C# 代码创建一个新的 Excel 应用程序,并获取第一张工作簿的第一张纸。
  • This is not a VSTO Addin, I don't have access to the 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.这不是 VSTO 插件,我无权访问Globals.Factory ,尽管我很想能够获得该工厂的实例并尝试Microsoft.Office.Tools.Worksheet方法来添加控件。
    • My project is inevitably a class library consumed by another non-related software我的项目不可避免地是一个 class 库被另一个不相关的软件消耗
  • The sheet must be saved and reopened later independently from the source project.工作表必须独立于源项目保存并在以后重新打开。
  • The sheet is populated before adding the button, also via C# code.在添加按钮之前填充工作表,也是通过 C# 代码。
  • Visual Studio debugger is able to step into the button's event handler without any special action Visual Studio 调试器无需任何特殊操作即可进入按钮的事件处理程序

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.主机控件和 Windows Forms 控件的确切行为不同。 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.注意: Microsoft Excel 2013 ,项目参考Microsoft office 15.0 object Library和 VS 2022 完美运行,但 Excel 2016 存在您所说的这个问题。 so I think this issue has come from Microsoft Office specific version.所以我认为这个问题来自 Microsoft Office 特定版本。

if you want to make it count clicks try this..如果你想让它计算点击次数试试这个..

 const btn = document.querySelector('.btn'); btn.onclick = Counter; const clicks = document.querySelector('.clicks'); clicks.id = document.querySelector('clicks'); var a = 0; function Counter() { a += 1; clicks.innerHTML = a; } const reset = document.querySelector('.reset'); reset.onclick = resetCounter; function resetCounter() { a = 0; clicks.innerHTML = a; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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