How to select highlighted listbox item to add to textbox - excel

My code has a listbox filled with common small strings of text that the user can click to add to a texbox instead of manually typing them out.
It works in everyway except the previously selected item cannot be clicked again to add to textbox.
I've tried setting listbox.selected = -1 and listbox1.value ="" and when I do this the text is added twice and not unselected.
At one point I was able to make a button that just does listbox1.value = "" and it worked, but when I add it after my code it fails and does the double text thing.
Private Sub ListBox1_Click()
For i = 0 To ListBox1.ListCount - 1
If ListBox1.selected(i) Then
selecteditemtext = ListBox1.List(i)
End If
Next i
TextBox2.Text = TextBox2.Text & selecteditemtext & ", "
What I need it for the selected listbox item become unselected after being clicked so it can be clicked again if needed.
When I run this code line by line it works. but all together it adds the text twice.
Private Sub ListBox1_Click()
For i = 0 To ListBox1.ListCount - 1
If ListBox1.selected(i) Then
selecteditemtext = ListBox1.List(i)
End If
Next i
TextBox2.Text = TextBox2.Text & selecteditemtext & ", "
call listdeselect
end sub
sub listdeselect()
sheet1.listbox1.value = ""
end sub

I believe I have your solution :)
Control the deselection in the MouseUp event as shown below:
Private Sub ListBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
ListBox1.ListIndex = -1
End Sub
As long as you don't interrupt the MouseUp event (such as with a MsgBox), this seems to work fine.
Sample code I have used is below:
Private Sub UserForm_Activate()
ListBox1.AddItem "asd"
ListBox1.AddItem "sad"
ListBox1.AddItem "dsa"
ListBox1.AddItem "das"
End Sub
Private Sub ListBox1_Click()
Sheets(1).Cells(1).Value = ListBox1.List(ListBox1.ListIndex)
'MsgBox "hi" 'notice this disrupts the MouseUp event...
End Sub
Private Sub ListBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
ListBox1.ListIndex = -1
End Sub
I hope this resolves your issue,
Cheers

Related

Listbox_Click run command before selecting new entry

Is it possible to run a command inbetween the moment a user clicks on a listbox item (in a userform) and the item being selected?
I have a mask with a listbox as index and want to make it possible when a user goes to another item, the entries are automatically saved. At the moment I am doing it with a button but I want to prevent the situation that a user goes to a different item and loses all the information put in because he forgot to press the button.
my code if you click on the listbox:
Private Sub ListBox1_Click()
Dim lrow As Long
Values_delete 'Sub that clears all text boxes
If ListBox1.ListIndex >= 0 Then
lrow = 2
Do While Trim(CStr(Tabelle10.Cells(lrow, 1).Value)) <> ""
If ListBox1.Text = Trim(CStr(Tabelle10.Cells(lrow, 1).Value)) Then
Values_read (lrow) 'values get read from the excel cells and written into the text boxes
Exit Do
End If
lrow = lrow + 1
Loop
End If
End Sub
As well as my code for the save button:
Public Sub SaveButton_Click()
Dim lrow As Long
If ListBox1.ListIndex = -1 Then Exit Sub
If Trim(CStr(Abteilung.Text)) = "" Then
MsgBox "Error", vbCritical + vbOKOnly, "Error"
Exit Sub
End If
lrow = 2
Do While Trim(CStr(Tabelle10.Cells(lrow, 1).Value)) <> ""
If ListBox1.Text = Trim(CStr(Tabelle10.Cells(lrow, 1).Value)) Then
Values_write (lrow) 'Values get written into the cells
If ListBox1.Text <> Trim(CStr(Abteilung.Text)) Then
Call UserForm_Initialize
If ListBox1.ListCount > 0 Then ListBox1.ListIndex = 0
End If
Exit Do
End If
lrow = lrow + 1
Loop
End Sub
Is this even possible?
Try MouseDown event that fires before updating anything. When you click on a new item,
.Selected or .Listindex points to the previous item within Mousedown. Then you can use MouseMove event to process the lately selected item.
I'm assuming you are using either an ActiveX control on your sheet OR a UserForm control so;
You can use the MouseDown event; below will print the text of the previously selected item (based on the user clicking a new item)
Private Sub ListBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Debug.Print ListBox1.Text
End Sub
MS Documentation breifly mentions this event: See here

