ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出
系列目录
前言:
导入导出实在多例子,很多成熟的组建都分装了导入和导出,这一节演示利用LinqToExcel组件对Excel的导入,这个是一个极其简单的例子。
我并不是说导入的简单。而是LinqToExcel让我们对Excel操作更加简单!
最后我们将利用ClosedXML输出Excel。这个比现流行NPOI与EPPlus更加优秀的组件,以Open XML SDK为基础,所以只支持xlsx,不支持xls格式(现阶段谁没有个office2007以上版本)
他导出的Excel根据官方描述,兼容性远超同行对手
如果你不是使用本架构只看2,3,4点,使用BLL层的代码,这同样适用你的MVC程序
知识点:
- LinqToExcel组件读取Excel文件
- ClosedXML组件输出Excel
准备:
- 一张演示的数据库表
- 安装LinqToExcel NuGet包
- 文件上传样例
- CloseXML导出Excel
开始:
1.数据表
- CREATE TABLE [dbo].[Spl_Person](
- [Id] [nvarchar](50) NOT NULL, --ID
- [Name] [nvarchar](50) NULL, --姓名
- [Sex] [nchar](10) NULL, --性别
- [Age] [int] NULL, --年龄
- [IDCard] [nvarchar](50) NULL, --IDCard
- [Phone] [nvarchar](50) NULL, --电话
- [Email] [nvarchar](200) NULL, --邮件
- [Address] [nvarchar](300) NULL, --地址
- [CreateTime] [datetime] NOT NULL, --创建时间
- [Region] [nvarchar](50) NULL, --区域
- [Category] [nvarchar](50) NULL, --类别
- CONSTRAINT [PK_Spl_Person] PRIMARY KEY CLUSTERED
- (
- [Id] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
按照之前的做法,更新到EF。并利用T4生成DAL,BLL,MODEL。再用代码生成器生成界面复制进解决方案,一步到位
配置好访问地址和权限,直接运行
再手动在工具栏添加导入和导出的按钮(别忘记添加权限)
- @Html.ToolButton("btnImport", "fa fa-level-down", Resource.Import, perm, "Import", true)
- @Html.ToolButton("btnExport", "fa fa-level-up", Resource.Export, perm, "Export", true)
2.安装LinqToExcel包
因为我们读取Excel放在BLL层,所有在BLL层安装LinqToExcel包
3.文件上传
(这一点简单带过,可以到网上下载上传代码植入到自己系统中)
或者下载第32节的源码 或者下载本节的示例代码都可以
我这里使用普通的form上传功能
添加导入前端代码
- <div id="uploadExcel" class="easyui-window" data-options="modal:true,closed:true,minimizable:false,shadow:false">
- <form name="form1" method="post" id="form1">
- <table>
- <tr>
- <th style=" padding:20px;">Excel:</th>
- <td style=" padding:20px;">
- <input name="ExcelPath" type="text" maxlength="" id="txtExcelPath" readonly="readonly" style="width:200px" class="txtInput normal left">
- <a href="javascript:$('#FileUpload').trigger('click').void(0);;" class="files">@Resource.Browse</a>
- <input class="displaynone" type="file" id="FileUpload" name="FileUpload" onchange="Upload('ExcelFile', 'txtExcelPath', 'FileUpload');">
- <span class="uploading">@Resource.Uploading</span>
- </td>
- </tr>
- </table>
- <div class="endbtndiv">
- <a id="btnSave" href="javascript:ImportData()" class="easyui-linkbutton btns">Save</a>
- <a id="btnReturn" href="javascript:$('#uploadExcel').window('close')" class="easyui-linkbutton btnc">Close</a>
- </div>
- </form>
- </div>
导入按钮事件只要弹出上传框就好
- $("#btnImport").click(function () {
- $("#uploadExcel").window({ title: '@Resource.Import', width: 450, height: 160, iconCls: 'icon-details' }).window('open');
- });
保证上传是成功的。
直接查看源码的C#上传代码
-------------------------------------------------------------------------------------------------------上面只是前期的准备工作--------------------------------------------------------------
在业务层添加以下代码
- using Apps.Common;
- using Apps.Models;
- using Apps.Models.Spl;
- using LinqToExcel;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace Apps.Spl.BLL
- {
- public partial class Spl_ProductBLL
- {
- /// <summary>
- /// 校验Excel数据
- /// </summary>
- public bool CheckImportData( string fileName, List<Spl_PersonModel> personList,ref ValidationErrors errors )
- {
- var targetFile = new FileInfo(fileName);
- if (!targetFile.Exists)
- {
- errors.Add("导入的数据文件不存在");
- return false;
- }
- var excelFile = new ExcelQueryFactory(fileName);
- //对应列头
- excelFile.AddMapping<Spl_PersonModel>(x => x.Name, "Name");
- excelFile.AddMapping<Spl_PersonModel>(x => x.Sex, "Sex");
- excelFile.AddMapping<Spl_PersonModel>(x => x.Age, "Age");
- excelFile.AddMapping<Spl_PersonModel>(x => x.IDCard, "IDCard");
- excelFile.AddMapping<Spl_PersonModel>(x => x.Phone, "Phone");
- excelFile.AddMapping<Spl_PersonModel>(x => x.Email, "Email");
- excelFile.AddMapping<Spl_PersonModel>(x => x.Address, "Address");
- excelFile.AddMapping<Spl_PersonModel>(x => x.Region, "Region");
- excelFile.AddMapping<Spl_PersonModel>(x => x.Category, "Category");
- //SheetName
- var excelContent = excelFile.Worksheet<Spl_PersonModel>(0);
- int rowIndex = 1;
- //检查数据正确性
- foreach (var row in excelContent)
- {
- var errorMessage = new StringBuilder();
- var person = new Spl_PersonModel();
- person.Id =
- person.Name = row.Name;
- person.Sex = row.Sex;
- person.Age = row.Age;
- person.IDCard = row.IDCard;
- person.Phone = row.Phone;
- person.Email = row.Email;
- person.Address = row.Address;
- person.Region = row.Region;
- person.Category = row.Category;
- if (string.IsNullOrWhiteSpace(row.Name))
- {
- errorMessage.Append("Name - 不能为空. ");
- }
- if (string.IsNullOrWhiteSpace(row.IDCard))
- {
- errorMessage.Append("IDCard - 不能为空. ");
- }
- //=============================================================================
- if (errorMessage.Length > 0)
- {
- errors.Add(string.Format(
- "第 {0} 列发现错误:{1}{2}",
- rowIndex,
- errorMessage,
- "<br/>"));
- }
- personList.Add(person);
- rowIndex += 1;
- }
- if (errors.Count > 0)
- {
- return false;
- }
- return true;
- }
- /// <summary>
- /// 保存数据
- /// </summary>
- public void SaveImportData(IEnumerable<Spl_PersonModel> personList)
- {
- try
- {
- DBContainer db = new DBContainer();
- foreach (var model in personList)
- {
- Spl_Person entity = new Spl_Person();
- entity.Id = ResultHelper.NewId;
- entity.Name = model.Name;
- entity.Sex = model.Sex;
- entity.Age = model.Age;
- entity.IDCard = model.IDCard;
- entity.Phone = model.Phone;
- entity.Email = model.Email;
- entity.Address = model.Address;
- entity.CreateTime = ResultHelper.NowTime;
- entity.Region = model.Region;
- entity.Category = model.Category;
- db.Spl_Person.Add(entity);
- }
- db.SaveChanges();
- }
- catch (Exception ex)
- {
- throw;
- }
- }
- }
- }
BLL
- public class ValidationErrors : List<ValidationError>
- {
- /// <summary>
- /// 添加错误
- /// </summary>
- /// <param name="errorMessage">信息描述</param>
- public void Add(string errorMessage)
- {
- base.Add(new ValidationError { ErrorMessage = errorMessage });
- }
- /// <summary>
- /// 获取错误集合
- /// </summary>
- public string Error
- {
- get {
- string error = "";
- this.All(a => {
- error += a.ErrorMessage;
- return true;
- });
- return error;
- }
- }
- }
ValidationError
代码包含两个方法
public bool CheckImportData( string fileName, List<Spl_PersonModel> personList,ValidationErrors errors )
fileName为我们上传的文件。
personList为承接数据List
ValidationErrors 错误集合
public void SaveImportData(IEnumerable<Spl_PersonModel> personList)
保存数据
别忘记添加接口
- public partial interface ISpl_PersonBLL
- {
- bool CheckImportData(string fileName, List<Spl_PersonModel> personList, ref ValidationErrors errors);
- void SaveImportData(IEnumerable<Spl_PersonModel> personList);
- }
简单明白,直接看代码,不再解析。OK这样控制器就可以直接调用了
- public ActionResult Import(string filePath)
- {
- var personList = new List<Spl_PersonModel>();
- //校验数据is
- bool checkResult = m_BLL.CheckImportData(filePath, personList, ref errors);
- //校验通过直接保存
- if (checkResult)
- {
- m_BLL.SaveImportData(personList);
- LogHandler.WriteServiceLog(GetUserId(),"导入成功", "成功", "导入", "Spl_Person");
- return Json(JsonHandler.CreateMessage(, Resource.InsertSucceed));
- }
- else
- {
- string ErrorCol = errors.Error;
- LogHandler.WriteServiceLog(GetUserId(), ErrorCol, "失败", "导入", "Spl_Person");
- return Json(JsonHandler.CreateMessage(, Resource.InsertFail + ErrorCol));
- }
- }
最后前端还需要把路径给回来。
- function ImportData()
- {
- $.post("@Url.Action("Import")?filePath=" + $("#txtExcelPath").val(), function (data) {
- if (data.type == ) {
- $("#List").datagrid('load');
- $('#uploadExcel').window('close');
- }
- $.messageBox5s('@Resource.Tip', data.message);
- }, "json");
- }
OK测试一下!建立一个新的excel格式
一般情况下我们是提供模版给用户下载供用户输入数据,来确保格式的正确性
--------------------------------------------------------------------------------------导出功能------------------------------------------------------------------------------
4.安装ClosedXML NuGet包
在控制器添加以下代码:
- public ActionResult Export()
- {
- var exportSpource = this.GetExportData();
- var dt = JsonConvert.DeserializeObject<DataTable>(exportSpource.ToString());
- var exportFileName = string.Concat(
- "Person",
- DateTime.Now.ToString("yyyyMMddHHmmss"),
- ".xlsx");
- return new ExportExcelResult
- {
- SheetName = "人员列表",
- FileName = exportFileName,
- ExportData = dt
- };
- }
- private JArray GetExportData()
- {
- List<Spl_PersonModel> list = m_BLL.GetList(ref setNoPagerAscById, "");
- JArray jObjects = new JArray();
- foreach (var item in list)
- {
- var jo = new JObject();
- jo.Add("Id", item.Id);
- jo.Add("Name", item.Name);
- jo.Add("Sex", item.Sex);
- jo.Add("Age", item.Age);
- jo.Add("IDCard", item.IDCard);
- jo.Add("Phone", item.Phone);
- jo.Add("Email", item.Email);
- jo.Add("Address", item.Address);
- jo.Add("CreateTime", item.CreateTime);
- jo.Add("Region", item.Region);
- jo.Add("Category", item.Category);
- jObjects.Add(jo);
- }
- return jObjects;
- }
注意:ExportExcelResult
此类是使用ClosedXML.Excel,已经封装好了。大家直接拿来用就可以。把关注点都放在业务中
- using ClosedXML.Excel;
- using System;
- using System.Data;
- using System.IO;
- using System.Text;
- using System.Web;
- using System.Web.Mvc;
- namespace Apps.Web.Core
- {
- public class ExportExcelResult : ActionResult
- {
- public string SheetName { get; set; }
- public string FileName { get; set; }
- public DataTable ExportData { get; set; }
- public ExportExcelResult()
- {
- }
- public override void ExecuteResult(ControllerContext context)
- {
- if (ExportData == null)
- {
- throw new InvalidDataException("ExportData");
- }
- if (string.IsNullOrWhiteSpace(this.SheetName))
- {
- this.SheetName = "Sheet1";
- }
- if (string.IsNullOrWhiteSpace(this.FileName))
- {
- this.FileName = string.Concat(
- "ExportData_",
- DateTime.Now.ToString("yyyyMMddHHmmss"),
- ".xlsx");
- }
- this.ExportExcelEventHandler(context);
- }
- /// <summary>
- /// Exports the excel event handler.
- /// </summary>
- /// <param name="context">The context.</param>
- private void ExportExcelEventHandler(ControllerContext context)
- {
- try
- {
- var workbook = new XLWorkbook();
- if (this.ExportData != null)
- {
- context.HttpContext.Response.Clear();
- // 编码
- context.HttpContext.Response.ContentEncoding = Encoding.UTF8;
- // 设置网页ContentType
- context.HttpContext.Response.ContentType =
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
- // 导出名字
- var browser = context.HttpContext.Request.Browser.Browser;
- var exportFileName = browser.Equals("Firefox", StringComparison.OrdinalIgnoreCase)
- ? this.FileName
- : HttpUtility.UrlEncode(this.FileName, Encoding.UTF8);
- context.HttpContext.Response.AddHeader(
- "Content-Disposition",
- string.Format("attachment;filename={0}", exportFileName));
- // Add all DataTables in the DataSet as a worksheets
- workbook.Worksheets.Add(this.ExportData, this.SheetName);
- using (var memoryStream = new MemoryStream())
- {
- workbook.SaveAs(memoryStream);
- memoryStream.WriteTo(context.HttpContext.Response.OutputStream);
- memoryStream.Close();
- }
- }
- workbook.Dispose();
- }
- catch (Exception ex)
- {
- throw;
- }
- }
- }
- }
总结:
本节知识点,全部聚集在CheckImportData方法上。
对应列头是模版xlsx的列头
1.如果模版需要是是中文的,如Name=名字,那么方法应该这么写
excelFile.AddMapping<Spl_PersonModel>(x => x.Name, "名字");
2.导入第几个sheet工作薄可以这么写
我这里写0是指第一个sheet工作薄。可以直接指定工作薄
var excelContent = excelFile.Worksheet<Spl_PersonModel>("Sheet1");
3.检查正确性可以确保数据的来源。可以给出用户正确的修改提示。
4.借助ClosedXML,导出实际只需要几行代码。哈哈..这是如此的简单。
- return new ExportExcelResult
- {
- SheetName = "人员列表",
- FileName = exportFileName,
- ExportData = dt
- };
ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出的更多相关文章
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(转)
开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 日程管理 http://ww ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)
开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 任务调度系统界面 http: ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(63)-Excel导入和导出-自定义表模导入
系列目录 前言 上一节使用了LinqToExcel和CloseXML对Excel表进行导入和导出的简单操作,大家可以跳转到上一节查看: ASP.NET MVC5+EF6+EasyUI 后台管理系统(6 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统-WebApi的用法与调试
1:ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-WebApi与Unity注入 使用Unity是为了使用我们后台的BLL和DAL层 2:ASP.NET MVC5+EF6+Easy ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(51)-系统升级
系统很久没有更新内容了,期待已久的更新在今天发布了,最近花了2个月的时间每天一点点,从原有系统 MVC4+EF5+UNITY2.X+Quartz 2.0+easyui 1.3.4无缝接入 MVC5+E ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(58)-DAL层重构
系列目录 前言:这是对本文系统一次重要的革新,很久就想要重构数据访问层了,数据访问层重复代码太多.主要集中增删该查每个模块都有,所以本次是为封装相同接口方法 如果你想了解怎么重构普通的接口DAL层请查 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(34)-文章发布系统①-简要分析
系列目录 最新比较闲,为了学习下Android的开发构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(1)-前言与,虽然有点没有目的的学习,但还是了解了Andro ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(54)-工作流设计-所有流程监控
系列目录 先补充一个平面化登陆页面代码,自己更换喜欢的颜色背景 @using Apps.Common; @{ Layout = null; } <!DOCTYPE html> <ht ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(56)-插件---单文件上传与easyui使用fancybox
系列目录 https://yunpan.cn/cZVeSJ33XSHKZ 访问密码 0fc2 今天整合lightbox插件Fancybox1.3.4,发现1.3.4版本太老了.而目前easyui 1 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航
系列目录 本节主要知识点是easyui 的手风琴加树结构做菜单导航 有园友抱怨原来菜单非常难看,但是基于原有树形无限级别的设计,没有办法只能已树形展示 先来看原来的效果 改变后的效果,当然我已经做好了 ...
随机推荐
- 201521123042 《java程序设计》 第八周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. ①泛型定义:泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展, ...
- 201521123089《Java程序设计》第6周学习总结
1. 本周学习总结 2. 书面作业 clone方法1.1 Object对象中的clone方法是被protected修饰,在自定义的类中覆盖clone方法时需要注意什么? ...
- 201521123104《JAVA程序设计》第三周学习总结
1. 本周学习总结 2. 书面作业 Q1. 代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; ...
- 201521123004《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 答:思维导图如下: Java中使用try-catch语法处理异常: try { 可能产生异常的代码段 }catch ...
- Java: 类继承中 super关键字
super 关键字的作用有两个: 1)在子类中调用超类的构造器,完成实例域参数的初始化,调用构造器的语句只能作为另一个构造器(通常指的是子类构造器)的第一条语句出现, 2)在子类中调用超类的方法,如: ...
- 磁盘管理之inode与block
索引式文件系统 什么是inode? Inode其实就是索引号,便于我们寻找我们文件所存储的数据块block,索引式文件系统在查找信息,读写操作上都比原来的文件系统要快,我们可以通过inode中记录的b ...
- Lucene第一篇【介绍Lucene、快速入门】
什么是Lucene?? Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎的架构,提供了完整的创建索引 ...
- java-枚举一些字典信息的例子
一个典型的枚举应用的例子 package opstools.vtm.dictionary.enums; import opstools.framework.view.ResourceValue; /* ...
- jmeter 分布式实战
最近作者在公司部署公司的分布式压力测试情况的时候,遇到了问题,什么问题呢,各种错误,于是大晚上的为了不耽误压测,我们就两个同事两台电脑搞,可是还是不行的呢,我要研究研究这个是什么梗,于是乎,大晚上加班 ...
- 黑马程序员Java基础班+就业班课程笔记全发布(持续更新)
正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G QQ 1481135711 这是我总 ...