1. 程式人生 > >ASP.NET MVC匯出excel(資料量大,非常耗時的,非同步匯出)

ASP.NET MVC匯出excel(資料量大,非常耗時的,非同步匯出)

要在ASP.NET MVC站點上做excel匯出功能,但是要匯出的excel檔案比較大,有幾十M,所以匯出比較費時,為了不影響對介面的其它操作,我就採用非同步的方式,後臺開闢一個執行緒將excel匯出到指定目錄,然後提供下載。匯出的excel涉及到了多個sheet(工作簿),表格合併,格式設定等,所以採用了NPOI元件。

效果如下:

選中了多行,會匯出多個工作簿sheet,一個彙總的,其他的就是明細資料。

下面是要幾個封裝好的類,從網上找的,然後修改了一下。這幾個類很多方法都封裝好了,十分利於複用。常見的excel格式都可以匯出,如果有特別的需求,可以自己修改一下原始碼進行擴充套件。

GenerateSheet.cs

using NPOI.SS.UserModel;
using NPOI.SS.Util;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;

namespace Core.Excel
{
    /// <summary>
    /// 匯出Excel基類
    /// </summary>
public class GenerateSheet<T> : BaseGenerateSheet { #region 私有欄位 // Excel 顯示時間的樣式 private ICellStyle dateStyle = null; // Excel 顯示列頭的樣式 private ICellStyle headStyle = null; // Excel 顯示內容的樣式 private ICellStyle contentsStyle = null
; // Excel 顯示總計的樣式 private ICellStyle totalStyle = null; // 列頭集合 private List<ColumnsMapping> columnHeadList = null; // 顯示的資料 private List<T> dataSource; private List<object> dataSource2; #endregion #region 屬性 /// <summary> /// Excel 顯示時間的樣式 /// </summary> protected ICellStyle DateStyle { get { return dateStyle; } set { dateStyle = value; } } /// <summary> /// Excel 顯示列頭的樣式 /// </summary> protected ICellStyle HeadStyle { get { return headStyle; } set { headStyle = value; } } /// <summary> /// Excel 顯示內容的樣式 /// </summary> protected ICellStyle ContentsStyle { get { return contentsStyle; } set { contentsStyle = value; } } /// <summary> /// Excel 顯示總計的樣式 /// </summary> protected ICellStyle TotalStyle { get { return totalStyle; } set { totalStyle = value; } } /// <summary> /// 是否有邊框 只讀 /// </summary> protected bool IsBorder { get; private set; } protected List<ColumnsMapping> ColumnHeadList { get { return this.columnHeadList; } private set { this.columnHeadList = value; } } #endregion #region 構造方法 /// <summary> /// 匯出Excel基類 /// </summary> /// <param name="_dataSource">Sheet裡面顯示的資料</param> public GenerateSheet(List<T> _dataSource) : this(_dataSource, null, string.Empty, true) { } /// <summary> /// 匯出Excel基類 /// </summary> /// <param name="_dataSource">Sheet裡面顯示的資料</param> public GenerateSheet(List<T> _dataSource, string sheetName) : this(_dataSource, null, sheetName, true) { } /// <summary> /// 匯出Excel基類 /// </summary> /// <param name="_dataSource">Sheet裡面顯示的資料</param> public GenerateSheet(List<T> _dataSource, List<object> _dataSource2, string sheetName) : this(_dataSource, _dataSource2, sheetName, true) { } /// <summary> /// 匯出Excel基類 /// </summary> /// <param name="_dataSource">Sheet裡面顯示的資料</param> /// <param name="isBorder">是否有邊框</param> public GenerateSheet(List<T> _dataSource, bool isBorder) : this(_dataSource, null, string.Empty, isBorder) { } /// <summary> /// 匯出Excel基類 /// </summary> /// <param name="_dataSource">Sheet裡面顯示的資料</param> /// <param name="isBorder">是否有邊框</param> public GenerateSheet(List<T> _dataSource, List<object> _dataSource2, string sheetName, bool isBorder) { //if (_dataSource != null && _dataSource.Count > 0) this.dataSource = _dataSource; this.dataSource2 = _dataSource2; //else // throw new Exception("資料不能為空!"); this.IsBorder = isBorder; this.SheetName = sheetName; } #endregion #region 可以被重寫的方法 /// <summary> /// 生成Excel的Sheet /// </summary> /// <param name="sheet"></param> public override void GenSheet(ISheet sheet) { this.SetSheetContents(sheet); } /// <summary> /// 初始化列頭 /// </summary> /// <returns></returns> protected virtual List<ColumnsMapping> InitializeColumnHeadData() { try { List<PropertyInfo> propertyList = this.GetObjectPropertyList(); List<ColumnsMapping> columnsList = new List<ColumnsMapping>(); int colIndex = 0; foreach (PropertyInfo propertyInfo in propertyList) { columnsList.Add(new ColumnsMapping() { ColumnsData = propertyInfo.Name, ColumnsText = propertyInfo.Name, ColumnsIndex = colIndex, IsTotal = false, Width = 15 }); colIndex++; } return columnsList; } catch (Exception ex) { throw ex; } } /// <summary> /// 設定列頭 /// </summary> /// <param name="sheet">Excel Sheet</param> /// <param name="rowIndex">記錄Excel最大行的位置,最大值為65535</param> protected virtual void SetColumnHead(ISheet sheet, ref int rowIndex) { if (columnHeadList.Count > 0) { IRow headerRow = sheet.CreateRow(rowIndex); foreach (ColumnsMapping columns in columnHeadList) { ICell newCell = headerRow.CreateCell(columns.ColumnsIndex); newCell.SetCellValue(columns.ColumnsText); newCell.CellStyle = headStyle; //設定列寬 SetColumnsWidth(sheet, columns.ColumnsIndex, columns.Width); } rowIndex++; } } /// <summary> /// 設定Excel內容 /// </summary> /// <param name="sheet"></param> /// <param name="dataSource"></param> /// <param name="rowIndex"></param> protected virtual void SetSheetContents(ISheet sheet, List<T> dataSource, ref int rowIndex) { if (dataSource != null) { foreach (T value in dataSource) { #region 填充內容 IRow dataRow = sheet.CreateRow(rowIndex); int colIndex = 0; foreach (ColumnsMapping columns in columnHeadList) { if (columns.ColumnsIndex >= 0) { if (columns.ColumnsIndex >= colIndex) colIndex = columns.ColumnsIndex; else columns.ColumnsIndex = colIndex; ICell newCell = dataRow.CreateCell(colIndex); string drValue = string.Empty; if (!string.IsNullOrEmpty(columns.ColumnsData)) drValue = GetModelValue(columns.ColumnsData, value); SetCellValue(newCell, rowIndex, drValue, columns); colIndex++; } } #endregion rowIndex++; } //rowIndex++; } } /// <summary> /// 設定單元格的資料 /// </summary> /// <param name="cell">單元格對像</param> /// <param name="rowIndex">單元格行索引</param> /// <param name="drValue">單元格資料</param> /// <param name="columns">單元格的列資訊</param> protected virtual void SetCellValue(ICell cell, int rowIndex, string drValue, ColumnsMapping columns) { cell.CellStyle = contentsStyle; if (!string.IsNullOrEmpty(columns.ColumnsData)) { PropertyInfo info = GetObjectProperty(columns.ColumnsData); switch (info.PropertyType.FullName) { case "System.String": //字串型別 double result; if (IsNumeric(drValue, out result)) { double.TryParse(drValue, out result); cell.SetCellValue(result); break; } else { cell.SetCellValue(drValue); break; } case "System.DateTime": //日期型別 if (string.IsNullOrEmpty(drValue)||drValue=="0001/1/1 0:00:00") { cell.SetCellValue(""); } else { DateTime dateV; DateTime.TryParse(drValue, out dateV); cell.SetCellValue(dateV); cell.CellStyle = dateStyle; //格式化顯示 } break; case "System.Boolean": //布林型 bool boolV = false; bool.TryParse(drValue, out boolV); cell.SetCellValue(boolV); break; case "System.Int16": //整型 case "System.Int32": case "System.Int64": case "System.Byte": int intV = 0; int.TryParse(drValue, out intV); cell.SetCellValue(intV); break; case "System.Decimal": //浮點型 case "System.Double": double doubV = 0; double.TryParse(drValue, out doubV); cell.SetCellValue(doubV); break; case "System.DBNull": //空值處理 cell.SetCellValue(""); break; default: cell.SetCellValue(""); break; } } else { cell.SetCellValue(""); } } /// <summary> /// 設定總計單元格的資料 /// </summary> /// <param name="cell">總計單元格</param> /// <param name="rowIndex">當前行的索引</param> /// <param name="startRowIndex">內容資料的開始行</param> /// <param name="columns">當前列資訊</param> protected virtual void SetTotalCellValue(ICell cell, int rowIndex, int startRowIndex, ColumnsMapping columns) { if (columns.IsTotal) { string colItem = CellReference.ConvertNumToColString(columns.ColumnsIndex); cell.CellStyle = totalStyle; cell.SetCellFormula(string.Format("SUM({0}{1}:{2}{3})", colItem, startRowIndex, colItem, rowIndex)); } } /// <summary> /// 在所有資料最後新增總計,當然也可以是其它的公式 /// </summary> /// <param name="sheet">工作薄Sheet</param> /// <param name="rowIndex">當前行</param> /// <param name="startRowIndex">內容開始行</param> protected virtual void SetTotal(ISheet sheet, ref int rowIndex, int startRowIndex) { if (rowIndex > startRowIndex) { IRow headerRow = sheet.CreateRow(rowIndex) as IRow; foreach (ColumnsMapping columns in columnHeadList) { ICell newCell = headerRow.CreateCell(columns.ColumnsIndex); SetTotalCellValue(newCell, rowIndex, startRowIndex, columns); } } } /// <summary> /// 資料來源2 /// </summary> /// <param name="sheet">工作薄Sheet</param> /// <param name="rowIndex">當前行</param> protected virtual void SetToSecond(ISheet sheet, ref int rowIndex, List<object> dataSource2) { } #endregion #region 公共方法 /// <summary> /// 獲取屬性名字 /// </summary> /// <param name="expr"></param> /// <returns></returns> protected string GetPropertyName(Expression<Func<T, object>> expr) { var rtn = ""; if (expr.Body is UnaryExpression) { rtn = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name; } else if (expr.Body is MemberExpression) { rtn = ((MemberExpression)expr.Body).Member.Name; } else if (expr.Body is ParameterExpression) { rtn = ((ParameterExpression)expr.Body).Type.Name; } return rtn; } protected void SetColumnsWidth(ISheet sheet, int colIndex, int width) { //設定列寬 sheet.SetColumnWidth(colIndex, width * 256); } #endregion #region 私有方法 private void SetSheetContents(ISheet sheet) { if (sheet != null) { // 初始化相關樣式 this.InitializeCellStyle(); // 初始化列頭的相關資料 this.columnHeadList = InitializeColumnHeadData(); // 當前行 int rowIndex = 0; // 設定列頭 this.SetColumnHead(sheet, ref rowIndex); // 內容開始行 int startRowIndex = rowIndex; // 設定Excel內容 this.SetSheetContents(sheet, dataSource, ref rowIndex); // 在所有資料最後新增總計,當然也可以是其它的公式 if (dataSource.Count > 0) { this.SetTotal(sheet, ref rowIndex, startRowIndex); } this.SetToSecond(sheet, ref rowIndex, dataSource2); } } /// <summary> /// 初始化相關對像 /// </summary> private void InitializeCellStyle() { columnHeadList = new List<ColumnsMapping>(); // 初始化Excel 顯示時間的樣式 dateStyle = this.Workbook.CreateCellStyle(); IDataFormat format = this.Workbook.CreateDataFormat(); dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); if (this.IsBorder) { //有邊框 dateStyle.BorderBottom = BorderStyle.Thin; dateStyle.BorderLeft = BorderStyle.Thin; dateStyle.BorderRight = BorderStyle.Thin; dateStyle.BorderTop = BorderStyle.Thin; } // 初始化Excel 列頭的樣式 headStyle = this.Workbook.CreateCellStyle(); headStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;// 文字居左 IFont font = this.Workbook.CreateFont(); font.FontHeightInPoints = 12; // 字型大小 font.Boldweight = 700; // 字型加粗 headStyle.SetFont(font); if (this.IsBorder) { //有邊框 headStyle.BorderBottom = BorderStyle.Thin; headStyle.BorderLeft = BorderStyle.Thin; headStyle.BorderRight = BorderStyle.Thin; headStyle.BorderTop = BorderStyle.Thin; } // 初始化Excel 顯示內容的樣式 contentsStyle = this.Workbook.CreateCellStyle(); font = this.Workbook.CreateFont(); font.FontHeightInPoints = 10; contentsStyle.SetFont(font); if (this.IsBorder) { //有邊框 contentsStyle.BorderBottom = BorderStyle.Thin; contentsStyle.BorderLeft = BorderStyle.Thin; contentsStyle.BorderRight = BorderStyle.Thin; contentsStyle.BorderTop = BorderStyle.Thin; } // 初始化Excel 顯示總計的樣式 totalStyle = this.Workbook.CreateCellStyle(); font = this.Workbook.CreateFont(); font.Boldweight = 700; font.FontHeightInPoints = 10; totalStyle.SetFont(font); if (this.IsBorder) { //有邊框 totalStyle.BorderBottom = BorderStyle.Thin; totalStyle.BorderLeft = BorderStyle.Thin; totalStyle.BorderRight = BorderStyle.Thin; totalStyle.BorderTop = BorderStyle.Thin; } } /// <summary> /// 獲取 T 對像的所有屬性 /// </summary> /// <returns></returns> private List<PropertyInfo> GetObjectPropertyList() { List<PropertyInfo> result = new List<PropertyInfo>(); Type t = typeof(T); if (t != null) { PropertyInfo[] piList = t.GetProperties(); foreach (var pi in piList) { if (!pi.PropertyType.IsGenericType) { result.Add(pi); } } } return result; } /// <summary> /// 根據屬性名字獲取 T 對像的屬性 /// </summary> /// <returns></returns> private PropertyInfo GetObjectProperty(string propertyName) { Type t = typeof(T); PropertyInfo result = t.GetProperty(propertyName); return result; } /// <summary> /// 獲取類中的屬性值 /// </summary> /// <param name="FieldName"></param> /// <param name="obj"></param> /// <returns></returns> private string GetModelValue(string FieldName, object obj) { try { Type Ts = obj.GetType(); object o = Ts.GetProperty(FieldName).GetValue(obj, null); string Value = Convert.ToString(o); if (string.IsNullOrEmpty(Value)) return null; return Value; } catch { return null; } } /// <summary> /// 判斷是否為一個數字並反回值 /// </summary> /// <param name="message"></param> /// <param name="result"></param> /// <returns></returns> private bool IsNumeric(String message, out double result) { if (!string.IsNullOrEmpty(message)) { Regex rex = new Regex(@"^[-]?\d+[.]?\d*$"); result = -1; if (rex.IsMatch(message)) { result = double.Parse(message); return true; } else return false; } else { result = 0; return false; } } #endregion } }
View Code

GenerateExcel.cs

using NPOI.HPSF;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.Excel
{
    public class GenerateExcel
    {
        #region 私有欄位
        protected XSSFWorkbook workbook = null;
        #endregion

        #region 屬性
        /// <summary>
        /// Excel的Sheet集合
        /// </summary>
        public List<BaseGenerateSheet> SheetList { get; set; }
        #endregion

        #region 構造方法
        public GenerateExcel()
        {
            InitializeWorkbook();
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 初始化相關對像
        /// </summary>
        private void InitializeWorkbook()
        {
            workbook = new XSSFWorkbook();
            SheetList = new List<BaseGenerateSheet>();
            #region 右擊檔案 屬性資訊

            //DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
            //dsi.Company = "http://www.kjy.cn";
            //workbook.DocumentSummaryInformation = dsi;



            //SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
            //si.Author = "深圳市跨境易電子商務有限公司"; //填加xls檔案作者資訊
            //si.ApplicationName = "深圳市跨境易電子商務有限公司"; //填加xls檔案建立程式資訊
            //si.LastAuthor = "深圳市跨境易電子商務有限公司"; //填加xls檔案最後儲存者資訊
            //si.Comments = "深圳市跨境易電子商務有限公司"; //填加xls檔案作者資訊
            //si.Title = "深圳市跨境易電子商務有限公司"; //填加xls檔案標題資訊
            //si.Subject = "深圳市跨境易電子商務有限公司"; //填加檔案主題資訊
            //si.CreateDateTime = DateTime.Now;
            //workbook.SummaryInformation = si;


            #endregion
            
           

相關推薦

ASP.NET MVC匯出excel料量非常耗時非同步匯出

要在ASP.NET MVC站點上做excel匯出功能,但是要匯出的excel檔案比較大,有幾十M,所以匯出比較費時,為了不影響對介面的其它操作,我就採用非同步的方式,後臺開闢一個執行緒將excel匯出到指定目錄,然後提供下載。匯出的excel涉及到了多個sheet(工作簿),表格合併,格式設定等,所以採用了N

ASP.NET MVC與CSRF跨站腳本攻擊

轉移 off end gis 帳戶 blank 表單 密碼 message CSRF 一 何為CSRF CSRF(Cross-site request forgery跨站請求偽造,也被稱成為“one click attack”或者session riding,通常縮寫為CS

.NET/ASP.NET MVC Controller 控制器深入解析控制器執行原理

閱讀目錄: 1.開篇介紹 2.ASP.NETMVC Controller 控制器的入口(Controller的執行流程) 3.ASP.NETMVC Controller 控制器的入口(Controller的繼承體系) 4.ASP.NETMVC IController Factory 控制器工廠(C

.NET/ASP.NET MVC Controller 控制器IController控制器的建立過程

閱讀目錄: 1.開篇介紹 2.ASP.NETMVC IControllerFactory 控制器工廠介面 3.ASP.NETMVC DefaultControllerFactory 預設控制器工廠 4.ASP.NETMVC ControllerBuilder 控制器建立入口設定 5.ASP.NE

ASP.NET MVC 開發隨筆

att bsp mis 最簡 目前 request 使用 重復 validate 1.目前在局部視圖中使用多個model時候,發現使用IEnumerable的時候,讀取不了原來model的內容,所以采用List發現沒問題 2. 如果想在JS中使用Razor,則需要在Ra

Asp.net MVC 使用PagedList新的已更名 為X.PagedList.Mvc 分頁

在asp.net mvc 中,可以bootstrap來作為介面,自己來寫分頁程式。也可以使用PagedList(作者已更名為 X.PagedList.Mvc)來分頁。 1、首先,在NuGet程式包管理控制檯 ,輸入Install-Package PagedList.mvc 安裝PagedList 和Page

ASP.NET MVC 系列之 強型別HTML輔助方法使用

強型別輔助方法及及相關普通方法介紹一、普通Html輔助方法 1、@Html.Lable(元素名稱,元素值,元素屬性) 示例: @Html.Lable("GenreName","流行",new { @class="validation" }) 渲染之後程式碼如下 <la

Asp.net mvc 知多少

本節主要講解MVC的基本概念 Q1. 什麼是MVC? Ans. MVC是Model-View-Controller的簡稱。它是在1970年引入的軟體設計模式。MVC 模式強迫關注分離 — 域模型和控制器邏輯與UI是鬆耦合關係。從而使應用程式的維護和測試更加簡單容易。 Q2. 解釋一下MVC設計模式? A

ASP.NET MVC Framework體驗5:路徑選擇URL Routing

概述 在傳統的ASP.NET應用程式中,發生一個請求之後將對映到一個.aspx檔案,且會對應到一個具體的物理aspx檔案。ASP.NET MVC Framework中,進入一個請求之後,不再是對映到.aspx檔案,而是由MVC Framework中提供的路徑選擇引擎,對映到

ASP.NET MVC案例教程基於ASP.NET MVC beta——第四篇:傳遞表單資料

 1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Release.aspx.cs" Inherits="MVCDemo.Views.Announce.Release"%> 2<%@ Import Namespace="

自定義ASP.NET MVC身份驗證Identity資訊

自定義ASP.NET MVC身份驗證資訊 1.前言 2.正文 ASP.NET 身份驗證(Identity)是ASP.NET應用的新一代身份認證(membership)系統。想要了解更多關於ASP.NET Identity的資訊請訪問http:/

ASP.NET MVC + EF 利用儲存過程讀取資料1億資料測試很OK

 看到本文的標題,相信你會忍不住進來看看!   沒錯,本文要講的就是這個重量級的東西,這個不僅僅支援單表查詢,更能支援連線查詢,   加入一個表10W資料,另一個表也是10萬資料,當你用linq建立一個連線查詢然後

AOP實踐--ASP.NET MVC 5使用Filter過濾Action引數防止sql注入讓你程式碼安全簡潔

在開發程式的過程中,稍微不注意就會隱含有sql注入的危險。今天我就來說下,ASP.NET mvc 5使用Filter過濾Action引數防止sql注入,讓你程式碼安全簡潔。不用每下地方對引數的值都進行檢查,看是使用者輸入的內容是否有危險的sql。如果沒個地方都要加有幾個缺

ASP.NET MVC 學習 --- 第七課(在非正常關閉IE之後自動清除資料庫中的登陸資訊)

使用者Logon之後,我們可以在logoff裡面寫一些方法幫助我們清理資料庫中的一些資料。 但是如果使用者是非正常Logoff,而是直接關閉IE,如何去自動的清理資料庫中的資料吶。這裡是用session_end方法  方法一: 在Web.Config裡面 <sessi

asp.net MVC 檔案流匯出Excel

1 <form id="FormEsExcel" action="/**/ExportEsExcelData" method="post"> 2 3 </form> <div style="float: right; margin-top: 25p

ASP.NET mvc匯出Excel檔案

首先要下載 NPOI.dll 引用到專案中     第一步。     第二步控制檯(業務邏輯層) public ActionResult Export(string CustomerName="",int SumbitUser=0,string Level

asp.net mvc 資料匯出excel表及自excel表匯入資料到相應表

一、自資料表匯出excel /// <summary> /// 匯出excel /// </summary> /// <param name="sortgid"></param>

C# MVC 自學筆記—11 在 ASP.NET MVC 中使用EXCEL匯出

====================此部分為轉載內容==================== 因為是轉載文章 在此標明出處,以前有文章是轉的沒標明的請諒解,因為有些已經無法找到出處,或者與其它原因。 如有冒犯請聯絡本人,或刪除,或標明出處。 因為好的文章,以前只想收藏,

ASP.Net MVC利用NPOI匯入匯出Excel

原文連結 因近期專案遇到所以記錄一下: 首先匯出Excel : 首先引用NPOI包 (Action一定要用FileResult) /// <summary>/// 批量匯出本校第一批派位學生/// </summary>/// <r

Asp.Net MVC匯出下載excel

    CSDN廣告是越來越多了,所有部落格筆記不再更新,新網址 DotNet筆記 程式碼: 注意:編碼方式可適當調整 ExportExcel Code public FileResult ExportExcel() {