vb.net chart with week numbers as X Axis - vb.net

I know a similar question was asked before, but it wasn't answered.
I have a chart where I use week numbers as its X-axis, that are retrieved as part of the SQL query.
It works fine up until a new year starts. In such a case, even though the weeks are ordered correctly when retrieved (for example, 49, 50, 51, 52, 1, 2, 3), they appear on the axis numerically ordered: 1, 2, 3, 49, 50, 51, 52.
Is there a way to fix that?
The relevant sql query part is:
SELECT DATEPART(year, start_charge_time),
DATEPART(week, start_charge_time) week_num,
COUNT(*) num_sessions
FROM parking_log
GROUP BY DATEPART(year, start_charge_time),
DATEPART(week, start_charge_time)
ORDER BY DATEPART(year, start_charge_time),
DATEPART(week, start_charge_time)
The Chart is:
Dim SeriesParkingRev As Series
SeriesParkingRev = ChartParkingSummery.Series("SeriesParkingRev")
' Set series chart type
SeriesParkingRev.ChartType = SeriesChartType.Line
SeriesParkingRev.MarkerStyle = MarkerStyle.Square
SeriesParkingRev.MarkerSize = 10
SeriesParkingRev.BorderWidth = 3
SeriesParkingRev.Color = Color.Red
SeriesParkingRev.IsValueShownAsLabel = True
SeriesParkingRev.IsVisibleInLegend = True
'' Set series members names for the X and Y values
SeriesParkingRev.XValueMember = "week_num"
SeriesParkingRev.YValueMembers = "total_charge"
SeriesParkingRev.LegendText = "Parking Revenue"
'' --------------------------
' Create the destination series and add it to the chart
'Dim SeriesParkingTime As New Series("SeriesParkingTime")
'ChartParkingSummery.Series.Add(SeriesParkingTime)
Dim SeriesParkingTime As Series
SeriesParkingTime = ChartParkingSummery.Series("SeriesParkingTime")
' Ensure the destination series is a Line or Spline chart type
SeriesParkingTime.ChartType = SeriesChartType.Line
SeriesParkingTime.MarkerStyle = MarkerStyle.Diamond
SeriesParkingTime.MarkerSize = 12
SeriesParkingTime.BorderWidth = 3
SeriesParkingTime.IsValueShownAsLabel = True
SeriesParkingTime.Color = Color.Blue
' Assign the series to the same chart area as the column chart
SeriesParkingTime.ChartArea = ChartParkingSummery.Series("SeriesParkingRev").ChartArea
' Assign this series to use the secondary axis and set its maximum to be 100%
SeriesParkingTime.YAxisType = AxisType.Secondary
ChartParkingSummery.Series("SeriesParkingTime").XValueMember = "week_num"
ChartParkingSummery.Series("SeriesParkingTime").YValueMembers = "avg_time"
ChartParkingSummery.Series("SeriesParkingTime").LegendText = "Average Time"
'' ----------------------------------------
'Dim SeriesCars As New Series("SeriesCars")
'ChartParkingSummery.Series.Add(SeriesCars)
Dim SeriesCars As Series
SeriesCars = ChartParkingSummery.Series("SeriesCars")
SeriesCars.ChartType = SeriesChartType.Point
SeriesCars.MarkerStyle = MarkerStyle.Triangle
SeriesCars.MarkerSize = 8
SeriesCars.BorderWidth = 3
SeriesCars.IsValueShownAsLabel = True
SeriesCars.MarkerStyle = MarkerStyle.Triangle
SeriesCars.MarkerSize = 15
SeriesCars.MarkerColor = Color.Green
ChartParkingSummery.Series("SeriesCars").XValueMember = "week_num"
ChartParkingSummery.Series("SeriesCars").YValueMembers = "num_cars"
ChartParkingSummery.Series("SeriesCars").LegendText = "Cars"
'' ----------------------------------------
ChartParkingSummery.Legends.Add(New Legend("Default"))
' Set legend style
ChartParkingSummery.Legends("Default").LegendStyle = LegendStyle.Table
' Set table style if legend style is Table
' Set legend docking
ChartParkingSummery.Legends("Default").Docking = Docking.Right
' Set legend alignment
ChartParkingSummery.Legends("Default").Alignment = StringAlignment.Center
ChartParkingSummery.Titles.Add("Revenue, Avg Time & Cars")

