JS實現(xiàn)讀取Excel文件內(nèi)容并生成二維碼
需求
一次普通的技術(shù)需求會議
? 項目經(jīng)理首先發(fā)言 我們技術(shù)這邊需要將xls表格中的幾千條數(shù)據(jù)變成二維碼,并且中間鑲嵌logo,圖片底部放置編號,由于xls表格數(shù)據(jù)私密,不能通過第三方完成
? 平常這個事情都是后端處理的,前端就是來摸魚的,但是這次一反常態(tài),后端臉黑了,帶樣式搞不來,腳一蹬,直接裝死
? 項目經(jīng)理用期盼的眼神看著我,頓時我緊張了起來,眼神飄忽,我已經(jīng)好多年沒搞過node了?。?!會議室都沉默了,在項目經(jīng)理不斷精神攻擊下,后端裝死的情況下,看來注定要大前端來拯救世界了,畢竟JavaScript萬能語言,俺來試試吧!
實現(xiàn)方案
? 以上情節(jié)純屬虛構(gòu),但是需求確實是這樣的,雖然好幾年沒碰過node,好歹年輕記性好,用過的基本都還記得,調(diào)研實現(xiàn)方案上沒出現(xiàn)太多問題,有如下方案
puppeteer
使用基于node環(huán)境的puppeteer,進(jìn)行二維碼繪制,圖片繪制,是JavaScript開發(fā)者面對此類需求的主流選擇
node-canvas
同樣是在服務(wù)端完成渲染,但是這個庫依賴node-gyp,如果不安裝python2,那安裝過程懂得都懂,不過這也是很不錯的方案
瀏覽器
通過瀏覽器canvas繪制,然后下載下來,會有刷刷刷下載圖片的炫酷效果
很明顯有刷刷刷下載圖片炫酷效果的方案更好,所以就選擇你了 瀏覽器方案!
問題分解
確定了技術(shù)方案,就要考慮具體實現(xiàn)了
- JavaScript讀取execl文件,并處理成理想格式
- 將讀取到的execl中的網(wǎng)址字段生成一張二維碼
- 將二維碼寫入canvas,在其中間加上logo,并在底部加一行文字
- 將canva轉(zhuǎn)化為DataURL,下載它
- 不斷遞歸生成,直到xls數(shù)據(jù)全部處理完畢
理論存在,實踐開始!
具體實現(xiàn)
啟動一個本地服務(wù)器
首先我們通過VScode Live Server 啟動一個本地服務(wù)器
這里有好奇寶寶要問了,為啥第一步是這?
答:因為瀏覽器是訪問不了電腦的文件系統(tǒng)的,所以只能通過啟動一個本地服務(wù)器的方案,來讀取我們的資源文件
創(chuàng)建html,引入資源庫
分析需要用到的第三方開源庫
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>生成二維碼</title> <script src="./qrcode.js"></script> <script src="./xlsx.full.min.js"></script> </head> <body> <!-- 用于生成載體 最終生成的圖片大小,按自己的需求來 --> <canvas width="260" height="310" id="canvas"></canvas> </body> <script> const ctx = initCanvas(); // 獲取ctx實例 // 初始化畫布 function initCanvas() { const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, 260, 310); return ctx; } </script> </html>
解析xls文件
readWorkbookFromRemoteFile().then((res) => { // res 為實際解析代碼 [{key:'xxxx',value:'xxxx'},....] }); // 讀取xls信息,并處理 function readWorkbookFromRemoteFile() { return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); xhr.open("get", "http://127.0.0.1:5500/xls.xls", true); xhr.responseType = "arraybuffer"; xhr.onload = (e) => { if (xhr.status == 200) { var data = new Uint8Array(xhr.response); var workbook = XLSX.read(data, { type: "array" }); // 獲取實際表格長度(去除表頭) let carryLen = 0; for (const key in workbook.Sheets["Sheet"]) { const ele = workbook.Sheets["Sheet"][key]; if (key.includes("A")) { carryLen++; } } // 解析數(shù)據(jù) let xls = []; for (let i = 2; i <= carryLen; i++) { let data = workbook.Sheets["Sheet"]; xls.push({ key: data["A" + i].w, value: data["B" + i].w, }); } resolve(xls); } }; xhr.send(); }); }
看到這里肯定也有細(xì)心的好奇寶寶問,為啥循環(huán)體中的i
為2呢?
答案:因為表格中的A1,B1為表格的第一行,而第一行是表頭,要去除
將鏈接生成為二維碼
new Promise((resolve, reject) => { // 生成二維碼 QRCode.toDataURL( 'xxxxxxx', { width: 260, height: 260, margin: 3, }, (error, url) => { if (error) console.error(error); const code = new Image(); code.src = url; code.onload = () => { ctx.drawImage(code, 0, 0); resolve(code); }; } );
寫入中間logo
return new Promise((resolve, reject) => { const code = new Image(); code.src = "http://127.0.0.1:5500/logo.jpeg"; code.onload = () => { ctx.drawImage(code, 260 / 2 - 20, 260 / 2 - 20, 40, 40); resolve(); }; });
寫入底部文字
// 寫入編號 ctx.font = "24px Arial"; ctx.fillStyle = "#000"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(xls[index].value, 130, 270);
canvas轉(zhuǎn)化為圖片,并下載到本地
// 用于預(yù)覽 let url = document.getElementById("canvas").toDataURL("image/png"); var a = document.createElement("a"); // 生成一個a元素 var event = new MouseEvent("click"); // 創(chuàng)建一個單擊事件 a.download = xls[index].value; // 將a的download屬性設(shè)置為我們想要下載的圖片名稱,若name不存在則使用‘下載圖片名稱'作為默認(rèn)名稱 a.href = url; // 將生成的URL設(shè)置為a.href屬性 a.dispatchEvent(event); // 觸發(fā)a的單擊事件
第一張圖片,完成生成
遞歸調(diào)用
我們修改發(fā)起邏輯代碼,邏輯尾部增加遞歸調(diào)用就好啦
readWorkbookFromRemoteFile().then((res) => { createImg(res, 0); // 遞歸生成 }); // ...... // 實際生成邏輯 function createImg(xls, index) { new Promise((resolve, reject) => { // 生成二維碼 }) .then((res) => { // 生成中間logo }) .then(() => { // 寫入編號 }) .then(() => { // 下載圖片 }) .then(() => { setTimeout(() => { if (xls.length > index + 1) { ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, 260, 310); // 初始化畫布 createImg(xls, index + 1); } }, 20); // 愛惜機器,加個延時,也可以去掉延時,體會機器的極致速度 }); }
最終效果
至此,終于實現(xiàn)了刷刷刷下載圖片炫酷效果,此時可以腦部一段很快的rap,如果華佗再世,崇洋可以醫(yī)治,外邦來學(xué)漢字...............
最終生成的文件
到此這篇關(guān)于JS實現(xiàn)讀取Excel文件內(nèi)容并生成二維碼的文章就介紹到這了,更多相關(guān)JS讀取Excel文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript使用sort函數(shù)實現(xiàn)漢字排序
JavaScript中的sort函數(shù)是一個強大且多用途的工具,能夠?qū)?shù)組的元素進(jìn)行排序,而漢字按照拼音排序又是一個常見需求,下面我們就來看看如何使用JavaScript實現(xiàn)漢字排序吧2023-12-12webpack-dev-server 的 host 配置 0.0.0.0的方法
這篇文章主要介紹了webpack-dev-server 的 host 配置 0.0.0.0的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,,需要的朋友可以參考下2024-01-01javascript getElementByTagName的使用
javascript getElementByTagName當(dāng)鼠標(biāo)放上去時將超鏈接的顏色設(shè)為藍(lán)色的。2009-06-06Javascript循環(huán)刪除數(shù)組中元素的幾種方法示例
這篇文章主要給大家介紹了關(guān)于Javascript循環(huán)刪除數(shù)組中元素的幾種方法,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-05-05微信小程序input框中加入小圖標(biāo)的實現(xiàn)方法
這篇文章主要介紹了微信小程序input框中加入小圖標(biāo)的實現(xiàn)方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-06-06