.NET之NPOI Excel数据导出和批量导入功能

简介: .NET之NPOI Excel数据导出和批量导入功能

一、介绍NPOI和编写demo的原因

Npoi是什么:

  它是一个专门用于读写Microsoft Office二进制和OOXML文件格式的.NET库,我们使用它能够轻松的实现对应数据的导入,导出功能,并且还能通过其对应的属性对Excel进行对应的样式调整。是一个简洁而又强大的第三方库。

编写该demo的原因:

  首先是为了巩固自己,其次是为了帮助一些刚开始接触的开发者更快的了解该库的操作原理。并且很多开发者在使用npoi进行大量数据导入的时候经常会遇到数据操作时间过长问题,不知道如何优化的。其实这样优化导入的方式有很多,不过一般为了提高效率都会使用T-sql进行数据批量的导入,大家需要优化导入的话可以参考下邹大佬的(http://www.cnblogs.com/jiekzou/p/6145550.html)这篇博客写的非常的详细,而我在这次使用的是EF 的 AddRange 批量插入,并且是用来layui前端框架进行了相应的布局,该demo已上传到了我的github中,需要的可以下载,地址会在文章结尾奉上。

 

🚀回到顶部

二、导入、导出的功能实现和逻辑代码展示

首先看看界面效果:

image.png

首先通过Nuget下载安装Npoi:

image.png

批量导入:

  /// <summary>
        /// 数据导入
        /// </summary>
        /// <param name="FileStram"></param>
        /// <returns></returns>
        public ActionResult DataImport(HttpPostedFileBase  file)
        {
            var message="";
            int Columns = 0;
            //判断是否提交excel文件
            var FileName = file.FileName.Split('.');
            if (file!=null&&file.ContentLength>0)
            {
                if (FileName[1]=="xls"||FileName[1]== "xlsx")
                {
                    //首先我们需要导入数据的话第一步其实就是先把excel数据保存到本地中,然后通过Npoi封装的方法去读取已保存的Excel数据
                    string DictorysPath=Server.MapPath("~/Content/ExcelFiles/"+ DateTime.Now.ToString("yyyyMMdd"));
                    if (!System.IO.Directory.Exists(DictorysPath))
                    {
                        System.IO.Directory.CreateDirectory(DictorysPath);
                    }
                    file.SaveAs(System.IO.Path.Combine(DictorysPath,file.FileName));
                    //将Excel数据转化为DataTable数据源
                    DataTable  Dt=NpoiHelper.Import(System.IO.Path.Combine(DictorysPath, file.FileName), FileName[1]);
                    List<UserInfo> list = new List<UserInfo>();
                    for (int i = 0; i < Dt.Rows.Count; i++)
                    {
                        UserInfo U = new UserInfo();
                        //从行索引从1开始,标题除外
                        U.UserName = Dt.Rows[i][0].ToString();
                        U.Sex = Dt.Rows[i][1].ToString();
                        U.Phone = Dt.Rows[i][2].ToString();
                        U.Hobby = Dt.Rows[i][3].ToString();
                        list.Add(U);
                    }
                    //数据全部添加
                    UserEntites.Set<UserInfo>().AddRange(list);
                    Columns=UserEntites.SaveChanges();
                    if (Columns>0)
                    {
                        message = "导入成功";
                    }
                    else
                    {
                        message = "导入失败";
                    }
                }
                else
                {
                    message = "格式错误";
                }
            }
            else
            {
                message = "未找到需要导入的数据";
            }
            ViewBag.Columns = Columns;
            ViewBag.Message = message;
            return View();
        }

导出:

 /// <summary>
        /// 数据导出
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Export()
        {
            try
            {
                //导出所有数据
                var All_ListData = UserEntites.UserInfo.ToList();
                //将list 转化为datatable类型
                var Dt = DatabaseOpreas._.ListToDataTable(All_ListData);
                NpoiHelper.Export(Dt, "用户信息", Server.MapPath("~/Content/Export.xls"));//这里的路径是需要写入你需要保存的文件格式的,不需要创建自动检测创建
                return Json(new {code=1,msg= "/Content/Export.xls" });
            }
            catch (Exception ex)
            {
                return Json(new {code=0,msg=ex.Message });    
            }
        }

NPOI导入导出帮助类:

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Utility
{
    /// <summary>
    /// NPOI操作帮助类
    /// </summary>
    public class NpoiHelper
    {
        /// <summary>  
        /// DataTable导出到Excel文件  
        /// </summary>  
        /// <param name="dtSource">源DataTable</param>  
        /// <param name="strHeaderText">表头文本</param>  
        /// <param name="strFileName">保存位置</param>  
        public static void Export(DataTable dtSource, string strHeaderText, string strFileName)
        {
            using (MemoryStream ms = Export(dtSource, strHeaderText))
            {
                using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write))
                {
                    //数据填写
                    byte[] data = ms.ToArray();
                    fs.Write(data, 0, data.Length);
                    fs.Flush();
                }
            }
        }
        /// <summary>  
        /// DataTable导出到Excel的MemoryStream  
        /// </summary>  
        /// <param name="dtSource">源DataTable</param>  
        /// <param name="strHeaderText">表头文本</param>  
        public static MemoryStream Export(DataTable dtSource, string strHeaderText)
        {
            HSSFWorkbook workbook = new HSSFWorkbook();
            ISheet sheet = workbook.CreateSheet();
            ICellStyle dateStyle = workbook.CreateCellStyle();
            IDataFormat format = workbook.CreateDataFormat();
            dateStyle.DataFormat = format.GetFormat("yyyy-MM-dd");
            #region 取得每列的列宽(最大宽度)
            int[] arrColWidth = new int[dtSource.Columns.Count];
            foreach (DataColumn item in dtSource.Columns)
            {
                //GBK对应的code page是CP936
                arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length;
            }
            for (int i = 0; i < dtSource.Rows.Count; i++)
            {
                for (int j = 0; j < dtSource.Columns.Count; j++)
                {
                    int intTemp = Encoding.GetEncoding(936).GetBytes(dtSource.Rows[i][j].ToString()).Length;
                    if (intTemp > arrColWidth[j])
                    {
                        arrColWidth[j] = intTemp;
                    }
                }
            }
            #endregion
            int rowIndex = 0;
            foreach (DataRow row in dtSource.Rows)
            {
                #region 新建表,填充表头,填充列头,样式
                if (rowIndex == 65535 || rowIndex == 0)
                {
                    if (rowIndex != 0)
                    {
                        sheet = workbook.CreateSheet();
                    }
                    #region 表头及样式
                    {
                        IRow headerRow = sheet.CreateRow(0);
                        headerRow.HeightInPoints = 25;
                        headerRow.CreateCell(0).SetCellValue(strHeaderText);//第一列表头名称
                        ICellStyle headStyle = workbook.CreateCellStyle();
                        headStyle.Alignment = HorizontalAlignment.Center;
                        IFont font = workbook.CreateFont();
                        font.FontHeightInPoints = 20;
                        font.Boldweight = 700;
                        headStyle.SetFont(font);
                        headerRow.GetCell(0).CellStyle = headStyle;
                        sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1));
                    }
                    #endregion
                    #region 列头及样式
                    {
                        //也可自定义标题名称,填写到 headerRow.CreateCell(1).SetCellValue();需使用directory<string,string>先填写标题,然后遍历操作中即可
                        IRow headerRow = sheet.CreateRow(1);
                        ICellStyle headStyle = workbook.CreateCellStyle();
                        headStyle.Alignment = HorizontalAlignment.Center;
                        IFont font = workbook.CreateFont();
                        font.FontHeightInPoints = 10;
                        font.Boldweight = 700;
                        headStyle.SetFont(font);
                        foreach (DataColumn column in dtSource.Columns)
                        {
                            headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
                            headerRow.GetCell(column.Ordinal).CellStyle = headStyle;
                            //设置列宽  
                            sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256);
                        }
                    }
                    #endregion
                    rowIndex = 2;
                }
                #endregion
                #region 填充内容
                ICellStyle contentStyle = workbook.CreateCellStyle();
                contentStyle.Alignment = HorizontalAlignment.Left;
                IRow dataRow = sheet.CreateRow(rowIndex);
                foreach (DataColumn column in dtSource.Columns)
                {
                    ICell newCell = dataRow.CreateCell(column.Ordinal);
                    newCell.CellStyle = contentStyle;
                    string drValue = row[column].ToString();
                    switch (column.DataType.ToString())
                    {
                        case "System.String"://字符串类型  
                            newCell.SetCellValue(drValue);
                            break;
                        case "System.DateTime"://日期类型  
                            DateTime dateV;
                            DateTime.TryParse(drValue, out dateV);
                            newCell.SetCellValue(dateV);
                            newCell.CellStyle = dateStyle;//格式化显示  
                            break;
                        case "System.Boolean"://布尔型  
                            bool boolV = false;
                            bool.TryParse(drValue, out boolV);
                            newCell.SetCellValue(boolV);
                            break;
                        case "System.Int16"://整型  
                        case "System.Int32":
                        case "System.Int64":
                        case "System.Byte":
                            int intV = 0;
                            int.TryParse(drValue, out intV);
                            newCell.SetCellValue(intV);
                            break;
                        case "System.Decimal"://浮点型  
                        case "System.Double":
                            double doubV = 0;
                            double.TryParse(drValue, out doubV);
                            newCell.SetCellValue(doubV);
                            break;
                        case "System.DBNull"://空值处理  
                            newCell.SetCellValue("");
                            break;
                        default:
                            newCell.SetCellValue("");
                            break;
                    }
                }
                #endregion
                rowIndex++;
            }
            using (MemoryStream ms = new MemoryStream())
            {
                workbook.Write(ms);
                ms.Flush();
                ms.Position = 0;
                //sheet.Dispose();
                //workbook.Dispose();//一般只用写这一个就OK了,他会遍历并释放所有资源,但当前版本有问题所以只释放sheet  
                return ms;
            }
        }
        /// <summary>
        /// 读取excel,将数据Excel数据源转化为datatable类型  
        /// 默认第一行为标头  
        /// </summary>  
        /// <param name="strFileName">excel文档路径</param>  
        /// <returns></returns>  
        public static DataTable Import(string strFileName,string FileType)
        {
            IWorkbook hssfworkbook;
            DataTable dt = new DataTable();
            //HSSFWorkbook hssfworkbook;
            using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read))//数据读取
            {
                ////XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
                //不同格式excle判断
                if (FileType == "xls")
                {
                    hssfworkbook = new HSSFWorkbook(file);
                }
                else
                {
                    hssfworkbook = new XSSFWorkbook(file);
                }
            }
            ISheet sheet = hssfworkbook.GetSheetAt(0);
            System.Collections.IEnumerator rows = sheet.GetRowEnumerator();
            IRow headerRow = sheet.GetRow(0);
            int cellCount = headerRow.LastCellNum;
            for (int j = 0; j < cellCount; j++)
            {
                ICell cell = headerRow.GetCell(j);
                dt.Columns.Add(cell.ToString());
            }
            for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
            {
                IRow row = sheet.GetRow(i);
                DataRow dataRow = dt.NewRow();
                for (int j = row.FirstCellNum; j < cellCount; j++)
                {
                    if (row.GetCell(j) != null)
                        dataRow[j] = row.GetCell(j).ToString();
                }
                dt.Rows.Add(dataRow);
            }
            return dt;
        }
    }
}

