C#实现Word页脚图片水平居中与垂直底部对齐
Word页脚图片水平居中+垂直靠下的OpenXML实现方案
方法1:基于Inline元素(推荐,无文档损坏风险)
通过调整段落对齐属性实现水平居中,同时让段落垂直填充页脚空间,使图片紧贴底部。
修改原代码的段落构造部分,添加段落属性配置:
private static void AddImageToFooter(FooterPart footerPart, string imagePath) { ImagePart imagePart = footerPart.AddImagePart(ImagePartType.Png); using (FileStream stream = new FileStream(imagePath, FileMode.Open)) { imagePart.FeedData(stream); } string relationshipId = footerPart.GetIdOfPart(imagePart); int imageWidthPx = 795; int imageHeightPx = 137; long imageWidthEmus = imageWidthPx * 9525; long imageHeightEmus = imageHeightPx * 9525; Drawing imageElement = new Drawing( new DW.Inline( new DW.Extent() { Cx = imageWidthEmus, Cy = imageHeightEmus }, new DW.EffectExtent() { LeftEdge = 0, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }, new DW.DocProperties() { Id = (UInt32Value)1U, Name = "Picture" }, new DW.NonVisualGraphicFrameDrawingProperties(new A.GraphicFrameLocks() { NoChangeAspect = true }), new A.Graphic( new A.GraphicData( new PIC.Picture( new PIC.NonVisualPictureProperties( new PIC.NonVisualDrawingProperties() { Id = (UInt32Value)0U, Name = "New Image" }, new PIC.NonVisualPictureDrawingProperties()), new PIC.BlipFill( new A.Blip() { Embed = relationshipId }, new A.Stretch(new A.FillRectangle())), new PIC.ShapeProperties( new A.Transform2D( new A.Offset() { X = 0L, Y = 0L }, new A.Extents() { Cx = imageWidthEmus, Cy = imageHeightEmus }), new A.PresetGeometry(new A.AdjustValueList()) { Preset = A.ShapeTypeValues.Rectangle }) ) ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" } ) ) { DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, DistanceFromLeft = (UInt32Value)0U, DistanceFromRight = (UInt32Value)0U, EditId = "50D07946" } ); // 配置段落属性:水平居中,垂直靠下 ParagraphProperties paraProps = new ParagraphProperties( new Justification() { Val = JustificationValues.Center }, new SpacingBetweenLines() { After = "0", Before = "0", LineRule = LineSpacingRuleValues.Auto }, new ParagraphMarkRunProperties( new VerticalAlignment() { Val = VerticalAlignmentValues.Bottom } ) ); Paragraph paragraph = new Paragraph(paraProps, new Run(imageElement)); footerPart.Footer.Append(paragraph); footerPart.Footer.Save(); }
核心修改点:
- 给段落添加
ParagraphProperties,设置JustificationValues.Center实现水平居中 - 通过
ParagraphMarkRunProperties的VerticalAlignmentValues.Bottom让图片在段落内垂直靠下 - 清除段落前后间距,避免多余留白
方法2:正确使用Anchor元素(需完整构造)
之前的Anchor代码因缺少必需的子元素导致文档损坏,以下是符合OpenXML规范的完整实现,通过绝对定位实现对齐:
private static void AddImageToFooter(FooterPart footerPart, string imagePath, long pageWidthEmus, long pageHeightEmus, long footerTopMarginEmus) { ImagePart imagePart = footerPart.AddImagePart(ImagePartType.Png); using (FileStream stream = new FileStream(imagePath, FileMode.Open)) { imagePart.FeedData(stream); } string relationshipId = footerPart.GetIdOfPart(imagePart); int imageWidthPx = 795; int imageHeightPx = 137; long imageWidthEmus = imageWidthPx * 9525; long imageHeightEmus = imageHeightPx * 9525; // 计算位置:水平居中,垂直紧贴页脚底部(页面高度 - 页脚上边距 - 图片高度) long horizontalPosEmus = (pageWidthEmus - imageWidthEmus) / 2; long verticalPosEmus = pageHeightEmus - footerTopMarginEmus - imageHeightEmus; Drawing imageElement = new Drawing( new DW.Anchor( new DW.SimplePosition() { X = horizontalPosEmus, Y = verticalPosEmus }, new DW.HorizontalPosition( new DW.PositionOffset() { Val = horizontalPosEmus } ) { RelativeFrom = DW.HorizontalRelativePositionValues.Page }, new DW.VerticalPosition( new DW.PositionOffset() { Val = verticalPosEmus } ) { RelativeFrom = DW.VerticalRelativePositionValues.Page }, new DW.Extent() { Cx = imageWidthEmus, Cy = imageHeightEmus }, new DW.EffectExtent() { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }, new DW.DocProperties() { Id = (UInt32Value)1U, Name = "Picture" }, new DW.NonVisualGraphicFrameDrawingProperties(new A.GraphicFrameLocks() { NoChangeAspect = true }), new A.Graphic( new A.GraphicData( new PIC.Picture( new PIC.NonVisualPictureProperties( new PIC.NonVisualDrawingProperties() { Id = (UInt32Value)0U, Name = "New Image" }, new PIC.NonVisualPictureDrawingProperties()), new PIC.BlipFill( new A.Blip() { Embed = relationshipId }, new A.Stretch(new A.FillRectangle())), new PIC.ShapeProperties( new A.Transform2D( new A.Offset() { X = 0L, Y = 0L }, new A.Extents() { Cx = imageWidthEmus, Cy = imageHeightEmus }), new A.PresetGeometry(new A.AdjustValueList()) { Preset = A.ShapeTypeValues.Rectangle }) ) ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" } ), new DW.WrapNone() // 必须添加环绕类型,否则文档损坏 ) { AllowOverlap = true, DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, DistanceFromLeft = (UInt32Value)0U, DistanceFromRight = (UInt32Value)0U } ); Paragraph paragraph = new Paragraph(new Run(imageElement)); footerPart.Footer.Append(paragraph); footerPart.Footer.Save(); }
关键注意事项:
- 必须添加
DW.WrapNone(或其他合法环绕类型),这是Anchor元素的必需子节点 - 位置计算需考虑页脚的上边距(
footerTopMarginEmus),可通过文档的SectionProperties获取 - HorizontalPosition和VerticalPosition必须包含
PositionOffset子元素,否则结构不合法
内容的提问来源于stack exchange,提问作者Mars
相关产品推荐
相关产品推荐

