Pareto Chart in C#

Pareto Chart C#

Pareto Chart
 
Introduction

The main purpose of this article is to create a simple Pareto Chart Control. There are a few third-party Pareto Charts available and also a Pareto Chart can be made using Microsoft Chart controls. My intent is to creata a simple Pareto Chart User Control. As a result, yes I have created a Pareto Chart user control using C#. First we start with a description of what a Pareto Chart is.

Pareto Chart

A Pareto Chart is a combination of both a Bar graph and a Line graph. In a Pareto Chart an X-Axis we will plot the Data Names. In the left Y-Axis we will plot the Data Frequency and in the right side Y-Axis we will plot the Data Cumulative Frequency Percentage. A Pareto Chart is used to graphically summarize and display the relative importance of the differences among groups of data.

The rules of a Pareto Chart are to start displaying the highest to the lowest frequency data as a Bar Graph. Display the Cumulative Frequency Percentage data as a Line Graph.

Here we can see some sample data.

S.No Name Freq Cum Freq Cum Per %
1 Pareto1 53 53 19.27272727
2 pareto2 45 98 35.63636364
3 pareto3 43 141 51.27272727
4 pareto4 37 178 64.72727273
5 pareto5 35 213 77.45454545
6 pareto6 27 240 87.27272727
7 pareto7 23 263 95.63636364
8 pareto8 12 275 100
  Sum 275    
 
The preceding sample data has been used in my program to display the result of the Pareto Chart. From the preceding data we can see.

Fre (Frequency)

Frequency is the total count of data of each sample. For example, a sample pareto1 has 53 data count and pareto2 has 45 and and so on.

Frequency = Total Count of Each Data

Cum Freq (Cumulative Frequency)

Cumulative Frequency is previous frequency plus current frequency. For example the first frequency is 53 so the Cumulative Frequency will be as 53. The next frequency is 45 so the Cumulative Frequency will be 45+53=98 and and so on.

Cumulative Frequency = previous Frequency + Current Frequency (for first data previous frequency will be as zero).

Cum per % (Cumulative Frequency Percentage)

Cumulative Frequency Percentage will be calculated by Cumulative Frequency divded by the Sum of Frequency and multiplied by 100. For example the Sum of Frequency is 275. The first Cumulative Frequency is 53 so 53/275*100=19.27.

Cumulative Frequency percentage =SUM of Frequency / Current Frequency *100

From the following image we can see the sample Excel file that has the preceding sample data with the result and my Pareto Control Chart with the result.

Cumulative Frequency Percentage
Now we start with our code.

I have created a Pareto Chart as a User Control so that it can be used easily in all projects.

In this article I have attached a Zip file named SHANUParetoChart.zip that contains:

1)  "ShanuParetoChart_CTL" folder (containing the Pareto Chart User control Source code).

Note : I will pass the data to the user control as a DataTable. You can allow the same method or change my code as per your requirements.

The DataTable format is the first column as Serial Number. The second column as Data Name and the third column as Frequency. For my sample I will pass the total Data count for every sample as Frequency. The DataTable I have created like this .
  1. DataTable dt = new DataTable();  
  2.  dt.Columns.Add("No");  
  3.             dt.Columns.Add("Names");  
  4.             dt.Columns.Add("Frequency");  
  5.             dt.Columns["Frequency"].DataType = Type.GetType("System.Int32");  
2) The "SHANUParetoChart_DEMO" folder (conaining the demo program that includes the paretoChart User Control with a random data sample using a Timer control).

Using the code

1)  First we will start with the User Control. To create a user control:

