使用NPOI 操作Excel
个人使用的电脑基本默认安装Excel 操作起来
调用Excel的组件便可.如果是一台服务器.没有安装Excel,也就无法调用Excel组件.
在此推荐第三方插件.NPOI 支持XLS(2007)和XLSX(2012)读写.
using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.IO; namespace WebApplication1.Helper { public class ExcelHelper : IDisposable { private string fileName = null; //文件名 private IWorkbook workbook = null; private FileStream fs = null; private bool disposed; public ExcelHelper(string fileName) { this.fileName = fileName; disposed = false; fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); if (fileName.IndexOf(\".xlsx\") > 0) // 2007版本 workbook = new XSSFWorkbook(fs); else if (fileName.IndexOf(\".xls\") > 0) // 2003版本 workbook = new HSSFWorkbook(fs); } public List<string> SheetName { get { List<string> data = null; if (workbook != null) { data = new List<string>(); for (int i = 0; i < workbook.NumberOfSheets; i++) { data.Add(workbook.GetSheetAt(i).SheetName.ToString()); } } return data; } } public int SheetCount { get { return workbook == null ? 0 : workbook.NumberOfSheets; } } /// <summary> /// 将excel中的数据导入到DataTable中 /// </summary> /// <param name=\"sheetName\">excel工作薄sheet的名称</param> /// <param name=\"isFirstRowColumn\">第一行是否是DataTable的列名</param> /// <returns>返回的DataTable</returns> public DataTable ExcelToDataTable(string sheetName, bool isFirstRowColumn) { ISheet sheet = null; DataTable data = new DataTable(); int startRow = 0; try { //fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); //if (fileName.IndexOf(\".xlsx\") > 0) // 2007版本 // workbook = new XSSFWorkbook(fs); //else if (fileName.IndexOf(\".xls\") > 0) // 2003版本 // workbook = new HSSFWorkbook(fs); if (sheetName != null) { sheet = workbook.GetSheet(sheetName); if (sheet == null) //如果没有找到指定的sheetName对应的sheet,则尝试获取第一个sheet { sheet = workbook.GetSheetAt(0); } } else { sheet = workbook.GetSheetAt(0); } if (sheet != null) { IRow firstRow = sheet.GetRow(0); int cellCount = firstRow.LastCellNum; //一行最后一个cell的编号 即总的列数 if (isFirstRowColumn) { for (int i = firstRow.FirstCellNum; i < cellCount; ++i) { ICell cell = firstRow.GetCell(i); if (cell != null) { string cellValue = cell.StringCellValue; if (cellValue != null) { DataColumn column = new DataColumn(cellValue); data.Columns.Add(column); } } } startRow = sheet.FirstRowNum + 1; } else { startRow = sheet.FirstRowNum; } //最后一列的标号 int rowCount = sheet.LastRowNum; for (int i = startRow; i <= rowCount; ++i) { IRow row = sheet.GetRow(i); if (row == null) continue; //没有数据的行默认是null DataRow dataRow = data.NewRow(); for (int j = row.FirstCellNum; j < cellCount; ++j) { if (row.GetCell(j) != null) //同理,没有数据的单元格都默认是null dataRow[j] = row.GetCell(j).ToString(); } data.Rows.Add(dataRow); } } return data; } catch (Exception ex) { Console.WriteLine(\"Exception: \" + ex.Message); return null; } } public static void CreateExcel(string projectName) { try { string fileName = $\"{projectName}.xlsx\"; // 文件名称 string filePath = $\"{ConfigurationManager.AppSettings[\"file\"].ToString()}\" + \"\\\\\" + fileName; // 2.解析单元格头部,设置单元头的中文名称 XSSFWorkbook workbook = new XSSFWorkbook(); // 工作簿 ISheet sheet = workbook.CreateSheet(\"sheet\"); //#region 设置Excel表格第一行的样式 //IRow Info = sheet.CreateRow(0); //ICell cell = Info.CreateCell(0); //cell .SetCellValue(\"会员信息批量录入模板\"); //ICellStyle Style = workbook.CreateCellStyle(); //IFont Font = workbook.CreateFont(); // Font.FontHeightInPoints = 25; // Font.Boldweight = short.MaxValue;//字体加粗 // Style.SetFont( Font); //cell .CellStyle = Style; //#endregion //IRow dataFields = sheet.CreateRow(2); //ICellStyle style = workbook.CreateCellStyle();//创建样式对象 //style.Alignment = HorizontalAlignment.CENTER;//水平对齐 //style.VerticalAlignment = VerticalAlignment.CENTER;//垂直对齐 //IFont font = workbook.CreateFont(); //创建一个字体样式对象 //font.FontName = \"宋体\"; //和excel里面的字体对应 //font.Color = new HSSFColor.RED().GetIndex();//颜色参考NPOI的颜色对照表(替换掉PINK()) //font.FontHeightInPoints = 10;//字体大小 //font.Boldweight = short.MaxValue;//字体加粗 //style.SetFont(font); //将字体样式赋给样式对象 //sheet.SetColumnWidth(0, 20 * 256);//设置列宽 //string[] colums = { \"*会员卡号\", \"*会员手机\", \"*会员姓名\", \"*会员等级\", \"会员性别\", \"电子邮箱\", \"会员状态\", \"固定电话\", \"永久有效\", \"身份证号\", \"开卡费用\", \"会员地址\", \"备注信息\" }; //ICell Cell = null; //for (int i = 0; i < colums.Count(); i++) //{ // Cell = dataFields.CreateCell(i); // Cell.CellStyle = style; // Cell.SetCellValue(colums[i]); // sheet.SetColumnWidth(i, 17 * 256); //} //sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, colums.Count()));//合并单元格 // 4.生成文件 FileStream file = new FileStream(filePath, FileMode.Create); workbook.Write(file); file.Close(); } catch (Exception ex) { throw ex; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { if (fs != null) fs.Close(); } fs = null; disposed = true; } } } }
读:
using (ExcelHelper excelHelper = new ExcelHelper(ConfigurationManager.AppSettings[\"ExcelFile\"])) { var dataTable = excelHelper.ExcelToDataTable(null, true); }
ConfigurationManager.AppSettings[\"ExcelFile\"]) 指文件位置 ExcelToDataTable(null, true); sheetName指Excel中每个Sheet的名字 isFirstRowColumn指第一行是否是列名
写:
ExcelHelper.CreateExcel(projectName); FileStream fs = new FileStream($\"{ConfigurationManager.AppSettings[\"file\"].ToString()}\\\\{projectName}.xlsx\", FileMode.Open, FileAccess.Read); IWorkbook workbook = new XSSFWorkbook(fs); for (int i = 0; i < Sheet.Count; i++) { var Srarch = data.Where(a => a.Sheet == Sheet[i]).ToList(); DataTable dataTable = new DataTable(); dataTable.Columns.Add(\"Template\"); dataTable.Columns.Add(\"Code\"); dataTable.Columns.Add(\"ZH_CN\"); dataTable.Columns.Add(\"De ion\"); dataTable.Columns.Add(\"EN_US\"); dataTable.Columns.Add(\"ZH_TW\"); dataTable.Columns.Add(\"KO\"); dataTable.Columns.Add(\"ZH_HK\"); for (int a = 0; a < Srarch.Count; a++) { DataRow row = dataTable.NewRow(); row[0] = Srarch[a].Template; row[1] = Srarch[a].Code; row[2] = Srarch[a].ZH_CN; row[3] = Srarch[a].De ion; row[4] = Srarch[a].EN_US; row[5] = Srarch[a].ZH_TW; row[6] = Srarch[a].KO; row[7] = Srarch[a].ZH_HK; dataTable.Rows.Add(row); } dataTable.TableName = Sheet[i]; ISheet sheet = workbook.CreateSheet(dataTable.TableName); //表头 IRow row2 = sheet.CreateRow(0); for (int a = 0; a < dataTable.Columns.Count; a++) { ICell cell = row2.CreateCell(a); cell.SetCellValue(dataTable.Columns[a].ColumnName); } //数据 for (int a = 0; a < dataTable.Rows.Count; a++) { IRow row1 = sheet.CreateRow(a + 1); for (int j = 0; j < dataTable.Columns.Count; j++) { ICell cell = row1.CreateCell(j); cell.SetCellValue(dataTable.Rows[a][j].ToString()); } } } MemoryStream stream = new MemoryStream(); workbook.Write(stream); var buf = stream.ToArray(); //保存为Excel文件 using (FileStream fs1 = new FileStream($\"{ConfigurationManager.AppSettings[\"file\"].ToString()}\\\\{projectName}.xlsx\", FileMode.Open, FileAccess.Write)) { fs1.Write(buf, 0, buf.Length); fs1.Flush(); }
ExcelHelper.CreateExcel(projectName);
创建Excel ,projectName 是Excel名字,路径默认是解决方案下File文件夹
两个For循环,第一个循环是创建列名,第二个循环是创建列下字段的内容
当然这只是创建Datatable
所以后面还有两个循环 将每个TABLE中列名放到Excel中的Sheet.以及内容
最后fs1.Write写入Excel
RabbitMQ
是一种应用程序对应用程序的通信方法
举个例子
前端站点向服务站点发起请求。一般服务站点要考虑到并发和数据总量保持运行稳定.
如果前端的请求发送到Rabbit并做持久化.服务端隔段时间批量响应请求。就大大减少了服务站点的压力
接下来的栗子就是A站点向Rabbit发消息并走入队列.然后B站点拉取消息并回应,至于隔多久取,一次取多少条.这部分就没做限制(计数就好).
下面是A站点
ConnectionFactory factory = new ConnectionFactory(); factory.HostName = \"127.0.0.1\"; //默认端口 factory.Port = 5672; factory.UserName = \"guest\";//用户名 factory.Password = \"guest\";//密码 using (IConnection conn = factory.CreateConnection()) { using (IModel channel = conn.CreateModel()) { //在MQ上定义一个持久化队列,如果名称相同不会重复创建 channel.QueueDeclare(\"MQTest\", true, false, false, null); while (true) { string message = string.Format(\"Message_{0}\", Console.ReadLine()); byte[] buffer = Encoding.UTF8.GetBytes(message); IBasicProperties properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; channel.BasicPublish(\"\", \"MQTest\", properties, buffer); Console.WriteLine(\"消息发送成功:\" + message); } } }
消息在Rabbit中.A接触Rabbit,B接触Rabbit.
最终是AB交互.但是过程相互不接触
ConnectionFactory factory = new ConnectionFactory(); factory.HostName = \"127.0.0.1\"; //默认端口 factory.Port = 5672; factory.UserName = \"guest\";//用户名 factory.Password = \"guest\";//密码 using (IConnection conn = factory.CreateConnection()) { using (IModel channel = conn.CreateModel()) { //在MQ上定义一个持久化队列,如果名称相同不会重复创建 channel.QueueDeclare(\"MQTest\", true, false, false, null); //输入1,那如果接收一个消息,但是没有应答,则客户端不会收到下一个消息 channel.BasicQos(0, 1, false); Console.WriteLine(\"Listening...\"); //在队列上定义一个消费者 QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel); //消费队列,并设置应答模式为程序主动应答 channel.BasicConsume(\"MQTest\", false, consumer); while (true) { //阻塞函数,获取队列中的消息 BasicDeliverEventArgs ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue(); byte[] bytes = ea.Body; string str = Encoding.UTF8.GetString(bytes); Console.WriteLine(\"队列消息:\" + str.ToString()); //回复确认 channel.BasicAck(ea.DeliveryTag, false); } } }
EF
像这个被大家用的滚瓜烂熟的框架.我这会拿出来说似乎有点小儿科.不过我就是要写(还写得贼简单)
Nuget中引入EF
自定义DbContext继承DbContext
public class HotelDbContext : DbContext { public HotelDbContext() : (\"name=ConnCodeFirst\") { Data .SetInitializer(new MigrateData ToLatestVersion<HotelDbContext, Configuration>(\"ConnCodeFirst\")); } public DbSet<TSM_Admin1111111111111> TSM_Admin { get; set; } }
ConnCodeFirst 是数据库连接字符串
Configuration 如下
internal sealed class Configuration : DbMigrationsConfiguration<HotelDbContext> { public Configuration() { // 自动迁移 TRUE code frist AutomaticMigrationsEnabled = true; } protected override void Seed(HotelDbContext context) { context.TSM_Admin.AddOrUpdate( p => p.UserID, new TSM_Admin1111111111111 { UserID = \"1\", UserName = \"111\" }, new TSM_Admin1111111111111 { UserID = \"2\", UserName = \"222\" }, new TSM_Admin1111111111111 { UserID = \"3\", UserName = \"333\" } ); } }
AutomaticMigrationsEnabled 意思就是找不到数据库的时候自动创建数据库。顺带还会创建初始数据(表和数据)。在Seed中
说真的很鸡肋.用的很想骂街
接下来是EF的各种使用方式。。婴儿教学版
new Configuration(); using (var data = new HotelDbContext()) { //查询.全表 var a = data.TSM_Admin.ToList(); //插入 data.TSM_Admin.Add(new TSM_Admin1111111111111 { UserID = \"高1030测试\" }); data.SaveChanges(); //修改 var model = data.TSM_Admin.Where(b => b.UserID == \"高1030测试\").First(); if (model != null) { model.UserName = \"高1030测试名字\"; data.Entry<TSM_Admin1111111111111>(model).State = System.Data.Entity.EntityState.Modified; data.SaveChanges(); } //删除 var delete = data.TSM_Admin.Where(b => b.UserID == \"高1030测试\").First(); if (delete != null) { var result = data.TSM_Admin.Where(b => b.UserID == delete.UserID).FirstOrDefault(); data.TSM_Admin.Remove(result); data.SaveChanges(); } var select = data.Data .SqlQuery<TSM_Admin1111111111111>(\"select * from tsm_123 \").ToList(); var insert = data.Data .ExecuteSqlCommand(\"insert into TSM_Admin(UserID) values(\'高1030测试\')\"); }
能用Dapper。就别用EF..
Attribute。
很多人都梦想着自定义属于自己的属性.那么
我用双手成就你的梦想
StringLength是自定义属性的名字Attribute是必须加上去的。并且在使用中会被忽视
[AttributeUsage(AttributeTargets.Property)] public class StringLengthAttribute : Attribute { private int _maximumLength; public StringLengthAttribute(int maximumLength) { _maximumLength = maximumLength; } public int MaximumLength { get { return _maximumLength; } } }
接下来定义使用的实体
public class People { [StringLength(8)] public string Name { get; set; } [StringLength(15)] public string De ion { get; set; } }
接下来定义获取属性内容的方法
public class ValidationModel { public void Validate( obj) { var t = obj.GetType(); //由于我们只在Property设置了Attibute,所以先获取Property var properties = t.GetProperties(); foreach (var property in properties) { //这里只做一个stringlength的验证,这里如果要做很多验证,需要好好设计一下,千万不要用if elseif去链接 //会非常难于维护,类似这样的开源项目很多,有兴趣可以去看源码。 if (!property.IsDefined(typeof(StringLengthAttribute), false)) continue; var attributes = property.GetCustomAttributes(false); foreach (var attribute in attributes) { //这里的MaximumLength 最好用常量去做 var maxinumLength = (int)attribute.GetType(). GetProperty(\"MaximumLength\"). GetValue(attribute); //获取属性的值 var propertyValue = property.GetValue(obj) as string; if (propertyValue == null) throw new Exception(\"exception info\");//这里可以自定义,也可以用具体系统异常类 if (propertyValue.Length > maxinumLength) throw new Exception(string.Format(\"属性{0}的值{1}的长度超过了{2}\", property.Name, propertyValue, maxinumLength)); } } } }
接下来是调用过程
var people = new People() { Name = \"qweasdzxcasdqweasdzxc\", De ion = \"de ion\" }; try { new ValidationModel().Validate(people); } catch (Exception ex) { Console.WriteLine(ex.Message); }
这个段子充分解释了如何使用自定义Attribute
核心思想是万物皆可supreme
HttpRuntime.Cache
开发中很多不常改动的数据。可以考虑将数据从数据库里取出来后的指定时间内存在本地内存中
using System; using System.Web; using System.Web.Caching; namespace Chinamoney.Core { public class CacheHelper { /// <summary> /// 获取数据缓存 /// </summary> /// <param name=\"cacheKey\">键</param> public static GetCache(string cacheKey) { var objCache = HttpRuntime.Cache.Get(cacheKey); return objCache; } /// <summary> /// 设置数据缓存 /// </summary> public static void SetCache(string cacheKey, obj ) { var objCache = HttpRuntime.Cache; objCache.Insert(cacheKey, obj ); } /// <summary> /// 设置数据缓存 /// </summary> public static void SetCache(string cacheKey, obj , int Hours) { try { if (obj == null) return; var objCache = HttpRuntime.Cache; //相对过期 //objCache.Insert(cacheKey, obj , null, DateTime.MaxValue, timeout, CacheItemPriority.NotRemovable, null); //绝对过期时间 objCache.Insert(cacheKey, obj , null, DateTime.Now.AddHours(Hours), TimeSpan.Zero, CacheItemPriority.High, null); } catch (Exception e) { Log.Logger.Log(\"缓存写入异常:\",e); } } /// <summary> /// 移除指定数据缓存 /// </summary> public static void RemoveAllCache(string cacheKey) { var cache = HttpRuntime.Cache; cache.Remove(cacheKey); } /// <summary> /// 移除全部缓存 /// </summary> public static void RemoveAllCache() { var cache = HttpRuntime.Cache; var cacheEnum = cache.GetEnumerator(); while (cacheEnum.MoveNext()) { cache.Remove(cacheEnum.Key.ToString()); } } } }
读取
CacheHelper.GetCache(\"cacheExtraterritorial\") as List<ExtraterritorialDataEntity>;
写入
CacheHelper.SetCache(\"cacheExtraterritorial继续阅读与本文标签相同的文章
人工智能AI(1)开篇:小白之学习计划
ODOO优化层级关系查询效率的方法
-
Serverless Kubernetes全面升级2.0架构:支持多命名空间、RBAC、CRD、PV/PVC等功能
2026-05-19栏目: 教程
-
6个常见的高并发缓存问题,你知道几个?
2026-05-19栏目: 教程
-
再有人问你ThreadLocal,就把这篇文章扔给他
2026-05-19栏目: 教程
-
RocketMQ消费失败消息深入分析(consumer,broker的具体处理逻辑)
2026-05-19栏目: 教程
-
RocketMQ消费失败重试机制分析
2026-05-19栏目: 教程
