Update SQL Table from Userform (Excel VBA) - vba

I have a table that lists Departments and Passwords in SQL Server. I am creating a Userform UI so that users are able to view list, amend an entry or delete an entry.
I have made it look like this:
I managed to set up the ADODB connection when a user opens the form, it would automatically load the list using:
Private Sub Userform_Activate()
My rational is that I want a user to select from the list box, it would display the Department and Password in textbox1 and textbox2, respectively.
The user then can either Update the record or Delete the record. This would be a very straight-forward SQL operation.
What I am hitting a road block with at the moment is actually getting the data displayed in Textbox1 and Textbox2.
Code
Private Sub Select_Click()
If Me.ListBox1.Selected(i) Then
Me.TextBox1 = Me.ListBox1.List(i, 0)
Me.TextBox2 = Me.ListBox1.List(i, 1)
End If
End Sub
Any advise would be appreciated.
Furthermore, is my logic sound? Or is there a better way of doing things?
I know this is 2-in-1 question, but thanks!

Just tested and this works.
Private Sub ListBox1_Click()
TextBox1.Value = ListBox1.List(ListBox1.ListIndex, 0)
TextBox2.Value = ListBox1.List(ListBox1.ListIndex, 1)
End Sub

Related

Can you reference the control name within a sub in vba?

So I'm attempting to filter a large section of data in a spreadsheet with checkboxes. So far around 80 individual checkboxes. I'm wondering if there is anyway to refer to the checkbox (or any other control) name within the sub, as a specific reference, i.e. thiscontrol.name. At present the first checkbox reads:
Private Sub_F1_Click()
StringVariableForLaterUse ="F1"
If F1.Value = True Then
'Display Data Relevant to F1
End If
End
I'm wondering if I can use
StringVariableForLaterUse = ThisControl.Name
and
If ThisControl.Value = True Then
I'd then be able to replicate this a further 78 times. Currently pure laziness factor, however I want my Subs to be self sufficient as possible. Any thoughts folks?
You can never use a string like an object... But, for an ActiveXcheck box, use the next workaround code.
Public chk1 As Shape
Private Sub CheckBox1_Click()
Set chk1 = ActiveSheet.Shapes(CheckBox1.Name)
MsgBox chk1.OLEFormat.Object.Object.value
End Sub
You can use now chk1 in another Sub inside the sheet module.
You can also refer to it from a module Sub, referencing the sheet, too:
Sub testSheetChk()
Debug.Print Worksheets("Sheet Name").chk1.OLEFormat.Object.Object.value
End Sub
But, this will work only after you firstly run (once) the click event, in order to alocate a value to the object variable.

Userform in Excel to control the flow of a macro

This has got to be ridiculously easy, but I just cannot figure it out searching the web.
I have an Excel macro that performs various data entry/manipulation tasks. There is a point in the macro where I want the user to have the option of using data in column A or column B for calculations. All I want is to call a userform with two command buttons which pass their "true" or "false" value to the main macro and then perform "if" statements based on this information.
The trouble is I cannot get the userform to "tell" the macro anything. I'm sure this is a major noob question and I'm missing the method, but I cannot get this to work. Thank you!
Edit, I've attached the userform code below by request:
Private Sub CommandButton1_Click()
Unload Me
End Sub
Private Sub OptionButton1_Click()
End Sub
Private Sub OptionButton2_Click()
End Sub
Private Sub UserForm_Initialize()
End Sub
you could avoid userform for that and use a simple message box:
If MsgBox("use data in column A or B [Yes=A, NO=B]", vbYesNo) = vbYes Then
' code for using data in column A
Else
' code for using data in column B
End If

Excel VBA - Remember Last Userform Textbox Cursor Focus

