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

使用OpenXML C#动态替换Word文档中的图表数值

使用OpenXML C#动态更新Word图表数据的实现方案

核心思路

Word文档中的图表数据实际存储在嵌入式Excel工作簿中(对应OpenXML里的EmbeddedPackagePart),要动态更新图表,本质就是修改这个嵌入式Excel里的单元格数值,Word会自动关联更新图表展示。

实现步骤

  1. 加载目标Word文档,遍历文档内所有ChartPart(每个图表对应一个ChartPart)
  2. 从ChartPart中获取对应的EmbeddedPackagePart,这就是存储图表数据的Excel包
  3. 打开Excel包的流,用OpenXML SDK操作Excel工作簿,修改指定单元格的数值
  4. 将修改后的Excel流写回EmbeddedPackagePart
  5. 保存并关闭Word文档

完整代码示例

首先需要安装NuGet包:DocumentFormat.OpenXml

using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

public static void UpdateWordChartData(string wordFilePath, int chartIndex, string sheetName, string cellAddress, decimal newValue)
{
    // 以可写模式打开Word文档
    using (var wordDoc = WordprocessingDocument.Open(wordFilePath, true))
    {
        // 获取所有ChartPart,按索引定位目标图表(索引从0开始)
        var chartParts = wordDoc.MainDocumentPart.ChartParts.ToList();
        if (chartIndex >= chartParts.Count)
            throw new ArgumentOutOfRangeException(nameof(chartIndex), "指定的图表索引不存在");

        var targetChartPart = chartParts[chartIndex];
        var excelPackagePart = targetChartPart.EmbeddedPackagePart;

        // 操作嵌入式Excel工作簿
        using (var excelStream = new MemoryStream())
        {
            excelPackagePart.GetStream().CopyTo(excelStream);
            excelStream.Position = 0;

            using (var excelDoc = SpreadsheetDocument.Open(excelStream, true))
            {
                var workbookPart = excelDoc.WorkbookPart;
                var sheet = workbookPart.Workbook.Descendants<Sheet>().FirstOrDefault(s => s.Name == sheetName);
                if (sheet == null)
                    throw new ArgumentException($"找不到名为{sheetName}的工作表");

                var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
                var cell = GetCell(worksheetPart.Worksheet, cellAddress);

                // 修改单元格数值
                cell.CellValue = new CellValue(newValue.ToString());
                cell.DataType = new EnumValue<CellValues>(CellValues.Number);

                worksheetPart.Worksheet.Save();
            }

            // 将修改后的Excel流写回EmbeddedPackagePart
            excelStream.Position = 0;
            excelPackagePart.FeedData(excelStream);
        }

        wordDoc.Save();
    }
}

// 辅助方法:根据单元格地址(如"A1")获取单元格对象
private static Cell GetCell(Worksheet worksheet, string cellAddress)
{
    var columnName = new string(cellAddress.TakeWhile(c => char.IsLetter(c)).ToArray());
    var rowIndex = int.Parse(new string(cellAddress.SkipWhile(c => char.IsLetter(c)).ToArray()));

    var sheetData = worksheet.GetFirstChild<SheetData>();
    var row = sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex == rowIndex);
    if (row == null)
    {
        row = new Row { RowIndex = (uint)rowIndex };
        sheetData.Append(row);
    }

    var cell = row.Elements<Cell>().FirstOrDefault(c => c.CellReference == cellAddress);
    if (cell == null)
    {
        cell = new Cell { CellReference = cellAddress };
        row.Append(cell);
    }

    return cell;
}

// 辅助方法:将列名(如"A"、"AB")转换为列索引
private static int ColumnNameToIndex(string columnName)
{
    int index = 0;
    foreach (char c in columnName.ToUpper())
    {
        index = index * 26 + (c - 'A' + 1);
    }
    return index;
}

使用示例

比如要修改第1个图表(索引0)里名为Sheet1的工作表中B2单元格的数值为150:

UpdateWordChartData(@"C:\YourDocument.docx", 0, "Sheet1", "B2", 150);

关键注意事项

  • 图表数据映射:确保你修改的Excel单元格是图表实际绑定的数据范围,可以打开Word文档右键图表→选择数据,查看数据来源的单元格位置
  • 多图表区分:如果需要精准定位特定图表,可以通过ChartPart的Id或者图表的标题文本(解析ChartSpace里的标题元素)来区分,而不是仅靠索引
  • 文件权限:操作前确保Word文档未被其他进程占用,否则会抛出异常
  • 数据类型匹配:修改单元格时要注意数据类型(数值、文本等),和原数据类型保持一致,避免图表展示异常

内容的提问来源于stack exchange,提问作者Neerajyadav Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 16:07:30