我们先来看看效果图:

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

相关代码实现

我们来看相关代码:

页面代码:

@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. SQLite数据库文件格式

    数据库命名约定 sqlite3_open()API用到数据库的文件名,可以是相对当前工作目录的相对路径名,也可以是从系统根文件树开始的完整路径名.任何被本地文件系统接受的正规文件名都是好的. 如果文件 ...

  2. MySQL_杭州11月销售昨日未上架的SKU_20161212

    #C034杭州11月销售昨日未上架的SKU SELECT 城市,a.订单日期,a.客户数,a.订单数,b.产品数,a.金额,c.销售确认额,c.毛利额,c.毛利率 FROM ( SELECT 城市,订 ...

  3. IntelliJ IDEA 16 本地LicenseServer激活(破解)

    IntelliJ IDEA 16 本地LicenseServer激活(破解) IntelliJ IDEA 是Java开发利器,用社区版不爽,干催就用旗舰版,这个是收费的,需要licence. 网上找到 ...

  4. Redis过期时间

    上次开发用了redis后效果不错,后来在进阶的开发中查询到,如果redis一直不释放也会占用内存,于是就想着给redis加上个过期时间. 具体操作很简单,只要在设置redis的时候加上exp就可以了, ...

  5. access数据库连接问题

    使用Visual Studio连接access数据库(数据库后缀.accdb)时连接不上(access数据库提示未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序)解决办 ...

  6. [转] mhvtl虚拟磁带库的安装与应用

    转自:candon123  -- http://candon123.blog.51cto.com/704299/388192/ 1.获取mhvtl: 官方网站:http://mhvtl.nimsa.u ...

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

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

  8. yii2.0 Cache缓存

    1.控制器中CacheDemoController.php 1 <?php 2 /** 3 * Created by PhpStorm. 4 * User: liangzi 5 * Date: ...

  9. Windows上安装Maven

    Maven的具体参考书可以看:<Maven实战> 下载maven可以到:http://maven.apache.org/ Maven的eclipse基本使用可以在这里看到:http://w ...

  10. acm入门编成题

    http://wenku.baidu.com/view/c8f2f64acf84b9d528ea7aee.html