1.  Create a new Windows Control Library project.
2.   Set the Name of Project and Click Ok (here my user control name is ShanuParetoChart_CTL).
3.  Add all the controls that are needed.
4.  In code behind declare all the public variables and public property variables.

  1. private System.Windows.Forms.PictureBox PicBox;  
  2.         private System.Windows.Forms.Panel OuterPanel;  
  3.         private System.ComponentModel.Container components = null;  
  4.         private string m_sPicName = "";  
  5.         ContextMenuStrip docmenu = new System.Windows.Forms.ContextMenuStrip();  
  6.         ToolStripMenuItem saveimg = new ToolStripMenuItem();  
  7.   
  8.         int NoofPlots = 5;  
  9.   
  10.         public DataTable dt = new DataTable();  
  11.   
  12.         Font f12 = new Font("arial", 12, FontStyle.Bold, GraphicsUnit.Pixel);  
  13.         Pen B1pen = new Pen(Color.Black, 1);  
  14.         Pen B2pen = new Pen(Color.Black, 2);  
  15.          
  16.   
  17.        int[] intDataValue;  
  18.         int[] intCumulativeValue;  
  19.         Double[] intCumulativeValuePer;  
  20.         Double[] XaxisplotWidth;  
  21.   
  22.         int First_chartDatarectHeight = 400;  
  23.         int First_chartDatarectWidth = 600;  
  24.         Font f10 = new Font("arial", 10, FontStyle.Bold, GraphicsUnit.Pixel);  
  25.         LinearGradientBrush a2 = new LinearGradientBrush(new RectangleF(0, 0, 100, 19), Color.DarkGreen, Color.Green, LinearGradientMode.Horizontal);  
  26.         LinearGradientBrush a3 = new LinearGradientBrush(new RectangleF(0, 0, 100, 19), Color.DarkRed, Color.Red, LinearGradientMode.Horizontal);  
  27.         LinearGradientBrush a1 = new LinearGradientBrush(new RectangleF(0, 0, 100, 19), Color.Blue, Color.DarkBlue, LinearGradientMode.Horizontal);  

5. In Pictuerbox Paint Method I call a method to draw the Pareto Chart. I have used .NET GDI+ to draw both a Bar and Line Graph in Pareto Chart with the Datatable result. In the paint method I check for the Datatable Data and store the Frequency, Cumulative Frequency and Cumulative Frequency Percentage to an Array.

  1. public void PicBox_Paint(object sender, PaintEventArgs e)  
  2.      {     
  3.   
  4.          int opacity = 58; // 50% opaque (0 = invisible, 255 = fully opaque)  
  5.   
  6.          e.Graphics.DrawString("SHANU Pareto CHART",  
  7.              new Font("Arial", 28),  
  8.              new SolidBrush(Color.FromArgb(opacity, Color.OrangeRed)),  
  9.              20,  
  10.               10);  
  11.          if (dt.Rows.Count <= 2)  
  12.          {  
  13.              return;  
  14.          }  
  15.   
  16.          int NoofTrials = dt.Rows.Count;  
  17.          int NoofParts = dt.Columns.Count - 1;  
  18.          NoofPlots = NoofTrials;  
  19.   
  20.   
  21.          intDataValue = new int[NoofTrials];  
  22.          intCumulativeValue = new int[NoofTrials];  
  23.          intCumulativeValuePer = new Double[NoofTrials];  
  24.          if (dt.Rows.Count <= 2)  
  25.          {  
  26.              return;  
  27.          }  
  28.          int idataval = 0;  
  29.          dt.DefaultView.Sort = "Frequency DESC";  
  30.          dt = dt.DefaultView.ToTable();  
  31.   
  32.   
  33.          for (int iRow = 0; iRow < dt.Rows.Count; iRow++)  
  34.          {  
  35.              intDataValue[idataval] = System.Convert.ToInt32(dt.Rows[iRow][2].ToString());  
  36.              idataval = idataval + 1;  
  37.   
  38.          }  
  39.          int sumofFrequence = intDataValue.Sum();  
  40.          intCumulativeValue[0] = intDataValue[0];  
  41.          intCumulativeValuePer[0] = Convert.ToDouble(intCumulativeValue[0]) / Convert.ToDouble(sumofFrequence) * 100;  
  42.          for (int ival = 1; ival < intDataValue.Length; ival++)  
  43.          {  
  44.   
  45.              intCumulativeValue[ival] = intCumulativeValue[ival - 1] + intDataValue[ival];  
  46.              intCumulativeValuePer[ival] = Convert.ToDouble(intCumulativeValue[ival]) / Convert.ToDouble(sumofFrequence) * 100;  
  47.   
  48.          }  
  49.   
  50.          drawPareto(e.Graphics, sumofFrequence);  
  51.   
  52.      }  
In the "drawpareto" function chek all data and draw the X-axis, Y-Axis with both frequency and cumulative frequency percentage. Read all the sample frequency data and draw a bar graph using a draw and fill rectangle method.

  1. public void drawPareto(Graphics e, int sumofFrequence)  
  2.         {  
  3.             try  
  4.             {  
  5.                 First_chartDatarectHeight = PicBox.Height - 20;  
  6.                 First_chartDatarectWidth = PicBox.Width - 20;  
  7.   
  8.   
  9.                 // 1) For the Chart Data Display ---------  
  10.                 e.DrawRectangle(Pens.Black, 10, 10, First_chartDatarectWidth, First_chartDatarectHeight);  
  11.   
  12.                 int historgramHeigt = First_chartDatarectHeight - 30;  
  13.                 int historgramWidth = First_chartDatarectWidth - 20;  
  14.                 int StartXval = 80;  
  15.                 int startyval = 60;  
  16.   
  17.                 // Measurement Horizontal Line  
  18.                 e.DrawLine(B1pen, StartXval, historgramHeigt, historgramWidth, historgramHeigt);  
  19.   
  20.                 //Frequency Vertical line  
  21.                 e.DrawLine(B1pen, StartXval, startyval, StartXval, historgramHeigt);  
  22.   
  23.                 //Cumulative frequency Persentage Ploting  
  24.                 e.DrawLine(B1pen, historgramWidth, startyval, historgramWidth, historgramHeigt);  
  25.   
  26.                 //  NoofPlots =7;  
  27.                 //Draw Xaxis plots  
  28.                 int widthcalculation = (historgramWidth) / NoofPlots + 1;  
  29.                 if (widthcalculation <= StartXval)  
  30.                 {  
  31.                     widthcalculation = StartXval;  
  32.                 }  
  33.                 int XvalPosition = widthcalculation;  
  34.   
  35.                 widthcalculation = widthcalculation - 18;  
  36.   
  37.                 String[] Xaxisplotdata = new String[NoofPlots];  
  38.   
  39.                 XaxisplotWidth = new Double[NoofPlots];  
  40.   
  41.                 RectangleF rectF1 = new RectangleF(30, 10, 100, 122);  
  42.   
  43.                 // End of Xaxis Plot  
  44.   
  45.                 Double yValmaxDataVal = intDataValue.Max();  
  46.                 Double yValminDataVal = intDataValue.Min();  
  47.                 Double yValresultMaxMin = yValmaxDataVal - yValminDataVal;  
  48.   
  49.                 //for ploting the xval data  
  50.                 Double yValMeasurementYAxisValue = yValmaxDataVal / NoofPlots;  
  51.                 int yValheightcalculation = historgramHeigt / NoofPlots;  
  52.                 int yValXvalPosition = yValheightcalculation;  
  53.   
  54.                 Double plotYvals = yValmaxDataVal + 4;  
  55.   
  56.                 Double[] YaxisplotHight = new Double[NoofPlots];  
  57.                 Double[] YaxisplotData = new Double[NoofPlots];  
  58.   
  59.                 for (int ival = 0; ival < NoofPlots; ival++)  
  60.                 {  
  61.                     //Draw Xaxis plots  
  62.                     String MeasurementXAxisValue = dt.Rows[ival][1].ToString();  
  63.                     Xaxisplotdata[ival] = MeasurementXAxisValue;  
  64.                     e.DrawLine(B1pen, XvalPosition, historgramHeigt, XvalPosition, historgramHeigt + 15);  
  65.                     rectF1 = new RectangleF(XvalPosition, historgramHeigt + 6, widthcalculation, 34);  
  66.                     e.DrawString(MeasurementXAxisValue.ToString(), f10, a2, rectF1);  
  67.                     // e.DrawRectangle(Pens.Black, Rectangle.Round(rectF1));  
  68.   
  69.                     XaxisplotWidth[ival] = XvalPosition;  
  70.                     XvalPosition = XvalPosition + widthcalculation;  
  71.   
  72.                     // End of Xaxis Plot  
  73.   
  74.                     // Draw Y axis Plot  
  75.                     if (ival == NoofPlots - 1)  
  76.                     {  
  77.                         e.DrawString("0", f10, a2, StartXval - 12, yValXvalPosition + 4);  
  78.                     }  
  79.                     else  
  80.                     {  
  81.                         e.DrawLine(B1pen, StartXval - 10, yValXvalPosition, StartXval, yValXvalPosition);  
  82.                         e.DrawString(Math.Round(plotYvals, 0).ToString(), f10, a2, StartXval - 20, yValXvalPosition + 4);  
  83.                     }  
  84.   
  85.                     //else  
  86.                     //{  
  87.                     //    plotYvals = plotYvals - yValMeasurementYAxisValue;  
  88.                     //}  
  89.                     YaxisplotData[ival] = plotYvals;  
  90.                     plotYvals = plotYvals - yValMeasurementYAxisValue;  
  91.   
  92.                     YaxisplotHight[ival] = yValXvalPosition;  
  93.                     yValXvalPosition = yValXvalPosition + yValheightcalculation;  
  94.   
  95.                     //End of Yaxis Plot.  
  96.   
  97.                 }  
  98.   
  99.                 int widthcalculation_new = historgramWidth / NoofPlots;  
  100.   
  101.                 int XvalPosition_Start = Convert.ToInt32(XaxisplotWidth[0]);  
  102.   
  103.                 int XvalPosition_new = Convert.ToInt32(XaxisplotWidth[1]) - XvalPosition_Start;  
  104.   
  105.                 widthcalculation = widthcalculation - 18;  
  106.   
  107.                 int Ystartval = 100;  
  108.                 int YEndval = 100;  
  109.                 //Fill Rectangle  
  110.                 LinearGradientBrush a6;// new LinearGradientBrush(new RectangleF(StartXval, Ystartval, widthcalculation_new - StartXval, YEndval), Color.GreenYellow, Color.Green, LinearGradientMode.Vertical);  
  111.   
  112.                 Font f2 = new Font("arial", 12, FontStyle.Bold, GraphicsUnit.Pixel);  
  113.                 for (int ival = 0; ival < YaxisplotData.Length - 1; ival++)  
  114.                 {  
  115.                     for (int yval = 1; yval < YaxisplotData.Length - 1; yval++)  
  116.                     {  
  117.   
  118.                         Double finaldisplayvalue = YaxisplotHight[yval - 1] + ((YaxisplotData[yval - 1] - intDataValue[ival]) * 6);  
  119.   
  120.   
  121.                         if (intDataValue[ival] <= YaxisplotData[yval - 1] && intDataValue[ival] > YaxisplotData[yval])  
  122.                         {  
  123.   
  124.                             Ystartval = Convert.ToInt32(finaldisplayvalue);  
  125.                             YEndval = historgramHeigt - Convert.ToInt32(finaldisplayvalue);  
  126.                         }  
  127.   
  128.                         else if (intDataValue[ival] <= YaxisplotData[yval - 1] && intDataValue[ival] < YaxisplotData[yval])  
  129.                         {  
  130.                             //  Double finaldisplayvalue = YaxisplotHight[yval - 1] + ((YaxisplotData[yval - 1] - intDataValue[ival]));  
  131.   
  132.                             Ystartval = Convert.ToInt32(finaldisplayvalue);  
  133.                             YEndval = historgramHeigt - Convert.ToInt32(finaldisplayvalue);  
  134.                         }  
  135.                     }  
  136.   
  137.                     if (YEndval > 2)  
  138.                     {  
  139.                     }  
  140.                     else  
  141.                     {  
  142.                         Ystartval = historgramHeigt - 2;  
  143.                         YEndval = 2;  
  144.                     }  
  145.                     a6 = new LinearGradientBrush(new RectangleF(StartXval, Ystartval, XvalPosition_new, YEndval), Color.LightBlue, Color.CornflowerBlue, LinearGradientMode.Vertical);  
  146.   
  147.                     XvalPosition_Start = Convert.ToInt32(XaxisplotWidth[ival]);  
  148.                     e.DrawRectangle(B1pen, XvalPosition_Start, Ystartval, XvalPosition_new, YEndval);  
  149.                     e.FillRectangle(a6, XvalPosition_Start, Ystartval - 1, XvalPosition_new - 1, YEndval - 1);  
  150.                     e.DrawString(intDataValue[ival].ToString(), f2, a2, XvalPosition_Start + 10, Ystartval - 20);  
  151.   
  152.   
  153.   
  154.                     XvalPosition_new = Convert.ToInt32(XaxisplotWidth[ival + 1]) - XvalPosition_Start;// XvalPosition_Start+XvalPosition_new + widthcalculation_new;  
  155.   
  156.   
  157.                     if (ival == YaxisplotData.Length - 2)  
  158.                     {  
  159.                         for (int yval = 1; yval < YaxisplotData.Length - 1; yval++)  
  160.                         {  
  161.                             if (intDataValue[ival + 1] <= YaxisplotData[yval - 1] && intDataValue[ival] > YaxisplotData[yval])  
  162.                             {  
  163.                                 Double finaldisplayvalue = YaxisplotHight[yval - 1] + ((YaxisplotData[yval - 1] - intDataValue[ival + 1]) * 6);  
  164.   
  165.                                 Ystartval = Convert.ToInt32(finaldisplayvalue);  
  166.                                 YEndval = historgramHeigt - Convert.ToInt32(finaldisplayvalue);  
  167.                             }  
  168.                             else if (intDataValue[ival + 1] <= YaxisplotData[yval - 1] && intDataValue[ival + 1] < YaxisplotData[yval])  
  169.                             {  
  170.                                 Double finaldisplayvalue = YaxisplotHight[yval - 1] + ((YaxisplotData[yval - 1] - intDataValue[ival + 1]) * 6);  
  171.   
  172.                                 Ystartval = Convert.ToInt32(finaldisplayvalue);  
  173.                                 YEndval = historgramHeigt - Convert.ToInt32(finaldisplayvalue);  
  174.                             }  
  175.                         }  
  176.   
  177.                         if (YEndval > 2)  
  178.                         {  
  179.                         }  
  180.                         else  
  181.                         {  
  182.                             Ystartval = historgramHeigt - 2;  
  183.                             YEndval = 2;  
  184.                         }  
  185.   
  186.   
  187.                         XvalPosition_Start = Convert.ToInt32(XaxisplotWidth[ival + 1]);  
  188.   
  189.                         if (XvalPosition_Start + XvalPosition_new > historgramWidth)  
  190.                         {  
  191.                             XvalPosition_new = XvalPosition_new - (XvalPosition_Start + XvalPosition_new - historgramWidth);  
  192.                         }  
  193.   
  194.   
  195.                         //  a6 = new LinearGradientBrush(new RectangleF(StartXval, Ystartval, XvalPosition_new, YEndval), Color.GreenYellow, Color.Green, LinearGradientMode.Vertical);  
  196.                         e.DrawRectangle(B1pen, XvalPosition_Start, Ystartval, XvalPosition_new, YEndval);  
  197.                         e.FillRectangle(a6, XvalPosition_Start, Ystartval - 1, XvalPosition_new - 1, YEndval - 1);  
  198.                         e.DrawString(intDataValue[ival + 1].ToString(), f2, a2, XvalPosition_Start + 10, Ystartval - 20);  
  199.                     }  
  200.   
  201.   
  202.                 }  
  203.   
  204.                 //Draw Line Curve on pareto Chart  
  205.                 drawParetoCurveLine(e);  
  206.   
  207.             }  
  208.             catch (Exception ex)  
  209.             {  
  210.                 MessageBox.Show(ex.ToString());  
  211.             }  
  212.         }  
