如何在受保护的 Word 文档中使用 Word RepeatingSection ContentControl

Posted

技术标签:

【中文标题】如何在受保护的 Word 文档中使用 Word RepeatingSection ContentControl【英文标题】:How to use the Word RepeatingSection ContentControl in a protected word document 【发布时间】:2018-11-19 10:48:37 【问题描述】:

列表项

我正在 Visual Studio 2017 中使用 VSTO 和 c# 为表单填写应用程序实现 Word 模板,并希望利用 Word 重复部分内容控件。但是,在我之前保护了文档以进行表单填写之后,我无法以编程方式应用这种类型的控件。在这种情况下,取消保护文档似乎不会使文档恢复到与保护之前相同的未受保护状态。这是一个精简的演示程序来突出这个问题:

在 Visual Studio 中新建一个 Word 2013 和 2016 VSTO 模板项目,让项目使用未更改的默认空白文档模板,将以下代码添加到 ThisDocument 部分类

private void ThisDocument_Startup(object sender, System.EventArgs e)
    
        //Demonstrates an unexpected impact of protecting then subsequently unprotecting a document 
        AddTableDirect();
        DocProtect();
        DocUnprotect();
        AddTableRepeatingSection();
    
    private void ThisDocument_Shutdown(object sender, System.EventArgs e)
    
    
    private void DocProtect()
    
        //Protects the active document restricting the operator to form filling
        object noReset = true;
        object password = System.String.Empty;
        object useIRM = false;
        object enforceStyleLock = false;
        this.Protect(Word.WdProtectionType.wdAllowOnlyFormFields,
            ref noReset, ref password, ref useIRM, ref enforceStyleLock);
    
    private void DocUnprotect()
    
        // Unprotects the active document allowing programmatic manipulation
        object password = System.String.Empty;
        this.Unprotect(ref password);
    
    private void AddTableDirect()
    
        //Creates a one row table directly adding a single plain text content control
        Word.Range range = this.Sections[1].Range.Paragraphs[1].Range;
        Word.Table table = this.Tables.Add
            (range, 1, 1, Word.WdDefaultTableBehavior.wdWord9TableBehavior, Word.WdAutoFitBehavior.wdAutoFitWindow);
        Word.ContentControl cc = this.ContentControls.Add
            (Word.WdContentControlType.wdContentControlText, table.Cell(1, 1).Range);
    
    private void AddTableRepeatingSection()
    
        //Programatically duplicates the table as a repeating section
        Word.Table table = this.Sections[1].Range.Tables[1];
        Word.Range rSRange = table.Range;
        Word.ContentControl rSCC = this.ContentControls.Add
            (Word.WdContentControlType.wdContentControlRepeatingSection, rSRange);
        rSCC.RepeatingSectionItems[1].InsertItemAfter();
    

如果您按原样构建并运行此代码,则会在添加重复部分的语句中生成带有文本的 System.Runtime.InteropServices.COMException:“此方法或属性不可用,因为当前选择部分覆盖纯文本内容控件” AddTableRepeatingSection() 方法中的控件(InsertItemAfter 之前的行)。

但是,如果您将ThisDocument_StartUp 中的DocProtect()DocUnprotect() 语句注释掉,则此代码将成功运行。

在以编程方式应用重复部分内容控件时,我需要更改哪些内容才能保护和取消保护文档而不产生此异常?

【问题讨论】:

1) 内容控件是 WORD 原生的,与 Windows 窗体无关。 2) 在 VSTO 文档级自定义中使用this.Application.ActiveDocumentthis 确实代表 VSTO 文档。如果您想使用本机对象而不是 VSTO 对象,请使用this.InnerObject。 3) 您需要描述您应用重复部分内容控制的文档的原始状态,以便我们可以测试/重现问题。 4) 哪一行代码触发了错误? InsertItemAfter 还是之前的那一行? 注意重新 WinForms,我确实是指 Word 中的重复部分内容控件。我已按照建议在代码中用简单的“this”替换了 this.Application.ActiveDocument 的使用(结果没有明显变化)。我有兴趣了解在 VSTO 文档级自定义中使用 this.Application.ActiveDocument 所带来的风险吗? 这个demo中的文档状态是一个不变的默认空白文档模板。要重新创建,只需在 Visual Studio 2017 中创建一个新的 Word 2013 和 2016 VSTO 模板项目,将代码复制到 ThisDocument 部分类(但要更正使用 this.Application.Activedocument),然后按开始。其余的按照说明进行。 触发错误的那一行是InsertItemAfter之前的那一行 【参考方案1】:

我可以复制你所看到的 - 我不知道它为什么这样做,似乎几乎是某种竞争条件,因为在打开文档后(点击“继续”)它手动工作......

我找到了解决方法。似乎选择表格会将导致 Word 在第一个单元格中拾取内容控件的任何内容放回它所属的位置:

private void AddTableRepeatingSection()

    //Programatically duplicates the table as a repeating section
    Word.Table table = this.Sections[1].Range.Tables[1];
    Word.Range rSRange = table.Range;
    rSRange.Select();
    Word.Range r = this.Application.Selection.Range;
    Word.ContentControl rSCC = this.ContentControls.Add
        (Word.WdContentControlType.wdContentControlRepeatingSection, r);
    rSCC.RepeatingSectionItems[1].InsertItemAfter();

【讨论】:

是的,添加 rSRange.Select(); 似乎可以解决。为什么还要单独添加附加语句 Word.Range r = this.Application.Selection.Range;rSRange.Select(); 似乎就足够了? @January59 只是因为拥有一个 Range 对象对我来说感觉更好 :-) 那,它使更长的代码行更适合在页面上。在我最初的测试中,我使用了“straight”选项。

以上是关于如何在受保护的 Word 文档中使用 Word RepeatingSection ContentControl的主要内容,如果未能解决你的问题,请参考以下文章

如何给文档加密

word文件属性内容怎么去掉加密内容以便保护数据?

为啥word不能打字?:

如何对word以及excel进行保护,别人不可以进行任何操作

C# 将Word转为PDF时,设置PDF文档保护

如何将htmlTable从查看器导出到R中的word文档