更新excel 数据 C值更新

This commit is contained in:
GukSang.Jin
2026-06-01 16:48:38 +08:00
parent b891a5b8a0
commit f5f4dc73ac
5 changed files with 83 additions and 10 deletions

View File

@@ -18,7 +18,7 @@ public sealed class ModbusRealtimeDataService : IRealtimeDataService
private const ushort OrificeTemperatureRegister = 30; private const ushort OrificeTemperatureRegister = 30;
private const ushort SampleTemperatureRegister = 36; private const ushort SampleTemperatureRegister = 36;
private const ushort AbsorbanceRegister = 120; private const ushort AbsorbanceRegister = 120;
private const ushort CFactorRegister = 312; private const ushort CFactorRegister = 308;
private const ushort HeatReleaseRateRegister = 354; private const ushort HeatReleaseRateRegister = 354;
private const ushort PeakHeatReleaseRateRegister = 376; private const ushort PeakHeatReleaseRateRegister = 376;
private const ushort Qa180Register = 366; private const ushort Qa180Register = 366;

View File

@@ -153,6 +153,9 @@ public sealed class NpoiReportExportService : IReportExportService
{ {
ClearSheet(sheet); ClearSheet(sheet);
var fourDecimalCellStyle = sheet.Workbook.CreateCellStyle();
fourDecimalCellStyle.DataFormat = sheet.Workbook.CreateDataFormat().GetFormat("0.0000");
var headerRow = sheet.CreateRow(0); var headerRow = sheet.CreateRow(0);
for (var i = 0; i < DataHeaders.Length; i++) for (var i = 0; i < DataHeaders.Length; i++)
{ {
@@ -191,7 +194,7 @@ public sealed class NpoiReportExportService : IReportExportService
SetNumeric(row, 22, record.CurrentMass); SetNumeric(row, 22, record.CurrentMass);
SetNumeric(row, 23, record.InitialMass); SetNumeric(row, 23, record.InitialMass);
SetNumeric(row, 24, record.PeakHeatReleaseRate); SetNumeric(row, 24, record.PeakHeatReleaseRate);
SetNumeric(row, 25, record.CFactor); SetNumeric(row, 25, record.CFactor, fourDecimalCellStyle);
} }
for (var i = 0; i < DataHeaders.Length; i++) for (var i = 0; i < DataHeaders.Length; i++)
@@ -524,11 +527,16 @@ public sealed class NpoiReportExportService : IReportExportService
} }
} }
private static void SetNumeric(IRow row, int columnIndex, double value) private static void SetNumeric(IRow row, int columnIndex, double value, ICellStyle? cellStyle = null)
{ {
if (double.IsFinite(value)) if (double.IsFinite(value))
{ {
row.CreateCell(columnIndex).SetCellValue(value); var cell = row.CreateCell(columnIndex);
cell.SetCellValue(value);
if (cellStyle is not null)
{
cell.CellStyle = cellStyle;
}
} }
} }
@@ -601,7 +609,9 @@ public sealed class NpoiReportExportService : IReportExportService
private static string FormatValue(double? value) private static string FormatValue(double? value)
{ {
return value is null || !double.IsFinite(value.Value) ? "" : $"{value.Value:0.00}"; return value is null || !double.IsFinite(value.Value)
? ""
: value.Value.ToString("0.0000", CultureInfo.InvariantCulture);
} }
private static string FormatSeconds(int? value) private static string FormatSeconds(int? value)

View File

@@ -25,7 +25,10 @@ public sealed class MainViewModel : ObservableObject
_deviceStatusText = tcpDeviceConnectionService.StatusText; _deviceStatusText = tcpDeviceConnectionService.StatusText;
_tcpDeviceConnectionService.ConnectionStatusChanged += DeviceConnectionStatusChanged; _tcpDeviceConnectionService.ConnectionStatusChanged += DeviceConnectionStatusChanged;
var testPage = new TestPageViewModel(experimentDataService, tcpDeviceConnectionService); var testPage = new TestPageViewModel(experimentDataService, tcpDeviceConnectionService);
var reportPage = new ReportPageViewModel(experimentDataService, reportExportService); var reportPage = new ReportPageViewModel(
experimentDataService,
reportExportService,
tcpDeviceConnectionService);
NavigationItems = []; NavigationItems = [];
var testItem = new NavigationItemViewModel("测试界面", testPage); var testItem = new NavigationItemViewModel("测试界面", testPage);

View File

