NPOI以及在ASP.NET MVC中的使用

NPOI以及在ASP.NET MVC中的使用

1.前言

相信大家在工作中经常要遇到一些导入导出Execl操作。学习贵在分享,分享使人快乐,园子里的前辈已经有很多好的文章,鄙人也是能力有限,在这里把这些好的文章总结,方便以后再工作中使用。

NPOI:是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目。

NPOI是构建在POI 3.x版本之上的,它可以在没有安装Office的情况下对Word/Excel文档进行读写操作。

它不使用Office COM组件(Microsoft.Office.Interop.XXX.dll),不需要安装Microsoft Office,支持对Office 97-2003的文件格式,功能比较强大。

能够读写几乎所有的Office 97-2003文件格式,至少能够支持Word, PowerPoint, Excel, Visio的格式。

NPOI官方网站【点击这里】

1、整个Excel表格叫做工作表:WorkBook(工作薄),包含的叫页(工作表):Sheet;行:Row;单元格Cell。

2、NPOI是POI的C#版本,NPOI的行和列的index都是从0开始

3、POI读取Excel有两种格式一个是HSSF,另一个是XSSF。

HSSF和XSSF的区别如下:

HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls

XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx

即:HSSF适用2007以前的版本,XSSF适用2007版本及其以上的。

HSSFWorkbook对应的就是Excel文件  工作簿,

HSSFSheet对应的就是Excel中sheet 工作表,

HSSFCell对应的就是Excel的单元格,

HSSFRow对应的就是Excel的行

.NET调用NPOI组件导入导出Excel的操作类

     此NPOI操作类的优点如下:
       (1)支持web及winform从DataTable导出到Excel; 
       (2)生成速度很快; 
       (3)准确判断数据类型,不会出现身份证转数值等问题; 
       (4)如果单页条数大于65535时会新建工作表; 
       (5)列宽自适应;

2.简单用法

namespace 导入导出
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnInput_Click(object sender, EventArgs e)
        {
            #region 导入到DataTable
            using (FileStream stream = File.OpenRead("huangjinfeng.xls"))
            {
                IWorkbook workbook = new HSSFWorkbook(stream);
                ISheet sheet = workbook.GetSheet("员工捐款信息表");

                DataTable table = new DataTable();
                IRow headerRow = sheet.GetRow(0);
                int cellCount = headerRow.LastCellNum;
                int rowCount = sheet.LastRowNum;

                for (int i = headerRow.FirstCellNum; i < cellCount; i++)
                {
                    DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
                    table.Columns.Add(column);
                }

                for (int i = (sheet.FirstRowNum + 1); i <= rowCount; i++)
                {
                    IRow row = sheet.GetRow(i);
                    DataRow dataRow = table.NewRow();

                    if (row != null)
                    {
                        for (int j = row.FirstCellNum; j < cellCount; j++)
                        {
                            if (row.GetCell(j) != null)
                                dataRow[j] = row.GetCell(j);
                        }
                    }

                    table.Rows.Add(dataRow);
                }

                this.dataGridView1.DataSource = table;
                MessageBox.Show("导入数据成功");
            }
            #endregion

            #region 导入到数据库
            //using (FileStream stream = File.OpenRead("huangjinfeng.xls"))
            //{
            //    string sql="INSERT INTO [dbo].[DonationDetail]([dUserName],[dcID],[dAmount],[dDate],[disdelete],[dCreateTime])";
            //    RenderToDb(stream,sql);
            //    MessageBox.Show("SQL");
            //}
            #endregion

        }

        private void btnOut_Click(object sender, EventArgs e)
        {
            DonationEntities2 db = new DonationEntities2();
            var lists = db.CreateObjectSet<DonationDetail>().Where(c => c.disdelete == 0).ToList();

            #region 自由导出
            HSSFWorkbook workbook = new HSSFWorkbook();
            //2.创建工作表
            ISheet sheet = workbook.CreateSheet("员工捐款信息表");
            IRow rowHeader = sheet.CreateRow(0);
            rowHeader.CreateCell(0, CellType.String).SetCellValue("DId");
            rowHeader.CreateCell(1, CellType.String).SetCellValue("员工姓名");
            rowHeader.CreateCell(2, CellType.String).SetCellValue("DcId");
            rowHeader.CreateCell(3, CellType.String).SetCellValue("捐款金额");
            rowHeader.CreateCell(4, CellType.String).SetCellValue("捐款日期");
            rowHeader.CreateCell(5, CellType.String).SetCellValue("是否删除");
            rowHeader.CreateCell(6, CellType.String).SetCellValue("创建日期");

            for (int i = 0; i < lists.Count; i++)
            {
                IRow row = sheet.CreateRow(i + 1);
                //为指定的行添加列
                row.CreateCell(0, CellType.String).SetCellValue(lists[i].dId);
                row.CreateCell(1, CellType.String).SetCellValue(lists[i].dUserName);
                row.CreateCell(2, CellType.String).SetCellValue(lists[i].dcID);
                row.CreateCell(3, CellType.String).SetCellValue(lists[i].dAmount.ToString());
                row.CreateCell(4, CellType.String).SetCellValue(Convert.ToDateTime(lists[i].dDate.ToString()));
                row.CreateCell(5, CellType.String).SetCellValue(lists[i].disdelete);
                row.CreateCell(6, CellType.String).SetCellValue(Convert.ToDateTime(lists[i].dCreateTime.ToString()));
            }

            //使用文件流做数据的写入
            using (FileStream fss = new FileStream("huangjinfeng.xls", FileMode.Create))
            {
                workbook.Write(fss);
            }
            MessageBox.Show("导出数据成功");
            #endregion
        }

 RenderToDb(Stream excelFileStream, string insertSql)

 HasData(Stream excelFileStream)

    }
 }

