新增加用户导入、Excel通用导入方法封装

This commit is contained in:
不做码农 2021-12-12 16:41:33 +08:00
parent b84e8b6774
commit 9dbd5eb654
4 changed files with 228 additions and 50 deletions

View File

@ -1,7 +1,6 @@
using Infrastructure; using Infrastructure;
using Infrastructure.Model; using Infrastructure.Model;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
@ -9,8 +8,6 @@ using OfficeOpenXml;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection;
using ZR.Admin.WebApi.Filters; using ZR.Admin.WebApi.Filters;
namespace ZR.Admin.WebApi.Controllers namespace ZR.Admin.WebApi.Controllers
@ -134,5 +131,37 @@ namespace ZR.Admin.WebApi.Controllers
return sFileName; return sFileName;
} }
/// <summary>
/// 下载导入模板
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="stream"></param>
/// <param name="fileName">下载文件名</param>
/// <returns></returns>
protected string DownloadImportTemplate<T>(List<T> list, Stream stream, string fileName)
{
IWebHostEnvironment webHostEnvironment = (IWebHostEnvironment)App.ServiceProvider.GetService(typeof(IWebHostEnvironment));
string sFileName = $"{fileName}模板.xlsx";
string newFileName = Path.Combine(webHostEnvironment.WebRootPath, "importTemplate", sFileName);
//调试模式需要加上
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
if (!Directory.Exists(newFileName))
{
Directory.CreateDirectory(Path.GetDirectoryName(newFileName));
}
using (ExcelPackage package = new(new FileInfo(newFileName)))
{
// 添加worksheet
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(fileName);
//全部字段导出
worksheet.Cells.LoadFromCollection(list, true, OfficeOpenXml.Table.TableStyles.Light13);
package.SaveAs(stream);
}
return sFileName;
}
} }
} }

View File

@ -1,6 +1,7 @@
using Infrastructure.Attribute; using Infrastructure.Attribute;
using Infrastructure.Enums; using Infrastructure.Enums;
using Infrastructure.Model; using Infrastructure.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -8,7 +9,9 @@ using OfficeOpenXml;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection;
using ZR.Admin.WebApi.Filters; using ZR.Admin.WebApi.Filters;
using ZR.Common;
using ZR.Model; using ZR.Model;
using ZR.Model.System; using ZR.Model.System;
using ZR.Service; using ZR.Service;
@ -170,43 +173,37 @@ namespace ZR.Admin.WebApi.Controllers.System
return ToResponse(ToJson(result)); return ToResponse(ToJson(result));
} }
///// <summary> /// <summary>
///// 导入 ok /// 导入
///// </summary> /// </summary>
///// <param name="formFile">使用IFromFile必须使用name属性否则获取不到文件</param> /// <param name="formFile">使用IFromFile必须使用name属性否则获取不到文件</param>
///// <returns></returns> /// <returns></returns>
//[HttpPost("importData")] [HttpPost("importData")]
//[Log(Title = "用户导入", BusinessType = BusinessType.IMPORT)] [Log(Title = "用户导入", BusinessType = BusinessType.IMPORT)]
//[ActionPermissionFilter(Permission = "system:user:import")] [ActionPermissionFilter(Permission = "system:user:import")]
//public IActionResult ImportData([FromForm(Name = "file")] IFormFile formFile) public IActionResult ImportData([FromForm(Name = "file")] IFormFile formFile)
//{ {
// var mapper = new Mapper(formFile.OpenReadStream());// 从流获取 IEnumerable<SysUser> users = ExcelHelper<SysUser>.ImportData(formFile.OpenReadStream());
// //读取的sheet信息
// var rows = mapper.Take<SysUser>(0);
// foreach (var item in rows)
// {
// SysUser u = item.Value;
// }
// //TODO 业务逻辑
// return SUCCESS(1);
//}
///// <summary> //TODO 业务逻辑,自行插入数据到db
///// 用户模板 ok return SUCCESS(users);
///// </summary> }
///// <returns></returns>
//[HttpGet("importTemplate")] /// <summary>
//[Log(Title = "用户模板", BusinessType = BusinessType.EXPORT)] /// 用户导入模板下载
//[ActionPermissionFilter(Permission = "system:user:export")] /// </summary>
//public IActionResult ImportTemplateExcel() /// <returns></returns>
//{ [HttpGet("importTemplate")]
// List<SysUser> user = new List<SysUser>(); [Log(Title = "用户模板", BusinessType = BusinessType.EXPORT)]
// var mapper = new Mapper(); [AllowAnonymous]
// MemoryStream stream = new MemoryStream(); public IActionResult ImportTemplateExcel()
// mapper.Save(stream, user, "sheel1", overwrite: true, xlsx: true); {
// //Response.Headers.Append("content-disposition", "attachment;filename=sysUser.xlsx"); List<SysUser> user = new List<SysUser>();
// return File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "sysUser.xlsx"); MemoryStream stream = new MemoryStream();
//}
string sFileName = DownloadImportTemplate(user, stream, "用户列表");
return File(stream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{sFileName}");
}
/// <summary> /// <summary>
/// 用户导出 /// 用户导出

