更新
This commit is contained in:
10
WindowsFormsApp6/Form1.Designer.cs
generated
10
WindowsFormsApp6/Form1.Designer.cs
generated
@@ -13,10 +13,18 @@
|
|||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing && (components != null))
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (components != null)
|
||||||
{
|
{
|
||||||
components.Dispose();
|
components.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 释放自定义资源
|
||||||
|
dataTimer?.Dispose();
|
||||||
|
clockTimer?.Dispose();
|
||||||
|
sampleDataTable?.Dispose();
|
||||||
|
}
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
10
WindowsFormsApp6/Form2.Designer.cs
generated
10
WindowsFormsApp6/Form2.Designer.cs
generated
@@ -13,10 +13,18 @@
|
|||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing && (components != null))
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (components != null)
|
||||||
{
|
{
|
||||||
components.Dispose();
|
components.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 释放自定义资源
|
||||||
|
dataTimer?.Dispose();
|
||||||
|
clockTimer?.Dispose();
|
||||||
|
sampleDataTable?.Dispose();
|
||||||
|
}
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,26 @@ namespace WindowsFormsApp6
|
|||||||
{
|
{
|
||||||
public partial class Form2 : Form
|
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 dataTimer;
|
||||||
|
private System.Windows.Forms.Timer clockTimer;
|
||||||
private DataTable sampleDataTable;
|
private DataTable sampleDataTable;
|
||||||
private int sampleCount = 0;
|
private int sampleCount = 0;
|
||||||
|
private int currentSampleCount = 5; // 当前试样数量,可动态调整
|
||||||
|
private readonly Random random = new Random();
|
||||||
|
#endregion
|
||||||
|
|
||||||
public Form2()
|
public Form2()
|
||||||
{
|
{
|
||||||
@@ -39,136 +56,71 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeDataGridView()
|
private void InitializeDataGridView()
|
||||||
{
|
{
|
||||||
// 清除现有列
|
dataGridView1.SuspendLayout();
|
||||||
|
try
|
||||||
|
{
|
||||||
dataGridView1.Columns.Clear();
|
dataGridView1.Columns.Clear();
|
||||||
|
|
||||||
// 添加新列以匹配 Excel 表格结构
|
// 创建共享样式
|
||||||
|
var centerStyle = new DataGridViewCellStyle
|
||||||
|
{
|
||||||
|
Alignment = DataGridViewContentAlignment.MiddleCenter
|
||||||
|
};
|
||||||
|
|
||||||
|
var yellowCenterStyle = new DataGridViewCellStyle
|
||||||
|
{
|
||||||
|
Alignment = DataGridViewContentAlignment.MiddleCenter,
|
||||||
|
BackColor = Color.FromArgb(255, 255, 200)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加序号列
|
||||||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||||||
{
|
{
|
||||||
Name = "序号",
|
Name = "序号",
|
||||||
HeaderText = "序号",
|
HeaderText = "序号",
|
||||||
DataPropertyName = "序号",
|
DataPropertyName = "序号",
|
||||||
Width = 150,
|
Width = 180,
|
||||||
ReadOnly = true,
|
ReadOnly = true,
|
||||||
DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter }
|
DefaultCellStyle = centerStyle
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 根据当前试样数量动态添加列
|
||||||
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
|
{
|
||||||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||||||
{
|
{
|
||||||
Name = "试样1",
|
Name = $"试样{i}",
|
||||||
HeaderText = "试样1",
|
HeaderText = $"试样{i}",
|
||||||
DataPropertyName = "试样1",
|
DataPropertyName = $"试样{i}",
|
||||||
Width = 150,
|
Width = 150,
|
||||||
ReadOnly = true,
|
ReadOnly = true,
|
||||||
DefaultCellStyle = new DataGridViewCellStyle
|
DefaultCellStyle = yellowCenterStyle
|
||||||
{
|
});
|
||||||
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.DataSource = sampleDataTable;
|
||||||
|
|
||||||
// 添加单元格格式化事件
|
|
||||||
dataGridView1.CellFormatting += DataGridView1_CellFormatting;
|
dataGridView1.CellFormatting += DataGridView1_CellFormatting;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
dataGridView1.ResumeLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 单元格格式化事件 - 处理平均值行的显示
|
/// 单元格格式化事件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
||||||
{
|
{
|
||||||
if (dataGridView1.Columns[e.ColumnIndex].Name == "时间" && e.RowIndex >= 0)
|
if (e.RowIndex < 0) return;
|
||||||
{
|
|
||||||
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");
|
// 格式化数值显示为2位小数
|
||||||
e.FormattingApplied = true;
|
if (e.Value != null && e.Value != DBNull.Value)
|
||||||
}
|
|
||||||
}
|
|
||||||
else 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;
|
e.FormattingApplied = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,25 +131,17 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeEventHandlers()
|
private void InitializeEventHandlers()
|
||||||
{
|
{
|
||||||
// 连接设备按钮
|
|
||||||
button1.Click += Button1_Click;
|
button1.Click += Button1_Click;
|
||||||
|
|
||||||
// 打印按钮
|
|
||||||
button2.Click += Button2_Click;
|
button2.Click += Button2_Click;
|
||||||
|
|
||||||
// 导出按钮
|
|
||||||
button3.Click += Button3_Click;
|
button3.Click += Button3_Click;
|
||||||
|
|
||||||
// 返回按钮
|
|
||||||
button4.Click += Button4_Click;
|
button4.Click += Button4_Click;
|
||||||
|
|
||||||
// 生成模拟数据按钮
|
|
||||||
button5.Click += Button5_Click;
|
button5.Click += Button5_Click;
|
||||||
|
|
||||||
// 更新日期时间标签
|
clockTimer = new System.Windows.Forms.Timer
|
||||||
System.Windows.Forms.Timer clockTimer = new System.Windows.Forms.Timer();
|
{
|
||||||
clockTimer.Interval = 1000;
|
Interval = TIMER_INTERVAL
|
||||||
clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
};
|
||||||
|
clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString(DATE_TIME_FORMAT);
|
||||||
clockTimer.Start();
|
clockTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,16 +153,14 @@ namespace WindowsFormsApp6
|
|||||||
if (dataTimer.Enabled)
|
if (dataTimer.Enabled)
|
||||||
{
|
{
|
||||||
StopDataCollection();
|
StopDataCollection();
|
||||||
button1.Text = "🔗 连接设备";
|
UpdateButtonState(button1, "🔗 连接设备", Color.FromArgb(46, 204, 113));
|
||||||
button1.BackColor = Color.FromArgb(46, 204, 113);
|
ShowMessage("已停止数据采集");
|
||||||
MessageBox.Show("已停止数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StartDataCollection();
|
StartDataCollection();
|
||||||
button1.Text = "⏸️ 停止采集";
|
UpdateButtonState(button1, "⏸️ 停止采集", Color.FromArgb(231, 76, 60));
|
||||||
button1.BackColor = Color.FromArgb(231, 76, 60);
|
ShowMessage("开始数据采集");
|
||||||
MessageBox.Show("开始数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +169,24 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void Button2_Click(object sender, EventArgs e)
|
private void Button2_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
MessageBox.Show("打印功能开发中...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
ShowMessage("打印功能开发中...");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新按钮状态
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateButtonState(Button button, string text, Color backColor)
|
||||||
|
{
|
||||||
|
button.Text = text;
|
||||||
|
button.BackColor = backColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示提示消息
|
||||||
|
/// </summary>
|
||||||
|
private void ShowMessage(string message, string title = "提示", MessageBoxIcon icon = MessageBoxIcon.Information)
|
||||||
|
{
|
||||||
|
MessageBox.Show(message, title, MessageBoxButtons.OK, icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -271,12 +230,28 @@ namespace WindowsFormsApp6
|
|||||||
{
|
{
|
||||||
sampleDataTable = new DataTable();
|
sampleDataTable = new DataTable();
|
||||||
sampleDataTable.Columns.Add("序号", typeof(string));
|
sampleDataTable.Columns.Add("序号", typeof(string));
|
||||||
sampleDataTable.Columns.Add("试样1", typeof(double));
|
|
||||||
sampleDataTable.Columns.Add("试样2", typeof(double));
|
// 根据当前试样数量动态添加列
|
||||||
sampleDataTable.Columns.Add("试样3", typeof(double));
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
sampleDataTable.Columns.Add("试样4", typeof(double));
|
{
|
||||||
sampleDataTable.Columns.Add("试样5", typeof(double));
|
sampleDataTable.Columns.Add($"试样{i}", typeof(object));
|
||||||
sampleDataTable.Columns.Add("时间", typeof(DateTime));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置试样数量并重新初始化
|
||||||
|
/// </summary>
|
||||||
|
public void SetSampleCount(int count)
|
||||||
|
{
|
||||||
|
if (count < 1 || count > 20) // 限制最大20个试样
|
||||||
|
{
|
||||||
|
ShowMessage("试样数量必须在1-20之间", "参数错误", MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSampleCount = count;
|
||||||
|
InitializeDataTable();
|
||||||
|
InitializeDataGridView();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -284,8 +259,10 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeTimer()
|
private void InitializeTimer()
|
||||||
{
|
{
|
||||||
dataTimer = new System.Windows.Forms.Timer();
|
dataTimer = new System.Windows.Forms.Timer
|
||||||
dataTimer.Interval = 1000; // 每秒读取一次
|
{
|
||||||
|
Interval = TIMER_INTERVAL
|
||||||
|
};
|
||||||
dataTimer.Tick += DataTimer_Tick;
|
dataTimer.Tick += DataTimer_Tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,45 +271,48 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void DataTimer_Tick(object sender, EventArgs e)
|
private void DataTimer_Tick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// 移除旧的平均值行(如果存在)
|
// 清除旧的计算行
|
||||||
DataRow[] avgRows = sampleDataTable.Select("序号 = '平均时间(s)'");
|
RemoveCalculatedRows();
|
||||||
foreach (DataRow avgRow in avgRows)
|
|
||||||
|
// 读取初始重量和浸润后重量
|
||||||
|
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++;
|
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();
|
UpdateDisplay(initialWeights, afterWeights);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除计算行
|
||||||
|
/// </summary>
|
||||||
|
private void RemoveCalculatedRows()
|
||||||
|
{
|
||||||
|
var rowsToRemove = sampleDataTable.AsEnumerable()
|
||||||
|
.Where(r => r.Field<string>("序号") == ROW_ABSORPTION ||
|
||||||
|
r.Field<string>("序号") == ROW_AVG_ABSORPTION ||
|
||||||
|
r.Field<string>("序号") == ROW_MAX_ABSORPTION)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var row in rowsToRemove)
|
||||||
|
{
|
||||||
|
sampleDataTable.Rows.Remove(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模拟从寄存器读取数据
|
/// 模拟从寄存器读取数据
|
||||||
/// 实际应用中替换为真实的 Modbus 或其他协议读取
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private double ReadRegisterData(int registerAddress)
|
private double ReadRegisterData(int registerAddress)
|
||||||
{
|
{
|
||||||
// 模拟数据:30-34 之间的随机值
|
return MIN_WEIGHT + random.NextDouble() * (MAX_WEIGHT - MIN_WEIGHT);
|
||||||
Random random = new Random(Guid.NewGuid().GetHashCode());
|
|
||||||
return 30 + random.NextDouble() * 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -340,86 +320,125 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void GenerateMockData()
|
public void GenerateMockData()
|
||||||
{
|
{
|
||||||
// 清空现有数据
|
|
||||||
sampleDataTable.Clear();
|
sampleDataTable.Clear();
|
||||||
sampleCount = 0;
|
sampleCount = 0;
|
||||||
|
|
||||||
// 生成10条模拟数据
|
// 生成模拟数据
|
||||||
Random random = new Random();
|
double[] initialWeights = new double[currentSampleCount];
|
||||||
DateTime startTime = DateTime.Now.AddMinutes(-10);
|
double[] afterWeights = new double[currentSampleCount];
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
DataRow dataRow = sampleDataTable.NewRow();
|
initialWeights[i] = Math.Round(MIN_WEIGHT + random.NextDouble() * (MAX_WEIGHT - MIN_WEIGHT), 2);
|
||||||
dataRow["序号"] = "时间(s)";
|
afterWeights[i] = Math.Round(initialWeights[i] * (1.2 + random.NextDouble() * 0.3), 2); // 浸润后增重20%-50%
|
||||||
|
|
||||||
// 为每个试样生成模拟数据(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++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新显示(包括平均值)
|
sampleCount = 1;
|
||||||
UpdateDisplay();
|
UpdateDisplay(initialWeights, afterWeights);
|
||||||
|
|
||||||
MessageBox.Show($"已生成 {sampleCount} 条模拟数据", "模拟数据生成", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
ShowMessage($"已生成 {currentSampleCount} 个试样的模拟数据", "模拟数据生成");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 更新界面显示
|
/// 更新界面显示
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateDisplay()
|
private void UpdateDisplay(double[] initialWeights, double[] afterWeights)
|
||||||
{
|
{
|
||||||
// 刷新 DataGridView
|
sampleDataTable.Clear();
|
||||||
if (dataGridView1.DataSource != null)
|
|
||||||
|
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();
|
initialRow[$"试样{i + 1}"] = initialWeights[i];
|
||||||
dataGridView1.Refresh();
|
|
||||||
}
|
}
|
||||||
|
sampleDataTable.Rows.Add(initialRow);
|
||||||
|
|
||||||
// 计算平均时间并显示
|
// 2. 浸润后重量行
|
||||||
if (sampleDataTable.Rows.Count > 0)
|
DataRow afterRow = sampleDataTable.NewRow();
|
||||||
|
afterRow["序号"] = ROW_AFTER_WEIGHT;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
double avgSample1 = sampleDataTable.AsEnumerable().Average(r => r.Field<double>("试样1"));
|
afterRow[$"试样{i + 1}"] = afterWeights[i];
|
||||||
double avgSample2 = sampleDataTable.AsEnumerable().Average(r => r.Field<double>("试样2"));
|
}
|
||||||
double avgSample3 = sampleDataTable.AsEnumerable().Average(r => r.Field<double>("试样3"));
|
sampleDataTable.Rows.Add(afterRow);
|
||||||
double avgSample4 = sampleDataTable.AsEnumerable().Average(r => r.Field<double>("试样4"));
|
|
||||||
double avgSample5 = sampleDataTable.AsEnumerable().Average(r => r.Field<double>("试样5"));
|
|
||||||
|
|
||||||
double overallAvg = (avgSample1 + avgSample2 + avgSample3 + avgSample4 + avgSample5) / 5;
|
// 3. 液体吸收量行 (%)
|
||||||
|
DataRow absorptionRow = sampleDataTable.NewRow();
|
||||||
// 添加平均值行到表格底部(如果还没有)
|
absorptionRow["序号"] = ROW_ABSORPTION;
|
||||||
DataRow[] avgRows = sampleDataTable.Select("序号 = '平均时间(s)'");
|
double[] absorptions = new double[count];
|
||||||
if (avgRows.Length == 0)
|
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);
|
||||||
|
|
||||||
|
// 4. 液体吸收量平均值行
|
||||||
DataRow avgRow = sampleDataTable.NewRow();
|
DataRow avgRow = sampleDataTable.NewRow();
|
||||||
avgRow["序号"] = "平均时间(s)";
|
avgRow["序号"] = ROW_AVG_ABSORPTION;
|
||||||
avgRow["试样1"] = avgSample1;
|
double avgAbsorption = absorptions.Average();
|
||||||
avgRow["试样2"] = avgSample2;
|
double stdDev = CalculateStandardDeviation(absorptions);
|
||||||
avgRow["试样3"] = avgSample3;
|
|
||||||
avgRow["试样4"] = avgSample4;
|
// 第1列显示平均值
|
||||||
avgRow["试样5"] = avgSample5;
|
avgRow["试样1"] = avgAbsorption;
|
||||||
// avgRow["时间"] = $"({overallAvg:F2}) 系统计算";
|
|
||||||
sampleDataTable.Rows.Add(avgRow);
|
// 第2列显示标准偏差
|
||||||
}
|
if (count >= 2)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// 更新现有平均值行
|
avgRow["试样2"] = stdDev;
|
||||||
avgRows[0]["试样1"] = avgSample1;
|
|
||||||
avgRows[0]["试样2"] = avgSample2;
|
|
||||||
avgRows[0]["试样3"] = avgSample3;
|
|
||||||
avgRows[0]["试样4"] = avgSample4;
|
|
||||||
avgRows[0]["试样5"] = avgSample5;
|
|
||||||
// avgRows[0]["时间"] = $"({overallAvg:F2}) 系统计算";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 其他列为空
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算标准偏差
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新DataGridView
|
||||||
|
/// </summary>
|
||||||
|
private void RefreshDataGridView()
|
||||||
|
{
|
||||||
|
if (dataGridView1.DataSource is DataTable dt)
|
||||||
|
{
|
||||||
|
dt.AcceptChanges();
|
||||||
|
dataGridView1.Refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,131 +458,6 @@ namespace WindowsFormsApp6
|
|||||||
dataTimer.Stop();
|
dataTimer.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 导出数据到 Excel (.xlsx)
|
|
||||||
/// </summary>
|
|
||||||
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<string>("序号") != "平均时间(s)");
|
|
||||||
double avgSample1 = dataRows.Average(r => r.Field<double>("试样1"));
|
|
||||||
double avgSample2 = dataRows.Average(r => r.Field<double>("试样2"));
|
|
||||||
double avgSample3 = dataRows.Average(r => r.Field<double>("试样3"));
|
|
||||||
double avgSample4 = dataRows.Average(r => r.Field<double>("试样4"));
|
|
||||||
double avgSample5 = dataRows.Average(r => r.Field<double>("试样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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成报表(带格式的 Excel)
|
/// 生成报表(带格式的 Excel)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -575,6 +469,38 @@ namespace WindowsFormsApp6
|
|||||||
ISheet sheet = workbook.CreateSheet("液体吸收测试报表");
|
ISheet sheet = workbook.CreateSheet("液体吸收测试报表");
|
||||||
|
|
||||||
// 创建样式
|
// 创建样式
|
||||||
|
var styles = CreateReportStyles(workbook);
|
||||||
|
|
||||||
|
// 创建标题
|
||||||
|
CreateReportTitle(sheet, styles.titleStyle);
|
||||||
|
|
||||||
|
// 创建表头
|
||||||
|
CreateReportHeader(sheet, styles.headerStyle);
|
||||||
|
|
||||||
|
// 填充数据
|
||||||
|
FillReportData(sheet, styles.dataStyle, styles.yellowStyle);
|
||||||
|
|
||||||
|
// 设置列宽
|
||||||
|
SetReportColumnWidths(sheet);
|
||||||
|
|
||||||
|
// 保存文件
|
||||||
|
SaveWorkbook(workbook, filePath);
|
||||||
|
|
||||||
|
ShowMessage($"报表已成功生成:{filePath}", "生成成功");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ShowMessage($"生成报表失败:{ex.Message}", "错误", MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建报表样式
|
||||||
|
/// </summary>
|
||||||
|
private (ICellStyle titleStyle, ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle yellowStyle)
|
||||||
|
CreateReportStyles(IWorkbook workbook)
|
||||||
|
{
|
||||||
|
// 标题样式
|
||||||
ICellStyle titleStyle = workbook.CreateCellStyle();
|
ICellStyle titleStyle = workbook.CreateCellStyle();
|
||||||
IFont titleFont = workbook.CreateFont();
|
IFont titleFont = workbook.CreateFont();
|
||||||
titleFont.FontHeightInPoints = 16;
|
titleFont.FontHeightInPoints = 16;
|
||||||
@@ -582,103 +508,135 @@ namespace WindowsFormsApp6
|
|||||||
titleStyle.SetFont(titleFont);
|
titleStyle.SetFont(titleFont);
|
||||||
titleStyle.Alignment = NPOIHorizontalAlignment.Center;
|
titleStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||||
|
|
||||||
|
// 表头样式
|
||||||
ICellStyle headerStyle = workbook.CreateCellStyle();
|
ICellStyle headerStyle = workbook.CreateCellStyle();
|
||||||
headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
|
headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
|
||||||
headerStyle.FillPattern = FillPattern.SolidForeground;
|
headerStyle.FillPattern = FillPattern.SolidForeground;
|
||||||
headerStyle.BorderBottom = NPOIBorderStyle.Thin;
|
SetBorders(headerStyle);
|
||||||
headerStyle.BorderTop = NPOIBorderStyle.Thin;
|
|
||||||
headerStyle.BorderLeft = NPOIBorderStyle.Thin;
|
|
||||||
headerStyle.BorderRight = NPOIBorderStyle.Thin;
|
|
||||||
IFont headerFont = workbook.CreateFont();
|
IFont headerFont = workbook.CreateFont();
|
||||||
headerFont.IsBold = true;
|
headerFont.IsBold = true;
|
||||||
headerStyle.SetFont(headerFont);
|
headerStyle.SetFont(headerFont);
|
||||||
headerStyle.Alignment = NPOIHorizontalAlignment.Center;
|
headerStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||||
|
|
||||||
|
// 数据样式
|
||||||
ICellStyle dataStyle = workbook.CreateCellStyle();
|
ICellStyle dataStyle = workbook.CreateCellStyle();
|
||||||
dataStyle.BorderBottom = NPOIBorderStyle.Thin;
|
SetBorders(dataStyle);
|
||||||
dataStyle.BorderTop = NPOIBorderStyle.Thin;
|
|
||||||
dataStyle.BorderLeft = NPOIBorderStyle.Thin;
|
|
||||||
dataStyle.BorderRight = NPOIBorderStyle.Thin;
|
|
||||||
dataStyle.Alignment = NPOIHorizontalAlignment.Center;
|
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();
|
ICellStyle yellowStyle = workbook.CreateCellStyle();
|
||||||
yellowStyle.CloneStyleFrom(dataStyle);
|
yellowStyle.CloneStyleFrom(dataStyle);
|
||||||
yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
|
yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
|
||||||
yellowStyle.FillPattern = FillPattern.SolidForeground;
|
yellowStyle.FillPattern = FillPattern.SolidForeground;
|
||||||
|
|
||||||
|
return (titleStyle, headerStyle, dataStyle, yellowStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置单元格边框
|
||||||
|
/// </summary>
|
||||||
|
private void SetBorders(ICellStyle style)
|
||||||
|
{
|
||||||
|
style.BorderBottom = NPOIBorderStyle.Thin;
|
||||||
|
style.BorderTop = NPOIBorderStyle.Thin;
|
||||||
|
style.BorderLeft = NPOIBorderStyle.Thin;
|
||||||
|
style.BorderRight = NPOIBorderStyle.Thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建报表标题
|
||||||
|
/// </summary>
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建报表表头
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 填充报表数据
|
||||||
|
/// </summary>
|
||||||
|
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;
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存文件
|
/// <summary>
|
||||||
|
/// 设置报表列宽
|
||||||
|
/// </summary>
|
||||||
|
private void SetReportColumnWidths(ISheet sheet)
|
||||||
|
{
|
||||||
|
sheet.SetColumnWidth(0, 25 * 256);
|
||||||
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
|
{
|
||||||
|
sheet.SetColumnWidth(i, 18 * 256);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存工作簿
|
||||||
|
/// </summary>
|
||||||
|
private void SaveWorkbook(IWorkbook workbook, string filePath)
|
||||||
|
{
|
||||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||||
{
|
{
|
||||||
workbook.Write(fs);
|
workbook.Write(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBox.Show($"报表已成功生成:{filePath}", "生成成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"生成报表失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -688,7 +646,7 @@ namespace WindowsFormsApp6
|
|||||||
{
|
{
|
||||||
sampleDataTable.Clear();
|
sampleDataTable.Clear();
|
||||||
sampleCount = 0;
|
sampleCount = 0;
|
||||||
UpdateDisplay();
|
RefreshDataGridView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
WindowsFormsApp6/Form3.Designer.cs
generated
27
WindowsFormsApp6/Form3.Designer.cs
generated
@@ -13,10 +13,35 @@
|
|||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing && (components != null))
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (components != null)
|
||||||
{
|
{
|
||||||
components.Dispose();
|
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);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,23 @@ namespace WindowsFormsApp6
|
|||||||
{
|
{
|
||||||
public partial class Form3 : Form
|
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 dataTimer;
|
||||||
|
private System.Windows.Forms.Timer clockTimer;
|
||||||
private DataTable sampleDataTable;
|
private DataTable sampleDataTable;
|
||||||
|
private int currentSampleCount = 5; // 当前试样数量,可动态调整
|
||||||
|
private readonly Random random = new Random();
|
||||||
|
#endregion
|
||||||
|
|
||||||
public Form3()
|
public Form3()
|
||||||
{
|
{
|
||||||
@@ -34,125 +49,116 @@ namespace WindowsFormsApp6
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化 DataGridView 列 - 实现复杂多级表头
|
/// 设置试样数量(1-20)
|
||||||
|
/// </summary>
|
||||||
|
public void SetSampleCount(int count)
|
||||||
|
{
|
||||||
|
if (count < 1 || count > 20)
|
||||||
|
{
|
||||||
|
ShowMessage("试样数量必须在1-20之间", "参数错误", MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSampleCount = count;
|
||||||
|
|
||||||
|
// 重新初始化数据表和界面
|
||||||
|
sampleDataTable.Clear();
|
||||||
|
InitializeDataTable();
|
||||||
|
InitializeDataGridView();
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化 DataGridView 列 - 实现2级表头
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeDataGridView()
|
private void InitializeDataGridView()
|
||||||
{
|
{
|
||||||
// 禁用自动生成列
|
dataGridView1.SuspendLayout();
|
||||||
|
try
|
||||||
|
{
|
||||||
dataGridView1.AutoGenerateColumns = false;
|
dataGridView1.AutoGenerateColumns = false;
|
||||||
|
|
||||||
// 先解除数据绑定
|
|
||||||
dataGridView1.DataSource = null;
|
dataGridView1.DataSource = null;
|
||||||
|
|
||||||
// 清除现有列
|
|
||||||
dataGridView1.Columns.Clear();
|
dataGridView1.Columns.Clear();
|
||||||
|
|
||||||
// 先移除可能存在的事件处理器,避免重复绑定
|
// 移除可能存在的事件处理器
|
||||||
dataGridView1.CellFormatting -= DataGridView1_CellFormatting;
|
dataGridView1.CellFormatting -= DataGridView1_CellFormatting;
|
||||||
dataGridView1.CellValueChanged -= DataGridView1_CellValueChanged;
|
dataGridView1.CellValueChanged -= DataGridView1_CellValueChanged;
|
||||||
dataGridView1.CellBeginEdit -= DataGridView1_CellBeginEdit;
|
dataGridView1.CellBeginEdit -= DataGridView1_CellBeginEdit;
|
||||||
|
|
||||||
// 白色背景样式(只读)- 不设置BackColor,让隔行变色生效
|
// 创建共享样式(不设置背景色,让 AlternatingRowsDefaultCellStyle 生效)
|
||||||
DataGridViewCellStyle readonlyStyle = new DataGridViewCellStyle
|
DataGridViewCellStyle centerStyle = new DataGridViewCellStyle
|
||||||
{
|
{
|
||||||
Alignment = DataGridViewContentAlignment.MiddleCenter,
|
Alignment = DataGridViewContentAlignment.MiddleCenter
|
||||||
SelectionBackColor = Color.LightGray
|
|
||||||
};
|
|
||||||
|
|
||||||
// 白色背景样式(可编辑)- 不设置BackColor,让隔行变色生效
|
|
||||||
DataGridViewCellStyle editableStyle = new DataGridViewCellStyle
|
|
||||||
{
|
|
||||||
Alignment = DataGridViewContentAlignment.MiddleCenter,
|
|
||||||
SelectionBackColor = Color.LightBlue
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 序号列
|
// 序号列
|
||||||
DataGridViewTextBoxColumn seqCol = new DataGridViewTextBoxColumn
|
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||||||
{
|
{
|
||||||
Name = "序号",
|
Name = "序号",
|
||||||
HeaderText = "序号",
|
HeaderText = "序号",
|
||||||
DataPropertyName = "序号",
|
DataPropertyName = "序号",
|
||||||
Width = 120,
|
Width = 180,
|
||||||
ReadOnly = true,
|
ReadOnly = true,
|
||||||
DefaultCellStyle = (DataGridViewCellStyle)readonlyStyle.Clone()
|
DefaultCellStyle = centerStyle
|
||||||
};
|
});
|
||||||
dataGridView1.Columns.Add(seqCol);
|
|
||||||
|
|
||||||
// 为每个试样添加3列(试样次数:1、2、3)
|
// 为每个试样添加3列(2级表头:试样N + 子列1/2/3)
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
// 列1:试样次数1
|
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||||||
DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn
|
|
||||||
{
|
{
|
||||||
Name = $"试样{i}_1",
|
Name = $"试样{i}_1",
|
||||||
HeaderText = $"试样{i}\n1",
|
HeaderText = $"试样{i}\n1",
|
||||||
DataPropertyName = $"试样{i}_1",
|
DataPropertyName = $"试样{i}_1",
|
||||||
Width = 100,
|
Width = 100,
|
||||||
ReadOnly = false,
|
ReadOnly = false,
|
||||||
DefaultCellStyle = (DataGridViewCellStyle)editableStyle.Clone()
|
DefaultCellStyle = (DataGridViewCellStyle)centerStyle.Clone()
|
||||||
};
|
});
|
||||||
dataGridView1.Columns.Add(col1);
|
|
||||||
|
|
||||||
// 列2:试样次数2
|
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||||||
DataGridViewTextBoxColumn col2 = new DataGridViewTextBoxColumn
|
|
||||||
{
|
{
|
||||||
Name = $"试样{i}_2",
|
Name = $"试样{i}_2",
|
||||||
HeaderText = $"试样{i}\n2",
|
HeaderText = $"试样{i}\n2",
|
||||||
DataPropertyName = $"试样{i}_2",
|
DataPropertyName = $"试样{i}_2",
|
||||||
Width = 100,
|
Width = 100,
|
||||||
ReadOnly = false,
|
ReadOnly = false,
|
||||||
DefaultCellStyle = (DataGridViewCellStyle)editableStyle.Clone()
|
DefaultCellStyle = (DataGridViewCellStyle)centerStyle.Clone()
|
||||||
};
|
});
|
||||||
dataGridView1.Columns.Add(col2);
|
|
||||||
|
|
||||||
// 列3:试样次数3
|
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||||||
DataGridViewTextBoxColumn col3 = new DataGridViewTextBoxColumn
|
|
||||||
{
|
{
|
||||||
Name = $"试样{i}_3",
|
Name = $"试样{i}_3",
|
||||||
HeaderText = $"试样{i}\n3",
|
HeaderText = $"试样{i}\n3",
|
||||||
DataPropertyName = $"试样{i}_3",
|
DataPropertyName = $"试样{i}_3",
|
||||||
Width = 100,
|
Width = 100,
|
||||||
ReadOnly = false,
|
ReadOnly = false,
|
||||||
DefaultCellStyle = (DataGridViewCellStyle)editableStyle.Clone()
|
DefaultCellStyle = (DataGridViewCellStyle)centerStyle.Clone()
|
||||||
};
|
});
|
||||||
dataGridView1.Columns.Add(col3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绑定数据源
|
// 绑定数据源
|
||||||
dataGridView1.DataSource = sampleDataTable;
|
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++)
|
|
||||||
{
|
|
||||||
var col = dataGridView1.Columns[i];
|
|
||||||
System.Diagnostics.Debug.WriteLine($"列{i}: Name={col.Name}, DataPropertyName={col.DataPropertyName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加单元格格式化事件
|
|
||||||
dataGridView1.CellFormatting += DataGridView1_CellFormatting;
|
dataGridView1.CellFormatting += DataGridView1_CellFormatting;
|
||||||
|
|
||||||
// 添加单元格编辑事件(用于手动输入后重新计算)
|
|
||||||
dataGridView1.CellValueChanged += DataGridView1_CellValueChanged;
|
dataGridView1.CellValueChanged += DataGridView1_CellValueChanged;
|
||||||
|
|
||||||
// 添加单元格编辑前事件(动态控制可编辑性)
|
|
||||||
dataGridView1.CellBeginEdit += DataGridView1_CellBeginEdit;
|
dataGridView1.CellBeginEdit += DataGridView1_CellBeginEdit;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
dataGridView1.ResumeLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 单元格编辑前事件 - 动态控制哪些单元格可以编辑
|
/// 单元格编辑前事件 - 动态控制哪些单元格可以编辑
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void DataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
|
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() ?? "";
|
string rowName = dataGridView1.Rows[e.RowIndex].Cells["序号"].Value?.ToString() ?? "";
|
||||||
|
|
||||||
// 吸芯高度(mm)行 - 所有列都可以编辑
|
// 吸芯高度(mm)行 - 所有列都可以编辑
|
||||||
if (rowName == "吸芯高度(mm)")
|
if (rowName == ROW_WICKING_HEIGHT)
|
||||||
{
|
{
|
||||||
return; // 允许编辑
|
return; // 允许编辑
|
||||||
}
|
}
|
||||||
@@ -167,71 +173,32 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
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位小数)
|
|
||||||
string columnName = dataGridView1.Columns[e.ColumnIndex].Name;
|
|
||||||
if (columnName.Contains("试样") && columnName != "序号")
|
|
||||||
{
|
|
||||||
if (double.TryParse(e.Value.ToString(), out double value))
|
|
||||||
{
|
|
||||||
// 如果值为0,根据行和列决定是否显示
|
|
||||||
if (value == 0)
|
|
||||||
{
|
|
||||||
string rowName = dataGridView1.Rows[e.RowIndex].Cells["序号"].Value?.ToString() ?? "";
|
|
||||||
|
|
||||||
// 根据示意图,某些单元格应该显示为空白
|
// 格式化数值显示为2位小数
|
||||||
if (ShouldBeEmpty(rowName, columnName))
|
if (e.Value != null && e.Value != DBNull.Value)
|
||||||
|
{
|
||||||
|
if (double.TryParse(e.Value.ToString(), out double numValue))
|
||||||
|
{
|
||||||
|
// 如果值为0或接近0,显示为空白
|
||||||
|
if (Math.Abs(numValue) < 0.001)
|
||||||
{
|
{
|
||||||
e.Value = "";
|
e.Value = "";
|
||||||
e.FormattingApplied = true;
|
e.FormattingApplied = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
e.Value = value.ToString("F2");
|
// 显示2位小数
|
||||||
|
e.Value = numValue.ToString("F2");
|
||||||
e.FormattingApplied = true;
|
e.FormattingApplied = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 判断单元格是否应该为空白
|
|
||||||
/// </summary>
|
|
||||||
private bool ShouldBeEmpty(string rowName, string columnName)
|
|
||||||
{
|
{
|
||||||
// 吸水时间(s) - 只有试样次数1有数据
|
// null 或 DBNull 显示为空白
|
||||||
if (rowName == "吸水时间(s)")
|
e.Value = "";
|
||||||
{
|
e.FormattingApplied = true;
|
||||||
return columnName.EndsWith("_2") || columnName.EndsWith("_3");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 吸芯高度(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -244,9 +211,10 @@ namespace WindowsFormsApp6
|
|||||||
string rowName = dataGridView1.Rows[e.RowIndex].Cells["序号"].Value?.ToString() ?? "";
|
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
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeEventHandlers()
|
private void InitializeEventHandlers()
|
||||||
{
|
{
|
||||||
// 连接设备按钮
|
|
||||||
button1.Click += Button1_Click;
|
button1.Click += Button1_Click;
|
||||||
|
|
||||||
// 打印按钮
|
|
||||||
button2.Click += Button2_Click;
|
button2.Click += Button2_Click;
|
||||||
|
|
||||||
// 导出按钮
|
|
||||||
button3.Click += Button3_Click;
|
button3.Click += Button3_Click;
|
||||||
|
|
||||||
// 返回按钮
|
|
||||||
button4.Click += Button4_Click;
|
button4.Click += Button4_Click;
|
||||||
|
|
||||||
// 生成模拟数据按钮
|
|
||||||
button5.Click += Button5_Click;
|
button5.Click += Button5_Click;
|
||||||
|
|
||||||
// 更新日期时间标签
|
clockTimer = new System.Windows.Forms.Timer
|
||||||
System.Windows.Forms.Timer clockTimer = new System.Windows.Forms.Timer();
|
{
|
||||||
clockTimer.Interval = 1000;
|
Interval = TIMER_INTERVAL
|
||||||
clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
};
|
||||||
|
clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString(DATE_TIME_FORMAT);
|
||||||
clockTimer.Start();
|
clockTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,16 +246,14 @@ namespace WindowsFormsApp6
|
|||||||
if (dataTimer.Enabled)
|
if (dataTimer.Enabled)
|
||||||
{
|
{
|
||||||
StopDataCollection();
|
StopDataCollection();
|
||||||
button1.Text = "🔗 连接设备";
|
UpdateButtonState(button1, "🔗 连接设备", Color.FromArgb(46, 204, 113));
|
||||||
button1.BackColor = Color.FromArgb(46, 204, 113);
|
ShowMessage("已停止数据采集");
|
||||||
MessageBox.Show("已停止数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StartDataCollection();
|
StartDataCollection();
|
||||||
button1.Text = "⏸️ 停止采集";
|
UpdateButtonState(button1, "⏸️ 停止采集", Color.FromArgb(231, 76, 60));
|
||||||
button1.BackColor = Color.FromArgb(231, 76, 60);
|
ShowMessage("开始数据采集");
|
||||||
MessageBox.Show("开始数据采集", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +262,24 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void Button2_Click(object sender, EventArgs e)
|
private void Button2_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
MessageBox.Show("打印功能开发中...", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
ShowMessage("打印功能开发中...");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新按钮状态
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateButtonState(Button button, string text, Color backColor)
|
||||||
|
{
|
||||||
|
button.Text = text;
|
||||||
|
button.BackColor = backColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示提示消息
|
||||||
|
/// </summary>
|
||||||
|
private void ShowMessage(string message, string title = "提示", MessageBoxIcon icon = MessageBoxIcon.Information)
|
||||||
|
{
|
||||||
|
MessageBox.Show(message, title, MessageBoxButtons.OK, icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -352,19 +327,19 @@ namespace WindowsFormsApp6
|
|||||||
sampleDataTable.Columns.Add("序号", typeof(string));
|
sampleDataTable.Columns.Add("序号", typeof(string));
|
||||||
|
|
||||||
// 为每个试样添加3列(试样次数:1、2、3)
|
// 为每个试样添加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}_1", typeof(double));
|
||||||
sampleDataTable.Columns.Add($"试样{i}_2", typeof(double)); // 手动输入
|
sampleDataTable.Columns.Add($"试样{i}_2", typeof(double));
|
||||||
sampleDataTable.Columns.Add($"试样{i}_3", typeof(double)); // 系统计算
|
sampleDataTable.Columns.Add($"试样{i}_3", typeof(double));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化6行数据
|
// 初始化5行数据
|
||||||
AddDataRow("吸水时间(s)");
|
AddDataRow(ROW_WICKING_TIME);
|
||||||
AddDataRow("吸芯高度(mm)");
|
AddDataRow(ROW_WICKING_HEIGHT);
|
||||||
AddDataRow("芯吸速率(mm/min)");
|
AddDataRow(ROW_WICKING_RATE);
|
||||||
AddDataRow("平均芯吸速率(mm/min)");
|
AddDataRow(ROW_AVG_WICKING_RATE);
|
||||||
AddDataRow("标准偏差");
|
AddDataRow(ROW_STD_DEVIATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -376,7 +351,7 @@ namespace WindowsFormsApp6
|
|||||||
row["序号"] = rowName;
|
row["序号"] = rowName;
|
||||||
|
|
||||||
// 初始化所有数值列为0
|
// 初始化所有数值列为0
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
row[$"试样{i}_1"] = 0.0;
|
row[$"试样{i}_1"] = 0.0;
|
||||||
row[$"试样{i}_2"] = 0.0;
|
row[$"试样{i}_2"] = 0.0;
|
||||||
@@ -401,26 +376,22 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void DataTimer_Tick(object sender, EventArgs e)
|
private void DataTimer_Tick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// 读取吸水时间(s)- 从寄存器读取
|
// 读取吸水时间(s) - 从寄存器读取
|
||||||
DataRow timeRow = sampleDataTable.Rows[0]; // 第一行:吸水时间
|
DataRow timeRow = sampleDataTable.Rows[0];
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
double registerValue = ReadRegisterData(i - 1);
|
double registerValue = ReadRegisterData(i - 1);
|
||||||
timeRow[$"试样{i}_1"] = registerValue;
|
timeRow[$"试样{i}_1"] = registerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触发界面更新
|
|
||||||
UpdateDisplay();
|
UpdateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模拟从寄存器读取数据
|
/// 模拟从寄存器读取数据
|
||||||
/// 实际应用中替换为真实的 Modbus 或其他协议读取
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private double ReadRegisterData(int registerAddress)
|
private double ReadRegisterData(int registerAddress)
|
||||||
{
|
{
|
||||||
// 模拟数据:30-34 之间的随机值
|
|
||||||
Random random = new Random(Guid.NewGuid().GetHashCode());
|
|
||||||
return 30 + random.NextDouble() * 4;
|
return 30 + random.NextDouble() * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,49 +400,92 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void GenerateMockData()
|
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行:吸水时间(s)- 试样次数1(系统读数)
|
||||||
|
// 每个试样只在第1次测试时记录吸水时间
|
||||||
DataRow timeRow = sampleDataTable.Rows[0];
|
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" +
|
||||||
|
$"- 芯吸速率:输入吸芯高度后自动计算",
|
||||||
|
"模拟数据生成");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成完整的测试数据(包含吸芯高度)- 用于快速测试
|
||||||
|
/// </summary>
|
||||||
|
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);
|
double timeValue = Math.Round(30 + random.NextDouble() * 4, 2);
|
||||||
timeRow[$"试样{i}_1"] = timeValue;
|
timeRow[$"试样{i}_1"] = timeValue;
|
||||||
System.Diagnostics.Debug.WriteLine($"吸水时间 - 试样{i}_1 = {timeValue}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第2行:吸芯高度(mm)- 所有列都可编辑(手动输入)
|
// 第2行:吸芯高度(mm)- 生成测试数据
|
||||||
DataRow heightRow = sampleDataTable.Rows[1];
|
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 baseHeight = 55 + random.NextDouble() * 10;
|
||||||
double height2 = Math.Round(50 + random.NextDouble() * 20, 2);
|
double height1 = Math.Round(baseHeight + (random.NextDouble() - 0.5) * 4, 2);
|
||||||
double height3 = Math.Round(50 + random.NextDouble() * 20, 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}_1"] = height1;
|
||||||
heightRow[$"试样{i}_2"] = height2;
|
heightRow[$"试样{i}_2"] = height2;
|
||||||
heightRow[$"试样{i}_3"] = height3;
|
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();
|
CalculateAllRows();
|
||||||
|
|
||||||
// 更新显示
|
// 更新显示
|
||||||
UpdateDisplay();
|
RefreshDataGridView();
|
||||||
|
|
||||||
// 调试信息:验证数据
|
ShowMessage($"已生成完整测试数据(包含吸芯高度)\n" +
|
||||||
System.Diagnostics.Debug.WriteLine("=== 模拟数据生成完成 ===");
|
$"- 吸水时间:30-34秒\n" +
|
||||||
DataRow rateRow = sampleDataTable.Rows[2];
|
$"- 吸芯高度:50-70mm(自动生成)\n" +
|
||||||
for (int i = 1; i <= 5; i++)
|
$"- 芯吸速率:已自动计算",
|
||||||
{
|
"完整测试数据");
|
||||||
System.Diagnostics.Debug.WriteLine($"芯吸速率 - 试样{i}_3 = {rateRow[$"试样{i}_3"]}");
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageBox.Show("已生成模拟数据\n请查看输出窗口的调试信息", "模拟数据生成", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -479,10 +493,17 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateDisplay()
|
private void UpdateDisplay()
|
||||||
{
|
{
|
||||||
// 刷新 DataGridView
|
RefreshDataGridView();
|
||||||
if (dataGridView1.DataSource != null)
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新DataGridView
|
||||||
|
/// </summary>
|
||||||
|
private void RefreshDataGridView()
|
||||||
{
|
{
|
||||||
((DataTable)dataGridView1.DataSource).AcceptChanges();
|
if (dataGridView1.DataSource is DataTable dt)
|
||||||
|
{
|
||||||
|
dt.AcceptChanges();
|
||||||
dataGridView1.Refresh();
|
dataGridView1.Refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -502,15 +523,6 @@ namespace WindowsFormsApp6
|
|||||||
CalculateStandardDeviation();
|
CalculateStandardDeviation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重新计算指定行
|
|
||||||
/// </summary>
|
|
||||||
private void RecalculateRow(int rowIndex)
|
|
||||||
{
|
|
||||||
CalculateAllRows();
|
|
||||||
UpdateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计算芯吸速率(mm/min)
|
/// 计算芯吸速率(mm/min)
|
||||||
/// 公式:芯吸速率 = 吸芯高度(mm) / (吸水时间(s) / 60)
|
/// 公式:芯吸速率 = 吸芯高度(mm) / (吸水时间(s) / 60)
|
||||||
@@ -521,7 +533,7 @@ namespace WindowsFormsApp6
|
|||||||
DataRow heightRow = sampleDataTable.Rows[1]; // 吸芯高度
|
DataRow heightRow = sampleDataTable.Rows[1]; // 吸芯高度
|
||||||
DataRow rateRow = sampleDataTable.Rows[2]; // 芯吸速率
|
DataRow rateRow = sampleDataTable.Rows[2]; // 芯吸速率
|
||||||
|
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
// 获取吸水时间(试样次数1:系统读数)
|
// 获取吸水时间(试样次数1:系统读数)
|
||||||
double time = ConvertToDouble(timeRow[$"试样{i}_1"]);
|
double time = ConvertToDouble(timeRow[$"试样{i}_1"]);
|
||||||
@@ -584,7 +596,7 @@ namespace WindowsFormsApp6
|
|||||||
DataRow avgRow = sampleDataTable.Rows[3]; // 平均芯吸速率
|
DataRow avgRow = sampleDataTable.Rows[3]; // 平均芯吸速率
|
||||||
|
|
||||||
List<double> rates = new List<double>();
|
List<double> rates = new List<double>();
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
double rate = ConvertToDouble(rateRow[$"试样{i}_3"]);
|
double rate = ConvertToDouble(rateRow[$"试样{i}_3"]);
|
||||||
if (rate > 0)
|
if (rate > 0)
|
||||||
@@ -596,7 +608,7 @@ namespace WindowsFormsApp6
|
|||||||
double average = rates.Count > 0 ? rates.Average() : 0;
|
double average = rates.Count > 0 ? rates.Average() : 0;
|
||||||
|
|
||||||
// 所有试样显示相同的平均值(存储在试样次数3)
|
// 所有试样显示相同的平均值(存储在试样次数3)
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
avgRow[$"试样{i}_3"] = Math.Round(average, 2);
|
avgRow[$"试样{i}_3"] = Math.Round(average, 2);
|
||||||
}
|
}
|
||||||
@@ -611,7 +623,7 @@ namespace WindowsFormsApp6
|
|||||||
DataRow stdRow = sampleDataTable.Rows[4]; // 标准偏差
|
DataRow stdRow = sampleDataTable.Rows[4]; // 标准偏差
|
||||||
|
|
||||||
List<double> rates = new List<double>();
|
List<double> rates = new List<double>();
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
double rate = ConvertToDouble(rateRow[$"试样{i}_3"]);
|
double rate = ConvertToDouble(rateRow[$"试样{i}_3"]);
|
||||||
if (rate > 0)
|
if (rate > 0)
|
||||||
@@ -629,7 +641,7 @@ namespace WindowsFormsApp6
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 所有试样显示相同的标准偏差(存储在试样次数3)
|
// 所有试样显示相同的标准偏差(存储在试样次数3)
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
stdRow[$"试样{i}_3"] = Math.Round(stdDev, 2);
|
stdRow[$"试样{i}_3"] = Math.Round(stdDev, 2);
|
||||||
}
|
}
|
||||||
@@ -658,57 +670,88 @@ namespace WindowsFormsApp6
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IWorkbook workbook;
|
IWorkbook workbook = filePath.EndsWith(".xlsx")
|
||||||
|
? (IWorkbook)new XSSFWorkbook()
|
||||||
|
: new HSSFWorkbook();
|
||||||
|
|
||||||
// 根据文件扩展名选择格式
|
ISheet sheet = workbook.CreateSheet("液体芯吸速率测试报表");
|
||||||
if (filePath.EndsWith(".xlsx"))
|
|
||||||
{
|
|
||||||
workbook = new XSSFWorkbook(); // Excel 2007+
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
workbook = new HSSFWorkbook(); // Excel 97-2003
|
|
||||||
}
|
|
||||||
|
|
||||||
ISheet sheet = workbook.CreateSheet("液体吸收测试报表");
|
|
||||||
|
|
||||||
// 创建样式
|
// 创建样式
|
||||||
|
var styles = CreateReportStyles(workbook);
|
||||||
|
|
||||||
|
// 创建表头(2级)
|
||||||
|
CreateReportHeader(sheet, styles.headerStyle);
|
||||||
|
|
||||||
|
// 填充数据
|
||||||
|
FillReportData(sheet, styles.dataStyle, styles.yellowStyle);
|
||||||
|
|
||||||
|
// 设置列宽
|
||||||
|
SetReportColumnWidths(sheet);
|
||||||
|
|
||||||
|
// 保存文件
|
||||||
|
SaveWorkbook(workbook, filePath);
|
||||||
|
|
||||||
|
ShowMessage($"数据已成功导出到:{filePath}", "导出成功");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ShowMessage($"导出失败:{ex.Message}", "错误", MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建报表样式
|
||||||
|
/// </summary>
|
||||||
|
private (ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle yellowStyle)
|
||||||
|
CreateReportStyles(IWorkbook workbook)
|
||||||
|
{
|
||||||
|
// 表头样式
|
||||||
ICellStyle headerStyle = workbook.CreateCellStyle();
|
ICellStyle headerStyle = workbook.CreateCellStyle();
|
||||||
headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
|
headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
|
||||||
headerStyle.FillPattern = FillPattern.SolidForeground;
|
headerStyle.FillPattern = FillPattern.SolidForeground;
|
||||||
headerStyle.BorderBottom = NPOIBorderStyle.Thin;
|
SetBorders(headerStyle);
|
||||||
headerStyle.BorderTop = NPOIBorderStyle.Thin;
|
|
||||||
headerStyle.BorderLeft = NPOIBorderStyle.Thin;
|
|
||||||
headerStyle.BorderRight = NPOIBorderStyle.Thin;
|
|
||||||
headerStyle.Alignment = NPOIHorizontalAlignment.Center;
|
headerStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||||
headerStyle.VerticalAlignment = VerticalAlignment.Center;
|
headerStyle.VerticalAlignment = VerticalAlignment.Center;
|
||||||
IFont headerFont = workbook.CreateFont();
|
IFont headerFont = workbook.CreateFont();
|
||||||
headerFont.IsBold = true;
|
headerFont.IsBold = true;
|
||||||
headerStyle.SetFont(headerFont);
|
headerStyle.SetFont(headerFont);
|
||||||
|
|
||||||
// 白色背景样式(偶数行)
|
// 白色背景样式
|
||||||
ICellStyle whiteStyle = workbook.CreateCellStyle();
|
ICellStyle dataStyle = workbook.CreateCellStyle();
|
||||||
whiteStyle.BorderBottom = NPOIBorderStyle.Thin;
|
SetBorders(dataStyle);
|
||||||
whiteStyle.BorderTop = NPOIBorderStyle.Thin;
|
dataStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||||
whiteStyle.BorderLeft = NPOIBorderStyle.Thin;
|
dataStyle.VerticalAlignment = VerticalAlignment.Center;
|
||||||
whiteStyle.BorderRight = NPOIBorderStyle.Thin;
|
|
||||||
whiteStyle.Alignment = NPOIHorizontalAlignment.Center;
|
|
||||||
whiteStyle.VerticalAlignment = VerticalAlignment.Center;
|
|
||||||
|
|
||||||
// 黄色背景样式(奇数行)
|
// 黄色背景样式
|
||||||
ICellStyle yellowStyle = workbook.CreateCellStyle();
|
ICellStyle yellowStyle = workbook.CreateCellStyle();
|
||||||
yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.LightYellow.Index;
|
yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.LightYellow.Index;
|
||||||
yellowStyle.FillPattern = FillPattern.SolidForeground;
|
yellowStyle.FillPattern = FillPattern.SolidForeground;
|
||||||
yellowStyle.BorderBottom = NPOIBorderStyle.Thin;
|
SetBorders(yellowStyle);
|
||||||
yellowStyle.BorderTop = NPOIBorderStyle.Thin;
|
|
||||||
yellowStyle.BorderLeft = NPOIBorderStyle.Thin;
|
|
||||||
yellowStyle.BorderRight = NPOIBorderStyle.Thin;
|
|
||||||
yellowStyle.Alignment = NPOIHorizontalAlignment.Center;
|
yellowStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||||
yellowStyle.VerticalAlignment = VerticalAlignment.Center;
|
yellowStyle.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
|
||||||
// 创建第一行表头(试样1-5)
|
return (headerStyle, dataStyle, yellowStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置单元格边框
|
||||||
|
/// </summary>
|
||||||
|
private void SetBorders(ICellStyle style)
|
||||||
|
{
|
||||||
|
style.BorderBottom = NPOIBorderStyle.Thin;
|
||||||
|
style.BorderTop = NPOIBorderStyle.Thin;
|
||||||
|
style.BorderLeft = NPOIBorderStyle.Thin;
|
||||||
|
style.BorderRight = NPOIBorderStyle.Thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建报表表头(2级)
|
||||||
|
/// </summary>
|
||||||
|
private void CreateReportHeader(ISheet sheet, ICellStyle headerStyle)
|
||||||
|
{
|
||||||
|
// 创建第一行表头(试样1-N)
|
||||||
IRow headerRow1 = sheet.CreateRow(0);
|
IRow headerRow1 = sheet.CreateRow(0);
|
||||||
headerRow1.Height = 400; // 设置行高(单位:1/20点)
|
headerRow1.Height = 400;
|
||||||
|
|
||||||
ICell cell0 = headerRow1.CreateCell(0);
|
ICell cell0 = headerRow1.CreateCell(0);
|
||||||
cell0.SetCellValue("序号");
|
cell0.SetCellValue("序号");
|
||||||
@@ -716,7 +759,7 @@ namespace WindowsFormsApp6
|
|||||||
sheet.AddMergedRegion(new CellRangeAddress(0, 1, 0, 0)); // 合并序号列
|
sheet.AddMergedRegion(new CellRangeAddress(0, 1, 0, 0)); // 合并序号列
|
||||||
|
|
||||||
int colIndex = 1;
|
int colIndex = 1;
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
ICell cell = headerRow1.CreateCell(colIndex);
|
ICell cell = headerRow1.CreateCell(colIndex);
|
||||||
cell.SetCellValue($"试样{i}");
|
cell.SetCellValue($"试样{i}");
|
||||||
@@ -727,10 +770,10 @@ namespace WindowsFormsApp6
|
|||||||
|
|
||||||
// 创建第二行表头(试样次数:1、2、3)
|
// 创建第二行表头(试样次数:1、2、3)
|
||||||
IRow headerRow2 = sheet.CreateRow(1);
|
IRow headerRow2 = sheet.CreateRow(1);
|
||||||
headerRow2.Height = 400; // 设置行高
|
headerRow2.Height = 400;
|
||||||
|
|
||||||
colIndex = 1;
|
colIndex = 1;
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
ICell cell1 = headerRow2.CreateCell(colIndex++);
|
ICell cell1 = headerRow2.CreateCell(colIndex++);
|
||||||
cell1.SetCellValue("1");
|
cell1.SetCellValue("1");
|
||||||
@@ -744,30 +787,36 @@ namespace WindowsFormsApp6
|
|||||||
cell3.SetCellValue("3");
|
cell3.SetCellValue("3");
|
||||||
cell3.CellStyle = headerStyle;
|
cell3.CellStyle = headerStyle;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 填充数据
|
/// <summary>
|
||||||
|
/// 填充报表数据
|
||||||
|
/// </summary>
|
||||||
|
private void FillReportData(ISheet sheet, ICellStyle dataStyle, ICellStyle yellowStyle)
|
||||||
|
{
|
||||||
int rowIndex = 2;
|
int rowIndex = 2;
|
||||||
int dataRowIndex = 0;
|
int dataRowIndex = 0;
|
||||||
|
|
||||||
foreach (DataRow dataRow in sampleDataTable.Rows)
|
foreach (DataRow dataRow in sampleDataTable.Rows)
|
||||||
{
|
{
|
||||||
IRow row = sheet.CreateRow(rowIndex);
|
IRow row = sheet.CreateRow(rowIndex);
|
||||||
row.Height = 380; // 设置数据行高
|
row.Height = 380;
|
||||||
|
|
||||||
// 根据行索引选择样式(隔行变色)
|
// 根据行索引选择样式(隔行变色)
|
||||||
ICellStyle rowStyle = (dataRowIndex % 2 == 0) ? whiteStyle : yellowStyle;
|
ICellStyle rowStyle = (dataRowIndex % 2 == 0) ? dataStyle : yellowStyle;
|
||||||
|
|
||||||
// 序号列
|
// 序号列
|
||||||
ICell cellSeq = row.CreateCell(0);
|
ICell cellSeq = row.CreateCell(0);
|
||||||
cellSeq.SetCellValue(dataRow["序号"].ToString());
|
cellSeq.SetCellValue(dataRow["序号"].ToString());
|
||||||
cellSeq.CellStyle = rowStyle;
|
cellSeq.CellStyle = rowStyle;
|
||||||
|
|
||||||
colIndex = 1;
|
int colIndex = 1;
|
||||||
for (int i = 1; i <= 5; i++)
|
for (int i = 1; i <= currentSampleCount; i++)
|
||||||
{
|
{
|
||||||
// 试样次数1
|
// 试样次数1
|
||||||
ICell cell1 = row.CreateCell(colIndex++);
|
ICell cell1 = row.CreateCell(colIndex++);
|
||||||
double val1 = ConvertToDouble(dataRow[$"试样{i}_1"]);
|
double val1 = ConvertToDouble(dataRow[$"试样{i}_1"]);
|
||||||
if (val1 != 0)
|
if (Math.Abs(val1) >= 0.001) // 只有非0值才显示
|
||||||
{
|
{
|
||||||
cell1.SetCellValue(val1);
|
cell1.SetCellValue(val1);
|
||||||
}
|
}
|
||||||
@@ -776,7 +825,7 @@ namespace WindowsFormsApp6
|
|||||||
// 试样次数2
|
// 试样次数2
|
||||||
ICell cell2 = row.CreateCell(colIndex++);
|
ICell cell2 = row.CreateCell(colIndex++);
|
||||||
double val2 = ConvertToDouble(dataRow[$"试样{i}_2"]);
|
double val2 = ConvertToDouble(dataRow[$"试样{i}_2"]);
|
||||||
if (val2 != 0)
|
if (Math.Abs(val2) >= 0.001) // 只有非0值才显示
|
||||||
{
|
{
|
||||||
cell2.SetCellValue(val2);
|
cell2.SetCellValue(val2);
|
||||||
}
|
}
|
||||||
@@ -785,7 +834,7 @@ namespace WindowsFormsApp6
|
|||||||
// 试样次数3
|
// 试样次数3
|
||||||
ICell cell3 = row.CreateCell(colIndex++);
|
ICell cell3 = row.CreateCell(colIndex++);
|
||||||
double val3 = ConvertToDouble(dataRow[$"试样{i}_3"]);
|
double val3 = ConvertToDouble(dataRow[$"试样{i}_3"]);
|
||||||
if (val3 != 0)
|
if (Math.Abs(val3) >= 0.001) // 只有非0值才显示
|
||||||
{
|
{
|
||||||
cell3.SetCellValue(val3);
|
cell3.SetCellValue(val3);
|
||||||
}
|
}
|
||||||
@@ -795,26 +844,30 @@ namespace WindowsFormsApp6
|
|||||||
rowIndex++;
|
rowIndex++;
|
||||||
dataRowIndex++;
|
dataRowIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 手动设置列宽(单位:1/256字符宽度)
|
|
||||||
sheet.SetColumnWidth(0, 20 * 256); // 序号列:20个字符宽度
|
|
||||||
for (int i = 1; i <= 15; i++)
|
|
||||||
{
|
|
||||||
sheet.SetColumnWidth(i, 12 * 256); // 数据列:12个字符宽度
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存文件
|
/// <summary>
|
||||||
|
/// 设置报表列宽
|
||||||
|
/// </summary>
|
||||||
|
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); // 数据列
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存工作簿
|
||||||
|
/// </summary>
|
||||||
|
private void SaveWorkbook(IWorkbook workbook, string filePath)
|
||||||
|
{
|
||||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||||
{
|
{
|
||||||
workbook.Write(fs);
|
workbook.Write(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBox.Show($"数据已成功导出到:{filePath}", "导出成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -831,10 +884,9 @@ namespace WindowsFormsApp6
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ClearData()
|
public void ClearData()
|
||||||
{
|
{
|
||||||
// 重新初始化数据表
|
|
||||||
sampleDataTable.Clear();
|
sampleDataTable.Clear();
|
||||||
InitializeDataTable();
|
InitializeDataTable();
|
||||||
UpdateDisplay();
|
RefreshDataGridView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user