3.项目中的Execl导入导出

工作中我一般主要是用到的MVC,在这里就说说我们项目中一般的处理过程。先看看我自己写的一个NPOIBase父类。

    public class NPOIBase : ActionResult
    {
        public IWorkbook _workbook { get; set; }
        public ISheet _sheet { get; set; }
        public ICellStyle _titleStyle { get; set; }
        public ICellStyle _leftStyle { get; set; }
        public ICellStyle _centerStyle { get; set; }
        public ICellStyle _rightStyle { get; set; }
        public ICellStyle _headStyle { get; set; }
        public ICellStyle _leftborderStyle { get; set; }
        public ICellStyle _rightborderStyle { get; set; }
        public ICellStyle _noneRightBorderStyle { get; set; }
        public ICellStyle _noneLeftBorderStyle { get; set; }
        public ICellStyle _noneLeftAndRightBorderStyle { get; set; }
        public ICellStyle _borderStyle { get; set; }
        public override void ExecuteResult(ControllerContext context)
        {
        }
        public void IniNPOI(bool isHeadBorder = false, string sheetName = "")
        {
            _workbook = new HSSFWorkbook();
            _sheet = string.IsNullOrWhiteSpace(sheetName) ? _workbook.CreateSheet() : _workbook.CreateSheet(sheetName);
            IniStyle(isHeadBorder);
        }

 IniStyle

        public void FillHeadCell(IRow row, int colIndex, string value, ICellStyle cellStyle = null,                                   NPOI.SS.Util.CellRangeAddress mergedCellRangeAddress = null)
        {
            if (_sheet == null || row == null) return;
            if (cellStyle == null) cellStyle = _headStyle;
            FillCell(row, colIndex, value, cellStyle, mergedCellRangeAddress);
            _sheet.SetColumnWidth(colIndex, (Encoding.Default.GetBytes(value.Trim()).Length + 4) * 256);
        }
        public void FillCell(IRow row, int colIndex, string value, ICellStyle cellStyle = null,                              NPOI.SS.Util.CellRangeAddress mergedCellRangeAddress = null)
        {
            if (_sheet == null || row == null) return;
            ICell titleSum = row.CreateCell(colIndex);
            titleSum.SetCellValue(value);
            if (cellStyle != null) titleSum.CellStyle = cellStyle;
            else if (_centerStyle != null) titleSum.CellStyle = _centerStyle;
            if (mergedCellRangeAddress != null) _sheet.AddMergedRegion(mergedCellRangeAddress);
        }
        public void FillCell(IRow row, int colIndex, double value, ICellStyle cellStyle = null,                              NPOI.SS.Util.CellRangeAddress mergedCellRangeAddress = null)
        {
            if (_sheet == null || row == null) return;
            ICell titleSum = row.CreateCell(colIndex);
            titleSum.SetCellValue(value);
            if (cellStyle != null) titleSum.CellStyle = cellStyle;
            else if (_centerStyle != null) titleSum.CellStyle = _centerStyle;
            if (mergedCellRangeAddress != null) _sheet.AddMergedRegion(mergedCellRangeAddress);
        }
        public void ResponseOutPutExcelStream(string fildName)
        {
            if (string.IsNullOrWhiteSpace(fildName)) fildName = DateTime.Now.ToString("yyyyMMddHHmmss.xls");
            if (fildName.ToLower().IndexOf(".xls") == -1) fildName += ".xls";
            HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
            HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", fildName));
            HttpContext.Current.Response.Clear();

            MemoryStream file = new MemoryStream();
            _workbook.Write(file);
            file.WriteTo(HttpContext.Current.Response.OutputStream);
            HttpContext.Current.Response.End();
        }
        public void SetPrint(bool isLandscape = false, bool isFitToPage = false, double topMargin = 0, double rightMargin = 0,                              double bottomMargin = 0.5, double leftMargin = 0, short scale = 100)
        {
            _sheet.PrintSetup.Landscape = isLandscape;
            _sheet.SetMargin(MarginType.TopMargin, topMargin);
            _sheet.SetMargin(MarginType.RightMargin, rightMargin);
            _sheet.SetMargin(MarginType.LeftMargin, leftMargin);
            _sheet.SetMargin(MarginType.BottomMargin, bottomMargin);
            _sheet.PrintSetup.PaperSize = 9;
            _sheet.PrintSetup.Scale = scale;
            _sheet.FitToPage = isFitToPage;
            if (isFitToPage)
            {
                _sheet.PrintSetup.FitWidth = 1;
                _sheet.PrintSetup.FitHeight = 0;
            }
        }
    }

