1. 程式人生 > >electron-vue 實踐 2 —— 表格合併桌面工具

electron-vue 實踐 2 —— 表格合併桌面工具

前言

之前使用 vue-clielectron-vue 建立了工程,接下來就開始實現具體的邏輯,我們的目標很簡單,就是將一張或多張表中的所有 sheet 頁內容都垂直或水平合併在一個 sheet 中,並生成一張新的表。

UI 佈局檔案

新加一個 .vue 字尾的檔案,vue 的 UI 檔案格式大致如下,不瞭解的可以檢視

<template>
<!--html佈局內容-->
</template>
<script src="xxx.js"></script>
<style>
  /* 佈局元件的個性化樣式設定 */
</style
>

我們最終應用的 UI 佈局檔案內容如下:

<template>
    <div class="excel-merge">
        <div class="upload">
        <div class="upload_warp">
            <div class="upload_warp_left" @click="fileClick">
            <img src="static/imgs/ms-excel.png">

            </div>
            <
div class="upload_warp_right" @drop="drop($event)" @dragenter="dragenter($event)" @dragover="dragover($event)">
           <p>或將資料夾拖到此處</p>            </div>        </div>        <div class="upload_warp_text">            <p>選中 【{{xlsList.length}}】 張表</p>
<!-- ,共 {{bytesToSize(this.size)}} -->
       </div>        <input @change="fileChange($event)" type="file" accept=".xls, .xlsx" id="upload_file" multiple style="display: none"/>        <div class="upload_warp_img" v-show="xlsList.length!=0">            <div class="upload_warp_img_div" v-for="(item,index) of xlsList">                <div class="upload_warp_img_div_top">                    <div class="upload_warp_img_div_text">                    {{item.file.name}}                    </div>                    <img src="static/imgs/close.png" class="upload_warp_img_div_del" @click="fileDel(index)">                </div>                <img :src="item.file.src">            </div>        </div>        </div>        <transition>          <button id="VMBtn" @click="verticalMergeClick()">垂直合併</button>        </transition>        <button id="HMBtn" @click="horizontalMergeClick()">水平合併</button>        <button id="CABtn" @click="cleanAllClick()">清空重來</button>        <!--結果輸出欄-->        <div class="result" v-show="resLogs.length!=0">            <p>結果:</p>              <div class="" v-for="(item,index) of resLogs">                <div class="">                    <div>                        <!-- <img src="../assets/arrow.png"> -->                       => {{item.content}}                    </div>                </div>            </div>            <button id="OpenResult" @click="openExportDir()" v-show=OpenResVisible >開啟輸出目錄</button>        </div>    </div> </template> <!-- 業務指令碼 --> <script src="../logic/excel_merge.js"></script> <style scoped> ... </style>

引入表格之前的初始介面:

引入表格之後的表格列表展示介面:

合併成功介面如下:

獲取檔案

可以通過點選按鈕從檔案管理器中選擇檔案列表,也可以通過選中多個檔案然後拖動到應用的指定區域來獲取檔案列表。

  • 通過文字編輯器輸入的方式,限制檔案字尾名為 .xls.xlsx

    <input @change="fileChange($event)" type="file" accept=".xls, .xlsx" id="upload_file" multiple style="display: none"/>

    型別 multiple 表示可以輸入多個檔案。在指令碼中重寫 fileChange(el) 方法,在輸入檔案時會自動呼叫此介面:

    // 新增
    fileChange(el) {
        let filePath = el.target.files[0].path;
        let xlsxData = XLSX.readFile(filePath);
      // 空表過濾
        if (xlsxData.Sheets.length == 0){
            gLog("------------------ 引入一個空表");
            return;
        } 
      // 傳入檔案列表處理
        this.fileList(el.target);
      // 釋放記憶體
        el.target.value = ''
    },

  • 通過拖拽方式輸入檔案列表:

    <div class="upload_warp_right" @drop="drop($event)" @dragenter="dragenter($event)" @dragover="dragover($event)">
      <p>或將資料夾拖到此處</p>
    </div>

    然後在指令碼中實現 dropdragenterdragover 三個方法:

    需要引入檔案處理模組 fs

    const fs = require("fs");
    // 拖拽相關
    dragenter(el) {
      el.stopPropagation();
      el.preventDefault();
    },
    dragover(el) {
        el.stopPropagation();
        el.preventDefault();
    },
    drop(el) {
        el.stopPropagation();
        el.preventDefault();
        this.fileList(el.dataTransfer);
    }
    // 拖拽輸入的檔案列表處理
    fileList(fileList) {
        let files = fileList.files;
        for (let i = 0; i < files.length; i++) {
            console.log("--------------------- files[" + i + "].name = "+ files[i].name);
            //判斷是否為資料夾
            if (!fs.lstatSync(files[i].path).isDirectory()) {
              this.fileAdd(files[i]);
            } else {
              //資料夾處理
              this.folders(fileList.items[i]);
            }
        }
    },
    //資料夾處理
    folders(files) {
        let _this = this;
        //判斷是否為原生file
        if (files.kind) {
          files = files.webkitGetAsEntry();
        }
        files.createReader().readEntries(function (file) {
            for (let i = 0; i < file.length; i++) {
                if (file[i].isFile) {
                  _this.foldersAdd(file[i]);
                } else {
                  _this.folders(file[i]);
                }
            }
        })
    },
    foldersAdd(entry) {
        let _this = this;
        entry.file(function (file) {
          _this.fileAdd(file)
        })
    },

獲取到的檔案資訊存放在兩個陣列中:

data() {
    return {
        xlsList: [],    // 表格名稱表
        size: 0,// 表格檔案總大小
        xlsPathList: [],// 表格路徑表
    }
},
  • xlsList 表格名稱列表,僅用於 UI 上展示使用;

  • xlsPathList 表格完整路徑列表,用於後續獲取表格資料使用。

// 檔案新增到管理列表
fileAdd(file) {
    //總大小
    this.size = this.size + file.size;
    //判斷是否為表格
    if (file.name.indexOf('.xlsx') == -1 && file.name.indexOf('.xls') == -1) {
      console.log("--------------- 新增的不是表格檔案");
    } else {
        let xlsxPath = file.path;
        console.log("--------------- 新增表格檔案:" + xlsxPath);
        let _this=this;
        file.width=50;
        file.height=50;
        // 表格圖示
        file.src = "./src/renderer/assets/xls.png";
        _this.xlsList.push({
          file
        });
        _this.xlsPathList.push({
          xlsxPath
        });
    }
},

也可以在列表中移除某個表格檔案,呼叫 fileDel 方法:

// 刪除表格
fileDel(index) {
    this.size = this.size - this.xlsList[index].file.size;//總大小
    this.xlsList.splice(index, 1);
    this.xlsPathList.splice(index, 1);
    if(this.size == 0){
      this.cleanAllClick();
    }
},

一鍵清空重來功能其實就是清除資料結構中的資料而已:

// 清空重來
cleanAllClick(){
    if(lockBtn){
      return;
    }
    this.OpenResVisible = false;
    this.addResultLog(null, true);
    if(this.xlsPathList.length > 0){
        for(var i=0; i< this.xlsList.length; i ++){
          this.xlsList.splice(i, 1);
        }
        this.xlsList.length = 0;
        this.xlsPathList.length = 0;
    }
},

Excel 讀寫庫

目前支援 Excel 讀寫的 Node.js 模組大致有:

  • : 目前 Github 上 star 數量最多的處理 Excel 的庫,支援解析多種格式表格 XLSX / XLSM / XLSB / XLS /