Как найти номер страницы из абзаца с помощью OpenXML?

Как с помощью Open XML SDK 2.0 для Microsoft Office определить, на какой странице находится объект Абзац?


person Stef Heyenrath    schedule 18.02.2013    source источник


Ответы (3)


Невозможно получить номера страниц для документа Word с помощью OpanXml Sdk, так как это обрабатывается клиентом (например, MS Word).

Однако, если документ, с которым вы работаете, ранее был открыт клиентом Word и сохранен обратно, клиент добавит LastRenderedPageBreak для обозначения разрывов страниц. Обратитесь к моему ответу здесь для получения дополнительной информации о LastRenderedPageBreaks. Это позволяет вам подсчитать количество LastRenderedPageBreak элементов перед вашим абзацем, чтобы получить текущее количество страниц.

Если это не так, то вариант обхода вашего требования состоит в том, чтобы добавить нижние колонтитулы с номерами страниц (может быть того же цвета, что и ваши документы, чтобы практически скрыть это!). Единственный вариант - если вы автоматизируете генерацию документа Word с помощью OpenXML sdk.

person Flowerking    schedule 18.02.2013

@Flowerking: спасибо за информацию.

Поскольку мне все равно нужно зациклить все абзацы для поиска определенной строки, я могу использовать следующий код, чтобы найти номер страницы:

using (var document = WordprocessingDocument.Open(@"c:\test.docx", false))
{
    var paragraphInfos = new List<ParagraphInfo>();

    var paragraphs = document.MainDocumentPart.Document.Descendants<Paragraph>();

    int pageIdx = 1;
    foreach (var paragraph in paragraphs)
    {
        var run = paragraph.GetFirstChild<Run>();

        if (run != null)
        {
            var lastRenderedPageBreak = run.GetFirstChild<LastRenderedPageBreak>();
            var pageBreak = run.GetFirstChild<Break>();
            if (lastRenderedPageBreak != null || pageBreak != null)
            {
                pageIdx++;
            }
        }

        var info = new ParagraphInfo
        {
            Paragraph = paragraph,
            PageNumber = pageIdx
        };

        paragraphInfos.Add(info);
    }

    foreach (var info in paragraphInfos)
    {
        Console.WriteLine("Page {0}/{1} : '{2}'", info.PageNumber, pageIdx, info.Paragraph.InnerText);
    }
}
person Stef Heyenrath    schedule 18.02.2013
comment
Ницца. Я должен предоставить аналогичный код в своем ответе, если вы включили какой-то код в свой вопрос. Одна загвоздка => var pageBreak = run.GetFirstChild<Break>(); в Open Xml — не все Break являются разрывами страниц! - person Flowerking; 19.02.2013
comment
Всем будущим посетителям... оператор считает, что это ответ на его вопрос. Но это терпит неудачу во многих случаях. Это не удается, когда вы используете макет с несколькими столбцами. Также run.GetFirstChild<Break>(); даст вам все виды разрывов, которые могут включать в себя разрывы, отличные от просто разрывов страниц. Поэтому имейте в виду эти моменты при использовании приведенного выше кода. - person Flowerking; 25.02.2013
comment
doc, где у вас есть LastRenderedPageBreak, также будет иметь Break, поэтому просто использовать проверку Break будет нормально. Но есть сценарии, в которых не будет никаких разрывов, но содержимое будет расширено на несколько страниц. Как вы идентифицируете и разделяете содержимое по страницам? - person HaBo; 13.10.2016

Вот метод расширения, который я сделал для этого:

    public static int GetPageNumber(this OpenXmlElement elem, OpenXmlElement root)
    {
        int pageNbr = 1;
        var tmpElem = elem;
        while (tmpElem != root)
        {
            var sibling = tmpElem.PreviousSibling();
            while (sibling != null)
            {
                pageNbr += sibling.Descendants<LastRenderedPageBreak>().Count();
                sibling = sibling.PreviousSibling();
            }
            tmpElem = tmpElem.Parent;
        }
        return pageNbr;
    }
person Poppuff Arthem    schedule 28.03.2015
comment
LastRenderedPageBreak не всегда доступен - person HaBo; 13.10.2016
comment
Это будет подсчитывать только количество вставленных разрывов страниц в существующем документе, например. после того, как он был открыт в Word, который вставит разрывы. Если вы создаете документ самостоятельно с помощью SDK, единственными разрывами страниц в документе будут те, которые вы вставили сами, и вам не нужно их подсчитывать. - person IanGSY; 05.04.2017