【问题标题】:How to detect that a Paragraph.Range is inside a TOC in a C# Word AddIn如何检测 Paragraph.Range 在 C# Word AddIn 的 TOC 内
【发布时间】:2019-10-28 10:10:04
【问题描述】:

我正在制作一个具有一些功能的 MS-Word 插件。其中之一是删除过多的空行(当前规则规定 Document 不能有超过两个连续的空行,并且在最后一行文本之后不能有空行)。

我已经编写了一个代码来尝试实现这一点:

private void formatText() {
    Microsoft.Office.Interop.Word.Paragraphs paragraphs = Globals.ThisAddIn.Application.ActiveDocument.Paragraphs;
    Boolean isPreviousLineEmpty = false;
    Boolean isLastLine = true;

    for (int i = paragraphs.Count - 1; i > 0; i--) {
        Microsoft.Office.Interop.Word.Paragraph paragraph = paragraphs[i];

        if (paragraph.Range.Text.Trim().Equals("")) {
            if (isLastLine) {
                paragraph.Range.Delete();
                continue;
            }

            if (isPreviousLineEmpty) {
                paragraph.Range.Delete(); //This is the line where the error happens
            }   

            isPreviousLineEmpty = true;
            continue;
        }

        if (isLastLine) {
            paragraph.Range.Text = paragraph.Range.Text.TrimEnd();
            isLastLine = false;
        }

        isPreviousLineEmpty = false;
    }
}

在我向文档中添加“目录”(TOC) 之前,它一直有效。现在我得到一个错误:

System.Runtime.InteropServices.COMException: '无法编辑范围。'

原因是:我的代码试图删除 TOC 上的一条白线,但它不能。我已经搜索了文档/互联网,并尝试了我能想到的所有方法来阻止我的代码在 TOC 行上运行,但没有任何效果。

我需要一种方法来知道我可以跳过该行,因为我不需要删除 TOC 中的空白行。

目前,我能做的是用 Try/Catch 块包装执行删除的特定行,但我认为这不是最好的解决方案(因为我可能会忽略其他错误,这只是一个消音器)。

有谁知道这个案例的正确处理方法吗?


更新:

Freeflow 评论之后,我将所有方法代码都替换为:

private void formatText() {
    Microsoft.Office.Interop.Word.Find find = Globals.ThisAddIn.Application.ActiveDocument.Range().Find;
    Microsoft.Office.Interop.Word.Paragraphs paragraphs = Globals.ThisAddIn.Application.ActiveDocument.Paragraphs;
    Boolean operationResult = true;

    //Remove blank lines at the end of the document
    for (int i = paragraphs.Count - 1; i > 0; i--) {
        Microsoft.Office.Interop.Word.Paragraph paragraph = paragraphs[i];

        if (paragraph.Range.Text.Trim().Equals("")) {
            paragraph.Range.Delete();
            continue;
        }

        paragraph.Range.Text = paragraph.Range.Text.TrimEnd();

        break;
    }

    //Remove blank lines between paragraphs
    while (operationResult) {
        operationResult = find.Execute("^p^p^p", false, false, false, false, false, false, null, null, "^p^p",
            Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll);
    }
}

到目前为止,它一直运行良好。如果有什么问题,我会在这里发帖。

感谢您的评论。如果您将其转换为答案,我会将其标记为已接受。

【问题讨论】:

  • 为什么不直接在 ^p^p 上查找和替换 ^p。
  • 莫里斯,不要在问题中发布答案。放入一个答案框,然后(几天后)将其标记为“答案”。请注意,Freeflow 不会看到您关于撰写他们的评论作为答案的评论。
  • 一般来说,还有一个关于你想要做什么的评论:这是一个 TOC。这意味着它是一个动态生成的 字段结果。如果 TOC 更新,所做的任何编辑都将消失。真正解决此问题的唯一方法是找出这些额外段落的来源并将其从文档中删除。

标签: c# ms-word vsto word-addins


【解决方案1】:

Word 对象模型有一个有用的方法:InRange,它允许检查一个文本范围是否是另一个文本的一部分。从逻辑上讲,可以比较段落的位置是否在 TOC 内。

下面是一个测试示例,最初是用 VBA 编写的。我正在将其即时转换为 C#,因此可能存在一些小的语法错误...

public void TestRangeInToc()
{
    Word.Document doc =Globals.ThisAddIn.Application.ActiveDocument;
    bool HasToc = false;

    if(doc.TablesOfContents.Count > 0)
    {
        HasToc = true;
    }

    foreach(Word.Paragraph para In doc.Paragraphs)
    {
        if(HasToc)
        {
            if(IsRangeInTOC(para.Range, doc))
            {
               Debug.Print("in range");
               //skip this one
            }
        }
    }
}

public bool IsRangeInTOC(Word.Range rng, Word.Document doc)
{
    Word.TableOfContents toc         
    foreach(toc in doc.TablesOfContents)
    {
        if(rng.InRange(toc.Range))
        {
            return true;
            break;
        }
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多