一、基于Aspose.Cells、Dapper导出Excel

Dapper的Query返回要不是对象的IEnumerable,要不是Dynamic的IEnumerable,都不适合不用反射就能够动态获取各个属性值得情况,而反射浪费性能是大伙儿共同认知的,Down下来Dapper源码发现返回Dynamic的IEnumerable,是返回一个Dapper内部的对象DapperRow的Dynamic的IEnumerable,而DapperRow是可以通过属性索引的,当然需要做一下小的改变:

这就好办了,如下是基于Aspose.Cells

关于Aspose.Cells可以基于excel模板来生成Excel,这点解释如下:

  1. &=DataSource.Field,&=[DataSource].[Field]是对DataTable或集合类型的引用,将会从当前行开始竖直向下生成多行数据。
  2. &=$data:是对变量或数组的引用。数组存在skip,horizontal等属性
  3. &=&=动态公式计算;{r}当前行,{c}当前列,{-n},{n}当前行或列的偏移量前n或后n。
  4. &==是动态计算,如excel,if等语句。(if(logic_test,true_value,false_value))
public struct KeyValueDic
{
public KeyValueDic(string key,string value)
{
this.Key = key;
this.Value = value;
this.IsMutilText = false;
this.MatchText = null;
this.MatchTextDic = null;
} public KeyValueDic(string key, string value,bool isMutilText)
{
this.Key = key;
this.Value = value;
this.IsMutilText = isMutilText;
this.MatchText = null;
this.MatchTextDic = null;
} public KeyValueDic(string key, string value, string matchText)
{
Key = key;
Value = value;
IsMutilText = false;
MatchText = matchText;
MatchTextDic = null;
MatchTextDic = GetDic(matchText);
} public KeyValueDic(string key, string value, bool isMutilText, string matchText)
{
Key = key;
Value = value;
IsMutilText = isMutilText;
MatchText = matchText;
MatchTextDic = null;
MatchTextDic = GetDic(matchText);
}
public string Key { get; set; }//列名 public string Value { get; set; }//列中文名 public bool IsMutilText { get; set; }//是否是大字段 public string MatchText { get; set; }//需要匹配的文本,例sex=0;1,0;男,1;女,other;未知 public Dictionary<string, string> MatchTextDic { get; private set; } private Dictionary<string, string> GetDic(string text)
{
if (string.IsNullOrEmpty(text))
return null;
string[] _strs = text.Split(',');
if (_strs.Length == )
return null;
Dictionary<string, string> _dic = new Dictionary<string, string>();
foreach (string item in _strs)
{
string[] _strItems = item.Split(';');
if (_strItems.Length != ||string.IsNullOrEmpty(_strItems[]))
return null;
_dic.Add(_strItems[], _strItems[]);
}
return _dic;
} }
public class ExcelUtils
{
private static Style HeadStyle(Workbook workbook)//头部样式
{
//为单元格添加样式
Aspose.Cells.Style headStyle = workbook.Styles[workbook.Styles.Add()];
headStyle.HorizontalAlignment = Aspose.Cells.TextAlignmentType.Center;
headStyle.Pattern = BackgroundType.Solid;
headStyle.Font.IsBold = true;
headStyle.ForegroundColor = System.Drawing.Color.Blue;
headStyle.Font.Color = System.Drawing.Color.White;
headStyle.Font.IsSubscript = true;
headStyle.Font.Size = ;
headStyle.Borders[BorderType.LeftBorder].LineStyle = CellBorderType.Thin;
headStyle.Borders[BorderType.RightBorder].LineStyle = CellBorderType.Thin;
headStyle.Borders[BorderType.TopBorder].LineStyle = CellBorderType.Thin;
headStyle.Borders[BorderType.BottomBorder].LineStyle = CellBorderType.Thin;
return headStyle;
} private static Style BodyStyle(Workbook workbook)//文本样式
{
Aspose.Cells.Style bodyStyle = workbook.Styles[workbook.Styles.Add()];
bodyStyle.Borders[BorderType.LeftBorder].LineStyle = CellBorderType.Thin;
bodyStyle.Borders[BorderType.RightBorder].LineStyle = CellBorderType.Thin;
bodyStyle.Borders[BorderType.TopBorder].LineStyle = CellBorderType.Thin;
bodyStyle.Borders[BorderType.BottomBorder].LineStyle = CellBorderType.Thin;
bodyStyle.IsTextWrapped = true;
return bodyStyle;
} public static Stream SaveToStream(IEnumerable<DapperRow> list, List<KeyValueDic> listColumns, string sheetName)
{
if (list == null || list.Count() == || listColumns == null || listColumns.Count == || listColumns.Count > list.ElementAt().Count())
throw new Exception("Excel数据源不匹配导致无法保存!"); Workbook workbook = new Workbook();
Worksheet sheet = (Worksheet)workbook.Worksheets[];
sheet.Name = sheetName; for (int i = ; i < listColumns.Count; i++)
{
sheet.Cells[, i].PutValue(listColumns[i].Value);
if (listColumns[i].IsMutilText)
sheet.Cells.SetColumnWidth(i, );
}
sheet.Cells.CreateRange(, , , listColumns.Count).SetStyle(HeadStyle(workbook));
int row = ;
foreach (var item in list)
{
row++;
for (int i = ; i < listColumns.Count; i++)
{
object val = item[listColumns[i].Key];
if (val == null)
continue;
if (val.GetType() == typeof(DateTime))//时间格式
{
DateTime dtime = (DateTime)val;
if (dtime.Hour == || dtime.Minute == || dtime.Second == )
sheet.Cells[row, i].PutValue(dtime.ToString("yyyy-MM-dd"));
else
sheet.Cells[row, i].PutValue(dtime.ToString("yyyy-MM-dd HH:mm:ss"));
}
else if (listColumns[i].MatchText != null && listColumns[i].MatchTextDic != null)//是否有需要匹配的文本
{
string _val = val.ToString();
if (listColumns[i].MatchTextDic.ContainsKey(_val))
sheet.Cells[row, i].PutValue(listColumns[i].MatchTextDic[_val]);
else
sheet.Cells[row, i].PutValue(listColumns[i].MatchTextDic["other"]);
}
else
sheet.Cells[row, i].PutValue(val.ToString());
}
}
sheet.Cells.CreateRange(, , row, listColumns.Count).SetStyle(BodyStyle(workbook));
for (int i = ; i < listColumns.Count; i++)
{
if (!listColumns[i].IsMutilText)
sheet.AutoFitColumn(i);
}
sheet.AutoFitRows();
MemoryStream ms = new MemoryStream();
workbook.Save(ms, SaveFormat.Excel97To2003);
ms.Position = ;
return ms;
} }

logic:

public static class Utils
{
private static log4net.ILog log = log4net.LogManager.GetLogger("FMDS"); /// <summary>
/// 将指定的字符串信息写入日志。
/// </summary>
/// <param name="message">需要写入日志的字符串信息。</param>
public static void Log(string message)
{
log.Info(message);
}
/// <summary>
/// 将指定的异常实例详细信息写入日志
/// </summary>
public static void Log(Exception ex)
{
log.Error("Exception:", ex);
}
/// <summary>
/// 将指定的异常实例详细信息写入日志。
/// </summary>
public static void Log(object message, Exception e)
{
log.Error(message, e);
} public static string TrimOrNull(this string str)
{
return str == null ? null : str.Trim();
} }
public class DbConnection
{
public static SqlConnection OpenConnection()
{
if (string.IsNullOrEmpty(ConfigUtils.ConStr))
{
Utils.Log("数据库连接失败:没有读取到FMDS链接字符串。");
return null;
}
SqlConnection connection = new SqlConnection(ConfigUtils.ConStr);
try
{
connection.Open();
return connection;
}
catch (Exception ex)
{
Utils.Log("数据库FMDS连接失败:" + ex.Message);
return null;
}
}
}
public Stream Export()
{ string sql = @""; var param = new DynamicParameters();
param.Add("mydate", DateTime.Today, System.Data.DbType.DateTime); using (SqlConnection conn = DbConnection.OpenFMJConnection())
{
if (conn == null)
return null;
var list=conn.Query<SqlMapper.DapperRow>(sql, param);
List<KeyValueDic> listKeyValue = new List<KeyValueDic>()
{
new KeyValueDic("Column1","列1"),
new KeyValueDic("Column2","列2","0;男,1;女,other;未知"),
new KeyValueDic("Column3","列3",true)
};
System.IO.Stream stream = ExcelUtils.SaveToStream(list, listKeyValue, "excelSheetName");
return stream;
}
}
Action中使用: public FileResult Export()
{
Stream stream = logic.Export();
return File(stream, "application/vnd.ms-excel", DateTime.Now.ToString("yyyyMMddHHmmss") + "—excelName.xls");
}//"application/ms-excel",
View中使用: window.location.href = "@Url.Action("Export")";
二、基于System.Web.UI.WebControls.DataGrid、Ado.net导出Excel public void ExportExcel(DataTable dt, string filename)
{
StringWriter stringWriter = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
//使用System.Web.UI.WebControls的DataGrid导出excel
DataGrid excel = new DataGrid();
System.Web.UI.WebControls.TableItemStyle headerStyle = new TableItemStyle();//标题行样式
headerStyle.BackColor = System.Drawing.Color.LightGray;
headerStyle.Font.Bold = true;
headerStyle.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center;
excel.HeaderStyle.MergeWith(headerStyle);
System.Web.UI.WebControls.TableItemStyle alternatingStyle = new TableItemStyle();//隔行样式
alternatingStyle.BackColor = System.Drawing.Color.LightGray;
excel.AlternatingItemStyle.MergeWith(alternatingStyle);
System.Web.UI.WebControls.TableItemStyle itemStyle = new TableItemStyle();//单元格样式
itemStyle.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center;
excel.ItemStyle.MergeWith(itemStyle); excel.GridLines = GridLines.Both;
excel.HeaderStyle.Font.Bold = true;
excel.DataSource = dt.DefaultView;//输出DataTable的内容
excel.DataBind();
excel.RenderControl(htmlWriter);
MemoryStream stream = new MemoryStream();
System.IO.StreamWriter sw = new StreamWriter(stream, System.Text.Encoding.UTF8);
sw.Write(stringWriter.ToString());
sw.Flush();
DownResult(stream, filename);
} public ActionResult DownResult(Stream stream,string fileName)
{
stream.Position = ;
const int ChunkSize = ;
byte[] buffer = new byte[ChunkSize];
long dataLengthToRead = stream.Length;
Response.Clear();
Response.Charset = "UTF-8";
Response.ContentType = "application/octet-stream";
Response.AppendHeader("content-disposition", string.Format("attachment;filename={0}.xls", fileName));
Response.AppendHeader("Content-Length", dataLengthToRead.ToString());
Response.Filter.Close();
while (dataLengthToRead > && Response.IsClientConnected)
{
int lengthRead = stream.Read(buffer, , ChunkSize);
Response.OutputStream.Write(buffer, , lengthRead);
Response.Flush();
dataLengthToRead = dataLengthToRead - lengthRead;
}
stream.Close();
stream.Dispose();
Response.Flush();
/*****
这里可以做一些自己的处理,比如把谁下载的文件信息存到库里,但是这个时候,就不能用Response.Close();了,否则报下载失败,网络错误。这里可以使用如下(需放在自己的处理程序之后):
       参考:https://blogs.msdn.microsoft.com/aspnetue/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation/
        http://stackoverflow.com/questions/5533068/httpcontext-throws-httpexception
http://stackoverflow.com/questions/1087777/is-response-end-considered-harmful
if (Response.IsClientConnected)
{
Response.SuppressContent = true;//Prevents any other content from being sent to the browser
HttpContext.ApplicationInstance.CompleteRequest();//Directs the thread to finish, bypassing additional processing
}
GC.Collect();
*****/
Response.Close();//不要直接用Response.End();
return new EmptyResult();
}

附:以上代码偶尔仍回抛如下异常“System.Web.HttpException (0x80070057): 远程主机关闭了连接。错误代码是 0x80070057。”

突然在异常错误日志中看到这个错误,虽然在测试中发现不影响流的传输,但是不代表没错误,解决方法如下:
  Response.Flush();   Response.End();//结束文件下载,但是程序在运行时会报出“正在中止线程”的错误,可以确定的是引起错误的代码就是Response.End(),所以需要删除此方法。 在IIS .5下这样做问题就解决了,不过在IIS 7.0 下又会报出另外一个错误“与远程主机通信时发生错误。错误代码是 0x800704CD。” 在网上翻查了一翻资料后,终于找到了解决方法: 就是将Response.End();换成Response.Close(); 总结一下,帮助对Response.Close的解释是关闭到客户端的连接。对Response.End的解释是停止该页的执行,并引发Application_EndRequest。也就说用Response.End程序就直接停止后面的工作了转而触发Application_EndRequest,那么当程序在后面还有代码需要运行时,程序就会抛出ThreadAbortException的异常。还有需要了解的就是end方法在不抛出异常时还会调用flush的方法。接着来,close方法是关闭了连接,也就说程序顺利执行完了所有代码后关闭了连接。对于只运行flush后报出的“与远程主机通信时发生错误”,我的理解是当执行了flush后在底层马上开始向客户端发送数据,但是flush貌似只能指示 程序开始连接发送,却没有停止关闭的标识,导致程序报出异常。当然这是在IIS .0下会出错(可能在IIS 7.0 开始在调用flush后需要显示关闭socket连接)。所以以后再在用完flush后最好加上close。就像数据库连接一样,用完就关闭连接。

如下是Response.End()的source code:

public void End()
{
if (this._context.IsInCancellablePeriod)
{
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
}
else if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}

也就是说使用Response.End()是包含了Response.Flush()的功能的。

附:Response.End()同样是报(偶尔情况下):

