Как обнаружить, что Paragraph.Range находится внутри оглавления в C # Word AddIn - PullRequest
0 голосов
/ 28 октября 2019

Я создаю MS-Word Addin с некоторыми функциями. Одним из них является удаление лишних пустых строк (текущее правило гласит, что в документе не может быть более двух последовательных пустых строк и что в нем не должно быть пустых строк после последней строки текста).

Я сделал код, чтобы попытаться добиться этого:

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: «Невозможно редактировать диапазон».

Причина в том, что на оглавлении есть белая линиячто мой код пытается удалить, а это невозможно. Я искал документацию / Интернет и перепробовал все, что мог придумать, чтобы предотвратить выполнение моего кода в строках оглавления, но ничего не помогло.

Мне нужен способ узнать, что я могупропустите эту строку, потому что мне не нужно удалять пустые строки внутри оглавления.

На данный момент, что я могу сделать, это обернуть конкретную строку, которая выполняет удаление, с помощью блока 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);
    }
}

Он работал оченьхорошо до этого момента. Если возникнет какая-либо проблема, я опубликую здесь.

Спасибо за ваш комментарий. Если вы преобразуете его в ответ, я отмечу его как принятый.

1 Ответ

1 голос
/ 28 октября 2019

В объектной модели Word есть полезный метод: InRange, который позволяет проверить, является ли один диапазон текста частью другого. Таким образом, логически можно сравнить, находится ли абзац внутри оглавления.

Ниже приведен тестовый пример, изначально написанный на 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;
        }
    }

}
...