C# 借助 NPOI 库在 Word 指定位置动态创建表格:含字体、对齐方式、行高及列宽设置

首次发布:2025-09-28
开发语言:C#
源码大小:108KB


下载源码后,重新生成一下就会自动下载依赖文件,这里用的是NPOI 2.7.4

效果图

wechat_2025-09-28_115901_376.jpg

核心源码

public void AddTableToWord(string outputPath)
{
    //word模板位置
    string templatePaht = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Report", "report.docx");
    // 读取现有文档
    XWPFDocument doc;
    using (FileStream fs = new FileStream(templatePaht, FileMode.Open, FileAccess.Read))
    {
        doc = new XWPFDocument(fs);
    }
    //XWPFDocument doc = new XWPFDocument();
    {
        // 添加空行
        //doc.CreateParagraph();

        // 创建表格
        XWPFTable table = doc.CreateTable(5, 7);


        InsertEmptyParagraphAtPosition(doc, 5);
        MoveTableToPosition(doc, table, 6);


        // 1. 将表格布局设置为固定
        if (table.GetCTTbl().tblPr == null)
        {
            table.GetCTTbl().AddNewTblPr();
        }
        table.GetCTTbl().tblPr.tblLayout = new CT_TblLayoutType() { type = ST_TblLayoutType.@fixed };

        // 设置表格宽度(简单方式)
        table.Width = 4500;
        table.SetColumnWidth(0, 200);
        //table.SetColumnWidth(1, 800);
        // 设置行高 - 遍历每一行
        foreach (XWPFTableRow row in table.Rows)
        {
            // 设置行高为500缇(twips),高度规则为精确高度
            row.Height = 400;
            //row.Height = HeightRule.EXACTLY; // 或者使用 HeightRule.ATLEAST
            foreach (var cell in row.GetTableCells())
            {
                SetCellCenterAlignment(cell, ParagraphAlignment.CENTER);
            }
        }

        //设置表格水平居中对齐
        SetTableHorizontalCenter(table);
        // 填充内容(不设置复杂样式)
        FillSimpleTable(table);


        // 保存
        using (FileStream outFs = new FileStream(outputPath, FileMode.Create))
        {
            doc.Write(outFs);
        }
    }
}

private void FillSimpleTable(XWPFTable table)
{
    // 第一行:标题
    table.GetRow(0).MergeCells(0, 6);
    table.GetRow(0).GetCell(0).SetText("这是被插入的表格");
    //SetCellCenterAlignment(table.GetRow(0).GetCell(0), ParagraphAlignment.CENTER);
    // 第二行
    var row1 = table.GetRow(1);
    row1.GetCell(0).SetText("相别");
    row1.MergeCells(1, 2);
    row1.GetCell(1).SetText("A相");
    //SetCellCenterAlignment(row1.GetCell(1), ParagraphAlignment.CENTER);

    row1.MergeCells(2, 3);
    row1.GetCell(2).SetText("B相");
    row1.MergeCells(3, 4);
    row1.GetCell(3).SetText("C相");

    // 第三行
    var row2 = table.GetRow(2);
    row2.GetCell(0).SetText("负载");
    row2.GetCell(1).SetText("最大(%)");
    row2.GetCell(2).SetText("最小(%)");
    row2.GetCell(3).SetText("最大(%)");
    row2.GetCell(4).SetText("最小(%)");
    row2.GetCell(5).SetText("最大(%)");
    row2.GetCell(6).SetText("最小(%)");

    // 第四行:电压
    table.GetRow(3).GetCell(0).SetText("电压");
    //SetCellCenterAlignment(table.GetRow(3).GetCell(0), ParagraphAlignment.CENTER);

    // 第五行:电流
    table.GetRow(4).GetCell(0).SetText("电流");
}

