.NET6使用MiniExcel根据数据源横向导出头部标题及数据

.NET6+MiniExcel根据数据源横向导出头部标题

MiniExcel简单、高效避免OOM的.NET处理Excel查、写、填充数据工具。

特点:
低内存耗用,避免OOM、频繁 Full GC 情况
支持即时操作每行数据
兼具搭配 LINQ 延迟查询特性,能办到低消耗、快速分页等复杂查询
轻量,不需要安装 Microsoft Office、COM+,DLL小于150KB
简便操作的 API 风格

github地址: MiniExcel
gitee地址: MiniExcel

本案例实现的功能是使用Miniexcel横向导出指标编码、指标名称,医院类型及指标对应的数据值,
要求导出效果如下所示:

  1. 第一列展示医院
  2. 头部两行动态展示指标编码、指标名称,下面展示每家医院所对应指标的值
    在这里插入图片描述
  3. 安装NuGet程序包SqlSugarCore、MiniExcel、Furion

代码如下:
结合实际情况,可以适当改下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MiniExcelLibs;
using MiniExcelLibs.Attributes;
using MiniExcelLibs.OpenXml;
using SqlSugar;namespace DJPSMS.Application.Service
{[AllowAnonymous]public class MiniexcelTest : IDynamicApiController{private readonly ISqlSugarClient _db;private readonly SqlSugarRepository<TDU_HOSPITALTEST> _tduHospitalRepository;/// <summary>/// 构造函数注入SqlSugar/// </summary>/// <param name="db"></param>public MiniexcelTest(ISqlSugarClient db, SqlSugarRepository<TDU_HOSPITALTEST> tduHospitalRepository){_db = db;_tduHospitalRepository = tduHospitalRepository;}/// <summary>/// Miniexcel导出/// </summary>/// <param name="Chapter">章节(案例中未使用)</param>/// <returns></returns>[HttpGet("DownLoadExcel")]public void DownLoadExcel([FromQuery][Required] string Chapter = "1"){try{// 导出数据源总集合var quotaAssemble = new List<Dictionary<string, object>>();// 构建横向指标标题var quotaPairy = new Dictionary<string, object>();#region 构造excel模板及数据源Log.Information($"构造excel横向指标标题开始--------");// 使用SqlSugar查询数据库// var quotaArray = _db.Queryable<DW_QUOTATEST>()//    .Where(x => x.Q_CODE.StartsWith(Chapter))//    .GroupBy(x => new { x.Q_CODE, x.Q_NAME })//    .OrderBy(x => x.Q_CODE)//    .Select(g => new { g.Q_CODE, g.Q_NAME })//    .ToList();// 所有的指标类型var quotaArray = new List<DW_QUOTATEST>(){new DW_QUOTATEST{ Q_ID = "1", Q_CODE = "1.01.01",Q_NAME ="指标1"},new DW_QUOTATEST{ Q_ID = "2", Q_CODE = "1.01.02",Q_NAME ="指标2"},new DW_QUOTATEST{ Q_ID = "3", Q_CODE = "1.01.03",Q_NAME ="指标3"},new DW_QUOTATEST{ Q_ID = "4", Q_CODE = "1.01.04",Q_NAME ="指标4"},new DW_QUOTATEST{ Q_ID = "5", Q_CODE = "1.01.05",Q_NAME ="指标5"},new DW_QUOTATEST{ Q_ID = "6", Q_CODE = "1.01.06",Q_NAME ="指标6"},new DW_QUOTATEST{ Q_ID = "7", Q_CODE = "1.01.07",Q_NAME ="指标7"},new DW_QUOTATEST{ Q_ID = "8", Q_CODE = "1.01.08",Q_NAME ="指标8"},new DW_QUOTATEST{ Q_ID = "9", Q_CODE = "1.01.09",Q_NAME ="指标9"},new DW_QUOTATEST{ Q_ID = "10", Q_CODE = "1.01.10",Q_NAME ="指标10"},new DW_QUOTATEST{ Q_ID = "11", Q_CODE = "1.01.11",Q_NAME ="指标11"},new DW_QUOTATEST{ Q_ID = "12", Q_CODE = "1.01.12",Q_NAME ="指标12"},new DW_QUOTATEST{ Q_ID = "13", Q_CODE = "1.01.13",Q_NAME ="指标13"}};// 設置列宽var config = new OpenXmlConfiguration{DynamicColumns = CreateDynamicColumns(quotaArray.GroupBy(x => x.Q_CODE).Select(x => x.Key).ToList())};// 构建横向指标标题quotaPairy["医院名称"] = "";for (int i = 0; i < quotaArray.Count; i++){if (quotaPairy.ContainsKey(quotaArray[i].Q_CODE)) continue;var propertyCode = quotaArray[i].Q_CODE;var propertyName = quotaArray[i].Q_NAME;quotaPairy[propertyCode] = propertyName;}quotaAssemble.Add(quotaPairy);Log.Information($"构造excel横向指标标题结束--------");// 构建第一列医院类型var hospitalList = new List<TDU_HOSPITALTEST>(){new TDU_HOSPITALTEST{ FJGDM ="1",FDESC ="测试医院1" },new TDU_HOSPITALTEST{ FJGDM ="2",FDESC ="测试医院2" },new TDU_HOSPITALTEST{ FJGDM ="3",FDESC ="南京第一" },new TDU_HOSPITALTEST{ FJGDM ="3",FDESC ="测试医院4" },new TDU_HOSPITALTEST{ FJGDM ="4",FDESC ="测试医院5" },new TDU_HOSPITALTEST{ FJGDM ="5",FDESC ="测试医院6" },new TDU_HOSPITALTEST{ FJGDM ="6",FDESC ="测试医院7" },new TDU_HOSPITALTEST{ FJGDM ="7",FDESC ="测试医院8" },new TDU_HOSPITALTEST{ FJGDM ="8",FDESC ="测试医院9" },new TDU_HOSPITALTEST{ FJGDM ="9",FDESC ="测试医院10" },new TDU_HOSPITALTEST{ FJGDM ="10",FDESC ="测试医院11" },new TDU_HOSPITALTEST{ FJGDM ="11",FDESC ="测试医院12" },};//每家医院对应的指标的值var quotaValuePairy = new Dictionary<string, object>();// 总数据源,一般来说是从数据库联表中查询的数据,这边是声明的测试数据List<HospitalViewCodeDetailTest> resultList = new List<HospitalViewCodeDetailTest>(){// 测试医院1的数据new HospitalViewCodeDetailTest { Code = "1.01.01", CodeName = "指标1",HospitalCode ="1",HospitalName ="测试医院1" ,QValue = "11.8"},new HospitalViewCodeDetailTest { Code = "1.01.02", CodeName = "指标2",HospitalCode ="1",HospitalName ="测试医院2" ,QValue = "12.8"},// 测试医院2的数据new HospitalViewCodeDetailTest { Code = "1.01.01", CodeName = "指标1",HospitalCode ="2",HospitalName ="测试医院1" ,QValue = "22.6"},new HospitalViewCodeDetailTest { Code = "1.01.02", CodeName = "指标2",HospitalCode ="2",HospitalName ="测试医院1" ,QValue = "23.2"} ,// 测试医院3的数据new HospitalViewCodeDetailTest { Code = "1.01.01", CodeName = "指标1",HospitalCode ="3",HospitalName ="测试医院3" ,QValue = "65.8"} ,new HospitalViewCodeDetailTest { Code = "1.01.02", CodeName = "指标2",HospitalCode ="3",HospitalName ="测试医院4" ,QValue = "25.1"}};// 填充对应的指标值for (int i = 0; i < hospitalList.Count; i++){quotaValuePairy = new Dictionary<string, object>(); // 在每次迭代中创建新的字典对象var hospitalCodeDetails = resultList.Where(x => x.HospitalCode == hospitalList[i].FJGDM).Select(x => new{x.Code,x.QValue}).ToList();quotaValuePairy["医院名称"] = hospitalList[i].FDESC;for (int o = 0; o < quotaArray.Count; o++){if (quotaValuePairy.ContainsKey(quotaArray[o].Q_CODE)) continue;quotaValuePairy[quotaArray[o].Q_CODE] = hospitalCodeDetails.FirstOrDefault(x => x.Code == quotaArray[o].Q_CODE)?.QValue; //指标值}quotaAssemble.Add(quotaValuePairy);}#endregion#region 导出excelif (quotaAssemble.Count > 0){Log.Information("正在导出......");// 读取json文件中的自定义保存路径// App.GetConfig官网介绍地址:http://furion.baiqian.ltd/docs/global/app?_highlight=getconfig#12-%E8%8E%B7%E5%8F%96%E9%85%8D%E7%BD%AE%E5%AF%B9%E8%B1%A1//可以改成自己地址string savePath = $"{App.GetConfig<string>("GenerateExcelOfHospitalFillingJobConfig:SavePath")}\\DownLoadExcel\\";if (!Directory.Exists(savePath)){Directory.CreateDirectory(savePath);}string filename = $"{DateTime.Now:yyyyMMddHHmmss}.xlsx";var absoluteFilePath = Path.Combine(savePath, filename);// 保存MiniExcel.SaveAs(absoluteFilePath, quotaAssemble.ToArray(),configuration: config);Log.Information($"{filename}导出成功!");}#endregion}catch (Exception ex){// 异常处理逻辑Log.Error($"发生异常: {ex.Message}");}}/// <summary>/// 设置行宽/// </summary>/// <returns></returns>private DynamicExcelColumn[] CreateDynamicColumns(List<string> dwQuota){var dynamicColumns = new List<DynamicExcelColumn>{new DynamicExcelColumn("医院名称") { Index = 0, Width = 30 }};dynamicColumns.AddRange(dwQuota.Select((codeTitle, codeIndex) =>{if (string.IsNullOrEmpty(codeTitle)){// 处理空值的情况,例如使用默认列名或跳过该列return null; // 返回 null 或者其他处理方式}else{return new DynamicExcelColumn(codeTitle) { Index = codeIndex + 1, Width = 25 };}}).Where(c => c != null).ToArray());return dynamicColumns.ToArray();}}/// <summary>/// 指标实体/// </summary>public class DW_QUOTATEST{/// <summary>/// 主键guid/// </summary>[SugarColumn(ColumnDescription = "主键id", Length = 32, IsPrimaryKey = true)]public string Q_ID { get; set; }/// <summary>/// 编码/// </summary>public string Q_CODE { get; set; }/// <summary>/// 指标名称/// </summary>public string Q_NAME { get; set; }}/// <summary>/// 医院实体/// </summary>public class TDU_HOSPITALTEST{public string FJGDM { get; set; }public string FSEQ { get; set; }public string FDESC { get; set; }}public class HospitalViewCodeDetailTest{/// <summary>/// 医院编码/// </summary>public string HospitalCode { get; set; }/// <summary>/// 医院名称/// </summary>public string HospitalName { get; set; }/// <summary>/// 指标编码/// </summary>public string Code { get; set; }/// <summary>/// 指标名称/// </summary>public string CodeName { get; set; }/// <summary>/// QValue指标值/// </summary>public string QValue { get; set; }}
}

最后效果图如下所示:
在这里插入图片描述
写的不好,如有错误还请指正

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/149606.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue.js 短连接 动态连接

有这么一种场景&#xff0c;我们实现了某个业务&#xff0c;现在需要将这个业务连接对外推广以期实现我们的运营、推广、佣金目的&#xff0c;那么我们如何实现呢&#xff1f; 比如这个页面连接为&#xff1a; https://mp.domain.com/user/creation/editor?spm1&userno12…

“一键搜索,海量商品任你选!多平台聚合,购物更便捷!“

对于多平台聚合搜索&#xff0c;根据关键词取商品列表&#xff0c;您需要使用第三方服务或软件来实现。以下是一些可能的选择&#xff1a; 使用第三方聚合搜索工具&#xff1a;有些第三方工具可以聚合多个电商平台的商品数据&#xff0c;并提供统一的搜索接口。您可以使用这些…

基于数据库(MySQL)与缓存(Redis)实现分布式锁

分布式锁 分布式锁&#xff1a;分布式锁是在分布式的情况下实现互斥类型的一种锁 实现分布式锁需要满足的五个条件 可见性&#xff1a;多个进程都能看到结果互斥性&#xff1a;只允许一个持有锁的对象的进入临界资源可用性&#xff1a;无论何时都要保证锁服务的可用性&#x…

查看,取消终端代理

查看 echo $http_proxy echo $https_proxy在 Linux 终端中&#xff0c;你可以使用以下命令取消 HTTP 和 HTTPS 的代理设置&#xff1a; export http_proxy"" export https_proxy""或者使用 unset 命令取消这两个代理设置&#xff1a; unset http_prox…

T10 数据增强

文章目录 一、准备环境和数据1.环境2. 数据 二、数据增强&#xff08;增加数据集中样本的多样性&#xff09;三、将增强后的数据添加到模型中四、开始训练五、自定义增强函数六、一些增强函数 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f…

docker数据卷详细讲解及数据卷常用命令

docker数据卷详细讲解及数据卷常用命令 Docker 数据卷是一种将宿主机的目录或文件直接映射到容器中的特殊目录&#xff0c;用于实现数据的持久化和共享。Docker 数据卷有以下特点&#xff1a; 数据卷可以在一个或多个容器之间共享和重用&#xff0c;不受容器的生命周期影响。…

CSS-表格独有属性

属性名&#xff1a;able-layout功能&#xff1a;设置列宽度属性值&#xff1a; auto&#xff08;默认值&#xff09;&#xff1a;自动&#xff0c;列宽根据内容计算 table-layout: auto; fixed&#xff1a;固定列宽&#xff0c;平均分 table-layout: fixed; 属性名&#xff1a;…

C语言中文网 - Shell脚本 - 8

第1章 Shell基础&#xff08;开胃菜&#xff09; 8. Linux Shell命令提示符 启动 Linux 桌面环境自带的终端模拟包&#xff0c;或者从 Linux 控制台登录后&#xff0c;便可以看到 Shell 命令提示符。看见命令提示符就意味着可以输入命令了。命令提示符不是命令的一部分&#x…

Linux QT交叉编译环境安装

参考链接 linux交叉编译Qt_linux qt 交叉编译-CSDN博客 关键点&#xff1a;编译脚本&#xff0c;放在qt源代码根目录的.sh文件 #!/bin/shcd ./qt-everywhere-src-5.12.9./configure -prefix /home/qsqya/compile/qt5.12.9/build \ -opensource \ -release \ -confirm-license…

​LeetCode解法汇总2342. 数位和相等数对的最大和

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给你一个下…

充电桩负载测试需要检测哪些项目

充电桩负载测试在进行充电桩负载测试时&#xff0c;需要检测以下几个项目&#xff1a; 充电速度&#xff1a;测试充电桩的充电速度&#xff0c;包括直流充电桩的最大输出功率和交流充电桩的充电功率&#xff0c;以确定其是否符合标准要求。充电效率&#xff1a;测试充电桩的充电…

vue项目动态配置网站图标

1、在.env中配置图标地址 # 网站图标 VUE_APP_ICON_URL ./民政.png2、在main.js中将配置的图标地址存入缓存 if(process.env.VUE_APP_ICON_URL){sessionStorage.setItem(VUE_APP_ICON_URL, process.env.VUE_APP_ICON_URL); }else{sessionStorage.setItem(VUE_APP_ICON_URL, …

Go语言中ipv4与Uint32转换

简介 ip对于我们都不陌生&#xff0c;但是如果有一道题目要你判断某个ip在不在一个ip段的范围内&#xff0c;该怎么做呢&#xff0c;要是能把它弄成可比较的数字就好了 例如 127.0.0.1如何转数字呢&#xff0c;我们可以把它分成四段 127 0 0 1 每一段转为二进制拼起来 011111…

特征缩放和转换以及自定义Transformers(Machine Learning 研习之九)

特征缩放和转换 您需要应用于数据的最重要的转换之一是功能扩展。除了少数例外&#xff0c;机器学习算法在输入数值属性具有非常不同的尺度时表现不佳。住房数据就是这种情况:房间总数约为6至39320间&#xff0c;而收入中位数仅为0至15间。如果没有任何缩放&#xff0c;大多数…

初识分布式键值对存储etcd

欢迎大家到我的博客浏览。胤凯 (oyto.github.io)大家好&#xff0c;今天我带大家来学习一下 etcd。 一、什么是 etcd etcd 是一个开源的分布式键值存储系统&#xff0c;主要用于构建分布式系统中那点服务发现、配置管理、分布式锁等场景。它采用 Raft 一致性算法来确保所有节…

JavaScript 字符处理

1.删除前几个字符 使用 slice console.log(12345.slice(1))// 23452.首字母大写 var word abcconsole.log(word.charAt(0).toUpperCase() word.slice(1))// Abc3.字符为数字时可直接相乘 console.log(2*3) 4.字符串中是否包含某个子字符串 子串既可以为数字也可为字符串 /…

react中设置activeClassName的笔记

React是一种流行的JavaScript库&#xff0c;用于构建动态用户界面。它具有许多有用的组件&#xff0c;其中之一是NavLink组件。NavLink组件用于在React应用程序中创建链接&#xff0c;并且它具有许多有用的属性&#xff0c;例如选中的样式设置。 react-router-dom": “^6…

Pyside6/PyQt6如何添加右键菜单,源码示例

文章目录 📖 介绍 📖🏡 环境 🏡📒 源码分享 📒🎈 添加图标📖 介绍 📖 在UI开发中经常会使用到右键菜单,本文记录了一个添加右键菜单的示例,可以举一反三,仅供参考! 🏡 环境 🏡 本文演示环境如下 Windows11Python3.11.5PySide6📒 源码分享 📒 下面…

左支座零件的机械加工工艺规程及工艺装备设计【计算机辅助设计与制造CAD】

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;左支座 获取完整CAD工程源文件论文报告说明书等 一、论文目录 二、论文部分内容 设计任务 1.完成左支座零件—毛坯合图及左支座零件图 2.完成左支座零件工艺规程设计 3.完成左支座零件加工工艺卡 4.机床专用夹具装备总图 …

ACWSpring1.3

git使用git status看我们仓库有多少什么东西 首先,前端写ajax写上我们的访问路径(就在我们前端的源代码里面),我们建了两个包pkController用于前端页面url映射过来一层一层找到我们的RestController返回bot1里面有键值,返回的这就是一个session对象bot1这个map.前端拿到我们bot…