I have 10 text boxes on an Excel VBA Userform, and when I switch away from the window (say, to do other work in a different program) and come back, I want the focus to be on the textbox I was last using.
I think this should be an obvious question to an experienced person, but I can't find a well-asked question about this topic anywhere. If anyone can direct me to a proper answer, give me a searchable topic, or a good piece of code, that would be golden. I'm a sponge, I'll take anything.
Thank you!
-Chris
Cursor focus is not an event in VBA, thus it is a bit tough to do it. BUT you can use the _Change event and remember the last changed Textbox, which is quite close to you want.
You need a public variable in a module, for the name of the last changed TextBox. Thus, the next time the Form is activated, you may use a simple select case and use .SetFocus to the corresponding name of the form. The code below works with two TextBoxes.
In the form:
Option Explicit
Private Sub TextBox1_Change()
strLastTb = "TextBox1"
End Sub
Private Sub TextBox2_Change()
strLastTb = "TextBox2"
End Sub
Private Sub UserForm_Activate()
Select Case strLastTb
Case "TextBox1"
TextBox1.SetFocus
Case "TextBox2"
TextBox2.SetFocus
End Select
End Sub
In a module:
Option Explicit
Public strLastTb As String
In general, you may create a function that concatenates TextBox&Digit, so you will not be required to write 100s lines if you have 50 TextBoxes. And it would be looking better.

using one sub for multiple buttons in excel vba

I have a spreadsheet containing client data, one client per row and each row has a button that launches a userform showing the data for that client, you can then update the data for that client and write it back to the row for that client. Before we start using the spreadsheet each case worker will filter so that only their clients are shown.
I wondered whether there is a way of having one command button procedure for the buttons on each row ie when you press the button in row 6 it runs a procedure for CommandButton6 to call the data in that row, when you press the button in row 8 it runs a procedure for CommandButton8 to call the data in row 8. However the procedure for both is the same so can I have a CommandButtoni sub where I is the row number.
It is a very simple procedure but I don't want to have to copy it 350 times!
Private Sub CommandButton1_Click()
UserForm1.TextBox1.Value = Worksheets("Sheet1").Range("C2").Value
GetData
UserForm1.Show
End Sub
You would need a parameterized Click handler, which you can't have in VBA. You could assign 350 form buttons to the same handler procedure, but they would all assign UserForm1.TextBox1.Value whatever is in Worksheets("Sheet1").Range("C2").Value, and actually reading your question you seem to want to have some "row parameter".
Having 350 form/ActiveX buttons on a worksheet is generally not a very good idea: I'd try to think of a different approach instead.
Is the Selection in the row you need it to be when a button is clicked? You could make the current/active row highlight somehow (handle SelectionChanged worksheet event), and have one button somewhere (in the Ribbon?) that works off the Selection:
UserForm1.TextBox1.Value = Sheet1.Range("C" & Selection.Row).Value
Other than that, Rory's suggestion would work... but form buttons weren't intended to be used like this.
After implementing Rory's suggestion, I think it is the simplest and most elegant code solution. Allows copy and paste of the buttons without any further configuration if done uniformly with the code.
Sub AddVote()
' This is a simple vote tally counter. Each time a button is clicked,
' the vote count in the third column is incremented by one.
' Imagine: first column = candidate name; second column holds form button;
' Thid column = vote count
' Create a Form button and assign this macro. Copy and paste button!
Dim rngTally As Range
' Use rngTally to point to the cell in the third column (3, in the formula)
' in the same row as the top left corner of the button.
Set rngTally = Cells(ActiveSheet.Buttons(Application.Caller).TopLeftCell.Row, 3)
' Increment the value of the cell pointed to by rngTally by 1
rngTally = rngTally + 1
End Sub
If you don't want/need to design a custom user form, you could use the Form... command:
Click the Customize Quick Access Toolbar drop-down menu in the Excel
Title Bar.
Select More Commands.
If the document will be distributed to other users, change the "For all documents (default)" option to the document name.
Select to Choose commands from: Commands Not in the Ribbon.
Select the Form... command.
Click Add to add the button to the right side menu.
Click OK.
With any cell in a table selected, click the Form button. Edit and press Enter. Could also use Criteria to filter on a value. Unfortunately no way to edit the form, but useful for narrow cell contents. No coding required.
https://support.office.com/en-us/article/Add-edit-find-and-delete-rows-by-using-a-data-form-9443c80d-66c6-4c17-b844-64aac5ae841d
A neater way for a sub for each button.
Private Sub Delete0_Click(): DeleteRow (0): End Sub
Private Sub Delete1_Click(): DeleteRow (1): End Sub
Private Sub Delete2_Click(): DeleteRow (2): End Sub
Private Sub Delete3_Click(): DeleteRow (3): End Sub
Private Sub Delete4_Click(): DeleteRow (4): End Sub
Sub DeleteRow(row As Integer)
Debug.Print "DeleteRow(" & row & ")"
End Sub

