ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出

本文示例代码下载: 链接:http://pan.baidu.com/s/1jHBdgCA 密码:hzh7

ps:Vs数据库脚本在解压目录下,修改web.config数据库链接,示例代码包含:导入,导出,上传

前言:

导入导出实在多例子,很多成熟的组建都分装了导入和导出,这一节演示利用LinqToExcel组件对Excel的导入,这个是一个极其简单的例子。

我并不是说导入的简单。而是LinqToExcel让我们对Excel操作更加简单!

最后我们将利用ClosedXML输出Excel。这个比现流行NPOI与EPPlus更加优秀的组件,以Open XML SDK为基础,所以只支持xlsx,不支持xls格式(现阶段谁没有个office2007以上版本)

他导出的Excel根据官方描述,兼容性远超同行对手

如果你不是使用本架构只看2,3,4点,使用BLL层的代码,这同样适用你的MVC程序

知识点:

  • LinqToExcel组件读取Excel文件
  • ClosedXML组件输出Excel

准备:

  1. 一张演示的数据库表
  2. 安装LinqToExcel NuGet包
  3. 文件上传样例
  4. 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="255" 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(1, Resource.InsertSucceed));
             }             else
             {                 string ErrorCol = errors.Error;
                 LogHandler.WriteServiceLog(GetUserId(), ErrorCol, "失败", "导入", "Spl_Person");                 return Json(JsonHandler.CreateMessage(0, Resource.InsertFail + ErrorCol));
              }
        
        }

最后前端还需要把路径给回来。

 function ImportData()
    {
        $.post("@Url.Action("Import")?filePath=" + $("#txtExcelPath").val(), function (data) {            if (data.type == 1) {
                $("#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
            };

时间: 2024-10-06 01:32:14

ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出的相关文章

ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)

开发工具:VS2015(2012以上)+SQL2008R2以上数据库  您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB  升级后界面效果如下: 日程管理   http://www.cnblogs.com/ymnets/p/7094914.html 任务调度系统界面 http://www.cnblogs.com/ymnets/p/5065154.html 系统权限全套完整图  http://www.cnblogs.com/ymnets/p/5065201.html 系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统-关于WebApi的用法

1:ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-WebApi与Unity注入 使用Unity是为了使用我们后台的BLL和DAL层 2:ASP.NET MVC5+EF6+EasyUI 后台管理系统(2)-WebApi与Unity注入-配置文件 3:ASP.NET MVC5+EF6+EasyUI 后台管理系统(3)-MVC WebApi 用户验证 (1) 4:ASP.NET MVC5+EF6+EasyUI 后台管理系统(4)-MVC WebApi 用户验证 (2) 以往我们讲

ASP.NET MVC5+EF6+EasyUI 后台管理系统(75)-微信公众平台开发-用户管理

最近代码出现分享问题,360云盘宣布混不下去,所有分享的连接都失效了,最近有时间会把代码转移到百度云,再把文章的代码补回去 前言 本节主要是关注者(即用户)和用户组的管理,微信公众号提供了用户和用户组的管理,我们可以在微信公众号官方里面进行操作,添加备注和标签,以及移动用户组别,同时,微信公众号也提供了相应的接口另我们本地可以操作.我们主要是同步到本地,这样我们可以自己为用户定义更多的信息,以及与本地的业务更好的对接起来. 实现 一.关注与订阅事件 看到我们之前的消息处理类 我们需要扩展一个事件

ASP.NET MVC5+EF6+EasyUI 后台管理系统(84)-Quartz 作业调度用法详解一

前言 我从Quartz2.0开始使用,并对其进行了封装了界面,可以参考 http://www.cnblogs.com/ymnets/p/5065154.html 最近拿出来进行了优化,并升级到最新版,温故而知新嘛 当初教程较少,并且是英文,现在很多地方都有中文的教程也是学习起来事半功倍 Quartz能实现什么? 他类似于SQL Server的代理与Timer定时器: 1.指定时间执行一条SQL语句或存储过程 2.指定时间发送邮件(执行一个C#方法) 3.有规律的定时执行想要做的事情(通过配置Cr

ASP.NET MVC5+EF6+EasyUI 后台管理系统(73)-微信公众平台开发-消息管理

前言 回顾上一节,我们熟悉的了解了消息的请求和响应,这一节我们来建立数据库的表,表的设计蛮复杂 你也可以按自己所分析的情形结构来建表 必须非常熟悉表的结果才能运用这张表,这表表的情形涵盖比较多 思维导图 我这个人比较喜欢用思维导图来分析和表达一些模型: 表结构 根据思维导图,我们可以建立的表可以是3张表:消息表,规则表,类型表 消息表:实际的消息 规则表:文本.图文.语音等 类型表:文本.图文.语音(默认回复,订阅回复) 也可以是两张表:规制表,消息表(+一个类型字段) 我这里只设计一张表:消息

ASP.NET MVC5+EF6+EasyUI 后台管理系统(999)-如何使用

前言 这篇文本讲述了这个框架的使用方式,及一些疑问的答疑,更加精准的使用这个框架来建立功能 经过几个版本的迭代,系统使用更加方便,代码更加简洁也更加的智能,所以之前61节的文章也需要重新编排 对项目的了解 项目没有特别难以理解的类库, 就当成一个普通的MVC,三层项目看待即可 目录 我们只需要分为几步就能快速的建立一个具有权限的功能 表设计及约定 生成代码(代码生成器及TT模板) 配置(URL的配置及权限设置) 1.表设计及约定 框架表的设计必须遵循约定来设计,否则生成的代码需要再重载,而约定只

ASP.NET MVC5+EF6+EasyUI 后台管理系统(92)-打印EasyUI 的datagrid表格

前言 应用系统有时候需要打印Datagrid的表格内容,我们本节就来学习打印datagrid内容 打印主要使用:web打印(我们之前有讲过web打印插件jqprint) + 将datagrid重新编制成可以打印的html格式 一.建立一个普通的例子 我们使用官方下载的demo下的datagrid basic.html代码就好 引入Jqgrid打印插件,并增加一个按钮来触发打印事件 <!DOCTYPE html> <html> <head> <meta charse

ASP.NET MVC5+EF6+EasyUI 后台管理系统(65)-MVC WebApi 用户验证 (1)

系列目录 前言: WebAPI主要开放数据给手机APP,其他需要得知数据的系统,或者软件应用,所以移动端与系统的数据源往往是相通的. Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能,一个功能复杂的业务应用系统,通过角色授权来控制用户访问 本文通过Basic 方式进行基础认证Mvc的Controller基类及Action的权限验证来实现Web系统登录,Mvc前端权限校验以及WebApi服务端的访问校验功能,本文主要作为本人备忘使用,如能给予人帮助,深感荣幸,欢迎讨论和指正,下面梳

ASP.NET MVC5+EF6+EasyUI 后台管理系统(76)-微信公众平台开发-网页授权

前言 网页授权是:应用或者网站请求你用你的微信帐号登录,同意之后第三方应用可以获取你的个人信息 网上说了一大堆参数,实际很难理解和猜透,我们以实际的代码来演示比较通俗易懂 配置 实现之前我们必须配置用户授权获取用户信息的域名或者IP.正式公众号只能配置(域名) 第一步:登录公众号平台 跟我们之前配置公众号平台信息一样 第二步: 打开开发者工具 拉到下半部分位置的网页账号 第三步:配置你的授权回调域名 实现 我们模拟一个需要授权的页面(代码提供来自Senparc) 第一步:新建一个Controll