vb chart second xaxis label offset - vb.net

I am creating a VB.Net chart with date/time as the xAxis labels. It is working fine but what I want to do is sync the second label to a even hour boundary. The chart should have the first label as the first date/time in the dataset, but the labels following would then be on a 6 hour (00:00 - 06:00 - 12:00 - 18:00) boundry. I could also live with not having the first axis label as long as the rest were on a 6 (or 12, depending on the length of the data) hour boundary.
Current:
07:00-------13:00-------19:00-------01:00-------07:00-------13:00
What I'm after:
07:00--12:00-------18:00-------00:00-------06:00-------12:00
Chart as currently produced

I've got it... sort of.
For area As Integer = 0 To numLanes -1
myArea = New ChartArea("myArea" & area.ToString)
With myArea
.BackColor = mySetup.colorPlotBackground ' set from user preferences
.Area3DStyle.Enable3D = mySetup.is3D ' set from user preferences
.AxisX.LabelStyle.Format = "g"
.AxisX.Interval = 1
.AxisX.IntervalType = DateTimeIntervalType.Days
.AxisX.IntervalOffset = 0
.AxisX.IntervalOffsetType = DateTimeIntervalType.Hours ' Set the X value type of the displayed series to DateTime.
End With
cht.ChartAreas.Add(myArea)
Produces the attached chart.
Slightly Improved

Related

How does the array SPLIT function sort?

I set up a VBA routine in Word 2013 to create/display a calendar.
An array was set up for the weekdays, here's some of it:
Public arrDays As Variant
arrDays = Split("Mon,Tue,Wed,Thu,Fri,Sat,Sun,Mon,Tue,Wed,Thur,Fri,Sat,Sun", ",")
With .Rows(2)
.Cells.VerticalAlignment = wdAlignVerticalCenter
.Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Range.Font.Name = "Calibri"
.Range.Font.Italic = True
.Range.Font.Size = 28
.Height = 24
For J = 1 To 7
.Cells(J).Range.Text = arrDays(J + lngFirstDay - 2)
Next J
End With
When I place the .Cells(J).Range.Text in the specified cell number it starts with "Sun";
The watch window shows:
arrDays(0) "Sun"; arrDays(1) "Mon"; arrDays(2) "Tue";....
Mo matter how I arrange the weekdays in the split, it is the same.
The calendar routine does work, it's just this Split thing
Info that should have been in the original post:
Start of Calendar selection
Watch list of arrDays
First day of workweek - Sunday
Second day of workweek
Complete Calendar
It is fixed.
I moved Public arrDays As Variant from CallCalForm to Declarations and moved
arrDays = Split("Mon,Tue,Wed,Thu,Fri,Sat,Sun,Mon,Tue,Wed,Thur,Fri,Sat,Sun", ",")
from beginning of CallCalForm to top Sub CommandButton1_Click().
I'm not sure if moving around made a difference, maybe I had a typo somewhere. If I change the order of arrDays the outcome corresponds to the change.

Make the grid of chart control to begin at an even hour

I am using a chart control which in x axis displays time, initialized as follows:
With Chart1.ChartAreas(0)
.AxisX.Minimum = 0
.AxisX.LabelStyle.Format = "HH:mm"
.AxisX.IntervalType = DateTimeIntervalType.Hours
.AxisX.Interval = 2
.AxisY.Minimum = 0
End With
Chart1.Series(0).IsXValueIndexed = True
Sometimes the data points start at an odd hour like the picture bellow
My question is how can I make the grid and labels begin at an even hour instead.
Thanks in advance.
OK I got it. I just removed the commands
.AxisX.Minimum = 0 in With...End With statement and
Chart1.Series(0).IsXValueIndexed = True
and now the grid always begins at an even hour automatically.

Is there a way to plot a line graph with integer x values but label each point on the x axis with a string?

