I have the following which add 1 editBox and 1 comboBox every time I click on a button in a userForm :
Sub addCable()
'TextBox creation
Dim editTxtBox As MSForms.Control
Static iTxtBox As Integer
Set editTxtBox = Me.Controls.Add("Forms.TextBox.1")
iTxtBox = iTxtBox + 1
cbxs.Add editTxtBox
', editTxtBox.Name
With editTxtBox
.Name = "txtBox" & iTxtBox
.Top = iTxtBox * editTxtBox.Height + 10
.Left = 20
End With
'ComboBox creation
Dim editCmpBox As MSForms.Control
Static iCmpBox As Integer
Set editCmpBox = Me.Controls.Add("Forms.ComboBox.1")
iCmpBox = iCmpBox + 1
cbxs.Add editCmpBox
', editCmpBox.Name
With editCmpBox
.Name = "cmBox" & iCmpBox
.Top = iCmpBox * editCmpBox.Height + 10
.Left = 130
.List = Array("60", "125", "45")
End With
End Sub
I want to implement the undo function, as it delete the last exitBox and the last comboBox created when I click on a button.
I was thinking to loop over my cbxs collection and remove at the index iTxtBox as iTxtBox is a global variable :
Dim num As Integer
MsgBox (iTxtBox)
For num = iTxtBox To cbxs.Count
cbxs.Remove iTxtBox
Next
But it doesn't work, I guess it is because my loop is out of the scope I'm looking for....
Related
I create a form dynamically and fill it with check boxes generated based on all column names of the Excel sheet it is launched from.
I add also a command button.
Here is the code put directly on the form:
Option Explicit
Dim cmdArray() As New Class1
Private Sub UserForm_Initialize()
Dim lastCol As Integer
Dim i As Integer
Dim chkBox As MSForms.CheckBox
Dim myButton As Control
lastCol = Worksheets(1).Cells(1, Columns.Count).End(xlToLeft).Column
Me.Height = 500
Me.Width = 600
For i = 1 To lastCol
Set chkBox = Me.Controls.Add("Forms.CheckBox.1", i)
chkBox.Caption = Worksheets(1).Cells(1, i).Value
' chkBox.Name = i
If i Mod 2 = 1 Then
chkBox.Left = 5
chkBox.Top = 5 + (i - 1) * 10
chkBox.Width = 200
Else
chkBox.Left = 250
chkBox.Top = 5 + (i - 2) * 10
chkBox.Width = 200
End If
Next i
i = 1
Set myButton = Me.Controls.Add("Forms.CommandButton.1", "MyButton", False)
With myButton
.Left = 500
.Top = chkBox.Top - 50
.Width = 50
.Caption = "Hide"
.Visible = True
End With
ReDim Preserve cmdArray(1 To i)
Set cmdArray(i).CmdEvents = myButton
Set myButton = Nothing
Me.ScrollBars = fmScrollBarsVertical
Me.ScrollHeight = chkBox.Top + 20
End Sub
The form is generated without issue: all check-boxes and the command button are set correctly.
I am then supposed to select which columns I want to hide from my Excel sheet, and therefore I tick the relevant checkbox. So far so good. Here is the code set is a Class :
Option Explicit
Public WithEvents CmdEvents As MSForms.CommandButton
Private Sub CmdEvents_Click()
Dim i As Integer
Dim cbx As MSForms.Control
Dim colNum As Integer
i = 0
For Each cbx In Me.UserForm1.Controls
If TypeName(cbx) = "CheckBox" Then
If cbx.Value = True Then
colNum = cbx.Name - i
Worksheets(1).Columns(colNum).EntireColumn.Delete
i = i + 1
End If
End If
Next ctrl
End Sub
When I click the button, it is supposed to trigger the hiding of the columns in the Excel sheet, however, I got the following error:
Compile error: Method or data member not found
This error is reported in the code in the Class module, highlighting the term .UserForm1 and if I remove this .UserForm1, then still the same error highlighting the .Controls.
I am not a great specialist of VBA, I manage usually to create simple codes and reusing samples I can find here and there, but this time, I run out of idea (and understanding), so thanks in advance for any help.
I'm building a workout logging application that allows the user to add a movement, number of reps, and the associated weight while the userform is running. (You can also think of it as "order-picking" eg. "3" "red" "pencils", "2" "blue" "markers", etc.)
The code adds the two textboxes and the combo box when the "+" button is clicked.
When the "-" button is clicked, only the last added group of controls will be deleted but if the "-" button is clicked again I'll get the "Catastrophic Failure" error message.
I'm pretty sure these controls need to be deleted using controls.remove (object).name but once that last group is deleted, I'll need to update the object variable to the next group that could be removed which I'm struggling with.
I found similar questions on here with answers, but those deleted all userform controls. I only want to remove the last group added.
Option Explicit
Public movementCounter As Integer
Public repsTextBox As Object
Public movementComboBox As Object
Public weightTextBox As Object
Public cntrlsColl As Collection
Private Sub addMvmtCmndButt_Click()
movementCounter = movementCounter + 1
Set repsTextBox = Controls.Add("Forms.TextBox.1")
Set movementComboBox = Controls.Add("Forms.ComboBox.1")
Set weightTextBox = Controls.Add("Forms.TextBox.1")
With repsTextBox
.Name = "RepsTextBox" & movementCounter
.Height = 18
.Width = 45
.Left = 10
.Top = 30 * (movementCounter - 1) + 5
End With
With movementComboBox
.Name = "MovementComboBox" & movementCounter
.Height = 18
.Width = 90
.Left = 65
.Top = 30 * (movementCounter - 1) + 5
.RowSource = listsSht.Range("movementList").Address
End With
With weightTextBox
.Name = "WeightTextBox" & movementCounter
.Height = 18
.Width = 45
.Left = 165
.Top = 30 * (movementCounter - 1) + 5
End With
End Sub
Private Sub deleteMvmtCmndButt_Click()
'Works, but only for the most recently added group of controls
With Me.Controls
.Remove repsTextBox.Name
.Remove movementComboBox.Name
.Remove weightTextBox.Name
End With
'update what the next group of controls will be on-deck
' If movementCounter > 0 Then
' repsTextBox.Name = "RepsTextBox" & movementCounter
' movementComboBox.Name = "MovementComboBox" & movementCounter
' weightTextBox.Name = "WeightTextBox" & movementCounter
' End If
End Sub
Try the following code...
Private Sub deleteMvmtCmndButt_Click()
If movementCounter > 0 Then
With Me.Controls
.Remove "RepsTextBox" & movementCounter
.Remove "MovementComboBox" & movementCounter
.Remove "WeightTextBox" & movementCounter
End With
movementCounter = movementCounter - 1
End If
End Sub
Hope this helps!
I have a form that sets up a list of labels with content and an accompanying checkbox on initialisation.
I want to check the value of a checkbox when a button is clicked.
How do I reference back to the checkbox - I have called the checkbox a number (the value of i) when they are created.
Code to add the checkbox:
Sub addLabel()
Dim theCheck As Object
Dim theLabel As Object
Dim i As Long
Dim LastRow As Integer
LastRow = Worksheets("Assumptions").Cells(Rows.Count, "B").End(xlUp).Row
For i = 1 To LastRow
Set theLabel = UserForm1.Controls.Add("Forms.Label.1", "Assumption" & i, True)
With theLabel
.Name = "Assumption" & i
.Caption = Worksheets("Assumptions").Range("B" & i).Value ' & labelCounter
.Left = 156
.Width = 500
.Top = 138 + i * 20
End With
Set theCheck = UserForm1.Controls.Add("Forms.CheckBox.1", i, True)
With theCheck
.Name = i
.Left = 140
.Width = 10
.Top = 138 + i * 20
End With
Next
End Sub
My ultimate goal is to check which checkbox is 'True' and then IF true enter the accompanying label content into a worksheet.
My main struggle at the moment is how to reference the checkboxes by name (e.g. loop through them all where they are called 1-10 for example.
Thanks
To make reference of an object in your form you can use the following syntax
<Name of your form>.<Name of your control>
In you can I believe that something like UserForm1.1 but this is not a great idea to call your checkbox only with a number, give it with a proper name.
I strongly recommend that you change
With theCheck
.Name = i 'This is not great
.Left = 140
.Width = 10
.Top = 138 + i * 20
End With
By something more explicit like
With theCheck
.Name = "cb" & i 'Not great but better
.Left = 140
.Width = 10
.Top = 138 + i * 20
End With
Loop through each Checkbox in your form
To go through each Checkbox and check if it's checked or not, you can use something like this
'Go through each control in your UserForm
For Each myControl In UserForm1.Controls
'If the current control is a Checkbox
If (TypeName(myControl) = "Checkbox") Then
'Check it's value
If (myControl.Value = True) Then
'Do whatever you want
'You can access your checkbox properties with myControl.YOUR_PROPERTY
End If
End If
Next myControl
I have a class called autoCRUD in a class module in excel 2013. From another module (a regular one) I try to call a method from this class and I get the "Object required" exception.
Here's the method:
Public Function CreateCRUDView(TipoCRUD As String) 'TipoCRUD pode ser C (Create), R (Read), U (Update), D (Delete)
Dim myForm As Object
Dim NewFrame As MSForms.Frame
Dim NewButton As MSForms.CommandButton
Dim NewListBox As MSForms.ListBox
Dim NewLabel As MSForms.Label
Dim X As Integer
Dim Line As Integer
Dim t As Integer
Dim arrLeg() As Variant
arrLeg = legenda
'This is to stop screen flashing while creating form
Application.VBE.MainWindow.Visible = False
Set myForm = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
'Create the User Form
With myForm
.Properties("Caption") = "New Form"
.Properties("Width") = 300
.Properties("Height") = 270
End With
'Criar labels
t = 10
For Each lbl In arrLeg
Set NewLabel = myForm.Designer.Controls.Add("Forms.label.1")
With NewLabel
.name = "lbl_" + Replace(CStr(lbl.Value), " ", "")
.t = (10 + t)
.Left = 10
.Font.Size = 8
End With
t = t + 10
Next
'Create CommandButton Create
Set NewButton = myForm.Designer.Controls.Add("Forms.commandbutton.1")
With NewButton
.name = "cmd_1"
If UCase(TipoCRUD) = "C" Then
.Caption = "Salvar"
ElseIf UCase(TipoCRUD) = "U" Then
.Caption = "Alterar"
End If
.Accelerator = "M"
.Top = Top + 10
.Left = 200
.Width = 66
.Height = 20
.Font.Size = 8
.Font.name = "Tahoma"
.BackStyle = fmBackStyleOpaque
End With
Top = Top + 10
End Function
The code from another module that calls the method is :
Public Sub Main()
Dim ac As autoCrud
Set ac = New autoCrud
ac.CreateCRUDView ("c")
End Sub
I don't get it, why am I getting this error?
Here is the code for "legenda":
Public Property Get sht() As Worksheet
Const shtName As String = "Teste1"
Set sht = ActiveWorkbook.Worksheets(shtName)
End Property
Public Property Get legenda() As Range
Const linha As Integer = 3
Const colunaI As Integer = 2
Dim colunaF As Integer
Dim i As Integer
i = colunaI
Do While sht.Cells(linha, i).Value <> ""
i = i + 1
Loop
colunaF = (i - 1)
Set legenda = sht.Range(Cells(linha, colunaI), Cells(linha, colunaF))
End Property
The lbl.Value is supposed to be a string value, the name of the label. And it comes from the spread sheet in the header of the table, teh legenda() only selects that header and the arrLeg takes the legenda as a range and transforms it in an array.
Edit:
Apparently the error occurs in the line that says: .name = "lbl_" + Replace(CStr(lbl.Value), " ", "")
As you can see, I've tried to take the spaces from the string and also ensure that it is a string, but none of it worked.
Edit 2:
I actually just use a class for organization and re-usability purposes. I take the properties and other methods and use them inside the 'createCRUDView' method, this method will then create a CRUD View, that is, create a form either to "Create", "Read" (not used since it's excel),"Update or "Delete" data entries. It basically creates forms dynamically to any table you make
VBA error 424 is object required error. So I'm now pretty sure that lbl in CStr(lbl.Value) is not an object. With your code legenda is a Range but after
Dim arrLeg() As Variant
arrLeg = legenda
arrLeg will be a variant array. This array does not contain objects. You can debug this with
For Each lbl In arrLeg
...
MsgBox TypeName(lbl)
...
Next
So you should use CStr(lbl).
And
Set legenda = sht.Range(Cells(linha, colunaI), Cells(linha, colunaF))
will only work while the "Teste1" sheet is the ActiveSheet because Cells(linha, colunaI) is not explicit assigned to a sheet so the ActiveSheet will be supposed.
Set legenda = sht.Range(sht.Cells(linha, colunaI), sht.Cells(linha, colunaF))
will be better.
I have created a form where I am dynamically creating Textboxes and corresponding Comboboxes along with Combobox change event. Here is the class creating combobox event handler
Option Explicit
Public WithEvents cbx As MSforms.Combobox
Private avarSplit As Variant
Sub SetCombobox(ctl As MSforms.Combobox)
Set cbx = ctl
End Sub
Private Sub cbx_Change()
Dim i As Integer
If cbx.ListIndex > -1 Then
'MsgBox "You clicked on " & cbx.Name & vbLf & "The value is " & cbx.Value
avarSplit = Split(cbx.Name, "_")
'DecessionOnValue
End If
End Sub
And here is the code on the form which is dynamically creating textboxes and Comboboxes
Function AddTextBox(Frame1 As frame, numberOfColumns As Integer)
Dim counter As Integer
Dim i As Integer
Dim TxtBox As MSforms.TextBox
For counter = 1 To numberOfColumns
'Forms.CommandButton.1
Set TxtBox = Frame1.Controls.Add("Forms.TextBox.1")
TxtBox.Name = "tb_" + CStr(counter)
'Bouton.Caption = "Test"
TxtBox.Visible = True
i = Property.TextBoxDisable(TxtBox)
' Defining coordinates TextBox height is 18
If counter = 1 Then
TxtBox.Top = 23
Else
TxtBox.Top = (18 * counter) + 5 * counter
End If
TxtBox.Left = 50
Next counter
End Function
Function Combobox(Frame1 As frame, numberOfColumns As Integer)
Dim counter As Integer
Dim i As Integer
Dim CbBox As MSforms.Combobox
Dim cbx As ComboWithEvent
If pComboboxes Is Nothing Then Set pComboboxes = New Collection
For counter = 1 To numberOfColumns
'Forms.CommandButton.1
Set CbBox = Frame1.Controls.Add("Forms.ComboBox.1")
CbBox.Name = "cb_" + CStr(counter)
i = AddComboboxValues(CbBox)
' Defining coordinates TextBox height is 18
If counter = 1 Then
CbBox.Top = 23
Else
CbBox.Top = (18 * counter) + 5 * counter
End If
CbBox.Left = 150
Set cbx = New ComboWithEvent
cbx.SetCombobox CbBox
pComboboxes.Add cbx
Next counter
i = AddScrollBar(Frame1, counter)
End Function
Combobox event handler is working fine but my problem is that I dont know that how can I copy the text of textbox or enable disable the textbox according to the value selected in the dynamic combobox.
Thanks,
Jatin
you'll use this for example :
Me.Controls("ControlName").Visible = True or instead of Visible you can use enable, disable etc..