导入不同业务数据通过Excel实现
很多公司都用到了老系统移植到新系统,数据自然也需要迁移,这个解决方案之一就是使用Excel文件导入。
结合公司实现,然后简单写了个Demo。
(PS:去找朋友本想着花几十分钟弄出来炫耀一波,结果花了三四个小时。究其原因,还是JS问题,JS以后尽量放在Html后面,这样就不用担心渲染问题了。)
首先上效果图:
下面介绍下具体实现:
--将学生和课程数据导入到数据库
--以stu开头的是学生,以tea开头的是老师 后面加个_区分学校
--创建学生老师学校表
--下载导入文件
--根据规则匹配学校,然后决定插入学生表还是老师表
--显示导入结果
--学校表
--主键Id,学校名称,学校编号
--学生表
--主键Id,学生姓名,学生年级,学生年龄,所在学校
--老师表
--主键Id,老师姓名,老师年龄,所在学校
create table School( Id int primary key identity, Name nvarchar(50), Num nvarchar(30) ) create table Student( Id int primary key identity, Name nvarchar(50), Grade int, Age int, SchoolNum nvarchar(30) ) create table Teacher( Id int primary key identity, Name nvarchar(50), Age int, SchoolNum nvarchar(30) )
后台代码实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using ExportExcelDemo.Core; using ExportExcelDemo.Core.Helper; using ExportExcelDemo.Core.Models; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Text; using System.Web; using System.Web.Mvc; namespace ExportExcelDemo.Web.Controllers { public class HomeController : Controller { private const string prefix_stu = "stu"; private const string prefix_tea = "tea"; public readonly string[] _fileTypes = { prefix_stu, prefix_tea }; public ActionResult Index() { SchoolManager schoolManager = new SchoolManager(); string schoolNum = schoolManager.GetSchoolNum("廊坊师范学院"); ViewBag.SchoolNum = schoolNum; return View(); } [HttpPost()] public JsonResult ImportData() { try { //文件类型,学校编号 Tuple<string, string, HttpPostedFileBase> tuble = ValidateFile(); var file = tuble.Item3; var server = HttpContext.Server; string tempFileDownloadFolder = server.MapPath("~/Temp/Downloads"); AppFileHelper.DeleteFilesInFolderIfExists(tempFileDownloadFolder, file.FileName); //保存到临时文件夹 var tempFilePath = Path.Combine(tempFileDownloadFolder, file.FileName); file.SaveAs(tempFilePath); string r = string.Empty; r = ImportDataInteral(tempFilePath, tuble.Item1, tuble.Item2); return Json(r); } catch (Exception ex) { return Json(ex.Message); } } /// <summary> /// 验证文件是否合规 /// </summary> /// <returns></returns> public Tuple<string, string, HttpPostedFileBase> ValidateFile() { if (Request.Files.Count <= 0 || Request.Files[0] == null) { throw new Exception("未找到文件"); } var file = Request.Files[0]; if (file.ContentLength > 1024 * 1024 * 5) //5m { throw new Exception("文件不能超过5M"); } string[] names = System.IO.Path.GetFileNameWithoutExtension(file.FileName).Split('_');//下划线分隔 string msg = "文件名称错误,请根据导入提示来修改文件名称"; if (names.Length != 2) { throw new Exception(msg); } if (!_fileTypes.Contains(names[0].ToLower())) { throw new Exception(msg); } if (string.IsNullOrWhiteSpace(names[1])) { throw new Exception(msg); } SchoolManager schoolManager = new SchoolManager(); string schoolNum = schoolManager.GetSchoolNum(names[1]); if (string.IsNullOrEmpty(schoolNum)) { throw new Exception("传入的学校名不存在"); } return new Tuple<string, string, HttpPostedFileBase>(names[0], names[1],file); } private string ImportDataInteral(string filePath,string fileDateType,string schoolNum) { DataSet ds = ExeclHelper.ToDataTable(filePath);//根据文件路径转换为 DataTable dt = ds.Tables[0]; int rowsCount = dt.Rows.Count; int totalRows = rowsCount; StringBuilder successMessage = new StringBuilder(); StringBuilder errMessage = new StringBuilder(); Action<DataRow, string> action; switch (fileDateType) { case prefix_stu: action = RowDataProcessForStu;break; case prefix_tea: action = RowDataProcessForTea;break; default: return errMessage.Append($"文件名前缀{fileDateType}错误").ToString(); } for (int i = 0; i < dt.Rows.Count; i++) { DataRow dr = dt.Rows[i]; try { action(dr, schoolNum); successMessage.Append($"第{i + 1}行:导入成功\r\n"); } catch (System.Exception ex) { var error = $"第{i + 1}行 :{ex.Message}\r\n"; errMessage.Append(error); continue; } } return errMessage.ToString() + successMessage.ToString(); } private void RowDataProcessForStu(DataRow dr,string schoolNum) { Student model = new Student(); model.Name = dr[0].ToString(); model.Grade =Convert.ToInt32(dr[1]); model.Age=Convert.ToInt32(dr[2]); model.SchoolNum = schoolNum; StudentManager studentManager = new StudentManager(); studentManager.InsertStudent(model); } private void RowDataProcessForTea(DataRow dr, string schoolNum) { Teacher model = new Teacher(); model.Name = dr[0].ToString(); model.Age = Convert.ToInt32(dr[1]); model.SchoolNum = schoolNum; TeacherManager teacherManager = new TeacherManager(); teacherManager.InsertTeacher(model); } } }
前台Html实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@{ ViewBag.Title = "导入数据"; } <div class="page-title"> <div class="title-env"> <h1 class="title"><i class="fa fa-file-text"></i>导入</h1> </div> <div class="breadcrumb-env"> </div> </div> <div class="row form-leftlabel"> <div class="col-md-12"> <div class="row"> <div class="col-sm-12"> <div class="panel panel-default"> <div class="panel-heading"> <h1 class="panel-title">导入说明</h1> </div> <div class="panel panel-default"> <div class="panel-body"> <form class="form-horizontal form-leftlabel"> <div class="form-group"> <label class="col-sm-3 control-label">学生数据:</label> <div class="col-sm-7"> <label> Execl文件名称规则:<b>stu_学校名称</b>,如:stu_学校名称</label> <div class="form-group"> <a class="btn btn-default" href="~/Temp/Downloads/stu_学校名称.xlsx" download="学生信息导入.xlsx">下载学生模板文件<i class="fa-download"></i></a> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">老师数据:</label> <div class="col-sm-7"> <label> Execl文件名称规则:<b>tea_学校名称</b>,如:tea_学校名称</label> <div class="form-group"> <a class="btn btn-default" href="~/Temp/Downloads/tea_学校名称.xlsx" download="老师信息导入.xlsx">下载老师模板文件<i class="fa-download"></i></a> </div> </div> </div> </form> </div> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> <h1 class="panel-title">导入操作</h1> </div> <div class="panel-body"> <form id="DataImportForm" method="POST" action="@Url.Action("ImportData", "Home", new {area = string.Empty})"> <div class="col-sm-7"> <input type="file" placeholder="选择模板文件并上传" name="selectExecl" value="" class="form-control " id="selectMemberTxt" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" /> </div> <div class="col-sm-5"> <button class="button button-plain2 button-rounded" type="submit" id="btnImport">导入</button> </div> </form> </div> </div> </div> </div> <div class="row"> <div class="col-sm-12"> <div class="panel panel-default"> <div class="panel-heading"> <h1 class="panel-title">导入结果</h1> </div> <div class="panel-body"> <div class="col-sm-7"> <textarea id="verifyResult" class="form-control" value="" rows="6"></textarea> </div> </div> </div> </div> </div> </div> </div> <script src="~/Scripts/jquery-3.3.1.min.js"></script> <script src="~/Scripts/jquery.form.js"></script><!--提交表单--> <link href="~/Content/jquery-ui/jquery-ui.min.css" rel="stylesheet" /> <script src="~/Content/layer/layer.js"></script><!--layer控件--> <script src="~/Content/ExportExcel.js"></script>
ExportExcel.js实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var index; //Appearance/Logo $('#DataImportForm').ajaxForm({ beforeSubmit: function (formData, jqForm, options) { var $fileInput = $('#DataImportForm input[name=selectExecl]'); var files = $fileInput.get()[0].files; if (!files.length) { layer.msg("请选择execl文件", { icon: 7 }); return false; } var file = files[0]; var type = file.name.substring(file.name.lastIndexOf(".")).toLowerCase(); if (type != '.xlsx') { layer.msg("请选择后缀名为.xlsx格式的excel文件", { icon: 7 }); return false; } //File size check if (file.size > 1024 * 1024 * 5) //5m { layer.msg("文件不能超过5m", { icon: 7 }); return false; } $('#verifyResult').val(""); index =layer.msg("导入中...", { icon: 16 , shade: 0.5, time: false //取消自动关闭 }); return true; }, success: function (response) { $('#verifyResult').val(response); layer.close(index);//手动关闭 } });
百闻不如一见,百见不如一做,只有做了,才知道问题出现在哪儿,才能去解决问题。