1、业务背景

做导入某业务模块的Excel表格文件时,利用NPOI组件导入,

① 导入的日期错乱(如XX-X月-2022),关于此种情况之前没做格式化做了单独处理,可以查看文章.net NPOI Excel导入:时间格式2022/5/26导入变成26-5月-2022,做了格式化就快捷方便多了

② Excel表中某列通过公式计算好的列导入后获取到的是公式(如D1*E1),不是具体的值,

此时就需要在工作表生成DataTable之前做格式化处理操作,下面直接上代码

2、解决方案

1)写一个判断单元格列类型格式化的公共方法

/// <summary>
/// 判断单元格列的类型
/// </summary>
/// <param name="cell"></param>
/// <returns></returns>
public static object GetValueType(ICell cell)
{
bool flag = cell == null;
object result = null;
if(flag) result = null;
switch(cell.CellType)
{
case CellType.Boolean:
result = cell.BooleanCellValue;
break;
case CellType.Error:
result = cell.ErrorCellValue;
break;
case CellType.Formula:
switch(cell.CachedFormulaResultType)
{
case CellType.Boolean:
result = cell.BooleanCellValue;
break;
case CellType.Error:
result = ErrorEval.GetText(cell.ErrorCellValue);
break;
case CellType.Numeric:
if(DateUtil.IsCellDateFormatted(cell))
{
result = cell.DateCellValue.ToString("yyyy-MM-dd hh:MM:ss");
}
else
{
result = cell.NumericCellValue;
}
break;
case CellType.String:
string str = cell.StringCellValue;
if(!string.IsNullOrEmpty(str))
{
result = str.ToString();
}
else
{
result = null;
}
break;
case CellType.Unknown:
case CellType.Blank:
default:
result = string.Empty;
break;
}
break;
case CellType.Numeric:
if(DateUtil.IsCellDateFormatted(cell))
{
result = cell.DateCellValue.ToString("yyyy-MM-dd hh:MM:ss");
}
else
{
result = cell.NumericCellValue;
}
break;
case CellType.String:
string strValue = cell.StringCellValue;
if(!string.IsNullOrEmpty(strValue))
{
result = strValue.ToString();
}
else
{
result = null;
}
break;
case CellType.Unknown:
case CellType.Blank:
default:
result = string.Empty;
break;
}
return result;
}

2)在工作表生成DataTable时调用上述的公共方法

/// <summary>
/// 从工作表中生成DataTable
/// </summary>
/// <param name="sheet"></param>
/// <param name="headerRowIndex"></param>
/// <returns></returns>
public static DataTable GetDataTableFromSheet(ISheet sheet, int headerRowIndex)
{
DataTable table = new DataTable();
IRow headerRow = sheet.GetRow(headerRowIndex);
int cellCount = headerRow.LastCellNum;
for(int i = headerRow.FirstCellNum; i < cellCount; i++)
{
if(headerRow.GetCell(i) == null || headerRow.GetCell(i).StringCellValue.Trim() == "")
{
// 如果遇到第一个空列,则不再继续向后读取
cellCount = i;
break;
}
DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
table.Columns.Add(column);
}
for(int i = (headerRowIndex + 1); i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
//如果遇到某行的第一个单元格的值为空,则不再继续向下读取
if(row != null && row.GetCell(0) != null && !string.IsNullOrEmpty(row.GetCell(0).ToString()))
{
DataRow dataRow = table.NewRow();
for(int j = row.FirstCellNum; j < cellCount; j++)
{
ICell cell = row.GetCell(j);
object valueType = GetValueType(cell);
if(valueType == null || valueType.ToString() == string.Empty)
{
dataRow[j] = string.Empty;
}
else
{
dataRow[j] = valueType.ToString();
}
}
table.Rows.Add(dataRow);
}
}
return table;
}

3)在Excel导入方法中调用工作表生成DataTable

/// <summary>
/// 由Excel导入DataTable
/// </summary>
/// <param name="excelFileStream">Excel文件流</param>
/// <param name="sheetName">Excel工作表名称</param>
/// <param name="headerRowIndex">Excel表头行索引</param>
/// <param name="isCompatible">是否为兼容模式</param>
/// <returns>DataTable</returns>
public static DataTable ToDataTable(Stream excelFileStream, string sheetName, int headerRowIndex, bool isCompatible)
{
IWorkbook workbook = CreateWorkbook(isCompatible, excelFileStream);
ISheet sheet = null;
int sheetIndex = -1;
if(int.TryParse(sheetName, out sheetIndex))
{
sheet = workbook.GetSheetAt(sheetIndex);
}
else
{
sheet = workbook.GetSheet(sheetName);
}
DataTable table = GetDataTableFromSheet(sheet, headerRowIndex);
excelFileStream.Close();
workbook = null;
sheet = null;
return table;
}

4)文件处理

// 文件处理核心代码
if(files != null && files.Files.Count > 0)
{
try
{
var file = files.Files[0];
if(file == null)
{
return "文件不能为空";
}
var fileName = file.FileName;
// 判断文件大小
if(file.Length > 10 * 1024 * 1024)
{
return "文件大小不能大于10M";
}
string fileExtension = file.FileName.Substring(file.FileName.LastIndexOf(".")); // 获取文件名称后缀
bool GetIsCompatible = new []
{
".xls", ".xlt"
}.Count(e => e.Equals(fileExtension, StringComparison.OrdinalIgnoreCase)) > 0;
// 判断文件格式
if(!(fileExtension.ToLower() == ".xls" || fileExtension.ToLower() == ".xlsx"))
{
return "文件扩展名应该是.xls或.xlsx";
}
var stream = file.OpenReadStream();
var dt = ExcelInHelper.ToDataTable(stream, "Sheet1", 0, GetIsCompatible);
if(dt != null && dt.Rows.Count > 0)
{
// 处理数据
// ......
}
}
catch(Exception ex)
{
return $ "读取文件发生错误,错误原因:{ex.Message}";
}
}
else
{
return "请上传文件";
}

3、总结

通过格式化处理,Excel工作表中的各种类型数据都可以提前格式化成我们导入需要的数据形式,当然上面的格式化方法也只是列出了部分类型,还有很多类型欢迎补充,以此本文简单快速的解决了关于NPOI导入的格式化问题。

若本文有帮助到阅读本文的同学,欢迎点赞、关注、收藏,互相学习交流。

