Searching For Newly Added Command Button Procedure in VBA Excel - excel

Reference
I am trying to add code (a subroutine call) to a procedure within Sheet1 by finding the line number of the procedure's statement within sheet1 in VBE then adding the code to the next line over. The following code attempts to achieve this.
' This will search for and modify the appropriate Node#button_Click() subroutine
With ActiveWorkbook.VBProject.VBComponents("Sheet1").CodeModule
ProcLineNum = .ProcStartLine("Node" & NumNodes & "Button" & "_Click", 0)
.InsertLines ProcLineNum + 1, "load_node_form(" & DQUOTE & "Node " & NumNodes & DQUOTE & ")"
End With
The entire subroutine is the following:
Public Sub Node_Button_Duplication()
'
'Com: Copies and pastes Node 1's button to the appropriate column
Dim shp As Shape
Dim code As String
Dim ProcLineNum As Long
Const DQUOTE = """"
' Copy Node 1 button and paste in appropriate location
ActiveSheet.Shapes("CommandButton1").Select
Selection.Copy
Cells(5, 10 + 7 * (NumNodes - 1) - 1).Select
ActiveSheet.Paste
Selection.ShapeRange.IncrementLeft 47.25
Selection.ShapeRange.IncrementTop -13.5
Set shp = ActiveSheet.Shapes(Selection.Name)
With shp.OLEFormat.Object
.Object.Caption = "Node" & Str(NumNodes)
.Name = "Node" & NumNodes & "Button"
End With
' This will search for and modify the appropriate Node#button_Click() subroutine
With ActiveWorkbook.VBProject.VBComponents("Sheet1").CodeModule
ProcLineNum = .ProcStartLine("Node" & NumNodes & "Button" & "_Click", 0)
.InsertLines ProcLineNum + 1, "load_node_form(" & DQUOTE & "Node " & NumNodes & DQUOTE & ")"
End With
End Sub
The subroutine will copy and paste a button ("CommandButton1"), rename it, then attempts to assign a subroutine call. The problem in finding the procedure is that once the new button is created, the "CommandButton#_Click() procedure doesn't show up in VBE until I go and select it from the editor, thus causing an error when my code tries to search for that procedure.

Is this what you are trying?
Option Explicit
Public Sub Node_Button_Duplication()
Dim shp As Shape
Dim code As String
Dim ProcLineNum As Long, NumNodes As Long
Const DQUOTE = """"
ActiveSheet.Shapes("CommandButton1").Select
Selection.Copy
Cells(5, 10 + 7 * (NumNodes - 1) - 1).Select
ActiveSheet.Paste
Selection.ShapeRange.IncrementLeft 47.25
Selection.ShapeRange.IncrementTop -13.5
Set shp = ActiveSheet.Shapes(Selection.Name)
With shp.OLEFormat.Object
.Object.Caption = "Node" & Str(NumNodes)
.Name = "Node" & NumNodes & "Button"
End With
With ActiveWorkbook.VBProject.VBComponents( _
ActiveWorkbook.Worksheets("Sheet1").CodeName).CodeModule
.InsertLines Line:=.CreateEventProc("Click", "Node" & NumNodes & "Button") + 1, _
String:=vbCrLf & _
"load_node_form(" & DQUOTE & "Node " & NumNodes & DQUOTE & ")"
End With
End Sub

Related

"Procedure declaration does not match description of event or procedure having the same name" - When saved as Workbook_Deactivate

