我们先来看看效果图:

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

相关代码实现

我们来看相关代码:

页面代码:

@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 = , int pageSize = , 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 - ) * 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())即可。再结合数据特性配套使用,极大的提高了导出内容与格式的灵活性。

Magcodes.WeiChat——通过CsvFileResult以及DataAnnotations实现导出CSV文件的更多相关文章

  1. 导出csv文件示例

    导出csv文件示例 csv文件默认以英文逗号,做为列分隔符换行符\n作为行分隔符,写入到一个.csv文件即可.含有英文逗号,和换行符会发生数据输出会出现混乱,下面列出一些处理方法.特殊字符处理1.含有 ...

  2. mysql SQLyog导入导出csv文件

    1.选择数据库表 --> 右击属性 --> 备份/导出 --> 导出表数据作为 --> 选择cvs --> 选择下面的“更改” --> 字段 --> 变量长度 ...

  3. PHP 读取/导出 CSV文件

    工作中经常会有遇到导入/导出的需求,下面是常用的方法.读取CSV文件,可以分页读取,设置读取行数,起始行数即可.导出CSV文件,用两种方法进行实现. /** * 读取CSV文件 * @param st ...

  4. Web 端 js 导出csv文件(使用a标签)

    前言 导出文件,使用最多的方式还是服务器端来处理.比如jsp 中使用response 的方式. 但是,有时候可能就想使用web 前端是否也可以把页面上的内容导出来呢? 比如说,导出页面的一个表格. 这 ...

  5. PHP导出CSV文件出现乱码的解决方法

    在做项目时碰到使用外语的情况下,我们就会使用UTF-8编码.但是,在用PHP导出CSV文件时,如果写入的数据是使用UTF-8编码的日语.韩语之类的外文,就会出现乱码. 要解决PHP生成CSV文件的乱码 ...

  6. [转]PL/SQL Developer 导入导出csv文件

    PL/SQL Developer 可以导入或者导出CSV文件. 导入CSV文件步骤: 1.选择tools->text importer.... 2.选择第二个Data to oracle选项卡, ...

  7. 导出csv文件数字会自动变科学计数法的解决方法

    其实这个问题跟用什么语言导出csv文件没有关系.Excel显示数字时,如果数字大于12位,它会自动转化为科学计数法:如果数字大于15位,它不仅用于科学技术费表示,还会只保留高15位,其他位都变0.解决 ...

  8. web前端导出csv文件

    前言 导出文件,使用最多的方式还是服务器端来处理.比如jsp 中使用response 的方式. 但是,有时候可能就想使用web 前端是否也可以把页面上的内容导出来呢? 比如说,导出页面的一个表格. 这 ...

  9. 转:导出csv文件数字会自动变科学计数法的解决方法

    导出csv文件数字会自动变科学计数法的解决方法   其实这个问题跟用什么语言导出csv文件没有关系.Excel显示数字时,如果数字大于12位,它会自动转化为科学计数法:如果数字大于15位,它不仅用于科 ...

随机推荐

  1. Windows 7 下如何设置机器级别的DCOM权限

    Windows 7 下如何设置机器级别的DCOM权限 To grant Remote Activation permissions to the SMS Admins group From the S ...

  2. DataTable.Compute()用法

    DataTable.Compute()用法 2010-04-07 11:28 一.DataTable.Compute()方法說明如下 作用:          计算用来传递筛选条件的当前行上的给定表达 ...

  3. JavaScript valueOf() 函数详解

    valueOf()函数用于返回指定对象的原始值. 该方法属于Object对象,由于所有的对象都"继承"了Object的对象实例,因此几乎所有的实例对象都可以使用该方法. 所有主流浏 ...

  4. Log4j 配置 的webAppRootKey参数问题

    为了让Web项目中的Spring 使用Log4j做如下配置: 1.在web.xml中添加如下内容: <!--如果不定义webAppRootKey参数,那么webAppRootKey就是缺省的&q ...

  5. nginx环境下配置nagios-关于perl-fcgi.pl

    配置文件如下: 请注意,网上提供的官方文档在运行时可能会出现问题,此文中保证无问题. ; ; ; ;  ); ;  ); ; ;          my $pidnumber = $$;        ...

  6. Linux Shell脚本入门--cut命令

    Linux Shell脚本入门--cut命令 cut cut 命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields &l ...

  7. Servlet 利用Cookie实现一周内不重复登录

    import java.io.IOException;import java.io.PrintWriter; import javax.servlet.ServletException;import ...

  8. eclipse使用技巧、快捷键

    1.alt+/  自动提示符,可以快速补整,提高效率.  输入Sysout,再按下alt+/,就可以打印了.  输入main,再按下alt+/,可以直接显示main方法. 2.ctrl+左键,快速进入 ...

  9. [转][MSSQL]SQL Server 2008 记住密码功能

    本文转自:http://zhidao.baidu.com/link?url=V_laNOvutMin0kU3DUaMhLSFAYfgtz2IoEAjh8grNVPOZLpd8Pudb4iqZl88Tn ...

  10. 单片机TM4C123学习(八):SPI接口D/A

    1.头文件和变量定义(不是很清楚) #include "driverlib/ssi.h" #include "driverlib/i2c.h" #include ...