2025-12-31 09:43:35 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
|
using System.Data;
|
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using NPOI.SS.UserModel;
|
|
|
|
|
|
using NPOI.XSSF.UserModel; // 用于 .xlsx
|
|
|
|
|
|
using NPOI.HSSF.UserModel; // 用于 .xls
|
|
|
|
|
|
using NPOI.SS.Util;
|
|
|
|
|
|
|
|
|
|
|
|
// 使用别名解决命名空间冲突
|
|
|
|
|
|
using NPOIBorderStyle = NPOI.SS.UserModel.BorderStyle;
|
|
|
|
|
|
using NPOIHorizontalAlignment = NPOI.SS.UserModel.HorizontalAlignment;
|
|
|
|
|
|
|
|
|
|
|
|
namespace WindowsFormsApp6
|
|
|
|
|
|
{
|
|
|
|
|
|
public partial class Form1 : Form
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
#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 字段
|
2025-12-31 09:43:35 +08:00
|
|
|
|
private System.Windows.Forms.Timer dataTimer;
|
2025-12-31 13:44:33 +08:00
|
|
|
|
private System.Windows.Forms.Timer clockTimer;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
private DataTable sampleDataTable;
|
|
|
|
|
|
private int sampleCount = 0;
|
2025-12-31 13:44:33 +08:00
|
|
|
|
private int currentSampleCount = 5; // 当前试样数量,可动态调整
|
|
|
|
|
|
private readonly Random random = new Random();
|
|
|
|
|
|
#endregion
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
|
|
|
|
|
public Form1()
|
|
|
|
|
|
{
|
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
|
InitializeDataTable();
|
|
|
|
|
|
InitializeTimer();
|
|
|
|
|
|
InitializeDataGridView();
|
|
|
|
|
|
InitializeEventHandlers();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化 DataGridView 列
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void InitializeDataGridView()
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
dataGridView1.SuspendLayout();
|
|
|
|
|
|
try
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
dataGridView1.Columns.Clear();
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 创建共享样式
|
|
|
|
|
|
var centerAlignStyle = new DataGridViewCellStyle
|
|
|
|
|
|
{
|
|
|
|
|
|
Alignment = DataGridViewContentAlignment.MiddleCenter
|
|
|
|
|
|
};
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
var yellowCenterStyle = new DataGridViewCellStyle
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
|
|
|
|
|
Alignment = DataGridViewContentAlignment.MiddleCenter,
|
|
|
|
|
|
BackColor = Color.FromArgb(255, 255, 200)
|
2025-12-31 13:44:33 +08:00
|
|
|
|
};
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 添加序号列
|
|
|
|
|
|
AddColumn("序号", "序号", COLUMN_WIDTH_STANDARD, centerAlignStyle);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 添加试样列
|
|
|
|
|
|
for (int i = 1; i <= currentSampleCount; i++)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
AddColumn($"试样{i}", $"试样{i}", COLUMN_WIDTH_STANDARD, yellowCenterStyle);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 绑定数据源
|
|
|
|
|
|
dataGridView1.DataSource = sampleDataTable;
|
|
|
|
|
|
dataGridView1.CellFormatting += DataGridView1_CellFormatting;
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
dataGridView1.ResumeLayout();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加列的辅助方法
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void AddColumn(string name, string headerText, int width, DataGridViewCellStyle style)
|
|
|
|
|
|
{
|
2025-12-31 09:43:35 +08:00
|
|
|
|
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
Name = name,
|
|
|
|
|
|
HeaderText = headerText,
|
|
|
|
|
|
DataPropertyName = name,
|
|
|
|
|
|
Width = width,
|
2025-12-31 09:43:35 +08:00
|
|
|
|
ReadOnly = true,
|
2025-12-31 13:44:33 +08:00
|
|
|
|
DefaultCellStyle = style
|
2025-12-31 09:43:35 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 单元格格式化事件 - 处理平均值行的显示
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
if (e.RowIndex < 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 格式化数值显示为2位小数
|
|
|
|
|
|
if (e.Value != null && e.Value != DBNull.Value)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
if (double.TryParse(e.Value.ToString(), out double numValue))
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
e.Value = numValue.ToString("F2");
|
|
|
|
|
|
e.FormattingApplied = true;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
2025-12-31 13:44:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 尝试计算总平均值
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private bool TryCalculateOverallAverage(DataGridViewRow row, out double overallAvg)
|
|
|
|
|
|
{
|
|
|
|
|
|
overallAvg = 0;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
double sum = 0;
|
|
|
|
|
|
for (int i = 1; i <= currentSampleCount; i++)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
var cellValue = row.Cells[$"试样{i}"].Value;
|
|
|
|
|
|
if (cellValue == null) return false;
|
|
|
|
|
|
sum += Convert.ToDouble(cellValue);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
2025-12-31 13:44:33 +08:00
|
|
|
|
overallAvg = sum / currentSampleCount;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 移除TryCalculateOverallAverage方法,因为不再需要
|
|
|
|
|
|
|
2025-12-31 09:43:35 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化事件处理器
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void InitializeEventHandlers()
|
|
|
|
|
|
{
|
|
|
|
|
|
button1.Click += Button1_Click;
|
|
|
|
|
|
button2.Click += Button2_Click;
|
|
|
|
|
|
button3.Click += Button3_Click;
|
|
|
|
|
|
button4.Click += Button4_Click;
|
|
|
|
|
|
button5.Click += Button5_Click;
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 初始化时钟定时器
|
|
|
|
|
|
clockTimer = new System.Windows.Forms.Timer
|
|
|
|
|
|
{
|
|
|
|
|
|
Interval = TIMER_INTERVAL
|
|
|
|
|
|
};
|
|
|
|
|
|
clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString(DATE_TIME_FORMAT);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
clockTimer.Start();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 连接设备按钮点击事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Button1_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dataTimer.Enabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
StopDataCollection();
|
2025-12-31 13:44:33 +08:00
|
|
|
|
UpdateButtonState(button1, "🔗 连接设备", Color.FromArgb(46, 204, 113));
|
|
|
|
|
|
ShowMessage("已停止数据采集");
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
StartDataCollection();
|
2025-12-31 13:44:33 +08:00
|
|
|
|
UpdateButtonState(button1, "⏸️ 停止采集", Color.FromArgb(231, 76, 60));
|
|
|
|
|
|
ShowMessage("开始数据采集");
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 09:43:35 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 打印按钮点击事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Button2_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
ShowMessage("打印功能开发中...");
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 导出按钮点击事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Button3_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
SaveFileDialog saveFileDialog = new SaveFileDialog
|
|
|
|
|
|
{
|
|
|
|
|
|
Filter = "Excel 文件 (*.xlsx)|*.xlsx|Excel 97-2003 (*.xls)|*.xls",
|
|
|
|
|
|
FileName = $"液体吸收测试报告_{DateTime.Now:yyyyMMdd_HHmmss}",
|
|
|
|
|
|
Title = "导出数据"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
|
|
|
|
|
{
|
|
|
|
|
|
GenerateReport(saveFileDialog.FileName);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 返回按钮点击事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Button4_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 生成模拟数据按钮点击事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Button5_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
GenerateMockData();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化数据表结构
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void InitializeDataTable()
|
|
|
|
|
|
{
|
|
|
|
|
|
sampleDataTable = new DataTable();
|
|
|
|
|
|
sampleDataTable.Columns.Add("序号", typeof(string));
|
2025-12-31 13:44:33 +08:00
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= currentSampleCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sampleDataTable.Columns.Add($"试样{i}", typeof(double));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置试样数量并重新初始化
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void SetSampleCount(int count)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (count < 1 || count > 20)
|
|
|
|
|
|
{
|
|
|
|
|
|
ShowMessage("试样数量必须在1-20之间", "参数错误", MessageBoxIcon.Warning);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currentSampleCount = count;
|
|
|
|
|
|
InitializeDataTable();
|
|
|
|
|
|
InitializeDataGridView();
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化定时器用于模拟寄存器数据读取
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void InitializeTimer()
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
dataTimer = new System.Windows.Forms.Timer
|
|
|
|
|
|
{
|
|
|
|
|
|
Interval = TIMER_INTERVAL
|
|
|
|
|
|
};
|
2025-12-31 09:43:35 +08:00
|
|
|
|
dataTimer.Tick += DataTimer_Tick;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 定时器事件 - 模拟从寄存器读取数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void DataTimer_Tick(object sender, EventArgs e)
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 移除旧的平均值行
|
|
|
|
|
|
RemoveAverageRows();
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 创建新数据行
|
2025-12-31 09:43:35 +08:00
|
|
|
|
DataRow dataRow = sampleDataTable.NewRow();
|
2025-12-31 13:44:33 +08:00
|
|
|
|
dataRow["序号"] = TIME_ROW_LABEL;
|
|
|
|
|
|
|
|
|
|
|
|
// 读取寄存器数据
|
|
|
|
|
|
for (int i = 0; i < currentSampleCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
dataRow[$"试样{i + 1}"] = ReadRegisterData(i);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 不再设置时间列
|
2025-12-31 09:43:35 +08:00
|
|
|
|
sampleDataTable.Rows.Add(dataRow);
|
2025-12-31 13:44:33 +08:00
|
|
|
|
sampleCount++;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
|
|
|
|
|
UpdateDisplay();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 移除平均值行
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void RemoveAverageRows()
|
|
|
|
|
|
{
|
|
|
|
|
|
var avgRows = sampleDataTable.Select($"序号 = '{AVG_ROW_LABEL}'");
|
|
|
|
|
|
foreach (var row in avgRows)
|
|
|
|
|
|
{
|
|
|
|
|
|
sampleDataTable.Rows.Remove(row);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 09:43:35 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 模拟从寄存器读取数据
|
|
|
|
|
|
/// 实际应用中替换为真实的 Modbus 或其他协议读取
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private double ReadRegisterData(int registerAddress)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 模拟数据:30-34 之间的随机值
|
2025-12-31 13:44:33 +08:00
|
|
|
|
return MIN_SAMPLE_VALUE + random.NextDouble() * (MAX_SAMPLE_VALUE - MIN_SAMPLE_VALUE);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 生成模拟测试数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void GenerateMockData()
|
|
|
|
|
|
{
|
|
|
|
|
|
sampleDataTable.Clear();
|
|
|
|
|
|
sampleCount = 0;
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
const int mockDataCount = 1;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
for (int i = 0; i < mockDataCount; i++)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
|
|
|
|
|
DataRow dataRow = sampleDataTable.NewRow();
|
2025-12-31 13:44:33 +08:00
|
|
|
|
dataRow["序号"] = TIME_ROW_LABEL;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 为每个试样生成模拟数据
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 不再设置时间列
|
2025-12-31 09:43:35 +08:00
|
|
|
|
sampleDataTable.Rows.Add(dataRow);
|
|
|
|
|
|
sampleCount++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UpdateDisplay();
|
2025-12-31 13:44:33 +08:00
|
|
|
|
ShowMessage($"已生成 {sampleCount} 条模拟数据", "模拟数据生成");
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 更新界面显示
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void UpdateDisplay()
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
if (sampleDataTable.Rows.Count == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// 计算并添加/更新平均值行
|
2026-01-03 11:11:22 +08:00
|
|
|
|
UpdateAverageRow(null);
|
2025-12-31 13:44:33 +08:00
|
|
|
|
|
|
|
|
|
|
// 刷新界面
|
|
|
|
|
|
RefreshDataGridView();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-01-03 11:11:22 +08:00
|
|
|
|
/// 计算所有试样的总平均值
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// </summary>
|
2026-01-03 11:11:22 +08:00
|
|
|
|
private double CalculateOverallAverage()
|
2025-12-31 13:44:33 +08:00
|
|
|
|
{
|
2026-01-03 11:11:22 +08:00
|
|
|
|
var timeRows = sampleDataTable.AsEnumerable()
|
|
|
|
|
|
.Where(r => r.Field<string>("序号") == TIME_ROW_LABEL);
|
|
|
|
|
|
|
|
|
|
|
|
if (!timeRows.Any())
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
double sum = 0;
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var row in timeRows)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2026-01-03 11:11:22 +08:00
|
|
|
|
for (int i = 1; i <= currentSampleCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sum += row.Field<double>($"试样{i}");
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
2026-01-03 11:11:22 +08:00
|
|
|
|
|
|
|
|
|
|
return count > 0 ? sum / count : 0;
|
2025-12-31 13:44:33 +08:00
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 更新或添加平均值行
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void UpdateAverageRow(double[] averages)
|
|
|
|
|
|
{
|
|
|
|
|
|
var avgRows = sampleDataTable.Select($"序号 = '{AVG_ROW_LABEL}'");
|
|
|
|
|
|
|
2026-01-03 11:11:22 +08:00
|
|
|
|
// 计算总平均值
|
|
|
|
|
|
double overallAvg = CalculateOverallAverage();
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
if (avgRows.Length == 0)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 添加新的平均值行
|
|
|
|
|
|
DataRow avgRow = sampleDataTable.NewRow();
|
|
|
|
|
|
avgRow["序号"] = AVG_ROW_LABEL;
|
2026-01-03 11:11:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 只在第一列显示总平均值
|
|
|
|
|
|
avgRow["试样1"] = overallAvg;
|
|
|
|
|
|
|
|
|
|
|
|
// 其他列设置为空
|
|
|
|
|
|
for (int i = 2; i <= currentSampleCount; i++)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2026-01-03 11:11:22 +08:00
|
|
|
|
avgRow[$"试样{i}"] = DBNull.Value;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
2026-01-03 11:11:22 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
sampleDataTable.Rows.Add(avgRow);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 更新现有平均值行
|
2026-01-03 11:11:22 +08:00
|
|
|
|
avgRows[0]["试样1"] = overallAvg;
|
|
|
|
|
|
|
|
|
|
|
|
// 其他列设置为空
|
|
|
|
|
|
for (int i = 2; i <= currentSampleCount; i++)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2026-01-03 11:11:22 +08:00
|
|
|
|
avgRows[0][$"试样{i}"] = DBNull.Value;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 刷新DataGridView
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void RefreshDataGridView()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dataGridView1.DataSource is DataTable dt)
|
|
|
|
|
|
{
|
|
|
|
|
|
dt.AcceptChanges();
|
|
|
|
|
|
dataGridView1.Refresh();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-31 09:43:35 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 启动数据采集
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void StartDataCollection()
|
|
|
|
|
|
{
|
|
|
|
|
|
dataTimer.Start();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 停止数据采集
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void StopDataCollection()
|
|
|
|
|
|
{
|
|
|
|
|
|
dataTimer.Stop();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 导出数据到 Excel (.xlsx)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void ExportToExcel(string filePath)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
IWorkbook workbook = CreateWorkbook(filePath);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
ISheet sheet = workbook.CreateSheet("液体吸收测试报表");
|
|
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 创建样式
|
|
|
|
|
|
var styles = CreateExcelStyles(workbook);
|
|
|
|
|
|
|
2025-12-31 09:43:35 +08:00
|
|
|
|
// 创建标题行
|
2025-12-31 13:44:33 +08:00
|
|
|
|
CreateHeaderRow(sheet, styles.headerStyle);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
|
|
|
|
|
// 填充数据
|
2025-12-31 13:44:33 +08:00
|
|
|
|
FillDataRows(sheet, styles.dataStyle);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
|
|
|
|
|
// 添加平均值行
|
2025-12-31 13:44:33 +08:00
|
|
|
|
AddAverageRow(sheet, styles.avgStyle);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
|
|
|
|
|
// 自动调整列宽
|
2025-12-31 13:44:33 +08:00
|
|
|
|
AutoSizeColumns(sheet, 7);
|
|
|
|
|
|
|
|
|
|
|
|
// 保存文件
|
|
|
|
|
|
SaveWorkbook(workbook, filePath);
|
|
|
|
|
|
|
|
|
|
|
|
ShowMessage($"数据已成功导出到:{filePath}", "导出成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
ShowMessage($"导出失败:{ex.Message}", "错误", MessageBoxIcon.Error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建工作簿
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private IWorkbook CreateWorkbook(string filePath)
|
|
|
|
|
|
{
|
|
|
|
|
|
return filePath.EndsWith(".xlsx")
|
|
|
|
|
|
? (IWorkbook)new XSSFWorkbook()
|
|
|
|
|
|
: new HSSFWorkbook();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建Excel样式
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建标题行
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 填充数据行
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
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++)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
row.CreateCell(i).SetCellValue(Convert.ToDouble(dataRow[$"试样{i}"]));
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
2025-12-31 13:44:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加平均值行
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void AddAverageRow(ISheet sheet, ICellStyle avgStyle)
|
|
|
|
|
|
{
|
|
|
|
|
|
var dataRows = sampleDataTable.AsEnumerable()
|
|
|
|
|
|
.Where(r => r.Field<string>("序号") != AVG_ROW_LABEL);
|
|
|
|
|
|
|
|
|
|
|
|
if (!dataRows.Any())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
int rowIndex = sheet.LastRowNum + 1;
|
|
|
|
|
|
IRow avgRow = sheet.CreateRow(rowIndex);
|
2026-01-03 11:11:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 序号列
|
|
|
|
|
|
ICell labelCell = avgRow.CreateCell(0);
|
|
|
|
|
|
labelCell.SetCellValue(AVG_ROW_LABEL);
|
|
|
|
|
|
labelCell.CellStyle = avgStyle;
|
2025-12-31 13:44:33 +08:00
|
|
|
|
|
2026-01-03 11:11:22 +08:00
|
|
|
|
// 计算总平均值
|
|
|
|
|
|
double overallAvg = CalculateOverallAverage();
|
|
|
|
|
|
|
|
|
|
|
|
// 在第一个试样列显示总平均值
|
|
|
|
|
|
ICell avgCell = avgRow.CreateCell(1);
|
|
|
|
|
|
avgCell.SetCellValue(overallAvg);
|
|
|
|
|
|
avgCell.CellStyle = avgStyle;
|
|
|
|
|
|
|
|
|
|
|
|
// 合并所有试样列
|
|
|
|
|
|
if (currentSampleCount > 1)
|
2025-12-31 13:44:33 +08:00
|
|
|
|
{
|
2026-01-03 11:11:22 +08:00
|
|
|
|
sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, currentSampleCount));
|
2025-12-31 13:44:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 自动调整列宽
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void AutoSizeColumns(ISheet sheet, int columnCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i <= currentSampleCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sheet.AutoSizeColumn(i);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
2025-12-31 13:44:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 保存工作簿
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void SaveWorkbook(IWorkbook workbook, string filePath)
|
|
|
|
|
|
{
|
|
|
|
|
|
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
workbook.Write(fs);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 生成报表(带格式的 Excel)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void GenerateReport(string filePath)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
IWorkbook workbook = new XSSFWorkbook();
|
|
|
|
|
|
ISheet sheet = workbook.CreateSheet("液体吸收测试报表");
|
|
|
|
|
|
|
|
|
|
|
|
// 创建样式
|
2025-12-31 13:44:33 +08:00
|
|
|
|
var styles = CreateReportStyles(workbook);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 创建标题
|
|
|
|
|
|
CreateReportTitle(sheet, styles.titleStyle);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 创建表头
|
|
|
|
|
|
CreateReportHeader(sheet, styles.headerStyle);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 创建数据行
|
|
|
|
|
|
CreateReportDataRows(sheet, styles.dataStyle, styles.yellowStyle);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 设置列宽
|
|
|
|
|
|
SetReportColumnWidths(sheet);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
// 保存文件
|
|
|
|
|
|
SaveWorkbook(workbook, filePath);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
ShowMessage($"报表已成功生成:{filePath}", "生成成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
ShowMessage($"生成报表失败:{ex.Message}", "错误", MessageBoxIcon.Error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建报表样式
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置单元格边框
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void SetBorders(ICellStyle style)
|
|
|
|
|
|
{
|
|
|
|
|
|
style.BorderBottom = NPOIBorderStyle.Thin;
|
|
|
|
|
|
style.BorderTop = NPOIBorderStyle.Thin;
|
|
|
|
|
|
style.BorderLeft = NPOIBorderStyle.Thin;
|
|
|
|
|
|
style.BorderRight = NPOIBorderStyle.Thin;
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <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));
|
|
|
|
|
|
}
|
2025-12-31 09:43:35 +08:00
|
|
|
|
|
2025-12-31 13:44:33 +08:00
|
|
|
|
/// <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;
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
2025-12-31 13:44:33 +08:00
|
|
|
|
|
|
|
|
|
|
// 不再添加"根据标准"列
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建报表数据行
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void CreateReportDataRows(ISheet sheet, ICellStyle dataStyle, ICellStyle yellowStyle)
|
|
|
|
|
|
{
|
|
|
|
|
|
int rowIndex = 3;
|
|
|
|
|
|
|
2026-01-03 11:11:22 +08:00
|
|
|
|
// 从数据表中获取时间行数据
|
|
|
|
|
|
var timeRows = sampleDataTable.AsEnumerable()
|
|
|
|
|
|
.Where(r => r.Field<string>("序号") == TIME_ROW_LABEL);
|
2025-12-31 13:44:33 +08:00
|
|
|
|
|
2026-01-03 11:11:22 +08:00
|
|
|
|
if (timeRows.Any())
|
2025-12-31 13:44:33 +08:00
|
|
|
|
{
|
2026-01-03 11:11:22 +08:00
|
|
|
|
foreach (var dataRow in timeRows)
|
|
|
|
|
|
{
|
|
|
|
|
|
IRow timeRow = sheet.CreateRow(rowIndex++);
|
|
|
|
|
|
ICell labelCell = timeRow.CreateCell(0);
|
|
|
|
|
|
labelCell.SetCellValue(TIME_ROW_LABEL);
|
|
|
|
|
|
labelCell.CellStyle = dataStyle;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= currentSampleCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
ICell cell = timeRow.CreateCell(i);
|
|
|
|
|
|
cell.SetCellValue(dataRow.Field<double>($"试样{i}"));
|
|
|
|
|
|
cell.CellStyle = yellowStyle;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-31 13:44:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 平均时间行
|
|
|
|
|
|
IRow avgRow = sheet.CreateRow(rowIndex);
|
2026-01-03 11:11:22 +08:00
|
|
|
|
ICell avgLabelCell = avgRow.CreateCell(0);
|
|
|
|
|
|
avgLabelCell.SetCellValue(AVG_ROW_LABEL);
|
|
|
|
|
|
avgLabelCell.CellStyle = dataStyle;
|
2025-12-31 13:44:33 +08:00
|
|
|
|
|
2026-01-03 11:11:22 +08:00
|
|
|
|
// 计算并显示总平均值
|
|
|
|
|
|
double overallAvg = CalculateOverallAverage();
|
2025-12-31 13:44:33 +08:00
|
|
|
|
ICell avgCell = avgRow.CreateCell(1);
|
2026-01-03 11:11:22 +08:00
|
|
|
|
avgCell.SetCellValue(overallAvg);
|
2025-12-31 13:44:33 +08:00
|
|
|
|
avgCell.CellStyle = yellowStyle;
|
|
|
|
|
|
|
2026-01-03 11:11:22 +08:00
|
|
|
|
// 合并所有试样列
|
|
|
|
|
|
if (currentSampleCount > 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, currentSampleCount));
|
|
|
|
|
|
}
|
2025-12-31 13:44:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置报表列宽
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void SetReportColumnWidths(ISheet sheet)
|
|
|
|
|
|
{
|
|
|
|
|
|
sheet.SetColumnWidth(0, 20 * 256);
|
|
|
|
|
|
for (int i = 1; i <= currentSampleCount; i++)
|
2025-12-31 09:43:35 +08:00
|
|
|
|
{
|
2025-12-31 13:44:33 +08:00
|
|
|
|
sheet.SetColumnWidth(i, 15 * 256);
|
2025-12-31 09:43:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 清空数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void ClearData()
|
|
|
|
|
|
{
|
|
|
|
|
|
sampleDataTable.Clear();
|
|
|
|
|
|
sampleCount = 0;
|
|
|
|
|
|
UpdateDisplay();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|