/// <summary>
/// 设置表格水平居中对齐
/// </summary>
/// <param name="table"></param>
public void SetTableHorizontalCenter(XWPFTable table)
{
    try
    {
        // 使用反射获取表格的底层 CTTbl 对象
        Type tableType = table.GetType();
        FieldInfo ctTblField = tableType.GetField("ctTbl", BindingFlags.NonPublic | BindingFlags.Instance);

        if (ctTblField != null)
        {
            // 获取 CTTbl 对象
            object ctTbl = ctTblField.GetValue(table);

            if (ctTbl != null)
            {
                // 获取或创建 tblPr
                PropertyInfo tblPrProperty = ctTbl.GetType().GetProperty("tblPr");
                if (tblPrProperty != null)
                {
                    object tblPr = tblPrProperty.GetValue(ctTbl);
                    if (tblPr == null)
                    {
                        tblPr = Activator.CreateInstance(tblPrProperty.PropertyType);
                        tblPrProperty.SetValue(ctTbl, tblPr, null);
                    }

                    // 获取或创建 jc
                    PropertyInfo jcProperty = tblPr.GetType().GetProperty("jc");
                    if (jcProperty != null)
                    {
                        object jc = jcProperty.GetValue(tblPr);
                        if (jc == null)
                        {
                            jc = Activator.CreateInstance(jcProperty.PropertyType);
                            jcProperty.SetValue(tblPr, jc, null);
                        }

                        // 设置对齐方式为居中
                        PropertyInfo valProperty = jc.GetType().GetProperty("val");
                        if (valProperty != null)
                        {
                            // 使用 ST_Jc 枚举的 center 值
                            Type stJcType = typeof(ST_Jc);
                            object centerValue = Enum.Parse(stJcType, "center");
                            valProperty.SetValue(jc, centerValue, null);

                            Console.WriteLine("表格横向居中设置成功!");
                            return;
                        }
                    }
                }
            }
        }

        Console.WriteLine("无法设置表格横向居中,使用备选方案");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"设置表格横向居中时出错: {ex.Message}");
    }
}

/// <summary>
/// 设置单元格内容对齐类型
/// </summary>
/// <param name="cell">表格单元格</param>
/// <param name="paragraphAlignment">段落对齐类型,如ParagraphAlignment.CENTER 是水平居中</param>
/// <param name="isBold">是否加粗(用于标题)</param>
private void SetCellCenterAlignment(XWPFTableCell cell, ParagraphAlignment paragraphAlignment, bool isBold = false)
{
    try
    {
        // 1. 设置垂直居中
        cell.SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);

        // 2. 设置水平居中
        if (cell.Paragraphs.Count > 0)
        {
            // 获取或创建段落
            XWPFParagraph paragraph = cell.Paragraphs[0];
            paragraph.Alignment = paragraphAlignment; //ParagraphAlignment.CENTER; // 水平居中

            // 设置字体样式
            if (paragraph.Runs.Count > 0)
            {
                XWPFRun run = paragraph.Runs[0];
                run.FontSize = 10;
                run.FontFamily = "宋体";
                run.IsBold = isBold;
            }
            else
            {
                // 如果没有Run,创建一个
                XWPFRun run = paragraph.CreateRun();
                run.FontSize = 10;
                run.FontFamily = "宋体";
                run.IsBold = isBold;
            }
        }
        else
        {
            // 如果没有段落,创建一个
            XWPFParagraph paragraph = cell.AddParagraph();
            paragraph.Alignment = ParagraphAlignment.CENTER;

            XWPFRun run = paragraph.CreateRun();
            run.FontSize = 10;
            run.FontFamily = "宋体";
            run.IsBold = isBold;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"设置单元格对齐时出错: {ex.Message}");
    }
}
/// <summary>
/// 指定位置插入表格
/// </summary>
/// <param name="doc"></param>
/// <param name="table"></param>
/// <param name="targetPos"></param>
private static void MoveTableToPosition(XWPFDocument doc, XWPFTable table, int targetPos)
{
    try
    {
        // 获取表格的CTTbl
        var ctTable = table.GetCTTbl();

        // 获取body中的所有元素
        var bodyItems = doc.Document.body.Items;

        // 查找表格当前位置
        int currentPos = -1;
        for (int i = 0; i < bodyItems.Count; i++)
        {
            if (bodyItems[i] == ctTable)
            {
                currentPos = i;
                break;
            }
        }

        if (currentPos != -1 && currentPos != targetPos)
        {
            // 移除当前位置的表格
            bodyItems.RemoveAt(currentPos);

            // 在目标位置插入表格
            if (targetPos >= bodyItems.Count)
            {
                bodyItems.Add(ctTable);
            }
            else
            {
                bodyItems.Insert(targetPos, ctTable);
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"移动表格出错: {ex.Message}");
    }
}

/// <summary>
/// 辅助方法:在指定位置插入空段落
/// </summary>
/// <param name="doc"></param>
/// <param name="position"></param>
private static void InsertEmptyParagraphAtPosition(XWPFDocument doc, int position)
{
    try
    {
        // 获取文档的CT_Document
        var ctDocument = doc.Document;
        var ctBody = ctDocument.body;

        // 创建新的CT_P(段落)
        CT_P ctParagraph = new CT_P();

        // 在指定位置插入
        if (position >= ctBody.Items.Count)
        {
            ctBody.Items.Add(ctParagraph);
        }
        else
        {
            ctBody.Items.Insert(position, ctParagraph);
        }

        // 创建XWPFParagraph包装器(可选,如果需要后续操作)
        XWPFParagraph newParagraph = new XWPFParagraph(ctParagraph, doc);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"插入空段落出错: {ex.Message}");
    }
}

 测试方法调用

AddTableToWord("test.docx");

本文来自 www.luofenming.com