C#_.NetCore_Web項目_EXCEL數據導出

来源:https://www.cnblogs.com/lxhbky/archive/2019/10/29/11760000.html
-Advertisement-
Play Games

項目需要引用NPOI的Nuget包:DotNetCore.NPOI-v1.2.2 A-前端觸發下載Excel的方法有三種: 1-JS-Url跳轉請求-後臺需要返迴文件流數據: 2-使用form+iframe請求文件流-後臺需要返迴文件流數據: 3-JS-Fetch請求使用Blob保存二進位文件流數據 ...


項目需要引用NPOI的Nuget包:DotNetCore.NPOI-v1.2.2

 

A-前端觸發下載Excel的方法有三種:

  1-JS-Url跳轉請求-後臺需要返迴文件流數據:

window.Location.href = "/ajax/toolhelper.js?action=reBuyExport&beginTime=" + beginTime + "&endTime=" + endTime;

  2-使用form+iframe請求文件流-後臺需要返迴文件流數據:

<form target="downLoadIframe" method="post" action="/ajax/toolhelper.js?action=reBuyExport">
        <div class="form-group">
            <label for="datetime">beginTime:</label>
            <input type="date" class="form-control" name="beginTime" placeholder="Enter beginTime" />
        </div>
        <div class="form-group">
            <label for="datetime">endTime:</label>
            <input type="date" class="form-control" name="endTime" placeholder="Enter endTime">
        </div>
        <button type="submit" class="btn btn-primary" id="btnExport">導出Excel</button>
    </form>
    <iframe id="downLoadIframe" name="downLoadIframe" style="display:none;"></iframe>

  3-JS-Fetch請求使用Blob保存二進位文件流數據,通過A標簽下載流文件-後臺需要返迴文件流數據:

  領導推薦這種方法,經過檢驗的,可以應對大文件下載的超時問題

fetch(url).then(function (res) {
                    res.blob().then(function (blob) {
                        var a = document.createElement('a');
                        var url = window.URL.createObjectURL(blob);
                        a.href = url;
                        a.download = fileName;
                        a.click();
                        window.URL.revokeObjectURL(url);
                    });
                });

 

B-後臺返迴流數據:

 

Core下的Excel幫助類

