1

I have a button in a workdbook (wbShared), clicking on that button a second workbook (wbNewUnshared) opens. I want to add a button to wbNewUnshared with code programmatically. I already found how to add the button, but I didn't find how to add code to this button.

'create button
'--------------------------------------------------------
Dim objBtn As Object
Dim ws As Worksheet
Dim celLeft As Integer
Dim celTop As Integer
Dim celWidth As Integer
Dim celHeight As Integer

Set ws = wbNewUnshared.Sheets("Sheet1")
celLeft = ws.Range("S3").left
celTop = ws.Range("T2").top
celWidth = ws.Range("S2:T2").width
celHeight = ws.Range("S2:S3").height

Set objBtn = ws.OLEObjects.add(classType:="Forms.CommandButton.1", link:=False, _
    displayasicon:=False, left:=celLeft, top:=celTop, width:=celWidth, height:=celHeight)
objBtn.name = "Save"
'buttonn text
ws.OLEObjects(1).Object.Caption = "Save"

I found this online:

'macro text
'        Code = "Sub ButtonTest_Click()" & vbCrLf
'        Code = Code & "Call Tester" & vbCrLf
'        Code = Code & "End Sub"
'    'add macro at the end of the sheet module
'        With wbNewUnshared.VBProject.VBComponents(ActiveSheet.name).codeModule
'            .InsertLines .CountOfLines + 1, Code
'        End With

But this gives an error in the last line. Anybody has a clue? tx

EDIT: SOLVED Ok, the code given works, I had an error 'Programmatic Access To Visual Basic Project Is Not Trusted'. Thanks to the help of S Meaden I solved that via https://support.winshuttle.com/s/article/Error-Programmatic-Access-To-Visual-Basic-Project-Is-Not-Trusted. after that my code worked. So thanks again.

VeVi
  • 281
  • 2
  • 7
  • 17
  • What is the error? and when you say last line you mean in the commented block? You mean `.InsertLines...`? Is there anything else in the code module for that sheet? – S Meaden Dec 15 '17 at 09:05
  • The error I get is 'method or data member not found' and it selects VBproject. visual basicis checked in tools/references/microsoft visual basic for applications extensibility 5.3. With last line I indeed meant: With ws.VBProject.VBComponents(ActiveSheet.name).codeModule .InsertLines .CountOfLines + 1, Code End With. In wbShared I worte the code to open en new workbook, I copy some information and then I make a button and want to add a macro code to this button. There is nothing else of code in the second workbook. – VeVi Dec 15 '17 at 09:11
  • I assume you've got past the 'Programmatic access to Visual Basic Project is not trusted' issue. – S Meaden Dec 15 '17 at 09:18
  • I never got that error? :/ that's a good thing?:) – VeVi Dec 15 '17 at 09:21
  • Ok, it doesn't work for me if I attempt to add code to the same workbook, but it works for a different workbook. Re-reading your question you are operating on a different workbook, so it should work. – S Meaden Dec 15 '17 at 09:21
  • So, with this code you can program the button? So probably there is something wrong with my preferences/references of excel? – VeVi Dec 15 '17 at 09:23
  • Ah! ActiveSheet maybe the problem. You are assuming the ActiveSheet is part of wbNewUnshared workbook, check this please. – S Meaden Dec 15 '17 at 09:24
  • Oke S Meaden, I had an error in my code (a small typo) that isn't in the code above. So now I have indeed that error that you mentioned 'programmatic access to visual basic project is not trusted' – VeVi Dec 15 '17 at 09:31
  • 1
    https://support.winshuttle.com/s/article/Error-Programmatic-Access-To-Visual-Basic-Project-Is-Not-Trusted to fix – S Meaden Dec 15 '17 at 09:32
  • Tx S Meaden, it works now! – VeVi Dec 15 '17 at 11:16

1 Answers1

1

The first code I provided assumes 1 workbook. The code I'm presenting now does not. The limitation of this is that if the arrBttns is lost, the project is reset, the link between the code and the button is lost and the procedure addCodeToButtons has to be run again.

In the wbNewUnshared, create a class module with the following code

Option Explicit

