Files
CSI-Z420-Tablet-Multi-Funct…/Services/ExcelExportService.cs
GukSang.Jin df5c7566fb 更新
2026-05-20 14:27:16 +08:00

341 lines
14 KiB
C#

using OfficeOpenXml;
using OfficeOpenXml.Drawing.Chart;
using OfficeOpenXml.Style;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TabletTester2025.Models;
namespace TabletTester2025.Services
{
public class ExcelExportService
{
public void ExportToExcel(IEnumerable<TestBatch> batches, string filePath)
{
using var package = new ExcelPackage(new FileInfo(filePath));
var hardnessData = batches.Where(b => b.TestType == "硬度").ToList();
var friabilityData = batches.Where(b => b.TestType == "脆碎度").ToList();
var disintegrationData = batches.Where(b => b.TestType == "崩解").ToList();
var dissolutionData = batches.Where(b => b.TestType == "溶出").ToList();
AddHardnessSheet(package, hardnessData);
AddFriabilitySheet(package, friabilityData);
AddDisintegrationSheet(package, disintegrationData);
AddDissolutionSheet(package, dissolutionData);
package.Save();
}
public void ExportHardnessToExcel(IEnumerable<TestBatch> batches, string filePath)
{
using var package = new ExcelPackage(new FileInfo(filePath));
AddHardnessSheet(package, batches);
package.Save();
}
public void ExportFriabilityToExcel(IEnumerable<TestBatch> batches, string filePath)
{
using var package = new ExcelPackage(new FileInfo(filePath));
AddFriabilitySheet(package, batches);
package.Save();
}
public void ExportDisintegrationToExcel(IEnumerable<TestBatch> batches, string filePath)
{
using var package = new ExcelPackage(new FileInfo(filePath));
AddDisintegrationSheet(package, batches);
package.Save();
}
public void ExportDissolutionToExcel(IEnumerable<TestBatch> batches, string filePath)
{
using var package = new ExcelPackage(new FileInfo(filePath));
AddDissolutionSheet(package, batches);
package.Save();
}
private static void AddHardnessSheet(ExcelPackage package, IEnumerable<TestBatch> batches)
{
var data = batches.ToList();
var sheet = package.Workbook.Worksheets.Add("硬度报表");
WriteHeader(sheet, "检测时间", "样品名称", "平均值(N)", "平均偏差(N)", "RSD(%)", "最大值(N)", "测试次数", "单次数据(N)", "判定");
if (data.Count == 0)
{
sheet.Cells[2, 1].Value = "无硬度测试数据";
sheet.Cells.AutoFitColumns();
return;
}
int row = 2;
foreach (var b in data)
{
sheet.Cells[row, 1].Value = b.TestTime.ToString("yyyy-MM-dd HH:mm:ss");
sheet.Cells[row, 2].Value = b.SampleName;
sheet.Cells[row, 3].Value = b.HardnessAvg;
sheet.Cells[row, 4].Value = b.HardnessAverageDeviation;
sheet.Cells[row, 5].Value = b.HardnessRSD;
sheet.Cells[row, 6].Value = b.HardnessMax;
sheet.Cells[row, 7].Value = b.HardnessTestCount;
sheet.Cells[row, 8].Value = b.HardnessSampleSummary;
sheet.Cells[row, 9].Value = b.HardnessPassText;
row++;
}
sheet.Cells.AutoFitColumns();
AddHardnessSamplesSheet(package, data);
}
private static void AddHardnessSamplesSheet(ExcelPackage package, IEnumerable<TestBatch> batches)
{
var samples = GetHardnessSampleRows(batches).ToList();
if (samples.Count == 0)
return;
var sheet = package.Workbook.Worksheets.Add("硬度单次明细");
WriteHeader(sheet, "检测时间", "样品名称", "序号", "硬度值(N)", "与平均值偏差(N)", "记录时间");
int row = 2;
foreach (var item in samples)
{
sheet.Cells[row, 1].Value = item.Batch.TestTime.ToString("yyyy-MM-dd HH:mm:ss");
sheet.Cells[row, 2].Value = item.Batch.SampleName;
sheet.Cells[row, 3].Value = item.Sample.SequenceNo;
sheet.Cells[row, 4].Value = item.Sample.Value;
sheet.Cells[row, 5].Value = item.Sample.DeviationFromAverage;
sheet.Cells[row, 6].Value = item.Sample.RecordedAt.ToString("yyyy-MM-dd HH:mm:ss");
row++;
}
sheet.Cells.AutoFitColumns();
}
private static void AddFriabilitySheet(ExcelPackage package, IEnumerable<TestBatch> batches)
{
var data = batches.ToList();
var sheet = package.Workbook.Worksheets.Add("脆碎度报表");
WriteHeader(sheet, "检测时间", "样品名称", "失重率(%)", "设定转速(r/min)", "试验时间(min)", "试验转数", "前重(g)", "后重(g)", "判定");
if (data.Count == 0)
{
sheet.Cells[2, 1].Value = "无脆碎度测试数据";
sheet.Cells.AutoFitColumns();
return;
}
int row = 2;
foreach (var b in data)
{
sheet.Cells[row, 1].Value = b.TestTime.ToString("yyyy-MM-dd HH:mm:ss");
sheet.Cells[row, 2].Value = b.SampleName;
sheet.Cells[row, 3].Value = b.FriabilityLoss;
sheet.Cells[row, 4].Value = b.FriabilityTargetRpm;
sheet.Cells[row, 5].Value = b.FriabilityTargetTimeMin;
sheet.Cells[row, 6].Value = b.FriabilityTargetRounds;
sheet.Cells[row, 7].Value = b.WeightBefore;
sheet.Cells[row, 8].Value = b.WeightAfter;
sheet.Cells[row, 9].Value = b.FriabilityPassText;
row++;
}
sheet.Cells.AutoFitColumns();
}
private static void AddDisintegrationSheet(ExcelPackage package, IEnumerable<TestBatch> batches)
{
var data = batches.ToList();
var sheet = package.Workbook.Worksheets.Add("崩解报表");
WriteHeader(sheet, "检测时间", "样品名称", "崩解时间(秒)", "水浴温度(℃)", "判定");
if (data.Count == 0)
{
sheet.Cells[2, 1].Value = "无崩解测试数据";
sheet.Cells.AutoFitColumns();
return;
}
int row = 2;
foreach (var b in data)
{
sheet.Cells[row, 1].Value = b.TestTime.ToString("yyyy-MM-dd HH:mm:ss");
sheet.Cells[row, 2].Value = b.SampleName;
sheet.Cells[row, 3].Value = b.DisintegrationTimeSec;
sheet.Cells[row, 4].Value = b.DisintegrationTemp;
sheet.Cells[row, 5].Value = b.DisintegrationPassText;
row++;
}
sheet.Cells.AutoFitColumns();
}
private static void AddDissolutionSheet(ExcelPackage package, IEnumerable<TestBatch> batches)
{
var data = batches.ToList();
var sheet = package.Workbook.Worksheets.Add("溶出报表");
WriteHeader(sheet, "检测时间", "样品名称", "通道", "30min溶出度(%)", "R²", "取样明细", "判定");
if (data.Count == 0)
{
sheet.Cells[2, 1].Value = "无溶出测试数据";
sheet.Cells.AutoFitColumns();
return;
}
int row = 2;
foreach (var b in data)
{
sheet.Cells[row, 1].Value = b.TestTime.ToString("yyyy-MM-dd HH:mm:ss");
sheet.Cells[row, 2].Value = b.SampleName;
sheet.Cells[row, 3].Value = b.DissolutionChannel;
sheet.Cells[row, 4].Value = b.DissolutionRate30Min;
sheet.Cells[row, 5].Value = b.DissolutionRSquared;
sheet.Cells[row, 6].Value = b.DissolutionSampleSummary;
sheet.Cells[row, 7].Value = b.DissolutionPassText;
row++;
}
sheet.Cells.AutoFitColumns();
AddDissolutionSamplesSheet(package, data);
AddDissolutionChartSheet(package, data);
}
private static void AddDissolutionSamplesSheet(ExcelPackage package, IEnumerable<TestBatch> batches)
{
var samples = GetDissolutionSampleRows(batches).ToList();
if (samples.Count == 0)
return;
var sheet = package.Workbook.Worksheets.Add("溶出取样明细");
WriteHeader(sheet, "检测时间", "样品名称", "通道", "计划时间(min)", "实际时间(min)", "溶出度(%)", "记录时间");
int row = 2;
foreach (var item in samples)
{
sheet.Cells[row, 1].Value = item.Batch.TestTime.ToString("yyyy-MM-dd HH:mm:ss");
sheet.Cells[row, 2].Value = item.Batch.SampleName;
sheet.Cells[row, 3].Value = item.Sample.ChannelName;
sheet.Cells[row, 4].Value = item.Sample.ScheduledTimeMin;
sheet.Cells[row, 5].Value = item.Sample.ActualTimeMin;
sheet.Cells[row, 6].Value = item.Sample.Percent;
sheet.Cells[row, 7].Value = item.Sample.RecordedAt?.ToString("yyyy-MM-dd HH:mm:ss");
row++;
}
sheet.Cells.AutoFitColumns();
}
private static void AddDissolutionChartSheet(ExcelPackage package, IEnumerable<TestBatch> batches)
{
var seriesGroups = GetDissolutionSampleRows(batches)
.Where(x => x.Sample.Percent.HasValue
&& double.IsFinite(x.Sample.ScheduledTimeMin)
&& x.Sample.ScheduledTimeMin >= 0
&& double.IsFinite(x.Sample.Percent.Value))
.GroupBy(x => new
{
x.Batch.Id,
x.Batch.TestTime,
x.Batch.SampleName,
x.Sample.ChannelName
})
.Select(group => new
{
Name = $"{group.Key.TestTime:MM-dd HH:mm} {group.Key.SampleName} {group.Key.ChannelName}",
Points = group
.OrderBy(x => x.Sample.ScheduledTimeMin)
.Select(x => new { Time = x.Sample.ScheduledTimeMin, Percent = x.Sample.Percent!.Value })
.ToList()
})
.Where(group => group.Points.Count > 0)
.ToList();
var sheet = package.Workbook.Worksheets.Add("溶出曲线");
if (seriesGroups.Count == 0)
{
sheet.Cells[1, 1].Value = "无可绘制溶出曲线数据";
sheet.Cells.AutoFitColumns();
return;
}
int column = 1;
foreach (var group in seriesGroups)
{
sheet.Cells[1, column].Value = $"{group.Name} 时间(min)";
sheet.Cells[1, column + 1].Value = $"{group.Name} 溶出度(%)";
int row = 2;
foreach (var point in group.Points)
{
sheet.Cells[row, column].Value = point.Time;
sheet.Cells[row, column + 1].Value = point.Percent;
row++;
}
column += 3;
}
using (var header = sheet.Cells[1, 1, 1, Math.Max(1, column - 2)])
{
header.Style.Font.Bold = true;
}
int dataEndRow = seriesGroups.Max(group => group.Points.Count) + 1;
int chartStartRow = dataEndRow + 2;
var chart = sheet.Drawings.AddChart("DissolutionCurve", eChartType.LineMarkers);
chart.Title.Text = "溶出曲线";
chart.SetPosition(chartStartRow - 1, 0, 0, 0);
chart.SetSize(900, 420);
chart.XAxis.Title.Text = "计划时间(min)";
chart.YAxis.Title.Text = "溶出度(%)";
chart.YAxis.MinValue = 0;
chart.YAxis.MaxValue = 150;
chart.Legend.Position = eLegendPosition.Bottom;
column = 1;
foreach (var group in seriesGroups)
{
int endRow = group.Points.Count + 1;
var series = chart.Series.Add(
sheet.Cells[2, column + 1, endRow, column + 1],
sheet.Cells[2, column, endRow, column]);
series.Header = group.Name;
column += 3;
}
sheet.Cells.AutoFitColumns();
}
private static IEnumerable<(TestBatch Batch, DissolutionSamplePoint Sample)> GetDissolutionSampleRows(IEnumerable<TestBatch> batches)
{
return batches
.SelectMany(batch => (batch.DissolutionSamples ?? Enumerable.Empty<DissolutionSamplePoint>())
.Select(sample => (Batch: batch, Sample: sample)))
.OrderBy(x => x.Batch.TestTime)
.ThenBy(x => x.Sample.Channel)
.ThenBy(x => x.Sample.ScheduledTimeMin);
}
private static IEnumerable<(TestBatch Batch, HardnessSamplePoint Sample)> GetHardnessSampleRows(IEnumerable<TestBatch> batches)
{
return batches
.SelectMany(batch => (batch.HardnessSamples ?? Enumerable.Empty<HardnessSamplePoint>())
.Select(sample => (Batch: batch, Sample: sample)))
.OrderBy(x => x.Batch.TestTime)
.ThenBy(x => x.Sample.SequenceNo);
}
private static void WriteHeader(ExcelWorksheet sheet, params string[] headers)
{
for (int i = 0; i < headers.Length; i++)
sheet.Cells[1, i + 1].Value = headers[i];
using var range = sheet.Cells[1, 1, 1, headers.Length];
range.Style.Font.Bold = true;
range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
}
}
}