热门IT资讯网

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

发表于:2024-11-26 作者:热门IT资讯网编辑
编辑最后更新 2024年11月26日,本文示例代码下载: 链接:http://pan.baidu.com/s/1jHBdgCA 密码:hzh7ps:Vs数据库脚本在解压目录下,修改web.config数据库链接,示例代码包含:导入,导出,

本文示例代码下载: 链接: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上传功能

添加导入前端代码

Excel: @Resource.Browse @Resource.Uploading

导入按钮事件只要弹出上传框就好

  $("#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    {        ///         /// 校验Excel数据        ///         public bool CheckImportData( string fileName, List personList,ref ValidationErrors errors )        {                      var targetFile = new FileInfo(fileName);            if (!targetFile.Exists)            {                errors.Add("导入的数据文件不存在");                return false;            }            var excelFile = new ExcelQueryFactory(fileName);            //对应列头            excelFile.AddMapping(x => x.Name, "Name");            excelFile.AddMapping(x => x.Sex, "Sex");            excelFile.AddMapping(x => x.Age, "Age");            excelFile.AddMapping(x => x.IDCard, "IDCard");            excelFile.AddMapping(x => x.Phone, "Phone");            excelFile.AddMapping(x => x.Email, "Email");            excelFile.AddMapping(x => x.Address, "Address");            excelFile.AddMapping(x => x.Region, "Region");            excelFile.AddMapping(x => x.Category, "Category");            //SheetName            var excelContent = excelFile.Worksheet(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,                        "
")); } personList.Add(person); rowIndex += 1; } if (errors.Count > 0) { return false; } return true; } /// /// 保存数据 /// public void SaveImportData(IEnumerable 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    {        ///         /// 添加错误        ///         /// 信息描述        public void Add(string errorMessage)        {            base.Add(new ValidationError { ErrorMessage = errorMessage });        }        ///         /// 获取错误集合        ///         public string Error        {            get {                string error = "";                this.All(a => {                    error += a.ErrorMessage;                    return true;                });                return error;            }         }    }

ValidationError

代码包含两个方法

public bool CheckImportData( string fileName, List personList,ValidationErrors errors )

fileName为我们上传的文件。

personList为承接数据List

ValidationErrors 错误集合

public void SaveImportData(IEnumerable personList)

保存数据

别忘记添加接口

   public partial interface ISpl_PersonBLL    {        bool CheckImportData(string fileName, List personList, ref ValidationErrors errors);        void SaveImportData(IEnumerable personList);    }

简单明白,直接看代码,不再解析。OK这样控制器就可以直接调用了

  public ActionResult Import(string filePath)        {            var personList = new List();             //校验数据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(exportSpource.ToString());            var exportFileName = string.Concat(                "Person",                DateTime.Now.ToString("yyyyMMddHHmmss"),                ".xlsx");            return new ExportExcelResult            {                SheetName = "人员列表",                FileName = exportFileName,                ExportData = dt            };        }        private JArray GetExportData()        {            List 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);        }        ///         /// Exports the excel event handler.        ///         /// The context.        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(x => x.Name, "名字");

2.导入第几个sheet工作薄可以这么写

我这里写0是指第一个sheet工作薄。可以直接指定工作薄

var excelContent = excelFile.Worksheet("Sheet1");

3.检查正确性可以确保数据的来源。可以给出用户正确的修改提示。

4.借助ClosedXML,导出实际只需要几行代码。哈哈..这是如此的简单。

 return new ExportExcelResult            {                SheetName = "人员列表",                FileName = exportFileName,                ExportData = dt            };

0