C#_.NetCore_WebAPI项目_EXCEL数据导出(ExcelHelper_第二版_优化逻辑)
项目需要引用NPOI的Nuget包:DotNetCore.NPOI-v1.2.2
1-简单的设置下载文件的控制器方法:
//
// 摘要:
// /// Returns a file with the specified fileContents as content (Microsoft.AspNetCore.Http.StatusCodes.Status200OK),
// the /// specified contentType as the Content-Type and the specified fileDownloadName
// as the suggested file name. /// This supports range requests (Microsoft.AspNetCore.Http.StatusCodes.Status206PartialContent
// or /// Microsoft.AspNetCore.Http.StatusCodes.Status416RangeNotSatisfiable if
// the range is not satisfiable). ///
//
// 参数:
// fileContents:
// The file contents.
//
// contentType:
// The Content-Type of the file.
//
// fileDownloadName:
// The suggested file name.
//
// 返回结果:
// The created Microsoft.AspNetCore.Mvc.FileContentResult for the response.
[NonAction]
public FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName)
//这里以下载txt文件为例:
byte[] logByte = System.IO.File.ReadAllBytes(dateLogFilePath);
MediaTypeHeaderValue mediaTypeHeaderValue = new MediaTypeHeaderValue("text/plain");
mediaTypeHeaderValue.Encoding = Encoding.UTF8;
return File(logByte, mediaTypeHeaderValue.ToString(), date.ToString("yyyy-MM-dd") + ".log");
2-本篇文章是对WebAPI项目使用NPOI操作Excel时的帮助类:ExcelHelper的改进优化做下记录:
备注:下面的帮助类代码使用的文件格式为:xlsx文件,xlsx相对xls的优缺点代码里有注释,推荐使用xlsx文件保存数据!
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection; namespace PaymentAccountAPI.Helper
{
/// <summary>
/// EXCEL帮助类
/// </summary>
/// <typeparam name="T">泛型类</typeparam>
/// <typeparam name="TCollection">泛型类集合</typeparam>
public class ExcelHelp
{
private ILogger Logger = null; public ExcelHelp(ILogger<ExcelHelp> logger)
{
this.Logger = logger;
} /// <summary>
/// 将数据导出EXCEL
/// </summary>
/// <param name="tList">要导出的数据集</param>
/// <param name="fieldNameAndShowNameDic">键值对集合(键:字段名,值:显示名称)</param>
/// <param name="fileDirectoryPath">文件路径</param>
/// <param name="excelName">文件名(必须是英文或数字)</param>
/// <returns></returns>
public IWorkbook CreateOrUpdateWorkbook<T>(List<T> tList, Dictionary<string, string> fieldNameAndShowNameDic, IWorkbook workbook = null, string sheetName = "sheet1") where T : new()
{
//xls文件格式属于老版本文件,一个sheet最多保存65536行;而xlsx属于新版文件类型;
//Excel 07 - 2003一个工作表最多可有65536行,行用数字1—65536表示; 最多可有256列,列用英文字母A—Z,AA—AZ,BA—BZ,……,IA—IV表示;一个工作簿中最多含有255个工作表,默认情况下是三个工作表;
//Excel 2007及以后版本,一个工作表最多可有1048576行,16384列;
if (workbook == null)
{
workbook = new XSSFWorkbook();
//workbook = new HSSFWorkbook();
}
ISheet worksheet = workbook.CreateSheet(sheetName); List<string> columnNameList = fieldNameAndShowNameDic.Values.ToList();
//设置首列显示
IRow row1 = worksheet.CreateRow(); ICell cell = null;
ICellStyle cellHeadStyle = workbook.CreateCellStyle();
//设置首行字体加粗
IFont font = workbook.CreateFont();
font.Boldweight = short.MaxValue;
cellHeadStyle.SetFont(font);
int cloumnCount = columnNameList.Count;
for (var i = ; i < cloumnCount; i++)
{
cell = row1.CreateCell(i);
cell.SetCellValue(columnNameList[i]);
cell.CellStyle = cellHeadStyle;
} //根据反射创建其他行数据
var raws = tList.Count;
Dictionary<string, PropertyInfo> titlePropertyDic = this.GetIndexPropertyDic<T>(fieldNameAndShowNameDic); PropertyInfo propertyInfo = null;
T t = default(T);
for (int i = ; i < raws; i++)
{
if (i % == )
{
this.Logger.LogInformation($"Excel已创建{i + 1}条数据");
}
row1 = worksheet.CreateRow(i + );
t = tList[i]; int cellIndex = ;
foreach (var titlePropertyItem in titlePropertyDic)
{
propertyInfo = titlePropertyItem.Value;
cell = row1.CreateCell(cellIndex); if (propertyInfo.PropertyType == typeof(int)
|| propertyInfo.PropertyType == typeof(decimal)
|| propertyInfo.PropertyType == typeof(double))
{
cell.SetCellValue(Convert.ToDouble(propertyInfo.GetValue(t) ?? ));
}
else if (propertyInfo.PropertyType == typeof(DateTime))
{
cell.SetCellValue(Convert.ToDateTime(propertyInfo.GetValue(t)?.ToString()).ToString("yyyy-MM-dd HH:mm:ss"));
}
else if (propertyInfo.PropertyType == typeof(bool))
{
cell.SetCellValue(Convert.ToBoolean(propertyInfo.GetValue(t).ToString()));
}
else
{
cell.SetCellValue(propertyInfo.GetValue(t)?.ToString() ?? "");
}
cellIndex++;
} //重要:设置行宽度自适应(大批量添加数据时,该行代码需要注释,否则会极大减缓Excel添加行的速度!)
//worksheet.AutoSizeColumn(i, true);
} return workbook;
} /// <summary>
/// 保存Workbook数据为文件
/// </summary>
/// <param name="workbook"></param>
/// <param name="fileDirectoryPath"></param>
/// <param name="fileName"></param>
public void SaveWorkbookToFile(IWorkbook workbook, string fileDirectoryPath, string fileName)
{
//xls文件格式属于老版本文件,一个sheet最多保存65536行;而xlsx属于新版文件类型;
//Excel 07 - 2003一个工作表最多可有65536行,行用数字1—65536表示; 最多可有256列,列用英文字母A—Z,AA—AZ,BA—BZ,……,IA—IV表示;一个工作簿中最多含有255个工作表,默认情况下是三个工作表;
//Excel 2007及以后版本,一个工作表最多可有1048576行,16384列; MemoryStream ms = new MemoryStream();
//这句代码非常重要,如果不加,会报:打开的EXCEL格式与扩展名指定的格式不一致
ms.Seek(, SeekOrigin.Begin);
workbook.Write(ms);
byte[] myByteArray = ms.GetBuffer(); fileDirectoryPath = fileDirectoryPath.TrimEnd('\\') + "\\";
if (!Directory.Exists(fileDirectoryPath))
{
Directory.CreateDirectory(fileDirectoryPath);
} string filePath = fileDirectoryPath + fileName;
if (File.Exists(filePath))
{
File.Delete(filePath);
}
File.WriteAllBytes(filePath, myByteArray);
} /// <summary>
/// 保存Workbook数据为下载文件
/// </summary>
public FileContentResult SaveWorkbookToDownloadFile(IWorkbook workbook)
{
MemoryStream ms = new MemoryStream();
//这句代码非常重要,如果不加,会报:打开的EXCEL格式与扩展名指定的格式不一致
ms.Seek(, SeekOrigin.Begin);
workbook.Write(ms);
byte[] myByteArray = ms.GetBuffer(); //对于.xls文件
//application/vnd.ms-excel
//用于.xlsx文件。
//application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
mediaType.Encoding = System.Text.Encoding.UTF8;
//设置下载文件名
FileContentResult fileResult= new FileContentResult(myByteArray, mediaType.ToString());
fileResult.FileDownloadName="xxx.xlsx";
return new FileContentResult(myByteArray, mediaType.ToString());
} /// <summary>
/// 读取Excel数据
/// </summary>
/// <param name="filePath"></param>
/// <param name="fieldNameAndShowNameDic"></param>
/// <returns></returns>
public List<T> ReadDataList<T>(string filePath, Dictionary<string, string> fieldNameAndShowNameDic) where T : new()
{
List<T> tList = null;
T t = default(T); //标题属性字典列表
Dictionary<string, PropertyInfo> titlePropertyDic = this.GetIndexPropertyDic<T>(fieldNameAndShowNameDic);
//标题下标列表
Dictionary<string, int> titleIndexDic = new Dictionary<string, int>(); PropertyInfo propertyInfo = null; using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
IWorkbook xssfWorkbook = new XSSFWorkbook(fileStream);
var sheet = xssfWorkbook.GetSheetAt(); var rows = sheet.GetRowEnumerator();
tList = new List<T>(sheet.LastRowNum + );
//第一行数据为标题,
if (rows.MoveNext())
{
IRow row = (XSSFRow)rows.Current;
ICell cell = null;
string cellValue = null;
for (int i = ; i < row.Cells.Count; i++)
{
cell = row.Cells[i];
cellValue = cell.StringCellValue;
if (titlePropertyDic.ContainsKey(cellValue))
{
titleIndexDic.Add(cellValue, i);
}
}
}
//从第2行数据开始获取
while (rows.MoveNext())
{
IRow row = (XSSFRow)rows.Current;
t = new T(); foreach (var titleIndexItem in titleIndexDic)
{
var cell = row.GetCell(titleIndexItem.Value);
if (cell != null)
{
propertyInfo = titlePropertyDic[titleIndexItem.Key];
if (propertyInfo.PropertyType == typeof(int))
{
propertyInfo.SetValue(t, Convert.ToInt32(cell.NumericCellValue));
}
else if (propertyInfo.PropertyType == typeof(decimal))
{
propertyInfo.SetValue(t, Convert.ToDecimal(cell.NumericCellValue));
}
else if (propertyInfo.PropertyType == typeof(double))
{
propertyInfo.SetValue(t, Convert.ToDouble(cell.NumericCellValue));
}
else if (propertyInfo.PropertyType == typeof(bool))
{
propertyInfo.SetValue(t, Convert.ToBoolean(cell.StringCellValue));
}
else if (propertyInfo.PropertyType == typeof(DateTime))
{
propertyInfo.SetValue(t, Convert.ToDateTime(cell.StringCellValue));
}
else
{
propertyInfo.SetValue(t, cell.StringCellValue);
} }
}
tList.Add(t);
}
}
return tList ?? new List<T>();
} /// <summary>
/// 根据属性名顺序获取对应的属性对象
/// </summary>
/// <param name="fieldNameList"></param>
/// <returns></returns>
private Dictionary<string, PropertyInfo> GetIndexPropertyDic<T>(Dictionary<string, string> fieldNameAndShowNameDic)
{
Dictionary<string, PropertyInfo> titlePropertyDic = new Dictionary<string, PropertyInfo>(fieldNameAndShowNameDic.Count); List<PropertyInfo> tPropertyInfoList = typeof(T).GetProperties().ToList();
PropertyInfo propertyInfo = null; foreach (var item in fieldNameAndShowNameDic)
{
propertyInfo = tPropertyInfoList.Find(m => m.Name.Equals(item.Key, StringComparison.OrdinalIgnoreCase));
titlePropertyDic.Add(item.Value, propertyInfo);
}
return titlePropertyDic;
} }
}
C#_.NetCore_WebAPI项目_EXCEL数据导出(ExcelHelper_第二版_优化逻辑)的更多相关文章
- C#_.NetFramework_WebAPI项目_EXCEL数据导出
[推荐阅读我的最新的Core版文章,是最全的介绍:C#_.NetCore_Web项目_EXCEL数据导出] 项目需要引用NPOI的Nuget包: A-2--EXCEL数据导出--WebAPI项目--N ...
- C#_.NetFramework_Web项目_EXCEL数据导出
[推荐阅读我的最新的Core版文章,是最全的介绍:C#_.NetCore_Web项目_EXCEL数据导出] 项目需引用NPOI的NuGet包: A-2:EXCEL数据导出--Web项目--C#代码导出 ...
- C#_.NetCore_Web项目_EXCEL数据导出(ExcelHelper_第一版)
项目需要引用NPOI的Nuget包:DotNetCore.NPOI-v1.2.2 A-前端触发下载Excel的方法有三种: 1-JS-Url跳转请求-后台需要返回文件流数据: window.Locat ...
- C#_.NetFramework_Web项目_EXCEL数据导入
[推荐阅读我的最新的Core版文章,是最全的介绍:C#_.NetCore_Web项目_EXCEL数据导出] 需要引用NPOI的Nuget包:NPOI-v2.4.1 B-1:EXCEL数据导入--C#获 ...
- C#_.NetFramework_Web项目_NPOI_EXCEL数据导入
[推荐阅读我的最新的Core版文章,是最全的介绍:C#_.NetCore_Web项目_EXCEL数据导出] 项目需要引用NPOI的Nuget包: B-2--EXCEL数据导入--NPOI--C#获取数 ...
- 合并百度影音的离线数据 with python 第二版 基于yield
重新整理了一下代码. 增加了bdv,mkv的处理流程. 目前暂时支持windows平台. bdv,mkv,rmvb的不同处理流程 # -*- coding: UTF-8 -*- import os i ...
- 【基于WinForm+Access局域网共享数据库的项目总结】之篇二:WinForm开发扇形图统计和Excel数据导出
篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...
- DB数据导出工具分享
一个根据数据库链接字符串,sql语句 即可将结果集导出到Excel的工具 分享,支持sqlserver,mysql. 前因 一个月前朋友找到我,让我帮忙做一个根据sql导出查询结果到Excel的工具( ...
- .Net之Nopi Excel数据导出和批量导入功能
一.介绍NPOI和编写demo的原因 1.Npoi是什么: 它是一个专门用于读写Microsoft Office二进制和OOXML文件格式的.NET库,我们使用它能够轻松的实现对应数据的导入,导出功能 ...
随机推荐
- Ajax与Http协议
目录 Ajax与Http协议详解 Xhr对象 xhr对象发送请求整体感知 xhr对象的常用属性和方法 xhr对象发送post请求 xhr对象的兼容性问题 请求超时timeout与监听超时ontimeo ...
- 前端WEB编辑器最爱——webstrom
欲先善其事,必先利其器,如题.看到网上一篇介绍webstrom的文章,觉得功能确实强大,也知道为什么阿里巴巴的前端传到github上的文件为啥都有一个 .idea 文件,(传说淘宝内部推荐写js用we ...
- 【Android - 进阶】之Drawable简介
Drawable是什么?Android给我们的解释是:“A general abstraction for 'something that can be drawn'.”,翻译过来就是:对于可以绘制的 ...
- java静态初始化块(静态域)
1. 类变量的初始化可通过静态初始化块来进行. 代码放在一对大括号内,大括号前用static修饰:static {……} 一个类可定义1个或多个静态初始化块. 静态初始化块会在加载时调用而且只被调用一 ...
- Reachability的用法 判断用户的网络状态
- (void)viewDidLoad { [super viewDidLoad]; // 监听网络状态发生改变的通知 [[NSNotificationCenter defaultCenter] ad ...
- 第五章 Unity中的基础光照(1)
[TOC] 渲染总是围绕着一个基础问题:我们如何决定一个像素的颜色?从宏观上来说,渲染包括了两大部分:决定一个像素的可见性,决定这个像素上的光照计算.而光照模型用于决定在一个像素上进行怎样的光照计算. ...
- 最小生成树——Kruskal与Prim算法
最小生成树——Kruskal与Prim算法 序: 首先: 啥是最小生成树??? 咳咳... 如图: 在一个有n个点的无向连通图中,选取n-1条边使得这个图变成一棵树.这就叫“生成树”.(如下图) 每个 ...
- Ubuntu 18.04.3 LTS Virtualbox提示“Kernel driver not installed (rc=-1908)”问题修复一例
前两天Ubuntu升级了,重启后启动virtualbox保存 从错误报告上反映出来的问题原因是因为某些内核驱动程序没有经过编译,所以Virtualbox无法正常运行.事实上,在Ubuntu上处理这个问 ...
- springcloud集成redis
1.application.properties/application.yml配置: redis: # redis数据库索引(默认为0),我们使用索引为3的数据库,避免和其他数据库冲突 databa ...
- 一道时间复杂度为O(N)空间复杂度为O(1)的排序问题
题目:对1, 2, ... , n的一个无序数组,排序,要求时间复杂度为O(N),空间复杂度为O(1). 思路:该题利用数组元素和数组下标相差1的关系,Java代码如下: import java.ut ...