.net导出Excel有很多方法, 用过直接生成二进制xls的方式, 经过长期的测试发现,不是很稳定.生成的xls文件经常打不开.
其中最稳定的方法当属Html格式的导出, 也就是直接拼接 xml字符串.
强烈建议是用输出html的方式导出Excel
为了简化和灵活的生成html格式的excel字符串. 我采用了RazorEngine.Core 模板引擎, 用它生成excel非常的灵活. 这样做的好处是可以自己灵活的定义表头… 一般应用都是要自定义表头的…虽然不及直接编辑xls文件方便, 但是胜在稳定性远超xls…
使用RazorEngine.Core 引擎直接解析渲染出excel的内容.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RazorEngine;
using RazorEngine.Templating; // For extension methods.
namespace Common.Excel
{
public class HtmlExcel
{
public static string ListToExcel<T>(List<T> dySource,string templateFileName)
{
var tk = Engine.Razor.GetKey(templateFileName);
if (Engine.Razor.IsTemplateCached(tk, typeof(List<T>)))
{
string excelhtml = Engine.Razor.Run(tk, typeof(List<T>), dySource);
return excelhtml;
} else {
string template = File.ReadAllText(templateFileName);//得到文件内容
string excelhtml = Engine.Razor.RunCompile(template, templateFileName, typeof(List<T>), dySource);
return excelhtml;
}
}
}
}
excel文件的模板文件
这样的好处是可以自定义表头. 特殊格式也可以通过自己写代码控制, 非常方便.比使用Excel文件做模板要稳定的多.
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns=" http: //www.w3.org/TR/REC-html40">
<head>
<!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
<x:Name>Worksheet</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets>
</x:ExcelWorkbook></xml><![endif]-->
<style type="text/css">
table td {
border: 1px solid #000000;
width: 200px;
height: 30px;
text-align: center;
background-color: #4f891e;
color: #ffffff;
}
</style>
</head>
<body>
<table class="excelTable">
<thead>
<tr>
<th>Id</th>
<th>仓位</th>
<th>商品简称</th>
<th>商品编码</th>
<th>商品名称</th>
<th>商品条码</th>
<th>入库批次号</th>
<th>入库时间</th>
<th>报检号</th>
<th>过期时间</th>
<th>价格</th>
<th>所属商家</th>
<th>期初盘点数量</th>
<th>现存量</th>
<th>占用量</th>
<th>可用量</th>
<th>长</th>
<th>宽</th>
<th>高</th>
<th>箱规</th>
<th>净重</th>
<th>毛重</th>
<th>商品单位</th>
<th>商品类别</th>
<th>材积</th>
</tr>
</thead>
<tbody>
@foreach (var row in Model)
{
<tr>
<td>@row.Id</td>
<td x:str>@row.仓位</td>
<td x:str>@row.商品简称</td>
<td x:str>@row.商品编码</td>
<td x:str>@row.商品名称</td>
<td x:str>@row.商品条码</td>
<td x:str>@row.入库批次号</td>
<td>@row.入库时间</td>
<td>@row.报检号</td>
<td>@row.过期时间</td>
<td>@row.价格</td>
<td x:str>@row.所属商家</td>
<td>@row.期初盘点数量</td>
<td>@row.现存量</td>
<td>@row.占用量</td>
<td>@row.可用量</td>
<td>@row.长</td>
<td>@row.宽</td>
<td>@row.高</td>
<td x:str>@row.箱规</td>
<td>@row.净重</td>
<td>@row.毛重</td>
<td x:str>@row.商品单位</td>
<td x:str>@row.商品类别</td>
<td>@row.材积 ******</td>
</tr>
}
</tbody>
</table>
</body>
</html>
关于excel文件模板的小提示
模板文件中 中的x:str 代表的是这个单元格的内容是文本, 同样的 代表的是这个单元格的内容是数字
其它的格式可以自己在Excel中修改后,用记事本打开查看区别和变化.
使用方法
var excelstring = Common.Excel.HtmlExcel.ListToExcel<View库存量导出>(list, "Export/库位系统库存量信息.cshtml");
HtmlExcelToWebDownload(excelstring, "库位系统库存量信息导出.xls");
补上HtmlExcelToWebDownload的代码.
internal void HtmlExcelToWebDownload(string excelstring, string filename = "Export.xls", string ContentType = "application/vnd.ms-excel")
{
//Response.Clear();
var buffer = System.Text.Encoding.UTF8.GetBytes(excelstring);
Response.ContentType = ContentType;
//Response.ContentEncoding = System.Text.Encoding.UTF8;
//Response.Charset = "utf-8";
Response.Headers.Add("Content-Length", buffer.Length.ToString());
Response.Headers.Add("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(filename));
//Response.AddHeader("Content-Disposition", "inline;FileName=out.pdf"); //如果需要预览而不是直接下载的话的话
//如果附件名为中文:Response.AddHeader("Content-Disposition", "attachment;FileName=" + HttpUtility.UrlEncode("中文.pdf"));
//Response.BodyWriter.WriteAsync(buffer);// Async 当文件超长时Async 会导致excel乱序
//Response.BodyWriter.FlushAsync();// Async 当文件超长时Async 会导致excel乱序
Response.Body.Write(buffer, 0, buffer.Length);
Response.Body.Flush();
Response.Body.Close();
}
如果
Response.Body.Write(buffer, 0, buffer.Length);
这一行出错
那么在Startup.cs文件中.
public void ConfigureServices(IServiceCollection services)
{
// If using Kestrel:
//services.Configure<KestrelServerOptions>(options =>
//{
// options.AllowSynchronousIO = true;
//});
// If using IIS:
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
}