如何使用OpenXML从段落中找到页码?

5

对于一个段落对象,我如何使用Microsoft Office的Open XML SDK 2.0确定它位于哪一页?


简短回答:仅通过OOXML数据层面是不可能的。请参阅此处以获取详细解释。 - kjhughes
3个回答

6

使用OpanXml Sdk无法获取Word文档的页码,因为这是由客户端(如MS Word)处理的。

但是,如果您正在处理的文档先前已被Word客户端打开并保存,则客户端将添加 LastRenderedPageBreak 以标识分页符。有关LastRenderedPageBreaks的更多信息,请参见我的回答此处。这使您可以计算在您的段落之前的LastRenderedPageBreak元素的数量以获取当前页数。

如果不是这种情况,则围绕您的要求解决问题的简单方法是添加带有页码的页脚(可以使用与文档相同颜色来虚拟隐藏它!)。仅当您正在使用OpenXML sdk自动化Word文档生成时才可选。


2

@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);
    }
}

不错。如果您在问题中包含了一些代码,我应该会在我的答案中提供类似的代码。 但有一个注意点 => 在Open Xml中,“var pageBreak = run.GetFirstChild<Break>();”并不是所有的“Break”都是分页符! - Flowerking
6
对于所有未来的访问者..,原帖认为这回答了他的问题。但是,在使用多列布局时,它会失败。此外, run.GetFirstChild<Break>(); 会给你各种类型的换行符,可能包括除了页面分隔符以外的其他分隔符。因此,在使用上述代码时请牢记这些要点。 - Flowerking
1
文档中有LastRenderedPageBreak的地方也会有Break,因此只使用Break检查就可以了。但是有些情况下没有分页符,但内容延伸到多个页面,如何识别并按页面分隔内容? - HaBo

0
这是我为此编写的扩展方法:
    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;
    }

LastRenderedPageBreak并不总是可用的。 - HaBo
这仅会计算现有文档中已插入的分页符数量,例如在Word中打开后插入分页符。如果您使用SDK自己生成文档,则文档中唯一的分页符将是您自己插入的,因此您不需要计数。 - IanGSY

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接