在做系統的時候,很多時候信息量太大,這時候就需要進行Excel表格信息的導入和導出,今天就來給大家說一下我使用Excel表格信息導入和導出的心得。
1:首先需要在前端顯示界面View視圖中添加導入Excel和導出Excel按鈕:
@using (Html.BeginForm()) { <div class="options"> <input type="button" id="importexcel" name="importexcel" class="k-button" value="@T("從Excel表導入數據")" /> <input type="submit" name="exportexcel-all" class="k-button" value="@T("導出到Excel")" /> </div> }
這里注意,導出Excel是通過獲取當下的表單的方式來導出數據的。
2:然后為導入Excel添加function:
<script type="text/javascript"> $(document).ready(function () { $("#importexcel").click(function (e) { e.preventDefault(); var window = $("#importexcel-window");//點擊后彈出的操作界面 if (!window.data("kendoWindow")) { window.kendoWindow({ modal: true, width: "400px", title: "@T("從Excel表導入數據")", actions: ["Close"] }); } window.data('kendoWindow').center().open(); }); }); </script>
3:添加點擊事件后彈出來的操作界面(importexcel-window):
<div id="importexcel-window" style="display:none;"> @using (Html.BeginForm("ImportExcel", "Family", FormMethod.Post, new { enctype = "multipart/form-data" })) //這里"Family"是控制器的名稱 { //"ImportExcel"是控制器中相應方法名稱 @Html.AntiForgeryToken() <table style="text-align:left;"> <tr> <td> @T("Excel文件"): </td> <td> <input type="file" id="importexcelfile" name="importexcelfile" /> </td> </tr> <tr> <td colspan="2"> <input type="submit" class="k-button" value="@T("導入數據")" /> </td> </tr> </table> } </div>
4:在控制器端添加導入Excel和導出Excel方法:
(1)導入Excel
[HttpPost] public ActionResult ImportExcel() { if (_workContext.CurrentVendor != null) return AccessDeniedView(); try { var file = Request.Files["importexcelfile"]; if (file != null && file.ContentLength > 0) { _importManager.ImportFamiliesFromXlsx(file.InputStream); } else { ErrorNotification(_localizationService.GetResource("Admin.Common.UploadFile")); return RedirectToAction("GetFamilyListInfo"); } SuccessNotification(_localizationService.GetResource("導入成功")); return RedirectToAction("GetFamilyListInfo"); } catch (Exception exc) { ErrorNotification(exc); return RedirectToAction("GetFamilyListInfo"); } }
這里面 _importManager.ImportFamiliesFromXlsx(file.InputStream) 中_importManager是實例化接口並調用接口中的方法ImportFamiliesFromXlsx()
添加成員變量_importManager:private readonly IImportManager _importManager;
接口IImportManager :
public partial interface IImportManager { /// <summary> /// Import products from XLSX file /// </summary> /// <param name="stream">Stream</param> void ImportFamiliesFromXlsx(Stream stream); }
接口方法的實現:
public partial class ImportManager : IImportManager { public void ImportFamiliesFromXlsx(Stream stream) { using (var xlPackage = new ExcelPackage(stream)) { //得到第一個表的工作簿 var worksheet = xlPackage.Workbook.Worksheets.FirstOrDefault(); if (worksheet == null) throw new NopException("No worksheet found");
//列的屬性 var properties = new[] { "戶主姓名", }; int iRow = 2;//行 while (true) { bool allColumnsAreEmpty = true; if (worksheet.Cells[iRow, 2].Value != null && !String.IsNullOrEmpty(worksheet.Cells[iRow, 2].Value.ToString())) { allColumnsAreEmpty = false; } if (allColumnsAreEmpty) break; string Name = ConvertColumnToString(worksheet.Cells[iRow, GetColumnIndex(properties, "戶主姓名")].Value);
//這里主要說明一下在進行相應屬性值獲取的時候最好跟上面設置列的屬性值的順序一樣,為后面進行代碼審查的時候節省時間,同時這里面設置的字符串"戶主姓名"要與設置列屬性的值一樣 var group = _groupService.GetAllGroups().FirstOrDefault(m => m.Name == groupExcel.Trim() && m.Village.Name == villageExcel.Trim());//這里如果有表跟表之間的關系的時候需要進行鏈接查詢來獲得外鍵值,否則沒有導航就會導入失敗,就比如一個村子下面有很多個組,每個組下面又有很多的家庭,這里的_groupService.GetAllGroups()就是進行查詢. if (group == null) { break; } var family = _familyService.GetAllFamilies().FirstOrDefault(f => f.IDcardnumber == IDcardnumber);//這里的_family.GetAllFamilies()是得到全部的家庭. bool newFamily = false; if (family == null) { family = new Family(); newFamily = true; } family.Name = Name; family.GroupId = group.Id;//這里組的id值就是我們所需要的外鍵的值 if (newFamily) { _familyService.InsertFamily(family); } else { _familyService.UpdateFamily(family); } //next product iRow++; } } } }
這樣就可以通過Excel表格數據進行數據的導入了
(2)將數據導出到Excel表格:
進行導出時與進行導入時的步驟大庭相徑,不同的是一些接口的調用
[HttpPost, ActionName("GetFamilyListInfo")]//這里注意這里的ActionName是顯示信息列表對應的視圖的方法,同時也是導入功能和導出功能所在的視圖的方法. [FormValueRequired("exportexcel-all")]//這里面的值就是前端傳回來的"導出Excel"按鈕的name的值 public ActionResult ExportExcelAll(FamilyModel model) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers)) return AccessDeniedView(); var familys = _familyService.GetAllFamilies();//這里是得到全部家庭的信息 try { byte[] bytes; using (var stream = new MemoryStream()) { _exportManager.ExportFamiliesToXlsx(stream, familys); bytes = stream.ToArray(); } return File(bytes, "text/xls", "familys.xlsx"); } catch (Exception exc) { ErrorNotification(exc); return RedirectToAction("GetFamilyListInfo"); } }
同樣的這里面的_exportManager.ExportFamiliesToXlsx(stream, familys)是實現導出Excel方法的接口並調用方法ExportFamiliesToXlsx()
添加成員變量_exportManager:private readonly IExportManager _exportManager;
IExportManager 接口:
public partial interface IExportManager { /// <summary> /// Export family list to XLSX /// </summary> /// <param name="stream">Stream</param> /// <param name="families">Customers</param> void ExportFamiliesToXlsx(Stream stream, IQueryable<Family> families);//這里的Family是對應數據庫的類 }
IExportManager 接口實現:
public partial class ExportManager : IExportManager { /// <summary> /// Export family list to XLSX /// </summary> /// <param name="stream">Stream</param> /// <param name="families">Families</param> public virtual void ExportFamiliesToXlsx(Stream stream, IQueryable<Family> families) { if (stream == null) { throw new ArgumentNullException("stream"); } using (var xlPackage = new ExcelPackage(stream)) { //處理現有的工作表 var worksheet = xlPackage.Workbook.Worksheets.Add("Families");
//設置列屬性 var properties = new[] { "戶主姓名", "村", "組", }; for (int i = 0; i < properties.Length; i++) { worksheet.Cells[1, i + 1].Value = properties[i];//進行對比賦值 worksheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid;//固體填充樣式 worksheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));//背景顏色 worksheet.Cells[1, i + 1].Style.Font.Bold = true;//字體樣式,加粗 } int row = 2; foreach (var family in families.ToList())//這里需要注意,這里我們對查詢出的全部家庭信息進行ToList(),因為前面我們傳參數的時候用的是IQueryable<>,如果傳參的時候用的就是IList<>則不需要進行轉換.在這里我在應用的時候遇到了問題,在用IQueryable<>時,進行連接查詢是會出空值異常的,顯示找不到相應的村或者組. { int col = 1; worksheet.Cells[row, col].Value = family.Name; col++; worksheet.Cells[row, col].Value = family.Group.Village.Name; col++; worksheet.Cells[row, col].Value = family.Group.Name; col++;
//這里注意,一定要保證此處設置表格里面的值的時候的順序一定要與設置列的屬性的順序一樣. row++; } xlPackage.Save(); } } }
這樣就可以進行數據的導出了。
