Magcodes.WeiChat——通过CsvFileResult以及DataAnnotations实现导出CSV文件
我们先来看看效果图:


从上图中可以看出,导出的文件中列名与表格名称保持一致,并且忽略了某些字段。
相关代码实现
我们来看相关代码:
页面代码:
@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> 搜索</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> 新建</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> 移动分组</a>
</span>
</div>
</div>
<a class="btn btn-info btn-sm" href="@Url.Action("Sync")"><i class="fa fa-circle-o"></i> 全量同步</a>
<a class="btn btn-warning btn-sm" href="@Url.Action("Index","WeiChatUsers")"><i class="fa fa-chevron-up"></i> 切换视图</a>
<button type="submit" class="btn btn-sm btn-primary" name="exportType" value="1"><i class="fa fa-file-archive-o"></i> 导出CSV</button>
@*<button type="submit" class="btn btn-sm btn-primary" name="exportType" value="2"><i class="fa fa-file-excel-o"></i> 导出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文件的更多相关文章
- 导出csv文件示例
导出csv文件示例 csv文件默认以英文逗号,做为列分隔符换行符\n作为行分隔符,写入到一个.csv文件即可.含有英文逗号,和换行符会发生数据输出会出现混乱,下面列出一些处理方法.特殊字符处理1.含有 ...
- mysql SQLyog导入导出csv文件
1.选择数据库表 --> 右击属性 --> 备份/导出 --> 导出表数据作为 --> 选择cvs --> 选择下面的“更改” --> 字段 --> 变量长度 ...
- PHP 读取/导出 CSV文件
工作中经常会有遇到导入/导出的需求,下面是常用的方法.读取CSV文件,可以分页读取,设置读取行数,起始行数即可.导出CSV文件,用两种方法进行实现. /** * 读取CSV文件 * @param st ...
- Web 端 js 导出csv文件(使用a标签)
前言 导出文件,使用最多的方式还是服务器端来处理.比如jsp 中使用response 的方式. 但是,有时候可能就想使用web 前端是否也可以把页面上的内容导出来呢? 比如说,导出页面的一个表格. 这 ...
- PHP导出CSV文件出现乱码的解决方法
在做项目时碰到使用外语的情况下,我们就会使用UTF-8编码.但是,在用PHP导出CSV文件时,如果写入的数据是使用UTF-8编码的日语.韩语之类的外文,就会出现乱码. 要解决PHP生成CSV文件的乱码 ...
- [转]PL/SQL Developer 导入导出csv文件
PL/SQL Developer 可以导入或者导出CSV文件. 导入CSV文件步骤: 1.选择tools->text importer.... 2.选择第二个Data to oracle选项卡, ...
- 导出csv文件数字会自动变科学计数法的解决方法
其实这个问题跟用什么语言导出csv文件没有关系.Excel显示数字时,如果数字大于12位,它会自动转化为科学计数法:如果数字大于15位,它不仅用于科学技术费表示,还会只保留高15位,其他位都变0.解决 ...
- web前端导出csv文件
前言 导出文件,使用最多的方式还是服务器端来处理.比如jsp 中使用response 的方式. 但是,有时候可能就想使用web 前端是否也可以把页面上的内容导出来呢? 比如说,导出页面的一个表格. 这 ...
- 转:导出csv文件数字会自动变科学计数法的解决方法
导出csv文件数字会自动变科学计数法的解决方法 其实这个问题跟用什么语言导出csv文件没有关系.Excel显示数字时,如果数字大于12位,它会自动转化为科学计数法:如果数字大于15位,它不仅用于科 ...
随机推荐
- python基础知识---变量
一.变量是什么? python变量是对内存中一个数据结构的引用,用一个变量给另外一个变量赋值,那就有两个变量引用同一个数据结构(数字.字符串.列表.元组.字典.自定义对象等) 当一个数据结构的引用计数 ...
- CSS3基础01
一.选择器: 分为关系选择器 ,属性选择器 ,伪类选择器 1.1关系选择器 后代选择器 ul li 选择所有的后代元素 子代选择器 ul > li 选择ul的儿子 紧邻选择器 .b ...
- WPF TextBlock文本纵向排列
一.将TextBlock文本纵向排列输出有两种模式. 1.文字正常放置,只是纵向排列. 2.文字同样旋转90度,纵向排列. 二.详见下文实例 1.文本正常放置,纵向排列. (1)后台代码 string ...
- MAT内存问题分析定位
MAT内存问题分析定位 1.下载安装MemoryAnalyzer工具. 2.使用DDMS将对应线程的内存日志导出来后,使用hprof-conv工具进行转换,用MAT打开转换后的hprof文件.
- Explode TArray
function Explode(const Separator, S: string; Limit: Integer = 0): TArray;var SepLen : Integer; F, P ...
- python变量——黑板客老师课程学习
1.和C++.Java的区别: 动态类型:不需要声明a的类型. a=34 type(a) <type ‘int’> 一切皆对象: 4 2.数字: 自动转换类型:a=34 A=3.14 ...
- __new__
[__new__] object.__new__(cls[, ...]) Called to create a new instance of class cls. 用于创建类对象cls的实例. __ ...
- Rstudio代码的快捷键
按tab键:有自动补全的功能 Ctrl+Enter:运行改行代码 Ctrl+1: 移动焦点到source编辑区 Ctrl+2: 移动焦点到控制台 Ctrl+enter Ctrl+L:删除该控制台的所有 ...
- spark streaming 实战
最近在学习spark的相关知识, 重点在看spark streaming 和spark mllib相关的内容. 关于spark的配置: http://www.powerxing.com/spark-q ...
- [转载] Android Studio 上第一个 Xposed 模块
本文转载自: http://www.open-open.com/lib/view/open1451364108964.html 环境: 已root手机一枚 Android Studio一枚 官方文档参 ...