[工具] 前端 excel - Handsontable
Ref : https://handsontable.com/
最近有需要在網頁上用到類似 excel 的功能
於是使用 Handsontable 這個套件
這個套件有分 CE 跟 Pro 版本
CE也就是 Community Edition, 通常是免費的
Pro 則是有額外強大的功能, 要收費的
這邊就簡單筆記一下我用到的部分 (CE)
底下是 js 的部分
最近有需要在網頁上用到類似 excel 的功能
於是使用 Handsontable 這個套件
這個套件有分 CE 跟 Pro 版本
CE也就是 Community Edition, 通常是免費的
Pro 則是有額外強大的功能, 要收費的
這邊就簡單筆記一下我用到的部分 (CE)
<!-- 需要一個裝 handsontable 的容器 -->
<div id="handsome-table">
<button class="btn btn-success pull-right" id="export-btn">匯出EXCEL</button>
底下是 js 的部分
// 定義好欄位名稱
const COL_HEADER = [
'Permalink',
'觸及',
'點擊',
'點擊率',
'負評',
'負評率'
];
let container = document.getElementById('handsome-table');
// 裝 handsontable 的 data array
// handsontable 是直接操控 data, 也就是 data-binding
// 這個到後面很好用
let data = [];
// 定義匯出 handsontable 的按鈕
let $exportBtn = $('#export-btn');
// 初始化 handsontable
let hot = new Handsontable(container, {
data: data,
// 定義資料的 schema, 讓資料不要只是用陣列呈現, 而是物件
dataSchema: {
permalink: null,
impression: null,
click: null,
clickRate: null,
negative: null,
negativeRate: null
},
// 是否滿版
stretchH: "all",
// 要不要加上欄位名稱
colHeaders: true,
// 欄位名稱的值
colHeaders: COL_HEADER,
// 是否允許複製貼上
copyPaste: true,
contextMenu: true,
// 定義每一個欄位的屬性, ex: 型態是 number or text, number的話要到小數點後幾位, 欄位寬度等
columns: [
{
data: 'permalink',
type: 'text',
width: 800
}, {
data: 'impression',
type: 'numeric',
width: 80
}, {
data: 'click',
type: 'numeric',
width: 80
}, {
data: 'clickRate',
type: 'numeric',
numericFormat: {
pattern: '0.0000'
},
width: 80
}, {
data: 'negative',
type: 'numeric',
width: 80
}, {
data: 'negativeRate',
type: 'numeric',
numericFormat: {
pattern: '0.0000'
},
width: 80
}
],
// 定義貼上後觸發的 function
afterPaste: async function () {
$exportBtn.removeClass('btn-success').addClass('btn-warning').attr('disabled', true).text('處理中');
let processes = [];
// trim space
data.map(d => {
if (d.permalink) {
d.permalink = d.permalink.trim();
}
return d;
});
for (let x in data) {
if (!data[x].permalink) {
continue;
}
let result = await sendRequestAsync('POST', API_URL, { url: data[x].permalink });
let {
clicks, clicks_rate,
impressions, negative_feedback,
negative_feedback_rate
} = result.response;
data[x].impression = impressions;
data[x].click = clicks;
data[x].clickRate = clicks_rate * 100;
data[x].negative = negative_feedback;
data[x].negativeRate = negative_feedback_rate * 100;
// 刷新頁面
this.render();
}
// sort by negative rate descending
data.sort((a, b) => {
if (a.negativeRate === null) {
return 1;
} else if (b.negativeRate === null) {
return -1;
} else {
return b.negativeRate - a.negativeRate;
}
});
// 刷新頁面
this.render();
$exportBtn.removeClass('btn-warning').addClass('btn-success').removeAttr('disabled').text('匯出');
},
// 最少要幾個 rows
minRows: 30,
minSpareRows: 1
});
// 匯出 excel
$exportBtn.click(function () {
let rows = data.filter(d=>d.permalink);
let content = `data:text/csv;charset=utf-8,`;
rows.forEach((r, idx)=> {
if (idx === 0) {
content += `${COL_HEADER.join(',')}\r\n`;
}
let _c = [];
for (let key in r) {
_c.push(r[key]);
}
content += `${_c.join(',')}\r\n`;
});
let date = new Date();
let encodedUri = encodeURI(content);
let link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", `insight_${getyyyymmdd()}.csv`);
link.innerHTML= "Click Here to download";
document.body.appendChild(link); // Required for FF
link.click();
});
留言
張貼留言