简体   繁体   English

使用 EPPlus 复制/克隆 Excel 图表

[英]Copy/Clone an Excel Chart with EPPlus

I'm using EPPlus in my project and I know you can copy an existing Shape however there is no method for copying an existing Chart.我在我的项目中使用 EPPlus,我知道您可以复制现有的形状,但是没有复制现有图表的方法。

I have setup a workbook with template charts that I need to duplicate and update the series to point to different datatable/sets.我已经设置了一个带有模板图表的工作簿,我需要复制和更新系列以指向不同的数据表/集。

I can populate the data no worries and can create new charts, but then need to size and position and style.我可以毫无顾虑地填充数据并可以创建新图表,但随后需要调整大小、位置和样式。 It would be a lot easier to just clone the chart template and modify series and position to simplify the code.克隆图表模板并修改系列和位置以简化代码会容易得多。

Currently I use this approach:目前我使用这种方法:

// wb is an ExcelWorkbook
ExcelWorksheet ws = wb.Worksheets[sheetIdx];
ExcelChart chart = (ExcelChart)ws.Drawings[0];
ExcelChart cc = ws.Drawings.AddChart("Chart " + (i + 2), eChartType.ColumnClustered);

// invoke methods that will position and size new chart

// copy starting chart xml so will have identical styling, series, legend etc
var xml = XDocument.Parse(chart.ChartXml.InnerXml);
XNamespace nsC = "http://schemas.openxmlformats.org/drawingml/2006/chart";
XNamespace nsA = "http://schemas.openxmlformats.org/drawingml/2006/main";

// modify xml to update Category, Title and Values formulas
var fs = xml.Descendants(nsC + "f");
foreach (var f in fs)
{
    f.Value = ws.Cells[f.Value].Offset(chartNumRows + 1, 0).FullAddressAbsolute;
}

// set new chart xml to modified xml.
cc.ChartXml.InnerXml = xml.ToString();

Which works, but there are several drawbacks.哪个有效,但有几个缺点。

1) The chart.series of the clone (cc in my example) has not been set, peeking at the code this is because it is only done during the object construction. 1)克隆的chart.series(在我的例子中是cc)还没有设置,偷看代码这是因为它只在对象构造过程中完成。 If I could get this property to update then I would be able to easily resolve the second issue如果我可以更新此属性,那么我将能够轻松解决第二个问题

2) I need to remove all series and add new ones and because the series property isn't initialised properly this is harder than it should be. 2)我需要删除所有系列并添加新系列,因为系列属性没有正确初始化,这比应该的更难。

Any help getting properties to initialise in the chart or a better method of cloning the original would be greatly appreciated!任何帮助在图表中初始化属性或克隆原件的更好方法将不胜感激!

It seems like there is no built-in functionality for this and an other reload methods I could come up with required too many changes to the EPPlus source, so until I find a better solution I have added the following method to EPPlus\\Drawings\\ExcelDrawings.cs似乎没有内置功能,我可以想出的其他重新加载方法需要对 EPPlus 源进行太多更改,因此在找到更好的解决方案之前,我已将以下方法添加到 EPPlus\\Drawings\\ExcelDrawings 。CS

public ExcelChart CloneChart(ExcelChart SourceChart, String NewName)
{
    // Create clone
    var tempClone = this.AddChart(NewName, SourceChart.ChartType, null);
    tempClone.ChartXml.InnerXml = SourceChart.ChartXml.InnerXml;

    // Reload clone
    using (tempClone.Part.Stream = new MemoryStream())
    {
        // Create chart object using temps package and xml
        var chartXmlBytes = Encoding.ASCII.GetBytes(tempClone.ChartXml.OuterXml);
        tempClone.Part.Stream.Write(chartXmlBytes, 0, chartXmlBytes.Length);
        var finalClone = ExcelChart.GetChart(this, tempClone.TopNode);

        // Remove old from collection
        var index = _drawingNames[tempClone.Name];
        var draw = _drawings[index];
        for (int i = index + 1; i < _drawings.Count; i++)
            _drawingNames[_drawings[i].Name]--;
        _drawingNames.Remove(draw.Name);
        _drawings.Remove(draw);

        // Add new to collection
        finalClone.Name = tempClone.Name;
        _drawings.Add(finalClone);
        _drawingNames.Add(finalClone.Name, _drawings.Count - 1);

        // Done
        return finalClone;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM