@
- 本文旨在解決無需調用后端接口,實現前端讀取表格文件,獲取文件內容,渲染到界面的需求
- 我的其他文章可以解決擴展需求:
- 讀取解析表格后執行自動單元格合並
- 讀取解析表格后根據數據對比分析自動設置單元格顏色
- 讀取解析表格后執行數據分析(透析)生成可滿足用戶自定義需求的echarts關系圖
- 下載界面表格功能
說明
公司平時做后台管理系統比較多,類似需求更是十分常見,我也寫過類似帖子,但是都是只放代碼從來不寫注釋和步驟,嘿嘿,話不多說,此文章為完整的記錄:
前提
平時我經常使用的是:
Ant Design + Angular
Element UI + Vue
Ant Design + Vue
方便起見,今天我們使用Element UI + Vue
基於vue-element-admin直接開始
代碼倉庫
步驟一:准備工作
- 點擊進入vue-element-admin下載
- 下載解壓
- 安裝依賴、運行
- 運行成功
步驟二:實現導入表格解析
- 進入以下路徑;
src\views\dashboard\index.vue
- 刪除無用代碼,准備開始;
<template>
<div class="dashboard-container">
</div>
</template>
<script>
export default {
name: 'Dashboard'
}
</script>
<style lang="scss" scoped>
</style>
- 增加 導入 按鈕,保存刷新;
<template>
<div class="dashboard-container">
<!-- 導入按鈕 -->
<div class="button_group">
<a
href="javascript:;"
class="button_s my_file el-button button_s el-button--primary el-button--small"
>
<input type="file" class="my_input" @change="importExcel" id="upload" />導入
</a>
</div>
<!-- 導入按鈕 -->
</div>
</template>
<script>
export default {
name: 'Dashboard',
methods: {
/**
* 導入表格
*/
importExcel(e) {
}
}
}
</script>
<style lang="scss" scoped>
// 按鈕樣式
.button_group {
.button_s {
width: 78px;
margin: 5px 10px 5px 5px;
}
.button_m {
width: 100px;
margin: 5px 10px 5px 5px;
}
.my_file {
position: relative;
.my_input {
position: absolute;
opacity: 0;
width: 78px;
height: 30px;
top: 0;
left: 0;
}
}
}
// 按鈕樣式
</style>
-
下載xlsx 、引入;
-
編寫導入表格 功能、保存刷新;
<script>
import xlsx from "xlsx";
export default {
name: 'Dashboard',
methods: {
/**
* 導入表格
*/
importExcel(e) {
const files = e.target.files;
console.log(files);
if (!files.length) {
return ;
} else if (!/\.(xls|xlsx)$/.test(files[0].name.toLowerCase())) {
return alert("上傳格式不正確,請上傳xls或者xlsx格式");
}
const fileReader = new FileReader();
fileReader.onload = ev => {
try {
const data = ev.target.result;
const XLSX = xlsx;
const workbook = XLSX.read(data, {
type: "binary"
});
const wsname = workbook.SheetNames[0]; //取第一張表,wb.SheetNames[0]是獲取Sheets中第一個Sheet的名字
const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格內容,wb.Sheets[Sheet名]獲取第一個Sheet的數據
const excellist = []; //清空接收數據
//編輯數據
for (var i = 0; i < ws.length; i++) {
excellist.push(ws[i]);
}
console.log("讀取結果", excellist); // 此時得到的是一個內容是對象的數組需要處理
} catch (e) {
return alert("讀取失敗!");;
}
};
fileReader.readAsBinaryString(files[0]);
var input = document.getElementById("upload");
input.value = "";
}
}
}
</script>
-
編寫如下表格,用來測試功能 ;
-
有時候,表格題目是中文,讀取后我們想要得到英文屬性名,那么 增加如下代碼 、再次測試;
<script>
import xlsx from "xlsx";
export default {
name: 'Dashboard',
methods: {
getHeader(sheet) {
const XLSX = xlsx;
const headers = [];
const range = XLSX.utils.decode_range(sheet["!ref"]); // worksheet['!ref'] 是工作表的有效范圍
let C;
/* 獲取單元格值 start in the first row */
const R = range.s.r; // 行 // C 列
let i = 0;
for (C = range.s.c; C <= range.e.c; ++C) {
var cell =
sheet[
XLSX.utils.encode_cell({ c: C, r: R })
]; /* 根據地址得到單元格的值find the cell in the first row */
var hdr = "UNKNOWN" + C; // 如果有空表頭,會替換為您想要的默認值replace with your desired default
// XLSX.utils.format_cell 生成單元格文本值
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell);
if(hdr.indexOf('UNKNOWN') > -1){
if(!i) {
hdr = '__EMPTY';
}else {
hdr = '__EMPTY_' + i;
}
i++;
}
headers.push(hdr);
}
return headers;
},
/**
* 導入表格
*/
importExcel(e) {
const files = e.target.files;
console.log(files);
if (!files.length) {
return ;
} else if (!/\.(xls|xlsx)$/.test(files[0].name.toLowerCase())) {
return alert("上傳格式不正確,請上傳xls或者xlsx格式");
}
const fileReader = new FileReader();
fileReader.onload = ev => {
try {
const data = ev.target.result;
const XLSX = xlsx;
const workbook = XLSX.read(data, {
type: "binary"
});
const wsname = workbook.SheetNames[0]; //取第一張表,wb.SheetNames[0]是獲取Sheets中第一個Sheet的名字
const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格內容,wb.Sheets[Sheet名]獲取第一個Sheet的數據
const excellist = []; //清空接收數據
//編輯數據
for (var i = 0; i < ws.length; i++) {
excellist.push(ws[i]);
}
console.log("讀取結果", excellist); // 此時得到的是一個內容是對象的數組需要處理
// 獲取表頭2-1
const a = workbook.Sheets[workbook.SheetNames[0]];
const headers = this.getHeader(a);
console.log('headers', headers);
// 獲取表頭2-2
} catch (e) {
return alert("讀取失敗!");;
}
};
fileReader.readAsBinaryString(files[0]);
var input = document.getElementById("upload");
input.value = "";
}
}
}
</script>
我們把表格改成不規則狀態、保存、打開界面測試
步驟三:實現表格渲染
- 界面增加 表格組件 。
<!-- 表格組件 -->
<div class="myTable">
<el-table
max-height="600"
:data="dataArr"
v-loading="tableLoading"
:span-method="objectSpanMethod"
border
style="width: 100%"
>
<el-table-column
:prop="item.prop"
:label="item.label"
:width="item.width"
v-for="(item, i) in tableColumn"
:key="i"
></el-table-column>
</el-table>
</div>
<!-- 表格組件 -->
data() {
return {
dataArr: [], // 表格內容數據數組
// countArr: {}, // 分析表格數據以及表頭,得到一個對照數組,用來進行自定義合並,本文暫時只寫基礎,不介紹自動合並單元格了喲~~我的其他文章有寫自定義合並實現方法~
tableColumn: [], // 表格表頭配置數組
tableLoading: false // 表格是否loading
};
},
2. 增加 表格渲染方法 。
備注:表格渲染方法中有一部分代碼是用來映射中英文屬性名的,這個是我增加的一個功能,有時候也不不需要使用,可以按自己需求來修改代碼;
setTable(headers, excellist) {
const tableTitleData = []; // 存儲表格表頭數據
const tableMapTitle = {}; // 設置表格內容中英文對照用
headers.forEach((_, i) => {
tableMapTitle[_] = "prop" + i;
tableTitleData.push({
prop: "prop" + i,
label: _,
width: 100
});
});
console.log("tableTitleData", tableTitleData);
// 映射表格內容屬性名為英文
const newTableData = [];
excellist.forEach(_ => {
const newObj = {};
Object.keys(_).forEach(key => {
newObj[tableMapTitle[key]] = _[key];
});
newTableData.push(newObj);
});
console.log('newTableData',newTableData);
this.tableColumn = tableTitleData;
this.dataArr = newTableData;
},
- 調用 表格渲染方法 。
// 在importExcel(e)方法中添加下面代碼
// 渲染表格1-1
this.setTable(headers, excellist);
// 渲染表格1-2
- 功能測試
結語
本代碼支持不規則數據,沒有表頭的也可以渲染到界面哦~~
歡迎大家指出我代碼的錯誤~
如果有更好的寫法,歡迎大家提出來,共同進步喲~~