NPOI导出excel

  本人在项目中用到导出,以前几乎没做过导出导入这类的功能,最近自己独立开发了几个项目,都用到了导出,于是便来一篇文章,记录一下,方便以后查找,也方便各位新手!

例子比较简单,不喜勿喷,如果有其它补充,请留言!谢谢!以下导出采用的是导出DataTable,没有做过多复杂的!

 

1. NPOI 帮助类,我使用的是 V2.3.0,改造的代码:

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace bmy.Common
{
    public static class NPOIExcelHelper
    {
 /// <summary>
        ///  组装workbook.
        /// </summary>
        /// <param name="dictionary">列头</param>
        /// <param name="dt">dataTable数据</param>
        /// <param name="columnHeader">表头</param>
        /// <returns></returns>
        public static HSSFWorkbook BuildWorkbook1(Dictionary<string, string> dictionary, DataTable dt, string columnHeader = "")
        {
            var workbook = new HSSFWorkbook();
            ISheet sheet = workbook.CreateSheet(string.IsNullOrWhiteSpace(dt.TableName) ? "Sheet1" : dt.TableName);

            var dateStyle = workbook.CreateCellStyle();
            var format = workbook.CreateDataFormat();
            dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");

            //取得列宽
            // var arrColWidth = new int[dt.Columns.Count];
            var arrColWidth = new int[dictionary.Count + 1];
            int itemCoutn = 0;//需要导出的列的数量.
            foreach (DataColumn item in dt.Columns)
            {
                //判断需要导出的 “列”

                if (dictionary.ContainsKey(item.ColumnName))
                {
                    arrColWidth[itemCoutn] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length;
                    itemCoutn++;
                }
            }
            itemCoutn = 0;
            for (var i = 0; i < dt.Rows.Count; i++)
            {
                for (var j = 0; j < dt.Columns.Count; j++)
                {
                    //判断需要导出的 “列”
                    if (dictionary.ContainsKey(dt.Rows[i][j].ToString()))
                    {
                        int intTemp = Encoding.GetEncoding(936).GetBytes(dt.Rows[i][j].ToString()).Length;
                        if (intTemp > arrColWidth[j])
                        {
                            arrColWidth[j] = intTemp;
                        }
                    }
                }
            }
            int rowIndex = 0;//行索引,第一行为:表头(列头)

            foreach (DataRow row in dt.Rows)
            {
                #region 表头 列头
                if (rowIndex == 65535 || rowIndex == 0)
                {
                    if (rowIndex != 0)
                    {
                        sheet = workbook.CreateSheet();
                    }

                    #region 表头及样式
                    {
                        IRow headerRow = sheet.CreateRow(0);
                        headerRow.HeightInPoints = 19.5F;
                        headerRow.Height = 40 * 20;
                        headerRow.CreateCell(0).SetCellValue(columnHeader);

                        //CellStyle
                        ICellStyle headStyle = workbook.CreateCellStyle();
                        headStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;// 左右居中    
                        headStyle.VerticalAlignment = VerticalAlignment.Center;// 上下居中 
                        // 设置单元格的背景颜色(单元格的样式会覆盖列或行的样式)    
                        headStyle.FillForegroundColor = (short)11;
                        //定义font
                        IFont font = workbook.CreateFont();
                        font.FontHeightInPoints = 20;
                        font.Boldweight = 700;
                        headStyle.SetFont(font);
                        headerRow.GetCell(0).CellStyle = headStyle;
                        //根据表的列数计算
                        //sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dt.Columns.Count - 1));
                        sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dictionary.Count));
                    #endregion

                    }
                    {
                        #region 列头及样式

                        var headerRow = sheet.CreateRow(1);
                        //CellStyle
                        ICellStyle headStyle = workbook.CreateCellStyle();
                        headStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;// 左右居中    
                        headStyle.VerticalAlignment = VerticalAlignment.Center;// 上下居中 
                        //定义font
                        IFont font = workbook.CreateFont();
                        font.FontHeightInPoints = 10;
                        font.Boldweight = 700;
                        headStyle.SetFont(font);

                        int columnCount = 0;
                        foreach (var dic in dictionary)
                        {
                            foreach (DataColumn column in dt.Columns)
                            {
                                //判断需要导出的 “列”
                                if (dic.Key.ToLower()==column.ColumnName.ToLower())
                                {
                                    //headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
                                    //headerRow.GetCell(column.Ordinal).CellStyle = headStyle;
                                    //sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256);
                                    headerRow.CreateCell(columnCount).SetCellValue(dic.Value);//column.ColumnName
                                    headerRow.GetCell(columnCount).CellStyle = headStyle;
                                    sheet.SetColumnWidth(columnCount, (arrColWidth[columnCount]) * 256);
                                    columnCount++;
                                    continue;
                                }
                            }
                        }
                        #endregion
                    }

                    rowIndex = 2;
                }
                #endregion


                #region 内容
                var dataRow = sheet.CreateRow(rowIndex);

                int columnContentCount = 0; //column.Ordinal
                foreach (var dicKey in dictionary)
                {
                    foreach (DataColumn column in dt.Columns)
                    {
                        //判断需要导出的 “列”
                        if (dicKey.Key.ToLower()==column.ColumnName.ToLower())
                        {
                            var newCell = dataRow.CreateCell(columnContentCount);

                            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;
                            }
                            columnContentCount++;//列索引
                            continue;
                        }
                    }
                }

                #endregion

                rowIndex++;
            }
            //自动列宽
            for (int i = 0; i <= dictionary.Count; i++)
                sheet.AutoSizeColumn(i, true);


            return workbook;
        }
    
    }    

}
View Code

 

