From 4ce03e8fdaf235418f134a1547e5c3ee72eb4d4e Mon Sep 17 00:00:00 2001 From: "earo.lau" Date: Sun, 7 Sep 2025 17:36:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B1=87=E6=80=BB=E6=9C=88=E8=BE=BE=E6=88=90?= =?UTF-8?q?=E7=8E=87=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Model/ImportContext.cs | 2 +- Utils/WorkBookUtils.cs | 122 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 108 insertions(+), 16 deletions(-) diff --git a/Model/ImportContext.cs b/Model/ImportContext.cs index 6dbfa3d..34cfc2d 100644 --- a/Model/ImportContext.cs +++ b/Model/ImportContext.cs @@ -21,7 +21,7 @@ namespace KellyReport_D.Model public string ProductNameEN { get; set; } public decimal TotalAmount { get; set; } public decimal Quantity { get; set; } - public List Details { get; set; } + public IList Details { get; set; } } public IEnumerable GroupedSalesDetailBySalesName => SalesDetails diff --git a/Utils/WorkBookUtils.cs b/Utils/WorkBookUtils.cs index 17d79b4..556ca51 100644 --- a/Utils/WorkBookUtils.cs +++ b/Utils/WorkBookUtils.cs @@ -35,6 +35,87 @@ namespace KellyReport_D.Utils } GenSalesTotal(importContext); + + // 更新业务预估表 + UpdateEstimatedTable(importContext); + } + + private static void UpdateEstimatedTable(ImportContext importContext) + { + var app = importContext.Application; + Worksheet bussenessWorksheet = null; + + foreach (Worksheet item in app.Worksheets) + { + if (item.Name == "業務月達成率") + { + bussenessWorksheet = item; + break; + } + }; + + if (bussenessWorksheet == null) + { + throw new EntryPointNotFoundException("未找到「業務月達成率」工作表,请先生成预估表。"); + } + + bussenessWorksheet.Activate(); + Range usedRange = bussenessWorksheet.UsedRange; + int maxColIndex = usedRange.Columns.Count; + + for (int i = 2; i < maxColIndex; i += 4) + { + String salesName = bussenessWorksheet.Cells[1, i].Value2; + if (string.IsNullOrWhiteSpace(salesName)) + { + continue; + } + + var salesDetails = salesName.ToUpper() == "TOTAL" ? + importContext.SalesDetails : + importContext.GroupedSalesDetailBySalesName.FirstOrDefault(x => x.SalesName.ToUpper() == salesName.ToUpper())?.Details; + + if (salesDetails == null) + continue; + + salesDetails.GroupBy(x => x.Month) + .Select(grouped => new + { + Month = grouped.Key, + TotalAmount = grouped.Sum(x => x.TotalAmount ?? 0), + }) + .ToList() + .ForEach(monthlySales => + { + int startRowIndex = 3; + for (int rowIndex = startRowIndex; rowIndex < startRowIndex + 12; rowIndex++) + { + var monthCell = bussenessWorksheet.Cells[rowIndex, 1]; + if (monthCell.Value2 != null && monthCell.Value2.ToString() == monthlySales.Month) + { + var forecsastColLetter = GetColumnLetter(i); + + var turnoverCell = bussenessWorksheet.Cells[rowIndex, i + 1]; + var turnoverColLetter = GetColumnLetter(i + 1); + + turnoverCell.Value2 = monthlySales.TotalAmount; + turnoverCell.NumberFormat = "#,##0"; + + var completionCell = bussenessWorksheet.Cells[rowIndex, i + 2]; + completionCell.formula = $"={turnoverColLetter}{rowIndex}/{forecsastColLetter}{rowIndex}"; + completionCell.NumberFormat = "0.00%"; + + var accCompletionCell = bussenessWorksheet.Cells[rowIndex, i + 3]; + accCompletionCell.formula = $"=SUM(${turnoverColLetter}${startRowIndex}:{turnoverColLetter}{rowIndex})/SUM(${forecsastColLetter}${startRowIndex}:{forecsastColLetter}{rowIndex})"; + accCompletionCell.NumberFormat = "0.00%"; + + break; + } + } + }); + + } + } private static void GenSalesTotal(ImportContext context) @@ -139,10 +220,15 @@ namespace KellyReport_D.Utils // 自适应所有已用列宽 FormatSheetStyle(totalWorksheet); + + totalWorksheet.Cells[4, 12].Select(); + totalWorksheet.Application.ActiveWindow.FreezePanes = true; } private static void FormatSheetStyle(Worksheet worksheet) { + worksheet.Activate(); + // 自适应所有已用列宽 Range usedRange2 = worksheet.UsedRange; if (usedRange2 != null) @@ -151,11 +237,6 @@ namespace KellyReport_D.Utils usedRange2.Borders.LineStyle = XlLineStyle.xlContinuous; usedRange2.Borders.Weight = XlBorderWeight.xlThin; } - worksheet.Cells[4, 12].Select(); - - //worksheet.Application.ActiveWindow.SplitRow = 3; - //worksheet.Application.ActiveWindow.SplitColumn = 10; - worksheet.Application.ActiveWindow.FreezePanes = true; } @@ -245,6 +326,9 @@ namespace KellyReport_D.Utils } FormatSheetStyle(userSheet); + + userSheet.Cells[4, 12].Select(); + userSheet.Application.ActiveWindow.FreezePanes = true; } private static int WriteSalesDetailToSheet(Worksheet userSheet, int rowIndex, ClientContact clientContact, IEnumerable salesDetailList) @@ -551,17 +635,20 @@ namespace KellyReport_D.Utils yearRange.Value2 = yearValue.ToString(); yearRange.NumberFormat = "@"; // 文本格式 + int startRowIndex = 1; // 填入月份 - for (int i = 1; i < monthData.Length; i++) + for (int i = 0; i < 12; i++) { - sheet.Cells[i + 2, 1] = monthData[i]; + int rowOffset = startRowIndex + 2; + sheet.Cells[i + rowOffset, 1] = $"{i + 1}月"; } + sheet.Cells[startRowIndex + 14, 1].value2 = "Total"; // B列开始填 salesName 及相关数据 int col = 2; // B列 foreach (var salesForcastData in context.SalesForecastList) { - int rowIndex = 1; // Excel 行号从1开始 + int rowIndex = startRowIndex; // Excel 行号从1开始 int startCol = col; int endCol = col + 4; @@ -576,7 +663,7 @@ namespace KellyReport_D.Utils // 合并并填入“完成%” Range finishRange = sheet.Range[ sheet.Cells[rowIndex, startCol + 2], - sheet.Cells[rowIndex, startCol + 2] + sheet.Cells[rowIndex + 1, startCol + 2] ]; finishRange.Merge(); finishRange.Value2 = "完成%"; @@ -584,7 +671,7 @@ namespace KellyReport_D.Utils // 合并并填入“累積達成率” Range accRange = sheet.Range[ sheet.Cells[rowIndex, startCol + 3], - sheet.Cells[rowIndex, startCol + 3] + sheet.Cells[rowIndex + 1, startCol + 3] ]; accRange.Merge(); accRange.Value2 = "累積達成率"; @@ -603,16 +690,21 @@ namespace KellyReport_D.Utils cell.NumberFormat = "#,##0"; rowIndex++; } + var forecastColLetter = GetColumnLetter(col); + var turnoverColLetter = GetColumnLetter(col + 1); + + sheet.Cells[rowIndex, col].formula = $"=SUM({forecastColLetter}{startRowIndex}:{forecastColLetter}{rowIndex - 1})"; + sheet.Cells[rowIndex, col + 1].formula = $"=SUM({turnoverColLetter}{startRowIndex}:{turnoverColLetter}{rowIndex - 1})"; + + sheet.Cells[rowIndex, col + 2].formula = $"=SUM({turnoverColLetter}{rowIndex}/{forecastColLetter}{rowIndex})"; + sheet.Cells[rowIndex, col + 2].NumberFormat = "0.00%"; col = endCol; } + // 自适应所有已用列宽 - Range usedRange2 = sheet.UsedRange; - if (usedRange2 != null) - { - usedRange2.Columns.AutoFit(); - } + FormatSheetStyle(sheet); } catch (Exception ex) {