I'm showing a Chart to the user which has one chart area with a line chart. On this, I got, for example, one line. This line has about 200 values. Those values do all have a description (e.g. "01.01.2013"
, "05.02.2013"
and so on).
When the Chart is shown, I can only see two descriptions, even if there would be space for much more descriptions. The line gets displayed correctly, but there are only two points described.
I rotated the Text vertically so there is more space, but this didn't help. If I display less values (5 or 10), the descriptions get shown correctly.
This is how it actually looks like (the descriptions are actually Strings, not Dates).
Thank you for your help!
EDIT: My Code:
chart.ChartAreas(0).AxisY.Maximum = 6
chart.ChartAreas(0).AxisY.Minimum = 1
chart.ChartAreas(0).AxisX.LabelStyle.Angle = -90
chart.Series.Clear()
chart.ChartAreas(0).AxisY.StripLines.Clear()
Dim myStripLine1 as new StripLine()
myStripLine1.IntervalOffset = 4
chart.ChartAreas(0).AxisY.StripLines.add(myStripLine1)
'now adding all series
chart.Series.Add("Chemie") 'just to take the example in the image above
chart.Series(chart.Series.Count - 1).ChartType = DataVisualization.Charting.SeriesChartType.Line
chart.Series(chart.Series.Count - 1).BorderWidth = 4
'now adding quite much values (on every date, every Serie has a value)
chart.Series(chart.Series.Count - 1).Points.AddXY("01.03.2011", 4.9)
On every date, a new point gets entered for all series, but only those points where they have important values get highlighted. Those values between are calculated mathematically.
One example to explain this: I got two series, one has two values (6 and 4) on point "01.01.2013"
and "03.01.2013"
. The other series has 3 values (4,6,5.5) on "01.01.2013"
,"02.01.2013"
and "03.01.2013"
. When I just display them, the first series will end at the second date, even if there was a value for the third date. I solved this by filling a dummy value at the first series with date "02.01.2013"
which is just the average at this point (=5). This point simply does not get highlighted with a marker bullet. This is how I draw my graph.
EDIT2:
After Skippy's answer and comment, my new trial. The variable MainForm.grades
is a Dictionary(Of Integer,Dictionary(Of String, String))
which contains around 150 grades
Dim subjects As New Dictionary(Of Integer, ArrayList)
Dim allgrades As New ArrayList
For Each grade In MainForm.grades
Dim cD As New Dictionary(Of String, String)
cD.Add("SUBJECTID", grade.Value("SUBJECTID"))
cD.Add("GRADE", grade.Value("GRADE"))
cD.Add("DATE", grade.Value("DATE"))
allgrades.Add(cD)
Next
cht_main.ChartAreas(0).AxisX.IntervalType = DateTimeIntervalType.Days
cht_main.ChartAreas(0).AxisX.LabelStyle.Angle = -90
Dim gradesDateSorter = New gradesDateSorter()
allgrades.Sort(gradesDateSorter)
For Each grade In allgrades
If Not subjects.ContainsKey(Integer.Parse(grade("SUBJECTID"))) Then
subjects.Add(Integer.Parse(grade("SUBJECTID")), New ArrayList)
End If
Dim gradeDict As New Dictionary(Of String, String)
gradeDict.Add("DATE", grade("DATE"))
gradeDict.Add("GRADE", grade("GRADE"))
subjects(Integer.Parse(grade("SUBJECTID"))).Add(gradeDict)
Next
For Each subject In subjects
'adding serie
cht_main.Series.Add(MainForm.subjects(subject.Key)("NAME"))
cht_main.Series(cht_main.Series.Count - 1).ChartType = DataVisualization.Charting.SeriesChartType.Line
cht_main.Series(cht_main.Series.Count - 1).BorderWidth = 4
'cht_main.Series(cht_main.Series.Count - 1).IsXValueIndexed = True
For Each grade In subject.Value
cht_main.Series(cht_main.Series.Count - 1).Points.AddXY(Date.Parse(grade("DATE")), Double.Parse(grade("GRADE")))
Next
Next
On the 5th last row I commented IsXValueIndexed=True
because when I activated it, the chart gets generated with a big red error cross.
SOLUTION
Setting the Interval on the X-Axis does the trick!
chart.ChartAreas(0).AxisX.Interval = 1
Solution by Skippy
Yes I agree with Michael. I can only add to the explanation at this point.
By setting your interval:
myStripLine1.IntervalOffset = 4
You are guaranteeing that your X-axis values will be plotted only, at frequency of 4 " generic x-axis" values:
Setting this to vale to 1 will give a value for every x-axis value, that is incremented as a whole number (in this case days)
chart.ChartAreas(0).AxisX.Interval = 1
And to declare the x-axis values to type:
DateTimeIntervalType.Days
'Declaration
Public Sub Add( _
labelsStep As Double, _
intervalType As DateTimeIntervalType, _
format As String _
)
End Sub
chart.ChartAreas(0).AxisX.IntervalType = DateTimeIntervalType.Days
'which as shown in Michael's answer is parsed to string.
Dim format as String = "MM.dd.yyyy"
Dim actualDate as Date = Date.ParseExact(yourDate, format)
As mentioned by Michael in his comment.
By setting the
mySeries.XValueIndexed = True
Every indexed X-axis value will be plotted.
As explained in the following quote, with the link provided.
Each data point in a series has X and Y values that determine its position in the plotting area. With some charts, the X value of points is not important, and does not have to be provided. In this case, the point positions in the plotting area are determined only by their point index (i.e. their location in the Points collection) and their Y values.
When X values are "indexed", the data point index, not a point's X value, is used to determine the position of points along the categorical (X) axis. For example in Figure 1 below, two charts are shown displaying the same data. However, the first chart uses non-indexed X values, therefore the X values of those points determine their location along the x-axis. The second chart is indexed, therefore its point indices are used to determine their position along the x-axis. In this case the X values are only used for the axis labels, and nothing more.
http://support2.dundas.com/onlinedocumentation/winchart2005/Data_IndexedXValues.html
I sourced my original information regarding intervals and interval offsets at the following site:
http://support2.dundas.com/Default.aspx?article=705
Here it discusses datatype and addresses your issue of highlighted values.
On every date, a new point gets entered for all series, but only those points where they have important values get highlighted
For example, assume you wish to create a re-occurring StripLine to highlight weekends. You set the interval to 7 and its type to Days. Since the first point is Sunday you set the IntervalOffset to 6 (to mean the 6th day of the week) and its type to Days. The resulting chart does not show the first StripLine.
This is a an explanation for setting the interval.
A good rule of thumb to follow when using the Interval and IntervalOffset properties of the Chart is that the IntervalOffset should be a lower interval magnitude than the Interval (ie. Interval Days / IntervalOffset Hours, Interval Years / IntervalOffset Months, etc.).
I have added these sources:
- For your reference
- To show I have, also, done my research after ascertaining the problem, as stated in my comments above.
Florian, can you pls show the code for the labels, properties etc of the x-axis? – yvytty yesterday
Did you ever consider 3rd party plotting components, such as ZedGraph ? Most likely such little caveats are already covered there. Give it a shot! – Neolisk yesterday
In response to ZedGraph I advised:
And: After viewing your code
Hi can I clarify, you WANT to plot values daily? I think I have your solution, just need clarification, you have all the tools within vb.net
@yvytty, nope, the dates do not have to be daily, there can also be no value for a long time and I don't want a big span in my chart where no data is. Actually, I could also write some sample text at the X axis values, the dates are only confusing. The main problem is that the VB chart somehow calculates a very big margin on those descriptions at the X axis
It doesn't show that you have formatted your date and date string. There also needs to be taken into account, that you are not using the en-US date format (I'm in Australia, so we have the same format as you). The default date type is for en-US.
Please refer to DateTime.ParseExact
Method
http://msdn.microsoft.com/en-us/library/system.datetime.parseexact.aspx
I have taken snippets from MSDN.
Dim dateString, format As String
Dim result As Date
Dim provider As CultureInfo = CultureInfo.InvariantCulture
Parse date and time with custom specifier.
dateString = "Sun 15 Jun 2008 8:30 AM -06:00"
format = "ddd dd MMM yyyy h:mm tt zzz"
result = Date.ParseExact(dateString, format, provider)
See link:
http://msdn.microsoft.com/en-us/library/w2sa9yss.aspx
The DateTime.ToString(IFormatProvider) method returns the string representation of a date and time value using the short date and long time pattern of a specific culture. The following example uses the DateTime.ToString(IFormatProvider) method to display the date and time using the short date and long time pattern for the fr-FR culture.
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")))
' Displays 01/03/2008 07:00:00
Please see this link:
http://msdn.microsoft.com/en-us/library/system.datetime.aspx
So it should go, something like this:
'note
Imports System.Globalization
Dim format as String = "dd.MM.yyyy"
Dim actualDate as Date = Date.ParseExact(yourDate, format, provider)
chart.ChartAreas(0).AxisX.LabelStyle.Format ="dd.MM.yyyy"
cht_main.ChartAreas(0).AxisX.IntervalType = DateTimeIntervalType.Days
cht_main.ChartAreas(0).AxisX.Interval = 1
ALSO:
Double.Parse(grade("GRADE")
'grade is not of type double
I think you should convert the string date representation to an actual datetime object before adding it to the chart.
I didn't test it but something like this: (where yourDate
is the string you used to pass to the chart)
Dim format as String = "MM.dd.yyyy"
Dim actualDate as Date = Date.ParseExact(yourDate, format)
chart.Series(chart.Series.Count - 1).Points.AddXY(actualDate, 4.9)
The chart can manage datetime object instead of strings and it has special code that deals with dates. If you do this you you can adjust how it is displayed by formatting:
chart.ChartAreas(0).AxisX.LabelStyle.Format ="MM.dd.yyyy"
chart.ChartAreas(0).AxisX.Interval = 1
chart.ChartAreas(0).AxisX.IntervalType = DateTimeIntervalType.Days
If you wanted to only display every other day change the interval to 2