VBA Using Buttons Containing Pre-built Sentences to Build a Message About a Discussion with a Client - excel

Complete noob here. I work for a company where I take phone calls all day and after completing the call I need to document my discussion. I find myself typing the same thing over and over and I'm trying to create a solution using VBA in Excel. I cannot utilize outside programs so I'm stuck on VBA. Below is my code. The goal is to allow a user to click various buttons to build a message covering the topics of the call. I'll then add the ability to copy the message which can then be pasted into the program we use for documenting notes.
As of current:
I'm able to pull from two columns in a table on excel which create buttons for each row (column 1) and when I hover over the buttons I can see the desired text (Column 2), however, clicking the buttons does not display text in the textbox.
Any assistance would be GREATLY appreciated!!
Class1
Option Explicit
Public WithEvents Btn As MSForms.CommandButton
Private Sub Btn_Click()
UserForm1.TextBox1.Text = UserForm1.TextBox1.Text & Btn.Tag & " "
End Sub
UserForm1
Private Sub UserForm_Click()
Option Explicit
Private Btns As Collection
Private Sub UserForm_Initialize()
Dim DataList As ListObject
Set DataList = ThisWorkbook.Worksheets("Sheet1").ListObjects("Table1")
Dim btnTop As Long, btnLeft As Long
Dim btnHeight As Long, btnWidth As Long
Dim btnSpace As Long
Dim ColCount As Long, CurrentCol As Long
btnTop = 6: btnLeft = 6
btnWidth = 72: btnHeight = 24
btnSpace = 6
ColCount = 4: CurrentCol = 1
Set Btns = New Collection
Dim cmdbtn As CommandButton
Dim btnEvent As Class1
Dim itm As Range
For Each itm In DataList.ListColumns(1).DataBodyRange
Set cmdbtn = Me.Controls("Frame1").Controls.Add("Forms.CommandButton.1")
With cmdbtn
.Top = btnTop
.Left = btnLeft
.Width = btnWidth
.Height = btnHeight
.Caption = itm
.Tag = itm.Offset(, 1)
.ControlTipText = .Tag
End With
Set btnEvnt = New Class1
Set btnEvnt.Btn = cmdbtn
Btns.Add btnEvnt
btnLeft = (btnSpace + btnWidth) * CurrentCol + btnSpace
If CurrentCol Mod ColCount = 0 Then
CurrentCol = 1
btnTop = btnSpace + btnTop + btnHeight
btnLeft = btnSpace
Else
CurrentCol = CurrentCol + 1
End If
Next itm
Me.Frame1.ScrollHeight = btnTop + btnHeight + btnSpace
End Sub

Related

Userform works despite Run-Time Error 91. What's going on?

