Page 1 of 1

Display a TPointSeries when X axis is showing Date values

Posted: Wed Jan 19, 2005 6:21 pm
by 4209833
I am having some trouble getting a TPointSeries to display properly when the other line series on a chart are showing Date values on the XAxis.

I am using the code below to add the line series values:

// populate the chart here too
int date = ds->getDate(i);
int year = date / 10000;
int month = (date - (year * 10000)) / 100;
int day = date - (year * 10000) - (month *100);
// set the date as the label separately so we will not display weekends (i.e. gaps)
int pos = lineSeries->AddXY(i, closes->getValue(i));
AnsiString dateLabel = DateToStr(EncodeDate((Word)year, (Word)month, (Word)day));
lineSeries->Labels->Labels[pos] = dateLabel;

This code is designed to stop weekends from disrupting my data - so the chart looks as if there are five days in a week, with no 'gaps' for weekends.

I then am trying to add corresponding points into a PointSeries using the combinations below:

int pos = pointSeries->AddXY(x, y); // where x counts up from zero
pointSeries->Labels->Labels[pos] = dateLabel;

dateLabel holds the results of DateToStr(EncodeDate(year,month,day) as done for the original line series.

This causes my new points to be added at the start of my series. I also tried replacing the first parameter to AddXY with the return from EncodeDate but that also does not work. I think I need to be able to work out for a given date, which point that corresponds to in the lineSeries ?

Or is there an easier way of doing this. I have the code working fine when I am displaying times on the XAxis, because there is no need to worry about weekends then and the lineSeries->AddXY() takes the encoded time as the first parameter and I can do the same for the AddXY() call for the point series in this case.

Thanks

Stew

Posted: Tue Feb 01, 2005 10:32 am
by Marjan
Hi.
first parameter to AddXY with the return from EncodeDate but that also does not work.
This won't work because your x values are 0,1,2,3,...
Or is there an easier way of doing this.
I think not. But I'd use slightly different approach. First, make an array of all non-weekend datetimes. Then generate bottom axis custom labels from this array -> end result is chart with correct (no weekends) labels. Now all you have to do is match point (real) datetime value with correct value in the array. Basically, use matched array index as x parameter in AddXY method call. Here is Delphi example. A similar approach can be used for BCB and even for TeeChart .NET (C#).

Code: Select all

  private
    { Private declarations }
    ValidDates: Array [0..100] of TDate;
    DateCount : Integer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  // generate dates ... you can get this from sql, etc...
  DateCount := 15;
  ValidDates[0] := EncodeDate(2005,1,31);
  ValidDates[1] := EncodeDate(2005,2,1);
  ValidDates[2] := EncodeDate(2005,2,2);
  ValidDates[3] := EncodeDate(2005,2,3);
  ValidDates[4] := EncodeDate(2005,2,4);
  ValidDates[5] := EncodeDate(2005,2,7);
  ValidDates[6] := EncodeDate(2005,2,8);
  ValidDates[7] := EncodeDate(2005,2,9);
  ValidDates[8] := EncodeDate(2005,2,10);
  ValidDates[9] := EncodeDate(2005,2,11);
  ValidDates[10] := EncodeDate(2005,2,14);
  ValidDates[11] := EncodeDate(2005,2,15);
  ValidDates[12] := EncodeDate(2005,2,16);
  ValidDates[13] := EncodeDate(2005,2,17);
  ValidDates[14] := EncodeDate(2005,2,18);

  // populate bottom axis with labels
  // in this example user every 3rd label
  Chart1.Axes.Bottom.Items.Clear;
  for i := 0 to DateCount-1 do
    if i mod 3 = 0 then
      Chart1.Axes.Bottom.Items.Add(i,DateToStr(ValidDates[i]));
  Chart1.Axes.Bottom.SetMinMax(0,DateCount-1);
end;

function FindMatch(value: TDate; pool: Array of TDate; Const lo_bound, hi_bound: Integer): Integer;
var i: Integer;
begin
  Result := -1;
  for i := lo_bound to hi_bound do
    if value=pool[i] then
    begin
      Result := i;
      break;
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var xvals: Array[0..3] of TDate;
    yvals: Array[0..3] of double;
    i, xind: Integer;
begin
  // this is only sample array (example)
  xvals[0] := EncodeDate(2005,2,9);
  yvals[0] := 5.2;
  xvals[1] := EncodeDate(2005,2,10);
  yvals[1] := 3.1;
  xvals[2] := EncodeDate(2005,2,15);
  yvals[2] := 2.5;
  xvals[3] := EncodeDate(2005,2,16);
  yvals[3] := 7;

  // Add points to series
  // Note that points have real date x values =>
  // you have to map each value to internal index array
  for i := 0 to 3 do
  begin
    xind := FindMatch(xvals[i],ValidDates,0,DateCount-1);
    if xind <> -1 then Series1.AddXY(xind,yvals[i]);
  end;
end;
The above example demonstrates one way to do the no-weekends charting. Three basic steps:
1) generate an array of all valid dates
2) populate axis labels
3) populate series where point x value is mapped from valid dates array.