diff --git a/YLErpDAL/Modules/ReportModule/SettlementReportModule/SettlementReportFotShanXiService.cs b/YLErpDAL/Modules/ReportModule/SettlementReportModule/SettlementReportFotShanXiService.cs
index 565e604f..21736f28 100644
--- a/YLErpDAL/Modules/ReportModule/SettlementReportModule/SettlementReportFotShanXiService.cs
+++ b/YLErpDAL/Modules/ReportModule/SettlementReportModule/SettlementReportFotShanXiService.cs
@@ -1,4 +1,5 @@
using BaseOUDAL;
+using Newtonsoft.Json;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using Org.BouncyCastle.Ocsp;
@@ -309,6 +310,7 @@ namespace YLErp.Modules.ReportModule.SettlementReportModule
, shouldDeleteSheet: true, needToPdf: false, callback: sheets =>
{
FormatSwapValuationDisplayCells(sheets, report.EodSwapPositions);
+ ApplySwapValuationColumnConfig(sheets);
});
if (needToPdf)
{
@@ -384,6 +386,135 @@ namespace YLErp.Modules.ReportModule.SettlementReportModule
cell.Style.Numberformat.Format = "@";
}
+ ///
+ /// 每日估值报告的互换估值导出使用当前用户已保存的列配置,
+ /// 同时同步业务字段的显示状态和列顺序。
+ ///
+ private void ApplySwapValuationColumnConfig(IEnumerable sheets)
+ {
+ var worksheet = sheets.FirstOrDefault(x => x.Name == "互换估值");
+ if (worksheet == null)
+ {
+ return;
+ }
+
+ var config = configcolumnBLL.GetData(UserId, configcolumn_data.互换估值V1);
+ if (string.IsNullOrWhiteSpace(config?.data))
+ {
+ return;
+ }
+
+ List columns;
+ try
+ {
+ columns = JsonConvert.DeserializeObject>(config.data);
+ }
+ catch (JsonException)
+ {
+ // 列配置损坏时保留完整的模板字段,不能导致每日估值报告导出失败。
+ return;
+ }
+
+ if (columns == null || !columns.Any())
+ {
+ return;
+ }
+
+ var columnIndexByName = new Dictionary
+ {
+ ["ConfrimNo"] = 1,
+ ["TradeNumber"] = 2,
+ ["position.PosiStartDate"] = 3,
+ ["MaturitySettlementDate"] = 4,
+ ["position.ValueDate"] = 5,
+ ["position.UnderlyingCode"] = 6,
+ ["InterestRate"] = 7,
+ ["position.PosiNotionalValue"] = 8,
+ ["position.PosiQuantity"] = 9,
+ ["PeriodAmount"] = 10,
+ ["DividendAmount"] = 11,
+ ["position.PosiGrossPrice"] = 12,
+ ["InitYtm"] = 13,
+ ["position.UnderlyingPrice"] = 14,
+ ["DayCount"] = 15,
+ ["FloatRateAbs"] = 16,
+ ["InterestAmount"] = 17,
+ ["position.PosiProfitSum"] = 18,
+ ["position.PosiFeePending"] = 19,
+ ["OpenMarginRate"] = 20,
+ ["MarginInterestAmount"] = 21,
+ ["OpenMarginAmount"] = 22,
+ ["AdditionalMarginAmount"] = 23,
+ ["NetSettmentAmount"] = 24,
+ ["TrsValue"] = 25
+ };
+ // 前端 _.uniqBy 保留首次出现的配置项,导出按相同规则过滤重复字段,
+ // 并保留该列表的原始顺序作为 Excel 列顺序。
+ var visibleColumnIndexes = new List();
+ var configuredNames = new HashSet();
+ foreach (var column in columns)
+ {
+ if (column == null || string.IsNullOrEmpty(column.name) || !configuredNames.Add(column.name))
+ {
+ continue;
+ }
+
+ if (!column.hidden && columnIndexByName.TryGetValue(column.name, out var index))
+ {
+ visibleColumnIndexes.Add(index);
+ }
+ }
+
+ // 与前端一致:旧配置缺少的新增字段默认隐藏;若没有任何业务列可见,
+ // 前端会回退展示全部默认列,导出保持模板默认顺序。
+ if (!visibleColumnIndexes.Any())
+ {
+ return;
+ }
+
+ ReorderSwapValuationColumns(worksheet, visibleColumnIndexes);
+ }
+
+ ///
+ /// 使用临时工作表保存可见列,再按目标顺序复制回原工作表。
+ /// 原工作表始终保持在模板的 25 列范围内,避免 EPPlus 扩列时触发 ColumnMax 冲突。
+ ///
+ private static void ReorderSwapValuationColumns(ExcelWorksheet worksheet, IReadOnlyList visibleSourceIndexes)
+ {
+ var lastRow = worksheet.Dimension.End.Row;
+ var originalColumnCount = worksheet.Dimension.End.Column;
+ var workbook = worksheet.Workbook;
+ var bufferName = "__swap_cols_" + Guid.NewGuid().ToString("N").Substring(0, 12);
+ var buffer = workbook.Worksheets.Add(bufferName);
+ try
+ {
+ for (var targetIndex = 0; targetIndex < visibleSourceIndexes.Count; targetIndex++)
+ {
+ var sourceColumn = visibleSourceIndexes[targetIndex];
+ var bufferColumn = targetIndex + 1;
+ worksheet.Cells[1, sourceColumn, lastRow, sourceColumn]
+ .Copy(buffer.Cells[1, bufferColumn, lastRow, bufferColumn]);
+ }
+
+ for (var targetIndex = 0; targetIndex < visibleSourceIndexes.Count; targetIndex++)
+ {
+ var targetColumn = targetIndex + 1;
+ buffer.Cells[1, targetColumn, lastRow, targetColumn]
+ .Copy(worksheet.Cells[1, targetColumn, lastRow, targetColumn]);
+ }
+
+ var columnsToDelete = originalColumnCount - visibleSourceIndexes.Count;
+ if (columnsToDelete > 0)
+ {
+ worksheet.DeleteColumn(visibleSourceIndexes.Count + 1, columnsToDelete);
+ }
+ }
+ finally
+ {
+ workbook.Worksheets.Delete(buffer);
+ }
+ }
+
///
/// 财务状况
///