I am new to Userforms. I have created the following Userform which is called from a subroutine. The Userform picks up a range from a sheet and creates a corresponding number of textboxes and then checkboxes so as to allocate an original name with a new name.
The userform is created with the following:
Public Sub UserForm_Initialize()
'Declare variables
Dim txtBox As MSForms.TextBox
Dim comBox As MSForms.ComboBox
Dim i As Integer
Dim j As Integer
Dim n As Integer
Dim dist As Integer
Dim dstArr As Variant
Dim rng As Range
'Assign variables
Set rng = Range("Missing_MAERSK")
n = rng.Rows.Count
dist = 5
dstArr = Range("LU_Destination_Ports").Value
'Loop to add textboxes
For i = 1 To n
Set txtBox = UserForm1.Controls.Add("Forms.TextBox.1", Visible:=True)
With txtBox
.name = "txtBox" & i
.Value = rng(i)
.Height = 20
.Width = 150
.Left = 81
.Top = 30 + dist
.Font.Size = 10
End With
dist = dist + 20
Next i
'Loop to add list boxes
dist = 5
For j = 1 To n
Set comBox = UserForm1.Controls.Add("Forms.ComboBox.1", Visible:=True)
With comBox
.name = "comBox" & j
.List = dstArr
.Height = 20
.Width = 150
.Left = 315
.Top = 30 + dist
.Font.Size = 10
End With
dist = dist + 20
Next j
'Show userform
UserForm1.Show
End Sub
And then when the Replace Names button is clicked the following is ran:
Public Sub CommandButton1_Click()
'Close userform
Unload UserForm1
'This is the one
Dim cmb As MSForms.ComboBox
' Dim txt As MSForms.TextBox
Dim oldVal As String
Dim newVal As String
Dim rng As Range
Dim rng2 As Range
Dim n As Integer
Set rng = Range("MAERSK_Destin")
Set rng2 = Range("Missing_MAERSK")
n = rng2.Rows.Count
'Loop
For i = 1 To n
Set txt = Me.Controls("txtBox" & i)
Set cmb = Me.Controls("comBox" & i)
If cmb.Value <> "" Then
oldVal = txt.Value
newVal = cmb.Value
rng.Replace what:=oldVal, Replacement:=newVal
End If
Next i
End Sub
Let's say I populate Bangkok to Bangkok BMT, I get the following:
I think the issue might be with the way I call the values in the Command_Button1_Click sub.
Any advice would be appreciated.
Cheers
Figured out the problem.
According to this post: Call UserForm_Initialize from Module
a UserForm should not be initialized from outside the userform.
I was calling UserForm_Initialize() from my sub, so to rectify this I replaced it with UserForm1.Show

Get and write a value to a sheet from a textbox created dynamically in a UserForm

I have a UserForm composed of a TextBox and a CommandButton.
By entering a value in the TextBox, for example 3, and clicking the CommandButton, I create three new TextBox with labels linked to each one of them. It also creates just under those TextBox and Labels another CommandButton.
I write in each new TextBox a value. For example in the first TextBox I write "Banana", in the second "Apple" and so on.
I want by clicking the new CommandButton, to get the value from the new TextBoxes and write them in a sheet.
How do I get the value from these new TextBoxes considering they are created during the runtine.
Here is the code linked to my UserForm:
Option Explicit
Dim cmdArray() As New Classe1
Public Sub nbEquipButtonValidation_Click()
Dim i As Variant
Dim Nb_equip As Integer
Dim j As Long
Nb_equip = UserForm1.nbEquipTextBox.Value
For i = 1 To Nb_equip
Dim EquipLabel
Dim Text_Boxes
Dim CmdBtn
Set EquipLabel = Me.Controls.Add("Forms.Label.1")
With EquipLabel
.Top = 25 + 10 * i * 2
.Left = 10
.Caption = "Equipement n°" & CStr(i)
.Name = "Equip" & CStr(i)
End With
Set Text_Boxes = Me.Controls.Add("Forms.TextBox.1", True)
With Text_Boxes
.Top = 20 + 10 * i * 2.1
.Left = 100
.Name = "Text_Box" & CStr(i)
End With
Next i
Set CmdBtn = Me.Controls.Add("Forms.CommandButton.1")
With CmdBtn
.Top = 20 + 10 * Nb_equip * 2.1 + 30
.Left = 75
.Caption = "Créer"
.Name = "Validation"
End With
' Apply a class to the new Button
j = 1
ReDim Preserve cmdArray(1 To j)
Set cmdArray(j).CmdEvents = CmdBtn
Set CmdBtn = Nothing
End Sub
Here is the class I created to get these data and write them in a sheet by clicking the second CommandButton.
Option Explicit
Public WithEvents CmdEvents As MSForms.CommandButton
Private Sub CmdEvents_Click()
Dim Ws As Worksheet
Set Ws = Worksheets("Sheet1")
Dim i As Variant
Dim Nb_equip As Integer
Nb_equip = UserForm1.nbEquipTextBox.Value
For i = 1 To Nb_equip
With Ws
.Cells(6, 2 + i * 2).Value = "Exp" & CStr(i)
End With
Next i
End Sub
In my loop I want to replace "Exp" & CStr(i) by the name of the value in the TextBox according to the position i of creation.
This should work:
Modify your class to add a reference to the Form object:
Option Explicit
Public WithEvents CmdEvents As MSForms.CommandButton
Public frm As Object '<<<<<<<<<<<
Private Sub CmdEvents_Click()
Dim Ws As Worksheet
Set Ws = Worksheets("Sheet1")
Dim i As Variant
Dim Nb_equip As Integer
Nb_equip = frm.nbEquipTextBox.Value
For i = 1 To Nb_equip
Ws.Cells(6, 2 + i * 2).Value = frm.Controls("Exp" & CStr(i)).Text
Next i
End Sub
Then add the line below:
Set cmdArray(j).CmdEvents = CmdBtn
Set cmdArray(j).frm = Me '<<<<<<<<