Related

On a VB form why are graphics disappearing when the form is first displayed?

I have a form which displays graphs of various kinds, taken from sales data from a database.
These graphs are drawn on panels on the form but I have had a very recent issue. Up until recently, the form displayed the graphs when it was displayed but now the graphs appear then disappear and I cannot figure out why.
Here is a link to a Vimeo video showing the behaviour: https://vimeo.com/575969787
When the form is loaded a procedure is called in the Form_Shown event which draws the graphs - for ease of understanding I have restricted this to one graph only.
Private Sub FormDashboard_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'Once form is initialised and shown run all the reports
RunReports(True)
End Sub
Private Sub RunReports(All As Boolean)
'Display these reports
DrawDepartment(PanelFood, TableDepartment)
'DrawDepartment(PanelWine, TableDepartment)
'DrawDivision(PanelDivision, TableDepartment)
'DrawCLA(PanelCLA, TableCLA)
''If all = true then also display MAT
'If (All = True) Then
' DrawMAT(PanelMAT, TableMAT)
'End If
End Sub
Public Shared Sub DrawDepartment(TargetPanel As Panel, TableGraph As DataTable)
'Graphics object
Dim Dep_Graph As Graphics = TargetPanel.CreateGraphics
Dim Offset As Integer = 45
Dim DepName As String = ""
'Graph area
With TargetPanel
GraphHeight = .Height - (Offset + Gap)
GraphWidth = .Width - (2 * Gap)
GraphXOrigin = Gap
GraphYOrigin = (Offset + Gap)
End With
Dim Filter As String = "" 'Filter used for querying the data table
Dim FoundMax() As DataRow 'A data row generated by a filter
Dim FoundRows() As DataRow 'A data row generated by a filter
'The data table has a max value for food sales in the given period
If (TargetPanel.Name.Contains("Food")) Then
Filter = "Department LIKE 'F%' OR Department LIKE 'S%'"
Else
Filter = "Department LIKE 'W%'"
End If
Select Case Report
Case ReportMode.Day
TableGraph.DefaultView.Sort = "Day DESC"
FoundMax = TableGraph.Select(Filter)
MaxDataValue = FoundMax(0).Item("Day")
Case ReportMode.Week
TableGraph.DefaultView.Sort = "Week DESC"
FoundMax = TableGraph.Select(Filter)
MaxDataValue = FoundMax(0).Item("Week")
Case ReportMode.Month
TableGraph.DefaultView.Sort = "Month DESC"
FoundMax = TableGraph.Select(Filter)
MaxDataValue = FoundMax(0).Item("Month")
Case ReportMode.Year
TableGraph.DefaultView.Sort = "Year DESC"
FoundMax = TableGraph.Select(Filter)
MaxDataValue = FoundMax(0).Item("Year")
End Select
TableGraph.DefaultView.Sort = "Department"
'Select only the food department values
If (TargetPanel.Name.Contains("Food")) Then
Filter = "Department LIKE 'F%' OR Department LIKE 'S%'"
Else
Filter = "Department LIKE 'W%'"
End If
FoundRows = TableGraph.Select(Filter)
'Calculate the width of each column
Dim NumberOfColumns As Integer = (FoundRows.GetUpperBound(0) + 1)
ColWidth = (GraphWidth - ((NumberOfColumns) * Gap)) / NumberOfColumns
'Using the graphics object draw the columns
With Dep_Graph
MessageBox.Show("Clearing graph area")
'Using the FoundMax data row extract the Day max value
ClearGraph(TargetPanel)
For Counter As Integer = 0 To FoundRows.GetUpperBound(0)
Select Case Report
Case ReportMode.Day
DataValue = FoundRows(Counter).Item("Day")
DepName = FoundRows(Counter).Item("Department")
If (TargetPanel.Name.Contains("Wine")) Then
ReportLabel(Counter + 12).Text = GetLabelData(DepName, DataValue)
Else
ReportLabel(Counter).Text = GetLabelData(DepName, DataValue)
End If
Case ReportMode.Week
DataValue = FoundRows(Counter).Item("Week")
DepName = FoundRows(Counter).Item("Department")
If (TargetPanel.Name.Contains("Wine")) Then
ReportLabel(Counter + 12).Text = GetLabelData(DepName, DataValue)
Else
ReportLabel(Counter).Text = GetLabelData(DepName, DataValue)
End If
Case ReportMode.Month
DataValue = FoundRows(Counter).Item("Month")
DepName = FoundRows(Counter).Item("Department")
If (TargetPanel.Name.Contains("Wine")) Then
ReportLabel(Counter + 12).Text = GetLabelData(DepName, DataValue)
Else
ReportLabel(Counter).Text = GetLabelData(DepName, DataValue)
End If
Case ReportMode.Year
DataValue = FoundRows(Counter).Item("Year")
DepName = FoundRows(Counter).Item("Department")
If (TargetPanel.Name.Contains("Wine")) Then
ReportLabel(Counter + 12).Text = GetLabelData(DepName, DataValue)
Else
ReportLabel(Counter).Text = GetLabelData(DepName, DataValue)
End If
End Select
If (MaxDataValue > 0) Then
'Set column height to a scale of the maximum value
ColHeight = (DataValue * GraphHeight) / MaxDataValue
End If
'Set colours
PenWWC.Color = Colors(Counter + 2)
BrushWWC = New SolidBrush(Colors(Counter + 2))
'Draw and fill
DrawColumn(Dep_Graph, GraphXOrigin, TargetPanel.Height - ColHeight - Offset, ColWidth, ColHeight, PenWWC, BrushWWC)
'Reset X0 to the next point
GraphXOrigin = GraphXOrigin + ColWidth + Gap
Next
End With
GraphXOrigin = Gap
Dep_Graph.Dispose()
End Sub
As can be seen in the video I have included a message box at the point where I clear the graphing area to show that this is NOT what is happening.
As I say, up until recently the form displayed with graphs showing; no changes have been made to this section of the application code so i don't know what is happening.
Further, as shown in the video, if I select the date for which the form is set, the graphs appear and if I change date, the new graphs appear, without problem.
Any suggestions most welcome. AFAIK I have posted all the relevant code here.
TIA,
Dermot

