做的上一個項目用的是vs2013,傳統的 Mvc模式開發的,excel報表的導入導出都是那幾段代碼,已經習慣了。
導入:
string filename = ExcelFileUpload.FileName;//獲取Execle文件名 string savePath = Server.MapPath(("UploadExcel\\") + filename);//Server.MapPath 服務器上的指定虛擬路徑相對應的物理文件路徑 //savePath ="D:\vsproject\Projects\exceltestweb\exceltestweb\uploadfiles\test.xls" //Response.Write(savePath); DataTable ds = new DataTable(); ExcelFileUpload.SaveAs(savePath);//將文件保存到指定路徑 DataTable dt = GetExcelDatatable(savePath);//讀取excel數據 List<RegNumInfo> regList = ConvertDtToInfo(dt);//將datatable轉為list File.Delete(savePath);//刪除文件 Response.Write("<script>alert('上傳文件讀取數據成功!');</script>");
導出:
HSSFWorkbook workbook = new HSSFWorkbook();//創建一個excel文件
ISheet sheet = workbook.CreateSheet("sheet1");//創建一個sheet
IRow row = null;//設置行
ICell cell = null;//設置單元格
//創建第一行
row = sheet.CreateRow(0);
//創建第一列
cell = row.CreateCell(0);
//給第一列賦值
cell.SetCellValue("類型");
//創建第二列
cell = row.CreateCell(1);
//給第二列賦值
cell.SetCellValue("數量");
for (int i = 0; i < listHouse.Count; i++)
{
row = sheet.CreateRow(i+1);//第幾行
row.CreateCell(0).SetCellValue(listHouse[i].ParameterName);//第一個單元格
row.CreateCell(1).SetCellValue(listHouse[i].Count);//第二個單元格
// soure和count要和前台對應file
//var housepa = new { soure = listHouse[i].ParameterName, count = listHouse[i].Count };
//list.Add(housepa);
}
MemoryStream ms = new MemoryStream();//聲明一個內存流
workbook.Write(ms);//將文件寫入流中
context.Response.ContentType = "application/vnd.ms-excel";//輸入的格式
//文件信息(文件頭)attachment設置文件為打開 保存對話框
context.Response.AddHeader("Content-Disposition",
"attachment;filename=" + HttpUtility.UrlEncode(type, System.Text.Encoding.UTF8) +
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ".xls");
context.Response.BinaryWrite(ms.ToArray());//字節格式輸入
context.Response.End();
workbook = null;
ms.Close();//關閉流
ms.Dispose();//釋放資源
但是現在做項目我用的是vs2019 ,用.net core 2.2 開發。在做導入導出報表的時候發現以前的模式不好使了,原因是指定路徑的方法不能用了:Server.MapPath(),
用.net core 模式開發項目,也是剛接觸怎末導入導出也不知道,那就只能問百度了。然后搜了一下,復制粘貼,修修改改很快就搞定了。
在core里要注冊IHostingEnvironment 環境變量才能做excel的導入導出操作,(這里之說簡單操作,如何封裝就看個人了)
新建一個控制器,在控制器里直接注冊就行了。
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using SmartNet.Core; using System.Data; using Microsoft.AspNetCore.Http.Abstractions; using Microsoft.AspNetCore.Mvc.ViewFeatures; using System.IO; using Newtonsoft.Json; using SmartNet.Data; using Microsoft.AspNetCore.Hosting; using OfficeOpenXml; using Microsoft.Azure.ActiveDirectory.GraphClient; namespace SmartNet.Web.Areas.ProjectManage.Controllers { public class TaskController : ControllerBase { private IHostingEnvironment _hostingEnvironment; public TaskController(IHostingEnvironment hostingEnvironment) { _hostingEnvironment = hostingEnvironment; } } }
在做之前要下載插件:
裝完插件后,首先是導入操作:
頁面:
<div id="importBox" style="display:none"> <form enctype="multipart/form-data" method="post" action="/####/####/Import"> <input type="file" name="excelfile" /> <input type="submit" value="導入" /> </form> </div> <script> function TaiZhangExport() { layer.open({ type: 1, skin: 'layui-layer-rim', //加上邊框 area: ['420px', '240px'], //寬高 content: $("#importBox").html() }); } </script>
后台:
/// <summary> /// 公用路徑 /// </summary> /// <returns></returns> private Tuple<string, string> GetTuple(string ExcelName) { string sWebRootFolder = _hostingEnvironment.WebRootPath;//獲取根路徑,core資源文件夾一般都在www.root目錄下,關於這塊可以看我的 .net app接口文章,那里詳細介紹了這塊。 string sFileName = $"{ExcelName}.xlsx"; return Tuple.Create(sWebRootFolder, sFileName); } [HttpPost] public IActionResult Import(IFormFile excelfile) { string sWebRootFolder = GetTuple("報表模板").Item1; string sFileName = GetTuple("報表模板").Item2; FileInfo file = new FileInfo(Path.Combine(sWebRootFolder, sFileName)); string[] FileType = excelfile.FileName.Split('.'); if (FileType[1] != "xlsx" && FileType[1] != "xls") { ///financemanage/ledger/list return Content("你導如的文件格式不正確,請導入excel文件格式(.xlsx,xls)"); } if (!System.IO.Directory.Exists(sWebRootFolder + sFileName))//判斷路徑是否存在 { file.Delete(); //刪除服務器上的臨時文件 } try { //FileStream對象表示在磁盤或網絡路徑上指向文件的流。這個類提供了在文件中讀寫字節的方。 //Create:文件存在刪除該文件,不存在創建新文件。 using (FileStream fs = new FileStream(file.ToString(), FileMode.Create)) { excelfile.CopyTo(fs); fs.Flush(); } using (ExcelPackage package = new ExcelPackage(file)) { StringBuilder sb = new StringBuilder(); ExcelWorksheet worksheet = package.Workbook.Worksheets[0]; int rowCount = worksheet.Dimension.Rows; int ColCount = worksheet.Dimension.Columns; bool isTrue = false; ////////////////////////////////////////////////////////////////////////////////////// //注意在導入報表時,並不是能將導入就萬事大吉了,要判斷一下excel表里的數據是否和你要求的數據匹配,例如:時間數據,整型數據,浮點型數據,excel表中的每一列數據類型都要與你要求的每一列數據里類型匹配。 // 這時就需要我們自己在讀取excel表中的數據時,自己去一個一個審查了。審查一般也有兩種方式: // 1,表中數據哪一行數據不通過,就過濾掉不通過的數據,通過的數據還按原方式導入,不通過的輸出第幾行,第幾列的錯誤信息,比如:第二行,第三列,時間格式錯誤!(可以邊判斷邊導入,一行通過就導入一行) // 2,表中數據只要有一行不通過,整個表中的數據都不能導入,不通過的輸出第幾行,第幾列的錯誤信息,比如:第二行,第三列,時間格式錯誤!(先判斷后導入,就是先對整個表數據進行匹配,只要都通過了,才能導入) 我在這里做的事第二種方式,至於選哪種方式要根據業務情況的。下面就是如何匹配數據了。 // 比如我要導入的數據有四行,第一行時string,第二行是:int 第三行是:float 第四行是:datatime 格式是(2019/10/23) 注意:時間格式要盡量定一個統一模式 for (int row = 2; row <= rowCount; row++)//在excel表中第一行是標題,所以數據是從第二行開始的。 { for (int col = 1; col <= ColCount; col++) { if (col>1&&col<4) { if (worksheet.Cells[row, col].Value.ToString().Length == 0)//表中數據有可能是空,如果是字符格式就無所謂了,但是如果是整型或者浮點型,那就要判一下,給個默認值0了 { worksheet.Cells[row, col].Value = 0; } if (!Regex.IsMatch(worksheet.Cells[row, col].Value.ToString(), @"^[+-]?\d*[.]?\d*$"))//大家知道,整型可以轉浮點型,例如:float a 可以 a=1.0 也可以 a=1所以兩個一塊直接判斷了。 { if (isTrue == false) { sb.Append("導入文件失敗!" + "\t"); sb.Append(" 有一下錯誤:" + "\t"); } sb.Append("第" + row + "行" + col + "列數據類型錯誤!" + "\t"); isTrue = true; } } // Regex reg = new Regex(@"^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|30|31)/([1-9]\d{3})$", RegexOptions.None | RegexOptions.IgnoreCase | RegexOptions.Multiline); // MatchCollection mc = reg.Matches(worksheet.Cells[row, col].Value.ToString()); //^(?\d{2,4})/(?\d{1,2})/(?\d{1,2})$ if (col ==4) { if (SelectDateTime(worksheet.Cells[row, col].Value.ToString()))//判斷時間格式在SelectDatatime方法中處理的,在下面 { if (isTrue == false) { sb.Append("導入文件失敗!" + "\t"); sb.Append(" 有一下錯誤:" + "\t"); } sb.Append("第" + row + "行" + col + "列時間格式類型錯誤!" + "\t"); isTrue = true; } } } sb.Append(Environment.NewLine);//重新起一行 } if (isTrue == true) { return Content(sb.ToString()); //如果isture==true 說明有錯誤數據就直接返回錯誤數據,就不再進行導入操作了。 } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 下面是,如果所有數據都匹配成功了,那就要執行導入操作了。 for (int row = 2; row <= rowCount; row++) { string 第一個數據=worksheet.Cells[Row,1].Value.ToString(), int 第二個數據 = int.Parse(worksheet.Cells[Row,2].value.ToString()), int 第三個數據 =float.Parse(worksheet.Cells[Row,3].value.ToString()), string 第四個數據 =worksheet.Cells[Row,4].value.ToString(), //下面就是如何把excel表中的數據插入數據庫了,兩種方式:1,數據一行一行插入。2,將數據存入DadaTable中整體存入。具體要看數據量了。 例如一行一行插入可以直接在for循環中直接插入就行了。 --插入的sql語句 --存儲過程名 } file.Delete();//刪除剛創建的臨時文件。 return Redirect("/ReportManage/Finance_CostNoTower/List"); } } catch (Exception ex) { return Content(ex.Message); } } public bool SelectDateTime(string strtime) { try { DateTime.Parse(strtime);//籠統的判斷字符串格式是否是時間格式 } catch { return true; } string StrTime = strtime; //判斷系統讀取的時間格式是否和文件中的時間格式一致 //例如文件上時間格式是"2019/07"而系統讀取格式是:"2019/07/01 星期一 0:00:00" if (strtime.Length > 7) { //如果不一致,取第一個空格前的字符串。 StrTime = strtime.Substring(0, strtime.IndexOf(' ')); } //系統定義excel文件中時間格式是"2019/07"或者"2019/7"如果是其它格式則認為是錯誤時間格式。 if (!StrTime.Contains('/')) { return true; } return false; }
導入的基本過程也就這些了。下面是導出,導出就相對容易多了,不需要在進行數據匹配了。
頁面:
<button class="layui-btn" style="position: absolute;right: 20px;top: 60%; margin-top: -9px;cursor: pointer" onclick="Import()"> 導出數據 </button> <script> function Import() { location.href = "/ReportManage/Finance_CostNoTower/Export?" +傳入的參數 } </script>
后台:
public IActionResult Export() { DataTable dtList=獲取數據庫數據的方法(參數); string sWebRootFolder = GetTuple("報表模板").Item1; string sFileName = GetTuple("報表模板").Item2; FileInfo file = new FileInfo(Path.Combine(sWebRootFolder, sFileName));//創建一個FileInfo實例,創建路徑 if (!System.IO.Directory.Exists(sWebRootFolder + sFileName))//文件是否存在如果存在刪掉文件重新創建。 { file.Delete(); //刪除服務器上的臨時文件 } using (ExcelPackage package = new ExcelPackage(file))//創建excel { // 添加worksheet ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("aspnetcore"); //worksheet.Cells.Style.ShrinkToFit = true;//單元格自動適應大小 for (int i = 1; i < 4; i++) { worksheet.Column(i).Width = 25;//設置列寬 } //添加頭 worksheet.Cells[1, 1].Value = "excel表格第一列標題"; worksheet.Cells[1, 2].Value = "excel表格第二列標題"; worksheet.Cells[1, 3].Value = "excel表格第三列標題"; worksheet.Cells[1, 4].Value = "excel表格第四列標題"; if (dtList != null && dtList.Rows.Count > 0) { //添加值 int Count = 1; for (int i = 0; i < dtList.Rows.Count; i++) { Count++; DataRow item = dtList.Rows[i];//創建行 worksheet.Cells[Count, 1].Value = item[數據庫中數據參數名].ToString(); worksheet.Cells[Count, 2].Value = item[數據庫中數據參數名].ToString(); worksheet.Cells[Count, 3].Value = item[數據庫中數據參數名].ToString(); worksheet.Cells[Count, 4].Value = item[數據庫中數據參數名].ToString(); } } package.Save();//保存 } return File(sFileName, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "導出數據.xlsx");//導出excel表格 }
好了,到這里excel報表的導入導出就介紹完了。希望對一些朋友有些幫助。