.NET NPOI导出时间、公式等格式化的更多相关文章

  1. .NET NPOI导出Excel详解

    NPOI,顾名思义,就是POI的.NET版本.那POI又是什么呢?POI是一套用Java写成的库,能够帮助开发者在没有安装微软Office的情况下读写Office的文件. 支持的文件格式包括xls, ...

  2. NPOI导出模板样式

    /// <summary> /// 导出多种车辆统计表格 /// </summary> /// <returns></returns> [ActionN ...

  3. .NET Core使用NPOI导出复杂,美观的Excel详解

    前言: 这段时间一直专注于数据报表的开发,当然涉及到相关报表的开发数据导出肯定是一个不可避免的问题啦.客户要求要导出优雅,美观的Excel文档格式的来展示数据,当时的第一想法就是使用NPOI开源库来做 ...

  4. NPOI导出Excel (C#) 踩坑 之--The maximum column width for an individual cell is 255 charaters

    /******************************************************************* * 版权所有: * 类 名 称:ExcelHelper * 作 ...

  5. 基于NPOI导出和导入Excel

    概述 NPOI,顾名思义,就是POI的.NET版本.NPOI就是用.NET语言编写的一套数据导出Excel的开源项目,支持XML.xls.xlsx.ppt等格式..NET不仅实现Excel导出还可以实 ...

  6. NPOI导出多张图片到Excel

    常用NPOI导出数据到excel,但没有试过如何导出图片.NPOI最大的特点就是不依赖于Excel组件,服务端不需要安装Excel.在单元格中插入图片主要是用HSSFClientAnchor对象.他有 ...

  7. asp.net NPOI导出xlsx格式文件,打开文件报“Excel 已完成文件级验证和修复。此工作簿的某些部分可能已被修复或丢弃”

    NPOI导出xlsx格式文件,会出现如下情况: 点击“是”: 导出代码如下: /// <summary> /// 将datatable数据写入excel并下载 /// </summa ...

  8. NPOI导出Excel及使用问题

    NPOI导出Excel及使用问题 因为最近公司质管部门提出了一个统计报表的需求:要求导出一个2016及2017年度深圳区域的所有供应商的费用成本计算--一个22列的Excel表,其中还包括多列的合并单 ...

  9. Npoi导出excel整理(附源码)

    前些日子做了一个简单的winform程序,需要导出的功能,刚开始省事直接使用微软的组件,但是导出之后发现效率极其低下,绝对像web那样使用npoi组件,因此简单的进行了整理,包括直接根据DataTab ...

  10. WeihanLi.Npoi 导出支持自定义列内容啦

    WeihanLi.Npoi 导出支持自定义列内容啦 Intro 之前也有网友给提出过希望列合并或者自定义列内容的 issue 或请求,起初因为自己做 WeihanLi.Npoi 这个扩展的最初目的是导 ...

随机推荐

  1. go cookie session

    https://astaxie.gitbooks.io/build-web-application-with-golang/content/zh/06.1.html

  2. oracle问题记录

    ORA-01034: ORACLE not available [oracle@ilanni ~]$ sqlplus /nolog SQL*Plus: Release 10.2.0.1.0 – Pro ...

  3. 还在手撸TCP/UDP/COM通信?一个仅16K的库搞定!

    摘要 在一些项目中,可能会用到串口(COM)通信,也可能会使用TCP-Server,TCP-Client,UDP等等,这种实现起来都大差不差,所以我封装了一个无任何依赖小而美的通信框架,通用性强,安全 ...

  4. 随笔——写windows服务的时候如何调试 c# .net

    流程 1.更改项目 应用程序--输出类型--windows应用程序 改为 控制台应用程序 2.Program启动类中添加调用代码 3.服务类里面添加启动方法去启动OnStart和 Console.Re ...

  5. 快速构建一个简单的Springboot-web项目

    web项目基本的核心成分 数据落地 MYSQL数据库 登录标识 JWT :{Java web token } 记录有效登录状态 以及缓存常用数据: Redis 数据库与JAVA实体的快速自动映射ORM ...

  6. 数电第二周总结_by_yc

    数电第二周总结_CC 重点: 模块实例化.仿真测试.数值表示.参数.表达式. 模块实例化端口连接方法: A.顺序端口连接:需严格按照模块定义时的顺序 B.明明端口连接:对端口信号顺序不做要求 Ex-1 ...

  7. python连接MySQL数据库实现(用户登录测试功能)pymysql

    pymysql PyMySQL 是一个纯 Python 实现的 MySQL 客户端操作库,支持事务.存取过程.批量执行,实现增删改查等 # 注册 def register(cursor): usern ...

  8. 【机器学习】李宏毅——Recurrent Neural Network(循环神经网络)

    假设我们当前要做一个人工智能客服系统,那该系统就需要对用户输入的话语进行辨认,例如用户输入: I want to arrive Taipei on November 2nd 那么该系统就能够辨认出来T ...

  9. Django路由层之路由分发 名称空间 虚拟环境 视图层之三板斧 JsonRsponse对象 request对象获取文件 FBV与CBV CBV源码剖析 模板层

    目录 路由层之路由分发 路由层之名称空间 方式1:名称空间 方式2:别名不冲突即可 虚拟环境 pycharm创建虚拟环境 命令行形式创建虚拟环境 视图层之三板斧 HttpRsponse render ...

  10. VMware虚拟机开机黑屏解决方法

    挂起时可以看到显示,但是开机就黑屏 解决方法: 命令提示符,鼠标右键点击"命令提示符",弹出菜单之后选择"以管理员身份运行" 在命令提示符窗口中输入" ...