vue element 導出excel表格(前端實現excel合并單元格)

npm install --save xlsx file-saver


創建@/vendor/Export2Excel.js:

require('script-loader!file-saver');

require('script-loader!@/vendor/Blob'); //在vendor文件加下建立Blob.js,代碼在最下方

import XLSXfrom 'xlsx'


function datenum(v, date1904) {

if (date1904) v +=1462;

var epoch =Date.parse(v);

return (epoch -new Date(Date.UTC(1899,11,30))) / (24 *60 *60 *1000);

}

function sheet_from_array_of_arrays(data, opts) {

var ws = {};

var range = {s: {c:10000000,r:10000000},e: {c:0,r:0}};

for (var R =0;R != data.length; ++R) {

for (var C =0;C != data[R].length; ++C) {

if (range.s.r >R)range.s.r =R;

if (range.s.c >C)range.s.c =C;

if (range.e.r

if (range.e.c

var cell = {v: data[R][C]};

if (cell.v ==null)continue;

var cell_ref = XLSX.utils.encode_cell({c:C,r:R});

if (typeof cell.v ==='number')cell.t ='n';

else if (typeof cell.v ==='boolean')cell.t ='b';

else if (cell.v instanceof Date) {

cell.t ='n';

cell.z = XLSX.SSF._table[14];

cell.v =datenum(cell.v);

}

else cell.t ='s';

ws[cell_ref] =cell;

}

}

if (range.s.c <10000000)ws['!ref'] = XLSX.utils.encode_range(range);

return ws;

}

function Workbook() {

if (!(this instanceof Workbook))return new Workbook();

this.SheetNames = [];

this.Sheets = {};

}

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;

}

// 單列合并數據加工

//在tableData數據中對colName列進行加工(header:['xx','yy',...],mergeRule:[2,1,1,3,2,1...])

// 返回格式 newTableDatas = [[列頭s], ["abc", "ss", "yyy", 0], [null, "xx", "y", 1], ["bca", "xxx", "yy", 1], [null, "xxx", "yy", 1]]

// 返回格式 newMergeRules = [{"e":{"r":2,"c":0}, "s":{"r":1,"c":0}},{"e":{"r":4,"c":0}, "s":{"r":3,"c":0}}]

function formatTableData(header,tableDatas,mergeRules,colIndex,colName){

var newTableDatas = [header]// 第一行為列頭,

? var newMergeRules= []//加工合并規則

? var currRowIndex =1 // 因為第一行為列頭所以起始為1

? var mergeIndexs = [currRowIndex]// 因為第一行為列頭所以起始為1,為創建newTableDatas使用

? for(var i=0;i

var endRowIndex =currRowIndex + mergeRules[i] -1

? ? var merge = {"e":{"r":endRowIndex,"c": colIndex},"s":{"r":currRowIndex,"c":colIndex}}

newMergeRules.push(merge)

currRowIndex =currRowIndex + mergeRules[i]

mergeIndexs.push(currRowIndex)

}

for(var i=0;i

var currRow = tableDatas[i]

if(mergeIndexs.indexOf(i+1) === -1){

currRow[colName] =null //合并的數據 但不是第一行時,此列賦值null

? ? }

var newTabRow = []

for (var j in currRow) {

newTabRow.push(currRow[j])

}

newTableDatas.push(newTabRow)

}

return [newTableDatas,newMergeRules]

}




@/vendor/Blob.js:

export function export_data_to_excel(header,tableDatas,mergeRules,colIndex,colName,excelName) {

var oo =formatTableData(header,tableDatas,mergeRules,colIndex,colName);

var ranges =oo[1];

/* original data */

? var data =oo[0];

var ws_name ="SheetJS";

var wb =new Workbook(),ws =sheet_from_array_of_arrays(data);

/* add ranges to worksheet */

// ws['!cols'] = ['apple', 'banan'];

? ws['!merges'] =ranges;

/* add worksheet to workbook */

? wb.SheetNames.push(ws_name);

wb.Sheets[ws_name] =ws;

var wbout = XLSX.write(wb, {bookType:'xlsx',bookSST:false,type:'binary'});

saveAs(new Blob([s2ab(wbout)], {type:"application/octet-stream"}), excelName+".xlsx")

}


(function (view) {

"use strict";

view.URL = view.URL || view.webkitURL;

if (view.Blob && view.URL) {

try {

new Blob;

return;

}catch (e) {}

}

// Internally we use a BlobBuilder implementation to base Blob off of

// in order to support older browsers that only have BlobBuilder

? ? var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {

var

? ? ? ? ? ? ? ? get_class =function(object) {

return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];

}

,FakeBlobBuilder =function BlobBuilder() {

this.data = [];

}

,FakeBlob =function Blob(data, type, encoding) {

this.data = data;

this.size = data.length;

this.type = type;

this.encoding = encoding;

}

,FBB_proto =FakeBlobBuilder.prototype

,FB_proto =FakeBlob.prototype

,FileReaderSync = view.FileReaderSync

,FileException =function(type) {

this.code =this[this.name = type];

}

,file_ex_codes = (

"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "

? ? ? ? ? ? ? ? ? ? +"NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"

? ? ? ? ? ? ? ? ).split(" ")

,file_ex_code =file_ex_codes.length

,real_URL = view.URL || view.webkitURL || view

,real_create_object_URL =real_URL.createObjectURL

? ? ? ? ? ? ? ? ,real_revoke_object_URL =real_URL.revokeObjectURL

? ? ? ? ? ? ? ? ,URL =real_URL

? ? ? ? ? ? ? ? ,btoa = view.btoa

? ? ? ? ? ? ? ? ,atob = view.atob

? ? ? ? ? ? ? ? ,ArrayBuffer = view.ArrayBuffer

,Uint8Array = view.Uint8Array

;

FakeBlob.fake =FB_proto.fake =true;

while (file_ex_code--) {

FileException.prototype[file_ex_codes[file_ex_code]] =file_ex_code +1;

}

if (!real_URL.createObjectURL) {

URL = view.URL = {};

}

URL.createObjectURL =function(blob) {

var

? ? ? ? ? ? ? ? ? ? type = blob.type

? ? ? ? ? ? ? ? ? ? ,data_URI_header

? ? ? ? ? ? ? ? ? ? ;

if (type ===null) {

type ="application/octet-stream";

}

if (blobinstanceof FakeBlob) {

data_URI_header ="data:" +type;

if (blob.encoding ==="base64") {

return data_URI_header +";base64," + blob.data;

}else if (blob.encoding ==="URI") {

return data_URI_header +"," +decodeURIComponent(blob.data);

}if (btoa) {

return data_URI_header +";base64," +btoa(blob.data);

}else {

return data_URI_header +"," +encodeURIComponent(blob.data);

}

}else if (real_create_object_URL) {

return real_create_object_URL.call(real_URL, blob);

}

};

URL.revokeObjectURL =function(object_URL) {

if (object_URL.substring(0,5) !=="data:" &&real_revoke_object_URL) {

real_revoke_object_URL.call(real_URL, object_URL);

}

};

FBB_proto.append =function(data/*, endings*/) {

var bb =this.data;

// decode data to a binary string

? ? ? ? ? ? ? ? if (Uint8Array && (datainstanceof ArrayBuffer || datainstanceof Uint8Array)) {

var

? ? ? ? ? ? ? ? ? ? ? ? str =""

? ? ? ? ? ? ? ? ? ? ? ? ,buf =new Uint8Array(data)

,i =0

? ? ? ? ? ? ? ? ? ? ? ? ,buf_len =buf.length

;

for (;i

str +=String.fromCharCode(buf[i]);

}

bb.push(str);

}else if (get_class(data) ==="Blob" ||get_class(data) ==="File") {

if (FileReaderSync) {

var fr =new FileReaderSync;

bb.push(fr.readAsBinaryString(data));

}else {

// async FileReader won't work as BlobBuilder is sync

? ? ? ? ? ? ? ? ? ? ? ? throw new FileException("NOT_READABLE_ERR");

}

}else if (datainstanceof FakeBlob) {

if (data.encoding ==="base64" &&atob) {

bb.push(atob(data.data));

}else if (data.encoding ==="URI") {

bb.push(decodeURIComponent(data.data));

}else if (data.encoding ==="raw") {

bb.push(data.data);

}

}else {

if (typeof data !=="string") {

data +="";// convert unsupported types to strings

? ? ? ? ? ? ? ? ? ? }

// decode UTF-16 to binary string

? ? ? ? ? ? ? ? ? ? bb.push(unescape(encodeURIComponent(data)));

}

};

FBB_proto.getBlob =function(type) {

if (!arguments.length) {

type =null;

}

return new FakeBlob(this.data.join(""), type,"raw");

};

FBB_proto.toString =function() {

return "[object BlobBuilder]";

};

FB_proto.slice =function(start, end, type) {

var args =arguments.length;

if (args <3) {

type =null;

}

return new FakeBlob(

this.data.slice(start,args >1 ? end :this.data.length)

, type

,this.encoding

);

};

FB_proto.toString =function() {

return "[object Blob]";

};

FB_proto.close =function() {

this.size =this.data.length =0;

};

return FakeBlobBuilder;

}(view));

view.Blob =function Blob(blobParts, options) {

var type = options ? (options.type ||"") :"";

var builder =new BlobBuilder();

if (blobParts) {

for (var i =0,len = blobParts.length;i

builder.append(blobParts[i]);

}

}

return builder.getBlob(type);

};

}(typeof self !=="undefined" &&self ||typeof window !=="undefined" &&window ||this.content ||this));

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,041評論 0 2
  • 不支持上傳文件,所以就復制過來了。作者信息什么的都沒刪。對前端基本屬于一竅不通,所以沒有任何修改,反正用著沒問題就...
    全棧在路上閱讀 1,984評論 0 2
  • 感恩今天是周一,早上5點多就起來給女兒做飯,要送她去上學。感恩女兒夸我做的早餐好吃,感恩女兒這段時間學習的心態很好...
    武丹yoyo閱讀 209評論 0 4
  • 初見,一眼透過萬年。 他的容顏亙古不變,三千銀發,紫衫翩躚。 凝眸回首,他目光流轉,掠過千年的風塵而來,扣響她心間...
    與子同說閱讀 2,206評論 9 18
  • 昨晚睡覺前打開了阿加莎的這本無人生還,劇情太精彩,居然一口氣看完了,看到一點多,困。 讀這本阿婆的經典小說,首先映...
    eeMY9n閱讀 1,981評論 0 0