Getting actual absolute X,Y values for chart data point label

Hi,
I am looking to find an example of how to use this feature. I have used the following code to try and add a rectangle over a data label but it hasn’t worked as expected (the shape is too big and in the wrong place).

chart.ValidateChartLayout();
// FInd label position and dimensions for datapoint 6
float labelX = chart.ChartData.Series[0].DataPoints[6].Label.ActualX;
float labelY = chart.ChartData.Series[0].DataPoints[6].Label.ActualY;
float labelHeight = chart.ChartData.Series[0].DataPoints[6].Label.ActualHeight;
float labelWidth = chart.ChartData.Series[0].DataPoints[6].Label.ActualWidth;
// Add shape
IShape myShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, chart.X + labelX, chart.Y + labelY, labelWidth, labelHeight);

Any ideas where I am going wrong?

@mmr-jef,

I have observed your comments. Can you please share source presentation, generated result and environment details with us. Also please share which Aspose.Slides version you are using on your end so that we may further investigate to help you out.

Best Regards,

Hi, I am using Slides for .Net 4.0 17.5 with C# inside of Visual Studio 2017. I have been attempting to work out how to locate data labels with this example which attempts to put a rectangle shape over them. The shapes though all appear to be much bigger than the data label.

        // Create some data
        System.Data.DataTable table = new System.Data.DataTable();
        table.Columns.Add("Term", typeof(string));
        table.Columns.Add("Value", typeof(float));

        table.Rows.Add(@"Term 16", -1.5);
        table.Rows.Add(@"Term 15", -0.7);
        table.Rows.Add(@"Term 14", -0.7);
        table.Rows.Add(@"Term 13", -0.6);
        table.Rows.Add(@"Term 12", -0.6);
        table.Rows.Add(@"Term 11", -0.3);
        table.Rows.Add(@"Term 10", -0.1);
        table.Rows.Add(@"Term 9", 0.1);
        table.Rows.Add(@"Term 8", 0.3);
        table.Rows.Add(@"Term 7", 0.5);
        table.Rows.Add(@"Term 6", 0.6);
        table.Rows.Add(@"Term 5", 0.7);
        table.Rows.Add(@"Term 4", 0.9);
        table.Rows.Add(@"Term 3", 1.2);
        table.Rows.Add(@"Term 2", 1.4);
        table.Rows.Add(@"Term 1", 1.7);

        //create PPT document.
        Presentation presentation = new Presentation();

        // Get slides from presentation.
        ISlideCollection slides = presentation.Slides;

        // Set slide to first slide.
        ISlide slide = presentation.Slides[0];

        // Add a clustered bar chart.
        IChart chart = slide.Shapes.AddChart(ChartType.ClusteredBar, 208, 100, 290, 400);

        // Clear the current example data from the chart
        chart.ChartData.Series.Clear();
        chart.ChartData.Categories.Clear();
        chart.ChartData.ChartDataWorkbook.Clear(0);

        // Set the default chart worksheet index
        int defaultWorksheetIndex = 0;

        // Get the chart data worksheet
        IChartDataWorkbook workbook = chart.ChartData.ChartDataWorkbook;

        // Getting the chart data worksheet
        IChartDataWorkbook worksheet = chart.ChartData.ChartDataWorkbook;

        // Add Categories
        for (int i = 0; i < table.Rows.Count; i++)
        {
            chart.ChartData.Categories.Add(worksheet.GetCell(defaultWorksheetIndex, i + 1, 0, table.Rows[i].Field<string>(0)));
        }

        // Add series
        chart.ChartData.Series.Add(worksheet.GetCell(defaultWorksheetIndex, 0, 1, table.Columns[1].ColumnName), chart.Type);

        IChartSeries series = chart.ChartData.Series[0];

        for (int i = 0; i < table.Rows.Count; i++)
        {
            chart.ChartData.Categories.Add(worksheet.GetCell(defaultWorksheetIndex, i + 1, 0, table.Rows[i].Field<string>(0)));
            series.DataPoints.AddDataPointForBarSeries(worksheet.GetCell(defaultWorksheetIndex, i + 1, 1, table.Rows[i].Field<float>(1)));
        }

        // add data labels
        series.Labels.DefaultDataLabelFormat.ShowValue = true;

        // Put boxes around data labels
        chart.ValidateChartLayout();
        float labelX;
        float labelY;
        float labelHeight;
        float labelWidth;

        IShape myShape;

        for (int i = 0; i < chart.ChartData.Series[0].DataPoints.Count; i++)
        {
            labelX = chart.ChartData.Series[0].DataPoints[i].Label.ActualX;
            labelY = chart.ChartData.Series[0].DataPoints[i].Label.ActualY;
            labelHeight = chart.ChartData.Series[0].DataPoints[i].Label.ActualHeight;
            labelWidth = chart.ChartData.Series[0].DataPoints[i].Label.ActualWidth;
            myShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, chart.X + labelX, chart.Y + labelY, labelWidth, labelHeight);

        }

        // Save the file.
        string filePath = System.IO.Path.GetTempPath() + "/example_chart.pptx";
        presentation.Save(filePath, SaveFormat.Pptx);

        // Open the file
        System.Diagnostics.Process.Start(filePath);

