.NET 6.0 + 在Linux的Docker容器中 不安装任何依赖生成图形验证码教程
推荐使用SkiaSharp首先，安装SkiaSharp编写好图形生成代码。在windows 上简易代码using SkiaSharp; using System.Drawing; using System.Drawing.Text; namespace VertifyCode { public class VerifyCodeHelper { private static readonly char[] Chars = { '0','1','2','3','4','5','6','8','9', 'A','B','C','D','E','F','G','H','I','J','K', 'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' }; //private static readonly int Width = 90; //private static readonly int Height = 35; private static string GenCode(int num) { var code = string.Empty; var r = new Random(); for (int i = 0; i < num; i++) { code += Chars[r.Next(Chars.Length)].ToString(); } return code; } /// /// 获取图像数字验证码 /// /// <returns></returns> public static (string code, byte[] bytes) GetVerifyCode() { var code = GenCode(4); int width = 128; int height = 45; Random random = new(); //创建bitmap位图 using SKBitmap image = new(width, height, SKColorType.Bgra8888, SKAlphaType.Premul); //创建画笔 using SKCanvas canvas = new(image); //填充背景颜色为白色 canvas.DrawColor(SKColors.White); //画图片的背景噪音线 for (int i = 0; i < (width * height * 0.015); i++) { using SKPaint drawStyle = new(); drawStyle.Color = new(Convert.ToUInt32(random.Next(Int32.MaxValue))); canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width), random.Next(0, height), drawStyle); }//将文字写到画布上 using (SKPaint drawStyle = new()) { drawStyle.Color = SKColors.Red; drawStyle.TextSize = height; drawStyle.StrokeWidth = 1; float emHeight = height - (float)height * (float)0.14; float emWidth = ((float)width / code.Length) - ((float)width * (float)0.13); canvas.DrawText(code, emWidth, emHeight, drawStyle); } //画图片的前景噪音点 for (int i = 0; i < (width * height * 0.15); i++) { image.SetPixel(random.Next(0, width), random.Next(0, height), new SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue)))); } using var img = SKImage.FromBitmap(image); using SKData p = img.Encode(SKEncodedImageFormat.Png, 100); return (code, p.ToArray()); } } }以上代码docker 不可用，如果需要在linux 上课用，还需要下载SkiaSharp.linux,【SkiaSharp.NativeAssets.Linux.NoDependencies】本篇着重讲在docker 环境下的使用，兼容非docker 容器在docker 下使用的话需要使用外部字体[HttpGet] public FileContentResult Get() { string code; var img = Create(out code); // Console.WriteLine(code); HttpContext.Session.SetString("code", code); //GC.Collect(); return File(img.ToArray(), "image/png"); } private static string RndNum(int VcodeNum) { //验证码可以显示的字符集合 string Vchar = "1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,m,n,p" + ",q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q" + ",R,S,T,U,V,W,X,Y,Z"; string[] VcArray = Vchar.Split(new Char[] { ',' });//拆分成数组 string code = "";//产生的随机数 int temp = -1;//记录上次随机数值，尽量避避免生产几个一样的随机数 Random rand = new Random(); //采用一个简单的算法以保证生成随机数的不同 for (int i = 1; i < VcodeNum + 1; i++) { if (temp != -1) { rand = new Random(i * temp * unchecked((int)DateTime.Now.Ticks));//初始化随机类 } int t = rand.Next(58);//获取随机数 if (temp != -1 && temp == t) { return RndNum(VcodeNum);//如果获取的随机数重复，则递归调用 } temp = t;//把本次产生的随机数记录起来 code += VcArray[t];//随机数的位数加一 } return code; } public static MemoryStream Create(out string code, int numbers = 4) { code = RndNum(numbers); MemoryStream ms = new MemoryStream(); Random random = new Random(); int width = 72; int height = 32; var bitmap = new SKBitmap(width, height); using (var canvas = new SKCanvas(bitmap)) { canvas.Clear(SKColors.White); using (var paint = new SKPaint()) { // 绘制干扰线 paint.Color = SKColors.LightGray; paint.StrokeWidth = 2; for (int i = 0; i < 5; i++) { int x1 = random.Next(width); int y1 = random.Next(height); int x2 = random.Next(width); int y2 = random.Next(height); canvas.DrawLine(x1, y1, x2, y2, paint); } // 在随机位置画背景点 for (int i = 0; i < 100; i++) { int x = random.Next(width); int y = random.Next(height); canvas.DrawCircle(x, y, 1, paint); } SKFont sKFont = new SKFont(); // 绘制文字 sKFont.Size = 21; paint.IsAntialias = true; //sKFont.Typeface = SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright); sKFont.Typeface = SKTypeface.FromFile("msyh.ttc"); float textWidth = sKFont.MeasureText(code,paint); SKColor[] fcolor = { SKColors.Black, SKColors.Red, SKColors.DarkBlue, SKColors.Green, SKColors.Orange, SKColors.Brown, SKColors.DarkCyan, SKColors.Purple,SKColors.DeepPink }; for (int i = 0; i < code.Length; i++) { int top = random.Next(5, 15); int cindex = random.Next(7); paint.Color = fcolor[cindex]; canvas.DrawText(code.Substring(i, 1), 5 + (i * 16), height / 2 + top, sKFont, paint); } } } using var image = SKImage.FromBitmap(bitmap); using var data = image.Encode(SKEncodedImageFormat.Png, 100); //using var stream = new MemoryStream(); data.SaveTo(ms); //bitmap.Save(ms,SerializerCompression.GZip); return ms; }需要先把字体放在资源目录，记得字体文件要改为始终复制，本篇用到的是微软雅黑然后打包到linux 放进docker即可成功显示
{mtitle title="引用"/}阿里云服务器上不可用，需使用SSL，此代码不适用163邮箱using System.Net; using System.Net.Mail;方法如下/// /// 发送邮件方法 /// /// 接收人邮件 /// 发送邮件标题 /// 发送邮件内容 /// <returns></returns> public static bool SendEmail(string mailTo, string mailTitle, string mailContent) { //设置发送方邮件信息，例如：163邮箱（163已测试，其他邮箱未测试请根据实际自行测试） string stmpServer = @"smtp.163.com";//smtp服务器地址 string mailAccount = @"123456789@163.com";//邮箱账号 string pwd = @"12345678";//邮箱密码（qq邮箱请在此处使用授权码，其他邮箱见邮箱规定使用的是邮箱密码还是授权码） //邮件服务设置 SmtpClient smtpClient = new SmtpClient(); smtpClient.Port=25; smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;//指定电子邮件发送方式 smtpClient.Host = stmpServer;//指定发送方SMTP服务器 smtpClient.EnableSsl = true;//使用安全加密连接 smtpClient.UseDefaultCredentials = true;//不和请求一起发送 smtpClient.Credentials = new NetworkCredential(mailAccount, pwd);//设置发送账号密码 MailMessage mailMessage = new MailMessage(mailAccount, mailTo);//实例化邮件信息实体并设置发送方和接收方 mailMessage.Subject = mailTitle;//设置发送邮件得标题 mailMessage.Body = mailContent;//设置发送邮件内容 mailMessage.BodyEncoding = Encoding.UTF8;//设置发送邮件得编码 mailMessage.IsBodyHtml = false;//设置内容是否为HTML格式（true可以添加html标签） mailMessage.Priority = MailPriority.Normal;//设置邮件发送优先级 try { smtpClient.Send(mailMessage);//发送邮件 return true; } catch (SmtpException ex) { console.WriteLine(ex.message); throw ex; } }
C# 使用原生 System.IO.Compression 实现 zip 的压缩与解压
using System.IO.Compression;/// /// 将指定目录压缩为Zip文件 /// /// 文件夹地址 D:/download/ /// zip地址 D:/download/test.zip public static void CompressDirectoryZip(string folderPath, string zipPath) { DirectoryInfo directoryInfo = new(zipPath); if (directoryInfo.Parent != null) { directoryInfo = directoryInfo.Parent; } if (!directoryInfo.Exists) { directoryInfo.Create(); } ZipFile.CreateFromDirectory(folderPath, zipPath, CompressionLevel.Optimal, false); }其中 CompressionLevel 是个枚举，支持下面四种类型枚举值表意Optimal0压缩操作应以最佳方式平衡压缩速度和输出大小。Fastest1即使结果文件未可选择性地压缩，压缩操作也应尽快完成。NoCompression2该文件不应执行压缩。SmallestSize3压缩操作应尽可能小地创建输出，即使该操作需要更长的时间才能完成。这里直接固定了采用 CompressionLevel.Optimal/// /// 将指定文件压缩为Zip文件 /// /// 文件地址 D:/test.txt /// zip地址 D:/test.zip public static void CompressFileZip(string filePath, string zipPath) { //如果是多个文件请考虑一下整个文件夹迁移还是分文件迁移到临时目录 FileInfo fileInfo = new FileInfo(filePath); string dirPath = fileInfo.DirectoryName?.Replace("\\", "/") + "/"; string tempPath = dirPath + Guid.NewGuid() + "_temp/"; if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); } fileInfo.CopyTo(tempPath + fileInfo.Name); CompressDirectoryZip(tempPath, zipPath); DirectoryInfo directory = new(tempPath); if (directory.Exists) { //将文件夹属性设置为普通,如：只读文件夹设置为普通 directory.Attributes = FileAttributes.Normal; directory.Delete(true); } }这里压缩文件的逻辑其实就是先将我们要压缩的文件复制到一个临时目录，然后对临时目录执行了压缩动作，压缩完成之后又删除了临时目录以下是解压文件/// /// 解压Zip文件到指定目录 /// /// zip地址 D:/download/test.zip /// 文件夹地址 D:/test/ public static void DecompressZip(string zipPath, string folderPath) { DirectoryInfo directoryInfo = new(folderPath); ///这里注意，如果压缩文件已存在会报错，请自行判断处理 ///我的做法是先删除，请根据自己也无需要合理处理 if (!directoryInfo.Exists) { directoryInfo.Create(); } ZipFile.ExtractToDirectory(zipPath, folderPath); }至此 C# 使用原生 System.IO.Compression 实现 zip 的压缩与解压 就讲解完了
MysqlHelper.csusing System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using MySql.Data.MySqlClient; public class MySQLHelper { private string connectionString; public MySQLHelper(string connectionString) { this.connectionString = connectionString; } // /// /// 执行不返回结果集的SQL语句,影响的行数 /// /// /// /// <returns></returns> public int ExecuteNonQuery(string sql, params MySqlParameter[] parameters) { using (MySqlConnection connection = new MySqlConnection(connectionString)) { using (MySqlCommand command = new MySqlCommand(sql, connection)) { // 添加参数 command.Parameters.AddRange(parameters); // 打开连接 connection.Open(); // 执行SQL语句并返回影响行数 return command.ExecuteNonQuery(); } } } // /// /// 执行一个查询，并返回结果集中第一行的第一列 /// /// /// /// <returns></returns> public object ExecuteScalar(string sql, params MySqlParameter[] parameters) { using (MySqlConnection connection = new MySqlConnection(connectionString)) { using (MySqlCommand command = new MySqlCommand(sql, connection)) { // 添加参数 command.Parameters.AddRange(parameters); // 打开连接 connection.Open(); // 执行SQL查询并返回第一行第一列的值 return command.ExecuteScalar(); } } } // 执行一个查询，并返回结果集 public DataTable ExecuteQuery(string sql, params MySqlParameter[] parameters) { using (MySqlConnection connection = new MySqlConnection(connectionString)) { using (MySqlCommand command = new MySqlCommand(sql, connection)) { // 添加参数 command.Parameters.AddRange(parameters); // 打开连接 connection.Open(); // 创建DataAdapter和DataTable对象，并填充数据 using (MySqlDataAdapter adapter = new MySqlDataAdapter(command)) { DataTable dataTable = new DataTable(); adapter.Fill(dataTable); return dataTable; } } } } // 执行一个查询，并将结果集映射到一个对象列表 public List<T> ExecuteQuery<T>(string sql, Func<IDataRecord, T> selector, params MySqlParameter[] parameters) { using (MySqlConnection connection = new MySqlConnection(connectionString)) { using (MySqlCommand command = new MySqlCommand(sql, connection)) { // 添加参数 command.Parameters.AddRange(parameters); // 打开连接 connection.Open(); // 创建DataReader对象并读取数据，将每行数据映射到对象并添加到列表中 using (MySqlDataReader reader = command.ExecuteReader()) { List<T> list = new List<T>(); while (reader.Read()) { list.Add(selector(reader)); } return list; } } } } // 向数据库中插入数据 public int Insert(string tableName, Dictionary<string, object> data) { string[] columns = new string[data.Count]; object[] values = new object[data.Count]; int i = 0; foreach (KeyValuePair<string, object> item in data) { // 获取列名和值 columns[i] = item.Key; values[i] = item.Value; i++; } string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", tableName, string.Join(",", columns), "@" + string.Join(",@", columns)); // 将Dictionary转换为MySqlParameter数组，并执行SQL语句 return ExecuteNonQuery(sql, ToMySqlParameters(data)); } // 更新数据库中的数据 public int Update(string tableName, Dictionary<string, object> data, string whereClause = "") { string[] setValues = new string[data.Count]; int i = 0; foreach (KeyValuePair<string, object> item in data) { // 获取列名和值 setValues[i] = string.Format("{0}=@{0}", item.Key); i++; } string sql = string.Format("UPDATE {0} SET {1}", tableName, string.Join(",", setValues)); if (!string.IsNullOrEmpty(whereClause)) { sql += " WHERE " + whereClause; } // 将Dictionary转换为MySqlParameter数组，并执行SQL语句 return ExecuteNonQuery(sql, ToMySqlParameters(data)); } // 删除数据库中的数据 public int Delete(string tableName, string whereClause = "") { string sql = string.Format("DELETE FROM {0}", tableName); if (!string.IsNullOrEmpty(whereClause)) { sql += " WHERE " + whereClause; } // 执行SQL语句并返回影响 return ExecuteNonQuery(sql); } // 将Dictionary转换为MySqlParameter数组 private MySqlParameter[] ToMySqlParameters(Dictionary<string, object> data) { List<MySqlParameter> parameters = new List<MySqlParameter>(); foreach (KeyValuePair<string, object> item in data) { parameters.Add(new MySqlParameter("@" + item.Key, item.Value)); } return parameters.ToArray(); } }首先private static string consql = "server=localhost;user=root;password=root;database=test;port=3306;;Charset=utf8;"; private MySQLHelper mySQLHelper = new MySQLHelper(consql);然后//string sql = "CREATE DATABASE IF NOT EXISTS test DEFAULT CHARSET utf8 COLLATE utf8_general_ci;"; //mySQLHelper.ExecuteNonQuery(sql); //string sql = "SELECT * FROM `ssapp`.`data_account` where status=@status order by id desc;"; //var aaa = mySQLHelper.ExecuteScalar(sql,new MySqlParameter("@status",1)); string sql = "SELECT * FROM `data_account` where status=@status order by id desc;"; //var aa = mySQLHelper.ExecuteQuery(sql,new MySqlParameter("@status", 1)); var aa = mySQLHelper.ExecuteQuery(sql, r => new Info { gname = r["gname"].ToString(), id = int.Parse(r["id"].ToString()) }, new MySqlParameter("@status", 1)); //两种方法都可以 try { var bb = mySQLHelper.ExecuteQuery(sql, new MySqlParameter("@status", 1)); List<Info> cc = new List<Info>(); foreach (DataRow info in bb.Rows) { cc.Add(ToModel.DataRowToModel<Info>(info)); } } catch (Exception ex) { Console.WriteLine(ex.Message); //throw; }文中Infoprivate class Info { public int id { get; set; } public string gname { get; set; } }Tmodelpublic static class ToModel { public static Tmodel DataRowToModel<Tmodel>(this DataRow dr) { Type type = typeof(Tmodel); Tmodel md = (Tmodel)Activator.CreateInstance(type); foreach (var prop in type.GetProperties()) { object value = dr[prop.Name].ToString().Trim(); if (value != DBNull.Value) prop.SetValue(md, dr[prop.Name]); } return md; } }
一定要声明成全局变量以保持对Timer的引用，不要声明成业务内的局部变量，否则会被垃圾收集器回收！using System; using System.Threading; using System.Threading.Tasks; namespace ActionStudy { class Program { private System.Threading.Timer timer; public static Action Print_Action;//声明事件 static void Main(string[] args) { //创建定时器，2000是延迟多少毫秒，10000是间隔时间 timer = new Timer(new TimerCallback(Execute), null, 2000, 10000); //timer= new System.Threading.Timer(new TimerCallback(Print), this, 5000, 0); //事件触发绑定的方法 Print_Action += Print; Console.ReadKey(); } /// /// 创建回调触发方法 /// /// public static void Execute(object o) { //Console.WriteLine("just run now"); Print_Action?.Invoke(); } /// /// 需要定时执行的方法 /// public static void Print() { Console.WriteLine("Action我是狗子 希望你幸福!"+DateTime.Now.ToString()); } } }
一、引入NPOI NuGet：通过NuGet管理解决方案安装：搜索：NPOI进行安装：二、ASP.NET Core使用EF Core连接MySQL执行简单的CRUD操作：因为该篇文章会涉及到MySQL数据库的操作，所以前提我们需要有一点的CRUD的基础。这里就不做详细的讲解了三、使用NPOI获取Excel数据注意点：1、关于Excel的版本问题做过Excel相关工作的人应该都清楚Office Excel的格式有两种：a、一种是.XLS是03版的Office Excel，无法打开高版本的。b、一种是.XLSX是07版(或者07以上的)的Office Excel，可以打开低版本的。所以我们在使用NPOI导入数据时不同格式获取Excel工作簿对象也有所不同，如下代码所示：//Workbook对象代表一个工作簿,首先定义一个Excel工作薄 IWorkbook workbook; //XSSFWorkbook 适用XLSX格式，HSSFWorkbook 适用XLS格式 #region 判断Excel版本 switch (fileType) { //.XLSX是07版(或者07以上的)的Office Excel case ".xlsx": workbook = new XSSFWorkbook(stream); break; //.XLS是03版的Office Excel case ".xls": workbook = new HSSFWorkbook(stream); break; default: throw new Exception("Excel文档格式有误"); } #endregion2、NPOI获取Excel单元格中不同类型的数据：{message type="info" content="注意，咱们填写在Excel单元格中的数据可能为多种不同的数据类型，因此我们需要对单元格中的数据类型做判断然后在获取，否则程序会报异常。"/}#region NPOI获取Excel单元格中不同类型的数据 //获取指定的单元格信息 var cell = row.GetCell(j); switch (cell.CellType) { //首先在NPOI中数字和日期都属于Numeric类型 //通过NPOI中自带的DateUtil.IsCellDateFormatted判断是否为时间日期类型 case CellType.Numeric when DateUtil.IsCellDateFormatted(cell): dataRow[j] = cell.DateCellValue; break; case CellType.Numeric: //其他数字类型 dataRow[j] = cell.NumericCellValue; break; //空数据类型 case CellType.Blank: dataRow[j] = ""; break; //公式类型 case CellType.Formula: { HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(workbook); dataRow[j] = eva.Evaluate(cell).StringValue; break; } //布尔类型 case CellType.Boolean: dataRow[j] = row.GetCell(j).BooleanCellValue; break; //错误 case CellType.Error: dataRow[j] = HSSFErrorConstants.GetText(row.GetCell(j).ErrorCellValue); break; //其他类型都按字符串类型来处理（未知类型CellType.Unknown，字符串类型CellType.String） default: dataRow[j] = cell.StringCellValue; break; } #endregion 四、通用的NPOI Excel导入数据帮助类（NpoiExcelImportHelper）：/** * Description：Npoi数据导入帮助类 * Description：2024年1月10日 */ using System; using System.Data; using System.IO; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; namespace YY_Utility { public class NpoiExcelImportHelper { private static NpoiExcelImportHelper _excelImportHelper; public static NpoiExcelImportHelper _ { get => _excelImportHelper ?? (_excelImportHelper = new NpoiExcelImportHelper()); set => _excelImportHelper = value; } /// /// 读取excel表格中的数据,将Excel文件流转化为dataTable数据源 /// 默认第一行为标题 /// /// excel文档文件流 /// 文档格式 /// 是否转化成功 /// 转换结果消息 /// <returns></returns> public DataTable ExcelToDataTable(Stream stream, string fileType, out bool isSuccess, out string resultMsg) { isSuccess = false; resultMsg = "Excel文件流成功转化为DataTable数据源"; var excelToDataTable = new DataTable(); try { //Workbook对象代表一个工作簿,首先定义一个Excel工作薄 IWorkbook workbook; //XSSFWorkbook 适用XLSX格式，HSSFWorkbook 适用XLS格式 #region 判断Excel版本 switch (fileType) { //.XLSX是07版(或者07以上的)的Office Excel case ".xlsx": workbook = new XSSFWorkbook(stream); break; //.XLS是03版的Office Excel case ".xls": workbook = new HSSFWorkbook(stream); break; default: throw new Exception("Excel文档格式有误"); } #endregion var sheet = workbook.GetSheetAt(0); var rows = sheet.GetRowEnumerator(); var headerRow = sheet.GetRow(0); int cellCount = headerRow.LastCellNum;//最后一行列数（即为总列数） //获取第一行标题列数据源,转换为dataTable数据源的表格标题名称 for (var j = 0; j < cellCount; j++) { var cell = headerRow.GetCell(j); excelToDataTable.Columns.Add(cell.ToString()); } //补充一个获取图片 var pictures = workbook.GetAllPictures(); string polor_img=string.Empty;//路径 foreach (XSSFPictureData pic in pictures) { string ext = pic.SuggestFileExtension(); Image png = Image.FromStream(new MemoryStream(pic.Data)); polor_img = savepath+"\\"+c_id+"."+ ext; png.Save(polor_img); polor_img = $"{DateTime.Now:yyyyMMdd}/{c_id}.{ext}"; } //获取Excel表格中除标题以为的所有数据源，转化为dataTable中的表格数据源 for (var i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) { var dataRow = excelToDataTable.NewRow(); var row = sheet.GetRow(i); if (row == null) continue; //没有数据的行默认是null for (int j = row.FirstCellNum; j < cellCount; j++) { if (row.GetCell(j) != null)//单元格内容非空验证 { #region NPOI获取Excel单元格中不同类型的数据 //获取指定的单元格信息 var cell = row.GetCell(j); switch (cell.CellType) { //首先在NPOI中数字和日期都属于Numeric类型 //通过NPOI中自带的DateUtil.IsCellDateFormatted判断是否为时间日期类型 case CellType.Numeric when DateUtil.IsCellDateFormatted(cell): dataRow[j] = cell.DateCellValue; break; case CellType.Numeric: //其他数字类型 dataRow[j] = cell.NumericCellValue; break; //空数据类型 case CellType.Blank: dataRow[j] = ""; break; //公式类型 case CellType.Formula: { HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(workbook); dataRow[j] = eva.Evaluate(cell).StringValue; break; } //布尔类型 case CellType.Boolean: dataRow[j] = row.GetCell(j).BooleanCellValue; break; //错误 case CellType.Error: dataRow[j] = HSSFErrorConstants.GetText(row.GetCell(j).ErrorCellValue); break; //其他类型都按字符串类型来处理（未知类型CellType.Unknown，字符串类型CellType.String） default: dataRow[j] = cell.StringCellValue; break; } #endregion } } excelToDataTable.Rows.Add(dataRow); } isSuccess = true; } catch (Exception e) { resultMsg = e.Message; } return excelToDataTable; } } }OK~结束{card-describe title="其他C# NPIO文章"}.NET C#使用NPOI导出Word详解.NET c# 使用NPOI导出Excel{/card-describe}
一、首先引入NPOI NuGet通过NuGet管理解决方案安装,搜索：NPOI进行安装：二、导出的Work文档内容展示格式如下图所示：三、NPOI中的XWPFRun文本对象创建和常用属性简单概述XWPFRun文本对象说明： XWPFRun是段落的文本对象，先创建段落对象才能够在段落对象的基础上创建文本对象，并设置相关文本样式。使用方式，如下所示：/// /// 创建word文档中的段落对象和设置段落文本的基本样式（字体大小，字体，字体颜色，字体对齐位置） /// /// document文档对象 /// 段落第一个文本对象填充的内容 /// 是否加粗 /// 字体大小 /// 字体 /// 段落排列（左对齐，居中，右对齐） /// 是否在同一段落创建第二个文本对象（解决同一段落里面需要填充两个或者多个文本值的情况，多个文本需要自己拓展，现在最多支持两个） /// 第二次声明的文本对象填充的内容，样式与第一次的一致 /// 字体颜色--十六进制 /// 是否设置斜体（字体倾斜） /// <returns></returns> public XWPFParagraph ParagraphInstanceSetting(XWPFDocument document, string fillContent, bool isBold, int fontSize, string fontFamily, ParagraphAlignment paragraphAlign, bool isStatement = false, string secondFillContent = "", string fontColor = "000000", bool isItalic = false) { XWPFParagraph paragraph = document.CreateParagraph();//创建段落对象 paragraph.Alignment = paragraphAlign;//文字显示位置,段落排列（左对齐，居中，右对齐） XWPFRun xwpfRun = paragraph.CreateRun();//创建段落文本对象 xwpfRun.IsBold = isBold;//文字加粗 xwpfRun.SetText(fillContent);//填充内容 xwpfRun.FontSize = fontSize;//设置文字大小 xwpfRun.IsItalic = isItalic;//是否设置斜体（字体倾斜） xwpfRun.SetColor(fontColor);//设置字体颜色--十六进制 xwpfRun.SetFontFamily(fontFamily, FontCharRange.None); //设置标题样式如：（微软雅黑，隶书，楷体）根据自己的需求而定 if (!isStatement) return paragraph; XWPFRun secondXwpfRun = paragraph.CreateRun();//创建段落文本对象 secondXwpfRun.IsBold = isBold;//文字加粗 secondXwpfRun.SetText(secondFillContent);//填充内容 secondXwpfRun.FontSize = fontSize;//设置文字大小 secondXwpfRun.IsItalic = isItalic;//是否设置斜体（字体倾斜） secondXwpfRun.SetColor(fontColor);//设置字体颜色--十六进制 secondXwpfRun.SetFontFamily(fontFamily, FontCharRange.None); //设置标题样式如：（微软雅黑，隶书，楷体）根据自己的需求而定 return paragraph; }XWPFRun文本对象的属性比较多，以下我简单介绍下常用的一些属性：XWPFParagraph paragraph = document.CreateParagraph();//创建段落对象 XWPFRun xwpfRun= paragraph.CreateRun();//创建段落文本对象 xwpfRun.IsBold = isBold;//文字加粗 xwpfRun.SetText(fillContent);//填充内容 xwpfRun.FontSize = fontSize;//设置文字大小 xwpfRun.SetFontFamily(fontFamily, FontCharRange.None); //设置标题样式如：（微软雅黑，隶书，楷体）根据自己的需求而定 xwpfRun.SetColor("BED4F1");//设置字体颜色--十六进制 xwpfRun.IsDoubleStrikeThrough=true;//是否显示双删除线 xwpfRun.IsStrikeThrough = true;//是否显示单删除线 xwpfRun.SetUnderline(UnderlinePatterns.Dash);//设置下划线，枚举类型 xwpfRun.SetTextPosition(20);//设置文本位置（设置两行之间的行间） xwpfRun.AddBreak();//设置换行（ ） xwpfRun.AddTab();//添加tab键 xwpfRun.AddCarriageReturn();//添加回车键 xwpfRun.IsImprinted = true;//印迹（悬浮阴影）,效果和浮雕类似 xwpfRun.IsItalic=true;//是否设置斜体（字体倾斜） xwpfRun.Subscript = VerticalAlign.SUBSCRIPT;//设置下标，枚举类型NPOI中关于XWPFRun属性的更多使用技巧,请阅读源码：源码地址颜色的十六进制对照表:参考地址四、NPOI生成Word完整代码：/** * Description：Npoi之导出Word段落，文本，表格，字体等相关样式统一封装 * Description：2024年1月10日 */ using System; using NPOI.XWPF.UserModel; using NPOI.OpenXmlFormats.Wordprocessing; namespace YY_Utility { public class NpoiWordParagraphTextStyleHelper { private static NpoiWordParagraphTextStyleHelper _exportHelper; public static NpoiWordParagraphTextStyleHelper _ { get => _exportHelper ?? (_exportHelper = new NpoiWordParagraphTextStyleHelper()); set => _exportHelper = value; } /// /// 创建word文档中的段落对象和设置段落文本的基本样式（字体大小，字体，字体颜色，字体对齐位置） /// /// document文档对象 /// 段落第一个文本对象填充的内容 /// 是否加粗 /// 字体大小 /// 字体 /// 段落排列（左对齐，居中，右对齐） /// 是否在同一段落创建第二个文本对象（解决同一段落里面需要填充两个或者多个文本值的情况，多个文本需要自己拓展，现在最多支持两个） /// 第二次声明的文本对象填充的内容，样式与第一次的一致 /// 字体颜色--十六进制 /// 是否设置斜体（字体倾斜） /// <returns></returns> public XWPFParagraph ParagraphInstanceSetting(XWPFDocument document, string fillContent, bool isBold, int fontSize, string fontFamily, ParagraphAlignment paragraphAlign, bool isStatement = false, string secondFillContent = "", string fontColor = "000000", bool isItalic = false) { XWPFParagraph paragraph = document.CreateParagraph();//创建段落对象 paragraph.Alignment = paragraphAlign;//文字显示位置,段落排列（左对齐，居中，右对齐） XWPFRun xwpfRun = paragraph.CreateRun();//创建段落文本对象 xwpfRun.IsBold = isBold;//文字加粗 xwpfRun.SetText(fillContent);//填充内容 xwpfRun.FontSize = fontSize;//设置文字大小 xwpfRun.IsItalic = isItalic;//是否设置斜体（字体倾斜） xwpfRun.SetColor(fontColor);//设置字体颜色--十六进制 xwpfRun.SetFontFamily(fontFamily, FontCharRange.None); //设置标题样式如：（微软雅黑，隶书，楷体）根据自己的需求而定 if (!isStatement) return paragraph; XWPFRun secondXwpfRun = paragraph.CreateRun();//创建段落文本对象 secondXwpfRun.IsBold = isBold;//文字加粗 secondXwpfRun.SetText(secondFillContent);//填充内容 secondXwpfRun.FontSize = fontSize;//设置文字大小 secondXwpfRun.IsItalic = isItalic;//是否设置斜体（字体倾斜） secondXwpfRun.SetColor(fontColor);//设置字体颜色--十六进制 secondXwpfRun.SetFontFamily(fontFamily, FontCharRange.None); //设置标题样式如：（微软雅黑，隶书，楷体）根据自己的需求而定 return paragraph; } /// /// 创建Word文档中表格段落实例和设置表格段落文本的基本样式（字体大小，字体，字体颜色，字体对齐位置） /// /// document文档对象 /// 表格对象 /// 要填充的文字 /// 段落排列（左对齐，居中，右对齐） /// 设置文本位置（设置两行之间的行间,从而实现表格文字垂直居中的效果），从而实现table的高度设置效果 /// 是否加粗（true加粗，false不加粗） /// 字体大小 /// 字体颜色--十六进制 /// 是否设置斜体（字体倾斜） /// <returns></returns> public XWPFParagraph SetTableParagraphInstanceSetting(XWPFDocument document, XWPFTable table, string fillContent, ParagraphAlignment paragraphAlign, int textPosition = 24, bool isBold = false, int fontSize = 10, string fontColor = "000000", bool isItalic = false) { var para = new CT_P(); //设置单元格文本对齐 para.AddNewPPr().AddNewTextAlignment(); XWPFParagraph paragraph = new XWPFParagraph(para, table.Body);//创建表格中的段落对象 paragraph.Alignment = paragraphAlign;//文字显示位置,段落排列（左对齐，居中，右对齐） //paragraph.FontAlignment =Convert.ToInt32(ParagraphAlignment.CENTER);//字体在单元格内显示位置与 paragraph.Alignment效果相似 XWPFRun xwpfRun = paragraph.CreateRun();//创建段落文本对象 xwpfRun.SetText(fillContent); xwpfRun.FontSize = fontSize;//字体大小 xwpfRun.SetColor(fontColor);//设置字体颜色--十六进制 xwpfRun.IsItalic = isItalic;//是否设置斜体（字体倾斜） xwpfRun.IsBold = isBold;//是否加粗 xwpfRun.SetFontFamily("宋体", FontCharRange.None);//设置字体（如：微软雅黑,华文楷体,宋体） xwpfRun.SetTextPosition(textPosition);//设置文本位置（设置两行之间的行间），从而实现table的高度设置效果 return paragraph; } } }生成并保存Word:using Microsoft.AspNetCore.Hosting; using NPOI.OpenXmlFormats.Wordprocessing; using NPOI.XWPF.UserModel; using System; using System.IO; using YY_Utility; namespace Export.Services { public class NpoiWordExportService { private static IHostingEnvironment _environment; public NpoiWordExportService(IHostingEnvironment iEnvironment) { _environment = iEnvironment; } #region 生成word /// /// 生成word文档,并保存静态资源文件夹（wwwroot)下的SaveWordFile文件夹中 /// /// 保存路径 public bool SaveWordFile(out string savePath) { savePath = ""; try { string currentDate = DateTime.Now.ToString("yyyyMMdd"); string checkTime = DateTime.Now.ToString("yyyy年MM月dd日");//检查时间 //保存文件到静态资源wwwroot,使用绝对路径路径 var uploadPath = _environment.WebRootPath + "/SaveWordFile/" + currentDate + "/";//>>>相当于HttpContext.Current.Server.MapPath("") string workFileName = checkTime + "追逐时光企业员工培训考核统计记录表"; string fileName = string.Format("{0}.docx", workFileName, System.Text.Encoding.UTF8); if (!Directory.Exists(uploadPath)) { Directory.CreateDirectory(uploadPath); } //TODO:使用FileStream文件流来写入数据（传入参数为：文件所在路径，对文件的操作方式，对文件内数据的操作） //通过使用文件流，创建文件流对象，向文件流中写入内容，并保存为Word文档格式 using (var stream = new FileStream(Path.Combine(uploadPath, fileName), FileMode.Create, FileAccess.Write)) { //创建document文档对象对象实例 XWPFDocument document = new XWPFDocument(); /** *这里我通过设置公共的Word文档中SetParagraph（段落）实例创建和段落样式格式设置，大大减少了代码的冗余， * 避免每使用一个段落而去创建一次段落实例和设置段落的基本样式 *(如下，ParagraphInstanceSetting为段落实例创建和样式设置，后面索引表示为当前是第几行段落,索引从0开始) */ //文本标题 document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, workFileName, true, 19, "宋体", ParagraphAlignment.CENTER), 0); //TODO:这里一行需要显示两个文本 document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, $"编号：20190927101120445887", false, 14, "宋体", ParagraphAlignment.LEFT, true, $" 检查时间：{checkTime}"), 1); document.SetParagraph(NpoiWordParagraphTextStyleHelper._.ParagraphInstanceSetting(document, "登记机关：企业员工监督检查机构", false, 14, "宋体", ParagraphAlignment.LEFT), 2); #region 文档第一个表格对象实例 //创建文档中的表格对象实例 XWPFTable firstXwpfTable = document.CreateTable(4, 4);//显示的行列数rows:3行,cols:4列 firstXwpfTable.Width = 5200;//总宽度 firstXwpfTable.SetColumnWidth(0, 1300); /* 设置列宽 */ firstXwpfTable.SetColumnWidth(1, 1100); /* 设置列宽 */ firstXwpfTable.SetColumnWidth(2, 1400); /* 设置列宽 */ firstXwpfTable.SetColumnWidth(3, 1400); /* 设置列宽 */ //Table 表格第一行展示...后面的都是一样，只改变GetRow中的行数 firstXwpfTable.GetRow(0).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "企业名称", ParagraphAlignment.CENTER, 24, true)); firstXwpfTable.GetRow(0).GetCell(1).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "追逐时光", ParagraphAlignment.CENTER, 24, false)); firstXwpfTable.GetRow(0).GetCell(2).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "企业地址", ParagraphAlignment.CENTER, 24, true)); firstXwpfTable.GetRow(0).GetCell(3).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "湖南省-长沙市-岳麓区", ParagraphAlignment.CENTER, 24, false)); //Table 表格第二行 firstXwpfTable.GetRow(1).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "联系人", ParagraphAlignment.CENTER, 24, true)); firstXwpfTable.GetRow(1).GetCell(1).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "小明同学", ParagraphAlignment.CENTER, 24, false)); firstXwpfTable.GetRow(1).GetCell(2).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "联系方式", ParagraphAlignment.CENTER, 24, true)); firstXwpfTable.GetRow(1).GetCell(3).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "151****0456", ParagraphAlignment.CENTER, 24, false)); //Table 表格第三行 firstXwpfTable.GetRow(2).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "企业许可证号", ParagraphAlignment.CENTER, 24, true)); firstXwpfTable.GetRow(2).GetCell(1).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "XXXXX-66666666", ParagraphAlignment.CENTER, 24, false)); firstXwpfTable.GetRow(2).GetCell(2).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "检查次数", ParagraphAlignment.CENTER, 24, true)); firstXwpfTable.GetRow(2).GetCell(3).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, $"本年度检查8次", ParagraphAlignment.CENTER, 24, false)); firstXwpfTable.GetRow(3).MergeCells(0, 3);//合并3列 firstXwpfTable.GetRow(3).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "", ParagraphAlignment.LEFT, 10, false)); #endregion var checkPeopleNum = 0;//检查人数 var totalScore = 0;//总得分 #region 文档第二个表格对象实例（遍历表格项） //创建文档中的表格对象实例 XWPFTable secoedXwpfTable = document.CreateTable(5, 4);//显示的行列数rows:8行,cols:4列 secoedXwpfTable.Width = 5200;//总宽度 secoedXwpfTable.SetColumnWidth(0, 1300); /* 设置列宽 */ secoedXwpfTable.SetColumnWidth(1, 1100); /* 设置列宽 */ secoedXwpfTable.SetColumnWidth(2, 1400); /* 设置列宽 */ secoedXwpfTable.SetColumnWidth(3, 1400); /* 设置列宽 */ //遍历表格标题 secoedXwpfTable.GetRow(0).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "员工姓名", ParagraphAlignment.CENTER, 24, true)); secoedXwpfTable.GetRow(0).GetCell(1).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "性别", ParagraphAlignment.CENTER, 24, true)); secoedXwpfTable.GetRow(0).GetCell(2).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "年龄", ParagraphAlignment.CENTER, 24, true)); secoedXwpfTable.GetRow(0).GetCell(3).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "综合评分", ParagraphAlignment.CENTER, 24, true)); //遍历四条数据 for (var i = 1; i < 5; i++) { secoedXwpfTable.GetRow(i).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "小明" + i + "号", ParagraphAlignment.CENTER, 24, false)); secoedXwpfTable.GetRow(i).GetCell(1).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, "男", ParagraphAlignment.CENTER, 24, false)); secoedXwpfTable.GetRow(i).GetCell(2).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, 20 + i + "岁", ParagraphAlignment.CENTER, 24, false)); secoedXwpfTable.GetRow(i).GetCell(3).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, firstXwpfTable, 90 + i + "分", ParagraphAlignment.CENTER, 24, false)); checkPeopleNum++; totalScore += 90 + i; } #endregion #region 文档第三个表格对象实例 //创建文档中的表格对象实例 XWPFTable thirdXwpfTable = document.CreateTable(5, 4);//显示的行列数rows:5行,cols:4列 thirdXwpfTable.Width = 5200;//总宽度 thirdXwpfTable.SetColumnWidth(0, 1300); /* 设置列宽 */ thirdXwpfTable.SetColumnWidth(1, 1100); /* 设置列宽 */ thirdXwpfTable.SetColumnWidth(2, 1400); /* 设置列宽 */ thirdXwpfTable.SetColumnWidth(3, 1400); /* 设置列宽 */ //Table 表格第一行，后面的合并3列(注意关于表格中行合并问题，先合并，后填充内容) thirdXwpfTable.GetRow(0).MergeCells(0, 3);//从第一列起,合并3列 thirdXwpfTable.GetRow(0).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, thirdXwpfTable, " " + "检查内容: " + $"于{checkTime}下午检查了追逐时光企业员工培训考核并对员工的相关信息进行了相关统计，统计结果如下： " + "-------------------------------------------------------------------------------------" + $"共对该企业（{checkPeopleNum}）人进行了培训考核，培训考核总得分为（{totalScore}）分。 " + "", ParagraphAlignment.LEFT, 30, false)); //Table 表格第二行 thirdXwpfTable.GetRow(1).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, thirdXwpfTable, "检查结果: ", ParagraphAlignment.CENTER, 24, true)); thirdXwpfTable.GetRow(1).MergeCells(1, 3);//从第二列起，合并三列 thirdXwpfTable.GetRow(1).GetCell(1).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, thirdXwpfTable, "该企业非常优秀，坚持每天学习打卡，具有蓬勃向上的活力。", ParagraphAlignment.LEFT, 24, false)); //Table 表格第三行 thirdXwpfTable.GetRow(2).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, thirdXwpfTable, "处理结果: ", ParagraphAlignment.CENTER, 24, true)); thirdXwpfTable.GetRow(2).MergeCells(1, 3); thirdXwpfTable.GetRow(2).GetCell(1).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, thirdXwpfTable, "通过检查，评分为优秀！", ParagraphAlignment.LEFT, 24, false)); //Table 表格第四行，后面的合并3列(注意关于表格中行合并问题，先合并，后填充内容),额外说明 thirdXwpfTable.GetRow(3).MergeCells(0, 3);//合并3列 thirdXwpfTable.GetRow(3).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, thirdXwpfTable, "备注说明: 记住，坚持就是胜利，永远保持一种求知，好问的心理！", ParagraphAlignment.LEFT, 24, false)); //Table 表格第五行 thirdXwpfTable.GetRow(4).MergeCells(0, 1); thirdXwpfTable.GetRow(4).GetCell(0).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, thirdXwpfTable, " 检查人员签名： 年 月 日", ParagraphAlignment.LEFT, 30, false)); thirdXwpfTable.GetRow(4).MergeCells(1, 2); thirdXwpfTable.GetRow(4).GetCell(1).SetParagraph(NpoiWordParagraphTextStyleHelper._.SetTableParagraphInstanceSetting(document, thirdXwpfTable, " 企业法人签名： 年 月 日", ParagraphAlignment.LEFT, 30, false)); #endregion //向文档流中写入内容，生成word document.Write(stream); savePath = "/SaveWordFile/" + currentDate + "/" + fileName; return true; } } catch (Exception ex) { //ignore savePath = ex.Message; return false; } } #endregion } }.NET 使用NPOI导出Excel详解：传送门
一、通过NuGet管理解决方案安装 搜索：NPOI进行安装： 二、导出Excel文档内容展示格式如下如所示： 三、CellStyle单元格常用样式概述HSSFCellStyle cellStyle = (HSSFCellStyle)workbook.CreateCellStyle(); //创建列头单元格实例样式 cellStyle.Alignment = hAlignment; //水平布局方式（HorizontalAlignment hAlignment） cellStyle.VerticalAlignment = vAlignment; //垂直布局方式（VerticalAlignment vAlignment） cellStyle.WrapText =false;//是否自动换行 //TODO:十分注意，要设置单元格背景色必须是FillForegroundColor和FillPattern两个属性同时设置，否则是不会显示背景颜色 //如下设置黄色背景色 cellStyle.FillForegroundColor = cellBackgroundColor;//单元格背景颜色（short cellBackgroundColor = HSSFColor.Yellow.Index） cellStyle.FillPattern = fillPattern;//填充图案样式(FineDots 细点，SolidForeground立体前景，isAddFillPattern=true时存在（FillPattern fillPattern = FillPattern.SolidForeground） //设置单元格边框样式 //常用的边框样式 None(没有),Thin(细边框，瘦的),Medium(中等),Dashed(虚线),Dotted(星罗棋布的),Thick(厚的),Double(双倍),Hair(头发)[上右下左顺序设置] cellStyle.BorderBottom = BorderStyle.Thin; cellStyle.BorderRight = BorderStyle.Thin; cellStyle.BorderTop = BorderStyle.Thin; cellStyle.BorderLeft = BorderStyle.Thin; //设置单元格边框颜色[上右下左顺序设置] cellStyle.TopBorderColor = HSSFColor.DarkGreen.Index;//DarkGreen(黑绿色) cellStyle.RightBorderColor = HSSFColor.DarkGreen.Index; cellStyle.BottomBorderColor = HSSFColor.DarkGreen.Index; cellStyle.LeftBorderColor = HSSFColor.DarkGreen.Index;四、Font字体常用属性概述：var cellStyleFont = (HSSFFont)workbook.CreateFont();//创建字体对象实例 //假如字体大小只需要是粗体的话直接使用下面该属性即可 cellStyleFont.IsBold = true; //或者通过下面属性，设置字体weight来设置字体是否加粗 cellStyleFont.Boldweight = boldWeight; //字体加粗（字体加粗 (None = 0,Normal = 400，Bold = 700） cellStyleFont.FontHeightInPoints = fontHeightInPoints; //字体大小（short fontHeightInPoints） cellStyleFont.FontName = fontName;//字体（仿宋，楷体，宋体 ） cellStyleFont.Color = fontColor;//设置字体颜色（short fontColor = HSSFColor.Black.Index） cellStyleFont.IsItalic =true;//是否将文字变为斜体（true是，false否） cellStyleFont.Underline = underlineStyle;//字体下划线（下划线样式（无下划线[None],单下划线[Single],双下划线[Double],会计用单下划线[SingleAccounting],会计用双下划线[DoubleAccounting]）） cellStyleFont.TypeOffset = typeOffset;//字体上标下标（字体上标下标(普通默认值[None],上标[Sub],下标[Super]),即字体在单元格内的上下偏移量） cellStyleFont.IsStrikeout =true;//是否显示删除线（true显示，false不显示）五、NPOI HSSFColor 颜色索引对照表: 具体前往此处查看（潘小博1992） 六、关于NPOI对Excel中的行列常用操作方法概述： 创建Excel工作表，给工作表赋一个名称(Excel底部名称)： var sheet = workbook.CreateSheet("人才培训课程表"); 创建Excel中指定的行:/// /// TODO:先创建行，然后在创建对应的列 /// 创建Excel中指定的行 /// /// Excel工作表对象 /// 创建第几行(从0开始) /// 行高 public HSSFRow CreateRow(ISheet sheet, int rowNum, float rowHeight) { HSSFRow row = (HSSFRow)sheet.CreateRow(rowNum); //创建行 row.HeightInPoints = rowHeight; //设置列头行高 return row; }创建行内指定的单元格:/// /// 创建行内指定的单元格 /// /// 需要创建单元格的行 /// 单元格样式 /// 创建第几个单元格(从0开始) /// 给单元格赋值 /// <returns></returns> public HSSFCell CreateCells(HSSFRow row, HSSFCellStyle cellStyle, int cellNum, string cellValue) { HSSFCell cell = (HSSFCell)row.CreateCell(cellNum); //创建单元格 cell.CellStyle = cellStyle; //将样式绑定到单元格 if (!string.IsNullOrWhiteSpace(cellValue)) { //单元格赋值 cell.SetCellValue(cellValue); } return cell; }指定合并的行列://TODO:关于Excel行列单元格合并问题(注意：合并单元格后，只需对第一个位置赋值即可) /** 第一个参数：从第几行开始合并 第二个参数：到第几行结束合并 第三个参数：从第几列开始合并 第四个参数：到第几列结束合并 **/ CellRangeAddress region = new CellRangeAddress(0, 0, 0, 5); sheet.AddMergedRegion(region); cell.SetCellValue("人才培训课程表");//TODO:顶部标题设置单元格的列宽： `sheet.SetColumnWidth(单元格索引,1000);//设置对应列宽（单元格索引从0开始，后面接宽度） ` 七、NPOI生成Excel文档完整代码：NPOI之Excel数据导出帮助类（创建Excel表格行列，设置行高，设置字体样式，单元格边框样式，单元格背景颜色和样式，单元格内容对齐方式等常用属性和样式封装）:/** * Description：Npoi之Excel数据导出帮助类（创建Excel表格行列，设置行高，设置字体样式，单元格边框样式，单元格背景颜色和样式，单元格内容对齐方式等常用属性和样式封装） * Description：2020年3月29日 */ using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.HSSF.Util; namespace YY_Utility { public class NpoiExcelExportHelper { private static NpoiExcelExportHelper _exportHelper; public static NpoiExcelExportHelper _ { get => _exportHelper ?? (_exportHelper = new NpoiExcelExportHelper()); set => _exportHelper = value; } /// /// TODO:先创建行，然后在创建对应的列 /// 创建Excel中指定的行 /// /// Excel工作表对象 /// 创建第几行(从0开始) /// 行高 public HSSFRow CreateRow(ISheet sheet, int rowNum, float rowHeight) { HSSFRow row = (HSSFRow)sheet.CreateRow(rowNum); //创建行 row.HeightInPoints = rowHeight; //设置列头行高 return row; } /// /// 创建行内指定的单元格 /// /// 需要创建单元格的行 /// 单元格样式 /// 创建第几个单元格(从0开始) /// 给单元格赋值 /// <returns></returns> public HSSFCell CreateCells(HSSFRow row, HSSFCellStyle cellStyle, int cellNum, string cellValue) { HSSFCell cell = (HSSFCell)row.CreateCell(cellNum); //创建单元格 cell.CellStyle = cellStyle; //将样式绑定到单元格 if (!string.IsNullOrWhiteSpace(cellValue)) { //单元格赋值 cell.SetCellValue(cellValue); } return cell; } /// /// 行内单元格常用样式设置 /// /// Excel文件对象 /// 水平布局方式 /// 垂直布局方式 /// 字体大小 /// 是否需要边框 /// 字体加粗 (None = 0,Normal = 400，Bold = 700 /// 字体（仿宋，楷体，宋体，微软雅黑...与Excel主题字体相对应） /// 是否增加边框颜色 /// 是否将文字变为斜体 /// 是否自动换行 /// 是否增加单元格背景颜色 /// 填充图案样式(FineDots 细点，SolidForeground立体前景，isAddFillPattern=true时存在) /// 单元格背景颜色（当isAddCellBackground=true时存在） /// 字体颜色 /// 下划线样式（无下划线[None],单下划线[Single],双下划线[Double],会计用单下划线[SingleAccounting],会计用双下划线[DoubleAccounting]） /// 字体上标下标(普通默认值[None],上标[Sub],下标[Super]),即字体在单元格内的上下偏移量 /// 是否显示删除线 /// <returns></returns> public HSSFCellStyle CreateStyle(HSSFWorkbook workbook, HorizontalAlignment hAlignment, VerticalAlignment vAlignment, short fontHeightInPoints, bool isAddBorder, short boldWeight, string fontName = "宋体", bool isAddBorderColor = true, bool isItalic = false, bool isLineFeed = false, bool isAddCellBackground = false, FillPattern fillPattern = FillPattern.NoFill, short cellBackgroundColor = HSSFColor.Yellow.Index, short fontColor = HSSFColor.Black.Index, FontUnderlineType underlineStyle = FontUnderlineType.None, FontSuperScript typeOffset = FontSuperScript.None, bool isStrikeout = false) { HSSFCellStyle cellStyle = (HSSFCellStyle)workbook.CreateCellStyle(); //创建列头单元格实例样式 cellStyle.Alignment = hAlignment; //水平居中 cellStyle.VerticalAlignment = vAlignment; //垂直居中 cellStyle.WrapText = isLineFeed;//自动换行 //背景颜色，边框颜色，字体颜色都是使用 HSSFColor属性中的对应调色板索引，关于 HSSFColor 颜色索引对照表，详情参考：https://www.cnblogs.com/Brainpan/p/5804167.html //TODO：引用了NPOI后可通过ICellStyle 接口的 FillForegroundColor 属性实现 Excel 单元格的背景色设置，FillPattern 为单元格背景色的填充样式 //TODO:十分注意，要设置单元格背景色必须是FillForegroundColor和FillPattern两个属性同时设置，否则是不会显示背景颜色 if (isAddCellBackground) { cellStyle.FillForegroundColor = cellBackgroundColor;//单元格背景颜色 cellStyle.FillPattern = fillPattern;//填充图案样式(FineDots 细点，SolidForeground立体前景) } //是否增加边框 if (isAddBorder) { //常用的边框样式 None(没有),Thin(细边框，瘦的),Medium(中等),Dashed(虚线),Dotted(星罗棋布的),Thick(厚的),Double(双倍),Hair(头发)[上右下左顺序设置] cellStyle.BorderBottom = BorderStyle.Thin; cellStyle.BorderRight = BorderStyle.Thin; cellStyle.BorderTop = BorderStyle.Thin; cellStyle.BorderLeft = BorderStyle.Thin; } //是否设置边框颜色 if (isAddBorderColor) { //边框颜色[上右下左顺序设置] cellStyle.TopBorderColor = HSSFColor.DarkGreen.Index;//DarkGreen(黑绿色) cellStyle.RightBorderColor = HSSFColor.DarkGreen.Index; cellStyle.BottomBorderColor = HSSFColor.DarkGreen.Index; cellStyle.LeftBorderColor = HSSFColor.DarkGreen.Index; } /** * 设置相关字体样式 */ var cellStyleFont = (HSSFFont)workbook.CreateFont(); //创建字体 //假如字体大小只需要是粗体的话直接使用下面该属性即可 //cellStyleFont.IsBold = true; cellStyleFont.Boldweight = boldWeight; //字体加粗 cellStyleFont.FontHeightInPoints = fontHeightInPoints; //字体大小 cellStyleFont.FontName = fontName;//字体（仿宋，楷体，宋体 ） cellStyleFont.Color = fontColor;//设置字体颜色 cellStyleFont.IsItalic = isItalic;//是否将文字变为斜体 cellStyleFont.Underline = underlineStyle;//字体下划线 cellStyleFont.TypeOffset = typeOffset;//字体上标下标 cellStyleFont.IsStrikeout = isStrikeout;//是否有删除线 cellStyle.SetFont(cellStyleFont); //将字体绑定到样式 return cellStyle; } } }生成并保存指定的Excel文档内容：using System; using System.IO; using Microsoft.AspNetCore.Hosting; using NPOI.HSSF.UserModel; using NPOI.HSSF.Util; using NPOI.SS.UserModel; using NPOI.SS.Util; using YY_Utility; namespace YY_Services { /// /// Excel文档生成并保存操作类 /// public class NpoiExcelOperationService { private static IHostingEnvironment _environment; public NpoiExcelOperationService(IHostingEnvironment iEnvironment) { _environment = iEnvironment; } /// /// Excel数据导出简单示例 /// /// 导出结果 /// 保存excel文件路径 /// <returns></returns> public bool ExcelDataExport(out string resultMsg, out string excelFilePath) { var result = true; excelFilePath = ""; resultMsg = "successfully"; //Excel导出名称 string excelName = "人才培训课程表"; try { //首先创建Excel文件对象 var workbook = new HSSFWorkbook(); //设置文件右键属性信息 DocumentSummaryInformation document = PropertySetFactory.CreateDocumentSummaryInformation(); SummaryInformation info = PropertySetFactory.CreateSummaryInformation(); document.ApplicationVersion = 999; document.ByteCount = 6666; document.Category = "文件描述信息"; document.Company = "Roman Sultan Mehmed"; document.ContentStatus = "已完成"; document.ContentType = "表格"; info.Title = "测试的表格"; info.Author = "Sultan"; info.ApplicationName = "NPOI测试程序"; info.OSVersion = 3; workbook.DocumentSummaryInformation = document; workbook.SummaryInformation = info; //创建工作表，也就是Excel中的sheet，给工作表赋一个名称(Excel底部名称) var sheet = workbook.CreateSheet("人才培训课程表"); //sheet.DefaultColumnWidth = 20;//默认列宽 sheet.ForceFormulaRecalculation = true;//TODO:是否开始Excel导出后公式仍然有效（非必须） #region table 表格内容设置 #region 标题样式 //设置顶部大标题样式 var cellStyleFont = NpoiExcelExportHelper._.CreateStyle(workbook, HorizontalAlignment.Center, VerticalAlignment.Center, 20, true, 700, "楷体", true, false, false, true, FillPattern.SolidForeground, HSSFColor.Coral.Index, HSSFColor.White.Index, FontUnderlineType.None, FontSuperScript.None, false); //第一行表单 var row = NpoiExcelExportHelper._.CreateRow(sheet, 0, 28); var cell = row.CreateCell(0); //合并单元格 例： 第1行到第2行 第3列到第4列围成的矩形区域 //TODO:关于Excel行列单元格合并问题 /** 第一个参数：从第几行开始合并 第二个参数：到第几行结束合并 第三个参数：从第几列开始合并 第四个参数：到第几列结束合并 **/ CellRangeAddress region = new CellRangeAddress(0, 0, 0, 5); sheet.AddMergedRegion(region); cell.SetCellValue("人才培训课程表");//合并单元格后，只需对第一个位置赋值即可（TODO:顶部标题） cell.CellStyle = cellStyleFont; //二级标题列样式设置 var headTopStyle = NpoiExcelExportHelper._.CreateStyle(workbook, HorizontalAlignment.Center, VerticalAlignment.Center, 15, true, 700, "楷体", true, false, false, true, FillPattern.SolidForeground, HSSFColor.Grey25Percent.Index, HSSFColor.Black.Index, FontUnderlineType.None, FontSuperScript.None, false); //表头名称 var headerName = new[] { "课程类型", "序号", "日期", "课程名称", "内容概要", "讲师简介" }; row = NpoiExcelExportHelper._.CreateRow(sheet, 1, 24);//第二行 for (var i = 0; i < headerName.Length; i++) { cell = NpoiExcelExportHelper._.CreateCells(row, headTopStyle, i, headerName[i]); //设置单元格宽度 if (headerName[i] == "讲师简介" || headerName[i] == "内容概要") { sheet.SetColumnWidth(i, 10000); } else { sheet.SetColumnWidth(i, 5000); } } #endregion #region 单元格内容信息 //单元格边框样式 var cellStyle = NpoiExcelExportHelper._.CreateStyle(workbook, HorizontalAlignment.Center, VerticalAlignment.Center, 10, true, 400); //左侧列单元格合并 begin //TODO:关于Excel行列单元格合并问题（合并单元格后，只需对第一个位置赋值即可） /** 第一个参数：从第几行开始合并 第二个参数：到第几行结束合并 第三个参数：从第几列开始合并 第四个参数：到第几列结束合并 **/ CellRangeAddress leftOne = new CellRangeAddress(2, 7, 0, 0); sheet.AddMergedRegion(leftOne); CellRangeAddress leftTwo = new CellRangeAddress(8, 11, 0, 0); sheet.AddMergedRegion(leftTwo); //左侧列单元格合并 end var currentDate = DateTime.Now; string[] curriculumList = new[] { "艺术学", "设计学", "材料学", "美学", "心理学", "中国近代史", "管理人员的情绪修炼", "高效时间管理", "有效的目标管理", "沟通与协调" }; int number = 1; for (var i = 0; i < 10; i++) { row = NpoiExcelExportHelper._.CreateRow(sheet, i + 2, 20); //sheet.CreateRow(i+2);//在上面表头的基础上创建行 switch (number) { case 1: cell = NpoiExcelExportHelper._.CreateCells(row, cellStyle, 0, "公共类课程"); break; case 7: cell = NpoiExcelExportHelper._.CreateCells(row, cellStyle, 0, "管理类课程"); break; } //创建单元格列公众类课程 cell = NpoiExcelExportHelper._.CreateCells(row, cellStyle, 1, number.ToString()); cell = NpoiExcelExportHelper._.CreateCells(row, cellStyle, 2, currentDate.AddDays(number).ToString("yyyy-MM-dd")); cell = NpoiExcelExportHelper._.CreateCells(row, cellStyle, 3, curriculumList[i]); cell = NpoiExcelExportHelper._.CreateCells(row, cellStyle, 4, "提升，充实，拓展自己综合实力"); cell = NpoiExcelExportHelper._.CreateCells(row, cellStyle, 5, "追逐时光_" + number + "号金牌讲师！"); number++; } #endregion #endregion string folder = DateTime.Now.ToString("yyyyMMdd"); //保存文件到静态资源文件夹中（wwwroot）,使用绝对路径 var uploadPath = _environment.WebRootPath + "/UploadFile/" + folder + "/"; //excel保存文件名 string excelFileName = excelName + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls"; //创建目录文件夹 if (!Directory.Exists(uploadPath)) { Directory.CreateDirectory(uploadPath); } //Excel的路径及名称 string excelPath = uploadPath + excelFileName; //使用FileStream文件流来写入数据（传入参数为：文件所在路径，对文件的操作方式，对文件内数据的操作） var fileStream = new FileStream(excelPath, FileMode.OpenOrCreate, FileAccess.ReadWrite); //向Excel文件对象写入文件流，生成Excel文件 workbook.Write(fileStream); //关闭文件流 fileStream.Close(); //释放流所占用的资源 fileStream.Dispose(); //excel文件保存的相对路径，提供前端下载 var relativePositioning = "/UploadFile/" + folder + "/" + excelFileName; excelFilePath = relativePositioning; } catch (Exception e) { result = false; resultMsg = e.Message; } return result; } } }.NET使用NPIO 导出word传送门OK，结束~~~
MySqlDataReader reader = cmd.ExecuteReader(); DataTable dt = new DataTable(); DataTable schemaTable = reader.GetSchemaTable(); foreach (DataRow dr in schemaTable.Rows) { DataColumn dc = new DataColumn(); dc.DataType = dr[0].GetType(); dc.ColumnName = dr[0].ToString(); dt.Columns.Add(dc); } while (reader.Read()) { DataRow row = dt.NewRow(); for (int i = 0; i < schemaTable.Rows.Count; i++) { row[i] = reader[i].ToString(); } dt.Rows.Add(row); row = null; } schemaTable.Clear(); dt.DefaultView.Sort = "land_time ASC"; dt = dt.DefaultView.ToTable(); foreach (DataRow item in dt.Rows){ Console.WrintLine(item[0]); }
代码如下 public static class Tomodel{ public static Tmodel DataRowToModel<Tmodel>(this DataRow dr){ Type type = typeof(Tmodel); Tmodel md = (Tmodel)Activator.CreateInstance(type); foreach(var prop in type.GetProperties()){ prop.SetValue(md,dr[prop.Name]); } return md; } }使用（this 是扩展方法） dr.DataRowToModell<userModel>(); user.Add(dr.DataRowToModel<userModel>());