using Aitex.Core.RT.Log; using Aitex.Core.UI.ControlDataContext; using Aitex.Core.Util; using Caliburn.Micro; using Caliburn.Micro.Core; using MECF.Framework.Common.CommonData; using MECF.Framework.Common.ControlDataContext; using MECF.Framework.Common.DataCenter; using MECF.Framework.Common.Utilities; using MECF.Framework.UI.Client.CenterViews.Configs.SystemConfig; using MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory; using MECF.Framework.UI.Client.CenterViews.Dialogs; using MECF.Framework.UI.Client.CenterViews.Operations.RealTime; using MECF.Framework.UI.Client.ClientBase; using OpenSEMI.ClientBase; using SciChart.Charting.Visuals; using SciChart.Charting.Visuals.Annotations; using SciChart.Charting.Visuals.Axes; using SciChart.Charting.Visuals.RenderableSeries; using SciChart.Data.Model; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using static MECF.Framework.Common.FAServices.DataVariables; using Action = System.Action; using Media = System.Windows.Media; namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory { class ProcessExportAllViewModel : ModuleUiViewModelBase where T : IComparable { private ProcessExportAllView view; private CancellationTokenSource _cancellationTokenSource; private event EventHandler Exporting; private const int MAX_PARAMETERS = 1000; public List RecipeDatas { get; set; } private ObservableCollection _ParameterNodes; public ObservableCollection ParameterNodes { get { return _ParameterNodes; } set { _ParameterNodes = value; NotifyOfPropertyChange("ParameterNodes"); } } private Dictionary _processDetailDisplayDic = new Dictionary(); private Dictionary> _processProcessDetailAttributeDict = new Dictionary>(); // public ObservableCollection SelectedData { get; set; } public ObservableCollection GetParameters() { ObservableCollection rootNode = new ObservableCollection(); try { Dictionary displayDic = QueryDataClient.Instance.Service.GetData("System.ProcessDetailDisplay") as Dictionary; if (displayDic == null) return rootNode; List dataList = new List(); foreach (var key in displayDic.Keys) { string[] item = key.Split('.'); if (item != null) { if (item.Length == 2) { _processDetailDisplayDic.Add($"{item[1]}", displayDic[key]); dataList.Add($"{item[0]}.{item[1]}"); } else if (item.Length == 3) { _processDetailDisplayDic.Add($"{item[1]} {item[2]}", displayDic[key]); dataList.Add($"{item[0]}.{item[1]}.{item[2]}"); } } Dictionary indexer = new Dictionary(); foreach (string dataName in dataList) { string[] nodeName = dataName.Split('.'); ParameterNode parentNode = null; string pathName = ""; for (int i = 0; i < nodeName.Length; i++) { pathName = (i == 0 || i == 1) ? nodeName[i] : (pathName + " " + nodeName[i]); if (!indexer.ContainsKey(pathName)) { indexer[pathName] = new ParameterNode() { Name = pathName, ChildNodes = new ObservableCollection(), ParentNode = parentNode }; if (parentNode == null) { rootNode.Add(indexer[pathName]); } else { parentNode.ChildNodes.Add(indexer[pathName]); } } parentNode = indexer[pathName]; } } SortParameterNode(rootNode, "Heater", 0); SortParameterNode(rootNode, "MFC", 1); SortParameterNode(rootNode, "Pressure", 2); SortParameterNode(rootNode, "Boat", 3); SortParameterNode(rootNode, "HeaterBand", 4); SortParameterNode(rootNode, "Valve", 5); } } catch (Exception ex) { LOG.Write(ex); } return rootNode; } void SortParameterNode(ObservableCollection rootNode, string Name, int Index) { if (rootNode[Index].Name != Name) { for (int i = 0; i < rootNode.Count; i++) { rootNode[i].Selected = true; if (rootNode[i].Name == Name) { ParameterNode node = rootNode[i]; rootNode.RemoveAt(i); rootNode.Insert(Index, node); } } } } private IRange _timeRange; public IRange VisibleRangeTime { get { return _timeRange; } set { _timeRange = value; NotifyOfPropertyChange(nameof(VisibleRangeTime)); } } private IRange _VisibleRangeValue; public IRange VisibleRangeValue { get { return _VisibleRangeValue; } set { _VisibleRangeValue = value; NotifyOfPropertyChange(nameof(VisibleRangeValue)); } } private AnnotationCollection _annotations; public AnnotationCollection Annotations { get => _annotations; set { _annotations = value; InvokePropertyChanged(nameof(Annotations)); } } //private PeriodicJob _thread; private List _stepInfo = new List(); public List StepInfo { get { return _stepInfo; } set { _stepInfo = value; this.NotifyOfPropertyChange(nameof(StepInfo)); } } private bool _isBusy = false; private string _busyIndicatorMessage; /// /// 设置或返回忙信息。 /// public string BusyIndicatorContent { get => _busyIndicatorMessage; set { _busyIndicatorMessage = value; NotifyOfPropertyChange(nameof(BusyIndicatorContent)); } } /// /// 设置或返回视图是否正忙。 /// public bool IsBusy { get => _isBusy; set { _isBusy = value; NotifyOfPropertyChange(nameof(IsBusy)); } } private RealtimeProvider _realtimeProvider; public ProcessExportAllViewModel(List recipes) { DisplayName = "Process Export"; RecipeDatas = recipes; _realtimeProvider = new RealtimeProvider(); ParameterNodes = _realtimeProvider.GetParameters(out var dict, true); _processDetailDisplayDic = dict; _processProcessDetailAttributeDict = _realtimeProvider.GetProcessProcessDetailAttributeDict(); if (recipes == null || recipes.Count == 0) { return; } //SelectedData = new ObservableCollection(); var now = DateTime.Now; VisibleRangeTime = new DateRange(DateTime.Now.AddMinutes(60), DateTime.Now.AddMinutes(-60)); VisibleRangeValue = new DoubleRange(0, 10); Annotations = new AnnotationCollection(); // _thread = new PeriodicJob(200, MonitorData, "ProcessExport", true); RecipeDatas.ToList().ForEach(recipe => { QueryStep(recipe.StartTime, recipe.EndTime); }); if (StepInfo != null && StepInfo.Count > 0) { StepStartTime = StepInfo.FirstOrDefault().StartTime; StepEndTime = StepInfo.LastOrDefault().EndTime; } else { if (recipes.Count > 0) { StepStartTime = recipes[0].StartTime; StepEndTime = recipes[0].EndTime; } } } public bool IsStepVisiable => RecipeDatas.Count == 1; public DateTime StepStartTime { get; set; } public DateTime StepEndTime { get; set; } private bool _isAdding; private static object _lockSelection = new object(); private ConcurrentBag _lstTokenTimeData = new ConcurrentBag(); public class QueryIndexer { public TimeChartDataLine DataLine { get; set; } public List DataList { get; set; } public DateTime TimeToken { get; set; } } public class TimeChartDataLine : ChartDataLine { public string Module { get; set; } public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } public TimeChartDataLine(string dataName, string module, DateTime startTime, DateTime endTime) : base(dataName) { StartTime = startTime; EndTime = endTime; Module = module; } } private string _resolution; private AutoRange _autoRange; public AutoRange ChartAutoRange { get { return _autoRange; } set { _autoRange = value; NotifyOfPropertyChange(nameof(ChartAutoRange)); } } public void QueryStep(DateTime starTime, DateTime endTime)//, string recipeName去掉查询recipeName名称,有嵌套调用 { starTime = starTime.AddMinutes(-1); endTime = endTime.AddMinutes(1); string sql = $"SELECT * FROM \"process_data\" where (\"process_begin_time\" >= '{starTime:yyyy/MM/dd HH:mm:ss.fff}' and \"process_end_time\" <= '{endTime:yyyy/MM/dd HH:mm:ss.fff}') order by \"process_begin_time\" DESC;"; DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql); if (dbData != null && dbData.Rows.Count > 0) { List ProcessDataLotList = new List(); for (int i = 0; i < dbData.Rows.Count; i++) { ProcessDataLot item = new ProcessDataLot(); item.GUID = dbData.Rows[i]["guid"].ToString(); item.RecipeName = dbData.Rows[i]["recipe_name"].ToString(); item.ProcessStatus = dbData.Rows[i]["process_status"].ToString(); item.WaferDataGUID = dbData.Rows[i]["wafer_data_guid"].ToString(); item.ProcessIn = dbData.Rows[i]["process_in"].ToString(); if (!dbData.Rows[i]["process_begin_time"].Equals(DBNull.Value)) { item.ProcessBeginTime = (DateTime)dbData.Rows[i]["process_begin_time"]; } if (!dbData.Rows[i]["process_end_time"].Equals(DBNull.Value)) { item.ProcessEndTime = (DateTime)dbData.Rows[i]["process_end_time"]; } ProcessDataLotList.Add(item); } // Annotations.Add(VerLine(Media.Brushes.Blue, ProcessDataLotList[0].ProcessBeginTime, Media.Brushes.Blue, $"{ProcessDataLotList[0].RecipeName}")); //Annotations.Add(VerLine(Media.Brushes.Blue, ProcessDataLotList[0].ProcessEndTime, Media.Brushes.Blue, $"Recipe End")); string sql2 = $"SELECT * FROM \"recipe_step_data\" where"; sql2 += $" \"recipe_step_data\".\"process_data_guid\" = '{ProcessDataLotList[0].GUID.ToString()}'"; sql2 += " order by \"step_begin_time\" ASC;"; using (var table = QueryDataClient.Instance.Service.QueryData(sql2)) { if (!(table == null || table.Rows.Count == 0)) { for (int i = 0; i < table.Rows.Count; i++) { var item = table.Rows[i]; string startStepTime = ""; string endStepTime = ""; double stepTime = 0; string subRecipeStepNumber = ""; string subRecipeStepTime = ""; string subRecipeStepName = ""; string subRecipeLoopInfo = ""; string tempCorrection = ""; string tempPid = ""; if (!item["step_begin_time"].Equals(DBNull.Value)) startStepTime = ((DateTime)item["step_begin_time"]).ToString("yyyy/MM/dd HH:mm:ss.fff"); if (!item["step_end_time"].Equals(DBNull.Value)) { endStepTime = ((DateTime)item["step_end_time"]).ToString("yyyy/MM/dd HH:mm:ss.fff"); } if (!item["step_time"].Equals(DBNull.Value)) { stepTime = (float)item["step_time"]; } if (!item["sub_recipe_step_time"].Equals(DBNull.Value)) { subRecipeStepTime = item["sub_recipe_step_time"].ToString(); } if (!item["sub_recipe_step_number"].Equals(DBNull.Value)) { subRecipeStepNumber = item["sub_recipe_step_number"].ToString(); } if (!item["sub_recipe_step_name"].Equals(DBNull.Value)) { subRecipeStepName = item["sub_recipe_step_name"].ToString(); } if (!item["sub_recipe_loop_info"].Equals(DBNull.Value)) { subRecipeLoopInfo = item["sub_recipe_loop_info"].ToString(); } if (!item["temp_correction"].Equals(DBNull.Value)) { tempCorrection = item["temp_correction"].ToString().Replace(",", ":"); } if (!item["temp_pid"].Equals(DBNull.Value)) { tempPid = item["temp_pid"].ToString().Replace(",", ":"); } string stepNo = item["step_number"].ToString(); string stepName = item["step_name"].ToString(); if (DateTime.TryParse(startStepTime, out DateTime StartTime) && DateTime.TryParse(endStepTime, out DateTime EndTime)) { //Annotations.Add(VerLine(Media.Brushes.AliceBlue, StartTime, Media.Brushes.Blue, $"{stepNo}")); var time = StartTime.AddSeconds(stepTime); if (EndTime < time && time < ProcessDataLotList[0].ProcessEndTime)//解决process过程abort,数据导出问题:数据点时间范围大于recipe结束时间。 { EndTime = StartTime.AddSeconds(stepTime); } _stepInfo.Add(new StepInfo() { StartTime = StartTime, EndTime = EndTime, StepName = stepName, StepTime = stepTime, StepNo = stepNo, StepEndTime = StartTime.AddSeconds(stepTime), SubRecipeStepNumber = subRecipeStepNumber, SubRecipeStepTime = subRecipeStepTime, SubRecipeStepName = subRecipeStepName, SubRecipeLoopInfo = subRecipeLoopInfo, TempCorrection = tempCorrection, TempPid = tempPid, }); } } } } } } protected override void OnViewLoaded(object view) { base.OnViewLoaded(view); useMaxRow = (int)QueryDataClient.Instance.Service.GetConfig("System.SetUp.ExportMaxRow"); this.view = (ProcessExportAllView)view; } List nodeOrigin = new List(); void GetNode(ParameterNode pNode, bool Selected) { foreach (var item in pNode.ChildNodes) { if (item.ChildNodes.Count > 0) { GetNode(item, Selected); } else { //if(item.Selected == true) { nodeOrigin.Add(item.Name); } } } } public static int DivideAndRoundUp(int dividend, int divisor) { int result = dividend / divisor; int remainder = dividend % divisor; if (remainder > 0) { result++; } return result; } private int useMaxRow = 25000; string csv = ","; public async void ExportAll() { try { nodeOrigin.Clear(); if (StepStartTime.Year == 1 || StepEndTime.Year == 1) { MessageBox.Show("No data is available in the selected period!", "Export", MessageBoxButton.OK, MessageBoxImage.Warning); return; } foreach (var node in ParameterNodes) { if (node.Selected == true) { GetNode(node, node.Selected); } } if (nodeOrigin.Count == 0) { MessageBox.Show($"Please select the data you want to export.", "Export", MessageBoxButton.OK, MessageBoxImage.Warning); return; } Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog(); dlg.DefaultExt = ".csv"; // Default file extension dlg.Filter = "Excel数据表格文件(*.csv)|*.csv"; // Filter files by extension dlg.FileName = $"{DisplayName}_{string.Join(",", RecipeDatas.Select(x => x.RecipeName).ToArray())}_{DateTime.Now:yyyyMMdd_HHmmss}"; Nullable result = dlg.ShowDialog();// Show open file dialog box if (result == true) // Process open file dialog box results { BusyIndicatorContent = "Exporting start ..."; IsBusy = true; Exporting?.Invoke(this, System.EventArgs.Empty); _cancellationTokenSource = new CancellationTokenSource(); //System.Data.DataSet ds = new System.Data.DataSet(); //var sw = new Stopwatch(); //sw.Restart(); //BusyIndicatorContent = "Create table header start ..."; //ds.Tables.Add(new System.Data.DataTable($"{DisplayName}_{DateTime.Now:yyyyMMdd_HHmmss}")); //ds.Tables[0].Columns.Add("Recipe Info"); //ds.Tables[0].Columns[0].DataType = typeof(string); //ds.Tables[0].Columns.Add("Date"); //ds.Tables[0].Columns[1].DataType = typeof(string); //ds.Tables[0].Columns.Add("Time"); //ds.Tables[0].Columns[2].DataType = typeof(string); //ds.Tables[0].Columns.Add("Step ID"); //ds.Tables[0].Columns[3].DataType = typeof(string); //ds.Tables[0].Columns.Add("Step Name"); //ds.Tables[0].Columns[4].DataType = typeof(string); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Recipe Info{csv}Date{csv}Time{csv}Step ID{csv}Step Name"); Dictionary timeValue = new Dictionary(); await Task.Run(() => { for (int i = 0; i < nodeOrigin.Count; i++) { //List> data = (nodeOrigin[i] as ChartDataLine).Points; //foreach (var tuple in data) //{ // if (!timeValue.ContainsKey(tuple.Item1)) // timeValue[tuple.Item1] = new double[nodeOrigin.Count]; // timeValue[tuple.Item1][i] = tuple.Item2; //} // ds.Tables[0].Columns.Add(nodeOrigin[i]); // ds.Tables[0].Columns[i + 5].DataType = typeof(double); } stringBuilder.AppendLine($"Recipe:{string.Join(",", RecipeDatas.Select(x => x.RecipeName).ToArray())}"); stringBuilder.AppendLine($"Start Time{csv}{string.Join(",", RecipeDatas.Select(x => x.StartTime).ToArray())}{csv}{string.Join(",", RecipeDatas.Select(x => x.StartTime).ToArray())}"); stringBuilder.AppendLine($"End Time{csv}{string.Join(",", RecipeDatas.Select(x => x.EndTime).ToArray())}{csv}{string.Join(",", RecipeDatas.Select(x => x.EndTime).ToArray())}"); FileHelper.Instance.SaveText(dlg.FileName, stringBuilder.ToString()); //var recipeInfoRow = ds.Tables[0].NewRow(); //recipeInfoRow[0] = $"Recipe:{string.Join(",", RecipeDatas.Select(x => x.RecipeName).ToArray())}"; //ds.Tables[0].Rows.Add(recipeInfoRow); //recipeInfoRow = ds.Tables[0].NewRow(); //recipeInfoRow[0] = $"Start Time"; //recipeInfoRow[1] = string.Join(",", RecipeDatas.Select(x => x.StartTime).ToArray()); //recipeInfoRow[2] = string.Join(",", RecipeDatas.Select(x => x.StartTime).ToArray()); //ds.Tables[0].Rows.Add(recipeInfoRow); //recipeInfoRow = ds.Tables[0].NewRow(); //recipeInfoRow[0] = $"End Time"; //recipeInfoRow[1] = string.Join(",", RecipeDatas.Select(x => x.EndTime).ToArray()); //recipeInfoRow[2] = string.Join(",", RecipeDatas.Select(x => x.EndTime).ToArray()); //ds.Tables[0].Rows.Add(recipeInfoRow); //var rowCaption = ds.Tables[0].NewRow(); //for (int i = 0; i < ds.Tables[0].Columns.Count; i++) //{ // rowCaption[i] = ds.Tables[0].Columns[i].Caption; //} //ds.Tables[0].Rows.Add(rowCaption); //for (int i = 0; i < ds.Tables[0].Columns.Count; i++) //{ // ds.Tables[0].Columns[i].Caption = null; //} DateTime startTime = startTime = StepStartTime; QueryDataClientFromTable(dlg.FileName); }, _cancellationTokenSource.Token).ContinueWith(t => { if (t.IsCanceled || t.IsFaulted) { IsBusy = false; return; } }); if (_cancellationTokenSource?.Token.IsCancellationRequested == true) { IsBusy = false; return; } BusyIndicatorContent = "Data is written to Excel file ..."; IsBusy = false; MessageBox.Show($"Export succeed, file save as {dlg.FileName}", "Export", MessageBoxButton.OK, MessageBoxImage.Information); Window window = Window.GetWindow(this.view); window.Close(); } } catch (Exception ex) { LOG.Write(ex); MessageBox.Show("Write failed," + ex.Message, "export failed", MessageBoxButton.OK, MessageBoxImage.Warning); IsBusy = false; } } private void QueryDataClientFromTable(string fileName) { DateTime startTime = StepStartTime; DateTime endTime = StepEndTime; List keys = new List(nodeOrigin); List pmList = new List(); List systemList = new List(); if (keys != null && keys.Count > 0) { foreach (var dataKey in keys) { var dataId = _processDetailDisplayDic.ContainsKey(dataKey) ? _processDetailDisplayDic[dataKey] : dataKey; var module = dataId.Split('.').ToList()[0]; if (module.ToLower() == "pm1") { pmList.Add(dataId); } else if (module.ToLower() == "system") { systemList.Add(dataId); // systemList.Add(string.Format("\"{0}\"", dataId)); } } } if (StepStartTime.Date == StepEndTime.Date) { SaveDataToTable(fileName, pmList, systemList, startTime, endTime); } else { endTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 23, 59, 59); while (endTime < StepEndTime) { SaveDataToTable(fileName, pmList, systemList, startTime, endTime); startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 0, 0, 0).AddDays(1); endTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 23, 59, 59); } SaveDataToTable(fileName, pmList, systemList, startTime, StepEndTime); } } private bool firstHeader = false; private Dictionary GetReverseDict() { Dictionary keyValuePairs = new Dictionary(); foreach (var kvp in _processDetailDisplayDic) { if (!keyValuePairs.ContainsKey(kvp.Value)) keyValuePairs[kvp.Value] = kvp.Key.Trim().Contains(" ") ? kvp.Key.Trim().Substring(kvp.Key.Trim().LastIndexOf(" ") + 1) : kvp.Key; } return keyValuePairs; } private void SaveDataToTable(string fileName, List pmList, List systemList, DateTime startTime, DateTime endTime) { string stepID = "", stepName = "", subRecipeLoopInfo = "", subRecipeStepName = "", subRecipeStepNumber = "", tempCorrection = "", tempPid = ""; DataTable pmDataTable = null; Dictionary reverseDict = GetReverseDict(); var columnsql = $"select column_name from information_schema.columns where table_name = '{startTime.ToString("yyyyMMdd")}.PM1'"; var columnTable = QueryDataClient.Instance.Service.QueryData(columnsql); List col = columnTable.Rows.Cast().Select(x => x.ItemArray[0].ToString()).ToList(); pmList = pmList.Where(x => col.Any(y => y == x)).ToList(); string pmsql = $"select time AS InternalTimeStamp, {string.Join(",", pmList.Select(x => string.Format("\"{0}\"", x)))}"; DataTable systemDataTable = null; pmsql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc", startTime.ToString("yyyyMMdd") + "." + "PM1", startTime.Ticks, endTime.Ticks); BusyIndicatorContent = "Example Query PM data ..."; pmDataTable = QueryDataClient.Instance.Service.QueryData(pmsql); if (pmDataTable != null) { foreach (DataRow item in pmDataTable.Rows) { if (item.Table.Columns.Contains("PM1.APC.ModeFeedback")) { if (item.Table.Columns.Contains("PM1.APC.PressureSetPoint")) { if (item.Field("PM1.APC.ModeFeedback") != 7 && item.Field("PM1.APC.ModeFeedback") != 8) { item["PM1.APC.PressureSetPoint"] = 0; } } if (item.Table.Columns.Contains("PM1.APC.PositionSetPoint")) { if (item.Field("PM1.APC.ModeFeedback") != 2) { item["PM1.APC.PositionSetPoint"] = 0; } } if (item.Table.Columns.Contains("PM1.APC.SlowRateSetPoint")) { if (item.Field("PM1.APC.ModeFeedback") != 12) { item["PM1.APC.SlowRateSetPoint"] = 0; } } } } } var sysColumnsql = $"select column_name from information_schema.columns where table_name = '{startTime.ToString("yyyyMMdd")}.System'"; var sysColumnTable = QueryDataClient.Instance.Service.QueryData(sysColumnsql); List systemCol = sysColumnTable.Rows.Cast().Select(x => x.ItemArray[0].ToString()).ToList(); systemList = systemList.Where(x => systemCol.Any(y => y == x)).ToList(); string systemsql = $"select time AS InternalTimeStamp, {string.Join(",", systemList.Select(x => string.Format("\"{0}\"", x)))}"; systemsql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc", startTime.ToString("yyyyMMdd") + "." + "System", startTime.Ticks, endTime.Ticks); BusyIndicatorContent = "Example Query System data ..."; systemDataTable = QueryDataClient.Instance.Service.QueryData(systemsql); int maxRow = 0; if ((pmDataTable == null || pmDataTable.Rows.Count == 0)) { if (systemDataTable != null) { maxRow = systemDataTable.Rows.Count; } } else if ((systemDataTable == null || systemDataTable.Rows.Count == 0)) { if (pmDataTable != null) { maxRow = pmDataTable.Rows.Count; } } else { maxRow = pmDataTable.Rows.Count > systemDataTable.Rows.Count ? systemDataTable.Rows.Count : pmDataTable.Rows.Count; } var subColNames = new List() { new DataColumn("SubRecipeStepName"), new DataColumn("SubRecipeStepNumber"), new DataColumn("SubRecipeLoopInfo"), new DataColumn("TempCorrection"), new DataColumn("TempPid"), }; BusyIndicatorContent = "Data is saved to excel Table ..."; StringBuilder stringBuilder = new StringBuilder(); if (!firstHeader) { firstHeader = true; var systemColNames = systemDataTable?.Columns.Cast().Where(x => x.ColumnName != "internaltimestamp").Select(x => { if (_processProcessDetailAttributeDict.ContainsKey(x.ColumnName)) { var colAttributeName = "ColName"; if (!_processProcessDetailAttributeDict[x.ColumnName].ContainsKey(colAttributeName)) { colAttributeName = "DisplayName"; } return string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName][colAttributeName]) ? x.ColumnName : _processProcessDetailAttributeDict[x.ColumnName][colAttributeName]; } return x.ColumnName; }); var pmColNames = pmDataTable?.Columns.Cast().Where(x => x.ColumnName != "internaltimestamp").Select(x => { if (_processProcessDetailAttributeDict.ContainsKey(x.ColumnName)) { var colAttributeName = "ColName"; if (!_processProcessDetailAttributeDict[x.ColumnName].ContainsKey(colAttributeName)) { colAttributeName = "DisplayName"; } return string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName][colAttributeName]) ? x.ColumnName : _processProcessDetailAttributeDict[x.ColumnName][colAttributeName]; } return x.ColumnName; }); stringBuilder.AppendLine($"{csv}{csv}{csv}{csv}{csv}{string.Join($"{csv}", subColNames.Cast())} {csv}{string.Join($"{csv}", systemColNames ?? new string[0])} {csv}{string.Join($"{csv}", pmColNames ?? new string[0])}"); } for (int i = 0; i < maxRow; i++) { BusyIndicatorContent = $"Total data {maxRow} current {i + 1} ..."; var pmRow = pmDataTable != null && pmDataTable.Rows.Count > 0 ? pmDataTable.Rows[i] : null; var systemRow = systemDataTable != null && systemDataTable.Rows.Count > 0 ? systemDataTable.Rows[i] : null; //float timeIndex = 0; //float.TryParse(item.Key.ToString(), out timeIndex); //DateTime dateTimeKey = startTime.AddMilliseconds(timeIndex * 1000); ;// DateTime.Parse(item.Key.ToString()); DateTime dateTimeKey = new DateTime(systemRow != null ? (long)systemRow[0] : (long)pmRow[0]); var tempStepInfo = _stepInfo.OrderByDescending(x => x.StartTime).Where(x => x.StartTime <= dateTimeKey).FirstOrDefault(); if (tempStepInfo != null)// && dateTimeKey > _stepInfo[iIndex].StartTime && x.StepEndTime >= dateTimeKey { stepID = tempStepInfo.StepNo; stepName = tempStepInfo.StepName; subRecipeStepName = tempStepInfo.SubRecipeStepName; subRecipeStepNumber = tempStepInfo.SubRecipeStepNumber; subRecipeLoopInfo = !string.IsNullOrEmpty(tempStepInfo.SubRecipeLoopInfo) ? tempStepInfo.SubRecipeLoopInfo.Replace("/", "|") : tempStepInfo.SubRecipeLoopInfo; tempCorrection = !string.IsNullOrEmpty(tempStepInfo.TempCorrection) ? tempStepInfo.TempCorrection : ""; tempPid = !string.IsNullOrEmpty(tempStepInfo.TempPid) ? tempStepInfo.TempPid : ""; } if (pmRow == null && systemRow != null) { stringBuilder.AppendLine($"{csv}{dateTimeKey.ToString("yyyy/MM/dd")}{csv}{dateTimeKey.ToString("HH:mm:ss:fff")}{csv}{stepID}{csv}{stepName}{csv}{subRecipeStepName}{csv}{subRecipeStepNumber}{csv}{subRecipeLoopInfo}{csv}{tempCorrection}{csv}{tempPid}{csv}{string.Join($"{csv}", systemRow.ItemArray.ToList().GetRange(1, systemRow.ItemArray.Count() - 1).Select(x => x.ToString()))}{csv}{string.Join($"{csv}", Enumerable.Repeat("", pmDataTable?.Columns.Count ?? 0).ToArray())}"); } else if (pmRow != null && systemRow == null) { stringBuilder.AppendLine($"{csv}{dateTimeKey.ToString("yyyy/MM/dd")}{csv}{dateTimeKey.ToString("HH:mm:ss:fff")}{csv}{stepID}{csv}{stepName}{csv}{subRecipeStepName}{csv}{subRecipeStepNumber}{csv}{subRecipeLoopInfo}{csv}{tempCorrection}{csv}{tempPid}{csv}{string.Join($"{csv}", Enumerable.Repeat("", systemDataTable?.Columns?.Count ?? 0).ToArray())}{csv}{string.Join($"{csv}", pmRow.ItemArray.ToList().GetRange(1, pmRow.ItemArray.Count() - 1).Select(x => x.ToString()))}"); } else if (systemDataTable != null) { stringBuilder.AppendLine($"{csv}{dateTimeKey.ToString("yyyy/MM/dd")}{csv}{dateTimeKey.ToString("HH:mm:ss:fff")}{csv}{stepID}{csv}{stepName}{csv}{subRecipeStepName}{csv}{subRecipeStepNumber}{csv}{subRecipeLoopInfo}{csv}{tempCorrection}{csv}{tempPid}{csv}{string.Join($"{csv}", systemDataTable.Rows[i].ItemArray.ToList().GetRange(1, systemDataTable.Rows[i].ItemArray.Count() - 1).Select(x => x.ToString()))}{csv}{string.Join($"{csv}", pmDataTable.Rows[i].ItemArray.ToList().GetRange(1, pmDataTable.Rows[i].ItemArray.Count() - 1).Select(x => x.ToString()))}"); } if (i == maxRow - 1) { var str = stringBuilder.ToString(); str = str.TrimEnd((new char[] { '\r', '\n' })); FileHelper.Instance.SaveNewLineDataToTxt(fileName, str, true); stringBuilder.Clear(); } } } static string CheckAndReplace(string input) { if (input.StartsWith("PM1")) { return input.Substring(4); } if (input.StartsWith("System")) { return input.Substring(7); } return input; } /// /// 取消查询。 /// public void CancelQuery() { Task.Run(() => { if (_cancellationTokenSource?.Token.CanBeCanceled == true) { _cancellationTokenSource.Cancel(); } Thread.Sleep(100); //_progQueryUpdate.Report(new ProgressUpdatingEventArgs(100, 100, "")); //_progChartSuspendUpdating.Report(false); }); } } }