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

原文地址:https://www.cnblogs.com/passedbylove/p/12234352.html

时间: 2024-10-27 16:35:32

c# NPOI通过单元格里的公式,计算数值的相关文章

Excel 2003 中如何用VBA 代码访问单元格里的值及操作单元格 - 唐诗宋词的专栏 - 博客频道 - CSDN.NET

在Excel 中编写VBA 代码,最常做的事可能就是操作表单中单元格里的数据. 我这里总结一下如何从VBA 代码中操作单元格的数据. 在VBA 代码中操作单元格需要用到Range 对象,Range 是Excel 库(即Excel.exe文件)提供的一个类,封装了对表单中单元格的所有操作.Range 对象可以是一个单元格,一行单元格,一列单元格,或者四方的连续的单元格范围,甚至是几个单元格范围组合在一起.至于一个具体的Range 对象到底代表什么,就看我们怎么构造它了.(注,Range 类不支持N

NPOI Excel 单元格背景颜色对照表

NPOI Excel 单元格颜色对照表,在引用了 NPOI.dll 后可通过 ICellStyle 接口的 FillForegroundColor 属性实现 Excel 单元格的背景色设置,FillPattern 为单元格背景色的填充样式. NPOI Excel 单元格背景颜色设置方法以及颜色对照表: 1 2 3 4 5 6 ICellStyle style = workbook.CreateCellStyle(); style.FillForegroundColor = NPOI.HSSF.U

从excel的大单元格里快速提取内容

我公司的服务器信息会保存在一份高加密的excel里,由于历史遗留问题,里面的格式节选一部分出来是这样的: 注意看,ip地址不分内网外网是放在一个大的单元格里,中间是用空格隔开的,造成了这样的视觉效果. 现在公司需要把所有的服务器重新更换到新的zookeeper,那么使用ansible在批量处理的时候,就需要提取这些服务器的内网ip地址录入到hosts文件里,但是由于服务器实在太多不可能一个一个手动从excel的单元格挑选出"内网IP地址"复制粘贴,那么就需要进行一下批量挑选内网IP地址

【VBA研究】循环中用VBA在单元格中输入公式

作者:iamlaosong 先看一个简单的循环程序,VBA从数据库中读取数据后,需要在最后一个单元格输入求和公式: <span style="font-size:14px;">lineno = [A65536].End(xlUp).Row For i = 3 To lineno Cells(i, 9).FormulaR1C1 = "=RC[-3]+RC[-2]+RC[-1]" Next i </span> 公式的意思相当于Cells(i, 9

NPOI读取单元格日期问题

最近在使用ASP.Net MVC3来开发一个网站,需要实现数据的Excel导入导出功能.在处理导入时,遇到了一个问题:将所有的单元格都按字符串单元格来处理,运行时对日期类型的就会出错.搜了一下解决办法,最终解决了,将代码贴上: row = (HSSFRow)rows.Current; DataRow dataRow = dt.NewRow(); for (int i = 0; i < row.LastCellNum; i++) { ICell cell = row.GetCell(i); if

NPOI 读取单元格的格式

最近做项目需要导入一部分数据, 导入的数据的中, 有部分的百分比数据使用的是excel 的百分比, 有部分的数据使用的是字符串形式的格式,(数据来源于不同的人统计), 格式略微有点乱, 要求导入系统的时候, 将所有百分比的数据转换成百分制的数据存储起来. 因为之前项目使用的读取excel 的组件式NPOI , 所以我也就直接使用npoi来读, 我用的NPOI是2.0的版本的, 不算太新. 常规读取的时候, 是按照下面的方式读取到ICell的 IWorkbook workbook = null;

ios-根据单元格里的控件tag值,在方法外获得对应的section与row的值

在cell的代理方法里:cellForRowAtIndexPath btn.tag = indexPath.section *100 + indexPath.row; [cell.exitPersonBtn addTarget:self action:@selector(exitPersonBtnClick:) forControlEvents:UIControlEventTouchUpInside]; btn点击后触发的方法里,通过tag值获得cell里对应的控件 GroupMemberDat

NPOI设置单元格格式

本文转载自:http://blog.csdn.net/xxs77ch/article/details/50245641 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NPOI.HSSF.UserModel; using NPOI.SS.Formula.Eval; using NPOI.SS.Formu

NPOI 自定义单元格背景颜色-Excel

2016-12-27 10:44 by 杨新华, 5242 阅读, 0 评论, 收藏, 编辑 NPOI针对office2003使用HSSFWorkbook,对于offce2007及以上使用XSSFWorkbook:今天我以HSSFWorkbook自定义颜色为例说明,Office2007的未研究呢 在NPOI中默认的颜色类是HSSFColor,它内置的颜色有几十种供我们选择,如果不够怎么办,不能修改底层的HSSFColor类: 大概解决思路: 1.将颜色的RGB值添加进调色板HSSFPalette