private void buttonTest_Click(object sender, EventArgs e) { Mtb.Application MtbApp = new Mtb.Application(); Mtb.Project MtbProject = MtbApp.ActiveProject; Mtb.Worksheet MtbWorksheet = MtbProject.ActiveWorksheet; MtbApp.UserInterface.Visible = false; MtbApp.UserInterface.DisplayAlerts = false; try { //need to exe like %'c:\...\...\xx.mac' "99000R99" "1" string macro = "c:\\vm\\test.mac"; string robotname = "24010R01"; string appl = "Hand"; string subgroup = "Clamp"; MtbProject.ExecuteCommand("%'" + macro + "' \"" + robotname + "%\" \"" + appl + "%\" \"" + subgroup + "%\""); //MtbProject.ExecuteCommand("%'" + textBoxMacro.Text + "' \"" + textBoxRobot.Text + "\""); } catch (COMException ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } textBoxOutput.Text = "Commands count: " + MtbProject.Commands.Count + Environment.NewLine; for (int i = 1; i <= MtbProject.Commands.Count; i++) { textBoxOutput.Text += "*******************************************************************************" + Environment.NewLine; textBoxOutput.Text += "*******************************************************************************" + Environment.NewLine; textBoxOutput.Text += "Command " + i + Environment.NewLine; textBoxOutput.Text += "Command name: " + MtbProject.Commands.Item(i).Name + Environment.NewLine; textBoxOutput.Text += "Outputs count: " + MtbProject.Commands.Item(i).Outputs.Count + Environment.NewLine; for (int j = 1; j <= MtbProject.Commands.Item(i).Outputs.Count; j++) { textBoxOutput.Text += "-------------------------------------------------------------------------------" + Environment.NewLine; textBoxOutput.Text += "Output " + j + Environment.NewLine; textBoxOutput.Text += "Output type: " + MtbProject.Commands.Item(i).Outputs.Item(j).OutputType + Environment.NewLine; textBoxOutput.Text += "Output text: " + MtbProject.Commands.Item(i).Outputs.Item(j).Text + Environment.NewLine; if (MtbProject.Commands.Item(i).Outputs.Item(j).OutputType == Mtb.MtbOutputTypes.OTGraph) { MtbProject.Commands.Item(i).Outputs.Item(j).Graph.CopyToClipboard(); pictureBoxChart.Image = Clipboard.GetImage(); } } } while (MtbProject.Commands.Count > 0) { MtbProject.Commands.Remove(1); } }
static void Main(string[] args) { Mtb.Application mtbApp = new Mtb.Application(); Mtb.Project proj = mtbApp.ActiveProject; Mtb.Worksheet ws = proj.ActiveWorksheet; mtbApp.UserInterface.Visible = true; mtbApp.UserInterface.DisplayAlerts = false; proj.ExecuteCommand("rand 10 c1"); for (int i = 0; i < 1100; i++) { Console.WriteLine(i + 1); proj.ExecuteCommand(string.Format("Note line {0}", i + 1)); proj.Commands.Delete(); } Console.WriteLine("Done"); Console.ReadKey(); }
public BoxPlot(Mtb.Project proj, Mtb.Worksheet ws) : base(proj, ws) { SetDefault(); }
public override void Execute(Mtb.Project proj) { // 將資料匯入 Minitab if (RawData == null || RawData.Rows.Count == 0) { return; } _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉 proj.Commands.Delete(); proj.Worksheets.Delete(); Mtb.Worksheet ws = proj.Worksheets.Add(1); //新增工作表 Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab Mtb.Column bkCol = ws.Columns.Item("BK"); bkCol.Name = "斷絲率"; Mtb.Column grouCol = ws.Columns.Item("GROUP_DESC"); grouCol.Name = "紡位群"; grouCol.SetValueOrder(Mtb.MtbValueOrderTypes.WorksheetOrder); //如果沒有資料或欄位長度不一致就離開 if ((int)bkCol.DataType == 3 || (int)grouCol.DataType == 3 || (bkCol.RowCount != grouCol.RowCount)) { return; } StringBuilder cmnd = new StringBuilder(); cmnd.AppendLine("notitle"); cmnd.AppendLine("brief 0"); //繪製Boxplot cmnd.AppendFormat("boxplot ({0})*{1};\r\n", bkCol.SynthesizedName, grouCol.SynthesizedName); string gpath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("posidiff_{0}.jpg", _rawdata.TableName)); cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath); cmnd.AppendLine("repl;"); cmnd.AppendLine("jpeg;"); cmnd.AppendLine("iqrbox;"); cmnd.AppendLine("outl."); //計算統計量 cmnd.AppendFormat("stat {0};\r\n", bkCol.SynthesizedName); cmnd.AppendFormat("by {0};\r\n", grouCol.SynthesizedName); string[] colstr = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 5, Mtblib.Tools.MtbVarType.Column); Mtb.Column gvalCol = ws.Columns.Item(colstr[0]), meanCol = ws.Columns.Item(colstr[1]), stdevCol = ws.Columns.Item(colstr[2]), minCol = ws.Columns.Item(colstr[3]), maxCol = ws.Columns.Item(colstr[4]); cmnd.AppendFormat("mean {0};\r\n", meanCol.SynthesizedName); cmnd.AppendFormat("stdev {0};\r\n", stdevCol.SynthesizedName); cmnd.AppendFormat("mini {0};\r\n", minCol.SynthesizedName); cmnd.AppendFormat("maxi {0};\r\n", maxCol.SynthesizedName); cmnd.AppendFormat("gval {0}.\r\n", gvalCol.SynthesizedName); string mPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("Exec \"{0}\" 1", mPath), ws); if (File.Exists(gpath)) //如果檔案存在就加入報表內容 { _rptLst.Add( new RptOutput { OType = MtbOType.GRAPH, OutputInByteArr = File.ReadAllBytes(gpath) } ); } if (gvalCol.RowCount > 0 && (int)gvalCol.DataType != 3) // 有產出報表就加入報表 { DataTable descStatTable = Mtblib.Tools.MtbTools.GetDataTableFromMtbCols( new Mtb.Column[] { gvalCol, meanCol, stdevCol, minCol, maxCol }); if (descStatTable != null) { descStatTable.Columns[0].ColumnName = "紡位群組"; descStatTable.Columns[1].ColumnName = "平均"; descStatTable.Columns[2].ColumnName = "標準差"; descStatTable.Columns[3].ColumnName = "最小值"; descStatTable.Columns[4].ColumnName = "最大值"; _rptLst.Add( new RptOutput { OType = MtbOType.TABLE, OutputInByteArr = Tool.ConvertDataSetToByteArray(descStatTable) } ); } } }
public override void Execute(Mtb.Project proj) { // 將資料匯入 Minitab if (_rawdata == null || _rawdata.Rows.Count == 0) { throw new ArgumentNullException("查無對應資料"); } _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉 proj.Commands.Delete(); proj.Worksheets.Delete(); Mtb.Worksheet ws = proj.Worksheets.Add(1); //新增工作表 Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab StringBuilder cmnd = new StringBuilder(); /* * Create TSPlot * 該圖會將數據於多個平面中顯示(k*1的方式),所以要先設定 Panel 的安排方式 * */ cmnd.AppendLine("Unstack ('DateTime' 'Temperature');"); cmnd.AppendLine("Subscripts 'Area';"); cmnd.AppendLine("After;"); cmnd.AppendLine("VarNames."); for (int i = 0; i < CountPlotArea; i++) { cmnd.AppendLine(string.Format("NAME C{0} '{1}'.", 4 + 2 * (i + 1), AreaArray[i])); } string tmpCmnd = "Tsplot "; for (int i = 0; i < CountPlotArea; i++) { tmpCmnd = tmpCmnd + string.Format("C{0} ", (i + 3) * 2); } tmpCmnd = tmpCmnd + ";"; cmnd.AppendLine(tmpCmnd); string gpath_tsplot = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("trend_{0}.jpg", _rawdata.TableName)); cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath_tsplot); cmnd.AppendLine("repl;"); cmnd.AppendLine("jpeg;"); cmnd.AppendLine("Scale 2;"); cmnd.AppendLine("Min 100;"); cmnd.AppendLine("Max 600;"); cmnd.AppendLine("Min 100;"); cmnd.AppendLine("Max 600;"); cmnd.AppendLine("Same 2;"); cmnd.AppendLine("Panel;"); cmnd.AppendLine("Index;"); cmnd.AppendLine("Stamp C3;"); cmnd.AppendLine("Connect;"); cmnd.AppendLine("Symbol;"); cmnd.AppendLine("Type 6;"); cmnd.AppendLine("Color 4;"); cmnd.AppendLine("Size 0.7;"); cmnd.AppendLine("Title;"); cmnd.AppendLine("Footnote;"); cmnd.AppendLine("FPer;"); cmnd.AppendLine("Footnote;"); cmnd.AppendLine("FPanel;"); cmnd.AppendLine("NoDTitle;"); cmnd.AppendLine("NoPerFootnote."); //刪除所有圖形 cmnd.AppendLine("gmana;"); cmnd.AppendLine("all;"); cmnd.AppendLine("close;"); cmnd.AppendLine("nopr."); string fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("exec \"{0}\" 1", fpath), ws); //將檔案轉為二進位陣列 if (File.Exists(gpath_tsplot)) { this.Contents.Add(new RptOutput() { OType = MtbOType.GRAPH, OutputInByteArr = File.ReadAllBytes(gpath_tsplot), Tag = "TSPlot" }); } //Tsplot 'Temperature_1' 'Temperature_2'; //Scale 2; // Min 100; // Max 600; // Min 100; // Max 600; //Same 2; //Panel; //Index; //Stamp 'Plant_2'; //Connect; //Symbol; //Title; //Footnote; // FPer; //Footnote; // FPanel; //NoDTitle; //NoPerFootnote. this.Tag = "TSPlot"; }
public override void Execute(Mtb.Project proj) { if (_rawdata == null || _rawdata.Rows.Count == 0) { return; } _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉 Mtb.Worksheet ws = proj.Worksheets.Add(1); //新增工作表 Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab List <string> varnames = new List <string>(); List <Mtb.Column> varCols = new List <Mtb.Column>(); //變數的欄位集合 for (int i = 0; i < _rawdata.Columns.Count; i++) { DataColumn col = _rawdata.Columns[i]; switch (col.ColumnName) { case "TIMESTAMP": case "CHART_PARA_INDEX": break; default: varnames.Add(col.ColumnName); varCols.Add(ws.Columns.Item(col.ColumnName)); break; } } Mtb.Column timeCol = ws.Columns.Item("TIMESTAMP"); foreach (var col in varCols) { if ((int)col.DataType == 3 || col.MissingCount == col.RowCount) { throw new ArgumentNullException(string.Format("[{0}]查無資料-多變量管制圖", col.Name)); } } StringBuilder cmnd = new StringBuilder(); cmnd.AppendLine("notitle"); cmnd.AppendLine("brief 0"); cmnd.AppendFormat("fdate {0};\r\n", timeCol.SynthesizedName); cmnd.AppendLine("format(dtyyyy-MM-dd hh:mm)."); cmnd.AppendFormat("tsplot {0};\r\n", string.Join(" ", varCols.Select(x => x.SynthesizedName))); double gHeight = 4; if (varCols.Count > 4) { gHeight = Math.Min(30, 4 + ((double)varCols.Count - 4) * 0.8); } cmnd.AppendFormat("graph 8 {0};\r\n", gHeight); string gpath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("overlytrnd_{0}.jpg", _rawdata.TableName)); cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath); cmnd.AppendLine("repl;"); cmnd.AppendLine("jpeg;"); cmnd.AppendFormat("stamp {0};\r\n", timeCol.SynthesizedName); cmnd.AppendLine("axlab 1;"); cmnd.AppendLine("adis 0;"); cmnd.AppendLine("scale 1;"); cmnd.AppendLine(" psize 7;"); cmnd.AppendLine(" angle 90;"); cmnd.AppendLine("scale 2;"); cmnd.AppendLine(" psize 8;"); cmnd.AppendLine("symbol;"); cmnd.AppendLine("conn;"); cmnd.AppendLine("pane;"); cmnd.AppendFormat("rc {0} 1;\r\n", varCols.Count); cmnd.AppendLine("label;"); cmnd.AppendLine(" psize 8;"); cmnd.AppendLine("noal;"); cmnd.AppendLine("nodt."); //刪除所有圖形 cmnd.AppendLine("gmana;"); cmnd.AppendLine("all;"); cmnd.AppendLine("close;"); cmnd.AppendLine("nopr."); string macroPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("exec \"{0}\" 1", macroPath), ws); //將檔案轉為二進位陣列 this.Contents.Add(new RptOutput() { OType = MtbOType.GRAPH, OutputInByteArr = File.ReadAllBytes(gpath) }); }
/// <summary> /// 計算穩定狀態下的參數組(單一觀測值),使用一般的 Variance-Covariance Matrix 去計算,而非 Sullivan-Woodall /// </summary> /// <param name="data">欲使用的資料表</param> /// <returns></returns> public TsquareParameters Execute(Algebra.Matrix <double> data, Mtb.Project proj) { //確認基本資訊能否計算 int p = data.ColumnCount; int m = data.RowCount; if (m - p <= 0) { throw new Exception(string.Format("樣本數不可低於{0},請重新確認。", p)); } //組合管制界線指令並計算 Phase1 的 limit double ucl; StringBuilder cmnd = new StringBuilder(); cmnd.AppendLine("invCdf 0.9973 k1;"); cmnd.AppendFormat("Beta {0} {1}.\r\n", (double)p / 2, (double)(m - p - 1) / 2); cmnd.AppendFormat("let k1=(({0}-1)**2)/{0}*k1\r\n", m); try { Mtb.Worksheet ws = proj.Worksheets.Add(1); string fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("Exec \"{0}\" 1", fpath), ws); ucl = ws.Constants.Item("k1").GetData(); ws.Delete(); proj.Commands.Delete(); } catch (Exception e) { throw new Exception(e.Message); } double miss = Mtblib.Tools.MtbTools.MISSINGVALUE; var M = Algebra.Matrix <double> .Build; //計算 Mean vector & Covariance matrix IEnumerable <Algebra.Vector <double> > cols = data.EnumerateColumns(); var mean = M.DenseOfColumnMajor(1, data.ColumnCount, cols.Select(x => x.Where(o => o < miss).Average())); var subData = M.DenseOfRows((data.EnumerateRows().Where(x => x.All(y => y < miss)).ToArray())); var diff = subData - M.Dense(subData.RowCount, 1, (i, j) => 1).Multiply(mean); var cov = diff.Transpose().Multiply(diff) / (subData.RowCount - 1); var invS = cov.Inverse(); TsquareParameters tsquarePara = new TsquareParameters() { Mean = mean, Covariance = cov, SampleSize = m, SubgroupSize = 1 }; //計算出資料的Tsquare value List <double> t2 = new List <double>(); for (int i = 0; i < data.RowCount; i++) { if (data.Row(i).ToArray().All(x => x < miss)) { t2.Add(Tool.CalculateTSquare(data.Row(i).ToRowMatrix(), mean, invS)); } else { t2.Add(miss); } } if (t2.Any(x => x >= ucl && x < miss)) { int[] oocRow = t2.Select((x, i) => new { Tsquare = x, Index = i }).Where(x => x.Tsquare >= ucl && x.Tsquare < miss).Select(x => x.Index).OrderByDescending(x => x).ToArray(); subData = data.Clone(); //逐列移除OOC的資料列 for (int i = 0; i < oocRow.Length; i++) { subData = subData.RemoveRow(oocRow[i]); } tsquarePara = Execute(subData, proj); } return(tsquarePara); }
public override void Execute(Mtb.Project proj) { // 將資料匯入 Minitab if (_rawdata == null || _rawdata.Rows.Count == 0) { throw new ArgumentNullException("查無對應資料"); } _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉,因為 Cotent 唯讀 proj.Commands.Delete(); proj.Worksheets.Delete(); Mtb.Worksheet ws = proj.Worksheets.Add(1); //新增工作表 Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab List <Mtb.Column> varCols = new List <Mtb.Column>(); //變數的欄位集合 varCols.Add(ws.Columns.Item("VALUE")); Mtb.Column timeCol = ws.Columns.Item("TEST_DATE"); #region Create Minitab command StringBuilder cmnd = new StringBuilder(); cmnd.AppendLine("notitle"); cmnd.AppendLine("brief 0"); cmnd.AppendFormat("fdate {0};\r\n", timeCol.SynthesizedName); cmnd.AppendLine("format(dtyyyy-MM-dd)."); cmnd.AppendFormat("tsplot {0};\r\n", string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName))); cmnd.AppendFormat(" stamp {0};\r\n", timeCol.SynthesizedName); string propName = ws.Columns.Item("PROD_NAME").GetData(1, 1); string compName = ws.Columns.Item("ITEM_NAME").GetData(1, 1); string unitName = ws.Columns.Item("ITEM_UNIT").GetData(1, 1); string gpath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("trend_{0}_{1}.jpg", propName, compName)); cmnd.AppendFormat(" gsave \"{0}\";\r\n", gpath); cmnd.AppendLine(" repl;"); cmnd.AppendLine(" jpeg;"); cmnd.AppendFormat(" axlab 2 \"{0}({1})\";\r\n", compName, unitName); cmnd.AppendLine(" scale 1;"); cmnd.AppendLine(" angle 90;"); cmnd.AppendLine(" axlab 1;"); cmnd.AppendLine(" adis 0;"); cmnd.AppendLine(" conn;"); cmnd.AppendLine(" symb;"); cmnd.AppendLine(" size 2;"); cmnd.AppendLine(" nodt."); cmnd.AppendLine("brief 2"); cmnd.AppendFormat("Desc {0};\r\n", string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName))); //cmnd.AppendFormat(" by {0};\r\n"); cmnd.AppendLine(" n;"); cmnd.AppendLine(" mean;"); cmnd.AppendLine(" stdev;"); cmnd.AppendLine(" mini;"); cmnd.AppendLine(" maxi;"); cmnd.AppendLine(" ztag \"DESC\"."); cmnd.AppendLine("brief 0"); //刪除所有圖形 cmnd.AppendLine("gmana;"); cmnd.AppendLine("all;"); cmnd.AppendLine("close;"); cmnd.AppendLine("nopr."); #endregion string fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("exec \"{0}\" 1", fpath), ws); //取得圖和敘述統計量 try { if (File.Exists(gpath)) { this.Contents.Add(new RptOutput() { OType = MtbOType.GRAPH, OutputInByteArr = File.ReadAllBytes(gpath), Tag = "Trend" }); } } catch (Exception ex) { this.Contents.Add(new RptOutput() { OType = MtbOType.GRAPH, OutputInByteArr = null, Tag = "Trend" }); } #region 取得敘述統計量表格 try { //將報表結果放到 DataTable DataTable dt = new DataTable(); //取得結果的 html string string htmlCmnd = proj.Commands.Cast <Mtb.Command>().Where(x => x.Tag == "DESC").Select(x => x.Outputs).FirstOrDefault().Item(2).HTMLText; var htmlDoc = new HtmlDocument(); htmlDoc.LoadHtml(htmlCmnd); //取得並設定表頭 htmlDoc.LoadHtml(htmlDoc.DocumentNode.SelectSingleNode("//tr").OuterHtml); var htmlHeader = htmlDoc.DocumentNode.SelectSingleNode("//tr"); foreach (var cell in htmlHeader.SelectNodes("//td")) { if (cell.InnerText != "\n") { dt.Columns.Add(cell.InnerText); } } //取得表格內容 htmlDoc.LoadHtml(htmlCmnd); var htmlRows = htmlDoc.DocumentNode.SelectNodes("//table/tr"); DataRow dr; HtmlDocument tmpHtmlDoc = new HtmlDocument(); for (int i = 1; i < htmlRows.Count; i++) { dr = dt.NewRow(); var row = htmlRows[i]; tmpHtmlDoc.LoadHtml(row.OuterHtml); var xx = tmpHtmlDoc.DocumentNode.SelectNodes("//td").Select(x => x.InnerText).ToArray(); dr.ItemArray = xx; dt.Rows.Add(dr); } //轉成 DataTable this.Contents.Add(new RptOutput() { OType = MtbOType.TABLE, OutputInByteArr = Tool.ConvertDataSetToByteArray(dt), Tag = "Table" }); } catch (Exception ex) { this.Contents.Add(new RptOutput() { OType = MtbOType.TABLE, OutputInByteArr = null, Tag = "Table" }); } #endregion }
public Dictionary <string, object> MtbAnalysis(string chartType, Dictionary <string, string> rules) { try { foreach (Process proc in Process.GetProcessesByName("Mtb")) { proc.Kill(); } } catch (Exception ex) {} System.IO.FileInfo imgFile = new System.IO.FileInfo(imgDir + this.controlId + "_" + chartType + ".PNG"); if (imgFile.Exists) { imgFile.Delete(); } Mtb.Application MtbApp = new Mtb.Application(); Dictionary <string, object> resultObject = new Dictionary <string, object>(); try { MtbApp.UserInterface.Visible = false; Mtb.Project MtbProj = MtbApp.ActiveProject; Mtb.Columns MtbColumns = MtbProj.ActiveWorksheet.Columns; //加载dt所有数据到mtb for (int i = 0; i < endColumn; i++) { Mtb.Column MtbColumn1 = MtbColumns.Add(null, null, 1); ArrayList columnData = new ArrayList(); for (int j = 0; j < dt.Rows.Count; j++) { if (dt.Rows[j][i].ToString().Length < 1) { columnData.Add(DBNull.Value); } else { columnData.Add(dt.Rows[j][i]); } } MtbColumn1.SetData(columnData.ToArray()); } int rawColumnCount = MtbColumns.Count; //Minitab 控制图 or 能力分析命令。 //命令先生成,先调用checkRule()方法检查规则数量,以及对应生成的检验结果列数 string execAnalysis = this.GetExcuteCommands(chartType, rules); //Minitab 分析结果存储列命令 string varCommand = this.GetVarCommands(chartType); if (!string.IsNullOrEmpty(varCommand)) { MtbProj.ExecuteCommand(varCommand); } if (!string.IsNullOrEmpty(execAnalysis)) { MtbProj.ExecuteCommandAsync(execAnalysis); } Mtb.Output MtbOut = null; try { MtbOut = MtbProj.Commands.Item(MtbProj.Commands.Count).Outputs.Item(1); Console.WriteLine("Normal output!Normal output!Normal output!"); } catch (Exception ex) { MtbOut = MtbProj.Commands.Item(MtbProj.Commands.Count).Outputs.Item(1); Console.WriteLine("Unormal output!Unormal output!Unormal output!"); } //Minitab 图形保存 Mtb.Graph MtbGraph = MtbOut.Graph; MtbGraph.SaveAs(imgDir + this.controlId + "_" + chartType, true, Mtb.MtbGraphFileTypes.GFPNGHighColor, 790, 500); //Minitab 工作区表保存 Mtb.Worksheet MtbSheet = MtbProj.ActiveWorksheet; MtbSheet.SaveAs(imgDir + this.controlId + "_" + chartType, true); for (int i = 1; i <= MtbSheet.Columns.Count; i++) { resultObject.Add(MtbSheet.Columns.Item(i).Name, MtbSheet.Columns.Item(i).GetData()); } if (chartType.Contains("Chart")) { resultObject.Add("RuleOut", MtbProj.Commands.OutputDocument.Text); } MtbProj.Delete(); MtbApp.Quit(); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { MtbApp.Quit(); } return(resultObject); }
public override void Execute(Mtb.Project proj) { // 將資料匯入 Minitab if (_rawdata == null || _rawdata.Rows.Count == 0) { throw new ArgumentNullException("查無對應資料"); } _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉 proj.Commands.Delete(); proj.Worksheets.Delete(); Mtb.Worksheet ws = proj.Worksheets.Add(1); //新增工作表 Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab List <Mtb.Column> varCols = new List <Mtb.Column>(); //變數的欄位集合 List <Mtb.Column> bkCol = new List <Mtb.Column>(); //斷絲率的集合 Mtb.Column timeCol = null; for (int i = 0; i < _rawdata.Columns.Count; i++) { DataColumn col = _rawdata.Columns[i]; switch (col.ColumnName) { case "TIMESTAMP": timeCol = ws.Columns.Item(col.ColumnName); break; case "RPT_TIMEHOUR": case "GROUP_ID": break; case "BK": bkCol.Add(ws.Columns.Item(col.ColumnName)); break; default: varCols.Add(ws.Columns.Item(col.ColumnName)); break; } } foreach (var col in bkCol) { if ((int)col.DataType == 3 || col.MissingCount == col.RowCount) { throw new ArgumentNullException(string.Format("[{0}]查無資料", col.Name)); } } foreach (var col in varCols) { if ((int)col.DataType == 3 || col.MissingCount == col.RowCount) { throw new ArgumentNullException(string.Format("[{0}]查無資料", col.Name)); } } StringBuilder cmnd = new StringBuilder(); /* * Create TSPlot * 該圖會將數據於多個平面中顯示(k*1的方式),所以要先設定 Panel 的安排方式 * */ cmnd.AppendLine("notitle"); cmnd.AppendLine("brief 0"); cmnd.AppendFormat("fdate {0};\r\n", timeCol.SynthesizedName); cmnd.AppendLine("format(dtyyyy-MM-dd hh:mm)."); cmnd.AppendFormat("tsplot {0} {1};\r\n", string.Join(" &\r\n", bkCol.Select(x => x.SynthesizedName)), string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName))); double gHeight = 4; if (varCols.Count > 3) { gHeight = Math.Min(30, 4 + ((double)varCols.Count - 3) * 0.8); } cmnd.AppendFormat("graph 8 {0};\r\n", gHeight); string gpath_trend = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("trend_{0}.jpg", _rawdata.TableName)); cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath_trend); cmnd.AppendLine("repl;"); cmnd.AppendLine("jpeg;"); cmnd.AppendLine("panel;"); cmnd.AppendFormat("rc {0} 1;\r\n", varCols.Count + bkCol.Count); cmnd.AppendLine("noal;"); cmnd.AppendLine("label;"); cmnd.AppendLine(" psize 8;"); cmnd.AppendLine("scale 1;"); cmnd.AppendLine(" psize 8;"); cmnd.AppendLine("axlab 1;"); cmnd.AppendLine("lshow;"); cmnd.AppendLine(" angle 90;"); cmnd.AppendLine("scale 2;"); cmnd.AppendLine(" psize 8;"); if (timeCol != null && (int)timeCol.DataType != 3) { cmnd.AppendFormat("stamp {0};\r\n", timeCol.SynthesizedName); } cmnd.AppendLine("symb;"); cmnd.AppendLine("conn;"); //cmnd.AppendFormat("foot \"建立時間: {0}\";\r\n", DateTime.Now); cmnd.AppendLine("nodt."); //Create Matrix Plot cmnd.AppendFormat("matrixplot ({0})*({1});\r\n", string.Join(" &\r\n", bkCol.Select(x => x.SynthesizedName)), string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName))); double gWidth = 8; if (varCols.Count > 5) { gWidth = Math.Min(30, 8 + ((double)varCols.Count - 5) * 0.8); } cmnd.AppendFormat("graph {0} 5;\r\n", gWidth); string gpath_corr = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("corr_{0}.jpg", _rawdata.TableName)); cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath_corr); cmnd.AppendLine("repl;"); cmnd.AppendLine("jpeg;"); cmnd.AppendLine("scale 1;"); cmnd.AppendLine(" psize 8;"); cmnd.AppendLine("nojitter;"); cmnd.AppendLine("full;"); cmnd.AppendLine("bound;"); cmnd.AppendLine("noal;"); cmnd.AppendLine("regr;"); cmnd.AppendLine("symb;"); cmnd.AppendLine("nodt."); //Calculate correlation coefficient string[] matIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 1, Mtblib.Tools.MtbVarType.Matrix); cmnd.AppendFormat("corr {0} {1} {2}\r\n", string.Join(" &\r\n", bkCol.Select(x => x.SynthesizedName)), string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName)), string.Join(" &\r\n", matIds) ); //刪除所有圖形 cmnd.AppendLine("gmana;"); cmnd.AppendLine("all;"); cmnd.AppendLine("close;"); cmnd.AppendLine("nopr."); string fpath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("exec \"{0}\" 1", fpath), ws); //將檔案轉為二進位陣列 if (File.Exists(gpath_trend)) { this.Contents.Add(new RptOutput() { OType = MtbOType.GRAPH, OutputInByteArr = File.ReadAllBytes(gpath_trend), Tag = "Trend" }); } if (File.Exists(gpath_corr)) { this.Contents.Add(new RptOutput() { OType = MtbOType.GRAPH, OutputInByteArr = File.ReadAllBytes(gpath_corr), Tag = "Scatter" }); } //Create Correlation table DataTable corrTable = new DataTable(); corrTable.Columns.Add("熔爐項目", typeof(string)); corrTable.Columns.Add("與斷絲率相關係數", typeof(double)); var corrMat = ws.Matrices.Item(matIds[0]).GetData(); double[] subCorr = new double[varCols.Count]; double[] corr = corrMat as double[]; if (corr != null) { Array.Copy(corr, 1, subCorr, 0, varCols.Count); string[] labNames = varCols.Select(x => x.Name).ToArray(); DataRow dr; for (int i = 0; i < subCorr.Length; i++) { dr = corrTable.NewRow(); dr[0] = labNames[i]; dr[1] = (object)Math.Round(subCorr[i], 3); corrTable.Rows.Add(dr); } } this.Contents.Add(new RptOutput() { OType = MtbOType.TABLE, OutputInByteArr = Tool.ConvertDataSetToByteArray(corrTable) }); }
private void btQuery_Click(object sender, EventArgs e) { // // 收集資訊 // //User string user_id = ""; if (!string.IsNullOrWhiteSpace(cbUser.Text)) { user_id = "'" + cbUser.SelectedValue.ToString() + "'"; } //Purpose string purpose = ""; if (!string.IsNullOrWhiteSpace(textPurpose.Text)) { purpose = "'%" + textPurpose.Text.ToUpper() + "%'"; } //Prod type string prodType = ""; if (oProdTypeCollection != null && oProdTypeCollection.Count > 0) { List <string> tmp = new List <string>(); foreach (string item in oProdTypeCollection) { tmp.Add("'" + item + "'"); } prodType = string.Join(",", tmp); } //C tool string c_tool = ""; if (!string.IsNullOrWhiteSpace(cbCTool.Text)) { c_tool = "'" + cbCTool.SelectedValue.ToString() + "'"; } //Lot string lot = ""; if (oLotCollection != null && oLotCollection.Count > 0) { List <string> tmp = new List <string>(); tmp = oLotCollection.Select(x => "'" + x + "'").ToList(); lot = string.Join(",", tmp); } //customer string customer_id = ""; if (!string.IsNullOrWhiteSpace(cbCustomer.Text)) { customer_id = "'" + cbCustomer.SelectedValue.ToString() + "'"; } //datetime string start_date_time = "'" + dtPickerExpStartDate.Value.ToString("yyyy-MM-dd") + "'"; string end_date_time = "'" + dtPickerExpEndDate.Value.ToString("yyyy-MM-dd") + "'"; try { List <string> conditionList = new List <string>(); //組出基本條件 if (user_id != "") { conditionList.Add(string.Format("a.emp_id={0}", user_id)); } if (purpose != "") { conditionList.Add(string.Format("upper(a.purpose) like {0}", purpose)); } if (prodType != "") { conditionList.Add(string.Format("a.type in ({0})", prodType)); } if (c_tool != "") { conditionList.Add(string.Format("a.c_tool_id={0}", c_tool)); } if (lot != "") { conditionList.Add(string.Format("a.lot_id in ({0})", lot)); } conditionList.Add(string.Format("a.exp_date between {0} and {1}", start_date_time, end_date_time)); string conditionBasic = string.Join(" and ", conditionList); Dictionary <string, string> pivotInfo = new Dictionary <string, string>(); using (NpgsqlConnection conn = new NpgsqlConnection(_connString)) { conn.Open(); //先把大條件下的資料抓出,確認有多少 item 要 pivot using (NpgsqlDataAdapter da = new NpgsqlDataAdapter("", conn)) { string commandstring = "select distinct b.item_id, b.item_name,b.item_flag, b.unit, a.type from " + "exp_sum a, exp_detail b " + "where a.exp_sum_index = b.exp_sum_index and a.lot_id is not null and b.item_flag ~ '[PR]+' " + (string.IsNullOrEmpty(conditionBasic) ? "" : " and " + conditionBasic) + " order by b.item_flag desc"; da.SelectCommand.CommandText = commandstring; DataTable dt = new DataTable(); da.Fill(dt); //pivotCols = dt.Rows.Cast<DataRow>().Select(x => x["item_name"].ToString()).ToArray(); //pivotItemId = dt.Rows.Cast<DataRow>().Select(x => x["item_id"].ToString()).ToArray(); pivotInfo = dt.Rows.Cast <DataRow>().ToDictionary(x => x["item_id"].ToString(), x => x["item_name"].ToString() + "[" + x["unit"].ToString() + "]" + (x["item_flag"].ToString() == "P" ? string.Format("{{{0}}}", x["type"].ToString()) : "") ); } } //建立 pivot 後的欄位組 if (pivotInfo == null || pivotInfo.Count == 0) { MessageBox.Show(null, "無符合條件資料", "", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } // // 處理子條件 (配方、物性指定項或上下限),同時過濾出主條件中無法查詢之項目, // 因為 pivot 後項目會變成欄位,不存在的項目會引起查詢錯誤。 // Dictionary <string, string> invalidItems = new Dictionary <string, string>(); //取出 Recipe 的條件 conditionList.Clear(); foreach (DataGridViewRow item in dgViewFormula.Rows) { string id = item.Cells["colRId"].Value.ToString(); if (pivotInfo.ContainsKey(id)) { if (item.Cells["colRLower"].Value != null && !string.IsNullOrWhiteSpace(item.Cells["colRLower"].Value.ToString())) { conditionList.Add(string.Format("\"{0}\"::numeric>={1}", id, item.Cells["colRLower"].Value.ToString())); } if (item.Cells["colRUpper"].Value != null && !string.IsNullOrWhiteSpace(item.Cells["colRUpper"].Value.ToString())) { conditionList.Add(string.Format("\"{0}\"::numeric<={1}", id, item.Cells["colRUpper"].Value.ToString())); } if ((item.Cells["colRLower"].Value == null || string.IsNullOrWhiteSpace(item.Cells["colRLower"].Value.ToString())) && //如果沒有填上下限,表示實驗中一定要包含此項 (item.Cells["colRUpper"].Value == null || string.IsNullOrWhiteSpace(item.Cells["colRUpper"].Value.ToString()))) { conditionList.Add(string.Format("\"{0}\" is not null", id)); } } else { //因為 UI 不卡重複項目,所以要避免加入相同 id if (!invalidItems.ContainsKey(id)) { invalidItems.Add(id, item.Cells["colRName"].Value.ToString()); } } } //取出 Property 的條件 foreach (DataGridViewRow item in dgViewProperty.Rows) { string id = item.Cells["colPId"].Value.ToString(); if (pivotInfo.ContainsKey(id)) { if (item.Cells["colPLower"].Value != null && !string.IsNullOrWhiteSpace(item.Cells["colPLower"].Value.ToString())) { conditionList.Add(string.Format("\"{0}\"::numeric>={1}", id, item.Cells["colPLower"].Value.ToString())); } if (item.Cells["colPUpper"].Value != null && !string.IsNullOrWhiteSpace(item.Cells["colPUpper"].Value.ToString())) { conditionList.Add(string.Format("\"{0}\"::numeric<={1}", id, item.Cells["colPUpper"].Value.ToString())); } if ((item.Cells["colPLower"].Value == null || string.IsNullOrWhiteSpace(item.Cells["colPLower"].Value.ToString())) && //如果沒有填上下限,表示實驗中一定要包含此項 (item.Cells["colPUpper"].Value == null || string.IsNullOrWhiteSpace(item.Cells["colPUpper"].Value.ToString()))) { conditionList.Add(string.Format("\"{0}\" is not null", id)); } } else { //因為 UI 不卡重複項目,所以要避免加入相同 id if (!invalidItems.ContainsKey(id)) { invalidItems.Add(id, item.Cells["colPName"].Value.ToString()); } } } //若存在無效的條件,詢問是否繼續查詢? if (invalidItems.Count > 0) { string msg = string.Join(", ", invalidItems.Select(x => x.Value).ToArray()); if (MessageBox.Show(this, string.Format("以下查詢項目:\r\n{0}\r\n未出現在實驗結果或指定的查詢範圍內。\r\n\r\n是否忽略這些條件繼續查詢?", msg), "", MessageBoxButtons.YesNo, MessageBoxIcon.Information ) == System.Windows.Forms.DialogResult.No) { return; } } //建立最後要使用的配方、物性條件 string conditionAddtional = string.Join(" and ", conditionList); using (NpgsqlConnection conn = new NpgsqlConnection(_connString)) { conn.Open(); using (NpgsqlDataAdapter da = new NpgsqlDataAdapter("", conn)) { List <string> ctstring = new List <string>(); ctstring.Add("exp_sum_index text"); foreach (string itemId in pivotInfo.Keys.OrderBy(x => x)) { ctstring.Add(@"""" + itemId + @""" text"); } // // crosstab 裡面要用單引號 // da.SelectCommand.CommandText = "with t1 as (select * from crosstab($$select a.exp_sum_index::text, b.item_id::text, b.item_value::text from exp_sum a " + "join exp_detail b on a.exp_sum_index = b.exp_sum_index where a.lot_id is not null " + "and b.item_flag~'[PR]+'" + (string.IsNullOrEmpty(conditionBasic) ? "" : " and " + conditionBasic) + " order by 1,2 $$) AS ct(" + string.Join(",", ctstring) + ")) " + "select a.lot_id, b.emp_ename, c.customer_ename, a.c_tool_id, a.i_tool_id, a.type, d.* , a.remark " + "from exp_sum a, employee b, customer c, t1 d " + "where a.exp_sum_index = d.exp_sum_index " + "and a.customer_id = c.customer_id " + "and a.emp_id = b.emp_id" + //add condition for r_item and p_item conditionAddtional (string.IsNullOrEmpty(conditionAddtional) ? "" : " and " + conditionAddtional); DataTable dt = new DataTable(); da.Fill(dt); for (int i = 6; i < dt.Columns.Count - 1; i++) // r_item and p_item start from 7th and the last two columns { DataColumn col = dt.Columns[i]; string colName; pivotInfo.TryGetValue(col.ColumnName, out colName); col.ColumnName = colName ?? col.ColumnName; } // // 把資料回填 Minitab // if (_proj != null) { //Mtb.Worksheet ws = _proj.ActiveWorksheet; Mtb.Worksheet ws = _proj.Worksheets.Add(1); string[] colIdString = Tools.MtbTools.CreateVariableStrArray(ws, dt.Columns.Count, MtbVarType.Column); for (int i = 0; i < dt.Columns.Count; i++) { DataColumn col = dt.Columns[i]; ws.Columns.Item(colIdString[i]).Name = col.ColumnName; var dataarray = dt.Rows.Cast <DataRow>().Select(x => x[col.ColumnName] == System.DBNull.Value ? "" : x[col.ColumnName]).ToArray(); ws.Columns.Item(colIdString[i]).SetData(dataarray); } ws.Columns.Item("exp_sum_index").Delete(); ws = null; } } } } catch (Exception ex) { MessageBox.Show(null, "查詢時發生錯誤: " + ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } finally { MessageBox.Show(null, "查詢完成 ", "", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
/// <summary> /// 判斷individaul T2管制圖的參數是否合法? 如果合法不回發生任何事,若不合法則回傳例外。 /// </summary> /// <param name="paraSet"></param> /// <returns></returns> private void ParaValidation(ParaSetInfo paraSet) { DataTable mean = paraSet.Mean; DataTable cov = paraSet.Cov; int? ssiz = paraSet.SampleSize; if (mean == null || cov == null) { throw new ArgumentNullException("尚未輸入平均數向量或共變異數矩陣"); } if (SampleSize == null || SampleSize <= 0) { throw new Exception("樣本數內容不正確"); } //確認輸入的數據是否正確(數量、共變異矩陣對稱、對角項大於0、正定等特性) int r = cov.Columns.Count; int c = cov.Rows.Count; double result; if (mean.Rows.Cast <DataRow>().Any(x => x.ItemArray.Any(y => !Double.TryParse(y.ToString(), out result)))) { throw new Exception("平均數欄位內容必須為數字"); } if (cov.Rows.Cast <DataRow>().Any(x => x.ItemArray.Any(y => !Double.TryParse(y.ToString(), out result)))) { throw new Exception("共變異數內容必須為數字"); } //將共變異數矩陣轉到Minitab中判斷是否合法 double[] covArray = new double[r * c]; for (int cCnt = 0; cCnt < c; cCnt++) { for (int rCnt = cCnt; rCnt < r; rCnt++) { if (rCnt == cCnt) { double value = double.Parse(cov.Rows[rCnt][cCnt].ToString()); if (value <= 0) { throw new Exception("共變異數矩陣對角項小於等於0"); } covArray[cCnt * r + rCnt] = value; } else { if (cov.Rows[rCnt][cCnt].ToString() != cov.Rows[cCnt][rCnt].ToString()) { throw new Exception("共變異數矩陣不對稱"); } double value = double.Parse(CovarianceMatrix.Rows[rCnt][cCnt].ToString()); covArray[cCnt * r + rCnt] = value; covArray[rCnt * r + cCnt] = value; } } } Mtb.Worksheet ws = Project.Worksheets.Add(1); Mtb.Matrix mat = ws.Matrices.Add(Quantity: 1); Mtb.Column col = ws.Columns.Add(Quantity: 1); mat.SetData(covArray, 1, 1); Project.ExecuteCommand(string.Format("Eigen {0} {1}.\r\n", mat.SynthesizedName, col.SynthesizedName), ws); double[] eigvalue = col.GetData(); if (eigvalue.Any(x => x <= 0)) { throw new Exception("共變異數矩陣不為正定"); } ws.Delete(); Project.Commands.Delete(); }
public static Mtb.Column[] GetMatchColumns(string colsText, Mtb.Worksheet ws) { // // 如果輸入的字串是 empty string, null or white space 丟出例外 // if (string.IsNullOrEmpty(colsText) || string.IsNullOrWhiteSpace(colsText)) { throw new ArgumentNullException("Too few items.", new Exception()); } // // 準備 Minitab 欄位 // Mtb.Column[] cols = ws.Columns.Cast <Mtb.Column>().ToArray(); string[] colLabel = cols.Select(x => x.Label).ToArray(); string[] colNames = cols.Select(x => x.Name).ToArray(); string[] colId = cols.Select(x => x.SynthesizedName).ToArray(); List <Mtb.Column> selCols = new List <Mtb.Column>(); Regex regex = new Regex(@"(?<=\s|^)(([']).*?([']))(?=\s|$)|(?<=\s|^)(.*?)(?=\s|$)"); // // (?<=\s|^)(([']).*?([']))(?=\s|b): 處理用 quoted name // ==> 取得後判斷是否有違法的字元 // (?<=\s|^)(.*?)(?=\s|$): 處理 non-quoted name // ==> 取得後判斷是否是 1)遺漏 quote 2)有違法字元 // // 違法字元包含: ', # 或單獨一個* // MatchCollection matches = regex.Matches(colsText); Regex invalidRegex = new Regex(@"['#]+"); foreach (Match match in matches) { string matchString = match.Groups[0].Value; string name; //該 pattern 也會抓到 empty string, 所以要另外處理 ==> 跳過 if (string.IsNullOrWhiteSpace(match.Groups[0].Value) || string.IsNullOrEmpty(match.Groups[0].Value)) { continue; } if (match.Groups[1].Success == true) // quoted name { if (match.Groups[1].Value.Length == 2) //表示只有 '' { throw new FormatException("No characters in name."); } else if (match.Groups[1].Value.Length > 2) { name = match.Groups[1].Value; name = name.Substring(1, name.Length - 2); // 取得 quote 內的文字 if (string.IsNullOrWhiteSpace(name.Substring(0, 1)) || string.IsNullOrWhiteSpace(name.Substring(name.Length - 1, 1))) //判斷是否有空白在頭尾 { throw new FormatException("Leading or trailing blanks in name."); } else if (invalidRegex.IsMatch(name) || name.Equals("*")) { throw new FormatException( string.Format("There is an invalid character in this quoted name: {0}", match.Groups[1].Value)); } else { //判斷該名稱是否在現有工作表中的 label 中, 忽略 case if (!colLabel.Contains(name, StringComparer.OrdinalIgnoreCase)) { throw new ArgumentException( string.Format("There is no variable by this name: {0}", match.Groups[1].Value)); } else // 沒問題就加入選擇欄位清單 { selCols.Add(ws.Columns.Item(name)); } } } } else // non-quoted name or 連續表示式 { name = match.Groups[4].Value; // 先判斷連續表示式 // 判斷是否為連續表示式 C1-C3 or 'A'-C3 // ('.*?'|C[\d]+)-('.*?'|C[\d]+) Regex _regex = new Regex(@"('.*?'|C[\d]+)-('.*?'|C[\d]+)", RegexOptions.IgnoreCase); if (_regex.IsMatch(name)) { MatchCollection _mcollection = _regex.Matches(name); List <Mtb.Column> _cols = new List <Mtb.Column>(); foreach (Match m in _mcollection) //應該有兩個 match { _cols.AddRange(GetMatchColumns(m.Groups[1].Value, ws).ToList()); _cols.AddRange(GetMatchColumns(m.Groups[2].Value, ws).ToList()); } int start = int.Parse(new Regex(@"C([\d]+)").Match(_cols[0].SynthesizedName).Groups[1].Value); int end = int.Parse(new Regex(@"C([\d]+)").Match(_cols[1].SynthesizedName).Groups[1].Value); int step = start < end ? 1 : -1; for (int i = start; start > end ? i >= end : i <= end; i += step) { selCols.Add(ws.Columns.Item(i)); } } else // 非連續表示式 { if (Regex.IsMatch(name, "^'|'$")) //邊邊有一個 quote 或是裡面有多個 quote 都會被抓進來 { throw new FormatException( string.Format("Missing or stray quote in name: {0}", name)); } else if (invalidRegex.IsMatch(name)) { throw new FormatException( string.Format("This name contains invalid character(s): {0}", name)); } else { if (!colNames.Contains(name, StringComparer.OrdinalIgnoreCase) && !colId.Contains(name, StringComparer.OrdinalIgnoreCase)) { throw new ArgumentException( string.Format("There is no variable by this name: {0}", name)); } else // 沒問題就加入選擇欄位清單 { selCols.Add(ws.Columns.Item(name)); } } } } } return(selCols.ToArray()); }
public override void Execute(Mtb.Project proj) { // 將資料匯入 Minitab if (_rawdata == null || _rawdata.Rows.Count == 0) { return; } _rptLst = new List <IRptOutput>(); //重新建立一個分析結果列舉 Mtb.Worksheet ws = proj.Worksheets.Add(1); //新增工作表 Mtblib.Tools.MtbTools.InsertDataTableToMtbWs(_rawdata, ws); //匯入資料至 Minitab List <string> varnames = new List <string>(); List <Mtb.Column> varCols = new List <Mtb.Column>(); //變數的欄位集合 for (int i = 0; i < _rawdata.Columns.Count; i++) { DataColumn col = _rawdata.Columns[i]; switch (col.ColumnName) { case "TIMESTAMP": case "CHART_PARA_INDEX": break; default: varnames.Add(col.ColumnName); varCols.Add(ws.Columns.Item(col.ColumnName)); break; } } foreach (var col in varCols) { if ((int)col.DataType == 3 || col.MissingCount == col.RowCount) { throw new ArgumentNullException(string.Format("[{0}]查無資料-多變量管制圖", col.Name)); } } StringBuilder cmnd = new StringBuilder(); List <TsquareParameters> tmpParaList = new List <TsquareParameters>(); //用於計算 decomposition string[] colIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 4, Mtblib.Tools.MtbVarType.Column); //Plot point, CL, UCL and Test column // 指定繪圖時需要的欄位變數 Mtb.Column pplotCol = ws.Columns.Item(colIds[0]), clCol = ws.Columns.Item(colIds[1]), uclCol = ws.Columns.Item(colIds[2]), oocCol = ws.Columns.Item(colIds[3]), timeCol = ws.Columns.Item("TIMESTAMP"); // 計算 T2 plot points if (_parameters == null || _parameters.Count == 0) { //自己算的時候需要的變數和子命令 #region Phase I cmnd.AppendLine("macro"); cmnd.AppendLine("myt2calculator x.1-x.p;"); cmnd.AppendLine("variance cov ssiz;"); cmnd.AppendLine("meanvect location; "); cmnd.AppendLine("ppoint t2;"); cmnd.AppendLine("climit cl ucl;"); cmnd.AppendLine("test ooc;"); cmnd.AppendLine("siglevel alpha."); cmnd.AppendLine("mcolumn x.1-x.p t2"); cmnd.AppendLine("mcolumn loc.1-loc.p xx.1-xx.p tmp.1-tmp.3 ooc ucl cl"); cmnd.AppendLine("mconstant ssiz m alpha conf a1 a2 kk"); cmnd.AppendLine("mmatrix location diff cov tdiff invCov"); cmnd.AppendLine("default alpha = 0.0027"); cmnd.AppendLine("rnmiss x.1-x.p tmp.1"); cmnd.AppendLine("copy x.1-x.p xx.1-xx.p;"); cmnd.AppendLine("exclude;"); cmnd.AppendFormat("where \"tmp.1>0\".\r\n"); cmnd.AppendLine("cova xx.1-xx.p cov"); // Get Covariance matrix cmnd.AppendLine("let ssiz = n(xx.1)"); // Get the sample size of covariance calculation, ALSO..THAT IS THE NUMBER OF NONMISSING OBSERVATIONS cmnd.AppendLine("stat x.1-x.p;"); cmnd.AppendLine("mean loc.1-loc.p."); //Get mean vector. /* * Check if there is enough nonmissing observation to calculate control limit under * Tsquare command (m>p+1, where m=#observation, include missing obs, p=#items) * If no, you still need to draw plot points on graph.. * The trick is we given parameters (Mean & Covariance) and given a fake sample size, then * you get t-sq value, becasue we don't need the CL & UCL from Minitab. * (WE USE REGULAR COVARIANCE INSTEAD OF COVARIANCE BY Sullivan & Woodall) * */ cmnd.AppendLine("if(ssiz < p+1)"); cmnd.AppendLine("let kk = p+1"); cmnd.AppendLine("else"); cmnd.AppendLine("copy ssiz kk\r\n"); cmnd.AppendLine("endif"); cmnd.AppendLine("tsquare x.1-x.p 1;"); cmnd.AppendLine("mu loc.1-loc.p;"); cmnd.AppendLine("sigma cov;"); cmnd.AppendLine("number kk;"); cmnd.AppendLine("sampsize tmp.1;"); //Get subgroup size. cmnd.AppendLine("ppoint t2."); //Get Tsquare value. cmnd.AppendLine("copy loc.1-loc.p location"); //Copy column to mean vector cmnd.AppendLine("let m = sum(tmp.1)"); //Get the actual sample size (include missing observations) cmnd.AppendLine("if (m <= p+1)"); // Check if there is enough obs to calc contril limit... cmnd.AppendLine("let cl[m]=miss()"); //no center line cmnd.AppendLine("let ucl[m]=miss()"); //no control limit cmnd.AppendLine("set ooc"); //no ooc cmnd.AppendLine("(0)m"); cmnd.AppendLine("end"); cmnd.AppendLine("else"); cmnd.AppendLine("let conf = 1-alpha"); cmnd.AppendLine("let a1 = p/2"); cmnd.AppendLine("let a2 = (m-p-1)/2"); // Calculate UCL cmnd.AppendLine("set tmp.1"); cmnd.AppendLine("(conf)m"); cmnd.AppendLine("end"); cmnd.AppendLine("invcdf tmp.1 ucl;"); cmnd.AppendLine(" beta a1 a2."); cmnd.AppendLine("let ucl = (m-1)**2/m*ucl"); //Get upper control limit // Calculate CL cmnd.AppendLine("set tmp.1"); cmnd.AppendLine("(0.5)m"); cmnd.AppendLine("end"); cmnd.AppendLine("invcdf tmp.1 cl;"); cmnd.AppendLine(" beta a1 a2."); cmnd.AppendLine("let cl = (m-1)**2/m*cl"); //Get center line cmnd.AppendLine("let ooc = if(t2>ucl and t2<>MISS(),1,0)"); //Get OOC info cmnd.AppendLine("endif"); //刪除所有圖形 cmnd.AppendLine("gmana;"); cmnd.AppendLine("all;"); cmnd.AppendLine("close;"); cmnd.AppendLine("nopr."); cmnd.AppendLine("endmacro"); string macPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mytsquare.mac", cmnd.ToString()); string[] matIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 2, Mtblib.Tools.MtbVarType.Matrix); //紀錄Mean vecot & Covariance matrix string[] constIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 1, Mtblib.Tools.MtbVarType.Constant); // Sample size of Covariance matrix cmnd.Clear(); cmnd.AppendLine("notitle"); cmnd.AppendLine("brief 0"); cmnd.AppendFormat("%\"{0}\" {1};\r\n", macPath, string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName))); cmnd.AppendFormat("variance {0} {1};\r\n", matIds[0], constIds[0]); cmnd.AppendFormat("meanvect {0};\r\n", matIds[1]); cmnd.AppendFormat("ppoint {0};\r\n", pplotCol.SynthesizedName); cmnd.AppendFormat("climit {0} {1};\r\n", clCol.SynthesizedName, uclCol.SynthesizedName); cmnd.AppendFormat("test {0}.\r\n", oocCol.SynthesizedName); string path = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("exec \"{0}\" 1", path), ws); #endregion //取得參數組 TsquareParameters tmpPara = new TsquareParameters(); Mtb.Matrix mat; mat = ws.Matrices.Item(matIds[1]); tmpPara.Mean = LinearAlgebra.Matrix <double> .Build.DenseOfColumnMajor(1, mat.ColumnCount, mat.GetData()); mat = ws.Matrices.Item(matIds[0]); tmpPara.Covariance = LinearAlgebra.Matrix <double> .Build.DenseOfColumnMajor(mat.RowCount, mat.ColumnCount, mat.GetData()); tmpPara.SampleSize = ws.Constants.Item(constIds[0]).GetData(); tmpPara.SubgroupSize = 1; tmpPara.ParaID = null; tmpParaList.Add(tmpPara); } else { //有指定參數的時候 #region Phase II int nParas = ws.Columns.Item("CHART_PARA_INDEX").GetNumDistinctRows(); //宣告多組參數組 cmnd.AppendLine("macro"); cmnd.AppendLine("myt2calculator x.1-x.p;"); cmnd.AppendFormat("variance cov.1-cov.{0} ssiz.1-ssiz.{0};\r\n", nParas); cmnd.AppendFormat("meanvect mvect.1-mvect.{0};\r\n", nParas); cmnd.AppendLine("ppoint t2;"); cmnd.AppendLine("climit cl ucl;"); cmnd.AppendLine("test ooc;"); cmnd.AppendLine("siglevel alpha."); cmnd.AppendLine("mcolumn x.1-x.p xx.1-xx.p xxx.1-xxx.p loc.1-loc.p"); cmnd.AppendLine("mcolumn tmp t2 ucl cl ooc tmpT2 tmpUCL tmpCL tmpOOC"); cmnd.AppendFormat("mmatrix mvect.1-mvect.{0} cov.1-cov.{0}\r\n", nParas); cmnd.AppendFormat("mconstant m histm alpha conf a1 a2 ssiz.1-ssiz.{0} kk\r\n", nParas); cmnd.AppendLine("default alpha = 0.0027"); var _chartparaindex = _rawdata.AsEnumerable() .Select(x => x.Field <string>("CHART_PARA_INDEX")).ToArray(); var _distinctIds = _chartparaindex.Distinct().ToArray(); for (int i = 0; i < _distinctIds.Length; i++) //對每個參數與對應的資料計算 Tsquare 和管制界限 { string id = _distinctIds[i]; cmnd.AppendLine("copy x.1-x.p xx.1-xx.p;"); cmnd.AppendLine("include;"); cmnd.AppendFormat("rows {0}.\r\n", string.Join(" &\r\n", _chartparaindex.Select((x, rowid) => new { Value = x, RowId = rowid + 1 }) .Where(x => x.Value == id).Select(x => x.RowId).ToArray())); #region Set parameter information into Minitab macro TsquareParameters para = new TsquareParameters(); para.Mean = null; para.Covariance = null; para.SampleSize = MISSINGVALUE; para.SubgroupSize = 1; if (id != null) { para = _parameters.Where(x => x.ParaID == id).First(); } if (para.Mean != null) //把已知的 Mean vector 寫入 Minitab { cmnd.AppendLine("read loc.1-loc.p"); cmnd.AppendFormat("{0}\r\n", string.Join(" &\r\n", para.Mean.Enumerate())); cmnd.AppendLine("end"); } else { cmnd.AppendLine("stat xx.1-xx.p;"); cmnd.AppendLine("mean loc.1-loc.p."); } if (para.Covariance != null) //把已知的 Covariance 寫入 Minitab { cmnd.AppendFormat("read {1} {2} cov.{0} \r\n", i + 1, para.Covariance.RowCount, para.Covariance.ColumnCount); List <LinearAlgebra.Vector <double> > valuesByRow = para.Covariance.EnumerateRows().ToList(); for (int r = 0; r < para.Covariance.RowCount; r++) { cmnd.AppendFormat("{0}\r\n", string.Join(" &\r\n", valuesByRow[r])); } cmnd.AppendLine("end"); cmnd.AppendFormat("let ssiz.{0}={1}\r\n", i + 1, para.SampleSize); } else { cmnd.AppendLine("rnmiss xx.1-xx.p tmp"); cmnd.AppendLine("copy xx.1-xx.p xxx.1-xxx.p;"); cmnd.AppendLine("exclud;"); cmnd.AppendFormat("where \"tmp>0\".\r\n"); cmnd.AppendFormat("cova xxx.1-xxx.p cov.{0}\r\n", i + 1); cmnd.AppendFormat("let ssiz.{0} = count(xxx.1)\r\n", i + 1); } #endregion //Tsquare command cmnd.AppendFormat("if(ssiz.{0} < p+1)\r\n", i + 1); cmnd.AppendLine("let kk = p+1"); cmnd.AppendLine("else"); cmnd.AppendFormat("copy ssiz.{0} kk\r\n", i + 1); cmnd.AppendLine("endif"); if (id == null && _chartparaindex.Where(x => x == id).Count() == 1) //如果只有一個觀測值且沒有參數設定 { cmnd.AppendLine("let tmp=1"); cmnd.AppendLine("let tmpT2=miss()"); } else { cmnd.AppendFormat("tsquare xx.1-xx.p {0};\r\n", para.SubgroupSize); cmnd.AppendLine(" mu loc.1-loc.p;"); cmnd.AppendFormat(" sigma cov.{0};\r\n", i + 1); cmnd.AppendLine(" number kk;"); cmnd.AppendLine("sampsize tmp;"); //Get subgroup size. cmnd.AppendLine("ppoint tmpT2."); //Get Tsquare value. } cmnd.AppendFormat("copy loc.1-loc.p mvect.{0}\r\n", i + 1); //Copy column to mean vector /* * Get the value of m which use to calculate UCL, CL. * In phase II, m is the sample size of the data used to calculate historical * covariance matrix. * In phase I, m is the number of observations. * */ cmnd.AppendLine("let m = sum(tmp)"); //Get the actual sample size (include missing data) if (para.Covariance != null) { cmnd.AppendFormat("let histm = ssiz.{0}\r\n", i + 1); } else { cmnd.AppendLine("copy m histm"); } // Calculate control limits if (id == null && _chartparaindex.Where(x => x == id).Count() == 1) { cmnd.AppendLine("let tmpUCL=miss()"); cmnd.AppendLine("let tmpCL=miss()"); } else { cmnd.AppendLine("let conf = 1-alpha"); cmnd.AppendLine("let a1 = p"); cmnd.AppendLine("let a2 = histm"); #region Get UCL cmnd.AppendLine("set tmp"); cmnd.AppendLine("(conf)m"); cmnd.AppendLine("end"); if (id == null) //phase I case { cmnd.AppendLine("invcdf tmp tmpUCL;"); cmnd.AppendLine(" beta a1 a2."); cmnd.AppendLine("let tmpUCL = (m-1)**2/m*tmpUCL"); //Get upper control limit } else //phase II case { cmnd.AppendLine("invcdf tmp tmpUCL;"); cmnd.AppendLine(" f a1 a2."); cmnd.AppendLine("let tmpUCL = p*(histm+1)*(histm-1)/histm/(histm-p)*tmpUCL"); //Get upper control limit } #endregion #region Get CL cmnd.AppendLine("set tmp"); cmnd.AppendLine("(0.5)m"); cmnd.AppendLine("end"); if (id == null) { cmnd.AppendLine("invcdf tmp tmpCL;"); cmnd.AppendLine(" beta a1 a2."); cmnd.AppendLine("let tmpCL = (m-1)**2/m*tmpCL"); //Get upper control limit } else { cmnd.AppendLine("invcdf tmp tmpCL;"); cmnd.AppendLine(" f a1 a2."); cmnd.AppendLine("let tmpCL = p*(histm+1)*(histm-1)/histm/(histm-p)*tmpCL"); //Get center line } #endregion } cmnd.AppendLine("let tmpOOC = if(tmpT2>tmpUCL AND tmpT2<>MISS(),1,0)"); //Get OOC info if (i == 0) { cmnd.AppendLine("copy tmpT2 tmpUCL tmpCL tmpOOC t2 ucl cl ooc"); } else { cmnd.AppendLine("stack (t2 ucl cl ooc) (tmpT2 tmpUCL tmpCL tmpOOC) (t2 ucl cl ooc)"); } } //刪除所有圖形 cmnd.AppendLine("gmana;"); cmnd.AppendLine("all;"); cmnd.AppendLine("close;"); cmnd.AppendLine("nopr."); cmnd.AppendLine("endmacro"); string macPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mytsquare.mac", cmnd.ToString()); string[] matMeanIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, nParas, Mtblib.Tools.MtbVarType.Matrix); string[] matCovIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, nParas, Mtblib.Tools.MtbVarType.Matrix); string[] constIds = Mtblib.Tools.MtbTools.CreateVariableStrArray(ws, 1 * nParas, Mtblib.Tools.MtbVarType.Constant); cmnd.Clear(); cmnd.AppendLine("notitle"); cmnd.AppendLine("brief 0"); cmnd.AppendFormat("%\"{0}\" {1};\r\n", macPath, string.Join(" &\r\n", varCols.Select(x => x.SynthesizedName))); cmnd.AppendFormat("variance {0} {1};\r\n", string.Join(" &\r\n", matCovIds), string.Join(" &\r\n", constIds)); cmnd.AppendFormat("meanvect {0};\r\n", string.Join(" &\r\n", matMeanIds)); cmnd.AppendFormat("ppoint {0};\r\n", pplotCol.SynthesizedName); cmnd.AppendFormat("climit {0} {1};\r\n", clCol.SynthesizedName, uclCol.SynthesizedName); cmnd.AppendFormat("test {0}.\r\n", oocCol.SynthesizedName); string path = Mtblib.Tools.MtbTools.BuildTemporaryMacro("mymacro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("exec \"{0}\" 1", path), ws); #endregion //取得參數組 TsquareParameters tmpPara; Mtb.Matrix mat; for (int i = 0; i < _distinctIds.Length; i++) { tmpPara = new TsquareParameters(); tmpPara.ParaID = _distinctIds[i]; mat = ws.Matrices.Item(matMeanIds[i]); tmpPara.Mean = LinearAlgebra.Matrix <double> .Build.DenseOfColumnMajor(mat.RowCount, mat.ColumnCount, mat.GetData()); mat = ws.Matrices.Item(matCovIds[i]); tmpPara.Covariance = LinearAlgebra.Matrix <double> .Build.DenseOfColumnMajor(mat.RowCount, mat.ColumnCount, mat.GetData()); tmpPara.SampleSize = ws.Constants.Item(constIds[i]).GetData(); tmpParaList.Add(tmpPara); } } //繪圖 //會使用 TIMESTAMP, PPOINT, CL, UCL, TEST #region 繪製 T2 Control Chart (TSPLOT) string gpath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab", string.Format("tsquare_{0}.jpg", _rawdata.TableName)); cmnd.Clear(); cmnd.AppendFormat("fdate {0};\r\n", timeCol.SynthesizedName); cmnd.AppendLine("format(dtyyyy-MM-dd hh:mm)."); cmnd.AppendFormat("tsplot {0} {1} {2};\r\n", pplotCol.SynthesizedName, uclCol.SynthesizedName, clCol.SynthesizedName); cmnd.AppendFormat("gsave \"{0}\";\r\n", gpath); cmnd.AppendLine("repl;"); cmnd.AppendLine("jpeg;"); cmnd.AppendLine("over;"); cmnd.AppendFormat("symb {0};\r\n", oocCol.SynthesizedName); cmnd.AppendLine("type &"); double[] oocData = oocCol.GetData(); if (oocData.Any(x => x == 0)) { cmnd.AppendLine("6 &"); } if (oocData.Any(x => x == 1)) { cmnd.AppendLine("12 &"); } cmnd.AppendLine("0 0 0 0;"); cmnd.AppendLine("size 1;"); cmnd.AppendLine("color &"); if (oocData.Any(x => x == 0)) { cmnd.AppendLine("1 &"); //r17 color 64 } if (oocData.Any(x => x == 1)) { cmnd.AppendLine("2 &"); } cmnd.AppendLine(";"); cmnd.AppendLine("conn;"); cmnd.AppendLine("type 1 1 1;"); cmnd.AppendLine("color 1 2 120;"); //r17 conn:64 cl: 9, climit:8 //cmnd.AppendLine("graph;"); //cmnd.AppendLine("color 22;"); cmnd.AppendLine("nole;"); cmnd.AppendFormat("stamp {0};\r\n", timeCol.SynthesizedName); cmnd.AppendLine("scale 1;"); cmnd.AppendFormat("tick 1:{0}/{1};\r\n", pplotCol.RowCount, pplotCol.RowCount > 35 ? Math.Ceiling((double)pplotCol.RowCount / 35) : 1); cmnd.AppendLine("axla 1;"); cmnd.AppendLine("adis 0;"); cmnd.AppendLine("axla 2;"); cmnd.AppendLine("adis 0;"); string ttlString = string.Join(",", varnames); if (ttlString.Length > 23) { ttlString = ttlString.Substring(0, 20) + "..."; } cmnd.AppendLine("graph 8 4;"); cmnd.AppendFormat("title \"T2管制圖 {0}\";\r\n", ttlString); cmnd.AppendFormat("footn \"更新時間: {0}\";\r\n", DateTime.Now); cmnd.AppendFormat("ZTag \"{0}\";\r\n", "_T2CHART"); cmnd.AppendLine("."); //刪除所有圖形 cmnd.AppendLine("gmana;"); cmnd.AppendLine("all;"); cmnd.AppendLine("close;"); cmnd.AppendLine("nopr."); string t2MacroPath = Mtblib.Tools.MtbTools.BuildTemporaryMacro("myt2macro.mtb", cmnd.ToString()); proj.ExecuteCommand(string.Format("exec \"{0}\" 1", t2MacroPath), ws); #endregion //將檔案轉為二進位陣列 this.Contents.Add(new RptOutput() { OType = MtbOType.GRAPH, OutputInByteArr = File.ReadAllBytes(gpath) }); //計算 Decomposition if (oocData.Any(x => x == 1)) { DataTable tmpDataTable = _rawdata.Copy(); tmpDataTable.Columns.Add("OOC", typeof(int)); for (int r = 0; r < tmpDataTable.Rows.Count; r++) { DataRow dr = tmpDataTable.Rows[r]; dr["OOC"] = oocData[r]; } //建立 Decomposition 的表格 DataTable decoTable = new DataTable(); decoTable.Columns.Add("TIMESTAMP", typeof(DateTime)); foreach (var item in varnames) { decoTable.Columns.Add(item, typeof(double)); } //將OOC的項目值取出 var subData = tmpDataTable.Select("OOC=1").CopyToDataTable(); var oocParaSet = subData.AsEnumerable().Select(dr => dr.Field <string>("CHART_PARA_INDEX")).Distinct().ToArray(); //OOC 的參數組有哪些 foreach (var item in tmpParaList) { if (oocParaSet.Contains(item.ParaID)) //該參數組的觀測值是OOC { //把對應的觀測值轉換成 List<double[]>,其中每個 double[] 是每個 row 的數據 var subsubData = subData.Select(string.Format("CHART_PARA_INDEX {0}", item.ParaID == null ? "IS NULL" : "='" + item.ParaID + "'")) .CopyToDataTable(); var obsArray = subsubData.DefaultView.ToTable(false, varnames.ToArray()) .AsEnumerable().Select(x => x.ItemArray.Select(o => Convert.ToDouble(o)).ToArray()).ToList(); LinearAlgebra.Matrix <double> obs = LinearAlgebra.Matrix <double> .Build.DenseOfRowArrays(obsArray); LinearAlgebra.Matrix <double> t2deco = Tool.T2Decomposition(obs, item.Mean, item.Covariance); var t2decoByRow = t2deco.EnumerateRows().ToArray(); for (int r = 0; r < t2decoByRow.Count(); r++) { DataRow dr = decoTable.NewRow(); object[] o = new object[1 + t2deco.ColumnCount]; t2decoByRow[r].ToArray().CopyTo(o, 1); o[0] = subsubData.Rows[r].Field <DateTime>("TIMESTAMP"); decoTable.Rows.Add(o); } } } cmnd.Clear(); //LinearAlgebra.Matrix<double> obs = LinearAlgebra.Matrix<double>.Build.DenseOfRowArrays(subData); this.Contents.Add(new RptOutput() { OType = MtbOType.TABLE, OutputInByteArr = Tool.ConvertDataSetToByteArray(decoTable) }); } else // 沒有 OOC 就不做 { this.Contents.Add(new RptOutput() { OType = MtbOType.TABLE, OutputInByteArr = null }); } //Console.ReadKey(); }