electron

Electron+Vue+ElementUI excel文件合并

一、需求

在这里插入图片描述

excel表格式如上,前面14行的数据不要,最后一行不要,只要中间标题以及内容,多个表合并成一个excel:如下
在这里插入图片描述

二、效果

上部分:上次ecxel文件,上传完之后,点击合并按钮开始合并

下部分:打印日志,包括:错误日志,成功日志

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

桌面就会出现一个以当前日期命名的excel合并文件。

当然,如果你传入的格式不对,则会提示你格式错误,如下:

在这里插入图片描述

三、代码

目录结构:

在这里插入图片描述

该项目的主要难点就是一个,如何前后端通信,

1)在background.js 使用ipcMain监听通信

  1. 在mupload.vue组件中使用electron的ipcRenderer,发送通信

如下:

<template>
    <div
        class="mupload"
        v-loading="loading.staus"
        element-loading-text="拼命加载中"
        element-loading-spinner="el-icon-loading"
        element-loading-background="rgba(0, 0, 0, 0.8)"
    >
        <el-upload
            action="#"
            class="upload-component"
            drag
            multiple
            :file-list="fileList"
            :auto-upload="false"
            :on-remove="handleRemove"
            :on-change="handleChange"
        >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">
                将文件拖到此处,或<em>点击此处</em>
            </div>
        </el-upload>
        <el-button
            class="mupload-button"
            style="margin-left: 10px"
            size="small"
            type="success"
            @click="submitUpload"
            >点击合并</el-button
        >
    </div>
</template>

<script>
// import { Upload } from "element-ui";
const { ipcRenderer } = require("electron");
import log from "electron-log";
// import { mapState } from "vuex";
export default {
    components: {
        // Upload,
    },
    data() {
        return {
            fileList: [],
            // loading: false
        };
    },
    methods: {
        handleChange(file, fileList) {
            this.fileList = fileList;
        },
        handleRemove(file, fileList) {
            this.fileList = fileList;
        },
        submitUpload(e) {
            let fileList = this.fileList;
            if (fileList.length == 0) {
                this.$message.error("请上传文件");
                return;
            }
            fileList = fileList.map((v) => v.raw.path);
            this.$store.dispatch("changeLoading", {
                staus: true,
                clean: false,
            });
            log.info(`文件导入中... <br />`);
            ipcRenderer.send("uploadChooseExcel", fileList);
        },
        downloadFile() {
            // 下载合并文件
        }
    },
    computed: {
        ...Vuex.mapState(["loading",'loading']),
    },
    watch: {
        'loading.clean'(newVal,oldVal) {
            if(newVal) {
                this.fileList = []
            }
        }
    }
};
</script>

<style>
.mupload {
    display: flex;
    justify-content: center;
}
.el-upload-list {
    height: 200px;
    overflow-y: auto;
}
.mupload-button {
    height: 30px;
    margin-top: 70px !important;
}
</style>

上面的文件中使用:ipcRenderer.send(“uploadChooseExcel”, fileList); 发送文件列表。

import { ipcMain } from "electron";
const fs = require('fs');
// node path模块
const path = require('path');
const xlsx = require('node-xlsx');
import log from 'electron-log';
import { formatDate } from '@/utils';

// 收集所有的文件路径
var lists = []; // 储存所有数据
var oPath = __dirname.slice(0, __dirname.indexOf('dist_electron'))
log.transports.file.resolvePath = () => path.resolve(`${oPath}/log/${formatDate(new Date(), 'yyyy-MM-dd')}.log`);
log.transports.console.level = 'silly';
export const getExcel = (webContents) => {
    ipcMain.on("uploadChooseExcel", function (event, arg) {
        fileDisplay(arg)
    });
};

const fileDisplay = files => {
    //根据文件路径读取文件,返回文件列表
    log.info(`读取配置中...<br />`)
    files.forEach((filename, index) => {
        //获取当前文件的绝对路径
        // fs.stat(path)执行后,会将stats类的实例返回给其回调函数。
        log.info(`读取文件${filename}<br />`)
        fs.stat(filename, (eror, stats) => {
            if (eror) return log.error(`Error:(spec)${eror} <br />`);
            // 是否是文件
            const isFile = stats.isFile();
            // 是否是文件夹
            const isDir = stats.isDirectory();
            if (isFile) {
                if (filename.includes('.xls') || filename.includes('xlsx')) { // excel文件
                    //读取Excel文件
                    var data = xlsx.parse(filename);
                    var list1 = data[0].data
                    let excelHeader = [
                        '保单号',
                        '批单号',
                        '类别',
                        '期次',
                        '险种',
                        '客户',
                        '业务员',
                        '个团',
                        '新旧车',
                        '合作网点',
                        '含税保费',
                        '净保费',
                        '出单时间',
                        '保费收入',
                        '原比例%',
                        '本次比例%',
                        '本次手续费/经纪费(人民币)',
                        '手续费增值税',
                        '合计支付含增值税金额'
                    ]
                    let configPath = path.join(oPath, `/config.txt`)
                    fs.exists(configPath, (exists) => {
                        if (!exists) {
                            var filePath = path.join(oPath, `/config.txt`); // 创建txt
                            fs.writeFileSync(filePath, excelHeader);//
                            createMerge(list1, excelHeader, index, files, filename)
                            return
                        }
                        fs.readFile(configPath, (err, data) => {
                            var string = data.toString()
                            var arr = [];
                            if (string) {
                                arr = string.split(',').map(v => v.trim());
                            }
                            createMerge(list1, arr.length == 0 ? excelHeader : arr, index, files, filename)
                        })
                    })
                } else {
                    log.error(`${filename}:不是excel文件 <br />`)
                }
            }
            // 如果是文件夹
            if (isDir) fileDisplay(filename);
        })
    });
}

function getNowMonths() {
    let timeOne = new Date();
    let year = timeOne.getFullYear();
    let month = timeOne.getMonth() + 1;
    let day = timeOne.getDate();
    month = month < 10 ? "0" + month : month;
    day = day < 10 ? "0" + day : day;
    const NOW_MONTHS_AGO = `${year}-${month}-${day}`;
    return NOW_MONTHS_AGO;
}

function createMerge(list, excelHeader, index, files, filename) {
    let sum = 0, isTrue = false, lineNum = 0;
    for (let i = 0; i < list.length; i++) {
        if (isTrue) break
        if (excelHeader.length != list[i].length) {
            continue;
        }
        for (let j = 0; j < list[i].length; j++) {
            if (excelHeader[j] == list[i][j]) {
                lineNum = i
                isTrue = true
                sum++;
            }
        }
    }
    if (sum != excelHeader.length) {
        return log.error(`${filename}:表头与规定的格式不匹配 <br />`);
    }
    var tempList = list.slice(lineNum + 1, list.length - 1);
    lists = lists.concat(tempList)
    if (index == files.length - 1) { // 全部读取完
        try {
            lists.unshift(excelHeader)
            const options = {}
            var desktop = `${require('os').homedir()}\\Desktop`
            var buffer = xlsx.build([{ name: 'sheet1', data: lists }], options);
            var date = getNowMonths()
            var filePath = path.join(desktop, `/${date}.xlsx`); // 存储路劲和文件名
            fs.writeFileSync(filePath, buffer, { 'flag': 'w' });//
            log.info(`合并文件成功,文件储存在桌面,路径为:${require('os').homedir()}\\Desktop\\${date}.xlsx <br />`)
        } catch (err) {
            if (err.errno == -4082) {
                log.error(`上传失败,上一个合并的文件正在打开,请关闭之后再重新上传待合并文件 <br />`)
            }
        }
        lists = [];
        isTrue = false
    }
}

大概主要的就是这些,其实还是有很多优化的,后续会优化一下。

四、后续

噢,对了,还有一个设置表头的功能

在这里插入图片描述

在这里插入图片描述

log.error(上传失败,上一个合并的文件正在打开,请关闭之后再重新上传待合并文件 <br />)
}
}
lists = [];
isTrue = false
}
}


大概主要的就是这些,其实还是有很多优化的,后续会优化一下。

#### 四、后续

噢,对了,还有一个设置表头的功能

[外链图片转存中...(img-dRD6tXcl-1662538336371)]

[外链图片转存中...(img-yOUqn6PP-1662538336371)]

该功能就是excel默认表头,可以手动设置,一次设置,后面就按照设置的来,其实就是设置了一个txt文件,从该文件进行读取而已。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值