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

本文主要是介绍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 "";}}}}

这篇关于C#通过NPOI 读、写Excel数据;合并单元格、简单样式修改;通过读取已有的Excel模板另存为文件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/431100

相关文章

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

C++中使用vector存储并遍历数据的基本步骤

《C++中使用vector存储并遍历数据的基本步骤》C++标准模板库(STL)提供了多种容器类型,包括顺序容器、关联容器、无序关联容器和容器适配器,每种容器都有其特定的用途和特性,:本文主要介绍C... 目录(1)容器及简要描述‌php顺序容器‌‌关联容器‌‌无序关联容器‌(基于哈希表):‌容器适配器‌:(

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

一文详解Python中数据清洗与处理的常用方法

《一文详解Python中数据清洗与处理的常用方法》在数据处理与分析过程中,缺失值、重复值、异常值等问题是常见的挑战,本文总结了多种数据清洗与处理方法,文中的示例代码简洁易懂,有需要的小伙伴可以参考下... 目录缺失值处理重复值处理异常值处理数据类型转换文本清洗数据分组统计数据分箱数据标准化在数据处理与分析过

C#实现添加/替换/提取或删除Excel中的图片

《C#实现添加/替换/提取或删除Excel中的图片》在Excel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更加美观,下面我们来看看如何在C#中实现添加/替换/提取或删除E... 在Excandroidel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

详解Vue如何使用xlsx库导出Excel文件

《详解Vue如何使用xlsx库导出Excel文件》第三方库xlsx提供了强大的功能来处理Excel文件,它可以简化导出Excel文件这个过程,本文将为大家详细介绍一下它的具体使用,需要的小伙伴可以了解... 目录1. 安装依赖2. 创建vue组件3. 解释代码在Vue.js项目中导出Excel文件,使用第三