基于MiniExcel的三种常用导出Excel方法(固定列导出、动态列导出、按模板导出)

为了方便代码编写和测试,把很多代码都放在一个class里面,实际开发根据需要放到对应的目录下即可。

1.使用nuget下载安装miniexcel;

2.编写对应的测试接口,具体代码如下:

csharp 复制代码
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System;
using AutoMapper;
using MiniExcelLibs.Attributes;
using MiniExcelLibs;
using MiniExcelLibs.OpenXml;
using System.Linq;

namespace YY.Webapi.Controllers
{
    /// <summary>
    /// miniexcel测试
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    [Produces("application/json")]
    [AllowAnonymous]
    public class MiniExcelController : ControllerBase
    {
        private readonly IMapper _mapper;

        public MiniExcelController(
            IMapper mapper
            )
        {
            _mapper = mapper;
        }

        /// <summary>
        /// 固定列导出
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [HttpPost("Export")]
        public async Task<IActionResult> Export()
        {
            try
            {
                var models = new Custome().GetProducts();
                var exportDtos = _mapper.Map<List<CustomeExportDto>>(models);
                var memoryStream = new MemoryStream();
                memoryStream.SaveAs(exportDtos);
                memoryStream.Seek(0, SeekOrigin.Begin);
                return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                {
                    FileDownloadName = $"固定列报表导出-{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
                };
            }
            catch (Exception ex)
            {
                throw new Exception($"固定列报表导出出现错误:{ex.Message}");
            }
        }

        /// <summary>
        /// 动态列导出(指定列导出)
        /// </summary>
        /// <param name="columnParams"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [HttpPost("ExportByAssignColumn")]
        [AllowAnonymous]
        public async Task<IActionResult> ExportByAssignColumn(List<CustomeParam> columnParams)
        {
            try
            {
                if (columnParams == null || !columnParams.Any()) throw new Exception("请选择需要导出的列!");
                var dtos = new Custome().GetProducts();

                #region 配置
                var config = new OpenXmlConfiguration { };
                List<DynamicExcelColumn> objs = new List<DynamicExcelColumn>();
                int index = 0;
                foreach (var columnParam in columnParams)
                {
                    objs.Add(new DynamicExcelColumn(columnParam.ColumnDisplayName) { Index = index++, Width = columnParam.ColumnWidth });
                }
                config.DynamicColumns = objs.ToArray();
                #endregion

                #region 获取值
                var values = new List<Dictionary<string, object>>();
                foreach (var dto in dtos)
                {
                    var dic = new Dictionary<string, object>();
                    foreach (var columnParam in columnParams)
                    {
                        dic.Add(columnParam.ColumnDisplayName, GetModelValue(columnParam.ColumnName, dto));
                    }
                    values.Add(dic);
                }
                #endregion

                var memoryStream = new MemoryStream();
                memoryStream.SaveAs(values, configuration: config);
                memoryStream.Seek(0, SeekOrigin.Begin);
                return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                {
                    FileDownloadName = $"动态列报表导出-{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
                };
            }
            catch (Exception ex)
            {
                throw new Exception($"动态列报表导出错误:{ex.Message}");
            }
        }

        /// <summary>
        /// 按模板导出
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [HttpPost("{id}/ExportByTemplate")]
        public async Task<IActionResult> ExportByTemplate([FromRoute] int id)
        {
            try
            {
                var entity = new Custome() { Id = 1, Code = "Code", Name = "Test", Price = 12, CreateTime = DateTime.Now };

                string templatePath = $@"C:\Users\Administrator\Desktop\报表模板.xlsx";
                var value = new
                {
                    Code = entity.Code,
                    Name = entity.Name
                };

                byte[] bytes = System.IO.File.ReadAllBytes(templatePath);
                var memoryStream = new MemoryStream();
                await memoryStream.SaveAsByTemplateAsync(bytes, value);
                memoryStream.Seek(0, SeekOrigin.Begin);
                return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                {
                    FileDownloadName = $"按模板报表导出-{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
                };
            }
            catch (Exception ex)
            {
                throw new Exception($"按模板报表导出错误:{ex.Message}");
            }
        }

        #region 私有方法
        /// <summary>
        /// 根据字段名获取对应的值
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        private string GetModelValue(string fieldName, object obj)
        {
            try
            {
                object o = obj.GetType().GetProperty(fieldName).GetValue(obj, null);
                string Value = Convert.ToString(o);
                if (string.IsNullOrEmpty(Value)) return "";
                return Value;
            }
            catch
            {
                return "";
            }
        }
        #endregion
    }


    public class Custome
    {
        /// <summary>
        /// 产品Id
        /// </summary>
        public int Id { get; set; }
        /// <summary>
        /// 产品编码
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 产品名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 价格
        /// </summary>
        public int Price { get; set; }
        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }
        public List<Custome> GetProducts()
        {
            var products = new List<Custome>();
            for (int i = 0; i < 1000; i++)
            {
                products.Add(new Custome
                {
                    Id = i + 1,
                    Code = $"Code-{(i + 1).ToString()}",
                    Name = $"Name-{(i + 1).ToString()}",
                    Price = Random.Shared.Next(10, 100),
                    CreateTime = DateTime.Now
                });
            }
            return products;
        }
    }

    public class CustomeExportDto
    {
        /// <summary>
        /// 产品编码
        /// </summary>
        [ExcelColumn(Name = "产品编码", Width = 12)]
        public string Code { get; set; }
        /// <summary>
        /// 产品名称
        /// </summary>
        [ExcelColumn(Name = "产品名称", Width = 12)]
        public string Name { get; set; }
        /// <summary>
        /// 价格
        /// </summary>
        [ExcelColumn(Name = "价格", Width = 12)]
        public int Price { get; set; }
        /// <summary>
        /// 创建时间
        /// </summary>
        [ExcelColumn(Name = "创建时间", Width = 12, Format = "yyyy-MM-dd HH:mm:ss")]
        public DateTime CreateTime { get; set; }
    }


    public class CustomeParam
    {
        /// <summary>
        /// 列名
        /// </summary>
        public string ColumnName { get; set; }
        /// <summary>
        /// 列显示名
        /// </summary>
        public string ColumnDisplayName { get; set; }
        /// <summary>
        /// 列宽
        /// </summary>
        public double ColumnWidth { get; set; }
    }
}

3.固定列和按模板导出Excel都比较常规,,其中的动态列导出是根据前端传进来的参数进行选择性的动态列导出,swagger测试效果如下:


导出的文件如下:

相关推荐
测试界的酸菜鱼29 分钟前
C# NUnit 框架:高效使用指南
开发语言·c#·log4j
小码编匠1 小时前
领域驱动设计(DDD)要点及C#示例
后端·c#·领域驱动设计
工业甲酰苯胺1 小时前
C# 单例模式的多种实现
javascript·单例模式·c#
yi碗汤园1 小时前
【一文了解】C#基础-集合
开发语言·前端·unity·c#
Humbunklung3 小时前
一种EF(EntityFramework) MySQL修改表名去掉dbo前缀的方法
数据库·mysql·c#
Python大数据分析@11 小时前
python操作CSV和excel,如何来做?
开发语言·python·excel
John.liu_Test12 小时前
js下载excel示例demo
前端·javascript·excel
小码编匠13 小时前
一款 C# 编写的神经网络计算图框架
后端·神经网络·c#
ruleslol14 小时前
VBA02-初识宏——EXCEL录像机
excel·vba