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