Is it possible to increase the 256 character limit in excel validation drop down boxes? - excel

I am creating the validation dynamically and have hit a 256 character limit. My validation looks something like this:
Level 1, Level 2, Level 3, Level 4.....
Is there any way to get around the character limit other then pointing at a range?
The validation is already being produced in VBA. Increasing the limit is the easiest way to avoid any impact on how the sheet currently works.

I'm pretty sure there is no way around the 256 character limit, Joel Spolsky explains why here: http://www.joelonsoftware.com/printerFriendly/articles/fog0000000319.html.
You could however use VBA to get close to replicating the functionality of the built in validation by coding the Worksheet_Change event. Here's a mock up to give you the idea. You will probably want to refactor it to cache the ValidValues, handle changes to ranges of cells, etc...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ValidationRange As Excel.Range
Dim ValidValues(1 To 100) As String
Dim Index As Integer
Dim Valid As Boolean
Dim Msg As String
Dim WhatToDo As VbMsgBoxResult
'Initialise ValidationRange
Set ValidationRange = Sheet1.Range("A:A")
' Check if change is in a cell we need to validate
If Not Intersect(Target, ValidationRange) Is Nothing Then
' Populate ValidValues array
For Index = 1 To 100
ValidValues(Index) = "Level " & Index
Next
' do the validation, permit blank values
If IsEmpty(Target) Then
Valid = True
Else
Valid = False
For Index = 1 To 100
If Target.Value = ValidValues(Index) Then
' found match to valid value
Valid = True
Exit For
End If
Next
End If
If Not Valid Then
Target.Select
' tell user value isn't valid
Msg = _
"The value you entered is not valid" & vbCrLf & vbCrLf & _
"A user has restricted values that can be entered into this cell."
WhatToDo = MsgBox(Msg, vbRetryCancel + vbCritical, "Microsoft Excel")
Target.Value = ""
If WhatToDo = vbRetry Then
Application.SendKeys "{F2}"
End If
End If
End If
End Sub

Related

Can you assign a the value of a rich data type into a variable in Excel VBA?

I am trying to save the ticker symbol I derived using a Rich data type (I am not sure if I said it correctly) from B2 to a variable.
I used this code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Ticker As String
If Target.Address = "$A$2" Then
Ticker = Activesheet.Range("B2").Value
MsgBox Ticker
End If
End Sub
It happens when I make changes to A2.
I tried to convert it into text or string and it does not work. I assigned the variable as a Variant and String, but still, it won't work. Error is saying "Run time error'13' Type mismatch. But I cannot figure out where I did wrong.
When I debug it, Ticker = ""
I googled around and I cannot find an answer. Is it possible though?
Problem: when you change the rich data type in A2, Excel starts retrieving the ticker symbol in B2 via =A2.[Ticker symbol]. Fetching such data might take a short while, and while the request is pending, B2 will show as #FIELD!. While in this state, B2.Value will be read as an error, so that your code will bounce on Ticker = ActiveSheet.Range("B2").Value, since the variable is dimmed as String. This is why you get the "Type mismatch" error.
Solution: Build a slight delay into your code that will give Excel sufficient time to retrieve the requested data. We can use a Do While Loop for this. Define 2 booleans:
First boolean checks IsError(ActiveSheet.Range("B2"))
Second boolean functions as a timer
Exit the loop when either of these booleans becomes False. You want to include the second boolean to ensure that you do not end up in an infinite loop. This might otherwise happen if the value in B2 will always remain #FIELD, because you didn't supply a valid entry in A2.
Something like the following should work:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Ticker As String
Dim fieldError As Boolean, onTime As Boolean
Dim endTime As Date
'using Target.Text <> "" rather than Target.Value <> "", since the latter will throw an error
'if the range contains a 'rich data type'
If Not Intersect(Target, ActiveSheet.Range("A2")) Is Nothing And Target.Text <> "" Then
'set timeframe to wait for response, set to 1 second here
'we want to check: if "#FIELD!" hasn't changed into a proper value after 1 second
'then data in A2 is probably nonsense: exit loop
endTime = Now + TimeValue("00:00:01")
'set Booleans
onTime = True
fieldError = True
'enter Do While Loop
Do While fieldError And onTime 'continue until
If IsError(ActiveSheet.Range("B2")) Then
Else
'B2 (no longer) an error, switch bool to False to exit loop
fieldError = False
End If
'bool to False after time out to exit loop
onTime = Now < endTime
Loop
'In case of Error, probably incorrect input in A2
On Error GoTo ErrorHandling
Ticker = ActiveSheet.Range("B2").Value
ErrorHandling:
Debug.Print "A2.Text = " & ActiveSheet.Range("A2").Text & "), " & _
"ticker = " & Ticker & ", fieldError = " & fieldError & ", onTime = " & onTime
If Err.Number <> 0 Then
'do stuff (you probably got a correct response, but it's still an error
Debug.Print "Entered ErrorHandling"
Err.Number = 0
End If
Debug.Print "------"
Else
End If
End Sub
To exemplify, below you see a loop in action that populates A2 with a reference to items in the range LIST successively and tries to retrieve the ticker. Notice the output in the immediate window: for "AA", "AAPL" and "AMZN" we are exiting the loop on fieldError = False (ticker found). For "NONSENSE" we are exiting on onTime = False (no ticker: we timed out).

