2

How can I create a button (or a shape) on an Excel worksheet using C#? I am currently doing it with the code below, but I encounter two problems:

  1. the button gets moved when the columns to its left are resized
  2. the button does not respond when you select or right-click it, so there is no obvious way for a user to manually delete it from the sheet after it's been auto-added

EDIT: As Lance reminds me, #2 is due to my own misunderstanding -- in order to delete form buttons, you have to use Design Mode, which you can access through the Developer tab on the ribbon bar.

Is there a better way of generating buttons that will avoid these two problems?

        // prior code is equivalent to:
        // var name = "MyButton";
        // var row = 2;
        // var buttonCol = 5; 

        Range cell = sh.Cells[row, buttonCol];
        var width = cell.Width;
        var height = 25;
        var left = cell.Left;
        var top = Math.Max(cell.Top + cell.Height - height, 0);

        var items = sh.Shapes;
        var btn = items.AddOLEObject("Forms.CommandButton.1",
            null, null, null, null,
            null, null,
            left, top, width, height);
        btn.Name = name;

        OLEObject sheetBtn = sh.OLEObjects(name);
        sheetBtn.Object.Caption = isSubmit ? "Send" : "Cancel";

2 Answers 2

2

Well you could also try to create it using the OLEObjects collection with the .Add method, it uses the same parameters as the AddOLEObject method of the Shapes collection. Though I tried the AddOLEObject code you have in VBA and it worked great. I was able to go into design mode and select the button, and the columns didn't resize it, like so:

Public Sub Test()

Dim btn As Shape

Set btn = Sheets("Sheet1").Shapes.AddOLEObject("Forms.CommandButton.1", , , , , , , 1, 1, 100, 100)

End Sub
Sign up to request clarification or add additional context in comments.

1 Comment

D'oh -- I forgot about design mode.
2

To prevent the button from moving when columns before it are resized, set:

btn.Placement = XlPlacement.xlFreeFloating;

As an alternative to creating a button, you can use a shape:

        var items = sh.Shapes;
        var shape = sh.Shapes.AddShape(MsoAutoShapeType.msoShapeRectangle, left, top, width, height);
        shape.Name = name;
        shape.Placement = XlPlacement.xlFreeFloating;
        shape.TextFrame.Characters().Text = isSubmit ? "Send" : "Cancel";
        // an use this to assign a macro to it (won't happen by default as with a button)
        shape.OnAction = xl.Name + "!"+ sh.Name + "." + subName;

Note that the definition of MsoAutoShapeType is not included in the regular Office.Interop DLLs. I found it by using the COM tab of "Add Reference" and adding a reference to "Microsoft.Office 12.0 Object Library".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.