Kendo UI框架提供了強大的Excel導出功能,通過Grid的saveAsExcel能方便地導出Grid中的數據,而且格式美觀大方,使用起來也非常方便。但是在實際使用中不是很理想,主要有以下兩個問題:
1. 導出的列數據是原始值
Kendo UI默認導出的是該列的value值,及查出來的值,有時候我們會用template渲染一下導出的列,比如將“Y”顯示成“是”,把“N”顯示成“否”。而Kendo UI導出的卻是Y/N這種只有程序員看得懂的數據庫標識,顯然不是我們需要的,這種情況非常常見。
2. 不能靈活控制可導出的列
Kendo UI的Excel導出主要看兩點,一是該列(column)是field字段,而不是自定義的name;二是該列不是隱藏的(hidden:true)。這樣我們無法靈活導出我們需要的列。
爲了解決上面兩個問題,我查看了Kendo UI的源代碼,提取並改進了源代碼。主要更改點及使用方法請看下面源代碼。主要針對以上兩點做了更改,只需要在grid定義columns時加上isExport或exportTemplate即可:
- 在導出數據,先看該列有沒有自定義exportTemplate(),沒有則看Kendo UI自帶的template(),再沒有才會導出查出來的值。
- 判斷是否導出該列不再看hidden屬性,而是看列的isExport屬性,如果爲false則不導出,其它情況一律導出該列。
經過這兩個更改,基本可以應對所有業務場景,可以方便快捷地開發了!
但要注意,Kendo UI自帶的導出功能無法應用於導出大量數據,似乎是瀏覽器的jvm溢出了,建議超過5萬條的數據導出還是老老實實寫後臺導出功能吧。下篇文章將介紹使用POI導出百萬級別數據。
js代碼下載鏈接:https://download.csdn.net/download/qq_28830129/10628102
/**
* @summary ExcelExport
* @description 基於Kendo UI框架的Excel導出操作
* 使用方式:
* 1.引入該js,需在kendo ui的js之後
* 2.定義一個grid,通過id獲取其JQuery對象
* 3.調用saveAsExclePro()方法
* 如:$("#Grid").saveAsExclePro()
* grid新增column輔助屬性說明:
* isExport:
* 作爲grid.column的補充屬性,爲false時該column不導出
* 與grid.saveAsExcle()不同,hidden爲true時同樣會導出
* exportTemplate:
* 類似grid.column的template屬性,是一個函數,參數爲dataItem
* 如果不指定該屬性,將使用grid.column的template屬性的渲染值作爲導出值,也沒有就以原始Value導出
* 注意:調用該導出方法不會觸發grid的導出Excel相關事件
* @version 1.0
* @author chong.luo
*/
!(function ($) {
if (!window.ExcelExport) {
ExcelExport = {
version: '1.0'
};
MyExcelExporter = kendo.Class.extend({
init: function (options) {
options.columns = this._trimColumns(options.columns || []);
this.allColumns = $.map(this._leafColumns(options.columns || []), this._prepareColumn);
//---更改1---更改導出列的篩選,isExport爲false不導出
this.columns = $.grep(this.allColumns, function (column) {
if(column.isExport == false){
return false;
}
return true;
//return !column.hidden;
});
this.options = options;
var dataSource = options.dataSource;
if (dataSource instanceof kendo.data.DataSource) {
this.dataSource = new dataSource.constructor($.extend({}, dataSource.options, {
page: options.allPages ? 0 : dataSource.page(),
filter: dataSource.filter(),
pageSize: options.allPages ? dataSource.total() : dataSource.pageSize(),
sort: dataSource.sort(),
group: dataSource.group(),
aggregate: dataSource.aggregate()
}));
var data = dataSource.data();
if (data.length > 0) {
this.dataSource._data = data;
var transport = this.dataSource.transport;
if (dataSource._isServerGrouped() && transport.options && transport.options.data) {
transport.options.data = null;
}
}
} else {
this.dataSource = kendo.data.DataSource.create(dataSource);
}
},
_trimColumns: function (columns) {
var that = this;
return $.grep(columns, function (column) {
var result = !!column.field;
if (!result && column.columns) {
result = that._trimColumns(column.columns).length > 0;
}
return result;
});
},
_leafColumns: function (columns) {
var result = [];
for (var idx = 0; idx < columns.length; idx++) {
if (!columns[idx].columns) {
result.push(columns[idx]);
continue;
}
result = result.concat(this._leafColumns(columns[idx].columns));
}
return result;
},
workbook: function () {
return $.Deferred($.proxy(function (d) {
this.dataSource.fetch().then($.proxy(function () {
var workbook = {
sheets: [{
columns: this._columns(),
rows: this._rows(),
freezePane: this._freezePane(),
filter: this._filter()
}]
};
d.resolve(workbook, this.dataSource.view());
}, this));
}, this)).promise();
},
_prepareColumn: function (column) {
if (!column.field) {
return;
}
var value = function (dataItem) {
return dataItem.get(column.field);
};
var values = null;
if (column.values) {
values = {};
$.each(column.values, function () {
values[this.value] = this.text;
});
value = function (dataItem) {
return values[dataItem.get(column.field)];
};
}
return $.extend({}, column, {
value: value,
values: values,
groupHeaderTemplate: kendo.template(column.groupHeaderTemplate || '#= title #: #= value #'),
groupFooterTemplate: column.groupFooterTemplate ? kendo.template(column.groupFooterTemplate) : null,
footerTemplate: column.footerTemplate ? kendo.template(column.footerTemplate) : null
});
},
_filter: function () {
if (!this.options.filterable) {
return null;
}
var depth = this._depth();
return {
from: depth,
to: depth + this.columns.length - 1
};
},
_dataRow: function (dataItem, level, depth) {
if (this._hierarchical()) {
level = this.dataSource.level(dataItem) + 1;
}
var cells = [];
for (var li = 0; li < level; li++) {
cells[li] = {
background: '#dfdfdf',
color: '#333'
};
}
if (depth && dataItem.items) {
var column = $.grep(this.allColumns, function (column) {
return column.field == dataItem.field;
})[0];
var title = column && column.title ? column.title : dataItem.field;
var template = column ? column.groupHeaderTemplate : null;
var value = title + ': ' + dataItem.value;
var group = $.extend({
title: title,
field: dataItem.field,
value: column && column.values ? column.values[dataItem.value] : dataItem.value,
aggregates: dataItem.aggregates
}, dataItem.aggregates[dataItem.field]);
if (template) {
value = template(group);
}
cells.push({
value: value,
background: '#dfdfdf',
color: '#333',
colSpan: this.columns.length + depth - level
});
var rows = this._dataRows(dataItem.items, level + 1);
rows.unshift({
type: 'group-header',
cells: cells
});
return rows.concat(this._footer(dataItem));
} else {
var dataCells = [];
for (var ci = 0; ci < this.columns.length; ci++) {
dataCells[ci] = this._cell(dataItem, this.columns[ci]);
}
if (this._hierarchical()) {
dataCells[0].colSpan = depth - level + 1;
}
return [{
type: 'data',
cells: cells.concat(dataCells)
}];
}
},
_dataRows: function (dataItems, level) {
var depth = this._depth();
var rows = [];
for (var i = 0; i < dataItems.length; i++) {
rows.push.apply(rows, this._dataRow(dataItems[i], level, depth));
}
return rows;
},
_footer: function (dataItem) {
var rows = [];
var footer = false;
var cells = $.map(this.columns, $.proxy(function (column) {
if (column.groupFooterTemplate) {
footer = true;
return {
background: '#dfdfdf',
color: '#333',
value: column.groupFooterTemplate($.extend({}, this.dataSource.aggregates(), dataItem.aggregates, dataItem.aggregates[column.field]))
};
} else {
return {
background: '#dfdfdf',
color: '#333'
};
}
}, this));
if (footer) {
rows.push({
type: 'group-footer',
cells: $.map(new Array(this.dataSource.group().length), function () {
return {
background: '#dfdfdf',
color: '#333'
};
}).concat(cells)
});
}
return rows;
},
_isColumnVisible: function (column) {
return this._visibleColumns([column]).length > 0 && (column.field || column.columns);
},
_visibleColumns: function (columns) {
var that = this;
return $.grep(columns, function (column) {
//---更改1---更改導出列的篩選,isExport爲false不導出
if(column.isExport == false){
var result = false;
}else{
var result = true;
}
//var result = !column.hidden;
if (result && column.columns) {
result = that._visibleColumns(column.columns).length > 0;
}
return result;
});
},
_headerRow: function (row, groups) {
var headers = $.map(row.cells, function (cell) {
return {
background: '#7a7a7a',
color: '#fff',
value: cell.title,
colSpan: cell.colSpan > 1 ? cell.colSpan : 1,
rowSpan: row.rowSpan > 1 && !cell.colSpan ? row.rowSpan : 1
};
});
if (this._hierarchical()) {
headers[0].colSpan = this._depth() + 1;
}
return {
type: 'header',
cells: $.map(new Array(groups.length), function () {
return {
background: '#7a7a7a',
color: '#fff'
};
}).concat(headers)
};
},
_prependHeaderRows: function (rows) {
var groups = this.dataSource.group();
var headerRows = [{
rowSpan: 1,
cells: [],
index: 0
}];
this._prepareHeaderRows(headerRows, this.options.columns);
for (var idx = headerRows.length - 1; idx >= 0; idx--) {
rows.unshift(this._headerRow(headerRows[idx], groups));
}
},
_prepareHeaderRows: function (rows, columns, parentCell, parentRow) {
var row = parentRow || rows[rows.length - 1];
var childRow = rows[row.index + 1];
var totalColSpan = 0;
var column;
var cell;
for (var idx = 0; idx < columns.length; idx++) {
column = columns[idx];
if (this._isColumnVisible(column)) {
cell = {
title: column.title || column.field,
colSpan: 0
};
row.cells.push(cell);
if (column.columns && column.columns.length) {
if (!childRow) {
childRow = {
rowSpan: 0,
cells: [],
index: rows.length
};
rows.push(childRow);
}
cell.colSpan = this._trimColumns(this._visibleColumns(column.columns)).length;
this._prepareHeaderRows(rows, column.columns, cell, childRow);
totalColSpan += cell.colSpan - 1;
row.rowSpan = rows.length - row.index;
}
}
}
if (parentCell) {
parentCell.colSpan += totalColSpan;
}
},
_rows: function () {
var groups = this.dataSource.group();
var rows = this._dataRows(this.dataSource.view(), 0);
if (this.columns.length) {
this._prependHeaderRows(rows);
var footer = false;
var cells = $.map(this.columns, $.proxy(function (column) {
if (column.footerTemplate) {
footer = true;
var aggregates = this.dataSource.aggregates();
return {
background: '#dfdfdf',
color: '#333',
value: column.footerTemplate($.extend({}, aggregates, aggregates[column.field]))
};
} else {
return {
background: '#dfdfdf',
color: '#333'
};
}
}, this));
if (footer) {
rows.push({
type: 'footer',
cells: $.map(new Array(groups.length), function () {
return {
background: '#dfdfdf',
color: '#333'
};
}).concat(cells)
});
}
}
return rows;
},
_headerDepth: function (columns) {
var result = 1;
var max = 0;
for (var idx = 0; idx < columns.length; idx++) {
if (columns[idx].columns) {
var temp = this._headerDepth(columns[idx].columns);
if (temp > max) {
max = temp;
}
}
}
return result + max;
},
_freezePane: function () {
var columns = this._visibleColumns(this.options.columns || []);
var colSplit = this._visibleColumns(this._trimColumns(this._leafColumns($.grep(columns, function (column) {
return column.locked;
})))).length;
return {
rowSplit: this._headerDepth(columns),
colSplit: colSplit ? colSplit + this.dataSource.group().length : 0
};
},
_cell: function (dataItem, column) {
//-----更改2-----導出excel的值由temple決定,如果沒有temple才取value
if(!!column.exportTemplate){//存在自定義導出數據模板
return { value: column.exportTemplate(dataItem)};
}
return { value: (!!column.template)?column.template(dataItem):column.value(dataItem) };
//return { value: column.value(dataItem) };
},
_hierarchical: function () {
return this.options.hierarchy && this.dataSource.level;
},
_depth: function () {
var dataSource = this.dataSource;
var depth = 0;
var view, i, level;
if (this._hierarchical()) {
view = dataSource.view();
for (i = 0; i < view.length; i++) {
level = dataSource.level(view[i]);
if (level > depth) {
depth = level;
}
}
depth++;
} else {
depth = dataSource.group().length;
}
return depth;
},
_columns: function () {
var depth = this._depth();
var columns = $.map(new Array(depth), function () {
return { width: 20 };
});
return columns.concat($.map(this.columns, function (column) {
return {
width: parseInt(column.width, 10),
autoWidth: column.width ? false : true
};
}));
}
});
//定義一個kendo對象:Excle
Excel = kendo.Class.extend({
/*extend: function (proto) {
proto.events.push('excelExport');
proto.options.excel = $.extend(proto.options.excel, this.options);
proto.saveAsExcel = this.saveAsExcel;
},*/
options: {
proxyURL: '',
allPages: true,
filterable: true,
fileName: 'list.xlsx'
},
saveAsExcel: function (grid) {
//console.log("--------開始進行導出操作,時間"+ kendo.toString(new Date(), "yyyy-MM-dd HH:mm:ss") +"----------");
var excel = grid.options.excel || {};
var exporter = new MyExcelExporter({
columns: grid.columns,
dataSource: grid.dataSource,
allPages: excel.allPages,
filterable: excel.filterable,
hierarchy: excel.hierarchy
});
exporter.workbook().then($.proxy(function (book, data) {
/*if (!this.trigger('excelExport', {
workbook: book,
data: data
})) {*/
var workbook = new kendo.ooxml.Workbook(book);
kendo.saveAs({
dataURI: workbook.toDataURL(),
fileName: book.fileName || excel.fileName,
proxyURL: excel.proxyURL,
forceProxy: excel.forceProxy
});
//}
}, this));
}
})
//給JQuery對象添加全局方法
$.fn.saveAsExclePro = function(){
//只允許Kendo UI的Grid組件調用
if($(this).data('kendoGrid') instanceof kendo.ui.Grid){
Excel.prototype.saveAsExcel($(this).data('kendoGrid'));
}
}
}
})(jQuery)