Can't say that I understood everything. Let me put it in my words: Suppose I am selling some articles. There are several article types, and I want to plot how many of each article are sold per month. So, I create a table: "Month" in the first column, "Article 1" in the 2nd column containing how many articles of type 1 are sold in each month, then "Article 2" in the next column, etc - one column for each article, and each cell contains the count of articles sold in that specific month.
Similar to this:
| Month | Article 1 | Article 2 | Article 3 |
| 2023-1 | 521 | 204 | 0 |
| 2023-2 | 626 | 375 | 0 |
| 2023-3 | 457 | 212 | 0 |
| 2023-4 | 385 | 164 | 0 |
| 2023-5 | 501 | 0 | 0 |
| 2023-6 | 645 | 0 | 0 |
| 2023-7 | 693 | 0 | 0 |
| 2023-8 | 663 | 0 | 101 |
| 2023-9 | 721 | 0 | 130 |
| 2023-10 | 634 | 0 | 285 |
| 2023-11 | 548 | 0 | 363 |
| 2023-12 | 574 | 0 | 381 |
Here, article 2 is no longer available after 2023-4. It still must be kept in the table with zero in the following cells. And article 3 is newly available in 2023-8; it cannot appear out of nothing, it must already be present in the months before that date with zero cells.
If you can reduce your application to this situation you can visualize it in a stacked bar chart: Each row is a data point, in the example we have 12 data points. Each column (after the date column) is a level in the stacked series, here we have 3 levels. Each level is a y value in the chart - we need 3 y values.
How to store the values? There are many ways to do it, let's put them into a TListChartSource which must be attached to the Source property of the bar series. At first we specify the number of y values: ListChartSource.YCount := 3 - this sets up a data point record with 1 x and 3 y values. Then call ListChartSource.AddXYList(x, [y1, y2, y3]) for the data of each month (you can add the month text as well):
ListChartSource1.YCount := 3;
ListChartSource1.AddXYList(EncodeDate(2023, 1,1), [521, 204, 0], '2024-1');
ListChartSource1.AddXYList(EncodeDate(2023, 2,1), [626, 375, 0], '2024-2');
ListChartSource1.AddXYList(EncodeDate(2023, 3,1), [457, 212, 0], '2024-3');
...
In order to assign individual colors to each y level you need a TChartStyles component which must be assigned to the Styles property of the series. Add a Style for each y level, in each style you can specify the brush for filling this part of the bar stack, and you can also assign a Text to be displayed in the legend. The following code creates a random color for each stack level:
ChartStyles1.Styles.Clear;
for i := 1 to ListChartSource1.YCount do
with ChartStyles1.Add do
begin
Brush.Color := Random($FFFFFF); // Create a random color
Pen.Color := Brush.Color;
Text := 'Article ' + IntToStr(i);
end;
See attached project which contains additional comments.
When later a new article is added you must increment the source's YCount. Basically, a zero should be added to the existing y values in the square bracket of the AddXYList call, but TAChart is tolerant enough when YCount is expanded - the missing field is assumed to be a zero. Of course new data must be entered with the new YCount then.