这个由于父类是继承的ActionResult,我们用起来就比较方便,在Action中,直接使用就可以了。代码示例如下...

    public class BaseMaterialsExcelResult : NPOIBase
    {

        string[] __headers = null;
        IList<BaseMaterials> __BaseMaterialsList;
        public BaseMaterialsExcelResult(IList<BaseMaterials> BaseMaterialsList)
        {
            __BaseMaterialsList = BaseMaterialsList;
            __headers = new string[] {
                "序号",
                "材料",
                "型号",
                "推荐供应商",
                "出库数量",
                "入库数量",
                "结存"
               };
        }
        public override void ExecuteResult(ControllerContext context)
        {
            if (__BaseMaterialsList == null || __BaseMaterialsList.Count() == 0) return;
            IniNPOI();
            int rowIndex = 0;
            foreach (var item in __BaseMaterialsList)
            {
                #region 新建表,填充列头,样式
                int colIndex = 0;
                if (rowIndex == 65535 || rowIndex == 0)
                {
                    if (rowIndex != 0)
                        _sheet = _workbook.CreateSheet();
                    IRow headerRow = _sheet.CreateRow(rowIndex);
                    foreach (var head in __headers)
                        FillHeadCell(headerRow, colIndex++, head);
                    rowIndex = 1;
                }
                #endregion

                #region 填充内容
                IRow dataRow = _sheet.CreateRow(rowIndex);
                colIndex = 0;
                FillCell(dataRow, colIndex++, rowIndex);
                FillCell(dataRow, colIndex++, item.Name);
                FillCell(dataRow, colIndex++, item.Type);
                FillCell(dataRow, colIndex++, item.ProviderName);
                FillCell(dataRow, colIndex++, item.OutStorageCount.ToString());
                FillCell(dataRow, colIndex++, item.StorageCount.ToString());
                FillCell(dataRow, colIndex++, item.StockCount.ToString());
                #endregion

                rowIndex++;
            }

            _sheet.CreateFreezePane(1, 1, 1, 1);
            ResponseOutPutExcelStream("BaseMaterials.xls");
        }

    }

