Search code examples
c#chartsms-worddotnetcharting

asp.net chart with code based on chart build with excel


I need to determine the data in a chart at run-time and put it in a .doc. To construct the document I use Aspose to replace elements in a .doc template. An example chart was made by importing an Excel workbook into Word, they mostly use the defaults, yet I fail to construct a chart that looks like it.

What the graph should look likeWhat I got so far

On the right the example chart I'm trying to make in code, on the left what I got so far.

  1. It does not have the dots marking each data point
  2. The tick mark labels are located at the tick marks instead of in between (done with Axis postion) don't know how to do this in code.
  3. The graph is compressed in height because the picture made by .net charting was square and needed to be crammed inside the example picture bounds (how to change the width/heigh ratio?)
  4. Big numbers are not formatted with a . between each group of three numbers.

.docx is not an option, the file format must be .doc.

My code for building the graph. This code is called with data to populate the graph.

    public MemoryStream MakeLineChart(string title, string[] captions, Color[] colors, decimal[][] values)
    {
        var chart = new Chart();

        var area = new ChartArea("MyChartArea");
        area.AxisY2.LineWidth = 0;
        area.AxisY.LineWidth = 0;
        area.AxisY.MajorGrid.Enabled = false;
        area.AxisY.MinorGrid.Enabled = false;
        area.AxisX.IsMarginVisible = true;

        foreach (var axis in area.Axes)
        {
            axis.LineColor = Color.LightGray;
            axis.MajorGrid.LineColor = Color.LightGray;
            axis.MajorTickMark.Enabled = false;
        }

        var legend = new Legend();
        legend.LegendStyle = LegendStyle.Row;
        legend.Docking = Docking.Bottom;
        legend.DockedToChartArea = area.Name;
        legend.Enabled = true;

        chart.Legends.Add(legend);
        chart.ChartAreas.Add(area);
        chart.BorderlineColor = Color.Black;
        chart.BorderlineWidth = 2;
        chart.Titles.Add(title);
        chart.TextAntiAliasingQuality = TextAntiAliasingQuality.High;
        chart.AntiAliasing = AntiAliasingStyles.All;

        for (int i = 1; i < values.Length; i++)
        {
            var line = new Series(captions[i - 1]);
            line.ChartArea = area.Name;
            line.ChartType = SeriesChartType.Spline;
            line.Color = colors[i - 1];
            line.BorderWidth = 5;

            for (int j = 0; j < values[i].Length; j++)
            {
                line.Points.AddXY(values[0][j], values[i][j]);
            }

            chart.Series.Add(line);
        }

        var image = new MemoryStream();

        chart.SaveImage(image, ChartImageFormat.Emf);

        return image;
    }

Solution

  • I solved several of these problems:

    1. Specify markers on the series

              line.MarkerStyle = MarkerStyle.Circle;
              line.MarkerSize = 7;
      
    2. Still a problem, the tick mark label values are interpeted, I need them to exactly be the x-axis values, like the default when using an Excel workbook in Word.

    3. Specify the chart size:

          chart.Width = 280;
          chart.Height = 180;
      
    4. Specify the formatting:

          area.AxisY.LabelStyle.Format = "€{#,##0 }";
      

    I found two additional problems, will ask another question if I cannot solve them.

    1. Anti-aliasing is not applied to the line graphics. (even though the chart AntiAliasing setting is All).
    2. The legend is located inside the chart draw area, sometimes blocking the view of the actual graph.