How can I verify a specific format in a textbox? I am scanning a label into a textbox that contains a date which is formatted like:
mm.dd.yyyy.hh.mm.ss
I have tried things that do not work...
If Not Format(TextBox1, "mm.dd.yyyy.hh.mm.ss") Then
MsgBox "Wrong Format"
End If
You can use this simple function to check if is a date
Function checkFormatDate(str As String) As Boolean
Dim Y
Dim M
Dim D
Dim H
Dim I
Dim S
Dim theDate As Date
M = Mid(str, 1, 2)
D = Mid(str, 4, 2)
Y = Mid(str, 7, 4)
H = Mid(str, 12, 2)
I = Mid(str, 15, 2)
S = Mid(str, 18, 2)
theDate = DateSerial(Y, M, D) + TimeSerial(H, I, S)
If IsDate(theDate) Then
checkFormatDate = True
Else
checkFormatDate = False
End If
End Function
This returns TRUE (if is a date) or FALSE (if not)
Just care about the dates like: 02.05.2016.01.10.05 (where mm.dd.yyyy.hh.mm.ss), because, you need to trust that 02 is the month and not the day, as 05 is the day and not the month, always appears somebody with a great idea, and change the values just because.
Edit #2
Heres a better version of the code:
Tester:
Sub testDate()
Dim Check As Boolean
Check = checkFormatDate2(UserForm1.TextBox1.Text)
'the textbox is inside UserForm1
If Check Then
MsgBox "Is a Date"
Else
MsgBox "Not a Date"
End If
End Sub
Function:
Function checkFormatDate2(str As String) As Boolean
Dim ArrayD
Dim i
Dim m
ArrayD = Split(str, ".")
If UBound(ArrayD) <> 5 Then
checkFormatDate2 = False
Exit Function
End If
For i = 0 To 5
Select Case i
Case 0
If CInt(ArrayD(i)) < 1 Or CInt(ArrayD(i)) > 12 Then
checkFormatDate2 = False
Exit Function
End If
Case 1
If CInt(ArrayD(i + 1)) < 1900 Or CInt(ArrayD(i + 1)) > 2050 Then
'set the botton and limit year as you need
checkFormatDate2 = False
Exit Function
End If
Case 2
m = Day(DateSerial(CInt(ArrayD(2)), CInt(ArrayD(0)) + 1, 1) - 1)
'm = the last (num) day of the month
If CInt(ArrayD(i - 1)) < 1 Or CInt(ArrayD(i - 1)) > m Then
checkFormatDate2 = False
Exit Function
End If
Case 3
If CInt(ArrayD(i)) < 1 Or CInt(ArrayD(i)) > 23 Then
checkFormatDate2 = False
Exit Function
End If
Case 4
If CInt(ArrayD(i)) < 1 Or CInt(ArrayD(i)) > 59 Then
checkFormatDate2 = False
Exit Function
End If
Case 5
If CInt(ArrayD(i)) < 1 Or CInt(ArrayD(i)) > 59 Then
checkFormatDate2 = False
Exit Function
End If
Case Else
End Select
Next i
checkFormatDate2 = True
End Function
Use this function to validate if the text inside the TextBox is a date sending the TextBox.Value or TextBox.Text. Thanks MikeD for your advice. This way is better.
Edit #3
As you tell me in the comments you could use the AfterUpdate on the Textbox, like this:
Private Sub TextBox1_AfterUpdate()
Dim a As Boolean
a = checkFormatDate2(Me.TextBox1.Value)
If a Then
MsgBox "is date"
Else
MsgBox "no date"
End If
End Sub
Where the UserForm1 has a TextBox named TextBox1 inside, and the function checkFormatDate2 is in a regular module. In my case I just send a MsgBox saying that is not a date.
Edit #4
The same way you can validate the text inside the TextBox when Exit the UserForm this way:
1) Add a button and set the Cancel Property to TRUE:
2)And inside the code you put this:
Private Sub CommandButton1_Click()
Dim a As Boolean
a = checkFormatDate2(Me.TextBox1.Value)
If a Then
MsgBox "is date"
Else
MsgBox "no date"
End If
End Sub
This way, when you press ESC in the keyboard or press the button CommandButton1 you try to close the UserForm and fire the code inside, and test the text inside the TextBox and you could do whatever you want, as, don't let the user go away, go back to the TextBox after a message saying what is the right format, well whatever you want.
Try :
If textbox1 = Format(TextBox1, "mm.dd.yyyy.hh.mm.ss") Then
TextBox1 does not contain a date format, so you can't apply a Format() function using date/time format codes.
One solution would be to split your string into array elements and examine them one by one, e.g.
Sub Test()
Dim A() As String, Rslt As Boolean
A = Split(Me.TextBox1.Value, ".") ' load dot seperated elements into array
If UBound(A) <> 5 Then
MsgBox "not 6 numbers seperated by (5) dots"
Rslt = False
ElseIf Val(A(0)) < 1 Or Val(A(0)) > 12 Then
MsgBox "1st part not a valid month (01-12)"
Rslt = False
ElseIf Val(A(1)) < 1 Or Val(A(1)) > 31 Then
MsgBox "2nd part not a valid day (01-31)"
Rslt = False
ElseIf Val(A(2)) < 0 Or Val(A(1)) > 99 Then
MsgBox "3rd part not a valid year (00-99)"
Rslt = False
ElseIf Val(A(3)) < 0 Or Val(A(3)) > 23 Then
MsgBox "4th part not a valid hour (00-23)"
Rslt = False
ElseIf Val(A(4)) < 0 Or Val(A(4)) > 59 Then
MsgBox "5th part not a valid minute (00-59)"
Rslt = False
ElseIf Val(A(5)) < 0 Or Val(A(5)) > 59 Then
MsgBox "6th part not a valid second (00-59)"
Rslt = False
End If
If Not Rslt Then
'beat the user
End If
End Sub
This doesn't consider months with 28/29/30/31 days, but that's only 1 or 2 if's further away.
Related
I'm new here but hope you all can help with a solution I'm working towards. I'm working on an excel document and setting up a macro. It works until I try to add some logic to pad a number with zero's.
I'm trying to pad zero's in a select cell where the labels are less than 10, then add my integer. If the labels are greater than 9, I want to pad one less zero, likewise when they are greater than 99, one less from those with 10 or more.
My program asks the user how many labels they wish to print (1-999).
I've tried to add an IF statement within my For I = 1 To LabelCount:
For I = 1 To LabelCount
If I < 10 Then
ActiveSheet.Range("C20").Value = "C906BGM0880000" & I
ActiveSheet.PrintPreview
Else
ActiveSheet.Range("C20").Value = "C906BGM088000T" & I
ActiveSheet.PrintPreview
End If
Next
The above did not work.
Sub IncrementPrint()
'updateby Tyler Garretson
Dim LabelCount As Variant
Dim xScreen As Boolean
Dim I As Long
On Error Resume Next
LInput:
LabelCount = Application.InputBox("Please enter the number of copies you want to print:")
If TypeName(LabelCount) = "Boolean" Then Exit Sub
If (ActiveSheet.Range("F11").Value = "") Or (ActiveSheet.Range("F14").Value = "") Or (ActiveSheet.Range("C18").Value = "") Then
MsgBox "Error Occurred. Please enter values for Route, Stop, and Destination Name", vbExclamation
ElseIf (LabelCount = "") Or (Not IsNumeric(LabelCount)) Or (LabelCount < 1) Or (LabelCount > 999) Then
MsgBox "Error Occurred. Please enter 1 - 999", vbExclamation
ElseIf LabelCount < 10 Then
xScreen = Application.ScreenUpdating
Application.ScreenUpdating = False
For I = 1 To LabelCount
ActiveSheet.Range("C20").Value = "C906BGM0880000" & I
ActiveSheet.PrintPreview
Next
ActiveSheet.Range("C20").ClearContents
Application.ScreenUpdating = xScreen
End If
End Sub
User enters 11 labels that he or she wishes to print, the program prints out the following:
Label1: ABC00001
Label2: ABC00002
Label3: ABC00003
Label4: ABC00004
Label5: ABC00005
Label6: ABC00006
Label7: ABC00007
Label8: ABC00008
Label9: ABC00009
Label10: ABC00010
Label11: ABC00011
You want the Format command - Format(1, "00000") = 00001
Format(123,"00000") = 00123
' This might be the basis of what you need
for a = 1 to 1000
b = right("0000000000" & a,8) ' B will always be 8 long and paaded left with 0's
next a
This works well with a text prefix too
for a = 1 to 1000
c = "XYZ" & right("0000000000" & a,8)
next a
I am very much a novice and am trying to get certain rows to show/hide based on values in certain cells when a command button is pressed. I need help with 2 things:
1) Would like this to actually work without pressing a button. I.e. each time the value of cell C10 is changed the code runs to hide/show.
2) I have 4 subroutines that run when the button is pressed. Three of them work fine. I can't get "Rows1to13" subroutine to run. Can't understand it because t's te same exact routine I'm just changing the cells that trigger it and changing which range of rows get hidden.
My code is below
Private Sub CommandButton4_Click()
Call HideDefault
Call rows1to13
End Sub
Sub HideDefault()
If (Range("C10")) = "Manual" Then
For a = 44 To 90
If Worksheets("Sheet1").Cells(a, 1).Value >= "0" Then
Worksheets("Sheet1").Rows(a).Hidden = True
End If
Next
For a = 92 To 125
If Worksheets("Sheet1").Cells(a, 1).Value >= "0" Then
Worksheets("Sheet1").Rows(a).Hidden = False
End If
Next
End If
If (Range("C10")) = "Manual" Then
MsgBox "Manual Data Entry chosen"
End If
End Sub
Sub rows1to13()
'and if C11=yes and C16=yes'
If (Range("C11")) = "Yes" Then
For a = 12 To 13
If Worksheets("Sheet1").Cells(a, 1).Value >= "0" Then
Worksheets("Sheet1").Rows(a).Hidden = False
End If
Next
End If
If (Range("C16")) = "Yes" Then
For a = 17 To 20
If Worksheets("Sheet1").Cells(a, 1).Value >= "0" Then
Worksheets("Sheet1").Rows(a).Hidden = False
End If
Next
End If
'and if C11=No and C16=No'
If (Range("C11")) = "No" Then
For a = 12 To 13
If Worksheets("Sheet1").Cells(a, 1).Value >= "0" Then
Worksheets("Sheet1").Rows(a).Hidden = True
End If
Next
End If
If (Range("C16")) = "No" Then
For a = 12 To 13
If Worksheets("Sheet1").Cells(a, 1).Value >= "0" Then
Worksheets("Sheet1").Rows(a).Hidden = True
End If
Next
End If
'and if C11= blank and C16= Blank'
If (Range("C11")) = "" Then
For a = 12 To 13
If Worksheets("Sheet1").Cells(a, 1).Value >= "0" Then
Worksheets("Sheet1").Rows(a).Hidden = False
End If
Next
End If
If (Range("C16")) = "" Then
For a = 17 To 20
If Worksheets("Sheet1").Cells(a, 1).Value >= "0" Then
Worksheets("Sheet1").Rows(a).Hidden = False
End If
Next
End If
End Sub
I found the issue why the code wasn't executing. . It was very simple. The code is looking for value in a cell to execute, and it case sensitive. In the worksheet the cell input was done in Caps i.e. "NO", but the code was written to look for "No".
Used the worksheet change event to execute without having to press button. Thanks VBasic2008
I am adding TextBoxes dynamically in a userform and want to make them a date format to ensure correct date entry. I am unable to find any examples.
Here is my code for the userform activation:
Private Sub TextBox3_Exit(ByVal Cancel As MSForms.ReturnBoolean)
fltDays = TextBox3.Value If TextBox3.Value = 0 Then Exit Sub
For i = 1 To fltDays
n = i - 1
Dim TextBox As Control
Set theLbl = FloatDayFrm.Controls.add("Forms.Label.1", "lbl_" & i, True)
With theLbl
.Caption = "Day " & i
.Left = 20
.Width = 60
.Top = n * 24 + 100
.Font.Size = 10
End With
Set TextBox = FloatDayFrm.Controls.add("Forms.TextBox.1", "TextBox_" & n, True)
With TextBox
.Top = 100 + (n * 24)
.Left = 90
.Height = 18
.Width = 50
.Name = "txtBox" & i
.Font.Size = 10
.TabIndex = n + 4
.TabStop = True
End With Next i
FloatDayFrm.Height = 150 + fltDays * 24 With btnOK .Top = 102 + fltDays * 24 .TabStop = True .TabIndex = n + 5 End With
With btnCancel .Top = 102 + fltDays * 24 '.TabStop = True .TabIndex = n + 6 End With
End Sub
This is my code for the Command button:
Private Sub btnOK_Click()
n = TextBox3.Value
For j = 1 To n
Set varFloatDay = FloatDayFrm.Controls("txtBox" & j)
Select Case varFloatDay
Case ""
MsgBox "Day " & j & " can't be blank", vbOKOnly, "Incorrect Value"
Exit Sub
Case Is > TextBox2.Value
MsgBox "Date is after end date", vbOKOnly, "Incorrect Value"
Exit Sub
Case Is < TextBox1.Value
MsgBox "Date is BEFORE end date", vbOKOnly, "Incorrect Value"
Exit Sub
End Select
Next j
End Sub
Any help would be appreciated.
You have to convert text to date format. You can use multiple approach.
Add a label beside textbox to display the format user has to specify the date. Parse the text specified by user as per the format. Do validation and conversion as shown in code below.
Use a calendar control instead of textbox as user input.
Have separate textboxes or cells for year, month and day. Do validation and conversion as shown in code below.
If you are sure date is in the specified format as per regional setting. Do validation and conversion as shown in code below.
Try below
Private Sub TestDate()
Dim yr As Integer
Dim mnth As Integer
Dim day As Integer
Dim dt As Date
Dim strDate As String
'''''3rd approach''''''
yr = ActiveSheet.Range("A1")
mnth = ActiveSheet.Range("B1")
day = ActiveSheet.Range("C1")
If IsNumeric(yr) And IsNumeric(mnth) And IsNumeric(day) Then
If yr < 0 Or mnth < 0 Or day < 0 Then
MsgBox "Year, Month and Day must be greater than 0."
Exit Sub
End If
Else
MsgBox "Year, Month and Day must be an integer."
Exit Sub
End If
'convert to Date
dt = DateSerial(yr, mnth, day)
'''''4th approach''''''
'Display a date according to your system's short date format
'i.e. regional settings in control panel
strDate = Format(ActiveSheet.Range("D1"), "Short Date")
If Not IsDate(strDate) Then
MsgBox "Incorrect Date Format"
Exit Sub
End If
dt = CDate(strDate)
End Sub
Any input in a text box is a text string. If you want it to be a date you can use IsDate(TextBox1.Value) to determine if VBA is able to convert the string to a date (which is a number of Double type). VBA will not execute this test 100% correctly, however. For example, it may not recognised 3/2/17 as a date if your regional settings have the date separator as a period. It may convert 3.2.17 to March 2 if your regional settings are mm.dd.yy. While working on your own PC you may be able to control the regional settings. But if your project will be released into the wild it is better to use a calendar control to get a correct date.
Good Morning,
I am attempting to create VBA code that will identify if a variable value (number) is found within a string. The string can vary in lenght and can contain 1 or more numbers that are sepearted by a , and a space. I have attempted to use the InStr method but unfortunately if my value is 1 and the string contains a 17 it comes back as true. How can I make it so that would return false since 1 is not equal to 17.
Below is my current code:
'FRB_Code and FRB_Array are variable values within my code but for
'the purpose of this question I have assigned them values.
FRB_Array = "10, 17, 21"
FRB_Code = 1 'ce.Value
If InStr(FRB_Array, FRB_Code) Then
MsgBox "Found"
Else
MsgBox "Not Found"
ce.Delete Shift:=xlUp
End If
Next ce
End If
So the end result should be that the FRB_Code was not found in the FRB_Array and there for the cell was deleted.
Thank you for you help.
You can use an array for that.
Sub FindValue()
Dim sMyString As String
Dim sToFind As String
Dim Arr
Dim i As Long
Dim bFound As Boolean
sMyString = "10, 17, 21"
Arr = Split(sMyString, ", ")
sToFind = "17"
For i = 0 To UBound(Arr)
If Arr(i) = sToFind Then
MsgBox "Found"
bFound = True
Exit For
End If
Next i
If Not bFound Then MsgBox "Not found"
End Sub
Problem is that "1" will "instring" to "1", "217","871", etc. Better to pre-pad and post-pad with spaces:
Sub NumberInString()
BigString = " 1 23 54 79 "
LittleString = " 23 "
MsgBox InStr(1, BigString, LittleString)
End Sub
InStr is not really appropriate here because you are comparing numbers rather than strings. To do what you want split the string into pieces and cycle through the returned array checking each item. Val is used to convert each item in the array to an integer.
bFound = False
FRB_Array = "10, 17, 21"
FRB_Code = 17
ar = Split(FRB_Array, ",")
For i = 0 To UBound(ar)
If FRB_Code = Val(ar(i)) Then
bFound = True
End If
Next i
If bFound Then
MsgBox ("found")
Else
MsgBox ("not found")
End If
You can use REGEX to determine the match.
http://msdn.microsoft.com/en-us/library/twcw2f1c(v=vs.110).aspx
the regex expression would be "1[^\d]|1$" and you would replace 1 with your FB_Code value.
The expression has an or(|) to handle the last number in the array.
I have some vba code to grab information 4 times a minute from a device on it's web configuration page.
I need this to happen from when I place an x in column C and continue until I place an x in column D further down the page.
I have a function I can call which will tell if an X is in the proper place in d, relative to c.
What I'd like to do is have a button which says ok, be ready to scan. then have it start when the first value is entered in c, then stop when the d value is entered.
I'm also having trouble coming up with a way to enter values while the VBA script is actually running.
Any advice? Thanks.
Here is the code to check the columns.
Public Function BackgroundScan(MonitorSpreadsheet As Boolean) As Boolean
Dim LastStart As Integer
Dim LastStop As Integer
intDebug = 1
Select Case MonitorSpreadsheet
Case True
'We are actively testing
If intDebug = 1 Then MsgBox "we ARE monitoring the spreadsheet."
'Call scanning routine here
'Get the status TestingInProgress
LastStart = FindLastStartRow("SVQ")
LastStop = FindLastStopRow("SVQ")
If intDebug = 1 Then MsgBox "LastStart " & LastStart
If intDebug = 1 Then MsgBox "LastStop " & LastStop
Select Case LastStart
Case Is < 20
'We have not started.
If intDebug = 1 Then MsgBox "We have not started."
BackgroundScan = False
'Loop around, and check again
Case Else
'ok we have started, now check to see if we have stopped.
Select Case LastStop
Case Is < LastStart
'**** We ARE testing!!! ****
If intDebug = 1 Then MsgBox "We are testing, and haven't finished."
BackgroundScan = True
Case LastStart
'LastStart and LastStop are the same line, we have started AND finished
If intDebug = 1 Then MsgBox "We have started AND finished!"
BackgroundScan = False
'Loop around, and check again
Case Else
'We have finished testing, and the test spanned multiple rows
BackgroundScan = False
If intDebug = 1 Then MsgBox "We started on one line, and finished on another."
End Select
End Select
Case False
'we are not actively testing
If intDebug = 1 Then MsgBox "We are NOT monitoring the spreadsheet."
BackgroundScan = False
Case Else
MsgBox "Error: Boolean variable reports: " & MonitorSpreadsheet
BackgroundScan = False
End Select
End Function
Here is the code which scans the webpage.
Private Sub CommandButton1_Click()
Dim Some As String 'can't resist a good pun!
Dim intDelay As Integer
Dim intMinDelay As Integer
Dim i As Integer
Dim s As Integer
Dim RunStart As Date
Dim WhichSVBeam As String
Dim lLen As Integer
Dim CurrentSVID As String
Dim CurrentBeamID As String
Dim PreviousSVID As String
Dim PreviousBeamID As String
Dim ColonLocation As Integer
'*******************************************************
'*** Test Continuous Button ***
'*** Where n is specified in cell A6 ***
'*******************************************************
'grab the number of minutes between checking values
intMinDelay = GetValues("A7")
RunStart = Now
'Do this until the end of time, or the execution is halted.
Do 'uncomment do when we are sure the DoEvents will work as we expect
WhichSVBeam = Scan_SVBeam(PreviousSVID, PreviousBeamID)
If InStr(WhichSVBeam, ":") Then
lLen = Len(WhichSVBeam)
ColonLocation = InStr(WhichSVBeam, ":")
'MsgBox WhichSVBeam & ", " & ColonLocation
CurrentSVID = Left(WhichSVBeam, ColonLocation - 1)
'MsgBox CurrentSVID
CurrentBeamID = Right(WhichSVBeam, lLen - ColonLocation)
'MsgBox CurrentBeamID
Else
'no colon, nothing to parse (this shouldn't happen)
MsgBox "No ':' from Scan_SVBeam"
End If
'Call sCheckExecutionTimeGap(RunStart)
'loop for the number of minutes we specified
For i = 1 To intMinDelay
'check every second for events
For s = 1 To 240
Call AppSleep(250)
DoEvents
Next s
Next i
Loop
End Sub
A example of a piece of code that will run at regular intervals, and allows you to change values in your spreadsheet that will be checked, is the following:
Sub testCell()
Dim r1, r2 As Integer
Dim stopIt As Boolean
r1 = doWeStart
r2 = doWeStop(r1)
Debug.Print "The value of cell C1 is now " & [C1].Value
If r1 = 0 Then Debug.Print "We haven't started yet"
If r1 > 0 And r2 = 0 Then Debug.Print "We start but don't stop"
If r1 > 0 And r2 > 0 Then Debug.Print "We started and stopped"
If [C1].Value Like "stop" Or r1 > 0 And r2 > 0 Then stopIt = True Else stopIt = False
If Not stopIt Then
Application.OnTime Now + TimeValue("00:00:05"), "testCell"
End If
End Sub
'
Function doWeStart()
Dim xrow As Integer
' save old selection
Set r = Selection
xrow = 0
' search for "x" in column C
On Error Resume Next
xrow = Application.WorksheetFunction.Match("x", [C:C], 0)
doWeStart = xrow
End Function
'
Function doWeStop(r1)
Dim xrowd As Integer
xrowd = 0
' search for "x" in column D, starting at row r1
On Error Resume Next
xrowd = Application.WorksheetFunction.Match("x", Range("D" & r1, "D1048576"), 0)
If xrowd > 0 Then
doWeStop = xrowd + r1 - 1
Else
doWeStop = 0
End If
End Function
This will run every five seconds, will look for the first "x" in column C and the first "x" in column D below the one found in C. Depending on what is there, it will (for now) print a message in the debug window - you can put your code there. When you enter "stop" in C1, or an "x" is found in both C and D, it stops.
in pseudo code it would be something along th lines of:
start when column c=x
begin loop
get data
check value of column d
if column d= x exit loop
next loop iteration
end
is that what you want?
Philip