Create a Pie Chart in a PDF document using C# and .NET



Document .Net can help your application to create a Pie Chart and save it to a desired format.

Document .Net supports these formats:

PDF DOCX RTF HTML Text Image
Create/Read/Write Create/Read/Write Create/Read/Write Create/Read/Write Create/Read/Write Create/Read(OCR)/Write

Here we've prepared for you a method which creates a Pie Chart and saves the document as PDF.

This method is made specially with open source code. You may change and adjust anything you want: Chart colors, size, position, font name and font size, position of labels (inside or outside the chart), legend position.

Complete code

using System;
using System.IO;
using System.Collections.Generic;
using SautinSoft.Document;
using SautinSoft.Document.Drawing;
using System.Linq;

namespace Sample
{
    class Sample
    {
        static void Main(string[] args)
        {
            // Get your free 30-day key here:   
            // https://sautinsoft.com/start-for-free/

            PieChart();
        }
        /// <summary>
        /// Creates a simple Pie Chart in a document.
        /// </summary>
        /// <remarks>
        /// See details at: https://sautinsoft.com/products/document/help/net/developer-guide/reporting-create-simple-pie-chart-in-pdf-net-csharp-vb.php
        /// </remarks>
        public static void PieChart()
        {
            DocumentCore dc = new DocumentCore();

            FloatingLayout fl = new FloatingLayout(
                new HorizontalPosition(20f, LengthUnit.Millimeter, HorizontalPositionAnchor.LeftMargin),
                new VerticalPosition(15f, LengthUnit.Millimeter, VerticalPositionAnchor.TopMargin),
                new Size(200, 200));

            Dictionary<string, double> chartData = new Dictionary<string, double>
            {   {"Potato", 25},
                {"Carrot", 16},
                {"Salad", 10},
                {"Cucumber", 10},
                {"Tomato", 4},
                {"Rice", 30},
                {"Onion", 5} };

            AddPieChart(dc, fl, chartData, true, "%", true);


            // Let's save the document into PDF format (you may choose another).
            string filePath = @"Pie Chart.pdf";
            dc.Save(filePath);

            // Open the result for demonstration purposes.
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(filePath) { UseShellExecute = true });
        }
        /// <summary>
        /// This method creates a pie chart.
        /// </summary>
        /// <param name="dc">Document</param>
        /// <param name="chartLayout">Chart layout</param>
        /// <param name="data">Chart data</param>
        /// <param name="addLabels">Add labels or not</param>
        /// <param name="labelSign">Label sign</param>
        /// <param name="addLegend">Add legend</param>
        /// <remarks>
        /// This method is made specially with open source code. You may change anything you want:<br />
        /// Chart colors, size, position, font name and font size, position of labels (inside or outside the chart), legend position.<br />
        /// If you need any assistance, feel free to email us: support@sautinsoft.com.<br />
        /// </remarks>
        public static void AddPieChart(DocumentCore dc, FloatingLayout chartLayout, Dictionary<string, double> data, bool addLabels = true, string labelSign = null, bool addLegend = true)
        {
            // Assume that our chart can have 10 pies maximally.
            // And we'll use these colors order by order.
            // You may change the colors and their quantity.
            List<string> colors = new List<string>()
            {
                "#70AD47", // light green
                "#4472C4", // blue
                "#FFC000", // yellow
                "#A5A5A5", // grey
                "#ED7D31", // orange
                "#5B9BD5", // light blue
                "#44546A", // blue and grey
                "#C00000", // red
                "#00B050", // green
                "#9933FF"  // purple

            };
            // 1. To create a circle chart, assume that the sum of all values are 100%
            // and calculate the percent for the each value.
            // Translate all data to perce
            double amount = data.Values.Sum();
            List<double> percentages = new List<double>();

            foreach (double v in data.Values)
                percentages.Add(v * 100 / amount);

            // 2. Translate the percentage value of the each pie into degrees.
            // The whole circle is 360 degrees.
            int pies = data.Values.Count;
            List<double> pieDegrees = new List<double>();
            foreach (double p in percentages)
                pieDegrees.Add(p * 360 / 100);

            // 3. Translate degrees to the "Pie" measurement.
            List<double> pieMeasure = new List<double>();
            // Add the start position.
            pieMeasure.Add(0);
            double currentAngle = 0;
            foreach (double pd in pieDegrees)
            {
                currentAngle += pd;
                pieMeasure.Add(480 * currentAngle / 360);
            }

            // 4. Create the pies.
            Shape originalShape = new Shape(dc, chartLayout);

            for (int i = 0; i < pies; i++)
            {
                Shape shpPie = originalShape.Clone(true);
                shpPie.Outline.Fill.SetSolid(Color.White);
                shpPie.Outline.Width = 0.5;
                shpPie.Fill.SetSolid(new Color(colors[i]));

                shpPie.Geometry.SetPreset(Figure.Pie);
                shpPie.Geometry.AdjustValues["adj1"] = 45000 * pieMeasure[i];
                shpPie.Geometry.AdjustValues["adj2"] = 45000 * pieMeasure[i + 1];

                dc.Content.End.Insert(shpPie.Content);
            }

            // 5. Add labels
            if (addLabels)
            {
                // 0.5 ... 1.2 (inside/outside the circle).
                double multiplier = 0.8;
                double radius = chartLayout.Size.Width / 2 * multiplier;
                currentAngle = 0;
                double labelW = 35;
                double labelH = 20;

                for (int i = 0; i < pieDegrees.Count; i++)
                {
                    currentAngle += pieDegrees[i];
                    double middleAngleDegrees = 360 - (currentAngle - pieDegrees[i] / 2);
                    double middleAngleRad = middleAngleDegrees * (Math.PI / 180);

                    // Calculate the (x, y) on the circle.
                    double x = radius * Math.Cos(middleAngleRad);
                    double y = radius * Math.Sin(middleAngleRad);

                    // Correct the position depending of the label size;
                    x -= labelW / 2;
                    y += labelH / 2;

                    HorizontalPosition centerH = new HorizontalPosition(chartLayout.HorizontalPosition.Value + chartLayout.Size.Width / 2, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin);
                    VerticalPosition centerV = new VerticalPosition(chartLayout.VerticalPosition.Value + chartLayout.Size.Height / 2, LengthUnit.Point, VerticalPositionAnchor.TopMargin);

                    HorizontalPosition labelX = new HorizontalPosition(centerH.Value + x, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin);
                    VerticalPosition labelY = new VerticalPosition(centerV.Value - y, LengthUnit.Point, VerticalPositionAnchor.TopMargin);

                    FloatingLayout labelLayout = new FloatingLayout(labelX, labelY, new Size(labelW, labelH));
                    Shape shpLabel = new Shape(dc, labelLayout);
                    shpLabel.Outline.Fill.SetEmpty();
                    shpLabel.Text.Blocks.Content.Start.Insert($"{data.Values.ElementAt(i)}{labelSign}",
                        new CharacterFormat()
                        {
                            FontName = "Arial",
                            Size = 10,
                            //FontColor = new Color("#333333")
                            FontColor = new Color("#FFFFFF")
                        });
                    (shpLabel.Text.Blocks[0] as Paragraph).ParagraphFormat.Alignment = HorizontalAlignment.Center;
                    dc.Content.End.Insert(shpLabel.Content);
                }

                // 6. Add Legend
                if (addLegend)
                {
                    double legendTopMargin = LengthUnitConverter.Convert(5, LengthUnit.Millimeter, LengthUnit.Point);
                    double legendLeftMargin = LengthUnitConverter.Convert(-10, LengthUnit.Millimeter, LengthUnit.Point);
                    HorizontalPosition legendX = new HorizontalPosition(chartLayout.HorizontalPosition.Value + legendLeftMargin, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin);
                    VerticalPosition legendY = new VerticalPosition(chartLayout.VerticalPosition.Value + chartLayout.Size.Height + legendTopMargin, LengthUnit.Point, VerticalPositionAnchor.TopMargin);
                    double legendW = chartLayout.Size.Width * 2;
                    double legendH = 20;

                    FloatingLayout legendLayout = new FloatingLayout(legendX, legendY, new Size(legendW, legendH));
                    Shape shpLegend = new Shape(dc, legendLayout);
                    shpLegend.Outline.Fill.SetEmpty();

                    Paragraph pLegend = new Paragraph(dc);
                    pLegend.ParagraphFormat.Alignment = HorizontalAlignment.Left;

                    for (int i = 0; i < data.Count; i++)
                    {
                        string legendItem = data.Keys.ElementAt(i);

                        // 183 - circle, "Symbol"
                        // 167 - square, "Wingdings"

                        Run marker = new Run(dc, (char)167, new CharacterFormat()
                        {
                            FontColor = new Color(colors[i]),
                            FontName = "Wingdings"
                        });
                        pLegend.Content.End.Insert(marker.Content);
                        pLegend.Content.End.Insert($" {legendItem}   ", new CharacterFormat());
                    }


                    shpLegend.Text.Blocks.Add(pLegend);
                    dc.Content.End.Insert(shpLegend.Content);
                }
            }
        }

    }
}

