簡介
學了上一節的WebApi之後,我們會發現一片新天地
本節跟大家聊一聊,如何把本地的Excel資料匯入到NCF中
倉庫地址:https://github.com/NeuCharFramework/NCF
歡迎收藏,歡迎Star哦
步驟
1.首先在頁面上需要增加可以操作匯入的按鈕
2.在頁面上增加點選匯入按鈕後需要彈出的視窗
3.在視窗中增加下載匯入資料的模板
4.在視窗中增加點選上傳的資料的檔案進行上傳
5.在js中增加對應的視窗中需要處理的方法
6.引入NPOI
7.建立ExcelHelper類用來讀取Excel檔案內容
8.在api中增加上傳資料檔案的接收方法
9.在Service中處理上傳的檔案的資料
實施
1.首先在頁面上需要增加可以操作匯入的按鈕
1 <el-button class="filter-item" size="mini" type="primary" @@click="handleEdit('','','import')">匯入</el-button>
2.在頁面上增加點選匯入按鈕後需要彈出的視窗
1 @*匯入*@ 2 <el-dialog :title="dialogImport.title" 3 :visible.sync="dialogImport.visible" 4 :close-on-click-modal="false" 5 width="700px"> 6 7 <el-form ref="dataFormImport" 8 :rules="dialogImport.rules" 9 :model="dialogImport.data" 10 :disabled="dialogImport.disabled" 11 label-position="left" 12 label-width="100px" 13 style="max-width: 200px; margin-left:50px;"> 14 <el-button @@click="downloadTemplate">下載匯入模板</el-button> 15 <el-form-item label="匯入的檔案"> 16 <el-upload class="upload-demo" 17 action="@Model.UpFileUrl" 18 accept=".xls,.xlsx" 19 :on-success="uploadSuccess" 20 :on-preview="handlePreview" 21 :on-remove="handleRemove" 22 :before-remove="beforeRemove" 23 multiple 24 :limit="3" 25 :on-exceed="handleExceed" 26 :file-list="fileList" 27 ref="my-upload"> 28 <el-button size="small" type="primary">點選上傳</el-button> 29 <div slot="tip" class="el-upload__tip">只能上傳excel檔案</div> 30 </el-upload> 31 <el-input class="hidden" v-model="dialogImport.data.file" clearable placeholder="檔案" /> 32 </el-form-item> 33 </el-form> 34 <div slot="footer" class="dialog-footer"> 35 <el-button @@click="dialogImport.visible=false">取消</el-button> 36 <el-button :loading="dialogImport.updateLoading" :disabled="dialogImport.disabled" type="primary" @@click="dialogImport.visible=false">確認</el-button> 37 </div> 38 </el-dialog>
js中的程式碼
1 dialogImport: 2 { 3 title: '匯入資料', 4 visible: false, 5 data: 6 { 7 file: '' 8 }, 9 updateLoading: false, 10 disabled: false, 11 checkStrictly: true // 是否嚴格的遵守父子節點不互相關聯 12 }
3.在視窗中增加下載匯入資料的模板
這裡可以本地編輯一個Excel的檔案,欄位可以根據自己實際的隨便寫
4.在視窗中增加點選上傳的資料的檔案進行上傳
el-upload控制元件則是用來上傳檔案的
5.在js中增加對應的視窗中需要處理的方法
1 downloadTemplate() { 2 window.open("https://aaa.oss-cn-beijing.aliyuncs.com/ImportData.xls", '_blank') 3 }
6.引入NPOI
1 <PackageReference Include="NPOI" Version="2.5.3" />
7.建立ExcelHelper類用來讀取Excel檔案內容
1 using NPOI.SS.UserModel; 2 using System; 3 using System.Collections.Generic; 4 using System.Data; 5 using System.IO; 6 using System.Text; 7 8 namespace Senparc.Xncf.Admin.Utils 9 { 10 public class ExcelHeler 11 { 12 /// <summary> 13 /// 讀取Excel多Sheet資料 14 /// </summary> 15 /// <param name="filePath">檔案路徑</param> 16 /// <param name="sheetName">Sheet名</param> 17 /// <returns></returns> 18 public static DataSet ReadExcelToDataSet(string filePath, string sheetName = null) 19 { 20 if (!File.Exists(filePath)) 21 { 22 //logger.LogError($"未找到檔案{filePath}"); 23 return null; 24 } 25 //獲取檔案資訊 26 FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); 27 IWorkbook workbook = WorkbookFactory.Create(fs); 28 //獲取sheet資訊 29 ISheet sheet = null; 30 DataSet ds = new DataSet(); 31 if (!string.IsNullOrEmpty(sheetName)) 32 { 33 sheet = workbook.GetSheet(sheetName); 34 if (sheet == null) 35 { 36 //logger.LogError($"{filePath}未找到sheet:{sheetName}"); 37 return null; 38 } 39 DataTable dt = ReadExcelFunc(workbook, sheet); 40 ds.Tables.Add(dt); 41 } 42 else 43 { 44 //遍歷獲取所有資料 45 int sheetCount = workbook.NumberOfSheets; 46 for (int i = 0; i < sheetCount; i++) 47 { 48 sheet = workbook.GetSheetAt(i); 49 if (sheet != null) 50 { 51 DataTable dt = ReadExcelFunc(workbook, sheet); 52 if (dt != null) ds.Tables.Add(dt); 53 } 54 } 55 } 56 return ds; 57 } 58 59 /// <summary> 60 /// 讀取Excel多Sheet資料 61 /// </summary> 62 /// <param name="filePath">檔案路徑</param> 63 /// <param name="sheetName">Sheet名</param> 64 /// <returns></returns> 65 public static DataSet ReadExcelToDataSet(FileStream fs, string sheetName = null) 66 { 67 IWorkbook workbook = WorkbookFactory.Create(fs); 68 //獲取sheet資訊 69 ISheet sheet = null; 70 DataSet ds = new DataSet(); 71 if (!string.IsNullOrEmpty(sheetName)) 72 { 73 sheet = workbook.GetSheet(sheetName); 74 if (sheet == null) 75 { 76 //logger.LogError($"{filePath}未找到sheet:{sheetName}"); 77 return null; 78 } 79 DataTable dt = ReadExcelFunc(workbook, sheet); 80 ds.Tables.Add(dt); 81 } 82 else 83 { 84 //遍歷獲取所有資料 85 int sheetCount = workbook.NumberOfSheets; 86 for (int i = 0; i < sheetCount; i++) 87 { 88 sheet = workbook.GetSheetAt(i); 89 if (sheet != null) 90 { 91 DataTable dt = ReadExcelFunc(workbook, sheet); 92 if (dt != null) 93 ds.Tables.Add(dt); 94 } 95 } 96 } 97 return ds; 98 } 99 100 /// <summary> 101 /// 讀取Excel資訊 102 /// </summary> 103 /// <param name="workbook">工作區</param> 104 /// <param name="sheet">sheet</param> 105 /// <returns></returns> 106 private static DataTable ReadExcelFunc(IWorkbook workbook, ISheet sheet) 107 { 108 DataTable dt = new DataTable(); 109 //獲取列資訊 110 IRow cells = sheet.GetRow(sheet.FirstRowNum); 111 //空資料化返回 112 if (cells == null) return null; 113 int cellsCount = cells.PhysicalNumberOfCells; 114 //空列返回 115 if (cellsCount == 0) return null; 116 int emptyCount = 0; 117 int cellIndex = sheet.FirstRowNum; 118 List<string> listColumns = new List<string>(); 119 bool isFindColumn = false; 120 while (!isFindColumn) 121 { 122 emptyCount = 0; 123 listColumns.Clear(); 124 for (int i = 0; i < cellsCount; i++) 125 { 126 if (string.IsNullOrEmpty(cells.GetCell(i).StringCellValue)) 127 { 128 emptyCount++; 129 } 130 listColumns.Add(cells.GetCell(i).StringCellValue); 131 } 132 //這裡根據邏輯需要,空列超過多少判斷 133 if (emptyCount == 0) 134 { 135 isFindColumn = true; 136 } 137 cellIndex++; 138 cells = sheet.GetRow(cellIndex); 139 } 140 141 foreach (string columnName in listColumns) 142 { 143 if (dt.Columns.Contains(columnName)) 144 { 145 //如果允許有重複列名,自己做處理 146 continue; 147 } 148 dt.Columns.Add(columnName, typeof(string)); 149 } 150 //開始獲取資料 151 int rowsCount = sheet.PhysicalNumberOfRows; 152 var rowIndex = 1; 153 DataRow dr = null; 154 //空資料化返回 155 if (rowsCount <= 1) { return null; } 156 for (int i = rowIndex; i < rowsCount; i++) 157 { 158 cells = sheet.GetRow(i); 159 dr = dt.NewRow(); 160 for (int j = 0; j < dt.Columns.Count; j++) 161 { 162 //這裡可以判斷資料型別 163 switch (cells.GetCell(j).CellType) 164 { 165 case CellType.String: 166 dr[j] = cells.GetCell(j).StringCellValue; 167 break; 168 case CellType.Numeric: 169 dr[j] = cells.GetCell(j).NumericCellValue.ToString(); 170 break; 171 case CellType.Unknown: 172 dr[j] = cells.GetCell(j).StringCellValue; 173 break; 174 } 175 } 176 dt.Rows.Add(dr); 177 } 178 return dt; 179 } 180 } 181 }
8.在api中增加上傳資料檔案的接收方法
1 /// <summary> 2 /// 上傳資料 3 /// </summary> 4 /// <param name="file">檔案資訊</param> 5 /// <returns></returns> 6 [HttpPost] 7 public IActionResult ImportExcelData([FromForm] IFormFile file) 8 { 9 string prefixPath = string.Empty; 10 try 11 { 12 var file_data = this.Request.Form.Files[0]; 13 if (file_data == null) 14 { 15 return Fail("檔案引數無效,請提供name值為file_data的檔案"); 16 } 17 //驗證副檔名 18 var extension = Path.GetExtension(file_data.FileName); 19 if (!AllowFileExtension.FileExtension.Contains(extension)) 20 { 21 return Fail("不支援此副檔名檔案的上傳!"); 22 } 23 //基礎儲存路徑 24 var basePath = "default"; // sysKeyModel.Name; 25 //驗證檔案字首路徑有效性 26 if (!string.IsNullOrWhiteSpace(prefixPath)) 27 { 28 if (prefixPath.IndexOfAny(Path.GetInvalidPathChars()) > -1)//驗證路徑有效性 29 { 30 return Fail("無效路徑!"); 31 } 32 //進一步規範路徑 33 var invalidPattern = new Regex(@"[\\\/\:\*\?\042\<\>\|]"); 34 prefixPath = invalidPattern.Replace(prefixPath, ""); 35 36 prefixPath = prefixPath.Replace("_", "\\");//使用下劃線“_”代替斜槓“\” 37 basePath = Path.Combine(basePath, prefixPath); 38 } 39 //物理檔案路徑 40 var pathMp = Path.Combine(_webHostEnvironment.ContentRootPath, staticResourceSetting.CurrentValue.RootDir, basePath); 41 if (!Directory.Exists(pathMp)) Directory.CreateDirectory(pathMp); 42 43 string strFileName = file_data.FileName.Split('\\').LastOrDefault(); 44 45 var filename = $"{DateTime.Now:yyyyMMddHHmmss}-{UniqueHelper.LongId()}{extension}"; 46 string strFileHash = string.Empty; 47 string strFilePath = string.Empty; 48 using (var fs = new FileStream(Path.Combine(pathMp, filename), FileMode.CreateNew)) 49 { 50 file_data.CopyTo(fs); 51 strFileHash = HashHelper.SHA1File(fs);//賦值檔案Hash值 52 fs.Flush(); 53 } 54 //開始解析Excel 55 //呼叫ExcelHelper方法 56 DataSet ds = ExcelHeler.ReadExcelToDataSet(Path.Combine(pathMp, filename)); 57 SenparcTrace.Log($"{pathMp}----{filename}"); 58 dataService.ImportDataAsync(ds); 59 return Success("匯入成功"); 60 } 61 catch (Exception ex) 62 { 63 return Fail(ex.Message); 64 } 65 }
9.在Service中處理上傳的檔案的資料
1 public void ImportDataAsync(DataSet ds) 2 { 3 if (ds != null) 4 { 5 DataTable dt = ds.Tables[0]; 6 if (dt.Rows.Count > 0) 7 { 8 List<DataEntity> lstData = new List<DataEntity>(); 9 for (int i = 0; i < dt.Rows.Count; i++) 10 { 11 int iRows = GetCount(_ => _.Name.Equals(dt.Rows[i][0].ToString())); 12 if (iRows > 0) 13 { 14 continue; 15 } 16 DataEntity dataItem = new DataEntity() 17 { 18 Name = dt.Rows[i][0].ToString() 19 }; 20 lstData.Add(dataItem); 21 } 22 SaveObjectListAsync(lstData); 23 } 24 } 25 }
有疑問隨時歡迎交流