怎么设计手机网站,十堰网站制作公司,上海网络企业优化公司,联盟网目录
一、NPOI 核心原理#xff08;通俗版#xff09;
1. 什么是 NPOI#xff1f;
2. NPOI 核心对象模型#xff08;类比理解#xff09;
3. 核心逻辑#xff1a;流操作
二、环境准备#xff08;初学者第一步#xff09;
三、高频用法#xff08;带完整示例通俗版1. 什么是 NPOI2. NPOI 核心对象模型类比理解3. 核心逻辑流操作二、环境准备初学者第一步三、高频用法带完整示例极简版用法 1创建空白 Excel 并写入数据最基础用法 2读取已有 Excel 数据用法 3单元格类型处理初学者避坑重点用法 4设置列宽 / 行高优化显示用法 5批量写入数据实战常用四、初学者避坑指南高频错误五、完整工具类初学者可直接复用总结NPOI 是 .NET 平台下免费、开源的 Excel 操作库无需安装 Microsoft Office支持.xlsExcel 97-2003和.xlsxExcel 2007格式是 C# 处理 Excel 最常用的工具。本文从核心原理入手结合极简示例讲解高频用法适配初学者理解节奏。一、NPOI 核心原理通俗版1. 什么是 NPOINPOI 是 Apache POIJava 版 Excel 操作库的 C# 移植版本核心能力无需 Office 环境跨 Windows/Linux.NET Core/.NET Framework 均支持支持 Excel 读写、样式设置、公式计算基础区分两种格式HSSF对应.xlsXSSF对应.xlsx初学者重点记这两个类前缀。2. NPOI 核心对象模型类比理解Excel 文件的层级结构对应 NPOI 的核心对象初学者可类比 “书籍结构” 理解Excel 结构NPOI 核心对象类比书籍作用说明整个 Excel 文件IWorkbook接口整本书代表一个 Excel 文件是入口工作表SheetISheet书籍的章节一个 Workbook 可包含多个 Sheet行IRow章节里的行一个 Sheet 包含多行索引从 0 开始单元格ICell行里的文字格一个 Row 包含多个单元格索引从 0 开始3. 核心逻辑流操作NPOI 操作 Excel 本质是文件流FileStream处理读取 Excel从文件流加载到IWorkbook解析为 Sheet/Row/Cell写入 Excel将IWorkbook内容写入文件流生成物理文件。二、环境准备初学者第一步通过 NuGet 安装 NPOIVisual Studio 操作右键项目 → 管理 NuGet 程序包搜索NPOI安装最新稳定版建议 2.5核心命名空间必加// 基础核心所有操作都需要 using NPOI.SS.UserModel; // 处理 .xlsHSSF using NPOI.HSSF.UserModel; // 处理 .xlsxXSSF using NPOI.XSSF.UserModel; // 文件流处理 using System.IO;三、高频用法带完整示例极简版用法 1创建空白 Excel 并写入数据最基础需求创建一个测试.xlsx写入表头 1 行数据姓名、年龄、是否学生。// 步骤1创建 Workbook根据格式选 XSSF/HSSF IWorkbook workbook new XSSFWorkbook(); // .xlsx 用 XSSF.xls 用 HSSF // 步骤2创建 Sheet指定名称 ISheet sheet workbook.CreateSheet(学生信息); // 步骤3创建行表头行索引 0 IRow headerRow sheet.CreateRow(0); // 步骤4创建单元格并赋值表头 headerRow.CreateCell(0).SetCellValue(姓名); headerRow.CreateCell(1).SetCellValue(年龄); headerRow.CreateCell(2).SetCellValue(是否学生); // 步骤5创建数据行索引 1 IRow dataRow sheet.CreateRow(1); dataRow.CreateCell(0).SetCellValue(张三); dataRow.CreateCell(1).SetCellValue(20); // 数字类型 dataRow.CreateCell(2).SetCellValue(true); // 布尔类型 // 步骤6写入文件流核心using 自动释放流避免文件占用 string filePath 测试.xlsx; using (FileStream fs new FileStream(filePath, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); // 将 Workbook 写入流 } Console.WriteLine(Excel 创建成功);用法 2读取已有 Excel 数据需求读取上面创建的测试.xlsx输出所有单元格内容。string filePath 测试.xlsx; // 步骤1打开文件流读模式 using (FileStream fs new FileStream(filePath, FileMode.Open, FileAccess.Read)) { // 步骤2根据文件格式加载 Workbook初学者可简化判断后缀 IWorkbook workbook filePath.EndsWith(.xlsx) ? new XSSFWorkbook(fs) : new HSSFWorkbook(fs); // 步骤3获取第一个 Sheet索引 0 ISheet sheet workbook.GetSheetAt(0); // 步骤4遍历所有行从 0 到最后一行索引 for (int i 0; i sheet.LastRowNum; i) { IRow row sheet.GetRow(i); // 获取第 i 行 if (row null) continue; // 跳过空行初学者必加避免空引用 // 步骤5遍历当前行的所有单元格 for (int j 0; j row.LastCellNum; j) { ICell cell row.GetCell(j); // 获取第 j 列单元格 if (cell null) { Console.Write(空值\t); continue; } // 步骤6根据单元格类型读取值初学者核心避免类型转换错 string cellValue cell.CellType switch { CellType.String cell.StringCellValue, // 字符串 CellType.Numeric cell.NumericCellValue.ToString(), // 数字/日期 CellType.Boolean cell.BooleanCellValue.ToString(), // 布尔 _ 未知类型 // 其他类型公式、空等 }; Console.Write(cellValue \t); } Console.WriteLine(); // 换行 } } Console.WriteLine(Excel 读取完成);用法 3单元格类型处理初学者避坑重点Excel 单元格有多种类型字符串、数字、日期、布尔、公式直接强转容易报错推荐安全读取方法/// summary /// 安全读取单元格值适配所有类型返回字符串 /// /summary /// param namecell单元格/param /// param namedefaultValue默认值单元格为空/异常时返回/param private static string GetCellValue(ICell cell, string defaultValue ) { if (cell null) return defaultValue; return cell.CellType switch { CellType.String cell.StringCellValue.Trim(), // 字符串去空格 CellType.Numeric // 区分数字和日期NPOI 中日期也属于 Numeric 类型 DateUtil.IsCellDateFormatted(cell) ? cell.DateCellValue.ToString(yyyy-MM-dd) : cell.NumericCellValue.ToString(), CellType.Boolean cell.BooleanCellValue ? 是 : 否, // 转中文更友好 CellType.Formula // 公式类型读取计算结果 cell.CachedFormulaResultType CellType.Numeric ? cell.NumericCellValue.ToString() : cell.StringCellValue, _ defaultValue }; }使用示例// 读取年龄转int int age int.TryParse(GetCellValue(row.GetCell(1)), out int res) ? res : 0; // 读取是否学生转bool bool isStudent GetCellValue(row.GetCell(2)) 是;用法 4设置列宽 / 行高优化显示NPOI 列宽单位是「256 × 字符宽度」行高单位是「1/20 点」初学者直接传数字会显示异常ISheet sheet workbook.CreateSheet(学生信息); // 设置列宽第0列姓名宽度为 10 个字符 sheet.SetColumnWidth(0, 10 * 256); // 第1列年龄宽度为 8 个字符 sheet.SetColumnWidth(1, 8 * 256); // 设置行高表头行高 30px30×20 IRow headerRow sheet.CreateRow(0); headerRow.Height 30 * 20;用法 5批量写入数据实战常用需求将列表数据批量写入 Excel// 模拟数据 ListStudent studentList new ListStudent() { new Student { Name 张三, Age 20, IsStudent true }, new Student { Name 李四, Age 22, IsStudent false }, new Student { Name 王五, Age 19, IsStudent true } }; // 创建Workbook和Sheet IWorkbook workbook new XSSFWorkbook(); ISheet sheet workbook.CreateSheet(批量数据); // 写入表头 IRow headerRow sheet.CreateRow(0); headerRow.CreateCell(0).SetCellValue(姓名); headerRow.CreateCell(1).SetCellValue(年龄); headerRow.CreateCell(2).SetCellValue(是否学生); // 批量写入数据行 for (int i 0; i studentList.Count; i) { IRow row sheet.CreateRow(i 1); // 数据行从索引1开始 var student studentList[i]; row.CreateCell(0).SetCellValue(student.Name); row.CreateCell(1).SetCellValue(student.Age); row.CreateCell(2).SetCellValue(student.IsStudent ? 是 : 否); } // 保存文件 using (FileStream fs new FileStream(批量数据.xlsx, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } // 定义学生类 public class Student { public string Name { get; set; } public int Age { get; set; } public bool IsStudent { get; set; } }四、初学者避坑指南高频错误Sheet 索引越界GetSheetAt(0)报错 → 检查 Excel 是否有 Sheet或创建 Workbook 后是否手动创建了 Sheet空 Workbook 无默认 Sheet文件占用报错 “进程无法访问文件” → 确保所有FileStream用using包裹自动释放句柄或关闭 Excel 后再运行程序类型转换错读取数字时报 “无法将 double 转 int” → 用GetCellValue先转字符串再用int.TryParse空引用异常row.GetCell(j)报错 → 先判断row ! null和cell ! null格式不匹配用HSSFWorkbook处理.xlsx→ 严格区分.xls用HSSF.xlsx用XSSF。五、完整工具类初学者可直接复用封装极简版 Excel 读写工具类覆盖 80% 基础场景public static class SimpleExcelHelper { /// summary /// 写入数据到Excel /// /summary /// param namefilePath保存路径.xls/.xlsx/param /// param namesheetName工作表名称/param /// param nameheaders表头列表/param /// param namedataList数据列表每行是一个字符串数组/param public static void WriteExcel(string filePath, string sheetName, Liststring headers, Liststring[] dataList) { // 创建Workbook IWorkbook workbook filePath.EndsWith(.xlsx) ? new XSSFWorkbook() : new HSSFWorkbook(); ISheet sheet workbook.CreateSheet(sheetName); // 写入表头 IRow headerRow sheet.CreateRow(0); for (int i 0; i headers.Count; i) { headerRow.CreateCell(i).SetCellValue(headers[i]); sheet.SetColumnWidth(i, 12 * 256); // 统一列宽 } // 写入数据 for (int i 0; i dataList.Count; i) { IRow row sheet.CreateRow(i 1); string[] rowData dataList[i]; for (int j 0; j rowData.Length; j) { row.CreateCell(j).SetCellValue(rowData[j]); } } // 保存文件 using (FileStream fs new FileStream(filePath, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } } /// summary /// 读取Excel数据 /// /summary /// param namefilePath文件路径/param /// returns表头所有数据第一行是表头/returns public static Liststring[] ReadExcel(string filePath) { var result new Liststring[](); using (FileStream fs new FileStream(filePath, FileMode.Open, FileAccess.Read)) { IWorkbook workbook filePath.EndsWith(.xlsx) ? new XSSFWorkbook(fs) : new HSSFWorkbook(fs); ISheet sheet workbook.GetSheetAt(0); for (int i 0; i sheet.LastRowNum; i) { IRow row sheet.GetRow(i); if (row null) continue; string[] rowData new string[row.LastCellNum]; for (int j 0; j row.LastCellNum; j) { rowData[j] GetCellValue(row.GetCell(j)); } result.Add(rowData); } } return result; } /// summary /// 安全读取单元格值 /// /summary private static string GetCellValue(ICell cell) { if (cell null) return ; return cell.CellType switch { CellType.String cell.StringCellValue.Trim(), CellType.Numeric DateUtil.IsCellDateFormatted(cell) ? cell.DateCellValue.ToString(yyyy-MM-dd) : cell.NumericCellValue.ToString(), CellType.Boolean cell.BooleanCellValue ? 是 : 否, _ }; } }使用示例// 写入示例 var headers new Liststring { 姓名, 年龄, 城市 }; var data new Liststring[]() { new[] { 张三, 20, 北京 }, new[] { 李四, 22, 上海 } }; SimpleExcelHelper.WriteExcel(工具类测试.xlsx, 测试数据, headers, data); // 读取示例 var readData SimpleExcelHelper.ReadExcel(工具类测试.xlsx); foreach (var row in readData) { Console.WriteLine(string.Join(\t, row)); }总结初学者掌握 NPOI 核心记住 Workbook→Sheet→Row→Cell 的层级用 using 管理文件流按单元格类型读取值就能覆盖绝大多数基础场景。先从 “创建 / 读取空白 Excel” 入手再逐步扩展样式、批量数据等进阶用法避免一开始陷入复杂逻辑。