使用EPPlus将图表导出到Excel时出现X轴标签格式问题

时间:2019-04-18 10:13:25

标签: c# epplus

我正在使用EPPlus库从应用程序中导出图表。但是我想更改导出图形的X轴标签的文本方向。我无法在epplus中找到该物业。

我已经附加了要使用EPPLUS在图形中更改的属性图像。

这是将图形从数据集导出到excel工作表的代码。

 using (ExcelPackage objExcelPackage = new ExcelPackage())
                {
                    int i = 0, startIndex = 1, endIndex = 1, j = 0;
                    string[] seriesValues; string[] seriesHeader;

                    foreach (DataTable item in ds.Tables)
                    {
                        ExcelWorksheet objWorksheet = objExcelPackage.Workbook.Worksheets.Add("Sheet" + i.ToString());
                        objWorksheet.Cells.Style.Font.SetFromFont(new System.Drawing.Font("Calibri", 10));
                        objWorksheet.Cells.AutoFitColumns();
                        dynamic chart;

                        //Add the chart to the sheet
                        if (item.Rows[0].CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GetEnumDescription(CommonEnum.GraphType.ScatterChart) || item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GraphType.ScatterChart.ToString())
                        {
                            chart = objWorksheet.Drawings.AddChart(string.Empty, eChartType.XYScatterLines);
                        }
                        else if (item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GetEnumDescription(CommonEnum.GraphType.BarChart) || item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GraphType.BarChart.ToString())
                        {
                            chart = objWorksheet.Drawings.AddChart(string.Empty, eChartType.ColumnClustered) as ExcelBarChart;
                        }
                        else if (item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GetEnumDescription(CommonEnum.GraphType.BubbleChart) || item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GraphType.BubbleChart.ToString())
                        {
                            chart = objWorksheet.Drawings.AddChart(string.Empty, eChartType.Bubble) as ExcelBubbleChart;
                        }
                        else if (item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GetEnumDescription(CommonEnum.GraphType.BarSideBySideStackedSeries2D) || item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GraphType.BarSideBySideStackedSeries2D.ToString())
                        {
                            chart = objWorksheet.Drawings.AddChart(string.Empty, eChartType.BarStacked) as ExcelBarChart;
                        }
                        else if (item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GetEnumDescription(CommonEnum.GraphType.PointSeries2D) || item.Rows[0][CommonEnum.CommonColumnName.GraphType.ToString()].ToString() == CommonEnum.GraphType.PointSeries2D.ToString())
                        {
                            chart = objWorksheet.Drawings.AddChart(string.Empty, eChartType.XYScatter);
                        }
                        else
                        {
                            chart = objWorksheet.Drawings.AddChart(string.Empty, eChartType.Area);
                        }

                        if (item.TableName.Contains("TimeBased"))
                        {
                            //var chart1= objWorksheet.Drawings.AddChart(string.Empty, eChartType.XYScatter);
                            //Create the worksheet    
                            objWorksheet.Cells["A1"].LoadFromDataTable(item, true);
                            DataView view = new DataView(item);
                            DataTable distinctMeasNumber = view.ToTable(true, CommonEnum.CommonColumnName.Name.ToString());
                            objWorksheet.Column(2).Style.Numberformat.Format = "yyyy-mm-dd hh:mm:ss";

                            foreach (DataRow dtItemRow in distinctMeasNumber.Rows)
                            {
                                startIndex = endIndex + 1;
                                endIndex = GetStartEndRowCount(item, dtItemRow[CommonEnum.CommonColumnName.Name.ToString()].ToString()) + 1;
                                chart.Series.Add(ExcelRange.GetAddress(startIndex, 3, endIndex, 3), ExcelRange.GetAddress(startIndex, 2, endIndex, 2)).Header = dtItemRow[CommonEnum.CommonColumnName.Name.ToString()].ToString();
                            }


                            chart.Title.Font.Bold = true;
                            chart.Title.Font.Size = 8;
                            chart.PlotArea.Border.LineStyle = eLineStyle.Solid;
                            chart.SetSize(650, 320);
                            chart.XAxis.MajorTickMark = eAxisTickMark.Cross;
                            chart.XAxis.MinorTickMark = eAxisTickMark.Cross;
                            chart.XAxis.LabelPosition = eTickLabelPosition.Low;
                            chart.YAxis.LabelPosition = eTickLabelPosition.Low;

                            chart.YAxis.MajorTickMark = eAxisTickMark.None;
                            chart.YAxis.MinorTickMark = eAxisTickMark.None;
                            chart.XAxis.Title.Text = item.Columns[1].ColumnName;`enter code here`
                            chart.XAxis.Title.Font.Size = 8;
                            chart.YAxis.Title.Text = item.Columns[2].ColumnName;
                            chart.YAxis.Title.Font.Size = 8;
                            i++;
                        }                      
                            chart.Title.Font.Bold = true;
                            chart.Title.Font.Size = 8;
                            chart.PlotArea.Border.LineStyle = eLineStyle.Solid;
                            chart.SetSize(580, 300);
                            chart.XAxis.MajorTickMark = eAxisTickMark.None;
                            chart.XAxis.MinorTickMark = eAxisTickMark.None;
                            chart.XAxis.LabelPosition = eTickLabelPosition.Low;
                            chart.YAxis.LabelPosition = eTickLabelPosition.Low;

                            chart.YAxis.MajorTickMark = eAxisTickMark.None;
                            chart.YAxis.MinorTickMark = eAxisTickMark.None;

                            chart.XAxis.Title.Text = item.Rows[0][CommonEnum.CommonColumnName.Col1Value.ToString()].ToString();
                            chart.XAxis.Title.Font.Size = 8;
                            chart.YAxis.Title.Text = item.Rows[0][CommonEnum.CommonColumnName.Col2Value.ToString()].ToString();
                            chart.YAxis.Title.Font.Size = 8;
                        }

                        chart.SetPosition(4, 0, 7, 0);

                        chart.Style = eChartStyle.Style2;
                    }

                     if (File.Exists(saveAsLocation))
                       File.Delete(saveAsLocation);

                    //Create excel file on physical disk    
                    FileStream objFileStrm = File.Create(saveAsLocation);
                    objFileStrm.Close();

                    //Write content to excel file    
                    File.WriteAllBytes(saveAsLocation, objExcelPackage.GetAsByteArray());
                }

