.Net/C#把数据库文件导出成为Excel/CSV文件

  • 通过已下步骤进行写入如有报错或缺少方法请在下方留言
  • 我这里使用的是Sql Server数据库
  • EXCEL文件里面的标题字段必须和代码写的字段一样否则查找不到该字段
  • 数据库字段的限制:比如说你的数据库有5个字段,但是插入数据时候EXCEL只有四个字段,那么空的那个字段,一定要允许为空哦!!否则会插不进去的!!
  • 大家只需要修改参数和引用,其他逻辑方法不用修改,如果您有把握可以修改再修改
  • 如果您修改完参数和数据后还有方法报错,应该是您没有引用方法的命名空间,如有其他方法缺少请下方留言或私我我会更新
  • 还是以我的练习数据库为例已下为大家详细展示

1、首先下面这张图片是我把数据库的数据通过MVC展示到HTML上

 2、我们需要一个类,新建一个类ExcelCsvHelp(名字起什么无所谓),里面包含生成下载文档的方法和各种方法,我会在代码中给大家注释(如果报错可能是缺少引用,添加一下引用就可以了)代码直接复制贴进去就好,只需添加引用!

using ARC.Common.Extend;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace ARC.Common.Help
{
    /// <summary>
    /// 导出CSV下载文件帮助类
    /// </summary>
    public static class ExcelCsvHelp
    {
        #region 第一种导出CSV文件 封装 只需要传入集合,标题,绑定的列名

        /// <summary>
        /// 生成下载文件CSV
        /// </summary>
        /// <typeparam name="T">泛型实体类必须为可实例化类型</typeparam>
        /// <param name="list">数据集合</param>
        /// <param name="titles">标题</param>
        /// <param name="bindName">绑定的字段或属性名称,支持子属性字段</param>
        /// <returns></returns>
        public static byte[] GenerateFileContent<T>(List<T> list, string[] titles, string[] bindName) where T : new()
        {
            //获取到泛型的类型,通过类型可以拿到所有的属性和字段
            var modelType = typeof(T);

            var columnModels = bindName.Select(name => GetTypeByName(modelType, name.Split(".").ToList(), null)).ToList();

            Func<T, List<string>> bindRowFunc = (m) =>
                {
                    return columnModels.Select(item => GetValueByModel(item, m)).ToList();
                };

            return GenerateFileContent(list, titles, bindRowFunc);
        }

        /// <summary>
        /// 根据实体和对应的列属性获取内容(递归算法)
        /// </summary>
        /// <param name="columnModel">列实体</param>
        /// <param name="model">实体</param>
        /// <returns></returns>
        private static string GetValueByModel(ExportCsvColumnModel columnModel, object model)
        {
            //如果实体为空直接返回空
            if (model == null)
            {
                return string.Empty;
            }
            //先获取字段或属性的内容
            var value = columnModel.Type == 1 ? columnModel.PropertyInfo.GetValue(model) : columnModel.FieldInfo.GetValue(model);
            //判断是否有子级,如果有子级的话直接递归接着取内容,如果没有直接直接value返回
            var result = columnModel.IsChildren ? GetValueByModel(columnModel.Children, value) : value?.ToString();

            return result;
        }

        /// <summary>
        /// 根据字段或属性名称获取类型
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="names">字段名称集合上下级关系索引列越大约在下方</param>
        /// <param name="model">返回的数据集</param>
        /// <returns></returns>
        private static ExportCsvColumnModel GetTypeByName(Type type, List<string> names, ExportCsvColumnModel model)
        {
            //设置死循环
            while (true)
            {

                if (!names.Any())
                {
                    return null;
                }

                var name = names[0];
                if (string.IsNullOrEmpty(name))
                {
                    return null;
                }

                //声明本次会产生的对象
                ExportCsvColumnModel thisModel;
                //根据name 获取属性
                var prop = type.GetProperty(name);
                //设置字段
                FieldInfo field = null;
                //属性不为空
                if (prop != null)
                {
                    //该名称被检索未属性
                    thisModel = new ExportCsvColumnModel() { ColumnName = name, Type = 1 };
                }
                else
                {
                    //获取字段
                    field = type.GetField(name);
                    //字段为空,属性和字段全部未检索到抛出异常
                    if (field == null)
                    {
                        throw new Exception($"在类型:{type?.FullName}下未检索到,指定名称:{name}的属性或字段");
                    }

                    //查到了字段
                    thisModel = new ExportCsvColumnModel() { ColumnName = name, Type = 0 };
                }
                //设置属性和字段
                thisModel.PropertyInfo = prop;
                thisModel.FieldInfo = field;

                //父级属性或字段为空,则自己就是父级
                if (model == null)
                {
                    model = thisModel;
                }
                else
                {
                    //设置有子级,并设置子级对应的属性还是字段
                    model.IsChildren = true;
                    model.Children = thisModel;
                }
                //是否未最后一级
                if (names.Count == 1)
                {
                    //最后一级直接返回内容
                    return model;
                }
                else
                {
                    //还有子级先获取本次查询的属性或字段,他们为下次循环的父级
                    var t = prop == null ? field.FieldType : prop.PropertyType;
                    //清除第一个节点为下次循环准备
                    names.RemoveAt(0);
                    //设置下次循环的类型
                    type = t;
                }
            }
        }


        #endregion

        /// <summary>
        /// 生成下载文档
        /// </summary>
        /// <typeparam name="T">泛型实体类必须为可实例化类型</typeparam>
        /// <param name="list">数据集合</param>
        /// <param name="titles">标题</param>
        /// <param name="bindRowFunc">绑定每行的数据</param>
        /// <returns></returns>
        public static byte[] GenerateFileContent<T>(List<T> list, string[] titles, Func<T, List<string>> bindRowFunc) where T : new()
        {
            var userExportRowFormatter = string.Join(",", titles.Select((m, i) => $"\"{{{i}}}\"")) + "\n";
            var sb = new StringBuilder(string.Format(userExportRowFormatter, titles));
            if (list != null)
            {
                foreach (var item in list)
                {
                    if (bindRowFunc != null && item != null)
                    {
                        var values = bindRowFunc(item).ToArray();
                        if (titles.Length != values.Length)
                        {
                            throw new Exception("内容数量与标题数量不相同,请检查设置内容和标题。");
                        }
                        sb.AppendFormat(userExportRowFormatter, values);
                    }
                }
            }
            var buffer = Encoding.Default.GetBytes(sb.ToString());
            GC.Collect();
            return Encoding.Convert(Encoding.Default, Encoding.UTF8, buffer).ToUTF8BOM();
        }

        /// <summary>
        /// 获取csv文件名字
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string GetFileName(string fileName = "")
        {
            fileName = string.IsNullOrWhiteSpace(fileName) ? DateTime.Now.Ticks.ToString() : fileName;
            return $"{DateTime.Now.ToARCBjTime().ToARCDateString()}-{fileName}.csv";
        }
        /// <summary>
        /// 转为string 类型并增加\t
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string AddT(this string val)
        {
            return $"{val}\t";
        }
        /// <summary>
        /// 转为string 类型并增加\t
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string ToStringAddT<T>(this T val) where T : struct
        {
            return val.ToString().AddT();
        }
    }

    public class ExportCsvColumnModel
    {
        /// <summary>
        /// 属性或字段名
        /// </summary>
        public string ColumnName { get; set; }
        /// <summary>
        /// 类型 是属性还是字段(1属性 2字段)
        /// </summary>
        public int Type { get; set; }
        /// <summary>
        /// 字段
        /// </summary>
        public FieldInfo FieldInfo { get; set; }
        /// <summary>
        /// 属性
        /// </summary>
        public PropertyInfo PropertyInfo { get; set; }

        /// <summary>
        /// 是否存在子级
        /// </summary>
        public bool IsChildren { get; set; }
        /// <summary>
        /// 子级的信息
        /// </summary>
        public ExportCsvColumnModel Children { get; set; }

    }
}

