C#通过NPOI 读、写Excel数据;合并单元格、简单样式修改;通过读取已有的Excel模板另存为文件

文章目录

  • 1 需要引用的DLL
  • 2 调用示例
  • 3 工具类

1 需要引用的DLL

在这里插入图片描述

2 调用示例

public static void WriteExcel()
{string templateFile = @"F:\12312\excel.xlsx"; // 文件必须存在string outFile = @"F:\12312\" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".xlsx";string picPath = @"F:\12312\test.jpg";IWorkbook workbook = ExcelHelper.GetReadWorkbook(templateFile);ISheet sheet = workbook.GetSheetAt(0);try{ExcelHelper.SetCellValue(sheet, 20, 0, "这里是第1行第1列内容");ExcelHelper.SetCellValue(sheet, 0, 1, "这里是第1行第2列内容");ExcelHelper.SetCellValue(sheet, 1, 0, "这里是第2行第1列内容");ExcelHelper.SetCellValue(sheet, 1, 1, "这里是第2行第2列内容");// Height:单位是1/20个点,所以要想得到一个点的话,需要乘以20。sheet.GetRow(1).Height = 44 * 20; // 给第2行设置行高// Width: 单位是1/256个字符宽度,所以要乘以256才是一整个字符宽度sheet.SetColumnWidth(1, 50 * 256); // 给第1列设置宽度ExcelHelper.SetCellValue(sheet, 2, 0, "这里是第3行第1列内容,需要设置字体样式");// 从第3行到第6行,第1列到第4列合并单元格ExcelHelper.SetCellRangeAddress(sheet, 2, 5, 0, 3);// 给合并之后的单元格加边框,并设置字体大小、居中、字体颜色、背景色ExcelHelper.AddRengionBorder(workbook, sheet, 2, 5, 0, 3);// 插入图片var bitmap = (Bitmap)Image.FromFile("1.bmp");ExcelHelper.InsertImage(workbook, sheet, 7, 16, 0, 2, bitmap);ExcelHelper.Save(workbook, outFile);Process.Start(outFile);}catch (Exception ex){throw ex;}
}