enter image description here

1 个答案:

答案 0 :(得分:0)

我不认为EPPlus支持旋转图表轴(它可以完成图表标题)。

因此,您可以使用手动设置XML的选项。如果您这样做:

[TestMethod]
public void Chart_Rotate_x_Axis()
{
    //https://stackoverflow.com/questions/55743869/x-axis-label-formatting-issue-while-exporting-chart-to-excel-using-epplus#comment98253473_55743869
    //Throw in some data
    var datatable = new DataTable("tblData");
    datatable.Columns.AddRange(new[] {
        new DataColumn("Col1", typeof(int)),
        new DataColumn("Col2", typeof(int)),
        new DataColumn("Col3", typeof(object))
    });

    for (var i = 0; i < 10; i++)
    {
        var row = datatable.NewRow();
        row[0] = i;
        row[1] = i * 10;
        row[2] = Path.GetRandomFileName();
        datatable.Rows.Add(row);
    }

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

    using (var pck = new ExcelPackage(fileInfo))
    {
        var workbook = pck.Workbook;
        var worksheet = workbook.Worksheets.Add("Sheet1");
        worksheet.Cells.LoadFromDataTable(datatable, true);

        var chart = worksheet.Drawings.AddChart("chart test", eChartType.XYScatter);
        var series = chart.Series.Add(worksheet.Cells["B2:B11"], worksheet.Cells["A2:A11"]);

        //Get the chart's xml
        var chartXml = chart.ChartXml;
        var chartNsUri = chartXml.DocumentElement.NamespaceURI;
        var mainNsUri = "http://schemas.openxmlformats.org/drawingml/2006/main";

        //XML Namespaces
        var nsm = new XmlNamespaceManager(chartXml.NameTable);
        nsm.AddNamespace("c", chartNsUri);
        nsm.AddNamespace("a", mainNsUri);

        //Get the axis nodes
        var xdoc = worksheet.WorksheetXml;
        var valAxisNodes = chartXml.SelectNodes("c:chartSpace/c:chart/c:plotArea/c:valAx", nsm);

        foreach (XmlNode valAxisNode in valAxisNodes)
        {
            //Axis one should be the X Axis
            if (valAxisNode.SelectSingleNode("c:axId", nsm).Attributes["val"].Value == "1")
            {
                var txPrNode = valAxisNode.SelectSingleNode("c:txPr", nsm) ?? valAxisNode.AppendChild(chartXml.CreateNode(XmlNodeType.Element, "c:txPr", chartNsUri));
                var bodyPrNode = txPrNode.SelectSingleNode("a:bodyPr", nsm) ?? txPrNode.AppendChild(chartXml.CreateNode(XmlNodeType.Element, "a:bodyPr", mainNsUri));

                //Set the rotation angle
                var att = chartXml.CreateAttribute("rot");
                att.Value = "-5400000";
                bodyPrNode.Attributes.Append(att);

                var att2 = chartXml.CreateAttribute("vert");
                att2.Value = "horz";
                bodyPrNode.Attributes.Append(att2);

                txPrNode.AppendChild(chartXml.CreateNode(XmlNodeType.Element, "a:lstStyle", mainNsUri));

                var pNode = chartXml.CreateNode(XmlNodeType.Element, "a:p", mainNsUri);
                txPrNode.AppendChild(pNode);

                var pPrNode = chartXml.CreateNode(XmlNodeType.Element, "a:pPr", mainNsUri);
                pNode.AppendChild(pPrNode);

                var defRPrNode = chartXml.CreateNode(XmlNodeType.Element, "a:defRPr", mainNsUri);
                pPrNode.AppendChild(defRPrNode);
            }
        }

        pck.Save();
    }
}

你可以得到这个:

enter image description here

rot或Rotation属性的文档在这里:

  

指定将应用于边框内文本的旋转。如果未指定,则使用附带形状的旋转。如果指定,则独立于形状应用。也就是说,除了可以对文本本身施加旋转效果之外,还可以对形状施加旋转效果。如果省略此属性,则表示值为0。

     

请考虑对形状施加5400000旋转(即顺时针旋转90度)的情况。除此之外,文本主体本身还具有5400000的旋转或逆时针旋转90度。然后,最终的形状似乎将被旋转,但是其中的文本将看起来好像根本没有被旋转。指定此内容的DrawingML如下所示:

<p:sp>  
  <p:spPr>  
    <a:xfrm rot="5400000">  
      …  
    </a:xfrm>  
  </p:spPr>  
  …  
  <p:txBody>  
    <a:bodyPr rot="-5400000" … />  
    …  
    (Some text)  
    …  
  </p:txBody>  
</p:sp>

https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.drawing.bodyproperties.rotation?view=openxml-2.8.1#DocumentFormat_OpenXml_Drawing_BodyProperties_Rotation