With our transition to XPages, I’ve been finding more and more often that I don’t have a form interface in the Notes client to just change one field value on the back end. Too often, on the front end, in XPages, there’s a value I simply haven’t exposed for editing or don’t even display. I often don’t add the fields to the back end Notes form because it really doesn’t add much value. So, when I want to change one field, or change one field on multiple documents, I do it with an agent. Heck, over the years, we all have. We just usually did it in a very static manner – writing a quick @formula to change the value of a specific field. That requires changing the design to create the agent and then delete the agent – or leaving a mess behind that slowly grows your agent list with more and more single-use agents.
So, I wrote an agent that allowed me to replace a text field by naming the field and the value. Then, I found I wanted one for numbers as well. So, for a few weeks, I had two agents. Then, I realized the folly and wrote an agent that detects the field being updated (or asking you if the field doesn’t exist). I only did it for text, numbers and dates, so I imagine it could be extended. It’s enough for me. Since I had occasion to share it this week with another developer, I thought I’d also post it here to share via the blogosphere.
While there’s nothing brilliant about it, it sure is useful.
%REM
Agent Change Field Value
Created Jun 19, 2015 by David Navarre/DAI
Description: This Agent allows the user to name a field and change the value
It checks the field type on the first document selected and
handles strings, numbers and dates differently
%END REM
Option Public
Option Declare
Use "Utilities"
Dim ws As NotesUIWorkspace
Dim newDate As NotesDateTime
Dim newvalue As Variant
Dim fieldname As Variant
Dim change As String
Sub Initialize
Dim session As New NotesSession
' thisdb declared in Utilities '
Dim ndc As NotesDocumentCollection
Dim itemdoc As NotesDocument
Dim itemToChange As NotesItem
Dim numericValue As Double
Dim itemType As Long
Dim selectedType (2) As String
Dim choice As Variant
Dim reason As String
On Error GoTo errorhandler
Set ws = New NotesUIWorkspace
Set thisdb = session.CurrentDatabase
selectedType (0) = "Date"
selectedType (1) = "Text"
selectedType (2) = "Numbers"
Call StartAgentLogging (session )
fieldname = ws.Prompt ( PROMPT_OKCANCELEDIT, "Field Name", "Enter the name of the field to change" )
If IsEmpty ( fieldname ) Then
Exit Sub
End If
newvalue = ws.Prompt ( PROMPT_OKCANCELEDIT, fieldname, "Enter the new value for " & fieldname )
If IsEmpty ( newvalue ) Then
Exit Sub
End If
' get the collection before issuing the confirmation, so we can determine field type '
' from the first document selected, assuming it is the same on the rest '
Set ndc = thisdb.UnprocessedDocuments
Set itemdoc = ndc.GetFirstDocument
Call agentLog.LogAction ( "Items: " & ndc.Count )
If ( itemdoc.Hasitem(fieldname) ) Then
Set itemToChange = itemdoc.Getfirstitem(fieldname)
itemType = itemToChange.Type
Else
choice = ws.Prompt(PROMPT_OKCANCELLIST, "Select field type", "Field " & fieldname & " does not exist on the first document. Select field type to create", "Text", selectedType )
If IsEmpty ( choice ) Then
MessageBox "Action cancelled"
Exit Sub
End If
Select Case choice
Case "Date"
itemType = 1024
Case "Text"
itemType = 1280
Case "Number"
itemType = 768
End Select
End If
If Confirm ( itemType ) Then
While Not itemdoc Is Nothing
Select Case itemType
Case 1024 ' DATETIMES '
Call itemdoc.ReplaceItemValue ( fieldname, newDate )
Case 1280 ' TEXT '
Call itemdoc.ReplaceItemValue ( fieldname, newValue )
Case 768 ' NUMBERS '
' if the value supplied is an integer, save it that way '
If ( CInt ( CDbl ( newValue ) ) = CInt ( newValue ) ) Then
Call itemdoc.ReplaceItemValue ( fieldname, CInt ( newValue ) )
else
Call itemdoc.ReplaceItemValue ( fieldname, CDbl ( newValue ) )
End If
End Select
Call agentLog.LogAction ( change )
Call itemdoc.Save ( True, False )
Set itemdoc = ndc.GetNextDocument ( itemdoc )
Wend
MessageBox change & Chr$(10) & "Successful on " & ndc.Count & " documents"
End If
exiting:
Call agentLog.LogAction ( "-------" )
Call agentLog.LogAction ( "-------" )
Exit Sub
errorhandler:' report all errors in a messagebox '
reason = "Error #" & CStr (Err) & " (" & Error & ") on line " & CStr (Erl)
MessageBox reason, 16, "Error"
Call agentLog.LogAction ( reason )
Resume exiting
End Sub
%REM
Function ConfirmValue
Description: This function displays a confirmation dialog based on the field type
%END REM
Function Confirm ( itemType As Long ) As Boolean
Select Case itemType
Case 1024 ' DATETIMES '
Set newDate = New NotesDateTime ( newValue )
change = "Change date in " & fieldname & " to " & newDate.Dateonly
Case 1280 ' TEXT '
change = "Change text in " & fieldname & " to " & newValue
Case 768 ' NUMBERS '
change = "Change number in " & fieldname & " to " & newValue
Case 1 ' RICHTEXT '
Confirm = False
MessageBox "Cannot change rich text using this agent"
Exit Function
Case Else
Confirm = False
MessageBox "Cannot change " & fieldname & " using this agent" & Chr$(10) & "Field type: " & itemType
Exit Function
End Select
Confirm = ws.Prompt ( PROMPT_YESNO, "Confirmation", change & "?" )
End Function
Oh, and the relevant snippet of the Utilities script library….
%REM
Library Utilities
Created Mar 29, 2012 by David Navarre/DAI
Description: Some database utilities
%END REM
Option Public
Option Declare
Dim thisdb As NotesDatabase
Dim agentLog As NotesLog
Sub Initialize
End Sub
Sub StartAgentLogging ( session As NotesSession )
' this module starts agent logging '
' 29 Mar 12, David Navarre '
Dim title As String
Dim agent As NotesAgent
Set agentLog = session.CreateLog ("Agent log")
Set agent = session.Currentagent
Call agentLog.OpenAgentLog
Call agentLog.LogAction ( "Log Open" )
End Sub