整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          excel技巧:從網頁導入我們想要的數據

          excel技巧:從網頁導入我們想要的數據

          時候我們在網頁上找到資料,需要把數據存入表格。利用Excel,很輕松的就可以將網頁上的數據導入表格中,不但節約了工作時間,而且提高了數據的準確性。

          比如我們需要最新行政區劃代碼。從國家統計局我們找到這些數據。

          1.復制網頁的URL地址(即:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201703/t20170310_1471429.html)。

          2.我們在Excel的數據選項卡,點擊 【自網站】

          3.在彈出的對話框中,粘貼上網址,點擊【轉到】按鈕,就打開了網頁。

          在這窗口中,我們可以看到黃色的小箭頭。點擊表格旁邊的黃色小箭頭,然后點擊【導入】。

          有時候,我們需要的數據旁邊沒有小箭頭,則直接可以點擊導入。

          4.彈出確認對話框,我們點擊確認。這里也可以進行屬性設置。

          5.點擊確定后,會顯示正在獲取數據。

          6.稍等片刻,我們的數據就導入成功了。

          網頁中的數據已成功導入Excel表格中,然后我們可以根據自己的需要對數據進行處理。

          需求場景

          最近在開發項目時需要批量導入和導出Excel數據,在實現這個需求時,我們既可以在前端完成數據解析和文件生成工作,也可以通過前端發起導入以及導出請求后,后端實現解析文件流解析文件內容以及生成文件并提供下載鏈接的功能。

          相較于后端處理Excel數據而言,使用前端導入導出可以提供更高的實時性,用戶可以直接在瀏覽器中觸發導出操作,無需等待后端處理。且可以在前端完成數據生成以及數據校驗處理工作,大大減輕后端服務器的壓力,大幅增強用戶體驗。

          具體的技術方案選型主要看業務場景,如果對于小型數據集、實時性需求較高的導入導出操作,優先考慮前端實現。而對于大型數據集、需要業務邏輯處理、以及安全性要求高的場景,則后端處理更為合適。

          技術方案

          xlsx與xlsx-style組合方案:xlsx 是目前前端最常用的Excel解決方案,又叫做SheetJS,但社區版不支持修改Excel的樣式,需要購買Pro版才可以,如果需要修改導出的Excel文件樣式,需要結合xlsx-style庫一起使用。但遺憾的是xlsx庫已經兩年多不更新,而xlsx-style上一個版本更是8年前發布,目前已經不再推薦使用該方案。

          exceljs與file-saver方案:exceljs是一款免費開源支持導入導出Excel 操作工具,并且可以實現樣式的修改以及 Excel 的高級功能,是非常值得推薦的一個處理 Excel 的庫,file-saver可以實現保存文件到本地。本文以exceljs與file-saver操作xlsx格式文件為例介紹如何具體上手使用。

          exceljs介紹

          ExcelJS是一個用于在Node.js和瀏覽器中創建、讀取和修改Excel文件的強大JavaScript庫。它提供了豐富的功能和靈活的API,使你能夠在你的應用程序中處理和操作Excel文件。

          下面是一些ExcelJS庫的關鍵特性和功能:

          1. 創建和修改Excel文件:ExcelJS允許你創建新的Excel工作簿,并在其中添加工作表、行和單元格。你可以設置單元格的值、樣式、數據類型以及其他屬性。
          2. 讀取和解析Excel文件:ExcelJS支持讀取和解析現有的Excel文件。你可以將Excel文件加載到工作簿中,然后訪問工作表、行和單元格的數據。
          3. 導出和保存Excel文件:ExcelJS可以將工作簿保存為Excel文件,支持多種格式,如XLSX、XLS和CSV。你可以將工作簿保存到本地文件系統或將其發送到客戶端以供下載。
          4. 處理復雜的Excel功能:ExcelJS支持處理復雜的Excel功能,如公式、圖表、數據驗證、條件格式和保護工作表等。你可以根據需要設置和操作這些功能。
          5. 支持自定義樣式和格式:ExcelJS允許你自定義單元格、行、列和工作表的樣式和格式。你可以設置字體、顏色、填充、邊框、對齊方式以及數字和日期格式等。

          參考文檔

          npm倉庫地址:https://www.npmjs.com/package/exceljs

          官方中文文檔地址:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md

          快速上手

          安裝依賴

          exceljs用于Excel數據處理,file-sever用于保存到本地文件。

          npm i exceljs
          npm i file-saver

          導出Excel

          讓我們先從簡單的數據導出開始,快速體驗如何使用exceljs導出Excel文件,需要注意的是在瀏覽器環境中運行 JavaScript,瀏覽器的安全策略通常不允許直接訪問讀寫本地文件系統。在這種情況下,需要通過其他方式將文件轉換為buffer數據,在導出Excel時使用FileSaver.js庫將緩沖區數據保存到文件中。

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 導出數據列表
            const data=[
              {"姓名": "張三", "年齡": 18, "身高": 175, "體重": 74},
              {"姓名": "李四", "年齡": 22, "身高": 177, "體重": 84},
              {"姓名": "王五", "年齡": 53, "身高": 155, "體重": 64}
            ]
            // 獲取表頭所有鍵
            const headers=Object.keys(data[0])
            // 將標題寫入第一行
            sheet1.addRow(headers);
            // 將數據寫入工作表
            data.forEach((row)=> {
              const values=Object.values(row)
              sheet1.addRow(values);
            });
            // 導出表格文件
            workbook.xlsx.writeBuffer().then((buffer)=> {
              let file=new Blob([buffer], {type: "application/octet-stream"});
              FileSaver.saveAs(file, "ExcelJS.xlsx");
            }).catch(error=> console.log('Error writing excel export', error))
          }
          </script>
          
          <style scoped lang="scss">
          
          </style>

          當我們點擊導出excel按鈕時,調用exportFile函數,完成excel文件下載,下載后的文件內容如下:


          導入Excel

          導入excel文件時,同樣使用FileReader的readAsArrayBuffer方法,將文件轉換為二進制字符串,然后從buffer中加載數據并解析。

          <template>
            <input
                type="file"
                accept=".xls,.xlsx"
                class="upload-file"
                @change="importExcel($event)"/>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          // 導出excel文件
          const importExcel=(event)=> {
            //獲取選擇的文件
            const files=event.target.files
            //創建Workbook實例
            const workbook=new ExcelJS.Workbook();
            // 使用FileReader對象來讀取文件內容
            const fileReader=new FileReader()
            // 二進制字符串的形式加載文件
            fileReader.readAsArrayBuffer(files[0])
            fileReader.onload=ev=> {
              console.log(ev)
              // 從 buffer中加載數據解析
              workbook.xlsx.load(ev.target.result).then(workbook=> {
                // 獲取第一個worksheet內容
                const worksheet=workbook.getWorksheet(1);
                // 獲取第一行的標題
                const headers=[];
                worksheet.getRow(1).eachCell((cell)=> {
                  headers.push(cell.value);
                });
                console.log("headers", headers)
                // 創建一個空的JavaScript對象數組,用于存儲解析后的數據
                const data=[];
                // 遍歷工作表的每一行(從第二行開始,因為第一行通常是標題行)
                for (let rowNumber=2; rowNumber <=worksheet.rowCount; rowNumber++) {
                  const rowData={};
                  const row=worksheet.getRow(rowNumber);
                  // 遍歷當前行的每個單元格
                  row.eachCell((cell, colNumber)=> {
                    // 獲取標題對應的鍵,并將當前單元格的值存儲到相應的屬性名中
                    rowData[headers[colNumber - 1]]=cell.value;
                  });
                  // 將當前行的數據對象添加到數組中
                  data.push(rowData);
                }
                console.log("data", data)
              })
            }
          }
          </script>
          
          <style scoped lang="scss">
          
          </style>

          上傳文件后,解析內容如下所示:

          進階操作

          添加數據

          我們可以通過columns方法添加列標題并定義列鍵和寬度,設置好表頭后,我們可以直接通過addRow方法,根據key值去添加每一行的數據。

          參考文檔:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E5%88%97

          完整代碼如下:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 添加表頭列數據
            sheet1.columns=[
              {header: "姓名", key: "name", width: 20},
              {header: "年齡", key: "age", width: 10},
              {header: "身高", key: "height", width: 10},
              {header: "體重", key: "weight", width: 10},
            ];
            // 添加內容列數據
            sheet1.addRow({sort: 1, name: "張三", age: 18, height: 175, weight: 74});
            sheet1.addRow({sort: 2, name: "李四", age: 22, height: 177, weight: 88});
            sheet1.addRow({sort: 3, name: "王五", age: 53, height: 155, weight: 62});
            // 導出表格文件
            workbook.xlsx.writeBuffer().then((buffer)=> {
              let file=new Blob([buffer], {type: "application/octet-stream"});
              FileSaver.saveAs(file, "ExcelJS.xlsx");
            }).catch(error=> console.log('Error writing excel export', error))
          }
          
          </script>
          
          <style scoped lang="scss">
          
          </style>

          添加數據后導出文件效果如下:

          讀取數據

          我們可以使用getRow方法,傳入指定行參數讀取行數據。

          使用getColumn方法,傳入鍵、字母、id參數讀取列數據。

          使用eachCell方法可以遍歷每個單元格內容。

          參考文檔:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E8%A1%8C

          代碼如下:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 添加表頭列數據
            sheet1.columns=[
              {header: "姓名", key: "name", width: 20},
              {header: "年齡", key: "age", width: 10},
              {header: "身高", key: "height", width: 10},
              {header: "體重", key: "weight", width: 10},
            ];
            // 添加內容列數據
            sheet1.addRow({sort: 1, name: "張三", age: 18, height: 175, weight: 74});
            sheet1.addRow({sort: 2, name: "李四", age: 22, height: 177, weight: 88});
            sheet1.addRow({sort: 3, name: "王五", age: 53, height: 155, weight: 62});
            // 讀取行數據
            sheet1.getRow(1).eachCell((cell, rowIdx)=> {
              console.log("行數據", cell.value, rowIdx);
            });
            // 讀取列數據,可以通過鍵(name),字母(B)和基于id(1)的列號訪問單個列
            sheet1.getColumn("name").eachCell((cell, rowIdx)=> {
              console.log("列數據", cell.value, rowIdx);
            });
          }
          
          </script>
          
          <style scoped lang="scss">
          
          </style>

          效果

          樣式

          在導出excel文件時,默認沒有任何樣式的,為了美觀我們需要添加樣式,而exceljs支持修改表格樣式,具體內容可參考文檔https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E6%A0%B7%E5%BC%8F

          例如,我們需要設置所有單元格居中對齊,并添加邊框。并分別指定標題行和內容行字體大小、背景顏色、行高屬性,代碼如下:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 導出數據列表
            const data=[
              {"姓名": "張三", "年齡": 18, "身高": 175, "體重": 74},
              {"姓名": "李四", "年齡": 22, "身高": 177, "體重": 84},
              {"姓名": "王五", "年齡": 53, "身高": 155, "體重": 64}
            ]
            // 獲取表頭所有鍵
            const headers=Object.keys(data[0])
            // 將標題寫入第一行
            sheet1.addRow(headers);
            // 將數據寫入工作表
            data.forEach((row)=> {
              const values=Object.values(row)
              sheet1.addRow(values);
            });
            // 修改所有單元格樣式
            // 遍歷每一行
            sheet1.eachRow((row, rowNumber)=> {
              // 遍歷每個單元格
              row.eachCell((cell)=> {
                // 設置邊框樣式
                cell.border={
                  top: {style: 'thin'},
                  left: {style: 'thin'},
                  bottom: {style: 'thin'},
                  right: {style: 'thin'}
                };
                // 設置居中對齊
                cell.alignment={
                  vertical: 'middle',
                  horizontal: 'center'
                };
              });
            });
            // 獲取標題行數據
            const titleCell=sheet1.getRow(1);
            // 設置行高為30
            titleCell.height=30
            // 設置標題行單元格樣式
            titleCell.eachCell((cell)=> {
              // 設置標題行背景顏色為黃色
              cell.fill={
                type: 'pattern',
                pattern: 'solid',
                fgColor: {argb: 'FFFF00'}
              };
              // 設置標題行字體
              cell.font={
                color: {argb: 'FF0000'}, //顏色為紅色
                bold: true,// 字體粗體
                size: 18 // 設置字體大小為18
              };
            })
            // 獲取第二行到最后一行的內容數據
            const bodyRows=sheet1.getRows(2, sheet1.rowCount);
            // 處理內容行的數據
            bodyRows.forEach((bodyRow)=> {
              // 設置行高為20
              bodyRow.height=20
              bodyRow.eachCell((cell)=> {
                cell.font={
                  size: 16 // 設置內容行字體大小為16
                };
              });
            });
            // 導出表格文件
            workbook.xlsx.writeBuffer().then((buffer)=> {
              let file=new Blob([buffer], {type: "application/octet-stream"});
              FileSaver.saveAs(file, "ExcelJS.xlsx");
            }).catch(error=> console.log('Error writing excel export', error))
          }
          
          </script>
          
          <style scoped lang="scss">
          
          </style>

          導出Excel樣式效果如下所示,已經成功按我們指定的樣式導出了文件:

          篩選

          在很多的時候我們需要對表格中每一列的數據進行篩選,比如直接篩選姓名等列信息,我們可以通過 autoFilter 來添加篩選。參考文檔:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E8%87%AA%E5%8A%A8%E7%AD%9B%E9%80%89%E5%99%A8

          代碼如下:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 導出數據列表
            const data=[
              {"姓名": "張三", "年齡": 18, "身高": 175, "體重": 74},
              {"姓名": "李四", "年齡": 22, "身高": 177, "體重": 84},
              {"姓名": "王五", "年齡": 53, "身高": 155, "體重": 64}
            ]
            // 獲取表頭所有鍵
            const headers=Object.keys(data[0])
            // 將標題寫入第一行
            sheet1.addRow(headers);
            // 將數據寫入工作表
            data.forEach((row)=> {
              const values=Object.values(row)
              sheet1.addRow(values);
            });
            // 單列篩選
            // sheet1.autoFilter="A1";
            // 多個列篩選
            sheet1.autoFilter="A1:C1";
            // 導出表格文件
            workbook.xlsx.writeBuffer().then((buffer)=> {
              let file=new Blob([buffer], {type: "application/octet-stream"});
              FileSaver.saveAs(file, "ExcelJS.xlsx");
            }).catch(error=> console.log('Error writing excel export', error))
          }
          
          </script>
          
          <style scoped lang="scss">
          
          </style>

          導入后的效果如下,在姓名、年齡、身高列添加了篩選按鈕:

          公式值

          參考文檔:exceljs/README_zh.md at 5bed18b45e824f409b08456b59b87430ded023ab · exceljs/exceljs · GitHub

          我們可以直接對表格中的數據進行公式計算,比如 求和(SUM)平均數(AVERAGE) 等。

          例如我們需要計算平均值、最大值、指定公式時,代碼如下:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 導出數據列表
            const data=[
              {"姓名": "張三", "年齡": 18, "身高": 1.75, "體重": 74},
              {"姓名": "李四", "年齡": 22, "身高": 1.77, "體重": 84},
              {"姓名": "王五", "年齡": 53, "身高": 1.55, "體重": 64}
            ]
            // 獲取表頭所有鍵
            const headers=Object.keys(data[0])
            // 將標題寫入第一行
            sheet1.addRow(headers);
            // 將數據寫入工作表
            data.forEach((row)=> {
              const values=Object.values(row)
              sheet1.addRow(values);
            });
            // 添加單元格
            sheet1.getCell("E1").value="BMI指數";
            sheet1.getCell("F1").value="平均身高";
            sheet1.getCell("G1").value="最大體重";
            // 計算平均身高
            sheet1.getCell("F2").value={formula: "=AVERAGE(C2:C4)"};
            // 計算最大體重
            sheet1.getCell("G2").value={formula: "=MAX(D2:D4)"};
            // 計算BMI指數
            // 獲取第5列對象
            const BMIRange=sheet1.getColumn(5)
            BMIRange.eachCell((cell)=> {
              console.log("cell", cell)
              console.log(cell.row)
              // 從第二列開始添加計算公式
              if (cell.row >=2) {
                sheet1.getCell("E" + cell.row).value={formula: "D" + cell.row + "/" + "(C" + cell.row + "*" + "C" + cell.row + ")"};
              }
            })
            // 導出表格文件
            workbook.xlsx.writeBuffer().then((buffer)=> {
              let file=new Blob([buffer], {type: "application/octet-stream"});
              FileSaver.saveAs(file, "ExcelJS.xlsx");
            }).catch(error=> console.log('Error writing excel export', error))
          }
          
          </script>
          
          <style scoped lang="scss">
          
          </style>

          導出Excel文件效果如下,E列已經自動替換為公式計算。

          合并單元格

          表格的合并應該是業務需求中最頻繁的功能。當然這一功能使用 xlsx 也可以實現,我們只需要使用mergeCells方法,傳入合并單元格范圍參數即可。

          參考文檔:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E5%90%88%E5%B9%B6%E5%8D%95%E5%85%83%E6%A0%BC

          具體代碼實現如下所示:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 導出數據列表
            const data=[
              {"姓名": "張三", "年齡": 18, "身高": 175, "體重": 74},
              {"姓名": "李四", "年齡": 18, "身高": '未知', "體重": '未知'},
              {"姓名": "王五", "年齡": 53, "身高": '未知', "體重": '未知'},
              {"姓名": "趙六", "年齡": 12, "身高": '未知', "體重": '未知'}
            ]
            // 獲取表頭所有鍵
            const headers=Object.keys(data[0])
            // 將標題寫入第一行
            sheet1.addRow(headers);
            // 將數據寫入工作表
            data.forEach((row)=> {
              const values=Object.values(row)
              sheet1.addRow(values);
            });
            // 上下合并單元格
            sheet1.mergeCells("B2:B3");
            // 左右合并單元格
            sheet1.mergeCells("C3:D3");
            // 范圍合并單元格
            sheet1.mergeCells("C4:D5");
            // 導出表格文件
            workbook.xlsx.writeBuffer().then((buffer)=> {
              let file=new Blob([buffer], {type: "application/octet-stream"});
              FileSaver.saveAs(file, "ExcelJS.xlsx");
            }).catch(error=> console.log('Error writing excel export', error))
          }
          
          </script>
          
          <style scoped lang="scss">
          
          </style>
          

          單元格合并后導出文件效果如下:

          數據驗證

          有時候我們需要為某個單元格添加數據可以方便直接下拉選擇指定的值,此時就需要使用數據驗證功能,傳入可填寫的選項列表。

          參考文檔:https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#%E6%95%B0%E6%8D%AE%E9%AA%8C%E8%AF%81

          例如我們對是否注冊列添加數據驗證,可填值為"是、否、未知",具體代碼如下:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 導出數據列表
            const data=[
              {"姓名": "張三", "年齡": 18, "身高": 1.75, "體重": 74, "是否注冊": ''},
              {"姓名": "李四", "年齡": 22, "身高": 1.77, "體重": 84, "是否注冊": ''},
              {"姓名": "王五", "年齡": 53, "身高": 1.55, "體重": 64, "是否注冊": ''}
            ]
            // 獲取表頭所有鍵
            const headers=Object.keys(data[0])
            // 將標題寫入第一行
            sheet1.addRow(headers);
            // 將數據寫入工作表
            data.forEach((row)=> {
              const values=Object.values(row)
              sheet1.addRow(values);
            });
            // 獲取第5列對象
            const VerificationRange=sheet1.getColumn(5)
            VerificationRange.eachCell((cell)=> {
              // 從第二列開始添加數據驗證規則
              if (cell.row >=2) {
                sheet1.getCell("E" + cell.row).dataValidation={
                  type: "list",
                  allowBlank: true,
                  formulae: ['"是,否,未知"']
                };
              }
            })
            // 導出表格文件
            workbook.xlsx.writeBuffer().then((buffer)=> {
              let file=new Blob([buffer], {type: "application/octet-stream"});
              FileSaver.saveAs(file, "ExcelJS.xlsx");
            }).catch(error=> console.log('Error writing excel export', error))
          }
          
          </script>
          
          <style scoped lang="scss">
          
          </style>
          

          導出的excel文件效果如下:

          條件格式化

          我們可以為指定單元格添加條件格式,對滿足條件的單元格設置指定的樣式。

          參考文檔:exceljs/README_zh.md at 5bed18b45e824f409b08456b59b87430ded023ab · exceljs/exceljs · GitHub

          例如為年齡大于18歲單元格進行紅色標注,代碼如下:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
          </template>
          
          <script setup>
          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          // 導出excel文件
          const exportExcel=()=> {
            // 創建工作簿
            const workbook=new ExcelJS.Workbook();
            // 添加工作表,名為sheet1
            const sheet1=workbook.addWorksheet("sheet1");
            // 導出數據列表
            const data=[
              {"姓名": "張三", "年齡": 18, "身高": 1.75, "體重": 74},
              {"姓名": "李四", "年齡": 22, "身高": 1.77, "體重": 84},
              {"姓名": "王五", "年齡": 53, "身高": 1.55, "體重": 64}
            ]
            // 獲取表頭所有鍵
            const headers=Object.keys(data[0])
            // 將標題寫入第一行
            sheet1.addRow(headers);
            // 將數據寫入工作表
            data.forEach((row)=> {
              const values=Object.values(row)
              sheet1.addRow(values);
            });
            // 年齡大于18歲紅色標注
            sheet1.addConditionalFormatting({
              ref: "B2:B4",
              rules: [
                {
                  type: "cellIs",
                  operator: "greaterThan",
                  priority: 1,
                  formulae: [18],
                  style: {
                    fill: {
                      type: "pattern",
                      pattern: "solid",
                      bgColor: { argb: "FFFFC0CB" },
                    },
                  },
                },
              ],
            });
            // 導出表格文件
            workbook.xlsx.writeBuffer().then((buffer)=> {
              let file=new Blob([buffer], {type: "application/octet-stream"});
              FileSaver.saveAs(file, "ExcelJS.xlsx");
            }).catch(error=> console.log('Error writing excel export', error))
          }
          
          </script>
          
          <style scoped lang="scss">
          
          </style>

          導出后的文件效果如下:

          封裝exceljs

          封裝導入導出函數

          為了提高項目代碼的復用性,通常會將excel導入導出功能封裝到單獨的函數中方便調用,封裝后的函數如下:

          import ExcelJS from "exceljs";
          import FileSaver from "file-saver";
          import {timeFile} from "@/utils/timeFormat";
          // 導出excel文件
          export function exportFile(export_data, filename) {
              // 創建工作簿
              const workbook=new ExcelJS.Workbook();
              // 添加工作表,名為sheet1
              const sheet1=workbook.addWorksheet("sheet1");
              // 獲取表頭所有鍵
              const headers=Object.keys(export_data[0])
              // 將標題寫入第一行
              sheet1.addRow(headers);
              // 將數據寫入工作表
              export_data.forEach((row)=> {
                  const values=Object.values(row)
                  sheet1.addRow(values);
              });
              // 設置默認寬高屬性
              sheet1.properties.defaultColWidth=20
              sheet1.properties.defaultRowHeight=20
              // 修改所有單元格樣式
              // 遍歷每一行
              sheet1.eachRow((row, rowNumber)=> {
                  // 遍歷每個單元格
                  row.eachCell((cell)=> {
                      // 設置邊框樣式
                      cell.border={
                          top: {style: 'thin'},
                          left: {style: 'thin'},
                          bottom: {style: 'thin'},
                          right: {style: 'thin'}
                      };
                      // 設置居中對齊
                      cell.alignment={
                          vertical: 'middle',
                          horizontal: 'center'
                      };
                  });
              });
              // 獲取標題行數據
              const titleCell=sheet1.getRow(1);
              // 設置標題行單元格樣式
              titleCell.eachCell((cell)=> {
                  // 設置標題行背景顏色
                  cell.fill={
                      type: 'pattern',
                      pattern: 'solid',
                      fgColor: {argb: '3498db'}
                  };
                  // 設置標題行字體
                  cell.font={
                      bold: true,// 字體粗體
                  };
              })
              // 導出表格文件
              workbook.xlsx.writeBuffer().then((buffer)=> {
                  let file=new Blob([buffer], {type: "application/octet-stream"});
                  FileSaver.saveAs(file, filename + timeFile() + ".xlsx");
              }).catch(error=> console.log('Error writing excel export', error))
          }
          
          // 導入excel文件
          export function importFile(content) {
              return new Promise((resolve, reject)=> {
                  // 創建一個空的JavaScript對象數組,用于存儲解析后的數據
                  const data=[];
                  //創建Workbook實例
                  const workbook=new ExcelJS.Workbook();
                  workbook.xlsx.load(content).then(workbook=> {
                      // 獲取第一個worksheet內容
                      const worksheet=workbook.getWorksheet(1);
                      // 獲取第一行的標題
                      const headers=[];
                      worksheet.getRow(1).eachCell((cell)=> {
                          headers.push(cell.value);
                      });
                      // console.log("headers", headers)
                      // 遍歷工作表的每一行(從第二行開始,因為第一行通常是標題行)
                      for (let rowNumber=2; rowNumber <=worksheet.rowCount; rowNumber++) {
                          const rowData={};
                          const row=worksheet.getRow(rowNumber);
                          // 遍歷當前行的每個單元格
                          row.eachCell((cell, colNumber)=> {
                              // 獲取標題對應的鍵,并將當前單元格的值存儲到相應的屬性名中
                              rowData[headers[colNumber - 1]]=cell.value;
                          });
                          // 將當前行的數據對象添加到數組中
                          data.push(rowData);
                      }
                      // console.log("data", data)
                      resolve(data);
                  }).catch(error=> {
                      reject(error);
                  });
              })
          }

          vue組件調用

          以element plus為例,調用函數完成Excel文件導入與導出,代碼如下:

          <template>
            <el-button type="primary" @click="exportExcel">導出excel</el-button>
            <el-button type="success" @click="importExcel">導入excel</el-button>
            <p>導入數據預覽</p>
            {{ uploadData}}
            <el-dialog
                v-model="uploadDialogVisible"
                title="批量添加數據"
                width="40%"
            >
              <el-form label-width="120px">
                <el-form-item label="模板下載:">
                  <el-button type="info" @click="downloadTemplate">
                    <el-icon>
                      <Download/>
                    </el-icon>
                    點擊下載
                  </el-button>
                </el-form-item>
                <el-form-item label="文件上傳:">
                  <el-upload drag accept=".xls,.xlsx" :auto-upload="false" :on-change="handleChange">
                    <el-icon class="el-icon--upload">
                      <upload-filled/>
                    </el-icon>
                    <div class="el-upload__text">
                      將文件拖到此處,或<em>點擊上傳</em>
                    </div>
                    <template #tip>
                      <div class="el-upload__tip">
                        請上傳.xls,.xlsx格式文件,文件最大為500kb
                      </div>
                    </template>
                  </el-upload>
                </el-form-item>
              </el-form>
              <template #footer>
                <span class="dialog-footer">
                  <el-button @click="uploadDialogVisible=false">取消</el-button>
                  <el-button type="primary" @click="submitUpload">
                    導入
                  </el-button>
                </span>
              </template>
            </el-dialog>
          </template>
          
          <script setup>
          import {ref} from "vue";
          import {ElMessage} from "element-plus";
          import {Download, UploadFilled} from "@element-plus/icons-vue"
          import {getDemo} from "@/api/home";
          import {timeFormatConversion} from "@/utils/timeFormat";
          import {exportFile, importFile} from "@/utils/excel";
          // 表格字段配置
          const fieldConfig=ref([
            {
              'label': 'ID', // 標簽
              'model': 'id',// 字段名
              'is_export': true,// 是否導出該字段
            },
            {
              'label': '用戶名', // 標簽
              'model': 'username',// 字段名
              'is_export': true, // 是否導出該字段
            },
            {
              'label': '省份', // 標簽
              'model': 'province',// 字段名
              'is_export': true // 是否導出該字段
            },
            {
              'label': '性別', // 標簽
              'model': 'sex_name',// 字段名
              'is_export': true // 是否導出該字段
            },
            {
              'label': '生日', // 標簽
              'model': 'birthday',// 字段名
              'is_export': true, // 是否導出該字段
            },
            {
              'label': '身高(cm)', // 標簽
              'model': 'height',// 字段名
              'is_export': true, // 是否導出該字段
            },
            {
              'label': '體重(kg)', // 標簽
              'model': 'weight',// 字段名
              'is_export': true,// 是否導出該字段
            },
            {
              'label': '注冊時間', // 標簽
              'model': 'created_time',// 字段名
              'is_export': true, // 是否導出該字段
            },
            {
              'label': '個人介紹', // 標簽
              'model': 'introduction',// 字段名
              'is_export': true,// 是否導出該字段
            }
          ])
          // 導出Excel事件
          const exportExcel=()=> {
            ElMessage({
              message: '開始導出數據,請稍候!',
              type: 'success',
            })
            // 導出數據查詢參數
            const printParams={
              'size': 1000,
              'page': 1,
            }
            // 獲取需要導出的字段配置
            const export_fields=fieldConfig.value
                .filter(obj=> obj['is_export'])
                .map(({label, model})=> ({[model]: label}))
            // 處理數據結構
            getDemo(printParams).then((response)=> {
              // console.log(response.results)
              const export_data=response.results.map(obj=> {
                const newObj={};
                export_fields.forEach(field=> {
                  const [key, value]=Object.entries(field)[0];
                  if (key==='created_time') {
                    newObj[value]=timeFormatConversion((obj[key]), 'YYYY-MM-DD HH:mm:ss');
                  } else {
                    newObj[value]=obj[key];
                  }
                });
                return newObj;
              });
              let filename='示例用戶'
              exportFile(export_data, filename);
            }).catch(response=> {
              //發生錯誤時執行的代碼
              console.log(response)
              ElMessage.error('獲取列表數據失敗!')
            });
          }
          // 導入excel彈窗是否顯示
          const uploadDialogVisible=ref(false)
          // 點擊導入excel按鈕事件
          const importExcel=()=> {
            uploadDialogVisible.value=true
          }
          // 下載模板文件
          const downloadTemplate=()=> {
            window.open('https://api.cuiliangblog.cn/static/demo-template.xlsx')
          }
          // 文件數據
          const uploadData=ref([])
          // 文件上傳事件
          const handleChange=(file)=> {
            const reader=new FileReader();
            reader.onload=()=> {
              const content=reader.result;
              importFile(content).then((data)=> {
                console.log(data)
                uploadData.value=data
              }).catch(response=> {
                //發生錯誤時執行的代碼
                console.log(response)
                ElMessage.error('獲取列表數據失敗!')
              });
            };
            reader.readAsBinaryString(file.raw);
          };
          // 點擊導入excel提交數據事件
          const submitUpload=()=> {
            uploadDialogVisible.value=false
          }
          </script>
          
          <style scoped lang="scss">
          
          </style>

          頁面效果

          封裝后的頁面效果如下,至此,一個簡單的vue前端實現Excel文件導入導出功能便開發完成了。

          完整代碼

          gitee:https://gitee.com/cuiliang0302/vue3_vite_element-plus

          github:https://github.com/cuiliang0302/vue3-vite-template

          查看更多

          微信公眾號

          微信公眾號同步更新,歡迎關注微信公眾號《崔亮的博客》第一時間獲取最近文章。

          博客網站

          崔亮的博客-專注devops自動化運維,傳播優秀it運維技術文章。更多原創運維開發相關文章,歡迎訪問https://www.cuiliangblog.cn

          年年底曾有外媒報道,由于社區用戶的強烈要求,微軟正考慮添加 Python 作為官方的一種 Excel 腳本語言。不過在昨天的 Build 2018 開發者大會上,微軟沒有透露有關 Python 支持的消息,而是宣布 Excel 新增 JavaScript 支持,這意味著開發者現在可以在 Excel 中運行本地的 JavaScript 自定義函數。

          也就是說,開發者可以使用 JavaScript 代碼去自定義 Excel 公式,然后從 Excel 表格中插入并調用這些公式,并通過 JavaScript 解釋器計算表格數據,而不是使用 Excel 自己的計算引擎。

          微軟表示,辦公開發人員一直希望能夠在 Excel 中編寫 JavaScript 自定義函數去進行一些數學運算、銀行賬戶數據以及股票數據等等,此舉將讓他們可以更加靈活地定制 Excel 。

          不過該功能尚未正式發布,目前僅在 Windows 和 Mac 的 Excel 開發者預覽版,以及 Excel 在線版中提供,用戶需先加入 Office Insiders 并安裝自定義加載項方可進行體驗。


          主站蜘蛛池模板: 国产一区内射最近更新| 一区二区三区高清在线| 中文字幕一区二区三区精华液 | 亚洲一区欧洲一区| 一区二区无码免费视频网站| 国模精品一区二区三区视频| 亚洲第一区视频在线观看| 国产福利日本一区二区三区| 深夜福利一区二区| 日韩人妻精品一区二区三区视频 | 麻豆一区二区三区精品视频| 欧美日韩一区二区成人午夜电影| 久久人妻无码一区二区| 国产天堂一区二区综合| 亚洲a∨无码一区二区| 亚洲第一区在线观看| 精品国产伦一区二区三区在线观看 | 日韩AV无码久久一区二区| 日韩AV片无码一区二区不卡| 日韩视频一区二区三区| 午夜精品一区二区三区在线视 | 熟女少妇精品一区二区| 亚洲AV成人精品日韩一区 | 麻豆天美国产一区在线播放| 无码精品久久一区二区三区| 在线观看国产一区二三区| 国产成人AV一区二区三区无码| 精品国产亚洲一区二区三区在线观看| 亚洲视频一区调教| 日韩一区二区三区无码影院 | 亚洲一本一道一区二区三区 | 日本午夜精品一区二区三区电影 | 一区二区不卡久久精品| 福利片福利一区二区三区| 成人丝袜激情一区二区| 国产麻豆剧果冻传媒一区| 日韩免费视频一区| 国产福利电影一区二区三区,亚洲国模精品一区 | 国产乱码精品一区二区三区四川| 亚洲一区在线观看视频| 韩国理伦片一区二区三区在线播放|