diff --git a/KellyReport_D.csproj b/KellyReport_D.csproj
index cb2fa5f..32343c0 100644
--- a/KellyReport_D.csproj
+++ b/KellyReport_D.csproj
@@ -34,7 +34,7 @@
publish\
zh-chs
- 1.0.0.2
+ 1.0.0.4
true
true
7
diff --git a/Utils/WorkBookUtils.cs b/Utils/WorkBookUtils.cs
index 556ca51..0c279a3 100644
--- a/Utils/WorkBookUtils.cs
+++ b/Utils/WorkBookUtils.cs
@@ -38,6 +38,9 @@ namespace KellyReport_D.Utils
// 更新业务预估表
UpdateEstimatedTable(importContext);
+ UpdateDeptartmentSummary(importContext);
+
+ GenProductSummarySheet(importContext);
}
private static void UpdateEstimatedTable(ImportContext importContext)
@@ -523,9 +526,9 @@ namespace KellyReport_D.Utils
{
SalesName = rawSalesDetailData[i, 1]?.ToString() ?? "UNKNOWN",
Month = rawSalesDetailData[i, 2]?.ToString() ?? "",
- InvoiceDate = rawSalesDetailData[i, 3] is double invoiceDate ? DateTime.FromOADate(invoiceDate) : (DateTime?)null,
+ DeliveryDate = 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,
+ InvoiceDate = rawSalesDetailData[i, 5] != null ? DateTime.Parse(rawSalesDetailData[i, 5]?.ToString()) : (DateTime?)null,
InvoiceNumber = rawSalesDetailData[i, 6]?.ToString() ?? "",
ClientName = rawSalesDetailData[i, 7]?.ToString() ?? "",
ProductNameEN = rawSalesDetailData[i, 8]?.ToString() ?? "",
@@ -562,7 +565,7 @@ namespace KellyReport_D.Utils
return null;
}
- public static async void GenForecast(System.Windows.Forms.Button button)
+ public static void GenForecast(System.Windows.Forms.Button button)
{
String originLabel = button.Text;
if (button != null)
@@ -580,7 +583,8 @@ namespace KellyReport_D.Utils
// 获取「銷售年度預估」工作表
ReadSalesForecastData(context);
// 获取「產品年度預估」工作表
- ReadProductForecastData(context);
+ //ReadProductForecastData(context);
+ GenDepartmentSummary(context);
GenBussenessSheet(context);
}
@@ -839,5 +843,306 @@ namespace KellyReport_D.Utils
context.SalesForecastList = salesForecastInputList;
context.MonthData = monthData;
}
+
+ public static void GenProductSummarySheet(ImportContext context)
+ {
+ var app = context.Application;
+
+ string sheetName = $"產品年度預估";
+ 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 =>
+ {
+ Range usedRange = productSheet.UsedRange;
+
+ Range turnOverRange = usedRange.Find(What: $"{yearNumber}-Turnover", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+ if (turnOverRange == null)
+ {
+ Range estimateRange = usedRange.Find(What: $"{yearNumber}-Estimate", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+
+ int insertCol = 2;
+ if (estimateRange != null)
+ {
+ insertCol = estimateRange.Column;
+ }
+
+ Range insertRange = productSheet.Columns[$"{GetColumnLetter(insertCol)}:{GetColumnLetter(insertCol + 5)}"];
+ insertRange.EntireColumn.Insert(XlInsertShiftDirection.xlShiftToRight);
+ insertRange = productSheet.Columns[$"{GetColumnLetter(insertCol)}:{GetColumnLetter(insertCol + 5)}"];
+ insertRange.ClearFormats();
+
+ productSheet.Cells[1, insertCol].Value2 = $"{yearNumber}-Turnover";
+
+ productSheet.Cells[2, insertCol].Value2 = "數量";
+ productSheet.Cells[2, insertCol + 1].Value2 = "金額(含稅)";
+ productSheet.Cells[2, insertCol + 2].Value2 = "金額(未稅)";
+ productSheet.Cells[2, insertCol + 3].Value2 = "平均單價";
+ productSheet.Cells[2, insertCol + 4].Value2 = "成長率";
+ var growthRange = productSheet.Range[
+ productSheet.Cells[2, insertCol + 4],
+ productSheet.Cells[2, insertCol + 5]
+ ];
+ growthRange.Merge();
+
+ turnOverRange = productSheet.Range[
+ productSheet.Cells[1, insertCol],
+ productSheet.Cells[1, insertCol + 5]
+ ];
+ turnOverRange.Merge();
+ }
+
+ var productSalesList = context.SalesDetails
+ .Where(x => x.InvoiceDate.HasValue && x.InvoiceDate.Value.Year == yearNumber)
+ .GroupBy(x => x.ProductNameEN)
+ .Select(grouped => new ImportContext.GroupedSalesDetailModel()
+ {
+ ProductNameEN = grouped.Key,
+ Quantity = grouped.Sum(x => x.Quantity ?? 0),
+ TotalAmount = grouped.Sum(x => x.TotalAmount ?? 0),
+ Details = grouped.ToList()
+ })
+ .ToList();
+
+ Range totalRange = usedRange.Find(What: $"總計", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+
+ int totalRowCount = usedRange.Rows.Count + 1;
+ if (totalRange != null)
+ {
+ totalRowCount = totalRange.Row;
+ }
+
+ int startColIndex = turnOverRange.Column;
+ var quantityColLetter = GetColumnLetter(startColIndex);
+ var amountColLetter = GetColumnLetter(startColIndex + 1);
+ var amountNoTaxColLetter = GetColumnLetter(startColIndex + 2);
+ var prevQuantityColLetter = GetColumnLetter(startColIndex + 6);
+ var prevAmountColLetter = GetColumnLetter(startColIndex + 7);
+ var prevAmountNoTaxColLetter = GetColumnLetter(startColIndex + 8);
+
+ foreach (var productSalesSummary in productSalesList)
+ {
+ var curProductName = productSalesSummary.ProductNameEN;
+ // look for the product row
+ // if not exists then create a new row
+ Range productRange = usedRange.Find(
+ What: curProductName,
+ LookIn: XlFindLookIn.xlValues,
+ LookAt: XlLookAt.xlWhole,
+ SearchOrder: XlSearchOrder.xlByRows,
+ SearchDirection: XlSearchDirection.xlNext,
+ MatchCase: false
+ );
+
+ if (productRange == null)
+ {
+ productSheet.Rows[totalRowCount].Insert();
+ productSheet.Cells[totalRowCount, 1].Value2 = curProductName;
+ productRange = productSheet.Cells[totalRowCount, 1];
+
+ totalRowCount += 1;
+ }
+
+ int curRowIndex = productRange.Row;
+
+ productSheet.Cells[curRowIndex, startColIndex].Value2 = productSalesSummary.Quantity;
+ productSheet.Cells[curRowIndex, startColIndex + 1].Value2 = productSalesSummary.TotalAmount;
+ productSheet.Cells[curRowIndex, startColIndex + 2].formula = $"={amountColLetter}{curRowIndex}/1.13";
+ productSheet.Cells[curRowIndex, startColIndex + 3].formula = $"={amountColLetter}{curRowIndex}/${quantityColLetter}{curRowIndex}";
+
+ productSheet.Cells[curRowIndex, startColIndex + 4].formula = $"={quantityColLetter}{curRowIndex}/${prevQuantityColLetter}{curRowIndex}";
+ productSheet.Cells[curRowIndex, startColIndex + 5].formula = $"={amountColLetter}{curRowIndex}/${prevAmountColLetter}{curRowIndex}";
+
+ productSheet.Cells[curRowIndex, startColIndex + 4].NumberFormat = "0.00%";
+ productSheet.Cells[curRowIndex, startColIndex + 5].NumberFormat = "0.00%";
+ }
+
+ productSheet.Cells[totalRowCount, 1].Value2 = "總計";
+ productSheet.Cells[totalRowCount, startColIndex].formula = $"=SUM({quantityColLetter}5:{quantityColLetter}{totalRowCount - 1})";
+ productSheet.Cells[totalRowCount, startColIndex + 1].formula = $"=SUM({amountColLetter}5:{amountColLetter}{totalRowCount - 1})";
+ productSheet.Cells[totalRowCount, startColIndex + 2].formula = $"=SUM({amountNoTaxColLetter}5:{amountNoTaxColLetter}{totalRowCount - 1})";
+
+ productSheet.Cells[totalRowCount + 1, 1].Value2 = "備註";
+ productSheet.Cells[totalRowCount + 1, startColIndex].formula = $"={quantityColLetter}{totalRowCount}/{prevQuantityColLetter}{totalRowCount}";
+ productSheet.Cells[totalRowCount + 1, startColIndex + 1].formula = $"={amountColLetter}{totalRowCount}/{prevAmountColLetter}{totalRowCount}";
+ productSheet.Cells[totalRowCount + 1, startColIndex + 2].formula = $"={amountNoTaxColLetter}{totalRowCount}/{prevAmountNoTaxColLetter}{totalRowCount}";
+
+ productSheet.Cells[totalRowCount + 1, startColIndex].NumberFormat = "0.00%";
+ productSheet.Cells[totalRowCount + 1, startColIndex + 1].NumberFormat = "0.00%";
+ productSheet.Cells[totalRowCount + 1, startColIndex + 2].NumberFormat = "0.00%";
+ });
+
+ FormatSheetStyle(productSheet);
+ }
+
+ public static void GenDepartmentSummary(GenForecaseContext context)
+ {
+ var app = context.Application;
+
+ string sheetName = $"部门统计";
+ Worksheet deptSheet = CreateSheetIfNotExisted(app, sheetName);
+ deptSheet.Activate();
+
+ deptSheet.Cells[1, 1].Value2 = "鈞全";
+ deptSheet.Range[deptSheet.Cells[1, 1], deptSheet.Cells[2, 1]].Merge();
+
+ var yearList = context.SalesForecastList
+ .Select(x => x.Year)
+ .Distinct()
+ .ToList();
+
+ Range initUsedRange = deptSheet.UsedRange;
+
+ Range totalRange = initUsedRange.Find(What: $"Total", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+
+ int totalRowIndex = initUsedRange.Rows.Count + 1;
+ if (totalRange != null)
+ {
+ totalRowIndex = totalRange.Row;
+ }
+
+ yearList.ForEach(yearNumber =>
+ {
+ Range curYearRange = deptSheet.UsedRange.Find(What: $"{yearNumber}", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+
+ int startCol = deptSheet.UsedRange.Column + 1;
+ if (curYearRange != null)
+ {
+ startCol = curYearRange.Column;
+ }
+
+ var startColLetter = GetColumnLetter(startCol);
+ var endColLetter = GetColumnLetter(startCol + 3);
+
+ 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 = "";
+ string prevTurnoverColLetter = "";
+ if (prevYearRange != null)
+ {
+ prevStartCol = prevYearRange.Column;
+ prevForecastColLetter = GetColumnLetter(prevStartCol);
+ prevTurnoverColLetter = GetColumnLetter(prevStartCol + 1);
+ }
+
+ deptSheet.Range[$"{startColLetter}:{endColLetter}"]
+ .EntireColumn
+ .Insert(XlInsertShiftDirection.xlShiftToRight);
+
+ deptSheet.Cells[1, 2].Value2 = $"{yearNumber}";
+ deptSheet.Range[deptSheet.Cells[1, startCol], deptSheet.Cells[1, startCol + 3]].Merge();
+
+ deptSheet.Cells[2, startCol].Value2 = "Forecast";
+ deptSheet.Cells[2, startCol + 1].Value2 = "Turnover";
+ deptSheet.Cells[2, startCol + 2].Value2 = "成長率";
+ deptSheet.Cells[2, startCol + 3].Value2 = "達成率";
+
+ var forcastColLetter = startColLetter;
+ var turnoverColLetter = GetColumnLetter(startCol + 1);
+ foreach (var salesForecast in context.SalesForecastList.Where(x => x.Name.ToUpper() != "TOTAL"))
+ {
+ var salesName = salesForecast.Name;
+ Range curUsedRange = deptSheet.UsedRange;
+
+ Range salesNameRange = curUsedRange.Find(What: $"{salesName}", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+
+ if (salesNameRange == null)
+ {
+ deptSheet.Rows[totalRowIndex].Insert();
+ deptSheet.Cells[curUsedRange.Rows.Count + 1, 1].Value2 = salesName;
+
+ salesNameRange = deptSheet.Cells[curUsedRange.Rows.Count + 1, 1];
+ totalRowIndex++;
+ }
+
+ deptSheet.Cells[salesNameRange.Row, startCol].Value2 = salesForecast.Total;
+ if (prevYearRange != null)
+ {
+ deptSheet.Cells[salesNameRange.Row, startCol + 2].formula = $"=SUM({forcastColLetter}{salesNameRange.Row} - {prevTurnoverColLetter}{salesNameRange.Row})/{forcastColLetter}{salesNameRange.Row}";
+ deptSheet.Cells[salesNameRange.Row, startCol + 2].NumberFormat = "0.00%";
+ }
+ deptSheet.Cells[salesNameRange.Row, startCol + 3].formula = $"={turnoverColLetter}{salesNameRange.Row}/{forcastColLetter}{salesNameRange.Row}";
+ deptSheet.Cells[salesNameRange.Row, startCol + 3].NumberFormat = "0.00%";
+ }
+
+ deptSheet.Cells[totalRowIndex, 1].Value2 = "Total";
+ deptSheet.Cells[totalRowIndex, startCol].formula = $"=SUM({forcastColLetter}3:{forcastColLetter}{totalRowIndex - 1})";
+ deptSheet.Cells[totalRowIndex, startCol + 1].formula = $"=SUM({turnoverColLetter}3:{turnoverColLetter}{totalRowIndex - 1})";
+
+ if (prevYearRange != null)
+ {
+ deptSheet.Cells[totalRowIndex, startCol + 2].formula = $"=SUM({forcastColLetter}{totalRowIndex} - {prevTurnoverColLetter}{totalRowIndex})/{forcastColLetter}{totalRowIndex}";
+ deptSheet.Cells[totalRowIndex, startCol + 2].NumberFormat = "0.00%";
+ }
+ deptSheet.Cells[totalRowIndex, startCol + 3].formula = $"={turnoverColLetter}{totalRowIndex}/{forcastColLetter}{totalRowIndex}";
+ deptSheet.Cells[totalRowIndex, startCol + 3].NumberFormat = "0.00%";
+ });
+
+ FormatSheetStyle(deptSheet);
+ }
+
+ public static void UpdateDeptartmentSummary(ImportContext context)
+ {
+ var app = context.Application;
+
+ string sheetName = $"部门统计";
+ 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 =>
+ {
+ Range yearRange = deptSheet.UsedRange.Find(What: $"{yearoNumber}", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+
+ if (yearRange == null)
+ {
+ Console.WriteLine("Cannot find year column in department summary: {0}", yearoNumber);
+ return;
+ }
+
+ var startCol = yearRange.Column;
+ var startColLetter = GetColumnLetter(startCol);
+ var turnoverColLetter = GetColumnLetter(startCol + 1);
+
+ Range totalRange = deptSheet.UsedRange.Find(What: $"Total", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+ int totalRowIndex = deptSheet.UsedRange.Rows.Count + 1;
+ if (totalRange != null)
+ {
+ totalRowIndex = totalRange.Row;
+ }
+
+ var salesDetails = context.SalesDetails
+ .Where(x => x.InvoiceDate.HasValue && x.InvoiceDate.Value.Year == yearoNumber && x.SalesName.ToUpper() != "TOTAL")
+ .GroupBy(x => x.SalesName)
+ .Select(grouped => new
+ {
+ SalesName = grouped.Key,
+ Turnover = grouped.Sum(x => x.TotalAmount ?? 0)
+ })
+ .ToList();
+
+ foreach (var salesDetail in salesDetails)
+ {
+ var salesName = salesDetail.SalesName;
+ Range curUsedRange = deptSheet.UsedRange;
+
+ Range salesNameRange = curUsedRange.Find(What: $"{salesName}", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
+
+ if (salesNameRange != null)
+ {
+ deptSheet.Cells[salesNameRange.Row, startCol + 1].Value2 = salesDetail.Turnover;
+ }
+ }
+
+ deptSheet.Cells[totalRowIndex, startCol + 1].formula = $"=SUM({turnoverColLetter}3:{turnoverColLetter}{totalRowIndex - 1})";
+ });
+ }
}
}