如何以编程方式保护 Word 文档免受用户窗体命令按钮的影响?



>我有一个MS Word文档,它是一个10个问题的评估,由顶部的表格组成,其中包含您的姓名和下面的表格部分等详细信息,每个表格用于1个问题和答案,并根据需要添加书签。该文件的基本要点是;

  1. 打开时,文档"隐藏"并显示一个UserForm以完成所需问题,包括您的姓名(如以下示例代码所示(。
  2. UserForm被"锁定",关闭它的唯一方法是强制关闭MS Word或单击命令按钮并输入正确的密码。
  3. 表单的导航是通过"下一个"和"上一个"命令按钮实现的。
  4. 表单
  5. 末尾是一个"提交"按钮(代码如下所示(,单击该按钮时,系统会提示用户确认他们已准备好提交评估,如果"是",则表单将UserForm控件中的值写入文档中的相关书签,将一些书签替换为封闭书签, 保存文档,撰写电子邮件并附加准备发送的文档,然后调整窗口大小并关闭MS Word。

简而言之,上述方法非常有效,但是在测试之后,一些用户设法将他们的一些答案加倍。

由于用户遍布全国各地,因此可能很难取得联系(并且对于某些用户来说,试图弄清楚事情是如何发生的可能很困难(,所以我得出的结论是最合乎逻辑的原因是:

用户没有"启用内容",只是为了
  • "启用内容"而完成文档,并被迫通过UserForm完成评估,因此在提交时向书签位置添加另一个答案。

因此,为了克服这个问题,我包含了保护文档不被编辑的代码。

它按照各种代码块的预期保护和取消保护,例如管理员用于关闭用户表单的覆盖,通常用于标记以及文档打开(当然启用宏(或用户表单终止时。但是,在提交时保存文档之前保护文档的行似乎不起作用(由于缺乏更好的术语(。

文档在所有实例中打开时,最好受到保护。由于文档是在启用保护的情况下分发的,因此起初它可以正常工作,但是在提交后,如果未启用宏(如果出现提示(,则可以在没有UserForm的情况下打开和编辑保存的版本。

此代码是缩短版本(省略了 19 个变量、15 个书签引用和 4 个封闭书签替换(。对于示例,我们假设要保护/取消保护工作表,密码为"abc123"。

Private Sub cmdSubmit_Click()
Dim confirm As Integer
confirm = MsgBox("Have you checked all your answers are correct?" & vbNewLine & vbNewLine & "By clicking 'Yes' you are confirming your completion of this Assessment", vbYesNo, "Submission Confirmation")
If confirm = vbNo Then
Exit Sub
ElseIf confirm = vbYes Then
MsgBox "A new email will open with this document attached." & vbNewLine & vbNewLine & "Please click send and set the security status to 'Un-classified'", vbInformation, "For Your Information"
Dim yourName As String
yourName = UserForm1.TextBox1.Text
If Not ActiveDocument.ProtectionType = wdAllowOnlyReading Then
ActiveDocument.Protect wdAllowOnlyReading, , "abc123"
End If
ActiveDocument.Unprotect "abc123"
ActiveDocument.Bookmarks("name").Select
With Selection
.TypeText Text:=yourName
End With
ActiveDocument.Bookmarks("name").Select
With Selection
.MoveEnd Unit:=wdLine, Count:=1
.Bookmarks.Add name:="name"
End With
End If
ActiveDocument.Protect wdAllowOnlyReading, , "abc123"
ActiveDocument.SaveAs2 FileName:="H:Assessment 1_" & yourName, FileFormat:= _
wdFormatXMLDocumentMacroEnabled, LockComments:=False, password:="", _
AddToRecentFiles:=True, WritePassword:="", ReadOnlyRecommended:=False, _
EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData _
:=False, SaveAsAOCELetter:=False, CompatibilityMode:=14
'Some code executes here to attach the saved document to a new outlook mailitem ready for sending. 
Application.WindowState = wdWindowStateNormal
Application.Resize 600, 700
Application.Quit
End Sub

我已经逐步完成了代码并执行了该行。据我了解,整个代码是按逻辑顺序排列的,我认为没有任何理由它既不保护文档,要么在重新打开时打开并启用保护,因为它在设置保护后已保存。

我有一种感觉,要么是我还没有在Word VBA中学到的东西,要么是关于SaveAs代码没有保存保护的东西,有什么想法吗?

您正在应用完全只读保护。但是,当您保存为时,您将更改文档名称和文档类型,从不支持宏更改为支持宏。这将取消"只读"状态。因此,您需要在保存后再次保护,然后进行"普通"保存。

如果要实现对表单的保护而不是"只读",则可以避免这种情况。由于您没有在文档中设置任何可编辑区域,因此对于任何一种保护类型,我可以看到您使用哪个区域都不会有任何区别......

doc.Protect wdAllowOnlyFormFields, True, "abc123"

下面是我的测试代码,对您发布的内容进行了优化。我所做的一项重要更改是在发出 Unprotect 命令(如果有的话(之前检查保护类型,这是您最初遇到的问题。我使用Document对象,而不是重复ActiveDocument,因为用户可能会以某种方式更改文档。我使用对象而不是Selection作为书签。

Public Sub cmdSubmit_Click()
Dim confirm As Integer
Dim yourName As String
Dim doc As Word.Document
Dim rngBookmark As Word.Range
Set doc = ActiveDocument
confirm = MsgBox("Have you checked all your answers are correct?" & vbNewLine & _
vbNewLine & "By clicking 'Yes' you are confirming your completion of this Assessment", _
vbYesNo, "Submission Confirmation")
If confirm = vbNo Then
Exit Sub
ElseIf confirm = vbYes Then
MsgBox "A new email will open with this document attached." & vbNewLine & _
vbNewLine & "Please click send and set the security status to 'Un-classified'", _
vbInformation, "For Your Information"
yourName = UserForm1.TextBox1.Text
If doc.ProtectionType <> wdNoProtection Then
doc.Unprotect "abc123"
End If
Set rngBookmark = doc.Bookmarks("name").Range
rngBookmark.Text = yourName
doc.Bookmarks.Add Name:="name", Range:=rngBookmark
End If
doc.Protect wdAllowOnlyReading, , "abc123"
doc.SaveAs2 fileName:="c:TestAssessment 1_" & yourName, FileFormat:= _
wdFormatXMLDocumentMacroEnabled, LockComments:=False, Password:="", _
AddToRecentFiles:=True, WritePassword:="", ReadOnlyRecommended:=False, _
EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData _
:=False, SaveAsAOCELetter:=False, CompatibilityMode:=14
'Saving to a different name, in a different file type, annuls the read-only protection
'so protect again
doc.Protect wdAllowOnlyReading, , "abc123"
'Some code executes here to attach the saved document to a new outlook mailitem ready for sending.
Application.WindowState = wdWindowStateNormal
Application.Resize 600, 700
Application.Quit
End Sub

最新更新