Download

Imports System
Imports System.IO
Imports System.Linq
Imports System.Collections.Generic
Imports SautinSoft.Document
Imports SautinSoft.Document.Drawing

Module Sample
    Sub Main()
        PieChart()
    End Sub
    ''' Get your free 30-day key here:   
    ''' https://sautinsoft.com/start-for-free/
    ''' <summary>
    ''' Creates a simple Pie Chart in a document.
    ''' </summary>
    ''' <remarks>
    ''' See details at: https://sautinsoft.com/products/document/help/net/developer-guide/reporting-create-simple-pie-chart-in-pdf-net-csharp-vb.php
    ''' </remarks>
    Public Sub PieChart()
        Dim dc As New DocumentCore()

        Dim fl As New FloatingLayout(New HorizontalPosition(20.0F, LengthUnit.Millimeter, HorizontalPositionAnchor.LeftMargin), New VerticalPosition(15.0F, LengthUnit.Millimeter, VerticalPositionAnchor.TopMargin), New Size(200, 200))

        Dim chartData As New Dictionary(Of String, Double) From {
                {"Potato", 25},
                {"Carrot", 16},
                {"Salad", 10},
                {"Cucumber", 10},
                {"Tomato", 4},
                {"Rice", 30},
                {"Onion", 5}
            }

        AddPieChart(dc, fl, chartData, True, "%", True)


        ' Let's save the document into PDF format (you may choose another).
        Dim filePath As String = "Pie Chart.pdf"
        dc.Save(filePath)

        ' Open the result for demonstration purposes.
        System.Diagnostics.Process.Start(New System.Diagnostics.ProcessStartInfo(filePath) With {.UseShellExecute = True})
    End Sub
    ''' <summary>
    ''' This method creates a pie chart.
    ''' </summary>
    ''' <param name="dc">Document</param>
    ''' <param name="chartLayout">Chart layout</param>
    ''' <param name="data">Chart data</param>
    ''' <param name="addLabels">Add labels or not</param>
    ''' <param name="labelSign">Label sign</param>
    ''' <param name="addLegend">Add legend</param>
    ''' <remarks>
    ''' This method is made specially with open source code. You may change anything you want:<br />
    ''' Chart colors, size, position, font name and font size, position of labels (inside or outside the chart), legend position.<br />
    ''' If you need any assistance, feel free to email us: support@sautinsoft.com.<br />
    ''' </remarks>
    Public Sub AddPieChart(ByVal dc As DocumentCore, ByVal chartLayout As FloatingLayout, ByVal data As Dictionary(Of String, Double), Optional ByVal addLabels As Boolean = True, Optional ByVal labelSign As String = Nothing, Optional ByVal addLegend As Boolean = True)
        ' Assume that our chart can have 10 pies maximally.
        ' And we'll use these colors order by order.
        ' You may change the colors and their quantity.
        Dim colors As New List(Of String)() From {"#70AD47", "#4472C4", "#FFC000", "#A5A5A5", "#ED7D31", "#5B9BD5", "#44546A", "#C00000", "#00B050", "#9933FF"}
        ' 1. To create a circle chart, assume that the sum of all values are 100%
        ' and calculate the percent for the each value.
        ' Translate all data to perce
        Dim amount As Double = data.Values.Sum()
        Dim percentages As New List(Of Double)()

        For Each v As Double In data.Values
            percentages.Add(v * 100 / amount)
        Next v

        ' 2. Translate the percentage value of the each pie into degrees.
        ' The whole circle is 360 degrees.
        Dim pies As Integer = data.Values.Count
        Dim pieDegrees As New List(Of Double)()
        For Each p As Double In percentages
            pieDegrees.Add(p * 360 / 100)
        Next p

        ' 3. Translate degrees to the "Pie" measurement.
        Dim pieMeasure As New List(Of Double)()
        ' Add the start position.
        pieMeasure.Add(0)
        Dim currentAngle As Double = 0
        For Each pd As Double In pieDegrees
            currentAngle += pd
            pieMeasure.Add(480 * currentAngle / 360)
        Next pd

        ' 4. Create the pies.
        Dim originalShape As New Shape(dc, chartLayout)

        For i As Integer = 0 To pies - 1
            Dim shpPie As Shape = originalShape.Clone(True)
            shpPie.Outline.Fill.SetSolid(Color.White)
            shpPie.Outline.Width = 0.5
            shpPie.Fill.SetSolid(New Color(colors(i)))

            shpPie.Geometry.SetPreset(Figure.Pie)
            shpPie.Geometry.AdjustValues("adj1") = 45000 * pieMeasure(i)
            shpPie.Geometry.AdjustValues("adj2") = 45000 * pieMeasure(i + 1)

            dc.Content.End.Insert(shpPie.Content)
        Next i

        ' 5. Add labels
        If addLabels Then
            ' 0.5 ... 1.2 (inside/outside the circle).
            Dim multiplier As Double = 0.8
            Dim radius As Double = chartLayout.Size.Width / 2 * multiplier
            currentAngle = 0
            Dim labelW As Double = 35
            Dim labelH As Double = 20

            For i As Integer = 0 To pieDegrees.Count - 1
                currentAngle += pieDegrees(i)
                Dim middleAngleDegrees As Double = 360 - (currentAngle - pieDegrees(i) / 2)
                Dim middleAngleRad As Double = middleAngleDegrees * (Math.PI / 180)

                ' Calculate the (x, y) on the circle.
                Dim x As Double = radius * Math.Cos(middleAngleRad)
                Dim y As Double = radius * Math.Sin(middleAngleRad)

                ' Correct the position depending of the label size;
                x -= labelW / 2
                y += labelH / 2

                Dim centerH As New HorizontalPosition(chartLayout.HorizontalPosition.Value + chartLayout.Size.Width \ 2, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin)
                Dim centerV As New VerticalPosition(chartLayout.VerticalPosition.Value + chartLayout.Size.Height \ 2, LengthUnit.Point, VerticalPositionAnchor.TopMargin)

                Dim labelX As New HorizontalPosition(centerH.Value + x, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin)
                Dim labelY As New VerticalPosition(centerV.Value - y, LengthUnit.Point, VerticalPositionAnchor.TopMargin)

                Dim labelLayout As New FloatingLayout(labelX, labelY, New Size(labelW, labelH))
                Dim shpLabel As New Shape(dc, labelLayout)
                shpLabel.Outline.Fill.SetEmpty()
                shpLabel.Text.Blocks.Content.Start.Insert($"{data.Values.ElementAt(i)}{labelSign}", New CharacterFormat() With {
                        .FontName = "Arial",
                        .Size = 10,
                        .FontColor = New Color("#FFFFFF")
                    })
                TryCast(shpLabel.Text.Blocks(0), Paragraph).ParagraphFormat.Alignment = HorizontalAlignment.Center
                dc.Content.End.Insert(shpLabel.Content)
            Next i

            ' 6. Add Legend
            If addLegend Then
                Dim legendTopMargin As Double = LengthUnitConverter.Convert(5, LengthUnit.Millimeter, LengthUnit.Point)
                Dim legendLeftMargin As Double = LengthUnitConverter.Convert(-10, LengthUnit.Millimeter, LengthUnit.Point)
                Dim legendX As New HorizontalPosition(chartLayout.HorizontalPosition.Value + legendLeftMargin, LengthUnit.Point, HorizontalPositionAnchor.LeftMargin)
                Dim legendY As New VerticalPosition(chartLayout.VerticalPosition.Value + chartLayout.Size.Height + legendTopMargin, LengthUnit.Point, VerticalPositionAnchor.TopMargin)
                Dim legendW As Double = chartLayout.Size.Width * 2
                Dim legendH As Double = 20

                Dim legendLayout As New FloatingLayout(legendX, legendY, New Size(legendW, legendH))
                Dim shpLegend As New Shape(dc, legendLayout)
                shpLegend.Outline.Fill.SetEmpty()

                Dim pLegend As New Paragraph(dc)
                pLegend.ParagraphFormat.Alignment = HorizontalAlignment.Left

                For i As Integer = 0 To data.Count - 1
                    Dim legendItem As String = data.Keys.ElementAt(i)

                    ' 183 - circle, "Symbol"
                    ' 167 - square, "Wingdings"

                    Dim marker As Run = New Run(dc, ChrW(167), New CharacterFormat() With {
                            .FontColor = New Color(colors(i)),
                            .FontName = "Wingdings"
                        })
                    pLegend.Content.End.Insert(marker.Content)
                    pLegend.Content.End.Insert($" {legendItem}   ", New CharacterFormat())
                Next i


                shpLegend.Text.Blocks.Add(pLegend)
                dc.Content.End.Insert(shpLegend.Content)
            End If
        End If
    End Sub

End Module

Download


If you need a new code example or have a question: email us at support@sautinsoft.com or ask at Online Chat (right-bottom corner of this page) or use the Form below:



Questions and suggestions from you are always welcome!

We are developing .Net components since 2002. We know PDF, DOCX, RTF, HTML, XLSX and Images formats. If you need any assistance with creating, modifying or converting documents in various formats, we can help you. We will write any code example for you absolutely free.