<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
npm i node-xlsx
首先是查詢出資料庫內所有的表的資訊,然後傳至下一個下劃線轉大小寫的公用函數,進行key的轉換,然後就進行資料的加工;
因為匯出except表的宮功能會在業務中頻繁使用,所以我們需要給它封裝成一個公用函數,其他的業務使用直接傳參呼叫即可!
1、封裝公用函數
/** * excel 匯出 * list:[{}] * headers:表頭中文名 * headerKeys:與表頭中文名一一對應的資料區key * tableName:匯出的表名稱以什麼開頭 */ export const excelExport = (list, headers, headerKeys, tableName = 'excel') => { // excel 通用樣式 const sheetOptions = { '!cols': [] } headers.forEach(() => { sheetOptions['!cols'].push({ wch: 20 }) }) const data = [] list.forEach((item) => { let arr = [] const item2 = flatten(item) headerKeys.forEach((key) => { if (excelMap.changDictExport[key]) { arr.push(excelMap.changDictExport[key][item[key]]) } else { arr.push(item2[key]) } }) data.push(arr) }) data.unshift(headers) const buffer = xlsx.build( [{ options: {}, name: `${tableName}_${new Date().valueOf()}`, data: data }], { sheetOptions } ) return buffer }
2、headers例子:
userHeader: [ '使用者序號', '登入名稱', '使用者郵箱', '手機號碼', '使用者性別', '帳號狀態', '最後登入IP', '最後登入時間', '部門名稱', '部門負責人' ],
3、headerKeys例子:
userHeaderKeys: [ 'userId', 'userName', 'email', 'phonenumber', 'sex', 'status', 'loginIp', 'loginDate', 'dept.deptName', 'dept.leader' ]
4、因為資料可能存在跨表查詢,會出現物件巢狀結構,故需要封裝物件扁平化函數flatten,將多層結構的key變成dept.deptName這種格式
/** * 物件扁平化 */ export const flatten = (obj) => { let result = {} let process = (key, value) => { // 首先判斷是基礎資料型別還是參照資料型別 if (Object(value) !== value) { // 基礎資料型別 if (key) { result[key] = value } } else if (Array.isArray(value)) { for (let i = 0; i < value.length; i++) { process(`${key}[${i}]`, value[i]) } if (value.length === 0) { result[key] = [] } } else { let objArr = Object.keys(value) objArr.forEach((item) => { process(key ? `${key}.${item}` : `${item}`, value[item]) }) if (objArr.length === 0 && key) { result[key] = {} } } } process('', obj) return result }
5、node-xlsx接收的資料格式
[ [ '使用者序號', '登入名稱', '使用者郵箱', '手機號碼', '使用者性別', '帳號狀態', '最後登入IP', '最後登入時間', '部門名稱', '部門負責人' ], [ 1, 'admin', '12012311715@163.com', '12012311715', '男', '正常', '', '00:00:00', '深圳總公司', 'wen' ], [ 2, 'password', null, null, '未知', '正常', null, null, '研發部門', 'wen' ] ]
6、在業務函數中呼叫匯出excel表的資料
const buffer = excelExport( users, excelExportMap.userHeader, excelExportMap.userHeaderKeys, 'user' )
7、最終excel匯出的效果
因為匯入的情況比較複雜,會分為多種情況上傳excel檔案:
1、單檔案單工作表;
2、單檔案多工作表;
3、多檔案(單)多工作表;
我個人解決辦法是獲取放置excel檔案的資料夾內所有的excel檔案,然後進行資料的提取,在提取完資料後,就將該次的excel檔案刪除掉,當然匯入excel功能也是需要進行公用封裝的;
1、解析本次匯入的所有excel檔案內資料
// 匯入excel--解析 export const importExcelsMid = (tableMap: string) => { return async (ctx: Context, next: () => Promise<void>) => { try { const fileExistPath = path.resolve() + 'srcupload' let fileName = [] // 多個excel檔案儲存地 fs.readdirSync(path.format({ dir: fileExistPath })).forEach((excel) => { if (excel.split('.')[excel.split('.').length - 1] === 'xlsx' && 'xls') { fileName.push(excel) } }) // 拿去多個excel檔案 const workSheetsFromBuffer = [] fileName.forEach((item) => { const absoluteFilePath = fileExistPath + '' + item //整個檔案的絕對路徑 workSheetsFromBuffer.push(xlsx.parse(fs.readFileSync(absoluteFilePath))) //這種方式是解析buffer }) // 生成預設使用者密碼 const salt = bcrypt.genSaltSync(10) const hash = bcrypt.hashSync('123456', salt) const arr = [] // 儲存sql批次建立的資訊 object[] workSheetsFromBuffer.forEach((element) => { element.forEach((item: any) => { // 此層是遍歷表數量(單表資料提取) const data = item.data for (let j = 1; j < data.length; j++) { // 此層是加入每行資料 const obj = { password: hash } for (let i = 0; i < data[0].length; i++) { let key = excelMap[tableMap][data[0][i]] if (excelMap.changDict[key]) { obj[key] = excelMap.changDict[key][data[j][i]] } else { obj[key] = data[j][i] } } arr.push(obj) } }) }) // 獲取資料後刪除excel檔案 fileName.forEach((path) => { removeSpecifyFile(path) }) ctx.state.excelData = arr } catch (error) { console.error('使用者excel上傳表頭格式不正確!', ctx.request['body']) return ctx.app.emit('error', importUserListErr, ctx) } await next() } }
2、寫入本次匯入的所有excel檔案內資料
updates:是控制你更新哪些的key陣列
[ 'dept_id', 'user_name', 'nick_name', 'email', 'phonenumber', 'sex', 'status' ]
updates案例 ☝
// 匯入excel--新增修改sql export const judegImportMid = (table, updates) => { return async (ctx: Context, next: () => Promise<void>) => { const { updateSupport } = ctx.query try { if (updateSupport === '1') { // 新增 且 修改 await table.bulkCreate(ctx.state.excelData, { updateOnDuplicate: updates }) } else { // 不更改 只新增 await table.bulkCreate(ctx.state.excelData) } ctx.body = { code: 200, message: '使用者資訊上傳成功!' } } catch (error) { console.error('user excel新增與修改錯誤', ctx.request['body']) return ctx.app.emit('error', { code: '400', message: error.errors[0].message }, ctx) } } }
3、匯入的案例excel
4、解析後的資料
[ { password: '$2a$10$Mp19aHpTTIZXwAYpwAg8QuOUQ6DmBswHFhwR8iRqjduNw9tQU.xRO', undefined: 'test', user_name: 'test', email: 'test', phonenumber: 'test', sex: '0', status: '0' } ]
5、已寫入資料庫
上面的功能僅僅是完成了基本的excel匯入和匯出,更多關於koa2匯入匯出Excel的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45