業務場景
公司B是母公司A的子公司,每個月都需要將耗材銷售情況統計向總公司報賬。
其中計算的內容如下:
1、該時間段客戶a、b、c 。。。z的分別購買耗材金額,即該客戶端銷售額
2、對於a、b、c 。。。z公司,每銷售一個單位數量的耗材都有居間費(抽成)
以上Excel中A-P列是從系統導出來的,其中Q(佣金總額)、P(業績)列是公式拖拽生成的。
Q列的公式 H2 * M2(M列如果沒有,默認為0)
R列的公式 L2 - Q2
以上公式,如果在任何一個Excel中,經過拖拽都很容易實現。
筆者以下使用C#中NPOI實現,將計算獲得的數據存入DataTable
關鍵代碼DataField.cs
public class DataField { private string _label; private string _name; private Type _type; private int _columnWidth = 10 /* default 10 */; private string _formula; private bool _isRequireCreateColumn; public DataField() { } public DataField(string label, string name, Type type) { this._label = label; this._name = name; this._type = type; } public DataField(string label, string name, Type type, int columnWidth):this(label,name,type) { this.ColumnWidth = columnWidth; } public DataField(string label, string name, Type type, string formula) : this(label, name, type) { this._formula = formula; } public DataField(string label, string name, Type type, int columnWidth, string formula) : this(label, name, type,columnWidth) { this._formula = formula; } public DataField(string label, string name, Type type, string formula, bool isRequireCreateColumn) : this(label, name, type,formula) { this._isRequireCreateColumn = isRequireCreateColumn; } public DataField(string label, string name, Type type, int columnWidth, string formula, bool isRequireCreateColumn) : this(label, name, type,formula,isRequireCreateColumn) { this._columnWidth = columnWidth; } /// <summary> /// 字段顯示名稱 /// </summary> public string Label { get => _label; set => _label = value; } /// <summary> /// 字段屬性名 /// </summary> public string Name { get => _name; set => _name = value; } /// <summary> /// 字段數據類型 /// </summary> public Type Type { get => _type; set => _type = value; } /// <summary> /// 字段寬度(n *256) /// </summary> public int ColumnWidth { get => _columnWidth; set => _columnWidth = value; } /// <summary> /// 公式(該字段必須是計算生成的類型) /// </summary> public string Formula { get => _formula; set => _formula = value; } /// <summary> /// 該字段通過創建插入表格中 /// </summary> public bool IsRequireCreateColumn { get => _isRequireCreateColumn; set => _isRequireCreateColumn = value; } }
關鍵業務代碼
private static DataField[] fields = new DataField[] { new DataField("序號","id",typeof(short)), new DataField("選擇","checked",typeof(string)), //delivery time交貨時間 //發貨時間 new DataField("發貨日期","shippingTime",typeof(DateTime)), new DataField("客戶簡稱","customerAbbreviation",typeof(string)), new DataField("銷售部門","department",typeof(string)), new DataField("業 務 員","seller",typeof(string)), new DataField("存貨名稱","productName",typeof(string),25), new DataField("數量","quantity",typeof(int)), new DataField("銷售單位","unit",typeof(string)), new DataField("無稅單價","price",typeof(float)), new DataField("無稅金額","amount1",typeof(float)), new DataField("價稅合計","amount2",typeof(float)), new DataField("居間費","commission",typeof(float)), new DataField("發票總金額","",typeof(string)), new DataField("制單人","",typeof(string)), new DataField("審核人","",typeof(string)), new DataField("佣金總額","totalCommission",typeof(float),"H{0} * M{0}",true), new DataField("業績","performance",typeof(float),"L{0} - Q{0}",true) }; for (int lineNum = 0; lineNum < rowCount; ++lineNum) { DataRow NewRow = myTable.NewRow(); for (int index = 0; index < fields.Length; index++) { var field = fields[index]; string formula = field.Formula; string label = field.Label; string name = field.Name; Type type = field.Type; bool isRequireCreateColumn = field.IsRequireCreateColumn; ICell cell; object value = null; //如果公式的值不為null/空字符等,則認為該列是需要計算生成的 if (isRequireCreateColumn || !string.IsNullOrWhiteSpace(formula)) { //新建列並設置數據類型為公式 cell = defaultSheet.GetRow(lineNum + 1).CreateCell(index); cell.SetCellType(CellType.Formula); cell.SetCellFormula(string.Format(formula, lineNum + 2)); //評估表達式的值 workbook.GetCreationHelper().CreateFormulaEvaluator().EvaluateFormulaCell(cell); value = cell.NumericCellValue; } } }
筆者為每個列額外設置了數據類型(即DataField的Type屬性),是為了方便在DataTable及后續里面進行數值計算甚至精確度裁剪。
經過以上設置,就可以計算出數值了
最終效果
其他參考:
https://stackoverflow.com/questions/24088737/how-to-re-calculate-a-cells-formula
https://www.cr173.com/html/18143_all.html
https://www.cnblogs.com/shiyh/p/7478222.html
https://stackoverflow.com/questions/25077009/npoi-setcellformula-custom-formula-in-vba