<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實踐指南

          共 5686字,需瀏覽 12分鐘

           ·

          2021-07-16 01:23

          點擊上方關(guān)注 前端技術(shù)江湖,一起學(xué)習(xí),天天進步

          寫在前面

          雙手奉上代碼鏈接 

          https://github.com/ajun568/export-excel

          雙腳奉上最終效果圖

          觀前提醒

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

          準(zhǔn)備工作

          ?? 安裝 xlsx.js npm install xlsx

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

          workbook ??

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

          writeOpts ??

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

          下載文件

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

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

          通過模擬 click 事件觸發(fā) a 標(biāo)簽, 以實現(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ù): 詳細數(shù)據(jù)請?zhí)D(zhuǎn) Github, 在 mock.ts 中查看

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

          [
            ...
            {
              key'animal',
              value'動物',
              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)換對象的 key 應(yīng)為最小葉子結(jié)點的 key
          • 轉(zhuǎn)換對象的 value 應(yīng)為當(dāng)前層級的 value ( 即導(dǎo)出后當(dāng)前行所顯示的 value )
          • 既然是樹, 果斷遞歸, 準(zhǔn)沒錯

          ???♂? Code

          excel2.png

          ???♂? Image

          Merged 數(shù)據(jù)

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

          ?? 分析

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

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

          ???♂? Code

          excel4.png

          ???♂? Image

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

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

          ???♂? Code

          excel13.png

          ???♂? Image

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

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

          因為 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è)置樣式, 若有需求, 可采用 付費版本 或使用 xlsx-style, 使用方法與本文一致. 大家可參照文檔自行添加樣式部分.

          參考??鏈接

          https://github.com/SheetJS/sheetjs#writing-options

          https://juejin.cn/post/6872375842358919175

          http://www.seefly.top/archives/%E5%89%8D%E7%AB%AF%E4%BD%BF%E7%94%A8xlsxjs%E5%AF%BC%E5%87%BA%E6%9C%89%E5%A4%8D%E6%9D%82%E8%A1%A8%E5%A4%B4%E7%9A%84excelmd#6%E5%8D%95%E5%85%83%E6%A0%BC%E5%88%97%E5%AE%BD

          關(guān)于本文
          來源:黃刀小五
          https://segmentfault.com/a/1190000040067999

          The End

          歡迎自薦投稿到《前端技術(shù)江湖》,如果你覺得這篇內(nèi)容對你挺有啟發(fā),記得點個 「在看」


          點個『在看』支持下 

          瀏覽 63
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  午夜操一操一级 | 在线观看网址你懂的 | 精品无码人妻一区二区免费蜜桃 | 我要看免费 A片 | 亚洲啪啪啪网站 |