Page 1 of 1
Understanding bars and series
Posted: Wed Nov 22, 2023 3:12 pm
by 16895550
I can only see how to add series at runtime but not actual bars. I want a simple stacked bar chart. My data is -
Chartdate JobType Total
20/11/20203 0
21/11/20203 Tip/Return 2
Re: Understanding bars and series
Posted: Wed Nov 22, 2023 3:17 pm
by 16895550
The previous message posted while I was half way through.
I can only see how to add series at runtime but not actual bars. I want a simple stacked bar chart. My data is -
Code: Select all
Chartdate JobType Total
20/11/2023 0
21/11/2023 Tip/Return 2
21/11/2023 Deliver 1
22/11/2023 Deliver 1
23/11/2023 0
So only some days in the 6 day period have totals. The days with no totals should just be an empty bar, and the others stacked based on Jobtype.
I kinda was expecting to so something like
Code: Select all
while not eof etc.
add bar
for each jobtype
add series
but there only seems to be an add series
Can any one provide a bit of real or seudo code, so I can understand it better. Thanks
Re: Understanding bars and series
Posted: Thu Nov 23, 2023 10:13 am
by yeray
Hello,
I would create a self stacked
TBarSeries
for each jobtype:
Code: Select all
for jobtype in jobtypes do
begin
with TBarSeries(Chart1.AddSeries(TBarSeries)) do
begin
MultiBar:=mbSelfStacked;
Title:=jobtype.name;
end;
end;
Then I would loop the data and add the values to one series or another depending on it:
Code: Select all
while not dataset.eof do
begin
for s in Chart1.Series do
begin
if s.Title=currentField.jobtype then
begin
s.Add(currentField.value);
Break;
end;
end
dataset.next;
end;
Re: Understanding bars and series
Posted: Thu Nov 23, 2023 3:42 pm
by 16895550
Hi Yeray
Wouldn't it be a TBarseries
for each day ? and then jobtypes within each day ?
The bottom axis will have dates form Monday to Saturday, Left axis the totals, Each day could have up to 10 different series.
Andy
Re: Understanding bars and series
Posted: Thu Nov 23, 2023 3:51 pm
by 16895550
Ive added an image to show how I want it. Maybe its best to manipulate the datasource instead whihc is what I;ve done in the designer?
- Screenshottchart.png (39.25 KiB) Viewed 26071 times
Thanks
Andy
Re: Understanding bars and series
Posted: Thu Nov 23, 2023 6:15 pm
by 16895550
Hi
I've created a series for each JObtype requested - Code below. I've hard coded until I fully understand how it works.
- Screenshot 1chart2.png (16.57 KiB) Viewed 26066 times
. However the resulting chart shows an extra series on Tuesday that I'm not adding and also a value for Wednesday, when I passed 0.
I've attached the chart image.
Andy
Code: Select all
sJOBTYPE := 'Deliver' ;
S1 := TBarSeries(Chart1.AddSeries(TBarSeries));
S1.Clear;
S1.Title := sJOBTYPE;
S1.MultiBar := mbStacked;
S1.Marks.Visible := False;
S1.Marks.Style := smsValue ;
S1.Color := GetJobTypeColour(sJobType) ;
sJOBTYPE := 'Collect' ;
S2 := TBarSeries(Chart1.AddSeries(TBarSeries));
S2.Clear;
S2.Title := sJOBTYPE;
S2.MultiBar := mbStacked;
S2.Marks.Visible := False;
S2.Marks.Style := smsValue ;
S2.Color := GetJobTypeColour(sJobType) ;
sJOBTYPE := 'Exchange' ;
S3 := TBarSeries(Chart1.AddSeries(TBarSeries));
S3.Clear;
S3.Title := sJOBTYPE;
S3.MultiBar := mbStacked;
S3.Marks.Visible := False;
S3.Marks.Style := smsValue ;
S3.Color := GetJobTypeColour(sJobType) ;
S1.Add( 2 , 'Monday', clTeeColor);
S1.Add( 4 , 'Tuesday', clTeeColor);
S1.Add( 0 , 'Wednesday', clTeeColor);
S1.Add( 5 , 'Thursday', clTeeColor);
S2.Add( 3 , 'Monday', clTeeColor);
S2.Add( 4 , 'Tuesday', clTeeColor);
S2.Add( 1 , 'Thursday', clTeeColor);
S3.Add( 1 , 'Monday', clTeeColor);
S3.Add( 1 , 'Thursday', clTeeColor);
Re: Understanding bars and series
Posted: Mon Nov 27, 2023 12:34 pm
by yeray
Hello,
The
Add
function appends a value to the series value list, regardless of the label you are assigning to it.
That's the reason why the second value added in S3 is shown in the second bar, even if it's label is 'Thursday'. And the same for the third value in S2.
You should add the same number of values to all the series, so they can be stacked at the positions you expect them. To do so, you can add a zero (as you are doing in the first series for 'Wednesday') or a null, ie:
Code: Select all
S1.Add( 2 , 'Monday', clTeeColor);
S1.Add( 4 , 'Tuesday', clTeeColor);
S1.Add( 0 , 'Wednesday', clTeeColor);
S1.Add( 5 , 'Thursday', clTeeColor);
S2.Add( 3 , 'Monday', clTeeColor);
S2.Add( 4 , 'Tuesday', clTeeColor);
S2.AddNull();
S2.Add( 1 , 'Thursday', clTeeColor);
S3.Add( 1 , 'Monday', clTeeColor);
S3.AddNull();
S3.AddNull();
S3.Add( 1 , 'Thursday', clTeeColor);
I hope this clarifies how it works. Otherwise please let us know.
Re: Understanding bars and series
Posted: Tue Dec 05, 2023 5:57 pm
by 16895550
Hi Yeray
I've got that working now thanks.
Just one thing. I won't know how many series I will need each time as it depends on the data, Jobtypes in my case.
Is there a way to assign a Series on the fly ?
At the moment, I still need to do if Jobtype = 'Collect' then S1. createseries etc. and S1.Add
But it would be better if it just added the next one along, whatever its called. S1, S2 etc.
Thansk
Andy
Re: Understanding bars and series
Posted: Mon Dec 11, 2023 11:50 am
by yeray
Hello Andy,
To do it automatically, you'll need to create a series for each of the "jobs" you have, and then you can loop the "weekDays" you want to track and search in your data structure and your series and add the value for matching that weekDay, or a zero if none.
I created a simple example with a couple of dirty records to emulate your data structure. This part should be accommodated to your datasource.
Then, I'm creating the series and looping the
weekDays
as indicated above.
Code: Select all
uses Chart, Series, TeEngine;
var Chart1: TChart;
type TJobValue = record
Value: double;
WeekDay: string;
end;
type TJob = record
Title: string;
Values: array of TJobValue;
end;
var jobs: array of TJob;
const weekDays: array[0..3] of string = ('Monday', 'Tuesday', 'Wednesday', 'Thursday');
procedure TForm1.FormCreate(Sender: TObject);
function GetValueFromJob(job: TJob; AWeekDay: string): TChartValue;
var i: Integer;
begin
Result:=0;
for i:=0 to High(job.Values) do
if job.Values[i].WeekDay=AWeekDay then
begin
Result:=job.Values[i].Value;
Exit;
end;
end;
var i, j: Integer;
sJOBTYPE: string;
begin
SetLength(jobs, 3);
with jobs[0] do
begin
Title:='Deliver';
SetLength(Values, 4);
Values[0].WeekDay:=weekDays[0];
Values[0].Value:=2;
Values[1].WeekDay:=weekDays[1];
Values[1].Value:=4;
Values[2].WeekDay:=weekDays[2];
Values[2].Value:=0;
Values[3].WeekDay:=weekDays[3];
Values[3].Value:=5;
end;
with jobs[1] do
begin
Title:='Collect';
SetLength(Values, 3);
Values[0].WeekDay:=weekDays[0];
Values[0].Value:=3;
Values[1].WeekDay:=weekDays[1];
Values[1].Value:=4;
Values[2].WeekDay:=weekDays[3];
Values[2].Value:=1;
end;
with jobs[2] do
begin
Title:='Exchange';
SetLength(Values, 2);
Values[0].WeekDay:=weekDays[0];
Values[0].Value:=1;
Values[1].WeekDay:=weekDays[3];
Values[1].Value:=1;
end;
// Create Chart
Chart1:=TChart.Create(Self);
with Chart1 do
begin
Parent:=Self;
Align:=alClient;
Color:=clWhite;
Gradient.Visible:=False;
Walls.Back.Color:=clWhite;
Walls.Back.Gradient.Visible:=False;
Axes.Bottom.LabelsAngle:=90;
Axes.Left.Increment:=1;
end;
// Create a series for each "job"
for j:=0 to High(jobs) do
begin
with TBarSeries(Chart1.AddSeries(TBarSeries)) do
begin
Title := jobs[j].Title;
MultiBar := mbStacked;
Marks.Visible := False;
Marks.Style := smsValue;
end;
end;
// Populate series
for i:=0 to High(weekDays) do
begin
for j:=0 to High(jobs) do
Chart1[j].Add(GetValueFromJob(jobs[j], weekDays[i]), weekDays[i]);
end;
end;
And this is what I get with the example above:
- jobs.png (13.73 KiB) Viewed 25164 times