3 工具类

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;namespace Demo_Excel
{/// <summary>/// Excel导入导出帮助类--通过插件NPOI来实现导入导出操作/// 常见异常:/// 1.未添加ICSharpCode.SharpZipLib.dll/// </summary>public class ExcelHelper{/// <summary>/// 获取读取文件的IWorkbook对象/// </summary>/// <param name="filename">文件路径</param>/// <returns></returns>public static IWorkbook GetReadWorkbook(string filename){FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);IWorkbook workbook;string fileExt = Path.GetExtension(filename).ToLower();switch (fileExt){case ".xlsx":workbook = new XSSFWorkbook(fs);break;case ".xls":workbook = new HSSFWorkbook(fs);break;default:throw new Exception("不支持的文件类型");}fs.Close();return workbook;}/// <summary>/// 获取读取文件的IWorkbook对象/// </summary>/// <param name="filename">文件路径</param>/// <returns></returns>public static IWorkbook GetWriteWorkbook(string filename){if (string.IsNullOrWhiteSpace(filename))throw new Exception("不支持的文件类型");string fileExt = Path.GetExtension(filename).ToLower();switch (fileExt){case ".xlsx": return new XSSFWorkbook();case ".xls": return new HSSFWorkbook();default: throw new Exception("不支持的文件类型");}}public static void Save(IWorkbook workbook, string filename){MemoryStream stream = new MemoryStream();workbook.Write(stream);var buf = stream.ToArray();//保存文件  using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write)){fs.Write(buf, 0, buf.Length);fs.Flush();fs.Close();}}/// <summary>/// 根据Excel模板更新Excel数据/// </summary>/// <param name="sourcefile">模板文件的路径</param>/// <param name="outfile">输出文件的内容</param>/// <param name="sheetIndex">模板文件在sheet中的编号</param>/// <param name="dictionary">用于更新数据的键值对,key:模板中需要录入信息的标识;Value:录入信息的内容</param>/// <returns></returns>public static int UpdataExcel(string sourcefile, string outfile, int sheetIndex, Dictionary<string, string> dictionary){var allKeys = dictionary.Keys.ToArray();IWorkbook workbook = GetReadWorkbook(sourcefile);ISheet sheet = workbook.GetSheetAt(sheetIndex);int endRow = sheet.LastRowNum;for (int i = 0; i < endRow; i++){var row = sheet.GetRow(i);for (int j = 0; j < row.LastCellNum; j++){var data = GetCellString(row.GetCell(j));if (allKeys.Contains(data)){row.Cells[j].SetCellValue(dictionary[data]);}}}Save(workbook, outfile);return 0;}/// <summary>/// 根据Excel模板更新Excel数据/// </summary>/// <param name="sourcefile">模板文件的路径</param>/// <param name="outfile">输出文件的内容</param>/// <param name="sheetIndex">模板文件在sheet中的编号</param>/// <param name="dictionary">用于更新数据的键值对,key:模板中需要录入信息的单元格的位置,X:行,Y:列;Value:录入信息的内容</param>/// <returns></returns>public static int UpdataExcel(string sourcefile, string outfile, int sheetIndex, Dictionary<Point, string> dictionary){IWorkbook workbook = GetReadWorkbook(sourcefile);ISheet sheet = workbook.GetSheetAt(sheetIndex);foreach (var key in dictionary.Keys){SetCellValue(sheet, key.X, key.Y, dictionary[key]);}Save(workbook, outfile);return 0;}/// <summary>/// 将DataTable数据导入到excel中/// </summary>/// <param name="fileName">文件路径</param>/// <param name="data">要导入的数据</param>/// <param name="sheetName">要导入的excel的sheet的名称</param>/// <param name="isColumnWritten">DataTable的列名是否要导入</param>/// <returns>导入数据行数(包含列名那一行)</returns>public static int Write(string fileName, DataTable data, string sheetName, bool isColumnWritten){try{IWorkbook workbook = GetWriteWorkbook(fileName);ISheet sheet = workbook.CreateSheet(sheetName);int count = 0;//写入数据行if (isColumnWritten){//读取标题  IRow rowHeader = sheet.CreateRow(count++);for (int i = 0; i < data.Columns.Count; i++){ICell cell = rowHeader.CreateCell(i);cell.SetCellValue(data.Columns[i].ColumnName);}}//读取数据  for (int i = 0; i < data.Rows.Count; i++){IRow rowData = sheet.CreateRow(count++);for (int j = 0; j < data.Columns.Count; j++){ICell cell = rowData.CreateCell(j);cell.SetCellValue(data.Rows[i][j].ToString());}}Save(workbook, fileName);return count;}catch (Exception ex){return -1;}}/// <summary>/// 将DataTable数据导入到excel中/// </summary>/// <param name="fileName">文件路径</param>/// <param name="data">要导入的数据</param>/// <param name="isColumnWritten">DataTable的列名是否要导入</param>/// <returns>导入数据行数(包含列名那一行)</returns>public static int Write(string fileName, DataTable data, bool isColumnWritten){int ret = Write(fileName, data, "Sheet1", isColumnWritten);return ret;}/// <summary>/// 将DataTable数据导入到excel中(包含列名,工作簿名称为:Sheet1)/// </summary>/// <param name="fileName">文件路径</param>/// <param name="data">要导入的数据</param>/// <returns>导入数据行数(包含列名那一行)</returns>public static int Write(string fileName, DataTable data){int ret = Write(fileName, data, true);return ret;}/// <summary>/// 读取Excel数据到DataTable/// </summary>/// <param name="fileName">文件名称</param>/// <param name="sheetIndex">sheet索引</param>/// <param name="isFirstRowCellName">第一行数据是否为列名</param>/// <param name="data">存储读取的数据</param>/// <returns></returns>public static int Read(string fileName, int sheetIndex, bool isFirstRowCellName, out DataTable data){data = new DataTable();try{IWorkbook workbook = GetReadWorkbook(fileName);ISheet sheet = workbook.GetSheetAt(sheetIndex);if (isFirstRowCellName){IRow firstRow = sheet.GetRow(0);var list = ReadDataRow(firstRow);data.Columns.AddRange(list.Select(t => new DataColumn(t)).ToArray());}else{int nMaxCol = 0;for (int i = 0; i < sheet.LastRowNum; i++){nMaxCol = Math.Max(nMaxCol, sheet.GetRow(i).LastCellNum);}for (int i = 0; i < nMaxCol; i++){data.Columns.Add($"列{i + 1}");}}int startRow = !isFirstRowCellName ? 0 : 1;int endRow = sheet.LastRowNum;var ret2 = Read(sheet, startRow, endRow, ref data);if (ret2 < 0) return -1;return data.Rows.Count;}catch (Exception ex){throw ex;}}/// <summary>/// 读取Excel数据到DataTable/// </summary>/// <param name="fileName">文件名称</param>/// <param name="sheetName">sheet名称</param>/// <param name="isFirstRowCellName">第一行数据是否为列名</param>/// <param name="data">存储读取的数据</param>/// <returns></returns>public static int Read(string fileName, string sheetName, bool isFirstRowCellName, out DataTable data){data = new DataTable();try{IWorkbook workbook = GetReadWorkbook(fileName);ISheet sheet = workbook.GetSheet(sheetName);Console.WriteLine(sheet.SheetName);if (isFirstRowCellName){IRow firstRow = sheet.GetRow(0);var list = ReadDataRow(firstRow);data.Columns.AddRange(list.Select(t => new DataColumn(t)).ToArray());}else{int nMaxCol = 0;for (int i = 0; i < sheet.LastRowNum; i++){nMaxCol = Math.Max(nMaxCol, sheet.GetRow(i).LastCellNum);}for (int i = 0; i < nMaxCol; i++){data.Columns.Add($"列{i + 1}");}}int startRow = !isFirstRowCellName ? 0 : 1;int endRow = !isFirstRowCellName ? 0 : 1;var ret = Read(sheet, startRow, endRow, ref data);if (ret < 0)return -1;return data.Rows.Count;}catch (Exception ex){return -1;}}/// <summary>/// 读取Excel数据到DataTable/// </summary>/// <param name="fileName">文件名称</param>/// <param name="isFirstRowCellName">第一行数据是否为列名</param>/// <param name="data">存储读取的数据</param>/// <returns></returns>public static int Read(string fileName, bool isFirstRowCellName, out DataTable data){int ret = Read(fileName, "sheet1", isFirstRowCellName, out data);return ret;}/// <summary>/// 读取Excel数据到DataTable/// </summary>/// <param name="fileName">文件名称</param>/// <param name="data">存储读取的数据</param>/// <returns></returns>public static int Read(string fileName, out DataTable data){int ret = Read(fileName, "sheet1", false, out data);return ret;}/// <summary>/// 从指定行开始读取所有sheet的数据到DataTable(DataTable列名已创建)/// </summary>/// <param name="sheet">工作簿</param>/// <param name="startRow">指定读取起始行</param>/// <param name="endRow">指定读取结束行</param>/// <param name="data">存储读取的数据</param>/// <returns></returns>public static int Read(ISheet sheet, int startRow, int endRow, ref DataTable data){endRow += 1;for (int i = startRow; i < endRow; i++){var sheetRow = sheet.GetRow(i);if (sheetRow == null){data.Rows.Add();}else{var list = ReadDataRow(sheetRow);var row = data.NewRow();int count = Math.Min(list.Count, data.Columns.Count);for (int j = 0; j < count; j++){row[j] = list[j];}data.Rows.Add(row);}}return data.Rows.Count;}/// <summary>/// 读取数据行/// </summary>/// <param name="sheet"></param>/// <param name="index"></param>/// <returns></returns>public static List<string> ReadDataRow(ISheet sheet, int index) => ReadDataRow(sheet.GetRow(index));/// <summary>/// 读取数据行/// </summary>/// <param name="row"></param>/// <returns></returns>public static List<string> ReadDataRow(IRow row){List<string> result = null;if (row != null){result = new List<string>();int startColumn = 0;int endColumn = row.LastCellNum;for (int i = startColumn; i < endColumn; i++){result.Add(GetCellString(row.GetCell(i)));}}return result;}/// <summary>/// 往EXCEL指定单元格插入图片/// </summary>/// <param name="workbook"></param>/// <param name="sheet"></param>/// <param name="firstRow"> 起始单元格行序号,从0开始计算</param>/// <param name="lastRow">  终止单元格行序号,从0开始计算</param>/// <param name="firstCell"> 起始单元格列序号,从0开始计算</param>/// <param name="lastCell">  终止单元格列序号,从0开始计算</param>/// <param name="bitmap">插入的图片</param> public static void InsertImage(IWorkbook workbook, ISheet sheet, int firstRow, int lastRow, int firstCell, int lastCell, Bitmap bitmap){// 将图片转换为字节数组byte[] imgBytes = BitmapToBytes(bitmap);int pictureIdx = workbook.AddPicture(imgBytes, PictureType.PNG);if (workbook is XSSFWorkbook){XSSFDrawing patriarch = (XSSFDrawing)sheet.CreateDrawingPatriarch();// dx1:起始单元格的x偏移量,如例子中的255表示直线起始位置距A1单元格左侧的距离;// dy1:起始单元格的y偏移量,如例子中的125表示直线起始位置距A1单元格上侧的距离;// dx2:终止单元格的x偏移量,如例子中的1023表示直线起始位置距C3单元格左侧的距离;// dy2:终止单元格的y偏移量,如例子中的150表示直线起始位置距C3单元格上侧的距离;// col1:起始单元格列序号,从0开始计算;// row1:起始单元格行序号,从0开始计算,如例子中col1 = 0,row1 = 0就表示起始单元格为A1;// col2:终止单元格列序号,从0开始计算;// row2:终止单元格行序号,从0开始计算,如例子中col2 = 2,row2 = 2就表示起始单元格为C3;XSSFClientAnchor anchor = new XSSFClientAnchor(10, 10, 0, 0, firstCell, firstRow, lastCell, lastRow);//把图片插到相应的位置XSSFPicture pict = (XSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);}else{HSSFPatriarch patriarch = (HSSFPatriarch)sheet.CreateDrawingPatriarch();HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 0, 0, firstCell, firstRow, lastCell, lastRow);//把图片插到相应的位置HSSFPicture pict = (HSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);}}/// <summary>/// 单元格设置内容/// </summary>/// <param name="sheet"></param>/// <param name="rowIndex">第几行,从0开始</param>/// <param name="cellIndex">第几列,从0开始</param>/// <param name="value">内容(字符串)</param>public static void SetCellValue(ISheet sheet, int rowIndex, int cellIndex, string value){if (sheet.GetRow(rowIndex) == null){sheet.CreateRow(rowIndex);}if (sheet.GetRow(rowIndex).GetCell(cellIndex) == null){sheet.GetRow(rowIndex).CreateCell(cellIndex);}sheet.GetRow(rowIndex).GetCell(cellIndex).SetCellValue(value);}/// <summary>/// 合并单元格/// </summary>/// <param name="sheet">要合并单元格所在的sheet</param>/// <param name="rowstart">开始行的索引</param>/// <param name="rowend">结束行的索引</param>/// <param name="colstart">开始列的索引</param>/// <param name="colend">结束列的索引</param>public static void SetCellRangeAddress(ISheet sheet, int rowstart, int rowend, int colstart, int colend){for (int r = rowstart; r <= rowend; r++){for (int c = colstart; c <= colend; c++){if (sheet.GetRow(r) == null){sheet.CreateRow(r); // 如果行不存在,则创建行}if (sheet.GetRow(r).GetCell(c) == null){sheet.GetRow(r).CreateCell(c); // 如果列不存在,则创建列}}}CellRangeAddress cellRangeAddress = new CellRangeAddress(rowstart, rowend, colstart, colend);sheet.AddMergedRegion(cellRangeAddress);}/// <summary>/// 加范围边框和设置字体大小、颜色、背景色、居中/// </summary>/// <param name="firstRow">起始行</param>/// <param name="lastRow">结束行</param>/// <param name="firstCell">起始列</param>/// <param name="lastCell">结束列</param>/// <returns></returns>public static void AddRengionBorder(IWorkbook workbook, ISheet sheet, int firstRow, int lastRow, int firstCell, int lastCell){for (int i = firstRow; i < lastRow; i++){for (int n = firstCell; n < lastCell; n++){ICell cell;cell = sheet.GetRow(i).GetCell(n);if (cell == null){cell = sheet.GetRow(i).CreateCell(n);}ICellStyle style = sheet.Workbook.CreateCellStyle();style.BorderTop = BorderStyle.Thin;style.BorderBottom = BorderStyle.Thin;style.BorderLeft = BorderStyle.Thin;style.BorderRight = BorderStyle.Thin;style.Alignment = HorizontalAlignment.Center;   //水平对齐 :居中style.VerticalAlignment = VerticalAlignment.Center; //垂直对齐  :居中if (i == firstRow) //第一行{style.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Black.Index; // 背景色:黑色style.FillPattern = FillPattern.SolidForeground;IFont font = workbook.CreateFont(); //创建一个字体颜色font.Color = NPOI.HSSF.Util.HSSFColor.White.Index;  //字体颜色:白色      font.FontHeightInPoints = 18;//字体大小       style.SetFont(font); //给样式设置字体}cell.CellStyle = style;}}}/// <summary>/// Bitmap转换为字节数组/// </summary>/// <param name="bitmap"></param>/// <returns></returns>private static byte[] BitmapToBytes(Bitmap bitmap){// 1.先将BitMap转成内存流MemoryStream ms = new MemoryStream();bitmap.Save(ms, ImageFormat.Bmp);ms.Seek(0, SeekOrigin.Begin);// 2.再将内存流转成byte[]并返回byte[] bytes = new byte[ms.Length];ms.Read(bytes, 0, bytes.Length);ms.Dispose();return bytes;}/// <summary>/// 获取单元格数据/// </summary>/// <param name="cell"></param>/// <returns></returns>private static string GetCellString(ICell cell){if (cell != null){switch (cell.CellType){case CellType.Unknown:return "";case CellType.Numeric:return cell.NumericCellValue.ToString();case CellType.String:return cell.StringCellValue;case CellType.Formula:return cell.CellFormula;case CellType.Blank:return "";case CellType.Boolean:return cell.BooleanCellValue.ToString();case CellType.Error:return "";default:return "";}}else{return "";}}}}

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

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

相关文章

快速了解Spring AOP的概念及使用

文章目录 1. AOP概念1.1 什么是AOP&#xff1f;1.2 什么是Spring AOP&#xff1f; 2. Spring AOP的使用2.1 引入Spring AOP依赖2.2 编写AOP程序 3. Spring AOP详解3.1 Spring AOP核心概念1. 切点&#xff08;Pointcut&#xff09;2. 连接点&#xff08;Join Point&#xff09;3…

【软件测试】银行测试项目VS常规项目有什么区别?怎么做?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 银行测试项目跟常…

20世纪30年代的大危机

背景 1929年9月&#xff0c;美国财政部部长安德鲁梅隆向公众保证“现在没有担心的理由&#xff0c;这一繁荣的高潮将会继续下去”。 当时流行的一首儿歌&#xff1a;“梅隆拉响汽笛&#xff0c;胡佛敲起钟&#xff0c;华尔街发出信号&#xff0c;美国往地狱里冲&#xff01;”…

水文监测遥测终端机RTU

水文监测是指通过测量和监测水体的物理、化学和生物性质&#xff0c;以获得关于水资源质量和水体环境状态的信息的过程。包括地下水位、地表水位、河流水位等&#xff0c;从而能够及时采取措施应对水资源过度开采、污染等问题&#xff0c;保障水资源的可持续利用。其次&#xf…

Kubernetes入门篇

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容Kubernetes是什么&#xff1f;为什么需要 Kubernetes&#xff0c;它能做什么&#xff1f;Kubernetes 版本进化Kubernetes 概念Kubernetes 中 3 个重要概念 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介…

JAVA文件IO, File类, 字符流,字节流

文章目录 文件IO1. File2. IO流2.1 字符流2.1.1 Reader2.1.2 Writer 2.2 字节流2.2.1 InputStream2.2.2 FileInputStream2.2.3 利用Scanner进行字符读取2.2.4 OutputStream 文件IO I: Input, 从硬盘往内存读数据 O: Output, 从内存往硬盘输出数据 1. File Java 中通过 java…

SAP_ABAP_编程基础_二进制文件_SMW0中上传与下载

SAP ABAP 顾问&#xff08;开发工程师&#xff09;能力模型_Terry谈企业数字化的博客-CSDN博客文章浏览阅读448次。目标&#xff1a;基于对SAP abap 顾问能力模型的梳理&#xff0c;给一年左右经验的abaper 快速成长为三年经验提供超级燃料&#xff01;https://blog.csdn.net/j…

VT-VSPA1-1X比例压力阀控制板

替代力士乐同型号,可以完全互换使用&#xff1b;适用于力士乐系列所有无电位置反馈的直动式和先导式比例压力阀的控制&#xff1b;外置欧板式连接&#xff0c;VT-VSPA1-1X型放大器配套支架型号&#xff1a;VT-3002-1X/32D或VT-3002-2X/32D&#xff1b; VT-VSPA2-1-1X/T1、VT-V…

Joint Bilateral Upsampling

Abstract 图像分析和增强任务&#xff08;例如色调映射、着色、立体深度和蒙太奇&#xff09;通常需要在像素网格上计算解决方案&#xff08;例如&#xff0c;曝光、色度、视差、标签&#xff09;。计算和内存成本通常要求在下采样图像上运行较小的解决方案。尽管通用上采样方…

物理层之三种数据交换方式(电路交换、报文交换、分组交换(数据报方式、虚电路方式))

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

Oracle(2-7)Instance and Media Recovery Structures

文章目录 一、基础知识1、体系结构详解2、Database Files 数据库文件3、Database Other Files 其他数据文件4、Dynamic Views 动态视图5、Large Pool6、DB Buffer Cache,DBWn7、Configuring Tablespaces 配置表空间8、Redo Log Buffer, LGWR 二、基础操作1、查看数据库动态视图…

elk:filebeat也是一个日志收集工具

filebeat是一个轻量级的日志收集工具&#xff0c;所使用的系统资源比logstash部署和启动使用的资源要小的多 filebeat可以允许在非java环境&#xff0c;他可以代替logstash在非java环境上收集日志 filebeat无法实现数据的过滤&#xff0c;一般是结合logstash的数据过滤功能一…