Как создать круговую диаграмму в PDF документе - SautinSoft.Document



SautinSoft.Document может помочь вашему приложению создать круговую диаграмму и сохранить ее в нужном формате.

SautinSoft.Document поддерживает форматы:

PDF DOCX RTF HTML Текст Изображения
Create/Read/Write Create/Read/Write Create/Read/Write Create/Read/Write Create/Read/Write Create/Read(OCR)/Write

Здесь мы подготовили для вас метод, который позволяет создать круговую диаграмму и сохранить документ в формате PDF.

Этот метод разработан специально для использования с открытым исходным кодом. Вы можете изменять и корректировать все, что пожелаете: диаграмму цвета, размер, расположение, название и размер шрифта, расположение надписей (внутри или снаружи диаграммы), расположение условных обозначений.

Полный код

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: [email protected].<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: [email protected].<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


Если вам нужен пример кода или у вас есть вопрос: напишите нам по адресу [email protected] или спросите в онлайн-чате (правый нижний угол этой страницы) или используйте форму ниже:



Вопросы и предложения всегда приветствуются!

Мы разрабатываем компоненты .Net с 2002 года. Мы знаем форматы PDF, DOCX, RTF, HTML, XLSX и Images. Если вам нужна помощь в создании, изменении или преобразовании документов в различных форматах, мы можем вам помочь. Мы напишем для вас любой пример кода абсолютно бесплатно.