1

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.

  1. Is there a way to modify the VBA code to sign the Word document without having to close the Word document first?

  2. 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
Jerry Hess
  • 11
  • 1

0 Answers0