Add Textboxes to Userform Frame based on a Cell Value

I want a user to press a button to pull all their "Open" positions into a userform.
I have a Userform with a Frame and a command button to search through Column 3 (named "Status") on a spreadsheet and find the word "Open". Once this word is found I want textboxes to be automatically created inside the frame with the data from the "found" row for columns 4 - 10.
So if one row is found with "Open" then I expect 7 textboxes to be created on the userform. From the picture below I expect 28 textboxes.
When I press the command button nothing happens - no errors - nothing. I tried to use the breakpoints to troubleshoot but nothing was revealed to me to take action on. I am not "seeing" why it is not working here.
I tried moving the code outside the userform and into a module and calling the function but that didn't do anything.
I tried setting the rows I want as constants and creating a separate "AddBox" function to call within the main code but that didn't work but I also didn't understand that code as much as I do the one I am posting now.
Frame Name = Open_Positions_Frame
Command Button Name = open_post_but
Sheet Name = Database
Public Sub open_post_but_Click() '*****The command Button on the userform Frame*****
Dim i As Integer ' for the loop
Dim wb As Workbook
Dim wk As Worksheet
Dim ctlTextBox As MSForms.TextBox
Dim intCol, intCols As Integer '******for the columns I want to pull into the userform*****
Dim strCName As String '******this is to name the textboxes******
Dim lastRow As Long
Dim curColumn As Long
Set wb = ThisWorkbook
Set wk = wb.Sheets("Database")
curColumn = 3 '*********column index here - Mine starts at Column 3 ********
lastRow = wk.Cells(Rows.Count, curColumn).End(xlUp).row
For i = 3 To lastRow 'Loop through row 3 to last row
'********If the text "Open" is found in a row in column 3 then
' add & fill textboxes with data from Columns 4-10 onto the userform frame******
If wk.Cells(i, 3) = "Open" Then
'******Add the textboxes***********
'*****Columns 4-10 add textbox and give the control a name C# - #is the column*****
For intCol = 4 To intCols = 10
strCName = "C" & intCol
Set ctlTextBox = Open_Positions_Frame.Controls.Add("Forms.Textbox.1", strCName)
With ctlTextBox
.Top = 10
.width = 50
.height = 20
.Left = (intCol) * 60
.Value = intCol
End With
Next
'********************************
End If
Next i
End Sub
UPDATED and TESTED
You were writing the text boxes on top of each other. i added a separater by row.
Public Sub open_post_but_Click()
'you might want to experiment with these.
Const curColumn As Long = 4 'index will start a column 4 "Status"
Const theWidth As Long = 66 'you might experiment with these
Const theRowDifference As Long = 20
Dim i As Long, intCol As Long, rowspacer As Long
Dim ctlTextBox As MSForms.TextBox
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wk As Worksheet: Set wk = wb.Sheets("Database")
Dim lastRow As Long: lastRow = wk.Cells(Rows.Count, curColumn).End(xlUp).row
For i = 3 To lastRow
For Each cl In wk.Cells(3, curColumn)
If InStr(1, cl.Value, "Open", vbTextCompare) > 0 Then
rowspacer = rowspacer + theRowDifference
'******Add the textboxes***********
For intCol = 5 To 11
Set ctlTextBox = Open_Positions_Frame.Controls.Add("Forms.Textbox.1")
With ctlTextBox
.Top = rowspacer
.width = theWidth
.height = 20
.Left = intCol * 60
.Name = "openPosBox" & intCol
.Value = wk.Cells(i, intCol).Value
End With
Next intCol
'********************************
End If
Next cl
Next i
End Sub
PGSystemTester helped figure out the stacking textbox issues - Huge thank you! However, I was still struggling with my If Condition statement. I managed to figure it out and I am adding the complete code as an answer for anyone needing this use case
Public Sub open_post_but_Click()
Const curColumn As Long = 4 'index will start a column 4 "Status"
Const theWidth As Long = 70 'you might experiment with these
Const theRowDifference As Long = 20
Dim i As Long, intCol As Long, rowspacer As Long
Dim ctlTextBox As MSForms.TextBox
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wk As Worksheet: Set wk = wb.Sheets("Database")
Dim lastRow As Long: lastRow = wk.Cells(Rows.Count, curColumn).End(xlUp).row
Dim status As String
status = "Open"
For i = 3 To lastRow
If Cells(i, curColumn).Value = status Then 'took on the Instr() function and added this instead, textboxes will only be created if the column 4 status is "Open"
rowspacer = rowspacer + theRowDifference
'******Add the textboxes***********
For intCol = 4 To 11
Set ctlTextBox = Open_Positions_Frame.Controls.Add("Forms.Textbox.1")
With ctlTextBox
.Top = rowspacer
.width = theWidth
.height = 20
.Left = intCol * 40
.Name = "openPosBox" & intCol
.Value = wk.Cells(i, intCol).Value
End With
Next intCol
'********************************
End If
Next i
End Sub

