Series manipulation

This chapter documents how to manipulate Series and how to manipulate Series points and other Series internal data.

Note: Advanced. Series and values code is mainly located at TEENGINE.PAS unit.

Topics in this section:

Creating Series at runtime

SeriesList Collection

SeriesCount property

Deleting Series

Changing the Series Z order at runtime

Adding Points

Adding arrays of data

Null Values

Controlling Points Order

XY Points

Point Limits

Series Points

Retrieving and modifying Points

Locating Points

Point Statistics

Notifications

Point Colours

Point Labels

Changing the Series type at runtime - Advanced

Creating Series at runtime.

Series can be created at runtime just as like any other Delphi component:

First you need a Series variable:

Var MySeries : TBarSeries ;

{Then create the component:}

MySeries := TBarSeries.Create( Self );

{And then assign it to the desired Chart component:}

MySeries.ParentChart := Chart1 ;

{Now you can add points to MySeries or do whatever you can do with a design-time created Series.}

Shortcut:

{If you don’t need access to MySeries, the above code can be reduced to just one line of code:}

Chart1.AddSeries( TBarSeries.Create( Self ) );

{Class references:

Or you can use a Series class reference:

First declare the Series class variable:}

Var MyClass : TChartSeriesClass;

{Then set the desired Series class type:}

MyClass := TBarSeries ;

{Now you can create the Series component:}

Chart1.AddSeries( MyClass.Create( Self ) );

SeriesList collection

Chart components store all Series in SeriesList property, a Delphi TList object.

You have read-only access to this list in three ways:

A) Using the SeriesList property:

MySeries := Chart1.SeriesList [ 0 ]

B) Using the Series array property:

MySeries := Chart1.Series [ 0 ]

C) Or using the Chart1 default property:

MySeries := Chart1 [ 0 ]

Either way does the same.

SeriesCount property

The Chart1.SeriesCount property returns the number of Series in the SeriesList.

You can use SeriesCount to traverse all Chart Series:

for t := 0 to Chart1.SeriesCount - 1 do
With Chart1.Series [ t ] do 
begin
   SeriesColor := clBlue ;
end;

Deleting Series

Series can be hidden in three ways:

A) Setting the Series Active property:

Series1.Active := False ;

B) Removing the Series from their parent Chart:

Series1.ParentChart := nil;

C) Destroying the Series completely:

Series1.Free ;

Changing the Series Z order at runtime.

In 3D mode (when Chart1.View3D is True ), all Series are assigned a Z order position. That is, the order where Series will be drawn, starting with the far most Series on the Chart 3D space.

You can control the order Series will be drawn, using these methods:

Chart1.ExchangeSeries( 0, 1 );

or...

Chart1.SeriesUp( Series1 );
Chart1.SeriesDown( Series1 );

The Series.ZOrder integer property returns the corresponding Z position for the Series.

Some Series in certain modes share the same ZOrder, like Stacked BarSeries. You can check if more than one Series has the same Z order using these functions:

if Series1.FirstInZOrder then .....
if Series1.MoreSameZOrder then .....

Adding Points

Every Series type has, at least, 2 values for each point. These values are designed as X and Y point co-ordinates.

Note: Values are defined as “Double” floating point variables.

Extended Series types have more than 2 values, like BubbleSeries has X, Y and Radiusvalues for each point.

So, each Series type has its appropriate method to add points, although the most common Series types like Line, Bar, Point and Area share the generic AddY method to add points.

The following code empties a TPieSeries and adds some sample values to it:

Series1.Clear ;

    Series1.Add(  1234, ‘USA’, clBlue );
    Series1.Add(  2001, ‘Europe’, clRed );

For extended Series types, please refer to each specific Series reference to know which method should be used to add points.

The Series AddArray method can be used in some situations:

Series3.Clear;

    Series3.AddArray([ 1234, 2001, 4567.12 ] );

AddArray does not Clear the Series before adding points.

You can express points as constants or variables:

Series3.AddArray([ Table1Sales.AsFloat, 123, MyTotal ] );

Adding arrays of data

To add an array of data to a Chart Series simply allocate the array to the Series.

Example

