Data Validation Allowing More Than One Entries - vba

I have written down the lines that follow in order to allow the user to insert more that one entries in a data validated range. So if the dropdown list contains the elements: x1, x2, x3, .., xn, then, for any cell in the range, one can select and insert at first x1 value, then at the same cell select and insert x3 with the result being: x1, x3, and so it goes.
The problem is that when the user wishes to delete one of the value he gets an excel error saying the user has restricted the values for this cell. Therefore, he must delete the entire content of the cell and then select again the values he wants. Can you help improve this with regard to that?
Here is the code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDV As Range
Dim oldVal As String
Dim newVal As String
If Target.count > 1 Then GoTo exitHandler
On Error Resume Next
Set rngDV = Cells.SpecialCells(xlCellTypeAllValidation)
On Error GoTo exitHandler
If rngDV Is Nothing Then GoTo exitHandler
If Intersect(Target, rngDV) Is Nothing Then
'Column 7 is the one to which is the code is applied
ElseIf Target.Column = 7 Then
Application.EnableEvents = False
newVal = Target.Value
Application.Undo
oldVal = Target.Value
Target.Value = newVal
If oldVal = "" Then
Else
If newVal = "" Then
Else
Target.Value = oldVal _
& ", " & newVal
End If
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub

Violating validation through VBA is possible, that's why your code works in the first place. Deleting an entry is a manual action where the cell content (a comma separated list) is being compared to your validation list.
You could do one of the following:
use your cell with validation for selection of items only, and write the comma separated selection to a different cell.
write an edit function for the cell - that way the result of the edit will be again written into the cell via VBA.
add the list (and all possible results from deletions into the validation list as well (very messy though)

try with below
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDV As Range
Dim oldVal As String
Dim newVal As String
If Target.Count > 1 Then GoTo exitHandler
On Error Resume Next
Set rngDV = Range("G:G")
On Error GoTo exitHandler
If rngDV Is Nothing Then GoTo exitHandler
If Intersect(Target, rngDV) Is Nothing Then
ElseIf Target.Column = 7 Then
Application.EnableEvents = False
newVal = Target.Value
Application.Undo
oldVal = Target.Value
Target.Value = newVal
If oldVal = "" Then
Else
If newVal = "" Then
Else
Target.Value = oldVal & ", " & newVal
End If
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub

Related

Excel VBA - Select Multiple Values Drop Down Validation

I would appreciate some assistance with a problem i am having. The following code sample allows me to select multiple values from a dropdown list however i need the target.address to be every row within column S.
I am unsure how to change the target address so that it is the range s10 onwards (ie S10-S150)
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Oldvalue As String
Dim Newvalue As String
On Error GoTo Exitsub
If Target.Address = "$S10" Then
If Target.SpecialCells(xlCellTypeAllValidation) Is Nothing Then
GoTo Exitsub
Else: If Target.Value = "" Then GoTo Exitsub Else
Application.EnableEvents = False
Newvalue = Target.Value
Application.Undo
Oldvalue = Target.Value
If Oldvalue = "" Then
Target.Value = Newvalue
Else
Target.Value = Oldvalue & ", " & Newvalue
End If
End If
End If
Application.EnableEvents = True
Exitsub:
Application.EnableEvents = True
End Sub
Thank you!
You can test to see if the affected range is within another range like this:
If Not Intersect(Target, Range("S10:S150")) Is Nothing Then
The line above would replace this line in your original code:
If Target.Address = "$S10" Then

Excel VBA - Prevent All User Interaction In Cells Except Through Data Validation List

Please read my edits below the problem description.
I have a worksheet with cells (in column 4) that are edited through a data validation dropdown with multiple selection, using the below code coupled with the data validation list. Currently, the user can backspace items which, as expected, causes an alert to appear that warns the user not to edit the cell. However, when that alert is canceled, the cell is populated by multiple versions of what was in it prior to the attempt at backspacing. In addition to backspace, they can use the delete key to delete items.
How would I alter the VBA code to prevent users from doing ANYTHING except choosing items from the data validation dropdown (and choosing again to remove the item as currently occurs)? They should not be able to edit, delete, or otherwise manipulate the cells in any way.
Basically, I want to prevent every action for cells in column 4 except the existing entry and removal via data validation dropdown list. Protecting the workbook will not work because the cells would have to be unlocked for the data validation to work.
EDIT: Could I include something like this pseudocode Application.OnKey Key:="{BACKSPACE}", DO NOTHING? If so, where would that be included? I tried adding this above the Worksheet_Change():
Private Sub Worksheet_Activate()
Application.OnKey "{DELETE}", ""
End Sub
This had no effect.
This piece of code, added under If Target.Count > 1 Then GoTo exitHandler, causes the delete button to stop working, but using backspace still causes the same problems.
If Application.Intersect(Target, Range("D1:D150")) Is Nothing Then GoTo exitHandler
If Len(Target.Value) = 0 Then
Application.EnableEvents = False
Application.Undo
MsgBox "Please don't clear this cell."
Application.EnableEvents = True
End If
Full code without edits:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDV As Range
Dim oldVal As String
Dim newVal As String
Dim strVal As String
Dim i As Long
Dim lCount As Long
Dim Ar As Variant
On Error Resume Next
Dim lType As Long
If Target.Count > 1 Then GoTo exitHandler
lType = Target.Validation.Type
If lType = 3 Then
Application.EnableEvents = False
newVal = Target.Value
Application.Undo
oldVal = Target.Value
Target.Value = newVal
If Target.Column = 4 Then
If oldVal = "" Then
'do nothing
Else
If newVal = "" Then
'do nothing
Else
On Error Resume Next
Ar = Split(oldVal, ";" & vbCrLf)
strVal = ""
For i = LBound(Ar) To UBound(Ar)
Debug.Print strVal
Debug.Print CStr(Ar(i))
If newVal = CStr(Ar(i)) Then
'do not include this item
strVal = strVal
lCount = 1
Else
strVal = strVal & CStr(Ar(i)) & ";" & vbCrLf
End If
Next i
If lCount > 0 Then
Target.Value = Left(strVal, Len(strVal) - 3)
Else
Target.Value = strVal & newVal
End If
End If
End If
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub

vlookup multiple values in one cell

I am trying to vlookup multiple values in one cell based on the a selection from another cell.
I have the below table where I select a single "Gym" the "GymIDs" is automatically populated. I have then used the below VBA to allow me to select multiple "Gyms", I also want it to show me multiple "GymIDs".
Current vlookup =VLOOKUP(M7,Ignore!F1:G300,2,FALSE)
for some reason I could only upload one image so put them all together
excel table
VBA code for multiple selections
Private Sub Worksheet_Change(ByVal Target As Range)
'Code by Sumit Bansal from https://trumpexcel.com
' To Select Multiple Items from a Drop Down List in Excel
Dim Oldvalue As String
Dim Newvalue As String
On Error GoTo Exitsub
If Not Intersect(Target, Range("M7:M30")) Is Nothing Then
If Target.SpecialCells(xlCellTypeAllValidation) Is Nothing Then
GoTo Exitsub
ElseIf Target.Value = "All" Then GoTo Exitsub
ElseIf Target.Value = "Select" Then GoTo Exitsub
ElseIf Target.Value = "" Then GoTo Exitsub
Else
Application.EnableEvents = False
Newvalue = Target.Value
Application.Undo
Oldvalue = Target.Value
If Oldvalue = "" Then
Target.Value = Newvalue
ElseIf Oldvalue = "All" Then
Target.Value = Newvalue
ElseIf Oldvalue = "Select" Then
Target.Value = Newvalue
Else
Target.Value = Oldvalue & ", " & Newvalue
End If
End If
End If
Application.EnableEvents = True
Exitsub:
Application.EnableEvents = True
End Sub
I'd suggest writing a function in the lookup column. As you've not provided the vlookup i'll leave that part to you. The main concept at play here is to detect whether the Gyms column is a single value or a comma separated list and treat it based upon that:
Public Function GymLookup(ByVal stringToProcess As String) As Variant
Application.Volatile
Dim var As Variant
Dim arrData As Variant
Dim strConcat As String
If InStr(1, stringToProcess, ",") > 0 Then
arrData = Split(stringToProcess, ",")
For Each var In arrData
'multiple handler
If strConcat = "" Then
strConcat = "enter your vlookup to resolve a result here"
Else
strConcat = strConcat & ", " & "enter your vlookup to resolve a result here"
End If
Next var
GymLookup = strConcat
Else
'Single cell lookup
GymLookup = "enter your vlookup to resolve a result here"
End If
End Function

How to avoid duplication when entering a value into a data validation cell, which allows multiple selection

There are certain columns in my database, that requires me to type in new data as well as make selections. So, I made a drop down list through data validation. I can select multiple selections according to the code, but if I keyed in any data into that cell, the original selection will show up twice.
Eg. Cell contains the choices: ABC, XYZ
I chose ABC, typed in WWW
The cell will then show ABC, ABC, WWW
Anyone can help prevent the duplication of the original choice?
Here is the code I currently have, I tried to remove the "oldVal" part to prevent duplication, it prevented me from choosing multiple choices.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDV As Range
Dim oldVal As String
Dim newVal As String
Dim lUsed As Long
If Target.Count > 1 Then GoTo exitHandler
On Error Resume Next
Set rngDV = Cells.SpecialCells(xlCellTypeAllValidation)
On Error GoTo exitHandler
If rngDV Is Nothing Then GoTo exitHandler
If Intersect(Target, rngDV) Is Nothing Then
'do nothing
Else
Application.EnableEvents = False
newVal = Target.Value
Application.Undo
oldVal = Target.Value
Target.Value = newVal
If Target.Column = 28 Or Target.Column = 29 Or Target.Column = 30 Then
If oldVal = "" Then
'do nothing
Else
If newVal = "" Then
'do nothing
Else
lUsed = InStr(1, oldVal, newVal)
If lUsed > 0 Then
If oldVal = newVal Then
Target.Value = ""
ElseIf Right(oldVal, Len(newVal)) = newVal Then
Target.Value = Left(oldVal, Len(oldVal) - Len(newVal) - 1)
Else
Target.Value = Replace(oldVal, newVal & vbLf, "")
End If
Else
Target.Value = oldVal & vbLf & newVal
End If
End If
End If
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub

Data validation select multiple items error message from text entered in non drop down list cells

I'm trying to produce a code whereby the user can multiple items from a drop down menu (separated by a comma in the original cell) and then remove them by selecting the same item again. This pertains to only one column, I in the workbook and the other columns are regular columns where the user will be entering in text. I'm running into a problem in that the code that I have (see below) works on Column I but when the user tries to enter any information into other cells in other columns on the same worksheet, Run time error 1004 Application defined or object defined error pops up. When I press debug, it highlights If Target.Validation.Type = 3 Then. I copied this code from Contextures Inc and experience the same problem when I click on an outside cell in their test spreadsheet.
Any help would be much appreciated!
Option Explicit
' Developed by Contextures Inc.
' www.contextures.com
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDV As Range
Dim oldVal As String
Dim newVal As String
Dim strVal As String
Dim i As Long
Dim lCount As Long
Dim Ar As Variant
If Target.Count > 1 Then GoTo exitHandler
If Target.Validation.Type = 3 Then
Application.EnableEvents = False
newVal = Target.Value
Application.Undo
oldVal = Target.Value
Target.Value = newVal
If Target.Column = 9 Then
If oldVal = "" Then
'do nothing
Else
If newVal = "" Then
'do nothing
Else
On Error Resume Next
Ar = Split(oldVal, ", ")
strVal = ""
For i = LBound(Ar) To UBound(Ar)
Debug.Print strVal
Debug.Print CStr(Ar(i))
If newVal = CStr(Ar(i)) Then
'do not include this item
strVal = strVal
lCount = 1
Else
strVal = strVal & CStr(Ar(i)) & ", "
End If
Next i
If lCount > 0 Then
Target.Value = Left(strVal, Len(strVal) - 2)
Else
Target.Value = strVal & newVal
End If
End If
End If
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub
Add these lines immediately before If Target.Count > 1 Then GoTo exitHandler:
Set Target = Application.Intersect(Target, Me.Columns(9))
If Target Is Nothing Then Exit Sub
This will restrict the range Target only to cells in Column 9
Then you can remove this test:
If Target.Column = 9 Then
End If