Count with multiple variants

I have used Variants in the past for something similar, but it was one dimensional in its solution. I am wondering if utilizing Variants with two dimensions would be feasible.
I have ever changing list of dates that correspond with a week, that will be entered in chronologically. The next column is the count of that week. Column C is the building that it took place in.
For example, the first row shown in the image above takes place the week of "10/2/2016" and there was a count of 8 that week which means the buildings in rows 2-9 are correlated with that week, and it continues on for each corresponding week.
I have the sum of the counts for each year, so for the chart in "E1:G14", I want to count each time the building is counted for each year, respectively. I am just confused as to how to approach it and if Variants would be useful or if using a CountIfs for the ranges would work best.
Thank you in advance.
CODE
Private Sub maybe()
Dim sht As Worksheet: Set sht = Worksheets("Sheet3")
Dim wk_cnt As Double: wk_cnt = sht.Range("A1", sht.Range("A1").End(xlDown)).Rows.Count
Dim bld_cnt As Double: bld_cnt = sht.Range("C2", sht.Range("C2").End(xlDown)).Rows.Count
Dim cnt As Double
Dim yrs_cnt As Double
If sht.Range("D3").Value = "" Then
yrs_cnt = 1
Else:
yrs_cnt = sht.Range("D2", sht.Range("D2").End(xlDown)).Rows.Count
End If
Dim yrsArray As Range
If sht.Range("D3").Value = "" Then
Set yrsArray = sht.Range("D2")
Else:
Set yrsArray = sht.Range("D2", sht.Range("D2").End(xlDown))
End If
Dim vCnts As Variant
ReDim vCnts(1 To 12, 1 To yr_cnt)
vCnts(1, 1) = "Irving Building"
vCnts(2, 1) = "Memorial Building"
vCnts(3, 1) = "West Tower"
vCnts(4, 1) = "Witting Surgical Center"
vCnts(5, 1) = "Madison Irving Surgery Center"
vCnts(6, 1) = "Marley Education Center"
vCnts(7, 1) = "410 South Crouse"
vCnts(8, 1) = "Physicians Office Building"
vCnts(9, 1) = "Crouse Business Center"
vCnts(10, 1) = "Commonwealth Place"
vCnts(11, 1) = "Crouse Garage"
vCnts(12, 1) = "CNY Medical Center"
For x = 1 To yrs_cnt
cnt = 0
For y = 2 To wk_cnt
If Year(sht.Cells(y, 1).Value) = sht.Cells(1, x + 5).Value Then
cnt = cnt + sht.Cells(y, 2).Value
sht.Cells(14, x + 5) = cnt
End If
Next y
Next x
End Sub
EDIT
With Column C
With only Columns A & B
I need the numbers to match the second image, but when I include all three columns it looks like the first image after I group it by years year. How can I fix that?
It looks like your PivotTable is using the "Count" column improperly. Where it says "Count of Count", it's telling you that the number shown is how many lines on your data range fit the selected criteria. I think if you change the Value Field Settings to SUM you will be pleased with the difference. See below:

