C# OpenXML如何在Word文档中嵌入电子表格图表

6
我使用C# OpenXML生成了一张包含数据和基于数据的图表的电子表格。

enter image description here

我现在想把这个图表嵌入到一个Word文档中,这样当这些报告发送出去时,如果需要的话可以编辑这些图表(不是外部链接)。
我已经找了几个小时,没有找到任何一致的文档来实现这个功能。大多数文章似乎都谈到“EmbeddedPackageParts”。
如果有人有任何有用的文章或者能提供一些明确的信息,那将不胜感激。
谢谢, 邓肯。

2
创建一个非常简单的文档,并加入图表,保存该文档。然后插入一个图表并使用不同的名称保存。使用Open XML SDK生产力工具打开第一个文件,使用“比较”功能与第二个文件进行比较。这将生成创建文件中图表所需的代码;您还可以查看底层的Office Open XML。这就是如何开始... - Cindy Meister
2个回答

2

我最终解决了这个问题!

步骤:

  1. Generate xlsx file with my data in it.

  2. Save the xlsx file locally

  3. In my word document create a new chart part and generate the graph contents

    ChartPart wordChartPart = document.MainDocumentPart.AddNewPart<ChartPart>();
    string wordChartId = document.MainDocumentPart.GetIdOfPart(wordChartPart);
    WordDocumentBuilder.Workflows.SpreadsheetUtils.GenerateBarChartPart(wordChartPart, categories, dataRows);
    
  4. Embed the spreadsheet in the ChartPart

    EmbeddedPackagePart embeddedObjectPart = wordChartPart.AddEmbeddedPackagePart(@"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    
    using (FileStream stream = new FileStream(file, FileMode.Open))
    {
        byte[] documentBytes = new byte[stream.Length];
    
        stream.Read(documentBytes, 0, documentBytes.Length);
    
        using (BinaryWriter writer = new BinaryWriter(embeddedObjectPart.GetStream()))
        {
            writer.Write(documentBytes);
            writer.Flush();
        }
    }
    
  5. I could then insert an Inline Drawing into my word document which referenced the chart part.


@SachinthaNayanajith WordDocumentBuilder是我开发的一个组件,旨在帮助生成Word文档。 - Duncan Palmer
1
你能概述一下你在GenerateBarChartPart中做了什么,以及这对于步骤4是必要的吗?此外,步骤5是否必要才能在生成的文档中看到图表?(如果这些对于有OpenXML经验的人来说很明显,那我很抱歉。我刚开始使用DocumentFormat.OpenXML,正在进行一些原型设计,以查看我们团队是否可以合理地替换我们使用的EPPlus和Xceed DocX。) - William
@DuncanPalmer - 可以请您分享完整的代码吗?我已经尝试了Open XML SDK Productivity Tool和其他各种方法。 - Kevin Swann

0

您可以同时打开新的Word文档和包含图表的Excel表格。 您可以在Word文档中添加一些富文本内容控件,并将Excel表格的图表部分插入到这些位置。 请确保您的图表有标题。您可以通过标题来读取图表。 要将它们附加到Word文档中,您需要创建一个段落对象并将其附加到运行对象中,还需要定义一个内联对象以附加图表。 希望您能通过查看以下示例来理解我所说的事情。

private string WordReportGeneration(string docPath, string excelPath)
    {

        string[] chartTitles = new string[] {"","","","","","",.... };//Chart titles
        string[] bookMark = new string[] { "C1", "C2", "C3",..... };//rich text controls of the word doc

        for (int i = 0; i < chartTitles.Length; i++) //going through the chart title array
        {
            using (WordprocessingDocument myWordDoc = WordprocessingDocument.Open(docPath, true))
            {

                MainDocumentPart mainPart = myWordDoc.MainDocumentPart;

                SdtBlock sdt = null;
                mainPart.Document.Descendants<SdtBlock>().ToList().ForEach(b => {
                    var child = b.SdtProperties.GetFirstChild<Tag>();
                    if (child != null && child.Val.Equals(bookMark[i]))
                        sdt = b;
                });

                Paragraph p = sdt.SdtContentBlock.GetFirstChild<Paragraph>();
                p.RemoveAllChildren();

                Run r = new Run();
                p.Append(r);
                Drawing drawing = new Drawing();
                r.Append(drawing);


                Inline inline = new Inline(
                    new Extent()

                    { Cx = 5486400, Cy = 3200400 });

                using (SpreadsheetDocument mySpreadsheet = SpreadsheetDocument.Open(excelPath, true))
                {
                    WorkbookPart workbookPart = mySpreadsheet.WorkbookPart;
                    Sheet theSheet = workbookPart.Workbook.Descendants<Sheet>().FirstOrDefault(s => s.Name == "Report");

                    WorksheetPart worksheetPart = (WorksheetPart)workbookPart.GetPartById(theSheet.Id);

                    DrawingsPart drawingPart = worksheetPart.DrawingsPart;

                    ChartPart chartPart = (ChartPart)drawingPart.ChartParts.FirstOrDefault(x =>
                    x.ChartSpace.ChildElements[4].FirstChild.InnerText.Trim() == chartTitles[i]);

                    ChartPart importedChartPart = mainPart.AddPart<ChartPart>(chartPart);

                    string relId = mainPart.GetIdOfPart(importedChartPart);

                    DocumentFormat.OpenXml.Drawing.Spreadsheet.GraphicFrame frame = drawingPart.WorksheetDrawing.Descendants<DocumentFormat.OpenXml.Drawing.Spreadsheet.GraphicFrame>().First();

                    Graphic clonedGraphic = (Graphic)frame.Graphic.CloneNode(true);

                    ChartReference c = clonedGraphic.GraphicData.GetFirstChild<ChartReference>();

                    c.Id = relId;

                    DocProperties docPr = new DocProperties();

                    docPr.Name = "XXX";

                    docPr.Id = GetMaxDocPrId(mainPart) + 1;

                    inline.Append(docPr, clonedGraphic);
                    drawing.Append(inline);


                }
                myWordDoc.Save();
                myWordDoc.Close();
            }

        }

        return docPath;
    }

输入代码在这里

enter code here

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接