<input type="file" @change="fileChange">
1、txt文件
fileChange(event) {
console.log('fileChange', event)
const file = event.target.files[0];
const reader = new FileReader();
reader.readAsText(file);
reader.onload = function(e) {
console.log('reader', e)
// 文本内容
console.error(reader.result)
// 切分行
// reader.result.split('\n').forEach(function(v, i){
// console.log(v);
// });
};
}
2、excel文件
1)安装解析插件xlsx
npm i xlsx
2)以 array 形式读取
import * as XLSX from 'xlsx'
fileChange(event) {
console.log('fileChange', event)
const file = event.target.files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function(e) {
console.log('reader', e)
// excel文件 —— array
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, {type: 'array'});
// 假设我们只读取第一个工作表
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
const jsonData = XLSX.utils.sheet_to_json(worksheet);
console.log(jsonData, worksheet);
};
}
3)以 binary 形式读取
import * as XLSX from 'xlsx'
fileChange(event) {
console.log('fileChange', event)
const file = event.target.files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function(e) {
console.log('reader', e)
// excel文件 —— binary
const workbook = XLSX.read(e.target.result, {type: 'binary'});
const sheetNames = workbook.SheetNames; // 工作表名称集合
const worksheet = workbook.Sheets[sheetNames[0]]; // 这里我们只读取第一张sheet
// 输出字符串形式
const csv = XLSX.utils.sheet_to_csv(worksheet);
console.log(csv)
// 输出数组形式
const rows = csv.split('\n'); // 转化为数组
rows.pop(); // 最后一行没用的
console.log(rows); // 打印输出的数组
};
}
3、vue案例
1)组件形式
一个可以解析获取本地excel文件和txt文件的按钮组件,可以自定义插槽内容
<parseExcelBtn @getResult="getResult"></parseExcelBtn>
<parseExcelBtn @getResult="getResult" btnWidth="300px">
<span>自定义按钮</span>
</parseExcelBtn>
getResult(e) {
console.log(e)
},
<template>
<div class="parse-excel-btn"
:style="{
width: btnWidth
}"
@click="doClick">
<slot v-if="hasDefaultSlotContent"></slot>
<div v-else class="txt">{{ btnTxt }}</div>
<input type="file" hidden accept=".txt, .xlsx, .xls" ref="fileInput" @change="fileChange">
</div>
</template>
<script lang="ts" setup>
import { ref, withDefaults, defineProps, defineEmits, watch, useSlots, onMounted } from 'vue'
import * as XLSX from 'xlsx'
import { Message } from 'view-ui-plus'
interface Props {
btnTxt?: string, // 按钮文本
btnWidth?: string // 按钮宽度
resultType?: string // 输出结果类型
readType?: string // 读取类型
}
const props = withDefaults(defineProps<Props>(), {
btnTxt: '导入excel',
btnWidth: 'auto',
resultType: 'string', // array string
readType: 'binary' // array binary
})
console.log(props)
const emit = defineEmits(['getResult'])
const fileInput = ref(null)
const hasDefaultSlotContent = ref(false)
const slots = useSlots();
onMounted(() => {
// 检查默认插槽是否有内容
if (slots.default) {
const slotContent = slots.default();
if(slotContent) {
hasDefaultSlotContent.value = true
}
// hasDefaultSlotContent.value = slotContent.some(({ vnode }) => {
// console.log(vnode)
// // 检查节点是否是文本节点且不为空
// return vnode.type === Text && vnode.children.trim() !== '';
// });
}
})
// 按钮点击
function doClick() {
if(fileInput) {
fileInput.value.click()
}
}
// 本地文件选择
function fileChange(event: any) {
console.log('fileChange', event)
const file = event.target.files[0];
if(!file) {
return
}
let testMsg = file.name.substring(file.name.lastIndexOf('.')+1)
if(!['txt','xlsx', 'xls'].includes(testMsg)) {
Message.error('不是excel文件~')
return
}
const reader = new FileReader();
if(testMsg === 'txt') {
reader.readAsText(file);
} else {
if(props.readType === 'array'){
reader.readAsArrayBuffer(file);
} else {
reader.readAsBinaryString(file);
}
}
reader.onload = function(e) {
// console.log('reader', e)
if(testMsg === 'txt') {
// txt文件
// console.error(reader.result)
// reader.result.split('\n').forEach(function(v, i){
// console.log(v);
// });
emit('getResult', reader.result)
} else {
if(props.readType === 'array') {
// excel文件 —— array
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, {type: 'array'});
// 假设我们只读取第一个工作表
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
const jsonData = XLSX.utils.sheet_to_json(worksheet);
// console.log(jsonData, worksheet);
emit('getResult', jsonData)
} else {
// excel文件 —— binary
const workbook = XLSX.read(e.target.result, {type: 'binary'});
const sheetNames = workbook.SheetNames; // 工作表名称集合
const worksheet = workbook.Sheets[sheetNames[0]]; // 这里我们只读取第一张sheet
const csv = XLSX.utils.sheet_to_csv(worksheet);
if(props.resultType === 'array') {
// 数组形式
const rows = csv.split('\n'); // 转化为数组
rows.pop(); // 最后一行没用的
// console.log(rows); // 打印输出的数组
emit('getResult', rows)
} else {
// 字符串形式
// console.log(csv)
emit('getResult', csv)
}
}
}
}
}
</script>
<style lang="scss" scoped>
.parse-excel-btn {
cursor: pointer;
.txt {
line-height:40px;
background:#ebf2ff;
border-radius:6px;
text-align: center;
font-weight:500;
color:#0055ff;
font-size:16px;
}
}
</style>
2)函数调用形式
<button @click="handleParseExcel">excel</button>
mounted() {
this.doParseExcel = parseExcel({
// resultType?: string,
// readType?: string
}, this.parseExcelCallBack)
},
methods: {
// 回调
parseExcelCallBack(e) {
console.log(e)
},
// 导入
handleParseExcel() {
this.doParseExcel()
},
}
import * as XLSX from 'xlsx'
import { Message } from 'view-ui-plus'
export function parseExcel(props, fn) {
console.log('init parseExcel function')
const inputDom = document.createElement('input')
inputDom.type = 'file'
inputDom.accept = '.txt, .xlsx, .xls'
inputDom.addEventListener('change', fileChange)
// 本地文件选择
function fileChange(event) {
console.log('fileChange', event, event.target, event.target.value)
const file = event.target.files[0];
if(!file) {
return
}
let testMsg = file.name.substring(file.name.lastIndexOf('.')+1)
if(!['txt','xlsx', 'xls'].includes(testMsg)) {
Message.error('不是excel文件~')
// event.target.value = ''
return
}
const reader = new FileReader();
if(testMsg === 'txt') {
reader.readAsText(file);
} else {
if(props.readType === 'array'){
reader.readAsArrayBuffer(file);
} else {
reader.readAsBinaryString(file);
}
}
reader.onload = function(e) {
// console.log('reader', e)
if(testMsg === 'txt') {
// txt文件
// console.error(reader.result)
// reader.result.split('\n').forEach(function(v, i){
// console.log(v);
// });
fn(reader.result)
} else {
if(props.readType === 'array') {
// excel文件 —— array
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, {type: 'array'});
// 假设我们只读取第一个工作表
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
const jsonData = XLSX.utils.sheet_to_json(worksheet);
// console.log(jsonData, worksheet);
fn(jsonData)
} else {
// excel文件 —— binary
const workbook = XLSX.read(e.target.result, {type: 'binary'});
const sheetNames = workbook.SheetNames; // 工作表名称集合
const worksheet = workbook.Sheets[sheetNames[0]]; // 这里我们只读取第一张sheet
const csv = XLSX.utils.sheet_to_csv(worksheet);
if(props.resultType === 'array') {
// 数组形式
const rows = csv.split('\n'); // 转化为数组
rows.pop(); // 最后一行没用的
// console.log(rows); // 打印输出的数组
fn(rows)
} else {
// 字符串形式
// console.log(csv)
fn(csv)
}
}
}
inputDom.value = ''
}
reader.onerror = function(e) {
Message.error(e)
console.log(e)
inputDom.value = ''
}
}
return () => {
if(inputDom) {
inputDom.click()
}
}
}