Table of Contents

Chart API (Delphi)

Note

This demo is available in your FlexCel installation at <FlexCel Install Folder>\Demo\Delphi\Modules\10.API\16.Chart API and also at https:​//​github.​com/​tmssoftware/​TMS-​FlexCel.​VCL-​demos/​tree/​master/​Delphi/​Modules/​10.​API/​16.​Chart API

Overview

Here we will show how to create a simple chart only with code. Note that as charts are complex and have many configuration options, the best way to find out how to create a particular chart is to create it in Excel, and then open it with APIMate. APIMate has full support for showing the chart API.

Concepts

Files

UChartAPI.pas

unit UChartAPI;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, UPaths,
  Dialogs, StdCtrls, FlexCel.VCLSupport, FlexCel.Core, FlexCel.XlsAdapter, FlexCel.Render,
  {$if CompilerVersion >= 23.0} System.UITypes, {$IFEND}
  ShellAPI;

type
  TFChartAPI = class(TForm)
    Memo1: TMemo;
    btnCreateFile: TButton;
    SaveDialog: TSaveDialog;
    procedure btnCreateFileClick(Sender: TObject);
  private
    procedure CreateFile;
    procedure AddData(const Xls: TExcelFile);
    procedure AddChart(const Xls: TExcelFile);
    procedure OpenFile(const Xls: TExcelFile);
  end;

var
  FChartAPI: TFChartAPI;

implementation
uses IOUtils, DateUtils;

{$IFNDEF FPC}
{$R *.dfm}
{$ENDIF}


procedure TFChartAPI.AddChart(const Xls: TExcelFile);
var
  ChartOptions1: IShapeProperties;
  Chart1: IExcelChart;
  Title: IDataLabel;
  TextFillOptions: IChartFillOptions;
  LabelTextOptions: IChartTextOptions;
  LabelOptions: TDataLabelOptions;
  ChartLineOptions: IChartLineOptions;
  ChartFillOptions: IChartFillOptions;
  Paragraphs: TArray<TDrawingTextParagraph>;
  ParagraphRuns: TArray<TDrawingTextRun>;
  TextAttributes: TDrawingTextAttributes;
  RunProperties: TDrawingTextProperties;
  TextFill: IFillStyle;
  ParagraphEndProperties: TDrawingTextProperties;
  LabelValue1: TDrawingRichString;
  PlotAreaFrame: IChartFrameOptions;
  PlotAreaPos: TChartPlotAreaPosition;
  Series: IChartSeries;
  SeriesFill: IChartSeriesFillOptions;
  SeriesLine: IChartSeriesLineOptions;
  AxisFont: TFlxChartFont;
  AxisLine: TAxisLineOptions;
  AxisTicks: TAxisTickOptions;
  AxisRangeOptions: TAxisRangeOptions;
  CatAxis: TBaseAxis;
  ValAxis: TBaseAxis;

  LastYear, Year: integer;
  shade: double;
  i, xf: integer;
  SeriesColor: TDrawingColor;
