当前位置: 首页 > news >正文

.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; }}
}

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

相关文章:

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

.NET6MiniExcel根据数据源横向导出头部标题 MiniExcel简单、高效避免OOM的.NET处理Excel查、写、填充数据工具。 特点: 低内存耗用&#xff0c;避免OOM、频繁 Full GC 情况 支持即时操作每行数据 兼具搭配 LINQ 延迟查询特性&#xff0c;能办到低消耗、快速分页等复杂查询 轻量…...

表内容的操作(增删查改)【MySQL】

文章目录 表的 CRUDCreate&#xff08;增加&#xff09;插入记录插入冲突则更新记录替换记录 Retrieve&#xff08;查找&#xff09;查找记录指定表达式的别名为结果去重WHERE 子句运算符条件查询区间查询模糊查询空值查询 对结果排序筛选分页结果 Update&#xff08;修改&…...

C++快速入门 - 2(几分钟让你快速入门C++)

C快速入门 - 2 1. 内联函数1.1 概念1.2 特性 2. auto关键字(C11)2.1 类型别名思考2.2 auto简介2.3 auto的使用细则2.4 auto不能推导的场景 3. 基于范围的for循环(C11)3.1 范围for的语法3.2 范围for的使用条件 1. 内联函数 1.1 概念 以inline修饰的函数叫做内联函数&#xff0c…...

Excel自定义函数提取超链接

通过自定义函数的方法&#xff0c;批量提取超链接 首选开启开发工具选项 文件-选项-自定义功能区-勾选开发工具选项-确认 AltF11或者直接点击跳转到开发工具-Visual Basic 在左上方VBA project空白处右键点击空白区域-插入-模块 在弹出的窗口中输入以下命令定义GetURL函数 F…...

计算矩阵边缘元素之和

Description 输入一个整数矩阵&#xff0c;计算位于矩阵边缘的元素之和。所谓矩阵边缘的元素&#xff0c;就是第一行和最后一行的元素以及第一列和最后一列的元素。 Input 第一行分别为矩阵的行数m和列数n&#xff08;m<100&#xff0c;n<100&#xff09;&#xff0c;…...

回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测

回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测 目录 回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测&#xff08;…...

Flutter笔记:目录与文件存储以及在Flutter中的使用(下)

Flutter笔记 目录与文件存储以及在Flutter中的使用&#xff08;下&#xff09; 文件读写与Flutter中文件管理 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;…...

机器学习笔记 - Ocr识别中的CTC算法原理概述

一、文字识别 在文本检测步骤中,分割出了文本区域。现在需要识别这些片段中存在哪些文本。 机器学习笔记 - Ocr识别中的文本检测EAST网络概述-CSDN博客文章浏览阅读300次。在 EAST 网络的这个分支中,它合并了 VGG16 网络不同层的特征输出。现在,该层之后的特征大小将等于 p…...

系列二、Lock接口

一、多线程编程模板 线程 操作 资源类 高内聚 低耦合 二、实现步骤 1、创建资源类 2、资源类里创建同步方法、同步代码块 三、12306卖票程序 3.1、synchronized实现 3.1.1、Ticket /*** Author : 一叶浮萍归大海* Date: 2023/11/20 8:54* …...

JVM虚拟机:通过日志学习PS+PO垃圾回收器

我们刚才设置参数的时候看到了-XXPrintGCDetails表示输出详细的GC处理日志&#xff0c;那么我们如何理解这个日志呢&#xff1f;日志是有规则的&#xff0c;我们需要按照这个规则来理解日志中的内容&#xff0c;它有两个格式&#xff0c;一个格式是GC的格式&#xff08;新生代&…...

从0开始学习JavaScript--JavaScript使用Promise

JavaScript中的异步编程一直是开发中的重要话题。传统的回调函数带来了回调地狱和代码可读性的问题。为了解决这些问题&#xff0c;ES6引入了Promise&#xff0c;一种更现代、更灵活的异步编程解决方案。本文将深入探讨JavaScript中如何使用Promise&#xff0c;通过丰富的示例代…...

使用契约的链上限价订单

我们开发了链上限价订单。 它基于一种称为契约的智能合约&#xff0c;只有在花费输出的交易满足特定条件时才可以花费输出。 为了演示其工作原理&#xff0c;我们实施了以比特币支付的 Ordinals 代币买卖限价订单&#xff0c;无需托管人。 它可以运行在任何比特币协议链上&…...

Iceberg学习笔记(1)—— 基础知识

Iceberg是一个面向海量数据分析场景的开放表格式&#xff08;Table Format&#xff09;&#xff0c;其设计的目的是解决数据存储和计算引擎之间的适配的问题 表格式&#xff08;Table Format&#xff09;可以理解为元数据以及数据文件的一种组织方式&#xff0c;处于计算框架&…...

springboot中动态api如何设置

1.不需要编写controller 等mvc层&#xff0c;通过接口动态生成api。 这个问题&#xff0c;其实很好解决&#xff0c;以前编写接口&#xff0c;是要写controller&#xff0c;需要有 RestController RequestMapping("/test1") public class xxxController{ ApiOperat…...

Java —— 抽象类和接口

目录 1. 抽象类 1.1 抽象类概念 1.2 抽象类语法与特性 1.3 抽象类的作用 2. 接口 2.1 接口的概念 2.2 接口的语法规则与特性 2.3 实现多个接口(解决多继承的问题) 2.4 接口间的继承 2.5 抽象类和接口的区别 2.6 接口的使用实例 2.7 Clonable 接口和深拷贝 2.7.1 Cloneable接口 …...

数字IC前端学习笔记:异步复位,同步释放

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 异步复位 异步复位是一种常见的复位方式&#xff0c;可以使电路进入一个可知的状态。但是不正确地使用异步复位会导致出现意想不到的错误&#xff0c;复位释放便是…...

Linux内核移植之网络驱动更改说明一

一. 简介 本文学习 NXP官方Linux内核移植网络驱动的更改。 为了方便后面 Linux驱动的开发调试&#xff0c;所以&#xff0c;必须要把网络驱动调试好。 如果在做 Linux驱动开发时&#xff0c;写了一个 app或驱动&#xff0c;就需要将系统全部文件&#xff08;即 uboot&#…...

邮件|gitpushgithub报错|Lombok注解

基于 Spring Boot 搭建一个定时发送邮件的项目可以按照以下步骤进行&#xff1a; 创建一个新的 Spring Boot 项目&#xff0c;并添加所需的依赖。在 pom.xml 文件中添加以下依赖项&#xff08;根据你的需要进行调整&#xff09;&#xff1a; xml org.springframework.boot sp…...

【前端知识】Node——events模块的相关方法

一、events模块的常用方法 // 事件总线 const EventsEmitter require(events);const emitter new EventsEmitter();function HLog(msg){console.log(msg); }// 监听 emitter.on(hlog, HLog);setTimeout(() > {// 触发&#xff0c;打印emitter.emit(hlog, hello emitter!)…...

广州华锐互动VRAR | VR课件内容编辑器解决院校实践教学难题

VR课件内容编辑器由VR制作公司广州华锐互动开发&#xff0c;是一款专为虚拟现实教育领域设计的应用&#xff0c;它能够将传统的教学内容转化为沉浸式的三维体验。通过这款软件&#xff0c;教师可以轻松创建和编辑各种虚拟场景、模型和动画&#xff0c;以更生动、直观的方式展示…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...