Listbox in Excel - How to determine no selection - excel

I have an Excel spreadsheet with a listbox on sheet1 that populates from a named group on sheet2. There are 4 entries in this named group.
I want the user to make a selection from this listbox (1 column) before they do anything else. I'm trying to code to check for a valid selection from the listbox but, TopIndex = 0, and .Value, .Selection, .Selected either don't work or they return 0 but 0 is the index for the first entry in the listbox so it's like I always make a selection.
If I check for Listbox.value <> "" it returns null whether or not I make a selection.
I've searched the internet all night looking for a solution and keep coming up empty handed.
I'm stuck. Looking for suggestions.

You are possibly looking for this piece of code
If ListBox1.ListIndex = -1 Then
MsgBox "Nothing selected"
Else
MsgBox "Selected: " & ListBox1.ListIndex
End If
Listindex is equal -1 if nothing is selected in the listbox. Otherwise it is the index of the selected element starting with 0.
The above code works for a listbox where multiselect is false.
For a listbox with "multiselection" on this piece of code might probably help you
Dim i As Long
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) = True Then
MsgBox "Selected: " & i
End If
Next i

Not sure why it didn't work for me but when I used
listbox1.listindex I kept getting 0
So, I changed how I populated my listbox by using
Private Sub Workbook_Open()
' Add site names to listbox
With Sheet1.ListBox1
.AddItem "Hayward"
.AddItem "Exeland"
.AddItem "StoneLake"
.AddItem "Winter"
End With
End Sub
Later on, when I coded to define the file I needed to open, I used
x = Sheet1.ListBox1.ListIndex
Select Case x
Case 0
sSite = "Hayward"
Case 1
sSite = "Exeland"
Case 2
sSite = "StoneLake"
Case 3
sSite = "Winter"
Case Else
MsgBox "You MUST select a Site Location", vbOKOnly
GetTargetFile = "NoSite"
Exit Function
End Select
GetTargetFile = sSite & sMonth & Yr & ".xlsx"
Now, Listbox1.ListIndex will return -1 if no selection made.
I think my original problem was in how I was trying to populate my listbox in that no matter what I did, both the FIRST and NO SELECTION returned 0.
Thanks for responding!

You need to count the selected items, then make the condition:
For a = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(a) = True Then
Numselections = Numselections + 1
End If
Next a
If Numselections < 1 Then
MsgBox ("Please select item!")
Exit Sub
End If

Related

How to reverse the drop down selection when user decides not to change the selection in excel vba?

I have a drop down button and macro assigned to it. Upon selection of option from drop down the macro asks user whether he/she wants to make the change. If user selects yes code runs successfully. If user selects no the code ends. But the drop down selection changes to the new value which user selected. I want to reflect the old selection before user opted not to effect the change.
Here is how it works.
Step 1 - Proposal Origin is NA
Step 2 - User changes it to LA. But in the confirmation window opts "No".
Step 3 - Since in step 2 user selected "No" nothing happened. But the selection shows Proposal Origin as LA.
I want to keep it as NA when user selects "No" in conformation window.
Here is the code I have
Sub Dropdown6_BeiÄnderung()
'Dropbox Location
Dim Update As Integer
DropVal = Range("L18").Value
Update = MsgBox("You have selected " & Cells(18, 12) & " as Proposal Location. This will reset the Labor sheets. Do you want to continue?", vbYesNo, vbDefaultButton1)
If Update = vbYes Then
Worksheets("NA-Hours").Range("C8").Value = 0
Worksheets("LA-Hours").Range("C8").Value = 0
Worksheets("EU-Hours").Range("C8").Value = 0
Worksheets("MEA-Hours").Range("C8").Value = 0
Worksheets("AP-Hours").Range("C8").Value = 0
For i = 17 To 21
SName = Cells(i, 16).Value
If Cells(i, 17).Value = 1 Then
Worksheets(SName).Visible = True
Else: Worksheets(SName).Visible = False
End If
Next
Else
me.Drop Down 6.text = DropVal
End If
End Sub
Need help on the else part to reflect the earlier selection which is stored in variable DropVal.
Please, look at the next code example in order to understand how a Drop Down object value can be handled:
Sub handleDropDown()
Dim dd As DropDown, rngDL As Range, DropVal As String
Set dd = ActiveSheet.DropDowns("Drop Down 6")
Set rngDL = ActiveSheet.Range(dd.ListFillRange)
DropVal = "Test" 'use here what you need
Debug.Print dd.value 'it returns the index of the selected item in ListFillRange range
Debug.Print rngDL(dd.value) 'it returns the drop down value
rngDL.cells(dd.value) = DropVal 'it set/change the drop down value, but changing the cell in the range
End Sub
What I tried showing is to change the drop down object value. I must confess I am not sure that I understand what "to reverse the drop down selection" should mean...
The drop down value can be changed only if DropVal is part of the drop down ListFillRange and it was the previous selection. In such a case, the next approach should work.
Practically, you should implement the next code inside your Else part of the code:
Dim dd As DropDown, rngDL As Range, mtch As Long
Set dd = ActiveSheet.DropDowns("Drop Down 6")
Set rngDL = ActiveSheet.Range(dd.ListFillRange)
'If Range("L18").Value = "NA" the drop down value will become "NA"
mtch = Application.match(DropVal, rngDL, 0)' position/index of DropVal
If Not IsError(mtch) Then
dd.value = mtch
Else
MsgBox DropVal & " could not be found in " & rngDL.Address
End If