I am trying to save each sheet in my workbook to cell A1 when i exit and also clearing a load of cells when I exit. Why am i getting the error in the title. This is my code:
Private Sub Workbook_Deactivate(cancel As Boolean)
Application.ScreenUpdating = False
'Clear prior disaggregated returns data
With Worksheets("Scenario Results")
'Down scenario reuslts
.Range("J8:J" & .Range("J8").End(xlDown).Row).ClearContents
.Range("K8:K" & .Range("K8").End(xlDown).Row).ClearContents
.Range("L8:L" & .Range("L8").End(xlDown).Row).ClearContents
.Range("M8:M" & .Range("M8").End(xlDown).Row).ClearContents
.Range("N8:N" & .Range("N8").End(xlDown).Row).ClearContents
.Range("O8:O" & .Range("O8").End(xlDown).Row).ClearContents
.Range("P8:P" & .Range("P8").End(xlDown).Row).ClearContents
'Base scenario results
.Range("R8:R" & .Range("R8").End(xlDown).Row).ClearContents
.Range("S8:S" & .Range("S8").End(xlDown).Row).ClearContents
.Range("T8:T" & .Range("T8").End(xlDown).Row).ClearContents
.Range("U8:U" & .Range("U8").End(xlDown).Row).ClearContents
.Range("V8:V" & .Range("V8").End(xlDown).Row).ClearContents
.Range("W8:W" & .Range("W8").End(xlDown).Row).ClearContents
.Range("X8:X" & .Range("X8").End(xlDown).Row).ClearContents
'Up scenario reuslts
.Range("Z8:Z" & .Range("Z8").End(xlDown).Row).ClearContents
.Range("AA8:AA" & .Range("AA8").End(xlDown).Row).ClearContents
.Range("AB8:AB" & .Range("AB8").End(xlDown).Row).ClearContents
.Range("AC8:AC" & .Range("AC8").End(xlDown).Row).ClearContents
.Range("AD8:AD" & .Range("AD8").End(xlDown).Row).ClearContents
.Range("AE8:AE" & .Range("AE8").End(xlDown).Row).ClearContents
.Range("AE8:AF" & .Range("AF8").End(xlDown).Row).ClearContents
End With
'Save in cell A1 everytime
Dim sht As Worksheet, csheet As Worksheet
Set csheet = ActiveSheet
For Each sht In ActiveWorkbook.Worksheets
If sht.Visible Then
sht.Activate
Range("A1").Select
ActiveWindow.ScrollRow = 1
ActiveWindow.ScrollColumn = 1
End If
Next sht
csheet.Activate
applictaion.ScreenUpdating = True
End Sub
Thank you!
Jack,
Here's how to do the loop:
Option Explicit
Sub ClearRangeLoop()
Dim Col As Integer
Dim Ltr As String
With Worksheets("Sheet1")
For Col = 10 To 16 'J through P
Ltr = Chr(64 + Col)
.Range(Ltr & "8:" & Ltr & .Range(Ltr & "8").End(xlDown).Row).ClearContents
Next Col
End With
End Sub 'ClearRangeLoop
You'll have to do a little more work when you get to the double letter columns.
HTH

Ctrl + Page Up / Page Down not compatible with UserForm featuring refEdit

I created an "Index Match Wizard" using UserForm controls. The code works effectively, however, I am unable to use ctrl + pgup / pgdn while the userform is running. No other shortcuts appear to be unavailable. The requirement to use a mouse to click to a different tab largely eliminates the purpose of the macro.
My code is as follows:
Sub UserForm_Initialize()
ListBox1.AddItem "Exact"
ListBox1.AddItem "Approx."
End Sub
Sub CommandButton1_Click()
MatchRangeOne = RefEdit1.Value
MatchRangeTwo = RefEdit2.Value
IndexRange = RefEdit3.Value
If ListBox1.Value = "Approx." Then
ActiveCell.Formula = "=INDEX(" & RefEdit3.Value & ",MATCH(" & RefEdit1.Value & "," & RefEdit2.Value & ",1))"
Else
ActiveCell.Formula = "=INDEX(" & RefEdit3.Value & ",MATCH(" & RefEdit1.Value & "," & RefEdit2.Value & ",0))"
End If
Unload IndexMatchWizardForm
End Sub

Multi-optional macros using removeable checkboxes