3、刚才那几个类生成成功之后我们开始进行接口方法的编写,在Controllers文件夹中新建一个控制器,或者在你原有的控制器中写入已下方法。注意里面的where方法在第4点里面,如果不需要筛选可以自行调整去掉where方法

//导出EXCEL方法,里面的参数分别是分页查询的参数和我要搜索或下载的条件(看不懂参数的话算是白学了)

        public async Task<ActionResult> PrintInvoiceToExcel(int pageIndex = 1, int pageSize = 20, string SearchTitle = "", string Telephone = "", string CompanyName = "", string Department = "", string Position = "", string Email = "", string Scale = "")
        {
            string[] headline = { "用户ID", "姓名", "电话", "密码", "公司名称", "公司规模", "部门", "职位", "图片", "邮箱", "注册时间", "状态", "修改时间" };

            var headLine = new List<string>();
        //查询的条件
            var where = GetWhere1(SearchTitle, Telephone, CompanyName, Department, Position, Email, Scale);
            var startIndex = (pageIndex - 1) * pageSize;
             //生成一个根据你的实体生成的新对象
            var db = await (from m in dbContext.User_tbs

                            select new User_tb()
                            {
                                //id
                                Id = m.Id,
                                //名字
                                Name = m.Name,
                                //电话
                                Telephone = m.Telephone,
                                //密码
                                Password = m.Password,
                                //公司名称
                                CompanyName = m.CompanyName,
                                //公司规模
                                Scale = m.Scale,
                                //部门
                                Department = m.Department,
                                //职位
                                Position = m.Position,
                                //图片
                                ImgUrl = m.ImgUrl,
                                //邮箱
                                Email = m.Email,
                                //注册时间
                                RegisterTime = m.RegisterTime,
                                //状态
                                userid = m.userid,
                                //修改时间
                                UpdateTime = m.UpdateTime,

                            }).Where(where).ToListAsync();
    //下面这个里面字段的顺序必须和上方你写的字段顺序一致,否则就会数据混乱

            var ms = ExcelCsvHelp.GenerateFileContent(db, headline, (item) => new List<string>()
                {
                //把数据映射到表中
                //"用户ID", "姓名", "电话", "密码", "公司名称", "公司规模", "部门","职位","图片","邮箱","注册时间", "状态", "修改时间"
                    item.Id.ToString(),
                    item.Name.ToString(),
                    item.Telephone.ToString(),
                    item.Password.ToString(),
                    item.CompanyName.ToString(),
                    item.Scale == "10148"?"20人以下":(item.Scale == "10149"?"50-100人":(item.Scale == "10154"?"100-500人":"500-1000人")),
                    item.Department.ToString(),
                    item.Position.ToString(),
                    item.ImgUrl.ToString(),
                    item.Email.ToString(),
                    item.RegisterTime.ToString(),
                    item.userid == 0?"不显示":"显示",
                    item.UpdateTime.ToString()
                });
            if (ms != null)
            {
                var fileName = "练习—" + ExcelCsvHelp.GetFileName();
                Response.Headers.Add("Content-Length", ms.Length.ToString());
                return File(ms, "application/ms-excel", fileName);
            }
            else
            {
                return Content("");
            }
        }

