NCF 如何导入Excel数据
简介
学了上一节的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 }
有疑问随时欢迎交流
希望大家能一起加入到NCF的社区当中来,一起为中国之崛起Coding
QQ:365845726