控制器中的代码如下:

    public class HomeController : Controller
    {
        BluedonStockEntities  db = new BluedonStockEntities();

        public List<BaseMaterials> GetList()
        {
            return db.CreateObjectSet<BaseMaterials>().Where(c => true).ToList();
        }

        public ActionResult Index()
        {
            var list = GetList();
            return View(list);
        }

        public ActionResult Execl()
        {
            var list = GetList();
            return new BaseMaterialsExcelResult(list);

        }

    }

4.问题总结。

  1. 在实例化了一个WorkBook之后,最好添加一个sheet,虽然在最新版的Npoi.net中自动添加了,但是遇到迁移到原来版本就会出现问题。所以我建议还是最少添加一个sheet
  2. 在从单元格取值时要注意单元格的类型,一定要用对应的类型的方法来取单元格中的对应类型的值,如果不确定,那只能是强制转换成为string类型,毕竟string类型是excel中其他类型都可以转换过来的
  3. 在获取sheet中的某一行或者某一行的某一个单元格的时候,还要注意就是一定要确保创建了该行,并且取单元格还要确保创建了单元格,否则会报Null reference not to object 这个我们经常会看到的异常信息。在外层一定要加上try捕获异常
  4. 合并单元格是sheet的工作,因此需要获取对应的sheet,然后调用其AddMergedRegion方法合并单元格,在合并单元格的时候,我们不需要确保该单元格已经存在或创建。
  5. 在为单元格设置样式的过程中,我们会发现所有和样式相关的类的创建都是通过workBook.Create(Font)..这种方式来执行的,我们不可以直接new一个类的实例。
  6. 如果前面的工作都已经做好,需要把内存中的excel表写到硬盘上时,需要调用workBook.write()方法,传入一个文件流进行创建。在这里有可能会出现一个问题,就是你要创建的文件你已经打开了,这时程序就会出现异常,因此我们在调试程序的时候一定要记得打开了excel文件以后要关闭
  7. 最后需要注意的就是文件流,在我们把excel写到硬盘上以后,要显式的调用其close()方法关闭文件流。因为如果不关闭文件流的话,以后就会出现无法重新创建该文件的错误,并且会提示 某文件正由另一进程使用,因此该进程无法访问此文件。

简单用法的源码【点击下载】

MVC版的源码【点击下载】

感谢你的支持,为我点个赞吧!

时间: 2024-08-05 11:16:21

NPOI以及在ASP.NET MVC中的使用的相关文章

log4net 使用总结- (2)在ASP.NET MVC 中使用

log4net在ASP.NET MVC中的配置,还有一种配置方式,即不在web.config中,而是单独新建一个log4net.config 在根目录下 第一.引用log4net.dll 第二.在站点根目录下增加log4net.config <?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="

ASP.NET MVC中使用异步控制器

线程池 一直想把项目改写成异步,但是ASP.NETMVC3下写的过于繁琐,.NET 4.5与ASP.NET MVC下代码写起来就比较简单了, MS好像也一直喜欢这样搞,每一个成熟的东西,都要演变好几个版本,才能趋于规范. ASP.NET MVC 中为什么需要使用异步呢,IIS有一个线程池来处理用户的请求,当一个新的请求过来时,将调度池中的线程以处理该请求,然而,但并发量很高的情况下,池中的线程已经不能够满足这么多的请求时候,池中的每一个线程都处于忙的状态则在处理请求时将阻塞处理请求的线程,并且该

