diff --git a/JQSalesSummaryPanel.cs b/JQSalesSummaryPanel.cs index b14870e..c0b2a77 100644 --- a/JQSalesSummaryPanel.cs +++ b/JQSalesSummaryPanel.cs @@ -74,7 +74,7 @@ namespace KellyReport_D try { - WorkBookUtils.importSalesDetailFromWorkBook(workBook); + WorkBookUtils.ImportSalesDetailFromWorkBook(workBook); } catch (Exception ex) { diff --git a/Model/ImportContext.cs b/Model/ImportContext.cs index 34cfc2d..534bc74 100644 --- a/Model/ImportContext.cs +++ b/Model/ImportContext.cs @@ -14,6 +14,13 @@ namespace KellyReport_D.Model public Microsoft.Office.Interop.Excel.Application Application { get; set; } public IList ClientContactList { get; set; } public IList SalesDetails { get; set; } + + public List YearList => SalesDetails + .Where(x => x.InvoiceDate.HasValue) + .Select(x => x.InvoiceDate.Value.Year) + .Distinct() + .ToList(); + public class GroupedSalesDetailModel { public string SalesName { get; set; } diff --git a/Utils/WorkBookUtils.cs b/Utils/WorkBookUtils.cs index 0c279a3..84a7a22 100644 --- a/Utils/WorkBookUtils.cs +++ b/Utils/WorkBookUtils.cs @@ -12,7 +12,7 @@ namespace KellyReport_D.Utils { internal static class WorkBookUtils { - public static void importSalesDetailFromWorkBook(Workbook workbook) + public static void ImportSalesDetailFromWorkBook(Workbook workbook) { var importContext = new ImportContext() { @@ -28,8 +28,8 @@ namespace KellyReport_D.Utils foreach (var userGroupedSalesDetail in importContext.GroupedSalesDetailBySalesName) { var userSheet = GenUserSalesDetailSheet(importContext, userGroupedSalesDetail); - PrepareTotalHeader(userSheet); - WriteSalesDetailsData(importContext, userGroupedSalesDetail, userSheet); + var yearColIndex = PrepareTotalHeader(userSheet, importContext); + WriteSalesDetailsData(importContext, userGroupedSalesDetail, userSheet, yearColIndex); importContext.SalesWorksheets.Add(userSheet); } @@ -55,7 +55,7 @@ namespace KellyReport_D.Utils bussenessWorksheet = item; break; } - }; + } if (bussenessWorksheet == null) { @@ -116,25 +116,120 @@ namespace KellyReport_D.Utils } } }); - } } + private static void UpdateSalesDetailSummary(Worksheet userWorkSheet, int summaryRowStartIndex) + { + int lastColumnIndex = userWorkSheet.UsedRange.Columns.Count; + + int summaryRowIndex = summaryRowStartIndex; + int sumColStart = 13; // L列是第12列 + do + { + userWorkSheet.Cells[summaryRowIndex, 11].Value2 = "總銷量及金額(未稅)"; + for (int i = 0; i < 12; i++) + { + int quantityColIndex = sumColStart + i * 3 + 1; + string quantityColLetter = GetColumnLetter(quantityColIndex); + userWorkSheet.Cells[summaryRowIndex, quantityColIndex].formula = $"=(SUM({quantityColLetter}4:{quantityColLetter}{summaryRowIndex - 1})/2)"; + + int amountColIndex = sumColStart + i * 3 + 2; + string amountColLetter = GetColumnLetter(amountColIndex); + userWorkSheet.Cells[summaryRowIndex, amountColIndex].formula = $"=((SUM({amountColLetter}4:{amountColLetter}{summaryRowIndex - 1})/2) - {amountColLetter}{summaryRowIndex + 2})/1.13"; + } + string totalQuantityColLetter = GetColumnLetter(sumColStart + 36); + string totalAmountColLetter = GetColumnLetter(sumColStart + 37); + + userWorkSheet.Cells[summaryRowIndex, sumColStart + 36].formula = $"=(SUM({totalQuantityColLetter}4:{totalAmountColLetter}{summaryRowIndex - 1})/2)"; + userWorkSheet.Cells[summaryRowIndex, sumColStart + 37].formula = $"=((SUM({totalAmountColLetter}4:{totalAmountColLetter}{summaryRowIndex - 1})/2) - {totalAmountColLetter}{summaryRowIndex + 2})/1.13"; + + summaryRowIndex++; + userWorkSheet.Cells[summaryRowIndex, 11].Value2 = "總銷量及金額(含稅)"; + for (int i = 0; i < 12; i++) + { + int quantityColIndex = sumColStart + i * 3 + 1; + string quantityColLetter = GetColumnLetter(quantityColIndex); + userWorkSheet.Cells[summaryRowIndex, quantityColIndex].formula = $"=(SUM({quantityColLetter}4:{quantityColLetter}{summaryRowIndex - 1})/2)"; + + int amountColIndex = sumColStart + i * 3 + 2; + string amountColLetter = GetColumnLetter(amountColIndex); + userWorkSheet.Cells[summaryRowIndex, amountColIndex].formula = $"=(SUM({amountColLetter}4:{amountColLetter}{summaryRowIndex - 1})/2)"; + } + userWorkSheet.Cells[summaryRowIndex, sumColStart + 36].formula = $"=(SUM({totalQuantityColLetter}4:{totalQuantityColLetter}{summaryRowIndex - 1})/2)"; + userWorkSheet.Cells[summaryRowIndex, sumColStart + 37].formula = $"=(SUM({totalAmountColLetter}4:{totalAmountColLetter}{summaryRowIndex - 1})/2)"; + + summaryRowIndex++; + userWorkSheet.Cells[summaryRowIndex, 11].Value2 = "總銷量及金額(外銷)"; + for (int i = 0; i < 12; i++) + { + int quantityColIndex = sumColStart + i * 3 + 1; + userWorkSheet.Cells[summaryRowIndex, quantityColIndex].Value2 = 0; + + int amountColIndex = sumColStart + i * 3 + 2; + userWorkSheet.Cells[summaryRowIndex, amountColIndex].Value2 = 0; + } + userWorkSheet.Cells[summaryRowIndex, sumColStart + 36].Value2 = 0; + userWorkSheet.Cells[summaryRowIndex, sumColStart + 37].Value2 = 0; + + summaryRowIndex++; + userWorkSheet.Cells[summaryRowIndex, 11].Value2 = "總銷量及金額(內外銷)"; + for (int i = 0; i < 12; i++) + { + int quantityColIndex = sumColStart + i * 3 + 1; + string quantityColLetter = GetColumnLetter(quantityColIndex); + userWorkSheet.Cells[summaryRowIndex, quantityColIndex].formula = $"={quantityColLetter}{summaryRowIndex - 3}+{quantityColLetter}{summaryRowIndex - 1}"; + + int amountColIndex = sumColStart + i * 3 + 2; + string amountColLetter = GetColumnLetter(amountColIndex); + userWorkSheet.Cells[summaryRowIndex, amountColIndex].formula = $"={amountColLetter}{summaryRowIndex - 3}+{amountColLetter}{summaryRowIndex - 1}"; + } + userWorkSheet.Cells[summaryRowIndex, sumColStart + 36].formula = $"={totalQuantityColLetter}{summaryRowIndex - 3}+{totalQuantityColLetter}{summaryRowIndex - 1}"; + userWorkSheet.Cells[summaryRowIndex, sumColStart + 37].formula = $"={totalAmountColLetter}{summaryRowIndex - 3}+{totalAmountColLetter}{summaryRowIndex - 1}"; + + // 下一年的index + sumColStart += 38; + summaryRowIndex = summaryRowStartIndex; + } while (sumColStart < lastColumnIndex); + } + private static void GenSalesTotal(ImportContext context) { var app = context.Application; var totalWorksheet = CreateSheetIfNotExisted(app, "JQ Total(Total)"); - PrepareTotalHeader(totalWorksheet); + PrepareTotalHeader(totalWorksheet, context); + // 删除现有数据 int totalRowIndex = 4; + int lastRowIndex = totalWorksheet.UsedRange.Rows.Count; + if (lastRowIndex > totalRowIndex) + { + try + { + totalWorksheet.Application.DisplayAlerts = false; + var deleteRows = totalWorksheet.Rows[$"{totalRowIndex}:{lastRowIndex}"]; + deleteRows.UnMerge(); + deleteRows.EntireRow.Delete(XlDeleteShiftDirection.xlShiftUp); + } + catch (Exception ex) + { + Console.Error.WriteLine("delete error %s", ex.Message); + } + finally + { + totalWorksheet.Application.DisplayAlerts = true; + } + + } + foreach (var userSheet in context.SalesWorksheets) { Range usedRange = userSheet.UsedRange; int rowIndexStart = 4; - int rowIndexEnd = usedRange.Rows.Count; + int rowIndexEnd = usedRange.Rows.Count - 5; - int rowCount = rowIndexEnd - rowIndexStart + 1; + int rowCount = rowIndexEnd - rowIndexStart; if (rowCount > 1) { Range sourceRange = userSheet.Range[ @@ -148,78 +243,17 @@ namespace KellyReport_D.Utils totalWorksheet.Cells[totalRowIndexEnd, usedRange.Columns.Count] ]; sourceRange.Copy(targetRange); - totalRowIndex = totalRowIndexEnd; + totalRowIndex = totalRowIndexEnd + 1; } } totalWorksheet.Cells[totalRowIndex, 1].Value = "總結"; var sumRange = totalWorksheet.Range[ totalWorksheet.Cells[totalRowIndex, 1], - totalWorksheet.Cells[totalRowIndex + 4, 5] + totalWorksheet.Cells[totalRowIndex + 3, 5] ]; sumRange.Merge(); - - int sumColStart = 13; // L列是第12列 - totalWorksheet.Cells[totalRowIndex, 11].Value2 = "總銷量及金額(未稅)"; - for (int i = 0; i < 12; i++) - { - int quantityColIndex = sumColStart + i * 3 + 1; - string quantityColLetter = GetColumnLetter(quantityColIndex); - totalWorksheet.Cells[totalRowIndex, quantityColIndex].formula = $"=(SUM({quantityColLetter}4:{quantityColLetter}{totalRowIndex - 1})/2)"; - - int amountColIndex = sumColStart + i * 3 + 2; - string amountColLetter = GetColumnLetter(amountColIndex); - totalWorksheet.Cells[totalRowIndex, amountColIndex].formula = $"=((SUM({amountColLetter}4:{amountColLetter}{totalRowIndex - 1})/2) - {amountColLetter}{totalRowIndex + 2})/1.13"; - } - string totalQuantityColLetter = GetColumnLetter(49); - string totalAmountColLetter = GetColumnLetter(50); - - totalWorksheet.Cells[totalRowIndex, 49].formula = $"=(SUM({totalQuantityColLetter}4:{totalAmountColLetter}{totalRowIndex - 1})/2)"; - totalWorksheet.Cells[totalRowIndex, 50].formula = $"=((SUM({totalAmountColLetter}4:{totalAmountColLetter}{totalRowIndex - 1})/2) - {totalAmountColLetter}{totalRowIndex + 2})/1.13"; - - - totalRowIndex++; - totalWorksheet.Cells[totalRowIndex, 11].Value2 = "總銷量及金額(含稅)"; - for (int i = 0; i < 12; i++) - { - int quantityColIndex = sumColStart + i * 3 + 1; - string quantityColLetter = GetColumnLetter(quantityColIndex); - totalWorksheet.Cells[totalRowIndex, quantityColIndex].formula = $"=(SUM({quantityColLetter}4:{quantityColLetter}{totalRowIndex - 1})/2)"; - - int amountColIndex = sumColStart + i * 3 + 2; - string amountColLetter = GetColumnLetter(amountColIndex); - totalWorksheet.Cells[totalRowIndex, amountColIndex].formula = $"=(SUM({amountColLetter}4:{amountColLetter}{totalRowIndex - 1})/2)"; - } - totalWorksheet.Cells[totalRowIndex, 49].formula = $"=(SUM({totalQuantityColLetter}4:{totalQuantityColLetter}{totalRowIndex - 1})/2)"; - totalWorksheet.Cells[totalRowIndex, 50].formula = $"=(SUM({totalAmountColLetter}4:{totalAmountColLetter}{totalRowIndex - 1})/2)"; - - totalRowIndex++; - totalWorksheet.Cells[totalRowIndex, 11].Value2 = "總銷量及金額(外銷)"; - for (int i = 0; i < 12; i++) - { - int quantityColIndex = sumColStart + i * 3 + 1; - totalWorksheet.Cells[totalRowIndex, quantityColIndex].Value2 = 0; - - int amountColIndex = sumColStart + i * 3 + 2; - totalWorksheet.Cells[totalRowIndex, amountColIndex].Value2 = 0; - } - totalWorksheet.Cells[totalRowIndex, 49].Value2 = 0; - totalWorksheet.Cells[totalRowIndex, 50].Value2 = 0; - - totalRowIndex++; - totalWorksheet.Cells[totalRowIndex, 11].Value2 = "總銷量及金額(內外銷)"; - for (int i = 0; i < 12; i++) - { - int quantityColIndex = sumColStart + i * 3 + 1; - string quantityColLetter = GetColumnLetter(quantityColIndex); - totalWorksheet.Cells[totalRowIndex, quantityColIndex].formula = $"={quantityColLetter}{totalRowIndex - 3}+{quantityColLetter}{totalRowIndex - 1}"; - - int amountColIndex = sumColStart + i * 3 + 2; - string amountColLetter = GetColumnLetter(amountColIndex); - totalWorksheet.Cells[totalRowIndex, amountColIndex].formula = $"={amountColLetter}{totalRowIndex - 3}+{amountColLetter}{totalRowIndex - 1}"; - } - totalWorksheet.Cells[totalRowIndex, 49].formula = $"={totalQuantityColLetter}{totalRowIndex - 3}+{totalQuantityColLetter}{totalRowIndex - 1}"; - totalWorksheet.Cells[totalRowIndex, 50].formula = $"={totalAmountColLetter}{totalRowIndex - 3}+{totalAmountColLetter}{totalRowIndex - 1}"; + UpdateSalesDetailSummary(totalWorksheet, totalRowIndex); // 自适应所有已用列宽 FormatSheetStyle(totalWorksheet); @@ -256,16 +290,67 @@ namespace KellyReport_D.Utils return colLetter; } + public static int FindRowBySalesAndClient(Worksheet userSheet, string salesName, string clientName) + { + Range salesRows = userSheet.Columns[1]; + Range found = salesRows.Find(What: salesName, LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false); + if (found == null) + return 0; + + string firstAddress = found?.Address; + Range cur = found; + int result = 0; + do + { + var rIndex = cur.Row; + Range eCell = userSheet.Cells[rIndex, 5]; + var rawValue = eCell.Value2; + if (rawValue != null && string.Equals(rawValue.ToString().Trim(), clientName, StringComparison.OrdinalIgnoreCase)) + { + result = cur.Row; + break; + } + + cur = salesRows.FindNext(cur); + } while (cur != null && cur.Address != firstAddress); + + return result; + } + public static void WriteSalesDetailsData( ImportContext context, ImportContext.GroupedSalesDetailModel userGroupedSalesDetail, - Worksheet userSheet - ) + Worksheet userSheet, + int yearColIndex) { - int rowIndex = 4; // 从第四行开始写入数据 + var detailSummaryRow = userSheet.UsedRange.Find(What: "總結", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false); + int summaryRowIndex = userSheet.UsedRange.Rows.Count; // 从第四行开始写入数据 + bool hasSummary = detailSummaryRow != null; + if (hasSummary) + { + summaryRowIndex = detailSummaryRow.Row; + } + var clientSalesList = context.GetGroupedSalesDetailByClientName(userGroupedSalesDetail.Details); + foreach (var clientSalesDetail in clientSalesList) { + var clientSalesRowIndex = FindRowBySalesAndClient(userSheet, clientSalesDetail.SalesName, clientSalesDetail.ClientName); + if (clientSalesRowIndex == 0) + { + clientSalesRowIndex = summaryRowIndex; + if (hasSummary) + { + userSheet.Rows[clientSalesRowIndex].Insert(XlInsertShiftDirection.xlShiftDown); + summaryRowIndex++; + } + else + { + clientSalesRowIndex++; + summaryRowIndex++; + } + } + ClientContact clientContact = context.ClientContactList.FirstOrDefault(x => x.Name == clientSalesDetail.ClientName) ?? new ClientContact { Name = clientSalesDetail.ClientName, @@ -281,9 +366,30 @@ namespace KellyReport_D.Utils TotalAmount = grouped.Sum(x => x.TotalAmount ?? 0), Quantity = grouped.Sum(x => x.Quantity ?? 0), Details = grouped.ToList() - }); - rowIndex = WriteSalesDetailToSheet(userSheet, rowIndex, clientContact, productSalesList); + }).ToList(); + Range salesNameCell = userSheet.Cells[clientSalesRowIndex, 1]; + int curRowCount = 1; + int clientSalesRowCount = productSalesList.Count + 1; + if (salesNameCell.MergeCells) + { + Range mergedCell = salesNameCell.MergeArea; + curRowCount = mergedCell.Rows.Count; + } + // 添加行数 + if (curRowCount < clientSalesRowCount) + { + for (var i = 0; i < clientSalesRowCount - curRowCount; i++) + { + userSheet.Rows[clientSalesRowIndex + curRowCount].Insert(XlInsertShiftDirection.xlShiftDown); + summaryRowIndex++; + } + } + salesNameCell.Value2 = clientSalesDetail.SalesName; + int totalRowIndex = clientSalesRowIndex + clientSalesRowCount - 1; + userSheet.Range[userSheet.Cells[clientSalesRowIndex, 1], userSheet.Cells[totalRowIndex, 1]].Merge(); + + WriteSalesDetailToSheet(userSheet, clientSalesRowIndex, yearColIndex, clientContact, productSalesList); // 客户销量汇总 var totalSales = new List() { @@ -325,20 +431,33 @@ namespace KellyReport_D.Utils } }; - rowIndex = WriteSalesDetailToSheet(userSheet, rowIndex, clientContact, totalSales); + WriteSalesDetailToSheet(userSheet, totalRowIndex, yearColIndex, clientContact, totalSales); } + // 计算总结 + if (!hasSummary) + { + summaryRowIndex++; + } + userSheet.Cells[summaryRowIndex, 1].Value = "總結"; + var sumRange = userSheet.Range[ + userSheet.Cells[summaryRowIndex, 1], + userSheet.Cells[summaryRowIndex + 3, 5] + ]; + sumRange.Merge(); + UpdateSalesDetailSummary(userSheet, summaryRowIndex); + FormatSheetStyle(userSheet); userSheet.Cells[4, 12].Select(); userSheet.Application.ActiveWindow.FreezePanes = true; } - private static int WriteSalesDetailToSheet(Worksheet userSheet, int rowIndex, ClientContact clientContact, IEnumerable salesDetailList) + private static int WriteSalesDetailToSheet(Worksheet userSheet, int rowIndex, int yearColIndex, ClientContact clientContact, IEnumerable salesDetailList) { foreach (var productSalesDetail in salesDetailList) { - userSheet.Cells[rowIndex, 1].Value2 = productSalesDetail.SalesName; + //userSheet.Cells[rowIndex, 1].Value2 = productSalesDetail.SalesName; userSheet.Cells[rowIndex, 2].Value2 = clientContact.Region; userSheet.Cells[rowIndex, 3].Value2 = clientContact.Industry; userSheet.Cells[rowIndex, 4].Value2 = clientContact.AnnualCapacity; @@ -351,7 +470,7 @@ namespace KellyReport_D.Utils userSheet.Cells[rowIndex, 11].Value2 = productSalesDetail.ProductNameEN; // 计算每月的数量和金额 - int monthCol = 13; // L列是第12列 + int monthCol = yearColIndex; for (int i = 1; i < 13; i++) { int monthCounter = 0; @@ -373,6 +492,7 @@ namespace KellyReport_D.Utils return accSalesModel; }); + if (monthCounter > 1) { monthDetail.PriceWithTax = monthDetail.PriceWithTax / monthCounter; @@ -394,14 +514,13 @@ namespace KellyReport_D.Utils userSheet.Cells[rowIndex, 49].Value = productSalesDetail.Quantity; userSheet.Cells[rowIndex, 50].Value = productSalesDetail.TotalAmount; - rowIndex++; } return rowIndex; } - public static void PrepareTotalHeader(Worksheet userSheet) + public static int PrepareTotalHeader(Worksheet userSheet, ImportContext importContext) { // 合并A1:L1并设置标题 userSheet.Range["A1", "L1"].Merge(); @@ -434,11 +553,26 @@ namespace KellyReport_D.Utils userSheet.Range["L2"].Value2 = "需求/月"; // 计算起始列(L列后面,列号13) + int year = importContext.YearList[0]; + string yearTitle = $"{year}销售表"; int startCol = 13; + Range yearCol = userSheet.Rows[1].Find(What: yearTitle, LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false); + + if (yearCol != null) + { + // 已经存在年度销售数据,不需处理 + return yearCol.Column; + } + + for (int i = 0; i < 38; i++) + { + userSheet.Columns[13].EntireColumn.Insert(XlInsertShiftDirection.xlShiftToRight); + } + // 合并年度销售表标题 userSheet.Range[userSheet.Cells[1, startCol], userSheet.Cells[1, startCol + 37]].Merge(); - userSheet.Cells[1, startCol].Value2 = "年度销售表"; + userSheet.Cells[1, startCol].Value2 = yearTitle; // 设置月份表头 for (int i = 0; i < 12; i++) @@ -460,6 +594,8 @@ namespace KellyReport_D.Utils // 设置所有已用单元格居中 Range usedRange = userSheet.UsedRange; usedRange.HorizontalAlignment = XlHAlign.xlHAlignCenter; + + return startCol; } @@ -472,11 +608,6 @@ namespace KellyReport_D.Utils var salesName = groupedSalesDetail.SalesName ?? "UNKONW"; string sheetName = $"JQ Total({salesName.ToUpper()})"; Worksheet userSheet = CreateSheetIfNotExisted(app, sheetName); - Range usedRange = userSheet.UsedRange; - if (usedRange != null && usedRange.Cells.Count > 1) - { - usedRange.Clear(); - } return userSheet; } @@ -491,7 +622,8 @@ namespace KellyReport_D.Utils userSheet = item; break; } - }; + } + ; if (userSheet == null) { @@ -509,6 +641,28 @@ namespace KellyReport_D.Utils return userSheet; } + public static DateTime? ResolveExcelDate(object rawValue) + { + try + { + if (rawValue is double dateValue) + { + return DateTime.FromOADate(dateValue); + } + else if (rawValue != null) + { + return DateTime.Parse(rawValue.ToString()); + } + } + catch (Exception ex) + { + Console.Error.WriteLine("parse date error:" + ex.Message); + //throw new FormatException($"日期格式错误 '{rawValue}'"); + } + + return null; + + } private static void ReadSalesDetails(ImportContext context) { @@ -526,9 +680,9 @@ namespace KellyReport_D.Utils { SalesName = rawSalesDetailData[i, 1]?.ToString() ?? "UNKNOWN", Month = rawSalesDetailData[i, 2]?.ToString() ?? "", - DeliveryDate = rawSalesDetailData[i, 3] is double invoiceDate ? DateTime.FromOADate(invoiceDate) : (DateTime?)null, + DeliveryDate = ResolveExcelDate(rawSalesDetailData[i, 3]), OrderNumber = rawSalesDetailData[i, 4]?.ToString() ?? "", - InvoiceDate = rawSalesDetailData[i, 5] != null ? DateTime.Parse(rawSalesDetailData[i, 5]?.ToString()) : (DateTime?)null, + InvoiceDate = ResolveExcelDate(rawSalesDetailData[i, 5]), InvoiceNumber = rawSalesDetailData[i, 6]?.ToString() ?? "", ClientName = rawSalesDetailData[i, 7]?.ToString() ?? "", ProductNameEN = rawSalesDetailData[i, 8]?.ToString() ?? "", @@ -543,6 +697,10 @@ namespace KellyReport_D.Utils } } context.SalesDetails = salesDatailList; + if (context.YearList.Count > 1) + { + throw new Exception("抱歉,匯入的銷售資料格式有誤,每次只能處理同一個自然年的資料。"); + } } public static Workbook SelectAndOpenExcelFile() @@ -600,33 +758,57 @@ namespace KellyReport_D.Utils public static void GenBussenessSheet(GenForecaseContext context) { var app = context.Application; + Worksheet sheet = CreateSheetIfNotExisted(app, "業務月達成率"); - // 假设 app 是 Excel.Application - Worksheet sheet = null; - string sheetName = "業務月達成率"; + Range usedRange = sheet.UsedRange; + int totalRows = usedRange?.Rows?.Count ?? 0; + int yearRowIndex = 1; + Boolean updateCurrentBook = false; + while (yearRowIndex < totalRows - 1) + { + object rawYearValue = sheet.Cells[yearRowIndex, 1]?.Value2; + if (rawYearValue == null) + { + throw new Exception($"更新業務月達成率年份异常"); + } + string yearValue = ""; + if (rawYearValue is double d) + { + yearValue = (rawYearValue).ToString(); + } + + if (yearValue == context.MonthData[0]) + { + updateCurrentBook = true; + break; + } + + yearRowIndex += 15; + } try { - // 新增工作表 - sheet = app.Worksheets.Add(); - sheet.Name = sheetName; + string rowRanges = ""; + if (updateCurrentBook) + { + rowRanges = $"{yearRowIndex}:{yearRowIndex + 14}"; + Range updateRows = sheet.Rows[rowRanges]; + updateRows.Clear(); + } + else + { + yearRowIndex = 1; + rowRanges = "1:15"; + Range newRows = sheet.Rows[rowRanges]; + newRows.Insert(XlInsertShiftDirection.xlShiftDown); + } + // 插入后重新获取引用并清除新行格式 + Range targetRows = sheet.Rows[rowRanges]; + targetRows.ClearFormats(); } - catch + catch (Exception ex) { - // 已存在则获取 - sheet = app.Worksheets[sheetName] as Worksheet; - try - { - Range usedRange = sheet.UsedRange; - if (usedRange != null && usedRange.Cells.Count > 1) - { - usedRange.Clear(); - } - } - catch - { - // 无 UsedRange 可忽略 - } + throw new Exception($"更新{context.MonthData[0]}年業務月達成率失败", ex); } // 合并A1:A2并填入年份 @@ -634,12 +816,12 @@ namespace KellyReport_D.Utils { var monthData = context.MonthData; var yearValue = monthData[0]; - Range yearRange = sheet.Range["A1", "A2"]; + Range yearRange = sheet.Range[$"A{yearRowIndex}", $"A{yearRowIndex + 1}"]; yearRange.Merge(); yearRange.Value2 = yearValue.ToString(); yearRange.NumberFormat = "@"; // 文本格式 - int startRowIndex = 1; + int startRowIndex = yearRowIndex; // 填入月份 for (int i = 0; i < 12; i++) { @@ -717,7 +899,6 @@ namespace KellyReport_D.Utils } - private static void ReadClientContact(ImportContext context) { var app = context.Application; @@ -837,6 +1018,10 @@ namespace KellyReport_D.Utils Total = rawSalesData[i, 14] != null ? Convert.ToDecimal(rawSalesData[i, 14]) : 0, }; salesForecastInputList.Add(input); + + // 只读取第一段的数据 + if (input.Name == "total") + break; } } @@ -852,13 +1037,7 @@ namespace KellyReport_D.Utils Worksheet productSheet = CreateSheetIfNotExisted(app, sheetName); productSheet.Activate(); - var yearList = context.SalesDetails - .Where(x => x.InvoiceDate.HasValue) - .Select(x => x.InvoiceDate.Value.Year) - .Distinct() - .ToList(); - - yearList.ForEach(yearNumber => + context.YearList.ForEach(yearNumber => { Range usedRange = productSheet.UsedRange; @@ -1020,6 +1199,13 @@ namespace KellyReport_D.Utils var startColLetter = GetColumnLetter(startCol); var endColLetter = GetColumnLetter(startCol + 3); + if (curYearRange == null) + { + deptSheet.Range[$"{startColLetter}:{endColLetter}"] + .EntireColumn + .Insert(XlInsertShiftDirection.xlShiftToRight); + } + Range prevYearRange = deptSheet.UsedRange.Find(What: $"{yearNumber - 1}", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false); int prevStartCol = 0; string prevForecastColLetter = ""; @@ -1031,11 +1217,7 @@ namespace KellyReport_D.Utils prevTurnoverColLetter = GetColumnLetter(prevStartCol + 1); } - deptSheet.Range[$"{startColLetter}:{endColLetter}"] - .EntireColumn - .Insert(XlInsertShiftDirection.xlShiftToRight); - - deptSheet.Cells[1, 2].Value2 = $"{yearNumber}"; + deptSheet.Cells[1, startCol].Value2 = $"{yearNumber}"; deptSheet.Range[deptSheet.Cells[1, startCol], deptSheet.Cells[1, startCol + 3]].Merge(); deptSheet.Cells[2, startCol].Value2 = "Forecast"; @@ -1095,9 +1277,7 @@ namespace KellyReport_D.Utils Worksheet deptSheet = CreateSheetIfNotExisted(app, sheetName); deptSheet.Activate(); - var yearList = context.SalesDetails.Where(x => x.InvoiceDate.HasValue).Select(x => x.InvoiceDate.Value.Year).Distinct().ToList(); - - yearList.ForEach(yearoNumber => + context.YearList.ForEach(yearoNumber => { Range yearRange = deptSheet.UsedRange.Find(What: $"{yearoNumber}", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);