Is it possible to change a graphs x and y axis major/minor units using openpyxl?

I have tried the following but none work.
chart.auto_axis = False
chart.x_axis.unit = 365
chart.set_y_axis({'minor_unit': 100, 'major_unit':365})
changing the max and min scale for both axis is straight forward
chart.x_axis.scaling.min = 0
chart.x_axis.scaling.max = 2190
chart.y_axis.scaling.min = 0
chart.y_axis.scaling.max = 2
so I'm hoping there is a straight forward solution to this. Here is a mcve.
from openpyxl import load_workbook, Workbook
import datetime
from openpyxl.chart import ScatterChart, Reference, Series
wb = Workbook()
ws = wb.active
rows = [
['data point 1', 'data point2'],
[25, 1],
[100, 2],
[500, 3],
[800, 4],
[1200, 5],
[2100, 6],]
for row in rows:
ws.append(row)
chart = ScatterChart()
chart.title = "Example Chart"
chart.style = 18
chart.y_axis.title = 'y'
chart.x_axis.title = 'x'
chart.x_axis.scaling.min = 0
chart.y_axis.scaling.min = 0
chart.X_axis.scaling.max = 2190
chart.y_axis.scaling.max = 6
xvalues = Reference(ws, min_col=1, min_row=2, max_row=7)
yvalues = Reference(ws, min_col=2, min_row=2, max_row=7)
series = Series(values=yvalues, xvalues=xvalues, title="DP 1")
chart.series.append(series)
ws.add_chart(chart, "D2")
wb.save("chart.xlsx")
I need to automate changing the axis to units of 365 or what ever.
Very late answer, but I figured out how to do this just after finding this question.
You need to set the major unit axis to 365.25, and the format to show just the year:
chart.x_axis.number_format = 'yyyy'
chart.x_axis.majorUnit = 365.25

SeriesCollection().Values sume all series