I'm producing a line graph and I'm plotting points according to x and y values using points.addxy(X, Y). However the xvalues are plotted through regular intervals which I want to have labeled below the axis. My code is below:
Dim AllRaceArray() As String = GetAllRaceArray() 'Array of The race names in date order
Dim RaceIDs() As Integer = GetAllRaceID() 'Array Of The Race IDs Paralell to the above array
Dim Xnum As Integer = AllRaceArray.Length
Dim Interval As Integer = Math.Floor(Chart1.Size.Width / Xnum)
Chart1.Series.Clear()
For i = 0 To 3
If CompareSlotEmpty(i) = False Then
Chart1.Series.Add(i & CompPaddler(i).Name)
Chart1.Series(i).ChartType = SeriesChartType.Line
Chart1.Series(i).XValueType = ChartValueType.String
Chart1.Series(i).BorderWidth = 2
Chart1.Series(i).MarkerStyle = DataVisualization.Charting.MarkerStyle.Circle
Chart1.Series(i).MarkerSize = 8
For p = 0 To Xnum - 1
For q = 0 To CompPaddler(i).RacePoints.Length - 1
If CompPaddler(i).RacePoints(q).RaceID = RaceIDs(p) Then
Chart1.Series(i).Points.AddXY(Interval * p, CompPaddler(i).RacePoints(q).Points) ' this point plot creates the correct ordering
Chart1.Series(i).Points.AddXY(AllRaceArray(p), CompPaddler(i).RacePoints(q).Points) ' this point plot creates the correct labels
End If
Next
Next
End If
' EDIT
' This below Section has now been added but nothing appears below the axis at all now
For t = 0 To Chart1.Series(i).Points.Count - 1
Chart1.Series(i).Points(t).AxisLabel = AllRaceArray(t)
Next
'EDIT
Next
As annotated above One chart series creates the correct looking graph (http://tinypic.com/r/sobwbc/9) but x axis labels. Then the second plotter plots the correct labels but the ordering and scale gets messed up (http://tinypic.com/r/2w2g5s4/9).
TLDR: How to I change the xAxis Labels to strings that line up with regularly interval points?
Edit: I have added a loop to change the .axislabel but now nothing shows below the axis

VBA Excel Graphing Add time to X-Axis

I am graphing a trend for a pump for a day, I am getting a sample data every minuet
I got the graph all working but the problem I am running into is trying to get the time on the X-axis. There is a column that shows the time each sample data was taken, but when I tried to add it, it put the time for every point in the chart. Because I have 1440 points in the chart, it was just a blob of unreadable text, I removed that code and right now I am doing without. But I would like to figure it out.
'Chart for Monday
With wBM.ActiveSheet.ChartObjects.Add(Left:=300, Width:=300, Top:=10, Height:=300)
.Chart.SetSourceData Source:=wBM.ActiveSheet.Range("B1:B1440"), PlotBy:=xlColumns
.Chart.ChartType = xlLine
.Left = rngChart2.Left
.Top = rngChart2.Top
.Width = rngChart2.Width
.Height = rngChart2.Height
.Chart.HasTitle = True
.Chart.ChartTitle.Text = "Monday " & Monday
.Chart.HasLegend = False
End With
This is my code so far. In Column D has the time for each point so it would be "D1:D1440".
Is there a way to only have 1 label for every 60 points, or 120? So that I don't have such a blob of labels?
Starting with sample data that looks like this:
I ran this macro to hide all labels which 'location' is not multiple of 5
Sub formateDataLabels()
Dim chrt As Chart
Set chrt = ActiveChart
Dim cnt As Long: cnt = 1
For Each lbl In chrt.SeriesCollection(1).DataLabels
If cnt Mod 5 <> 0 Then
lbl.Text = ""
End If
cnt = cnt + 1
Next lbl
End Sub
Result:
Note that the current code is simply set up to run on the selected chart. Change the 5 to whatever you need such as 50 or 100 and adapt to your current chart.

Excel VBA only show labels for each series' max value

I am trying to create a macro which loops through series in a chart and only shows the maximum / minimum label dependent on what the max / min value is.
Some of the series will only have negative values and in these cases I wish to only show the minimum datapoint label, and vice versa for series with 0 or greater values.
The code I have so far is:
Sheets("Curve").ChartObjects("Chart 14").Activate
For Each serie In ActiveChart.SeriesCollection
Dim pointCount As Integer
Dim pointValues As Variant
pointCount = serie.Points.Count
pointValues = serie.Values
For pointIndex = 1 To pointCount
If pointValues(pointIndex) < 1000 Then
serie.Points(pointIndex).HasDataLabel = True
End If
Next pointIndex
Next serie
End Sub
Which works fine when I manually enter the threshold, but I want to replace the '1000' with Max(series) value instead, so that each series in the chart has only one label visible.
The following modified routine includes MaxPoint, MaxPointIndex, MinPoint, and MinPointIndex variables which are calculated in the For loop on each serie's points. It then sets the label for the maximum point if the series has only positive value and minimum point otherwise.
Option Explicit
Sub chart()
Dim serie As Variant
Dim Pointindex As Long
Dim MaxPoint As Long
Dim MaxPointIndex As Long
Dim MinPoint As Long
Dim MinPointIndex As Long
Sheets("Curve").ChartObjects("Chart 14").Activate
For Each serie In ActiveChart.SeriesCollection
Dim pointCount As Integer
Dim pointValues As Variant
pointCount = serie.Points.Count
pointValues = serie.Values
MinPoint = 10000 'set to value greater than any point in any serie
MaxPoint = 0
For Pointindex = 1 To pointCount
If pointValues(Pointindex) > MaxPoint Then
MaxPoint = pointValues(Pointindex)
MaxPointIndex = Pointindex
ElseIf pointValues(Pointindex) < MinPoint Then
MinPoint = pointValues(Pointindex)
MinPointIndex = Pointindex
End If
Next Pointindex
If MinPoint >= 0 Then
serie.Points(MaxPointIndex).HasDataLabel = True
Else
serie.Points(MinPointIndex).HasDataLabel = True
End If
Next serie
End Sub
I have an alternative approach, which does not require VBA. It adds an extra series with an invisible data point at the max and this point has a data label. It also changes dynamically if the data changes and a different point is maximum, without having to rerun the VBA procedure.
For each series in the chart you'll need to use a range the same size as the Y values of the series.
Assume the original Y values for a given series is in D2:D10, and we'll use G2:G10 for our extra data. In G2 enter
=IF($D2=MAX($D$2:$D$10),$D2,NA())
and fill this down to G10. Modify this formula for the case where you might instead look for the minimum value if everything is negative.
Copy G2:G10 and hold CTRL while you select the X values for this series. Copy. Select the chart, use Paste Special, and select Add data as new Series, in Columns, Categories in First Column.
Select the added series, which is one point (unless there are two points at the maximum), format to have no lines and no markers. Add your data labels to this series.
Repeat for the other series in the chart.