netcore项目中使用miniexcel

news/2024/5/20 0:33:33 标签: excel, .netcore

excel_0">1.miniexcel背景简介

常工作中经常与数据打交道的同学肯定会难以避免对Excel的一些数据操作如导入、导出等,但是当对一些大数据量操作Excel时经常会遇到一个常见的问题内存溢出。今天给大家推荐一个简单、高效、低内存避免OOM(内存溢出)的.NET操作Excel开源框架:MiniExcel。
MiniExcel简单、高效避免OOM的.NET处理Excel查、写、填充数据工具。目前主流框架大多需要将数据全载入到内存方便操作,但这会导致内存消耗问题,MiniExcel 尝试以 Stream 角度写底层算法逻辑,能让原本1000多MB占用降低到几MB,避免内存不够情况。
[gitee地址](https://gitee.com/dotnetchina/MiniExcel?_from=gitee_search#getstart1)

在这里插入图片描述

2.特点

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

3.主流Excel操作框架性能对比

导入、查询 Excel 比较
在这里插入图片描述
导出、创建 Excel 比较
在这里插入图片描述

4.使用经验示例

下面记录一些我自己项目中使用的经验和例子。
首先是查询:

var rows = MiniExcel.Query<ImportOrganizations>(path);
public class ImportOrganizations
{
    [ExcelColumnName("企业名称")]
    public string OrganizationName { get; set; }
    [ExcelColumnName("统一社会信用代码")]
    public string CreditCode { get; set; }
    [ExcelColumnName("联系人")]
    public string ContactPersonName { get; set; }
    [ExcelColumnName("联系人手机")]
    public string ContactPersonTel { get; set; }
    [ExcelColumnName("企业类型")]
    public string OrganizationTypes { get; set; }
}

ExcelColumnName可以加列名,中国肯定是中文的表头,这点使用起来就很方便了。

query的参数path这里需要注意一下,这个path是本地的路径,如果是远程的链接路径是 打不开的,这里翻看了底层代码,实际上使用的还是system.io 下的File.Open,File.Open注定了只能读取本地文件了。
这里还有个折中方案,就是先下载下来再去读下载下来的文件然后导入到库里。

 public static void SaveAsLocal(IFormFile file)
 {
      using (var stream  = file.OpenReadStream())
      {
          MiniExcel.SaveAs($"DownloadFile/{Guid.NewGuid()}_{file.FileName}",  stream.GetReader(),configuration:new OpenXmlConfiguration(){AutoFilter = false});
      }
  }

对于我们来说大多数还是传的文件流来读取文件(IFormFile file形式)。
我们 来看一种写法:

 public static List<T> GetList<T>(IFormFile file)
  {
       using (var stream = file.OpenReadStream())
       {
           var list = stream.Query().Cast<T>().ToList();
           return list;
       }
   }

Query支持Cast方法,按说可以转换为对象,但是这里我封装的这个泛型方法并没有好使,报错了。不得已我只能单独读取:

var rows = new List<ImportOrganizations>();
 using (var stream = file.OpenReadStream())
  {
      rows = (await stream.QueryAsync<ImportOrganizations>()).ToList();
  }

这样读取出来就不报错了,不知道为什么,暂时认定为miniexcel的bug。

获取excel表头值:

 using (var stream = file.OpenReadStream())
  {
        var columns = stream.GetColumns(useHeaderRow:true);//方式1
   }
        
var row2 = MiniExcel.Query(templateFilePath).Cast<IDictionary<string,object>>().First();//方式2

上面是两种获取的方式,templateFilePath是文件路径。

获取sheet页

 using (var stream = file.OpenReadStream())
 {
      var sheetNames = stream.GetSheetNames();
  }

导出:

public static FileStreamResult SaveAs(object value, string fileName)
{
    var memoryStream = new MemoryStream(); 
    memoryStream.SaveAs(value,configuration: new OpenXmlConfiguration() { AutoFilter = false });
    memoryStream.Seek(0, SeekOrigin.Begin);
    return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    {
        FileDownloadName = fileName
    };
}

value就是导出的list,fileName文件名称。AutoFilter=false是指导出的excel文件默认不加筛选。

导出完后可以调用一下SaveAs方法,将文件报存到服务器 (本地):

 MiniExcel.SaveAs($"DownloadFile/{Guid.NewGuid()}_{file.FileName}",rows):
 

rows是我们上面query后的list。

校验excel行数,排除掉空白行:

 public static void CheckRowCount(IFormFile file, int count = 8000)
    {
        using (var stream = file.OpenReadStream())
        {
            var dt = stream.QueryAsDataTable();
            var rows = dt.AsEnumerable().Where(row => !row.ItemArray.All(field => string.IsNullOrWhiteSpace(field.ToString())));
            if (rows.Count() > count)
            {
                throw new UserFriendlyException("ExcelRowNumber_Error");
            }
        }
    }

http://www.niftyadmin.cn/n/5141543.html

相关文章

【免费活动】11月4日敏捷武林上海站 | Scrum.org CEO 亲临现场

活动介绍 过去的几年里&#xff0c;外界的风云变幻为我们的生活增添了一些不一样的色彩。在VUCA世界的浪潮里&#xff0c;每一个人都成为自己生活里的冒险家。面对每一次的变化&#xff0c;勇于探索未知&#xff0c;迎接挑战&#xff0c;努力追逐更好的自己。 七月&#xff0…

性能压力测试主要目标及步骤

性能压力测试是软件开发生命周期中至关重要的一部分&#xff0c;旨在评估应用程序或系统在高负载和极端条件下的性能表现。这种测试有助于发现性能瓶颈、资源耗尽和错误&#xff0c;以确保应用程序在真实使用情况下的可靠性和稳定性。本文将探讨性能压力测试的概念、方法和最佳…

灰狼优化算法(GWO)python

目录 一、灰狼优化算法的python实现 二、灰狼优化算法与遗传算法的对比分析&#xff08;python&#xff09; 2.1 GWO1.py 2.2 GA1.py 2.3 GWO_vs_GA.py 2.4 运行结果 ​三、基于莱维飞行改进的灰狼优化算法的python实现 一、灰狼优化算法的python实现 import numpy as …

Web3 React项目Dapp获取智能合约对象

上文Web3 整理React项目 导入Web3 并获取区块链信息中&#xff0c;我们在react搭建的dapp中简单拿到了我们区块链中的账号授权信息 那 我们继续 先终端运行 ganache -d将ganache环境起起来 然后 我们运行 dapp 拿到授权列表 回到上文结束的一个状态 然后 我们发布一下自己的…

利用两个栈s1,s2模拟一个队列时,如何用栈的运算来实现该队列的运算?写出模拟队列插入和删除的函数。一个栈s1用于插入元素,另一个栈s2用于删除元素

利用两个栈s1&#xff0c;s2模拟一个队列时&#xff0c;如何用栈的运算来实现该队列的运算&#xff1f;写出模拟队列插入和删除的函数。一个栈s1用于插入元素&#xff0c;另一个栈s2用于删除元素。 前置知识点&#xff08;栈定义&#xff0c;及出栈入栈函数&#xff09; #def…

界面控件DevExpress WPF Gauge组件 - 轻松实现个性化商业仪表盘

DevExpress WPF Gauge&#xff08;仪表&#xff09;控件包含了多种圆形仪表类型、水平和垂直线性仪表、分段和矩阵数字仪表以及状态指示器&#xff0c;同时还具有最终用户交互性的集成支持。 P.S&#xff1a;DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至…

使用ant design pro出现面包屑导航和标题消失的问题

前端时间&#xff0c;我用ant design pro搭建了一个后台权限管理的项目模板&#xff0c;里面用到了PageContainer组件&#xff0c;默认会显示面包屑导航和标题&#xff0c;如图所示 后来&#xff0c;我把这个项目模板用于另外一个项目的前端页面&#xff0c;把整个项目的文件夹…

装备制造行业云MES解决方案

一、装备制造行业发展现状&#xff1a; 机械制造业主要是通过对金属原材料物理形状的改变、加工组装进而成为产品。机械制造业生产的主要特点是&#xff1a;离散为主、流程为辅、装配为重点。 工业生产基本上分为两大方式&#xff1a; 1.离散型&#xff1a;离散型是指以一个…