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

 

最后,完成!只是簡單記錄,對於代碼沒有更好的優化,盡量以后整理好點貢獻給大家!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM