下面的 Word VBA 代码使用 CoSign SAPI 对在 Word 中打开的包含 CoSign 签名字段的 Microsoft Word 文档进行签名。此代码成功执行并签署 Word 文档。VBA 代码必须在使用 SAPI 签名之前关闭 Word 文档,然后在签名后重新打开文档(参见下面带星号的代码)。当文档由用户签名时,需要执行自定义 VBA 代码。
有没有办法修改 VBA 代码来签署 Word 文档而不必先关闭 Word 文档?
右键单击 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