@mmr-jef

I have observed your following requirements:

I suggest you to please visit this thread post link where by I have added example for adding a rectangle shape along side chart labels in chart area. I hope the shared information will be helpful.

Many Thanks,

Mudassir Fayyaz

Hi,

I have looked at the link but it doesn’t help explain why I am not getting the right position and size when I use the code. I have attached the output I am getting for reference

Data Label Position Example.jpg (17.6 KB)
Thanks.

@mmr-jef,

I suggest you to please try using following alternate in your code sample.

        for (int i = 0; i < chart.ChartData.Series[0].DataPoints.Count; i++)
        {
            int offsetX = 0;
            int offsetY = 0;
            if (chart.ChartData.Series[0].DataPoints[i].Value.ToDouble() > 0)
            {
                offsetX = 5;
                offsetY = 10;
            }
            else
            {
                offsetX = -5;
                offsetY = 7;
            }
            chart.ValidateChartLayout();
            labelX = chart.ChartData.Series[0].DataPoints[i].Label.ActualX+offsetX;
            labelY = chart.ChartData.Series[0].DataPoints[i].Label.ActualY + offsetY;
            //labelHeight = chart.ChartData.Series[0].DataPoints[i].Label.ActualHeight;
           // labelWidth = chart.ChartData.Series[0].DataPoints[i].Label.ActualWidth;
            labelHeight = 10;// chart.ChartData.Series[0].DataPoints[i].Label.ActualHeight;
            labelWidth = chart.ChartData.Series[0].DataPoints[i].Label.ActualWidth;
            myShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, chart.X + labelX, chart.Y + labelY, labelWidth, labelHeight);
            myShape.FillFormat.FillType = FillType.NoFill;
            myShape.LineFormat.Width = 1;

        }

Many Thanks,

Mudassir Fayyaz

Hi,

I have implemented the changes you have specified but the outcome is still not as expected. Not all the boxes are of the same width and the vertical spacing between them is not consistent so adding a constant offset would not resolve the problem. I have attached a copy of the result for you to see. What are the ActualX, ActualY etc actually referencing? I would have thought it was the property of the label but it doesn’t look like this is the case.
Data Label Position Example ii.jpg (21.4 KB)

many thanks.

@mmr-jef,

I have observed the observations shared by you and request you to please provide a sample presentation with desired results. We will observe the requirements and will try our best to share a sample code meeting those requirements.

Many Thanks,

Mudassir Fayyaz

I am evaluating Aspose and a lot of the work I do relies on being able to accurately locate chart elements such as the labels. I was testing out label location trying to put a box around each of the labels as per the example attached but the values I am getting back do not seem to relate very well to the actual labels.
Data Label Position Example.zip (38.3 KB)
Thanks.

@mmr-jef,

Thank you for sharing the desired output presentation. I have generated the following sample code for your convenience to serve the purpose. I have also attached the generated presentation for your kind reference as well.

public static void TestCustomerChart()
{
    // Create some data
    System.Data.DataTable table = new System.Data.DataTable();
    table.Columns.Add("Term", typeof(string));
    table.Columns.Add("Value", typeof(float));

    table.Rows.Add(@"Term 16", -1.5);
    table.Rows.Add(@"Term 15", -0.7);
    table.Rows.Add(@"Term 14", -0.7);
    table.Rows.Add(@"Term 13", -0.6);
    table.Rows.Add(@"Term 12", -0.6);
    table.Rows.Add(@"Term 11", -0.3);
    table.Rows.Add(@"Term 10", -0.1);
    table.Rows.Add(@"Term 9", 0.1);
    table.Rows.Add(@"Term 8", 0.3);
    table.Rows.Add(@"Term 7", 0.5);
    table.Rows.Add(@"Term 6", 0.6);
    table.Rows.Add(@"Term 5", 0.7);
    table.Rows.Add(@"Term 4", 0.9);
    table.Rows.Add(@"Term 3", 1.2);
    table.Rows.Add(@"Term 2", 1.4);
    table.Rows.Add(@"Term 1", 1.7);

    //create PPT document.
    Presentation presentation = new Presentation();

    // Get slides from presentation.
    ISlideCollection slides = presentation.Slides;

    // Set slide to first slide.
    ISlide slide = presentation.Slides[0];

    // Add a clustered bar chart.
    IChart chart = slide.Shapes.AddChart(ChartType.ClusteredBar, 208, 100, 290, 400);

    // Clear the current example data from the chart
    chart.ChartData.Series.Clear();
    chart.ChartData.Categories.Clear();
    chart.ChartData.ChartDataWorkbook.Clear(0);

    // Set the default chart worksheet index
    int defaultWorksheetIndex = 0;

    // Get the chart data worksheet
    IChartDataWorkbook workbook = chart.ChartData.ChartDataWorkbook;

    // Getting the chart data worksheet
    IChartDataWorkbook worksheet = chart.ChartData.ChartDataWorkbook;

    // Add Categories
    for (int i = 0; i < table.Rows.Count; i++)
    {
        chart.ChartData.Categories.Add(worksheet.GetCell(defaultWorksheetIndex, i + 1, 0, table.Rows[i].ItemArray[0].ToString()));
    }

    // Add series
    chart.ChartData.Series.Add(worksheet.GetCell(defaultWorksheetIndex, 0, 1, table.Columns[1].ColumnName), chart.Type);

    IChartSeries series = chart.ChartData.Series[0];

    for (int i = 0; i < table.Rows.Count; i++)
    {
            chart.ChartData.Categories.Add(worksheet.GetCell(defaultWorksheetIndex, i + 1, 0, table.Rows[i].ItemArray[0].ToString()));
        series.DataPoints.AddDataPointForBarSeries(worksheet.GetCell(defaultWorksheetIndex, i + 1, 1, Convert.ToDecimal(table.Rows[i].ItemArray[1].ToString())));
    }

    chart.Axes.VerticalAxis.IsVisible = false;
    chart.Axes.HorizontalAxis.IsVisible = false;
    // add data labels
    series.Labels.DefaultDataLabelFormat.ShowValue = true;
    chart.Axes.VerticalAxis.MajorGridLinesFormat.Line.FillFormat.FillType=FillType.NoFill;
    chart.Axes.HorizontalAxis.MajorGridLinesFormat.Line.FillFormat.FillType = FillType.NoFill;
    chart.Axes.VerticalAxis.IsVisible = false;
    chart.Axes.HorizontalAxis.IsVisible = false;
    chart.BackWall.Format.Line.FillFormat.FillType = FillType.NoFill;
    chart.PlotArea.Format.Line.FillFormat.FillType = FillType.NoFill;
    chart.LineFormat.FillFormat.FillType = FillType.NoFill;
    series.InvertIfNegative = false;
    chart.HasLegend = false;


    // Put boxes around data labels
    chart.ValidateChartLayout();
    float labelX;
    float labelY;
    float labelHeight;
    float labelWidth;

    IShape myShape;

    for (int i = 0; i < chart.ChartData.Series[0].DataPoints.Count; i++)
    {
        int offsetX = 0;
        int offsetY = 0;
        if (chart.ChartData.Series[0].DataPoints[i].Value.ToDouble() >= 0)
        {
            offsetX = 5;
            offsetY = 4;
        }
        else
        {
            offsetX = -4;
            offsetY = 5;
        }
        chart.ValidateChartLayout();
        labelX = chart.ChartData.Series[0].DataPoints[i].Label.ActualX + offsetX;
        labelY = chart.ChartData.Series[0].DataPoints[i].Label.ActualY + offsetY;
        labelHeight = 10;// chart.ChartData.Series[0].DataPoints[i].Label.ActualHeight;
        labelWidth = chart.ChartData.Series[0].DataPoints[i].Label.ActualWidth;
        myShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, chart.X + labelX, chart.Y + labelY, labelWidth, labelHeight+7);
        myShape.FillFormat.FillType = FillType.NoFill;
        myShape.LineFormat.Width = 2;
        myShape.LineFormat.FillFormat.FillType=FillType.Solid;
        myShape.LineFormat.FillFormat.SolidFillColor.Color = Color.FromArgb(79,129,189);
        chart.ChartData.Series[0].DataPoints[i].Label.TextFormat.PortionFormat.FontHeight = 18;
        chart.ChartData.Series[0].DataPoints[i].Label.TextFormat.PortionFormat.LatinFont = new FontData("Calibri");

    
    }
    chart.PlotArea.Format.Line.FillFormat.FillType = FillType.NoFill;
    series.InvertIfNegative = false;
    chart.HasLegend = false;
    // Save the file.
    string filePath = System.IO.Path.GetTempPath() + "/example_chart.pptx";
    presentation.Save(filePath, Aspose.Slides.Export.SaveFormat.Pptx);

    // Open the file
    System.Diagnostics.Process.Start(filePath);
}

Many Thanks,

Mudassir Fayyaz

example_chart.zip (29.2 KB)

Ok, I see that when adding the series data you have changed the type of data to Decimal which has resolved the issues I was having.

            //series.DataPoints.AddDataPointForBarSeries(worksheet.GetCell(defaultWorksheetIndex, i + 1, 1, table.Rows[i].Field<float>(1)));
            series.DataPoints.AddDataPointForBarSeries(worksheet.GetCell(defaultWorksheetIndex, i + 1, 1, Convert.ToDecimal(table.Rows[i].ItemArray[1].ToString())));

Thanks for all your help!

@mmr-jef,

Yes, that is true. Please share, if I may help you further in this regard.

Many Thanks,

Mudassir Fayyaz