using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using static CowainHmi.LogSearch; using System.IO; using System.Runtime.InteropServices; using PCHMI; using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar; using System.Data.OleDb; using CowainHmi.ProductionQty; using System.Drawing.Design; using System.Threading; namespace CowainHmi { public partial class ProductionDisplay : UserControl { public ProductionDisplay() { InitializeComponent(); } [Category("PCHMI"), Description("PLC编号")] public int PLCId { get; set; } // 定义并添加自定义属性 [Browsable(true)] [Category("Custom Properties")] [Description("产量文件路径")] public string ProductionFolderPath { get; set; } [Browsable(true)] [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("Custom Properties")] [Description("班别A开始时间")] public string ShiftAStartAddress { get; set; } [Browsable(true)] [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("Custom Properties")] [Description("班别A结束时间")] public string ShiftAEndAddress { get; set; } [Browsable(true)] [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("Custom Properties")] [Description("班别B开始时间")] public string ShiftBStartAddress { get; set; } [Browsable(true)] [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("Custom Properties")] [Description("班别B结束时间")] public string ShiftBEndAddress { get; set; } [Browsable(true)] [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("Custom Properties")] [Description("班别C开始时间")] public string ShiftCStartAddress { get; set; } [Browsable(true)] [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("Custom Properties")] [Description("班别C结束时间")] public string ShiftCEndAddress { get; set; } [Category("PCHMI"), Description("工站名称")] public string StationName { get; set; } [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("PCHMI"), Description("上传命令地址")] public string UpCmdAddr { get; set; } [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("PCHMI"), Description("上传命令计数地址")] public string RetCmdAddr { get; set; } [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("PCHMI"), Description("反馈命令计数地址")] public string RetCountAddr { get; set; } [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("PCHMI"), Description("上传工单地址")] public string UpOrderAddr { get; set; } [Editor(typeof(StringText), typeof(UITypeEditor))] [Category("PCHMI"), Description("上传部件号地址")] public string UpPartNumAddr { get; set; } private void SetCombox() { string text = System.Windows.Forms.Application.StartupPath + @"\" + ProductionFolderPath; if (!Directory.Exists(text) && text.Length > 0) { Directory.CreateDirectory(text); } string productionFile = text + @"\" + dateTimePicker1.Value.ToString("yyMMdd") + ".csv"; List<生产数据> productionData = ReadProductionData(productionFile); //PartNum下拉框获取唯一的零部件编号 if (productionData.Count == 0) { partNum.DataSource = null; return; } var listDown = (from item in productionData where !string.IsNullOrWhiteSpace(item.零部件) select item.零部件).Distinct().ToList(); listDown.Insert(0, "全部"); partNum.DataSource = listDown; } private void button1_Click(object sender, EventArgs e) { CalcProductionQty(); } private void CalcProductionQty() { string text = System.Windows.Forms.Application.StartupPath + @"\" + ProductionFolderPath; if (!Directory.Exists(text) && text.Length > 0) { Directory.CreateDirectory(text); } string productionFile = text + @"\" + dateTimePicker1.Value.ToString("yyMMdd") + ".csv"; List<生产数据> productionData = ReadProductionData(productionFile); List hoursList = new List(); for (int i = 0; i < shiftTime.Count; i++) { var item = shiftTime[i]; DateTime shiftStartTime = item.开始时间; while (shiftStartTime < item.结束时间) { DateTime nextShiftStartTime = item.结束时间; // Check if there is a next shift if (i + 1 < shiftTime.Count) { nextShiftStartTime = shiftTime[i + 1].开始时间; } DateTime endTime = shiftStartTime.AddHours(1); // Adjust the end time if it overlaps with the next shift if (endTime > nextShiftStartTime) { endTime = nextShiftStartTime; } Hours hours1 = new Hours() { 开始时间 = shiftStartTime, 结束时间 = endTime, 班别 = item.班别, }; hoursList.Add(hours1); shiftStartTime = endTime; } } List<单班产量> shift = new List<单班产量>(); string partFilter = partNum.Text == "全部" ? "" : partNum.Text; foreach (var item in hoursList) { var info = productionData .Where(pd => pd.时间 >= item.开始时间 && pd.时间 < item.结束时间 && (partFilter == "" || pd.零部件 == partFilter)); 单班产量 production = new 单班产量() { 时间 = item.开始时间, 工单 = info.Any() ? info.FirstOrDefault().工单 : "", 零部件 = info.Any() ? info.FirstOrDefault().零部件 : "", 班别 = item.班别, 产量 = info.Any() ? info.Where(pd => pd.时间 >= item.开始时间 && pd.时间 < item.结束时间).Count() : 0, 合格 = info.Any() ? info.Where(pd => pd.时间 >= item.开始时间 && pd.时间 < item.结束时间 && pd.合格否 == 1).Count() : 0, 不合格 = info.Any() ? info.Where(pd => pd.时间 >= item.开始时间 && pd.时间 < item.结束时间 && pd.合格否 == 2).Count() : 0, }; shift.Add(production); }; dataGridView1.DataSource = shift; //统计按班别的总产量,总合格,总不合格 var shiftSum = (from item in shift group item by item.班别 into g select new 单班产量 { 班别 = g.Key, 产量 = g.Sum(x => x.产量), 合格 = g.Sum(x => x.合格),//合格=1,则直接对1求和 不合格 = g.Sum(x => x.不合格)//不合格=2,则对2-1求和 }).ToList(); var shiftASum = shiftSum.FirstOrDefault(x => x.班别 == "A"); var shiftBSum = shiftSum.FirstOrDefault(x => x.班别 == "B"); var shiftCSum = shiftSum.FirstOrDefault(x => x.班别 == "C"); totalA.Text = shiftASum.产量.ToString(); totalB.Text = shiftBSum.产量.ToString(); totalC.Text = shiftCSum.产量.ToString(); OK_A.Text = shiftASum.合格.ToString(); OK_B.Text = shiftBSum.合格.ToString(); OK_C.Text = shiftCSum.合格.ToString(); NG_A.Text = shiftASum.不合格.ToString(); NG_B.Text = shiftBSum.不合格.ToString(); NG_C.Text = shiftCSum.不合格.ToString(); } public bool IsWithinShiftTime(int hour, double startTime, double endTime) { if (startTime < endTime) { // 普通时间段 return hour >= startTime && hour < endTime; } else { // 跨越午夜的时间段 return hour >= startTime || hour < endTime; } } private List<生产数据> ReadProductionData(string filePath) { var productionData = new List<生产数据>(); if (!File.Exists(filePath)) { return productionData; } int N = 1; foreach (var line in File.ReadAllLines(filePath, Encoding.GetEncoding("GB2312"))) { try { if (N == 1) { N++; continue; } var parts = line.Split(','); var time = DateTime.ParseExact(parts[0].Trim(), "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); productionData.Add(new 生产数据 { 时间 = time, 工单 = parts[1], 零部件 = parts[2], 合格否 = int.Parse(parts[3]) } ); } catch (Exception ex) { //throw; } N++; } return productionData; } public class 班别时间 { public string 班别 { get; set; } public DateTime 开始时间 { get; set; } public DateTime 结束时间 { get; set; } } public class Hours { public string 班别 { get; set; } public DateTime 开始时间 { get; set; } public DateTime 结束时间 { get; set; } } public class 单班产量 { public DateTime 时间 { get; set; } public string 工单 { get; set; } public string 零部件 { get; set; } public string 班别 { get; set; } public int 产量 { get; set; } public int 合格 { get; set; } public int 不合格 { get; set; } public int SortOrder { get; set; } // 新增排序字段 } public class 生产数据 { public DateTime 时间 { get; set; } public string 工单 { get; set; } public string 零部件 { get; set; } public int 合格否 { get; set; } } static string ConvertTimeToFormattedString(string timeString) { if (string.IsNullOrWhiteSpace(timeString) || timeString.Length != 4) { throw new ArgumentException("Invalid time format. Please use 'HHmm' format."); } // 提取小时和分钟 int hour = int.Parse(timeString.Substring(0, 2)); int minute = int.Parse(timeString.Substring(2, 2)); // 创建TimeSpan对象 TimeSpan timeSpan = new TimeSpan(hour, minute, 0); // 将TimeSpan转换为字符串 return timeSpan.ToString("hh\\:mm\\:ss"); } public class CalcStartEndTime { public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } } private CalcStartEndTime GetDateTime(string startTimeChar, string endTimeChar, DateTime queryDateTime) { CalcStartEndTime calcStartEndTime = new CalcStartEndTime(); int startTime = int.Parse(startTimeChar.Substring(0, 2)); int endTime = int.Parse(endTimeChar.Substring(0, 2)); DateTime startDateTime; DateTime endDateTime; // Determine the start and end dates if (startTime > endTime) { startDateTime = queryDateTime; endDateTime = queryDateTime.AddDays(1); } else { if (startTime < 9 && endTime < 9) { startDateTime = queryDateTime.AddDays(1); endDateTime = queryDateTime.AddDays(1); } else { startDateTime = queryDateTime; endDateTime = queryDateTime; } } // Parse the exact times calcStartEndTime.StartTime = DateTime.ParseExact(startDateTime.ToString("yyyy-MM-dd ") + ConvertTimeToFormattedString(startTimeChar), "yyyy-MM-dd HH:mm:ss", null); calcStartEndTime.EndTime = DateTime.ParseExact(endDateTime.ToString("yyyy-MM-dd ") + ConvertTimeToFormattedString(endTimeChar), "yyyy-MM-dd HH:mm:ss", null); return calcStartEndTime; } private void SetShiftTime() { ReadShiftTime(); var shiftATime = GetDateTime(shiftTimePLC[0], shiftTimePLC[1], dateTimePicker1.Value); var shiftBTime = GetDateTime(shiftTimePLC[2], shiftTimePLC[3], dateTimePicker1.Value); var shiftCTime = GetDateTime(shiftTimePLC[4], shiftTimePLC[5], dateTimePicker1.Value); shiftTime = new List<班别时间>() { new 班别时间 { 班别="A",开始时间 = shiftATime.StartTime, 结束时间 = shiftATime.EndTime }, new 班别时间 { 班别="B",开始时间 = shiftBTime.StartTime, 结束时间 = shiftBTime.EndTime }, new 班别时间 { 班别="C",开始时间 = shiftCTime.StartTime, 结束时间 = shiftCTime.EndTime } }; } private List shiftTimePLC = new List(); private void ReadShiftTime() { if (!PClass.SystemRun) { return; } shiftTimePLC.Clear(); List shiftTimeDuration = new List() { PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftAStartAddress,4), PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftAEndAddress,4), PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftBStartAddress, 4), PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftBEndAddress, 4), PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftCStartAddress, 4), PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftCEndAddress, 4), }; foreach (var item in shiftTimeDuration) { if (!string.IsNullOrEmpty(item)) { shiftTimePLC.Add(item); } } if (shiftTimePLC.Count != 6) { shiftTimePLC.Clear(); shiftTimePLC.Add("0830"); shiftTimePLC.Add("1630"); shiftTimePLC.Add("1700"); shiftTimePLC.Add("0130"); shiftTimePLC.Add("0130"); shiftTimePLC.Add("0830"); } } /// /// 根据当前时间,获取存储的文件名 /// private string GetFileName() { var dateTime = DateTime.Now; var shiftATime = GetDateTime(shiftTimePLC[0], shiftTimePLC[1], dateTime.AddDays(-1)); var shiftBTime = GetDateTime(shiftTimePLC[2], shiftTimePLC[3], dateTime.AddDays(-1)); var shiftCTime = GetDateTime(shiftTimePLC[4], shiftTimePLC[5], dateTime.AddDays(-1)); List<班别时间> shiftTimeLastDay = new List<班别时间>() { new 班别时间 { 班别="A",开始时间 = shiftATime.StartTime, 结束时间 = shiftATime.EndTime }, new 班别时间 { 班别="B",开始时间 = shiftBTime.StartTime, 结束时间 = shiftBTime.EndTime }, new 班别时间 { 班别="C",开始时间 = shiftCTime.StartTime, 结束时间 = shiftCTime.EndTime } }; var shiftDuration = shiftTimeLastDay.Where(item => item.开始时间 <= dateTime && dateTime < item.结束时间); if (shiftDuration.Any()) { return shiftTimeLastDay[0].开始时间.ToString("yyMMdd"); } return dateTime.ToString("yyMMdd"); } private List<班别时间> shiftTime; private async void ProductionDisplay_Load(object sender, EventArgs e) { if (!PClass.SystemRun) { return; } PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftAStartAddress, 4); PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftAEndAddress, 4); PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftBStartAddress, 4); PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftBEndAddress, 4); PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftCStartAddress, 4); PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftCEndAddress, 4); PCHMI.RT.GET_INT16s(PLCId, UpCmdAddr, 6); PCHMI.RT.GET_SIEMENS_STRING(PLCId, UpOrderAddr, 30); PCHMI.RT.GET_SIEMENS_STRING(PLCId, UpPartNumAddr, 50); await Task.Delay(300); SetShiftTime(); dataGridView1.AutoGenerateColumns = false; SetCombox(); ReadShiftTime(); this.timer1.Enabled = true; } private void dateTimePicker1_ValueChanged(object sender, EventArgs e) { SetShiftTime(); } private short retCountSave; private void timer1_Tick(object sender, EventArgs e) { if (PClass.IsPlcLink(PLCId) && !string.IsNullOrEmpty(UpCmdAddr)) { var ar = PCHMI.RT.GET_INT16s(PLCId, UpCmdAddr, 6); var order = PCHMI.RT.GET_SIEMENS_STRING(PLCId, UpOrderAddr, 30); var partNum = PCHMI.RT.GET_SIEMENS_STRING(PLCId, UpPartNumAddr, 50); if (ar[0] == 1 && retCountSave != ar[1]) { //PLC触发产量上传 string fileName = GetFileName(); string stName = string.Empty; if (string.IsNullOrEmpty(StationName)) { stName = this.Name; } else { stName = StationName; } SaveData(stName, fileName, order, partNum, ar[5]); PCHMI.RT.SEND_INT16(PLCId, RetCmdAddr, 1); PCHMI.RT.SEND_INT16(PLCId, RetCountAddr, ar[1]); retCountSave = ar[1]; } } } public void SaveData(string stationName, string fileName, string order, string partNum, short isPass) { if (PClass.SystemRun) { string text = System.Windows.Forms.Application.StartupPath + @"\" + ProductionFolderPath; if (!Directory.Exists(text) && text.Length > 0) { Directory.CreateDirectory(text); } string productionFile = text + @"\" + fileName + ".csv"; if (!File.Exists(productionFile)) { CsvHelper.CreateCsv(productionFile, new string[] { "时间", "工单", "零部件", "合格否" }); } CsvHelper.WriteLine(productionFile, new List() { DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), order, partNum, isPass.ToString() }); } } private void btnTimeEdit_Click(object sender, EventArgs e) { List strings = new List() { ShiftAStartAddress, ShiftAEndAddress, ShiftBStartAddress, ShiftBEndAddress, ShiftCStartAddress, ShiftCEndAddress }; DlgProductionTimeEdit dlg = new DlgProductionTimeEdit(PLCId, strings); var result = dlg.ShowDialog(); if (result == DialogResult.OK) { SetShiftTime(); ReadShiftTime(); } } private void partNum_MouseDown(object sender, MouseEventArgs e) { SetCombox(); } } }