Thanks to these instructions
How do I assign a Macro to a checkbox dynamically using VBA
https://social.msdn.microsoft.com/Forums/office/en-US/877f15da-bbe4-4026-8ef2-8df77e1022f7/how-do-i-assign-a-macro-to-a-checkbox-dynamically-using-vba?forum=exceldev
I came up with an idea to:
Put checkboxes where I want on the sheet, e.g. in columns to the right from table with data for processing
Connect their (un)checking with logical variables which are used whether to start or not to start some procedures.
Wait for user to make his choices and check certain checkbox (e.g. the last in the list) to start selected procedures
Remove all (!) checkboxes and start the procedures selected shortly before.
This way the macros containing optional procedures are portable, as they don't DEPEND on the opened files but only WORK on them.
The files themselves remain unchanged by these free from control buttons coded in the macro (i.e. the sheet with checkboxes returns to it's previous state).
The following macro makes its own checkboxes (in column H), waits for user to choose options, memorizes choices, deletes all checkboxes, runs other procedures... and ends up without leaving a trace of itself in a workbook.
Dim FirstOptionLogical, SecondOptionLogical, ThirdOptionLogical As Boolean
' Making new checkboxes
Sub CheckBOxAdding()
Dim i As Long, id As Long
Dim cel As Range
Dim cbx As CheckBox
On Error GoTo CheckBoxAddingERROR
'FirstOptionLogical = False
'SecondOptionLogical = False
'ThirdOptionLogical = False
' Deleting all checkboxes, if any found
' Preventing error stops if there is no checkbox
On Error Resume Next
' Repeating with all checkboxes on active sheet
For Each chkbx In ActiveSheet.CheckBoxes
' Removing a checkbox
chkbx.Delete
' Next checkbox
Next
Range("G3").Select
ActiveSheet.Range(Columns("G:G"), Selection.End(xlToRight)).Select
Selection.Delete Shift:=xlToLeft
On Error GoTo 0
Set cel = ActiveSheet.Cells(3, 8)
With cel
Set cbx = ActiveSheet.CheckBoxes.Add(.Left, .Top, 90, 3)
' height will autosize larger to the font
End With
cbx.Name = "Option_1"
cbx.Caption = "First Attribute changes, name it"
cbx.Display3DShading = True
' with a linked can trap sheet change event or link to other formulas
cbx.LinkedCell = cel.Offset(0, -1).Address
cbx.OnAction = "'" & ThisWorkbook.Name & "'!CheckBoxHandling"
''''''''''
Set cel = ActiveSheet.Cells(5, 8)
With cel
Set cbx = ActiveSheet.CheckBoxes.Add(.Left, .Top, 90, 3)
' height will autosize larger to the font
End With
cbx.Name = "Option_2"
cbx.Caption = "Second Attribute changes, name it"
cbx.Display3DShading = True
' with a linked can trap sheet change event or link to other formulas
cbx.LinkedCell = cel.Offset(0, -1).Address
cbx.OnAction = "'" & ThisWorkbook.Name & "'!CheckBoxHandling"
Set cel = ActiveSheet.Cells(7, 8)
With cel
Set cbx = ActiveSheet.CheckBoxes.Add(.Left, .Top, 90, 3)
' height will autosize larger to the font
End With
cbx.Name = "Option_3"
cbx.Caption = "Third Attribute changes, name it"
cbx.Display3DShading = True
' with a linked can trap sheet change event or link to other formulas
cbx.LinkedCell = cel.Offset(0, -1).Address
cbx.OnAction = "'" & ThisWorkbook.Name & "'!CheckBoxHandling"
Set cel = ActiveSheet.Cells(9, 8)
With cel
Set cbx = ActiveSheet.CheckBoxes.Add(.Left, .Top, 90, 3)
' .Font.Size = 36
' height will autosize larger to the font
End With
cbx.Name = "Option_4"
cbx.Caption = "START THE MACRO"
cbx.Display3DShading = True
' with a linked can trap sheet change event or link to other formulas
cbx.LinkedCell = cel.Offset(0, -1).Address
cbx.OnAction = "'" & ThisWorkbook.Name & "'!CheckBoxHandling"
Exit Sub
CheckBoxAddingERROR:
MsgBox "Something went wrong... ;-) in the sub CheckBOxAdding", vbCritical + vbOKOnly
End
End Sub
Sub CheckBoxHandling()
Dim sCaller, UsersChoice As String
Dim id As Long
Dim cbx As CheckBox
Dim shp As Shape
UsersChoice = ""
On Error GoTo CheckBoxHandlingERROR
sCaller = Application.Caller
Set shp = ActiveSheet.Shapes(sCaller)
Set cbx = ActiveSheet.CheckBoxes(sCaller)
id = Val(Mid$(sCaller, Len("Option_") + 1, 5))
' maybe something based on Select Case?
Select Case id
Case 1:
'MsgBox "You clicked the checkbox with option" & vbCrLf & "'Larger description of First Attribute changes, name it'"
FirstOptionLogical = Not FirstOptionLogical
'FirstOptionLogical = IIf(cbx.Value = xlOn, True, False)
'MsgBox "FirstOptionLogical = " & FirstOptionLogical & vbCrLf & "SecondOptionLogical = " & SecondOptionLogical & vbCrLf & "ThirdOptionLogical= " & ThirdOptionLogical
Case 2:
'MsgBox "You clicked the checkbox with option" & vbCrLf & "'Larger description of Second Attribute changes, name it'"
SecondOptionLogical = Not SecondOptionLogical
'SecondOptionLogical = IIf(cbx.Value = xlOn, True, False)
'MsgBox "FirstOptionLogical = " & FirstOptionLogical & vbCrLf & "SecondOptionLogical = " & SecondOptionLogical & vbCrLf & "ThirdOptionLogical= " & ThirdOptionLogical
Case 3:
'MsgBox "You clicked the checkbox with option" & vbCrLf & "'Larger description of Third Attribute changes, name it'"
ThirdOptionLogical = Not ThirdOptionLogical
'ThirdOptionLogical = IIf(cbx.Value = xlOn, True, False)
'MsgBox "FirstOptionLogical = " & FirstOptionLogical & vbCrLf & "SecondOptionLogical = " & SecondOptionLogical & vbCrLf & "ThirdOptionLogical= " & ThirdOptionLogical
Case 4:
If FirstOptionLogical Then
UsersChoice = UsersChoice & "- Larger description of First Attribute changes, name it " & vbCrLf
End If
If SecondOptionLogical Then
UsersChoice = UsersChoice & "- Larger description of Second Attribute changes, name it " & vbCrLf
End If
If ThirdOptionLogical Then
UsersChoice = UsersChoice & "- Larger description of Third Attribute changes, name it " & vbCrLf
End If
Ans0 = MsgBox("The following options were chosen:" & vbCrLf & UsersChoice & vbCrLf & vbCrLf & _
"You chose a checkbox with an option" & vbCrLf & "'START THE MACRO'" & vbCrLf & vbCrLf & " S H O U L D W E S T A R T T H E M A C R O ? ", vbYesNo + vbDefaultButton2 + vbQuestion)
If Ans0 = vbYes Then
'MACRO WITH PARAMETERS WE CHOSE BY CLICKING GETS STARTED...
' Delete all remaining checkboxes, if any (removing traces of the macro)
' In case of error, resume
On Error Resume Next
For Each chkbx In ActiveSheet.CheckBoxes
chkbx.Delete
Next
' Deleting all columns from G to the right
Range("G3").Select
ActiveWorkbook.Sheets(1).Range(Columns("G:G"), Selection.End(xlToRight)).Select
Selection.Delete Shift:=xlToLeft
' Resetting on Error event to default
On Error GoTo 0
' If chosen, start sub 'Larger description of First Attribute changes, name it'
If FirstOptionLogical Then Call RunFirstOptionSub ' Name of the Sub
' If chosen, start sub 'Larger description of Second Attribute changes, name it'
If SecondOptionLogical Then Call RunSecondOptionSub ' Name of the Sub
' If chosen, start sub 'Larger description of Third Second Attribute changes, name it'
If ThirdOptionLogical Then Call RunThirdOptionSub ' Name of the Sub
Else
If Ans0 = vbNo Then
End If
End If
Exit Sub
End Select
cbx.TopLeftCell.Offset(, 2).Interior.Color = IIf(cbx.Value = xlOn, vbGreen, vbRed)
'MsgBox cbx.Caption & vbCr & IIf(cbx.Value = xlOn, " is ", " is not ") & "chosen"
Exit Sub
CheckBoxHandlingERROR:
MsgBox "Something went wrong... ;-) in the Sub CheckBoxHandling", vbCritical + vbOKOnly
End Sub
Sub RunFirstOptionSub()
' CODE
End Sub
Sub RunSecondOptionSub()
' CODE
End Sub
Sub RunThirdOptionSub()
' CODE
End Sub
Sub MacroWithOptionsEndsWithoutATrace()
FirstOptionLogical = False
SecondOptionLogical = False
ThirdOptionLogical = False
' OPTIONAL: Delete all remaining checkboxes, if any (most important when testing macro)
On Error Resume Next
For Each chkbx In ActiveSheet.CheckBoxes
chkbx.Delete
Next
' Resetting on Error event to default
On Error GoTo 0
CheckBOxAdding
End Sub
Share and use as you wish, as I used other's knowledge and experience.
I am very sorry, but I haven't found any other solution to present this to you, and I also haven't found anyone else presenting something similar to this.
Updated on Dec 17th 2019:
You could also use these checkboxes even easier way: write a macro that
creates a blank worksheet somewhere After:=Sheets(Sheets.Count) , so that it now becomes the new "last sheet",
put there these checkboxes,
check/uncheck them and start the macro by clicking the lowest one of them,
delete this last worksheet, leaving no traces of macro
That way you won't have to think again about where to put temporary checkboxes...
Updated on Oct 7th 2020:
I finally assumed, it would be better to make this an answered question, since it is.

Excel-VBA - list controls of all userforms for ANY given workbook

Task
My goal is to list all controls of all UserForms for ANY given workbook. My code works for all workbooks within the workbooks collection other than the calling workbook (ThisWorkBook).
Problem
If I try to list all the userforms' controls regarding the calling workbook, I get Error 91 Object variable or With block variable not set at numbered error line 200 (so called ERL). The code below is intently broken into 2 redundant portions, to show the error explicitly. Any help is appreciated.
Code
Sub ListWBControls()
' Purpose: list ALL userform controls of a given workbook within workbooks collection
'
Dim bProblem As Boolean
Dim vbc As VBIDE.VBComponent ' module, Reference to MS VBA Exte 5.3 needed !!!
Dim ctrl As MSForms.Control
Dim i As Integer, imax As Integer ' control counters
Dim cnr As Long, vbcnr As Long
Dim sLit As String
Dim sMsg As String ' result string
Dim owb As Workbook ' workbook object
Dim wb As String ' workbook name to choose by user
' --------------------
' choose Workbook name
' --------------------
wb = Me.ComboBox1.List(Me.ComboBox1.ListIndex, 0) ' << existing workbook name chosen in combobox
' check if wb is calling workbook or other
For Each owb In Workbooks
If owb.Name = wb And ThisWorkbook.Name = wb Then
bProblem = True
Exit For
End If
Next owb
' count workbooks
imax = Workbooks.Count
i = 1
' a) start message string showing workbook name
sMsg = sMsg & vbNewLine & String(25, "=") & vbNewLine & _
sLit & " WorkBook: " & Workbooks(i).Name & vbNewLine & String(25, "=")
'------------------------------
'Loop thru components (modules) - if of UserForm type
'------------------------------
For Each vbc In Workbooks(wb).VBProject.VBComponents
' Only if Component type is UserForm
If vbc.Type = vbext_ct_MSForm Then
' increment component and ctrl counters
sLit = Chr(i + 64) & "."
vbcnr = vbcnr + 1000
cnr = vbcnr
' b) build message new component
sMsg = sMsg & vbNewLine & String(25, "-") & vbNewLine & sLit & cnr & " '" & _
vbc.Name & "'" & vbNewLine & String(25, "-")
'-------------------
' Loop thru controls
'-------------------
' ===================================================================
' Code is intently broken into 2 portions, to show error explicitly !
' ===================================================================
On Error GoTo OOPS ' Error handler --> Error 91: Object variable or With block variable not set
If Not bProblem Then ' part 1 - other workbooks: shown explicitly, are no problem
100 For Each ctrl In Workbooks(wb).VBProject.VBComponents(vbc.Name).Designer.Controls
' increment ctrl counter
cnr = cnr + 1
' c) build messages controls)
sMsg = sMsg & vbLf & " " & Format(cnr, "0 000") & " " & ctrlInfo(ctrl)
Next
Else ' part 2 - problem arises here (wb = calling workbook)
200 For Each ctrl In Workbooks(wb).VBProject.VBComponents(vbc.Name).Designer.Controls ' << ERROR 91
' increment ctrl counter
cnr = cnr + 1
' c) build messages controls)
sMsg = sMsg & vbLf & " " & Format(cnr, "0 000") & " " & ctrlInfo(ctrl)
Next
End If
i = i + 1 ' increment letter counter i
End If
Next vbc
' show result
Debug.Print sMsg
Exit Sub
OOPS:
MsgBox "Error No " & Err.Number & " " & Err.Description & vbNewLine & _
"Error Line " & Erl
End Sub
Helper function
Private Function ctrlInfo(ctrl As MSForms.Control) As String
' Purpose: helper function returning userform control information
ctrlInfo = Left(TypeName(ctrl) & String(5, " "), 5) & " " & _
Left(ctrl.Name & String(20, " "), 20) & vbTab & _
" .." & IIf(TypeName(ctrl.Parent) = "UserForm", "Me " & String(15, " "), _
TypeName(ctrl.Parent) & ": " & _
Left(ctrl.Parent.Caption & String(15, " "), 15)) & vbTab & _
" T " & Format(ctrl.Top, "# 000") & "/ L " & Format(ctrl.Left, "# 000")
End Function
When a form is displayed, you can't get programmatic access to its designer. You are calling ListWBControls from an open UserForm. You could close the form beforehand, and let the code which opened it in the first place build the list, and re-open it afterwards.
Example
This code goes in a Module:
Public Sub Workaround()
On Error GoTo errHandler
Dim frmUserForm1 As UserForm1
Dim bDone As Boolean
bDone = False
Do
Set frmUserForm1 = New UserForm1
Load frmUserForm1
frmUserForm1.Show vbModal
If frmUserForm1.DoList Then
Unload frmUserForm1
Set frmUserForm1 = Nothing
ListWBControls
Else
bDone = True
End If
Loop Until bDone
Cleanup:
On Error Resume Next
Unload frmUserForm1
Set frmUserForm1 = Nothing
Exit Sub
errHandler:
MsgBox Err.Description, vbExclamation + vbOKOnly, "Error"
Resume Cleanup
End Sub
This code goes in UserForm1 where you've put one CommandButton named cmdDoList:
Option Explicit
Private m_bDoList As Boolean
Public Property Get DoList() As Boolean
DoList = m_bDoList
End Property
Private Sub cmdDoList_Click()
m_bDoList = True
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel = True
m_bDoList = False
Me.Hide
End Sub
The idea is to close the form, list the controls and re-open the form when cmdDoList is clicked, and to close the form for good if it is dismissed with the X button.
Found a direct solution covering most cases using the class properties of userforms and VBComponents.
I intently show the modified code below instead of re-editing. Of course, I highly appreciate the already accepted solution by #Excelosaurus :-)
Background
VBComponents have a .HasOpenDesigner property.
the calling userForm has the class properties .Controls AND can be referenced via the identifier Me.
(only the third seldom case remains unsolved and only if I don't reference these UFs directly: how to reference other userforms by a name string within the calling file IF they are active = .HasOpenDesigner is false; maybe worth a new question)
Modified code
Sub ListWBControls2()
' Purpose: list ALL userform controls of a given workbook within workbooks collection
' cf.: https://stackoverflow.com/questions/46894433/excel-vba-list-controls-of-all-userforms-for-any-given-workbook
Dim bProblem As Boolean
Dim vbc As VBIDE.VBComponent ' module, Reference to MS VBA Exte 5.3 needed !!!
Dim ctrl As MSForms.Control
Dim i As Integer, imax As Integer ' control counters
Dim cnr As Long, vbcnr As Long
Dim sLit As String
Dim sMsg As String ' result string
Dim owb As Workbook ' workbook object
Dim wb As String ' workbook name to choose by user
' ------------------
' chosen Workbook
' ------------------
wb = Me.ComboBox1.List(Me.ComboBox1.ListIndex, 0) ' << existing workbook name chosen in combobox
' count workbooks
imax = Workbooks.Count
i = 1
' a) build message new workbook
sMsg = sMsg & vbNewLine & String(25, "=") & vbNewLine & _
sLit & " WorkBook: " & Workbooks(i).Name & vbNewLine & String(25, "=")
'------------------------------
'Loop thru components (modules)
'------------------------------
For Each vbc In Workbooks(wb).VBProject.VBComponents
' Only if Component type is UserForm
If vbc.Type = vbext_ct_MSForm Then
' increment component and ctrl counters
sLit = Chr(i + 64) & "."
vbcnr = vbcnr + 1000
cnr = vbcnr
' b) build message new component
sMsg = sMsg & vbNewLine & String(25, "-") & vbNewLine & sLit & cnr & " '" & _
vbc.Name & "'" & vbNewLine & String(25, "-")
'-------------------
' Loop thru controls
'-------------------
If vbc.HasOpenDesigner Then ' i) problem for closed userforms in same file resolved
sMsg = sMsg & vbNewLine & "** " & vbc.Name & " active via Designer.Controls"
For Each ctrl In Workbooks(wb).VBProject.VBComponents(vbc.Name).Designer.Controls ' << ERROR 91
' increment ctrl counter
cnr = cnr + 1
' c) build messages controls)
sMsg = sMsg & vbLf & " " & Format(cnr, "0 000") & " " & ctrlInfo(ctrl)
Next
ElseIf vbc.Name = Me.Name Then ' ii) problem for calling userform resolved
sMsg = sMsg & vbNewLine & "** " & vbc.Name & " active via Me.Controls"
For Each ctrl In Me.Controls
' increment ctrl counter
cnr = cnr + 1
' c) build messages controls)
sMsg = sMsg & vbLf & " " & Format(cnr, "0 000") & " " & ctrlInfo(ctrl)
Next ctrl
' -----------------------------------------------------------
Else ' iii) problem reduced to other userforms within the calling file,
' but only IF OPEN
' -----------------------------------------------------------
sMsg = sMsg & vbLf & "** Cannot read controls in calling file when HasOpenDesigner property is false! **"
End If
End If
i = i + 1 ' increment letter counter i
Next vbc
' show result in textbox
Me.tbCtrls.Text = sMsg
Debug.Print sMsg
End Sub
Helper function
Private Function ctrlInfo(ctrl As MSForms.Control) As String
' Purpose: helper function returning userform control information
ctrlInfo = Left(TypeName(ctrl) & String(5, " "), 5) & " " & _
Left(ctrl.Name & String(20, " "), 20) & vbTab & _
" .." & IIf(TypeName(ctrl.Parent) = "UserForm", "Me " & String(15, " "), _
TypeName(ctrl.Parent) & ": " & _
Left(ctrl.Parent.Caption & String(15, " "), 15)) & vbTab & _
" T " & Format(ctrl.Top, "# 000") & "/ L " & Format(ctrl.Left, "# 000")
End Function

Can I rename every combobox with same name in excel?

There are a lot of combobox in sheet and they are appending dynamic. But all of combobox' assignments are same. They will run a function in macro. Can I rename all of combobox with same name? Or how can I do what I want?
Sub ekranadi()
Dim mainworkBook As Workbook
Set mainworkBook = ActiveWorkbook
For i = 1 To mainworkBook.Sheets.Count
If Left(mainworkBook.Sheets(i).Name, 5) = "Ekran"
Then ComboBoxEkranAdı.AddItem mainworkBook.Sheets(i).Name
End If
Next i
End Sub
If my understanding of your requirement is correct, the macro below will show you how to achieve the effect you seek.
A user form has a collection named Controls that contains every control on the form. Instead of MyControl.Name you can write Controls(6).Name if 6 is the index number within Controls of MyControl.
The macro below outputs the index number, type name and name of every control on a form. If the control is a ComboBox, it adds three items to it with each item value being unique to the box.
Edit
Sorry I did not read your question carefully enough. I do not use controls on worksheets because I consider controls on user forms to be more powerful and more convenient. Controls on worksheets are further complicated by having two types: those loaded from the Controls toolbox and those loaded from the Forms toolbox. Functionality depends on which type you have.
To test the new macro DemoWorksheet, I loaded worksheet "Test" with both types of control. The macro shows how to fill both type of combo box via their collections.
Option Explicit
Sub DemoUserForm()
Dim InxCtrl As Long
Load UserForm1
With UserForm1
For InxCtrl = 0 To .Controls.Count - 1
Debug.Print Right(" " & InxCtrl, 2) & " " & _
Left(TypeName(.Controls(InxCtrl)) & Space(10), 15) & _
.Controls(InxCtrl).Name
If TypeName(.Controls(InxCtrl)) = "ComboBox" Then
With .Controls(InxCtrl)
.AddItem InxCtrl & " A"
.AddItem InxCtrl & " B"
.AddItem InxCtrl & " C"
End With
End If
Next
End With
UserForm1.Show
End Sub
Sub DemoWorksheet()
Dim Inx As Long
With Worksheets("Test")
Debug.Print "Shapes.Count=" & .Shapes.Count
Debug.Print "OLEObjects.Count=" & .OLEObjects.Count
For Inx = 1 To .Shapes.Count
With .Shapes(Inx)
Debug.Print "S " & Right(" " & Inx, 2) & " ShapeType=" & _
ShapeTypeName(.Type) & " Name=" & .Name
If .Type = msoFormControl Then
Debug.Print " FormControlType=" & FormControlTypeName(.FormControlType)
If .FormControlType = xlDropDown Then
.ControlFormat.AddItem "S " & Inx & " A"
.ControlFormat.AddItem "S " & Inx & " B"
.ControlFormat.AddItem "S " & Inx & " C"
.ControlFormat.DropDownLines = 3
End If
End If
End With
Next
For Inx = 1 To .OLEObjects.Count
With .OLEObjects(Inx)
Debug.Print "O " & Right(" " & Inx, 2) & " OleType=" & _
OLETypeName(.OLEType) & " Name=" & .Name
If Left(.Name, 8) = "ComboBox" Then
.Object.AddItem "O " & Inx & " A"
.Object.AddItem "O " & Inx & " B"
.Object.AddItem "O " & Inx & " C"
End If
End With
Next
End With
End Sub
Function FormControlTypeName(ByVal FCType As Long) As String
Dim Inx As Long
Dim TypeName() As Variant
Dim TypeNumber() As Variant
TypeName = Array("ButtonControl", "CheckBox", "DropDown", "EditBox", "GroupBox", _
"Label", "ListBox", "OptionButton", "ScrollBar", "Spinner")
TypeNumber = Array(xlButtonControl, xlCheckBox, xlDropDown, xlEditBox, xlGroupBox, _
xlLabel, xlListBox, xlOptionButton, xlScrollBar, xlSpinner)
For Inx = 0 To UBound(TypeNumber)
If FCType = TypeNumber(Inx) Then
FormControlTypeName = TypeName(Inx)
Exit Function
End If
Next
FormControlTypeName = "Unknown"
End Function
Function OLETypeName(ByVal OType As Long) As String
If OType = xlOLELink Then
OLETypeName = "Link"
ElseIf OType = xlOLEEmbed Then
OLETypeName = "Embed"
ElseIf OType = xlOLEControl Then
OLETypeName = "Control"
Else
OLETypeName = "Unknown"
End If
End Function
Function ShapeTypeName(ByVal SType As Long) As String
Dim Inx As Long
Dim TypeName() As Variant
Dim TypeNumber() As Variant
TypeName = Array("AutoShape", "Callout", "Canvas", "Chart", "Comment", "Diagram", _
"EmbeddedOLEObject", "FormControl", "Freeform", "Group", "Line", _
"LinkedOLEObject", "LinkedPicture", "Media", "OLEControlObject", _
"Picture", "Placeholder", "ScriptAnchor", "ShapeTypeMixed", _
"Table", "TextBox", "TextEffect")
TypeNumber = Array(msoAutoShape, msoCallout, msoCanvas, msoChart, msoComment, msoDiagram, _
msoEmbeddedOLEObject, msoFormControl, msoFreeform, msoGroup, msoLine, _
msoLinkedOLEObject, msoLinkedPicture, msoMedia, msoOLEControlObject, _
msoPicture, msoPlaceholder, msoScriptAnchor, msoShapeTypeMixed, _
msoTable, msoTextBox, msoTextEffect)
For Inx = 0 To UBound(TypeNumber)
If SType = TypeNumber(Inx) Then
ShapeTypeName = TypeName(Inx)
Exit Function
End If
Next
ShapeTypeName = "Unknown"
End Function

Resources