Изменение цвета ряда линий в EPPlus

Есть ли более простой способ изменить цвет серии линий?

Я попытался использовать это. Но serieNode производит NullReferenceException в serieNode.AppendChild(spPr);.

Вот код, который генерирует график:

private void GenerateLicenseUsageStatsChart(FileInfo excelFileInfo, FileInfo 
                                           csvFileInfo, DateTime lastCheckedDate)
    {
        string worksheetsName = "Sheet1";
        const bool firstRowIsHeader = false;

        var excelTextFormat = new ExcelTextFormat { Delimiter = ',' };
        // excelTextFormat.EOL = "\r";

        using (ExcelPackage package = new ExcelPackage(excelFileInfo))
        {
            ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(worksheetsName);

            worksheet.Cells["A1"].LoadFromText(csvFileInfo, excelTextFormat, 
                      OfficeOpenXml.Table.TableStyles.None, firstRowIsHeader);

            var workbook = package.Workbook;
            ExcelWorksheet workSheet = workbook.Worksheets[1];

            var chart = workSheet.Drawings.AddChart("chart", 
                                              eChartType.ColumnClustered);
            chart.SetPosition(10, 250);
            chart.SetSize(700, 500);
            chart.Title.Text = $"LicenseUsageStats {lastCheckedDate:MMM} 
                         {lastCheckedDate.Year}";

            chart.YAxis.MajorUnit = 1;
            chart.YAxis.MinorUnit = 1;

            chart.XAxis.MajorTickMark = eAxisTickMark.None;
            chart.XAxis.MinorTickMark = eAxisTickMark.None;
            chart.XAxis.Title.Text = "Hour";
            chart.XAxis.Title.Font.Size = 10;

            var maxLicensesSerie = chart.Series.Add("B2:B25", "A2:A25");
            maxLicensesSerie.Header = "Max Licenses Used";

            var avgLicensesSerie = chart.Series.Add("C2:C25", "A2: A25");
            avgLicensesSerie.Header = "Avg Licenses Used";

            var maxLineChart = (ExcelLineChart) 
                            chart.PlotArea.ChartTypes.Add(eChartType.Line);
            var maxThreshLineSerie = maxLineChart.Series.Add("D2:D25", 
                                                             "A2:A25");
            maxThreshLineSerie.Header = "Max";

            SetLineChartColor(maxLineChart, 0, Color.Red);

            var warningLineChart = 
             (ExcelLineChart)chart.PlotArea.ChartTypes.Add(eChartType.Line);
            var warningThreshLineSerie = 
                 warningLineChart.Series.Add("E2:E25", "A2:A25");
            warningThreshLineSerie.Header = "Warning";

            SetLineChartColor(warningLineChart, 1, Color.Yellow);

            worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();

            // workSheet.Column(4).Hidden = true;
            // workSheet.Column(5).Hidden = true;

            package.Save();
        }
    }

Моя конечная цель: Моя конечная цель

Поскольку в Excel нет удобного способа создания горизонтальных линий, я создал столбцы max и warning. Я также хотел бы скрыть эти столбцы, чтобы они не влияли на график. Может быть, я мог бы «скрыть» их, переместив на другой лист?


person HelloWorld    schedule 25.01.2017    source источник
comment
Вы пробовали это: неправильный цвет в диаграмме Excel, созданной с помощью epplus"> stackoverflow.com/questions/36520427/   -  person Ernie S    schedule 26.01.2017
comment
Получение той же ошибки   -  person HelloWorld    schedule 30.01.2017
comment
Можете ли вы опубликовать свой обновленный код?   -  person Ernie S    schedule 31.01.2017


Ответы (1)


Я вижу проблему. Функция предполагает, что индекс серии соответствует количеству серий в коллекции объектов диаграммы. Но поскольку это смешанная диаграмма, это не так после приведения результата Add. Это немного хак, но он будет работать (мне действительно нужно немного подумать о том, как сопоставить числа):

public static void SetLineChartColor(this ExcelChart chart, int serieIdx, int chartSeriesIndex, Color color)
{
    var chartXml = chart.ChartXml;

    var nsa = chart.WorkSheet.Drawings.NameSpaceManager.LookupNamespace("a");
    var nsuri = chartXml.DocumentElement.NamespaceURI;

    var nsm = new XmlNamespaceManager(chartXml.NameTable);
    nsm.AddNamespace("a", nsa);
    nsm.AddNamespace("c", nsuri);

    var serieNode = chart.ChartXml.SelectSingleNode($@"c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[c:idx[@val='{serieIdx}']]", nsm);
    var serie = chart.Series[chartSeriesIndex];
    var points = serie.Series.Length;

    //Add reference to the color for the legend
    var srgbClr = chartXml.CreateNode(XmlNodeType.Element, "srgbClr", nsa);
    var att = chartXml.CreateAttribute("val");
    att.Value = $"{color.R:X2}{color.G:X2}{color.B:X2}";
    srgbClr.Attributes.Append(att);

    var solidFill = chartXml.CreateNode(XmlNodeType.Element, "solidFill", nsa);
    solidFill.AppendChild(srgbClr);

    var ln = chartXml.CreateNode(XmlNodeType.Element, "ln", nsa);
    ln.AppendChild(solidFill);

    var spPr = chartXml.CreateNode(XmlNodeType.Element, "spPr", nsuri);
    spPr.AppendChild(ln);

    serieNode.AppendChild(spPr);
}

И вы можете назвать это так:

maxLineChart.SetLineChartColor(2, 0, Color.Red);
warningLineChart.SetLineChartColor(3, 0, Color.Yellow);
person Ernie S    schedule 02.02.2017
comment
Спасибо! Есть идеи, как скрыть столбцы Max и Warning? Я просто использую их для создания пороговых линий на графике. - person HelloWorld; 03.02.2017
comment
Это работает: workSheet.Column(4).Style.Font.Color.SetColor(Color.White); workSheet.Column(5).Style.Font.Color.SetColor(Color.White); Но, если вы найдете что-то лучше, дайте мне знать. - person HelloWorld; 03.02.2017
comment
@HelloWorld Да, это сложно - я никогда не понимал, почему Excel никогда не добавляет это в качестве функции. Я всегда делал то же, что и вы, добавляя данные фиктивных линий как их собственные серии. Перемещение их на скрытый лист, как вы упомянули, обычно работает хорошо. - person Ernie S; 03.02.2017
comment
@HelloWorld Я использовал worksheet.Column(4).Hidden = true; chart.ShowHiddenData = true; для скрытия столбцов. - person Anlo; 13.01.2021