You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:44:53