procedure TDynArrays.Button1Click(Sender: TObject);
Var X,Y : Array of Double;   // TChartValues
    t   : Integer;
    Num : Integer;
begin
  { number of points here using an Editbox to set Array size}
  Num:=StrToInt(Edit1.Text);

  { allocate our custom arrays }
  SetLength(X,Num);
  SetLength(Y,Num);

  { fill data in our custom arrays }
  X[0]:=0;
  Y[0]:=Random(10000);
  for t:=1 to Num-1 do
  begin
    X[t]:=t;
    Y[t]:=Y[t-1]+Random(101)-50;
  end;

  { set our X array }
  With Series1.XValues do
  begin
    Value:=TChartValues(X);  { <-- the array }
    Count:=Num;               { <-- number of points }
    Modified:=True;           { <-- recalculate min and max }
  end;

  { set our Y array }
  With Series1.YValues do
  begin
    Value:=TChartValues(Y);
    Count:=Num;
    Modified:=True;
  end;

  Chart1.UndoZoom; { <-- remove zoom (optional) }

  { Show data }
  Series1.Repaint;
end;

Null Values

In some circumstances you might have no values for specific points. You should then add these points as “zero” or add them as “null” values.

Null values will not be displayed, while “zero” values will be displayed as usual.

The following code adds several points and a null point:

With Series1 do
begin
  Clear ;
  AddY( 10, ‘John’, clGreen );
  AddY( 20, ‘Anne’, clYellow );
  AddY( 15, ‘Thomas’, clRed );
  AddNull( ‘Peter’ );
  AddY( 25, ‘Tony’, clBlue );
  AddY( 20, ‘Mike’, clLime );
end;

Each Series type will handle null values in different ways.

Bar, HorizBar, Line, Area and Point do not display null points.

PieSeries use null values as “zero”.

Controlling Points Order

Points can be optionally sorted either by their X values or Y values. The Series.XValues and Series.YValues Order property controls the points Order:

Series1.XValues.Order := loAscending ;

Possible values are: loNone, loAscending or loDescending.

By default, XValues Order is set to loAscending, and YValues Order to loNone, which means new added points are ordered by their X co-ordinate. For non XY Charts, the X co-ordinate is always the point position, starting from zero.

The point Order is used by Series components to draw their points.

Note: Order must be set before points are added to the Series.

You can change the Order property at run-time, followed by a call to Sort method:

Example:

Drop a TChart onto a Form, add a Line Series.

Drop a TButton and assign this code to Button1Click:

Series1.AddArray([ 5, 2, 3, 9]);

Now drop another TButton and add this code to Button2Click:

With Series1 do
begin
    YValues.Order:=loAscending;
    YValues.Sort;
    Repaint;
end;

Now execute and press Button1 to fill Series1, and press Button2 to see Series1 points drawn on Series1 YValues Ascending order, but having the original X co-ordinates.

Note: If you aren’t using X co-ordinates, one more line of code is required.

Drop a new TButton (Button3) and add this code to Button3Click:

Series1.XValues.FillSequence;
Series1.Repaint;

Now points will be “re-numbered”, starting from zero among Series1 XValues axis. This will re-order points so now they will be drawn as if they were originally added to the Series in their new order.

This “two-step” point sorting allows Line Series to draw with vertical orientation.

XY Points

Adding X co-ordinates to points makes Series components calculate user specific horizontal point positions.

Note: Bar Charts can be difficult to interpret with X co-ordinates.

Pie Series do not allow X co-ordinates.

To add X co-ordinates, simply use the AddXY method:

Drop a TChart, add a Point Series:

With Series1 do
begin
  Clear ;
  AddXY(  10, 10, ‘Barcelona’, clBlue );
  AddXY(  1, 10, ‘San Francisco’, clRed );
end;

Note: If you use a Bubble Series, use the TBubbleSeries AddBubble method.

Remember to set XValues.Order to loNone if don’t want points to be sorted on their X co-ordinate.

Point Limits

Maximum number of points per Series and Series per Chart limited on available memory.

Deleting Points

Simply call the Series.Delete method, passing the point index as the argument. Point index starts at zero.

