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 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); // 获取「客户资料」工作表 readClientContact(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 = "@"; // 文本格式 // 填入月份 for (int i = 1; i < monthData.Length; i++) { sheet.Cells[i + 2, 1] = monthData[i]; } // B列开始填 salesName 及相关数据 int col = 2; // B列 foreach (var salesForcastData in context.SalesForecastList) { int rowIndex = 1; // 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, startCol + 2] ]; finishRange.Merge(); finishRange.Value2 = "完成%"; // 合并并填入“累積達成率” Range accRange = sheet.Range[ sheet.Cells[rowIndex, startCol + 3], sheet.Cells[rowIndex, 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++; } col = endCol; } // 自适应所有已用列宽 Range usedRange2 = sheet.UsedRange; if (usedRange2 != null) { usedRange2.Columns.AutoFit(); } } catch (Exception ex) { MessageBox.Show("写入业绩月达成率时发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private static void readClientContact(GenForecaseContext 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; } } }