js-xlsx實現Excel的匯入匯出功能
阿新 • • 發佈:2019-01-02
一:匯入功能
讀取excel的多個sheet資料
<script type="text/javascript" src="js/xlsx.core.min.js"></script>
<table style="width:80%;margin-left:10%;margin-top:30px;">
<td align="right" style="width: 50%;">
<h3 align="center">匯入參賽名單:</h3>
</td>
<td align="left" style="width: 50%;">
<input type="file" id="uploadfile" onchange="importf(this);"/>
</td>
</table>
<div style="width:80%;margin-left:10%;margin-top:30px;">
<div style="width:30%;height:100%;float:left;">
<table id="txtArea1" style ="width:100%;" cellspacing="0" cellpadding="0"> </table>
</div>
<div style="width:30%;height:100%;margin-left:5%;margin-right:5%;float:left;">
<table id="txtArea2" style="width:100%;" cellspacing="0" cellpadding="0"> </table>
</div>
<div style="width:30%;height:100%;float:left;" >
<table id="txtArea3" style="width:100%;" cellspacing="0" cellpadding="0"> </table>
</div>
</div>
js程式碼:
<script type="text/javascript">
// 遍歷每張表讀取
var persons1 = [];
var persons2 = [];
var persons3 = [];
function importf(obj) {
var wb;// 讀取完成的資料
var f = obj.files[0];
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
wb = XLSX.read(data, {
type : 'binary'
}); // 以二進位制流方式讀取得到整份excel表格物件
// 表格的表格範圍,可用於判斷表頭是否數量是否正確
var fromTo = '';
// wb.SheetNames[0]是獲取Sheets中第一個Sheet的名字
// wb.Sheets[Sheet名]獲取第一個Sheet的資料JSON.stringify(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]));
for (var i = 0; i < wb.SheetNames.length; i++) {
if (wb.Sheets.hasOwnProperty(wb.SheetNames[i])) {
fromTo = wb.Sheets[wb.SheetNames[i]]['!ref']; // output: A1:D5
if(i==0){
persons1 = persons1.concat(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[i]]));
}else if(i==1){
persons2 = persons2.concat(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[i]]));
}else if(i==2){
persons3 = persons3.concat(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[i]]));
}
//break; //如果只取第一張表,就加上這行
}
}
//document.getElementById("txtArea1").innerHTML= JSON.stringify(persons1)+JSON.stringify(persons2)+JSON.stringify(persons3);
appendTr("txtArea1",persons1);
appendTr("txtArea2",persons2);
appendTr("txtArea3",persons3);
};
reader.readAsBinaryString(f);
}
function appendTr(id, array){
if(array.length>0){
for(var i = 0; i < array.length; i++){
o=document.createElement("TR"); //<td align="center" width="20%" class="cx-nr"><%=orgname%></td>
// 所屬公司
o1=document.createElement("TD");
o1.innerHTML=array[i].所屬公司;
o1.setAttribute("align","center");
o1.setAttribute("width","50%");
o1.setAttribute("class","cx-nr");
// 參賽人員
o2=document.createElement("TD");
o2.innerHTML=array[i].參賽人員;
o2.setAttribute("align","center");
o2.setAttribute("width","50%");
o2.setAttribute("class","cx-nr1");
o.appendChild(o1);
o.appendChild(o2);
document.getElementById(id).appendChild(o);
}
}
}
</script>
二:匯出功能
var json;
var tmpdata;//?
var tmpdata1 = [];
var tmpdata2 = [];
var tmpdata3 = [];
var outputPos1;
var outputPos2;
var outputPos3;
var json1;
var json2;
var json3;
function getJson(num){
var tabLen = document.getElementById("jinji"+num);
var jsonStr = "[";
for (var i = 1; i < tabLen.rows.length; i++) {
jsonStr += '{"十六強":"' + tabLen.rows[i].cells[0].innerHTML + '","八強":"' + tabLen.rows[i].cells[1].innerHTML + '","四強":"' + tabLen.rows[i].cells[2].innerHTML + '"},'
}
jsonStr= jsonStr.substr(0, jsonStr.length - 1);
jsonStr += "]";
if(num==1) json1 = JSON.parse(jsonStr); //將json字串轉換為json陣列
if(num==2) json2 = JSON.parse(jsonStr); //將json字串轉換為json陣列
if(num==3) json3 = JSON.parse(jsonStr); //將json字串轉換為json陣列
}
function getTmpdataOutputPos(num){
if(num==1){json=json1; tmpdata = json1[0]; json1.unshift({});}
if(num==2){json=json2; tmpdata = json2[0]; json2.unshift({});}
if(num==3){json=json3; tmpdata = json3[0]; json3.unshift({});}
//var tmpdata = json[0];
//json.unshift({});
var keyMap = []; //獲取keys
for (var k in tmpdata) {
keyMap.push(k);
json[0][k] = k;
}
if(num==1){
tmpdata1 = [];//用來儲存轉換好的json
json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
v: v[k],
position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
}))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata1[v.position] = {
v: v.v
});
outputPos1 = Object.keys(tmpdata1); //設定區域,比如表格從A1到D10
}else if(num==2){
tmpdata2 = [];//用來儲存轉換好的json
json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
v: v[k],
position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
}))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata2[v.position] = {
v: v.v
});
outputPos2 = Object.keys(tmpdata2); //設定區域,比如表格從A1到D10
}else if(num==3){
tmpdata3 = [];//用來儲存轉換好的json
json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
v: v[k],
position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
}))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata3[v.position] = {
v: v.v
});
outputPos3 = Object.keys(tmpdata3); //設定區域,比如表格從A1到D10
}
}
var tmpDown; //匯出的二進位制物件
function PromotionTeamToExcel(type) {
getJson(1); //女單
getJson(2); //男單
getJson(3); //混雙
var uploadfile2 = document.getElementById("uploadfile2").value;
var filename = uploadfile2.substring(uploadfile2.lastIndexOf("\\")+1);
document.getElementById("hf").download=filename;
getTmpdataOutputPos(1); //json1
getTmpdataOutputPos(2); //json2
getTmpdataOutputPos(3); //json3
var tmpWB = {
SheetNames: ['女單晉級','男單晉級','混雙晉級'], //儲存的表標題
Sheets: {
'女單晉級': Object.assign({},
tmpdata1, //內容
{
'!ref': outputPos1[0] + ':' + outputPos1[outputPos1.length - 1] //設定填充區域
}),
'男單晉級': Object.assign({},
tmpdata2, //內容
{
'!ref': outputPos2[0] + ':' + outputPos2[outputPos2.length - 1] //設定填充區域
}),
'混雙晉級': Object.assign({},
tmpdata3, //內容
{
'!ref': outputPos3[0] + ':' + outputPos3[outputPos3.length - 1] //設定填充區域
})
}
};
tmpDown = new Blob([s2ab(XLSX.write(tmpWB,
{bookType: (type == undefined ? 'xlsx':type),bookSST: false, type: 'binary'}//這裡的資料是用來定義匯出的格式型別
))], {
type: ""
}); //建立二進位制物件寫入轉換好的位元組流
var href = URL.createObjectURL(tmpDown); //建立物件超連結
document.getElementById("hf").href = href; //繫結a標籤
document.getElementById("hf").click(); //模擬點選實現下載
setTimeout(function() { //延時釋放
URL.revokeObjectURL(tmpDown); //用URL.revokeObjectURL()來釋放這個object URL
}, 100);
}
function s2ab(s) { //字串轉字元流
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
// 將指定的自然數轉換為26進製表示。對映關係:[0-25] -> [A-Z]。
function getCharCol(n) {
let temCol = '',
s = '',
m = 0
while (n > 0) {
m = n % 26 + 1
s = String.fromCharCode(m + 64) + s
n = (n - m) / 26
}
return s
}
補充1:合併單元格,但是設定單元格樣式無效
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script src="http://oss.sheetjs.com/js-xlsx/xlsx.full.min.js"></script>
<script>
//如果使用 FileSaver.js 就不要同時使用以下函式
function saveAs(obj, fileName) {
//當然可以自定義簡單的下載檔案實現方式
var tmpa = document.createElement("a");
tmpa.download = fileName || "下載";
tmpa.href = URL.createObjectURL(obj); //繫結a標籤
tmpa.click(); //模擬點選實現下載
setTimeout(function () { //延時釋放
URL.revokeObjectURL(obj); //用URL.revokeObjectURL()來釋放這個object URL
}, 100);
}
var json = [{ //測試資料
"分組": 1,//A
"所屬公司": "aa",
"參賽人員": "bb"
}, {
"分組": 2,
"所屬公司": "cc",
"參賽人員": "dd"
}, {
"分組": 3,
"所屬公司": "ee",
"參賽人員": "ff"
}];
const wopts = { bookType: 'xlsx', bookSST: true, type: 'binary' };//這裡的資料是用來定義匯出的格式型別
function downloadExl(type) {
var wb = { SheetNames: ['Sheet1'], Sheets: {}, Props: {} };
//wb.Sheets['Sheet1'] = XLSX.utils.json_to_sheet(json);//通過json_to_sheet轉成單頁(Sheet)資料
json = XLSX.utils.json_to_sheet(json);
json["A2"] = { t: "s", v: "A組" };
json["!merges"] = [{//合併第一列資料[A2,A3,A4,A5]
s: {//s為開始
c: 0,//開始列
r: 1//開始行
}, e: {//e結束
c: 0,//結束列
r: 4//結束行
}
}];
wb.Sheets['Sheet1'] = json;
saveAs(
new Blob([s2ab(XLSX.write(wb, wopts))], { type: "application/octet-stream"}),
"這裡是下載的檔名" + '.' + (wopts.bookType == "biff2" ? "xls" : wopts.bookType));
}
function s2ab(s) {
if (typeof ArrayBuffer !== 'undefined') {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
} else {
var buf = new Array(s.length);
for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
}
</script>
<button onclick="downloadExl()">匯出</button>
</body>
</html>
補充2:合併單元格,可以設定單元格的寬度、居中、字型、顏色等
下載protobi/js-xlsx:https://github.com/protobi/js-xlsx
將js-xlsx-master\dist\xlsx.full.min.js放到js目錄中
<script type="text/javascript" src="js/xlsx.full.min.js"></script>
<input type="button" onclick="PromotionTeamToExcel();" value="匯出為Excel"/>
var resGroup = ["A組","B組","C組","D組","E組","F組","G組","H組"];
function saveAs(obj, fileName) {
var tmpa = document.createElement("a");
tmpa.download = fileName || "下載";
tmpa.href = URL.createObjectURL(obj);
tmpa.click();
setTimeout(function () {
URL.revokeObjectURL(obj);
}, 100);
}
const wopts = { bookType: 'xlsx', bookSST: true, type: 'binary', cellStyles: true };
function PromotionTeamToExcel(type) {
var jsonStr = "[";
for (var i = 0; i < result.length; i++) {
jsonStr += '{"分組":"","所屬公司":"' + $('#t'+i+'-1').text() + '","參賽人員":"' + $('#t'+i+'-2').text() + '"},'
}
jsonStr= jsonStr.substr(0, jsonStr.length - 1);
jsonStr += "]";
var json = JSON.parse(jsonStr); //將json字串轉換為json陣列
var tmpdata = json[0];
json.unshift({});
var keyMap = []; //獲取keys
for (var k in tmpdata) {
keyMap.push(k);
json[0][k] = k;
}
var tmpdata = [];//用來儲存轉換好的json
json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {v: v[k], position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
}))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata[v.position] = {v: v.v});
var outputPos = Object.keys(tmpdata); //設定區域,比如表格從A1到D10
//t = [[2,5],[6,9],[10,13],[14,17],[18,21],[22,25],[26,28],[29,31]];
//t = [[2,5],[6,9],[10,13],[14,17],[18,21],[22,24],[25,27],[28,30]];
//t = [[2,5],[6,9],[10,13],[14,17],[18,20],[21,23],[24,26],[27,29]];
//t = [[2,5],[6,9],[10,13],[14,16],[17,19],[20,22],[23,25],[26,28]];
//t = [[2,5],[6,9],[10,12],[13,15],[16,18],[19,21],[22,24],[25,27]];
//t = [[2,5],[6,8],[9,11],[12,14],[15,17],[18,20],[21,23],[24,26]];
var end = 0;
var t = [];
for(var i = 0; i < 8; i++){
// 分組
if(end < ((result.length%8)*4+1)){
end = 4*(i+1)+1;
t[i] = [end-3,end];
}else{
end = end+3;
t[i] = [end-2,end];
}
}
//列的寬度
tmpdata["!cols"] = [{wpx: 80}, {wpx: 160}, {wpx: 160}];
//合併單元格
var merges=[];
for(var i = 0; i < 8; i++){
merges.push({s: {c: 0, r: t[i][0]-1}, e: {c: 0, r: t[i][1]-1}});
}
tmpdata["!merges"] = merges;
//每個合併單元格的資料
for(var i = 0; i < 8; i++){
tmpdata["A"+t[i][0]] = { t: "s", v: resGroup[i], s: {alignment: {horizontal: "center", vertical: "center"} } };
}
//設定單元格居中顯示
for(var i = 0; i < result.length; i++){
var ii=i+2;
tmpdata["B"+ii].s = {alignment: {horizontal: "center", vertical: "center"} };
tmpdata["C"+ii].s = {alignment: {horizontal: "center", vertical: "center"} };
}
//設定標題字型、加粗、居中
tmpdata["A1"].s = {font: { sz: 13, bold: true, }, alignment: {horizontal: "center", vertical: "center", wrap_text:true} };//<====設定xlsx單元格樣式
tmpdata["B1"].s = {font: { sz: 13, bold: true, }, alignment: {horizontal: "center", vertical: "center", wrap_text:true} };//<====設定xlsx單元格樣式
tmpdata["C1"].s = {font: { sz: 13, bold: true, }, alignment: {horizontal: "center", vertical: "center", wrap_text:true} };//<====設定xlsx單元格樣式
var tmpWB = {
SheetNames: ['sheet1'], //儲存的表標題
Sheets: {
'sheet1': Object.assign({}, tmpdata, {
'!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] //設定填充區域
})
}
};
tmpDown = new Blob([s2ab(XLSX.write(tmpWB, { bookType: (type == undefined ? 'xlsx' : type), bookSST: false, type: 'binary' }))], {type: ""});
saveAs(tmpDown, title + '.' + (wopts.bookType == "biff2" ? "xls" : wopts.bookType));
}
function getCharCol(n) {
let temCol = '',
s = '',
m = 0
while (n > 0) {
m = n % 26 + 1
s = String.fromCharCode(m + 64) + s
n = (n - m) / 26
}
return s;
}
function s2ab(s) {
if (typeof ArrayBuffer !== 'undefined') {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
} else {
var buf = new Array(s.length);
for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
}