c#将单元格合并为标题地址epplus

时间:2016-02-10 13:24:55

标签: c# epplus

如何在EPPlus中将HeaderAddress设置为聚类条形图的两个单元格?我从我的数据库输出中得到以下数据,其中第一列是您可以看到合并的单元格。

enter image description here

我正在寻找数据enter image description here

的以下布局

请注意,图片来自数据的副本,但是在Excel中生成。

到目前为止我所尝试的基本上是

ExcelChartSerie s = chart.Series.Add(axis.Address, xAxis.Address);
s.HeaderAddress = new ExcelAddress(startRow + r, GetColumnNumberByName(startColumn), startRow + 1, GetColumnNumberByName(startColumn) + 1);

我或多或少选择当前行和两列。这给了我“地址必须是行,列或单个单元格”,但是为了让它工作,我必须选择多个单元格,不是吗?

1 个答案:

答案 0 :(得分:2)

Epplus无法设置它。它不是那么困难,但它需要XML操作。有点丑,但它完成了工作。不知道你的代码我编写了一个快速单元测试演示。它必须匹配正确的图表类型,所以如果它不是BarClustered,请告诉我:

[TestMethod]
public void Chart_Meged_Header_Test()
{
    //Throw in some data
    var datatable = new DataTable("tblData");
    datatable.Columns.AddRange(new[]
    {
        new DataColumn("Col1", typeof (string)),
        new DataColumn("Col2", typeof (int))
    });

    for (var i = 0; i < 10; i++)
    {
        var row = datatable.NewRow();
        row[0] = $"item {(i%2 == 0 ? "A" : "B")}";
        row[1] = i * 10;
        datatable.Rows.Add(row);
    }

    //Create a test file    
    var fileInfo = new FileInfo(@"c:\temp\Chart_Meged_Header_Test.xlsx");
    if (fileInfo.Exists)
        fileInfo.Delete();

    using (var pck = new ExcelPackage(fileInfo))
    {
        var workbook = pck.Workbook;
        var worksheet = workbook.Worksheets.Add("Sheet1");
        worksheet.Cells["B1"].LoadFromDataTable(datatable, true);
        worksheet.Column(4).Style.Numberformat.Format = "m/d/yyyy";

        var chart = worksheet.Drawings.AddChart("chart test", eChartType.BarClustered);
        var serie = chart.Series.Add(worksheet.Cells["C2:C11"], worksheet.Cells["B2:B11"]);
        chart.SetPosition(0, 0, 3, 0);
        chart.SetSize(120);

        //Add merged headers
        worksheet.Cells["A2"].Value = "Group 1";
        worksheet.Cells["A2:A6"].Merge = true;

        worksheet.Cells["A7"].Value = "Group 2";
        worksheet.Cells["A7:A11"].Merge = true;

        //Get reference to the worksheet xml for proper namespace
        var chartXml = chart.ChartXml;
        var nsm = new XmlNamespaceManager(chartXml.NameTable);

        var nsuri = chartXml.DocumentElement.NamespaceURI;
        nsm.AddNamespace("c", nsuri);

        //Get the Series ref and its cat
        var serNode = chartXml.SelectSingleNode("c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser", nsm);
        var catNode = serNode.SelectSingleNode("c:cat", nsm);

        //Get Y axis reference to replace with multi level node
        var numRefNode = catNode.SelectSingleNode("c:numRef", nsm);
        var multiLvlStrRefNode = chartXml.CreateNode(XmlNodeType.Element, "c:multiLvlStrRef", nsuri);

        //Set the proper cell reference and replace the node
        var fNode = chartXml.CreateElement("c:f", nsuri);
        fNode.InnerXml = numRefNode.SelectSingleNode("c:f", nsm).InnerXml;
        fNode.InnerXml = fNode.InnerXml.Replace("$B$2", "$A$2");
        multiLvlStrRefNode.AppendChild(fNode);
        catNode.ReplaceChild(multiLvlStrRefNode, numRefNode);

        //Set the multi level flag
        var noMultiLvlLblNode = chartXml.CreateElement("c:noMultiLvlLbl", nsuri);
        var att = chartXml.CreateAttribute("val");
        att.Value = "0";
        noMultiLvlLblNode.Attributes.Append(att);

        var catAxNode = chartXml.SelectSingleNode("c:chartSpace/c:chart/c:plotArea/c:catAx", nsm);
        catAxNode.AppendChild(noMultiLvlLblNode);

        pck.Save();
    }
}

将此作为输出:

enter image description here