diff --git a/WindowsFormsApp6/Form1.Designer.cs b/WindowsFormsApp6/Form1.Designer.cs
index 8f45716..b4a6866 100644
--- a/WindowsFormsApp6/Form1.Designer.cs
+++ b/WindowsFormsApp6/Form1.Designer.cs
@@ -13,9 +13,17 @@
/// true if managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing)
{
- if (disposing && (components != null))
+ if (disposing)
{
- components.Dispose();
+ if (components != null)
+ {
+ components.Dispose();
+ }
+
+ // 释放自定义资源
+ dataTimer?.Dispose();
+ clockTimer?.Dispose();
+ sampleDataTable?.Dispose();
}
base.Dispose(disposing);
}
diff --git a/WindowsFormsApp6/Form1.cs b/WindowsFormsApp6/Form1.cs
index 16a90f6..dcedfc6 100644
--- a/WindowsFormsApp6/Form1.cs
+++ b/WindowsFormsApp6/Form1.cs
@@ -21,9 +21,25 @@ namespace WindowsFormsApp6
{
public partial class Form1 : Form
{
+ #region 常量定义
+ private const int TIMER_INTERVAL = 1000;
+ private const double MIN_SAMPLE_VALUE = 30.0;
+ private const double MAX_SAMPLE_VALUE = 34.0;
+ private const int COLUMN_WIDTH_STANDARD = 150;
+ private const int COLUMN_WIDTH_TIME = 200;
+ private const string AVG_ROW_LABEL = "平均时间(s)";
+ private const string TIME_ROW_LABEL = "时间(s)";
+ private const string DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+ #endregion
+
+ #region 字段
private System.Windows.Forms.Timer dataTimer;
+ private System.Windows.Forms.Timer clockTimer;
private DataTable sampleDataTable;
private int sampleCount = 0;
+ private int currentSampleCount = 5; // 当前试样数量,可动态调整
+ private readonly Random random = new Random();
+ #endregion
public Form1()
{
@@ -39,105 +55,56 @@ namespace WindowsFormsApp6
///
private void InitializeDataGridView()
{
- // 清除现有列
- dataGridView1.Columns.Clear();
-
- // 添加新列以匹配 Excel 表格结构
- dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
+ dataGridView1.SuspendLayout();
+ try
{
- Name = "序号",
- HeaderText = "序号",
- DataPropertyName = "序号",
- Width = 150,
- ReadOnly = true,
- DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter }
- });
+ dataGridView1.Columns.Clear();
- 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) // 黄色背景
- }
- });
+ // 创建共享样式
+ var centerAlignStyle = new DataGridViewCellStyle
+ {
+ Alignment = DataGridViewContentAlignment.MiddleCenter
+ };
- dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
- {
- Name = "试样2",
- HeaderText = "试样2",
- DataPropertyName = "试样2",
- Width = 150,
- ReadOnly = true,
- DefaultCellStyle = new DataGridViewCellStyle
+ var yellowCenterStyle = 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
+ // 添加序号列
+ AddColumn("序号", "序号", COLUMN_WIDTH_STANDARD, centerAlignStyle);
+
+ // 添加试样列
+ for (int i = 1; i <= currentSampleCount; i++)
{
- Alignment = DataGridViewContentAlignment.MiddleCenter,
- BackColor = Color.FromArgb(255, 255, 200)
+ AddColumn($"试样{i}", $"试样{i}", COLUMN_WIDTH_STANDARD, yellowCenterStyle);
}
- });
+ // 绑定数据源
+ dataGridView1.DataSource = sampleDataTable;
+ dataGridView1.CellFormatting += DataGridView1_CellFormatting;
+ }
+ finally
+ {
+ dataGridView1.ResumeLayout();
+ }
+ }
+
+ ///
+ /// 添加列的辅助方法
+ ///
+ private void AddColumn(string name, string headerText, int width, DataGridViewCellStyle style)
+ {
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{
- Name = "试样4",
- HeaderText = "试样4",
- DataPropertyName = "试样4",
- Width = 150,
+ Name = name,
+ HeaderText = headerText,
+ DataPropertyName = name,
+ Width = width,
ReadOnly = true,
- DefaultCellStyle = new DataGridViewCellStyle
- {
- Alignment = DataGridViewContentAlignment.MiddleCenter,
- BackColor = Color.FromArgb(255, 255, 200)
- }
+ DefaultCellStyle = style
});
-
- 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;
}
///
@@ -145,59 +112,62 @@ namespace WindowsFormsApp6
///
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;
+ if (e.RowIndex < 0) return;
- e.Value = overallAvg.ToString("F2");
- e.FormattingApplied = true;
- }
- }
- else if (e.Value != null && e.Value != DBNull.Value)
+ // 格式化数值显示为2位小数
+ if (e.Value != null && e.Value != DBNull.Value)
+ {
+ if (double.TryParse(e.Value.ToString(), out double numValue))
{
- // 正常时间格式化
- DateTime dt = Convert.ToDateTime(e.Value);
- e.Value = dt.ToString("yyyy-MM-dd HH:mm:ss");
+ e.Value = numValue.ToString("F2");
e.FormattingApplied = true;
}
}
}
+ ///
+ /// 尝试计算总平均值
+ ///
+ private bool TryCalculateOverallAverage(DataGridViewRow row, out double overallAvg)
+ {
+ overallAvg = 0;
+ try
+ {
+ double sum = 0;
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ var cellValue = row.Cells[$"试样{i}"].Value;
+ if (cellValue == null) return false;
+ sum += Convert.ToDouble(cellValue);
+ }
+ overallAvg = sum / currentSampleCount;
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ // 移除TryCalculateOverallAverage方法,因为不再需要
+
///
/// 初始化事件处理器
///
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 = new System.Windows.Forms.Timer
+ {
+ Interval = TIMER_INTERVAL
+ };
+ clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString(DATE_TIME_FORMAT);
clockTimer.Start();
}
@@ -209,25 +179,40 @@ namespace WindowsFormsApp6
if (dataTimer.Enabled)
{
StopDataCollection();
- button1.Text = "🔗 连接设备";
- button1.BackColor = Color.FromArgb(46, 204, 113);
- MessageBox.Show("已停止数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ UpdateButtonState(button1, "🔗 连接设备", Color.FromArgb(46, 204, 113));
+ ShowMessage("已停止数据采集");
}
else
{
StartDataCollection();
- button1.Text = "⏸️ 停止采集";
- button1.BackColor = Color.FromArgb(231, 76, 60);
- MessageBox.Show("开始数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ UpdateButtonState(button1, "⏸️ 停止采集", Color.FromArgb(231, 76, 60));
+ ShowMessage("开始数据采集");
}
}
+ ///
+ /// 更新按钮状态
+ ///
+ private void UpdateButtonState(Button button, string text, Color backColor)
+ {
+ button.Text = text;
+ button.BackColor = backColor;
+ }
+
+ ///
+ /// 显示提示消息
+ ///
+ private void ShowMessage(string message, string title = "提示", MessageBoxIcon icon = MessageBoxIcon.Information)
+ {
+ MessageBox.Show(message, title, MessageBoxButtons.OK, icon);
+ }
+
///
/// 打印按钮点击事件
///
private void Button2_Click(object sender, EventArgs e)
{
- MessageBox.Show("打印功能开发中...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage("打印功能开发中...");
}
///
@@ -271,12 +256,27 @@ namespace WindowsFormsApp6
{
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));
+
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ sampleDataTable.Columns.Add($"试样{i}", typeof(double));
+ }
+ }
+
+ ///
+ /// 设置试样数量并重新初始化
+ ///
+ public void SetSampleCount(int count)
+ {
+ if (count < 1 || count > 20)
+ {
+ ShowMessage("试样数量必须在1-20之间", "参数错误", MessageBoxIcon.Warning);
+ return;
+ }
+
+ currentSampleCount = count;
+ InitializeDataTable();
+ InitializeDataGridView();
}
///
@@ -284,8 +284,10 @@ namespace WindowsFormsApp6
///
private void InitializeTimer()
{
- dataTimer = new System.Windows.Forms.Timer();
- dataTimer.Interval = 1000; // 每秒读取一次
+ dataTimer = new System.Windows.Forms.Timer
+ {
+ Interval = TIMER_INTERVAL
+ };
dataTimer.Tick += DataTimer_Tick;
}
@@ -294,36 +296,38 @@ namespace WindowsFormsApp6
///
private void DataTimer_Tick(object sender, EventArgs e)
{
- // 移除旧的平均值行(如果存在)
- DataRow[] avgRows = sampleDataTable.Select("序号 = '平均时间(s)'");
- foreach (DataRow avgRow in avgRows)
- {
- sampleDataTable.Rows.Remove(avgRow);
- }
+ // 移除旧的平均值行
+ RemoveAverageRows();
- // 模拟从寄存器读取数据(实际应用中替换为真实的寄存器读取代码)
- 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;
+ dataRow["序号"] = TIME_ROW_LABEL;
+
+ // 读取寄存器数据
+ for (int i = 0; i < currentSampleCount; i++)
+ {
+ dataRow[$"试样{i + 1}"] = ReadRegisterData(i);
+ }
+
+ // 不再设置时间列
sampleDataTable.Rows.Add(dataRow);
+ sampleCount++;
- // 更新界面显示
UpdateDisplay();
}
+ ///
+ /// 移除平均值行
+ ///
+ private void RemoveAverageRows()
+ {
+ var avgRows = sampleDataTable.Select($"序号 = '{AVG_ROW_LABEL}'");
+ foreach (var row in avgRows)
+ {
+ sampleDataTable.Rows.Remove(row);
+ }
+ }
+
///
/// 模拟从寄存器读取数据
/// 实际应用中替换为真实的 Modbus 或其他协议读取
@@ -331,8 +335,7 @@ namespace WindowsFormsApp6
private double ReadRegisterData(int registerAddress)
{
// 模拟数据:30-34 之间的随机值
- Random random = new Random(Guid.NewGuid().GetHashCode());
- return 30 + random.NextDouble() * 4;
+ return MIN_SAMPLE_VALUE + random.NextDouble() * (MAX_SAMPLE_VALUE - MIN_SAMPLE_VALUE);
}
///
@@ -340,37 +343,30 @@ namespace WindowsFormsApp6
///
public void GenerateMockData()
{
- // 清空现有数据
sampleDataTable.Clear();
sampleCount = 0;
- // 生成10条模拟数据
- Random random = new Random();
- DateTime startTime = DateTime.Now.AddMinutes(-10);
+ const int mockDataCount = 1;
- for (int i = 0; i < 1; i++)
+ for (int i = 0; i < mockDataCount; i++)
{
DataRow dataRow = sampleDataTable.NewRow();
- dataRow["序号"] = "时间(s)";
+ dataRow["序号"] = TIME_ROW_LABEL;
- // 为每个试样生成模拟数据(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);
+ // 为每个试样生成模拟数据
+ for (int j = 1; j <= currentSampleCount; j++)
+ {
+ double value = MIN_SAMPLE_VALUE + random.NextDouble() * (MAX_SAMPLE_VALUE - MIN_SAMPLE_VALUE);
+ dataRow[$"试样{j}"] = Math.Round(value, 2);
+ }
+ // 不再设置时间列
sampleDataTable.Rows.Add(dataRow);
sampleCount++;
}
- // 更新显示(包括平均值)
UpdateDisplay();
-
- MessageBox.Show($"已生成 {sampleCount} 条模拟数据", "模拟数据生成", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage($"已生成 {sampleCount} 条模拟数据", "模拟数据生成");
}
///
@@ -378,51 +374,71 @@ namespace WindowsFormsApp6
///
private void UpdateDisplay()
{
- // 刷新 DataGridView
- if (dataGridView1.DataSource != null)
+ if (sampleDataTable.Rows.Count == 0)
+ return;
+
+ // 计算并添加/更新平均值行
+ var averages = CalculateAverages();
+ UpdateAverageRow(averages);
+
+ // 刷新界面
+ RefreshDataGridView();
+ }
+
+ ///
+ /// 计算各试样的平均值
+ ///
+ private double[] CalculateAverages()
+ {
+ var averages = new double[currentSampleCount];
+ for (int i = 1; i <= currentSampleCount; i++)
{
- ((DataTable)dataGridView1.DataSource).AcceptChanges();
- dataGridView1.Refresh();
+ averages[i - 1] = sampleDataTable.AsEnumerable()
+ .Average(r => r.Field($"试样{i}"));
}
+ return averages;
+ }
- // 计算平均时间并显示
- if (sampleDataTable.Rows.Count > 0)
+ ///
+ /// 更新或添加平均值行
+ ///
+ private void UpdateAverageRow(double[] averages)
+ {
+ var avgRows = sampleDataTable.Select($"序号 = '{AVG_ROW_LABEL}'");
+
+ if (avgRows.Length == 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["序号"] = AVG_ROW_LABEL;
+ for (int i = 0; i < currentSampleCount; i++)
{
- 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);
+ avgRow[$"试样{i + 1}"] = averages[i];
}
- else
+ sampleDataTable.Rows.Add(avgRow);
+ }
+ else
+ {
+ // 更新现有平均值行
+ for (int i = 0; i < currentSampleCount; i++)
{
- // 更新现有平均值行
- avgRows[0]["试样1"] = avgSample1;
- avgRows[0]["试样2"] = avgSample2;
- avgRows[0]["试样3"] = avgSample3;
- avgRows[0]["试样4"] = avgSample4;
- avgRows[0]["试样5"] = avgSample5;
- // avgRows[0]["时间"] = $"({overallAvg:F2}) 系统计算";
+ avgRows[0][$"试样{i + 1}"] = averages[i];
}
}
}
+ ///
+ /// 刷新DataGridView
+ ///
+ private void RefreshDataGridView()
+ {
+ if (dataGridView1.DataSource is DataTable dt)
+ {
+ dt.AcceptChanges();
+ dataGridView1.Refresh();
+ }
+ }
+
///
/// 启动数据采集
///
@@ -446,121 +462,165 @@ namespace WindowsFormsApp6
{
try
{
- IWorkbook workbook;
-
- // 根据文件扩展名选择格式
- if (filePath.EndsWith(".xlsx"))
- {
- workbook = new XSSFWorkbook(); // Excel 2007+
- }
- else
- {
- workbook = new HSSFWorkbook(); // Excel 97-2003
- }
-
+ IWorkbook workbook = CreateWorkbook(filePath);
ISheet sheet = workbook.CreateSheet("液体吸收测试报表");
+ // 创建样式
+ var styles = CreateExcelStyles(workbook);
+
// 创建标题行
- 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;
- }
+ CreateHeaderRow(sheet, styles.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++;
- }
+ FillDataRows(sheet, styles.dataStyle);
// 添加平均值行
- 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;
- }
- }
+ AddAverageRow(sheet, styles.avgStyle);
// 自动调整列宽
- for (int i = 0; i < 7; i++)
- {
- sheet.AutoSizeColumn(i);
- }
+ AutoSizeColumns(sheet, 7);
// 保存文件
- using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
- {
- workbook.Write(fs);
- }
+ SaveWorkbook(workbook, filePath);
- MessageBox.Show($"数据已成功导出到:{filePath}", "导出成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage($"数据已成功导出到:{filePath}", "导出成功");
}
catch (Exception ex)
{
- MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ ShowMessage($"导出失败:{ex.Message}", "错误", MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// 创建工作簿
+ ///
+ private IWorkbook CreateWorkbook(string filePath)
+ {
+ return filePath.EndsWith(".xlsx")
+ ? (IWorkbook)new XSSFWorkbook()
+ : new HSSFWorkbook();
+ }
+
+ ///
+ /// 创建Excel样式
+ ///
+ private (ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle avgStyle) CreateExcelStyles(IWorkbook workbook)
+ {
+ // 标题样式
+ 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);
+
+ // 数据样式
+ ICellStyle dataStyle = workbook.CreateCellStyle();
+
+ // 平均值样式
+ ICellStyle avgStyle = workbook.CreateCellStyle();
+ avgStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
+ avgStyle.FillPattern = FillPattern.SolidForeground;
+
+ return (headerStyle, dataStyle, avgStyle);
+ }
+
+ ///
+ /// 创建标题行
+ ///
+ private void CreateHeaderRow(ISheet sheet, ICellStyle headerStyle)
+ {
+ IRow headerRow = sheet.CreateRow(0);
+
+ // 序号列
+ ICell cell0 = headerRow.CreateCell(0);
+ cell0.SetCellValue("序号");
+ cell0.CellStyle = headerStyle;
+
+ // 动态创建试样列
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ ICell cell = headerRow.CreateCell(i);
+ cell.SetCellValue($"试样{i}");
+ cell.CellStyle = headerStyle;
+ }
+ }
+
+ ///
+ /// 填充数据行
+ ///
+ private void FillDataRows(ISheet sheet, ICellStyle dataStyle)
+ {
+ int rowIndex = 1;
+ foreach (DataRow dataRow in sampleDataTable.Rows)
+ {
+ if (dataRow["序号"].ToString() == AVG_ROW_LABEL)
+ continue;
+
+ IRow row = sheet.CreateRow(rowIndex++);
+ row.CreateCell(0).SetCellValue(dataRow["序号"].ToString());
+
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ row.CreateCell(i).SetCellValue(Convert.ToDouble(dataRow[$"试样{i}"]));
+ }
+ }
+ }
+
+ ///
+ /// 添加平均值行
+ ///
+ private void AddAverageRow(ISheet sheet, ICellStyle avgStyle)
+ {
+ var dataRows = sampleDataTable.AsEnumerable()
+ .Where(r => r.Field("序号") != AVG_ROW_LABEL);
+
+ if (!dataRows.Any())
+ return;
+
+ int rowIndex = sheet.LastRowNum + 1;
+ IRow avgRow = sheet.CreateRow(rowIndex);
+ avgRow.CreateCell(0).SetCellValue(AVG_ROW_LABEL);
+
+ double[] averages = new double[currentSampleCount];
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ averages[i - 1] = dataRows.Average(r => r.Field($"试样{i}"));
+ avgRow.CreateCell(i).SetCellValue(averages[i - 1]);
+ }
+
+ // 不再添加总平均值到时间列
+
+ // 应用样式
+ for (int i = 0; i <= currentSampleCount; i++)
+ {
+ var cell = avgRow.GetCell(i);
+ if (cell != null)
+ {
+ cell.CellStyle = avgStyle;
+ }
+ }
+ }
+
+ ///
+ /// 自动调整列宽
+ ///
+ private void AutoSizeColumns(ISheet sheet, int columnCount)
+ {
+ for (int i = 0; i <= currentSampleCount; i++)
+ {
+ sheet.AutoSizeColumn(i);
+ }
+ }
+
+ ///
+ /// 保存工作簿
+ ///
+ private void SaveWorkbook(IWorkbook workbook, string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
+ {
+ workbook.Write(fs);
}
}
@@ -575,109 +635,158 @@ namespace WindowsFormsApp6
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;
+ var styles = CreateReportStyles(workbook);
- 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;
+ // 创建标题
+ CreateReportTitle(sheet, styles.titleStyle);
- ICellStyle dataStyle = workbook.CreateCellStyle();
- dataStyle.BorderBottom = NPOIBorderStyle.Thin;
- dataStyle.BorderTop = NPOIBorderStyle.Thin;
- dataStyle.BorderLeft = NPOIBorderStyle.Thin;
- dataStyle.BorderRight = NPOIBorderStyle.Thin;
- dataStyle.Alignment = NPOIHorizontalAlignment.Center;
+ // 创建表头
+ CreateReportHeader(sheet, styles.headerStyle);
- // 标题
- 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));
+ // 创建数据行
+ CreateReportDataRows(sheet, styles.dataStyle, styles.yellowStyle);
// 设置列宽
- sheet.SetColumnWidth(0, 20 * 256);
- for (int i = 1; i <= 6; i++)
- {
- sheet.SetColumnWidth(i, 15 * 256);
- }
+ SetReportColumnWidths(sheet);
// 保存文件
- using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
- {
- workbook.Write(fs);
- }
+ SaveWorkbook(workbook, filePath);
- MessageBox.Show($"报表已成功生成:{filePath}", "生成成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage($"报表已成功生成:{filePath}", "生成成功");
}
catch (Exception ex)
{
- MessageBox.Show($"生成报表失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ ShowMessage($"生成报表失败:{ex.Message}", "错误", MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// 创建报表样式
+ ///
+ private (ICellStyle titleStyle, ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle yellowStyle)
+ CreateReportStyles(IWorkbook workbook)
+ {
+ // 标题样式
+ 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;
+ SetBorders(headerStyle);
+ IFont headerFont = workbook.CreateFont();
+ headerFont.IsBold = true;
+ headerStyle.SetFont(headerFont);
+ headerStyle.Alignment = NPOIHorizontalAlignment.Center;
+
+ // 数据样式
+ ICellStyle dataStyle = workbook.CreateCellStyle();
+ SetBorders(dataStyle);
+ dataStyle.Alignment = NPOIHorizontalAlignment.Center;
+
+ // 黄色背景样式
+ ICellStyle yellowStyle = workbook.CreateCellStyle();
+ yellowStyle.CloneStyleFrom(dataStyle);
+ yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
+ yellowStyle.FillPattern = FillPattern.SolidForeground;
+
+ return (titleStyle, headerStyle, dataStyle, yellowStyle);
+ }
+
+ ///
+ /// 设置单元格边框
+ ///
+ private void SetBorders(ICellStyle style)
+ {
+ style.BorderBottom = NPOIBorderStyle.Thin;
+ style.BorderTop = NPOIBorderStyle.Thin;
+ style.BorderLeft = NPOIBorderStyle.Thin;
+ style.BorderRight = NPOIBorderStyle.Thin;
+ }
+
+ ///
+ /// 创建报表标题
+ ///
+ private void CreateReportTitle(ISheet sheet, ICellStyle titleStyle)
+ {
+ IRow titleRow = sheet.CreateRow(0);
+ ICell titleCell = titleRow.CreateCell(0);
+ titleCell.SetCellValue("液体吸收测试报表");
+ titleCell.CellStyle = titleStyle;
+ sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, currentSampleCount));
+ }
+
+ ///
+ /// 创建报表表头
+ ///
+ private void CreateReportHeader(ISheet sheet, ICellStyle headerStyle)
+ {
+ IRow headerRow = sheet.CreateRow(2);
+
+ // 序号列
+ ICell cell0 = headerRow.CreateCell(0);
+ cell0.SetCellValue("序号");
+ cell0.CellStyle = headerStyle;
+
+ // 动态创建试样列
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ ICell cell = headerRow.CreateCell(i);
+ cell.SetCellValue($"试样{i}");
+ cell.CellStyle = headerStyle;
+ }
+
+ // 不再添加"根据标准"列
+ }
+
+ ///
+ /// 创建报表数据行
+ ///
+ private void CreateReportDataRows(ISheet sheet, ICellStyle dataStyle, ICellStyle yellowStyle)
+ {
+ int rowIndex = 3;
+
+ // 时间行
+ IRow timeRow = sheet.CreateRow(rowIndex++);
+ timeRow.CreateCell(0).SetCellValue(TIME_ROW_LABEL);
+ timeRow.GetCell(0).CellStyle = dataStyle;
+
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ double value = 29 + i; // 示例数据
+ ICell cell = timeRow.CreateCell(i);
+ cell.SetCellValue(value);
+ cell.CellStyle = yellowStyle;
+ }
+
+ // 不再添加"根据标准"列
+
+ // 平均时间行
+ IRow avgRow = sheet.CreateRow(rowIndex);
+ avgRow.CreateCell(0).SetCellValue(AVG_ROW_LABEL);
+ avgRow.GetCell(0).CellStyle = dataStyle;
+
+ ICell avgCell = avgRow.CreateCell(1);
+ avgCell.SetCellValue("32");
+ avgCell.CellStyle = yellowStyle;
+
+ sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, currentSampleCount));
+ }
+
+ ///
+ /// 设置报表列宽
+ ///
+ private void SetReportColumnWidths(ISheet sheet)
+ {
+ sheet.SetColumnWidth(0, 20 * 256);
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ sheet.SetColumnWidth(i, 15 * 256);
}
}
diff --git a/WindowsFormsApp6/Form2.Designer.cs b/WindowsFormsApp6/Form2.Designer.cs
index 7848680..c210f91 100644
--- a/WindowsFormsApp6/Form2.Designer.cs
+++ b/WindowsFormsApp6/Form2.Designer.cs
@@ -13,9 +13,17 @@
/// true if managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing)
{
- if (disposing && (components != null))
+ if (disposing)
{
- components.Dispose();
+ if (components != null)
+ {
+ components.Dispose();
+ }
+
+ // 释放自定义资源
+ dataTimer?.Dispose();
+ clockTimer?.Dispose();
+ sampleDataTable?.Dispose();
}
base.Dispose(disposing);
}
diff --git a/WindowsFormsApp6/Form2.cs b/WindowsFormsApp6/Form2.cs
index 6ef9f92..e8082e0 100644
--- a/WindowsFormsApp6/Form2.cs
+++ b/WindowsFormsApp6/Form2.cs
@@ -21,9 +21,26 @@ namespace WindowsFormsApp6
{
public partial class Form2 : Form
{
+ #region 常量定义
+ private const int TIMER_INTERVAL = 1000;
+ private const double MIN_WEIGHT = 10.0;
+ private const double MAX_WEIGHT = 20.0;
+ private const string DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+ private const string ROW_INITIAL_WEIGHT = "初始重量(g)";
+ private const string ROW_AFTER_WEIGHT = "浸润后重量(g)";
+ private const string ROW_ABSORPTION = "液体吸收量(%)";
+ private const string ROW_AVG_ABSORPTION = "液体吸收量平均值(%)";
+ private const string ROW_MAX_ABSORPTION = "液体吸收量最大值(%)";
+ #endregion
+
+ #region 字段
private System.Windows.Forms.Timer dataTimer;
+ private System.Windows.Forms.Timer clockTimer;
private DataTable sampleDataTable;
private int sampleCount = 0;
+ private int currentSampleCount = 5; // 当前试样数量,可动态调整
+ private readonly Random random = new Random();
+ #endregion
public Form2()
{
@@ -39,136 +56,71 @@ namespace WindowsFormsApp6
///
private void InitializeDataGridView()
{
- // 清除现有列
- dataGridView1.Columns.Clear();
-
- // 添加新列以匹配 Excel 表格结构
- dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
+ dataGridView1.SuspendLayout();
+ try
{
- Name = "序号",
- HeaderText = "序号",
- DataPropertyName = "序号",
- Width = 150,
- ReadOnly = true,
- DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter }
- });
+ dataGridView1.Columns.Clear();
- dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
- {
- Name = "试样1",
- HeaderText = "试样1",
- DataPropertyName = "试样1",
- Width = 150,
- ReadOnly = true,
- DefaultCellStyle = new DataGridViewCellStyle
+ // 创建共享样式
+ var centerStyle = new DataGridViewCellStyle
{
- Alignment = DataGridViewContentAlignment.MiddleCenter,
- BackColor = Color.FromArgb(255, 255, 200) // 黄色背景
- }
- });
+ Alignment = DataGridViewContentAlignment.MiddleCenter
+ };
- dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
- {
- Name = "试样2",
- HeaderText = "试样2",
- DataPropertyName = "试样2",
- Width = 150,
- ReadOnly = true,
- DefaultCellStyle = new DataGridViewCellStyle
+ var yellowCenterStyle = 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
+ // 添加序号列
+ dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{
- Alignment = DataGridViewContentAlignment.MiddleCenter,
- BackColor = Color.FromArgb(255, 255, 200)
- }
- });
+ Name = "序号",
+ HeaderText = "序号",
+ DataPropertyName = "序号",
+ Width = 180,
+ ReadOnly = true,
+ DefaultCellStyle = centerStyle
+ });
- dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
- {
- Name = "试样4",
- HeaderText = "试样4",
- DataPropertyName = "试样4",
- Width = 150,
- ReadOnly = true,
- DefaultCellStyle = new DataGridViewCellStyle
+ // 根据当前试样数量动态添加列
+ for (int i = 1; i <= currentSampleCount; i++)
{
- Alignment = DataGridViewContentAlignment.MiddleCenter,
- BackColor = Color.FromArgb(255, 255, 200)
+ dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
+ {
+ Name = $"试样{i}",
+ HeaderText = $"试样{i}",
+ DataPropertyName = $"试样{i}",
+ Width = 150,
+ ReadOnly = true,
+ DefaultCellStyle = yellowCenterStyle
+ });
}
- });
- dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
+ // 绑定数据源
+ dataGridView1.DataSource = sampleDataTable;
+ dataGridView1.CellFormatting += DataGridView1_CellFormatting;
+ }
+ finally
{
- 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;
+ dataGridView1.ResumeLayout();
+ }
}
///
- /// 单元格格式化事件 - 处理平均值行的显示
+ /// 单元格格式化事件
///
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;
+ if (e.RowIndex < 0) return;
- e.Value = overallAvg.ToString("F2");
- e.FormattingApplied = true;
- }
- }
- else if (e.Value != null && e.Value != DBNull.Value)
+ // 格式化数值显示为2位小数
+ if (e.Value != null && e.Value != DBNull.Value)
+ {
+ if (double.TryParse(e.Value.ToString(), out double numValue))
{
- // 正常时间格式化
- DateTime dt = Convert.ToDateTime(e.Value);
- e.Value = dt.ToString("yyyy-MM-dd HH:mm:ss");
+ e.Value = numValue.ToString("F2");
e.FormattingApplied = true;
}
}
@@ -179,25 +131,17 @@ namespace WindowsFormsApp6
///
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 = new System.Windows.Forms.Timer
+ {
+ Interval = TIMER_INTERVAL
+ };
+ clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString(DATE_TIME_FORMAT);
clockTimer.Start();
}
@@ -209,16 +153,14 @@ namespace WindowsFormsApp6
if (dataTimer.Enabled)
{
StopDataCollection();
- button1.Text = "🔗 连接设备";
- button1.BackColor = Color.FromArgb(46, 204, 113);
- MessageBox.Show("已停止数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ UpdateButtonState(button1, "🔗 连接设备", Color.FromArgb(46, 204, 113));
+ ShowMessage("已停止数据采集");
}
else
{
StartDataCollection();
- button1.Text = "⏸️ 停止采集";
- button1.BackColor = Color.FromArgb(231, 76, 60);
- MessageBox.Show("开始数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ UpdateButtonState(button1, "⏸️ 停止采集", Color.FromArgb(231, 76, 60));
+ ShowMessage("开始数据采集");
}
}
@@ -227,7 +169,24 @@ namespace WindowsFormsApp6
///
private void Button2_Click(object sender, EventArgs e)
{
- MessageBox.Show("打印功能开发中...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage("打印功能开发中...");
+ }
+
+ ///
+ /// 更新按钮状态
+ ///
+ private void UpdateButtonState(Button button, string text, Color backColor)
+ {
+ button.Text = text;
+ button.BackColor = backColor;
+ }
+
+ ///
+ /// 显示提示消息
+ ///
+ private void ShowMessage(string message, string title = "提示", MessageBoxIcon icon = MessageBoxIcon.Information)
+ {
+ MessageBox.Show(message, title, MessageBoxButtons.OK, icon);
}
///
@@ -271,12 +230,28 @@ namespace WindowsFormsApp6
{
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));
+
+ // 根据当前试样数量动态添加列
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ sampleDataTable.Columns.Add($"试样{i}", typeof(object));
+ }
+ }
+
+ ///
+ /// 设置试样数量并重新初始化
+ ///
+ public void SetSampleCount(int count)
+ {
+ if (count < 1 || count > 20) // 限制最大20个试样
+ {
+ ShowMessage("试样数量必须在1-20之间", "参数错误", MessageBoxIcon.Warning);
+ return;
+ }
+
+ currentSampleCount = count;
+ InitializeDataTable();
+ InitializeDataGridView();
}
///
@@ -284,8 +259,10 @@ namespace WindowsFormsApp6
///
private void InitializeTimer()
{
- dataTimer = new System.Windows.Forms.Timer();
- dataTimer.Interval = 1000; // 每秒读取一次
+ dataTimer = new System.Windows.Forms.Timer
+ {
+ Interval = TIMER_INTERVAL
+ };
dataTimer.Tick += DataTimer_Tick;
}
@@ -294,45 +271,48 @@ namespace WindowsFormsApp6
///
private void DataTimer_Tick(object sender, EventArgs e)
{
- // 移除旧的平均值行(如果存在)
- DataRow[] avgRows = sampleDataTable.Select("序号 = '平均时间(s)'");
- foreach (DataRow avgRow in avgRows)
+ // 清除旧的计算行
+ RemoveCalculatedRows();
+
+ // 读取初始重量和浸润后重量
+ double[] initialWeights = new double[currentSampleCount];
+ double[] afterWeights = new double[currentSampleCount];
+
+ for (int i = 0; i < currentSampleCount; i++)
{
- sampleDataTable.Rows.Remove(avgRow);
+ initialWeights[i] = ReadRegisterData(i * 2); // 初始重量
+ afterWeights[i] = ReadRegisterData(i * 2 + 1); // 浸润后重量
}
- // 模拟从寄存器读取数据(实际应用中替换为真实的寄存器读取代码)
- 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(initialWeights, afterWeights);
+ }
- // 更新界面显示
- UpdateDisplay();
+ ///
+ /// 移除计算行
+ ///
+ private void RemoveCalculatedRows()
+ {
+ var rowsToRemove = sampleDataTable.AsEnumerable()
+ .Where(r => r.Field("序号") == ROW_ABSORPTION ||
+ r.Field("序号") == ROW_AVG_ABSORPTION ||
+ r.Field("序号") == ROW_MAX_ABSORPTION)
+ .ToList();
+
+ foreach (var row in rowsToRemove)
+ {
+ sampleDataTable.Rows.Remove(row);
+ }
}
///
/// 模拟从寄存器读取数据
- /// 实际应用中替换为真实的 Modbus 或其他协议读取
///
private double ReadRegisterData(int registerAddress)
{
- // 模拟数据:30-34 之间的随机值
- Random random = new Random(Guid.NewGuid().GetHashCode());
- return 30 + random.NextDouble() * 4;
+ return MIN_WEIGHT + random.NextDouble() * (MAX_WEIGHT - MIN_WEIGHT);
}
///
@@ -340,86 +320,125 @@ namespace WindowsFormsApp6
///
public void GenerateMockData()
{
- // 清空现有数据
sampleDataTable.Clear();
sampleCount = 0;
- // 生成10条模拟数据
- Random random = new Random();
- DateTime startTime = DateTime.Now.AddMinutes(-10);
+ // 生成模拟数据
+ double[] initialWeights = new double[currentSampleCount];
+ double[] afterWeights = new double[currentSampleCount];
- for (int i = 0; i < 10; i++)
+ for (int i = 0; i < currentSampleCount; 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++;
+ initialWeights[i] = Math.Round(MIN_WEIGHT + random.NextDouble() * (MAX_WEIGHT - MIN_WEIGHT), 2);
+ afterWeights[i] = Math.Round(initialWeights[i] * (1.2 + random.NextDouble() * 0.3), 2); // 浸润后增重20%-50%
}
- // 更新显示(包括平均值)
- UpdateDisplay();
+ sampleCount = 1;
+ UpdateDisplay(initialWeights, afterWeights);
- MessageBox.Show($"已生成 {sampleCount} 条模拟数据", "模拟数据生成", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage($"已生成 {currentSampleCount} 个试样的模拟数据", "模拟数据生成");
}
///
/// 更新界面显示
///
- private void UpdateDisplay()
+ private void UpdateDisplay(double[] initialWeights, double[] afterWeights)
{
- // 刷新 DataGridView
- if (dataGridView1.DataSource != null)
+ sampleDataTable.Clear();
+
+ int count = Math.Min(initialWeights.Length, currentSampleCount);
+
+ // 1. 初始重量行
+ DataRow initialRow = sampleDataTable.NewRow();
+ initialRow["序号"] = ROW_INITIAL_WEIGHT;
+ for (int i = 0; i < count; i++)
{
- ((DataTable)dataGridView1.DataSource).AcceptChanges();
- dataGridView1.Refresh();
+ initialRow[$"试样{i + 1}"] = initialWeights[i];
}
+ sampleDataTable.Rows.Add(initialRow);
- // 计算平均时间并显示
- if (sampleDataTable.Rows.Count > 0)
+ // 2. 浸润后重量行
+ DataRow afterRow = sampleDataTable.NewRow();
+ afterRow["序号"] = ROW_AFTER_WEIGHT;
+ for (int i = 0; i < count; i++)
{
- 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"));
+ afterRow[$"试样{i + 1}"] = afterWeights[i];
+ }
+ sampleDataTable.Rows.Add(afterRow);
- double overallAvg = (avgSample1 + avgSample2 + avgSample3 + avgSample4 + avgSample5) / 5;
+ // 3. 液体吸收量行 (%)
+ DataRow absorptionRow = sampleDataTable.NewRow();
+ absorptionRow["序号"] = ROW_ABSORPTION;
+ double[] absorptions = new double[count];
+ for (int i = 0; i < count; i++)
+ {
+ absorptions[i] = ((afterWeights[i] - initialWeights[i]) / initialWeights[i]) * 100;
+ absorptionRow[$"试样{i + 1}"] = absorptions[i];
+ }
+ sampleDataTable.Rows.Add(absorptionRow);
- // 添加平均值行到表格底部(如果还没有)
- 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}) 系统计算";
- }
+ // 4. 液体吸收量平均值行
+ DataRow avgRow = sampleDataTable.NewRow();
+ avgRow["序号"] = ROW_AVG_ABSORPTION;
+ double avgAbsorption = absorptions.Average();
+ double stdDev = CalculateStandardDeviation(absorptions);
+
+ // 第1列显示平均值
+ avgRow["试样1"] = avgAbsorption;
+
+ // 第2列显示标准偏差
+ if (count >= 2)
+ {
+ avgRow["试样2"] = stdDev;
+ }
+
+ // 其他列为空
+ for (int i = 3; i <= count; i++)
+ {
+ avgRow[$"试样{i}"] = DBNull.Value;
+ }
+ sampleDataTable.Rows.Add(avgRow);
+
+ // 5. 液体吸收量最大值行
+ DataRow maxRow = sampleDataTable.NewRow();
+ maxRow["序号"] = ROW_MAX_ABSORPTION;
+ double maxAbsorption = absorptions.Max();
+
+ // 第1列显示最大值
+ maxRow["试样1"] = maxAbsorption;
+
+ // 其他列为空
+ for (int i = 2; i <= count; i++)
+ {
+ maxRow[$"试样{i}"] = DBNull.Value;
+ }
+ sampleDataTable.Rows.Add(maxRow);
+
+ // 刷新界面
+ RefreshDataGridView();
+ }
+
+ ///
+ /// 计算标准偏差
+ ///
+ private double CalculateStandardDeviation(double[] values)
+ {
+ if (values.Length == 0) return 0;
+
+ double avg = values.Average();
+ double sumOfSquares = values.Sum(val => Math.Pow(val - avg, 2));
+ return Math.Sqrt(sumOfSquares / values.Length);
+ }
+
+ ///
+ /// 刷新DataGridView
+ ///
+ private void RefreshDataGridView()
+ {
+ if (dataGridView1.DataSource is DataTable dt)
+ {
+ dt.AcceptChanges();
+ dataGridView1.Refresh();
}
}
@@ -439,131 +458,6 @@ namespace WindowsFormsApp6
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)
///
@@ -575,109 +469,173 @@ namespace WindowsFormsApp6
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;
+ var styles = CreateReportStyles(workbook);
- 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;
+ // 创建标题
+ CreateReportTitle(sheet, styles.titleStyle);
- ICellStyle dataStyle = workbook.CreateCellStyle();
- dataStyle.BorderBottom = NPOIBorderStyle.Thin;
- dataStyle.BorderTop = NPOIBorderStyle.Thin;
- dataStyle.BorderLeft = NPOIBorderStyle.Thin;
- dataStyle.BorderRight = NPOIBorderStyle.Thin;
- dataStyle.Alignment = NPOIHorizontalAlignment.Center;
+ // 创建表头
+ CreateReportHeader(sheet, styles.headerStyle);
- // 标题
- 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));
+ // 填充数据
+ FillReportData(sheet, styles.dataStyle, styles.yellowStyle);
// 设置列宽
- sheet.SetColumnWidth(0, 20 * 256);
- for (int i = 1; i <= 6; i++)
- {
- sheet.SetColumnWidth(i, 15 * 256);
- }
+ SetReportColumnWidths(sheet);
// 保存文件
- using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
- {
- workbook.Write(fs);
- }
+ SaveWorkbook(workbook, filePath);
- MessageBox.Show($"报表已成功生成:{filePath}", "生成成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage($"报表已成功生成:{filePath}", "生成成功");
}
catch (Exception ex)
{
- MessageBox.Show($"生成报表失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ ShowMessage($"生成报表失败:{ex.Message}", "错误", MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// 创建报表样式
+ ///
+ private (ICellStyle titleStyle, ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle yellowStyle)
+ CreateReportStyles(IWorkbook workbook)
+ {
+ // 标题样式
+ 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;
+ SetBorders(headerStyle);
+ IFont headerFont = workbook.CreateFont();
+ headerFont.IsBold = true;
+ headerStyle.SetFont(headerFont);
+ headerStyle.Alignment = NPOIHorizontalAlignment.Center;
+
+ // 数据样式
+ ICellStyle dataStyle = workbook.CreateCellStyle();
+ SetBorders(dataStyle);
+ dataStyle.Alignment = NPOIHorizontalAlignment.Center;
+
+ // 黄色背景样式
+ ICellStyle yellowStyle = workbook.CreateCellStyle();
+ yellowStyle.CloneStyleFrom(dataStyle);
+ yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
+ yellowStyle.FillPattern = FillPattern.SolidForeground;
+
+ return (titleStyle, headerStyle, dataStyle, yellowStyle);
+ }
+
+ ///
+ /// 设置单元格边框
+ ///
+ private void SetBorders(ICellStyle style)
+ {
+ style.BorderBottom = NPOIBorderStyle.Thin;
+ style.BorderTop = NPOIBorderStyle.Thin;
+ style.BorderLeft = NPOIBorderStyle.Thin;
+ style.BorderRight = NPOIBorderStyle.Thin;
+ }
+
+ ///
+ /// 创建报表标题
+ ///
+ private void CreateReportTitle(ISheet sheet, ICellStyle titleStyle)
+ {
+ IRow titleRow = sheet.CreateRow(0);
+ ICell titleCell = titleRow.CreateCell(0);
+ titleCell.SetCellValue("液体吸收测试报表");
+ titleCell.CellStyle = titleStyle;
+ sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, currentSampleCount));
+ }
+
+ ///
+ /// 创建报表表头
+ ///
+ private void CreateReportHeader(ISheet sheet, ICellStyle headerStyle)
+ {
+ IRow headerRow = sheet.CreateRow(2);
+
+ // 序号列
+ ICell cell0 = headerRow.CreateCell(0);
+ cell0.SetCellValue("序号");
+ cell0.CellStyle = headerStyle;
+
+ // 动态创建试样列
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ ICell cell = headerRow.CreateCell(i);
+ cell.SetCellValue($"试样{i}");
+ cell.CellStyle = headerStyle;
+ }
+ }
+
+ ///
+ /// 填充报表数据
+ ///
+ private void FillReportData(ISheet sheet, ICellStyle dataStyle, ICellStyle yellowStyle)
+ {
+ int rowIndex = 3;
+
+ foreach (DataRow dataRow in sampleDataTable.Rows)
+ {
+ IRow row = sheet.CreateRow(rowIndex++);
+ string rowName = dataRow["序号"].ToString();
+
+ // 序号列
+ ICell nameCell = row.CreateCell(0);
+ nameCell.SetCellValue(rowName);
+ nameCell.CellStyle = dataStyle;
+
+ // 数据列
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ ICell cell = row.CreateCell(i);
+ var value = dataRow[$"试样{i}"];
+
+ if (value != null && value != DBNull.Value)
+ {
+ if (double.TryParse(value.ToString(), out double numValue))
+ {
+ cell.SetCellValue(numValue);
+ }
+ else
+ {
+ cell.SetCellValue(value.ToString());
+ }
+ }
+
+ cell.CellStyle = yellowStyle;
+ }
+ }
+ }
+
+ ///
+ /// 设置报表列宽
+ ///
+ private void SetReportColumnWidths(ISheet sheet)
+ {
+ sheet.SetColumnWidth(0, 25 * 256);
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ sheet.SetColumnWidth(i, 18 * 256);
+ }
+ }
+
+ ///
+ /// 保存工作簿
+ ///
+ private void SaveWorkbook(IWorkbook workbook, string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
+ {
+ workbook.Write(fs);
}
}
@@ -688,7 +646,7 @@ namespace WindowsFormsApp6
{
sampleDataTable.Clear();
sampleCount = 0;
- UpdateDisplay();
+ RefreshDataGridView();
}
}
}
diff --git a/WindowsFormsApp6/Form3.Designer.cs b/WindowsFormsApp6/Form3.Designer.cs
index 27544c8..e8061e5 100644
--- a/WindowsFormsApp6/Form3.Designer.cs
+++ b/WindowsFormsApp6/Form3.Designer.cs
@@ -13,9 +13,34 @@
/// true if managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing)
{
- if (disposing && (components != null))
+ if (disposing)
{
- components.Dispose();
+ if (components != null)
+ {
+ components.Dispose();
+ }
+
+ // 释放定时器资源
+ if (clockTimer != null)
+ {
+ clockTimer.Stop();
+ clockTimer.Dispose();
+ clockTimer = null;
+ }
+
+ if (dataTimer != null)
+ {
+ dataTimer.Stop();
+ dataTimer.Dispose();
+ dataTimer = null;
+ }
+
+ // 释放数据表资源
+ if (sampleDataTable != null)
+ {
+ sampleDataTable.Dispose();
+ sampleDataTable = null;
+ }
}
base.Dispose(disposing);
}
diff --git a/WindowsFormsApp6/Form3.cs b/WindowsFormsApp6/Form3.cs
index b87904b..daf3b18 100644
--- a/WindowsFormsApp6/Form3.cs
+++ b/WindowsFormsApp6/Form3.cs
@@ -21,8 +21,23 @@ namespace WindowsFormsApp6
{
public partial class Form3 : Form
{
+ #region 常量定义
+ private const int TIMER_INTERVAL = 1000;
+ private const string DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+ private const string ROW_WICKING_TIME = "吸水时间(s)";
+ private const string ROW_WICKING_HEIGHT = "吸芯高度(mm)";
+ private const string ROW_WICKING_RATE = "芯吸速率(mm/min)";
+ private const string ROW_AVG_WICKING_RATE = "平均芯吸速率(mm/min)";
+ private const string ROW_STD_DEVIATION = "标准偏差";
+ #endregion
+
+ #region 字段
private System.Windows.Forms.Timer dataTimer;
+ private System.Windows.Forms.Timer clockTimer;
private DataTable sampleDataTable;
+ private int currentSampleCount = 5; // 当前试样数量,可动态调整
+ private readonly Random random = new Random();
+ #endregion
public Form3()
{
@@ -34,112 +49,103 @@ namespace WindowsFormsApp6
}
///
- /// 初始化 DataGridView 列 - 实现复杂多级表头
+ /// 设置试样数量(1-20)
+ ///
+ public void SetSampleCount(int count)
+ {
+ if (count < 1 || count > 20)
+ {
+ ShowMessage("试样数量必须在1-20之间", "参数错误", MessageBoxIcon.Warning);
+ return;
+ }
+
+ currentSampleCount = count;
+
+ // 重新初始化数据表和界面
+ sampleDataTable.Clear();
+ InitializeDataTable();
+ InitializeDataGridView();
+ UpdateDisplay();
+ }
+
+ ///
+ /// 初始化 DataGridView 列 - 实现2级表头
///
private void InitializeDataGridView()
{
- // 禁用自动生成列
- dataGridView1.AutoGenerateColumns = false;
-
- // 先解除数据绑定
- dataGridView1.DataSource = null;
-
- // 清除现有列
- dataGridView1.Columns.Clear();
-
- // 先移除可能存在的事件处理器,避免重复绑定
- dataGridView1.CellFormatting -= DataGridView1_CellFormatting;
- dataGridView1.CellValueChanged -= DataGridView1_CellValueChanged;
- dataGridView1.CellBeginEdit -= DataGridView1_CellBeginEdit;
-
- // 白色背景样式(只读)- 不设置BackColor,让隔行变色生效
- DataGridViewCellStyle readonlyStyle = new DataGridViewCellStyle
+ dataGridView1.SuspendLayout();
+ try
{
- Alignment = DataGridViewContentAlignment.MiddleCenter,
- SelectionBackColor = Color.LightGray
- };
-
- // 白色背景样式(可编辑)- 不设置BackColor,让隔行变色生效
- DataGridViewCellStyle editableStyle = new DataGridViewCellStyle
- {
- Alignment = DataGridViewContentAlignment.MiddleCenter,
- SelectionBackColor = Color.LightBlue
- };
-
- // 序号列
- DataGridViewTextBoxColumn seqCol = new DataGridViewTextBoxColumn
- {
- Name = "序号",
- HeaderText = "序号",
- DataPropertyName = "序号",
- Width = 120,
- ReadOnly = true,
- DefaultCellStyle = (DataGridViewCellStyle)readonlyStyle.Clone()
- };
- dataGridView1.Columns.Add(seqCol);
-
- // 为每个试样添加3列(试样次数:1、2、3)
- for (int i = 1; i <= 5; i++)
- {
- // 列1:试样次数1
- DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn
+ dataGridView1.AutoGenerateColumns = false;
+ dataGridView1.DataSource = null;
+ dataGridView1.Columns.Clear();
+
+ // 移除可能存在的事件处理器
+ dataGridView1.CellFormatting -= DataGridView1_CellFormatting;
+ dataGridView1.CellValueChanged -= DataGridView1_CellValueChanged;
+ dataGridView1.CellBeginEdit -= DataGridView1_CellBeginEdit;
+
+ // 创建共享样式(不设置背景色,让 AlternatingRowsDefaultCellStyle 生效)
+ DataGridViewCellStyle centerStyle = new DataGridViewCellStyle
{
- Name = $"试样{i}_1",
- HeaderText = $"试样{i}\n1",
- DataPropertyName = $"试样{i}_1",
- Width = 100,
- ReadOnly = false,
- DefaultCellStyle = (DataGridViewCellStyle)editableStyle.Clone()
+ Alignment = DataGridViewContentAlignment.MiddleCenter
};
- dataGridView1.Columns.Add(col1);
- // 列2:试样次数2
- DataGridViewTextBoxColumn col2 = new DataGridViewTextBoxColumn
+ // 序号列
+ dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{
- Name = $"试样{i}_2",
- HeaderText = $"试样{i}\n2",
- DataPropertyName = $"试样{i}_2",
- Width = 100,
- ReadOnly = false,
- DefaultCellStyle = (DataGridViewCellStyle)editableStyle.Clone()
- };
- dataGridView1.Columns.Add(col2);
+ Name = "序号",
+ HeaderText = "序号",
+ DataPropertyName = "序号",
+ Width = 180,
+ ReadOnly = true,
+ DefaultCellStyle = centerStyle
+ });
- // 列3:试样次数3
- DataGridViewTextBoxColumn col3 = new DataGridViewTextBoxColumn
+ // 为每个试样添加3列(2级表头:试样N + 子列1/2/3)
+ for (int i = 1; i <= currentSampleCount; i++)
{
- Name = $"试样{i}_3",
- HeaderText = $"试样{i}\n3",
- DataPropertyName = $"试样{i}_3",
- Width = 100,
- ReadOnly = false,
- DefaultCellStyle = (DataGridViewCellStyle)editableStyle.Clone()
- };
- dataGridView1.Columns.Add(col3);
+ dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
+ {
+ Name = $"试样{i}_1",
+ HeaderText = $"试样{i}\n1",
+ DataPropertyName = $"试样{i}_1",
+ Width = 100,
+ ReadOnly = false,
+ DefaultCellStyle = (DataGridViewCellStyle)centerStyle.Clone()
+ });
+
+ dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
+ {
+ Name = $"试样{i}_2",
+ HeaderText = $"试样{i}\n2",
+ DataPropertyName = $"试样{i}_2",
+ Width = 100,
+ ReadOnly = false,
+ DefaultCellStyle = (DataGridViewCellStyle)centerStyle.Clone()
+ });
+
+ dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
+ {
+ Name = $"试样{i}_3",
+ HeaderText = $"试样{i}\n3",
+ DataPropertyName = $"试样{i}_3",
+ Width = 100,
+ ReadOnly = false,
+ DefaultCellStyle = (DataGridViewCellStyle)centerStyle.Clone()
+ });
+ }
+
+ // 绑定数据源
+ dataGridView1.DataSource = sampleDataTable;
+ dataGridView1.CellFormatting += DataGridView1_CellFormatting;
+ dataGridView1.CellValueChanged += DataGridView1_CellValueChanged;
+ dataGridView1.CellBeginEdit += DataGridView1_CellBeginEdit;
}
-
- // 绑定数据源
- dataGridView1.DataSource = sampleDataTable;
-
- // 调试:输出列信息
- System.Diagnostics.Debug.WriteLine("=== DataGridView 列信息 ===");
- System.Diagnostics.Debug.WriteLine($"DataTable 列数: {sampleDataTable.Columns.Count}");
- System.Diagnostics.Debug.WriteLine($"DataGridView 列数: {dataGridView1.Columns.Count}");
-
- for (int i = 0; i < dataGridView1.Columns.Count; i++)
+ finally
{
- var col = dataGridView1.Columns[i];
- System.Diagnostics.Debug.WriteLine($"列{i}: Name={col.Name}, DataPropertyName={col.DataPropertyName}");
+ dataGridView1.ResumeLayout();
}
-
- // 添加单元格格式化事件
- dataGridView1.CellFormatting += DataGridView1_CellFormatting;
-
- // 添加单元格编辑事件(用于手动输入后重新计算)
- dataGridView1.CellValueChanged += DataGridView1_CellValueChanged;
-
- // 添加单元格编辑前事件(动态控制可编辑性)
- dataGridView1.CellBeginEdit += DataGridView1_CellBeginEdit;
}
///
@@ -147,12 +153,12 @@ namespace WindowsFormsApp6
///
private void DataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
- if (e.RowIndex >= 0 && e.ColumnIndex > 0) // 跳过序号列
+ if (e.RowIndex >= 0 && e.ColumnIndex > 0)
{
string rowName = dataGridView1.Rows[e.RowIndex].Cells["序号"].Value?.ToString() ?? "";
- // 吸芯高度(mm)行 - 所有列都可以编辑
- if (rowName == "吸芯高度(mm)")
+ // 吸芯高度(mm)行 - 所有列都可以编辑
+ if (rowName == ROW_WICKING_HEIGHT)
{
return; // 允许编辑
}
@@ -167,71 +173,32 @@ namespace WindowsFormsApp6
///
private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
- if (e.RowIndex >= 0 && e.Value != null && e.Value != DBNull.Value)
+ if (e.RowIndex < 0 || e.ColumnIndex == 0) return; // 跳过序号列
+
+ // 格式化数值显示为2位小数
+ if (e.Value != null && e.Value != DBNull.Value)
{
- // 格式化数值列(保留2位小数)
- string columnName = dataGridView1.Columns[e.ColumnIndex].Name;
- if (columnName.Contains("试样") && columnName != "序号")
+ if (double.TryParse(e.Value.ToString(), out double numValue))
{
- if (double.TryParse(e.Value.ToString(), out double value))
+ // 如果值为0或接近0,显示为空白
+ if (Math.Abs(numValue) < 0.001)
{
- // 如果值为0,根据行和列决定是否显示
- if (value == 0)
- {
- string rowName = dataGridView1.Rows[e.RowIndex].Cells["序号"].Value?.ToString() ?? "";
-
- // 根据示意图,某些单元格应该显示为空白
- if (ShouldBeEmpty(rowName, columnName))
- {
- e.Value = "";
- e.FormattingApplied = true;
- return;
- }
- }
-
- e.Value = value.ToString("F2");
+ e.Value = "";
e.FormattingApplied = true;
+ return;
}
+
+ // 显示2位小数
+ e.Value = numValue.ToString("F2");
+ e.FormattingApplied = true;
}
}
- }
-
- ///
- /// 判断单元格是否应该为空白
- ///
- private bool ShouldBeEmpty(string rowName, string columnName)
- {
- // 吸水时间(s) - 只有试样次数1有数据
- if (rowName == "吸水时间(s)")
+ else
{
- return columnName.EndsWith("_2") || columnName.EndsWith("_3");
+ // null 或 DBNull 显示为空白
+ e.Value = "";
+ e.FormattingApplied = true;
}
-
- // 吸芯高度(mm) - 所有列都有数据(全部可编辑)
- if (rowName == "吸芯高度(mm)")
- {
- return false; // 不应该为空
- }
-
- // 芯吸速率(mm/min) - 只有试样次数3有数据
- if (rowName == "芯吸速率(mm/min)")
- {
- return columnName.EndsWith("_1") || columnName.EndsWith("_2");
- }
-
- // 平均芯吸速率(mm/min) - 只有试样次数3有数据
- if (rowName == "平均芯吸速率(mm/min)")
- {
- return columnName.EndsWith("_1") || columnName.EndsWith("_2");
- }
-
- // 标准偏差 - 只有试样次数3有数据
- if (rowName == "标准偏差")
- {
- return columnName.EndsWith("_1") || columnName.EndsWith("_2");
- }
-
- return false;
}
///
@@ -244,9 +211,10 @@ namespace WindowsFormsApp6
string rowName = dataGridView1.Rows[e.RowIndex].Cells["序号"].Value?.ToString() ?? "";
// 如果是吸芯高度行,任何列的修改都触发重新计算
- if (rowName == "吸芯高度(mm)")
+ if (rowName == ROW_WICKING_HEIGHT)
{
- RecalculateRow(e.RowIndex);
+ CalculateAllRows();
+ RefreshDataGridView();
}
}
}
@@ -256,25 +224,17 @@ namespace WindowsFormsApp6
///
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 = new System.Windows.Forms.Timer
+ {
+ Interval = TIMER_INTERVAL
+ };
+ clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString(DATE_TIME_FORMAT);
clockTimer.Start();
}
@@ -286,16 +246,14 @@ namespace WindowsFormsApp6
if (dataTimer.Enabled)
{
StopDataCollection();
- button1.Text = "🔗 连接设备";
- button1.BackColor = Color.FromArgb(46, 204, 113);
- MessageBox.Show("已停止数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ UpdateButtonState(button1, "🔗 连接设备", Color.FromArgb(46, 204, 113));
+ ShowMessage("已停止数据采集");
}
else
{
StartDataCollection();
- button1.Text = "⏸️ 停止采集";
- button1.BackColor = Color.FromArgb(231, 76, 60);
- MessageBox.Show("开始数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ UpdateButtonState(button1, "⏸️ 停止采集", Color.FromArgb(231, 76, 60));
+ ShowMessage("开始数据采集");
}
}
@@ -304,7 +262,24 @@ namespace WindowsFormsApp6
///
private void Button2_Click(object sender, EventArgs e)
{
- MessageBox.Show("打印功能开发中...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage("打印功能开发中...");
+ }
+
+ ///
+ /// 更新按钮状态
+ ///
+ private void UpdateButtonState(Button button, string text, Color backColor)
+ {
+ button.Text = text;
+ button.BackColor = backColor;
+ }
+
+ ///
+ /// 显示提示消息
+ ///
+ private void ShowMessage(string message, string title = "提示", MessageBoxIcon icon = MessageBoxIcon.Information)
+ {
+ MessageBox.Show(message, title, MessageBoxButtons.OK, icon);
}
///
@@ -352,19 +327,19 @@ namespace WindowsFormsApp6
sampleDataTable.Columns.Add("序号", typeof(string));
// 为每个试样添加3列(试样次数:1、2、3)
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
{
- sampleDataTable.Columns.Add($"试样{i}_1", typeof(double)); // 系统读数
- sampleDataTable.Columns.Add($"试样{i}_2", typeof(double)); // 手动输入
- sampleDataTable.Columns.Add($"试样{i}_3", typeof(double)); // 系统计算
+ sampleDataTable.Columns.Add($"试样{i}_1", typeof(double));
+ sampleDataTable.Columns.Add($"试样{i}_2", typeof(double));
+ sampleDataTable.Columns.Add($"试样{i}_3", typeof(double));
}
- // 初始化6行数据
- AddDataRow("吸水时间(s)");
- AddDataRow("吸芯高度(mm)");
- AddDataRow("芯吸速率(mm/min)");
- AddDataRow("平均芯吸速率(mm/min)");
- AddDataRow("标准偏差");
+ // 初始化5行数据
+ AddDataRow(ROW_WICKING_TIME);
+ AddDataRow(ROW_WICKING_HEIGHT);
+ AddDataRow(ROW_WICKING_RATE);
+ AddDataRow(ROW_AVG_WICKING_RATE);
+ AddDataRow(ROW_STD_DEVIATION);
}
///
@@ -376,7 +351,7 @@ namespace WindowsFormsApp6
row["序号"] = rowName;
// 初始化所有数值列为0
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
{
row[$"试样{i}_1"] = 0.0;
row[$"试样{i}_2"] = 0.0;
@@ -401,26 +376,22 @@ namespace WindowsFormsApp6
///
private void DataTimer_Tick(object sender, EventArgs e)
{
- // 读取吸水时间(s)- 从寄存器读取
- DataRow timeRow = sampleDataTable.Rows[0]; // 第一行:吸水时间
- for (int i = 1; i <= 5; i++)
+ // 读取吸水时间(s) - 从寄存器读取
+ DataRow timeRow = sampleDataTable.Rows[0];
+ for (int i = 1; i <= currentSampleCount; i++)
{
double registerValue = ReadRegisterData(i - 1);
timeRow[$"试样{i}_1"] = registerValue;
}
- // 触发界面更新
UpdateDisplay();
}
///
/// 模拟从寄存器读取数据
- /// 实际应用中替换为真实的 Modbus 或其他协议读取
///
private double ReadRegisterData(int registerAddress)
{
- // 模拟数据:30-34 之间的随机值
- Random random = new Random(Guid.NewGuid().GetHashCode());
return 30 + random.NextDouble() * 4;
}
@@ -429,49 +400,92 @@ namespace WindowsFormsApp6
///
public void GenerateMockData()
{
- Random random = new Random();
+ // 清空所有行的数据(保持表结构)
+ foreach (DataRow row in sampleDataTable.Rows)
+ {
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ row[$"试样{i}_1"] = 0.0;
+ row[$"试样{i}_2"] = 0.0;
+ row[$"试样{i}_3"] = 0.0;
+ }
+ }
// 第1行:吸水时间(s)- 试样次数1(系统读数)
+ // 每个试样只在第1次测试时记录吸水时间
DataRow timeRow = sampleDataTable.Rows[0];
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ double timeValue = Math.Round(30 + random.NextDouble() * 4, 2); // 30-34秒
+ timeRow[$"试样{i}_1"] = timeValue;
+ // 试样次数2和3不使用,保持为0
+ }
+
+ // 第2行:吸芯高度(mm)- 手动输入,不自动生成
+ // 保持为0,等待用户手动输入
+
+ // 第3-5行:芯吸速率、平均值、标准偏差 - 保持为0
+ // 等待用户输入吸芯高度后,会自动计算
+
+ // 更新显示
+ RefreshDataGridView();
+
+ ShowMessage($"已生成 {currentSampleCount} 个试样的吸水时间数据\n" +
+ $"- 吸水时间:30-34秒(系统读数)\n" +
+ $"- 吸芯高度:请手动输入(每个试样3次测试)\n" +
+ $"- 芯吸速率:输入吸芯高度后自动计算",
+ "模拟数据生成");
+ }
+
+ ///
+ /// 生成完整的测试数据(包含吸芯高度)- 用于快速测试
+ ///
+ public void GenerateFullMockData()
+ {
+ // 清空所有行的数据(保持表结构)
+ foreach (DataRow row in sampleDataTable.Rows)
+ {
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ row[$"试样{i}_1"] = 0.0;
+ row[$"试样{i}_2"] = 0.0;
+ row[$"试样{i}_3"] = 0.0;
+ }
+ }
+
+ // 第1行:吸水时间(s)
+ DataRow timeRow = sampleDataTable.Rows[0];
+ for (int i = 1; i <= currentSampleCount; i++)
{
double timeValue = Math.Round(30 + random.NextDouble() * 4, 2);
timeRow[$"试样{i}_1"] = timeValue;
- System.Diagnostics.Debug.WriteLine($"吸水时间 - 试样{i}_1 = {timeValue}");
}
- // 第2行:吸芯高度(mm)- 所有列都可编辑(手动输入)
+ // 第2行:吸芯高度(mm)- 生成测试数据
DataRow heightRow = sampleDataTable.Rows[1];
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
{
- double height1 = Math.Round(50 + random.NextDouble() * 20, 2);
- double height2 = Math.Round(50 + random.NextDouble() * 20, 2);
- double height3 = Math.Round(50 + random.NextDouble() * 20, 2);
+ double baseHeight = 55 + random.NextDouble() * 10;
+ double height1 = Math.Round(baseHeight + (random.NextDouble() - 0.5) * 4, 2);
+ double height2 = Math.Round(baseHeight + (random.NextDouble() - 0.5) * 4, 2);
+ double height3 = Math.Round(baseHeight + (random.NextDouble() - 0.5) * 4, 2);
heightRow[$"试样{i}_1"] = height1;
heightRow[$"试样{i}_2"] = height2;
heightRow[$"试样{i}_3"] = height3;
-
- System.Diagnostics.Debug.WriteLine($"吸芯高度 - 试样{i}_1 = {height1}");
- System.Diagnostics.Debug.WriteLine($"吸芯高度 - 试样{i}_2 = {height2}");
- System.Diagnostics.Debug.WriteLine($"吸芯高度 - 试样{i}_3 = {height3}");
}
// 计算所有行
CalculateAllRows();
// 更新显示
- UpdateDisplay();
+ RefreshDataGridView();
- // 调试信息:验证数据
- System.Diagnostics.Debug.WriteLine("=== 模拟数据生成完成 ===");
- DataRow rateRow = sampleDataTable.Rows[2];
- for (int i = 1; i <= 5; i++)
- {
- System.Diagnostics.Debug.WriteLine($"芯吸速率 - 试样{i}_3 = {rateRow[$"试样{i}_3"]}");
- }
-
- MessageBox.Show("已生成模拟数据\n请查看输出窗口的调试信息", "模拟数据生成", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage($"已生成完整测试数据(包含吸芯高度)\n" +
+ $"- 吸水时间:30-34秒\n" +
+ $"- 吸芯高度:50-70mm(自动生成)\n" +
+ $"- 芯吸速率:已自动计算",
+ "完整测试数据");
}
///
@@ -479,10 +493,17 @@ namespace WindowsFormsApp6
///
private void UpdateDisplay()
{
- // 刷新 DataGridView
- if (dataGridView1.DataSource != null)
+ RefreshDataGridView();
+ }
+
+ ///
+ /// 刷新DataGridView
+ ///
+ private void RefreshDataGridView()
+ {
+ if (dataGridView1.DataSource is DataTable dt)
{
- ((DataTable)dataGridView1.DataSource).AcceptChanges();
+ dt.AcceptChanges();
dataGridView1.Refresh();
}
}
@@ -502,15 +523,6 @@ namespace WindowsFormsApp6
CalculateStandardDeviation();
}
- ///
- /// 重新计算指定行
- ///
- private void RecalculateRow(int rowIndex)
- {
- CalculateAllRows();
- UpdateDisplay();
- }
-
///
/// 计算芯吸速率(mm/min)
/// 公式:芯吸速率 = 吸芯高度(mm) / (吸水时间(s) / 60)
@@ -521,7 +533,7 @@ namespace WindowsFormsApp6
DataRow heightRow = sampleDataTable.Rows[1]; // 吸芯高度
DataRow rateRow = sampleDataTable.Rows[2]; // 芯吸速率
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
{
// 获取吸水时间(试样次数1:系统读数)
double time = ConvertToDouble(timeRow[$"试样{i}_1"]);
@@ -584,7 +596,7 @@ namespace WindowsFormsApp6
DataRow avgRow = sampleDataTable.Rows[3]; // 平均芯吸速率
List rates = new List();
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
{
double rate = ConvertToDouble(rateRow[$"试样{i}_3"]);
if (rate > 0)
@@ -596,7 +608,7 @@ namespace WindowsFormsApp6
double average = rates.Count > 0 ? rates.Average() : 0;
// 所有试样显示相同的平均值(存储在试样次数3)
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
{
avgRow[$"试样{i}_3"] = Math.Round(average, 2);
}
@@ -611,7 +623,7 @@ namespace WindowsFormsApp6
DataRow stdRow = sampleDataTable.Rows[4]; // 标准偏差
List rates = new List();
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
{
double rate = ConvertToDouble(rateRow[$"试样{i}_3"]);
if (rate > 0)
@@ -629,7 +641,7 @@ namespace WindowsFormsApp6
}
// 所有试样显示相同的标准偏差(存储在试样次数3)
- for (int i = 1; i <= 5; i++)
+ for (int i = 1; i <= currentSampleCount; i++)
{
stdRow[$"试样{i}_3"] = Math.Round(stdDev, 2);
}
@@ -658,162 +670,203 @@ namespace WindowsFormsApp6
{
try
{
- IWorkbook workbook;
-
- // 根据文件扩展名选择格式
- if (filePath.EndsWith(".xlsx"))
- {
- workbook = new XSSFWorkbook(); // Excel 2007+
- }
- else
- {
- workbook = new HSSFWorkbook(); // Excel 97-2003
- }
+ IWorkbook workbook = filePath.EndsWith(".xlsx")
+ ? (IWorkbook)new XSSFWorkbook()
+ : new HSSFWorkbook();
- ISheet sheet = workbook.CreateSheet("液体吸收测试报表");
+ ISheet sheet = workbook.CreateSheet("液体芯吸速率测试报表");
// 创建样式
- ICellStyle headerStyle = workbook.CreateCellStyle();
- headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
- headerStyle.FillPattern = FillPattern.SolidForeground;
- headerStyle.BorderBottom = NPOIBorderStyle.Thin;
- headerStyle.BorderTop = NPOIBorderStyle.Thin;
- headerStyle.BorderLeft = NPOIBorderStyle.Thin;
- headerStyle.BorderRight = NPOIBorderStyle.Thin;
- headerStyle.Alignment = NPOIHorizontalAlignment.Center;
- headerStyle.VerticalAlignment = VerticalAlignment.Center;
- IFont headerFont = workbook.CreateFont();
- headerFont.IsBold = true;
- headerStyle.SetFont(headerFont);
+ var styles = CreateReportStyles(workbook);
- // 白色背景样式(偶数行)
- ICellStyle whiteStyle = workbook.CreateCellStyle();
- whiteStyle.BorderBottom = NPOIBorderStyle.Thin;
- whiteStyle.BorderTop = NPOIBorderStyle.Thin;
- whiteStyle.BorderLeft = NPOIBorderStyle.Thin;
- whiteStyle.BorderRight = NPOIBorderStyle.Thin;
- whiteStyle.Alignment = NPOIHorizontalAlignment.Center;
- whiteStyle.VerticalAlignment = VerticalAlignment.Center;
-
- // 黄色背景样式(奇数行)
- ICellStyle yellowStyle = workbook.CreateCellStyle();
- yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.LightYellow.Index;
- yellowStyle.FillPattern = FillPattern.SolidForeground;
- yellowStyle.BorderBottom = NPOIBorderStyle.Thin;
- yellowStyle.BorderTop = NPOIBorderStyle.Thin;
- yellowStyle.BorderLeft = NPOIBorderStyle.Thin;
- yellowStyle.BorderRight = NPOIBorderStyle.Thin;
- yellowStyle.Alignment = NPOIHorizontalAlignment.Center;
- yellowStyle.VerticalAlignment = VerticalAlignment.Center;
-
- // 创建第一行表头(试样1-5)
- IRow headerRow1 = sheet.CreateRow(0);
- headerRow1.Height = 400; // 设置行高(单位:1/20点)
-
- ICell cell0 = headerRow1.CreateCell(0);
- cell0.SetCellValue("序号");
- cell0.CellStyle = headerStyle;
- sheet.AddMergedRegion(new CellRangeAddress(0, 1, 0, 0)); // 合并序号列
-
- int colIndex = 1;
- for (int i = 1; i <= 5; i++)
- {
- ICell cell = headerRow1.CreateCell(colIndex);
- cell.SetCellValue($"试样{i}");
- cell.CellStyle = headerStyle;
- sheet.AddMergedRegion(new CellRangeAddress(0, 0, colIndex, colIndex + 2));
- colIndex += 3;
- }
-
- // 创建第二行表头(试样次数:1、2、3)
- IRow headerRow2 = sheet.CreateRow(1);
- headerRow2.Height = 400; // 设置行高
-
- colIndex = 1;
- for (int i = 1; i <= 5; i++)
- {
- ICell cell1 = headerRow2.CreateCell(colIndex++);
- cell1.SetCellValue("1");
- cell1.CellStyle = headerStyle;
-
- ICell cell2 = headerRow2.CreateCell(colIndex++);
- cell2.SetCellValue("2");
- cell2.CellStyle = headerStyle;
-
- ICell cell3 = headerRow2.CreateCell(colIndex++);
- cell3.SetCellValue("3");
- cell3.CellStyle = headerStyle;
- }
+ // 创建表头(2级)
+ CreateReportHeader(sheet, styles.headerStyle);
// 填充数据
- int rowIndex = 2;
- int dataRowIndex = 0;
- foreach (DataRow dataRow in sampleDataTable.Rows)
- {
- IRow row = sheet.CreateRow(rowIndex);
- row.Height = 380; // 设置数据行高
-
- // 根据行索引选择样式(隔行变色)
- ICellStyle rowStyle = (dataRowIndex % 2 == 0) ? whiteStyle : yellowStyle;
-
- // 序号列
- ICell cellSeq = row.CreateCell(0);
- cellSeq.SetCellValue(dataRow["序号"].ToString());
- cellSeq.CellStyle = rowStyle;
+ FillReportData(sheet, styles.dataStyle, styles.yellowStyle);
- colIndex = 1;
- for (int i = 1; i <= 5; i++)
- {
- // 试样次数1
- ICell cell1 = row.CreateCell(colIndex++);
- double val1 = ConvertToDouble(dataRow[$"试样{i}_1"]);
- if (val1 != 0)
- {
- cell1.SetCellValue(val1);
- }
- cell1.CellStyle = rowStyle;
-
- // 试样次数2
- ICell cell2 = row.CreateCell(colIndex++);
- double val2 = ConvertToDouble(dataRow[$"试样{i}_2"]);
- if (val2 != 0)
- {
- cell2.SetCellValue(val2);
- }
- cell2.CellStyle = rowStyle;
-
- // 试样次数3
- ICell cell3 = row.CreateCell(colIndex++);
- double val3 = ConvertToDouble(dataRow[$"试样{i}_3"]);
- if (val3 != 0)
- {
- cell3.SetCellValue(val3);
- }
- cell3.CellStyle = rowStyle;
- }
-
- rowIndex++;
- dataRowIndex++;
- }
-
- // 手动设置列宽(单位:1/256字符宽度)
- sheet.SetColumnWidth(0, 20 * 256); // 序号列:20个字符宽度
- for (int i = 1; i <= 15; i++)
- {
- sheet.SetColumnWidth(i, 12 * 256); // 数据列:12个字符宽度
- }
+ // 设置列宽
+ SetReportColumnWidths(sheet);
// 保存文件
- using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
- {
- workbook.Write(fs);
- }
+ SaveWorkbook(workbook, filePath);
- MessageBox.Show($"数据已成功导出到:{filePath}", "导出成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ ShowMessage($"数据已成功导出到:{filePath}", "导出成功");
}
catch (Exception ex)
{
- MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ ShowMessage($"导出失败:{ex.Message}", "错误", MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// 创建报表样式
+ ///
+ private (ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle yellowStyle)
+ CreateReportStyles(IWorkbook workbook)
+ {
+ // 表头样式
+ ICellStyle headerStyle = workbook.CreateCellStyle();
+ headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
+ headerStyle.FillPattern = FillPattern.SolidForeground;
+ SetBorders(headerStyle);
+ headerStyle.Alignment = NPOIHorizontalAlignment.Center;
+ headerStyle.VerticalAlignment = VerticalAlignment.Center;
+ IFont headerFont = workbook.CreateFont();
+ headerFont.IsBold = true;
+ headerStyle.SetFont(headerFont);
+
+ // 白色背景样式
+ ICellStyle dataStyle = workbook.CreateCellStyle();
+ SetBorders(dataStyle);
+ dataStyle.Alignment = NPOIHorizontalAlignment.Center;
+ dataStyle.VerticalAlignment = VerticalAlignment.Center;
+
+ // 黄色背景样式
+ ICellStyle yellowStyle = workbook.CreateCellStyle();
+ yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.LightYellow.Index;
+ yellowStyle.FillPattern = FillPattern.SolidForeground;
+ SetBorders(yellowStyle);
+ yellowStyle.Alignment = NPOIHorizontalAlignment.Center;
+ yellowStyle.VerticalAlignment = VerticalAlignment.Center;
+
+ return (headerStyle, dataStyle, yellowStyle);
+ }
+
+ ///
+ /// 设置单元格边框
+ ///
+ private void SetBorders(ICellStyle style)
+ {
+ style.BorderBottom = NPOIBorderStyle.Thin;
+ style.BorderTop = NPOIBorderStyle.Thin;
+ style.BorderLeft = NPOIBorderStyle.Thin;
+ style.BorderRight = NPOIBorderStyle.Thin;
+ }
+
+ ///
+ /// 创建报表表头(2级)
+ ///
+ private void CreateReportHeader(ISheet sheet, ICellStyle headerStyle)
+ {
+ // 创建第一行表头(试样1-N)
+ IRow headerRow1 = sheet.CreateRow(0);
+ headerRow1.Height = 400;
+
+ ICell cell0 = headerRow1.CreateCell(0);
+ cell0.SetCellValue("序号");
+ cell0.CellStyle = headerStyle;
+ sheet.AddMergedRegion(new CellRangeAddress(0, 1, 0, 0)); // 合并序号列
+
+ int colIndex = 1;
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ ICell cell = headerRow1.CreateCell(colIndex);
+ cell.SetCellValue($"试样{i}");
+ cell.CellStyle = headerStyle;
+ sheet.AddMergedRegion(new CellRangeAddress(0, 0, colIndex, colIndex + 2));
+ colIndex += 3;
+ }
+
+ // 创建第二行表头(试样次数:1、2、3)
+ IRow headerRow2 = sheet.CreateRow(1);
+ headerRow2.Height = 400;
+
+ colIndex = 1;
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ ICell cell1 = headerRow2.CreateCell(colIndex++);
+ cell1.SetCellValue("1");
+ cell1.CellStyle = headerStyle;
+
+ ICell cell2 = headerRow2.CreateCell(colIndex++);
+ cell2.SetCellValue("2");
+ cell2.CellStyle = headerStyle;
+
+ ICell cell3 = headerRow2.CreateCell(colIndex++);
+ cell3.SetCellValue("3");
+ cell3.CellStyle = headerStyle;
+ }
+ }
+
+ ///
+ /// 填充报表数据
+ ///
+ private void FillReportData(ISheet sheet, ICellStyle dataStyle, ICellStyle yellowStyle)
+ {
+ int rowIndex = 2;
+ int dataRowIndex = 0;
+
+ foreach (DataRow dataRow in sampleDataTable.Rows)
+ {
+ IRow row = sheet.CreateRow(rowIndex);
+ row.Height = 380;
+
+ // 根据行索引选择样式(隔行变色)
+ ICellStyle rowStyle = (dataRowIndex % 2 == 0) ? dataStyle : yellowStyle;
+
+ // 序号列
+ ICell cellSeq = row.CreateCell(0);
+ cellSeq.SetCellValue(dataRow["序号"].ToString());
+ cellSeq.CellStyle = rowStyle;
+
+ int colIndex = 1;
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ // 试样次数1
+ ICell cell1 = row.CreateCell(colIndex++);
+ double val1 = ConvertToDouble(dataRow[$"试样{i}_1"]);
+ if (Math.Abs(val1) >= 0.001) // 只有非0值才显示
+ {
+ cell1.SetCellValue(val1);
+ }
+ cell1.CellStyle = rowStyle;
+
+ // 试样次数2
+ ICell cell2 = row.CreateCell(colIndex++);
+ double val2 = ConvertToDouble(dataRow[$"试样{i}_2"]);
+ if (Math.Abs(val2) >= 0.001) // 只有非0值才显示
+ {
+ cell2.SetCellValue(val2);
+ }
+ cell2.CellStyle = rowStyle;
+
+ // 试样次数3
+ ICell cell3 = row.CreateCell(colIndex++);
+ double val3 = ConvertToDouble(dataRow[$"试样{i}_3"]);
+ if (Math.Abs(val3) >= 0.001) // 只有非0值才显示
+ {
+ cell3.SetCellValue(val3);
+ }
+ cell3.CellStyle = rowStyle;
+ }
+
+ rowIndex++;
+ dataRowIndex++;
+ }
+ }
+
+ ///
+ /// 设置报表列宽
+ ///
+ private void SetReportColumnWidths(ISheet sheet)
+ {
+ sheet.SetColumnWidth(0, 20 * 256); // 序号列
+ int totalColumns = currentSampleCount * 3;
+ for (int i = 1; i <= totalColumns; i++)
+ {
+ sheet.SetColumnWidth(i, 12 * 256); // 数据列
+ }
+ }
+
+ ///
+ /// 保存工作簿
+ ///
+ private void SaveWorkbook(IWorkbook workbook, string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
+ {
+ workbook.Write(fs);
}
}
@@ -831,10 +884,9 @@ namespace WindowsFormsApp6
///
public void ClearData()
{
- // 重新初始化数据表
sampleDataTable.Clear();
InitializeDataTable();
- UpdateDisplay();
+ RefreshDataGridView();
}
}
}