using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; // 用于 .xlsx using NPOI.HSSF.UserModel; // 用于 .xls using NPOI.SS.Util; // 使用别名解决命名空间冲突 using NPOIBorderStyle = NPOI.SS.UserModel.BorderStyle; using NPOIHorizontalAlignment = NPOI.SS.UserModel.HorizontalAlignment; namespace WindowsFormsApp6 { public partial class Form1 : Form { private System.Windows.Forms.Timer dataTimer; private DataTable sampleDataTable; private int sampleCount = 0; public Form1() { InitializeComponent(); InitializeDataTable(); InitializeTimer(); InitializeDataGridView(); InitializeEventHandlers(); } /// /// 初始化 DataGridView 列 /// private void InitializeDataGridView() { // 清除现有列 dataGridView1.Columns.Clear(); // 添加新列以匹配 Excel 表格结构 dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "序号", HeaderText = "序号", DataPropertyName = "序号", Width = 150, ReadOnly = true, DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter } }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "试样1", HeaderText = "试样1", DataPropertyName = "试样1", Width = 150, ReadOnly = true, DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter, BackColor = Color.FromArgb(255, 255, 200) // 黄色背景 } }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "试样2", HeaderText = "试样2", DataPropertyName = "试样2", Width = 150, ReadOnly = true, DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter, BackColor = Color.FromArgb(255, 255, 200) } }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "试样3", HeaderText = "试样3", DataPropertyName = "试样3", Width = 150, ReadOnly = true, DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter, BackColor = Color.FromArgb(255, 255, 200) } }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "试样4", HeaderText = "试样4", DataPropertyName = "试样4", Width = 150, ReadOnly = true, DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter, BackColor = Color.FromArgb(255, 255, 200) } }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "试样5", HeaderText = "试样5", DataPropertyName = "试样5", Width = 150, ReadOnly = true, DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter, BackColor = Color.FromArgb(255, 255, 200) } }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "时间", HeaderText = "时间", DataPropertyName = "时间", Width = 200, ReadOnly = true, DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter } }); // 绑定数据源 dataGridView1.DataSource = sampleDataTable; // 添加单元格格式化事件 dataGridView1.CellFormatting += DataGridView1_CellFormatting; } /// /// 单元格格式化事件 - 处理平均值行的显示 /// private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (dataGridView1.Columns[e.ColumnIndex].Name == "时间" && e.RowIndex >= 0) { DataGridViewRow row = dataGridView1.Rows[e.RowIndex]; if (row.Cells["序号"].Value != null && row.Cells["序号"].Value.ToString() == "平均时间(s)") { // 计算总平均值并显示 if (row.Cells["试样1"].Value != null) { double avg1 = Convert.ToDouble(row.Cells["试样1"].Value); double avg2 = Convert.ToDouble(row.Cells["试样2"].Value); double avg3 = Convert.ToDouble(row.Cells["试样3"].Value); double avg4 = Convert.ToDouble(row.Cells["试样4"].Value); double avg5 = Convert.ToDouble(row.Cells["试样5"].Value); double overallAvg = (avg1 + avg2 + avg3 + avg4 + avg5) / 5; e.Value = overallAvg.ToString("F2"); e.FormattingApplied = true; } } else if (e.Value != null && e.Value != DBNull.Value) { // 正常时间格式化 DateTime dt = Convert.ToDateTime(e.Value); e.Value = dt.ToString("yyyy-MM-dd HH:mm:ss"); e.FormattingApplied = true; } } } /// /// 初始化事件处理器 /// private void InitializeEventHandlers() { // 连接设备按钮 button1.Click += Button1_Click; // 打印按钮 button2.Click += Button2_Click; // 导出按钮 button3.Click += Button3_Click; // 返回按钮 button4.Click += Button4_Click; // 生成模拟数据按钮 button5.Click += Button5_Click; // 更新日期时间标签 System.Windows.Forms.Timer clockTimer = new System.Windows.Forms.Timer(); clockTimer.Interval = 1000; clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); clockTimer.Start(); } /// /// 连接设备按钮点击事件 /// private void Button1_Click(object sender, EventArgs e) { if (dataTimer.Enabled) { StopDataCollection(); button1.Text = "🔗 连接设备"; button1.BackColor = Color.FromArgb(46, 204, 113); MessageBox.Show("已停止数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { StartDataCollection(); button1.Text = "⏸️ 停止采集"; button1.BackColor = Color.FromArgb(231, 76, 60); MessageBox.Show("开始数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } /// /// 打印按钮点击事件 /// private void Button2_Click(object sender, EventArgs e) { MessageBox.Show("打印功能开发中...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } /// /// 导出按钮点击事件 /// private void Button3_Click(object sender, EventArgs e) { SaveFileDialog saveFileDialog = new SaveFileDialog { Filter = "Excel 文件 (*.xlsx)|*.xlsx|Excel 97-2003 (*.xls)|*.xls", FileName = $"液体吸收测试报告_{DateTime.Now:yyyyMMdd_HHmmss}", Title = "导出数据" }; if (saveFileDialog.ShowDialog() == DialogResult.OK) { GenerateReport(saveFileDialog.FileName); } } /// /// 返回按钮点击事件 /// private void Button4_Click(object sender, EventArgs e) { this.Close(); } /// /// 生成模拟数据按钮点击事件 /// private void Button5_Click(object sender, EventArgs e) { GenerateMockData(); } /// /// 初始化数据表结构 /// private void InitializeDataTable() { sampleDataTable = new DataTable(); sampleDataTable.Columns.Add("序号", typeof(string)); sampleDataTable.Columns.Add("试样1", typeof(double)); sampleDataTable.Columns.Add("试样2", typeof(double)); sampleDataTable.Columns.Add("试样3", typeof(double)); sampleDataTable.Columns.Add("试样4", typeof(double)); sampleDataTable.Columns.Add("试样5", typeof(double)); sampleDataTable.Columns.Add("时间", typeof(DateTime)); } /// /// 初始化定时器用于模拟寄存器数据读取 /// private void InitializeTimer() { dataTimer = new System.Windows.Forms.Timer(); dataTimer.Interval = 1000; // 每秒读取一次 dataTimer.Tick += DataTimer_Tick; } /// /// 定时器事件 - 模拟从寄存器读取数据 /// private void DataTimer_Tick(object sender, EventArgs e) { // 移除旧的平均值行(如果存在) DataRow[] avgRows = sampleDataTable.Select("序号 = '平均时间(s)'"); foreach (DataRow avgRow in avgRows) { sampleDataTable.Rows.Remove(avgRow); } // 模拟从寄存器读取数据(实际应用中替换为真实的寄存器读取代码) double sample1 = ReadRegisterData(0); // 寄存器地址 0 double sample2 = ReadRegisterData(1); // 寄存器地址 1 double sample3 = ReadRegisterData(2); // 寄存器地址 2 double sample4 = ReadRegisterData(3); // 寄存器地址 3 double sample5 = ReadRegisterData(4); // 寄存器地址 4 // 添加到数据表 sampleCount++; DataRow dataRow = sampleDataTable.NewRow(); dataRow["序号"] = $"时间(s)"; dataRow["试样1"] = sample1; dataRow["试样2"] = sample2; dataRow["试样3"] = sample3; dataRow["试样4"] = sample4; dataRow["试样5"] = sample5; dataRow["时间"] = DateTime.Now; sampleDataTable.Rows.Add(dataRow); // 更新界面显示 UpdateDisplay(); } /// /// 模拟从寄存器读取数据 /// 实际应用中替换为真实的 Modbus 或其他协议读取 /// private double ReadRegisterData(int registerAddress) { // 模拟数据:30-34 之间的随机值 Random random = new Random(Guid.NewGuid().GetHashCode()); return 30 + random.NextDouble() * 4; } /// /// 生成模拟测试数据 /// public void GenerateMockData() { // 清空现有数据 sampleDataTable.Clear(); sampleCount = 0; // 生成10条模拟数据 Random random = new Random(); DateTime startTime = DateTime.Now.AddMinutes(-10); for (int i = 0; i < 1; i++) { DataRow dataRow = sampleDataTable.NewRow(); dataRow["序号"] = "时间(s)"; // 为每个试样生成模拟数据(30-34之间的随机值,带小数点) dataRow["试样1"] = Math.Round(30 + random.NextDouble() * 4, 2); dataRow["试样2"] = Math.Round(30 + random.NextDouble() * 4, 2); dataRow["试样3"] = Math.Round(30 + random.NextDouble() * 4, 2); dataRow["试样4"] = Math.Round(30 + random.NextDouble() * 4, 2); dataRow["试样5"] = Math.Round(30 + random.NextDouble() * 4, 2); // 时间递增 dataRow["时间"] = startTime.AddMinutes(i); sampleDataTable.Rows.Add(dataRow); sampleCount++; } // 更新显示(包括平均值) UpdateDisplay(); MessageBox.Show($"已生成 {sampleCount} 条模拟数据", "模拟数据生成", MessageBoxButtons.OK, MessageBoxIcon.Information); } /// /// 更新界面显示 /// private void UpdateDisplay() { // 刷新 DataGridView if (dataGridView1.DataSource != null) { ((DataTable)dataGridView1.DataSource).AcceptChanges(); dataGridView1.Refresh(); } // 计算平均时间并显示 if (sampleDataTable.Rows.Count > 0) { double avgSample1 = sampleDataTable.AsEnumerable().Average(r => r.Field("试样1")); double avgSample2 = sampleDataTable.AsEnumerable().Average(r => r.Field("试样2")); double avgSample3 = sampleDataTable.AsEnumerable().Average(r => r.Field("试样3")); double avgSample4 = sampleDataTable.AsEnumerable().Average(r => r.Field("试样4")); double avgSample5 = sampleDataTable.AsEnumerable().Average(r => r.Field("试样5")); double overallAvg = (avgSample1 + avgSample2 + avgSample3 + avgSample4 + avgSample5) / 5; // 添加平均值行到表格底部(如果还没有) DataRow[] avgRows = sampleDataTable.Select("序号 = '平均时间(s)'"); if (avgRows.Length == 0) { DataRow avgRow = sampleDataTable.NewRow(); avgRow["序号"] = "平均时间(s)"; avgRow["试样1"] = avgSample1; avgRow["试样2"] = avgSample2; avgRow["试样3"] = avgSample3; avgRow["试样4"] = avgSample4; avgRow["试样5"] = avgSample5; // avgRow["时间"] = $"({overallAvg:F2}) 系统计算"; sampleDataTable.Rows.Add(avgRow); } else { // 更新现有平均值行 avgRows[0]["试样1"] = avgSample1; avgRows[0]["试样2"] = avgSample2; avgRows[0]["试样3"] = avgSample3; avgRows[0]["试样4"] = avgSample4; avgRows[0]["试样5"] = avgSample5; // avgRows[0]["时间"] = $"({overallAvg:F2}) 系统计算"; } } } /// /// 启动数据采集 /// public void StartDataCollection() { dataTimer.Start(); } /// /// 停止数据采集 /// public void StopDataCollection() { dataTimer.Stop(); } /// /// 导出数据到 Excel (.xlsx) /// public void ExportToExcel(string filePath) { try { IWorkbook workbook; // 根据文件扩展名选择格式 if (filePath.EndsWith(".xlsx")) { workbook = new XSSFWorkbook(); // Excel 2007+ } else { workbook = new HSSFWorkbook(); // Excel 97-2003 } ISheet sheet = workbook.CreateSheet("液体吸收测试报表"); // 创建标题行 IRow headerRow = sheet.CreateRow(0); headerRow.CreateCell(0).SetCellValue("序号"); headerRow.CreateCell(1).SetCellValue("试样1"); headerRow.CreateCell(2).SetCellValue("试样2"); headerRow.CreateCell(3).SetCellValue("试样3"); headerRow.CreateCell(4).SetCellValue("试样4"); headerRow.CreateCell(5).SetCellValue("试样5"); headerRow.CreateCell(6).SetCellValue("时间"); // 设置标题行样式 ICellStyle headerStyle = workbook.CreateCellStyle(); headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index; headerStyle.FillPattern = FillPattern.SolidForeground; IFont headerFont = workbook.CreateFont(); headerFont.IsBold = true; headerStyle.SetFont(headerFont); for (int i = 0; i < 7; i++) { headerRow.GetCell(i).CellStyle = headerStyle; } // 填充数据 int rowIndex = 1; foreach (DataRow dataRow in sampleDataTable.Rows) { // 跳过平均值行 if (dataRow["序号"].ToString() == "平均时间(s)") continue; IRow row = sheet.CreateRow(rowIndex); row.CreateCell(0).SetCellValue(dataRow["序号"].ToString()); row.CreateCell(1).SetCellValue(Convert.ToDouble(dataRow["试样1"])); row.CreateCell(2).SetCellValue(Convert.ToDouble(dataRow["试样2"])); row.CreateCell(3).SetCellValue(Convert.ToDouble(dataRow["试样3"])); row.CreateCell(4).SetCellValue(Convert.ToDouble(dataRow["试样4"])); row.CreateCell(5).SetCellValue(Convert.ToDouble(dataRow["试样5"])); // 处理时间列 if (dataRow["时间"] != DBNull.Value) { row.CreateCell(6).SetCellValue(Convert.ToDateTime(dataRow["时间"]).ToString("yyyy-MM-dd HH:mm:ss")); } rowIndex++; } // 添加平均值行 IRow avgRow = sheet.CreateRow(rowIndex); avgRow.CreateCell(0).SetCellValue("平均时间(s)"); // 计算平均值(排除平均值行) var dataRows = sampleDataTable.AsEnumerable().Where(r => r.Field("序号") != "平均时间(s)"); double avgSample1 = dataRows.Average(r => r.Field("试样1")); double avgSample2 = dataRows.Average(r => r.Field("试样2")); double avgSample3 = dataRows.Average(r => r.Field("试样3")); double avgSample4 = dataRows.Average(r => r.Field("试样4")); double avgSample5 = dataRows.Average(r => r.Field("试样5")); double overallAvg = (avgSample1 + avgSample2 + avgSample3 + avgSample4 + avgSample5) / 5; avgRow.CreateCell(1).SetCellValue(avgSample1); avgRow.CreateCell(2).SetCellValue(avgSample2); avgRow.CreateCell(3).SetCellValue(avgSample3); avgRow.CreateCell(4).SetCellValue(avgSample4); avgRow.CreateCell(5).SetCellValue(avgSample5); // 显示总平均值 ICell avgCell = avgRow.CreateCell(6); avgCell.SetCellValue(overallAvg.ToString("F2")); // 设置平均值行样式 ICellStyle avgStyle = workbook.CreateCellStyle(); avgStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index; avgStyle.FillPattern = FillPattern.SolidForeground; for (int i = 0; i < 7; i++) { if (avgRow.GetCell(i) != null) { avgRow.GetCell(i).CellStyle = avgStyle; } } // 自动调整列宽 for (int i = 0; i < 7; i++) { sheet.AutoSizeColumn(i); } // 保存文件 using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } MessageBox.Show($"数据已成功导出到:{filePath}", "导出成功", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// /// 生成报表(带格式的 Excel) /// public void GenerateReport(string filePath) { try { IWorkbook workbook = new XSSFWorkbook(); ISheet sheet = workbook.CreateSheet("液体吸收测试报表"); // 创建样式 ICellStyle titleStyle = workbook.CreateCellStyle(); IFont titleFont = workbook.CreateFont(); titleFont.FontHeightInPoints = 16; titleFont.IsBold = true; titleStyle.SetFont(titleFont); titleStyle.Alignment = NPOIHorizontalAlignment.Center; ICellStyle headerStyle = workbook.CreateCellStyle(); headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index; headerStyle.FillPattern = FillPattern.SolidForeground; headerStyle.BorderBottom = NPOIBorderStyle.Thin; headerStyle.BorderTop = NPOIBorderStyle.Thin; headerStyle.BorderLeft = NPOIBorderStyle.Thin; headerStyle.BorderRight = NPOIBorderStyle.Thin; IFont headerFont = workbook.CreateFont(); headerFont.IsBold = true; headerStyle.SetFont(headerFont); headerStyle.Alignment = NPOIHorizontalAlignment.Center; ICellStyle dataStyle = workbook.CreateCellStyle(); dataStyle.BorderBottom = NPOIBorderStyle.Thin; dataStyle.BorderTop = NPOIBorderStyle.Thin; dataStyle.BorderLeft = NPOIBorderStyle.Thin; dataStyle.BorderRight = NPOIBorderStyle.Thin; dataStyle.Alignment = NPOIHorizontalAlignment.Center; // 标题 IRow titleRow = sheet.CreateRow(0); ICell titleCell = titleRow.CreateCell(0); titleCell.SetCellValue("液体吸收测试报表"); titleCell.CellStyle = titleStyle; sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, 6)); // 表头 IRow headerRow = sheet.CreateRow(2); string[] headers = { "序号", "试样1", "试样2", "试样3", "试样4", "试样5", "根据标准" }; for (int i = 0; i < headers.Length; i++) { ICell cell = headerRow.CreateCell(i); cell.SetCellValue(headers[i]); cell.CellStyle = headerStyle; } // 数据行 int rowIndex = 3; IRow timeRow = sheet.CreateRow(rowIndex++); timeRow.CreateCell(0).SetCellValue("时间(s)"); timeRow.GetCell(0).CellStyle = dataStyle; for (int i = 1; i <= 5; i++) { double value = 29 + i; // 示例数据:30, 31, 32, 33, 34 ICell cell = timeRow.CreateCell(i); cell.SetCellValue(value); cell.CellStyle = dataStyle; // 黄色背景 ICellStyle yellowStyle = workbook.CreateCellStyle(); yellowStyle.CloneStyleFrom(dataStyle); yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index; yellowStyle.FillPattern = FillPattern.SolidForeground; cell.CellStyle = yellowStyle; } ICell standardCell = timeRow.CreateCell(6); standardCell.CellStyle = dataStyle; // 平均时间行 IRow avgRow = sheet.CreateRow(rowIndex); avgRow.CreateCell(0).SetCellValue("平均时间(s)"); avgRow.GetCell(0).CellStyle = dataStyle; ICell avgCell = avgRow.CreateCell(1); avgCell.SetCellValue("32"); avgCell.CellStyle = dataStyle; // 黄色背景 ICellStyle avgYellowStyle = workbook.CreateCellStyle(); avgYellowStyle.CloneStyleFrom(dataStyle); avgYellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index; avgYellowStyle.FillPattern = FillPattern.SolidForeground; avgCell.CellStyle = avgYellowStyle; sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, 5)); // 设置列宽 sheet.SetColumnWidth(0, 20 * 256); for (int i = 1; i <= 6; i++) { sheet.SetColumnWidth(i, 15 * 256); } // 保存文件 using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } MessageBox.Show($"报表已成功生成:{filePath}", "生成成功", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { MessageBox.Show($"生成报表失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// /// 清空数据 /// public void ClearData() { sampleDataTable.Clear(); sampleCount = 0; UpdateDisplay(); } } }