简体   繁体   English

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

[英]X-Axis label formatting issue while exporting Chart to Excel using EPPlus

I am using EPPlus library to exporting charts from the application.我正在使用 EPPlus 库从应用程序导出图表。 But I want to change the text direction of X-Axis labels of exported graphs.但我想更改导出图形的 X 轴标签的文本方向。 I am not able to find the property in epplus.我无法在 epplus 中找到该属性。

I have attached the image of property which I want to change in the graph using EPPLUS.我已经附上了我想使用 EPPLUS 在图表中更改的属性图像。

This is code to export the graph from Dataset to excel sheet.这是将图形从数据集中导出到 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());
                }

在此处输入图片说明

I dont believe EPPlus supports rotating the chart axis (it can do the chart title). 我不相信EPPlus支持旋转图表轴(它可以完成图表标题)。

So, you could use the option of manually setting the XML. 因此,您可以使用手动设置XML的选项。 If you do something like this: 如果您执行以下操作:

[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();
    }
}

You can get this: 你可以得到这个:

在此处输入图片说明

The documentation for the rot or Rotation attribute is here: rot或Rotation属性的文档在这里:

Specifies the rotation that is being applied to the text within the bounding box. 指定将应用于边框内文本的旋转。 If it not specified, the rotation of the accompanying shape is used. 如果未指定,则使用附带形状的旋转。 If it is specified, then this is applied independently from the shape. 如果指定,则独立于形状应用。 That is the shape can have a rotation applied in addition to the text itself having a rotation applied to it. 也就是说,除了可以对文本本身施加旋转效果之外,还可以对形状施加旋转效果。 If this attribute is omitted, then a value of 0 is implied. 如果忽略此属性,则意味着值为0。

Consider the case where a shape has a rotation of 5400000, meaning 90 degrees clockwise, applied to it. 考虑对形状施加54000000旋转(即顺时针旋转90度)的情况。 In addition to this, the text body itself has a rotation of 5400000, or 90 degrees counter-clockwise, applied to it. 除此之外,文本主体本身还具有5400000的旋转或逆时针旋转90度。 Then the resulting shape would appear to be rotated but the text within it would appear as though it had not been rotated at all. 然后,最终的形状似乎将被旋转,但是其中的文本将看起来好像根本没有被旋转。 The DrawingML specifying this would look like the following: 指定此内容的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 https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.drawing.bodyproperties.rotation?view=openxml-2.8.1#DocumentFormat_OpenXml_Drawing_BodyProperties_Rotation

In EPPlus 5 at least (not sure about earlier versions), this can be done via the XAxis.TextBody.Rotation property.至少在 EPPlus 5 中(不确定早期版本),这可以通过XAxis.TextBody.Rotation属性完成。 Be sure to set it between -90 and +90 for the values to align with the tick marks properly.请务必将其设置在 -90 和 +90 之间,以使值与刻度线正确对齐。

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

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