begin

  //Objects
  ChartOptions1 := TShapeProperties_Create;
  ChartOptions1.Anchor := TClientAnchor.Create(TFlxAnchorType.MoveAndResize, 1, 215, 1, 608, 30, 228, 17, 736);
  ChartOptions1.ShapeName := 'Lines of Code';
  ChartOptions1.Print := true;
  ChartOptions1.Visible := true;
  ChartOptions1.ShapeOptions.SetValue(TShapeOption.fLockText, true);
  ChartOptions1.ShapeOptions.SetValue(TShapeOption.LockRotation, true);
  ChartOptions1.ShapeOptions.SetValue(TShapeOption.fAutoTextMargin, true);
  ChartOptions1.ShapeOptions.SetValue(TShapeOption.fillColor, 134217806);
  ChartOptions1.ShapeOptions.SetValue(TShapeOption.wzName, 'Lines of code');
  Chart1 := xls.AddChart(ChartOptions1, TChartType.Area, TChartStyle.Create(102), false);

  Title := TDataLabel_Create();
  Title.PositionZeroBased := nil;

  TextFillOptions := TChartFillOptions_Create(TShapeFill_Create(TSolidFill_Create(TDrawingColor.FromRgb($80, $80, $80)), true, TFormattingType.Subtle, TDrawingColor.FromRgb($00, $00, $00, TColorTransformArray.Create(TColorTransform.Create(TColorTransformType.Alpha, 0))), false));
  LabelTextOptions := TChartTextOptions_Create(TFlxChartFont.Create('Calibri Light', 320, TExcelColor.FromArgb($80, $80, $80), [TFlxFontStyles.Bold], TFlxUnderline.None, TFontScheme.Major), THFlxAlignment.center, TVFlxAlignment.center, TBackgroundMode.Transparent, TextFillOptions);
  Title.TextOptions := LabelTextOptions;
  LabelOptions := TDataLabelOptions.Create();
  Title.LabelOptions := LabelOptions;
  ChartLineOptions := TChartLineOptions_Create(TShapeLine_Create(true, TLineStyle_Create(TNoFill_Create(), nil), nil, TFormattingType.Subtle));
  ChartFillOptions := TChartFillOptions_Create(TShapeFill_Create(TNoFill_Create(), false, TFormattingType.Subtle, nil, false));
  Title.Frame := TChartFrameOptions_Create(ChartLineOptions, ChartFillOptions, false);

  SetLength(Paragraphs, 1);
  SetLength(ParagraphRuns, 1);
  TextAttributes := TDrawingTextAttributes.Create(nil, 'en-US', '', 1600, TRUE, nil,
     NullableTDrawingUnderlineStyle.Null, NullableTDrawingTextStrike.Null, nil,
     NullableTDrawingTextCapitalization.Null, NullableTDrawingCoordinate.Null,
     nil, nil, nil, false, false, false, 0, '');
  TextFill := TSolidFill_Create(TDrawingColor.FromRgb($80, $80, $80));
  RunProperties := TDrawingTextProperties.Create(TextFill,
      nil,
      nil,
      nil,
      TDrawingUnderline.Null,
      TThemeTextFont.Create('Calibri Light'),
      nil,
      nil,
      nil,
      TDrawingHyperlink.Null,
      TDrawingHyperlink.Null,
      false,
      TextAttributes);

  ParagraphRuns[0] := TDrawingTextRun.Create('FlexCel: Lines of code over time', RunProperties);
  ParagraphEndProperties := TDrawingTextProperties.Create(nil, TDrawingTextAttributes.Empty);
  Paragraphs[0] := TDrawingTextParagraph.Create(ParagraphRuns, TDrawingParagraphProperties.Empty, ParagraphEndProperties);

  LabelValue1 := TDrawingRichString.Create(Paragraphs);

  Title.LabelValues := TArray<TDrawingValue>.Create(
    LabelValue1
  );

  Chart1.SetTitle(Title);

  Chart1.Background := TChartFrameOptions_Create(TDrawingColor.FromTheme(TThemeColor.Dark1, TColorTransformArray.Create(TColorTransform.Create(TColorTransformType.LumMod, 0.15), TColorTransform.Create(TColorTransformType.LumOff, 0.85))), 9525, TDrawingColor.FromTheme(TThemeColor.Light1), false);

  ChartLineOptions := TChartLineOptions_Create(TShapeLine_Create(true, TLineStyle_Create(TNoFill_Create(), nil), nil, TFormattingType.Subtle));
  ChartFillOptions := TChartFillOptions_Create(TShapeFill_Create(TPatternFill_Create(TDrawingColor.FromTheme(TThemeColor.Dark1, TColorTransformArray.Create(TColorTransform.Create(TColorTransformType.LumMod, 0.15), TColorTransform.Create(TColorTransformType.LumOff, 0.85))), TDrawingColor.FromTheme(TThemeColor.Light1), TDrawingPattern.ltDnDiag), true, TFormattingType.Subtle, nil, false));
  PlotAreaFrame := TChartFrameOptions_Create(ChartLineOptions, ChartFillOptions, false);
  PlotAreaPos := TChartPlotAreaPosition.Create(true, TChartRelativeRectangle.Automatic, TChartLayoutTarget.Inner, true);
  Chart1.PlotArea := TChartPlotArea_Create(PlotAreaFrame, PlotAreaPos, false);

  Chart1.SetChartOptions(1, TAreaChartOptions_Create(false, TStackedMode.Stacked, nil));

  LastYear := 0;
  shade := 1;
  for i := 2 to 189 do
  begin


    Series := TChartSeries_Create(
               '=' + TCellAddress.Create('Data', 1, i, true, true).CellRef,
               '=' + TCellAddress.Create('Data', 2, i, true, true).CellRef + ':' + TCellAddress.Create('Data', 189, i, true, true).CellRef,
               '=Data!$A$2:$A$189');

    //We will display every year in a single color. Each month gets its own shade.
    xf := -1;
    Year := YearOf(TFlxDateTime.FromOADate((xls.GetCellValue(2, 1, i, xf).AsNumber), false));
    if (LastYear <> Year) then shade := 1 else if (shade > 0.3) then shade := shade - 0.05;
    LastYear := Year;
    SeriesColor := TDrawingColor.FromTheme(TThemeColor(integer(TThemeColor.Accent1) + Year mod 6),
                    TColorTransformArray.Create(TColorTransform.Create(TColorTransformType.Shade, shade)));

    SeriesFill := TChartSeriesFillOptions_Create(TShapeFill_Create(TSolidFill_Create(SeriesColor), true, TFormattingType.Subtle, nil, false), nil, false, false);
    SeriesLine := TChartSeriesLineOptions_Create(TShapeLine_Create(true, TLineStyle_Create(TNoFill_Create(), nil), nil, TFormattingType.Subtle), false);
    Series.Options.Add(TChartSeriesOptions.CreateNoClone(-1, SeriesFill, SeriesLine, nil, nil, nil, true));
    Chart1.AddSeries(Series);
  end;

  Chart1.PlotEmptyCells := TPlotEmptyCells.Zero;
  Chart1.ShowDataInHiddenRowsAndCols := false;


  AxisFont := TFlxChartFont.Create('Calibri', 180, TExcelColor.FromArgb($59, $59, $59), [], TFlxUnderline.None, TFontScheme.Minor);
  AxisLine := TAxisLineOptions.Create();
  AxisLine.MainAxis := TChartLineOptions_Create(TShapeLine_Create(true, TLineStyle_Create(TSolidFill_Create(TDrawingColor.FromTheme(TThemeColor.Dark1, TColorTransformArray.Create(TColorTransform.Create(TColorTransformType.LumMod, 0.15), TColorTransform.Create(TColorTransformType.LumOff, 0.85)))), 9525, TPenAlignment.Center, TLineCap.Flat, TCompoundLineType.Single, NullableTLineDashing.Null, TLineJoin.Round, nil, nil, nil), nil, TFormattingType.Subtle));
  AxisLine.DoNotDrawLabelsIfNotDrawingAxis := false;
  AxisTicks := TAxisTickOptions.Create(TTickType.Outside, TTickType.None, TAxisLabelPosition.NextToAxis, TBackgroundMode.Transparent, TDrawingColor.FromRgb($59, $59, $59), 0);
  AxisRangeOptions := TAxisRangeOptions.Create(12, 1, false, false, false);
  CatAxis := TCategoryAxis.Create(0, 0, 12, TDateUnits.Days, 12, TDateUnits.Days, TDateUnits.Months, 0, [TCategoryAxisOptions.AutoMin, TCategoryAxisOptions.AutoMax, TCategoryAxisOptions.DateAxis, TCategoryAxisOptions.AutoCrossDate, TCategoryAxisOptions.AutoDate], AxisFont, 'yyyy\-mm\-dd;@', true, AxisLine, AxisTicks, AxisRangeOptions, nil, TChartAxisPos.Bottom, 1);
  AxisFont := TFlxChartFont.Create('Calibri', 180, TExcelColor.FromArgb($59, $59, $59), [], TFlxUnderline.None, TFontScheme.Minor);
  AxisLine := TAxisLineOptions.Create();
  AxisLine.MainAxis := TChartLineOptions_Create(TShapeLine_Create(true, TLineStyle_Create(TSolidFill_Create(TDrawingColor.FromTheme(TThemeColor.Dark1, TColorTransformArray.Create(TColorTransform.Create(TColorTransformType.LumMod, 0.15), TColorTransform.Create(TColorTransformType.LumOff, 0.85)))), 9525, TPenAlignment.Center, TLineCap.Flat, TCompoundLineType.Single, NullableTLineDashing.Null, TLineJoin.Round, nil, nil, nil), nil, TFormattingType.Subtle));
  AxisLine.MajorGridLines := TChartLineOptions_Create(TShapeLine_Create(true, TLineStyle_Create(TSolidFill_Create(TDrawingColor.FromTheme(TThemeColor.Dark1, TColorTransformArray.Create(TColorTransform.Create(TColorTransformType.LumMod, 0.15), TColorTransform.Create(TColorTransformType.LumOff, 0.85)))), 9525, TPenAlignment.Center, TLineCap.Flat, TCompoundLineType.Single, NullableTLineDashing.Null, TLineJoin.Round, nil, nil, nil), nil, TFormattingType.Subtle));
  AxisLine.DoNotDrawLabelsIfNotDrawingAxis := false;
  AxisTicks := TAxisTickOptions.Create(TTickType.None, TTickType.None, TAxisLabelPosition.NextToAxis, TBackgroundMode.Transparent, TDrawingColor.FromRgb($59, $59, $59), 0);
  ValAxis := TValueAxis.Create(0, 0, 0, 0, 0, [TValueAxisOptions.AutoMin, TValueAxisOptions.AutoMax, TValueAxisOptions.AutoMajor, TValueAxisOptions.AutoMinor, TValueAxisOptions.AutoCross], AxisFont, 'General', true, AxisLine, AxisTicks, nil, TChartAxisPos.Left);
  Chart1.SetChartAxis(TChartAxis_Create(0, CatAxis, ValAxis));