ASP.NET MVC中使用ASP.NET AJAX异步访问WebService

使用过ASP.NET AJAX的朋友都知道,怎么通过ASP.NET AJAX在客户端访问WebService,其实在ASP.NET MVC中使用ASP.NET AJAX异步访问WebService 也没什么大的差别. 在ASP.NET应用程序里使用ASP.NET AJAX访问WebService通常都是通过ScriptMananger引入WebService生成客户端代理的方法,同时也可以使用Microsoft Ajax Library来完成.本文将介绍在ASP.NET MVC中使用ASP.NE

ASP.NET MVC中使用FluentValidation验证实体

1.FluentValidation介绍 FluentValidation是与ASP.NET DataAnnotataion Attribute验证实体不同的数据验证组件,提供了将实体与验证分离开来的验证方式,同时FluentValidation还提供了表达式链式语法. 2.安装FluentValidation FluentValidation地址:http://fluentvalidation.codeplex.com/ 使用Visual Studio的管理NuGet程序包安装FluentVa

ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器

ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器一:闲谈一下:1.现在任务跟踪管理系统已经开发快要结束了,抽一点时间来写一下,想一想自己就有成就感啊!!  2.关于任务跟踪管理系统项目中遇到的Windows服务以及Webservice的综合应用的问题. 大家好这是我第二次写博客 ,写的不好请大家多多谅解, 希望大家可以多多指正. 二:我稍微的整理了一下关于这个分布式定时器需求:1.根据任务跟踪管理系统中的数据库的AnswerSheet 表格中找到客户编

Asp.Net MVC中DropDownListFor的用法(转)

2016.03.04 扩展:如果 view中传入的是List<T>类型 怎么使用 DropList 既然是List<T> 那么我转化成 T  List<T>的第一个,最后一个不就是M吗? @Html.DropDownListFor(model=>model.First().Title, ViewData["Title"] as List<SelectListItem>, "标题", @"dropdown

ASP.NET MVC中使用窗体验证出现上下文的模型在数据库创建后发生更改,导致调试失败

在ASP.NET MVC中使用窗体验证.(首先要明白,验证逻辑是应该加在Model.View和Controller哪一个里面?由于Model的责任就是负责信息访问与商业逻辑验证的,所以我们把验证逻辑加在Model里面.) 第一步:引用下面这个命名空间 第二步:添加验证 第三步:启动调试,出现以下问题: 解决方法: 超链接中包含了解决这个问题的详细介绍,也就是通过Code First数据库迁移的方式让Entity Framework帮助我们自动调整数据库里面的架构. 解决这个问题最简单的方法就是将

关于asp.net MVC 中的TryUpdateModel方法

有比较才会有收货,有需求才会发现更多. 在传统的WebFormk开发工作中,我们常常会存在如下的代码块 //保存 protected void btnSubmit_Click(object sender, EventArgs e) { try { BLL.MoneyBll cun = new BLL.MoneyBll(); Model.Money m1 = new Model.Money(); m1.Commany = int.Parse(this.Commany.Text); m1.Count

在asp.net mvc中使用PartialView返回部分HTML段

问题链接: MVC怎样实现异步调用输出HTML页面 该问题是个常见的 case, 故写篇文章用于提示新人. 在asp.net mvc中返回View时使用的是ViewResult,它继承自ViewResultBase 同一时候它还有个兄弟PartialViewResult 相信聪明的你已经知道了它俩的差别了,没错 一个用于返回总体,还有一个返回局部(部分). 如果我有这样一个需求,输入username,然后返回相关信息.之前的做法可能会是用json格式来返回用户的相关信息,然后到页面去渲染相关 的