三、总结

       其实做任何东西我们都需要总结和积累,首先通过自己的搜索然后参考各位网上前辈的经验然后再根据自己的理解去写。其实没有什么事情是通过自己的努力解决不了的,解决不了就是说明你还不够努力,就像我做的导入就是一次导入五六十万的数据,通过查阅了一些大佬的经验最终将导入速度优化到了比较理想的结果,当然这里我只是写了一个完整的demo,大家想要深入研究的话就得花时间自己学了啦,最后附上项目地址:https://github.com/YSGStudyHards/ShipBuilding/tree/master/C%23%EF%BC%8C.Net%EF%BC%8C.Net%20Core%20%E7%BC%96%E7%A8%8B%E7%BB%83%E4%B9%A0/Asp.NetMVC%E4%B9%8BNpoi%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E5%AE%9E%E4%BE%8B

相关文章
|
20天前
|
前端开发
实现Excel文件和其他文件导出为压缩包,并导入
实现Excel文件和其他文件导出为压缩包,并导入
25 1
|
22天前
|
数据格式 UED
记录一次NPOI库导出Excel遇到的小问题解决方案
【11月更文挑战第16天】本文记录了使用 NPOI 库导出 Excel 过程中遇到的三个主要问题及其解决方案:单元格数据格式错误、日期格式不正确以及合并单元格边框缺失。通过自定义单元格样式、设置数据格式和手动添加边框,有效解决了这些问题,提升了导出文件的质量和用户体验。
147 3
|
29天前
|
消息中间件 监控 数据可视化
基于.NET开源、功能强大且灵活的工作流引擎框架
基于.NET开源、功能强大且灵活的工作流引擎框架
|
28天前
|
XML 开发框架 .NET
.NET 9 中 LINQ 新增功能实操
.NET 9 中 LINQ 新增功能实操
|
29天前
|
网络协议 Unix Linux
精选2款C#/.NET开源且功能强大的网络通信框架
精选2款C#/.NET开源且功能强大的网络通信框架
|
29天前
|
开发框架 JavaScript 前端开发
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
|
29天前
|
网络协议 网络安全 Apache
一个整合性、功能丰富的.NET网络通信框架
一个整合性、功能丰富的.NET网络通信框架
|
1月前
|
消息中间件 开发框架 .NET
.NET 8 强大功能 IHostedService 与 BackgroundService 实战
【11月更文挑战第7天】本文介绍了 ASP.NET Core 中的 `IHostedService` 和 `BackgroundService` 接口及其用途。`IHostedService` 定义了 `StartAsync` 和 `StopAsync` 方法,用于在应用启动和停止时执行异步操作,适用于资源初始化和清理等任务。`BackgroundService` 是 `IHostedService` 的抽象实现,简化了后台任务的编写,通过 `ExecuteAsync` 方法实现长时间运行的任务逻辑。文章还提供了创建和注册这两个服务的实战步骤,帮助开发者在实际项目中应用这些功能。
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
46 7
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
74 0

热门文章

最新文章