Series1.Delete( 0 );  { <-- removes the first point in Series1 }
Series1.Delete( Series1.Count - 1 ) ;  { <-- removes the last point in Series1 }

An exception “List out of bounds” will be raised when attempting to Delete a non-existing point, so always check there are enough points in the Series prior to delete them:

if Series1.Count > MyIndex then Series1.Delete( MyIndex );

Calling Delete forces re-calculation of Functions and repainting of the Chart.

Series Points

Retrieving and modifying Points

Once points have been added, you can retrieve their co-ordinates or change them.

The XValues and YValues array properties can be used:

Var MyValue : Double ;

MyValue := Series1.YValues[ 0 ] ; { <-- retrieves the first Y value }

You can traverse these arrays to perform calculations:

Var MyTotal : Double ;

        t : Integer ;

    MyTotal := 0 ;
    for t:= 0 to Series1.Count - 1 do
        MyTotal := MyTotal + Series1.YValues[ t ] ;

    ShowMessage( FloatToStr( MyTotal ) );

Extended Series types have additional array properties, such as

BubbleSeries RadiusValues. You can access these properties in

the same way as with XValues or YValues arrays:

if BubbleSeries1.RadiusValues[ Index ] > 100 then .....

Modifying point values can be performed using the above properties:

Series1.YValues[ 0 ] := Series1.YValues[ 0 ] + 1 ;

    Series1.RefreshSeries ;

Locating Points

The XValues and YValues Locate function searches a specific

value in the List and, if found, returns the value Index, starting

from zero.

Var MyIndex : Integer ;

    MyIndex := Series1.YValues.Locate( 123 );

    if MyIndex = -1 then 
      ShowMessage(‘  123 not found in Series1 !! ‘ )
    else
       ShowMessage(‘  123 is the ‘+IntToStr( MyIndex+1 )+’ th point in Series1 !! ‘ );

Point Statistics

XValues and YValues properties maintain the following statistical figures:

TotalThe sum of all values in the list.

TotalABSThe sum of all values as absolute (positive).

MaxValueThe maximum value in the list.

MinValueThe minimum value in the list.

You can call manually to RecalcMinMax method to recalculate MinValue and MaxValue. Total and TotalABS are maintained automatically.

These values are used to speed up several Axis scaling calculations and are used as helpers for percent calculations.

TChartValueList object has several other methods and properties to manipulate point values. Please refer to online help documentation.

Notifications

Whenever points are added, deleted or modified, the Series generates internal notification events. These events are used to recalculate Series that depend on other Series points.

Advanced: You can use RecalcOptions property to control when recalculations are performed.

Point Colours

All Series maintain an internal List of colours. One for each point in the Series.

You can access this list with ValueColor array property, to retrieve or change point colours:

Var MyColor : TColor ;

    MyColor := Series1.ValueColor[ 0 ] ;

    Series1.ValueColor[ 1 ] := clBlue ;

TeeChart defines a generic colour constant named: clTeeColor.

Points with clTeeColor colour will be drawn using the SeriesColor colour.

Delphi predefines constants for basic colours (clBlue, clRed, etc.). Colours can also be expressed in RGB format. Using a video colour depth of 16k colours or more results in better colour matching.

Point Labels

Each point has an associated text, called XLabel, and declared as a Delphi string.

Point Labels are used in Axis Labels, Chart Legend and Point Marks.

Labels are stored at Series XLabel array property.

You can access and modify XLabel point texts:

Series1.XLabel [ 0 ] := ‘Sales’ ;

Changing the Series type at runtime - Advanced

Every Chart type corresponds to a different Delphi Component.

Changing a Series type involves changing the Series component class.

That means a new Series of the new class must be created, old Series properties should be assigned to the new instance, and finally the old Series must be destroyed.

All this happens automatically when you manually change a Series type at design-time using the Chart Editor Dialog and the Gallery.

You can change a Series type at run-time calling:

ChangeSeriesTypeGallery(Self, MySeries );

Warning:

You should change your private Series components.

You can change also Series components owned by the Form,

but only if not using them after.

Var MySeries : TChartSeries ;
MySeries := Series1 ;
ChangeSeriesTypeGallery(Self, MySeries );