end;

procedure TFChartAPI.AddData(const Xls: TExcelFile);
begin
  //Add a new empty sheet for adding the chart.
  Xls.InsertAndCopySheets(0, 1, 1);
  Xls.ActiveSheet := 1;
  Xls.SheetName := 'Chart';
  Xls.PrintToFit := true;
  Xls.PrintScale := 70;
  Xls.PrintXResolution := 600;
  Xls.PrintYResolution := 600;
  Xls.PrintOptions := [];
  Xls.PrintPaperSize := TPaperSize.Letter;
  Xls.PrintLandscape := true;

  AddChart(Xls);

end;

procedure TFChartAPI.btnCreateFileClick(Sender: TObject);
begin
   CreateFile;
end;


procedure TFChartAPI.CreateFile;
var
  Xls: TExcelFile;
begin
  Xls := TXlsFile.Create(TPath.Combine(DataFolder, 'git-stats.xlsx'), true);

  try
    AddData(Xls);
    OpenFile(Xls);
  finally
    FreeAndNil(Xls);
  end;
end;

procedure TFChartAPI.OpenFile(const Xls: TExcelFile);
begin
  if not SaveDialog.Execute then exit;
  Xls.Save(SaveDialog.FileName);

  if MessageDlg('Do you want to open the generated file?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  begin
    ShellExecute(0, 'open', PCHAR(SaveDialog.FileName), nil, nil, SW_SHOWNORMAL);
  end;
end;

end.