Magcodes.WeiChat——通过CsvFileResult以及DataAnnotations实现导出CSV文件

简介: 我们先来看看效果图: 从上图中可以看出,导出的文件中列名与表格名称保持一致,并且忽略了某些字段。 相关代码实现 我们来看相关代码: 页面代码: @using (Html.BeginForm("Index", @Request.

我们先来看看效果图:

image

image

从上图中可以看出,导出的文件中列名与表格名称保持一致,并且忽略了某些字段。

相关代码实现

我们来看相关代码:

页面代码:

@using (Html.BeginForm("Index", @Request.RequestContext.RouteData.GetRequiredString("controller"), FormMethod.Get))
                    {
                        <div class="row">
                            <div class="col-sm-3">

                                <div class="input-group">
                                    @Html.TextBox("q", ViewBag.q as string, new { @placeholder = "请输入关键字", @class = "input-sm form-control" })
                                    <span class="input-group-btn">
                                        <button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-search"></i>&nbsp;搜索</button>
                                    </span>
                                </div>

                            </div>
                            @*<div class="col-sm-2">
                                    <a class="btn btn-primary btn-sm" href="@Url.Action("Create")" id="btnAdd"><i class="fa fa-plus"></i>&nbsp;新建</a>
                                </div>*@

                            <div class="col-sm-3">
                                <div class="input-group">
                                    @Html.DropDownList("UserGroups", null, htmlAttributes: new { @class = "input-sm form-control" })
                                    <span class="input-group-btn">
                                        <a class="btn btn-success btn-sm" id="btnMove" data-action="Move" data-comfirmmessage="确定要移动所选用户么?"><i class="fa  fa-arrow-circle-o-right"></i>&nbsp;移动分组</a>
                                    </span>
                                </div>

                            </div>
                            <a class="btn btn-info btn-sm" href="@Url.Action("Sync")"><i class="fa fa-circle-o"></i>&nbsp;全量同步</a>
                            <a class="btn btn-warning btn-sm" href="@Url.Action("Index","WeiChatUsers")"><i class="fa fa-chevron-up"></i>&nbsp;切换视图</a>
                            <button type="submit" class="btn btn-sm btn-primary" name="exportType" value="1"><i class="fa fa-file-archive-o"></i>&nbsp;导出CSV</button>
                            @*<button type="submit" class="btn btn-sm btn-primary" name="exportType" value="2"><i class="fa fa-file-excel-o"></i>&nbsp;导出Excel</button>*@
                        </div>
                    }

控制器代码:

// GET: WeiChat_User
        public async Task<ActionResult> Index(string q, int pageIndex = 1, int pageSize = 10, ExportTypes exportType = ExportTypes.None)
        {
            var syncHelper = new SyncHelper();
            //同步微信用户组
            await syncHelper.Sync(WeiChat_SyncTypes.Sync_WeiChat_User, TenantId, true, UserId);
            var queryable = db.WeiChat_Users.AsQueryable();
            if (!string.IsNullOrWhiteSpace(q))
            {
                //请替换为相应的搜索逻辑
                queryable = queryable.Where(p => p.NickName.Contains(q) || p.City.Contains(q) || p.Country.Contains(q) || p.Province.Contains(q) || p.Remark.Contains(q));
            }
            queryable = queryable.OrderByDescending(p => p.SubscribeTime);
            switch (exportType)
            {
                case Helpers.ExportTypes.Csv:
                    return Csv(queryable.ToList());
                //case Helpers.ExportTypes.Excel:
                //    return Excel(queryable.ToList());

            }
            var pagedList = new PagedList<WeiChat_User>(
                             await queryable
                             .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(),
                             pageIndex, pageSize, await queryable.CountAsync());
            var myGroups = db.WeiChat_UserGroups.Where(p => p.TenantId == TenantId).ToList();
            foreach (var item in pagedList)
            {
                item.UserGroup = myGroups.FirstOrDefault(p => p.GroupId == item.GroupId);
            }
            ViewBag.UserGroups = new SelectList(myGroups, "GroupId", "Name");
            return View(pagedList);
        }

注意上述代码中的Csv方法,通过该方法可以将当前List导出为CSV。而且支持查询结果导出。

CSV方法封装在TenantBaseController<TEntry>中,具体实现如下:

/// <summary>
        /// 导出CSV
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>

        public ActionResult Csv(IEnumerable<TEntry> data)
        {
            return new CsvFileResult<TEntry>(data);
        }

CsvFileResult<T>代码如下:

/// <summary>
    /// 导出CSV格式文件
    /// </summary>
    /// <typeparam name="T">实体数据类型</typeparam>
    //http://joshclose.github.io/CsvHelper/
    public class CsvFileResult<T> : FileResult where T : class
    {
        private IEnumerable<T> _data;

        public CsvFileResult(IEnumerable<T> data)
            : base("text/csv")
        {
            this.FileDownloadName = string.Format("{0}.csv",DateTime.Now.ToString("yyyyMMddHHmmss"));
            _data = data;
        }

        protected override void WriteFile(HttpResponseBase response)
        {
            var outPutStream = response.OutputStream;
            using (var streamWriter = new StreamWriter(outPutStream, System.Text.Encoding.UTF8))
            using (var writer = new CsvWriter(streamWriter))
            {
                writer.WriteHeader<T>();
                foreach (var item in _data)
                {
                    writer.WriteRecord(item);
                }
                streamWriter.Flush();
                response.Flush();
            }
        }
    }

这里使用到了CsvHelper。框架对CsvHelper进行了修改,以支持Display特性以及ExportIgnore特性。

ExportIgnoreAttribute

导出时忽略此属性

DisplayAttribute

指定本地化显示的字符串,这里使用其Name属性作为导出内容的字段友好名称

如前面导出内容所示,WeiChat_User定义如下:

/// <summary>
    /// 微信用户信息
    /// </summary>
    public class WeiChat_User : ITenantId
    {
        /// <summary>
        /// 用户的标识,对当前公众号唯一
        /// </summary>
        [Key]
        [Display(Name = "OpenId")]
        public string OpenId { get; set; }
        /// <summary>
        /// 用户是否订阅该公众号标识
        /// </summary>
        [Display(Name = "是否订阅")]
        public bool Subscribe { get; set; }

        /// <summary>
        /// 用户的昵称
        /// </summary>
        [Display(Name = "昵称")]
        public string NickName { get; set; }
        /// <summary>
        /// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
        /// </summary>
        [Display(Name = "性别")]
        public WeChatSexTypes Sex { get; set; }
        /// <summary>
        /// 用户所在城市
        /// </summary>
        [Display(Name = "所在城市")]
        public string City { get; set; }
        /// <summary>
        /// 用户所在国家
        /// </summary>
        [Display(Name = "所在国家")]
        public string Country { get; set; }
        /// <summary>
        /// 用户所在省份
        /// </summary>
        [Display(Name = "所在省份")]
        public string Province { get; set; }

        /// <summary>
        /// 用户的语言,简体中文为zh_CN
        /// </summary>
        [Display(Name = "语言")]
        public string Language { get; set; }
        /// <summary>
        /// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
        /// </summary>
        [Display(Name = "头像")]
        public string HeadImgUrl { get; set; }
        /// <summary>
        /// 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
        /// </summary>
        [Display(Name = "关注时间")]
        public DateTime SubscribeTime { get; set; }
        /// <summary>
        /// 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。详见:获取用户个人信息(UnionID机制)
        /// </summary>
        [Display(Name = "UnionId")]
        public string UnionId { get; set; }
        /// <summary>
        /// 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
        /// </summary>
        [Display(Name = "备注")]
        public string Remark { get; set; }
        /// <summary>
        /// 用户所在的分组ID
        /// </summary>
        [Display(Name = "分组Id")]
        public int? GroupId { get; set; }
        /// <summary>
        /// 所在用户组
        /// </summary>
        [Display(Name = "所在用户组")]
        [NotMapped]
        [ExportIgnore]
        public WeiChat_UserGroup UserGroup { get; set; }
        /// <summary>
        /// 是否允许测试
        /// </summary>
        [Display(Name = "测试用户")]
        [ExportIgnore]
        public bool AllowTest { get; set; }
        [ExportIgnore]
        public int TenantId { get; set; }
}

注意:字段“UserGroup”,“AllowTest”,“TenantId“将在导出时被忽略,同时导出字段名使用Display特性中的Name属性。

总结:通过封装CsvFileResult可以极大的简化导出CSV的编码工作,只需要在Action中return Csv(queryable.ToList())即可。再结合数据特性配套使用,极大的提高了导出内容与格式的灵活性。

目录
相关文章
|
6月前
|
Java Apache
导出csv格式的文件
导出csv格式的文件
54 0
|
3月前
|
存储 Python
使用CSV模块读取CSV文件--含代码
使用CSV模块读取CSV文件--含代码
25 0
|
3月前
|
开发框架 算法 .NET
C#使用MiniExcel导入导出数据到Excel/CSV文件
C#使用MiniExcel导入导出数据到Excel/CSV文件
70 0
|
6月前
|
XML JSON 数据处理
C# | 导出DataGridView中的数据到Excel、CSV、TXT
从DataGridView中导出数据到Excel、CSV、TXT是开发中非常常见的一种需求。本文将讲解如何高效的完成对这三种格式的单向导出。 倘若直接写三种格式的导出必定会产生大量的重复代码,而从表中获取结构化数据的思路是基本一致的,因此有一个思路是先将DataGridView中的数据转换为DataTable对象,再进一步导出成我们的目标格式。 本文将介绍如何将DataGridView中的数据转换为DataTable格式,并提供将DataTable转换为Excel、CSV、TXT三种格式的例子。
533 0
C# | 导出DataGridView中的数据到Excel、CSV、TXT
|
11月前
|
前端开发 小程序 JavaScript
phpexcel(二)导入excel文件
有导出。自然就有导入。功能多样化嘛。 我这里使用的是laravel5.8框架(框架老点,但是这玩意完全就是一个自定义方法,跟框架版本什么的没有关系)
56 1
|
前端开发
前端实现导出word(docxtemplater、pizzip、jszip-utils、file-saver )
docxtemplater、pizzip、jszip-utils、file-saver 前端实现导出word
1215 0
前端实现导出word(docxtemplater、pizzip、jszip-utils、file-saver )
|
关系型数据库 数据库 PostgreSQL
导出CSV文件
导出CSV文件
377 0
es数据导出csv文件
es数据导出csv文件
|
数据格式
举例:Excel怎么导出手机通讯录vCard文件?
知识拓展1:标准通信薄基本格式 VCard 数据格式的标识符是VCARD 预定义的值类型:uri, date, date-time, float 新增加的值类型:binary, phone-number, utc-offset and vcard value 预定义的类型:SOURCE, NAME, PROFILE, BEGIN, END. 新增加的类型:FN, N, NICKNAME, PHOTO, BDAY, ADR, LABEL, TEL, EMAIL, MAILER, TZ, GEO, TITLE, ROLE, LOGO, AGENT, ORG, CATEGORIES, NOTE,
举例:Excel怎么导出手机通讯录vCard文件?
|
关系型数据库 MySQL 中间件
Hyperf结合PhpOffice/PhpSpreadsheet实现Excel&CSV文件导出导入
Hyperf结合PhpOffice/PhpSpreadsheet实现Excel&CSV文件导出导入。PhpSpreadsheet是一个用纯PHP编写的库,它提供了一组类,允许您读取和写入各种电子表格文
978 0
Hyperf结合PhpOffice/PhpSpreadsheet实现Excel&CSV文件导出导入