The same as in the preceding function I check for all the cumulative frequency percentage data and draw a line graph using the drawline and fillpie methods.

  1. public void drawParetoCurveLine(Graphics e)  
  2.       {  
  3.   
  4.           First_chartDatarectHeight = PicBox.Height - 20;  
  5.           First_chartDatarectWidth = PicBox.Width - 20;  
  6.   
  7.   
  8.           int historgramHeigt = First_chartDatarectHeight - 30;  
  9.           int historgramWidth = First_chartDatarectWidth - 20;  
  10.           int StartXval = historgramWidth + 12;  
  11.           int startyval = 60;  
  12.   
  13.           Double yValmaxDataVal = 100;  
  14.           Double yValminDataVal = 0;  
  15.           Double yValresultMaxMin = yValmaxDataVal - yValminDataVal;  
  16.           int NoofPlots = 5;  
  17.           Double yValMeasurementYAxisValue = yValmaxDataVal / NoofPlots;  
  18.           int yValheightcalculation = historgramHeigt / NoofPlots;  
  19.           int yValXvalPosition = startyval;// yValheightcalculation;  
  20.   
  21.           Double plotYvals = yValmaxDataVal;  
  22.   
  23.           Double[] YaxisplotHight = new Double[NoofPlots];  
  24.           Double[] YaxisplotData = new Double[NoofPlots];  
  25.   
  26.           for (int ival = 0; ival <= NoofPlots - 1; ival++)  
  27.           {  
  28.   
  29.               if (ival == NoofPlots)  
  30.               {  
  31.                   e.DrawString("0", f10, a2, StartXval - 12, yValXvalPosition + 4);  
  32.               }  
  33.               else  
  34.               {  
  35.                   e.DrawLine(B1pen, StartXval - 10, yValXvalPosition, StartXval, yValXvalPosition);  
  36.                   e.DrawString(Math.Round(plotYvals, 0).ToString() + "%", f10, a2, StartXval - 11, yValXvalPosition + 4);  
  37.               }  
  38.   
  39.               YaxisplotData[ival] = plotYvals;  
  40.               plotYvals = plotYvals - yValMeasurementYAxisValue;  
  41.   
  42.               YaxisplotHight[ival] = yValXvalPosition;  
  43.               yValXvalPosition = yValXvalPosition + yValheightcalculation;  
  44.   
  45.   
  46.           }  
  47.   
  48.   
  49.           SolidBrush brush = new SolidBrush(Color.Aquamarine);  
  50.           Random rnd = new Random();  
  51.   
  52.           NoofPlots = intCumulativeValuePer.Length;  
  53.   
  54.           int widthcalculation_new = historgramWidth / NoofPlots;  
  55.   
  56.           int XvalPosition_Start = Convert.ToInt32(XaxisplotWidth[0]);  
  57.   
  58.           int XvalPosition_new = Convert.ToInt32(XaxisplotWidth[1]) - XvalPosition_Start;  
  59.   
  60.   
  61.   
  62.           int Ystartval = 100;  
  63.           int YEndval = 100;  
  64.           //Fill Rectangle  
  65.           LinearGradientBrush a6 = new LinearGradientBrush(new RectangleF(StartXval, Ystartval, widthcalculation_new - StartXval, YEndval), Color.GreenYellow, Color.Green, LinearGradientMode.Vertical);  
  66.           brush = new SolidBrush(Color.Aquamarine);  
  67.           Pen pen = new Pen(Color.Gray);  
  68.           Font f2 = new Font("arial", 12, FontStyle.Bold, GraphicsUnit.Pixel);  
  69.           Point p1 = new Point();  
  70.           Point p2 = new Point();  
  71.           int smallLength = (historgramWidth / (intCumulativeValuePer.Length + 1));  
  72.           Double smallHeight = 0;  
  73.           // int smallX = topX;  
  74.           for (int i = 0; i < intCumulativeValuePer.Length - 1; i++)  
  75.           {  
  76.   
  77.   
  78.               brush.Color = Color.FromArgb(rnd.Next(200, 255), rnd.Next(255),  
  79.          rnd.Next(255), rnd.Next(255));  
  80.               p1 = p2;  
  81.   
  82.               if (i == 0)  
  83.               {  
  84.                   p2.X = p2.X + smallLength + 40;  
  85.               }  
  86.               else  
  87.               {  
  88.                   p2.X = p2.X + smallLength + 14;  
  89.               }  
  90.   
  91.               smallHeight = YaxisplotHight[YaxisplotHight.Length - 1] + ((YaxisplotData[YaxisplotHight.Length - 1] - intCumulativeValuePer[i]) * 2);  
  92.   
  93.   
  94.               for (int yval = 1; yval < YaxisplotData.Length; yval++)  
  95.               {  
  96.   
  97.                   // Double finaldisplayvalue = YaxisplotHight[yval - 1] + ((YaxisplotData[yval - 1] - intCumulativeValuePer[i])*10);  
  98.   
  99.                   Double finaldisplayvalue = YaxisplotHight[yval] + ((YaxisplotData[yval] - intCumulativeValuePer[i]) * 2);  
  100.                   if (intCumulativeValuePer[i] <= YaxisplotData[yval - 1] && intCumulativeValuePer[i] > YaxisplotData[yval])  
  101.                   {  
  102.   
  103.                       Ystartval = Convert.ToInt32(finaldisplayvalue);  
  104.                       smallHeight = Convert.ToInt32(finaldisplayvalue);  
  105.                   }  
  106.   
  107.   
  108.   
  109.               }  
  110.               // smallHeight = historgramHeigt - YaxisplotHight[i]+150;  
  111.   
  112.               p2.Y = Convert.ToInt32(smallHeight);  
  113.               if (p1.X != 0 && p1.Y != 0)  
  114.               {  
  115.                   e.DrawLine(pen, p1, p2);  
  116.   
  117.               }  
  118.               Color pointColor = new Color();  
  119.               pointColor = Color.Green;  
  120.   
  121.   
  122.               DrawDots(e, p2, pointColor);  
  123.               e.DrawString(Math.Round(intCumulativeValuePer[i], 2).ToString(), f2, a2, p2.X, p2.Y - 18);  
  124.   
  125.               if (i == 0)  
  126.               {  
  127.                   smallLength = smallLength - 15;  
  128.               }  
  129.   
  130.               if (i == intCumulativeValuePer.Length - 2)  
  131.               {  
  132.                   p1.X = p2.X;  
  133.                   p1.Y = p2.Y;  
  134.                   for (int yval = 1; yval < YaxisplotData.Length; yval++)  
  135.                   {  
  136.   
  137.                       // Double finaldisplayvalue = YaxisplotHight[yval - 1] + ((YaxisplotData[yval - 1] - intCumulativeValuePer[i])*10);  
  138.   
  139.                       Double finaldisplayvalue = YaxisplotHight[yval] + ((YaxisplotData[yval] - intCumulativeValuePer[i + 1]) * 3);  
  140.                       if (intCumulativeValuePer[i + 1] <= YaxisplotData[yval - 1] && intCumulativeValuePer[i + 1] > YaxisplotData[yval])  
  141.                       {  
  142.   
  143.                           Ystartval = Convert.ToInt32(finaldisplayvalue);  
  144.                           smallHeight = Convert.ToInt32(finaldisplayvalue);  
  145.                       }  
  146.   
  147.   
  148.                   }  
  149.                   //    p2.X = p2.X + smallLength - 24;  
  150.                   p2.Y = Convert.ToInt32(smallHeight);  
  151.                   if (p1.X != 0 && p1.Y != 0)  
  152.                   {  
  153.   
  154.   
  155.                       p2.X = p2.X + smallLength + 14;  
  156.                       e.DrawLine(pen, p1, p2);  
  157.   
  158.                   }  
  159.                   DrawDots(e, p2, pointColor);  
  160.                   e.DrawString(Math.Round(intCumulativeValuePer[i + 1], 2).ToString(), f2, a2, p2.X, p2.Y - 18);  
  161.               } } }  