4、在上面那个方法的下面再加一个条件方法,也就是上面的Where1方法上面那个代码里面有用到过。再次声明:如果您不需要条件,想直接全部下载的话,可以把上面条件方法去掉。下面这个方法也不用写了。方法如下:

//参数是我数据库里面有的参数,我通过目录树表达式的方法生成条件,可以查找自己所需要的,从而省略我们不需要的提高效率
public Expression<Func<User_tb, bool>> GetWhere1(string Name = "", string Telephone = "", string CompanyName = "", string Department = "", string Position = "", string Email = "", string Scale = "")
        {
            //声明一个初始的表达式目录树
            Expression<Func<User_tb, bool>> where = b => b.userid > -1;
            //如果传过来的参数不是空的
            if (!string.IsNullOrEmpty(Name))
            {
                where = where.And(b => b.Name == Name);
            }
            if (!string.IsNullOrEmpty(Telephone))
            {
                where = where.And(b => b.Telephone.Contains(Telephone));
            }
            if (!string.IsNullOrEmpty(CompanyName))
            {
                where = where.And(b => b.CompanyName.Contains(CompanyName));
            }
            if (!string.IsNullOrEmpty(Department))
            {
                where = where.And(b => b.Department.Contains(Department));
            }
            if (!string.IsNullOrEmpty(Position))
            {
                where = where.And(b => b.Position.Contains(Position));
            }
            if (!string.IsNullOrEmpty(Email))
            {
                where = where.And(b => b.Email == Email);
            }
            if (!string.IsNullOrEmpty(Scale))
            {
                where = where.And(b => b.Scale == Scale);
            }
            return where;
        }

6、做出以上几步后,如果没有报错那么就可以正常使用了,您可以通过一些事件来调用第三步的那个方法,从而实现把数据库的东西导出成EXCEL中的SVC格式

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值