1

下面的 Word VBA 代码使用 CoSign SAPI 对在 Word 中打开的包含 CoSign 签名字段的 Microsoft Word 文档进行签名。此代码成功执行并签署 Word 文档。VBA 代码必须在使用 SAPI 签名之前关闭 Word 文档,然后在签名后重新打开文档(参见下面带星号的代码)。当文档由用户签名时,需要执行自定义 VBA 代码。

  1. 有没有办法修改 VBA 代码来签署 Word 文档而不必先关闭 Word 文档?

  2. 右键单击 Word 中的 CoSign 签名字段并单击 Sign 时,是否有办法拦截 VBA 代码中的 CoSign Sign 事件?

'** VBA for Word Code 使用 CoSign SAPI 签署 Word 文档

 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
4

0 回答 0