C# 使用NPOI操作Excel的工具类

写在前面

NPOI是POI项目的.NET迁移版本。POI是一个开源的Java 读写 Excel、Word 等微软Ole2组件文档的项目;使用NPOI可以在没有安装Office或者相应环境的机器上对Word或Excel文档进行读写操作。

NPOI类库中操作EXCEL有两个模块分别是:

1️.HSSF模块,操作拓展名为.xls的Excel,对应Excel2003及以前的版本。
2️.XSSF模块,操作拓展名为.xlsx的Excel,对应Excel2007及以后的版本,可向下兼容xls,故本例使用XSSF下的XSSFWorkbook来操作。

通过NuGet获取NPOI

需要引用的命名空间如下:

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Collections;
using System.Data;

代码实现

   public class ExcelProcessor{#region 私有变量private int _perSheetCount = 40000;//每个sheet要保存的条数private string _filePath;private IWorkbook _currentWorkbook;private List<string> _sheets;private Dictionary<string, DataTable> _dataDict;#endregion#region 属性public List<string> Sheets{get { return _sheets ?? (_sheets = GetSheets(_filePath)); }}#endregion#region 构造器/// <summary>/// 默认构造器/// </summary>/// <param name="filePath"></param>public ExcelProcessor(string filePath){_filePath = filePath;_dataDict = new Dictionary<string, DataTable>();}/// <summary>/// 加载数据/// </summary>public bool LoadData(){try{using (var fs = new FileStream(_filePath, FileMode.OpenOrCreate, FileAccess.Read)){_currentWorkbook = new XSSFWorkbook(fs);}return true;}catch (Exception ex){return false;}}/// <summary>/// 最大接收5万条每页,大于5万时,使用系统默认的值(4万)/// </summary>/// <param name="perSheetCounts"></param>public ExcelProcessor(int perSheetCounts){if (_perSheetCount <= 50000)_perSheetCount = perSheetCounts;}#endregion#region 公有方法public List<string> GetSheets(string fileName){var sheets = new List<string>();if (_currentWorkbook == null)return sheets;for (int i = 0; i < _currentWorkbook.NumberOfSheets; i++){sheets.Add(_currentWorkbook.GetSheetName(i));}return sheets;}public object GetNumericCellValue(string sheetName, int rowIndex, int colIndex){if (!Sheets.Contains(sheetName))return null;var cell = _currentWorkbook.GetSheet(sheetName).GetRow(rowIndex).GetCell(colIndex - 1);return cell.NumericCellValue;}public object GetStringCellValue(string sheetName, int rowIndex, int colIndex){if (!Sheets.Contains(sheetName))return null;var cell = _currentWorkbook.GetSheet(sheetName).GetRow(rowIndex).GetCell(colIndex - 1);if (cell == null)return null;if (cell.CellType == CellType.Formula){if (cell.CachedFormulaResultType == CellType.String)return cell.StringCellValue;if (cell.CachedFormulaResultType == CellType.Numeric)return cell.NumericCellValue;if (cell.CachedFormulaResultType == CellType.Boolean)return cell.BooleanCellValue;return null;}if (cell.CellType == CellType.Numeric)return cell.NumericCellValue;if (cell.CellType == CellType.Boolean)return cell.NumericCellValue;return cell.StringCellValue;}public object GetDateTimeCellValue(string sheetName, int rowIndex, int colIndex){if (!Sheets.Contains(sheetName))return null;var cell = _currentWorkbook.GetSheet(sheetName).GetRow(rowIndex).GetCell(colIndex - 1);if (cell.CellType == CellType.String)return cell.StringCellValue;return cell.DateCellValue;}public ICell GetCell(string sheetName, int rowIndex, int colIndex){if (!Sheets.Contains(sheetName))return null;var sheet = _currentWorkbook.GetSheet(sheetName);if (sheet == null)return null;var row = sheet.GetRow(rowIndex);if (row == null)return null;var cell = row.GetCell(colIndex - 1);if (cell == null)return null;return cell;}/// <summary>/// 获取单元格里面的值/// </summary>/// <param name="sheetName">表名</param>/// <param name="x">行索引从1开始</param>/// <param name="y">列索引从1开始</param>/// <returns></returns>public object GetCellValue(string sheetName, int rowIndex, int colIndex){if (!Sheets.Contains(sheetName))return null;DataTable dt = null;if (!_dataDict.ContainsKey(sheetName)){dt = Import(sheetName);_dataDict.Add(sheetName, dt);}else{dt = _dataDict[sheetName];}if (dt == null)return null;if (dt.Rows.Count < rowIndex)return null;var rowIdx = rowIndex - 1;var row = dt.Rows[rowIdx];var colIdx = colIndex - 1;return row[colIdx];}public void SetCellValues(ICell cell, string cellType, string cellValue){switch (cellType){case "System.String": //字符串类型double result;if (double.TryParse(cellValue, out result))cell.SetCellValue(result);elsecell.SetCellValue(cellValue);break;case "System.DateTime": //日期类型DateTime dateV;DateTime.TryParse(cellValue, out dateV);cell.SetCellValue(dateV);break;case "System.Boolean": //布尔型bool boolV = false;bool.TryParse(cellValue, out boolV);cell.SetCellValue(boolV);break;case "System.Int16": //整型case "System.Int32":case "System.Int64":case "System.Byte":int intV = 0;int.TryParse(cellValue, out intV);cell.SetCellValue(intV);break;case "System.Decimal": //浮点型case "System.Double":double doubV = 0;double.TryParse(cellValue, out doubV);cell.SetCellValue(doubV);break;case "System.DBNull": //空值处理cell.SetCellValue("");break;default:cell.SetCellValue("");break;}}public DataTable Import(string sheetName){sheetName = string.IsNullOrEmpty(sheetName) ? "Sheet1" : sheetName;ISheet sheet = _currentWorkbook.GetSheet(sheetName);if (sheet == null){sheet = _currentWorkbook.GetSheetAt(0);}IEnumerator ie = sheet.GetRowEnumerator();IRow row = null;var maxCol = 0;while (ie.MoveNext()){row = ie.Current as IRow;//取一行,为了得到column的总数if (row.LastCellNum > maxCol)maxCol = row.LastCellNum;}var dt = new DataTable();for (int i = 0; i < maxCol; i++){dt.Columns.Add(string.Format("Col{0}", i));}ie.Reset();DataRow drow = null;ICell cell = null;var isHeader = true;while (ie.MoveNext()){if (isHeader){isHeader = false;continue;}row = ie.Current as IRow;drow = dt.NewRow();for (int i = 0; i < row.LastCellNum; i++){if (row.GetCell(i) == null){drow[i] = null;continue;}cell = row.GetCell(i) as ICell;switch (cell.CellType){case CellType.Blank:drow[i] = string.Empty;break;case CellType.Boolean:drow[i] = cell.BooleanCellValue;break;case CellType.Error:drow[i] = cell.ErrorCellValue;break;case CellType.Formula:drow[i] = "=" + cell.CellFormula;break;case CellType.Numeric:if (DateUtil.IsCellDateFormatted(cell)){drow[i] = cell.DateCellValue;}else{drow[i] = cell.NumericCellValue;}break;case CellType.String:drow[i] = cell.StringCellValue;break;case CellType.Unknown:break;default:drow[i] = null;break;}}dt.Rows.Add(drow);}return dt;}public string Export(string excelFileName, List<DataTable> dataTables){var workbook = new HSSFWorkbook();ISheet sheet = null;IRow row = null;ICell cell = null;var index = 0;foreach (var dataTable in dataTables){var tableName = dataTable.TableName;if (string.IsNullOrEmpty(tableName))tableName = "Sheet" + (++index);sheet = workbook.CreateSheet(tableName);//填充表头row = sheet.CreateRow(0);for (int i = 0; i < dataTable.Columns.Count; i++){cell = row.CreateCell(i);cell.SetCellValue(dataTable.Columns[i].ColumnName);}//填充内容for (int i = 0; i < dataTable.Rows.Count; i++){row = sheet.CreateRow(i + 1);for (int j = 0; j < dataTable.Columns.Count; j++){cell = row.CreateCell(j);SetCellValues(cell, dataTable.Columns[j].DataType.ToString(), dataTable.Rows[i][j].ToString());}}}if (File.Exists(excelFileName)) File.Delete(excelFileName);using (var fs = new FileStream(excelFileName, FileMode.CreateNew, FileAccess.Write)) workbook.Write(fs);return excelFileName;}public string Export(string excelFileName, DataTable dataTable){HSSFWorkbook workbook = new HSSFWorkbook();ISheet sheet = null;IRow row = null;ICell cell = null;int sheetCount = 1;//当前的sheet数量int currentSheetCount = 0;//循环时当前保存的条数,每页都会清零//表头样式ICellStyle style = workbook.CreateCellStyle();style.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;//内容样式style = workbook.CreateCellStyle();style.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;sheet = workbook.CreateSheet("Sheet" + sheetCount);//填充表头row = sheet.CreateRow(0);for (int i = 0; i < dataTable.Columns.Count; i++){cell = row.CreateCell(i);cell.SetCellValue(dataTable.Columns[i].ColumnName);cell.CellStyle = style;}//填充内容for (int i = 0; i < dataTable.Rows.Count; i++){if (currentSheetCount >= _perSheetCount){sheetCount++;currentSheetCount = 0;sheet = workbook.CreateSheet("Sheet" + sheetCount);}if (sheetCount == 1)//因为第一页有表头,所以从第二页开始写row = sheet.CreateRow(currentSheetCount + 1);else//以后没有表头了,所以从开始写,都是基于0的row = sheet.CreateRow(currentSheetCount);currentSheetCount++;for (int j = 0; j < dataTable.Columns.Count; j++){cell = row.CreateCell(j);cell.CellStyle = style;SetCellValues(cell, dataTable.Columns[j].DataType.ToString(), dataTable.Rows[i][j].ToString());}}FileStream fs = new FileStream(excelFileName, FileMode.CreateNew, FileAccess.Write);workbook.Write(fs);fs.Close();return excelFileName;}#endregion}

总结

本例中主要侧重对目标excel的单元格数据进行访问,对单元格的数据格式进行了比较详细的区分,可自行参考删减。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/218036.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos7搭建ftp服务

一、安装 yum -y install vsftpd vi /etc/vsftpd/vsftpd.conf二、编辑配置文件 /etc/vsftpd/vsftpd.conf 内容如下 #是否允许匿名&#xff0c;默认no anonymous_enableNO#这个设定值必须要为YES 时&#xff0c;在/etc/passwd内的账号才能以实体用户的方式登入我们的vsftpd主机…

DGL的图数据处理管道

DGL在 dgl.data 里实现了很多常用的图数据集。它们遵循了由 dgl.data.DGLDataset 类定义的标准的数据处理管道。 DGL推荐用户将图数据处理为 dgl.data.DGLDataset 的子类。该类为导入、处理和保存图数据提供了简单而干净的解决方案。 DGL中的Dataset类 它是处理、导入以及保存…

【小沐学写作】免费在线AI辅助写作汇总

文章目录 1、简介2、文涌Effidit&#xff08;腾讯&#xff09;2.1 工具简介2.2 工具功能2.3 工具体验 3、PPT小助手&#xff08;officeplus&#xff09;3.1 工具简介3.2 使用费用3.3 工具体验 4、DeepL Write&#xff08;仅英文&#xff09;4.1 工具简介4.2 工具体验 5、天工AI…

人工智能轨道交通行业周刊-第66期(2023.11.20-11.26)

本期关键词&#xff1a;智能铁鞋、TFDS、道岔密贴检查、Agent、Q*假说 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通RailMetro轨道世界铁路那些事铁路…

模型优化【2】-剪枝[局部剪枝]

模型剪枝是一种常见的模型压缩技术&#xff0c;它可以通过去除模型中不必要的参数和结构来减小模型的大小和计算量&#xff0c;从而提高模型的效率和速度。在 PyTorch 中&#xff0c;我们可以使用一些库和工具来实现模型剪枝。 pytorch实现剪枝的思路是生成一个掩码&#xff0…

css Vue尺子样式

原生css生成尺子样式 <template><div class"page"><div class"Light"></div><div class"rile"><ul id"list"><!--尺子需要几个单位就加几个--><li></li><li></li&…

Vue框架学习笔记——事件修饰符

文章目录 前文提要事件修饰符prevent&#xff08;常用&#xff09;stop&#xff08;不常用&#xff09;事件冒泡stop使用方法三层嵌套下的stop三层嵌套看出的stop&#xff1a; once&#xff08;常用&#xff09;capture&#xff08;不常用&#xff09;self&#xff08;不常用&a…

python多线程为什么没有跑满CPU?

1、实验环境 Vmvare虚拟机&#xff1a;单处理器2核。 2、Python获取CPU使用率 import psutildef get_cpu_percent():cpu_percent psutil.cpu_percent(interval1)return cpu_percentwhile(1):cpu_percent get_cpu_percent()print("当前CPU占用率&#xff1a;{}%"…

【C++】IO流

文章目录 一、C语言的输入与输出二、流是什么&#xff1f;三、CIO流1. C标准IO流2. C文件IO流 四、stringstream简单介绍 一、C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是 scanf () 与 printf()。 scanf(): 从标准输入设备(键盘)读取数据&#xff0c;并将值…

区块链技术将如何影响未来的数字营销?

你是否听腻了区块链和数字营销等流行语&#xff0c;却不明白它们对未来意味着什么&#xff1f;那么&#xff0c;准备好系好安全带吧&#xff0c;因为区块链技术将彻底改变我们对数字营销的看法。从建立消费者信任到提高透明度和效率&#xff0c;其可能性是无限的。 让我们来探…

Docker 部署 Nacos(单机),利用 MySQL 数据库存储配置信息

前面的话 默认你已经懂 Docker、docker-compose Nacos版本&#xff1a;v2.2.3 MySQL 版本&#xff1a;8.2.0 一、下载 打开 Nacos 官网 官网地址&#xff1a;官网 点击手册 左侧 Nacos Docker 克隆项目到本地 # 克隆项目&#xff0c;如果提示连接不到 github 请自行解决 …

4-20mA高精度采集方案

下载链接&#xff01;https://mp.weixin.qq.com/s?__bizMzU2OTc4ODA4OA&mid2247557466&idx1&snb5a323285c2629a41d2a896764db27eb&chksmfcfaf28dcb8d7b9bb6211030d9bda53db63ab51f765b4165d9fa630e54301f0406efdabff0fb&token976581939&langzh_CN#rd …