如何将Kendo Grid数据导出到Excel / CSV / ZipFile - 替代方法

时间:2017-02-09 11:40:25

标签: c# excel kendo-grid kendo-asp.net-mvc epplus

假设您有一个kendo网格,并希望将数据导出为Excel或CSV文件格式。

使用通用的Kendo方法,您会发现它变得非常困难,因为它还会带来大量元数据。这将使大型擅长无用。

使用下面的方法,您可以导出到Excel,CSV,并考虑过滤器和其他。

1 个答案:

答案 0 :(得分:1)

首先在cshtml文件中定义JS函数和kendo网格:

    @section scripts{
    <script>
        function DownloadExcelFile(e)
        {
            if(e != "undefined")
                e.preventDefault();
            var grid = $("#mainGrid").data("kendoGrid");
            var parameterMap = grid.dataSource.transport.parameterMap;
            var data = parameterMap({ sort: grid.dataSource.sort(), filter: grid.dataSource.filter(), group: grid.dataSource.group() });
            window.location = "Report/GetSummaryExcelReport?" + "filter=" + data.filter + "&sort=" + data.sort + "&group=" + data.group;

            return false;
        }
    </script>
    }


<div class="col-md-12 col-sm-12 col-xs-12 text-center padding-0 inner">
    <div class="grid-area">
        @(Html.Kendo().Grid<SummaryGridRowModel>().Name("mainGrid")
   </div>
</div>

在此之后,您在控制器中声明一个函数,该函数将生成已排序的数据并调用帮助程序以生成EXCEL / CSV / ZIP文件。

    public FileResult GetSummaryExcelReport([DataSourceRequest] DataSourceRequest request)
    {
        var query = DbContext.vwReportSummary.AsQueryable();

        var summaryGridRowModelList = query.Select(SummaryRequestsSelector);

        var dsResult = summaryGridRowModelList.ToDataSourceResult(request);    
        string fileName = string.Format("RequestDetailsExcelReport_{0}.xlsx", DateTime.Now.ToString("yyyyMMdd_HHmmss"));

        ExcelFileCreator fileCreator = new ExcelFileCreator();

        //var result = fileCreator.CreateExcelFileFileStreamResult<SummaryGridRowModel>(dsResult.Data as IEnumerable<SummaryGridRowModel>, fileName);        
        var result = fileCreator.CreateZipFileFileContentResult<SummaryGridRowModel>(dsResult.Data as IEnumerable<SummaryGridRowModel>, fileName);  



        return result;
    }

最后但并非最不重要的是,定义将生成EXCEL / CSV / ZipArchive文件创建者的帮助程序。

Excel File Creator助手

public class ExcelFileCreator
{
    /// <summary>
    /// Generates a FileStreamResult containing a Excel file in it
    /// </summary>
    /// <typeparam name="T">Type of object in the object list parameter</typeparam>
    /// <param name="objectList">The object list enumerable. This contains the data for the Excel file</param>
    /// <param name="fileName">The file name of the Excel</param>
    /// <returns>FileStreamResult</returns>
    public FileStreamResult CreateExcelFileFileStreamResult<T>(IEnumerable<T> objectList, string fileName)
    {
        var ms = new MemoryStream();

        var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

        try
        {

            ExcelPackage excelPackage = new ExcelPackage(ms);

            excelPackage.Compression = OfficeOpenXml.CompressionLevel.BestCompression;

            var workSheet1 = excelPackage.Workbook.Worksheets.Add("Sheet1");
            workSheet1.Cells["A1"].LoadFromCollection<T>(objectList, true);

            var firstRow = workSheet1.Row(1);
            if(firstRow != null)
                firstRow.Style.Font.Bold = true;

            excelPackage.SaveAs(ms);

            ms.Seek(0, SeekOrigin.Begin);

            var fsr = new FileStreamResult(ms, contentType);
            fsr.FileDownloadName = fileName;
            return fsr;
        }
        catch (Exception ex)
        {
            if (ms != null)
            {
                ms.Dispose();
            }

            throw;
        }

    }


    /// <summary>
    /// Generates a FileStreamResult containing a zip file with the EXCEL file in it
    /// </summary>
    /// <typeparam name="T">Type of object in the object list parameter</typeparam>
    /// <param name="objectList">The object list enumerable. This contains the data for the EXCEL file</param>
    /// <param name="fileName">The file name of the EXCEL</param>
    /// <returns>FileStreamResult</returns>        
    public FileContentResult CreateZipFileFileContentResult<T>(IEnumerable<T> objectList, string fileName)
    {
        var contentType = System.Net.Mime.MediaTypeNames.Application.Zip;

        using (var memoryStream = new System.IO.MemoryStream())
        {
            using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
            {
                using (var package = new OfficeOpenXml.ExcelPackage())
                {
                    var workSheet1 = package.Workbook.Worksheets.Add("Sheet1");
                    workSheet1.Cells["A1"].LoadFromCollection<T>(objectList, true);

                    var firstRow = workSheet1.Row(1);
                    if (firstRow != null)
                        firstRow.Style.Font.Bold = true;

                    zip.AddEntry(fileName, package.GetAsByteArray());
                    zip.Save(memoryStream);
                    var fcr = new FileContentResult(memoryStream.ToArray(), contentType); //NOTE: Using a File Stream Result will not work.
                    fcr.FileDownloadName = fileName + ".zip";
                    return fcr;
                }
            }
        }
    }


    /// <summary>
    /// Generates a HttpResponseMessage containing a Excel file in it
    /// </summary>
    /// <typeparam name="T">Type of object in the object list parameter</typeparam>
    /// <param name="objectList">The object list enumerable. This contains the data for the Excel file</param>
    /// <param name="fileName">The file name of the Excel</param>
    /// <returns>HttpResponseMessage</returns>
    public HttpResponseMessage CreateExcelFileHttpResponseMessage<T>(IEnumerable<T> objectList, string fileName)
    {
        using (var ms = new MemoryStream())
        {
            HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

            using (ExcelPackage excelPackage = new ExcelPackage(ms))
            {
                var workSheet1 = excelPackage.Workbook.Worksheets.Add("Sheet1");

                workSheet1.Cells["A1"].LoadFromCollection<T>(objectList, true);
            }

            result.Content = new ByteArrayContent(ms.GetBuffer());

            result.Content.Headers.ContentType =
                new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
            {
                FileName = fileName
            };

            return result;
        }
    }


    /// <summary>
    /// Generates a HttpResponseMessage containing a zip file with the EXCEL file in it
    /// </summary>
    /// <typeparam name="T">Type of object in the object list parameter</typeparam>
    /// <param name="objectList">The object list enumerable. This contains the data for the EXCEL file</param>
    /// <param name="fileName">The file name of the EXCEL</param>
    /// <returns>HttpResponseMessage</returns>
    public HttpResponseMessage CreateZipFileHttpResponseMessage<T>(IEnumerable<T> objectList, string fileName)
    {
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        using (var ms = new MemoryStream())
        {
            using (var archive = new System.IO.Compression.ZipArchive(ms, System.IO.Compression.ZipArchiveMode.Create, true))
            {
                var newEntry = archive.CreateEntry(fileName, System.IO.Compression.CompressionLevel.Fastest);

                using (var newEntryStream = newEntry.Open())
                using (ExcelPackage excelPackage = new ExcelPackage(ms))
                {
                    var workSheet1 = excelPackage.Workbook.Worksheets.Add("Sheet1");

                    workSheet1.Cells["A1"].LoadFromCollection<T>(objectList, true);
                }
            }
            ms.Seek(0, SeekOrigin.Begin);
            result.Content = new ByteArrayContent(ms.ToArray());

            result.Content.Headers.ContentType =
                new System.Net.Http.Headers.MediaTypeHeaderValue("application/zip");
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
            {
                FileName = fileName + ".zip"
            };

            return result;
        }
    }


}

CsvFile Creator助手

/// <summary>
/// Enumerator for the CSV file separator
/// </summary>
public enum CsvFileSeparatorType
{
    /// <summary>
    /// Values will be separated by a comma: ", "
    /// </summary>
    Comma
    ,
    /// <summary>
    /// Values will be separated by a tab delimiter: "\t "
    /// </summary>
    Tab
    ,
    /// <summary>
    /// Values will be separated by a semicolon: "; "
    /// </summary>
    Semicolon
}

/// <summary>
/// This class helps create a CSV file
/// </summary>
public class CsvFileCreator
{
    public CsvFileSeparatorType CsvFileSeparatorType
    {
        get
        {
            CsvFileSeparatorType csvFileSeparatorType = CsvFileSeparatorType.Tab;
            switch (ConfigurationManager.AppSettings["CsvFileSeparatorType"])
            {
                case "Comma":
                    csvFileSeparatorType = CsvFileSeparatorType.Comma;
                    break;
                case "Tab":
                    csvFileSeparatorType = CsvFileSeparatorType.Tab;
                    break;
                case "Semicolon":
                    csvFileSeparatorType = CsvFileSeparatorType.Semicolon;
                    break;
                default:
                    csvFileSeparatorType = CsvFileSeparatorType.Tab;
                    break;
            }
            return csvFileSeparatorType;
        }
    }


    /// <summary>
    /// Generates a HttpResponseMessage containing a zip file with the CSV file in it
    /// </summary>
    /// <typeparam name="T">Type of object in the object list parameter</typeparam>
    /// <param name="objectList">The object list enumerable. This contains the data for the CSV file</param>
    /// <param name="fileName">The file name of the CSV</param>
    /// <returns>HttpResponseMessage</returns>
    public HttpResponseMessage CreateZipFileHttpResponseMessage<T>(IEnumerable<T> objectList, string fileName)
    {
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        using (var ms = new MemoryStream())
        {
            using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
            {
                var csvEnumerable = CreateCsvEnumerable<T>(objectList, CsvFileSeparatorType);
                var newEntry = archive.CreateEntry(fileName, CompressionLevel.Fastest);

                using (var newEntryStream = newEntry.Open())
                using (var streamWriter = new StreamWriter(newEntryStream))
                {
                    foreach (var csvLine in csvEnumerable)
                    {
                        streamWriter.WriteLine(csvLine);
                    }
                    streamWriter.Flush();

                }
            }
            ms.Seek(0, SeekOrigin.Begin);
            result.Content = new ByteArrayContent(ms.ToArray());

            result.Content.Headers.ContentType =
                new System.Net.Http.Headers.MediaTypeHeaderValue("application/zip");
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
            {
                FileName = fileName + ".zip"
            };

            return result;
        }
    }

    /// <summary>
    /// Generates a HttpResponseMessage containing a CSV file in it
    /// </summary>
    /// <typeparam name="T">Type of object in the object list parameter</typeparam>
    /// <param name="objectList">The object list enumerable. This contains the data for the CSV file</param>
    /// <param name="fileName">The file name of the CSV</param>
    /// <returns>HttpResponseMessage</returns>
    public HttpResponseMessage CreateCsvFileHttpResponseMessage<T>(IEnumerable<T> objectList, string fileName)
    {
        using (var ms = new MemoryStream())
        {
            HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

            using (var streamWriter = new StreamWriter(ms))
            {
                var csvEnumerable = CreateCsvEnumerable<T>(objectList, CsvFileSeparatorType);

                foreach (var csvLine in csvEnumerable)
                {
                    streamWriter.WriteLine(csvLine);
                }
                streamWriter.Flush();
            }

            result.Content = new ByteArrayContent(ms.GetBuffer());

            result.Content.Headers.ContentType =
                new System.Net.Http.Headers.MediaTypeHeaderValue("text/csv");
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
            {
                FileName = fileName
            };

            return result;
        }
    }

    /// <summary>
    /// Generates an Enumerable containing the CSV data in it. First row contains the headers
    /// </summary>
    /// <typeparam name="T">Type of object in the object list parameter</typeparam>
    /// <param name="objectList">The object list enumerable. This contains the data for the CSV file</param>
    /// <param name="separatorType">Enumerator for the CSV file separator</param>
    /// <returns>IEnumerable</returns>
    private IEnumerable<string> CreateCsvEnumerable<T>(IEnumerable<T> objectlist, CsvFileSeparatorType separatorType)
    {

        string separator = ", ";
        switch (separatorType)
        {
            case CsvFileSeparatorType.Comma:
                separator = ", ";
                break;
            case CsvFileSeparatorType.Semicolon:
                separator = "; ";
                break;
            case CsvFileSeparatorType.Tab:
                separator = "\t ";
                break;
        }

        PropertyInfo[] properties = typeof(T).GetProperties();
        yield return "\"" + String.Join(separator, properties.Select(f => f.Name).ToArray()) + "\"";
        foreach (var o in objectlist)
        {
            yield return "\"" + HttpUtility.HtmlDecode(string.Join(separator, properties.Select(f => (f.GetValue(o) ?? "").ToString()).ToArray())) + "\"";
        }
    }
}