@@ -31,14 +31,14 @@ public sealed class ReportFieldViewModel : ObservableObject
} }
} }
public void SetAutoValue(string value) public void SetAutoValue(string value, bool overwriteManual = false)
{ {
if (string.IsNullOrWhiteSpace(value)) if (string.IsNullOrWhiteSpace(value))
{ {
return; return;
} }
if (!string.IsNullOrWhiteSpace(Value) && !_isAutoFilled) if (!overwriteManual && !string.IsNullOrWhiteSpace(Value) && !_isAutoFilled)
{ {
return; return;
} }

View File

@@ -14,16 +14,26 @@ namespace ConeCalorimeter.ViewModels;
public sealed class ReportPageViewModel : PageViewModel public sealed class ReportPageViewModel : PageViewModel
{ {
private const ushort CFactorRegister = 308;
private const double CFactorMinimum = 0;
private const double CFactorMaximum = 1000;
private const double DisplayZeroTolerance = 0.00005;
private const string FourDecimalDisplayFormat = "0.0000";
private readonly IExperimentDataService _experimentDataService; private readonly IExperimentDataService _experimentDataService;
private readonly IReportExportService _reportExportService; private readonly IReportExportService _reportExportService;
private readonly ITcpDeviceConnectionService _tcpDeviceConnectionService;
private ModbusFloatByteOrder? _cFactorByteOrder;
private string _statusText = "报表信息可手动录入,导出时会合并当前采集数据。"; private string _statusText = "报表信息可手动录入,导出时会合并当前采集数据。";
public ReportPageViewModel( public ReportPageViewModel(
IExperimentDataService experimentDataService, IExperimentDataService experimentDataService,
IReportExportService reportExportService) : base("报表") IReportExportService reportExportService,
ITcpDeviceConnectionService tcpDeviceConnectionService) : base("报表")
{ {
_experimentDataService = experimentDataService; _experimentDataService = experimentDataService;
_reportExportService = reportExportService; _reportExportService = reportExportService;
_tcpDeviceConnectionService = tcpDeviceConnectionService;
Sections = CreateSections(); Sections = CreateSections();
SummaryItems = SummaryItems =
@@ -160,6 +170,7 @@ public sealed class ReportPageViewModel : PageViewModel
return; return;
} }
RefreshCurrentCValueReportField(overwriteManual: true);
var input = BuildInput(); var input = BuildInput();
var defaultName = BuildDefaultFileName(input); var defaultName = BuildDefaultFileName(input);
var dialog = new SaveFileDialog var dialog = new SaveFileDialog
@@ -255,6 +266,48 @@ public sealed class ReportPageViewModel : PageViewModel
FindField("EndTime")?.SetAutoValue(FormatSeconds(LastNonNegative(records, record => record.TestSeconds))); FindField("EndTime")?.SetAutoValue(FormatSeconds(LastNonNegative(records, record => record.TestSeconds)));
} }
private void RefreshCurrentCValueReportField(bool overwriteManual)
{
if (TryReadCurrentCValueText(out var value))
{
FindField("CFactor")?.SetAutoValue(value, overwriteManual);
}
}
private bool TryReadCurrentCValueText(out string value)
{
value = string.Empty;
if (!_tcpDeviceConnectionService.TryReadFloatValues(CFactorRegister, out var result))
{
Log.Warning(
"Report C factor D{RegisterAddress} read failed before export. ConnectionStatus={ConnectionStatus}.",
CFactorRegister,
_tcpDeviceConnectionService.StatusText);
return false;
}
if (!ModbusFloatSelector.TrySelectRangedFloat(
result,
CFactorMinimum,
CFactorMaximum,
out var byteOrder,
out var cFactor,
out var matchCount,
_cFactorByteOrder))
{
Log.Warning(
"Report C factor D{RegisterAddress} has no valid decoded value. Raw={RawHex}, Matches={MatchCount}.",
CFactorRegister,
result.RawHex,
matchCount);
return false;
}
_cFactorByteOrder = byteOrder;
value = FormatValue(NormalizeDisplayValue(cFactor));
return true;
}
private ReportFieldViewModel? FindField(string key) private ReportFieldViewModel? FindField(string key)
{ {
return Sections.SelectMany(section => section.Fields) return Sections.SelectMany(section => section.Fields)
@@ -296,7 +349,14 @@ public sealed class ReportPageViewModel : PageViewModel
private static string FormatValue(double value) private static string FormatValue(double value)
{ {
return double.IsFinite(value) ? $"{value:0.00}" : string.Empty; return double.IsFinite(value)
? value.ToString(FourDecimalDisplayFormat, CultureInfo.InvariantCulture)
: string.Empty;
}
private static double NormalizeDisplayValue(double value)
{
return Math.Abs(value) < DisplayZeroTolerance ? 0 : value;
} }
private static bool IsValidExperimentRecord(RealtimeDataRecord record) private static bool IsValidExperimentRecord(RealtimeDataRecord record)