当前位置: 首页 > news >正文

.NET Core 实现Excel的导入导出

.NET Core 使用NPOI实现Excel的导入导出

  • 前言
  • NPOI简介
  • 一、安装相对应的程序包
    • 1.1、在 “管理NuGet程序包” 中的浏览搜索:“NPOI”
  • 二、新建Excel帮助类
  • 三、调用
    • 3.1、增加一个“keywords”模型类,用作导出
    • 3.2、添加一个控制器
    • 3.3、编写导入导出的控制器代码
      • 3.3.1、重写“Close”函数
      • 3.3.2、添加控制器代码
      • 3.3.3、Excel导出效果
      • 3.3.4、Excel导入效果

前言

我们在日常开发中对Excel的操作可能会比较频繁,好多功能都会涉及到Excel的操作。在.Net Core中大家可能使用Npoi比较多,这款软件功能也十分强大,而且接近原始编程。但是直接使用Npoi大部分时候我们可能都会自己封装一下,毕竟根据二八原则,我们百分之八十的场景可能都是进行简单的导入导出操作,这里就引出我们的主角Npoi。

NPOI简介

NPOI是指构建在POI 3.x版本之上的一个程序,NPOI可以在没有安装Office的情况下对Word或Excel文档进行读写操作。NPOI是一个开源的C#读写Excel、WORD等微软OLE2组件文档的项目。

一、安装相对应的程序包

在 .Net Core 中使用NPOI首先必须先安装NPOI;如下图所示:
右键项目,选择“管理 NuGet 程序包”菜单

1.1、在 “管理NuGet程序包” 中的浏览搜索:“NPOI”

相关安装包的安装
点击安装以上两个即可,安装完成之后最好重新编译一下项目以防出错

二、新建Excel帮助类

