SPC XBAR 和 Range 图





5.00/5 (5投票s)
使用 C# 的 XBAR 和 Range 图。
引言
在我们开始之前,请参考我之前关于 USL 和 LSL 的控制图的文章 控制图链接。 在我之前的文章中,我解释了如何为 USL 和 LSL 数据检查创建一个简单的控制条形图。
在今天的这篇文章中,我将解释如何创建一个简单的 SPC(统计过程控制)X-bar 和 Range 线性图表。 如果您有兴趣学习 SPC 和 X-Bar,Range 图表请参考以下链接
- https://www.moresteam.com/toolbox/statistical-process-control-spc.cfm
- http://www.qualitytrainingportal.com/resources/spc/form_3839a_app1.htm
- http://www.pqsystems.com/qualityadvisor/formulas/x_bar_range_f.php
现在,让我们看看我是如何创建 SPC X-Bar 和 Range 图表的。 我的主要目标是制作一个非常简单的 SPC 图表,供最终用户使用。
我创建了一个 SPC Xbar/Range 图表作为用户控件,以便可以在所有项目中轻松使用它。
在本文中,我附上了一个名为 SHANUSPCXbarRangeChartSRC.zip 的 zip 文件,其中包含
- “SHANUXbarRangeChart”文件夹(此文件夹包含
<span style="font-size: 12px; background-color: rgb(255,255,255)">SHANUXbarRangeChart</span>
用户控件源代码。) - “SHANUSPCXBarDemo”文件夹(此文件夹包含演示程序,其中包括
<span style="font-size: 12px; background-color: rgb(255,255,255)">SHANUXbarRangeChart</span>
用户控件,带有随机数据样本)。
注意:我使用 DataTable
作为 UserControl
的数据输入。 从 Windows Form 中,我们需要将 DataTable
传递给用户控件以绘制 XBAR 和 Range 线性图。
Using the Code
- 首先,我们将从用户控件开始。要创建用户控件,
- 创建一个新的 Windows 控件库项目。
- 设置项目的名称并单击“确定”(这里,我的用户控件名称是
<span style="font-size: 12px; background-color: rgb(255,255,255)">SHANUXbarRangeChart</span>
)。 - 添加所有需要的控件。
- 在代码隐藏中,声明所有
public
变量和Public
方法。 在用户控件中,我添加了一个面板和一个名为“PIC_SHANUSPC
”的PictureBox
控件。//Public Variable public DataTable dt=new DataTable(); Font f12 = new Font("arial", 12, FontStyle.Bold, GraphicsUnit.Pixel); Pen B1pen = new Pen(Color.Black, 1); Pen B2pen = new Pen(Color.Black, 2); Double XDoublkeBAR = 0; Double RBAR = 0; Double XBARUCL = 0; Double XBARLCL = 0; Double RANGEUCL = 0; Double RANGELCL = 0; Double[] intMeanArrayVals; Double[] intRangeArrayVals; int First_chartDatarectHeight = 80; Font f10 = new Font("arial", 10, FontStyle.Bold, GraphicsUnit.Pixel); LinearGradientBrush a2 = new LinearGradientBrush(new RectangleF(0, 0, 100, 19), Color.DarkGreen, Color.Green, LinearGradientMode.Horizontal); LinearGradientBrush a1 = new LinearGradientBrush(new RectangleF(0, 0, 100, 19), Color.Blue, Color.DarkBlue, LinearGradientMode.Horizontal);
声明变量后,我创建了一个
public
函数,即Bindgrid
。 此函数将从 Windows Form 中使用,以传递DataTable
。 在此函数中,我检查DataTable
,如果DataTable
不是null
,我刷新PictureBox
,这将调用PictureBox paint
方法。public void Bindgrid(DataTable dtnew) { if (dtnew != null) { dt = dtnew; PIC_SHANUSPC.Refresh(); } }
在
PictureBox paint
事件中,我将检查DataTable
数据。 使用这些数据,我创建了所有数据的Sum
、Mean
和Range
。 使用此信息,我使用标准公式创建了 UCL 和 LCL。 有关 UCL 和 LCL 计算的详细信息,请检查上面的链接。 使用所有这些信息,我使用GrawLine
、DrawRectangle
绘制了 SPC XBAR 和 Range 图表。//Paint Method public void PIC_SHANUSPC_Paint(object sender, PaintEventArgs e) { if (dt.Rows.Count <= 0) { return; } int opacity = 48; e.Graphics.DrawString("SHANU SPC CHART", new Font("Arial", 72), new SolidBrush(Color.FromArgb(opacity, Color.OrangeRed)), 80, PIC_SHANUSPC.Height / 2 - 50); int NoofTrials = dt.Rows.Count; int NoofParts = dt.Columns.Count - 1; intMeanArrayVals = new Double[NoofParts]; intRangeArrayVals = new Double[NoofParts]; PIC_SHANUSPC.Width = dt.Columns.Count * 50 + 40; // 1) For the Chart Data Display --------- e.Graphics.DrawRectangle(Pens.Black, 10, 10, PIC_SHANUSPC.Width - 20, First_chartDatarectHeight); // for the chart data Horizontal Line Display e.Graphics.DrawLine(B1pen, 10, 30, PIC_SHANUSPC.Width - 10, 30); e.Graphics.DrawLine(B1pen, 10, 60, PIC_SHANUSPC.Width - 10, 60); // for the chart data Vertical Line Display e.Graphics.DrawLine(B1pen, 60, 10, 60, First_chartDatarectHeight + 8); e.Graphics.DrawLine(B1pen, 110, 10, 110, First_chartDatarectHeight + 8); //------------- // DrawItemEventArgs String e.Graphics.DrawString("SUM", f12, a1, 14, 12); e.Graphics.DrawString("MEAN", f12, a1, 14, 40); e.Graphics.DrawString("Range", f12, a1, 14, 68); // load data //Outer Loop for Columns count int xLineposition = 110; int xStringDrawposition = 14; for (int iCol = 1; iCol <= dt.Columns.Count - 1; iCol++) { //inner Loop for Rows count Double Sumresult = 0; Double Meanresult = 0; Double Rangeresult = 0; Double minRangeValue = int.MaxValue; Double maxRangeValue = int.MinValue; for (int iRow = 0; iRow < dt.Rows.Count; iRow++) { Sumresult = Sumresult + System.Convert.ToDouble (dt.Rows[iRow][iCol].ToString()); Double accountLevel = System.Convert.ToDouble (dt.Rows[iRow][iCol].ToString()); minRangeValue = Math.Min(minRangeValue, accountLevel); maxRangeValue = Math.Max(maxRangeValue, accountLevel); } xLineposition = xLineposition + 50; xStringDrawposition = xStringDrawposition + 50; e.Graphics.DrawLine(B1pen, xLineposition, 10, xLineposition, First_chartDatarectHeight + 8); //Sum Data Display e.Graphics.DrawString(Math.Round(Sumresult, 3).ToString(), f10, a2, xStringDrawposition, 12); //MEAN Data Display Meanresult = Sumresult / NoofTrials; e.Graphics.DrawString(Math.Round(Meanresult, 3).ToString(), f10, a2, xStringDrawposition, 40); //RANGE Data Display Rangeresult = maxRangeValue - minRangeValue; e.Graphics.DrawString(Math.Round(Rangeresult, 3).ToString(), f10, a2, xStringDrawposition, 68); //XDoubleBar used to display in chart XDoublkeBAR = XDoublkeBAR + Meanresult; //RBAR used to display in chart RBAR = RBAR + Rangeresult; intMeanArrayVals[iCol - 1] = Meanresult; intRangeArrayVals[iCol - 1] = Rangeresult; } //End 1 ) ------------------- // 2) -------------------------- // XdoubleBAr/RBAR/UCL and LCL Calculation. //XDoubleBar used to display in chart XDoublkeBAR = XDoublkeBAR / NoofParts; //RBAR used to display in chart RBAR = RBAR / NoofParts; //XBARUCL to display in chart XBARUCL = XDoublkeBAR + UCLLCLTYPE("A2", RBAR, NoofTrials); //XBARLCL to display in chart XBARLCL = XDoublkeBAR - UCLLCLTYPE("A2", RBAR, NoofTrials); //XBARUCL to display in chart RANGEUCL = UCLLCLTYPE("D4", RBAR, NoofTrials); //XBARLCL to display in chart RANGELCL = UCLLCLTYPE("D3", RBAR, NoofTrials); //--------------------------------- //3) Average chart Display --------------- // e.Graphics.DrawRectangle(Pens.Black, 10, 10, // picSpcChart.Width - 20, First_chartDatarectHeight); int chartAvarageDatarectHeight = 18; e.Graphics.DrawRectangle(Pens.Black, 10, First_chartDatarectHeight + 20, PIC_SHANUSPC.Width - 20, chartAvarageDatarectHeight); e.Graphics.DrawLine(B2pen, 476, 116, 480, 100); e.Graphics.DrawString("MEAN CHART", f12, a1, 14, First_chartDatarectHeight + 22); e.Graphics.DrawString("XBarS:", f12, a1, 160, First_chartDatarectHeight + 22); e.Graphics.DrawString(Math.Round(XDoublkeBAR, 3).ToString(), f12, a2, 202, First_chartDatarectHeight + 22); e.Graphics.DrawString("UCL:", f12, a1, 300, First_chartDatarectHeight + 22); e.Graphics.DrawString(Math.Round(XBARUCL, 3).ToString(), f12, a2, 330, First_chartDatarectHeight + 22); e.Graphics.DrawString("LCL:", f12, a1, 400, First_chartDatarectHeight + 22); e.Graphics.DrawString(Math.Round(XBARLCL, 3).ToString(), f12, a2, 430, First_chartDatarectHeight + 22); e.Graphics.DrawString("RANGE CHART", f12, a1, 490, First_chartDatarectHeight + 22); e.Graphics.DrawString("RBar : ", f12, a1, 600, First_chartDatarectHeight + 22); e.Graphics.DrawString(Math.Round(RBAR, 3).ToString(), f12, a2, 638, First_chartDatarectHeight + 22); e.Graphics.DrawString("UCL : ", f12, a1, 700, First_chartDatarectHeight + 22); e.Graphics.DrawString(Math.Round(RANGEUCL, 3).ToString(), f12, a2, 734, First_chartDatarectHeight + 22); e.Graphics.DrawString("LCL : ", f12, a1, 800, First_chartDatarectHeight + 22); e.Graphics.DrawString(Math.Round(RANGELCL, 3).ToString(), f12, a2, 834, First_chartDatarectHeight + 22); //Mean Line Chart DrawLineChart(e.Graphics, intMeanArrayVals, XBARUCL, XBARLCL, PIC_SHANUSPC.Width - 70, 164, 60, 130, "MEAN"); DrawLineChart(e.Graphics, intRangeArrayVals, RANGEUCL, RANGELCL, PIC_SHANUSPC.Width - 70, 164, 60, 300, "RANGE"); //End 3)--------------------- }
对于 UCL 和 LCL,我们需要在计算中使用 A2、D4、D3 常数。 为此,我创建了一个名为“
UCLLCLTYPE
”的函数,该函数将返回这些常数。 例如,要计算 UCL 和 LCL,请参阅以下代码//In paint method, we have used this to call the UCL and LCL constant data. //XBARUCL to display in chart - >This is to calculate XBAR UCL XBARUCL = XDoublkeBAR + UCLLCLTYPE("A2", RBAR, NoofTrials); //XBARLCL to display in chart - >This is to calculate XBAR LCL XBARLCL = XDoublkeBAR - UCLLCLTYPE("A2", RBAR, NoofTrials); //RANGEUCL to display in chart RANGEUCL = UCLLCLTYPE("D4", RBAR, NoofTrials); //RANGELCL to display in chart RANGELCL = UCLLCLTYPE("D3", RBAR, NoofTrials); public double UCLLCLTYPE(String ControlUCLLCLType, Double RBAR, int NoofTrials) { Double Result = 0; Double A2Val = 0; Double D3val = 0; Double D4val = 0; //Constant value for the UCL and LCL calculation. if (ControlUCLLCLType == "A2") { switch (NoofTrials) { case 2: A2Val = 1.880; break; case 3: A2Val = 1.023; break; case 4: A2Val = 0.729; break; case 5: A2Val = 0.577; break; case 6: A2Val = 0.483; break; case 7: A2Val = 0.419; break; case 8: A2Val = 0.373; break; case 9: A2Val = 0.337; break; case 10: A2Val = 0.308; break; case 11: A2Val = 0.285; break; case 12: A2Val = 0.266; break; case 13: A2Val = 0.249; break; case 14: A2Val = 0.235; break; case 15: A2Val = 0.223; break; case 16: A2Val = 0.212; break; case 17: A2Val = 0.203; break; case 18: A2Val = 0.194; break; case 19: A2Val = 0.187; break; case 20: A2Val = 0.180; break; case 21: A2Val = 0.173; break; case 22: A2Val = 0.167; break; case 23: A2Val = 0.162; break; case 24: A2Val = 0.157; break; case 25: A2Val = 0.153; break; } Result = A2Val * RBAR; } else if (ControlUCLLCLType == "D3") { switch (NoofTrials) { case 2: D3val = 0; break; case 3: D3val = 0; break; case 4: D3val = 0; break; case 5: D3val = 0; break; case 6: D3val = 0; break; case 7: D3val = 0.076; break; case 8: D3val = 0.136; break; case 9: D3val = 0.184; break; case 10: D3val = 0.223; break; case 11: D3val = 0.256; break; case 12: D3val = 0.283; break; case 13: D3val = 0.307; break; case 14: D3val = 0.328; break; case 15: D3val = 0.347; break; case 16: D3val = 0.363; break; case 17: D3val = 0.378; break; case 18: D3val = 0.391; break; case 19: D3val = 0.403; break; case 20: D3val = 0.415; break; case 21: D3val = 0.425; break; case 22: D3val = 0.434; break; case 23: D3val = 0.443; break; case 24: D3val = 0.451; break; case 25: D3val = 0.459; break; } Result = D3val * RBAR; } else if (ControlUCLLCLType == "D4") { switch (NoofTrials) { case 2: D4val = 3.268; break; case 3: D4val = 2.574; break; case 4: D4val = 2.282; break; case 5: D4val = 2.114; break; case 6: D4val = 2.004; break; case 7: D4val = 1.924; break; case 8: D4val = 1.864; break; case 9: D4val = 1.816; break; case 10: D4val = 1.777; break; case 11: D4val = 1.744; break; case 12: D4val = 1.717; break; case 13: D4val = 1.693; break; case 14: D4val = 1.672; break; case 15: D4val = 1.653; break; case 16: D4val = 1.637; break; case 17: D4val = 1.622; break; case 18: D4val = 1.608; break; case 19: D4val = 1.597; break; case 20: D4val = 1.585; break; case 21: D4val = 1.575; break; case 22: D4val = 1.566; break; case 23: D4val = 1.557; break; case 24: D4val = 1.548; break; case 25: D4val = 1.541; break; } Result = D4val * RBAR; } return Result; }
- 完成保存后,构建并运行项目。
- 现在,我们创建一个 Windows 应用程序并添加和测试我们的“
SHANUXbarRangeChart
”用户控件。- 创建一个新的 Windows 项目。
- 打开您的表单,然后从工具箱 > 右键单击 > 选择项目 >,浏览选择您的用户控件 DLL 并添加。
- 将用户控件拖到您的 Windows 窗体上。
- 调用用户控件的“
Bindgrid
”方法并将Datatable
传递给Usercontrol
并检查结果。
private void button1_Click(object sender, EventArgs e) { loadgrid(); //shanuXBARChart is the User-control Name //here we call the function and pass the DataTable. shanuXBARChart.Bindgrid(dt); }
在“
loadgrid
”方法中,我将随机数据加载到DataTable
并显示在gridview
中。
结论
本文的主要目的是创建一个简单且标准的 SPC X-Bar 和 Range 图表用户控件。 我计划向图表中添加更多功能。
历史
- 2014/07/16:初始版本