2.调用,先保存数据到文件夹,再将文件返回给调用页面提供下载,下载完成就删除文件,节省资源。

  public static string WriteSheet(Dictionary<string, string> dictionary, DataTable dt, string path, string sheetName)
        {
            HSSFWorkbook newBook = BuildWorkbook1(dictionary, dt, sheetName);
            string date = DateTime.Now.ToString("yyyyMMddHHmmss");
            string fileName = sheetName + "_" + date;

            #region 保存C:\ExcelList
            //string urlPath = "\\ExcelList\\" + fileName;
            //string filePath = urlPath;
            //string directoryName = Path.GetDirectoryName(urlPath);
            //if (!Directory.Exists(directoryName))
            //{
            //    Directory.CreateDirectory(directoryName);
            //}
            //using (var fs = File.OpenWrite(urlPath + ".xls"))
            //{
            //    newBook.Write(fs);
            //    Console.WriteLine("生成成功");
            //} 
            #endregion

           
            string urlPath2 = "/ExcelList/" + fileName;
            string directoryName2 = Path.GetDirectoryName(urlPath2);

            string newUrl = path + directoryName2;
            if (!Directory.Exists(newUrl))
            {
                Directory.CreateDirectory(newUrl);
            }
            using (var fs = File.OpenWrite(path + urlPath2 + ".xls"))
            {
                newBook.Write(fs);
                Console.WriteLine("生成成功");
            } 

            return fileName + ".xls";

        }
View Code

 

3.页面调用方法, Dictionary<string, string>的作用就是将要导出的DataTable数据的字段,换成中文名称,方便阅读。

 Dictionary<string, string> dictionary = new Dictionary<string, string>();

            DataTable dt = ExcelExport(1, 10000);
            if (dt.Rows.Count > 0)
            {
                sheetName = "待审核订单列表";
                dictionary.Add("OrderNo", "待审核订单号");
                dictionary.Add("Mobile", "手机号码");

                //返回路径下载
                string path = System.AppDomain.CurrentDomain.BaseDirectory;
                string fileName = MxWeiXinPF.Common.NPOIExcelHelper.WriteSheet(dictionary, dt, path, sheetName);
                //文件夹
                string folder = "/ExcelList/";
                //下载
                this.ResponDown(Response, path, folder, fileName);
View Code

 

4.下载方法

  /// <summary>
        /// 下载
        /// </summary>
        /// <param name="response">封装来自ASP.NET 的http相应消息</param>
        /// <param name="path">文件路径</param>
        /// <param name="folder">文件夹</param>
        /// <param name="fileName">文件名</param>
        public void ResponDown(HttpResponse response, string path, string folder, string fileName)
        {
            response.Clear();
            response.ClearHeaders();
            response.Buffer = false;
            response.ContentType = "application/ms-excel";
            response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
            //Response.Write(writer);
            FileStream file = new FileStream(path + folder + fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReader br = new BinaryReader(file);
            response.AppendHeader("Content-Length", file.Length.ToString());
            // StringReader sr = new StringReader(writer.GetStringBuilder().ToString());
            long flen = file.Length;
            int size = 102400;//每100k同时下载数据
            byte[] readdata = new byte[size];//指定缓冲区的大小
            if (size > flen) size = Convert.ToInt32(flen);
            long fpos = 0;
            bool isend = false;
            while (!isend)
            {
                if (response.IsClientConnected)
                {
                    if ((fpos + size) > flen)
                    {
                        size = Convert.ToInt32(flen - fpos);
                        readdata = new byte[size];
                        isend = true;
                    }
                    if (size > 1)
                    {
                        br.Read(readdata, 0, size);//读入一个压缩块
                        // byte[] re = Encoding.UTF8.GetBytes(readdata, 0, readdata.Length);
                        response.BinaryWrite(readdata);
                        //Response.OutputStream.Write(re, 0, size);
                    }
                    fpos += size;
                }
                else
                {
                    response.End();
                }
            }
            file.Close();
            br.Close();
            response.Flush();
            Response.Close();

            File.Delete(path + folder + fileName);   //删除文件
            response.End();
        }
View Code

 

最后,完成!只是简单记录,对于代码没有更好的优化,尽量以后整理好点贡献给大家!

 

posted @ 2018-08-31 14:15  baileyer  阅读(1413)  评论(0编辑  收藏  举报