欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ClosedXML、DocumentFormat.OpenXml导出DataTable到Excel

程序员文章站 2023-08-29 13:57:40
在很多系统中都用到导出,使用过多种导出方式,觉得ClosedXML插件的导出简单又方便。 并且ClosedXML、DocumentFormat.OpenXml都是MIT开源。 ......

在很多系统中都用到导出,使用过多种导出方式,觉得closedxml插件的导出简单又方便。

并且closedxml、documentformat.openxml都是mit开源。

首先通过 nuget 安装 closedxml 插件,同时会自动安装 documentformat.openxml 插件。

以下就是导出相关的代码:

1、mvc控制器中的导出

// mvc 控制器中
/// <summary>
/// 导出 (无论是否需要返回值,都有 response)
/// </summary>
public void export1() // 传入搜索条件
{
    // 1、根据条件查询到想要的数据
    datatable data = new datatable();
    // 2、设置表名(对应sheet名)、列名(对应列名)
    data.tablename = "xx统计";
    // 3、列宽设置(需要慢慢设置)
    int[] colswidth = new int[] { 160, 200, 300, 160 };
    // 4、生成导出文件
    byte[] filedata = exporthelper.exportexcel(data);
    // 5、输出文件流
    httpcontext.output(filedata, "xx统计_导出" + datetime.today.showdate() + ".xlsx");
}

2、生成导出文件

using closedxml.excel;
using system.data;
using system.io;

/// <summary>
/// 导出excel文件
/// </summary>
/// <param name="data">导出的数据</param>
/// <param name="colswidth">列宽</param>
/// <returns></returns>
public static byte[] exportexcel(datatable data, int[] colswidth = null)
{
    using (xlworkbook workbook = new xlworkbook())
    {
        ixlworksheet worksheet = workbook.addworksheet(data.tablename);

        // 处理列
        for (int i = 0; i < data.columns.count; i++)
        {
            worksheet.cell(1, i + 1).value = data.columns[i].columnname;
            worksheet.cell(1, i + 1).style.font.bold = true;
        }

        // 处理列宽
        if (colswidth != null)
        {
            for (int j = 1; j <= colswidth.length; j++)
            {
                worksheet.columns(j, j).width = colswidth[j - 1];
            }
        }

        // 处理数据
        int r = 2;// 第二行开始
        foreach (datarow dr in data.rows)
        {
            // 第一列开始
            for (int c = 1; c <= data.columns.count; c++)
            {
                worksheet.cell(r, c).value = data.rows[r][c].tostring();
            }
            r++;
        }

        // 缓存到内存流,然后返回
        using (memorystream stream = new memorystream())
        {
            workbook.saveas(stream);
            return stream.toarray();
        }
    }
}

3、输出文件流

using system.text;
using system.text.regularexpressions;
using system.web;

/// <summary>
/// 输出文件流
/// </summary>
/// <param name="httpcontext">http上下文</param>
/// <param name="filedata">文件数据</param>
/// <param name="filename">文件名(要后缀名)</param>
public static void output(this httpcontextbase httpcontext, byte[] filedata, string filename)
{
    //文件名称效验 文件名不能包含\/:*?<>| 其中\需要两次转义
    if (regex.ismatch(filename, @"[\\/:*?<>|]"))
    {
        filename = regex.replace(filename, @"[\\/:*?<>|]", "_");
    }

    //判断是否为火狐浏览器(下载时,有些浏览器中文名称乱码)
    if (httpcontext.request.browser.browser != "firefox")
    {
        filename = httputility.urlencode(filename, encoding.utf8);
    }

    // 没有定义类型,用二进制流类型的mime
    string mime = "application/octet-stream";
    httpcontext.response.clear();
    httpcontext.response.buffer = true; //该值指示是否缓冲输出,并在完成处理整个响应之后将其发送
    httpcontext.response.contenttype = mime;
    httpcontext.response.contentencoding = encoding.utf8;
    httpcontext.response.charset = encoding.utf8.headername;
    httpcontext.response.addheader("content-disposition", "attachment;filename=" + filename);
    httpcontext.response.addheader("accept-language", "zh-cn");
    httpcontext.response.addheader("content-length", filedata.longlength.tostring());
    httpcontext.response.binarywrite(filedata);
    httpcontext.response.flush();
    httpcontext.response.end();
}

通过closedxml导出操作方便。