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
How you can use TExcelFile.AddChart, IExcelChart.AddSeries and other commands to create a simple chart.
The chart API works only in xlsx files, so this demo wouldn't work with xls files.
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.