OpenXml中为SectionProperty正确设置HeaderReference的问题咨询
问题根因
- Word分节默认开启页眉继承(对应界面上的「链接到前一条页眉」选项),OpenXML规则下如果某节的
SectionProperties没有显式声明对应类型的页眉引用,会自动沿用前一节的页眉配置 - 你的代码仅给第2节(A3章节)的分节符配置了自定义页眉引用,第1节、第3节未做配置,且模板自带的、位于Body末尾的全局
SectionProperties(负责管辖最后一个分节符之后的所有内容)未修改,导致所有章节依然沿用模板预设页眉 - 你注释的批量删除所有
HeaderReference的代码,执行后没有补充新的页眉引用,才会导致所有页眉消失
解决方法
按以下规则调整代码即可:
- 所有需要自定义页眉的节,都要在对应的
SectionProperties中显式声明所需类型的HeaderReference(如果模板开启了首页不同、奇偶页不同,需要对应补充HeaderFooterValues.First、HeaderFooterValues.Even类型的引用) - 不要遗漏修改Body末尾的全局
SectionProperties,它管辖最后一节的所有配置 - 不需要删除原有
HeaderReference,显式声明新的引用后会自动覆盖继承关系
修改后代码示例
using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(sourceDocx, true)) { var headerPart = wordprocessingDocument.MainDocumentPart.AddNewPart<HeaderPart>(); headerPart.Header = new Header(new Paragraph(new Run(new Text("Hallo")))); string headerId = wordprocessingDocument.MainDocumentPart.GetIdOfPart(headerPart); Body body = wordprocessingDocument.MainDocumentPart.Document.Body; RemoveLastEmptyParagraph(body); var firstsection = body.GetFirstChild<SectionProperties>(); var defaultPageSize = firstsection.Descendants<PageSize>().FirstOrDefault(); var pageMargins1 = firstsection.Descendants<PageMargin>().FirstOrDefault(); // 第一节:如果需要用自定义页眉,就把第一个参数改为headerId,传null则沿用模板页眉 body.AppendChild(new Paragraph(new Run(new Text("A4")))); body.AppendChild(new Paragraph(new ParagraphProperties(CreateSectionBreak(null, defaultPageSize, pageMargins1)))); // 第二节:已配置自定义页眉 body.AppendChild(new Paragraph(new Run(new Text("A3")))); body.AppendChild(new Paragraph(new ParagraphProperties(CreateSectionBreakA3(headerId)))); body.AppendChild(new Paragraph(new Run(new Text("A4")))); // 新增:处理全局SectionProperties(管辖最后一节) var finalSection = body.GetLastChild<SectionProperties>(); // 如果最后一节需要用自定义页眉就加下面这行,不需要就删除 finalSection.AddChild(new HeaderReference() { Id = headerId, Type = HeaderFooterValues.Default }); } private static void RemoveLastEmptyParagraph(Body body) { Paragraph lastParagraph = null; foreach (var element in body.ChildElements) { if (element is Paragraph paragraph) { lastParagraph = paragraph; } } lastParagraph?.Remove(); } private SectionProperties CreateSectionBreak(string headerId, PageSize pageSize, PageMargin margins) { var section = new SectionProperties(); if (headerId != null) { section.AddChild(new HeaderReference() { Id = headerId, Type = HeaderFooterValues.Default }); } section.AddChild(new SectionType { Val = SectionMarkValues.NextPage }); section.AddChild((PageSize)pageSize.Clone()); section.AddChild((PageMargin)margins.Clone()); return section; } private SectionProperties CreateSectionBreakA3(string headerId) { if (headerId == null) throw new ArgumentNullException(nameof(headerId)); var pageSize = new PageSize(); pageSize.Width = (UInt32)(42.0 * 566.92556267362); pageSize.Height = (UInt32)(29.7 * 566.92556267362); pageSize.Orient = new EnumValue<PageOrientationValues>(PageOrientationValues.Landscape); var margin = new PageMargin(); margin.Top = (Int32)(1.0 * 566.92556267362); margin.Left = (Int32)(1.0 * 566.92556267362); margin.Right = (Int32)(1.0 * 566.92556267362); margin.Bottom = (Int32)(1.0 * 566.92556267362); margin.Header = (Int32)(1.0 * 566.92556267362); margin.Footer = (Int32)(1.0 * 566.92556267362); return CreateSectionBreak(headerId, pageSize, margin); }
补充说明
如果需要某节完全不显示页眉,只需要给该节的SectionProperties添加一个内容为空的HeaderPart的引用即可,不要直接删除所有HeaderReference。
内容的提问来源于stack exchange,提问作者Thomas Woelfer
相关产品推荐
相关产品推荐