VBA Placeholder text that disappears only upon typing, not when entering textbox on UserFrom

' I'm looking to create placeholder text (ghosting text) to help users know what to type in the field, but I want it to act very similar to on-line forms where the placeholder text does not disappear upon entering a textbox, but only disappears if you type new text into it.
' enterfieldbehavior is set to 1 - fmEnterFieldBehaviorRecallSelection in properties to avoid selecting placeholder text
Private Sub userform_initialize()
TextBox2.Value = "Name" 'upon starting UserForm, the placeholder text is launched in the textbox
TextBox2.ForeColor = &H8000000C 'grey
End Sub
Private Sub TextBox2_Enter()
If TextBox2.Text <> "Name" Then
TextBox2.SelStart = TextBox2.SelLength 'Upon entering the textbox, the cursor is placed only at the start and not the middle or end of the placeholder text
Else
' I need the oppositie of the above, to put the cursor at the end of text as the placeholder text is gone
End If
End Sub
Private Sub TextBox2_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
TextBox2.SelStart = TextBox2.SelLength ' If a user uses the mouse to enter the textbox
End Sub
Private Sub TextBox2_Change()
If TextBox2.Text <> "Name" Then
TextBox2.Text = ""
TextBox2.ForeColor = &H8000000C 'grey
Else
TextBox2.Value = TextBox2.Value ' This is where I'm lost as I want to earse the holder text, and let the user type whatever they want
TextBox2.ForeColor = vbBlack
End If
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If TextBox2.Text = "" Then
TextBox2.Text = "Name" ' If there are no changes to the textbox, replace the placeholder text
TextBox2.ForeColor = &H8000000C 'grey
Else
End If
End Sub
Here is how I would do it:
Private Sub Label1_Click()
TextBox1.SetFocus
End Sub
Private Sub TextBox1_Change()
Label1.Visible = Len(TextBox1.Text) = 0
End Sub
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Label1.Visible = Len(TextBox1.Text) = 0
End Sub
Private Sub UserForm_Initialize()
With Label1
.SpecialEffect = fmSpecialEffectSunken
.BackColor = vbGrayText
.Caption = " Name"
End With
End Sub
The easiest solution in only 1 line of code is:
Duplicate (copy/paste) your TextBox2 and name it e.g. TextBox2PlaceHolder
Set its Text property to whatever placeholder value you want, eg. "YYYY/MM/DD"
Set its Enabled property to False so that text color will be light gray
Send it to the background just behind your original TextBox2 (same Left and Top properties)
And finally, the masterpiece of code below will just switch the TextBox2.BackStyle to transparent if no text exists and so will let the placeholder appear!
Private Sub TextBox2_Change()
TextBox2.BackStyle = IIf(Len(TextBox2.Text) = 0, fmBackStyleTransparent, fmBackStyleOpaque)
End Sub
Here's what that looks like:

Excel form - go to last selected value

I'm trying to get a listbox from an excel form to set focus on the last selected value.
Because the listbox is multiselect, if I use the code below, it will deselect things that i want to remain selected:
With Me.listName
For lsti=0 To .listCount-1
If .selected(lsti) Then
lastSelectedIndex = lsti
End If
Next
If lastSelectedIndex >-1 Then
.listindex = lastSelectedIndex 'this causes other items to become deselected
End If
End With
Is there a way i can set focus to the last selected item, without items being deselected?
In what "event" you put this code? If it is in _click or _change?
This line of code will re-trigger the event
.listindex = lastSelectedIndex
Use this technique:
Declare a module level variable
Option Explicit
Public mbCancel As Boolean
Then use this code
Private Sub myListName_Change()
If mbCancel Then Exit Sub
With myListName
'
If lastSelectedIndex >-1 Then
mbCancel=true
.listindex = lastSelectedIndex
mbCancel=false
End If
Thanks M.R for your idea, but it made me realise i was not calling the function correctly.
I have a second list box that i use as a filer with unique values, and i should change the focus only when using the filter. I was also changing the focus on MouseUp on the main listbox, whitch now with a clear head, makes no sense.
So i used the following code separatelly, to change the focus:
Private Sub lstFilter_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'filterMainList
'addIdsToSelected
setFocusToLast
End Sub
Sub setFocusToLast()
Dim indexI, lastSelectedId, currentId
Dim lstI
With Me.lstFilter
indexI = .listIndex
lastSelectedId = .LIST(indexI, 0)
End With
With Me.lstIds
For lstI = .listCount - 1 To 0 Step -1
currentId = .LIST(lstI, 0)
If currentId = lastSelectedId Then
.listIndex = lstI
Exit For
End If
Next
End With
End Sub

Excel - Unicode named cell range

I have written a small function to expedite naming cells:
Public Sub InputSelectedNames()
For Each Cell In Selection
On Error Resume Next
Dim strName As String
strName = InputBox("Enter name for cell " & Cell.Address(False, False) & ":", "Name cell")
If Len(strName) = 0 Then
Exit Sub
End If
ActiveSheet.Names.Add Name:=strName, RefersTo:=Cell
Next Cell
End Sub
This works great until I try to enter a unicode string as a name. If I enter something like "αβγ" it appears as "aß?" in the InputBox.
I've read about VBA using ANSI encoding so I understand why this is the case. The example solution given in that tutorial works for displaying unicode (by passing a pointer instead of a string object), but I wasn't able to utilize the same idea for an InputBox.
If I enter these characters through Excel's 'Define Name' button on the formula tab, or through referencing the character in another cell it works fine, so the mistranslation definitely seems to lay in the InputBox.
My guess is that I'll have to make a Userform to handle the input, unless anyone knows a way to get InputBox to play nicely with unicode?
Creating a custom InputBox did solve this problem.
frmInputBox : UserForm
lblOutput : Label providing prompt
txtInput : TextBox for input
cmdOK : CommandButton for accepting input
cmdCancel : CommandButton for aborting prompt
VBA Form Code:
Private Sub cmdOK_Click()
Accept
End Sub
Private Sub cmdCancel_Click()
Cancel
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel
End Sub
Private Sub txtInput_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = vbKeyReturn Then
Accept
ElseIf KeyCode = vbKeyEscape Then
Cancel
End If
End Sub
Private Sub Accept()
Me.Hide
End Sub
Private Sub Cancel()
txtInput.Text = ""
Me.Hide
End Sub
Public Function Prompt(strPrompt As String, Optional strTitle As String = "Input", Optional strDefault As String = "")
With Me
.Caption = strTitle
.lblOutput.Caption = strPrompt
.txtInput.Text = strDefault
.StartUpPosition = 0
.Left = Application.Left + (0.5 * Application.Width) - (0.5 * .Width)
.Top = Application.Top + (0.5 * Application.Height) - (0.5 * .Height)
.Show
End With
If txtInput.Text <> "" Then
Prompt = txtInput.Text
Else
Prompt = ""
End If
Unload Me
End Function
Called like:
strMyName = frmInputBox.Prompt("What's your name?", "Name Prompt")

How to select the contents of a textbox once it is activated?

