更新
This commit is contained in:
@@ -321,14 +321,11 @@ namespace WindowsFormsApp6
|
||||
/// </summary>
|
||||
private void RemoveAverageRows()
|
||||
{
|
||||
var avgRows1 = sampleDataTable.Select($"序号 = '平均时间(s)试样1-5'");
|
||||
var avgRows2 = sampleDataTable.Select($"序号 = '平均时间(s)试样6-10'");
|
||||
|
||||
foreach (var row in avgRows1)
|
||||
{
|
||||
sampleDataTable.Rows.Remove(row);
|
||||
}
|
||||
foreach (var row in avgRows2)
|
||||
var avgRows = sampleDataTable.AsEnumerable()
|
||||
.Where(row => IsAverageTimeRow(row.Field<string>("序号")))
|
||||
.ToList();
|
||||
|
||||
foreach (var row in avgRows)
|
||||
{
|
||||
sampleDataTable.Rows.Remove(row);
|
||||
}
|
||||
@@ -422,14 +419,11 @@ namespace WindowsFormsApp6
|
||||
private void UpdateAverageRow(double[] averages)
|
||||
{
|
||||
// 移除所有平均值行
|
||||
var avgRows1 = sampleDataTable.Select($"序号 = '平均时间(s)试样1-5'");
|
||||
var avgRows2 = sampleDataTable.Select($"序号 = '平均时间(s)试样6-10'");
|
||||
|
||||
foreach (var row in avgRows1)
|
||||
{
|
||||
sampleDataTable.Rows.Remove(row);
|
||||
}
|
||||
foreach (var row in avgRows2)
|
||||
var avgRows = sampleDataTable.AsEnumerable()
|
||||
.Where(row => IsAverageTimeRow(row.Field<string>("序号")))
|
||||
.ToList();
|
||||
|
||||
foreach (var row in avgRows)
|
||||
{
|
||||
sampleDataTable.Rows.Remove(row);
|
||||
}
|
||||
@@ -441,78 +435,61 @@ namespace WindowsFormsApp6
|
||||
if (!timeRows.Any())
|
||||
return;
|
||||
|
||||
// 计算试样1-5的平均值
|
||||
int group1Count = Math.Min(5, currentSampleCount);
|
||||
if (group1Count > 0)
|
||||
int groupCount = (int)Math.Ceiling(currentSampleCount / 5.0);
|
||||
for (int groupIndex = 0; groupIndex < groupCount; groupIndex++)
|
||||
{
|
||||
double sum1 = 0;
|
||||
int count1 = 0;
|
||||
|
||||
int startSample = groupIndex * 5 + 1;
|
||||
int endSample = Math.Min(startSample + 4, currentSampleCount);
|
||||
double sum = 0;
|
||||
int count = 0;
|
||||
|
||||
foreach (var row in timeRows)
|
||||
{
|
||||
for (int i = 1; i <= group1Count; i++)
|
||||
for (int i = startSample; i <= endSample; i++)
|
||||
{
|
||||
sum1 += row.Field<double>($"试样{i}");
|
||||
count1++;
|
||||
if (TryGetDouble(row[$"试样{i}"], out double value))
|
||||
{
|
||||
sum += value;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double avg1 = count1 > 0 ? sum1 / count1 : 0;
|
||||
|
||||
// 添加试样1-5平均值行 - 只在第一列显示平均值
|
||||
DataRow avgRow1 = sampleDataTable.NewRow();
|
||||
avgRow1["序号"] = "平均时间(s)试样1-5";
|
||||
|
||||
// 只在试样1列显示平均值
|
||||
avgRow1["试样1"] = avg1;
|
||||
|
||||
// 其他列设置为DBNull(不显示)
|
||||
for (int i = 2; i <= currentSampleCount; i++)
|
||||
|
||||
DataRow avgRow = sampleDataTable.NewRow();
|
||||
avgRow["序号"] = $"平均时间(s)试样{startSample}-{endSample}";
|
||||
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
avgRow1[$"试样{i}"] = DBNull.Value;
|
||||
avgRow[$"试样{i}"] = i == startSample && count > 0 ? (object)(sum / count) : DBNull.Value;
|
||||
}
|
||||
|
||||
sampleDataTable.Rows.Add(avgRow1);
|
||||
|
||||
sampleDataTable.Rows.Add(avgRow);
|
||||
}
|
||||
|
||||
// 计算试样6-10的平均值(仅当试样数量>5时)
|
||||
if (currentSampleCount > 5)
|
||||
}
|
||||
|
||||
private bool IsAverageTimeRow(string rowName)
|
||||
{
|
||||
return !string.IsNullOrEmpty(rowName) && rowName.StartsWith("平均时间(s)");
|
||||
}
|
||||
|
||||
private bool TryGetDouble(object value, out double result)
|
||||
{
|
||||
result = 0;
|
||||
if (value == null || value == DBNull.Value)
|
||||
{
|
||||
int group2Count = Math.Min(5, currentSampleCount - 5);
|
||||
double sum2 = 0;
|
||||
int count2 = 0;
|
||||
|
||||
foreach (var row in timeRows)
|
||||
{
|
||||
for (int i = 6; i <= 5 + group2Count; i++)
|
||||
{
|
||||
sum2 += row.Field<double>($"试样{i}");
|
||||
count2++;
|
||||
}
|
||||
}
|
||||
|
||||
double avg2 = count2 > 0 ? sum2 / count2 : 0;
|
||||
|
||||
// 添加试样6-10平均值行 - 只在第6列显示平均值
|
||||
DataRow avgRow2 = sampleDataTable.NewRow();
|
||||
avgRow2["序号"] = "平均时间(s)试样6-10";
|
||||
|
||||
// 前5列为DBNull(不显示)
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
avgRow2[$"试样{i}"] = DBNull.Value;
|
||||
}
|
||||
|
||||
// 只在试样6列显示平均值
|
||||
avgRow2["试样6"] = avg2;
|
||||
|
||||
// 其他列为DBNull(不显示)
|
||||
for (int i = 7; i <= currentSampleCount; i++)
|
||||
{
|
||||
avgRow2[$"试样{i}"] = DBNull.Value;
|
||||
}
|
||||
|
||||
sampleDataTable.Rows.Add(avgRow2);
|
||||
return false;
|
||||
}
|
||||
|
||||
return double.TryParse(value.ToString(), out result) &&
|
||||
!double.IsNaN(result) &&
|
||||
!double.IsInfinity(result);
|
||||
}
|
||||
|
||||
private IEnumerable<(int Start, int End)> GetSampleGroups(int sampleCount)
|
||||
{
|
||||
for (int start = 1; start <= sampleCount; start += 5)
|
||||
{
|
||||
yield return (start, Math.Min(start + 4, sampleCount));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,6 +572,8 @@ namespace WindowsFormsApp6
|
||||
/// </summary>
|
||||
private (ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle avgStyle) CreateExcelStyles(IWorkbook workbook)
|
||||
{
|
||||
short numberFormat = workbook.CreateDataFormat().GetFormat("0.00");
|
||||
|
||||
// 标题样式
|
||||
ICellStyle headerStyle = workbook.CreateCellStyle();
|
||||
headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
|
||||
@@ -605,11 +584,13 @@ namespace WindowsFormsApp6
|
||||
|
||||
// 数据样式
|
||||
ICellStyle dataStyle = workbook.CreateCellStyle();
|
||||
dataStyle.DataFormat = numberFormat;
|
||||
|
||||
// 平均值样式
|
||||
ICellStyle avgStyle = workbook.CreateCellStyle();
|
||||
avgStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
|
||||
avgStyle.FillPattern = FillPattern.SolidForeground;
|
||||
avgStyle.DataFormat = numberFormat;
|
||||
|
||||
return (headerStyle, dataStyle, avgStyle);
|
||||
}
|
||||
@@ -643,7 +624,7 @@ namespace WindowsFormsApp6
|
||||
int rowIndex = 1;
|
||||
foreach (DataRow dataRow in sampleDataTable.Rows)
|
||||
{
|
||||
if (dataRow["序号"].ToString() == AVG_ROW_LABEL)
|
||||
if (IsAverageTimeRow(dataRow["序号"].ToString()))
|
||||
continue;
|
||||
|
||||
IRow row = sheet.CreateRow(rowIndex++);
|
||||
@@ -662,81 +643,53 @@ namespace WindowsFormsApp6
|
||||
private void AddAverageRow(ISheet sheet, ICellStyle avgStyle)
|
||||
{
|
||||
var dataRows = sampleDataTable.AsEnumerable()
|
||||
.Where(r => r.Field<string>("序号") != "平均时间(s)试样1-5" &&
|
||||
r.Field<string>("序号") != "平均时间(s)试样6-10");
|
||||
.Where(r => !IsAverageTimeRow(r.Field<string>("序号")))
|
||||
.ToList();
|
||||
|
||||
if (!dataRows.Any())
|
||||
return;
|
||||
|
||||
int rowIndex = sheet.LastRowNum + 1;
|
||||
|
||||
// 计算试样1-5的平均值
|
||||
int group1Count = Math.Min(5, currentSampleCount);
|
||||
if (group1Count > 0)
|
||||
|
||||
foreach (var group in GetSampleGroups(currentSampleCount))
|
||||
{
|
||||
double sum1 = 0;
|
||||
int count1 = 0;
|
||||
|
||||
foreach (var row in dataRows)
|
||||
double sum = 0;
|
||||
int count = 0;
|
||||
|
||||
foreach (var dataRow in dataRows)
|
||||
{
|
||||
for (int i = 1; i <= group1Count; i++)
|
||||
for (int i = group.Start; i <= group.End; i++)
|
||||
{
|
||||
sum1 += row.Field<double>($"试样{i}");
|
||||
count1++;
|
||||
if (TryGetDouble(dataRow[$"试样{i}"], out double value))
|
||||
{
|
||||
sum += value;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double avg1 = count1 > 0 ? sum1 / count1 : 0;
|
||||
|
||||
// 添加试样1-5平均值行
|
||||
IRow avgRow1 = sheet.CreateRow(rowIndex++);
|
||||
ICell labelCell1 = avgRow1.CreateCell(0);
|
||||
labelCell1.SetCellValue("平均时间(s)试样1-5");
|
||||
labelCell1.CellStyle = avgStyle;
|
||||
|
||||
ICell avgCell1 = avgRow1.CreateCell(1);
|
||||
avgCell1.SetCellValue(avg1);
|
||||
avgCell1.CellStyle = avgStyle;
|
||||
|
||||
// 合并试样1-5列
|
||||
if (group1Count > 1)
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, 1, group1Count));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 计算试样6-10的平均值(仅当试样数量>5时)
|
||||
if (currentSampleCount > 5)
|
||||
{
|
||||
int group2Count = Math.Min(5, currentSampleCount - 5);
|
||||
double sum2 = 0;
|
||||
int count2 = 0;
|
||||
|
||||
foreach (var row in dataRows)
|
||||
|
||||
IRow avgRow = sheet.CreateRow(rowIndex++);
|
||||
ICell labelCell = avgRow.CreateCell(0);
|
||||
labelCell.SetCellValue($"平均时间(s)试样{group.Start}-{group.End}");
|
||||
labelCell.CellStyle = avgStyle;
|
||||
|
||||
ICell avgCell = avgRow.CreateCell(group.Start);
|
||||
avgCell.SetCellValue(sum / count);
|
||||
avgCell.CellStyle = avgStyle;
|
||||
|
||||
for (int i = group.Start + 1; i <= group.End; i++)
|
||||
{
|
||||
for (int i = 6; i <= 5 + group2Count; i++)
|
||||
{
|
||||
sum2 += row.Field<double>($"试样{i}");
|
||||
count2++;
|
||||
}
|
||||
avgRow.CreateCell(i).CellStyle = avgStyle;
|
||||
}
|
||||
|
||||
double avg2 = count2 > 0 ? sum2 / count2 : 0;
|
||||
|
||||
// 添加试样6-10平均值行
|
||||
IRow avgRow2 = sheet.CreateRow(rowIndex);
|
||||
ICell labelCell2 = avgRow2.CreateCell(0);
|
||||
labelCell2.SetCellValue("平均时间(s)试样6-10");
|
||||
labelCell2.CellStyle = avgStyle;
|
||||
|
||||
ICell avgCell2 = avgRow2.CreateCell(6);
|
||||
avgCell2.SetCellValue(avg2);
|
||||
avgCell2.CellStyle = avgStyle;
|
||||
|
||||
// 合并试样6-10列
|
||||
if (group2Count > 1)
|
||||
|
||||
if (group.End > group.Start)
|
||||
{
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 6, 5 + group2Count));
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, group.Start, group.End));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -805,6 +758,8 @@ namespace WindowsFormsApp6
|
||||
private (ICellStyle titleStyle, ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle yellowStyle)
|
||||
CreateReportStyles(IWorkbook workbook)
|
||||
{
|
||||
short numberFormat = workbook.CreateDataFormat().GetFormat("0.00");
|
||||
|
||||
// 标题样式
|
||||
ICellStyle titleStyle = workbook.CreateCellStyle();
|
||||
IFont titleFont = workbook.CreateFont();
|
||||
@@ -827,12 +782,14 @@ namespace WindowsFormsApp6
|
||||
ICellStyle dataStyle = workbook.CreateCellStyle();
|
||||
SetBorders(dataStyle);
|
||||
dataStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||
dataStyle.DataFormat = numberFormat;
|
||||
|
||||
// 黄色背景样式
|
||||
ICellStyle yellowStyle = workbook.CreateCellStyle();
|
||||
yellowStyle.CloneStyleFrom(dataStyle);
|
||||
yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
|
||||
yellowStyle.FillPattern = FillPattern.SolidForeground;
|
||||
yellowStyle.DataFormat = numberFormat;
|
||||
|
||||
return (titleStyle, headerStyle, dataStyle, yellowStyle);
|
||||
}
|
||||
@@ -912,73 +869,50 @@ namespace WindowsFormsApp6
|
||||
}
|
||||
}
|
||||
|
||||
// 计算试样1-5的平均值
|
||||
int group1Count = Math.Min(5, currentSampleCount);
|
||||
if (group1Count > 0 && timeRows.Any())
|
||||
if (!timeRows.Any())
|
||||
{
|
||||
double sum1 = 0;
|
||||
int count1 = 0;
|
||||
|
||||
foreach (var row in timeRows)
|
||||
{
|
||||
for (int i = 1; i <= group1Count; i++)
|
||||
{
|
||||
sum1 += row.Field<double>($"试样{i}");
|
||||
count1++;
|
||||
}
|
||||
}
|
||||
|
||||
double avg1 = count1 > 0 ? sum1 / count1 : 0;
|
||||
|
||||
// 添加试样1-5平均值行
|
||||
IRow avgRow1 = sheet.CreateRow(rowIndex++);
|
||||
ICell avgLabelCell1 = avgRow1.CreateCell(0);
|
||||
avgLabelCell1.SetCellValue("平均时间(s)试样1-5");
|
||||
avgLabelCell1.CellStyle = dataStyle;
|
||||
|
||||
ICell avgCell1 = avgRow1.CreateCell(1);
|
||||
avgCell1.SetCellValue(avg1);
|
||||
avgCell1.CellStyle = yellowStyle;
|
||||
|
||||
// 合并试样1-5列
|
||||
if (group1Count > 1)
|
||||
{
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, 1, group1Count));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算试样6-10的平均值(仅当试样数量>5时)
|
||||
if (currentSampleCount > 5 && timeRows.Any())
|
||||
|
||||
foreach (var group in GetSampleGroups(currentSampleCount))
|
||||
{
|
||||
int group2Count = Math.Min(5, currentSampleCount - 5);
|
||||
double sum2 = 0;
|
||||
int count2 = 0;
|
||||
|
||||
double sum = 0;
|
||||
int count = 0;
|
||||
|
||||
foreach (var row in timeRows)
|
||||
{
|
||||
for (int i = 6; i <= 5 + group2Count; i++)
|
||||
for (int i = group.Start; i <= group.End; i++)
|
||||
{
|
||||
sum2 += row.Field<double>($"试样{i}");
|
||||
count2++;
|
||||
if (TryGetDouble(row[$"试样{i}"], out double value))
|
||||
{
|
||||
sum += value;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double avg2 = count2 > 0 ? sum2 / count2 : 0;
|
||||
|
||||
// 添加试样6-10平均值行
|
||||
IRow avgRow2 = sheet.CreateRow(rowIndex);
|
||||
ICell avgLabelCell2 = avgRow2.CreateCell(0);
|
||||
avgLabelCell2.SetCellValue("平均时间(s)试样6-10");
|
||||
avgLabelCell2.CellStyle = dataStyle;
|
||||
|
||||
ICell avgCell2 = avgRow2.CreateCell(6);
|
||||
avgCell2.SetCellValue(avg2);
|
||||
avgCell2.CellStyle = yellowStyle;
|
||||
|
||||
// 合并试样6-10列
|
||||
if (group2Count > 1)
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 6, 5 + group2Count));
|
||||
continue;
|
||||
}
|
||||
|
||||
IRow avgRow = sheet.CreateRow(rowIndex++);
|
||||
ICell avgLabelCell = avgRow.CreateCell(0);
|
||||
avgLabelCell.SetCellValue($"平均时间(s)试样{group.Start}-{group.End}");
|
||||
avgLabelCell.CellStyle = dataStyle;
|
||||
|
||||
ICell avgCell = avgRow.CreateCell(group.Start);
|
||||
avgCell.SetCellValue(sum / count);
|
||||
avgCell.CellStyle = yellowStyle;
|
||||
|
||||
for (int i = group.Start + 1; i <= group.End; i++)
|
||||
{
|
||||
avgRow.CreateCell(i).CellStyle = yellowStyle;
|
||||
}
|
||||
|
||||
if (group.End > group.Start)
|
||||
{
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, group.Start, group.End));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,15 +304,7 @@ namespace WindowsFormsApp6
|
||||
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")
|
||||
IsAbsorptionStatRow(r.Field<string>("序号")))
|
||||
.ToList();
|
||||
|
||||
foreach (var row in rowsToRemove)
|
||||
@@ -412,11 +404,18 @@ namespace WindowsFormsApp6
|
||||
// 3. 液体吸收量行 (%)
|
||||
DataRow absorptionRow = sampleDataTable.NewRow();
|
||||
absorptionRow["序号"] = ROW_ABSORPTION;
|
||||
double[] absorptions = new double[count];
|
||||
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];
|
||||
if (TryCalculateAbsorption(initialWeights[i], afterWeights[i], out double absorption))
|
||||
{
|
||||
absorptions[i] = absorption;
|
||||
absorptionRow[$"试样{i + 1}"] = absorption;
|
||||
}
|
||||
else
|
||||
{
|
||||
absorptionRow[$"试样{i + 1}"] = DBNull.Value;
|
||||
}
|
||||
}
|
||||
sampleDataTable.Rows.Add(absorptionRow);
|
||||
|
||||
@@ -453,157 +452,7 @@ namespace WindowsFormsApp6
|
||||
}
|
||||
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);
|
||||
}
|
||||
AddAbsorptionStatRows(sampleDataTable, absorptions, count);
|
||||
|
||||
// 刷新界面
|
||||
RefreshDataGridView();
|
||||
@@ -615,11 +464,99 @@ namespace WindowsFormsApp6
|
||||
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));
|
||||
|
||||
var validValues = values
|
||||
.Where(v => !double.IsNaN(v) && !double.IsInfinity(v))
|
||||
.ToArray();
|
||||
|
||||
if (validValues.Length <= 1) return 0;
|
||||
|
||||
double avg = validValues.Average();
|
||||
double sumOfSquares = validValues.Sum(val => Math.Pow(val - avg, 2));
|
||||
// 使用样本标准偏差公式:除以 (n-1)
|
||||
return Math.Sqrt(sumOfSquares / (values.Length - 1));
|
||||
return Math.Sqrt(sumOfSquares / (validValues.Length - 1));
|
||||
}
|
||||
|
||||
private bool TryCalculateAbsorption(double initialWeight, double afterWeight, out double absorption)
|
||||
{
|
||||
absorption = 0;
|
||||
if (initialWeight <= 0 ||
|
||||
double.IsNaN(initialWeight) ||
|
||||
double.IsInfinity(initialWeight) ||
|
||||
double.IsNaN(afterWeight) ||
|
||||
double.IsInfinity(afterWeight))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
absorption = ((afterWeight - initialWeight) / initialWeight) * 100;
|
||||
return !double.IsNaN(absorption) && !double.IsInfinity(absorption);
|
||||
}
|
||||
|
||||
private bool IsAbsorptionStatRow(string rowName)
|
||||
{
|
||||
return !string.IsNullOrEmpty(rowName) &&
|
||||
(rowName.StartsWith(ROW_AVG_ABSORPTION) ||
|
||||
rowName.StartsWith(ROW_MAX_ABSORPTION) ||
|
||||
rowName.StartsWith(ROW_STD_DEVIATION));
|
||||
}
|
||||
|
||||
private IEnumerable<(int Start, int End)> GetSampleGroups(int sampleCount)
|
||||
{
|
||||
for (int start = 1; start <= sampleCount; start += 5)
|
||||
{
|
||||
yield return (start, Math.Min(start + 4, sampleCount));
|
||||
}
|
||||
}
|
||||
|
||||
private void AddAbsorptionStatRows(DataTable dataTable, double?[] absorptions, int sampleCount)
|
||||
{
|
||||
foreach (var group in GetSampleGroups(sampleCount))
|
||||
{
|
||||
double[] groupValues = Enumerable.Range(group.Start, group.End - group.Start + 1)
|
||||
.Select(index => absorptions[index - 1])
|
||||
.Where(value => value.HasValue)
|
||||
.Select(value => value.Value)
|
||||
.ToArray();
|
||||
|
||||
AddAbsorptionStatRow(dataTable, $"{ROW_AVG_ABSORPTION}试样{group.Start}-{group.End}",
|
||||
group.Start, sampleCount, groupValues.Length > 0 ? (object)groupValues.Average() : DBNull.Value);
|
||||
|
||||
AddAbsorptionStatRow(dataTable, $"{ROW_MAX_ABSORPTION}试样{group.Start}-{group.End}",
|
||||
group.Start, sampleCount, groupValues.Length > 0 ? (object)groupValues.Max() : DBNull.Value);
|
||||
|
||||
AddAbsorptionStatRow(dataTable, $"{ROW_STD_DEVIATION}试样{group.Start}-{group.End}",
|
||||
group.Start, sampleCount, groupValues.Length > 1 ? (object)CalculateStandardDeviation(groupValues) : DBNull.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddAbsorptionStatRow(DataTable dataTable, string rowName, int startSample, int sampleCount, object statValue)
|
||||
{
|
||||
DataRow row = dataTable.NewRow();
|
||||
row["序号"] = rowName;
|
||||
|
||||
for (int i = 1; i <= sampleCount; i++)
|
||||
{
|
||||
row[$"试样{i}"] = i == startSample ? statValue : DBNull.Value;
|
||||
}
|
||||
|
||||
dataTable.Rows.Add(row);
|
||||
}
|
||||
|
||||
private int FindStatStartSample(DataRow row)
|
||||
{
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
string columnName = $"试样{i}";
|
||||
if (row.Table.Columns.Contains(columnName) &&
|
||||
row[columnName] != null &&
|
||||
row[columnName] != DBNull.Value)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -692,6 +629,8 @@ namespace WindowsFormsApp6
|
||||
private (ICellStyle titleStyle, ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle yellowStyle)
|
||||
CreateReportStyles(IWorkbook workbook)
|
||||
{
|
||||
short numberFormat = workbook.CreateDataFormat().GetFormat("0.00");
|
||||
|
||||
// 标题样式
|
||||
ICellStyle titleStyle = workbook.CreateCellStyle();
|
||||
IFont titleFont = workbook.CreateFont();
|
||||
@@ -714,12 +653,14 @@ namespace WindowsFormsApp6
|
||||
ICellStyle dataStyle = workbook.CreateCellStyle();
|
||||
SetBorders(dataStyle);
|
||||
dataStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||
dataStyle.DataFormat = numberFormat;
|
||||
|
||||
// 黄色背景样式
|
||||
ICellStyle yellowStyle = workbook.CreateCellStyle();
|
||||
yellowStyle.CloneStyleFrom(dataStyle);
|
||||
yellowStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index;
|
||||
yellowStyle.FillPattern = FillPattern.SolidForeground;
|
||||
yellowStyle.DataFormat = numberFormat;
|
||||
|
||||
return (titleStyle, headerStyle, dataStyle, yellowStyle);
|
||||
}
|
||||
@@ -779,10 +720,8 @@ namespace WindowsFormsApp6
|
||||
{
|
||||
string rowName = dataRow["序号"].ToString();
|
||||
|
||||
// 处理试样1-5分组行的合并单元格
|
||||
if (rowName == "液体吸收量平均值(%)试样1-5" ||
|
||||
rowName == "液体吸收量最大值(%)试样1-5" ||
|
||||
rowName == "标准偏差试样1-5")
|
||||
// 处理每5个试样一组的统计行
|
||||
if (IsAbsorptionStatRow(rowName))
|
||||
{
|
||||
IRow row = sheet.CreateRow(rowIndex++);
|
||||
|
||||
@@ -790,48 +729,32 @@ namespace WindowsFormsApp6
|
||||
ICell nameCell = row.CreateCell(0);
|
||||
nameCell.SetCellValue(rowName);
|
||||
nameCell.CellStyle = dataStyle;
|
||||
|
||||
// 获取试样1的值
|
||||
var value = dataRow["试样1"];
|
||||
if (value != null && value != DBNull.Value)
|
||||
|
||||
int startSample = FindStatStartSample(dataRow);
|
||||
int endSample = startSample > 0 ? Math.Min(startSample + 4, currentSampleCount) : startSample;
|
||||
|
||||
if (startSample > 0)
|
||||
{
|
||||
ICell cell = row.CreateCell(1);
|
||||
cell.SetCellValue(Convert.ToDouble(value));
|
||||
cell.CellStyle = yellowStyle;
|
||||
|
||||
// 合并试样1-5列
|
||||
int group1Count = Math.Min(5, currentSampleCount);
|
||||
if (group1Count > 1)
|
||||
ICell cell = row.CreateCell(startSample);
|
||||
object value = dataRow[$"试样{startSample}"];
|
||||
if (value != null && value != DBNull.Value && double.TryParse(value.ToString(), out double numValue))
|
||||
{
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, 1, group1Count));
|
||||
cell.SetCellValue(numValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理试样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)
|
||||
else
|
||||
{
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, 6, 5 + group2Count));
|
||||
cell.SetCellValue("");
|
||||
}
|
||||
cell.CellStyle = yellowStyle;
|
||||
|
||||
for (int i = startSample + 1; i <= endSample; i++)
|
||||
{
|
||||
row.CreateCell(i).CellStyle = yellowStyle;
|
||||
}
|
||||
|
||||
if (endSample > startSample)
|
||||
{
|
||||
sheet.AddMergedRegion(new CellRangeAddress(rowIndex - 1, rowIndex - 1, startSample, endSample));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,11 +331,11 @@ namespace WindowsFormsApp6
|
||||
|
||||
if (isVerticalLayout)
|
||||
{
|
||||
// 纵向布局:检查芯吸速率行(第3行,索引2)
|
||||
if (sampleDataTable.Rows.Count <= 2)
|
||||
// 纵向布局:检查芯吸速率行
|
||||
DataRow rateRow = FindDataRow(ROW_WICKING_RATE);
|
||||
if (rateRow == null)
|
||||
return false;
|
||||
|
||||
DataRow rateRow = sampleDataTable.Rows[2];
|
||||
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
for (int j = 1; j <= 3; j++)
|
||||
@@ -497,7 +497,10 @@ namespace WindowsFormsApp6
|
||||
string colName = $"试样{i}_{j}";
|
||||
if (row.Table.Columns.Contains(colName))
|
||||
{
|
||||
rowData[colName] = ConvertToDouble(row[colName]);
|
||||
if (TryGetExistingDouble(row[colName], out double value))
|
||||
{
|
||||
rowData[colName] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,7 +510,7 @@ namespace WindowsFormsApp6
|
||||
else
|
||||
{
|
||||
// 从横向布局保存:需要转换数据结构
|
||||
// 初始化5个数据行
|
||||
// 初始化数据行
|
||||
data[ROW_WICKING_TIME] = new Dictionary<string, double>();
|
||||
data[ROW_WICKING_HEIGHT] = new Dictionary<string, double>();
|
||||
data[ROW_WICKING_RATE] = new Dictionary<string, double>();
|
||||
@@ -525,20 +528,25 @@ namespace WindowsFormsApp6
|
||||
DataRow row = sampleDataTable.Rows[rowIndex];
|
||||
string colName = $"试样{i}_{j}";
|
||||
|
||||
if (row.Table.Columns.Contains(ROW_WICKING_TIME))
|
||||
data[ROW_WICKING_TIME][colName] = ConvertToDouble(row[ROW_WICKING_TIME]);
|
||||
if (row.Table.Columns.Contains(ROW_WICKING_TIME) &&
|
||||
TryGetExistingDouble(row[ROW_WICKING_TIME], out double wickingTime))
|
||||
data[ROW_WICKING_TIME][colName] = wickingTime;
|
||||
|
||||
if (row.Table.Columns.Contains(ROW_WICKING_HEIGHT))
|
||||
data[ROW_WICKING_HEIGHT][colName] = ConvertToDouble(row[ROW_WICKING_HEIGHT]);
|
||||
if (row.Table.Columns.Contains(ROW_WICKING_HEIGHT) &&
|
||||
TryGetExistingDouble(row[ROW_WICKING_HEIGHT], out double wickingHeight))
|
||||
data[ROW_WICKING_HEIGHT][colName] = wickingHeight;
|
||||
|
||||
if (row.Table.Columns.Contains(ROW_WICKING_RATE))
|
||||
data[ROW_WICKING_RATE][colName] = ConvertToDouble(row[ROW_WICKING_RATE]);
|
||||
if (row.Table.Columns.Contains(ROW_WICKING_RATE) &&
|
||||
TryGetExistingDouble(row[ROW_WICKING_RATE], out double wickingRate))
|
||||
data[ROW_WICKING_RATE][colName] = wickingRate;
|
||||
|
||||
if (row.Table.Columns.Contains(ROW_AVG_WICKING_RATE))
|
||||
data[ROW_AVG_WICKING_RATE][colName] = ConvertToDouble(row[ROW_AVG_WICKING_RATE]);
|
||||
if (row.Table.Columns.Contains(ROW_AVG_WICKING_RATE) &&
|
||||
TryGetExistingDouble(row[ROW_AVG_WICKING_RATE], out double avgWickingRate))
|
||||
data[ROW_AVG_WICKING_RATE][colName] = avgWickingRate;
|
||||
|
||||
if (row.Table.Columns.Contains(ROW_STD_DEVIATION))
|
||||
data[ROW_STD_DEVIATION][colName] = ConvertToDouble(row[ROW_STD_DEVIATION]);
|
||||
if (row.Table.Columns.Contains(ROW_STD_DEVIATION) &&
|
||||
TryGetExistingDouble(row[ROW_STD_DEVIATION], out double stdDeviation))
|
||||
data[ROW_STD_DEVIATION][colName] = stdDeviation;
|
||||
|
||||
rowIndex++;
|
||||
}
|
||||
@@ -615,6 +623,19 @@ namespace WindowsFormsApp6
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetExistingDouble(object value, out double result)
|
||||
{
|
||||
result = 0;
|
||||
if (value == null || value == DBNull.Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return double.TryParse(value.ToString(), out result) &&
|
||||
!double.IsNaN(result) &&
|
||||
!double.IsInfinity(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接设备按钮点击事件
|
||||
/// </summary>
|
||||
@@ -713,7 +734,7 @@ namespace WindowsFormsApp6
|
||||
sampleDataTable.Columns.Add($"试样{i}_3", typeof(double));
|
||||
}
|
||||
|
||||
// 初始化5行数据
|
||||
// 初始化数据行
|
||||
AddDataRow(ROW_WICKING_TIME);
|
||||
AddDataRow(ROW_WICKING_HEIGHT);
|
||||
AddDataRow(ROW_WICKING_RATE);
|
||||
@@ -737,11 +758,11 @@ namespace WindowsFormsApp6
|
||||
{
|
||||
DataRow row = sampleDataTable.NewRow();
|
||||
row["序号"] = $"试样{i}_{j}";
|
||||
row[ROW_WICKING_TIME] = 0.0;
|
||||
row[ROW_WICKING_HEIGHT] = 0.0;
|
||||
row[ROW_WICKING_RATE] = 0.0;
|
||||
row[ROW_AVG_WICKING_RATE] = 0.0;
|
||||
row[ROW_STD_DEVIATION] = 0.0;
|
||||
row[ROW_WICKING_TIME] = DBNull.Value;
|
||||
row[ROW_WICKING_HEIGHT] = DBNull.Value;
|
||||
row[ROW_WICKING_RATE] = DBNull.Value;
|
||||
row[ROW_AVG_WICKING_RATE] = DBNull.Value;
|
||||
row[ROW_STD_DEVIATION] = DBNull.Value;
|
||||
sampleDataTable.Rows.Add(row);
|
||||
}
|
||||
}
|
||||
@@ -756,17 +777,35 @@ namespace WindowsFormsApp6
|
||||
DataRow row = sampleDataTable.NewRow();
|
||||
row["序号"] = rowName;
|
||||
|
||||
// 初始化所有数值列为0
|
||||
// 未采集的数据保持为空,避免报表把空数据导出为0。
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
row[$"试样{i}_1"] = 0.0;
|
||||
row[$"试样{i}_2"] = 0.0;
|
||||
row[$"试样{i}_3"] = 0.0;
|
||||
row[$"试样{i}_1"] = DBNull.Value;
|
||||
row[$"试样{i}_2"] = DBNull.Value;
|
||||
row[$"试样{i}_3"] = DBNull.Value;
|
||||
}
|
||||
|
||||
sampleDataTable.Rows.Add(row);
|
||||
}
|
||||
|
||||
private DataRow FindDataRow(string rowName)
|
||||
{
|
||||
if (sampleDataTable == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (DataRow row in sampleDataTable.Rows)
|
||||
{
|
||||
if (string.Equals(row["序号"]?.ToString(), rowName, StringComparison.Ordinal))
|
||||
{
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化定时器用于模拟寄存器数据读取
|
||||
/// </summary>
|
||||
@@ -785,7 +824,12 @@ namespace WindowsFormsApp6
|
||||
if (isVerticalLayout)
|
||||
{
|
||||
// 纵向布局:第1行读取吸水时间
|
||||
DataRow timeRow = sampleDataTable.Rows[0];
|
||||
DataRow timeRow = FindDataRow(ROW_WICKING_TIME);
|
||||
if (timeRow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
double time1 = ReadRegisterData((i - 1) * 3);
|
||||
@@ -839,14 +883,19 @@ namespace WindowsFormsApp6
|
||||
{
|
||||
for (int colIndex = 1; colIndex < sampleDataTable.Columns.Count; colIndex++)
|
||||
{
|
||||
row[colIndex] = 0.0;
|
||||
row[colIndex] = DBNull.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (isVerticalLayout)
|
||||
{
|
||||
// 纵向布局:第1行生成吸水时间
|
||||
DataRow timeRow = sampleDataTable.Rows[0];
|
||||
DataRow timeRow = FindDataRow(ROW_WICKING_TIME);
|
||||
if (timeRow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
double baseTime = 31 + random.NextDouble() * 2;
|
||||
@@ -935,9 +984,13 @@ namespace WindowsFormsApp6
|
||||
if (isVerticalLayout)
|
||||
{
|
||||
// 纵向布局
|
||||
DataRow timeRow = sampleDataTable.Rows[0];
|
||||
DataRow heightRow = sampleDataTable.Rows[1];
|
||||
DataRow rateRow = sampleDataTable.Rows[2];
|
||||
DataRow timeRow = FindDataRow(ROW_WICKING_TIME);
|
||||
DataRow heightRow = FindDataRow(ROW_WICKING_HEIGHT);
|
||||
DataRow rateRow = FindDataRow(ROW_WICKING_RATE);
|
||||
if (timeRow == null || heightRow == null || rateRow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
@@ -949,13 +1002,9 @@ namespace WindowsFormsApp6
|
||||
double height2 = ConvertToDouble(heightRow[$"试样{i}_2"]);
|
||||
double height3 = ConvertToDouble(heightRow[$"试样{i}_3"]);
|
||||
|
||||
double rate1 = (time1 > 0 && height1 > 0) ? height1 / (time1 / 60.0) : 0;
|
||||
double rate2 = (time2 > 0 && height2 > 0) ? height2 / (time2 / 60.0) : 0;
|
||||
double rate3 = (time3 > 0 && height3 > 0) ? height3 / (time3 / 60.0) : 0;
|
||||
|
||||
rateRow[$"试样{i}_1"] = Math.Round(rate1, 2);
|
||||
rateRow[$"试样{i}_2"] = Math.Round(rate2, 2);
|
||||
rateRow[$"试样{i}_3"] = Math.Round(rate3, 2);
|
||||
rateRow[$"试样{i}_1"] = (time1 > 0 && height1 > 0) ? (object)(height1 / (time1 / 60.0)) : DBNull.Value;
|
||||
rateRow[$"试样{i}_2"] = (time2 > 0 && height2 > 0) ? (object)(height2 / (time2 / 60.0)) : DBNull.Value;
|
||||
rateRow[$"试样{i}_3"] = (time3 > 0 && height3 > 0) ? (object)(height3 / (time3 / 60.0)) : DBNull.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -965,8 +1014,7 @@ namespace WindowsFormsApp6
|
||||
{
|
||||
double time = ConvertToDouble(row[ROW_WICKING_TIME]);
|
||||
double height = ConvertToDouble(row[ROW_WICKING_HEIGHT]);
|
||||
double rate = (time > 0 && height > 0) ? height / (time / 60.0) : 0;
|
||||
row[ROW_WICKING_RATE] = Math.Round(rate, 2);
|
||||
row[ROW_WICKING_RATE] = (time > 0 && height > 0) ? (object)(height / (time / 60.0)) : DBNull.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1000,15 +1048,19 @@ namespace WindowsFormsApp6
|
||||
if (isVerticalLayout)
|
||||
{
|
||||
// 纵向布局
|
||||
DataRow rateRow = sampleDataTable.Rows[2];
|
||||
DataRow avgRow = sampleDataTable.Rows[3];
|
||||
DataRow rateRow = FindDataRow(ROW_WICKING_RATE);
|
||||
DataRow avgRow = FindDataRow(ROW_AVG_WICKING_RATE);
|
||||
if (rateRow == null || avgRow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 清空平均值行的所有数据
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
avgRow[$"试样{i}_1"] = 0.0;
|
||||
avgRow[$"试样{i}_2"] = 0.0;
|
||||
avgRow[$"试样{i}_3"] = 0.0;
|
||||
avgRow[$"试样{i}_1"] = DBNull.Value;
|
||||
avgRow[$"试样{i}_2"] = DBNull.Value;
|
||||
avgRow[$"试样{i}_3"] = DBNull.Value;
|
||||
}
|
||||
|
||||
// 计算每个试样的平均值,并填充到该试样的第1列(合并显示效果)
|
||||
@@ -1024,11 +1076,11 @@ namespace WindowsFormsApp6
|
||||
if (rate3 > 0) groupRates.Add(rate3);
|
||||
|
||||
// 计算该试样的平均值
|
||||
double groupAvg = groupRates.Count > 0 ? groupRates.Average() : 0;
|
||||
|
||||
// 只填充到该试样的第1列,实现合并显示效果
|
||||
avgRow[$"试样{i}_1"] = Math.Round(groupAvg, 2);
|
||||
// 第2、3列保持为0(显示为空白)
|
||||
if (groupRates.Count > 0)
|
||||
{
|
||||
// 只填充到该试样的第1列,实现合并显示效果
|
||||
avgRow[$"试样{i}_1"] = groupRates.Average();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1037,7 +1089,7 @@ namespace WindowsFormsApp6
|
||||
// 清空所有行的平均值列
|
||||
foreach (DataRow row in sampleDataTable.Rows)
|
||||
{
|
||||
row[ROW_AVG_WICKING_RATE] = 0.0;
|
||||
row[ROW_AVG_WICKING_RATE] = DBNull.Value;
|
||||
}
|
||||
|
||||
// 计算每个试样的平均值
|
||||
@@ -1056,13 +1108,14 @@ namespace WindowsFormsApp6
|
||||
}
|
||||
|
||||
// 计算该试样的平均值
|
||||
double groupAvg = groupRates.Count > 0 ? groupRates.Average() : 0;
|
||||
|
||||
// 填充到该试样的第3次测试行(合并显示效果)
|
||||
int targetRowIndex = (i - 1) * 3 + 2; // 第3次测试的行索引
|
||||
if (targetRowIndex < sampleDataTable.Rows.Count)
|
||||
if (groupRates.Count > 0)
|
||||
{
|
||||
sampleDataTable.Rows[targetRowIndex][ROW_AVG_WICKING_RATE] = Math.Round(groupAvg, 2);
|
||||
// 填充到该试样的第3次测试行(合并显示效果)
|
||||
int targetRowIndex = (i - 1) * 3 + 2; // 第3次测试的行索引
|
||||
if (targetRowIndex < sampleDataTable.Rows.Count)
|
||||
{
|
||||
sampleDataTable.Rows[targetRowIndex][ROW_AVG_WICKING_RATE] = groupRates.Average();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1083,8 +1136,12 @@ namespace WindowsFormsApp6
|
||||
if (isVerticalLayout)
|
||||
{
|
||||
// 纵向布局
|
||||
DataRow rateRow = sampleDataTable.Rows[2];
|
||||
DataRow stdRow = sampleDataTable.Rows[4];
|
||||
DataRow rateRow = FindDataRow(ROW_WICKING_RATE);
|
||||
DataRow stdRow = FindDataRow(ROW_STD_DEVIATION);
|
||||
if (rateRow == null || stdRow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 清空标准偏差行的所有数据(设置为DBNull,不显示)
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
@@ -1124,17 +1181,14 @@ namespace WindowsFormsApp6
|
||||
}
|
||||
}
|
||||
|
||||
// 基于该组试样的平均值计算标准偏差
|
||||
double stdDev = 0;
|
||||
if (groupAverages.Count > 1)
|
||||
{
|
||||
double overallAverage = groupAverages.Average();
|
||||
double sumOfSquares = groupAverages.Sum(avg => Math.Pow(avg - overallAverage, 2));
|
||||
stdDev = Math.Sqrt(sumOfSquares / (groupAverages.Count - 1));
|
||||
double stdDev = Math.Sqrt(sumOfSquares / (groupAverages.Count - 1));
|
||||
// 只在该组第1个试样的第1列显示标准偏差,其他列保持DBNull(不显示)
|
||||
stdRow[$"试样{startSample}_1"] = stdDev;
|
||||
}
|
||||
|
||||
// 只在该组第1个试样的第1列显示标准偏差,其他列保持DBNull(不显示)
|
||||
stdRow[$"试样{startSample}_1"] = Math.Round(stdDev, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1179,20 +1233,17 @@ namespace WindowsFormsApp6
|
||||
}
|
||||
}
|
||||
|
||||
// 基于该组试样的平均值计算标准偏差
|
||||
double stdDev = 0;
|
||||
if (groupAverages.Count > 1)
|
||||
{
|
||||
double overallAverage = groupAverages.Average();
|
||||
double sumOfSquares = groupAverages.Sum(avg => Math.Pow(avg - overallAverage, 2));
|
||||
stdDev = Math.Sqrt(sumOfSquares / (groupAverages.Count - 1));
|
||||
}
|
||||
|
||||
// 只在该组第1个试样的第1次测试行显示标准偏差,其他行保持DBNull(不显示)
|
||||
int targetRowIndex = (startSample - 1) * 3; // 第1次测试的行索引
|
||||
if (targetRowIndex < sampleDataTable.Rows.Count)
|
||||
{
|
||||
sampleDataTable.Rows[targetRowIndex][ROW_STD_DEVIATION] = Math.Round(stdDev, 2);
|
||||
double stdDev = Math.Sqrt(sumOfSquares / (groupAverages.Count - 1));
|
||||
// 只在该组第1个试样的第1次测试行显示标准偏差,其他行保持DBNull(不显示)
|
||||
int targetRowIndex = (startSample - 1) * 3; // 第1次测试的行索引
|
||||
if (targetRowIndex < sampleDataTable.Rows.Count)
|
||||
{
|
||||
sampleDataTable.Rows[targetRowIndex][ROW_STD_DEVIATION] = stdDev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1256,6 +1307,8 @@ namespace WindowsFormsApp6
|
||||
private (ICellStyle headerStyle, ICellStyle dataStyle, ICellStyle yellowStyle)
|
||||
CreateReportStyles(IWorkbook workbook)
|
||||
{
|
||||
short numberFormat = workbook.CreateDataFormat().GetFormat("0.00");
|
||||
|
||||
// 表头样式
|
||||
ICellStyle headerStyle = workbook.CreateCellStyle();
|
||||
headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
|
||||
@@ -1272,6 +1325,7 @@ namespace WindowsFormsApp6
|
||||
SetBorders(dataStyle);
|
||||
dataStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||
dataStyle.VerticalAlignment = VerticalAlignment.Center;
|
||||
dataStyle.DataFormat = numberFormat;
|
||||
|
||||
// 黄色背景样式
|
||||
ICellStyle yellowStyle = workbook.CreateCellStyle();
|
||||
@@ -1280,6 +1334,7 @@ namespace WindowsFormsApp6
|
||||
SetBorders(yellowStyle);
|
||||
yellowStyle.Alignment = NPOIHorizontalAlignment.Center;
|
||||
yellowStyle.VerticalAlignment = VerticalAlignment.Center;
|
||||
yellowStyle.DataFormat = numberFormat;
|
||||
|
||||
return (headerStyle, dataStyle, yellowStyle);
|
||||
}
|
||||
@@ -1300,6 +1355,29 @@ namespace WindowsFormsApp6
|
||||
/// </summary>
|
||||
private void CreateReportHeader(ISheet sheet, ICellStyle headerStyle)
|
||||
{
|
||||
if (!isVerticalLayout)
|
||||
{
|
||||
string[] headers =
|
||||
{
|
||||
"序号",
|
||||
ROW_WICKING_TIME,
|
||||
ROW_WICKING_HEIGHT,
|
||||
ROW_WICKING_RATE,
|
||||
ROW_AVG_WICKING_RATE,
|
||||
ROW_STD_DEVIATION
|
||||
};
|
||||
|
||||
IRow headerRow = sheet.CreateRow(0);
|
||||
headerRow.Height = 400;
|
||||
for (int i = 0; i < headers.Length; i++)
|
||||
{
|
||||
ICell cell = headerRow.CreateCell(i);
|
||||
cell.SetCellValue(headers[i]);
|
||||
cell.CellStyle = headerStyle;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建第一行表头(试样1-N)
|
||||
IRow headerRow1 = sheet.CreateRow(0);
|
||||
headerRow1.Height = 400;
|
||||
@@ -1345,6 +1423,12 @@ namespace WindowsFormsApp6
|
||||
/// </summary>
|
||||
private void FillReportData(ISheet sheet, ICellStyle dataStyle, ICellStyle yellowStyle)
|
||||
{
|
||||
if (!isVerticalLayout)
|
||||
{
|
||||
FillHorizontalReportData(sheet, dataStyle, yellowStyle);
|
||||
return;
|
||||
}
|
||||
|
||||
int rowIndex = 2;
|
||||
int dataRowIndex = 0;
|
||||
|
||||
@@ -1362,33 +1446,24 @@ namespace WindowsFormsApp6
|
||||
cellSeq.CellStyle = rowStyle;
|
||||
|
||||
int colIndex = 1;
|
||||
string rowName = dataRow["序号"].ToString();
|
||||
bool sourceRow = rowName == ROW_WICKING_TIME ||
|
||||
rowName == ROW_WICKING_HEIGHT;
|
||||
for (int i = 1; i <= currentSampleCount; i++)
|
||||
{
|
||||
// 试样次数1
|
||||
ICell cell1 = row.CreateCell(colIndex++);
|
||||
double val1 = ConvertToDouble(dataRow[$"试样{i}_1"]);
|
||||
if (Math.Abs(val1) >= 0.001) // 只有非0值才显示
|
||||
{
|
||||
cell1.SetCellValue(val1);
|
||||
}
|
||||
SetForm3ReportCell(cell1, dataRow[$"试样{i}_1"], sourceRow);
|
||||
cell1.CellStyle = rowStyle;
|
||||
|
||||
// 试样次数2
|
||||
ICell cell2 = row.CreateCell(colIndex++);
|
||||
double val2 = ConvertToDouble(dataRow[$"试样{i}_2"]);
|
||||
if (Math.Abs(val2) >= 0.001) // 只有非0值才显示
|
||||
{
|
||||
cell2.SetCellValue(val2);
|
||||
}
|
||||
SetForm3ReportCell(cell2, dataRow[$"试样{i}_2"], sourceRow);
|
||||
cell2.CellStyle = rowStyle;
|
||||
|
||||
// 试样次数3
|
||||
ICell cell3 = row.CreateCell(colIndex++);
|
||||
double val3 = ConvertToDouble(dataRow[$"试样{i}_3"]);
|
||||
if (Math.Abs(val3) >= 0.001) // 只有非0值才显示
|
||||
{
|
||||
cell3.SetCellValue(val3);
|
||||
}
|
||||
SetForm3ReportCell(cell3, dataRow[$"试样{i}_3"], sourceRow);
|
||||
cell3.CellStyle = rowStyle;
|
||||
}
|
||||
|
||||
@@ -1397,12 +1472,103 @@ namespace WindowsFormsApp6
|
||||
}
|
||||
}
|
||||
|
||||
private void FillHorizontalReportData(ISheet sheet, ICellStyle dataStyle, ICellStyle yellowStyle)
|
||||
{
|
||||
string[] columns =
|
||||
{
|
||||
"序号",
|
||||
ROW_WICKING_TIME,
|
||||
ROW_WICKING_HEIGHT,
|
||||
ROW_WICKING_RATE,
|
||||
ROW_AVG_WICKING_RATE,
|
||||
ROW_STD_DEVIATION
|
||||
};
|
||||
|
||||
int rowIndex = 1;
|
||||
foreach (DataRow dataRow in sampleDataTable.Rows)
|
||||
{
|
||||
IRow row = sheet.CreateRow(rowIndex++);
|
||||
row.Height = 380;
|
||||
|
||||
for (int i = 0; i < columns.Length; i++)
|
||||
{
|
||||
ICell cell = row.CreateCell(i);
|
||||
string columnName = columns[i];
|
||||
if (sampleDataTable.Columns.Contains(columnName) &&
|
||||
dataRow[columnName] != null &&
|
||||
dataRow[columnName] != DBNull.Value)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
cell.SetCellValue(dataRow[columnName].ToString());
|
||||
}
|
||||
else if (double.TryParse(dataRow[columnName].ToString(), out double value))
|
||||
{
|
||||
if ((columnName == ROW_WICKING_TIME ||
|
||||
columnName == ROW_WICKING_HEIGHT) &&
|
||||
Math.Abs(value) < 0.001)
|
||||
{
|
||||
cell.SetCellValue("");
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.SetCellValue(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.SetCellValue("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.SetCellValue("");
|
||||
}
|
||||
|
||||
cell.CellStyle = i == 0 ? dataStyle : yellowStyle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetForm3ReportCell(ICell cell, object value, bool blankZeroSourceValue)
|
||||
{
|
||||
if (value == null || value == DBNull.Value)
|
||||
{
|
||||
cell.SetCellValue("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!double.TryParse(value.ToString(), out double number))
|
||||
{
|
||||
cell.SetCellValue("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (blankZeroSourceValue && Math.Abs(number) < 0.001)
|
||||
{
|
||||
cell.SetCellValue("");
|
||||
return;
|
||||
}
|
||||
|
||||
cell.SetCellValue(number);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置报表列宽
|
||||
/// </summary>
|
||||
private void SetReportColumnWidths(ISheet sheet)
|
||||
{
|
||||
sheet.SetColumnWidth(0, 20 * 256); // 序号列
|
||||
if (!isVerticalLayout)
|
||||
{
|
||||
sheet.SetColumnWidth(1, 16 * 256);
|
||||
sheet.SetColumnWidth(2, 16 * 256);
|
||||
sheet.SetColumnWidth(3, 18 * 256);
|
||||
sheet.SetColumnWidth(4, 22 * 256);
|
||||
sheet.SetColumnWidth(5, 14 * 256);
|
||||
return;
|
||||
}
|
||||
|
||||
int totalColumns = currentSampleCount * 3;
|
||||
for (int i = 1; i <= totalColumns; i++)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -102,9 +102,6 @@
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Design" />
|
||||
<Reference Include="System.IO.Ports, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.IO.Ports.8.0.0\lib\net462\System.IO.Ports.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -215,4 +212,4 @@
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
<package id="SunnyUI.Common" version="3.7.2" targetFramework="net48" />
|
||||
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
|
||||
<package id="System.ComponentModel.Annotations" version="5.0.0" targetFramework="net48" />
|
||||
<package id="System.IO.Ports" version="8.0.0" targetFramework="net48" />
|
||||
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
|
||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net48" />
|
||||
@@ -27,4 +26,4 @@
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.5.2" targetFramework="net48" />
|
||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
|
||||
<package id="ZString" version="2.6.0" targetFramework="net48" />
|
||||
</packages>
|
||||
</packages>
|
||||
|
||||
Reference in New Issue
Block a user