VBA obtaining checkbox values from userform

I'm having trouble obtaining values from checkboxes of a userform. The problem I have is that the userform creates a variable number of checkboxes based on a value from a sheet. The code for this:
Private Sub UserForm_Initialize()
Dim LastRow As Long
Dim i As Long
Dim Teller As Long
Dim chkBox As MSForms.CheckBox
Teller = 1
LastRow = Worksheets("Sheet").Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To LastRow
If Worksheets("Sheet").Cells(i, 1).Value = Worksheets("Sheet").Range("S1").Value Then
Set chkBox = Me.Controls.Add("Forms.CheckBox.1", "CheckBox_" & Teller)
chkBox.Caption = Worksheets("Sheet").Cells(i, 9).Value
chkBox.Left = 5
chkBox.Top = 25 + ((Teller - 1) * 20)
Teller = Teller + 1
End If
Next i
End Sub
So this creates a number of checkboxes named CheckBox_1, CheckBox_2 etc.
The problem is when I try to get the value for CheckBox_1 in the module, CheckBox_1 has not yet been created so I'm not able to use it.
Dim x as String
With UserForm4
.Show
x = .CheckBox_1
MsgBox (x)
End
End With
You'll need to loop through .Controls the textbox is not a property on your form.

vba dynamically created checkboxes onclick events

I have a list of checkboxes on a userform created from a list on an Excel sheet.
I want to have an additional checkbox that when checked, is testing the caption value of all the checkboxes in the list. If there is a match to a target string, these checkboxes should check as well.
I can create the list but referencing the checkboxes after creation and triggering events is the issue. So far this is all I have:
Private Sub UserForm_Initialize()
Dim curColumn As Long
Dim LastRow As Long
Dim i As Long
Dim chkBox As MSForms.CheckBox
curColumn = 1 'column index
LastRow = Worksheets("Parts").Cells(Rows.Count, curColumn).End(xlUp).Row
For i = 2 To LastRow
Set chkBox = Me.Controls.Add("Forms.CheckBox.1", "CheckBox_" & i)
chkBox.Caption = Worksheets("Parts").Cells(i, curColumn).Value
chkBox.Left = 5
chkBox.Top = 25 + ((i - 1) * 20)
chkBox.Width = 200
Next i
End Sub

Resources