I have added a user friendly feature to save my Pareto Chart as an image. The user can save the Pareto Chart as an image by double-clicking on the Pareto Chart control or by right-clicking and save.

  1. private void PicBox_DoubleClick(object sender, EventArgs e)  
  2.         {  
  3.             saveImages();  
  4.         }  
  5.   
  6.         private void docmenu_Click(object sender, EventArgs e)  
  7.         {  
  8.             saveImages();  
  9.         }  
  10.   
  11.         public void saveImages()  
  12.         {  
  13.             if (dt.Rows.Count <= 0)  
  14.             {  
  15.                 return;  
  16.             }  
  17.   
  18.             using (var bitmap = new Bitmap(PicBox.Width, PicBox.Height))  
  19.             {  
  20.                 PicBox.DrawToBitmap(bitmap, PicBox.ClientRectangle);  
  21.   
  22.   
  23.                 SaveFileDialog dlg = new SaveFileDialog();  
  24.                 dlg.FileName = "*";  
  25.                 dlg.DefaultExt = "bmp";  
  26.                 dlg.ValidateNames = true;  
  27.   
  28.                 dlg.Filter = "Bitmap Image (.bmp)|*.bmp|Gif Image (.gif)|*.gif|JPEG Image (.jpeg)|*.jpeg|Png Image (.png)|*.png";  
  29.                 if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)  
  30.                 {  
  31.   
  32.                     bitmap.Save(dlg.FileName);  
  33.                 }}  
  34.         }  

 6. After completion save, build and run the project.

