【问题标题】:How to find the page number from a paragraph using OpenXML?如何使用 OpenXML 从段落中查找页码?
【发布时间】:2013-02-02 21:46:23
【问题描述】:

对于 Paragraph 对象,如何使用 Open XML SDK 2.0 for Microsoft Office 确定它位于哪个页面上?

【问题讨论】:

    标签: ms-word document openxml paragraph page-numbering


    【解决方案1】:

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

    但是,如果您正在使用的文档以前由 word 客户端打开并保存回来,那么客户端将添加 LastRenderedPageBreak 以识别分页符。有关LastRenderedPageBreaks 的更多信息,请参阅我的回答here。这使您可以计算段落之前的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);
          }
      }
      

      【讨论】:

      • 不错。如果您在 Q 中包含一些代码,我应该在我的答案中提供类似的代码。一个问题 => Open Xml 中的 var pageBreak = run.GetFirstChild&lt;Break&gt;(); - 并非所有 Breaks 都是分页符!
      • 致所有未来的访问者.. 操作员认为这回答了他的问题。但在很多情况下都失败了。当您使用多列布局时,它会失败。此外,run.GetFirstChild&lt;Break&gt;(); 会为您提供各种中断,其中可能包括分页符以外的中断。所以在使用上面的代码时要记住这几点。
      • 您拥有 LastRenderedPageBreak 的文档也会有 Break,因此只需使用 Break check 就可以了。但是有些场景不会有任何中断但内容扩展到多个页面,您如何按页面识别和分隔内容?
      【解决方案3】:

      这是我为此做的扩展方法:

          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 并不总是可用
      • 这只会计算现有文档中插入的分页符的数量,例如一旦它在 Word 中打开,它将插入中断。如果您使用 SDK 自己生成文档,则文档中唯一的分页符将是您自己插入的分页符,您无需计算。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-22
      • 2013-07-05
      相关资源
      最近更新 更多