I´m having trouble with my code because when the second serie is ploted it has the value of the sume of both series 1 and 2.
This is my code:
Dim Chart2 As ChartObject
Set Chart2 = ActiveSheet.ChartObjects.Add(Left:=10, Width:=1380, Top:=450, Height:=380)
Chart2.Chart.ChartType = xlLineStacked
Chart2.Chart.SeriesCollection.NewSeries
Chart2.Chart.SeriesCollection(1).Name = "Hours"
Chart2.Chart.SeriesCollection(1).XValues = ActiveSheet.Range("B93:S93)
Chart2.Chart.SeriesCollection(1).Values = ActiveSheet.Range("B95:W95)
Chart2.Chart.SeriesCollection.NewSeries
Chart2.Chart.SeriesCollection(2).Name = "CdT"
Chart2.Chart.SeriesCollection(2).XValues = ActiveSheet.Range("B93:S93)
Chart2.Chart.SeriesCollection(2).Values = ActiveSheet.Range("B99:W99)
Thank you in advance¡

How to create a virtual column on a gridview based on a particular gridview columns

Please i have a project that i query the database using entity framework as my ORM. This is my query
Dim subjectSearch = From subSearch In DemoSchool.EssenceSubjectRegistrations Where subSearch.Session = drpSession.SelectedItem.Text _
AndAlso subSearch.Term = drpTerm.SelectedItem.Text AndAlso subSearch.RealClass.ClassSN = findClassSN.FirstOrDefault AndAlso _
subSearch.SubjectCode = drpSubject.SelectedValue _
Select New With {.SubjectRegSN = subSearch.SubjectRegSN,
.FirstName = subSearch.Student.FirstName,
.Surname = subSearch.Student.Surname,
.CA1 = subSearch.CA1,
.CA2 = subSearch.CA2,
.CA3 = subSearch.CA3,
.CA4 = subSearch.CA4,
.CA5 = subSearch.CA5}
Then i query my result so that i can be able to do some operation on it by doing this
Dim secSubjectSearch = (From jamie In subjectSearch Select jamie).ToList() _
.Select(Function(jamie) New With {.SubjectRegSN = jamie.SubjectRegSN,
.FirstName = jamie.FirstName,
.Surname = jamie.Surname,
.CA1 = jamie.CA1,
.CA2 = jamie.CA2,
.CA3 = jamie.CA3,
.CA4 = jamie.CA4,
.CA5 = jamie.CA5,
.MidTerm = CDbl(jamie.CA1 + jamie.CA2 + jamie.CA3 + jamie.CA4 + jamie.CA5) / 5})
The result of the second query is bounded to the gridview which renders properly as it is suppose to rendered. My problem is that i want to create a virtual column called Rank on the gridview after the .MidTerm bounded column that will display the position of each person record in the search result.
NAME CA1 CA2 CA3 CA4 CA5 MIDTERM RANK
James 50 50 60 40 60 52 3
Essty 100 50 50 50 50 60 2
Markus 100 40 50 60 50 60 2
Code 100 100 100 100 50 90 1
Above is a format of the gridview columns. I want column Rank to be a virtual column that is calculated based on the Midterm score of the students.Code VB scored 90 so his rank so be 1 and so on.Please i don't know how to calculate this rank column and the code to get the highest and the smallest.Really i need help thanks
Two ways.
Use Unbound column and calculate/display the rank
Have a RANK field and pre-calculate it and bound it, something like:
Dim secSubjectSearch = (From jamie In subjectSearch Select jamie).ToList() _
.Select(Function(jamie) New With {.SubjectRegSN = jamie.SubjectRegSN,
.FirstName = jamie.FirstName,
.Surname = jamie.Surname,
.CA1 = jamie.CA1,
.CA2 = jamie.CA2,
.CA3 = jamie.CA3,
.CA4 = jamie.CA4,
.CA5 = jamie.CA5,
.MidTerm = CDbl(jamie.CA1 + jamie.CA2 + jamie.CA3 + jamie.CA4 + jamie.CA5) / 5,
.RANK = -1}).ToList()
dim sorted = secSubjectSearch.Select(function(n) n.MidTerm).Distinct().OrderByDescending(function(n) n).ToList()
for each itm in secSubjectSearch
itm.RANK = sorted.IndexOf(itm.MidTerm) + 1
next
-- Not tested, wrote it with notepad...