Files
NonWovenFabric/WindowsFormsApp6/Form2.cs
GukSang.Jin 75504b6870 更新
2026-01-05 18:31:26 +08:00

907 lines
32 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 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_SOAK_TIME = "浸润时间";
private const string ROW_HANG_TIME = "悬挂时间";
private const string ROW_RUN_SPEED = "运行速度";
private const string ROW_AVG_ABSORPTION = "液体吸收量平均值(%)";
private const string ROW_MAX_ABSORPTION = "液体吸收量最大值(%)";
private const string ROW_STD_DEVIATION = "标准偏差";
#endregion
#region
private System.Windows.Forms.Timer dataTimer;
private System.Windows.Forms.Timer clockTimer;
private DataTable sampleDataTable;
private int sampleCount = 0;
private int currentSampleCount = 5; // 当前试样数量,可动态调整
private readonly Random random = new Random();
#endregion
public Form2()
{
InitializeComponent();
InitializeDataTable();
InitializeTimer();
InitializeDataGridView();
InitializeEventHandlers();
}
/// <summary>
/// 初始化 DataGridView 列
/// </summary>
private void InitializeDataGridView()
{
dataGridView1.SuspendLayout();
try
{
dataGridView1.Columns.Clear();
// 创建共享样式
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
{
Name = "序号",
HeaderText = "序号",
DataPropertyName = "序号",
Width = 180,
ReadOnly = true,
DefaultCellStyle = centerStyle
});
// 根据当前试样数量动态添加列
for (int i = 1; i <= currentSampleCount; i++)
{
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
{
Name = $"试样{i}",
HeaderText = $"试样{i}",
DataPropertyName = $"试样{i}",
Width = 150,
ReadOnly = true,
DefaultCellStyle = yellowCenterStyle
});
}
// 绑定数据源
dataGridView1.DataSource = sampleDataTable;
dataGridView1.CellFormatting += DataGridView1_CellFormatting;
}
finally
{
dataGridView1.ResumeLayout();
}
}
/// <summary>
/// 单元格格式化事件
/// </summary>
private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.RowIndex < 0) return;
// 格式化数值显示为2位小数
if (e.Value != null && e.Value != DBNull.Value)
{
if (double.TryParse(e.Value.ToString(), out double numValue))
{
e.Value = numValue.ToString("F2");
e.FormattingApplied = true;
}
}
}
/// <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;
clockTimer = new System.Windows.Forms.Timer
{
Interval = TIMER_INTERVAL
};
clockTimer.Tick += (s, e) => label2.Text = DateTime.Now.ToString(DATE_TIME_FORMAT);
clockTimer.Start();
}
/// <summary>
/// 连接设备按钮点击事件
/// </summary>
private void Button1_Click(object sender, EventArgs e)
{
if (dataTimer.Enabled)
{
StopDataCollection();
UpdateButtonState(button1, "🔗 连接设备", Color.FromArgb(46, 204, 113));
ShowMessage("已停止数据采集");
}
else
{
StartDataCollection();
UpdateButtonState(button1, "⏸️ 停止采集", Color.FromArgb(231, 76, 60));
ShowMessage("开始数据采集");
}
}
/// <summary>
/// 打印按钮点击事件
/// </summary>
private void Button2_Click(object sender, EventArgs e)
{
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>
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));
// 根据当前试样数量动态添加列
for (int i = 1; i <= currentSampleCount; i++)
{
sampleDataTable.Columns.Add($"试样{i}", typeof(object));
}
}
/// <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>
private void InitializeTimer()
{
dataTimer = new System.Windows.Forms.Timer
{
Interval = TIMER_INTERVAL
};
dataTimer.Tick += DataTimer_Tick;
}
/// <summary>
/// 定时器事件 - 模拟从寄存器读取数据
/// </summary>
private void DataTimer_Tick(object sender, EventArgs e)
{
// 清除旧的计算行
RemoveCalculatedRows();
// 读取初始重量和浸润后重量
double[] initialWeights = new double[currentSampleCount];
double[] afterWeights = new double[currentSampleCount];
for (int i = 0; i < currentSampleCount; i++)
{
initialWeights[i] = ReadRegisterData(i * 2); // 初始重量
afterWeights[i] = ReadRegisterData(i * 2 + 1); // 浸润后重量
}
sampleCount++;
// 更新显示
UpdateDisplay(initialWeights, afterWeights);
}
/// <summary>
/// 移除计算行
/// </summary>
private void RemoveCalculatedRows()
{
var rowsToRemove = sampleDataTable.AsEnumerable()
.Where(r => r.Field<string>("序号") == ROW_ABSORPTION ||
r.Field<string>("序号") == ROW_SOAK_TIME ||
r.Field<string>("序号") == ROW_HANG_TIME ||
r.Field<string>("序号") == ROW_RUN_SPEED ||
r.Field<string>("序号") == ROW_AVG_ABSORPTION ||
r.Field<string>("序号") == ROW_MAX_ABSORPTION ||
r.Field<string>("序号") == ROW_STD_DEVIATION ||
r.Field<string>("序号") == "液体吸收量平均值(%)试样1-5" ||
r.Field<string>("序号") == "液体吸收量平均值(%)试样6-10" ||
r.Field<string>("序号") == "液体吸收量最大值(%)试样1-5" ||
r.Field<string>("序号") == "液体吸收量最大值(%)试样6-10" ||
r.Field<string>("序号") == "标准偏差试样1-5" ||
r.Field<string>("序号") == "标准偏差试样6-10")
.ToList();
foreach (var row in rowsToRemove)
{
sampleDataTable.Rows.Remove(row);
}
}
/// <summary>
/// 模拟从寄存器读取数据
/// </summary>
private double ReadRegisterData(int registerAddress)
{
return MIN_WEIGHT + random.NextDouble() * (MAX_WEIGHT - MIN_WEIGHT);
}
/// <summary>
/// 生成模拟测试数据(精确模拟真实测试场景)
/// </summary>
public void GenerateMockData()
{
sampleDataTable.Clear();
sampleCount = 0;
// 生成模拟数据
double[] initialWeights = new double[currentSampleCount];
double[] afterWeights = new double[currentSampleCount];
// 设置基准值,使数据更真实
double baseInitialWeight = 15.0; // 基准初始重量
double baseAbsorptionRate = 0.35; // 基准吸收率 35%
for (int i = 0; i < currentSampleCount; i++)
{
// 初始重量:在基准值附近波动 ±3g
initialWeights[i] = Math.Round(baseInitialWeight + (random.NextDouble() - 0.5) * 6.0, 2);
// 吸收率:在基准吸收率附近波动 ±10%
double absorptionRate = baseAbsorptionRate + (random.NextDouble() - 0.5) * 0.2;
// 浸润后重量 = 初始重量 × (1 + 吸收率)
afterWeights[i] = Math.Round(initialWeights[i] * (1 + absorptionRate), 2);
}
sampleCount = 1;
UpdateDisplay(initialWeights, afterWeights);
// 计算并显示统计信息
double[] absorptions = new double[currentSampleCount];
for (int i = 0; i < currentSampleCount; i++)
{
absorptions[i] = ((afterWeights[i] - initialWeights[i]) / initialWeights[i]) * 100;
}
double avgAbsorption = absorptions.Average();
double stdDev = CalculateStandardDeviation(absorptions);
double maxAbsorption = absorptions.Max();
double minAbsorption = absorptions.Min();
string message = $"已生成 {currentSampleCount} 个试样的模拟数据\n\n" +
$"液体吸收量统计:\n" +
$"平均值:{avgAbsorption:F2}%\n" +
$"标准偏差:{stdDev:F2}%\n" +
$"最大值:{maxAbsorption:F2}%\n" +
$"最小值:{minAbsorption:F2}%";
ShowMessage(message, "模拟数据生成");
}
/// <summary>
/// 更新界面显示
/// </summary>
private void UpdateDisplay(double[] initialWeights, double[] afterWeights)
{
sampleDataTable.Clear();
int count = Math.Min(initialWeights.Length, currentSampleCount);
// 1. 初始重量行
DataRow initialRow = sampleDataTable.NewRow();
initialRow["序号"] = ROW_INITIAL_WEIGHT;
for (int i = 0; i < count; i++)
{
initialRow[$"试样{i + 1}"] = initialWeights[i];
}
sampleDataTable.Rows.Add(initialRow);
// 2. 浸润后重量行
DataRow afterRow = sampleDataTable.NewRow();
afterRow["序号"] = ROW_AFTER_WEIGHT;
for (int i = 0; i < count; i++)
{
afterRow[$"试样{i + 1}"] = afterWeights[i];
}
sampleDataTable.Rows.Add(afterRow);
// 3. 液体吸收量行 (%)
DataRow absorptionRow = sampleDataTable.NewRow();
absorptionRow["序号"] = ROW_ABSORPTION;
double[] absorptions = new double[count];
for (int i = 0; i < count; i++)
{
absorptions[i] = ((afterWeights[i] - initialWeights[i]) / initialWeights[i]) * 100;
absorptionRow[$"试样{i + 1}"] = absorptions[i];
}
sampleDataTable.Rows.Add(absorptionRow);
// 4. 浸润时间行
DataRow soakTimeRow = sampleDataTable.NewRow();
soakTimeRow["序号"] = ROW_SOAK_TIME;
// 为每个试样生成浸润时间基准60s波动±10s
for (int i = 1; i <= count; i++)
{
int soakTime = 60 + random.Next(-10, 11); // 50-70秒
soakTimeRow[$"试样{i}"] = $"{soakTime}s";
}
sampleDataTable.Rows.Add(soakTimeRow);
// 5. 悬挂时间行
DataRow hangTimeRow = sampleDataTable.NewRow();
hangTimeRow["序号"] = ROW_HANG_TIME;
// 为每个试样生成悬挂时间基准30s波动±5s
for (int i = 1; i <= count; i++)
{
int hangTime = 30 + random.Next(-5, 6); // 25-35秒
hangTimeRow[$"试样{i}"] = $"{hangTime}s";
}
sampleDataTable.Rows.Add(hangTimeRow);
// 6. 运行速度行
DataRow runSpeedRow = sampleDataTable.NewRow();
runSpeedRow["序号"] = ROW_RUN_SPEED;
// 为每个试样生成运行速度基准100mm/min波动±10mm/min
for (int i = 1; i <= count; i++)
{
int runSpeed = 100 + random.Next(-10, 11); // 90-110 mm/min
runSpeedRow[$"试样{i}"] = $"{runSpeed}mm/min";
}
sampleDataTable.Rows.Add(runSpeedRow);
// 7. 液体吸收量平均值行试样1-5
DataRow avgRow1 = sampleDataTable.NewRow();
avgRow1["序号"] = "液体吸收量平均值(%)试样1-5";
// 计算试样1-5的平均值
int group1Count = Math.Min(5, count);
if (group1Count > 0)
{
double avgAbsorption1 = absorptions.Take(group1Count).Average();
avgRow1["试样1"] = avgAbsorption1;
}
// 试样2-5列为空只设置到第5列或count取较小值
int maxCol1 = Math.Min(5, count);
for (int i = 2; i <= maxCol1; i++)
{
avgRow1[$"试样{i}"] = DBNull.Value;
}
// 如果有试样6-10这些列也设置为空
for (int i = 6; i <= count; i++)
{
avgRow1[$"试样{i}"] = DBNull.Value;
}
sampleDataTable.Rows.Add(avgRow1);
// 8. 液体吸收量平均值行试样6-10- 仅当试样数量>5时添加
if (count > 5)
{
DataRow avgRow2 = sampleDataTable.NewRow();
avgRow2["序号"] = "液体吸收量平均值(%)试样6-10";
// 计算试样6-10的平均值
int group2Count = Math.Min(5, count - 5);
if (group2Count > 0)
{
double avgAbsorption2 = absorptions.Skip(5).Take(group2Count).Average();
avgRow2["试样6"] = avgAbsorption2;
}
// 其他列为空
for (int i = 1; i <= 5; i++)
{
avgRow2[$"试样{i}"] = DBNull.Value;
}
for (int i = 7; i <= count; i++)
{
avgRow2[$"试样{i}"] = DBNull.Value;
}
sampleDataTable.Rows.Add(avgRow2);
}
// 9. 液体吸收量最大值行试样1-5
DataRow maxRow1 = sampleDataTable.NewRow();
maxRow1["序号"] = "液体吸收量最大值(%)试样1-5";
// 计算试样1-5的最大值
if (group1Count > 0)
{
double maxAbsorption1 = absorptions.Take(group1Count).Max();
maxRow1["试样1"] = maxAbsorption1;
}
// 试样2-5列为空
for (int i = 2; i <= maxCol1; i++)
{
maxRow1[$"试样{i}"] = DBNull.Value;
}
// 如果有试样6-10这些列也设置为空
for (int i = 6; i <= count; i++)
{
maxRow1[$"试样{i}"] = DBNull.Value;
}
sampleDataTable.Rows.Add(maxRow1);
// 10. 液体吸收量最大值行试样6-10- 仅当试样数量>5时添加
if (count > 5)
{
DataRow maxRow2 = sampleDataTable.NewRow();
maxRow2["序号"] = "液体吸收量最大值(%)试样6-10";
// 计算试样6-10的最大值
int group2Count = Math.Min(5, count - 5);
if (group2Count > 0)
{
double maxAbsorption2 = absorptions.Skip(5).Take(group2Count).Max();
maxRow2["试样6"] = maxAbsorption2;
}
// 其他列为空
for (int i = 1; i <= 5; i++)
{
maxRow2[$"试样{i}"] = DBNull.Value;
}
for (int i = 7; i <= count; i++)
{
maxRow2[$"试样{i}"] = DBNull.Value;
}
sampleDataTable.Rows.Add(maxRow2);
}
// 11. 标准偏差行试样1-5
DataRow stdDevRow1 = sampleDataTable.NewRow();
stdDevRow1["序号"] = "标准偏差试样1-5";
// 计算试样1-5的标准偏差
if (group1Count > 1)
{
double stdDev1 = CalculateStandardDeviation(absorptions.Take(group1Count).ToArray());
stdDevRow1["试样1"] = stdDev1;
}
// 试样2-5列为空
for (int i = 2; i <= maxCol1; i++)
{
stdDevRow1[$"试样{i}"] = DBNull.Value;
}
// 如果有试样6-10这些列也设置为空
for (int i = 6; i <= count; i++)
{
stdDevRow1[$"试样{i}"] = DBNull.Value;
}
sampleDataTable.Rows.Add(stdDevRow1);
// 12. 标准偏差行试样6-10- 仅当试样数量>5时添加
if (count > 5)
{
DataRow stdDevRow2 = sampleDataTable.NewRow();
stdDevRow2["序号"] = "标准偏差试样6-10";
// 计算试样6-10的标准偏差
int group2Count = Math.Min(5, count - 5);
if (group2Count > 1)
{
double stdDev2 = CalculateStandardDeviation(absorptions.Skip(5).Take(group2Count).ToArray());
stdDevRow2["试样6"] = stdDev2;
}
// 其他列为空
for (int i = 1; i <= 5; i++)
{
stdDevRow2[$"试样{i}"] = DBNull.Value;
}
for (int i = 7; i <= count; i++)
{
stdDevRow2[$"试样{i}"] = DBNull.Value;
}
sampleDataTable.Rows.Add(stdDevRow2);
}
// 刷新界面
RefreshDataGridView();
}
/// <summary>
/// 计算标准偏差样本标准偏差n-1
/// </summary>
private double CalculateStandardDeviation(double[] values)
{
if (values == null || values.Length <= 1) return 0;
double avg = values.Average();
double sumOfSquares = values.Sum(val => Math.Pow(val - avg, 2));
// 使用样本标准偏差公式:除以 (n-1)
return Math.Sqrt(sumOfSquares / (values.Length - 1));
}
/// <summary>
/// 刷新DataGridView
/// </summary>
private void RefreshDataGridView()
{
if (dataGridView1.DataSource is DataTable dt)
{
dt.AcceptChanges();
dataGridView1.Refresh();
}
}
/// <summary>
/// 启动数据采集
/// </summary>
public void StartDataCollection()
{
dataTimer.Start();
}
/// <summary>
/// 停止数据采集
/// </summary>
public void StopDataCollection()
{
dataTimer.Stop();
}
/// <summary>
/// 生成报表(带格式的 Excel
/// </summary>
public void GenerateReport(string filePath)
{
try
{
IWorkbook workbook = new XSSFWorkbook();
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();
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);
}
/// <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)
{
string rowName = dataRow["序号"].ToString();
// 处理试样1-5分组行的合并单元格
if (rowName == "液体吸收量平均值(%)试样1-5" ||
rowName == "液体吸收量最大值(%)试样1-5" ||
rowName == "标准偏差试样1-5")
{
IRow row = sheet.CreateRow(rowIndex++);
// 序号列
ICell nameCell = row.CreateCell(0);
nameCell.SetCellValue(rowName);
nameCell.CellStyle = dataStyle;
// 获取试样1的值
var value = dataRow["试样1"];
if (value != null && value != DBNull.Value)
{
ICell cell = row.CreateCell(1);
cell.SetCellValue(Convert.ToDouble(value));
cell.CellStyle = yellowStyle;
// 合并试样1-5列
int group1Count = Math.Min(5, currentSampleCount);
if (group1Count > 1)
{
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, 1, group1Count));
}
}
}
// 处理试样6-10分组行的合并单元格
else if (rowName == "液体吸收量平均值(%)试样6-10" ||
rowName == "液体吸收量最大值(%)试样6-10" ||
rowName == "标准偏差试样6-10")
{
IRow row = sheet.CreateRow(rowIndex++);
// 序号列
ICell nameCell = row.CreateCell(0);
nameCell.SetCellValue(rowName);
nameCell.CellStyle = dataStyle;
// 获取试样6的值
var value = dataRow["试样6"];
if (value != null && value != DBNull.Value)
{
ICell cell = row.CreateCell(6);
cell.SetCellValue(Convert.ToDouble(value));
cell.CellStyle = yellowStyle;
// 合并试样6-10列
int group2Count = Math.Min(5, currentSampleCount - 5);
if (group2Count > 1)
{
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, 6, 5 + group2Count));
}
}
}
else
{
// 普通行处理
IRow row = sheet.CreateRow(rowIndex++);
// 序号列
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;
}
}
}
}
/// <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))
{
workbook.Write(fs);
}
}
/// <summary>
/// 清空数据
/// </summary>
public void ClearData()
{
sampleDataTable.Clear();
sampleCount = 0;
RefreshDataGridView();
}
}
}