• MVC 导出CSV


    其实本来的工作任务是要导出excel, 很普通的工作,但是实现的时候发现没有完美的解决办法, 最后改为导出CSV文件.

    导出Excel

    方法一

    导出一个Html的Table, 缺点是导出后在Excel中看不到网络线.

    如 http://stephenwalther.com/archive/2008/06/16/asp-net-mvc-tip-2-create-a-custom-action-result-that-returns-microsoft-excel-documents.aspx

    方法二

    先生成xml, 再通过xslt把数据转换成excel识别的格式. 缺点是维护,修改xslt比较困难.

    http://blogs.msdn.com/b/brian_jones/archive/2005/06/27/433152.aspx

     方法三

    调用Excel SDK, 缺点是要在服务器上安装Excel, 不通用, 而且如果出错的话, Kill Excel进程是个麻烦事.

     方法四

    调用开源组件epplus,推荐这个,在nopCommerce中就是用的它。

     

    导出CSV

    最后还是决定导出为csv格式, 但碰到的问题是导出中文乱码(用editplus打开正常), 即使是用Utf-8编码导出. 

    经过查找, 原来是因为excel默认是以ansi模式去开启csv文件的,并不直接支持unicode格式.

    解决办法, 添加BOM(UTF-8的BOM为EFBBBF)。 

     

    代码片断

    1,javascript调用

            jQuery(document).ready(function() {
                $("#btnExport").click(myExport);
            });
    
            function myExport() {
                var url = "/Credential/ExportToExcel?CredentialName={0}&Owner={1}";
    
                url = format(url,
                    $("#qCredentialName").val(),
                    $("#qOwner").val()
                );
    
                window.location.href = url;
            }
    

      2, Controller 

            public ActionResult ExportToExcel(string CredentialName, string Owner)
            {
                var items = repository.Search(CredentialName, Owner);
    
                var data = (
                        from item in items
                        select new
                        {
                            CredentialName = item.CredentialName,
                            Owner = item.Owner,
                            CredentialNo = item.CredentialNo,
                        }).ToList();
    
                StringBuilder sw = new StringBuilder("证件名称, 持有人, 证件编号");
                sw.AppendLine();
    
                foreach (var item in data)
                {
                    sw.Append(item.CredentialName).Append(",");
                    sw.Append(item.Owner).Append(",");
                    sw.Append(item.CredentialNo).Append(",");
                    sw.AppendLine();
                }
    
                return this.Excel(sw.ToString(), "证件资料.xls");
            }
    

      3, 帮助类

            ExcelControllerExtensions.cs        

    using System;
     using System.Web.Mvc;
     using System.Data.Linq;
     using System.Collections;
     using System.Web.UI.WebControls;
     using System.Linq;
     using System.Collections.Generic;
    
    namespace MIS.Helper
     {
         public static class ExcelControllerExtensions
         {
             public static ActionResult Excel
             (
                 this Controller controller,
                 string content,
                 string fileName
             )
             {
                 return new ExcelResult(content, fileName);
             }
    
         }
     }
    

      ExcelResult.cs

    using System;
    using System.Web.Mvc;
    using System.Data.Linq;
    using System.Collections.Generic;
    using System.IO;
    using System.Web.UI.WebControls;
    using System.Linq;
    using System.Web;
    using System.Text;
    using System.Web.UI;
    
    
    namespace MIS.Helper
     {
         public class ExcelResult : ActionResult
         {
             private string _fileName;
             private string _content;
    
             public string FileName
             {
                 get { return _fileName; }
             }
    
             public string Content
             {
                 get { return _content; }
             }
             
    
             public ExcelResult(string content, string fileName)
             {
                 _content = content;
                 _fileName = fileName;
             }
    
             public override void ExecuteResult(ControllerContext context)
             {
                 WriteFile(_fileName, "application/ms-excel", _content);
             }
    
             private static void WriteFile(string fileName, string contentType, string content)
             {
                 HttpContext context = HttpContext.Current;
    
                 fileName = HttpUtility.UrlEncode(fileName, Encoding.UTF8);    //对中文文件名进行HTML转码
    
                 byte[] buffer = Encoding.UTF8.GetBytes(content);
                 context.Response.ContentEncoding = Encoding.UTF8;
                 byte[] outBuffer = new byte[buffer.Length + 3];
                 outBuffer[0] = (byte)0xEF;//有BOM,解决乱码
                 outBuffer[1] = (byte)0xBB;
                 outBuffer[2] = (byte)0xBF;
                 Array.Copy(buffer, 0, outBuffer, 3, buffer.Length);
                 char[] cpara= Encoding.UTF8.GetChars(outBuffer); // byte[] to char[]
    
                 context.Response.Clear();
                 context.Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
                 context.Response.Charset = "";
                 context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                 context.Response.ContentType = contentType;
                 context.Response.Write(cpara, 0, cpara.Length);
                 context.Response.End();
             }
         }
     }
    

     

    OK,一切大功造成了. 但发现找开CSV时, Excel总是跳出一个安全警告. 实在看烦了它, 通过修改注册表把它搞定了.

    方法为: 打开注册表, 找到HKEY_CURRENT_USER->Software->Microsoft>Office>12.0>Excel>Security

    添加一DWORD值, 名称为ExtensionHardening, 值为0.

    关于BOM

    Q: What is a BOM?

    A: A byte order mark (BOM) consists of the character code U+FEFF at the beginning of a data stream, where it can be used as a signature defining the byte order and encoding form, primarily of unmarked plaintext files. Under some higher level protocols, use of a BOM may be mandatory (or prohibited) in the Unicode data stream defined in that protocol. 

    摘自 http://unicode.org/faq/utf_bom.html#bom1;

  • 相关阅读:
    深刻理解Docker镜像大小
    UVA 12657 Boxes in a Line
    STL 之 iterator traits 备忘
    python设计模式 之 简单工厂模式
    extjs 时间范围选择的实现
    数据结构
    nodeJS npm grunt grunt-cli
    Ubuntu: GlusterFS+HBase安装教程
    ubuntu 休眠之后蓝牙鼠标无效果。
    基于sparksql调用shell脚本运行SQL
  • 原文地址:https://www.cnblogs.com/season2009/p/2680298.html
Copyright © 2020-2023  润新知