C# 匯出excel的壓縮包到瀏覽器頁面
阿新 • • 發佈:2018-12-16
需求背景:TCX_1710專案產品質量匯出功能,客戶希望每個總成匯出到一個Excel表中
實現分析:客戶選擇時間段,點選匯出按鈕,預設匯出開始時間當天的資料,每個總成一個Excel,將各個Excel打包壓縮,返回壓縮包到瀏覽器頁面供客戶下載
控制器類:
/// <summary> /// 匯出產品質量資訊(每個總成一個Excel) /// </summary> /// <param name="keyword"></param> /// <returns></returns>public void exportExcel(string keyword) { string SNum = Request.QueryString["SNum"]; string PSCode = Request.QueryString["PSCode"]; string StartTime = Request.QueryString["StartTime"]; string EndTime = Request.QueryString["EndTime"];//dictionary根據以上查詢條件查詢的資料字典 Dictionary<string, Dictionary<string, List<PR_Product>>> dictionary = new Dictionary<string, Dictionary<string, List<PR_Product>>>(); if (keyword == "TimeAndSnum") { dictionary = this.CreateService<IProductInfoAppServices>().GetDictionary("TimeAndSnum", SNum, PSCode, StartTime, EndTime); } else { dictionary = this.CreateService<IProductInfoAppServices>().GetDictionary("NoTimeNoSnum", SNum, PSCode, StartTime, EndTime); } //初始化需要匯出欄位 List<ExportFieldInfo> fieldInfo10 = new List<ExportFieldInfo>(); var tableInfo10 = this.CreateService<IProductInfoAppServices>().getFiledByTable(); for (var i = 0; i < tableInfo10.Count; i++) { fieldInfo10.Add(new ExportFieldInfo() { FieldName = tableInfo10[i].filedName, DisplayName = tableInfo10[i].filedExplain, DataType = DataTypeEnum.String }); } string filePath = ConfigurationManager.AppSettings["filePath"];//配置寫在E:\MyProject\1710\02_程式碼\DoMes.Web\Configs\system.config //string filePath = "F:\\exporfolder"; FileStream stream = ExcelHelper<PR_Product>.ToExcel(filePath, dictionary, fieldInfo10, Response); Response.Flush(); Response.End();//關閉響應 stream.Close();//關閉zip流,否則無法刪除zip檔案 //獲取指定路徑下所有資料夾 //string[] folderPaths = Directory.GetDirectories(filePath); //獲取指定路徑下所有檔案 var filePaths = Directory.GetFiles(filePath); foreach (string filePath_2 in filePaths) { //刪除所有檔案 System.IO.File.Delete(filePath_2); } //foreach (string folderPath in folderPaths) //{ // Directory.Delete(folderPath, true); //} //刪除最外面的資料夾 Directory.Delete(filePath, true); }
獲取資料的方法:
/// <summary> /// 根據查詢條件獲取資料,並將資料轉換為資料字典 /// </summary> /// <param name="type">查詢型別(暫時不用)</param> /// <param name="sNum">產品總成</param> /// <param name="pSCode">工位</param> /// <param name="startTime">開始時間</param> /// <param name="endTime">結束時間</param> /// <returns></returns> public Dictionary<string, Dictionary<string, List<PR_Product>>> GetDictionary(string type, string sNum, string pSCode, string startTime, string endTime) { //第一層key為日期(年/月/日),value為該日所有總成的資料字典集合 //第二層key為總成,value為該總成所有的質量資料 Dictionary<string, Dictionary<string, List<PR_Product>>> dictionary = new Dictionary<string, Dictionary<string, List<PR_Product>>>(); Expression<Func<PR_Product, bool>> exp = (a => 1 == 1); if (!string.IsNullOrEmpty(pSCode)) { exp = exp.And(a => a.PSCode == pSCode); } if (!string.IsNullOrEmpty(startTime)) { DateTime ctStart = Convert.ToDateTime(startTime); exp = exp.And(a => a.CreationTime >= ctStart); } if (!string.IsNullOrEmpty(endTime)) { DateTime ctEnd = Convert.ToDateTime(endTime); exp = exp.And(a => a.CreationTime < ctEnd.AddDays(1)); } if (!string.IsNullOrEmpty(sNum)) { exp = exp.And(a => a.SNum.Contains(sNum)); } //根據查詢條件獲得的產品質量資料 List<PR_Product> product = this.DbContext.Query<PR_Product>().Where(exp).OrderBy(a => a.SNum).ThenBy(it => it.PSCode).ToList(); //產品總成不為空則只有一個總成 if (!string.IsNullOrEmpty(sNum)) { Dictionary<string, List<PR_Product>> dictionary2 = new Dictionary<string, List<PR_Product>>(); dictionary2.Add(sNum, product); dictionary.Add(startTime, dictionary2); } else//產品總成為空 { Dictionary<string, List<PR_Product>> dictionary2 = new Dictionary<string, List<PR_Product>>(); //從查詢的資料集合中查詢出所有的總成 List<PR_Product> snumDistinct = product.Where((x, firstId) => product.FindIndex(z => z.SNum == x.SNum) == firstId).ToList(); foreach(PR_Product item in snumDistinct) { //從大資料集合中查詢該總成的資料集合 List<PR_Product> snumList = product.Where(x => x.SNum == item.SNum).ToList(); dictionary2.Add(item.SNum, snumList); } dictionary.Add(startTime, dictionary2); } return dictionary; }
Excel檔案幫助類方法:
/// <summary> /// 匯出產品質量資料,每個總成一個Excel /// </summary> /// <param name="filePath">匯出檔案路徑</param> /// <param name="dictionary">匯出資料字典</param> /// <param name="fieldInfies">匯出資料表頭</param> /// <param name="Response">頁面響應</param> /// <returns></returns> public static FileStream ToExcel(String filePath, Dictionary<string, Dictionary<string, List<T>>> dictionary, List<ExportFieldInfo> fieldInfies, HttpResponseBase Response) { //匯出檔案路徑(這裡也可以寫成固定路徑"F:\\exporfolder") //String filePath = "F:\\exporfolder"; //建立此路徑(配置檔案中的地址一定要保證磁碟存在) Directory.CreateDirectory(filePath); //匯出壓縮檔案的全路徑(zipFilePath) DateTime dateTimeZip = DateTime.Now; string zipFilePath = filePath + Path.DirectorySeparatorChar + "QM_" + dateTimeZip.ToString("yyyyMMdd") + "_" + dateTimeZip.ToString("HHmmss") + "_" + dateTimeZip.ToString("fff") + ".zip"; //匯出Excel檔案路徑 string fullFilePath = ""; //儲存Excel檔名 string fileName = ""; //用於存放生成的Excel檔名稱集合 List<string> fileNames = new List<string>(); //excel檔案流 FileStream excel = null; foreach (Dictionary<string, List<T>> items in dictionary.Values) { foreach (var item in items) { DateTime dateTimeExcel = DateTime.Now; //Excel檔名 fileName = item.Key + "_" + dateTimeExcel.ToString("yyyyMMdd") + "_" + dateTimeExcel.ToString("HHmmss") + "_" + dateTimeExcel.ToString("fff") + ".xlsx"; //Excel檔案路徑 fullFilePath = filePath + Path.DirectorySeparatorChar + fileName; //存放到Excel檔名稱集合 fileNames.Add(fullFilePath); excel = File.Create(fullFilePath); HSSFWorkbook book = createColumnHSSF(item.Key, item.Value, fieldInfies); // 寫檔案 book.Write(excel); excel.Close(); } } FileStream stream = ZipFiles(fileNames, zipFilePath, Response); return stream; }
/// <summary> /// 壓縮多個檔案 /// </summary> /// <param name="filesToZip">要進行壓縮的檔名集合</param> /// <param name="zipedFile">壓縮後生成的壓縮檔名</param> public static FileStream ZipFiles(List<string> filesToZip, string zipedFile, HttpResponseBase Response) { Response.AddHeader("content-disposition", "attachment;filename=" + zipedFile.Substring(zipedFile.LastIndexOf("\\", StringComparison.Ordinal) + 1) ); //Zip檔案流 FileStream zipFile = File.Create(zipedFile); //將zipStream寫到響應輸出流中 ZipOutputStream zipStream = new ZipOutputStream(Response.OutputStream); //遍歷所有的Excel檔案 foreach (string fileToZip in filesToZip) { if (string.IsNullOrEmpty(fileToZip)) { throw new ArgumentException(fileToZip); } if (string.IsNullOrEmpty(zipedFile)) { throw new ArgumentException(zipedFile); } if (!File.Exists(fileToZip)) { throw new FileNotFoundException("指定要壓縮的檔案: " + fileToZip + " 不存在!"); } try { //讀取Excel檔案到檔案流中 using (var fs = File.OpenRead(fileToZip)) { var buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length); fs.Close(); //從Excel檔案路徑中讀取Excel檔名 var fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\", StringComparison.Ordinal) + 1); //根據檔名建立ZipEntry var zipEntry = new ZipEntry(fileName); //將ZipEntry放入zipStream流中 zipStream.PutNextEntry(zipEntry); zipStream.SetLevel(5); zipStream.Write(buffer, 0, buffer.Length); } } catch (IOException ioex) { throw new IOException(ioex.Message); } catch (Exception ex) { throw new Exception(ex.Message); } } //zipStream完成後返回 zipStream.Finish(); return zipFile; }