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.rhkb.cn/news/202719.html

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

相关文章

Spring Beans;Spring Bean的生命周期;spring Bean的作用域,spring处理线程并发问题

文章目录 Spring Beans请解释Spring Bean的生命周期解释Spring支持的几种bean的作用域Spring容器中的bean可以分为5个范围&#xff1a; Spring如何处理线程并发问题&#xff1f; 在现在的项目开发中经常使用到spring bean&#xff0c;那么来谈谈spring bean的生命周期&#xff…

Lua脚本解决redis实现的分布式锁多条命令原子性问题

线程1现在持有锁之后&#xff0c;在执行业务逻辑过程中&#xff0c;他正准备删除锁&#xff0c;而且已经走到了条件判断的过程中&#xff0c;比如他已经拿到了当前这把锁确实是属于他自己的&#xff0c;正准备删除锁&#xff0c;但是此时他的锁到期了&#xff0c;那么此时线程2…

(三) Windows 下 Sublime Text 3 配置Python环境和Anaconda代码提示

一&#xff1a;新建一个 Python3.7 编译环境。 1 Tools--Build System--New Build System... 修改前&#xff1a; 修改后&#xff1a; 内容&#xff1a; {"cmd":["C:\\Python\\Python37-32\\python.exe","-u","$file"],"file_r…

复数的几何意义

1、复平面&#xff0c;复数的其它表示法 (1)几何表示法 直角平面坐标&#xff1a; 复平面 实轴&#xff0c;虚轴 (2)向量表示法 向量 模&#xff1a; 复数加减法可用向量的三角形法则或者平行四边形法则 (3)结论 (两边之和大于第三边) ((两边之差大于第三边)) *辐角&am…

FlinkCDC实现主数据与各业务系统数据的一致性(瀚高、TIDB)

文章末尾附有flinkcdc对应瀚高数据库flink-cdc-connector代码下载地址 1、业务需求 目前项目有主数据系统和N个业务系统,为保障“一数一源”,各业务系统表涉及到主数据系统的字段都需用主数据系统表中的字段进行实时覆盖,这里以某个业务系统的一张表举例说明:业务系统表Ta…

pytorch安装GPU版本 (Cuda12.1)教程

使用本教程前&#xff0c;默认您已经安装并配置好了python3以上版本 1. 去官网下载匹配的Cuda Cuda下载地址 当前最高版本的Cuda是12.1 我安装的就是这个版本 小提示&#xff1a;自定义安装可以只选择安装Cuda Runtime。Nvidia全家桶不必全部安装。把全家桶全部安装完直接系统…

机器人规划算法——movebase导航框架源码分析

这里对MoveBase类的类成员进行了声明&#xff0c;以下为比较重要的几个类成员函数。 构造函数 MoveBase::MoveBase | 初始化Action 控制主体 MoveBase::executeCb收到目标&#xff0c;触发全局规划线程&#xff0c;循环执行局部规划 全局规划线程 void MoveBase::planThread |…

【小黑送书—第五期】>>《MATLAB科学计算从入门到精通》

从代码到函数&#xff0c;从算法到实战&#xff0c;从问题到应用&#xff0c;由浅入深掌握科学计算方法&#xff0c;高效解决实际问题。 从代码到函数&#xff0c;掌握多种经典算法 跨越多个领域&#xff0c;精通各类科学计算 多种应用实例&#xff0c;高效解决实际问题 今天给…

【尚跑】2023宝鸡马拉松安全完赛,顺利PB达成

1、赛事背景 千年宝地&#xff0c;一马当先&#xff01;10月15日7时30分&#xff0c;吉利银河2023宝鸡马拉松在宝鸡市行政中心广场鸣枪开跑。 不可忽视的是&#xff0c;这次赛事的卓越之处不仅在于规模和参与人数&#xff0c;还在于其精心的策划和细致入微的组织。为了确保每位…

操作NAND flash W25N01G

