自动生成客户/产品年度统计,新增日志功能
- 新增 FileLogger 日志工具类,增强异常记录 - 自动生成“客户年度预估”“产品年度销量统计”表 - 升级版本号至 1.0.0.7
This commit is contained in:
parent
aedbd788be
commit
f839573712
@ -34,7 +34,7 @@
|
|||||||
<PublishUrl>publish\</PublishUrl>
|
<PublishUrl>publish\</PublishUrl>
|
||||||
<InstallUrl />
|
<InstallUrl />
|
||||||
<TargetCulture>zh-chs</TargetCulture>
|
<TargetCulture>zh-chs</TargetCulture>
|
||||||
<ApplicationVersion>1.0.0.4</ApplicationVersion>
|
<ApplicationVersion>1.0.0.7</ApplicationVersion>
|
||||||
<AutoIncrementApplicationRevision>true</AutoIncrementApplicationRevision>
|
<AutoIncrementApplicationRevision>true</AutoIncrementApplicationRevision>
|
||||||
<UpdateEnabled>true</UpdateEnabled>
|
<UpdateEnabled>true</UpdateEnabled>
|
||||||
<UpdateInterval>7</UpdateInterval>
|
<UpdateInterval>7</UpdateInterval>
|
||||||
@ -227,6 +227,7 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs">
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Utils\FileLogger.cs" />
|
||||||
<Compile Include="Utils\WorkBookUtils.cs" />
|
<Compile Include="Utils\WorkBookUtils.cs" />
|
||||||
<EmbeddedResource Include="JQSalesSummaryPanel.resx">
|
<EmbeddedResource Include="JQSalesSummaryPanel.resx">
|
||||||
<DependentUpon>JQSalesSummaryPanel.cs</DependentUpon>
|
<DependentUpon>JQSalesSummaryPanel.cs</DependentUpon>
|
||||||
|
|||||||
@ -34,5 +34,5 @@ using System.Security;
|
|||||||
// 方法是按如下所示使用“*”: :
|
// 方法是按如下所示使用“*”: :
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.0.0.6")]
|
||||||
|
|
||||||
|
|||||||
18
Ribbon1.cs
18
Ribbon1.cs
@ -3,7 +3,9 @@ using Microsoft.Office.Tools;
|
|||||||
using Microsoft.Office.Tools.Ribbon;
|
using Microsoft.Office.Tools.Ribbon;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace KellyReport_D
|
namespace KellyReport_D
|
||||||
@ -12,6 +14,20 @@ namespace KellyReport_D
|
|||||||
{
|
{
|
||||||
private CustomTaskPane jqSalesSummaryPanel;
|
private CustomTaskPane jqSalesSummaryPanel;
|
||||||
|
|
||||||
|
private string GetAppVersion()
|
||||||
|
{
|
||||||
|
var asm = Assembly.GetExecutingAssembly();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fvi = FileVersionInfo.GetVersionInfo(asm.Location);
|
||||||
|
if (!string.IsNullOrWhiteSpace(fvi.FileVersion))
|
||||||
|
return fvi.FileVersion;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
return asm.GetName().Version.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
|
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
|
||||||
{
|
{
|
||||||
this.button1.Label = Resources.APP_NAME;
|
this.button1.Label = Resources.APP_NAME;
|
||||||
@ -23,7 +39,7 @@ namespace KellyReport_D
|
|||||||
if (jqSalesSummaryPanel == null)
|
if (jqSalesSummaryPanel == null)
|
||||||
{
|
{
|
||||||
var panel = new JQSalesSummaryPanel();
|
var panel = new JQSalesSummaryPanel();
|
||||||
jqSalesSummaryPanel = Globals.ThisAddIn.CustomTaskPanes.Add(panel, Resources.APP_NAME);
|
jqSalesSummaryPanel = Globals.ThisAddIn.CustomTaskPanes.Add(panel, $"{Resources.APP_NAME} v{GetAppVersion()}");
|
||||||
jqSalesSummaryPanel.Width = 600;
|
jqSalesSummaryPanel.Width = 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
47
Utils/FileLogger.cs
Normal file
47
Utils/FileLogger.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace KellyReport_D.Utils
|
||||||
|
{
|
||||||
|
internal static class FileLogger
|
||||||
|
{
|
||||||
|
private static readonly object _sync = new object();
|
||||||
|
private static string LogDirectory =>
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "KellyReport", "logs");
|
||||||
|
|
||||||
|
private static string GetLogFilePath()
|
||||||
|
{
|
||||||
|
string fileName = $"kellyreport_{DateTime.Now:yyyyMMdd}.log";
|
||||||
|
return Path.Combine(LogDirectory, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteInternal(string level, string message, Exception ex = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (_sync)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(LogDirectory);
|
||||||
|
var path = GetLogFilePath();
|
||||||
|
using (var sw = new StreamWriter(path, true, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
sw.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} [{level}] {message}");
|
||||||
|
if (ex != null)
|
||||||
|
{
|
||||||
|
sw.WriteLine(ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 日志写入不应影响主流程,忽略任何异常
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Info(string message) => WriteInternal("INFO", message);
|
||||||
|
public static void Debug(string message) => WriteInternal("DEBUG", message);
|
||||||
|
public static void Error(string message, Exception ex = null) => WriteInternal("ERROR", message, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,8 +5,8 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using KellyReport_D.Model;
|
using KellyReport_D.Model;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace KellyReport_D.Utils
|
namespace KellyReport_D.Utils
|
||||||
{
|
{
|
||||||
@ -40,7 +40,10 @@ namespace KellyReport_D.Utils
|
|||||||
UpdateEstimatedTable(importContext);
|
UpdateEstimatedTable(importContext);
|
||||||
UpdateDeptartmentSummary(importContext);
|
UpdateDeptartmentSummary(importContext);
|
||||||
|
|
||||||
|
// 产品年度销量统计
|
||||||
GenProductSummarySheet(importContext);
|
GenProductSummarySheet(importContext);
|
||||||
|
// 生成客户年度销量统计
|
||||||
|
GenClientSummarySheet(importContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateEstimatedTable(ImportContext importContext)
|
private static void UpdateEstimatedTable(ImportContext importContext)
|
||||||
@ -66,9 +69,12 @@ namespace KellyReport_D.Utils
|
|||||||
Range usedRange = bussenessWorksheet.UsedRange;
|
Range usedRange = bussenessWorksheet.UsedRange;
|
||||||
int maxColIndex = usedRange.Columns.Count;
|
int maxColIndex = usedRange.Columns.Count;
|
||||||
|
|
||||||
|
int yearRowIndex = 1;
|
||||||
|
FindBussenessYearRow(bussenessWorksheet, importContext.YearList[0].ToString(), ref yearRowIndex);
|
||||||
|
|
||||||
for (int i = 2; i < maxColIndex; i += 4)
|
for (int i = 2; i < maxColIndex; i += 4)
|
||||||
{
|
{
|
||||||
String salesName = bussenessWorksheet.Cells[1, i].Value2;
|
String salesName = bussenessWorksheet.Cells[yearRowIndex, i].Value2;
|
||||||
if (string.IsNullOrWhiteSpace(salesName))
|
if (string.IsNullOrWhiteSpace(salesName))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -90,7 +96,7 @@ namespace KellyReport_D.Utils
|
|||||||
.ToList()
|
.ToList()
|
||||||
.ForEach(monthlySales =>
|
.ForEach(monthlySales =>
|
||||||
{
|
{
|
||||||
int startRowIndex = 3;
|
int startRowIndex = yearRowIndex + 2;
|
||||||
for (int rowIndex = startRowIndex; rowIndex < startRowIndex + 12; rowIndex++)
|
for (int rowIndex = startRowIndex; rowIndex < startRowIndex + 12; rowIndex++)
|
||||||
{
|
{
|
||||||
var monthCell = bussenessWorksheet.Cells[rowIndex, 1];
|
var monthCell = bussenessWorksheet.Cells[rowIndex, 1];
|
||||||
@ -214,7 +220,7 @@ namespace KellyReport_D.Utils
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine("delete error %s", ex.Message);
|
FileLogger.Error("删除Total(All)旧数据时发生错误", ex);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -381,7 +387,7 @@ namespace KellyReport_D.Utils
|
|||||||
{
|
{
|
||||||
for (var i = 0; i < clientSalesRowCount - curRowCount; i++)
|
for (var i = 0; i < clientSalesRowCount - curRowCount; i++)
|
||||||
{
|
{
|
||||||
userSheet.Rows[clientSalesRowIndex + curRowCount].Insert(XlInsertShiftDirection.xlShiftDown);
|
userSheet.Rows[clientSalesRowIndex + curRowCount - 1].Insert(XlInsertShiftDirection.xlShiftDown);
|
||||||
summaryRowIndex++;
|
summaryRowIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -455,19 +461,61 @@ namespace KellyReport_D.Utils
|
|||||||
|
|
||||||
private static int WriteSalesDetailToSheet(Worksheet userSheet, int rowIndex, int yearColIndex, ClientContact clientContact, IEnumerable<ImportContext.GroupedSalesDetailModel> salesDetailList)
|
private static int WriteSalesDetailToSheet(Worksheet userSheet, int rowIndex, int yearColIndex, ClientContact clientContact, IEnumerable<ImportContext.GroupedSalesDetailModel> salesDetailList)
|
||||||
{
|
{
|
||||||
|
Range productNamesCellRange = userSheet.Range[
|
||||||
|
userSheet.Cells[rowIndex, 11],
|
||||||
|
userSheet.Cells[rowIndex + salesDetailList.Count(), 11]
|
||||||
|
];
|
||||||
|
|
||||||
foreach (var productSalesDetail in salesDetailList)
|
foreach (var productSalesDetail in salesDetailList)
|
||||||
{
|
{
|
||||||
|
int currentRowIndex = rowIndex;
|
||||||
|
// 如果存在相同产品名称,则写入对应行
|
||||||
|
if (productSalesDetail.ProductNameEN != "總銷售額")
|
||||||
|
{
|
||||||
|
|
||||||
|
var targetProductCell = productNamesCellRange.Find(What: productSalesDetail.ProductNameEN, LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
|
||||||
|
if (targetProductCell != null)
|
||||||
|
{
|
||||||
|
currentRowIndex = targetProductCell.Row;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Range blankCell = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
blankCell = productNamesCellRange.SpecialCells(XlCellType.xlCellTypeBlanks);
|
||||||
|
}
|
||||||
|
catch (COMException)
|
||||||
|
{
|
||||||
|
// 没有空白单元格
|
||||||
|
//productNamesCellRange.Insert(XlInsertShiftDirection.xlShiftDown);
|
||||||
|
MessageBox.Show($"写入数据时发生错误,可能是因为产品名称过多导致,错误数据:{productSalesDetail.SalesName}-{productSalesDetail.ClientName}-{productSalesDetail.ProductNameEN}。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
rowIndex++;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
//userSheet.Rows[rowIndex + salesDetailList.Count() - 1].Insert(XlInsertShiftDirection.xlShiftDown);
|
||||||
|
//blankCell = userSheet.Cells[rowIndex + salesDetailList.Count() - 1, 11];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blankCell != null)
|
||||||
|
{
|
||||||
|
currentRowIndex = blankCell.Row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//userSheet.Cells[rowIndex, 1].Value2 = productSalesDetail.SalesName;
|
//userSheet.Cells[rowIndex, 1].Value2 = productSalesDetail.SalesName;
|
||||||
userSheet.Cells[rowIndex, 2].Value2 = clientContact.Region;
|
userSheet.Cells[currentRowIndex, 2].Value2 = clientContact.Region;
|
||||||
userSheet.Cells[rowIndex, 3].Value2 = clientContact.Industry;
|
userSheet.Cells[currentRowIndex, 3].Value2 = clientContact.Industry;
|
||||||
userSheet.Cells[rowIndex, 4].Value2 = clientContact.AnnualCapacity;
|
userSheet.Cells[currentRowIndex, 4].Value2 = clientContact.AnnualCapacity;
|
||||||
userSheet.Cells[rowIndex, 5].Value2 = clientContact.Name;
|
userSheet.Cells[currentRowIndex, 5].Value2 = clientContact.Name;
|
||||||
userSheet.Cells[rowIndex, 6].Value2 = clientContact.PurchasingManager;
|
userSheet.Cells[currentRowIndex, 6].Value2 = clientContact.PurchasingManager;
|
||||||
userSheet.Cells[rowIndex, 7].Value2 = clientContact.PurchasingManagerPhone;
|
userSheet.Cells[currentRowIndex, 7].Value2 = clientContact.PurchasingManagerPhone;
|
||||||
userSheet.Cells[rowIndex, 8].Value2 = clientContact.Purchaser;
|
userSheet.Cells[currentRowIndex, 8].Value2 = clientContact.Purchaser;
|
||||||
userSheet.Cells[rowIndex, 9].Value2 = clientContact.PurchaserPhone;
|
userSheet.Cells[currentRowIndex, 9].Value2 = clientContact.PurchaserPhone;
|
||||||
userSheet.Cells[rowIndex, 10].Value2 = clientContact.Address;
|
userSheet.Cells[currentRowIndex, 10].Value2 = clientContact.Address;
|
||||||
userSheet.Cells[rowIndex, 11].Value2 = productSalesDetail.ProductNameEN;
|
userSheet.Cells[currentRowIndex, 11].Value2 = productSalesDetail.ProductNameEN;
|
||||||
|
|
||||||
// 计算每月的数量和金额
|
// 计算每月的数量和金额
|
||||||
int monthCol = yearColIndex;
|
int monthCol = yearColIndex;
|
||||||
@ -500,19 +548,19 @@ namespace KellyReport_D.Utils
|
|||||||
|
|
||||||
if (monthDetail == null)
|
if (monthDetail == null)
|
||||||
{
|
{
|
||||||
userSheet.Cells[rowIndex, monthCol + (i - 1) * 3].Value2 = 0; // 單價
|
userSheet.Cells[currentRowIndex, monthCol + (i - 1) * 3].Value2 = 0; // 單價
|
||||||
userSheet.Cells[rowIndex, monthCol + (i - 1) * 3 + 1].Value2 = 0; // 數量
|
userSheet.Cells[currentRowIndex, monthCol + (i - 1) * 3 + 1].Value2 = 0; // 數量
|
||||||
userSheet.Cells[rowIndex, monthCol + (i - 1) * 3 + 2].Value2 = 0; // 金額
|
userSheet.Cells[currentRowIndex, monthCol + (i - 1) * 3 + 2].Value2 = 0; // 金額
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
userSheet.Cells[rowIndex, monthCol + (i - 1) * 3].Value2 = monthDetail.PriceWithTax ?? 0; // 單價
|
userSheet.Cells[currentRowIndex, monthCol + (i - 1) * 3].Value2 = monthDetail.PriceWithTax ?? 0; // 單價
|
||||||
userSheet.Cells[rowIndex, monthCol + (i - 1) * 3 + 1].Value2 = monthDetail.Quantity ?? 0; // 數量
|
userSheet.Cells[currentRowIndex, monthCol + (i - 1) * 3 + 1].Value2 = monthDetail.Quantity ?? 0; // 數量
|
||||||
userSheet.Cells[rowIndex, monthCol + (i - 1) * 3 + 2].Value2 = monthDetail.TotalAmount ?? 0; // 总额
|
userSheet.Cells[currentRowIndex, monthCol + (i - 1) * 3 + 2].Value2 = monthDetail.TotalAmount ?? 0; // 总额
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
userSheet.Cells[rowIndex, 49].Value = productSalesDetail.Quantity;
|
userSheet.Cells[currentRowIndex, 49].Value = productSalesDetail.Quantity;
|
||||||
userSheet.Cells[rowIndex, 50].Value = productSalesDetail.TotalAmount;
|
userSheet.Cells[currentRowIndex, 50].Value = productSalesDetail.TotalAmount;
|
||||||
|
|
||||||
rowIndex++;
|
rowIndex++;
|
||||||
}
|
}
|
||||||
@ -656,7 +704,7 @@ namespace KellyReport_D.Utils
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine("parse date error:" + ex.Message);
|
FileLogger.Error($"解析日期错误 '{rawValue}'", ex);
|
||||||
//throw new FormatException($"日期格式错误 '{rawValue}'");
|
//throw new FormatException($"日期格式错误 '{rawValue}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,28 +789,25 @@ namespace KellyReport_D.Utils
|
|||||||
// 获取「銷售年度預估」工作表
|
// 获取「銷售年度預估」工作表
|
||||||
ReadSalesForecastData(context);
|
ReadSalesForecastData(context);
|
||||||
// 获取「產品年度預估」工作表
|
// 获取「產品年度預估」工作表
|
||||||
//ReadProductForecastData(context);
|
// GenProductForecastData(context);
|
||||||
GenDepartmentSummary(context);
|
GenDepartmentSummary(context);
|
||||||
|
|
||||||
GenBussenessSheet(context);
|
GenBussenessSheet(context);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Error generating forecast:" + ex.Message);
|
FileLogger.Error("生成销售年度预估表失败", ex);
|
||||||
|
|
||||||
MessageBox.Show("分析预估表失败: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
MessageBox.Show("分析预估表失败: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.Text = originLabel;
|
button.Text = originLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GenBussenessSheet(GenForecaseContext context)
|
public static bool FindBussenessYearRow(Worksheet sheet, string targetYear, ref int yearRowIndex)
|
||||||
{
|
{
|
||||||
var app = context.Application;
|
|
||||||
Worksheet sheet = CreateSheetIfNotExisted(app, "業務月達成率");
|
|
||||||
|
|
||||||
Range usedRange = sheet.UsedRange;
|
Range usedRange = sheet.UsedRange;
|
||||||
int totalRows = usedRange?.Rows?.Count ?? 0;
|
int totalRows = usedRange?.Rows?.Count ?? 0;
|
||||||
int yearRowIndex = 1;
|
|
||||||
Boolean updateCurrentBook = false;
|
Boolean updateCurrentBook = false;
|
||||||
while (yearRowIndex < totalRows - 1)
|
while (yearRowIndex < totalRows - 1)
|
||||||
{
|
{
|
||||||
@ -777,7 +822,7 @@ namespace KellyReport_D.Utils
|
|||||||
yearValue = (rawYearValue).ToString();
|
yearValue = (rawYearValue).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yearValue == context.MonthData[0])
|
if (yearValue == targetYear)
|
||||||
{
|
{
|
||||||
updateCurrentBook = true;
|
updateCurrentBook = true;
|
||||||
break;
|
break;
|
||||||
@ -786,6 +831,19 @@ namespace KellyReport_D.Utils
|
|||||||
yearRowIndex += 15;
|
yearRowIndex += 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return updateCurrentBook;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void GenBussenessSheet(GenForecaseContext context)
|
||||||
|
{
|
||||||
|
var app = context.Application;
|
||||||
|
Worksheet sheet = CreateSheetIfNotExisted(app, "業務月達成率");
|
||||||
|
|
||||||
|
Range usedRange = sheet.UsedRange;
|
||||||
|
int totalRows = usedRange?.Rows?.Count ?? 0;
|
||||||
|
int yearRowIndex = 1;
|
||||||
|
Boolean updateCurrentBook = FindBussenessYearRow(sheet, context.MonthData[0], ref yearRowIndex);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string rowRanges = "";
|
string rowRanges = "";
|
||||||
@ -808,6 +866,7 @@ namespace KellyReport_D.Utils
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
FileLogger.Error($"更新{context.MonthData[0]}年業務月達成率失败", ex);
|
||||||
throw new Exception($"更新{context.MonthData[0]}年業務月達成率失败", ex);
|
throw new Exception($"更新{context.MonthData[0]}年業務月達成率失败", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -894,6 +953,8 @@ namespace KellyReport_D.Utils
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
FileLogger.Error($"写入{context.MonthData[0]}年業務月達成率失败", ex);
|
||||||
|
|
||||||
MessageBox.Show("写入业绩月达成率时发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
MessageBox.Show("写入业绩月达成率时发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -934,44 +995,6 @@ namespace KellyReport_D.Utils
|
|||||||
context.ClientContactList = clientContactList;
|
context.ClientContactList = clientContactList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadProductForecastData(GenForecaseContext context)
|
|
||||||
{
|
|
||||||
var app = context.Application;
|
|
||||||
|
|
||||||
var productForecastSheet = app.Worksheets["產品年度預估"] as Worksheet;
|
|
||||||
var productRange = productForecastSheet.UsedRange;
|
|
||||||
IList<ProductForecastInput> productForecastList = new List<ProductForecastInput>();
|
|
||||||
|
|
||||||
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)
|
private static void ReadSalesForecastData(GenForecaseContext context)
|
||||||
{
|
{
|
||||||
var app = context.Application;
|
var app = context.Application;
|
||||||
@ -1076,6 +1099,7 @@ namespace KellyReport_D.Utils
|
|||||||
];
|
];
|
||||||
turnOverRange.Merge();
|
turnOverRange.Merge();
|
||||||
}
|
}
|
||||||
|
usedRange = productSheet.UsedRange;
|
||||||
|
|
||||||
var productSalesList = context.SalesDetails
|
var productSalesList = context.SalesDetails
|
||||||
.Where(x => x.InvoiceDate.HasValue && x.InvoiceDate.Value.Year == yearNumber)
|
.Where(x => x.InvoiceDate.HasValue && x.InvoiceDate.Value.Year == yearNumber)
|
||||||
@ -1089,9 +1113,9 @@ namespace KellyReport_D.Utils
|
|||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
Range totalRange = usedRange.Find(What: $"總計", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
|
Range totalRange = productSheet.UsedRange.Find(What: $"總計", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
|
||||||
|
|
||||||
int totalRowCount = usedRange.Rows.Count + 1;
|
int totalRowCount = productSheet.UsedRange.Rows.Count + 1;
|
||||||
if (totalRange != null)
|
if (totalRange != null)
|
||||||
{
|
{
|
||||||
totalRowCount = totalRange.Row;
|
totalRowCount = totalRange.Row;
|
||||||
@ -1110,7 +1134,7 @@ namespace KellyReport_D.Utils
|
|||||||
var curProductName = productSalesSummary.ProductNameEN;
|
var curProductName = productSalesSummary.ProductNameEN;
|
||||||
// look for the product row
|
// look for the product row
|
||||||
// if not exists then create a new row
|
// if not exists then create a new row
|
||||||
Range productRange = usedRange.Find(
|
Range productRange = productSheet.UsedRange.Find(
|
||||||
What: curProductName,
|
What: curProductName,
|
||||||
LookIn: XlFindLookIn.xlValues,
|
LookIn: XlFindLookIn.xlValues,
|
||||||
LookAt: XlLookAt.xlWhole,
|
LookAt: XlLookAt.xlWhole,
|
||||||
@ -1159,6 +1183,127 @@ namespace KellyReport_D.Utils
|
|||||||
|
|
||||||
FormatSheetStyle(productSheet);
|
FormatSheetStyle(productSheet);
|
||||||
}
|
}
|
||||||
|
public static void GenClientSummarySheet(ImportContext context)
|
||||||
|
{
|
||||||
|
var app = context.Application;
|
||||||
|
|
||||||
|
string sheetName = $"客戶年度預估";
|
||||||
|
Worksheet clientSheet = CreateSheetIfNotExisted(app, sheetName);
|
||||||
|
clientSheet.Activate();
|
||||||
|
|
||||||
|
context.YearList.ForEach(yearNumber =>
|
||||||
|
{
|
||||||
|
Range turnOverRange = clientSheet.UsedRange.Find(What: $"{yearNumber}-Turnover", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
|
||||||
|
var clientSalesList = context.SalesDetails
|
||||||
|
.Where(x => x.InvoiceDate.HasValue && x.InvoiceDate.Value.Year == yearNumber)
|
||||||
|
.GroupBy(x => x.ClientName)
|
||||||
|
.Select(grouped => new ImportContext.GroupedSalesDetailModel()
|
||||||
|
{
|
||||||
|
ClientName = grouped.Key,
|
||||||
|
Quantity = grouped.Sum(x => x.Quantity ?? 0),
|
||||||
|
TotalAmount = grouped.Sum(x => x.TotalAmount ?? 0),
|
||||||
|
Details = grouped.ToList()
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
if (turnOverRange == null)
|
||||||
|
{
|
||||||
|
int insertCol = 2;
|
||||||
|
|
||||||
|
Range insertRange = clientSheet.Columns[$"{GetColumnLetter(insertCol)}:{GetColumnLetter(insertCol + 5)}"];
|
||||||
|
insertRange.EntireColumn.Insert(XlInsertShiftDirection.xlShiftToRight);
|
||||||
|
insertRange = clientSheet.Columns[$"{GetColumnLetter(insertCol)}:{GetColumnLetter(insertCol + 5)}"];
|
||||||
|
insertRange.ClearFormats();
|
||||||
|
|
||||||
|
clientSheet.Cells[1, insertCol].Value2 = $"{yearNumber}-Turnover";
|
||||||
|
|
||||||
|
clientSheet.Cells[2, insertCol].Value2 = "數量";
|
||||||
|
clientSheet.Cells[2, insertCol + 1].Value2 = "金額(含稅)";
|
||||||
|
clientSheet.Cells[2, insertCol + 2].Value2 = "金額(未稅)";
|
||||||
|
clientSheet.Cells[2, insertCol + 3].Value2 = "平均單價";
|
||||||
|
clientSheet.Cells[2, insertCol + 4].Value2 = "成長率";
|
||||||
|
var growthRange = clientSheet.Range[
|
||||||
|
clientSheet.Cells[2, insertCol + 4],
|
||||||
|
clientSheet.Cells[2, insertCol + 5]
|
||||||
|
];
|
||||||
|
growthRange.Merge();
|
||||||
|
|
||||||
|
turnOverRange = clientSheet.Range[
|
||||||
|
clientSheet.Cells[1, insertCol],
|
||||||
|
clientSheet.Cells[1, insertCol + 5]
|
||||||
|
];
|
||||||
|
turnOverRange.Merge();
|
||||||
|
}
|
||||||
|
|
||||||
|
Range totalRange = clientSheet.UsedRange.Find(What: $"總計", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
|
||||||
|
|
||||||
|
int totalRowCount = clientSheet.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 clientSalesGroup in clientSalesList)
|
||||||
|
{
|
||||||
|
var curClientName = clientSalesGroup.ClientName;
|
||||||
|
// look for the Client row
|
||||||
|
// if not exists then create a new row
|
||||||
|
Range clientRange = clientSheet.UsedRange.Find(
|
||||||
|
What: curClientName,
|
||||||
|
LookIn: XlFindLookIn.xlValues,
|
||||||
|
LookAt: XlLookAt.xlWhole,
|
||||||
|
SearchOrder: XlSearchOrder.xlByRows,
|
||||||
|
SearchDirection: XlSearchDirection.xlNext,
|
||||||
|
MatchCase: false
|
||||||
|
);
|
||||||
|
|
||||||
|
if (clientRange == null)
|
||||||
|
{
|
||||||
|
clientSheet.Rows[totalRowCount].Insert();
|
||||||
|
clientSheet.Cells[totalRowCount, 1].Value2 = curClientName;
|
||||||
|
clientRange = clientSheet.Cells[totalRowCount, 1];
|
||||||
|
|
||||||
|
totalRowCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int curRowIndex = clientRange.Row;
|
||||||
|
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex].Value2 = clientSalesGroup.Quantity;
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 1].Value2 = clientSalesGroup.TotalAmount;
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 2].formula = $"={amountColLetter}{curRowIndex}/1.13";
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 3].formula = $"={amountColLetter}{curRowIndex}/${quantityColLetter}{curRowIndex}";
|
||||||
|
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 4].formula = $"={quantityColLetter}{curRowIndex}/${prevQuantityColLetter}{curRowIndex}";
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 5].formula = $"={amountColLetter}{curRowIndex}/${prevAmountColLetter}{curRowIndex}";
|
||||||
|
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 4].NumberFormat = "0.00%";
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 5].NumberFormat = "0.00%";
|
||||||
|
}
|
||||||
|
|
||||||
|
clientSheet.Cells[totalRowCount, 1].Value2 = "總計";
|
||||||
|
clientSheet.Cells[totalRowCount, startColIndex].formula = $"=SUM({quantityColLetter}5:{quantityColLetter}{totalRowCount - 1})";
|
||||||
|
clientSheet.Cells[totalRowCount, startColIndex + 1].formula = $"=SUM({amountColLetter}5:{amountColLetter}{totalRowCount - 1})";
|
||||||
|
clientSheet.Cells[totalRowCount, startColIndex + 2].formula = $"=SUM({amountNoTaxColLetter}5:{amountNoTaxColLetter}{totalRowCount - 1})";
|
||||||
|
|
||||||
|
clientSheet.Cells[totalRowCount + 1, 1].Value2 = "備註";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex].formula = $"={quantityColLetter}{totalRowCount}/{prevQuantityColLetter}{totalRowCount}";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex + 1].formula = $"={amountColLetter}{totalRowCount}/{prevAmountColLetter}{totalRowCount}";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex + 2].formula = $"={amountNoTaxColLetter}{totalRowCount}/{prevAmountNoTaxColLetter}{totalRowCount}";
|
||||||
|
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex].NumberFormat = "0.00%";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex + 1].NumberFormat = "0.00%";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex + 2].NumberFormat = "0.00%";
|
||||||
|
});
|
||||||
|
|
||||||
|
FormatSheetStyle(clientSheet);
|
||||||
|
}
|
||||||
|
|
||||||
public static void GenDepartmentSummary(GenForecaseContext context)
|
public static void GenDepartmentSummary(GenForecaseContext context)
|
||||||
{
|
{
|
||||||
@ -1171,10 +1316,7 @@ namespace KellyReport_D.Utils
|
|||||||
deptSheet.Cells[1, 1].Value2 = "鈞全";
|
deptSheet.Cells[1, 1].Value2 = "鈞全";
|
||||||
deptSheet.Range[deptSheet.Cells[1, 1], deptSheet.Cells[2, 1]].Merge();
|
deptSheet.Range[deptSheet.Cells[1, 1], deptSheet.Cells[2, 1]].Merge();
|
||||||
|
|
||||||
var yearList = context.SalesForecastList
|
var yearList = context.SalesForecastList.Select(x => x.Year).Distinct().ToList();
|
||||||
.Select(x => x.Year)
|
|
||||||
.Distinct()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
Range initUsedRange = deptSheet.UsedRange;
|
Range initUsedRange = deptSheet.UsedRange;
|
||||||
|
|
||||||
@ -1269,6 +1411,133 @@ namespace KellyReport_D.Utils
|
|||||||
FormatSheetStyle(deptSheet);
|
FormatSheetStyle(deptSheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* public static void GenProductForecastData(GenForecaseContext context)
|
||||||
|
{
|
||||||
|
var app = context.Application;
|
||||||
|
|
||||||
|
string sheetName = $"產品年度預估";
|
||||||
|
Worksheet productSheet = CreateSheetIfNotExisted(app, sheetName);
|
||||||
|
productSheet.Activate();
|
||||||
|
|
||||||
|
var yearList = context.SalesForecastList.Select(x => x.Year).Distinct().ToList();
|
||||||
|
string yearNumber = yearList[0].ToString();
|
||||||
|
|
||||||
|
Range estimateRange = productSheet.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}-Estimate";
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
estimateRange = productSheet.Range[
|
||||||
|
productSheet.Cells[1, insertCol],
|
||||||
|
productSheet.Cells[1, insertCol + 5]
|
||||||
|
];
|
||||||
|
estimateRange.Merge();
|
||||||
|
|
||||||
|
var productSalesList = context.SalesForecastList
|
||||||
|
.Where(x => x..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 = clientSheet.UsedRange.Find(What: $"總計", LookIn: XlFindLookIn.xlValues, LookAt: XlLookAt.xlWhole, SearchOrder: XlSearchOrder.xlByRows, SearchDirection: XlSearchDirection.xlNext, MatchCase: false);
|
||||||
|
|
||||||
|
int totalRowCount = clientSheet.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 = clientSheet.UsedRange.Find(
|
||||||
|
What: curProductName,
|
||||||
|
LookIn: XlFindLookIn.xlValues,
|
||||||
|
LookAt: XlLookAt.xlWhole,
|
||||||
|
SearchOrder: XlSearchOrder.xlByRows,
|
||||||
|
SearchDirection: XlSearchDirection.xlNext,
|
||||||
|
MatchCase: false
|
||||||
|
);
|
||||||
|
|
||||||
|
if (productRange == null)
|
||||||
|
{
|
||||||
|
clientSheet.Rows[totalRowCount].Insert();
|
||||||
|
clientSheet.Cells[totalRowCount, 1].Value2 = curProductName;
|
||||||
|
productRange = clientSheet.Cells[totalRowCount, 1];
|
||||||
|
|
||||||
|
totalRowCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int curRowIndex = productRange.Row;
|
||||||
|
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex].Value2 = productSalesSummary.Quantity;
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 1].Value2 = productSalesSummary.TotalAmount;
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 2].formula = $"={amountColLetter}{curRowIndex}/1.13";
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 3].formula = $"={amountColLetter}{curRowIndex}/${quantityColLetter}{curRowIndex}";
|
||||||
|
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 4].formula = $"={quantityColLetter}{curRowIndex}/${prevQuantityColLetter}{curRowIndex}";
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 5].formula = $"={amountColLetter}{curRowIndex}/${prevAmountColLetter}{curRowIndex}";
|
||||||
|
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 4].NumberFormat = "0.00%";
|
||||||
|
clientSheet.Cells[curRowIndex, startColIndex + 5].NumberFormat = "0.00%";
|
||||||
|
}
|
||||||
|
|
||||||
|
clientSheet.Cells[totalRowCount, 1].Value2 = "總計";
|
||||||
|
clientSheet.Cells[totalRowCount, startColIndex].formula = $"=SUM({quantityColLetter}5:{quantityColLetter}{totalRowCount - 1})";
|
||||||
|
clientSheet.Cells[totalRowCount, startColIndex + 1].formula = $"=SUM({amountColLetter}5:{amountColLetter}{totalRowCount - 1})";
|
||||||
|
clientSheet.Cells[totalRowCount, startColIndex + 2].formula = $"=SUM({amountNoTaxColLetter}5:{amountNoTaxColLetter}{totalRowCount - 1})";
|
||||||
|
|
||||||
|
clientSheet.Cells[totalRowCount + 1, 1].Value2 = "備註";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex].formula = $"={quantityColLetter}{totalRowCount}/{prevQuantityColLetter}{totalRowCount}";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex + 1].formula = $"={amountColLetter}{totalRowCount}/{prevAmountColLetter}{totalRowCount}";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex + 2].formula = $"={amountNoTaxColLetter}{totalRowCount}/{prevAmountNoTaxColLetter}{totalRowCount}";
|
||||||
|
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex].NumberFormat = "0.00%";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex + 1].NumberFormat = "0.00%";
|
||||||
|
clientSheet.Cells[totalRowCount + 1, startColIndex + 2].NumberFormat = "0.00%";
|
||||||
|
});
|
||||||
|
FormatSheetStyle(clientSheet);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public static void UpdateDeptartmentSummary(ImportContext context)
|
public static void UpdateDeptartmentSummary(ImportContext context)
|
||||||
{
|
{
|
||||||
var app = context.Application;
|
var app = context.Application;
|
||||||
@ -1283,7 +1552,7 @@ namespace KellyReport_D.Utils
|
|||||||
|
|
||||||
if (yearRange == null)
|
if (yearRange == null)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Cannot find year column in department summary: {0}", yearoNumber);
|
FileLogger.Info($"Cannot find year column in department summary: {yearoNumber}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user