How to click out of Combobox?

I have a combobox with the properties MatchEntry 1-fmMatchEntryCompleteand MatchRequired True.
I need it true to prevent any invalid entry in the combobox. I dont want to make this a Style 2-fmStyleDropDownList but rather keep it a Style 0-fmStyleDropDownCombo because I have about 1000 items to choose from.
This setup works, except if you accidentally click in the combobox, and try to click out of it. You keep getting
Invalid Property Value
Is there anyway I could code the invalid entries so I don't have to assign the property to True?
Figured it out if anyone has this problem in the future. All I did was keep the properties above, and add this code to my userform for the combobox1.
Private Sub ComboBox1_Change()
If Me.ComboBox1.Value = "" Then
'Match not required if zero lenght string
Me.ComboBox1.MatchRequired = False
Else
'Match is required if other than zero length string
Me.ComboBox1.MatchRequired = True
End If
End Sub
You can use the combo LostFocus event. It will check if the value matches one of the combo entries, send a message in case of not, and delete the combo value. Or it can do something else, if my suggestion is not good enough:
Private Sub ComboBox1_LostFocus()
If ComboBox1.Value = "" Then Exit Sub
Dim cbVal As Variant, boolFound As Boolean, i As Long
cbVal = ComboBox1.Value
For i = 0 To ComboBox1.ListCount - 1
If cbVal = ComboBox1.list(i) Then boolFound = True: Exit For
Next i
If Not boolFound Then _
MsgBox "The value """ & cbVal & """ does not exist between the combo items" & vbCrLf & _
"It will be deleted", vbInformation, "Illegal entry": ComboBox1.Value = ""
End Sub
MatchRequired should remain False (default)...

Run time error '1004' Application defined or object defined error on Vlookup function

I am trying to utilize Vlookup function, according to the Textbox1 value user put in in Userform Guntest, automatically looking for corresponding features of the gun.
However the program currently doesn't run as it reminds me
'Runtime error '1004', method 'Range of object' _Global' failed.
The error appears on Retrieve1=…
I will be appreciated if you could help me to check where the problem is as I have really limited knowledge and experience on using VBA.
Thanks in advance.
It looks like some objects is undefined but I can't figure out where.
The module 1 code is:
Public Guncode As String
Option Explicit
Sub Test()
Call Vlookup
End Sub
Sub Vlookup()
Dim Retrieve1 As String
Dim Retrieve2 As String
Dim FinalRow As Long
Dim FinalColumn As Long
Dim WholeRange As String
If GunTest.TextBox1 = "" Then
Exit Sub
If GunTest.TextBox1 <> "" Then
MsgBox Guncode
End If
End If
With Sheets(1)
FinalRow = Range("A65536").End(xlUp).Row
FinalColumn = Range("IV1").End(xlToLeft).Column
WholeRange = "A2:" & CStr(FinalColumn) & CStr(FinalRow)
Retrieve1 = Application.WorksheetFunction.Vlookup(Trim(Guncode), Range(WholeRange), 1, False) 'Locate specific tool according to QR code number
Retrieve2 = Application.WorksheetFunction.Vlookup(Trim(Guncode), Range(WholeRange), 5, False) 'Locate specific gun type according to QR code number
If Guncode = "" Then
MsgBox "This gun doesn't exist in database!"
Else
MsgBox "The tool number is:" & Retrieve1 & vbCrLf & "The gun type is:" & Retrieve2
End If
End With
End Sub
The userform code is:
Option Explicit
Private Sub Label1_Click()
End Sub
Private Sub CommandButton1_Click()
If TextBox1 = "" Then Exit Sub 'Set condition 1 of exiting the program
Guncode = GunTest.TextBox1
With Me
Call Module1.Test
End With
End Sub
Private Sub PartID_Click()
End Sub
Private Sub TextBox1_Change()
End Sub
Private Sub UserForm_Click()
End Sub
It should run properly but it doesn't. Any help would be appreciated, thanks!
First off, you were passing in a number as the column letter value. CSTR() doesnt magically transform it into the letter equivalent but I like your enthusiasm.
Second, your method will bomb if the value isnt found - so you'll need to write your own error handling for it.
Sub Vlookup()
Dim Retrieve1 As String
Dim Retrieve2 As String
Dim FinalRow As Long
Dim FinalColumn As Long
Dim WholeRange As String
Dim vArr
Dim col_Letter As String
If GunTest.TextBox1 = "" Then
Exit Sub
If GunTest.TextBox1 <> "" Then
MsgBox Guncode
End If
End If
With ThisWorkbook.Sheets("Sheet1")
FinalRow = .Range("A65536").End(xlUp).Row
FinalColumn = .Range("IV1").End(xlToLeft).Column
vArr = Split(Cells(1, FinalColumn).Address(True, False), "$")
col_Letter = vArr(0)
WholeRange = "A2:" & col_Letter & CStr(FinalRow) '<---- you were passing a number in as the column value
Retrieve1 = Application.WorksheetFunction.Vlookup(Trim(Guncode), .Range(WholeRange), 1, False) 'Locate specific tool according to QR code number
Retrieve2 = Application.WorksheetFunction.Vlookup(Trim(Guncode), .Range(WholeRange), 5, False) 'Locate specific gun type according to QR code number
If Guncode = "" Then
MsgBox "This gun doesn't exist in database!"
Else
MsgBox "The tool number is:" & Retrieve1 & vbCrLf & "The gun type is:" & Retrieve2
End If
End With
End Sub
1. I am not sure what is the reason using Address(True, False) for row number.
This comes from a combination of these two functions. The true/false setting is telling the funciton to use/not use absolute references in the address.
Split ( expression [,delimiter] [,limit] [,compare] )
https://www.techonthenet.com/excel/formulas/split.php
expression.Address (RowAbsolute, ColumnAbsolute, ReferenceStyle, External, RelativeTo)
https://learn.microsoft.com/en-us/office/vba/api/excel.range.address
Shouldn't Cell (1, FinalColumn) stands for the column number?
No, the cells fucntiosn basically returns an intersection/address of rows & column.
Try this for example: debug.Print; thisworkbook.Sheets("Sheet1").Cells(2,2)
You mentioned CSTR doesn't magically transform to letter equivalent so what would it transform to? Could you further elaborate?
This is a data type conversion function. CSTR(666) essentially does this: this 666 becomes this "666"
2. vArr(0). I am confused with what does the parameter 0 stands for in the bracket. Actually this is a general question I always have regarding to parameter specification.
This is an array position refence. The split function returns an array of strings. Since we're using to capture the column label value, we only need to reference the first position.
(3) I tried copy your code and run it but still reminds me error on the same row.
Works fine for me unless there is no returning value, which returns an error which is what I meant by "bomb."

Excel Data Validation (Text Length) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
This will probably have to be something that is done in VBA, which is fine.
Some background information: I am wanting to use the text length option in Excel's Data validation. I am needing to limit to 60 characters or less. This is the easy part, however.
My question is, if a user has exceeded this 60-character threshold, I do not want my error alert to remain static and give a generic response saying "you must keep below 60 characters..." I want it to actually count the number of characters the user attempted to place in the cell, then on the Error Alert popup I would like it to be more specific, such as: You have exceeded the 60-character limit by ## characters. Please shorten the input and try again. Anyone know of a solution?
I wrote something similar to the code provided by K Davis in another answer. Beyond coding style, here are major functional differences.
        •  handles multiple target columns
        •  adds address to message
        •  selects the rogue cell after notification
        •  loops backwards so that in the event of multiple rogue inputs, the user ends up at the first
        •  declaration and assignment of variables are reserved to when they are actually required
        •  critical stop message box
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Union(Columns("B"), Columns("D"))) Is Nothing Then
On Error GoTo bm_Safe_Exit
Application.EnableEvents = False
Dim mssg As String, iLimit As Long, a As Long, t As Long, trgt As Range
iLimit = 60
Set trgt = Intersect(Target, Union(Columns("B"), Columns("D")))
'loop backwards through multiples so we end up at the first rogue entry
For a = trgt.Areas.Count To 1 Step -1
For t = trgt.Areas(a).Cells.Count To 1 Step -1
If Len(trgt.Areas(a).Cells(t).Value2) > iLimit Then
mssg = "You have exceeded the " & iLimit & "-character limit by " & _
Len(trgt.Areas(a).Cells(t).Value2) - iLimit & " characters in " & _
trgt.Areas(a).Cells(t).Address(0, 0) & ". Please shorten the input and try again."
MsgBox mssg, vbCritical + vbOKOnly, "Bad Input"
trgt.Areas(a).Cells(t).ClearContents: trgt.Areas(a).Cells(t).Select
End If
Next t
Next a
Set trgt = Nothing
End If
bm_Safe_Exit:
Application.EnableEvents = True
End Sub
You might want to split the sentences with one or two vbLF. To my eye, it makes the alert message more effective; particularly so with the cell address added.
I had thought about putting all of the rogue input cell addresses into a single message but that would preclude the specific overdrawn character count.
Sample text courtesy of Lorem Ipsum Generator
Thanks to a suggestion made by Jeepeed, I performed an internet search and stumbled upon this site. I have modified this person's code a bit to accomplish what I needed in my original question, and would like to share it in the event anyone else comes across my same issue.
Here is the code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
Dim rCell As Range
Dim iChars As Integer
On Error GoTo ErrHandler
'Change these as desired
iChars = 60
Set rng = Me.Range("B:B")
If Not Intersect(Target, rng) Is Nothing Then
Application.EnableEvents = False
For Each rCell In Intersect(Target, rng)
If Len(rCell.value) > iChars Then
MsgBox "You have exceeded the 60-character" & _
" limit by " & Len(rCell.value) - iChars & _
" characters." & vbCrLf & "Please shorten" & _
" your input and try again.", vbRetryCancel
End If
Next
End If
ExitHandler:
Application.EnableEvents = True
Set rCell = Nothing
Set rng = Nothing
Exit Sub
ErrHandler:
MsgBox Err.Description
Resume ExitHandler
End Sub
I think that would be better with an Excel formula next to the cell:
= IF( LEN( B2 ) > 60, "You have exceeded the 60-character limit by "
& ( LEN( B2 ) - 60 ) & " characters. Please shorten your input and try again.", "" )

How to deal with a dash in an Excel VBA input variable?

I'm having some trouble with an Excel VBA macro and was hoping you could give me some advice on how to fix it. In the code below, when a user clicks a command button, an InputBox pops up and the user inputs a number in the form XXX-XXXXXX (e.g. 111-222222). Then, the macro takes the value from the column adjacent to button and uses the input variable to replace a certain part of the adjacent column's value. However, when I tried to run the macro and input a number such as 123-456789, nothing happens. I believe it has something to do with the dash that the user inputs, however I'm not sure how to fix it. Please help!
Sub CommandButtonTitleXXXdashXXXXXX_Click()
Application.ScreenUpdating = False
On Error Resume Next
Dim n As Integer
n = Worksheets("REVISIONS").Range("D3:D17").Cells.SpecialCells(xlCellTypeConstants).Count
If n = 15 Then
If MsgBox("Title revision box full. Add manually.", vbOKOnly, "Error") = vbOK Then
Exit Sub
End If
End If
Dim rs As Integer
rs = ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row
Dim amount As String
Application.ScreenUpdating = True
amount = Application.InputBox("Enter case number:", "")
Application.ScreenUpdating = False
If amount = False Then
Exit Sub
Else
Dim newCell As String
newCell = Replace(Worksheets("TITLE").Range("A" & rs).Value, "XXX-XXXXXX", amount)
Worksheets("REVISIONS").Range("D17").End(xlUp).Offset(1, 0) = newCell
End If
End Sub
I would take your code to an extra step.
No need to declare amount as String. You can keep it as a Variant. Also like I mentioned in the comment above
Can your Case number be like #D1-1%#456? If not then you have an additional problem to handle ;)
See this example. I have commented the code so that you will not have a problem understanding it. Still if you do lemme know :) The other way would be to use REGEX to validate your Case ID. Let me know if you want that example as well.
Code
Sub Sample()
Dim amount As Variant
' 123-$456789 <~~ Invalid
' 123-4567890 <~~ Valid
' ABC-&456789 <~~ Invalid
' 456-3456789 <~~ Valid
amount = Application.InputBox("Enter case number:", "")
'~~> Check if user pressed cancel
If amount = False Then Exit Sub
'~~> Check if then Case ID is valid
If IsValidCaseNo(amount) Then
MsgBox amount
Else
MsgBox "Invalid case ID"
End If
End Sub
Function IsValidCaseNo(sAmount) As Boolean
Dim s As String
Dim i As Long, j As Long
s = sAmount
'
'~~> Initial basic checks
'
'~~> Check if the length is 11 characters
If Len(Trim(s)) <> 11 Then GoTo Whoa
'~~> Check if the string contains "-"
If InStr(1, s, "-") = 0 Then GoTo Whoa
'~~> Check if the 4th character is a "-"
If Mid(s, 4, 1) <> "-" Then GoTo Whoa
'~~> Loop through 1st 3 characters and check
'~~> If they are numbers
For i = 1 To 3
Select Case Asc(Mid(s, i, 1))
Case 48 To 57
Case Else: GoTo Whoa
End Select
Next
'~~> Loop through last 6 characters and check
'~~> If they are numbers
For i = 5 To 11
Select Case Asc(Mid(s, i, 1))
Case 48 To 57
Case Else: GoTo Whoa
End Select
IsValidCaseNo = True
Next
Whoa:
End Function
If you Dim amount as String, you can test it as a string:
Sub GetDash()
Dim amount As String
amount = Application.InputBox(Prompt:="Enter case number", Type:=2)
If amount = "False" Then
MsgBox "You cancelled"
End If
End Sub

Resources