Testing your demo I do not see a speed improvement when the NavPanel is gone.
The issue is something very simple, and we had this topic several times recently in the forum: when the Canvas.Pen.Width is >1 a severe speed loss is observed in Windows (due to "cosmetic" and "geometric" pen style optimizations in the API). While not noticable with "normal-sized" plots it becomes very dramatic with large datasets as in your case. So, just setting "ls.LinePen.Width := 1" in AcPlotFromGridExecute does the job.
You can also speed up populating the chart series when you put a "ls.ListSource.BeginUpdate" and "ls.ListSource.EndUpdate" around the "i" loop in AcPlotFromGridExecute. With this change the file reads in 0.46 s instead of 1.21 s.
To make the data file readable also in other countries (I could not read your data file at first) you should also take care of the DateSeparator and the year-month-day order in ShortDateFormat. Instead of touching DefaultFormatSettings I usually introduce a local TFormatSettings variable which defaults to DefaultFormatSettings and changes the elements needed, and is passed to the string conversion function as last parameter. This way the format settings of the OS are retained and the user can work with his standard format settings.
In order to visualize the zoomed range within the entire data range you can also use a TChartNavScrollBar, instead of the TChartNavPanel.
procedure TForm1.AcPlotfromGridExecute(Sender: TObject);
var
colnumber: Integer;
rownumber: integer;
ls: Tlineseries;
x: TDateTime;
y: double;
i, n: integer;
fs: TFormatSettings; // <------ added
begin
// <---- added
fs := DefaultFormatSettings;
fs.DecimalSeparator := '.';
fs.DateSeparator := '/';
fs.ShortDateFormat := 'dd/mm/yyyy';
// ------- end addition ------>
colnumber := StringGrid1.ColCount;
rownumber := StringGrid1.RowCount;
for i := 1 to colnumber-1 do
begin
ls := Tlineseries.Create(Chart1);
chart1.addSeries(ls);
ls.Title := StringGrid1.Cells[i, 0];
ls.SeriesColor:= RGBToColor(Random(256), Random(256), Random(256));
ls.LinePen.Width := 1; // <--- changed from 2 to 1.
ls.Pointer.Style := psCircle;
ls.ShowPoints:= true;
ls.Pointer.Visible := false; // <----------- This reverts the previous line. ShowPoints and Pointer.Visible are the same!
//ls.Marks.Style:= smsLabel;
ls.Marks.Visible := False;
ls.ZPosition := colnumber-1-i;
ls.ListSource.BeginUpdate; // <-------- added
for n := 1 to Rownumber-1 do
begin
if TryStrToDateTime(StringGrid1.Cells[0, n], x, fs) then
begin
if not TryStrToFloat(StringGrid1.Cells[i, n], y, fs) then
y := NaN;
end;
ls.AddXY(x, y);
end;
ls.ListSource.EndUpdate; // <-------- added
end;
end;
To avoid double storage of values as floating point numbers in the chart's source and as strings in the grid you could introduce an array or list of records (or objects) resembling the native data and use a TUserDefinedChartSource to pass these data to the series. And you could use a TDrawGrid instead of a TStringGrid to display the data values; this will also speed up populating the grid dramatically.
I am attaching a modified version of your demo in which a UserDefinedChartSource and a DrawGrid are used.