基于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测试效果如下:


导出的文件如下:

相关推荐
Coder_Shenshen34 分钟前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
学以智用3 小时前
ASP.NET MVC5(.NET Framework)底层完整运行逻辑
.net
寂寞的船6 小时前
【Unity知识速递】第10期 Unity GC 零分配实战:从 UnityEngine.Pool 到手动 GC 控制的全链路优化
jvm·unity·c#·游戏引擎·lucene
学以智用8 小时前
FilterAttribute(ASP.NET Core MVC 过滤器特性)
.net
Jeff-Tsai9 小时前
Day 15:API 契约分层与类型注册表
.net·架构设计·erp·definition-driven
1-1=09 小时前
C# 数据结构和特殊类型
数据结构·c#·.net·.netcore
总裁余(余登武)10 小时前
【python项目】:1操作EXCEl自动化开发
python·自动化·excel
IT规划师10 小时前
Redis 数据类型全解 - Stream 深度:消费者组、Pending 队列与死信处理(十)
redis·.net
Jeff-Tsai1 天前
Day 14:业务对象的扩展点与重写时机
.net·架构设计·erp·definition-driven
IT规划师1 天前
Redis 数据类型全解 - GEO 地理空间:附近的人、外卖、打车——背后原理与精度陷阱(九)
redis·.net