Back Population of VBA InputBox? - excel

So currently under specific conditions I have this InputBox poping up for the user to enter notes into and then that box fill those notes to a cell. What I would like to try to do is if notes are already in the cell that the InputBox is filling notes to, those notes will already appear in the input field so that the user can add to them. I have no idea if this can be done and could not find anything on google. If this cannot be done ill just use a user form insted.
The current code that brings up the input box is below, "notes" is the feild that the InputBox fills to:
If InStr(OPs, "Incomplete") > 0 Or InStr(OPs, "Miss") Then
notes.Interior.Color = RGB(255, 200, 0)
If notes = "" Then
Do While notes = ""
notes = notes & InputBox("You must imput notes for " & Desc & " !", "Notes")
Loop
End If
End If

Use the Default parameter of InputBox:
Something like:
notes = notes & InputBox("You must input notes for " & Desc & " !", "Notes", notes)
However, if you use this, you don't want to use the notes = notes & ... as the string field will quickly overfill.. so perhaps just:
notes = InputBox("You must input notes for " & Desc & " !", "Notes", notes)

Related

Excel VBA Textbox_Exit Event Handler

At a road block here. Simple user form using three text boxes, one for user id, two to enter serial number using hand scanner. User loads excel file, userform.show loads, user enters id then simple validation to verify numberic number, then focus set on first textbox, user scans barcode to input serial number, again simple validation to ensure numeric and length, same with last textbox, scan serial number, validate first textbox entry matches second textbox entry.
Hand scanner is used to input serial number and also returns a "return carriage" character; e.g. enter button press after serial number scan.
Using "return carriage" to fire textbox_exit event handler. Issue is very intermittent but consistent. I load userform, input data, when record is complete, data is transferred to object worksheet. However, when troubleshooting, I initially open workbook and userform, create a few records, save, and close. Everything works well and data is recorded and archived. Issue generally arises when i load workbook a second time, enter data for one record, save, and begin second record. Once serial number is entered into first textbox, exit event never fires using "return carriage". I can manually transfer focus to other objects; e.g. diff textbox, but the overall operation is not as expected.
I have tried inserting application.eventhandler=true commands, different event handlers, as well as numerous code changes; e.g. exit sub at end of IF statements, to make this work.
Thought I would reach out to the community for some feedback. FYI, issues still arises if I simulate hand scanner using copy/paste and enter key.
Example of exit event handler for first serial textbox below.
Private Sub SerialIn_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Cancel = False
If Not IsNumeric(SerialIn.Value) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
MsgBox Msg, vbCritical, "Warning" 'display msg
Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Exit Sub
Else
If Not Len(SerialIn.Value) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
MsgBox Msg, vbCritical, "Warning"
Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Exit Sub
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
Me.SerialOut.SetFocus
Exit Sub
End If
End If
End Sub
New code:
Private Sub SerialIn_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Cancel = ValidateSerialIn(SerialIn)
End Sub
Function ValidateSerialIn(ByVal TextBox As Object) As Boolean
If Not IsNumeric(SerialIn.Value) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning" 'display msg
SerialIn.SetFocus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
ValidateSerialIn = True
Else
If Not Len(SerialIn.Value) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning"
'Cancel = True 'stop user from changing focus
SerialIn.SelStart = 0 'highlight user text
SerialIn.SelLength = Len(SerialIn.Value) 'select user text
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
ValidateSerialIn = True
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
ValidateSerialIn = False
End If
End If
End Function
Third go using Tim's TextBox_Change solution:
Private Sub SerialIn_Change()
Dim v
v = ScannedValue1(SerialIn.Text)
If Len(v) > 0 Then
If Not IsNumeric(v) Then 'validate serial number is numeric
'error msg serial number is not numeric
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning" 'display msg
SerialIn.Text = vbNullString
Else
If Not Len(v) = 19 Then 'validate serial number length
'error msg incorrect length
Msg = "Opps, something went wrong! Serial number was incorrect." _
& vbNewLine & vbNewLine & "Rescan module serial number."
msgbox Msg, vbCritical, "Warning"
SerialIn.Text = vbNullString
'Image1.Picture = LoadPicture(StopLightRed) 'display red stop light
Else
SerialInTime.Caption = Now 'record date and time
'Image1.Picture = LoadPicture(StopLightYellow) 'display yellow WIP stop light
SerialOut.SetFocus
End If
End If
End If
End Sub
'check if a value ends with vbcrlf or vblf
' - if yes strip that off and return the rest
' - otherwise returns empty string
Function ScannedValue1(vIn) As String
Dim rv As String
If Right(vIn, 2) = vbCrLf Then
ScannedValue1 = Replace(vIn, vbCrLf, "")
ElseIf Right(vIn, 1) = vbLf Then
ScannedValue1 = Replace(vIn, vbLf, "")
End If
End Function
If you want to detect the "Enter" from the scanner then use the Change event to check if the textbox value ends with vbCrLf or vbLf (in that order): if it does, then trigger the "scan" action.
Note you need to set your textbox to "multiline=true" and "EnterKeyBehaviour = true" in order for the Change event to capture the enter key.
Private Sub TextBox1_Change()
Dim v
v = ScannedValue(TextBox1.Text)
If Len(v) > 0 Then
TriggerScanAction v
TextBox1.Value = ""
End If
End Sub
'check if a value ends with vbcrlf or vblf
' - if yes strip that off and return the rest
' - otherwise returns empty string
Function ScannedValue(vIn) As String
Dim rv As String
If Right(vIn, 2) = vbCrLf Then
ScannedValue = Replace(vIn, vbCrLf, "")
ElseIf Right(vIn, 1) = vbLf Then
ScannedValue = Replace(vIn, vbLf, "")
End If
End Function
'execute some action triggered by a scanned value
Sub TriggerScanAction(v)
MsgBox "You scanned " & v
End Sub
The Exit event has more to it than meets the eye. On most forms, one enters a value in a textbox and then clicks "OK", a command button. Tbx.Exit event occurs. It also occurs if you click anywhere else, such as a button to close the form. In your system the CR triggers the event as well, and that would appear to be the problem.
When a CR or TAB is entered in your Tbx the form's tapping sequence takes over. The exit occurs, followed by the enter event of the next control in your tapping order. (Compare that to the manual change of focus that occurs when the user determines the next control.)
So, the solution should be not to use the Exit event but to let the CR initiate a change of focus, using the tapping order setting, which lands the focus on an "OK" button, then let that button's Enter event trigger its Click event (if it doesn't do that by default).
You probably want a cycle there, where the CR triggers the worksheet entry and the focus comes back to the Tbx. That's one more reason not to use the Exit event because you don't want an entry made in the worksheet when you exit the Tbx to close the form.
However, perhaps your form doesn't have or need an "OK" button. In that case I would recommend the BeforeUpdate event of the Tbx. Both Exit and BeforeUpdate occur in close succession. The sequence isn't important however (though that's not the reason why I forgot it :-)) but their nature. Use the exit event in the context of form control, setting focus or reacting to focus change. BeforeUpdate obviously refers to data. Each of these events is fine tuned to its own task and therefore does it better than the other.

How to take text from a cell and input it into VBA?

What I am trying to do is basically you click a button, it brings up the Excel MailEnvelope to send an email, and you can then send it off to the relevant button email address'.
However one of the email addresses needs to be modifiable by the end user.
So I want a drop down where you select said email, and it then inputs that into the VBA code.
I know basically nothing about VBA and I could not find a way of doing this by searching around the web.
I figured I need some way of setting a variable to read a cell (the drop down cell), and then input that into the MailEnvelope Item.CC but I was struggling.
Any help would be appreciated.
This is what I have so far;
Sub Send_Range_Email()
' Select the range of cells on the active worksheet.
ActiveSheet.Range("B6:D302").Select
' Show the envelope on the ActiveWorkbook.
ActiveWorkbook.EnvelopeVisible = True
' Set the optional introduction field thats adds
' some header text to the email body. It also sets
' the To, CC and Subject lines.
With ActiveSheet.MailEnvelope
.Introduction = ""
.Item.To = "Email 0"
.Item.Subject = "Email Tracker Results"
.Item.CC = "Email 1" & text input here & "Email 2"
End With
End Sub
When using formulas, if you want to put a variable in there, just break it apart and add in the variable. As commented,
.Item.CC = "email 1" & "," & Range("A1").Value & ", " & "Email 2"
So to make super clear, say we want to add A1's value in this string: str = The man lives in STATE all the time by doing str = "The man lives in " & Range("A1").Value & " all the time"

Excel 2016 Macro to edit Hyperlink

Currently I need to change over hundreds of cells of hyperlinks to a new format that is being used.
Previously we would have for example "https://oldServer:oldPort/project_code/Some_File"
and we are now moving to
"https://newServer:newPort/project_code/Some_File".
I only want to be able to change the "oldServer:oldPort" to "newServer:newPort" without changing the rest of the hyperlink.
I know an excel macro would be the easiest solution but I do not have the experience to be able to create one.
You'd want to loop through each of the hyperlink objects in each sheet.
Code something like this should work. (Make sure you backup before testing this, since I can't test on your actual data!)
Also, note that this changes the link but not the text displayed, since I'm not sure what that consists of. The text could be changed with the same procedure by updating TextToDisplay, or else by using Find & Replace.
Edit: (added confirmation on each change.)
Sub changeLinks()
Const oldPrefix = "https://oldServer:oldPort/"
Const newPrefix = "https://newServer:newPort/"
Dim h As Hyperlink, oldLink As String, newLink As String
For Each h In ActiveSheet.Hyperlinks
'this will change Address but not TextToDisplay
oldLink = h.Address
Debug.Print "Found link: " & oldLink
If Left(oldLink, Len(oldPrefix)) = oldPrefix Then
newLink = newPrefix & Right(h.Address, Len(h.Address) - Len(oldPrefix))
If MsgBox("Click OK to change:" & vbLf & vbLf & oldLink & _
vbLf & vbLf & "to" & vbLf & vbLf & newLink, vbOKCancel, _
"Confirmation?") <> vbOK Then Exit Sub
h.Address = newLink
Debug.Print " Changed to " & h.Address
End If
Next h
End Sub
I removed the hyperlink from the column containing the old server information. Then I created a couple of new columns. I typed in the full path to the new server in the first new columns and filled it down. In the other new column I created a formula to concatenate the full path and the friendly name (which happened to be what the link was originally named). This created the new server path along with the file name. I copied/pasted values of this column and deleted the contents of the first new column I created. I then used the HYPERLINK formula to put the hyperlink and the friendly name back together. It sounds more convoluted than it was - took me longer to write it down here than to actually do it in my Excel spreadsheet. I hope this makes sense.

cannot split email address and show on text box

I am selecting an email address from a combobox using a form in Excel and want to split the email address and display only first name from the selected email address. Please check the code as below:
Private Sub UserForm_Initialize()
Me.CboBugSts.List = Array("Open-Crtical", "Open-ShowStopper")
Me.CboCC.List = Array("Nandesh.kalyankar#wipro.com")
Me.CboToEmail.List = Array("firstName.LastName#Email.com")
Me.CboGrtngs.List = Array("Hi", "Dear")
TxtSubj.Value = "Bug notification logged by " & Environ("Username") & " - " & Now
End Sub
Private Sub TxtMsg_Change()
arTemp = Split(Me.CboToEmail.Text, "#")
Fname = arTemp(LBound(arTemp))
TxtMsg.Text = Me.CboGrtngs.Text & " " & Fname
End Sub
Here Me.CboToEmail.text is a value that user selects from a combobox text, and then I split the email address and concatenate it with another combobox text Me.CboGrtngs.text, but it shows the whole email, not just the first name from email.
Not sure (not a vba programmer), but since CboToEmail is defined as a list or array (with one item):
Me.CboToEmail.List = Array("firstName.LastName#Email.com")
Don't you need to extract the first element here, instead of calling .Text on the whole list?
arTemp = Split(Me.CboToEmail.Text, "#")
If not, what's the value of Me.CboToEmail.Text?

LotusScript: Saving on read mode on Audit Trail

I have a audit trail that records two fields. I just want to ask if its possible to save changes in audit trail while on read mode? My code doesn't record anything while on read mode. Can you help me guys? Here's my code:
Querysave:
Sub Querysave(Source As Notesuidocument, Continue As Variant)
initial = Source.IsNewDoc
If initial Then m$ = session.CommonUserName & " - " & Cstr(Now()) & " - Document Created"
Forall F In old
v$ = Source.FieldGetText(Listtag(F))
If Not initial And Not v$ = F Then
If m$ = "" Then
m$ = session.CommonUserName & " - " & Cstr(Now()) & " - Modified "
Else
m$ = m$ & ", "
End If
If F = "" Then F = {""}
m$ = m$ & Listtag(F) & " from " & F & " to " & v$
End If
F = v$
End Forall
If initial Then
Source.FieldSetText "History", m$
Elseif Not m$ = "" Then
Source.FieldAppendText "History", Chr$(10) & m$
End If
X: Exit Sub
E: Continue = False
Resume X
End Sub
Postopen:
Sub Postopen(Source As Notesuidocument)
Set session = New NotesSession
old("DocName") = Source.FieldGetText("DocName")
old("DocStatus") = Source.FieldGetText("DocStatus")
'Disable edit in double click
Set uidoc = source
Set doc = uidoc.Document
doc.mc = 1
End
End Sub
Whenever you need to use variables/objects between events and do not want to pollute the document with temporary values, use global variables for everything.
On postOpen the document is presumably in read mode, any changes you make to fields on the backend document (ie uidoc.document) during this event while the document is in read mode will not "stick" because you're writing to an object that is currently in read-mode. That "old" list variable is global (?), instead of trying to write to the "history" field, setup your "History" variable as a global string variable, don't try and write it to the document during postopen. When QuerySave event triggers write the global "history" string variable onto the history field on the document.
The best way (in my opinion) to create a history/audit trail when documents are saved is to put that code in the PostSave event, using backend classes.
That code is executed after the save.
One think that I often do is declaring a global list of strings. In the PostOpen event, I populate it with values from all fields except the ones that start with $.
In the PostSave (or even Terminate) event I then compare the values in that list with the current values on the document, if any value is different, I can update the document history/audit field.

Resources