The below Word VBA code signs a Microsoft Word document that is opened in Word containing a CoSign signature field using CoSign SAPI. This code successfully executes and signs the Word document. The VBA code must close the Word document before signing with SAPI and then re-open the document after signing (see below code with asterisks). When the document is signed by user there is custom VBA code that needs to execute.
Is there a way to modify the VBA code to sign the Word document without having to close the Word document first?
Is there a way to intercept the CoSign Sign event in VBA code when right-clicking on the CoSign signature field in Word and clicking Sign?
'** VBA for Word Code using CoSign SAPI to sign Word document
Public Sub CoSign_SignDocument()
Const SAPI_OK As Integer = 0
Const SUB_NAME As String = "coSign_SignDocument"
Dim i As Integer
Dim rc As Integer
Dim SAPI As SAPICrypt
Dim sesHandle As sesHandle
Dim SFS As SigFieldSettings
Dim SFI As SigFieldInfo
Dim SFH As SigFieldHandle
Set SFI = New SigFieldInfo
Set SFS = New SigFieldSettings
Set sesHandle = Nothing
Set SAPI = New SAPICrypt
'Custom Values
Dim filePath As String 'file to sign
Dim username As String 'CoSign account username
Dim FH As FileHandle
Dim password As String 'CoSign account password
Dim domain As String 'CoSign account domain
Dim flags As Integer
Dim FieldName As String
'Assign values to the variables declared above
username = "{signer_username}" 'CoSign account username
password = "{signer_password}" 'CoSign account password
domain = "" 'CoSign account domain
flags = 0
On Error GoTo CatchExecption
'Initialize SAPI library
rc = SAPI.Init
If rc <> SAPI_OK Then
Err.Raise vbObjectError + 1001, MODULE_NAME + ":" + SUB_NAME, _
"Failed to initialize SAPI " + Str(rc) + " " + Err.Description
End If
'Acquire SAPI session handle
rc = SAPI.HandleAcquire(sesHandle)
If rc <> SAPI_OK Then
Err.Raise vbObjectError + 1001, MODULE_NAME + ":" + SUB_NAME, _
"Failed in SAPIHandleAcquire() " + Str(rc) + " " +
Err.Description
End If
'Personalize SAPI Session
SAPI.Logon sesHandle, username, domain, password
If rc <> SAPI_OK Then
Err.Raise vbObjectError + 1001, MODULE_NAME + ":" + SUB_NAME, _
"Failed to authenticate user " + Str(rc) + " " + Err.Description
End If
Dim fileType As SAPI_ENUM_FILE_TYPE
fileType = SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_WORD
'**** Close the Word Document before processing with SAPI functions
filePath = ActiveDocument.FullName
ActiveDocument.Close SaveChanges:=False
FieldName = "Secretary"
'Initialize enumerating signature fields
Dim SFC As SAPIContext
Set SFC = New SAPIContext
Dim SFNum As Long
Dim SFFlags As Integer
rc = SAPI.SignatureFieldEnumInit(sesHandle, SFC, fileType, filePath, 0, SFNum)
If rc <> 0 Then
Err.Raise vbObjectError + 1001, MODULE_NAME, _
"Failed in SignatureFieldEnumInit() " + Str(rc) + " " + Err.Description
End If
Dim isFound As Boolean
For i = 1 To SFNum
'Get Next field's handle
rc = SAPI.SignatureFieldEnumCont(sesHandle, SFC, SFH)
If rc <> 0 Then
SAPI.ContextRelease SFC
SAPI.Logoff sesHandle
SAPI.HandleRelease sesHandle
Err.Raise vbObjectError + 1001, MODULE_NAME, _
"Failed in SignatureFieldEnumCont() " + Str(rc) + " " + Err.Description
End If
'Retrieve Signature Field's info
rc = SAPI.SignatureFieldInfoGet(sesHandle, SFH, SFS, SFI)
If rc <> 0 Then
SAPI.HandleRelease SFH
SAPI.ContextRelease SFC
SAPI.Logoff sesHandle
SAPI.HandleRelease sesHandle
Err.Raise vbObjectError + 1001, MODULE_NAME, _
"Failed in SAPI.SignatureFieldInfoGet() " + Str(rc) + " " + Err.Description
End If
'Check that the field we've found is not signed. If Signed - just skip it.
If SFI.IsSigned <> 0 Then
GoTo NextLoop
End If
If SFS.Name = FieldName Then
SAPI.ContextRelease SFC
isFound = True
Exit For
End If
'Release handle of irrelevant signature field
SAPI.HandleRelease SFH
NextLoop:
Next i
If Not isFound Then
SAPI.ContextRelease SFC
SAPI.Logoff sesHandle
SAPI.HandleRelease sesHandle
Err.Raise vbObjectError + 1001, MODULE_NAME, _
"The file doesn't contain any signature field named: " + FieldName + " " + Err.Description
End If
'Sign signature field
rc = SAPI.SignatureFieldSignEx(sesHandle, SFH, 0, "")
If rc <> 0 Then
Err.Raise vbObjectError + 1001, MODULE_NAME, _
"Failed in SignatureFieldSign() " + Str(rc) + " " + Err.Description
End If
'***** Re-open the Word document after signing with SAPI
Dim wd As Word.Document
Set wd = Word.Documents.Open(FileName:=filePath)
wd.Activate
Set wd = Nothing
GoTo Finally
CatchExecption:
MsgBox "Error: " + Err.Description
Finally:
On Error GoTo errProc
If Not sesHandle Is Nothing Then
SAPI.Logoff sesHandle 'Release user context
SAPI.HandleRelease sesHandle 'Release session handle
End If
Exit Sub
errProc:
MsgBox "Error in coSign_SignDocument Routine. " & Err.Description
End Sub