Public WithEvents cmdButtonSave As MSForms.CommandButton
Public WithEvents cmdButtonDoStuff As MSForms.CommandButton

Private Sub cmdButtonDoStuff_Click()
    'Your code to execut on "Do Stuff" button click goes here
    MsgBox "You've just clicked the Do Stuff button"
End Sub

Private Sub cmdButtonSave_Click()
    'Your code to execut on "Save" button click goes here
    MsgBox "You've just clicked the Save button"

End Sub

In the wbNewUnshared add a standard module with the following code

Option Explicit

Dim arrBttns() As New Class1

Public Sub addCodeToButtons()
    Dim bttn As OLEObject
    Dim ws As Worksheet
    Dim i As Long

    ReDim arrBttns(0)

    'Iterate through worksheets
    For Each ws In ThisWorkbook.Worksheets
        'Iterate through buttons on worksheet
        For Each bttn In ws.OLEObjects
            'Expand arrBttns for valid buttons.
            If bttn.Name = "Save" Or bttn.Name = "DoStuff" Then
                If UBound(arrBttns) = 0 Then
                    ReDim arrBttns(1 To 1)
                Else
                    ReDim Preserve arrBttns(1 To UBound(arrBttns) + 1)
                End If
            End If
            'Link button to correct code
            Select Case bttn.Name
                Case "Save"
                    Set arrBttns(UBound(arrBttns)).cmdButtonSave = bttn.Object
                Case "DoStuff"
                    Set arrBttns(UBound(arrBttns)).cmdButtonDoStuff = bttn.Object
            End Select
        Next bttn
    Next ws

End Sub

In the wbNewUnshared add the following code in the ThisWorkbook module, this is to add the code to the buttons on workbook open.

Option Explicit

Private Sub Workbook_Open()
    Call addCodeToButtons
End Sub

In the wbShared add the following line after you're done adding buttons

Application.Run "wbNewUnshared.xlsm!addCodeToButtons"

Original Answer

Add a class module to your project to which you add.

Option Explicit

Public WithEvents cmdButton As MSForms.CommandButton  'cmdButton can be an name you like, if changed be sure to also change the Private Sub below

Private Sub cmdButton_Click()
    'Your code on button click goes here
    MsgBox "You just clicked me!"
End Sub

To a module you add the code below

Option Explicit

Dim arrBttns() As New Class1 'Change Class1 to the actual name of your classmodule

'The sub which adds a button
Sub addButton()
    Dim bttn As OLEObject
    Dim ws As Worksheet

    Set ws = ThisWorkbook.Worksheets("Sheet1")
    Set bttn = ws.OLEObjects.Add(ClassType:="Forms.CommandButton.1")
    ReDim arrBttns(0)

    If UBound(arrBttns) = 0 Then
        ReDim arrBttns(1 To 1)
    Else
        ReDim Preserve arrBttns(1 To UBound(arrBttns))
    End If

    Set arrBttns(UBound(arrBttns)).cmdBttn = bttn.Object

End Sub
SilentRevolution
  • 1,495
  • 1
  • 16
  • 31
  • So this I add to my original workbook and in the sub addButton I set the new workbook (second) as ws? – VeVi Dec 15 '17 at 09:27
  • @VeVi and @S Meaden, I've not tested this with multiple workbooks, give me a few to work this out. – SilentRevolution Dec 15 '17 at 09:31
  • @SMeaden, I've update my answer to span across 2 workbooks. I've tested it and it works. – SilentRevolution Dec 15 '17 at 10:49
  • Hi SilentRevolution, tx for your help and effort, but second workbook is something that will be generated by the user, so I need to add the code automatically at the moment that the workbook is created. I'm actually making a template, the user is not in the position to add the macro data in the new workbook. – VeVi Dec 15 '17 at 11:14
  • @VeVi In that case, I would recommend making a hidden sheet in which the buttons and code are already present. If you then copy and rename that hidden sheet, make it visible because then, the code and buttons will also copy over. No need to add it by code anymore – SilentRevolution Dec 15 '17 at 15:09
  • That is actually a great idea! I did not think of that! Thank you! – VeVi Dec 20 '17 at 08:39