在项目中新建“ExcelHelper”类;此类用于封装导入导出以及其他配置方法。代码如下:

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using NPOI;
using System.Text;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.SS.Formula.Eval;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Collections;
using NPOI.HSSF.Util;namespace WebApplication1 //命名空间依据自己的项目进行修改
{/// <summary>/// Excel帮助类/// 功能:///   1、导出数据到Excel文件中///   2、将Excel文件的数据导入到List<T>对象集合中/// </summary>public static class ExcelHelper{/// <summary>/// 导出列名/// </summary>public static SortedList ListColumnsName;#region 从DataTable导出到excel文件中,支持xls和xlsx格式#region 导出为xls文件内部方法/// <summary>/// 从DataTable 中导出到excel/// </summary>/// <param name="strFileName">excel文件名</param>/// <param name="dtSource">datatabe源数据</param>/// <param name="strHeaderText">表名</param>/// <param name="sheetnum">sheet的编号</param>/// <returns></returns>static MemoryStream ExportDT(string strFileName, DataTable dtSource, string strHeaderText, Dictionary<string, string> dir, int sheetnum){//创建工作簿和sheetIWorkbook workbook = new HSSFWorkbook();using (Stream writefile = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Read)){if (writefile.Length > 0 && sheetnum > 0){workbook = WorkbookFactory.Create(writefile);}}ISheet sheet = null;ICellStyle dateStyle = workbook.CreateCellStyle();IDataFormat format = workbook.CreateDataFormat();dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");int[] arrColWidth = new int[dtSource.Columns.Count];foreach (DataColumn item in dtSource.Columns){arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(Convert.ToString(item.ColumnName)).Length;}for (int i = 0; i < dtSource.Rows.Count; i++){for (int j = 0; j < dtSource.Columns.Count; j++){int intTemp = Encoding.GetEncoding(936).GetBytes(Convert.ToString(dtSource.Rows[i][j])).Length;if (intTemp > arrColWidth[j]){arrColWidth[j] = intTemp;}}}int rowIndex = 0;foreach (DataRow row in dtSource.Rows){#region 新建表,填充表头,填充列头,样式if (rowIndex == 0){string sheetName = strHeaderText + (sheetnum == 0 ? "" : sheetnum.ToString());if (workbook.GetSheetIndex(sheetName) >= 0){workbook.RemoveSheetAt(workbook.GetSheetIndex(sheetName));}sheet = workbook.CreateSheet(sheetName);#region 表头及样式{sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1));IRow headerRow = sheet.CreateRow(0);headerRow.HeightInPoints = 25;headerRow.CreateCell(0).SetCellValue(strHeaderText);ICellStyle headStyle = workbook.CreateCellStyle();headStyle.Alignment = HorizontalAlignment.Center;IFont font = workbook.CreateFont();font.FontHeightInPoints = 20;font.Boldweight = 700;headStyle.SetFont(font);headerRow.GetCell(0).CellStyle = headStyle;rowIndex = 1;}#endregion#region 列头及样式if (rowIndex == 1){IRow headerRow = sheet.CreateRow(1);//第二行设置列名ICellStyle headStyle = workbook.CreateCellStyle();headStyle.Alignment = HorizontalAlignment.Center;IFont font = workbook.CreateFont();font.FontHeightInPoints = 10;font.Boldweight = 700;headStyle.SetFont(font);//写入列标题foreach (DataColumn column in dtSource.Columns){headerRow.CreateCell(column.Ordinal).SetCellValue(dir[column.ColumnName]);headerRow.GetCell(column.Ordinal).CellStyle = headStyle;//设置列宽sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256 * 2);}rowIndex = 2;}#endregion}#endregion#region 填充内容IRow dataRow = sheet.CreateRow(rowIndex);foreach (DataColumn column in dtSource.Columns){NPOI.SS.UserModel.ICell newCell = dataRow.CreateCell(column.Ordinal);string drValue = row[column].ToString();switch (column.DataType.ToString()){case "System.String": //字符串类型double result;if (isNumeric(drValue, out result)){//数字字符串double.TryParse(drValue, out result);newCell.SetCellValue(result);break;}else{newCell.SetCellValue(drValue);break;}case "System.DateTime": //日期类型DateTime dateV;DateTime.TryParse(drValue, out dateV);newCell.SetCellValue(dateV);newCell.CellStyle = dateStyle; //格式化显示break;case "System.Boolean": //布尔型bool boolV = false;bool.TryParse(drValue, out boolV);newCell.SetCellValue(boolV);break;case "System.Int16": //整型case "System.Int32":case "System.Int64":case "System.Byte":int intV = 0;int.TryParse(drValue, out intV);newCell.SetCellValue(intV);break;case "System.Decimal": //浮点型case "System.Double":double doubV = 0;double.TryParse(drValue, out doubV);newCell.SetCellValue(doubV);break;case "System.DBNull": //空值处理newCell.SetCellValue("");break;default:newCell.SetCellValue(drValue.ToString());break;}}#endregionrowIndex++;}using (MemoryStream ms = new MemoryStream()){workbook.Write(ms, true);ms.Flush();ms.Position = 0;return ms;}}#endregion#region 导出为xlsx文件内部方法/// <summary>/// 从DataTable 中导出到excel/// </summary>/// <param name="dtSource">DataTable数据源</param>/// <param name="strHeaderText">表名</param>/// <param name="fs">文件流</param>/// <param name="readfs">内存流</param>/// <param name="sheetnum">sheet索引</param>static void ExportDTI(DataTable dtSource, string strHeaderText, FileStream fs, MemoryStream readfs, Dictionary<string, string> dir, int sheetnum){IWorkbook workbook = new XSSFWorkbook();if (readfs.Length > 0 && sheetnum > 0){workbook = WorkbookFactory.Create(readfs);}ISheet sheet = null;ICellStyle dateStyle = workbook.CreateCellStyle();IDataFormat format = workbook.CreateDataFormat();dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");//取得列宽int[] arrColWidth = new int[dtSource.Columns.Count];foreach (DataColumn item in dtSource.Columns){arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(Convert.ToString(item.ColumnName)).Length;}for (int i = 0; i < dtSource.Rows.Count; i++){for (int j = 0; j < dtSource.Columns.Count; j++){int intTemp = Encoding.GetEncoding(936).GetBytes(Convert.ToString(dtSource.Rows[i][j])).Length;if (intTemp > arrColWidth[j]){arrColWidth[j] = intTemp;}}}int rowIndex = 0;foreach (DataRow row in dtSource.Rows){#region 新建表,填充表头,填充列头,样式if (rowIndex == 0){#region 表头及样式{string sheetName = strHeaderText + (sheetnum == 0 ? "" : sheetnum.ToString());if (workbook.GetSheetIndex(sheetName) >= 0){workbook.RemoveSheetAt(workbook.GetSheetIndex(sheetName));}sheet = workbook.CreateSheet(sheetName);sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1));IRow headerRow = sheet.CreateRow(0);headerRow.HeightInPoints = 25;headerRow.CreateCell(0).SetCellValue(strHeaderText);ICellStyle headStyle = workbook.CreateCellStyle();headStyle.Alignment = HorizontalAlignment.Center;IFont font = workbook.CreateFont();font.FontHeightInPoints = 20;font.Boldweight = 700;headStyle.SetFont(font);headerRow.GetCell(0).CellStyle = headStyle;}#endregion#region 列头及样式{IRow headerRow = sheet.CreateRow(1);ICellStyle headStyle = workbook.CreateCellStyle();headStyle.Alignment = HorizontalAlignment.Center;IFont font = workbook.CreateFont();font.FontHeightInPoints = 10;font.Boldweight = 700;headStyle.SetFont(font);foreach (DataColumn column in dtSource.Columns){headerRow.CreateCell(column.Ordinal).SetCellValue(dir[column.ColumnName]);headerRow.GetCell(column.Ordinal).CellStyle = headStyle;//设置列宽sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256 * 2);}}#endregionrowIndex = 2;}#endregion#region 填充内容IRow dataRow = sheet.CreateRow(rowIndex);foreach (DataColumn column in dtSource.Columns){NPOI.SS.UserModel.ICell newCell = dataRow.CreateCell(column.Ordinal);string drValue = row[column].ToString();switch (column.DataType.ToString()){case "System.String": //字符串类型double result;if (isNumeric(drValue, out result)){double.TryParse(drValue, out result);newCell.SetCellValue(result);break;}else{newCell.SetCellValue(drValue);break;}case "System.DateTime": //日期类型DateTime dateV;DateTime.TryParse(drValue, out dateV);newCell.SetCellValue(dateV);newCell.CellStyle = dateStyle; //格式化显示break;case "System.Boolean": //布尔型bool boolV = false;bool.TryParse(drValue, out boolV);newCell.SetCellValue(boolV);break;case "System.Int16": //整型case "System.Int32":case "System.Int64":case "System.Byte":int intV = 0;int.TryParse(drValue, out intV);newCell.SetCellValue(intV);break;case "System.Decimal": //浮点型case "System.Double":double doubV = 0;double.TryParse(drValue, out doubV);newCell.SetCellValue(doubV);break;case "System.DBNull": //空值处理newCell.SetCellValue("");break;default:newCell.SetCellValue(drValue.ToString());break;}}#endregionrowIndex++;}workbook.Write(fs,true);fs.Close();}#endregion#region 导出excel表格/// <summary>///  DataTable导出到Excel文件,xls文件/// </summary>/// <param name="dtSource">数据源</param>/// <param name="strHeaderText">表名</param>/// <param name="strFileName">excel文件名</param>/// <param name="dir">DataTable和excel列名对应字典</param>/// <param name="sheetRow">每个sheet存放的行数</param>public static void ExportDTtoExcel(DataTable dtSource, string strHeaderText, string strFileName, Dictionary<string, string> dir, bool isNew, int sheetRow = 50000){int currentSheetCount = GetSheetNumber(strFileName);//现有的页数sheetnumif (sheetRow <= 0){sheetRow = dtSource.Rows.Count;}string[] temp = strFileName.Split('.');string fileExtens = temp[temp.Length - 1];int sheetCount = (int)Math.Ceiling((double)dtSource.Rows.Count / sheetRow);//sheet数目if (temp[temp.Length - 1] == "xls" && dtSource.Columns.Count < 256 && sheetRow < 65536){if (isNew){currentSheetCount = 0;}for (int i = currentSheetCount; i < currentSheetCount + sheetCount; i++){DataTable pageDataTable = dtSource.Clone();int hasRowCount = dtSource.Rows.Count - sheetRow * (i - currentSheetCount) < sheetRow ? dtSource.Rows.Count - sheetRow * (i - currentSheetCount) : sheetRow;for (int j = 0; j < hasRowCount; j++){pageDataTable.ImportRow(dtSource.Rows[(i - currentSheetCount) * sheetRow + j]);}using (MemoryStream ms = ExportDT(strFileName, pageDataTable, strHeaderText, dir, i)){using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)){byte[] data = ms.ToArray();fs.Write(data, 0, data.Length);fs.Flush();}}}}else{if (temp[temp.Length - 1] == "xls")strFileName = strFileName + "x";if (isNew){currentSheetCount = 0;}for (int i = currentSheetCount; i < currentSheetCount + sheetCount; i++){DataTable pageDataTable = dtSource.Clone();int hasRowCount = dtSource.Rows.Count - sheetRow * (i - currentSheetCount) < sheetRow ? dtSource.Rows.Count - sheetRow * (i - currentSheetCount) : sheetRow;for (int j = 0; j < hasRowCount; j++){pageDataTable.ImportRow(dtSource.Rows[(i - currentSheetCount) * sheetRow + j]);}FileStream readfs = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Read);MemoryStream readfsm = new MemoryStream();readfs.CopyTo(readfsm);readfs.Close();using (FileStream writefs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)){ExportDTI(pageDataTable, strHeaderText, writefs, readfsm, dir, i);}readfsm.Close();}}}/// <summary>/// 导出Excel(//超出10000条数据 创建新的工作簿)/// </summary>/// <param name="dtSource">数据源</param>/// <param name="dir">导出Excel表格的字段名和列名的字符串字典实例;例如:dir.Add("IllegalKeywords", "姓名");</param>public static XSSFWorkbook ExportExcel(DataTable dtSource, Dictionary<string, string> dir){XSSFWorkbook excelWorkbook = new XSSFWorkbook();//int columnsCount = columnsNames.GetLength(0);int columnsCount = dir.Count;if (columnsCount > 0){ListColumnsName = new SortedList(new NoSort());//for (int i = 0; i < columnsCount; i++)//{//    ListColumnsName.Add(columnsNames[i, 0], columnsNames[i, 1]);//}foreach (KeyValuePair<string,string> item in dir){ListColumnsName.Add(item.Key, item.Value);}if (ListColumnsName == null || ListColumnsName.Count == 0){throw (new Exception("请对ListColumnsName设置要导出的列明!"));}else{excelWorkbook = InsertRow(dtSource);}}else{throw (new Exception("请对ListColumnsName设置要导出的列明!"));}return excelWorkbook;}#endregion/// <summary>/// 创建Excel文件/// </summary>/// <param name="filePath"></param>private static XSSFWorkbook CreateExcelFile(){XSSFWorkbook xssfworkbook = new XSSFWorkbook();//右击文件“属性”信息#region 文件属性信息{POIXMLProperties props = xssfworkbook.GetProperties();props.CoreProperties.Creator = "Joy";//Excel文件的创建作者props.CoreProperties.Title = "";//Excel文件标题props.CoreProperties.Description = "";//Excel文件备注props.CoreProperties.Category = "";//Excel文件类别信息props.CoreProperties.Subject = "";//Excel文件主题信息props.CoreProperties.Created = DateTime.Now;//Excel文件创建时间props.CoreProperties.Modified = DateTime.Now;//Excel文件修改时间props.CoreProperties.SetCreated(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));props.CoreProperties.LastModifiedByUser = "Joy";//Excel文件最后一次保存者props.CoreProperties.SetModified(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));//Excel文件最后一次保存日期}#endregionreturn xssfworkbook;}/// <summary>/// 创建excel表头/// </summary>/// <param name="dgv"></param>/// <param name="excelSheet"></param>private static void CreateHeader(XSSFSheet excelSheet, XSSFWorkbook excelWorkbook, XSSFCellStyle cellStyle){int cellIndex = 0;//循环导出列foreach (System.Collections.DictionaryEntry de in ListColumnsName){XSSFRow newRow = (XSSFRow)excelSheet.CreateRow(0);XSSFCellStyle? headTopStyle = CreateStyle(excelWorkbook, cellStyle,HorizontalAlignment.Center, VerticalAlignment.Center, 18, true, true, "宋体", true, false, false, true, FillPattern.SolidForeground, HSSFColor.Grey25Percent.Index, HSSFColor.Black.Index,FontUnderlineType.None, FontSuperScript.None, false);XSSFCell newCell = (XSSFCell)newRow.CreateCell(cellIndex);newCell.SetCellValue(de.Value.ToString());newCell.CellStyle = headTopStyle;cellIndex++;}}/// <summary>/// 插入数据行/// </summary>private static XSSFWorkbook InsertRow(DataTable dtSource){XSSFWorkbook excelWorkbook = CreateExcelFile();int rowCount = 0;int sheetCount = 1;XSSFSheet newsheet = null;//循环数据源导出数据集newsheet = (XSSFSheet)excelWorkbook.CreateSheet("Sheet" + sheetCount);XSSFCellStyle headCellStyle = (XSSFCellStyle)excelWorkbook.CreateCellStyle(); //创建列头单元格实例样式CreateHeader(newsheet, excelWorkbook, headCellStyle);//单元格内容信息foreach (DataRow dr in dtSource.Rows){rowCount++;//超出10000条数据 创建新的工作簿if (rowCount == 10000){rowCount = 1;sheetCount++;newsheet = (XSSFSheet)excelWorkbook.CreateSheet("Sheet" + sheetCount);CreateHeader(newsheet, excelWorkbook, headCellStyle);}XSSFRow newRow = (XSSFRow)newsheet.CreateRow(rowCount);XSSFCellStyle cellStyle = (XSSFCellStyle)excelWorkbook.CreateCellStyle(); //创建单元格实例样式XSSFCellStyle? style = CreateStyle(excelWorkbook, cellStyle, HorizontalAlignment.Center, VerticalAlignment.Center, 14, true, false);InsertCell(dtSource, dr, newRow, style, excelWorkbook);}//自动列宽//for (int i = 0; i <= dtSource.Columns.Count; i++)//{//    newsheet.AutoSizeColumn(i, true);//}return excelWorkbook;}/// <summary>/// 导出数据行/// </summary>/// <param name="dtSource"></param>/// <param name="drSource"></param>/// <param name="currentExcelRow"></param>/// <param name="excelSheet"></param>/// <param name="excelWorkBook"></param>private static void InsertCell(DataTable dtSource, DataRow drSource, XSSFRow currentExcelRow, XSSFCellStyle cellStyle, XSSFWorkbook excelWorkBook){for (int cellIndex = 0; cellIndex < ListColumnsName.Count; cellIndex++){//列名称string columnsName = ListColumnsName.GetKey(cellIndex).ToString();XSSFCell newCell = null;System.Type rowType = drSource[columnsName].GetType();string drValue = drSource[columnsName].ToString().Trim();switch (rowType.ToString()){case "System.String"://字符串类型drValue = drValue.Replace("&", "&");drValue = drValue.Replace(">", ">");drValue = drValue.Replace("<", "<");newCell = (XSSFCell)currentExcelRow.CreateCell(cellIndex);newCell.SetCellValue(drValue);newCell.CellStyle = cellStyle;break;case "System.DateTime"://日期类型DateTime dateV;DateTime.TryParse(drValue, out dateV);newCell = (XSSFCell)currentExcelRow.CreateCell(cellIndex);newCell.SetCellValue(dateV);newCell.CellStyle = cellStyle;break;case "System.Boolean"://布尔型bool boolV = false;bool.TryParse(drValue, out boolV);newCell = (XSSFCell)currentExcelRow.CreateCell(cellIndex);newCell.SetCellValue(boolV);newCell.CellStyle = cellStyle;break;case "System.Int16"://整型case "System.Int32":case "System.Int64":case "System.Byte":int intV = 0;int.TryParse(drValue, out intV);newCell = (XSSFCell)currentExcelRow.CreateCell(cellIndex);newCell.SetCellValue(intV.ToString());newCell.CellStyle = cellStyle;break;case "System.Decimal"://浮点型case "System.Double":double doubV = 0;double.TryParse(drValue, out doubV);newCell = (XSSFCell)currentExcelRow.CreateCell(cellIndex);newCell.SetCellValue(doubV);newCell.CellStyle = cellStyle;break;case "System.DBNull"://空值处理newCell = (XSSFCell)currentExcelRow.CreateCell(cellIndex);newCell.SetCellValue("");newCell.CellStyle = cellStyle;break;default:throw (new Exception(rowType.ToString() + ":类型数据无法处理!"));}}}/// <summary>/// 行内单元格常用样式设置/// </summary>/// <param name="workbook">Excel文件对象</param>/// <param name="cellStyle">Excel文件中XSSFCellStyle对象</param>/// <param name="hAlignment">水平布局方式</param>/// <param name="vAlignment">垂直布局方式</param>/// <param name="fontHeightInPoints">字体大小</param>/// <param name="isAddBorder">是否需要边框</param>/// <param name="boldWeight">字体加粗 (None = 0,Normal = 400,Bold = 700</param>/// <param name="fontName">字体(仿宋,楷体,宋体,微软雅黑...与Excel主题字体相对应)</param>/// <param name="isAddBorderColor">是否增加边框颜色</param>/// <param name="isItalic">是否将文字变为斜体</param>/// <param name="isLineFeed">是否自动换行</param>/// <param name="isAddCellBackground">是否增加单元格背景颜色</param>/// <param name="fillPattern">填充图案样式(FineDots 细点,SolidForeground立体前景,isAddFillPattern=true时存在)</param>/// <param name="cellBackgroundColor">单元格背景颜色(当isAddCellBackground=true时存在)</param>/// <param name="fontColor">字体颜色</param>/// <param name="underlineStyle">下划线样式(无下划线[None],单下划线[Single],双下划线[Double],会计用单下划线[SingleAccounting],会计用双下划线[DoubleAccounting])</param>/// <param name="typeOffset">字体上标下标(普通默认值[None],上标[Sub],下标[Super]),即字体在单元格内的上下偏移量</param>/// <param name="isStrikeout">是否显示删除线</param>/// <param name="dataFormat">格式化日期显示</param>/// <returns></returns>public static XSSFCellStyle CreateStyle(XSSFWorkbook workbook, XSSFCellStyle cellStyle, HorizontalAlignment hAlignment, VerticalAlignment vAlignment, short fontHeightInPoints, bool isAddBorder, bool boldWeight, string fontName = "宋体", bool isAddBorderColor = true, bool isItalic = false, bool isLineFeed = true, 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,string dataFormat="yyyy-MM-dd HH:mm:ss"){cellStyle.Alignment = hAlignment; //水平居中cellStyle.VerticalAlignment = vAlignment; //垂直居中cellStyle.WrapText = isLineFeed;//自动换行//格式化显示XSSFDataFormat format = (XSSFDataFormat)workbook.CreateDataFormat();cellStyle.DataFormat = format.GetFormat(dataFormat);//背景颜色,边框颜色,字体颜色都是使用 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立体前景)}else{cellStyle.FillForegroundColor = HSSFColor.White.Index;//单元格背景颜色}//是否增加边框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 = XSSFFont.DEFAULT_FONT_COLOR;//DarkGreen(黑绿色)cellStyle.RightBorderColor = XSSFFont.DEFAULT_FONT_COLOR;cellStyle.BottomBorderColor = XSSFFont.DEFAULT_FONT_COLOR;cellStyle.LeftBorderColor = XSSFFont.DEFAULT_FONT_COLOR;}/*** 设置相关字体样式*/var cellStyleFont = (XSSFFont)workbook.CreateFont(); //创建字体//假如字体大小只需要是粗体的话直接使用下面该属性即可//cellStyleFont.IsBold = true;cellStyleFont.IsBold = 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;}#endregion#region 从excel文件中将数据导出到List<T>对象集合/// <summary>/// 将制定sheet中的数据导出到DataTable中/// </summary>/// <param name="sheet">需要导出的sheet</param>/// <param name="HeaderRowIndex">列头所在行号,-1表示没有列头</param>/// <param name="dir">excel列名和DataTable列名的对应字典</param>/// <returns></returns>static DataTable ImportDt(ISheet sheet, int HeaderRowIndex, Dictionary<string, string> dir){DataTable table = new DataTable();IRow headerRow;int cellCount;try{//没有标头或者不需要表头用excel列的序号(1,2,3..)作为DataTable的列名if (HeaderRowIndex < 0){headerRow = sheet.GetRow(0);cellCount = headerRow.LastCellNum;for (int i = headerRow.FirstCellNum; i <= cellCount; i++){DataColumn column = new DataColumn(Convert.ToString(i));table.Columns.Add(column);}}//有表头,使用表头做为DataTable的列名else{headerRow = sheet.GetRow(HeaderRowIndex);cellCount = headerRow.LastCellNum;for (int i = headerRow.FirstCellNum; i <cellCount; i++){//如果excel某一列列名不存在:以该列的序号作为DataTable的列名,如果DataTable中包含了这个序列为名的列,那么列名为重复列名+序号if (headerRow.GetCell(i) == null){if (table.Columns.IndexOf(Convert.ToString(i)) > 0){DataColumn column = new DataColumn(Convert.ToString("重复列名" + i));table.Columns.Add(column);}else{DataColumn column = new DataColumn(Convert.ToString(i));table.Columns.Add(column);}}//excel中的某一列列名不为空,但是重复了:对应的DataTable列名为“重复列名+序号”else if (table.Columns.IndexOf(headerRow.GetCell(i).ToString()) > 0){DataColumn column = new DataColumn(Convert.ToString("重复列名" + i));table.Columns.Add(column);}else//正常情况,列名存在且不重复:用excel中的列名作为DataTable中对应的列名{string aaa = headerRow.GetCell(i).ToString();string colName = dir.Where(s => s.Value == headerRow.GetCell(i).ToString()).First().Key;DataColumn column = new DataColumn(colName);table.Columns.Add(column);}}}int rowCount = sheet.LastRowNum;for (int i = (HeaderRowIndex + 1); i <= sheet.LastRowNum; i++)//excel行遍历{try{IRow row;if (sheet.GetRow(i) == null)//如果excel有空行,则添加缺失的行{row = sheet.CreateRow(i);}else{row = sheet.GetRow(i);}DataRow dataRow = table.NewRow();for (int j = row.FirstCellNum; j <= cellCount; j++)//excel列遍历{try{if (row.GetCell(j) != null){switch (row.GetCell(j).CellType){case CellType.String://字符串string str = row.GetCell(j).StringCellValue;if (str != null && str.Length > 0){dataRow[j] = str.ToString();}else{dataRow[j] = default(string);}break;case CellType.Numeric://数字if (DateUtil.IsCellDateFormatted(row.GetCell(j)))//时间戳数字{dataRow[j] = DateTime.FromOADate(row.GetCell(j).NumericCellValue);}else{dataRow[j] = Convert.ToDouble(row.GetCell(j).NumericCellValue);}break;case CellType.Boolean:dataRow[j] = Convert.ToString(row.GetCell(j).BooleanCellValue);break;case CellType.Error:dataRow[j] = ErrorEval.GetText(row.GetCell(j).ErrorCellValue);break;case CellType.Formula://公式switch (row.GetCell(j).CachedFormulaResultType){case CellType.String:string strFORMULA = row.GetCell(j).StringCellValue;if (strFORMULA != null && strFORMULA.Length > 0){dataRow[j] = strFORMULA.ToString();}else{dataRow[j] = null;}break;case CellType.Numeric:dataRow[j] = Convert.ToString(row.GetCell(j).NumericCellValue);break;case CellType.Boolean:dataRow[j] = Convert.ToString(row.GetCell(j).BooleanCellValue);break;case CellType.Error:dataRow[j] = ErrorEval.GetText(row.GetCell(j).ErrorCellValue);break;default:dataRow[j] = "";break;}break;default:dataRow[j] = "";break;}}}catch (Exception exception){//loger.Error(exception.ToString());}}table.Rows.Add(dataRow);}catch (Exception exception){//loger.Error(exception.ToString());}}}catch (Exception exception){//loger.Error(exception.ToString());}return table;}/// <summary>/// DataTable 转换为List<T>对象集合/// </summary>/// <typeparam name="TResult">类型</typeparam>/// <param name="dt">DataTable</param>/// <returns></returns>public static List<TResult> DataTableToList<TResult>(this DataTable dt) where TResult : class, new(){//创建一个属性的列表List<PropertyInfo> prlist = new List<PropertyInfo>();//获取TResult的类型实例  反射的入口Type t = typeof(TResult);//获得TResult 的所有的Public 属性 并找出TResult属性和DataTable的列名称相同的属性(PropertyInfo) 并加入到属性列表Array.ForEach<PropertyInfo>(t.GetProperties(), p => { if (dt.Columns.IndexOf(p.Name) != -1) prlist.Add(p); });//创建返回的集合List<TResult> oblist = new List<TResult>();foreach (DataRow row in dt.Rows){//创建TResult的实例TResult ob = new TResult();//找到对应的数据  并赋值prlist.ForEach(p => { if (row[p.Name] != DBNull.Value) p.SetValue(ob, row[p.Name], null); });//放入到返回的集合中.oblist.Add(ob);}return oblist;}/// <summary>/// DataTable转化为List集合/// </summary>/// <typeparam name="T">实体对象</typeparam>/// <param name="dt">datatable表</param>/// <param name="isStoreDB">是否存入数据库datetime字段,date字段没事,取出不用判断</param>/// <returns>返回list集合</returns>private static List<T> DataTableToList<T>(DataTable dt, bool isStoreDB = true){List<T> list = new List<T>();Type type = typeof(T);//List<string> listColums = new List<string>();PropertyInfo[] pArray = type.GetProperties(); //集合属性数组foreach (DataRow row in dt.Rows){T entity = Activator.CreateInstance<T>(); //新建对象实例 foreach (PropertyInfo p in pArray){if (!dt.Columns.Contains(p.Name) || row[p.Name] == null || row[p.Name] == DBNull.Value){continue;  //DataTable列中不存在集合属性或者字段内容为空则,跳出循环,进行下个循环   }if (isStoreDB && p.PropertyType == typeof(DateTime) && Convert.ToDateTime(row[p.Name]) < Convert.ToDateTime("1753-01-01")){continue;}try{var obj = Convert.ChangeType(row[p.Name], p.PropertyType);//类型强转,将table字段类型转为集合字段类型  p.SetValue(entity, obj, null);}catch (Exception){// throw;}             }list.Add(entity);}return list;}/// <summary>/// DataSet 转换成List/// </summary>/// <typeparam name="T"></typeparam>/// <param name="ds"></param>/// <param name="tableIndext"></param>/// <returns></returns>private static List<T> DataTable2List<T>(DataTable dt){//确认参数有效 if (dt == null || dt.Rows.Count <= 0){return null;}IList<T> list = new List<T>(); //实例化一个list // 在这里写 获取T类型的所有公有属性。 注意这里仅仅是获取T类型的公有属性,不是公有方法,也不是公有字段,当然也不是私有属性 PropertyInfo[] tMembersAll = typeof(T).GetProperties();for (int i = 0; i < dt.Rows.Count; i++){//创建泛型对象。为什么这里要创建一个泛型对象呢?是因为目前我不确定泛型的类型。 T t = Activator.CreateInstance<T>();//获取t对象类型的所有公有属性。但是我不建议吧这条语句写在for循环里,因为没循环一次就要获取一次,占用资源,所以建议写在外面 //PropertyInfo[] tMembersAll = t.GetType().GetProperties();for (int j = 0; j < dt.Columns.Count; j++){//遍历tMembersAll foreach (PropertyInfo tMember in tMembersAll){//取dt表中j列的名字,并把名字转换成大写的字母。整条代码的意思是:如果列名和属性名称相同时赋值 if (dt.Columns[j].ColumnName.ToUpper().Equals(tMember.Name.ToUpper())){//dt.Rows[i][j]表示取dt表里的第i行的第j列;DBNull是指数据库中当一个字段没有被设置值的时候的值,相当于数据库中的“空值”。 if (dt.Rows[i][j] != DBNull.Value){//SetValue是指:将指定属性设置为指定值。 tMember是T泛型对象t的一个公有成员,整条代码的意思就是:将dt.Rows[i][j]赋值给t对象的tMember成员,参数详情请参照http://msdn.microsoft.com/zh-cn/library/3z2t396t(v=vs.100).aspx/htmltMember.SetValue(t, Convert.ToString(dt.Rows[i][j]), null);}else{tMember.SetValue(t, null, null);}break;//注意这里的break是写在if语句里面的,意思就是说如果列名和属性名称相同并且已经赋值了,那么我就跳出foreach循环,进行j+1的下次循环 }}}list.Add(t);}dt.Dispose();return list.ToList();}/// <summary>/// 读取Excel文件特定名字sheet的内容到List<T>对象集合/// </summary>/// <param name="strFileName">excel文件路径</param>/// <param name="dir">excel列名和DataTable列名的对应字典</param>/// <param name="SheetName">excel表名</param>/// <param name="HeaderRowIndex">列头所在行号,-1表示没有列头</param>/// <returns></returns>public static List<T> ImportExceltoDt<T>(string strFileName, Dictionary<string, string> dir, string SheetName, int HeaderRowIndex = 0){DataTable table = new DataTable();using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)){if (file.Length > 0){IWorkbook wb = WorkbookFactory.Create(file);ISheet isheet = wb.GetSheet(SheetName);table = ImportDt(isheet, HeaderRowIndex, dir);isheet = null;}}List<T> results = DataTableToList<T>(table);table.Dispose();return results;}/// <summary>/// 读取Excel文件某一索引sheet的内容到DataTable/// </summary>/// <param name="strFileName">excel文件路径</param>/// <param name="sheet">需要导出的sheet序号</param>/// <param name="HeaderRowIndex">列头所在行号,-1表示没有列头</param>/// <param name="dir">excel列名和DataTable列名的对应字典</param>/// <returns></returns>public static List<T> ImportExceltoDt<T>(string strFileName, Dictionary<string, string> dir, int HeaderRowIndex = 0, int SheetIndex = 0){DataTable table = new DataTable();using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)){if (file.Length > 0){IWorkbook wb = WorkbookFactory.Create(file);ISheet isheet = wb.GetSheetAt(SheetIndex);table = ImportDt(isheet, HeaderRowIndex, dir);isheet = null;}}List<T> results = DataTableToList<T>(table);table.Dispose();return results;}#endregion/// <summary>/// 获取excel文件的sheet数目/// </summary>/// <param name="outputFile"></param>/// <returns></returns>public static int GetSheetNumber(string outputFile){int number = 0;using (FileStream readfile = new FileStream(outputFile, FileMode.OpenOrCreate, FileAccess.Read)){if (readfile.Length > 0){IWorkbook wb = WorkbookFactory.Create(readfile);number = wb.NumberOfSheets;}}return number;}/// <summary>/// 判断内容是否是数字/// </summary>/// <param name="message"></param>/// <param name="result"></param>/// <returns></returns>public static bool isNumeric(String message, out double result){Regex rex = new Regex(@"^[-]?\d+[.]?\d*$");result = -1;if (rex.IsMatch(message)){result = double.Parse(message);return true;}elsereturn false;}/// <summary>/// 验证导入的Excel是否有数据/// </summary>/// <param name="excelFileStream"></param>/// <returns></returns>public static bool HasData(Stream excelFileStream){using (excelFileStream){IWorkbook workBook = new HSSFWorkbook(excelFileStream);if (workBook.NumberOfSheets > 0){ISheet sheet = workBook.GetSheetAt(0);return sheet.PhysicalNumberOfRows > 0;}}return false;}}/// <summary>/// 排序实现接口 不进行排序 根据添加顺序导出/// </summary>public class NoSort : IComparer{public int Compare(object x, object y){return -1;}}}

三、调用

3.1、增加一个“keywords”模型类,用作导出

public class keywords
{[Column("姓名")]public string IllegalKeywords { get; set; }
}

3.2、添加一个控制器

3.3、编写导入导出的控制器代码

3.3.1、重写“Close”函数

在导出时,为了防止MemoryStream无法关闭从而报错,所以我们继承MemoryStream;代码如下:

namespace WebApplication1    //命名空间依据自己的项目进行修改
{public class NpoiMemoryStream : MemoryStream{public NpoiMemoryStream(){AllowClose = true;}public bool AllowClose { get; set; }public override void Close(){if (AllowClose)base.Close();}}
}

3.3.2、添加控制器代码

/// <summary>
/// 本地环境
/// </summary>
private IHostingEnvironment _hostingEnv;/// <summary>
/// Excel导入的具体实现
/// </summary>
/// <returns></returns>
public IActionResult import_excel()
{string filepath = _hostingEnv.WebRootPath + "/在线用户20230324.xlsx";//导入的文件地址路径,可动态传入Dictionary<string, string> dir = new Dictionary<string, string>();//申明excel列名和DataTable列名的对应字典dir.Add("IllegalKeywords","姓名");List<keywords> keyWordsList = ExcelHelper.ImportExceltoDt<keywords>(filepath, dir,"Sheet1",0);#region 将List动态添加至数据库//……#endregionreturn Json(new { code = 200, msg = "导入成功" });
}/// <summary>
/// Excel导出的具体实现
/// </summary>
/// <returns></returns>
public IActionResult export_excel()
{#region 添加测试数据List<keywords> keys = new List<keywords>();for (int i = 0; i < 6; i++){keywords keyword = new keywords();keyword.IllegalKeywords = "测试_" + i;keys.Add(keyword);}#endregion#region 实例化DataTable并进行赋值DataTable dt = new DataTable();dt = listToDataTable(keys);//List<T>对象集合转DataTable#endregionstring filename = DateTime.Now.ToString("在线用户yyyyMMdd") + ".xlsx";Dictionary<string, string> dir = new Dictionary<string, string>();dir.Add("IllegalKeywords", "姓名");XSSFWorkbook book= ExcelHelper.ExportExcel(dt,  dir);dt.Dispose();//释放DataTable所占用的数据资源NpoiMemoryStream ms = new NpoiMemoryStream();ms.AllowClose = false;book.Write(ms, true);ms.Flush();ms.Position = 0;ms.Seek(0, SeekOrigin.Begin);ms.AllowClose = true;book.Dispose();//使用由XSSFWorkbook所占用的资源return File(ms, "application/vnd.ms-excel", Path.GetFileName(filename));//进行浏览器下载
}

3.3.3、Excel导出效果

Excel导出效果

3.3.4、Excel导入效果

导入后的List再根据需求调用添加方法实现数据的添加
Excel导入效果

相关文章:

.NET Core 实现Excel的导入导出

.NET Core 使用NPOI实现Excel的导入导出前言NPOI简介一、安装相对应的程序包1.1、在 “管理NuGet程序包” 中的浏览搜索&#xff1a;“NPOI”二、新建Excel帮助类三、调用3.1、增加一个“keywords”模型类&#xff0c;用作导出3.2、添加一个控制器3.3、编写导入导出的控制器代码…...

排好队,一个一个来:宫本武藏教你学队列(附各种队列源码)

文章目录前言&#xff1a;理解“队列”的正确姿势一个关于队列的小思考——请求处理队列的两大“护法”————顺序队列和链式队列数组实现的队列链表实现的队列循环队列关于开篇&#xff0c;你明白了吗&#xff1f;最后说一句前言&#xff1a; 哈喽&#xff01;欢迎来到黑洞晓…...

C语言--动态内存管理1

目录前言动态内存函数介绍mallocfreecallocrealloc常见的动态内存错误对NULL指针的解引用操作对动态开辟空间的越界访问对非动态开辟内存使用free释放使用free释放一块动态开辟内存的一部分对同一块动态内存多次释放动态开辟内存忘记释放&#xff08;内存泄漏&#xff09;对通讯…...

HTTPS 的工作原理

1、客户端发起 HTTPS 请求 这个没什么好说的&#xff0c;就是用户在浏览器里输入一个 https 网址&#xff0c;然后连接到 server 的 443 端口。 2、服务端的配置 采用 HTTPS 协议的服务器必须要有一套数字证书&#xff0c;可以自己制作&#xff0c;也可以向组织申请&#xf…...

游戏开发中建议使用半兰伯特光照

游戏开发中建议使用半兰伯特光照模型 在基本光照模型中求出漫反射部分的计算公式: 漫反射 = 入射光线的颜色和强度(c light) * 材质漫反射系数 (m diffuse)* 表面法线(n) * 其光源防线 (I) 在shader中为了不让 n和i的点乘结果为负数,即使用了saturate函数让值截取在[0,1]区…...

JavaScript到底如何存储数据?

1.var的迷幻操作 普遍的观点&#xff1a;JavaScript中的基本数据类型是保存在栈空间&#xff0c;而引用数据类型则是保存在堆空间里, 是否正确&#xff1f; 浏览器环境下JavaScript变量类型的运行实践结果: var a 10;console.log(a);console.log(window.a); console.log(wind…...

python实战应用讲解-【numpy专题篇】numpy应用案例(一)(附python示例代码)

目录 用Python分析二手车的销售价格 用Python构建GUI应用的铅笔草图 需要的包 实现步骤 完整代码 用Python分析二手车的销售价格 如今&#xff0c;随着技术的进步&#xff0c;像机器学习等技术正在许多组织中得到大规模的应用。这些模型通常与一组预定义的数据点一起工作…...

网络割接项目

某企业准备采购2台华为设备取代思科旧款设备,针对下列问题作出解答。 (1)做设备替换的时候,如何尽可能保证业务稳定性,请给出解决方案。 a)对现网拓扑进行分析,分析现网拓扑的规划(链路类型、cost、互联IP、互联接口等信息)、分析现网流量模型(路由协议、数据流向特…...

SpringBoot整合数据可视化大屏使用

1 前言 DataV数据可视化是使用可视化应用的方式来分析并展示庞杂数据的产品。DataV旨让更多的人看到数据可视化的魅力,帮助非专业的工程师通过图形化的界面轻松搭建专业水准的可视化应用,满足您会议展览、业务监控、风险预警、地理信息分析等多种业务的展示需求, 访问地址:h…...

蓝桥杯Web前端练习题-----水果拼盘

一、水果拼盘 介绍 目前 CSS3 中新增的 Flex 弹性布局已经成为前端页面布局的首选方案&#xff0c;本题可以使用 Flex 属性快速完成布局。 准备 开始答题前&#xff0c;需要先打开本题的项目代码文件夹&#xff0c;目录结构如下&#xff1a; ├── css │ └── style.…...

[攻城狮计划]如何优雅的在RA2E1上运行RT_Thread

文章目录[攻城狮计划]|如何优雅的在RA2E1上运行RT_Thread准备阶段&#x1f697;开发板&#x1f697;开发环境&#x1f697;下载BSP&#x1f697;编译烧录连接串口总结[攻城狮计划]|如何优雅的在RA2E1上运行RT_Thread &#x1f680;&#x1f680;开启攻城狮的成长之旅&#xff0…...

1.linux操作命令

1. pwd -> 打印当前绝对工作路径。 2. ls -> 查看目录的文件名 ls -> 默认列出当前目录的全部文件名 ls . -> 列出当前目录的全部文件名(.代表当前目录) ls / -> 列出根目录下的全部文件命名 ls -a -> 列出当前目录下全部文件名(包括隐藏…...

STL--vector

vector 头文件 #include<vector>向量的定义&#xff1a; vector<int> vec&#xff1b;//定义一个vec型的向量a vector<int> vec(5); //定义一个初始大小为5的向量 vector<int> vec(5,1); //初始大小为5&#xff0c;值都为1的向量二维数组&#xff1…...

Java每日一练(20230324)

目录 1. 链表插入排序 &#x1f31f;&#x1f31f; 2. 最接近的三数之和 &#x1f31f;&#x1f31f; 3. 寻找旋转排序数组中的最小值 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一…...

你掌握了吗?在PCB设计中,又快又准地放置元件

在印刷电路板设计中&#xff0c;设置电路板轮廓后&#xff0c;将零件(占地面积)调用到工作区。然后将零件重新放置到正确的位置&#xff0c;并在完成后进行接线。 组件放置是这项工作的第一步&#xff0c;对于之后的平滑布线工作是非常重要的工作。如果在接线工作期间模块不足…...

springboot学生综合测评系统

031-springboot学生综合测评系统演示录像2022开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&…...

【Unity3D】法线贴图和凹凸映射

1 法线贴图原理 表面着色器中介绍了使用表面着色器进行法线贴图&#xff0c;实现简单快捷。本文将介绍使用顶点和片元着色器实现法线贴图和凹凸映射&#xff0c;实现更灵活。 本文完整代码资源见→法线贴图和凹凸映射。 1&#xff09;光照原理 Phong 光照模型和 Blinn Phong 光…...

代码误写到master分支(或其他分支),此时代码还未提交,如何转移到新建分支?

问题背景 有时候&#xff0c;我们拿到需求&#xff0c;没仔细看当前分支是什么&#xff0c;就开始撸代码了。完成了需求或者写到一半发现开发错分支了。 比如此时新需求代码都在master分支上&#xff0c;提交必然是不可能的&#xff0c;所有修改还是要在新建分支上进行&#x…...

java多线程之线程安全(重点,难点)

线程安全1. 线程不安全的原因:1.1 抢占式执行1.2 多个线程修改同一个变量1.3 修改操作不是原子的锁(synchronized)1.一个锁对应一个锁对象.2.多个锁对应一个锁对象.2.多个锁对应多个锁对象.4. 找出代码错误5. 锁的另一种用法1.4 内存可见性解决内存可见性引发的线程安全问题(vo…...

如何免费使用chatGPT4?无需注册!

Poe体验真滴爽首先提大家问一个大家最关心的问题如何在一年内赚到一百万&#xff1f;用个插件给他翻译一下体验地址效果是非常炸裂的&#xff0c;那么我就将网址分分享给大家https://poe.com/前提&#xff1a;要有魔法&#xff0c;能够科学shangwangChatGPT-3 随便问GPT-4 模型…...

Android Flutter在点击事件上添加动画效果

在Android App的开发项目中&#xff0c;我们需要在点击事件上实现一个动画效果来提高用户的体验度。比如闲鱼底部中间按钮的那种。该怎么实现呢&#xff1f; 一起来看看吧 实现效果如图&#xff1a; ​实现思路 根据UI的设计图&#xff0c;对每个模块设计好动画效果&#xff0…...

VSCode嵌入式开发环境搭建

Vscode开发环境搭建 看这个链接就可以了&#xff0c;后面下载调试有点问题看下3.3。 在VSCode上部署STM32F1的开发环境 1. MXCube配置工程生成Makefile文件 借助正确的编译工具链进行编译&#xff0c; 2. 编译工具链搭建 编译工具链使用GCC的ARM版本 arm-none-eabi-gcc &am…...

数据结构之栈的使用

栈是计算机科学中一个重要的数据结构。它是一种特殊的线性表&#xff0c;只允许在一端进行进出操作。这一端被称为栈顶&#xff0c;另外一端被称为栈底。栈的特点是后进先出&#xff0c;即最后进入栈的元素会先被弹出栈。栈的应用广泛&#xff0c;例如在编译器中&#xff0c;栈…...

QMessageBox手动添加按钮并绑定按钮的信号

视频展示效果&#xff08;结合代码看效果更佳哦&#xff0c;代码在最下面&#xff09;&#xff1a; QMessageBox手动添加有重试效果的按钮效果图&#xff1a; 点击详细文本之后展开如下图&#xff1a; 图标可选&#xff1a; QMessageBox::Critical错误图标QMessageBox::NoIco…...

【C++进阶】位图和布隆过滤器

文章目录位图位图概念位图使用场景位图的结构构造setresettest完整代码布隆过滤器布隆过滤器概念布隆过滤器结构构造setresettest完整版代码位图 位图概念 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xff0c;数据无重复的场景。通常是用…...

Android开发-Android UI与布局

01 Android UI 1.1 UI 用户界面(User Interface&#xff0c;简称 UI&#xff0c;亦称使用者界面)是系统和用户之间进行交互和信息交换的媒介&#xff0c;它实现信息的内部形式与人类可以接受形式之间的转换。软件设计可分为两个部分&#xff1a;编码设计与UI设计。 1.2 Andr…...

在不丢失数据的情况下解锁锁定的 Android 手机的 4 种方法

尽管您可以使用指纹解锁手机&#xff0c;但大多数智能手机都需要 PIN 码、图案或字母数字代码作为主密码。如果您有一段时间没有输入手机密码&#xff0c;很容易忘记。正是由于这个原因&#xff0c;即使您打开了指纹解锁&#xff0c;大多数智能手机也会让您每天至少输入一次 PI…...

【11】核心易中期刊推荐——人工智能 | 图形图像处理

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…...

Spring 中的事件发布与监听

主要代码在org.springframework.context&#xff0c;org.springframework.context.event包中 事件发布与监听主要包含以下角色&#xff1a; 事件&#xff1a;ApplicationEvent事件监听器&#xff1a;ApplicationListener SmartApplicationListener GenericApplicationListene…...

c++ 一些常识 2

前言 今天主要讲类相关概念。 构造和析构函数是否可以抛出异常 在构造函数中抛出异常&#xff0c;控制权会转出构造函数之外&#xff0c;对象的析构函数不会被调用&#xff0c;造成内存泄漏。 如果析构函数中抛出异常&#xff0c;而且没有在当地捕捉&#xff0c;析构函数便执…...

合肥网站建设公司 推荐/免费刷粉网站推广免费

关于c语言中的指针的一些相关的问题: 1.int *p; 2.int **p; 3.int *p[10]; 4.int (*p)[10]; 5.int *p(int); 6.int (*p)(int); 7.int (*p[10])(int); 这七个难度还不是很大&#xff0c;相信大多数读者都能够答的出来。 答案&#xff1a; 1.一个指向整型数据的指针 2.一个指针的…...

怎么做会员自动售卡网站/爱站网收录

2019独角兽企业重金招聘Python工程师标准>>> 收集scrum ABCD的project列表。 list中的war包要到uk中找对应的war和TEST。 加入几个常用的list。 发送email通知。 Dev: 新建一个workItem&#xff1a; 命名 修改Field Against 修改Owned by 修改Priority 修改Planned …...

东台专业做网站/株洲网站设计外包首选

5.1 Laravel中的文件上传 文件系统 Laravel 的文件系统是基于 Frank de Jonge 的 Flysystem 扩展包 提供了简单的接口&#xff0c;可以操作本地端空间、Amazong S3、Rackspace Clound Storage 可以非常简单的切换不同的保存方式&#xff0c;但仍使用相同的api操作 配置文件…...

广州云脑网站建设/媒体吧软文平台

效果&#xff1a; 代码&#xff1a; 第一步&#xff1a;页面底部放两个浮动层&#xff0c;让指向图标不透明&#xff1a; <div class"share" style"display:none;filter:alpha(Opacity30);-moz-opacity:0.9;opacity: 0.5;width:100%;height:90%; background:…...

泉州网站建设选择讯呢/网络软文发布平台

转载&#xff1a; https://blog.51cto.com/darrenmemos/2151566 Redis Cluster特点 (1)Redis Cluster 共有16384(0-16383)个hash slots,数据写入时&#xff0c;根据CRC16(key)%16384 hash slots分配到不同的节点上&#xff1b; (2)当整个集群部分节点crash不影响继续使用&am…...

新手做网站免费域名/seo优化推荐

常用命令:npm install -g ionic cordova(需要安装node) ionic start cutePuppyPics --v2(建app cutePuppyPics app名字 v2表示用ionic2)cd cutePuppyPicsionic g page myPage (创建某页面 √ Create app/pages/my-page/my-page.html √ Create app/pages/my-page/my-page.ts √…...