文章目录 W25N01G1 描述2 特点3 封装3.3.2 连接线 4 引脚/CSDO/WP/Hold SPI指令标准SPI命令双SPI四元SPI命令写保护 5 地址PA与PC最后一个扇区 OTP寄存器1块保护清除块保护指令* WP-E 寄存器2寄存器3BUSYP-FAILE-FAILECC位 8 命令8.1 装置ID 指令解读写状态寄存器 注意内容上拉…

今天给大家带来Python炫酷爱心代码

前言&#xff1a; 这个是小编之前朋友一直要小编去做的&#xff0c;不过之前技术不够所以一直拖欠今天也完成之前的约定吧&#xff01; 至于他是谁&#xff0c;我就不多说了直接上代码 一.代码展示 import random from math import sin, cos, pi, log from tkinter import …

Navicat 技术指引 | 适用于 GaussDB 的用户权限设置

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对 GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

SpringMVC系列-7 @CrossOrigin注解与跨域问题

背景 前段时间帮同事分析了一个跨域问题&#xff0c;正好系统分析和整理一下。 1.跨域 理解同源策略是理解跨域的前提。同源策略定义如下&#xff1a; 在同一来源的页面和脚本之间进行数据交互时&#xff0c;浏览器会默认允许操作&#xff0c;而不会造成跨站脚本攻击&#x…

2023年最新前端面试题汇总大全(含答案超详细,HTML,JS,CSS汇总篇)-- 持续更新

专项练习–持续更新 HTML篇CSS篇JS篇Vue篇TypeScript篇React篇微信小程序篇前端面试题汇总大全二&#xff08;含答案超详细&#xff0c;Vue&#xff0c;TypeScript&#xff0c;React&#xff0c;微信小程序&#xff0c;Webpack 汇总篇&#xff09;-- 持续更新 前端面试题汇总大…

Wireshark的捕获过滤器

Wireshark的过滤器&#xff0c;顾名思义&#xff0c;作用是对数据包进行过滤处理。具体过滤器包括捕获过滤器和显示过滤器。本文对捕获过滤器进行分析。 捕获过滤器&#xff1a;当进行数据包捕获时&#xff0c;只有那些满足给定的包含/排除表达式的数据包会被捕获。 捕获过滤器…

float和double(浮点型数据)在内存中的储存方法

作者&#xff1a;元清加油 主页&#xff1a;主页 编译环境&#xff1a;visual studio 2022 (x86) 相信大家都知道数据在内存中是以二进制储存的 整数的储存方法是首位是符号位&#xff0c;后面便是数值位 那么浮点数在内存中是怎么储存的呢&#xff1f;我们先来看一个例子&am…

深度学习技巧应用30-深度学习中的GPU的基本架构原理与应用技巧

大家好,我是微学AI,今天给大家介绍一下深度学习技巧应用30-深度学习中的GPU的基本架构原理与应用技巧,GPU是一种专门用于处理大量并行操作的硬件设备,它的架构设计主要是为了图形渲染。然而,由于其并行处理能力,现在广泛应用于深度学习、科学计算等领域。主要的GPU制造商…

C#,《小白学程序》第十九课:随机数(Random)第六,随机生成任意长度的大数(BigInteger)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// 除法运算为 Truffer…

【数据结构】什么是队列?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;队列的定义 &#x1f4cc;队列的抽象数据类型 &#x1f4cc;队列的顺序存储结构 &#x1f4cc;队列的链式存储结构 结语 人生,是一个又一个小小的队列…

KVM虚拟机的NAT网络模式原理及过程展示

NAT的方式及原理 NAT方式是KVM安装后的默认方式。 它支持主机与虚拟机的互访&#xff0c;同时也支持虚拟机访问互联网&#xff0c;但不支持外界访问虚拟机。 default是宿主机安装虚拟机支持模块的时候自动安装的。 其中 virbr0是由宿主机虚拟机支持模块安装时产生的虚拟网络接…