Excel
注意:这里是前端使用xlsx插件,将前端上传的.xls、.xlsx文件,解析得到原始列表数据
我的是vue3项目
文章目录
- 1.安装依赖
- 2.组件封装
- 3.子组件使用
1.安装依赖
pnpm add xlsx@0.18.5
2.组件封装
src/components/MyExcelData/index.vue
<template><div v-loading="loading"><div class="drop-area" @dragenter="highlight" @dragover="highlight" @dragleave="unHighlight" @drop="handleDrop"@click="handleClick"><el-icon :size="67" color="#9ea1a9" class="el-icon--upload"><upload-filled /></el-icon><div class="desc" v-if="props.msg">{{ props.msg }}</div><input type="file" ref="fileInput" @change="handleFiles" :multiple="multipleFlag" accept=".xlsx, .xls"style="display: none;"></div></div>
</template><script setup>
import { defineProps } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'import { ref } from 'vue';
import * as XLSX from 'xlsx';defineOptions({name: "MyExcelData"
})
const props = defineProps({headerList: { type: Array, default: () => [] }, // 表头英文列表msg: { type: String, default: () => '' }, // 描述
})
const emit = defineEmits(["setExcelData"])let loading = ref(false)
const tableData = ref([]);
const tableHeader = ref([]);// const fileList = ref([]) // 当前组件内的文件集合
const inputList = ref([]) // 这个是input拿到的list 不一定调用上传接口
const fileInput = ref(null); // 上传ref
const multipleFlag = ref(false) // 是否多选const highlight = (e) => {e.preventDefault();e.stopPropagation();e.target.classList.add('hover');
};const unHighlight = (e) => {e.target.classList.remove('hover');
};// 拖拽
const handleDrop = (e) => {e.preventDefault();e.stopPropagation();unHighlight(e);const files = e.dataTransfer.files;inputList.value = [] // 必须这几步都置空 不然无效for (let i = 0; i < files.length; i++) {inputList.value.push({...files[i],name: files[i].name,size: files[i].size,type: files[i].type});}uploadFile();
};// 点击
const handleClick = () => {// console.log(fileInput.value);fileInput.value.click(); // 使用 ref 的 value 直接访问 DOM 元素
};// 获取点击文件
const handleFiles = (e) => {const files = e.target.files || e;// console.log('files', files, typeof files, files[0]);inputList.value = [] // 必须这几步都置空 不然无效for (let i = 0; i < files.length; i++) {inputList.value.push({file: files[i],name: files[i].name,size: files[i].size,type: files[i].type});}uploadFile();
};// 上传文件
const uploadFile = () => {// console.log('inputList', inputList.value);const file = inputList.value[0].file// console.log('上传接口的文件', file);handleFileUpload(file)
};const handleFileUpload = (event) => {loading.value = truetableData.value = [];tableHeader.value = [];// const file = event.target.files[0];const file = eventconst reader = new FileReader();reader.onload = (e) => {const data = new Uint8Array(e.target.result);const workbook = XLSX.read(data, { type: 'array' });const sheetName = workbook.SheetNames[0];const sheet = workbook.Sheets[sheetName];const jsonData = XLSX.utils.sheet_to_json(sheet, { header: 1 });// console.log('jsonData', jsonData);tableHeader.value = props.headerList.length ? props.headerList : jsonData[0]//tableData.value = jsonData.slice(1);// 遍历总数居中除第一项的每个数组for (let i = 1; i < jsonData.length; i++) {let obj = {};// 遍历arr1第一项的数组,将其元素作为key,与当前遍历的数组对应位置的元素作为value,构建对象for (let j = 0; j < tableHeader.value.length; j++) {obj[tableHeader.value[j]] = jsonData[i][j];}tableData.value.push(obj); // 将构建好的对象添加到arr2中}// console.log('tableData.value', tableData.value);// 过滤掉属性值全是undefined的对象function removeItemsWithUndefinedValues(arr) {return arr.filter(obj => {return Object.values(obj).some(value => value !== undefined);});}tableData.value = removeItemsWithUndefinedValues(tableData.value)// console.log(tableData.value)emit('setExcelData', { tableHeader: tableHeader.value, tableData: tableData.value })ElMessage.success('解析成功')loading.value = false};reader.onerror = (e) => {ElMessage.error('解析失败', e)emit('setExcelData', { tableHeader: tableHeader.value, tableData: [] })loading.value = false; // 可以在这里取消加载状态或者进行其他错误处理操作};reader.readAsArrayBuffer(file);// return 掉 不调用接口的报错return false
};</script>
<style lang="scss" scoped>
.drop-area {width: 440px;height: 185px;border: 1px dashed #dcdfe6;border-radius: 6px;text-align: center;cursor: pointer;padding-top: 40px;
}.drop-area:hover {border-color: #11716f;
}
</style>
3.子组件使用
注意点:
headerList就是列表数据的表头;一定要保证headerList的长度和数据列对应
<!-- 导入组件 -->
<MyExcelData :headerList="['tableName', 'tableType', 'tableAuthority', 'tableNameDesc']"@setExcelData="setExcelData" :msg="'仅支持导入表格格式,扩展名.xls、.xlsx,导入成功后,表信息将全部更新,请核对导入数据'"></MyExcelData>// 解析数据
const setExcelData = (val) => {console.log('解析数据', val)
}