JS實(shí)現(xiàn)讀取Excel文件內(nèi)容并生成二維碼
需求
一次普通的技術(shù)需求會議
? 項(xiàng)目經(jīng)理首先發(fā)言 我們技術(shù)這邊需要將xls表格中的幾千條數(shù)據(jù)變成二維碼,并且中間鑲嵌logo,圖片底部放置編號,由于xls表格數(shù)據(jù)私密,不能通過第三方完成
? 平常這個事情都是后端處理的,前端就是來摸魚的,但是這次一反常態(tài),后端臉黑了,帶樣式搞不來,腳一蹬,直接裝死
? 項(xiàng)目經(jīng)理用期盼的眼神看著我,頓時我緊張了起來,眼神飄忽,我已經(jīng)好多年沒搞過node了啊??!會議室都沉默了,在項(xiàng)目經(jīng)理不斷精神攻擊下,后端裝死的情況下,看來注定要大前端來拯救世界了,畢竟JavaScript萬能語言,俺來試試吧!
實(shí)現(xiàn)方案
? 以上情節(jié)純屬虛構(gòu),但是需求確實(shí)是這樣的,雖然好幾年沒碰過node,好歹年輕記性好,用過的基本都還記得,調(diào)研實(shí)現(xiàn)方案上沒出現(xiàn)太多問題,有如下方案
puppeteer
使用基于node環(huán)境的puppeteer,進(jìn)行二維碼繪制,圖片繪制,是JavaScript開發(fā)者面對此類需求的主流選擇
node-canvas
同樣是在服務(wù)端完成渲染,但是這個庫依賴node-gyp,如果不安裝python2,那安裝過程懂得都懂,不過這也是很不錯的方案
瀏覽器
通過瀏覽器canvas繪制,然后下載下來,會有刷刷刷下載圖片的炫酷效果
很明顯有刷刷刷下載圖片炫酷效果的方案更好,所以就選擇你了 瀏覽器方案!
問題分解
確定了技術(shù)方案,就要考慮具體實(shí)現(xiàn)了
- JavaScript讀取execl文件,并處理成理想格式
- 將讀取到的execl中的網(wǎng)址字段生成一張二維碼
- 將二維碼寫入canvas,在其中間加上logo,并在底部加一行文字
- 將canva轉(zhuǎn)化為DataURL,下載它
- 不斷遞歸生成,直到xls數(shù)據(jù)全部處理完畢
理論存在,實(shí)踐開始!
具體實(shí)現(xiàn)
啟動一個本地服務(wù)器
首先我們通過VScode Live Server 啟動一個本地服務(wù)器
這里有好奇寶寶要問了,為啥第一步是這?
答:因?yàn)闉g覽器是訪問不了電腦的文件系統(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實(shí)例
// 初始化畫布
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 為實(shí)際解析代碼 [{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" });
// 獲取實(shí)際表格長度(去除表頭)
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呢?
答案:因?yàn)楸砀裰械腁1,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); // 遞歸生成
});
// ......
// 實(shí)際生成邏輯
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); // 愛惜機(jī)器,加個延時,也可以去掉延時,體會機(jī)器的極致速度
});
}最終效果

至此,終于實(shí)現(xiàn)了刷刷刷下載圖片炫酷效果,此時可以腦部一段很快的rap,如果華佗再世,崇洋可以醫(yī)治,外邦來學(xué)漢字...............
最終生成的文件

到此這篇關(guān)于JS實(shí)現(xiàn)讀取Excel文件內(nèi)容并生成二維碼的文章就介紹到這了,更多相關(guān)JS讀取Excel文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

