Microsoft chart bar chart diagram has spaces

I use the .Net 4.0 chart library to create a multi-series column bar chart. My goal is a histogram showing the total number of actions (finalization of reports) per day in several series (teachers). Often there is no data (on the same day a certain teacher has no activity).

I get spaces in bars when there is no data in the series:

Histogram with gaps in the columns

My code is:

public ActionResult CompletionHistogram(int sid, int width, int height) { Site site = SiteRepository.Get(sid); if (site == null) return new HttpNotFoundResult(); Chart chart = new Chart(); chart.Height = height; chart.Width = width; ChartArea area = chart.ChartAreas.Add("Default"); // Treat each teacher as a series foreach (Teacher t in site.Teachers) { Series series = chart.Series.Add(t.FullName); series.ChartType = SeriesChartType.StackedColumn; series.Name = t.FullName; // Group completions by day (filter out incomplete reports and null timestamps) var groups = t.StudentReports .Where<StudentReport>(rep => rep.IsComplete && rep.FirstSaveTimestamp.HasValue) .GroupBy<StudentReport, DateTime>(rep => rep.FirstSaveTimestamp.Value.Date); bool hasPoints = false; foreach (var g in groups) { series.Points.AddXY(g.Key, g.Count()); hasPoints = true; } series.IsValueShownAsLabel = true; series.ToolTip = "#VALX"; if (hasPoints) chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Days, series); } area.AxisX.LabelStyle.Format = "ddd M/d"; return new ChartResult(chart); } 

How to delete

+6
source share
3 answers

I have a way to make this work.
Sorry for the long answer, but I found a way by which you try to implement this answer will affect if it works or not.

You need to set zero manually when you add points. Note. I could not do this job by adding zero points after the fact.

See the following example and screenshots: chart1.Series.Clear (); chart1.Series.Add (new series ()); chart1.Series.Add (new series ()); chart1.Series.Add (new series ()); chart1.Series.Add (new series ());

 foreach (Series s in chart1.Series) { s.ChartType = SeriesChartType.StackedColumn; } //chart1.Series[0].Points.Add(new DataPoint(0, 0)); chart1.Series[0].Points.Add(new DataPoint(1, 3)); chart1.Series[0].Points.Add(new DataPoint(2, 3)); chart1.Series[0].Points.Add(new DataPoint(3, 3)); chart1.Series[1].Points.Add(new DataPoint(0, 3)); //chart1.Series[1].Points.Add(new DataPoint(1, 0)); chart1.Series[1].Points.Add(new DataPoint(2, 3)); chart1.Series[1].Points.Add(new DataPoint(3, 3)); chart1.Series[2].Points.Add(new DataPoint(0, 3)); chart1.Series[2].Points.Add(new DataPoint(1, 3)); //chart1.Series[2].Points.Add(new DataPoint(2, 0)); chart1.Series[2].Points.Add(new DataPoint(3, 3)); chart1.Series[3].Points.Add(new DataPoint(0, 3)); chart1.Series[3].Points.Add(new DataPoint(1, 3)); chart1.Series[3].Points.Add(new DataPoint(2, 3)); //chart1.Series[3].Points.Add(new DataPoint(3, 0)); chart1.SaveImage("C:\\Before.png", ChartImageFormat.Png); 

Image of "before.png": enter image description here

Now delete the comments for the series without any data points for the given x value:

(Note: I didn’t find this to work if you added points at a given x-value for the values ​​where you do y = 0 at the end - aka right before saving the image. The order of the points in the series seems to matter for StackedColumn, I have never worked with this type, except to explore how to answer this question, so that they can be well known to users of this type)

 chart1.Series.Clear(); chart1.Series.Add(new Series()); chart1.Series.Add(new Series()); chart1.Series.Add(new Series()); chart1.Series.Add(new Series()); foreach (Series s in chart1.Series) { s.ChartType = SeriesChartType.StackedColumn; } chart1.Series[0].Points.Add(new DataPoint(0, 0)); chart1.Series[0].Points.Add(new DataPoint(1, 3)); chart1.Series[0].Points.Add(new DataPoint(2, 3)); chart1.Series[0].Points.Add(new DataPoint(3, 3)); chart1.Series[1].Points.Add(new DataPoint(0, 3)); chart1.Series[1].Points.Add(new DataPoint(1, 0)); chart1.Series[1].Points.Add(new DataPoint(2, 3)); chart1.Series[1].Points.Add(new DataPoint(3, 3)); chart1.Series[2].Points.Add(new DataPoint(0, 3)); chart1.Series[2].Points.Add(new DataPoint(1, 3)); chart1.Series[2].Points.Add(new DataPoint(2, 0)); chart1.Series[2].Points.Add(new DataPoint(3, 3)); chart1.Series[3].Points.Add(new DataPoint(0, 3)); chart1.Series[3].Points.Add(new DataPoint(1, 3)); chart1.Series[3].Points.Add(new DataPoint(2, 3)); chart1.Series[3].Points.Add(new DataPoint(3, 0)); // If you add the empty points here, it does not seem to work. // Empty points are as follows, and are already added above in the 'after' example. // chart1.Series[0].Points.Add(new DataPoint(0, 0)); // chart1.Series[1].Points.Add(new DataPoint(1, 0)); // chart1.Series[2].Points.Add(new DataPoint(2, 0)); // chart1.Series[3].Points.Add(new DataPoint(3, 0)); chart1.SaveImage("C:\\After.png", ChartImageFormat.Png); 

Image of "after.png": enter image description here

So, given that after the fact you cannot add zero points (although you can insert them?), You will need to change your code to something like this:

 var allPossibleGroups = t.StudentReports; var groups = t.StudentReports .Where<StudentReport>(rep => rep.IsComplete && rep.FirstSaveTimestamp.HasValue) .GroupBy<StudentReport, DateTime>(rep => rep.FirstSaveTimestamp.Value.Date); bool hasPoints = false; foreach (var g in allPossibleGroups) { if(groups.ContainsKey(g)) { series.Points.AddXY(g.Key, g.Count()); hasPoints = true; } else { series.Points.AddXY(g.Key, 0); } } 

Sorry for the long blocks of code, but this example was necessary to demonstrate how to make it work without falling into the trap of adding empty dots (where y = 0) at the end, as this will not work.

Let me know if you need more help.

+9
source

Go to the same problem yourself and want to share the right solution:

Use DataManipulator to insert missing values ​​(x, y):

 foreach (Series s in chart.Series) { chart.DataManipulator.Sort(PointSortOrder.Ascending, "X", s); chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, s); } 
+5
source

The loop loop does not work for me for some reason, but the following solution works like a charm:

 Chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, "Series1, Series2, Series3, Series4") 
0
source

Source: https://habr.com/ru/post/889050/


All Articles