I have this simple Userform, where I only have TextBox1 and TextBox2. I enter some text in both of them. Assume the focus is on (the cursor is in) the TextBox2. When I click on TextBox1, I want the whole text in this control to be highlighted (selected). Thus I use this code:
Private Sub TextBox1_Enter()
With TextBox1
.SetFocus
.SelStart = 0
.SelLength = Len(.Text)
End With
MsgBox "enter event was fired"
End Sub
There is a MsgBox at the end which is loaded, that means the event works. However, the text is not highlighted. How to fix this?
I use the Enter event and don't want to use the MouseDown event, because I need the code to also work when the TextBox1 is activated programatically, so I feel the Enter event to be the best choice, as it's fired in both cases! Another drawback of the MouseDown event is: when I click for the second time on the TextBox1, I would not expect the whole text to be highlighted anymore, because the focus was set on the first click and it was not changed after I clicked on the same control for the second time; so in this case I would like the cursor to act normally (not to keep the text marked).
Update
When I click once on the TextBox1, I expect to have this result:
If clicked again, the highlight would be removed and the cursor would be placed in the place where it was clicked.
Can't be more simple than this I guess...
Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, _
ByVal X As Single, ByVal Y As Single)
With TextBox1
.SelStart = 0
.SelLength = Len(.Text)
End With
End Sub
Whether you click on the textbox or you tab into it, it will do what you want. To deselect the text, use the arrow keys.
Explanation
If you debug the code you will see that even though you have said .SetFocus, the focus is not on the Textbox. .SetFocus doesn't work in TextBox1_Enter() and you need to have focus for the rest of the code to work. And hence my alternative...
Alternative
You may also like this version :) This overcomes the limitation of using the mouse in the TextBox
Dim boolEnter As Boolean
Private Sub TextBox1_Enter()
boolEnter = True
End Sub
Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, _
ByVal X As Single, ByVal Y As Single)
If boolEnter = True Then
With TextBox1
.SelStart = 0
.SelLength = Len(.Text)
End With
boolEnter = False
End If
End Sub
Pff, took me a while. Actually, your code works, but it highlights the text BEFORE the click event happens. So you clicking in the box instantly overrides the selection created by the code.
I have used a delayed selection, and it works, though it is a bit disgusting...
The code for the textboxes:
Private Sub TextBox1_Enter()
Application.OnTime Now + TimeValue("00:00:01"), "module1.SelectText1"
End Sub
Private Sub TextBox2_Enter()
Application.OnTime Now, "module1.SelectText2"
End Sub
Note that it works even withouth the {+ TimeValue("00:00:01")} part, but it might theoretically stop it from working at times. Hmm, on a second thought, just leave it out. I doubt it would ever cause a problem.
Now the code in module1:
Sub SelectText1()
UserForm1.TextBox1.SelStart = 0
UserForm1.TextBox1.SelLength = Len(UserForm1.TextBox1.Text)
End Sub
Sub SelectText2()
UserForm1.TextBox2.SelStart = 0
UserForm1.TextBox2.SelLength = Len(UserForm1.TextBox2.Text)
End Sub
Hope this works for you too. Ineresting problem. :) Cheers!
I couldn't manage to select/highlight text in the Enter event as the the mousedown and mouseup events coming after are somewhat resetting the selection.
I think the most proper way of achieving what you want is this :
' if you want to allow highlight more then once, reset the variable LastEntered prior to call SelectTboxText:
' LastEntered = ""
' SelectTboxText TextBox2
Dim LastEntered As String
' Button to select Textbox1
Private Sub CommandButton1_Click()
SelectTboxText TextBox1
End Sub
' Button to select Textbox2
Private Sub CommandButton2_Click()
SelectTboxText TextBox2
End Sub
Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
SelectTboxText TextBox1
End Sub
Private Sub TextBox2_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
SelectTboxText TextBox2
End Sub
Public Sub SelectTboxText(ByRef tBox As MSForms.TextBox)
If LastEntered <> tBox.Name Then
LastEntered = tBox.Name
With tBox
.SetFocus
.SelStart = 0
.SelLength = Len(.Text)
End With
End If
End Sub
So each time you want to activate one of the textbox programmatically, you should call the sub SelectTboxText, which is not really annoying IMO. I made 2 buttons for this as an example.
This is somewhat an enhancement of what #vacip posted. The benefit you get is that you don't need to add a separate method in the Module for each new textbox.
The following code in your User Form:
'===== User Form Code ========
Option Explicit
Private Sub TextBox1_Enter()
OnTextBoxEnter
End Sub
Private Sub TextBox2_Enter()
OnTextBoxEnter
End Sub
Private Sub TextBox3_Enter()
OnTextBoxEnter
End Sub
The following code goes in a Module:
'===== Module Code ========
Sub SelectAllText()
SendKeys "{HOME}+{END}", True
End Sub
Sub OnTextBoxEnter()
Application.OnTime Now + 0.00001, "SelectAllText", Now + 0.00002
End Sub
Private Sub UserForm_Initialize()
TextBox1.SetFocus
TextBox1.SelStart = 0
TextBox1.SelLength = Len(TextBox1.Text)
End Sub
Add this to the form's code
I know this is well out of date but I'm leaving this here in case it helps someone in my position.
What I want is:
If I click on the box for the first time: select all the text
If I click on it a subsequent time: put the cursor where the mouse is and allow me to use the mouse to select a substring
Firstly it is important to know that "Select all the text" is the default behaviour when tabbing into a TextBox and that "Put the cursor here" is the default behaviour when clicking on a TextBox so we only need to worry about what the mouse is doing.
To do this, we can keep track of the Active Control, but only while the mouse is moving over our TextBox (ie. before the Click)
Code:
Private m_ActiveControlName As String
Private Sub Text1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
m_ActiveControlName = Me.ActiveControl.Name
End Sub
Private Sub Text1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If m_ActiveControlName <> Me.Text1.Name Then
Call Text1_Enter 'we don't have to use Text1_Enter for this, any method will do
Exit Sub 'quit here so that VBA doesn't finish doing its default Click behaviour
End If
End Sub
Private Sub Text1_Enter()
With Text1
.SelStart = 0
.SelLength = Len(.Text)
End With
End Sub
There's another solution than the one given by Siddharth.
EDIT: but there's this bug of SendKeys, so the solution I propose below is a lot worse than Siddharth one. I keep it in case one day the bug is corrected...
It relies on the property EnterFieldBehavior of the TextBox field. This property works only when the Tab key is pressed to enter that field, and if this property is fmEnterFieldBehaviorSelectAll (0) the whole field text is automatically selected.
So a dummy caret movement between fields when the form is shown, will activate the feature automatically. For instance this movement can be achieved by pressing Tab to move to the next field, and pressing Shift+Tab to move to the previous field (so back to the original field):
Private Sub UserForm_Activate()
SendKeys "{TAB}+{TAB}"
End Sub
The (very little) advantage of this solution is that you can tune your user form by editing manually the properties EnterFieldBehavior, TabIndex, TabKeyBehavior and TabStop without changing the VBA code anymore to set "select all" on the field with the initial focus.
In short, the VBA code above tells to consider the property EnterFieldBehavior of the field which has the initial focus when the user form is displayed (provided that it's a TextBox or ComboBox field of course).
use this
Private Sub TextBox1_Enter()
With TextBox2
.ForeColor = vbBlack
.Font.Bold = False
End With
With TextBox1
.ForeColor = vbRed
.Font.Bold = True
End With
End Sub
Private Sub TextBox2_Enter()
With TextBox1
.ForeColor = vbBlack
.Font.Bold = False
End With
With TextBox2
.ForeColor = vbRed
.Font.Bold = True
End With
End Sub
The behavior you're trying to implement is already built in to the TextBox. When you move the mouse over the left side of the text box, the mouse pointer will point to the right. If you click, it will select all the text in the field. Clicking anywhere else will deselect the text.
I will try a few other strategies to see if I can get this to work in one Sub.
Try the same code with TextBox1_MouseDown. It should work.
Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
With TextBox1
.SetFocus
.SelStart = 0
.SelLength = Len(.Text)
End With
MsgBox "Text in TextBox1 is selected"
End Sub

Resources