Failed to Create Multiple Chart Series on Clustered Column Chart in Node.js

Hi team, I have requirement where I need multiple category axis points. I’ve attached the screenshot for reference.
image.png (2.2 KB)

I’m adding both the category axis data and values axis data using the getChartDataWorkbook method. The value axis data is getting loaded properly but the category axis data is not getting displayed properly in the chart output.
At first it shows only one category axis data point like the screenshot attached below.
image.png (14.6 KB)

Once I open the chart work book using the edit data options both the category axis data gets displayed properly.
image.png (36.9 KB)

I’m using the below code to prepare the chart.

 "data": {
            "categories": [
             [
              "2021-new",
              "2022-new",
              "2023-new",
              "2024-new"
             ],
             [
              "Warehouse-new",
              "Warehouse-new",
              "Warehouse-new",
              "Warehouse-new"
             ]
            ],
            "series": [
              {
                "name": "Average of renewable rate",
                "values": [
                  0.18,
                  0.70,
                  0.50,
                  0.30
                ]
              },
              {
                "name": "Average of expiring rate",
                "values": [
                  0.2,
                  1,
                  0.5,
                  0.75
                ]
              }
            ]
          },
"config": {
            "chartTitle": "Test Title",
            "multipleCategory": true
          }
 const chartDataObject = placeHolder.data as IChartData;
  const chartData = shape.getChartData();
  const chartCategory = chartData.getCategories();
  const fact = chartData.getChartDataWorkbook();

  chartDataObject.categories.forEach((category: any, categoryIndex: number) => {
      category.forEach((ele: any, elementIndex: number) => {
        chartData.getCategories().add(fact.getCell(0, elementIndex + 1, categoryIndex, ele));
      }) 
  });

 const chartDataObject = placeHolder.data as IChartData;
  const chartData = shape.getChartData();
  const chartSeries = chartData.getSeries();
  const fact = chartData.getChartDataWorkbook();
  const columnType = shape.getType();
  const columnShift = placeHolder?.config?.multipleCategory ? chartDataObject.categories.length - 1 : 0;

  chartDataObject.series.forEach((ele, seriesIndex) => {
    chartSeries.add(fact.getCell(0, 0, seriesIndex + 1 + columnShift, ele.name), columnType);
    const series = chartSeries.get_Item(seriesIndex);
    series.setInvertIfNegative(false);
    ele.values.forEach((value, valueIndex) => {
      const dataPoint = series
        .getDataPoints()
        .addDataPointForBarSeries(
          fact.getCell(0, valueIndex + 1, seriesIndex + 1 + columnShift, value ? value : 0)
        );
    });
  });

@karanmarsh,
Thank you for posting your requirements. I am working on the issue and will get back to you soon.

@karanmarsh,
Unfortunately, I cannot use your code snippet to reproduce the problem you described. Could you please share a complete standalone code example and presentation file you used?

Hi @andrey.potapov
Here is the full code snippet
consider the shape as that chart

 shape.getChartData().getSeries().clear();
  shape.getChartData().getCategories().clear();
  const chartDataObject = 
  {
            categories: [
             [
              "2021-new",
              "2022-new",
              "2023-new",
              "2024-new"
             ],
             [
              "Warehouse-new",
              "Warehouse-new",
              "Warehouse-new",
              "Warehouse-new"
             ]
            ],
            series: [
              {
                name: "Average of renewable rate",
                values: [
                  0.18,
                  0.70,
                  0.50,
                  0.30
                ]
              },
              {
                name: "Average of expiring rate",
                values: [
                  0.2,
                  1,
                  0.5,
                  0.75
                ]
              }
            ]
          }
        
  const chartData = shape.getChartData();
  const fact = chartData.getChartDataWorkbook();

  chartDataObject.categories.forEach((category: any, categoryIndex: number) => {
      category.forEach((ele: string, elementIndex: number) => {
        chartData.getCategories().add(fact.getCell(0, elementIndex + 1, categoryIndex, ele));
      })
  });

  const chartSeries = chartData.getSeries();
  const columnType = shape.getType();
  const columnShift = chartDataObject.categories.length - 1;

  chartDataObject.series.forEach((ele, seriesIndex) => {
    chartSeries.add(fact.getCell(0, 0, seriesIndex + 1 + columnShift, ele.name), columnType);
    const series = chartSeries.get_Item(seriesIndex);
    series.setInvertIfNegative(false);
    ele.values.forEach((value, valueIndex) => {
      const dataPoint = series
        .getDataPoints()
        .addDataPointForBarSeries(
          fact.getCell(0, valueIndex + 1, seriesIndex + 1 + columnShift, value ? value : 0)
        );
    });
  });

@karanmarsh,
Thank you for the code example. I am working on the issue and will get back to you soon.

@karanmarsh,
Thank you for your patience. I’ve reproduced the problem you described.

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): SLIDESNODEJS-65

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

@karanmarsh,
Our developers have investigated the case. Please try using the following code snippet:

shape.getChartData().getSeries().clear();
shape.getChartData().getCategories().clear();

workbook = shape.getChartData().getChartDataWorkbook();
workbook.clear(0);

