Hi all!,
This is an example to create a link to download a sap.ui.table.Table to CSV at client side (JS, supported by HTML5 browsers).
The next JS code, extracts header and content from table column&binding definition to generate a CSV B64 string. The download link uses 'download' HTML5 attr and Data Uri scheme (Data URI scheme - Wikipedia, the free encyclopedia) to export a filename at client side.
Html:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.ui.commons,sap.ui.table"
data-sap-ui-theme="sap_goldreflection">
</script>
<!-- add sap.ui.table,sap.ui.ux3 and/or other libraries to 'data-sap-ui-libs' if required -->
<script src="util/Base64.js"></script>
<script>
//Default view PortalUserView
sap.ui.localResources("view");
var view = sap.ui.view({id:"ExampleView", viewName:"view.ExampleView", type:sap.ui.core.mvc.ViewType.JS});
view.placeAt("content");
</script>
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>
View:
sap.ui.jsview("view.ExampleView", {
/** Specifies the Controller belonging to this View.
* In the case that it is not implemented, or that "null" is returned, this View does not have a Controller.
* @memberOf view.ExampleView
*/
getControllerName : function() {
return "view.ExampleView";
},
/** Is initially called once after the Controller has been instantiated. It is the place where the UI is constructed.
* Since the Controller is given to this method, its event handlers can be attached right away.
* @memberOf view.ExampleView
*/
createContent : function(oController) {
//Define some sample data
var aData = [
{lastName: "Dente", name: "Al", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 4},
{lastName: "Friese", name: "Andy", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 2},
{lastName: "Mann", name: "Anita", checked: false, linkText: "www.sap.com", href: "http://www.sap.com", gender: "female", rating: 3},
{lastName: "Schutt", name: "Doris", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "female", rating: 4},
{lastName: "Open", name: "Doris", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "female", rating: 2},
{lastName: "Dewit", name: "Kenya", checked: false, linkText: "www.sap.com", href: "http://www.sap.com", gender: "female", rating: 3},
{lastName: "Zar", name: "Lou", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 1},
{lastName: "Burr", name: "Tim", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 2},
{lastName: "Hughes", name: "Tish", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 5},
{lastName: "Lester", name: "Mo", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 3},
{lastName: "Case", name: "Justin", checked: false, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 3},
{lastName: "Time", name: "Justin", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 4},
{lastName: "Barr", name: "Gaye", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 2},
{lastName: "Poole", name: "Gene", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 1},
{lastName: "Ander", name: "Corey", checked: false, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 5},
{lastName: "Early", name: "Brighton", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 3},
{lastName: "Noring", name: "Constance", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "female", rating: 4},
{lastName: "Haas", name: "Jack", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 2},
{lastName: "Tress", name: "Matt", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "male", rating: 4},
{lastName: "Turner", name: "Paige", checked: true, linkText: "www.sap.com", href: "http://www.sap.com", gender: "female", rating: 3}
];
var oTable = createTable(aData);
var csvText = generateTableCSV(oTable, aData);
var oLink = createDownloadLink(csvText);
var layout = new sap.ui.commons.layout.VerticalLayout("layout", {
content: [oLink, oTable]
});
return layout;
}
});
/**
* Example table creation.
* See https://sapui5.netweaver.ondemand.com/sdk/#test-resources/sap/ui/table/demokit/Table.html#__2
* @param aData Table json data
*/
function createTable(aData) {
//Create an instance of the table control
var oTable = new sap.ui.table.Table({
title: "Table Example",
visibleRowCount: 7,
firstVisibleRow: 3,
selectionMode: sap.ui.table.SelectionMode.Single
});
//Define the columns and the control templates to be used
var oColumn = new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "lastName"}),
template: new sap.ui.commons.TextView().bindProperty("text", "lastName"),
sortProperty: "lastName",
filterProperty: "lastName",
width: "200px"
});
var oCustomMenu = new sap.ui.commons.Menu();
oCustomMenu.addItem(new sap.ui.commons.MenuItem({
text:"Custom Menu",
select:function() {
alert("Custom Menu");
}
}));
oColumn.setMenu(oCustomMenu);
oTable.addColumn(oColumn);
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "firstName"}),
template: new sap.ui.commons.TextField().bindProperty("value", "name"),
sortProperty: "name",
filterProperty: "name",
width: "100px"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "checked"}),
template: new sap.ui.commons.CheckBox().bindProperty("checked", "checked"),
sortProperty: "checked",
filterProperty: "checked",
width: "75px",
hAlign: "Center"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "website"}),
template: new sap.ui.commons.Link().bindProperty("text", "linkText").bindProperty("href", "href"),
sortProperty: "linkText",
filterProperty: "linkText"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "gender"}),
template: new sap.ui.commons.ComboBox({items: [
new sap.ui.core.ListItem({text: "female"}),
new sap.ui.core.ListItem({text: "male"})
]}).bindProperty("value","gender"),
sortProperty: "gender",
filterProperty: "gender"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "rating"}),
template: new sap.ui.commons.RatingIndicator().bindProperty("value", "rating"),
sortProperty: "rating",
filterProperty: "rating"
}));
//Create a model and bind the table rows to this model
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData({modelData: aData});
oTable.setModel(oModel);
oTable.bindRows("/modelData");
//Initially sort the table
oTable.sort(oTable.getColumns()[0]);
//Bring the table onto the UI
return oTable;
}
/**
* Export table header and data into a CSV string.
*/
function generateTableCSV(table, jsonData) {
var info = '';
for (var i =0; i<table.getColumns().length; i++) {
info+= encodeURIComponent(table.getColumns()[i].getLabel().getText()) + ';';
}
info += '\r\n';
if (jsonData.length != undefined) {
for (var j=0; j<jsonData.length; j++) {
for (var i =0; i<table.getColumns().length; i++) {
if (table.getColumns()[i].getTemplate() != undefined && table.getColumns()[i].getTemplate().getBinding('text') != undefined) {
var valor = eval('jsonData[j].'+table.getColumns()[i].getTemplate().getBinding('text').sPath);
info+= encodeURIComponent(valor) + ';';
} else if (table.getColumns()[i].getTemplate() != undefined && table.getColumns()[i].getTemplate().getBinding('value') != undefined) {
var valor = eval('jsonData[j].'+table.getColumns()[i].getTemplate().getBinding('value').sPath);
info+= encodeURIComponent(valor) + ';';
} else
info+= ';';
}
info += '\r\n';
}
} else {
$.each(jsonData, function(key,value){
for (var i =0; i<table.getColumns().length; i++) {
if (table.getColumns()[i].getTemplate() != undefined && table.getColumns()[i].getTemplate().getBinding('text') != undefined) {
var valor = eval('jsonData[j].'+table.getColumns()[i].getTemplate().getBinding('text').sPath);
info+= encodeURIComponent(valor) + ';';
} else if (table.getColumns()[i].getTemplate() != undefined && table.getColumns()[i].getTemplate().getBinding('value') != undefined) {
var valor = eval('jsonData[j].'+table.getColumns()[i].getTemplate().getBinding('value').sPath);
info+= encodeURIComponent(valor) + ';';
} else
info+= ';';
}
info += '\r\n';
});
}
return info;
}
/**
* Creates a link target to base64 data
*/
function createDownloadLink(b64text) {
var oLink = new sap.ui.commons.Link("linkExportCsv", {
text: 'Download as CSV',
href: 'data:application/csv;charset=utf-8;base64,' + (Base64.encode(b64text))
});
initDownloadAttr('FileName-Example.csv')
return oLink;
}
/**
* Creates download attribute to set filename
*/
function initDownloadAttr() {
if ($( "#linkExportCsv" ).length > 0) {
$( "#linkExportCsv" ).attr('download', 'filename.csv');
} else {
setTimeout(initDownloadAttr, 1000);
}
}
Base 64 util:
/**
*
* Base64 encode / decode
*
**/
var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}