using KellyReport_D.Properties; using System.Windows.Forms; using Microsoft.Office.Interop.Excel; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using KellyReport_D.Model; namespace KellyReport_D.Utils { internal static class WorkBookUtils { public static void importSalesDetailFromWorkBook(Workbook workbook) { var importContext = new ImportContext() { Application = Globals.ThisAddIn.Application, ImportWorkbook = workbook, SalesWorksheets = new List(), }; // 获取「客户资料」工作表 ReadClientContact(importContext); // 读取「销售明细」工作表 ReadSalesDetails(importContext); foreach (var userGroupedSalesDetail in importContext.GroupedSalesDetailBySalesName) { var userSheet = GenUserSalesDetailSheet(importContext, userGroupedSalesDetail); PrepareTotalHeader(userSheet); WriteSalesDetailsData(importContext, userGroupedSalesDetail, userSheet); importContext.SalesWorksheets.Add(userSheet); } 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) { var app = context.Application; var totalWorksheet = CreateSheetIfNotExisted(app, "JQ Total(Total)"); PrepareTotalHeader(totalWorksheet); int totalRowIndex = 4; foreach (var userSheet in context.SalesWorksheets) { Range usedRange = userSheet.UsedRange; int rowIndexStart = 4; int rowIndexEnd = usedRange.Rows.Count; int rowCount = rowIndexEnd - rowIndexStart + 1; if (rowCount > 1) { Range sourceRange = userSheet.Range[ userSheet.Cells[rowIndexStart, 1], userSheet.Cells[rowIndexEnd, usedRange.Columns.Count] ]; int totalRowIndexEnd = totalRowIndex + rowCount; Range targetRange = totalWorksheet.Range[ totalWorksheet.Cells[totalRowIndex, 1], totalWorksheet.Cells[totalRowIndexEnd, usedRange.Columns.Count] ]; sourceRange.Copy(targetRange); totalRowIndex = totalRowIndexEnd; } } totalWorksheet.Cells[totalRowIndex, 1].Value = "總結"; var sumRange = totalWorksheet.Range[ totalWorksheet.Cells[totalRowIndex, 1], totalWorksheet.Cells[totalRowIndex + 4, 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}"; // 自适应所有已用列宽 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) { usedRange2.Columns.AutoFit(); usedRange2.Borders.LineStyle = XlLineStyle.xlContinuous; usedRange2.Borders.Weight = XlBorderWeight.xlThin; } } // 列号转字母方法 private static string GetColumnLetter(int col) { string colLetter = ""; while (col > 0) { int mod = (col - 1) % 26; colLetter = (char)(65 + mod) + colLetter; col = (col - mod - 1) / 26; } return colLetter; } public static void WriteSalesDetailsData( ImportContext context, ImportContext.GroupedSalesDetailModel userGroupedSalesDetail, Worksheet userSheet ) { int rowIndex = 4; // 从第四行开始写入数据 var clientSalesList = context.GetGroupedSalesDetailByClientName(userGroupedSalesDetail.Details); foreach (var clientSalesDetail in clientSalesList) { ClientContact clientContact = context.ClientContactList.FirstOrDefault(x => x.Name == clientSalesDetail.ClientName) ?? new ClientContact { Name = clientSalesDetail.ClientName, }; var productSalesList = clientSalesDetail.Details .GroupBy(x => x.ProductNameEN) .Select(grouped => new ImportContext.GroupedSalesDetailModel { SalesName = clientSalesDetail.SalesName, ClientName = clientSalesDetail.ClientName, ProductNameEN = grouped.Key, TotalAmount = grouped.Sum(x => x.TotalAmount ?? 0), Quantity = grouped.Sum(x => x.Quantity ?? 0), Details = grouped.ToList() }); rowIndex = WriteSalesDetailToSheet(userSheet, rowIndex, clientContact, productSalesList); // 客户销量汇总 var totalSales = new List() { new ImportContext.GroupedSalesDetailModel { SalesName = clientSalesDetail.SalesName, ClientName = clientSalesDetail.ClientName, ProductNameEN = "總銷售額", TotalAmount = clientSalesDetail.TotalAmount, Quantity = clientSalesDetail.Quantity, Details = clientSalesDetail.Details.Aggregate( new List(), (accDetail, curDetail) => { var monthSales = accDetail.FirstOrDefault(x => x.Month == curDetail.Month); if (monthSales == null) { monthSales = new SalesDetail { Month = curDetail.Month, SalesName = curDetail.SalesName, ProductNameEN = "總銷售額", Quantity = 0, Tax = 0, TotalAmount = 0, PriceWithTax = 0, AmountWithoutTax = 0 }; accDetail.Add(monthSales); } monthSales.Quantity += curDetail.Quantity; monthSales.Tax += curDetail.Tax; monthSales.TotalAmount += curDetail.TotalAmount; //monthSales.PriceWithTax += curDetail.PriceWithTax; monthSales.AmountWithoutTax += curDetail.AmountWithoutTax; return accDetail; }) } }; rowIndex = WriteSalesDetailToSheet(userSheet, rowIndex, clientContact, totalSales); } FormatSheetStyle(userSheet); userSheet.Cells[4, 12].Select(); userSheet.Application.ActiveWindow.FreezePanes = true; } private static int WriteSalesDetailToSheet(Worksheet userSheet, int rowIndex, ClientContact clientContact, IEnumerable salesDetailList) { foreach (var productSalesDetail in salesDetailList) { 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; userSheet.Cells[rowIndex, 5].Value2 = clientContact.Name; userSheet.Cells[rowIndex, 6].Value2 = clientContact.PurchasingManager; userSheet.Cells[rowIndex, 7].Value2 = clientContact.PurchasingManagerPhone; userSheet.Cells[rowIndex, 8].Value2 = clientContact.Purchaser; userSheet.Cells[rowIndex, 9].Value2 = clientContact.PurchaserPhone; userSheet.Cells[rowIndex, 10].Value2 = clientContact.Address; userSheet.Cells[rowIndex, 11].Value2 = productSalesDetail.ProductNameEN; // 计算每月的数量和金额 int monthCol = 13; // L列是第12列 for (int i = 1; i < 13; i++) { int monthCounter = 0; var monthDetail = productSalesDetail.Details.Where(x => x.Month == $"{i}月") .Aggregate(new SalesDetail() { Month = $"{i}月", Quantity = 0, TotalAmount = 0, PriceWithTax = 0, AmountWithoutTax = 0, Tax = 0 }, (accSalesModel, curSalesModel) => { accSalesModel.Quantity += (curSalesModel.Quantity ?? 0); accSalesModel.TotalAmount += (curSalesModel.TotalAmount ?? 0); accSalesModel.PriceWithTax += (curSalesModel.PriceWithTax ?? 0); monthCounter++; return accSalesModel; }); if (monthCounter > 1) { monthDetail.PriceWithTax = monthDetail.PriceWithTax / monthCounter; } if (monthDetail == null) { userSheet.Cells[rowIndex, monthCol + (i - 1) * 3].Value2 = 0; // 單價 userSheet.Cells[rowIndex, monthCol + (i - 1) * 3 + 1].Value2 = 0; // 數量 userSheet.Cells[rowIndex, monthCol + (i - 1) * 3 + 2].Value2 = 0; // 金額 } else { userSheet.Cells[rowIndex, monthCol + (i - 1) * 3].Value2 = monthDetail.PriceWithTax ?? 0; // 單價 userSheet.Cells[rowIndex, monthCol + (i - 1) * 3 + 1].Value2 = monthDetail.Quantity ?? 0; // 數量 userSheet.Cells[rowIndex, monthCol + (i - 1) * 3 + 2].Value2 = monthDetail.TotalAmount ?? 0; // 总额 } } userSheet.Cells[rowIndex, 49].Value = productSalesDetail.Quantity; userSheet.Cells[rowIndex, 50].Value = productSalesDetail.TotalAmount; rowIndex++; } return rowIndex; } public static void PrepareTotalHeader(Worksheet userSheet) { // 合并A1:L1并设置标题 userSheet.Range["A1", "L1"].Merge(); userSheet.Range["A1"].Value2 = "客戶資料"; // 合并并设置各列标题 userSheet.Range["A2", "A3"].Merge(); userSheet.Range["A2"].Value2 = "業務"; userSheet.Range["B2", "B3"].Merge(); userSheet.Range["B2"].Value2 = "地區"; userSheet.Range["C2", "C3"].Merge(); userSheet.Range["C2"].Value2 = "行業"; userSheet.Range["D2", "D3"].Merge(); userSheet.Range["D2"].Value2 = "產能/年"; userSheet.Range["E2", "E3"].Merge(); userSheet.Range["E2"].Value2 = "名稱"; userSheet.Range["F2", "F3"].Merge(); userSheet.Range["F2"].Value2 = "採購主管"; userSheet.Range["G2", "G3"].Merge(); userSheet.Range["G2"].Value2 = "電話"; userSheet.Range["H2", "H3"].Merge(); userSheet.Range["H2"].Value2 = "採購"; userSheet.Range["I2", "I3"].Merge(); userSheet.Range["I2"].Value2 = "電話"; userSheet.Range["J2", "J3"].Merge(); userSheet.Range["J2"].Value2 = "地址"; userSheet.Range["K2", "K3"].Merge(); userSheet.Range["K2"].Value2 = "產品"; userSheet.Range["L2", "L3"].Merge(); userSheet.Range["L2"].Value2 = "需求/月"; // 计算起始列(L列后面,列号13) int startCol = 13; // 合并年度销售表标题 userSheet.Range[userSheet.Cells[1, startCol], userSheet.Cells[1, startCol + 37]].Merge(); userSheet.Cells[1, startCol].Value2 = "年度销售表"; // 设置月份表头 for (int i = 0; i < 12; i++) { int monthCol = startCol + i * 3; userSheet.Range[userSheet.Cells[2, monthCol], userSheet.Cells[2, monthCol + 2]].Merge(); userSheet.Cells[2, monthCol].Value2 = $"{i + 1}月"; userSheet.Cells[3, monthCol].Value2 = "單價"; userSheet.Cells[3, monthCol + 1].Value2 = "數量"; userSheet.Cells[3, monthCol + 2].Value2 = "金額"; } // 合并Total表头 userSheet.Range[userSheet.Cells[2, startCol + 36], userSheet.Cells[2, startCol + 37]].Merge(); userSheet.Cells[2, startCol + 36].Value2 = "Total"; userSheet.Cells[3, startCol + 36].Value2 = "總數量"; userSheet.Cells[3, startCol + 37].Value2 = "總金額"; // 设置所有已用单元格居中 Range usedRange = userSheet.UsedRange; usedRange.HorizontalAlignment = XlHAlign.xlHAlignCenter; } private static Worksheet GenUserSalesDetailSheet( ImportContext context, ImportContext.GroupedSalesDetailModel groupedSalesDetail ) { var app = context.Application; 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; } private static Worksheet CreateSheetIfNotExisted(Microsoft.Office.Interop.Excel.Application app, string sheetName) { Worksheet userSheet = null; foreach (Worksheet item in app.Worksheets) { if (item.Name == sheetName) { userSheet = item; break; } }; if (userSheet == null) { try { // 新建工作表并命名 userSheet = app.Worksheets.Add(); userSheet.Name = sheetName; } catch { throw new FormatException("创建或获取用户工作表失败,请检查是否存在同名工作表。"); } } return userSheet; } private static void ReadSalesDetails(ImportContext context) { var dataRange = context.ImportWorkbook.Sheets[1].UsedRange; IList salesDatailList = new List(); if (dataRange.Value2 is object[,] rawSalesDetailData) { int rowCount = rawSalesDetailData.GetLength(0); int colCount = rawSalesDetailData.GetLength(1); for (int i = 3; i <= rowCount; i++) { SalesDetail item = new SalesDetail { SalesName = rawSalesDetailData[i, 1]?.ToString() ?? "UNKNOWN", Month = rawSalesDetailData[i, 2]?.ToString() ?? "", InvoiceDate = rawSalesDetailData[i, 3] is double invoiceDate ? DateTime.FromOADate(invoiceDate) : (DateTime?)null, OrderNumber = rawSalesDetailData[i, 4]?.ToString() ?? "", DeliveryDate = rawSalesDetailData[i, 5] is double deliveryDate ? DateTime.FromOADate(deliveryDate) : (DateTime?)null, InvoiceNumber = rawSalesDetailData[i, 6]?.ToString() ?? "", ClientName = rawSalesDetailData[i, 7]?.ToString() ?? "", ProductNameEN = rawSalesDetailData[i, 8]?.ToString() ?? "", Quantity = rawSalesDetailData[i, 9] != null ? Convert.ToDecimal(rawSalesDetailData[i, 9]) : (decimal?)null, PriceWithTax = rawSalesDetailData[i, 10] != null ? Convert.ToDecimal(rawSalesDetailData[i, 10]) : (decimal?)null, AmountWithoutTax = rawSalesDetailData[i, 11] != null ? Convert.ToDecimal(rawSalesDetailData[i, 11]) : (decimal?)null, Tax = rawSalesDetailData[i, 12] != null ? Convert.ToDecimal(rawSalesDetailData[i, 12]) : (decimal?)null, TotalAmount = rawSalesDetailData[i, 13] != null ? Convert.ToDecimal(rawSalesDetailData[i, 13]) : (decimal?)null, Remark = rawSalesDetailData[i, 14]?.ToString() ?? "", }; salesDatailList.Add(item); } } context.SalesDetails = salesDatailList; } public static Workbook SelectAndOpenExcelFile() { var app = Globals.ThisAddIn.Application; var curWorkbook = app.ActiveWorkbook; using (OpenFileDialog dialog = new OpenFileDialog()) { dialog.Filter = "Excel 文件 (*.xlsx)|*.xlsx"; dialog.Title = "请选择要打开的 Excel 文件"; if (dialog.ShowDialog() == DialogResult.OK) { string filePath = dialog.FileName; Workbook workbook = app.Workbooks.Open(filePath); curWorkbook.Activate(); return workbook; } } return null; } public static async void GenForecast(System.Windows.Forms.Button button) { String originLabel = button.Text; if (button != null) { button.Text = Resources.GENERATING; } var app = Globals.ThisAddIn.Application; var context = new GenForecaseContext { Application = app }; try { // 获取「銷售年度預估」工作表 ReadSalesForecastData(context); // 获取「產品年度預估」工作表 ReadProductForecastData(context); GenBussenessSheet(context); } catch (Exception ex) { Console.WriteLine("Error generating forecast:" + ex.Message); MessageBox.Show("分析预估表失败: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } button.Text = originLabel; } public static void GenBussenessSheet(GenForecaseContext context) { var app = context.Application; // 假设 app 是 Excel.Application Worksheet sheet = null; string sheetName = "業務月達成率"; try { // 新增工作表 sheet = app.Worksheets.Add(); sheet.Name = sheetName; } catch { // 已存在则获取 sheet = app.Worksheets[sheetName] as Worksheet; try { Range usedRange = sheet.UsedRange; if (usedRange != null && usedRange.Cells.Count > 1) { usedRange.Clear(); } } catch { // 无 UsedRange 可忽略 } } // 合并A1:A2并填入年份 try { var monthData = context.MonthData; var yearValue = monthData[0]; Range yearRange = sheet.Range["A1", "A2"]; yearRange.Merge(); yearRange.Value2 = yearValue.ToString(); yearRange.NumberFormat = "@"; // 文本格式 int startRowIndex = 1; // 填入月份 for (int i = 0; i < 12; 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 = startRowIndex; // Excel 行号从1开始 int startCol = col; int endCol = col + 4; // 合并并填入 salesName Range salesNameRange = sheet.Range[ sheet.Cells[rowIndex, startCol], sheet.Cells[rowIndex, startCol + 1] ]; salesNameRange.Merge(); salesNameRange.Value2 = salesForcastData.Name; // 合并并填入“完成%” Range finishRange = sheet.Range[ sheet.Cells[rowIndex, startCol + 2], sheet.Cells[rowIndex + 1, startCol + 2] ]; finishRange.Merge(); finishRange.Value2 = "完成%"; // 合并并填入“累積達成率” Range accRange = sheet.Range[ sheet.Cells[rowIndex, startCol + 3], sheet.Cells[rowIndex + 1, startCol + 3] ]; accRange.Merge(); accRange.Value2 = "累積達成率"; // 第二行填入 Y-forecast 和 turnover rowIndex++; sheet.Cells[rowIndex, startCol] = "Y-forecast"; sheet.Cells[rowIndex, startCol + 1] = "turnover"; // 填入每月数据 rowIndex++; foreach (var forcastMonth in salesForcastData.MonthlyForecast) { var cell = sheet.Cells[rowIndex, startCol]; cell.Value2 = forcastMonth; 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; } // 自适应所有已用列宽 FormatSheetStyle(sheet); } catch (Exception ex) { MessageBox.Show("写入业绩月达成率时发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private static void ReadClientContact(ImportContext context) { var app = context.Application; var clientContactSheet = app.Worksheets["客戶資料"] as Worksheet; var clientContactRange = clientContactSheet.UsedRange; IList clientContactList = new List(); if (clientContactRange.Value2 is object[,] rawContactData) { int rowCount = rawContactData.GetLength(0); int colCount = rawContactData.GetLength(1); // 模板第二行开始是数据 for (int i = 2; i <= rowCount; i++) { var input = new ClientContact { Region = rawContactData[i, 1]?.ToString() ?? "", Industry = rawContactData[i, 2]?.ToString() ?? "", AnnualCapacity = rawContactData[i, 3]?.ToString() ?? "", Name = rawContactData[i, 4]?.ToString() ?? "", PurchasingManager = rawContactData[i, 5]?.ToString() ?? "", PurchasingManagerPhone = rawContactData[i, 6]?.ToString() ?? "", Purchaser = rawContactData[i, 7]?.ToString() ?? "", PurchaserPhone = rawContactData[i, 8]?.ToString() ?? "", Address = rawContactData[i, 9]?.ToString() ?? "" }; clientContactList.Add(input); } } context.ClientContactList = clientContactList; } private static void ReadProductForecastData(GenForecaseContext context) { var app = context.Application; var productForecastSheet = app.Worksheets["產品年度預估"] as Worksheet; var productRange = productForecastSheet.UsedRange; IList productForecastList = new List(); if (productRange.Value2 is object[,] rawProductData) { int rowCount = rawProductData.GetLength(0); int colCount = rawProductData.GetLength(1); if (rawProductData[1, 2] == null) { throw new MissingMemberException("「產品年度預估」工作表的(年份)不能为空,请检查数据格式。"); } var year = Convert.ToInt32(rawProductData[1, 2]); // 模板第三行开始是数据 for (int i = 3; i <= rowCount; i++) { var input = new ProductForecastInput { Year = year, Name = rawProductData[i, 1]?.ToString() ?? "", Quantity = rawProductData[i, 2] != null ? Convert.ToDecimal(rawProductData[i, 2]) : 0, AmountTax = rawProductData[i, 3] != null ? Convert.ToDecimal(rawProductData[i, 3]) : 0, Amount = rawProductData[i, 4] != null ? Convert.ToDecimal(rawProductData[i, 4]) : 0, PriceAvg = rawProductData[i, 5] != null ? Convert.ToDecimal(rawProductData[i, 5]) : 0, }; productForecastList.Add(input); } } context.ProductForecastList = productForecastList; } private static void ReadSalesForecastData(GenForecaseContext context) { var app = context.Application; var salesForecastSheet = app.Worksheets["銷售年度預估"] as Worksheet; var salesRange = salesForecastSheet.UsedRange; IList salesForecastInputList = new List(); string[] monthData = new string[13]; if (salesRange.Value2 is object[,] rawSalesData) { int rowCount = rawSalesData.GetLength(0); int colCount = rawSalesData.GetLength(1); if (rawSalesData[1, 2] == null) { throw new MissingMemberException("「銷售年度預估」工作表的(年份)不能为空,请检查数据格式。"); } var year = Convert.ToInt32(rawSalesData[1, 2]); monthData[0] = year.ToString(); for (int i = 1; i <= 12; i++) { monthData[i] = rawSalesData[2, i + 1].ToString(); } // 模板第三行开始是数据 for (int i = 3; i <= rowCount; i++) { var input = new SalesForecastInput { Year = year, Name = rawSalesData[i, 1]?.ToString() ?? "", January = rawSalesData[i, 2] != null ? Convert.ToDecimal(rawSalesData[i, 2]) : 0, February = rawSalesData[i, 3] != null ? Convert.ToDecimal(rawSalesData[i, 3]) : 0, March = rawSalesData[i, 4] != null ? Convert.ToDecimal(rawSalesData[i, 4]) : 0, April = rawSalesData[i, 5] != null ? Convert.ToDecimal(rawSalesData[i, 5]) : 0, May = rawSalesData[i, 6] != null ? Convert.ToDecimal(rawSalesData[i, 6]) : 0, June = rawSalesData[i, 7] != null ? Convert.ToDecimal(rawSalesData[i, 7]) : 0, July = rawSalesData[i, 8] != null ? Convert.ToDecimal(rawSalesData[i, 8]) : 0, August = rawSalesData[i, 9] != null ? Convert.ToDecimal(rawSalesData[i, 9]) : 0, September = rawSalesData[i, 10] != null ? Convert.ToDecimal(rawSalesData[i, 10]) : 0, October = rawSalesData[i, 11] != null ? Convert.ToDecimal(rawSalesData[i, 11]) : 0, November = rawSalesData[i, 12] != null ? Convert.ToDecimal(rawSalesData[i, 12]) : 0, December = rawSalesData[i, 13] != null ? Convert.ToDecimal(rawSalesData[i, 13]) : 0, Total = rawSalesData[i, 14] != null ? Convert.ToDecimal(rawSalesData[i, 14]) : 0, }; salesForecastInputList.Add(input); } } context.SalesForecastList = salesForecastInputList; context.MonthData = monthData; } } }