const chartDataObject = 
  {
            categories: [
             [
              "2021-new",
              "2022-new",
              "2023-new",
              "2024-new"
             ]
            ],
            secondLvlCategory: 
            [
             [
              "Warehouse-new",
              "Warehouse-new",
              "Warehouse-new",
              "Warehouse-new"
             ]
            ],
            series: [
              {
                name: "Average of renewable rate",
                values: [
                  0.18,
                  0.70,
                  0.50,
                  0.30
                ]
              },
              {
                name: "Average of expiring rate",
                values: [
                  0.2,
                  1,
                  0.5,
                  0.75
                ]
              }
            ]
          };

  const chartData = shape.getChartData();
  const fact = chartData.getChartDataWorkbook();
  const categoryStartIndex = 1;

  chartDataObject.categories.forEach((category) => {
      category.forEach((ele, elementIndex) => {
        chartData.getCategories().add(fact.getCell(0, elementIndex + 1, categoryStartIndex, ele));
      });
  });

  chartDataObject.secondLvlCategory.forEach((category) => {
      category.forEach((ele, elementIndex) => {
        chartData.getCategories().get_Item(elementIndex).getGroupingLevels().setGroupingItem(1, ele);
      });
  });

  const chartSeries = chartData.getSeries();
  const columnType = shape.getType();
  const columnShift = chartDataObject.categories.length - 1 + categoryStartIndex;

  chartDataObject.series.forEach((ele, seriesIndex) => {
    chartSeries.add(fact.getCell(0, 0, seriesIndex + 1 + columnShift, ele.name), columnType);
    const series = chartSeries.get_Item(seriesIndex);
    series.setInvertIfNegative(false);
    ele.values.forEach((value, valueIndex) => {
      const dataPoint = series
        .getDataPoints()
        .addDataPointForBarSeries(
          fact.getCell(0, valueIndex + 1, seriesIndex + 1 + columnShift, value ? value : 0)
        );
    });
  });

Hi @andrey.potapov,

Whist this solution is working I want to know how I can scale this. How do I add third level category and forth level category. What is the meaning of this line. How does it work ?

chartData.getCategories().get_Item(elementIndex).getGroupingLevels().setGroupingItem(1, ele);

@karanmarsh,
Thank you for posting the questions.

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): SLIDESNODEJS-66

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

Hi @andrey.potapov

any update on this ?

@karanmarsh,
We are working on your questions and will get back to you as soon as possible.

@karanmarsh,
Our developers have reviewed your questions. Please note that all multi-level categories are added to the left. To add new levels, you need to shift the whole table to the right. For this, the categoryStartIndex variable is used here:

presentation = new aspose.slides.Presentation();
slide = presentation.getSlides().get_Item(0);

shape = slide.getShapes().addChart(aspose.slides.ChartType.ClusteredColumn, 20, 20, 800, 400);

shape.getChartData().getSeries().clear();
shape.getChartData().getCategories().clear();

workbook = shape.getChartData().getChartDataWorkbook();
workbook.clear(0);

const chartDataObject = 
  {
            categories: [
             [
              "2021-new",
              "2022-new",
              "2023-new",
              "2024-new"
             ]
            ],
            secondLvlCategory: 
            [
             [
              "Warehouse-new",
              "Warehouse-new",
              "Warehouse-new",
              "Warehouse-new"
             ]
            ],
            thirdLevelCategory: [
              [
              "third-level",
              "third-level",
              "third-level",
              "third-level"
              ]
            ],
            series: [
              {
                name: "Average of renewable rate",
                values: [
                  0.18,
                  0.70,
                  0.50,
                  0.30
                ]
              },
              {
                name: "Average of expiring rate",
                values: [
                  0.2,
                  1,
                  0.5,
                  0.75
                ]
              }
            ]
          };

  const chartData = shape.getChartData();
  const fact = chartData.getChartDataWorkbook();
  const categoryStartIndex = 2;

  chartDataObject.categories.forEach((category) => {
      category.forEach((ele, elementIndex) => {
        chartData.getCategories().add(fact.getCell(0, elementIndex + 1, categoryStartIndex, ele));
      });
  });

  chartDataObject.secondLvlCategory.forEach((category) => {
      category.forEach((ele, elementIndex) => {
        chartData.getCategories().get_Item(elementIndex).getGroupingLevels().setGroupingItem(1, ele);
      });
  });

    chartDataObject.thirdLevelCategory.forEach((category) => {
      category.forEach((ele, elementIndex) => {
        chartData.getCategories().get_Item(elementIndex).getGroupingLevels().setGroupingItem(2, ele);
      });
    });

  const chartSeries = chartData.getSeries();
  const columnType = shape.getType();
  const columnShift = chartDataObject.categories.length - 1 + categoryStartIndex;

  chartDataObject.series.forEach((ele, seriesIndex) => {
    chartSeries.add(fact.getCell(0, 0, seriesIndex + 1 + columnShift, ele.name), columnType);
    const series = chartSeries.get_Item(seriesIndex);
    series.setInvertIfNegative(false);
    ele.values.forEach((value, valueIndex) => {
      const dataPoint = series
        .getDataPoints()
        .addDataPointForBarSeries(
          fact.getCell(0, valueIndex + 1, seriesIndex + 1 + columnShift, value ? value : 0)
        );
    });
  });

presentation.save("output.pptx", aspose.slides.SaveFormat.Pptx);
presentation.dispose();