/// <summary>
    /// EXCEL幫助類
    /// </summary>
    /// <typeparam name="T">泛型類</typeparam>
    /// <typeparam name="TCollection">泛型類集合</typeparam>
    public class ExcelHelp<T, TCollection> where TCollection : List<T> where T : new()
    {
        public static ExcelHelp<T, TCollection> INSTANCE = new ExcelHelp<T, TCollection>();
        //獲取httpResponse對象原位置,放在這裡不知道會報錯:伺服器無法在發送 HTTP 標頭之後追加標頭
        //可能是這裡拿到的httpResponse對象不是最新請求的對象導致的,將其放到方法內部即可
        //HttpResponse baseResponse = HttpContext.Current.Response;

        /// <summary>
        /// 將數據導出EXCEL
        /// </summary>
        /// <param name="tList">要導出的數據集</param>
        /// <param name="fieldNameAndShowNameDic">鍵值對集合(鍵:欄位名,值:顯示名稱)</param>
        /// <param name="httpResponse">響應</param>
        /// <param name="excelName">文件名(必須是英文或數字)</param>
        /// <returns></returns>
        public async Task ExportExcelData(TCollection tList, Dictionary<string, string> fieldNameAndShowNameDic, HttpResponse httpResponse, string excelName = "exportResult")
        {
            IWorkbook workbook = new HSSFWorkbook();
            ISheet worksheet = workbook.CreateSheet("sheet1");

            List<string> columnNameList = fieldNameAndShowNameDic.Values.ToList();
            //設置首列顯示
            IRow row1 = worksheet.CreateRow(0);
            ICell cell = null;
            ICellStyle cellHeadStyle = workbook.CreateCellStyle();
            //設置首行字體加粗
            IFont font = workbook.CreateFont();
            font.Boldweight = short.MaxValue;
            cellHeadStyle.SetFont(font);
            for (var i = 0; i < columnNameList.Count; i++)
            {
                cell = row1.CreateCell(i);
                cell.SetCellValue(columnNameList[i]);
                cell.CellStyle = cellHeadStyle;
            }

            //根據反射創建其他行數據
            var raws = tList.Count;
            Dictionary<int, PropertyInfo> indexPropertyDic = this.GetIndexPropertyDic(fieldNameAndShowNameDic.Keys.ToList());

            for (int i = 0; i < raws; i++)
            {
                row1 = worksheet.CreateRow(i + 1);

                for (int j = 0; j < fieldNameAndShowNameDic.Count; j++)
                {
                    cell = row1.CreateCell(j);
                    if (indexPropertyDic[j].PropertyType == typeof(int)
                        || indexPropertyDic[j].PropertyType == typeof(decimal)
                        || indexPropertyDic[j].PropertyType == typeof(double))
                    {
                        cell.SetCellValue(Convert.ToDouble(indexPropertyDic[j].GetValue(tList[i])));
                    }
                    else if (indexPropertyDic[j].PropertyType == typeof(DateTime))
                    {
                        cell.SetCellValue(Convert.ToDateTime(indexPropertyDic[j].GetValue(tList[i]).ToString()));
                    }
                    else if (indexPropertyDic[j].PropertyType == typeof(bool))
                    {
                        cell.SetCellValue(Convert.ToBoolean(indexPropertyDic[j].GetValue(tList[i]).ToString()));
                    }
                    else
                    {
                        cell.SetCellValue(indexPropertyDic[j].GetValue(tList[i]).ToString());
                    }
                }
                //設置行寬度自適應
                worksheet.AutoSizeColumn(i, true);
            }

            MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/vnd.ms-excel");
            mediaType.Encoding = System.Text.Encoding.UTF8;

            httpResponse.ContentType = mediaType.ToString();
            //設置導出文件名
            httpResponse.Headers.Add("content-disposition", $"attachment;filename={excelName}.xls");
            MemoryStream ms = new MemoryStream();
            workbook.Write(ms);
            //這句代碼非常重要,如果不加,會報:打開的EXCEL格式與擴展名指定的格式不一致
            ms.Seek(0, SeekOrigin.Begin);
            byte[] myByteArray = ms.GetBuffer();
            httpResponse.Headers.Add("Content-Length", myByteArray.Length.ToString());
            await httpResponse.Body.WriteAsync(myByteArray, 0, myByteArray.Length);
        }

        /// <summary>
        /// 根據屬性名順序獲取對應的屬性對象
        /// </summary>
        /// <param name="fieldNameList"></param>
        /// <returns></returns>
        private Dictionary<int, PropertyInfo> GetIndexPropertyDic(List<string> fieldNameList)
        {
            Dictionary<int, PropertyInfo> indexPropertyDic = new Dictionary<int, PropertyInfo>(fieldNameList.Count);
            List<PropertyInfo> tPropertyInfoList = typeof(T).GetProperties().ToList();
            PropertyInfo propertyInfo = null;
            for (int i = 0; i < fieldNameList.Count; i++)
            {
                propertyInfo = tPropertyInfoList.Find(m => m.Name.Equals(fieldNameList[i], StringComparison.OrdinalIgnoreCase));
                indexPropertyDic.Add(i, propertyInfo);
            }

            return indexPropertyDic;
        }

    }
View Code

 

Core的中間件請求方法:

TBDataHelper為提前註入的資料庫幫助類,需要改成自己的數據請求類;

自定義的導出文件名,不能輸入中文,暫時還沒有找到解決辦法;

BaseMiddleware為基類,切記基類中只能存常態化的數據,如:下一中間件,配置,緩存。不能存放Request,Response等!!!