at System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect)
at System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush()
at System.Web.HttpResponse.Flush(Boolean finalFlush)
at System.Web.HttpResponse.Flush()

参照:https://blogs.msdn.microsoft.com/aspnetue/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation/

修改为如下(待测试吧):

//Response.End();
HttpContext.ApplicationInstance.CompleteRequest();

mvc Dapper_Report_Down_ExcelFile的更多相关文章

  1. Asp.Net Mvc 使用WebUploader 多图片上传

    来博客园有一个月了,哈哈.在这里学到了很多东西.今天也来试着分享一下学到的东西.希望能和大家做朋友共同进步. 最近由于项目需要上传多张图片,对于我这只菜鸟来说,以前上传图片都是直接拖得控件啊,而且还是 ...

  2. .Net Core MVC 网站开发(Ninesky) 2.4、添加栏目与异步方法

    在2.3中完成依赖注入后,这次主要实现栏目的添加功能.按照前面思路栏目有三种类型,常规栏目即可以添加子栏目也可以选择是否添加内容,内容又可以分文章或其他类型,所以还要添加一个模块功能.这次主要实现栏目 ...

  3. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库

    在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...

  4. ASP.NET Core MVC/WebAPi 模型绑定探索

    前言 相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用 ...

  5. ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入

    原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...

  6. 开源:Taurus.MVC 框架

    为什么要创造Taurus.MVC: 记得被上一家公司忽悠去负责公司电商平台的时候,情况是这样的: 项目原版是外包给第三方的,使用:WebForm+NHibernate,代码不堪入目,Bug无限,经常点 ...

  7. Taurus.MVC 2.2 开源发布:WebAPI 功能增强(请求跨域及Json转换)

    背景: 1:有用户反馈了关于跨域请求的问题. 2:有用户反馈了参数获取的问题. 3:JsonHelper的增强. 在综合上面的条件下,有了2.2版本的更新,也因此写了此文. 开源地址: https:/ ...

  8. Taurus.MVC 2.0 开源发布:WebAPI开发教程

    背景: 有用户反映,Tausus.MVC 能写WebAPI么? 能! 教程呢? 嗯,木有! 好吧,刚好2.0出来,就带上WEBAPI教程了! 开源地址: https://github.com/cyq1 ...

  9. 使用Visual Studio 2015 开发ASP.NET MVC 5 项目部署到Mono/Jexus

    最新的Mono 4.4已经支持运行asp.net mvc5项目,有的同学听了这句话就兴高采烈的拿起Visual Studio 2015创建了一个mvc 5的项目,然后部署到Mono上,浏览下发现一堆错 ...

随机推荐

  1. Bus of Characters(栈和队列)

    In the Bus of Characters there are nn rows of seat, each having 22 seats. The width of both seats in ...

  2. PAT 1058 选择题

    https://pintia.cn/problem-sets/994805260223102976/problems/994805270356541440 批改多选题是比较麻烦的事情,本题就请你写个程 ...

  3. pythoh使用 xpath去除空格空格

    html_str = """ <!DOCTYPE html> <html lang="en"> <head> &l ...

  4. Jenkins系列-Jenkins构建触发器

    触发器说明 build whenever a snapshot dependency is built,当job依赖的快照版本被build时,执行本job. 触发远程构建 (例如,使用脚本):这里使用 ...

  5. php中的<?= ?>替换<?php echo ?>

    首先修改PHP.ini文件.如下: 1. 将short_open_tag = Off 改成On 开启以后可以使用PHP的短标签:<? ?> <?= $test ?>来代替 &l ...

  6. 安全的API接口解决方案

    在各种手机APP泛滥的现在,背后都有同样泛滥的API接口在支撑,其中鱼龙混杂,直接裸奔的WEB API大量存在,安全性令人堪优 在以前WEB API概念没有很普及的时候,都采用自已定义的接口和结构,对 ...

  7. PL/SQL在 win8.1系统下连接Oracle11g没有database处理方法(亲身实验,吐血分享)

    一.问题 这里首先说明下我的环境:win8.1(64bit)+oracle11g(64bit)+PL/SQL(32bit).状况是:net manager正常配置,测试也成功,但是用PL/SQL连接的 ...

  8. java中sql语句能不能加分号的问题?

    一.原因  在程序运行中,当执行sql后总是报无效字符错误:但是把程序放在pl/sql中执行又没有错误.让我很纳闷!于是我开始查找资料,然后我终于发现了问题. 二.问题剖析 原来在程序中:如果你在程序 ...

  9. 进程&线程间通信方式总结

    一.进程间的通信方式 # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系. # 有名管道 (namedpip ...

  10. Spring AOP 源码解析

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...