156
ZR.Common/ExcelHelper.cs Normal file
View File

@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using OfficeOpenXml;
namespace ZR.Common
{
public class ExcelHelper<T> where T : new()
{
/// <summary>
/// 导入数据
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static IEnumerable<T> ImportData(Stream stream)
{
using ExcelPackage package = new(stream);
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];//读取第1个sheet
//获取表格的列数和行数
int colStart = worksheet.Dimension.Start.Column;
int colEnd = worksheet.Dimension.End.Column;
int rowStart = worksheet.Dimension.Start.Row;
int rowEnd = worksheet.Dimension.End.Row;
//int rowCount = worksheet.Dimension.Rows;
//int ColCount = worksheet.Dimension.Columns;
List<T> resultList = new();
List<PropertyInfo> propertyInfos = new();// new(typeof(T).GetProperties());
Dictionary<string, int> dictHeader = new();
for (int i = colStart; i < colEnd; i++)
{
var name = worksheet.Cells[rowStart, i].Value.ToString();
dictHeader[name] = i;
PropertyInfo propertyInfo = MapPropertyInfo(name);
if (propertyInfo != null)
{
propertyInfos.Add(propertyInfo);
}
}
for (int row = rowStart + 1; row <= rowEnd; row++)
{
T result = new();
foreach (PropertyInfo p in propertyInfos)
{
try
{
ExcelRange cell = worksheet.Cells[row, dictHeader[p.Name]];
if (cell.Value == null)
{
continue;
}
switch (p.PropertyType.Name.ToLower())
{
case "string":
p.SetValue(result, cell.GetValue<string>());
break;
case "int16":
p.SetValue(result, cell.GetValue<short>()); break;
case "int32":
p.SetValue(result, cell.GetValue<int>()); break;
case "int64":
p.SetValue(result, cell.GetValue<long>()); break;
case "decimal":
p.SetValue(result, cell.GetValue<decimal>());
break;
case "double":
p.SetValue(result, cell.GetValue<double>()); break;
case "datetime":
p.SetValue(result, cell.GetValue<DateTime>()); break;
case "boolean":
p.SetValue(result, cell.GetValue<bool>()); break;
case "char":
p.SetValue(result, cell.GetValue<string>()); break;
default:
break;
}
}
catch (KeyNotFoundException ex)
{
Console.WriteLine("未找到该列将继续循环," + ex.Message);
continue;
}
}
resultList.Add(result);
}
return resultList;
}
/// <summary>
/// 查找Excel列名对应的实体属性
/// </summary>
/// <param name="columnName"></param>
/// <returns></returns>
public static PropertyInfo MapPropertyInfo(string columnName)
{
PropertyInfo[] propertyList = GetProperties(typeof(T));
PropertyInfo propertyInfo = propertyList.Where(p => p.Name == columnName).FirstOrDefault();
if (propertyInfo != null)
{
return propertyInfo;
}
else
{
foreach (PropertyInfo tempPropertyInfo in propertyList)
{
System.ComponentModel.DescriptionAttribute[] attributes = (System.ComponentModel.DescriptionAttribute[])tempPropertyInfo.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);
if (attributes.Length > 0)
{
if (attributes[0].Description == columnName)
{
return tempPropertyInfo;
}
}
}
}
return null;
}
/// <summary>
/// 得到类里面的属性集合
/// </summary>
/// <param name="type"></param>
/// <param name="columns"></param>
/// <returns></returns>
public static PropertyInfo[] GetProperties(Type type, string[] columns = null)
{
PropertyInfo[] properties = null;
properties = type.GetProperties();
if (columns != null && columns.Length > 0)
{
// 按columns顺序返回属性
var columnPropertyList = new List<PropertyInfo>();
foreach (var column in columns)
{
var columnProperty = properties.Where(p => p.Name == column).FirstOrDefault();
if (columnProperty != null)
{
columnPropertyList.Add(columnProperty);
}
}
return columnPropertyList.ToArray();
}
else
{
return properties;
}
}
}
}

View File

@ -191,16 +191,13 @@
:action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess" :auto-upload="false" drag> :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-upload__text"> <div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
将文件拖到此处 <div class="el-upload__tip text-center" slot="tip">
<em>点击上传</em> <div class="el-upload__tip" slot="tip">
</div> <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的用户数据
<div class="el-upload__tip" slot="tip"> </div>
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据 <span>仅允许导入xlsxlsx格式文件</span>
<el-link type="info" style="font-size: 12px" @click="importTemplate">下载模板</el-link> <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
</div>
<div class="el-upload__tip" style="color: red" slot="tip">
提示仅允许导入xlsxlsx格式文件
</div> </div>
</el-upload> </el-upload>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@ -221,7 +218,6 @@ import {
exportUser, exportUser,
resetUserPwd, resetUserPwd,
changeUserStatus, changeUserStatus,
importTemplate,
} from "@/api/system/user"; } from "@/api/system/user";
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
import { treeselect } from "@/api/system/dept"; import { treeselect } from "@/api/system/dept";