C# 使用 NPOI 处理Excel导入单元格内容是公式问题

C# 使用 NPOI 处理Excel导入单元格内容是公式问题

引言:今天在处理业务的时候,碰到导入Excel数据不成功的问题,那么就在这里做下笔记吧。
首先,我们有以下的数据。整块业务逻辑的代码在最后会贴上!
1.数值公式示例:
可以看出L3的内容值是80,公式J3*0.2
C# 使用 NPOI 处理Excel导入单元格内容是公式问题_第1张图片
我们需要使用判断ICell对象的CellType枚举类型,当=CellType.Formula,则代表单元格是公式类型的。则直接用cell.NumericCellValue取值即可。
C# 使用 NPOI 处理Excel导入单元格内容是公式问题_第2张图片
对于Excel来讲,除了数值的一些公式以外,还会有日期公式,不过最后都是进入到CellType.Formula判断中,需要另外根据转换出来的数值进行转换成日期类型即可。
2.日期公式示例:
G4的内容我使用的是TODAY公式获取当前日期。
C# 使用 NPOI 处理Excel导入单元格内容是公式问题_第3张图片
同样的,我们需要使用判断ICell对象的CellType枚举类型,当=CellType.Formula,则代表单元格是公式类型的。则直接用cell.NumericCellValue取值,需要根据取出来的数值进行转换成日期类型即可。
C# 使用 NPOI 处理Excel导入单元格内容是公式问题_第4张图片
数值转换成日期的处理代码:

long isNumberDateTime = 0;
if (Int64.TryParse(cellVal.ToString(), out isNumberDateTime))
{
    //数值型,则转换成日期
    DateTime d = DateTime.FromOADate(double.Parse(cellVal.ToString()));
}

转换后的结果:
C# 使用 NPOI 处理Excel导入单元格内容是公式问题_第5张图片
3.整块业务逻辑的代码:

#region Excel
        /// 
        /// Excel文件转换成DataTable
        /// 
        /// 文件路径
        /// 是否使用新列名,默认:是
        /// 删除上面的行索引(由于有些Excel导入时上面会存在多余行)
        /// 返回列名Cols0,Cols1,Cols2···以此类推
        public DataTable ExcelToTable(string filePath, bool isUseNewColumnName = true, int deleteEndRowIndex = 0)
        {
            DataTable dataTable = new DataTable();
            string a = Path.GetExtension(filePath).ToLower();
            DataTable result;
            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                IWorkbook workbook;
                if (a == ".xlsx")
                {
                    workbook = new XSSFWorkbook(fileStream);
                }
                else
                {
                    if (a == ".xls")
                    {
                        workbook = new HSSFWorkbook(fileStream);
                    }
                    else
                    {
                        workbook = null;
                        throw new Exception("请导入.xlsx或.xls格式的文档");
                    }
                }
                if (workbook == null)
                {
                    result = null;
                    return result;
                }
                ISheet sheetAt = workbook.GetSheetAt(0);
                if (deleteEndRowIndex != 0)
                {
                    for (int i = deleteEndRowIndex; i >= 1; i--)
                    {
                        sheetAt.ShiftRows(i, i + 1, -1);
                    }
                }

                IRow row = sheetAt.GetRow(sheetAt.FirstRowNum);
                List<int> list = new List<int>();
                for (int i = 0; i < (int)row.LastCellNum; i++)
                {
                    if (isUseNewColumnName)
                    {
                        dataTable.Columns.Add(new DataColumn("Cols" + i.ToString()));
                    }
                    else
                    {
                        object valueType = this.GetValueType(row.GetCell(i));
                        if (valueType == null || valueType.ToString() == string.Empty)
                        {
                            dataTable.Columns.Add(new DataColumn("Cols" + i.ToString()));
                        }
                        else
                        {
                            dataTable.Columns.Add(new DataColumn(valueType.ToString()));
                        }
                    }

                    list.Add(i);
                }
                for (int j = sheetAt.FirstRowNum + 1; j <= sheetAt.LastRowNum; j++)
                {
                    DataRow dataRow = dataTable.NewRow();
                    bool bCellIsNull = false;
                    foreach (int current in list)
                    {
                        if (sheetAt.GetRow(j) == null)
                            break;
                        ICell cell = sheetAt.GetRow(j).GetCell(current);
                        dataRow[current] = this.GetValueType(cell);
                        if (dataRow[current] != null && dataRow[current].ToString() != string.Empty)
                        {
                            bCellIsNull = true;
                        }
                    }
                    if (bCellIsNull)
                    {
                        dataTable.Rows.Add(dataRow);
                    }
                }
            }
            result = dataTable;
            return result;
        }

        /// 
        /// 获取单元格类型
        /// 
        /// 
        /// 
        private object GetValueType(ICell cell)
        {
            bool flag = cell == null;
            object result;
            if (flag)
            {
                result = null;
            }
            else
            {
                switch (cell.CellType)
                {
                    case CellType.Numeric:                  //数值
                        result = cell.NumericCellValue;
                        return result;
                    case CellType.String:                   //文本
                        result = cell.StringCellValue;
                        return result;
                    case CellType.Blank:                    //空值
                        result = null;
                        return result;
                    case CellType.Boolean:                  //布尔类型
                        result = cell.BooleanCellValue;
                        return result;
                    case CellType.Error:                    //二进制
                        result = cell.ErrorCellValue;
                        return result;
                    case CellType.Formula:                  //公式
                        //这里只能处理数值公式。其他公式将会被转换成数值类型,如:日期公式。
                        result = cell.NumericCellValue;
                        return result;

                }

                result = "=" + cell.CellFormula;
            }
            return result;
        }

        #endregion

感谢支持,有写得不好的地方还望多多指教。

你可能感兴趣的:(C#,c#,开发语言,后端)