Barcode scanner automatic submit

I already have a barcode scanner VBA function, that recognizes the barcode number, but the problem I have is that I have to click enter every time, is there any way to do it automatically and store the count in a certain column? Currently it works if I enter the same value stored in column B, it will count the records in column C, but I want to avoid hitting enter every time
This is what I got so far
Private Sub btnAdd_Click()
Dim TargetCell As Range
If WorksheetFunction.CountIf(Sheets("Sheet1").Columns(2), TextBox1.Value) = 1 Then
Set TargetCell = Sheets("Sheet1").Columns(2).Find(TextBox1.Value, , xlValues, xlWhole).Offset(0, 1)
TargetCell.Value = TargetCell.Value + 1
Else
MsgBox "Code not found"
End If
Me.Hide
End Sub
It's hard to say what you have. For example, who presses the button? Or, does your scanner enter a return. I think the code below should work under any circumstances. Please try it.
Private Sub TextBox1_Change()
Dim TargetCell As Range
Dim Qty As Long
With TextBox1
If Len(.Value) = 3 Then
Set TargetCell = Worksheets("Sheet1").Columns(2) _
.Find(.Value, , xlValues, xlWhole)
If TargetCell Is Nothing Then
MsgBox """" & .Value & """ Code not found"
Else
With TargetCell.Offset(0, 1)
Qty = .Value + 1
.Value = Qty
End With
Application.EnableEvents = False
TextBox1.Value = "Count = " & Qty
Application.EnableEvents = True
End If
.SelStart = 0
.SelLength = Len(.Value)
End If
End With
End Sub
I think you have a user form and in this form you have a text box called TextBox1. If so, the code should be in the user form's code module. If you have a text box in your worksheet paste the code to the code module of the sheet on which the text box resides.
Now, you need to adjust this line of code If Len(.Value) = 3 Then to determine when to process the data. This is because the Change event will occur whenever even a single character is entered. I tested with 3 characters. Change the number to a value equal to the length of the numbers you scan in. In theory that still leaves the CR hanging which your scanner might also send. If that causes a problem experiment with >= in place of the = in my code.
The code will add the scan to the existing quantity, just as you had it, and indicate the new total in the text box, in case you are interested. You might replace this with "OK". The code will select the text it enters. Therefore when you enter something else, such as a new scan, it will be over-written without extra clicks being required.

ActiveX Command Button that unhides next to a Cell if a value is entered, and hides if the cell is empty

I have 80 rows where the user can enter a predetermined value under column Ward. This unhides a button next to it. Upon clicking it, it empties the adjacent value and increments (+1) a particular cell in another sheet depending on the original value.
Currently, I have 80 ActiveX buttons next to the Ward cells that hides/unhides depending on the value of the Ward cells. I've noticed that adding more buttons slows down the spreadsheet because of the sheer volume of If Then statements I have.
If Range("F8").Value = 0 Then
Sheets("Admissions").EDAdmit1.Visible = False
Else
Sheets("Admissions").EDAdmit1.Visible = True
End If
If Range("L8").Value = 0 Then
Sheets("Admissions").ElecAdmit1.Visible = False
Else
Sheets("Admissions").ElecAdmit1.Visible = True
End If
If Range("F9").Value = 0 Then
Sheets("Admissions").EDAdmit2.Visible = False
Else
Sheets("Admissions").EDAdmit2.Visible = True
End If
If Range("L9").Value = 0 Then
Sheets("Admissions").ElecAdmit2.Visible = False
Else
Sheets("Admissions").ElecAdmit2.Visible = True
End If
.. and so on.
Not to mention the If Then statements I have for every button click.
Private Sub EDAdmit1_Click()
If Range("F8") = "ICU" Then
Worksheets("Overview").Range("AD11").Value = Worksheets("Overview").Range("AD11") + 1
ElseIf Range("F8") = "HDU" Then
Worksheets("Overview").Range("AF11").Value = Worksheets("Overview").Range("AF11") + 1
ElseIf Range("F8") = "DPU" Or Range("F8") = "Other" Then
Else
Col = WorksheetFunction.VLookup(Range("F8"), Range("U1:V27"), 2)
Worksheets("Overview").Range(Col).Value = Worksheets("Overview").Range(Col).Value + 1
End If
Range("F8").ClearContents
End Sub
Is there a more efficient way of doing this?
Admission List:
You could consider using "admit" hyperlinks in the cells next to the Ward selections: that way you only need one handler (Worksheet_FollowHyperlink in the worksheet module). Note you need to use Insert >> Hyperlink and not the HYPERLINK() formula-type links here (because formula-based links don't trigger the FollowHyperlink event).
You can ditch the hide/show code and instead use conditional formatting to change the link font color to hide the links when there's no Ward selected. If a user clicks on one of the hidden links then you can just do nothing.
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim rngSrc As Range, addr, ward
Set rngSrc = Target.Range '<< the cell with the link
ward = rngSrc.Offset(0, 1).Value '<< cell with Ward
'only do anything if a ward is selected
If Len(ward) > 0 Then
'find the cell to update
Select Case ward
Case "ICU"
addr = "AD11"
Case "HDU"
addr = "AF11"
Case "DPU", "Other"
addr = ""
Case Else
addr = Application.VLookup(ward, Me.Range("U1:V27"), 2, False)
End Select
'if we have a cell to update then
If Len(addr) > 0 Then
With Worksheets("Overview").Range(addr)
.Value = .Value + 1
End With
End If
rngSrc.Offset(0, 1).ClearContents
End If
rngSrc.Select '<< select the clicked-on link cell
' (in case the link points elsewhere)
End Sub
At the beginning of your code put this line:
Application.ScreenUpdating = False
this will disable all screen updates. Let your code do changes, and then enable screen updating, and all your changes will appear.
Application.ScreenUpdating = True
Disabling screen updating usually makes the execution of code faster.

How To Use Private Sub Checkbox Name variable in Code?

I have an ActiveX Checkbox in Excel that when clicked will change a cell value to add 1.
I need to repeat this VBA code when I use the same Checkbox in a different Cell Value, which I need to repeat many times.
How do I reference the automatically generated checkbox name variable in the VBA code for each new cell value?
This is for a Excel spreadsheet that I use to update a database when new reports are turned in with "checked" information on it.
Private Sub CheckBox21_Click()
Range("L2").Activate
'Don't want to type CheckBoxXX each time, just find way to automatically reference?'
If CheckBox21.Value = True Then
ActiveCell.Value = ActiveCell.Value + 1
Else
If ActiveCell.Value > 0 Then
ActiveCell.Value = ActiveCell.Value - 1
Else
End If
End If
_____________________________________________________________________________
'Next line'
Private Sub CheckBox22_Click()
Range("L2").Activate
If CheckBox22.Value = True Then
ActiveCell.Value = ActiveCell.Value + 1
Else
If ActiveCell.Value > 0 Then
ActiveCell.Value = ActiveCell.Value - 1
Else
End If
End If
End Sub
I don't want to type CheckBoxXX each time, just to automatically reference?

Remove items from list box by selecting a different item using excel-vba

I apologise now as I am an absolute beginner (also my pictures and code haven't been generalised).
I have a drop down list box in Excel, populated by a range I selected whilst inside excel (ie right click the ActiveX Control after it has been placed and alter the properties). I would like it so that if certain items in the list are selected, other items are removed from the list so that they cannot be selected. Eg. there is a list A, B, and C, but upon a user selecting A, B disappears from the list.
My code is as follows. This first part codes for the drop down list
Sub Rectangle1_Click()
Dim SelShp As Shape, ListShp As Shape, SelList As Variant, i As Integer
Set SelShp = Sheet8.Shapes(Application.Caller)
Set ListBx = Sheet8.ListBox1
If SelShp.TextFrame2.TextRange.Characters.Text = "Select Buffers" Then
ListBx.Visible = True
SelShp.TextFrame2.TextRange.Characters.Text = "Set Buffers"
Else
ListBx.Visible = False
SelShp.TextFrame2.TextRange.Characters.Text = "Select Buffers"
For i = 0 To Sheet8.ListBox1.ListCount - 1
If Sheet8.ListBox1.Selected(i) = True Then
SelList = SelList & "; " & Sheet8.ListBox1.List(i)
End If
Next i
If SelList <> "" Then
Range("ListBox1Output") = Right(SelList, Len(SelList) - 1)
Else
Range("ListBox1Output") = ""
End If
End If
End Sub
This second code is what is supposed to remove items from the list
Private Sub ListBox1_Change()
If Sheet8.ListBox1.Selected(0) Then
Sheet8.ListBox1.RemoveItem 1
End If
End Sub
The problem is, when I try it out I get a run-time error '-2147467259 (80004005)': Unspecified error., and if I try and debug it highlights the 'Sheet8.ListBox1.RemoveItem 1', but I just don't know enough to know what I'm doing wrong. Any help would be much appreciated, and I'm sorry if I'm missing something really simple.
Edit: I've been working on this since I posted, and have found some solutions, but run into other roadblocks.
My first problem was that the .RemoveItem method wasn't doing anything. Turns out if a ListBox is populated by using the .ListFillRange method, .RemoveItem won't work – a ListBox has to be populated by using .AddItem if I later want to .RemoveItem.
After I worked that out, I decided to try and do what I want with simpler data:
I have 2 Listboxes and I populate one of them with data. Upon selecting an item in ListBox1, that item is copied into ListBox2, and it is removed from ListBox1. Also, if certain items in ListBox1 are selected, other items are removed from the listbox so that they cannot be selected. Eg. there is a list A, B, and C, but upon a user selecting A, B disappears from the list.
I have got my code to the point where it works in certain situations. Unfortunately, the sequence of the items is important, and for some reason, for certain sequences of items, the code does not work as expected – eg my generalised items happen to be: Germany, India, France, USA, England. Upon selecting 'Germany', this item appears in ListBox2, it is removed from ListBox1, and also, 'France' is removed from ListBox1. This works fine, until the items are put in alphabetical order, at which point upon selecting 'Germany', this item appears in ListBox2, it is removed from ListBox1, 'France' is removed from ListBox1, AND India and USA are moved into ListBox2...?? It's as if once 'France' has been deleted, whatever was below it is selected and runs through the first 2 loops of the ListBox1_Change() sub for some reason. Interrupting it with a messagebox works for some reason, but I can't work out how to interrupt it without using the messagebox...
My code is as follows, with some comments on what I tried included in it.
Populate ListBox1 with items in random positions
Sub Populate_ListBox1()
'Clear LB1 before populating it
Sheet1.ListBox1.Clear
Sheet1.ListBox2.Clear
Sheet1.ListBox1.AddItem "Germany"
Sheet1.ListBox1.AddItem "India"
Sheet1.ListBox1.AddItem "France"
Sheet1.ListBox1.AddItem "USA"
Sheet1.ListBox1.AddItem "England"
End Sub
Try to move selected ListBox1 items while changing what items are in ListBox1
Private Sub ListBox1_Change()
'Variable Declaration
Dim iCnt As Integer
Dim jCnt As Integer
Dim kCnt As Integer
'Move Selected Item from Listbox1 to Listbox2
For iCnt = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(iCnt) = True Then
Me.ListBox2.AddItem Me.ListBox1.List(iCnt)
End If
Next
'Clear Selected Item from Listbox1
For iCnt = Me.ListBox1.ListCount - 1 To 0 Step -1
If Me.ListBox1.Selected(iCnt) = True Then
Me.ListBox1.RemoveItem iCnt
'Me.ListBox1.Selected(iCnt) = False 'Nope
'Exit For
End If
Next
'If Germany is in Listbox2, then remove France from LB1
For kCnt = 0 To Me.ListBox2.ListCount - 1
If Me.ListBox2.Column(0, kCnt) = "Germany" Then
For jCnt = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Column(0, jCnt) = "France" Then
Me.ListBox1.RemoveItem jCnt
'Me.ListBox1.Locked = True 'Nope
'Me.ListBox1.Enabled = False 'Nope
'Me.ListBox1.ListIndex = -1 'This crashes excel...
'MsgBox "blah" 'For some reason this works >.<
Exit Sub
End If
Next jCnt
End If
Next
End Sub
I'd really appreciate help with this, and would even take advice on using a different program that would work with excel (trying to alter items in a listbox based upon their index, which changes, rather than on their values is a nightmare)

Resources