【发布时间】:2013-02-02 21:46:23
【问题描述】:
对于 Paragraph 对象,如何使用 Open XML SDK 2.0 for Microsoft Office 确定它位于哪个页面上?
【问题讨论】:
标签: ms-word document openxml paragraph page-numbering
对于 Paragraph 对象,如何使用 Open XML SDK 2.0 for Microsoft Office 确定它位于哪个页面上?
【问题讨论】:
标签: ms-word document openxml paragraph page-numbering
无法使用OpanXml Sdk 获取 Word 文档的页码,因为这是由客户端处理的(如 MS Word)。
但是,如果您正在使用的文档以前由 word 客户端打开并保存回来,那么客户端将添加 LastRenderedPageBreak 以识别分页符。有关LastRenderedPageBreaks 的更多信息,请参阅我的回答here。这使您可以计算段落之前的LastRenderedPageBreak 元素的数量,以获取当前页数。
如果不是这种情况,那么解决您的要求的点头选项是添加带有页码的页脚(可能与您的文档具有相同的颜色以虚拟隐藏它!)。只有一个选项 - 如果您使用 OpenXML sdk 自动生成 Word 文档。
【讨论】:
@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);
}
}
【讨论】:
var pageBreak = run.GetFirstChild<Break>(); - 并非所有 Breaks 都是分页符!
run.GetFirstChild<Break>(); 会为您提供各种中断,其中可能包括分页符以外的中断。所以在使用上面的代码时要记住这几点。
这是我为此做的扩展方法:
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;
}
【讨论】: