不少公司都用到了老系統移植到新系統,數據天然也須要遷移,這個解決方案之一就是使用Excel文件導入。
結合公司實現,而後簡單寫了個Demo。
(PS:去找朋友本想着花幾十分鐘弄出來炫耀一波,結果花了三四個小時。究其緣由,仍是JS問題,JS之後儘可能放在Html後面,這樣就不用擔憂渲染問題了。)
首先上效果圖:css
下面介紹下具體實現: jquery
--將學生和課程數據導入到數據庫
--以stu開頭的是學生,以tea開頭的是老師 後面加個_區分學校
--建立學生老師學校表
--下載導入文件
--根據規則匹配學校,而後決定插入學生表仍是老師表
--顯示導入結果
--學校表
--主鍵Id,學校名稱,學校編號
--學生表
--主鍵Id,學生姓名,學生年級,學生年齡,所在學校
--老師表
--主鍵Id,老師姓名,老師年齡,所在學校git
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) )
後臺代碼實現:ajax
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實現:數據庫
@{ 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實現:app
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);//手動關閉 } });