c# NPOI通過單元格里的公式,計算數值


業務場景

公司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

https://stackoverflow.com/questions/17475359/how-to-use-npoi-to-read-excel-spreadsheet-that-contains-empty-cells


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM