Сопоставление абзаца в OpenXML SDK с взаимодействием абзаца в документе Word

Взаимодействие Word безумно медленное, когда я пытаюсь разобрать текст в документе, состоящем из 100+ страниц. Я переписал свой код, чтобы использовать OpenXML SDK, который работает намного быстрее. Моя проблема в том, что как только я нашел информацию в документе OpenXML, мне нужно найти ее в документе Word и прокрутить к ней главное окно. Для этого мне нужно как-то сопоставить абзац OpenXML с абзацем взаимодействия. Я думал, что абзацы взаимодействия идеально соответствуют абзацам openxml, но я ошибался. Фактически, в интерфейсе обычно больше абзацев, чем в OpenXML. Есть ли какой-нибудь трюк или какая-то информация, которая могла бы помочь мне сопоставить их? Например, я выяснил, что обычно у interop есть еще 1 пустой абзац после каждой строки в таблице. Так что я, вероятно, мог бы использовать эту информацию и иметь ее в виду, однако я боюсь, что это гораздо больше, чем просто один случай, который я обнаружил.

ОБНОВЛЕНИЕ

Ниже приведены снимки экрана простой надстройки, которые я создал, чтобы продемонстрировать разницу между абзацами interop и openxml в документе Word с таким простым содержимым, как это:

Образец документа MS Word Затем надстройка извлекает список абзацев взаимодействия и список абзацев OpenXML и показывает их рядом:

Параллельное сравнение

Вот код, который я использовал:

var document = Globals.ThisAddIn.Application.ActiveDocument;

if (document == null)
    return;

var interopParagraphs = document
    .StoryRanges
    .Cast<Range>()
    .SingleOrDefault(r => r.StoryType == WdStoryType.wdMainTextStory)
    .Paragraphs
    .Cast<Paragraph>()
    .Select(p => p.Range.Text);

var openXmlDocument = WordprocessingDocument.FromFlatOpcString(document.Content.WordOpenXML);

if (openXmlDocument == null)
    return;

var openXmlParagraphs = openXmlDocument
    .MainDocumentPart
    .Document
    .Body
    .Descendants<DocumentFormat.OpenXml.Wordprocessing.Paragraph>()
    .Select(p => p.InnerText);

var compareDialog = new CompareForm(interopParagraphs, openXmlParagraphs);
compareDialog.ShowDialog();

person Alexey Andrushkevich    schedule 08.11.2018    source источник
comment
Вы пробовали использовать selection.Find в первых 255 символах абзаца?   -  person Cindy Meister    schedule 08.11.2018
comment
Я просто попробовал создать документ в Word 2013 с таблицей 2x2 и одним абзацем сразу после нее. Никаких лишних абзацев. Попробовал еще раз с большим количеством строк, то же самое. Вы можете привести нам пример OpenXML?   -  person Chris    schedule 08.11.2018
comment
@Chris Я обновил свой вопрос более подробной информацией.   -  person Alexey Andrushkevich    schedule 09.11.2018
comment
@AlexeyAndrushkevich Вы правы, есть массовки, я смотрел на OpenXML, а не на взаимодействие. В этом конкретном случае, если вы повторяете их, вы можете использовать Range.IsEndOfRowMark или Range.Information[WdInformation.wdAtEndOfRowMarker] (не забудьте сначала свернуть диапазон, иначе это не сработает), чтобы игнорировать их, но я не знаю, какие другие случаи могут существует. Также это не сработает, если вы просто пытаетесь сопоставить индексы без итерации.   -  person Chris    schedule 09.11.2018


Ответы (1)


Превращаю мой комментарий в ответ.


В случае строк таблицы вы можете проверить, просматриваете ли вы абзац в конце строки, используя Range.IsEndOfRowMark.

Это свойство возвращает True, если указанный диапазон свернут и находится в конце строки в таблице, и False, если нет.

Вы также можете использовать Range.Information [WdInformation.wdAtEndOfRowMarker].

Возвращает True, если указанный выбор или диапазон находится в конце строки в таблице.

Несмотря на небольшое различие в документации, для этого свойства также необходимо свернуть диапазон. AFAIK, они эквивалентны.

Я также заметил, что это не работает, если вы обращаетесь к абзацу напрямую, например, Document.Paragraph [4]. Вы должны перебирать их, чтобы это сработало. Это не задокументировано.

person Chris    schedule 13.03.2019