I\'m trying to write a quick little macro that asks the user for an input, and then copies this to a specific cell (B14 in Sheet1). Here\'s what I\'ve got so far:
Sub updatesheet()
Dim vReply As String
Do
'edit: added UCase on INputBox
vReply = UCase(InputBox("Enter period (format: Q4 2010) to update, or hit enter to escape"))
Loop Until Len(vReply) = 0 Or vReply Like "Q# ####"
If vReply = vbNullString Then Exit Sub
'continue...
End Sub
something like this, you were very close (rather than Inputbox
you just needed to use vReply
when writing to Sheet1 B14)
Updated Overhauled to de-hmmm:
Application.InputBox
rather than 'InputBox' as this provides the coder with more optionality. But nice to have in this instance rather than critcal "^Q[1-4]\s20[11-13]{2}$"
. The "q" test is case insensitiveInt((Month(Now()) - 1) / 3) + 1 & " " & Year(Now())
returns Q4 2011 . You can remove this prompt if desiredDo
loop is used to test invalid strings, if an invalid string is supplied than the strTitle
variable of "Please retry"" is used to let the user know that prior attempts were invalid (the msg doesn't show the first time through as the user is yet to make a mistake)Pressing Cancel triggers a separate exit message to let the user know the code has terminated early
Option Explicit
Sub Rattle_and_hmmmm()
Dim strReply As String
Dim strTitle As String
Dim objRegex As Object
Set objRegex = CreateObject("vbscript.regexp")
With objRegex
.ignorecase = True
.Pattern = "^Q[1-4]\s20[10-20]{2}$"
Do
If strReply <> vbNullString Then strTitle = "Please retry"
strReply = Application.InputBox("Enter period (format: Q4 2010) to update, or hit enter to escape", strTitle, "Q" & Int((Month(Now()) - 1) / 3) + 1 & " " & Year(Now()), , , , , 2)
If strReply = "False" Then
MsgBox "User hit cancel, exiting code", vbCritical
Exit Sub
End If
Loop Until .test(strReply)
End With
Sheets("Sheet1").[b14].Value = UCase$(strReply)
End Sub
I have difficulties with both the earlier answers.
I agree that validation is essential; the user might type "2011-4" if they do not think hard enough about the prompt. Checking that its format is "Q# ####" is definitely a step in the right direction. However:
I would have pointed out that this level of checking is not enough. "Q5 1234", for example, would match this format. "Q5 1234" would suggest the user was trying to break the system but "Q4 2101" is an easy error to make.
The Like operator is your only choice with Excel 2003 but with later versions I would recommend considering regular expressions. I have been trying them out with VB 2010. I do not deny they are a struggle to understand but they do so much for you. Perhaps heavyarms has enough learning on his plate at the moment but I would still suggest looking at some of the recent questions about their use.
As used in the earlier answers, InputBox does not achieve heavyarms' objective. If I typed "Q4 2101" instead of "Q4 2011" and the macro was enhanced to check for impossible dates, I would not know of my simple error unless the error message included the value I typed. Also I could not edit "Q4 2101" to the value I meant to type. The syntax for InputBox is vReply = InputBox(Prompt, Title, Default, ...). So if I was going to recommend the use of the Like operator, I would suggest:
Sub updatesheet()
Dim vReply As String
Dim Prompt As String
Dim Title As String
Dim UpdateQuarter As Integer
Dim UpdateYear As Integer
' I have found users respond better to something like "Qn ccyy"
Prompt = "Enter period (format: Qn ccyy) to update, or hit enter to escape"
' I find a title that gives context can be helpful.
Title = "Update sheet"
vReply = InputBox(Prompt, Title)
Do While True
' I have had too many users add a space at the end of beginning of a string
' or an extra space in the middle not to fix these errors for them.
' Particularly as spotting extra spaces can be very difficult.
vReply = UCase(Trim(VReply))
vReply = Replace(vReply, " ", " ") ' Does not cater for three spaces
If Len(vReply) = 0 Then Exit Sub
If vReply Like "Q# ####" Then
' I assume your macro will need these value so get them now
' so you can check them.
UpdateQuarter = Mid(vReply, 2, 1)
UpdateYear = Mid(vReply, 4)
' The check here is still not as full as I would include in a macro
' released for general use. I assume "Q4-2011" is not valid because
' the quarter is not finished yet. Is "Q3-2011" available yet? I
' would use today's date to calculate the latest possible quarter.
' I know "You cannot make software foolproof because fools are so
' ingenious" but I have learnt the hard way that you must try.
If UpdateQuarter >= 1 And UpdateQuarter <= 4 And _
UpdateYear >= 2009 And UpdateYear <= 2012 Then
Exit Do
Else
' Use MsgBox to output error message or include it in Prompt
End If
Else
' Use MsgBox to output error message or include it in Prompt
End If
vReply = InputBox(Prompt, Title, vReply)
Loop
End Sub
Lastly, I rarely use InputBox because Forms, once mastered, are so easy to create and offer far more control.