public class ToolHelperMiddleware : BaseMiddleware
    {
        public TBDataHelper TBDataHelper { get; set; }
        public ToolHelperMiddleware(RequestDelegate next, ConfigurationManager configurationManager, IMemoryCache memoryCache, TBDataHelper tBDataHelper) : base(next, configurationManager, memoryCache)
        {
            this.TBDataHelper = tBDataHelper;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            var query = httpContext.Request.Query;
            var queryAction = query["action"];

            switch (queryAction)
            {
                case "reBuyExport":
                    await this.ReBuyExport(httpContext);
                    break;
            }
        }

        /// <summary>
        /// 復購數據導出
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        private async Task ReBuyExport(HttpContext httpContext)
        {
            var request = httpContext.Request;
            var response = httpContext.Response;
            var requestForm = request.Form;

            try
            {
                DateTime beginTime = Convert.ToDateTime(requestForm["beginTime"]);
                DateTime endTime = Convert.ToDateTime(requestForm["endTime"]);

                List<RebuyModel> rebuyModelList = this.TBDataHelper.SelectReBuyList(beginTime, endTime);

                Dictionary<string, string> fieldNameAndShowNameDic = new Dictionary<string, string>(0);
                fieldNameAndShowNameDic.Add("UserID", "用戶ID");
                fieldNameAndShowNameDic.Add("PayCount", "支付數");
                fieldNameAndShowNameDic.Add("BeforeBuyCount", beginTime.ToString("MM/dd") + "之前支付數");

                string fileName = $"{beginTime.ToString("MMdd")}_{endTime.ToString("MMdd")}ReBuyExport_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";
                await ExcelHelp<RebuyModel, List<RebuyModel>>.INSTANCE.ExportExcelData(rebuyModelList, fieldNameAndShowNameDic, response, fileName);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

    }
View Code
/// <summary>
    /// 中間件基類
    /// </summary>
    public abstract class BaseMiddleware
    {
        /// <summary>
        /// 等同於ASP.NET裡面的WebCache(HttpRuntime.Cache)
        /// </summary>
        protected IMemoryCache MemoryCache { get; set; }

        /// <summary>
        /// 獲取配置文件裡面的配置內容
        /// </summary>
        protected ConfigurationManager ConfigurationManager { get; set; }

        /// <summary>
        /// 下一個中間件
        /// </summary>
        protected RequestDelegate Next { get; set; }

        public BaseMiddleware(RequestDelegate next, params object[] @params)
        {
            this.Next = next;
            foreach (var item in @params)
            {
                if (item is IMemoryCache)
                {
                    this.MemoryCache = (IMemoryCache)item;
                }
                else if (item is ConfigurationManager)
                {
                    this.ConfigurationManager = (ConfigurationManager)item;
                }
            }
        }

    }
View Code

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在下麵這個例子中,我們分別在父類和子類中測試了 靜態代碼塊、普通代碼塊、靜態成員變數、普通成員變數、構造器、靜態內部類 。 一:代碼塊及變數測試 二:測試結果 三:測試靜態內部類 四:總結 經過我們反覆調整順序進行測試後,可得出如下結論: 1、靜態代碼塊、靜態成員變數只有第一次載入類時才會執行。 2 ...
  • 註意:eg a+2a=4 第一個a的k等於0 特例 eg -2=6y 等號右邊f要變 ...
  • 在 Scala 中所有值都有一種對應的類型 單例類型 形式: ,返回類型 / 場景1:鏈式API調用時的類型指定 由於 Scala 會將 推斷為當前類(即 ),因此無法完成鏈式調用 場景2:方法中使用 實例作為參數 Note:不可定義為 ~~def c1(obj: Foo)~~,因為 Foo 為單例 ...
  • Default Executables 預設可執行文件 Default Executables 預設可執行文件 在 dotnet build 或 dotnet publish 期間,將創建一個與你使用的 SDK 的環境和平臺相匹配的可執行文件。 和其他本機可執行文件一樣,可以使用這些可執行文件執行相 ...
  • 簡介 本教程採用 WHY WHAT HOW 黃金圈思維模式編寫,黃金圈法則強調的是從 WHY 為什麼學,到 WHAT 學到什麼,再到 HOW 如何學。從模糊到清晰的學習模式。大家的時間都很寶貴,我們做事前先想清楚為什麼要做,學完能達到什麼樣的目標,然後我們再考慮要達到這個目的,通過什麼樣的方法來實現 ...
  • AForge.NET是一個專門為開發者和研究者基於C#框架設計的,提供了不同的類庫和關於類庫的資源,還有很多應用程式例子,包括電腦視覺與人工智慧,圖像處理,神經網路,遺傳演算法,機器學習,機器人等領域。本文主要講解利用AForge進行圖像採集的相關內容【包括拍照,視頻錄製】,僅供學習分享使用。 ...
  • .NET Core從最早期的版本就開始支持全局工具了。如果僅僅需要在某個項目中或某個文件夾中使用特定的工具,那麼.NET Core 3.0就允許您這樣做。 .NET Core從最早期的版本就開始支持全局工具了。如果僅僅需要在某個項目中或某個文件夾中使用特定的工具,那麼.NET Core 3.0就允許 ...
  • C# 程式中的類型、成員和其他實體支持使用修飾符來控制其行為的某些方面。 例如,方法的可訪問性是由 public、protected、internal 和 private 修飾符控制。 C# 整合了這種能力,以便可以將用戶定義類型的聲明性信息附加到程式實體,併在運行時檢索此類信息。 程式通過定義和使 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...