<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          前端導(dǎo)出Excel實(shí)踐指北

          共 6170字,需瀏覽 13分鐘

           ·

          2021-07-09 14:36


          點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)

          回復(fù)1,加入高級(jí)Node交流群

          Hello, 各位勇敢的小伙伴, 大家好, 我是你們的嘴強(qiáng)王者小五, 身體健康, 腦子沒病.

          本人有豐富的脫發(fā)技巧, 能讓你一躍成為資深大咖.

          一看就會(huì)一寫就廢是本人的主旨, 菜到摳腳是本人的特點(diǎn), 卑微中透著一絲絲剛強(qiáng), 傻人有傻福是對(duì)我最大的安慰.

          歡迎來到小五隨筆系列前端導(dǎo)出Excel在線指北.

          寫在前面

          雙手奉上代碼鏈接 傳送門 - ajun568

          雙腳奉上最終效果圖

          觀前提醒

          ?? 本文最終實(shí)現(xiàn)效果如上圖, 具體功能為: 導(dǎo)出Excel + 多個(gè)Sheet + 可合并的多行表頭. 代碼部分采用 React+TS 作為工具進(jìn)行編寫.

          準(zhǔn)備工作

          ?? 安裝 xlsx.js npm install xlsx

          ?? 寫入Excel文件: XLSX.write(workbook, writeOpts)

          workbook ??

          • SheetNames @types string[]: 當(dāng)前 Sheet 的名稱
          • Sheets: 當(dāng)前sheet的對(duì)象, 格式如下
          [SheetNames]: {
            "!refs""A1:G7"// 表示從 第1行第A列 到 第7行第G列
            "!cols": [{wpx80} ... ], // 表示 列寬 80px
            "!rows": [{hpx20} ... ], // 表示 行高 20px
            "!merges": [{s: {r0c2}, e: {r0c3}} ... ], // 表示 將 第0行第2列 和 第0行第3列 進(jìn)行合并 (s: start, e: end, c: column, r: row)
            "A1": {v"姓名"}, // 表示第1行第A列 顯示數(shù)據(jù)為 "姓名", 以此類推 ...
            ...
          }

          writeOpts ??

          {
            type, // 數(shù)據(jù)編碼, 本文采用 binary 二進(jìn)制格式
            bookType, // 導(dǎo)出類型, 本文采用 xlsx 類型
            compression, // 是否使用 Gzip 壓縮
          }

          下載文件

          想要下載文件, 我小A第一個(gè)表示不服, 申請(qǐng)出戰(zhàn) <a 標(biāo)簽的 download 屬性>

          通過 URL.createObjectURL(Object) 來創(chuàng)建下載所需的 URL. 由于每次調(diào)用都會(huì)產(chǎn)生新的 URL 對(duì)象, 故使用后記得釋放, 釋放方法 URL.revokeObjectURL(FileUrl)

          通過模擬 click 事件觸發(fā) a 標(biāo)簽, 以實(shí)現(xiàn)下載

          const saveAs = (obj: Blob, fileName?: string): void => {
            const temp = document.createElement('a')
            temp.download = fileName || 'download'
            temp.href = URL.createObjectURL(obj)
            temp.click()
            setTimeout(() =>  { URL.revokeObjectURL(temp.href) }, 100)
          }

          頭部處理

          Mock數(shù)據(jù): 詳細(xì)數(shù)據(jù)請(qǐng)?zhí)D(zhuǎn) Github, 在 mock.ts 中查看

          Header 部分?jǐn)?shù)據(jù)格式

          [
            ...
            {
              key'animal',
              value'動(dòng)物',
              child: [
                {
                  key'dog',
                  value'狗',
                  child: [
                    {
                      key'corgi',
                      value'柯基',
                    },
                    {
                      key'husky',
                      value'哈士奇',
                    },
                  ],
                },
                {
                  key'tiger',
                  value'老虎',
                },
              ],
            },
            ...
          ]

          Data 部分?jǐn)?shù)據(jù)格式

          [
            {
              name'黃刀小五',
              desc'基于搜索引擎的復(fù)制粘貼攻城獅',
              watermelon'喜歡',
              banana'不喜歡',
              corgi'喜歡',
              husky'喜歡',
              tiger'不喜歡',
            },
            ...
          ]

          頭部數(shù)據(jù)處理

          ?? 分析

          • Header 數(shù)據(jù)為樹形結(jié)構(gòu), 其深度為頭部所占行數(shù)
          • Header 數(shù)據(jù)要轉(zhuǎn)換成 Data 數(shù)據(jù)的格式, 并與 Data 數(shù)組合并, 共同處理成導(dǎo)出所需格式
          • 轉(zhuǎn)換對(duì)象的 key 應(yīng)為最小葉子結(jié)點(diǎn)的 key
          • 轉(zhuǎn)換對(duì)象的 value 應(yīng)為當(dāng)前層級(jí)的 value ( 即導(dǎo)出后當(dāng)前行所顯示的 value )
          • 既然是樹, 果斷遞歸, 準(zhǔn)沒錯(cuò)

          ???♂? Code

          excel2.png

          ???♂? Image

          Merged 數(shù)據(jù)

          {
            s: { // start
              r: x, // row
              c: y, // column
            },
            e: { ... } // end
          }

          ?? 分析

          • 將處理后的頭部數(shù)據(jù)看成一個(gè)矩陣
          • 行或列中, 相鄰元素若相同, 則進(jìn)行合并

          tips: 本文采用的是判斷相鄰 value 值是否相等進(jìn)行合并, 若有需求, 建議改寫為對(duì)象形式加以完善.

          ???♂? Code

          excel4.png

          ???♂? Image

          生成sheet數(shù)據(jù)

          • 利用Object.assign進(jìn)行對(duì)象合并
          • 利用String.fromCharCode(65 + i)對(duì)列進(jìn)行大寫字母的轉(zhuǎn)換

          ???♂? Code

          excel13.png

          ???♂? Image

          轉(zhuǎn)換字節(jié)流

          利用 new ArrayBuffer(str) 創(chuàng)建一個(gè)緩沖區(qū), 使用 new Uint8Array(buf) 引用

          因?yàn)?nbsp;unicode 編碼是 0~65535, 而 Uint8Array 范圍為 0~255, 故需要按位與 0xFF, 以保持位數(shù)一致

          const s2ab = (str: string): ArrayBuffer => {
            let buf = new ArrayBuffer(str.length)
            let view = new Uint8Array(buf)

            for (let i = 0; i !== str.length; ++i) {
              view[i] = str.charCodeAt(i) & 0xFF
            }

            return buf
          }

          導(dǎo)出文件

          結(jié)合前文 準(zhǔn)備工作 部分所講, 導(dǎo)出的代碼邏輯就出來了, 直接上代碼

          excel14.png

          結(jié)束語

          開源版本不支持設(shè)置樣式, 若有需求, 可采用 付費(fèi)版本 或使用 xlsx-style, 使用方法與本文一致. 大家可參照文檔自行添加樣式部分.

          參考??鏈接

          【Github】 SheetJS ~ js-xlsx

          【mySoul】 優(yōu)雅 | 前后端優(yōu)雅的導(dǎo)入導(dǎo)出Excel

          【Seefly】 前端使用xlsx.js導(dǎo)出有復(fù)雜表頭的excel

          關(guān)于本文
          來源:黃刀小五
          https://segmentfault.com/a/1190000040067999
          如果覺得這篇文章還不錯(cuò)
          點(diǎn)擊下面卡片關(guān)注我
          來個(gè)【分享、點(diǎn)贊、在看】三連支持一下吧

             “分享、點(diǎn)贊在看” 支持一波 

          瀏覽 38
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日逼黄色视频 | 日韩蜜桃久久久 | 亚洲精品国产AV婷婷在 | 97资源人妻 | 三级久久久 |