Is it possible set my Excel Userform Combo box to begin narrowing the fields while data is entered?

VBA Newbie here.
I have searched high and low for this answer, and even come across other questions very similar to mine, but cannot get an answer. So I am hoping that this is my lucky day.
I have a Userform in excel that has Four combo boxes. Each combo box has a drop down with several choices. In two of these boxes, there are many business names and a lot of these names are similar. I was wanting to have the feature where are the data was being typed into the box, it would begin to narrow the options. EXAMPLE: if I type "heating and air" it begins to only show items in the list that include that word or phrase.
Is this a properties change in the box, or a code written, or something else?
Please help- I am stumped and no one seems to have the answer.
Very grateful-
Excel Newbie
Yes this is very possible. All you have to do is create a sub that populates that combo box, set it up so that when adding it checks the value of the box for example if it was the basic typing example. basic format. This assumes the possible values are stored in an array. This would add any item that has the string entered in it. (in any position)
For I = 0 to Number of Values
If instr(Value(I), ComboBox.Text) > 0 then
add item
endif
next
I played around a bit and came up with something to get you started. This basically functions as an "auto search". It is not autocomplete because it will search entire terms, not just terms which begin with whatever you've typed in. Basically I assume you have a range of cells (in this example cells A2:A121) that have the date for your drop down in it.
Setup
Add a new generic module (I named mine GlobalVars and add the following code:
Option Explicit
Public IgnoreChange As Boolean
Public RangeOfData As Variant
The Code
Open the code to your UserForm.
Add the following code:
Private Sub UserForm_Initialize()
RangeOfData = Application.WorksheetFunction.Transpose(Sheet1.Range("A2:A121").Value)
IgnoreChange = False
End Sub
Be sure to update A2:A121 and Sheet1 (I am using code name, but Worksheets("Sheet1") would work just as well) to point to the data which contains your combobox choices.
Now, the meat of the job is handled in the Combobox_Change event
Private Sub ComboBox1_Change()
If Me.ComboBox1.Text = vbNullString Then
Me.ComboBox1.Clear
SendKeys ("{Enter}")
End If
If Me.ComboBox1.TextLength > 2 Then
Dim i As Long, j As Long
If IgnoreChange = False Then
Me.ComboBox1.Clear
SendKeys ("{Enter}")
DoEvents 'Bug with NumLock
For i = LBound(RangeOfData) To UBound(RangeOfData)
If UCase(RangeOfData(i)) Like "*" & UCase(Me.ComboBox1.Text) & "*" Then
Me.ComboBox1.AddItem RangeOfData(i)
End If
Next i
Me.ComboBox1.DropDown
End If
End If
IgnoreChange = False
End Sub
Be sure to change ComboBox1 to the name of your combobox control.
Basically, what this does is it handles user input when it reaches two characters or longer. The code will search through your input data range and then return results that match the string as the user is entering it. The results is like a suggestions box.
I should note that with this method, the combobox is NOT pre-populated with data, so users must begin typing something into the combobox.
Additionally, I added the following code to handle the backspace key:
Private Sub ComboBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 8 Then
IgnoreChange = True
End If
End Sub
Again be sure to change ComboBox1 as appropriate.
For my example, I loaded all 120 crayola crayon colors into a spreadsheet (that is what is in Sheet1 from A2:A121).
Here is example output for when I start typing, first I input blu:
As you can see I am getting all values that contain blu, including those that don't start with blu such as Cadet Blue or Midnight blue.
As another example, I will search for flower
So as you can see, instead of being a combobox with 120 static options, it is updated based on what the user types and tied to a list of values in your cells.
I did notice that SendKeys sometimes toggled my NumLock, this is a known issue. The point of that line is to collapse the drop down after the user deletes all of the text or continues texting so as to "refresh" the auto-generated list.