2) Now we create a Windows application and test our "ShanuParetoChart_CTL" User Control.

1. Create a new Windows project.
2. Open your form and then from Toolbox right-click then choose items then select your user control DLL and add.
3. Drag the User Control to your Windows form.
4. Create a DataTable and pass the Datatable to our User Control.

  1. public void loadGridColums()  
  2.         {  
  3.             dt.Columns.Add("No");  
  4.             dt.Columns.Add("Names");  
  5.             dt.Columns.Add("Frequency");  
  6.             dt.Columns["Frequency"].DataType = Type.GetType("System.Int32");  
  7.         }  
5.In my demo program I used the Timer for the random sample data. I have used the "button1" as a Toggle button. When clicking Enabled the first time and starting the Timer and the same button is clicked again it stops the Timer. When the timer is started I have generated a random number and pass the different data to the user control and check for the chart result.

  1. private void frmShanuPaerto_Load(object sender, EventArgs e)  
  2.         {  
  3.             loadgrid(1);  
  4.             shanuParetoChart.Bindgrid(dt);     
  5.         }  
  6.   
  7.         private void button1_Click(object sender, EventArgs e)  
  8.         {  
  9.             if (button1.Text == "Real Time Data ON")  
  10.             {  
  11.                 timer1.Enabled = true;  
  12.                 timer1.Start();  
  13.                 button1.Text = "Real Time Data Off";  
  14.             }  
  15.             else  
  16.             {  
  17.                 timer1.Enabled = false;  
  18.                 timer1.Stop();  
  19.                 button1.Text = "Real Time Data ON";  
  20.             }  
  21.         }  
  22.   
  23.         private void timer1_Tick(object sender, EventArgs e)  
  24.         {  
  25.             loadgrid(2);  
  26.             shanuParetoChart.Bindgrid(dt);     
  27.         }  

Conclusion

The main purpose of this article is to create a simple user friendly Pareto Chart Control that will be useful for many users to use and use for free in their projects. I hope my Pareto Chart control will be useful for many users from now on.
If you like my article and Pareto Chart Control kindly leave me a comment.

Reference links:

http://www.wikihow.com/Create-a-Pareto-Chart-in-MS-Excel-2010
http://asq.org/learn-about-quality/cause-analysis-tools/overview/pareto.html
http://whatis.techtarget.com/definition/Pareto-chart-Pareto-distribution-diagram

History

Initial release on 2014/08/01.